@dofe/infra-module-registry 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,88 @@
1
+ import { DynamicModule, Provider, Type } from '@nestjs/common';
2
+ import { ModuleRegistration } from './module-registry.service';
3
+ /**
4
+ * Feature module configuration
5
+ */
6
+ export interface FeatureConfig {
7
+ /** Feature identifier */
8
+ id: string;
9
+ /** Module IDs to include */
10
+ modules: string[];
11
+ /** Additional providers to register */
12
+ providers?: Provider[];
13
+ /** Additional exports */
14
+ exports?: (string | Type<any>)[];
15
+ }
16
+ /**
17
+ * Options for DynamicFeatureModule
18
+ */
19
+ export interface DynamicFeatureModuleOptions {
20
+ /** Feature configurations */
21
+ features: FeatureConfig[];
22
+ /** Auto-register modules to registry */
23
+ autoRegister?: boolean;
24
+ /** Global module (available everywhere) */
25
+ isGlobal?: boolean;
26
+ }
27
+ /**
28
+ * Dynamic module that loads feature-specific modules on demand.
29
+ *
30
+ * Reduces the "dependency explosion" problem by grouping related modules
31
+ * and loading them conditionally based on feature flags or configuration.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * @Module({
36
+ * imports: [
37
+ * DynamicFeatureModule.register({
38
+ * features: [
39
+ * {
40
+ * id: 'bot-management',
41
+ * modules: ['bot-query', 'bot-sse', 'bot-config-resolver'],
42
+ * },
43
+ * {
44
+ * id: 'model-management',
45
+ * modules: ['model-sync', 'model-verification'],
46
+ * },
47
+ * ],
48
+ * }),
49
+ * ],
50
+ * })
51
+ * export class BotApiModule {}
52
+ * ```
53
+ */
54
+ export declare class DynamicFeatureModule {
55
+ /**
56
+ * Create a dynamic module with feature-based loading
57
+ */
58
+ static register(options: DynamicFeatureModuleOptions): DynamicModule;
59
+ /**
60
+ * Create a dynamic module with pre-configured module map
61
+ *
62
+ * Use this when you have a static mapping of module IDs to classes
63
+ */
64
+ static withModuleMap(moduleMap: Record<string, Type<any>>, featureIds: string[], options?: {
65
+ isGlobal?: boolean;
66
+ }): DynamicModule;
67
+ /**
68
+ * Create a dynamic module with registry integration
69
+ *
70
+ * This approach registers all modules to the registry first,
71
+ * then uses dependency resolution to determine load order
72
+ */
73
+ static withRegistry(registrations: ModuleRegistration[], options?: {
74
+ categories?: string[];
75
+ includeOptional?: boolean;
76
+ isGlobal?: boolean;
77
+ }): DynamicModule;
78
+ /**
79
+ * Resolve module ID to class
80
+ *
81
+ * In a real implementation, this could use:
82
+ * - A static module map
83
+ * - Dynamic import()
84
+ * - ModuleRegistry lookup
85
+ */
86
+ private static resolveModule;
87
+ }
88
+ //# sourceMappingURL=dynamic-feature.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic-feature.module.d.ts","sourceRoot":"","sources":["../src/dynamic-feature.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAU,QAAQ,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAkB,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/E;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,4BAA4B;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,uCAAuC;IACvC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,yBAAyB;IACzB,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,6BAA6B;IAC7B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,wCAAwC;IACxC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBACa,oBAAoB;IAC/B;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,2BAA2B,GAAG,aAAa;IAiCpE;;;;OAIG;IACH,MAAM,CAAC,aAAa,CAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EACpC,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAC/B,aAAa;IAiBhB;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CACjB,aAAa,EAAE,kBAAkB,EAAE,EACnC,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QACtB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;KACpB,GACA,aAAa;IAoBhB;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;CAY7B"}
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var DynamicFeatureModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.DynamicFeatureModule = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const module_registry_service_1 = require("./module-registry.service");
13
+ /**
14
+ * Dynamic module that loads feature-specific modules on demand.
15
+ *
16
+ * Reduces the "dependency explosion" problem by grouping related modules
17
+ * and loading them conditionally based on feature flags or configuration.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * @Module({
22
+ * imports: [
23
+ * DynamicFeatureModule.register({
24
+ * features: [
25
+ * {
26
+ * id: 'bot-management',
27
+ * modules: ['bot-query', 'bot-sse', 'bot-config-resolver'],
28
+ * },
29
+ * {
30
+ * id: 'model-management',
31
+ * modules: ['model-sync', 'model-verification'],
32
+ * },
33
+ * ],
34
+ * }),
35
+ * ],
36
+ * })
37
+ * export class BotApiModule {}
38
+ * ```
39
+ */
40
+ let DynamicFeatureModule = DynamicFeatureModule_1 = class DynamicFeatureModule {
41
+ /**
42
+ * Create a dynamic module with feature-based loading
43
+ */
44
+ static register(options) {
45
+ const { features, autoRegister = true, isGlobal = false } = options;
46
+ // Collect all module classes from features
47
+ const moduleClasses = [];
48
+ const providers = [];
49
+ const exports = [];
50
+ for (const feature of features) {
51
+ for (const moduleId of feature.modules) {
52
+ // In a real implementation, we would resolve module IDs to actual classes
53
+ // For now, this requires pre-registered modules in ModuleRegistry
54
+ moduleClasses.push(this.resolveModule(moduleId));
55
+ }
56
+ if (feature.providers) {
57
+ providers.push(...feature.providers);
58
+ }
59
+ if (feature.exports) {
60
+ exports.push(...feature.exports);
61
+ }
62
+ }
63
+ return {
64
+ module: DynamicFeatureModule_1,
65
+ imports: moduleClasses,
66
+ providers: autoRegister ? [module_registry_service_1.ModuleRegistry, ...providers] : providers,
67
+ exports: [...exports],
68
+ global: isGlobal,
69
+ };
70
+ }
71
+ /**
72
+ * Create a dynamic module with pre-configured module map
73
+ *
74
+ * Use this when you have a static mapping of module IDs to classes
75
+ */
76
+ static withModuleMap(moduleMap, featureIds, options) {
77
+ const modules = [];
78
+ for (const id of featureIds) {
79
+ const moduleClass = moduleMap[id];
80
+ if (moduleClass) {
81
+ modules.push(moduleClass);
82
+ }
83
+ }
84
+ return {
85
+ module: DynamicFeatureModule_1,
86
+ imports: modules,
87
+ global: options?.isGlobal,
88
+ };
89
+ }
90
+ /**
91
+ * Create a dynamic module with registry integration
92
+ *
93
+ * This approach registers all modules to the registry first,
94
+ * then uses dependency resolution to determine load order
95
+ */
96
+ static withRegistry(registrations, options) {
97
+ // Create a temporary registry for resolution
98
+ const registry = new module_registry_service_1.ModuleRegistry();
99
+ registry.registerAll(registrations);
100
+ // Get modules in dependency order
101
+ const modules = registry.getModuleClasses({
102
+ categories: options?.categories,
103
+ includeOptional: options?.includeOptional,
104
+ });
105
+ return {
106
+ module: DynamicFeatureModule_1,
107
+ imports: modules,
108
+ providers: [module_registry_service_1.ModuleRegistry],
109
+ exports: [module_registry_service_1.ModuleRegistry],
110
+ global: options?.isGlobal,
111
+ };
112
+ }
113
+ /**
114
+ * Resolve module ID to class
115
+ *
116
+ * In a real implementation, this could use:
117
+ * - A static module map
118
+ * - Dynamic import()
119
+ * - ModuleRegistry lookup
120
+ */
121
+ static resolveModule(moduleId) {
122
+ // Placeholder - in real implementation, this would resolve to actual module class
123
+ // For now, return a dummy module that will be replaced
124
+ let PlaceholderModule = class PlaceholderModule {
125
+ };
126
+ PlaceholderModule = __decorate([
127
+ (0, common_1.Module)({})
128
+ ], PlaceholderModule);
129
+ Object.defineProperty(PlaceholderModule, 'name', {
130
+ value: `Placeholder_${moduleId}`,
131
+ });
132
+ return PlaceholderModule;
133
+ }
134
+ };
135
+ exports.DynamicFeatureModule = DynamicFeatureModule;
136
+ exports.DynamicFeatureModule = DynamicFeatureModule = DynamicFeatureModule_1 = __decorate([
137
+ (0, common_1.Module)({})
138
+ ], DynamicFeatureModule);
139
+ //# sourceMappingURL=dynamic-feature.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic-feature.module.js","sourceRoot":"","sources":["../src/dynamic-feature.module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * ModuleRegistry 模块导出
3
+ *
4
+ * 提供通用的模块注册和动态加载功能,不包含任何业务模块定义。
5
+ * 业务模块映射应放在各自的 API 模块或 domain 层。
6
+ */
7
+ export { ModuleRegistryModule } from './module-registry.module';
8
+ export { ModuleRegistry } from './module-registry.service';
9
+ export type { ModuleRegistration, ModuleCategory, ModuleGroupConfig, } from './module-registry.service';
10
+ export { DynamicFeatureModule } from './dynamic-feature.module';
11
+ export { RegisterModule, type RegisterModuleMetadata, } from './register-module.decorator';
12
+ export { ModuleScanner, MODULE_SCANNER_OPTIONS, type ModuleScannerOptions, } from './module-scanner.service';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGhE,OAAO,EACL,cAAc,EACd,KAAK,sBAAsB,GAC5B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,KAAK,oBAAoB,GAC1B,MAAM,0BAA0B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ /**
3
+ * ModuleRegistry 模块导出
4
+ *
5
+ * 提供通用的模块注册和动态加载功能,不包含任何业务模块定义。
6
+ * 业务模块映射应放在各自的 API 模块或 domain 层。
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.MODULE_SCANNER_OPTIONS = exports.ModuleScanner = exports.RegisterModule = exports.DynamicFeatureModule = exports.ModuleRegistry = exports.ModuleRegistryModule = void 0;
10
+ var module_registry_module_1 = require("./module-registry.module");
11
+ Object.defineProperty(exports, "ModuleRegistryModule", { enumerable: true, get: function () { return module_registry_module_1.ModuleRegistryModule; } });
12
+ var module_registry_service_1 = require("./module-registry.service");
13
+ Object.defineProperty(exports, "ModuleRegistry", { enumerable: true, get: function () { return module_registry_service_1.ModuleRegistry; } });
14
+ var dynamic_feature_module_1 = require("./dynamic-feature.module");
15
+ Object.defineProperty(exports, "DynamicFeatureModule", { enumerable: true, get: function () { return dynamic_feature_module_1.DynamicFeatureModule; } });
16
+ // Auto-registration
17
+ var register_module_decorator_1 = require("./register-module.decorator");
18
+ Object.defineProperty(exports, "RegisterModule", { enumerable: true, get: function () { return register_module_decorator_1.RegisterModule; } });
19
+ var module_scanner_service_1 = require("./module-scanner.service");
20
+ Object.defineProperty(exports, "ModuleScanner", { enumerable: true, get: function () { return module_scanner_service_1.ModuleScanner; } });
21
+ Object.defineProperty(exports, "MODULE_SCANNER_OPTIONS", { enumerable: true, get: function () { return module_scanner_service_1.MODULE_SCANNER_OPTIONS; } });
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,mEAAgE;AAAvD,8HAAA,oBAAoB,OAAA;AAC7B,qEAA2D;AAAlD,yHAAA,cAAc,OAAA;AAMvB,mEAAgE;AAAvD,8HAAA,oBAAoB,OAAA;AAE7B,oBAAoB;AACpB,yEAGqC;AAFnC,2HAAA,cAAc,OAAA;AAGhB,mEAIkC;AAHhC,uHAAA,aAAa,OAAA;AACb,gIAAA,sBAAsB,OAAA"}
@@ -0,0 +1,13 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import { ModuleScannerOptions } from './module-scanner.service';
3
+ export declare class ModuleRegistryModule {
4
+ /**
5
+ * Register with custom scanner options
6
+ */
7
+ static withOptions(options: ModuleScannerOptions): DynamicModule;
8
+ /**
9
+ * Register without auto-scan (manual registration only)
10
+ */
11
+ static withoutAutoScan(): DynamicModule;
12
+ }
13
+ //# sourceMappingURL=module-registry.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-registry.module.d.ts","sourceRoot":"","sources":["../src/module-registry.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,aAAa,EAAY,MAAM,gBAAgB,CAAC;AAEzE,OAAO,EAGL,oBAAoB,EACrB,MAAM,0BAA0B,CAAC;AAElC,qBAKa,oBAAoB;IAC/B;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa;IAchE;;OAEG;IACH,MAAM,CAAC,eAAe,IAAI,aAAa;CAGxC"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var ModuleRegistryModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ModuleRegistryModule = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const module_registry_service_1 = require("./module-registry.service");
13
+ const module_scanner_service_1 = require("./module-scanner.service");
14
+ let ModuleRegistryModule = ModuleRegistryModule_1 = class ModuleRegistryModule {
15
+ /**
16
+ * Register with custom scanner options
17
+ */
18
+ static withOptions(options) {
19
+ const optionsProvider = {
20
+ provide: module_scanner_service_1.MODULE_SCANNER_OPTIONS,
21
+ useValue: options,
22
+ };
23
+ return {
24
+ module: ModuleRegistryModule_1,
25
+ providers: [module_registry_service_1.ModuleRegistry, module_scanner_service_1.ModuleScanner, optionsProvider],
26
+ exports: [module_registry_service_1.ModuleRegistry, module_scanner_service_1.ModuleScanner],
27
+ global: true,
28
+ };
29
+ }
30
+ /**
31
+ * Register without auto-scan (manual registration only)
32
+ */
33
+ static withoutAutoScan() {
34
+ return this.withOptions({ autoScan: false });
35
+ }
36
+ };
37
+ exports.ModuleRegistryModule = ModuleRegistryModule;
38
+ exports.ModuleRegistryModule = ModuleRegistryModule = ModuleRegistryModule_1 = __decorate([
39
+ (0, common_1.Global)(),
40
+ (0, common_1.Module)({
41
+ providers: [module_registry_service_1.ModuleRegistry, module_scanner_service_1.ModuleScanner],
42
+ exports: [module_registry_service_1.ModuleRegistry, module_scanner_service_1.ModuleScanner],
43
+ })
44
+ ], ModuleRegistryModule);
45
+ //# sourceMappingURL=module-registry.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-registry.module.js","sourceRoot":"","sources":["../src/module-registry.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAyE;AACzE,uEAA2D;AAC3D,qEAIkC;AAO3B,IAAM,oBAAoB,4BAA1B,MAAM,oBAAoB;IAC/B;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,OAA6B;QAC9C,MAAM,eAAe,GAAa;YAChC,OAAO,EAAE,+CAAsB;YAC/B,QAAQ,EAAE,OAAO;SAClB,CAAC;QAEF,OAAO;YACL,MAAM,EAAE,sBAAoB;YAC5B,SAAS,EAAE,CAAC,wCAAc,EAAE,sCAAa,EAAE,eAAe,CAAC;YAC3D,OAAO,EAAE,CAAC,wCAAc,EAAE,sCAAa,CAAC;YACxC,MAAM,EAAE,IAAI;SACb,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,eAAe;QACpB,OAAO,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC;CACF,CAAA;AAxBY,oDAAoB;+BAApB,oBAAoB;IALhC,IAAA,eAAM,GAAE;IACR,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,CAAC,wCAAc,EAAE,sCAAa,CAAC;QAC1C,OAAO,EAAE,CAAC,wCAAc,EAAE,sCAAa,CAAC;KACzC,CAAC;GACW,oBAAoB,CAwBhC"}
@@ -0,0 +1,130 @@
1
+ import { OnModuleInit, Type } from '@nestjs/common';
2
+ /**
3
+ * Module feature category for grouping related modules
4
+ */
5
+ export type ModuleCategory = 'database' | 'cache' | 'queue' | 'client' | 'domain' | 'infrastructure' | 'integration' | 'feature' | 'monitoring' | 'optional';
6
+ /**
7
+ * Module registration metadata
8
+ */
9
+ export interface ModuleRegistration {
10
+ /** Unique module identifier */
11
+ id: string;
12
+ /** Module category for grouping */
13
+ category: ModuleCategory;
14
+ /** Module class reference */
15
+ module: Type<any>;
16
+ /** Human-readable name */
17
+ name?: string;
18
+ /** Module description */
19
+ description?: string;
20
+ /** Dependencies (module IDs that must be loaded first) */
21
+ dependencies?: string[];
22
+ /** Whether module is required for app to function */
23
+ required?: boolean;
24
+ /** Whether module is enabled (can be toggled via config) */
25
+ enabled?: boolean;
26
+ /** Priority for load order (lower = earlier) */
27
+ priority?: number;
28
+ }
29
+ /**
30
+ * Module group configuration
31
+ */
32
+ export interface ModuleGroupConfig {
33
+ /** Group ID */
34
+ id: string;
35
+ /** Display name */
36
+ name: string;
37
+ /** Module IDs in this group */
38
+ modules: string[];
39
+ /** Whether all modules in group are required */
40
+ required?: boolean;
41
+ /** Whether group is enabled by default */
42
+ enabled?: boolean;
43
+ }
44
+ /**
45
+ * Registry for dynamic module loading and dependency management.
46
+ *
47
+ * Provides:
48
+ * - Module registration with metadata
49
+ * - Dependency resolution
50
+ * - Conditional loading based on config
51
+ * - Load order optimization
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * // Register a module
56
+ * moduleRegistry.register({
57
+ * id: 'bot-query',
58
+ * category: 'domain',
59
+ * module: BotQueryModule,
60
+ * dependencies: ['prisma', 'redis'],
61
+ * });
62
+ *
63
+ * // Get modules for a feature
64
+ * const modules = moduleRegistry.getModulesForFeature('bot-management');
65
+ * ```
66
+ */
67
+ export declare class ModuleRegistry implements OnModuleInit {
68
+ private readonly logger;
69
+ private readonly registrations;
70
+ private readonly categories;
71
+ private initialized;
72
+ onModuleInit(): Promise<void>;
73
+ /**
74
+ * Register a module with metadata
75
+ */
76
+ register(registration: ModuleRegistration): void;
77
+ /**
78
+ * Register multiple modules at once
79
+ */
80
+ registerAll(registrations: ModuleRegistration[]): void;
81
+ /**
82
+ * Get a module registration by ID
83
+ */
84
+ get(id: string): ModuleRegistration | undefined;
85
+ /**
86
+ * Check if a module is registered
87
+ */
88
+ has(id: string): boolean;
89
+ /**
90
+ * Get all registered module IDs
91
+ */
92
+ getAllIds(): string[];
93
+ /**
94
+ * Get all registrations
95
+ */
96
+ getAllRegistrations(): ModuleRegistration[];
97
+ /**
98
+ * Get modules by category
99
+ */
100
+ getByCategory(category: ModuleCategory): ModuleRegistration[];
101
+ /**
102
+ * Get module classes for dynamic import, sorted by dependencies and priority
103
+ */
104
+ getModuleClasses(options?: {
105
+ categories?: ModuleCategory[];
106
+ includeOptional?: boolean;
107
+ onlyEnabled?: boolean;
108
+ }): Type<any>[];
109
+ /**
110
+ * Get module classes for a specific feature set
111
+ */
112
+ getModulesForFeature(featureIds: string[]): Type<any>[];
113
+ /**
114
+ * Validate all module dependencies exist
115
+ */
116
+ private validateDependencies;
117
+ /**
118
+ * Get all dependencies for a module recursively
119
+ */
120
+ private getDependenciesRecursive;
121
+ /**
122
+ * Topological sort for dependency-ordered loading
123
+ */
124
+ private topologicalSort;
125
+ /**
126
+ * Log registration summary
127
+ */
128
+ private logRegistrationSummary;
129
+ }
130
+ //# sourceMappingURL=module-registry.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-registry.service.d.ts","sourceRoot":"","sources":["../src/module-registry.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,YAAY,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,UAAU,GACV,OAAO,GACP,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,gBAAgB,GAChB,aAAa,GACb,SAAS,GACT,YAAY,GACZ,UAAU,CAAC;AAEf;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,mCAAmC;IACnC,QAAQ,EAAE,cAAc,CAAC;IACzB,6BAA6B;IAC7B,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,eAAe;IACf,EAAE,EAAE,MAAM,CAAC;IACX,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBACa,cAAe,YAAW,YAAY;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmC;IAC1D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAyC;IACvE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0C;IACrE,OAAO,CAAC,WAAW,CAAS;IAEtB,YAAY;IAYlB;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,kBAAkB,GAAG,IAAI;IAoBhD;;OAEG;IACH,WAAW,CAAC,aAAa,EAAE,kBAAkB,EAAE,GAAG,IAAI;IAMtD;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAI/C;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIxB;;OAEG;IACH,SAAS,IAAI,MAAM,EAAE;IAIrB;;OAEG;IACH,mBAAmB,IAAI,kBAAkB,EAAE;IAI3C;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,cAAc,GAAG,kBAAkB,EAAE;IAS7D;;OAEG;IACH,gBAAgB,CAAC,OAAO,CAAC,EAAE;QACzB,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;QAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE;IA+Bf;;OAEG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE;IAqBvD;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAsB5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAkBhC;;OAEG;IACH,OAAO,CAAC,eAAe;IA2CvB;;OAEG;IACH,OAAO,CAAC,sBAAsB;CAe/B"}
@@ -0,0 +1,239 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var ModuleRegistry_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ModuleRegistry = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ /**
13
+ * Registry for dynamic module loading and dependency management.
14
+ *
15
+ * Provides:
16
+ * - Module registration with metadata
17
+ * - Dependency resolution
18
+ * - Conditional loading based on config
19
+ * - Load order optimization
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Register a module
24
+ * moduleRegistry.register({
25
+ * id: 'bot-query',
26
+ * category: 'domain',
27
+ * module: BotQueryModule,
28
+ * dependencies: ['prisma', 'redis'],
29
+ * });
30
+ *
31
+ * // Get modules for a feature
32
+ * const modules = moduleRegistry.getModulesForFeature('bot-management');
33
+ * ```
34
+ */
35
+ let ModuleRegistry = ModuleRegistry_1 = class ModuleRegistry {
36
+ logger = new common_1.Logger(ModuleRegistry_1.name);
37
+ registrations = new Map();
38
+ categories = new Map();
39
+ initialized = false;
40
+ async onModuleInit() {
41
+ if (this.initialized)
42
+ return;
43
+ // Validate dependencies after all registrations
44
+ this.validateDependencies();
45
+ // Log registration summary
46
+ this.logRegistrationSummary();
47
+ this.initialized = true;
48
+ }
49
+ /**
50
+ * Register a module with metadata
51
+ */
52
+ register(registration) {
53
+ if (this.registrations.has(registration.id)) {
54
+ this.logger.warn(`Module "${registration.id}" already registered, overwriting`);
55
+ }
56
+ this.registrations.set(registration.id, registration);
57
+ // Add to category index
58
+ if (!this.categories.has(registration.category)) {
59
+ this.categories.set(registration.category, new Set());
60
+ }
61
+ this.categories.get(registration.category).add(registration.id);
62
+ this.logger.debug(`Registered module: ${registration.id} [${registration.category}]`);
63
+ }
64
+ /**
65
+ * Register multiple modules at once
66
+ */
67
+ registerAll(registrations) {
68
+ for (const reg of registrations) {
69
+ this.register(reg);
70
+ }
71
+ }
72
+ /**
73
+ * Get a module registration by ID
74
+ */
75
+ get(id) {
76
+ return this.registrations.get(id);
77
+ }
78
+ /**
79
+ * Check if a module is registered
80
+ */
81
+ has(id) {
82
+ return this.registrations.has(id);
83
+ }
84
+ /**
85
+ * Get all registered module IDs
86
+ */
87
+ getAllIds() {
88
+ return Array.from(this.registrations.keys());
89
+ }
90
+ /**
91
+ * Get all registrations
92
+ */
93
+ getAllRegistrations() {
94
+ return Array.from(this.registrations.values());
95
+ }
96
+ /**
97
+ * Get modules by category
98
+ */
99
+ getByCategory(category) {
100
+ const ids = this.categories.get(category);
101
+ if (!ids)
102
+ return [];
103
+ return Array.from(ids)
104
+ .map((id) => this.registrations.get(id))
105
+ .filter(Boolean);
106
+ }
107
+ /**
108
+ * Get module classes for dynamic import, sorted by dependencies and priority
109
+ */
110
+ getModuleClasses(options) {
111
+ const { categories, includeOptional = true, onlyEnabled = true, } = options || {};
112
+ // Filter registrations
113
+ let filtered = this.getAllRegistrations();
114
+ // Filter by category
115
+ if (categories?.length) {
116
+ filtered = filtered.filter((r) => categories.includes(r.category));
117
+ }
118
+ // Filter by enabled status
119
+ if (onlyEnabled) {
120
+ filtered = filtered.filter((r) => r.enabled !== false);
121
+ }
122
+ // Filter optional modules
123
+ if (!includeOptional) {
124
+ filtered = filtered.filter((r) => r.required !== false);
125
+ }
126
+ // Sort by dependencies and priority
127
+ const sorted = this.topologicalSort(filtered);
128
+ return sorted.map((r) => r.module);
129
+ }
130
+ /**
131
+ * Get module classes for a specific feature set
132
+ */
133
+ getModulesForFeature(featureIds) {
134
+ const featureModules = [];
135
+ for (const id of featureIds) {
136
+ const reg = this.registrations.get(id);
137
+ if (reg) {
138
+ featureModules.push(reg);
139
+ // Include dependencies
140
+ const deps = this.getDependenciesRecursive(id);
141
+ for (const depId of deps) {
142
+ const depReg = this.registrations.get(depId);
143
+ if (depReg && !featureModules.find((m) => m.id === depId)) {
144
+ featureModules.push(depReg);
145
+ }
146
+ }
147
+ }
148
+ }
149
+ return this.topologicalSort(featureModules).map((r) => r.module);
150
+ }
151
+ /**
152
+ * Validate all module dependencies exist
153
+ */
154
+ validateDependencies() {
155
+ const errors = [];
156
+ for (const reg of this.registrations.values()) {
157
+ if (reg.dependencies) {
158
+ for (const depId of reg.dependencies) {
159
+ if (!this.registrations.has(depId)) {
160
+ errors.push(`Module "${reg.id}" depends on "${depId}" which is not registered`);
161
+ }
162
+ }
163
+ }
164
+ }
165
+ if (errors.length > 0) {
166
+ this.logger.warn(`Module dependency validation found ${errors.length} issues:\n${errors.join('\n')}`);
167
+ }
168
+ }
169
+ /**
170
+ * Get all dependencies for a module recursively
171
+ */
172
+ getDependenciesRecursive(moduleId, visited = new Set()) {
173
+ const reg = this.registrations.get(moduleId);
174
+ if (!reg?.dependencies)
175
+ return [];
176
+ const deps = [];
177
+ for (const depId of reg.dependencies) {
178
+ if (!visited.has(depId)) {
179
+ visited.add(depId);
180
+ deps.push(depId);
181
+ deps.push(...this.getDependenciesRecursive(depId, visited));
182
+ }
183
+ }
184
+ return deps;
185
+ }
186
+ /**
187
+ * Topological sort for dependency-ordered loading
188
+ */
189
+ topologicalSort(registrations) {
190
+ const sorted = [];
191
+ const visited = new Set();
192
+ const visiting = new Set();
193
+ const visit = (reg) => {
194
+ if (visited.has(reg.id))
195
+ return;
196
+ if (visiting.has(reg.id)) {
197
+ this.logger.warn(`Circular dependency detected at: ${reg.id}`);
198
+ return;
199
+ }
200
+ visiting.add(reg.id);
201
+ // Visit dependencies first
202
+ if (reg.dependencies) {
203
+ for (const depId of reg.dependencies) {
204
+ const depReg = this.registrations.get(depId);
205
+ if (depReg && registrations.includes(depReg)) {
206
+ visit(depReg);
207
+ }
208
+ }
209
+ }
210
+ visiting.delete(reg.id);
211
+ visited.add(reg.id);
212
+ sorted.push(reg);
213
+ };
214
+ // Sort by priority first (lower priority = earlier)
215
+ const byPriority = [...registrations].sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
216
+ for (const reg of byPriority) {
217
+ visit(reg);
218
+ }
219
+ return sorted;
220
+ }
221
+ /**
222
+ * Log registration summary
223
+ */
224
+ logRegistrationSummary() {
225
+ const byCategory = {};
226
+ for (const [category, ids] of this.categories) {
227
+ byCategory[category] = ids.size;
228
+ }
229
+ this.logger.log(`Module registry initialized: ${this.registrations.size} modules across ${this.categories.size} categories`);
230
+ for (const [category, count] of Object.entries(byCategory)) {
231
+ this.logger.debug(` ${category}: ${count} modules`);
232
+ }
233
+ }
234
+ };
235
+ exports.ModuleRegistry = ModuleRegistry;
236
+ exports.ModuleRegistry = ModuleRegistry = ModuleRegistry_1 = __decorate([
237
+ (0, common_1.Injectable)()
238
+ ], ModuleRegistry);
239
+ //# sourceMappingURL=module-registry.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-registry.service.js","sourceRoot":"","sources":["../src/module-registry.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import { OnModuleInit, Type } from '@nestjs/common';
2
+ import { ModulesContainer } from '@nestjs/core';
3
+ import { ModuleRegistry, ModuleRegistration } from './module-registry.service';
4
+ /**
5
+ * Options for ModuleScanner
6
+ */
7
+ export interface ModuleScannerOptions {
8
+ /** Whether to scan all modules automatically on init */
9
+ autoScan?: boolean;
10
+ /** Module IDs to exclude from registration */
11
+ excludeIds?: string[];
12
+ /** Categories to exclude from registration */
13
+ excludeCategories?: string[];
14
+ /** Log discovered modules */
15
+ verbose?: boolean;
16
+ }
17
+ /** DI token for scanner options */
18
+ export declare const MODULE_SCANNER_OPTIONS = "MODULE_SCANNER_OPTIONS";
19
+ /**
20
+ * ModuleScanner - Auto-discovers and registers modules with ModuleRegistry.
21
+ *
22
+ * This service scans all loaded NestJS modules and automatically registers
23
+ * those decorated with @RegisterModule() to the ModuleRegistry.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // In app.module.ts
28
+ * @Module({
29
+ * imports: [
30
+ * ModuleRegistryModule,
31
+ * // Scanner will auto-discover modules below
32
+ * BotQueryModule,
33
+ * BotSseModule,
34
+ * ],
35
+ * providers: [
36
+ * {
37
+ * provide: MODULE_SCANNER_OPTIONS,
38
+ * useValue: { verbose: true },
39
+ * },
40
+ * ],
41
+ * })
42
+ * export class AppModule {}
43
+ * ```
44
+ */
45
+ export declare class ModuleScanner implements OnModuleInit {
46
+ private readonly registry;
47
+ private readonly modulesContainer;
48
+ private readonly logger;
49
+ private readonly options;
50
+ constructor(registry: ModuleRegistry, modulesContainer: ModulesContainer, options?: ModuleScannerOptions);
51
+ onModuleInit(): Promise<void>;
52
+ /**
53
+ * Scan all modules and register those with @RegisterModule decorator
54
+ */
55
+ scanAndRegister(): Promise<number>;
56
+ /**
57
+ * Extract registration metadata from a module
58
+ */
59
+ private extractModuleRegistration;
60
+ /**
61
+ * Get all modules that would be registered (without actually registering)
62
+ */
63
+ previewModules(): ModuleRegistration[];
64
+ /**
65
+ * Manually register a specific module
66
+ */
67
+ registerModule(moduleClass: Type<any>): boolean;
68
+ /**
69
+ * Log discovered modules for debugging
70
+ */
71
+ private logDiscoveredModules;
72
+ }
73
+ //# sourceMappingURL=module-scanner.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-scanner.service.d.ts","sourceRoot":"","sources":["../src/module-scanner.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EAGZ,IAAI,EACL,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/E;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,8CAA8C;IAC9C,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,6BAA6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,mCAAmC;AACnC,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBACa,aAAc,YAAW,YAAY;IAK9C,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IALnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;gBAG5B,QAAQ,EAAE,cAAc,EACxB,gBAAgB,EAAE,gBAAgB,EAGnD,OAAO,CAAC,EAAE,oBAAoB;IAS1B,YAAY;IAMlB;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAyCxC;;OAEG;IACH,OAAO,CAAC,yBAAyB;IA8BjC;;OAEG;IACH,cAAc,IAAI,kBAAkB,EAAE;IAatC;;OAEG;IACH,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO;IAsB/C;;OAEG;IACH,OAAO,CAAC,oBAAoB;CAsB7B"}
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var ModuleScanner_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.ModuleScanner = exports.MODULE_SCANNER_OPTIONS = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const core_1 = require("@nestjs/core");
19
+ const module_registry_service_1 = require("./module-registry.service");
20
+ const register_module_decorator_1 = require("./register-module.decorator");
21
+ /** DI token for scanner options */
22
+ exports.MODULE_SCANNER_OPTIONS = 'MODULE_SCANNER_OPTIONS';
23
+ /**
24
+ * ModuleScanner - Auto-discovers and registers modules with ModuleRegistry.
25
+ *
26
+ * This service scans all loaded NestJS modules and automatically registers
27
+ * those decorated with @RegisterModule() to the ModuleRegistry.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // In app.module.ts
32
+ * @Module({
33
+ * imports: [
34
+ * ModuleRegistryModule,
35
+ * // Scanner will auto-discover modules below
36
+ * BotQueryModule,
37
+ * BotSseModule,
38
+ * ],
39
+ * providers: [
40
+ * {
41
+ * provide: MODULE_SCANNER_OPTIONS,
42
+ * useValue: { verbose: true },
43
+ * },
44
+ * ],
45
+ * })
46
+ * export class AppModule {}
47
+ * ```
48
+ */
49
+ let ModuleScanner = ModuleScanner_1 = class ModuleScanner {
50
+ registry;
51
+ modulesContainer;
52
+ logger = new common_1.Logger(ModuleScanner_1.name);
53
+ options;
54
+ constructor(registry, modulesContainer, options) {
55
+ this.registry = registry;
56
+ this.modulesContainer = modulesContainer;
57
+ this.options = {
58
+ autoScan: true,
59
+ verbose: false,
60
+ ...options,
61
+ };
62
+ }
63
+ async onModuleInit() {
64
+ if (this.options.autoScan) {
65
+ await this.scanAndRegister();
66
+ }
67
+ }
68
+ /**
69
+ * Scan all modules and register those with @RegisterModule decorator
70
+ */
71
+ async scanAndRegister() {
72
+ const discovered = [];
73
+ const excludedIds = new Set(this.options.excludeIds || []);
74
+ const excludedCategories = new Set(this.options.excludeCategories || []);
75
+ // Scan all modules in the container
76
+ for (const [, moduleRef] of this.modulesContainer) {
77
+ const registration = this.extractModuleRegistration(moduleRef);
78
+ if (registration) {
79
+ // Check exclusions
80
+ if (excludedIds.has(registration.id)) {
81
+ this.logger.debug(`Skipping excluded module: ${registration.id}`);
82
+ continue;
83
+ }
84
+ if (excludedCategories.has(registration.category)) {
85
+ this.logger.debug(`Skipping excluded category: ${registration.category} (${registration.id})`);
86
+ continue;
87
+ }
88
+ discovered.push(registration);
89
+ }
90
+ }
91
+ // Register all discovered modules
92
+ this.registry.registerAll(discovered);
93
+ this.logger.log(`ModuleScanner discovered ${discovered.length} modules with @RegisterModule()`);
94
+ if (this.options.verbose) {
95
+ this.logDiscoveredModules(discovered);
96
+ }
97
+ return discovered.length;
98
+ }
99
+ /**
100
+ * Extract registration metadata from a module
101
+ */
102
+ extractModuleRegistration(moduleRef) {
103
+ // Get the module class
104
+ const moduleClass = moduleRef.metatype;
105
+ if (!moduleClass) {
106
+ return null;
107
+ }
108
+ // Check for @RegisterModule decorator
109
+ const metadata = Reflect.getMetadata(register_module_decorator_1.MODULE_REGISTRATION_METADATA, moduleClass);
110
+ if (!metadata) {
111
+ return null;
112
+ }
113
+ // Build full registration
114
+ const registration = {
115
+ ...metadata,
116
+ module: moduleClass,
117
+ enabled: true,
118
+ };
119
+ return registration;
120
+ }
121
+ /**
122
+ * Get all modules that would be registered (without actually registering)
123
+ */
124
+ previewModules() {
125
+ const discovered = [];
126
+ for (const [, moduleRef] of this.modulesContainer) {
127
+ const registration = this.extractModuleRegistration(moduleRef);
128
+ if (registration) {
129
+ discovered.push(registration);
130
+ }
131
+ }
132
+ return discovered;
133
+ }
134
+ /**
135
+ * Manually register a specific module
136
+ */
137
+ registerModule(moduleClass) {
138
+ const metadata = Reflect.getMetadata(register_module_decorator_1.MODULE_REGISTRATION_METADATA, moduleClass);
139
+ if (!metadata) {
140
+ this.logger.warn(`Module ${moduleClass.name} does not have @RegisterModule decorator`);
141
+ return false;
142
+ }
143
+ this.registry.register({
144
+ ...metadata,
145
+ module: moduleClass,
146
+ enabled: true,
147
+ });
148
+ return true;
149
+ }
150
+ /**
151
+ * Log discovered modules for debugging
152
+ */
153
+ logDiscoveredModules(modules) {
154
+ const byCategory = {};
155
+ for (const mod of modules) {
156
+ const cat = mod.category;
157
+ if (!byCategory[cat]) {
158
+ byCategory[cat] = [];
159
+ }
160
+ byCategory[cat].push(mod);
161
+ }
162
+ this.logger.debug('Discovered modules by category:');
163
+ for (const [category, mods] of Object.entries(byCategory)) {
164
+ this.logger.debug(` ${category}:`);
165
+ for (const mod of mods) {
166
+ const deps = mod.dependencies?.length
167
+ ? ` deps: [${mod.dependencies.join(', ')}]`
168
+ : '';
169
+ this.logger.debug(` - ${mod.id}${deps}`);
170
+ }
171
+ }
172
+ }
173
+ };
174
+ exports.ModuleScanner = ModuleScanner;
175
+ exports.ModuleScanner = ModuleScanner = ModuleScanner_1 = __decorate([
176
+ (0, common_1.Injectable)(),
177
+ __param(2, (0, common_1.Optional)()),
178
+ __param(2, (0, common_1.Inject)(exports.MODULE_SCANNER_OPTIONS)),
179
+ __metadata("design:paramtypes", [module_registry_service_1.ModuleRegistry,
180
+ core_1.ModulesContainer, Object])
181
+ ], ModuleScanner);
182
+ //# sourceMappingURL=module-scanner.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-scanner.service.js","sourceRoot":"","sources":["../src/module-scanner.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { ModuleCategory } from './module-registry.service';
2
+ /**
3
+ * Module registration metadata for auto-discovery
4
+ */
5
+ export interface RegisterModuleMetadata {
6
+ /** Unique module identifier */
7
+ id: string;
8
+ /** Module category for grouping */
9
+ category: ModuleCategory;
10
+ /** Human-readable name */
11
+ name?: string;
12
+ /** Module description */
13
+ description?: string;
14
+ /** Dependencies (module IDs that must be loaded first) */
15
+ dependencies?: string[];
16
+ /** Whether module is required for app to function */
17
+ required?: boolean;
18
+ /** Priority for load order (lower = earlier) */
19
+ priority?: number;
20
+ /** Feature IDs this module belongs to */
21
+ features?: string[];
22
+ }
23
+ /**
24
+ * Metadata key for module registration
25
+ */
26
+ export declare const MODULE_REGISTRATION_METADATA = "module:registration";
27
+ /**
28
+ * Decorator to mark a module for auto-registration with ModuleRegistry.
29
+ *
30
+ * The ModuleScanner will discover all modules with this decorator
31
+ * and register them with the ModuleRegistry during application bootstrap.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * @RegisterModule({
36
+ * id: 'bot-query',
37
+ * category: 'domain',
38
+ * name: 'Bot Query Module',
39
+ * dependencies: ['prisma', 'redis'],
40
+ * features: ['bot-management'],
41
+ * })
42
+ * @Module({})
43
+ * export class BotQueryModule {}
44
+ * ```
45
+ */
46
+ export declare function RegisterModule(metadata: RegisterModuleMetadata): ClassDecorator;
47
+ //# sourceMappingURL=register-module.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-module.decorator.d.ts","sourceRoot":"","sources":["../src/register-module.decorator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,+BAA+B;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,mCAAmC;IACnC,QAAQ,EAAE,cAAc,CAAC;IACzB,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,eAAO,MAAM,4BAA4B,wBAAwB,CAAC;AAElE;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,sBAAsB,GAC/B,cAAc,CAIhB"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MODULE_REGISTRATION_METADATA = void 0;
4
+ exports.RegisterModule = RegisterModule;
5
+ const common_1 = require("@nestjs/common");
6
+ /**
7
+ * Metadata key for module registration
8
+ */
9
+ exports.MODULE_REGISTRATION_METADATA = 'module:registration';
10
+ /**
11
+ * Decorator to mark a module for auto-registration with ModuleRegistry.
12
+ *
13
+ * The ModuleScanner will discover all modules with this decorator
14
+ * and register them with the ModuleRegistry during application bootstrap.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * @RegisterModule({
19
+ * id: 'bot-query',
20
+ * category: 'domain',
21
+ * name: 'Bot Query Module',
22
+ * dependencies: ['prisma', 'redis'],
23
+ * features: ['bot-management'],
24
+ * })
25
+ * @Module({})
26
+ * export class BotQueryModule {}
27
+ * ```
28
+ */
29
+ function RegisterModule(metadata) {
30
+ return (target) => {
31
+ (0, common_1.SetMetadata)(exports.MODULE_REGISTRATION_METADATA, metadata)(target);
32
+ };
33
+ }
34
+ //# sourceMappingURL=register-module.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-module.decorator.js","sourceRoot":"","sources":["../src/register-module.decorator.ts"],"names":[],"mappings":";;;AAiDA,wCAMC;AAvDD,2CAA6C;AAyB7C;;GAEG;AACU,QAAA,4BAA4B,GAAG,qBAAqB,CAAC;AAElE;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,cAAc,CAC5B,QAAgC;IAEhC,OAAO,CAAC,MAAuB,EAAE,EAAE;QACjC,IAAA,oBAAW,EAAC,oCAA4B,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;IAC9D,CAAC,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@dofe/infra-module-registry",
3
+ "version": "0.1.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "peerDependencies": {
7
+ "@nestjs/common": "^11.0.0",
8
+ "@nestjs/core": "^11.0.0",
9
+ "reflect-metadata": "^0.2.0",
10
+ "rxjs": "^7.8.0"
11
+ },
12
+ "devDependencies": {
13
+ "rimraf": "^5.0.0",
14
+ "typescript": "^5.4.5"
15
+ },
16
+ "type": "commonjs",
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "license": "UNLICENSED",
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "typecheck": "tsc --noEmit",
27
+ "clean": "rimraf dist"
28
+ }
29
+ }