Route Registration Implementation
Documentation for Claude Docs
Dynamic Route Registration Implementation
Summary
Successfully implemented dynamic route registration system for the gograb-admin application using the module-integrator library. The system automatically discovers and registers routes from all registered modules at application startup.
Implementation Details
1. Extended BrowserModuleContract
File: libs/core/module-base/src/lib/contracts/browser-module.contract.ts
Added optional properties to support dynamic registration:
routes?: Routes- Module route definitionsembeddableComponents?: EmbeddableComponent[]- Components for embeddingpublicActions?: ModuleAction[]- Public module actions
2. Created RouteRegistrationService
File: libs/core/module-integrator/src/lib/navigation/route-registration.service.ts
Core service that handles dynamic route registration:
Key Features:
- Discovers routes from all registered modules via ModuleRegistryService
- Creates route configurations with module ID as base path
- Injects routes into AppShell children (protected by authGuard)
- Updates Angular Router configuration using
Router.resetConfig() - Provides metadata about registered routes
Public API:
// Register all module routes
registerModuleRoutes(): RouteRegistrationResult
// Get metadata about registered routes
getRegisteredRoutes(): Array<{moduleId, routes, routeCount}>
// Check if a specific module has routes
hasRoutes(moduleId: string): boolean
Result Interface:
interface RouteRegistrationResult {
success: boolean;
modulesRegistered: number;
totalRoutes: number;
errors: string[];
registeredModules: Array<{
moduleId: string;
routeCount: number;
basePath: string;
}>;
}
3. Integrated with BrowserBootstrapperService
File: libs/core/module-integrator/src/lib/bootstrap/browser-bootstrapper.service.ts
Added route registration as part of the bootstrap sequence:
- Module discovery
- Module initialization
- Route registration ← NEW
- Module activation
The route registration happens after initialization, ensuring all modules are ready before their routes are injected.
4. Updated UserManagementModule
File: libs/core/user-management/src/lib/user-management.module.ts
Added routes property to expose module routes:
readonly routes = userManagementRoutes;
5. Created Comprehensive Tests
File: libs/core/module-integrator/src/lib/navigation/route-registration.service.spec.ts
Test coverage includes:
- Successful route registration from single/multiple modules
- Handling modules without routes
- Error handling and recovery
- Route injection into AppShell
- Metadata retrieval methods
How It Works
Route Discovery Flow
- Bootstrap Phase: BrowserBootstrapperService initializes
- Module Discovery: ModuleRegistryService discovers all registered modules
- Route Collection: RouteRegistrationService:
- Iterates through all registered modules
- Collects routes from modules that have them
- Creates route configuration with module ID as base path
- Route Injection:
- Finds the AppShell route (identified by authGuard and children array)
- Injects module routes as children of AppShell
- Router Update: Calls
router.resetConfig(updatedConfig)to apply changes
Example Route Structure
Before injection:
[
{ path: 'login', component: LoginComponent },
{
path: '',
component: AppShellComponent,
canActivate: [authGuard],
children: [
{ path: 'dashboard', component: DashboardComponent }
]
}
]
After injection (with user-management module):
[
{ path: 'login', component: LoginComponent },
{
path: '',
component: AppShellComponent,
canActivate: [authGuard],
children: [
{ path: 'dashboard', component: DashboardComponent },
{
path: 'user-management', // Module ID as base path
children: [
{ path: 'list', component: UserListComponent },
{ path: 'create', component: UserFormComponent },
{ path: ':id', component: UserDetailComponent },
{ path: ':id/edit', component: UserFormComponent },
{ path: 'admin/manage', component: UserListComponent }
]
}
]
}
]
Final Routes Available
/login- Public login page/dashboard- Protected dashboard (requires auth)/user-management/list- User list (requires auth + users:read permission)/user-management/create- Create user (requires auth + users:create permission)/user-management/:id- User details (requires auth + users:read permission)/user-management/:id/edit- Edit user (requires auth + users:update permission)/user-management/admin/manage- Admin management (requires auth + admin role + users:manage permission)
Security Integration
All routes maintain their original security guards:
authGuard- Applied at AppShell level (all child routes protected)permissionGuard- Applied at individual route levelroleGuard- Applied at admin routes
Benefits
- Dynamic Registration: No manual route configuration needed in app.routes.ts
- Loose Coupling: Modules are self-contained with their own routes
- Multi-tenant Support: Routes registered per tenant context
- Type Safety: Full TypeScript support with proper typing
- Lazy Loading: Routes support lazy-loaded components
- Security Integration: Maintains all guard protections
- Monitoring: Full logging and error tracking
Build Status
✅ All libraries build successfully ✅ gograb-admin app builds successfully ✅ Tests pass (excluding empty placeholder files) ⚠️ Minor warnings (bundle size, CommonJS dependencies) - non-blocking
Next Steps for Testing
- Run the application:
npx nx serve gograb-admin - Verify routes in browser DevTools console logs
- Navigate to
/user-management/listto verify route registration - Check that guards are enforced (redirect to login if not authenticated)
- Verify multi-tenant context is maintained across navigation
Files Modified
libs/core/module-base/src/lib/contracts/browser-module.contract.tslibs/core/user-management/src/lib/user-management.module.tslibs/core/module-integrator/src/lib/navigation/route-registration.service.ts(new)libs/core/module-integrator/src/lib/navigation/route-registration.service.spec.ts(new)libs/core/module-integrator/src/lib/navigation/index.tslibs/core/module-integrator/src/lib/bootstrap/browser-bootstrapper.service.ts
Implementation Date
2025-10-07