Universal Module Architecture - Quick Reference

Quick reference for developers working with the new architecture

⚡ Universal Module Architecture - Quick Reference

Fast lookup for developers


📦 Imports

// Types
import {
  UniversalModule,
  ModuleType,
  CreateModuleData,
  UpdateModuleData,
  ModuleQueryOptions,
  MODULE_TYPE_REGISTRY
} from '@libs-foundational/core-models';

// Service
import { UniversalModuleService } from '@libs-foundational/core-angular';

// Components
import {
  UniverseMapComponent,
  ModuleTreeViewComponent,
  ModuleCreationWizardComponent
} from '@universe-map';

🎯 Module Types

'galaxy'      // Route collection, has children
'world'       // Page container, has children
'page'        // Content page with widgets
'navigation'  // Nav components (TopNav, Footer)
'feature'     // Features (Cart, Auth, Search)
'widget'      // UI components
'layout'      // Layout wrappers
'data'        // Data providers
'flow'        // Logic flows
'custom'      // Anything else

🔧 Common Operations

Create a Galaxy

moduleService.createGalaxy(
  universeId,
  'Products',
  '/products'
).subscribe(galaxy => {
  console.log('Created:', galaxy);
});

Create a World

moduleService.createWorld(
  universeId,
  'Electronics',
  '/electronics',
  galaxyId  // parentId
).subscribe(world => {
  console.log('Created:', world);
});

Create a Page

moduleService.createPage(
  universeId,
  'Laptops',
  '/laptops',
  worldId  // parentId
).subscribe(page => {
  console.log('Created:', page);
});

Create Navigation

moduleService.createNavigation(
  universeId,
  'TopNav',
  'header',
  TopNavComponent
).subscribe(nav => {
  console.log('Created:', nav);
});

Generic Module Creation

moduleService.install(universeId, {
  name: 'My Module',
  type: 'galaxy',
  route: '/my-route',
  parentId: 'optional-parent-id'
}).subscribe(module => {
  console.log('Created:', module);
});

🔍 Query Operations

Get All Modules

moduleService.query({}).subscribe(modules => {
  console.log('All modules:', modules);
});

Filter by Type

moduleService.query({ 
  type: 'galaxy' 
}).subscribe(galaxies => {
  console.log('All galaxies:', galaxies);
});

// Or use convenience method
moduleService.getByType('galaxy').subscribe(galaxies => {
  console.log('All galaxies:', galaxies);
});

Filter by Parent

moduleService.query({
  parentId: galaxyId
}).subscribe(children => {
  console.log('Galaxy children:', children);
});

// Or use convenience method
moduleService.getByParent(galaxyId).subscribe(children => {
  console.log('Galaxy children:', children);
});

Get Root Modules

moduleService.getRootModules(universeId).subscribe(roots => {
  console.log('Root modules:', roots);
});

Complex Query

moduleService.query({
  type: ['galaxy', 'world'],
  isActive: true,
  tags: ['featured'],
  search: 'product',
  sortBy: 'name',
  sortOrder: 'asc',
  limit: 10
}).subscribe(modules => {
  console.log('Filtered modules:', modules);
});

🌳 Tree Operations

Get Full Tree

moduleService.getModuleTree(universeId).subscribe(tree => {
  console.log('Module tree:', tree);
  // tree is ModuleTreeNode[]
});

Get Module with Children

moduleService.getModuleWithChildren(moduleId).subscribe(module => {
  console.log('Module with children:', module);
  // module.children is populated recursively
});

Build Tree from List

const tree = moduleService.buildModuleTree(modules);
// Returns ModuleTreeNode[]

✏️ Update Operations

Update Module

moduleService.update(moduleId, {
  name: 'New Name',
  description: 'New description',
  isActive: false
}).subscribe(updated => {
  console.log('Updated:', updated);
});

Move Module

moduleService.move(moduleId, {
  newParentId: newGalaxyId,
  newOrder: 5
}).subscribe(moved => {
  console.log('Moved:', moved);
});

🗑️ Delete Operations

Delete Module

moduleService.remove(moduleId).subscribe(() => {
  console.log('Deleted (children orphaned)');
});

Delete with Children

moduleService.remove(moduleId, true).subscribe(() => {
  console.log('Deleted with all children');
});

🎨 Visualization

Get Module Icon

const visualization = inject(ModuleVisualizationService);
const icon = visualization.getIcon('galaxy');
// Returns: 'fa-galaxy'

Get Module Color

const color = visualization.getColor('galaxy');
// Returns: '#8b5cf6' (purple)

Get Cosmic Term

const term = visualization.getCosmicTerm('galaxy');
// Returns: 'Galaxy'

🔄 Migration

Migrate Universe

const migration = inject(ModuleMigrationService);

migration.migrateUniverse(universeId, spaceId).subscribe(result => {
  if (result.success) {
    console.log(`Migrated ${result.migratedModules} modules`);
  } else {
    console.error('Errors:', result.errors);
    // Rollback if needed
    migration.rollbackMigration(result).subscribe();
  }
});

🌐 Backend API

Create Module

POST /api/:spaceId/universes/:universeId/modules
Content-Type: application/json

{
  "name": "Products",
  "type": "galaxy",
  "route": "/products",
  "description": "Product catalog"
}

Query Modules

GET /api/:spaceId/universes/:universeId/modules?type=galaxy&isActive=true

Update Module

PUT /api/:spaceId/universes/:universeId/modules/:moduleId
Content-Type: application/json

{
  "name": "Updated Name",
  "isActive": false
}

Delete Module

DELETE /api/:spaceId/universes/:universeId/modules/:moduleId?removeChildren=true

💾 Storage

Save Module

await storage.putInUniverse(
  universeId,
  `modules/${moduleId}`,
  moduleData
);

Load Module

const module = await storage.getFromUniverse(
  universeId,
  `modules/${moduleId}`
);

Query Modules

const modules = await storage.queryUniverseData(
  universeId,
  'modules',
  { type: 'galaxy', isActive: true }
);

🧪 Testing

Test Service

describe('UniversalModuleService', () => {
  it('should create a galaxy', (done) => {
    service.createGalaxy('u1', 'Products', '/products')
      .subscribe(galaxy => {
        expect(galaxy.type).toBe('galaxy');
        done();
      });
  });
});

Test Component

describe('UniverseMapComponent', () => {
  it('should render module tree', () => {
    const fixture = TestBed.createComponent(UniverseMapComponent);
    fixture.detectChanges();
    
    const tree = fixture.nativeElement.querySelector('.module-tree');
    expect(tree).toBeTruthy();
  });
});

🔑 Key Concepts

Everything is a Module

// Don't think in layers
❌ Universe → Galaxy → World → Page

// Think in modules with types
✅ Module (type='galaxy')
   └─ Module (type='world')
      └─ Module (type='page')

Type Determines Behavior

// Galaxy module acts as route collection
{ type: 'galaxy', route: '/products', children: [...] }

// Navigation module acts as UI component
{ type: 'navigation', position: 'header', component: TopNav }

Composition is Infinite

// Can nest any combination
Galaxy → Galaxy → Page
Galaxy → World → Page
Galaxy → Page (skip world!)
Just Pages (skip everything!)

⚠️ Common Pitfalls

Don't Over-Nest

// ❌ BAD: Too complex for simple blog
Galaxy → World → Page → Widget

// ✅ GOOD: Keep it simple
Page → Widget

Use Correct Types

// ❌ BAD: Wrong type
{ type: 'page', position: 'header' }  // Pages don't have position

// ✅ GOOD: Correct type
{ type: 'navigation', position: 'header' }

Set Required Fields

// ❌ BAD: Missing route for structural module
{ type: 'galaxy', name: 'Products' }  // No route!

// ✅ GOOD: Include route
{ type: 'galaxy', name: 'Products', route: '/products' }

📚 Resources


Keep this handy while implementing! ⚡