@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.
- package/dist/dynamic-feature.module.d.ts +88 -0
- package/dist/dynamic-feature.module.d.ts.map +1 -0
- package/dist/dynamic-feature.module.js +139 -0
- package/dist/dynamic-feature.module.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/module-registry.module.d.ts +13 -0
- package/dist/module-registry.module.d.ts.map +1 -0
- package/dist/module-registry.module.js +45 -0
- package/dist/module-registry.module.js.map +1 -0
- package/dist/module-registry.service.d.ts +130 -0
- package/dist/module-registry.service.d.ts.map +1 -0
- package/dist/module-registry.service.js +239 -0
- package/dist/module-registry.service.js.map +1 -0
- package/dist/module-scanner.service.d.ts +73 -0
- package/dist/module-scanner.service.d.ts.map +1 -0
- package/dist/module-scanner.service.js +182 -0
- package/dist/module-scanner.service.js.map +1 -0
- package/dist/register-module.decorator.d.ts +47 -0
- package/dist/register-module.decorator.d.ts.map +1 -0
- package/dist/register-module.decorator.js +34 -0
- package/dist/register-module.decorator.js.map +1 -0
- package/package.json +29 -0
|
@@ -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":";;;;;;;;;;AAAA,2CAAuE;AACvE,uEAA+E;AA4B/E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEI,IAAM,oBAAoB,4BAA1B,MAAM,oBAAoB;IAC/B;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAoC;QAClD,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,EAAE,QAAQ,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;QAEpE,2CAA2C;QAC3C,MAAM,aAAa,GAAgB,EAAE,CAAC;QACtC,MAAM,SAAS,GAAe,EAAE,CAAC;QACjC,MAAM,OAAO,GAA2B,EAAE,CAAC;QAE3C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACvC,0EAA0E;gBAC1E,kEAAkE;gBAClE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;YACnD,CAAC;YAED,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACtB,SAAS,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;QAED,OAAO;YACL,MAAM,EAAE,sBAAoB;YAC5B,OAAO,EAAE,aAAa;YACtB,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,wCAAc,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;YACpE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;YACrB,MAAM,EAAE,QAAQ;SACjB,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,aAAa,CAClB,SAAoC,EACpC,UAAoB,EACpB,OAAgC;QAEhC,MAAM,OAAO,GAAgB,EAAE,CAAC;QAEhC,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;YAC5B,MAAM,WAAW,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;YAClC,IAAI,WAAW,EAAE,CAAC;gBAChB,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,OAAO;YACL,MAAM,EAAE,sBAAoB;YAC5B,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,OAAO,EAAE,QAAQ;SAC1B,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CACjB,aAAmC,EACnC,OAIC;QAED,6CAA6C;QAC7C,MAAM,QAAQ,GAAG,IAAI,wCAAc,EAAE,CAAC;QACtC,QAAQ,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QAEpC,kCAAkC;QAClC,MAAM,OAAO,GAAG,QAAQ,CAAC,gBAAgB,CAAC;YACxC,UAAU,EAAE,OAAO,EAAE,UAAiB;YACtC,eAAe,EAAE,OAAO,EAAE,eAAe;SAC1C,CAAC,CAAC;QAEH,OAAO;YACL,MAAM,EAAE,sBAAoB;YAC5B,OAAO,EAAE,OAAO;YAChB,SAAS,EAAE,CAAC,wCAAc,CAAC;YAC3B,OAAO,EAAE,CAAC,wCAAc,CAAC;YACzB,MAAM,EAAE,OAAO,EAAE,QAAQ;SAC1B,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACY,AAAP,MAAM,CAAC,aAAa,CAAC,QAAgB;QAC3C,kFAAkF;QAClF,uDAAuD;QAEvD,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;SAAG,CAAA;QAApB,iBAAiB;YADtB,IAAA,eAAM,EAAC,EAAE,CAAC;WACL,iBAAiB,CAAG;QAE1B,MAAM,CAAC,cAAc,CAAC,iBAAiB,EAAE,MAAM,EAAE;YAC/C,KAAK,EAAE,eAAe,QAAQ,EAAE;SACjC,CAAC,CAAC;QAEH,OAAO,iBAAiB,CAAC;IAC3B,CAAC;CACF,CAAA;AApHY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,oBAAoB,CAoHhC"}
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|