Module Base Plan
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
Plan de Desarrollo - Librería Module Base
Estado Actual
- Librería: @libs-core/module-base
- Prioridad: Muy Alta - Fundamento arquitectónico del sistema modular
- Estado: Solo estructura básica con componente placeholder
- API Pública: Solo barrel export (src/index.ts)
Cambios de Arquitectura
- Auto-registro: Los módulos se auto-registran al iniciar la aplicación
- Configuración API: Activación de módulos basada en configuración del API
- Carga Angular: Toda la carga depende de Angular (sin Module Federation)
- Module Integrator: Centraliza la gestión basada en configuración del API
- Multitenancy: Soporte nativo para múltiples tenants con aislamiento completo
Dependencias Fundamentales Verificadas
- @gograb-space/utilities: ✅ APIs disponibles - ValidationUtils, ObjectUtils, DateUtils, StringUtils, ArrayUtils
- @libs-core/log-system: ✅ APIs disponibles - LoggerService, @Loggable, @LogError, @Performance decorators
- @libs-core/event-system: ✅ APIs disponibles - EventBusService, SystemEventService, BaseEvent, DomainEvent
- @libs-core/action-registry: ✅ APIs disponibles - ActionRegistryService, @PublicAction, ModuleActionContract, ActionDiscoveryService
- @libs-core/data-access: ✅ Librería configurada (APIs pendientes de implementar)
- @libs-core/security: ✅ APIs disponibles - AuthService, PermissionService, guards, directivas multitenancy
- @libs-core/shared-models: ✅ APIs disponibles - Context, UserProfile, Permission, Role, AuthState
Plan de Implementación por Pasos
Paso 1: Estructura Base del Proyecto
1.1 Crear estructura de directorios
src/lib/
├── contracts/ # Contratos principales
├── actions/ # Sistema de acciones
├── state/ # Gestión de estado
├── components/ # Componentes base
├── services/ # Servicios base
├── models/ # Modelos y tipos
├── decorators/ # Decoradores
└── utils/ # Utilidades específicas
1.2 Configurar dependencias del proyecto (solo revisar ya debe estar implementado)
- Actualizar
package.jsoncon dependencias core - Configurar
tsconfigpara paths de librerías - Configurar
eslintyprettier - Setup inicial de testing con Vitest
Paso 2: Modelos y Tipos Fundamentales
2.1 Modelos base
ModuleTypes: Tipos y enums compartidosLifecycleStates: Estados del ciclo de vidaModuleEvents: Eventos estándar del ciclo de vidaModulePermissions: Sistema de permisos básicos
2.2 Inyección de configuración
- Configuración pasada directamente via
configure(config)- sin tokens ModuleConfigService: Servicio para resolver configuración por módulo desde API
Paso 3: Contratos Principales
3.1 Contratos base
BrowserModuleContract: Contrato base para módulos del navegadorModuleManifest: Descriptor completo de módulos (no debe ser muy detallado, solo lo necesario)ActionContract: Contrato para acciones inter-móduloStateContract: Contrato para intercambio de estadoComponentContract: Contrato para comunicación entre componentesServiceContract: Contrato para servicios inter-módulo
3.2 Contratos de configuración y registro
ModuleRegistrationContract: Contrato para auto-registro de módulosModuleConfigurationContract: Contrato para configuración basada en API
Paso 4: Servicios Base del Sistema
4.1 Registro y descubrimiento
ModuleRegistryService: Servicio para registro central de módulosModuleDiscoveryService: Servicio para descubrimiento y auto-registroModuleConfigurationService: Servicio para configuración basada en API
4.2 Comunicación y validación
ModuleCommunicationService: Comunicación entre módulosModuleConfigService: Gestión de configuración por módulo
Paso 5: Sistema de Estado y Acciones
5.1 Gestión de estado
BaseModuleState: Estado base con logging integradoModuleStateService: Servicio de gestión de estadoModuleStateActions: Acciones CRUD estándarStateSelectors.base: Selectores base para estado
5.2 Sistema de acciones
ModuleActions: Registro y ejecución de accionesActionMetadata: Metadata de acciones (permisos, parámetros)PublicActions.base: Acciones base del sistemaActionRegistry: Registro de acciones
Paso 6: Componentes Base
6.1 Componentes principales
BaseModuleComponent: Componente base con funcionalidades comunesModuleLayoutComponent: Layout estándar para módulosModuleRouterOutlet: Outlet personalizado para rutasComponentBase: Clase base para componentes embebibles
Paso 7: Servicios Base de Módulos
7.1 Servicio base
BaseModuleService: Servicio base con eventosBaseModuleContract: Implementación base con signalsServiceBase: Clase base para servicios
Paso 8: Decoradores y Utilidades
8.1 Decoradores principales
@ModuleDecorator: Decorador para módulos (incluye auto-registro por defecto)@PublicAction: Decorador para acciones públicas
8.2 Utilidades (mínimas)
ContractImplementationHelper: Utilidad para implementar contratos fácilmente
Paso 9: Eventos del Ciclo de Vida
9.1 Eventos base
- Eventos de inicialización, configuración, inicio, parada, destrucción
- Eventos de auto-registro y activación basada en configuración
- Integración con @libs-core/event-system
- Logging automático de eventos
Paso 10: Testing Comprehensivo
10.1 Tests unitarios
- Unit tests para todos los contratos
- Tests para componentes base
- Tests para decoradores y utilidades
10.2 Tests de integración
- Integration tests con otras librerías core
- Tests de integración con @libs-core/security para multitenancy
- Coverage mínimo del 90%
Paso 11: Integración Angular 20 y Browser APIs
11.1 Features Angular 20
- Signals: Implementación completa de estado reactivo
- httpResource: Para comunicación HTTP declarativa
- createComponent API: Creación dinámica de componentes
- Standalone Components: Todos los componentes son standalone
- New Control Flow: Sintaxis @if, @for, @switch en templates
- inject() function: Inyección de dependencias moderna
11.2 Browser APIs
- Service Workers: Integración para funcionamiento offline
- Web Workers: Procesamiento en background
- Performance API: Monitoring de rendimiento
- Intersection Observer: Lazy loading y virtualización
11.3 Integración NGXS
- State Management: Estados básicos de módulos
- Actions: Acciones base del sistema
- Selectors: Selectores base
- Plugins: Plugins básicos para módulos
Paso 12: Finalización e Integración
12.1 Integración final
- Actualizar barrel exports (src/index.ts)
- Integrar con Module Integrator para gestión de módulos
- Integrar con @libs-core/security para funcionalidades de multitenancy
- Configuración final del ecosistema
12.2 Documentación
- API documentation con examples
- Guías de implementación de contratos
- Ejemplos de implementación
- Best practices para módulos
- Performance guidelines
12.3 Validación final
- Validar integración con todas las librerías core
- Testing de contratos con módulos reales
- Verificar que multitenancy funciona via @libs-core/security
Estructura Detallada del Paquete
src/lib/
├── contracts/
│ ├── module-contract.ts # BrowserModuleContract
│ ├── module-manifest.ts # ModuleManifest y tipos relacionados
│ ├── action-contract.ts # ActionContract
│ ├── state-contract.ts # StateContract
│ ├── component-contract.ts # ComponentContract
│ ├── service-contract.ts # ServiceContract
│ ├── registration-contract.ts # ModuleRegistrationContract
│ └── module-configuration-contract.ts # ModuleConfigurationContract
├── actions/
│ ├── module-actions.ts # ModuleActions
│ ├── action-metadata.ts # ActionMetadata
│ ├── public-actions.base.ts # Acciones base del sistema
│ └── action-registry.ts # ActionRegistry
├── state/
│ ├── base-module-state.ts # BaseModuleState
│ ├── module-state-actions.ts # ModuleStateActions
│ ├── module-state.service.ts # ModuleStateService
│ └── state-selectors.base.ts # Selectores base
├── components/
│ ├── base-module.component.ts # BaseModuleComponent
│ ├── module-layout.component.ts # ModuleLayoutComponent
│ ├── module-router-outlet.ts # ModuleRouterOutlet
│ └── component-base.ts # ComponentBase
├── services/
│ ├── base-module.service.ts # BaseModuleService
│ ├── module-config.service.ts # ModuleConfigService (para obtener config por moduleId)
│ ├── module-communication.service.ts # ModuleCommunicationService
│ ├── module-configuration.service.ts # ModuleConfigurationService
│ ├── module-discovery.service.ts # ModuleDiscoveryService
│ ├── module-registry.service.ts # ModuleRegistryService
│ ├── service-base.ts # ServiceBase
│ └── base-module.ts # BaseModule
├── models/
│ ├── module-types.ts # Tipos y enums
│ ├── module-events.ts # Eventos del ciclo de vida
│ ├── module-permissions.ts # Permisos básicos
│ └── lifecycle-states.ts # Estados del ciclo de vida
├── decorators/
│ ├── module.decorator.ts # @ModuleDecorator (incluye auto-registro)
│ └── public-action.decorator.ts # @PublicAction
├── browser/
│ ├── service-worker.service.ts # ServiceWorkerService
│ └── performance-monitor.service.ts # PerformanceMonitorService
└── utils/
└── contract-implementation.helper.ts # ContractImplementationHelper
Dependencias Técnicas
Dependencias de Desarrollo
{
"@gograb-space/utilities": "^1.0.0",
"@libs-core/log-system": "^1.0.0",
"@libs-core/event-system": "^1.0.0",
"@libs-core/action-registry": "^1.0.0",
"@libs-core/data-access": "^1.0.0",
"@libs-core/security": "^1.0.0",
"@angular/core": "^20.0.0",
"rxjs": "^7.8.0",
"@ngxs/store": "^3.8.1"
}
Peer Dependencies
{
"@angular/common": "^20.0.0",
"@angular/core": "^20.0.0",
"rxjs": "^7.8.0"
}
Cronograma de Implementación
Fase 1: Fundamentos (Pasos 1-3)
- Estructura de directorios simplificada
- Modelos y tipos fundamentales
- Contratos principales del sistema
Fase 2: Servicios y Estado (Pasos 4-5)
- Servicios base del sistema
- Sistema de gestión de estado
- Sistema de acciones
- Integración con NGXS y signals
Fase 3: Componentes y UI (Pasos 6-7)
- Componentes base
- Servicios base de módulos
- Layout y comunicación
Fase 4: Herramientas (Pasos 8-9)
- Decoradores principales
- Utilidades para implementación
- Eventos del ciclo de vida
Fase 5: Testing y Finalización (Pasos 10-12)
- Tests comprehensivos
- Integración Angular 20 y Browser APIs
- Integración final con @libs-core/security para multitenancy
- Documentación completa
Consideraciones Técnicas
Angular 20 Features
- Standalone Components: Todos los componentes deben ser standalone
- Signals: Preferir signals sobre Observables para estado reactivo
- OnPush Change Detection: Implementar estrategia OnPush
- New Control Flow: Usar @if, @for, @switch
- inject() function: Usar inject() para inyección de dependencias
Performance
- Tree Shaking: Estructura optimizada para eliminación de código muerto
- Bundle Splitting: Configuración para code splitting automático
- Memory Management: Patrones para gestión eficiente en navegador
- Lazy Loading: Soporte para import() dinámico
Security
- CSP Compliance: Validación de Content Security Policy
- Permission System: Sistema de permisos por módulo
- Input Validation: Validación estricta de inputs
- XSS Protection: Protección contra cross-site scripting
Browser Compatibility
- Angular Nativo: Carga estática de módulos con Angular standalone components
- Service Workers: Integración con service workers para offline
- Web Workers: Soporte para procesamiento en background
- Progressive Enhancement: Mejoras progresivas basadas en capacidades del navegador
Configuración Específica por Módulo
Enfoque simplificado: Pasar configuración directamente al módulo, sin tokens de Angular:
// Contrato base con método configure que recibe configuración específica
export interface BrowserModuleContract {
readonly manifest: ModuleManifest;
configure<T = ModuleConfig>(config: T): Promise<void>;
initialize(): Promise<void>;
start(): Promise<void>;
stop(): Promise<void>;
destroy(): Promise<void>;
}
// Servicio para resolver configuración por módulo desde API
@Injectable({ providedIn: 'root' })
export class ModuleConfigService {
constructor(private authService: AuthService) {}
async getModuleConfig<T = ModuleConfig>(moduleId: string): Promise<T | undefined> {
const tenantContext = this.authService.getCurrentTenantContext();
return await this.loadConfigForModule(moduleId, tenantContext?.tenantId);
}
}
Uso en Módulos:
// Interface específica del módulo
interface UserModuleConfig {
enableAdvancedSearch: boolean;
maxUsers: number;
features: string[];
}
@ModuleDecorator({
id: 'user-management',
version: '1.0.0',
})
export class UserManagementModule implements BrowserModuleContract {
private config: UserModuleConfig | null = null;
constructor(private authService: AuthService) {}
async configure<UserModuleConfig>(config: UserModuleConfig): Promise<void> {
this.config = config;
console.log('User module configured with:', this.config);
}
async initialize(): Promise<void> {
if (!this.config) {
throw new Error('Module must be configured before initialization');
}
// Usar configuración específica del módulo
if (this.config.enableAdvancedSearch) {
await this.initializeAdvancedSearch();
}
// Configuración diferente para cada módulo:
// - user-management: { enableAdvancedSearch: true, maxUsers: 1000 }
// - product-catalog: { enableRecommendations: false, maxProducts: 1000 }
// - order-management: { allowCancelation: true, timeoutMinutes: 30 }
}
async start(): Promise<void> {
// Lógica de inicio usando this.config
}
}
Integración con Security para Multitenancy
Module-base ahora consume directamente los servicios de multitenancy desde @libs-core/security. Todos los tokens relacionados con tenant (incluyendo API_BASE_URL_TOKEN) están en security porque cada tenant puede tener su propia configuración de API:
// Los módulos consumen tenant context desde security
@ModuleDecorator({
id: 'user-management',
version: '1.0.0',
})
export class UserManagementModule implements BrowserModuleContract {
constructor(
private authService: AuthService, // Desde @libs-core/security
private logSystem: LogSystem,
private eventSystem: EventSystem
) {}
async initialize(): Promise<void> {
// Obtener contexto de tenant desde security
const tenantContext = this.authService.getCurrentTenantContext();
if (tenantContext) {
this.logSystem.info('Module initialized for tenant', {
tenantId: tenantContext.tenantId,
});
await this.loadTenantSpecificConfiguration(tenantContext);
}
}
private async loadTenantSpecificConfiguration(context: TenantContext): Promise<void> {
// La configuración específica del tenant viene desde security
const permissions = this.authService.getCurrentPermissions();
// Configurar módulo basado en permisos del tenant actual
}
}
Sistema de Auto-Registro y Configuración API
Auto-Registro Simplificado (Carga Estática)
// Decorador para auto-registro con carga nativa de Angular
@ModuleDecorator({
id: 'user-management',
version: '1.0.0',
autoRegister: true, // Auto-registro al cargar la aplicación
})
export class UserManagementModule implements BrowserModuleContract {
constructor(private authService: AuthService) {}
async initialize(): Promise<void> {
// Inicialización del módulo
const tenantContext = this.authService.getCurrentTenantContext();
if (tenantContext) {
await this.loadTenantSpecificConfiguration(tenantContext);
}
}
}
// Servicio de registro central
@Injectable({ providedIn: 'root' })
export class ModuleRegistryService {
private readonly registry = new Map<string, BrowserModuleContract>();
registerModule(module: BrowserModuleContract): void {
this.registry.set(module.manifest.id, module);
this.eventSystem.emit(new ModuleRegisteredEvent(module.manifest.id));
}
getModules(): BrowserModuleContract[] {
return Array.from(this.registry.values());
}
getModule(moduleId: string): BrowserModuleContract | undefined {
return this.registry.get(moduleId);
}
}
Configuración API con Tokens Específicos
// Servicio de configuración que resuelve configs específicas por módulo
@Injectable({ providedIn: 'root' })
export class ModuleConfigurationService {
constructor(
private configService: AppConfigService,
private authService: AuthService // Para obtener tenant context desde security
) {}
async getModuleConfiguration(): Promise<Record<string, ModuleConfig>> {
const tenantContext = this.authService.getCurrentTenantContext();
return await this.configService.getModuleConfiguration(tenantContext?.tenantId);
}
async getModuleConfig<T = ModuleConfig>(moduleId: string): Promise<T | undefined> {
const config = await this.getModuleConfiguration();
return config[moduleId] as T;
}
}
// Ejemplo: Diferentes configuraciones por módulo y tenant
// Tenant A - user-management: { enableAdvancedSearch: true, maxUsers: 1000 }
// Tenant A - product-catalog: { enableRecommendations: true, maxProducts: 10000 }
// Tenant B - user-management: { enableAdvancedSearch: false, maxUsers: 100 }
// Tenant B - product-catalog: { enableRecommendations: false, maxProducts: 1000 }
Integración con Module Integrator
// Module Integrator simplificado - multitenancy manejado por security
@Injectable({ providedIn: 'root' })
export class ModuleIntegratorService {
constructor(
private configService: AppConfigService,
private registry: ModuleRegistryService,
private authService: AuthService, // Security maneja tenant context
private eventSystem: EventSystem,
private logSystem: LogSystem
) {}
async initializeApplication(): Promise<void> {
this.eventSystem.emit(new ApplicationInitializingEvent());
try {
// 1. Cargar configuración de módulos
const moduleConfig = await this.configService.getModuleConfiguration();
// 2. Obtener módulos registrados
const registeredModules = this.registry.getModules();
// 3. Gestionar ciclo de vida de módulos
for (const module of registeredModules) {
const config = moduleConfig[module.manifest.id];
await this.manageModuleLifecycle(module, config);
}
this.eventSystem.emit(new ApplicationInitializedEvent());
this.logSystem.info('Application initialized successfully');
} catch (error) {
this.logSystem.error('Failed to initialize application', { error });
throw error;
}
}
private async manageModuleLifecycle(module: BrowserModuleContract, config: ModuleConfig): Promise<void> {
try {
if (config?.enabled && this.validateModuleAccess(module)) {
this.logSystem.debug(`Activating module: ${module.manifest.id}`);
// 1. Configurar módulo con su configuración específica
await module.configure(config);
// 2. Inicializar módulo (tenant context viene desde security)
await module.initialize();
// 3. Iniciar módulo
await module.start();
this.eventSystem.emit(new ModuleActivatedEvent(module.manifest.id));
}
} catch (error) {
this.logSystem.error(`Failed to manage module lifecycle: ${module.manifest.id}`, { error });
}
}
private validateModuleAccess(module: BrowserModuleContract): boolean {
// Validación de acceso usando security service
return this.authService.hasModulePermission(module.manifest.id);
}
}
Integración con Librerías Core
// Ejemplo simplificado: Módulo con configuración directa (sin tokens)
interface UserModuleConfig {
enableAdvancedSearch: boolean;
maxUsers: number;
allowBulkOperations: boolean;
}
@ModuleDecorator({
id: 'user-management',
version: '1.0.0',
})
export class UserManagementModule implements BrowserModuleContract {
private config: UserModuleConfig | null = null;
constructor(
private logSystem: LogSystem,
private eventSystem: EventSystem,
private actionRegistry: ActionRegistryService,
private dataAccess: DataAccessService,
private authService: AuthService, // Todo el contexto tenant viene de security
private utilities: ValidationUtils
) {}
async configure(config: UserModuleConfig): Promise<void> {
this.config = config;
this.logSystem.debug('User module configured', { config });
}
async initialize(): Promise<void> {
if (!this.config) {
throw new Error('Module must be configured before initialization');
}
// Obtener contexto tenant desde security
const tenantContext = this.authService.getCurrentTenantContext();
if (tenantContext) {
// Registrar acciones basadas en configuración
this.actionRegistry.registerActions(this.getModuleActions());
// Configurar listeners de eventos
this.eventSystem.subscribe('user-created', this.handleUserCreated.bind(this));
// Verificar permisos usando security
if (!this.authService.hasPermission('users:manage')) {
throw new Error('Insufficient permissions for user management');
}
this.logSystem.info('UserManagement module initialized', {
tenantId: tenantContext.tenantId,
config: this.config,
});
}
}
private getModuleActions(): ActionConfig[] {
const actions = [
{
id: 'create-user',
action: this.createUser.bind(this),
permissions: ['users:write'],
validation: this.utilities.validateUserData.bind(this),
},
];
// Agregar acciones basadas en configuración
if (this.config?.allowBulkOperations) {
actions.push({
id: 'bulk-create-users',
action: this.bulkCreateUsers.bind(this),
permissions: ['users:bulk-write'],
});
}
return actions;
}
@PublicAction()
async createUser(userData: UserData): Promise<User> {
// Validar límites basados en configuración
if (this.config?.maxUsers && (await this.getUserCount()) >= this.config.maxUsers) {
throw new Error('Maximum user limit reached');
}
// El tenant context es manejado automáticamente por security
return this.dataAccess.create<User>('users', userData);
}
}
Métricas de Éxito
Funcionalidad Core
- Contratos Claros: Interfaces bien definidas para implementación de módulos
- Auto-registro: Módulos se registran automáticamente al cargar
- Configuración Directa: Cada módulo recibe su configuración via
configure()- sin tokens - Integración Security: Consumo transparente de multitenancy desde @libs-core/security
- API Ultra-Simple: Sin factory functions ni complejidad de Angular DI
Calidad y Performance
- Coverage: ≥ 90% unit tests, ≥ 85% integration tests
- Bundle Size: < 12KB gzipped (solo contratos, clases base y servicios mínimos - sin tokens, Module Federation ni asset loading)
- Type Safety: 100% tipado, sin uso de
any - Documentation: APIs completamente documentadas con ejemplos
Compatibilidad
- Angular 20: Uso completo de features modernas (signals, standalone components)
- Browser Support: Compatible con navegadores modernos
- Security Integration: Integración transparente con @libs-core/security para multitenancy
Consideraciones de Implementación
Prioridades de Desarrollo
- Paso 1-3: Contratos sólidos y modelos fundamentales
- Paso 4-6: Servicios base, estado y componentes
- Paso 7-9: Decoradores, utilidades y eventos
- Paso 10-12: Integración Angular 20 y testing exhaustivo
Criterios de Calidad
- Testing automático en cada paso
- Integración continua con @libs-core/security
- Validación de contratos en todos los componentes
- API simple y fácil de usar
Próximos Pasos Inmediatos
- Crear estructura base según Paso 1
- Implementar modelos fundamentales según Paso 2
- Definir contratos principales según Paso 3
- Coordinar con @libs-core/security para tokens de multitenancy (
API_BASE_URL_TOKEN, etc.) - Configurar testing environment con integración a @libs-core/security
- Establecer CI/CD pipeline con validación de contratos
Comandos de Desarrollo
# Desarrollo y testing
nx test module-base --watch
nx lint module-base
nx build module-base
# Análisis de dependencias
nx graph --focus=module-base
# Testing de integración con security
nx test module-base --grep="security"
Este plan proporciona una base sólida para implementar module-base como una librería de contratos y clases base ultra-simplificada con configuración directa por módulo (sin tokens, factory functions ni Module Federation), usando únicamente carga nativa de Angular, delegando toda la funcionalidad de multitenancy a @libs-core/security, manteniendo la consistencia arquitectónica y la máxima simplicidad en el ecosistema GoGrab Space.