@cepseudo/engine 1.0.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/LICENSE +21 -0
- package/README.md +209 -0
- package/dist/component_types.d.ts +92 -0
- package/dist/component_types.d.ts.map +1 -0
- package/dist/component_types.js +93 -0
- package/dist/component_types.js.map +1 -0
- package/dist/digital_twin_engine.d.ts +390 -0
- package/dist/digital_twin_engine.d.ts.map +1 -0
- package/dist/digital_twin_engine.js +1200 -0
- package/dist/digital_twin_engine.js.map +1 -0
- package/dist/endpoints.d.ts +45 -0
- package/dist/endpoints.d.ts.map +1 -0
- package/dist/endpoints.js +87 -0
- package/dist/endpoints.js.map +1 -0
- package/dist/error_handler.d.ts +20 -0
- package/dist/error_handler.d.ts.map +1 -0
- package/dist/error_handler.js +68 -0
- package/dist/error_handler.js.map +1 -0
- package/dist/global_assets_handler.d.ts +63 -0
- package/dist/global_assets_handler.d.ts.map +1 -0
- package/dist/global_assets_handler.js +127 -0
- package/dist/global_assets_handler.js.map +1 -0
- package/dist/graceful_shutdown.d.ts +44 -0
- package/dist/graceful_shutdown.d.ts.map +1 -0
- package/dist/graceful_shutdown.js +79 -0
- package/dist/graceful_shutdown.js.map +1 -0
- package/dist/health.d.ts +112 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +190 -0
- package/dist/health.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/initializer.d.ts +62 -0
- package/dist/initializer.d.ts.map +1 -0
- package/dist/initializer.js +110 -0
- package/dist/initializer.js.map +1 -0
- package/dist/loader/component_loader.d.ts +133 -0
- package/dist/loader/component_loader.d.ts.map +1 -0
- package/dist/loader/component_loader.js +340 -0
- package/dist/loader/component_loader.js.map +1 -0
- package/dist/openapi/generator.d.ts +93 -0
- package/dist/openapi/generator.d.ts.map +1 -0
- package/dist/openapi/generator.js +293 -0
- package/dist/openapi/generator.js.map +1 -0
- package/dist/queue_manager.d.ts +87 -0
- package/dist/queue_manager.d.ts.map +1 -0
- package/dist/queue_manager.js +196 -0
- package/dist/queue_manager.js.map +1 -0
- package/dist/scheduler.d.ts +29 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +375 -0
- package/dist/scheduler.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Component auto-discovery and loading utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to automatically discover and load Digital Twin components
|
|
5
|
+
* from a directory based on file naming conventions.
|
|
6
|
+
*/
|
|
7
|
+
import type { LoadedComponents } from '../component_types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Options for component auto-discovery
|
|
10
|
+
*/
|
|
11
|
+
export interface LoadComponentsOptions {
|
|
12
|
+
/**
|
|
13
|
+
* File patterns to match by suffix.
|
|
14
|
+
* Keys are component types, values are file suffixes (without extension).
|
|
15
|
+
* @default Standard naming conventions
|
|
16
|
+
*/
|
|
17
|
+
patterns?: {
|
|
18
|
+
collectors?: string;
|
|
19
|
+
harvesters?: string;
|
|
20
|
+
handlers?: string;
|
|
21
|
+
assetsManagers?: string;
|
|
22
|
+
customTableManagers?: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* File extensions to scan for.
|
|
26
|
+
* @default ['.js', '.mjs']
|
|
27
|
+
*/
|
|
28
|
+
extensions?: string[];
|
|
29
|
+
/**
|
|
30
|
+
* Whether to scan subdirectories recursively.
|
|
31
|
+
* @default true
|
|
32
|
+
*/
|
|
33
|
+
recursive?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Patterns to exclude (glob-like patterns applied to file names).
|
|
36
|
+
* @default ['*.spec.*', '*.test.*', 'index.*']
|
|
37
|
+
*/
|
|
38
|
+
exclude?: string[];
|
|
39
|
+
/**
|
|
40
|
+
* Enable verbose logging during discovery.
|
|
41
|
+
* @default false
|
|
42
|
+
*/
|
|
43
|
+
verbose?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Custom logger function for verbose output.
|
|
46
|
+
* When provided, verbose messages are sent to this function instead of console.log.
|
|
47
|
+
*/
|
|
48
|
+
logger?: (message: string) => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Result of component loading operation
|
|
52
|
+
*/
|
|
53
|
+
export interface LoadComponentsResult extends LoadedComponents {
|
|
54
|
+
/** Files that were scanned */
|
|
55
|
+
scannedFiles: string[];
|
|
56
|
+
/** Errors encountered during loading */
|
|
57
|
+
errors: Array<{
|
|
58
|
+
file: string;
|
|
59
|
+
error: string;
|
|
60
|
+
}>;
|
|
61
|
+
/** Summary statistics */
|
|
62
|
+
summary: {
|
|
63
|
+
total: number;
|
|
64
|
+
collectors: number;
|
|
65
|
+
harvesters: number;
|
|
66
|
+
handlers: number;
|
|
67
|
+
assetsManagers: number;
|
|
68
|
+
customTableManagers: number;
|
|
69
|
+
errors: number;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Auto-discovers and loads Digital Twin components from a directory.
|
|
74
|
+
*
|
|
75
|
+
* This function scans the specified directory for component files following
|
|
76
|
+
* the naming conventions (*_collector.js, *_harvester.js, etc.), dynamically
|
|
77
|
+
* imports them, and instantiates any component classes found.
|
|
78
|
+
*
|
|
79
|
+
* ## Naming Conventions
|
|
80
|
+
*
|
|
81
|
+
* Component files should follow these naming patterns:
|
|
82
|
+
* - Collectors: `*_collector.js` (e.g., `weather_collector.js`)
|
|
83
|
+
* - Harvesters: `*_harvester.js` (e.g., `traffic_harvester.js`)
|
|
84
|
+
* - Handlers: `*_handler.js` (e.g., `api_handler.js`)
|
|
85
|
+
* - Assets Managers: `*_assets_manager.js` (e.g., `gltf_assets_manager.js`)
|
|
86
|
+
* - Custom Table Managers: `*_custom_table.js` (e.g., `wms_custom_table.js`)
|
|
87
|
+
*
|
|
88
|
+
* ## Component Export Requirements
|
|
89
|
+
*
|
|
90
|
+
* Components should be exported as default export or named export matching the class name:
|
|
91
|
+
* ```typescript
|
|
92
|
+
* // Default export (preferred)
|
|
93
|
+
* export default class WeatherCollector extends Collector { ... }
|
|
94
|
+
*
|
|
95
|
+
* // Named export matching file name
|
|
96
|
+
* export class WeatherCollector extends Collector { ... }
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* @param directory - Directory path to scan for components (absolute or relative to cwd)
|
|
100
|
+
* @param options - Configuration options for discovery
|
|
101
|
+
* @returns Promise resolving to loaded components and metadata
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* import { loadComponents, DigitalTwinEngine } from 'digitaltwin-core'
|
|
106
|
+
*
|
|
107
|
+
* // Basic usage - scan compiled components
|
|
108
|
+
* const result = await loadComponents('./dist/components')
|
|
109
|
+
*
|
|
110
|
+
* console.log(`Loaded ${result.summary.total} components`)
|
|
111
|
+
*
|
|
112
|
+
* const engine = new DigitalTwinEngine({ storage, database })
|
|
113
|
+
* engine.registerComponents(result)
|
|
114
|
+
* await engine.start()
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* // Advanced usage with options
|
|
120
|
+
* const result = await loadComponents('./dist/components', {
|
|
121
|
+
* recursive: true,
|
|
122
|
+
* verbose: true,
|
|
123
|
+
* extensions: ['.js'],
|
|
124
|
+
* exclude: ['*.test.*', 'deprecated_*']
|
|
125
|
+
* })
|
|
126
|
+
*
|
|
127
|
+
* if (result.errors.length > 0) {
|
|
128
|
+
* console.warn('Some components failed to load:', result.errors)
|
|
129
|
+
* }
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export declare function loadComponents(directory: string, options?: LoadComponentsOptions): Promise<LoadComponentsResult>;
|
|
133
|
+
//# sourceMappingURL=component_loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component_loader.d.ts","sourceRoot":"","sources":["../../src/loader/component_loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,uBAAuB,CAAA;AAS3E;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,QAAQ,CAAC,EAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,mBAAmB,CAAC,EAAE,MAAM,CAAA;KAC/B,CAAA;IAED;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IAEnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAElB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC1D,8BAA8B;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAA;IAEtB,wCAAwC;IACxC,MAAM,EAAE,KAAK,CAAC;QACV,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,CAAA;KAChB,CAAC,CAAA;IAEF,yBAAyB;IACzB,OAAO,EAAE;QACL,KAAK,EAAE,MAAM,CAAA;QACb,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,EAAE,MAAM,CAAA;QAClB,QAAQ,EAAE,MAAM,CAAA;QAChB,cAAc,EAAE,MAAM,CAAA;QACtB,mBAAmB,EAAE,MAAM,CAAA;QAC3B,MAAM,EAAE,MAAM,CAAA;KACjB,CAAA;CACJ;AAkKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,wBAAsB,cAAc,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,qBAA0B,GACpC,OAAO,CAAC,oBAAoB,CAAC,CA4J/B"}
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Component auto-discovery and loading utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to automatically discover and load Digital Twin components
|
|
5
|
+
* from a directory based on file naming conventions.
|
|
6
|
+
*/
|
|
7
|
+
import { pathToFileURL } from 'node:url';
|
|
8
|
+
import fs from 'node:fs/promises';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { isCollector, isHarvester, isHandler, isAssetsManager, isCustomTableManager } from '../component_types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Default file patterns for component detection based on naming conventions
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_PATTERNS = {
|
|
15
|
+
collectors: '_collector',
|
|
16
|
+
harvesters: '_harvester',
|
|
17
|
+
handlers: '_handler',
|
|
18
|
+
assetsManagers: '_assets_manager',
|
|
19
|
+
customTableManagers: '_custom_table'
|
|
20
|
+
};
|
|
21
|
+
const DEFAULT_EXTENSIONS = ['.js', '.mjs'];
|
|
22
|
+
const DEFAULT_EXCLUDE = ['*.spec.*', '*.test.*', 'index.*', '*.d.ts'];
|
|
23
|
+
/**
|
|
24
|
+
* Check if a filename matches an exclusion pattern.
|
|
25
|
+
*/
|
|
26
|
+
function matchesExcludePattern(filename, patterns) {
|
|
27
|
+
const nameWithoutExt = filename.replace(/\.[^.]+$/, '');
|
|
28
|
+
for (const pattern of patterns) {
|
|
29
|
+
// Convert glob pattern to regex
|
|
30
|
+
const regexPattern = pattern.replace(/\./g, '\\.').replace(/\*/g, '.*');
|
|
31
|
+
const regex = new RegExp(`^${regexPattern}$`, 'i');
|
|
32
|
+
// Match against full filename and name without extension
|
|
33
|
+
if (regex.test(filename) || regex.test(nameWithoutExt)) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Determine component type from filename based on patterns.
|
|
41
|
+
*/
|
|
42
|
+
function getComponentTypeFromFilename(filename, patterns) {
|
|
43
|
+
const baseName = path.basename(filename);
|
|
44
|
+
// Remove extension for matching
|
|
45
|
+
const nameWithoutExt = baseName.replace(/\.[^.]+$/, '');
|
|
46
|
+
if (nameWithoutExt.endsWith(patterns.collectors))
|
|
47
|
+
return 'collectors';
|
|
48
|
+
if (nameWithoutExt.endsWith(patterns.harvesters))
|
|
49
|
+
return 'harvesters';
|
|
50
|
+
if (nameWithoutExt.endsWith(patterns.handlers))
|
|
51
|
+
return 'handlers';
|
|
52
|
+
if (nameWithoutExt.endsWith(patterns.assetsManagers))
|
|
53
|
+
return 'assetsManagers';
|
|
54
|
+
if (nameWithoutExt.endsWith(patterns.customTableManagers))
|
|
55
|
+
return 'customTableManagers';
|
|
56
|
+
// Also check for *_manager pattern for tileset/map managers
|
|
57
|
+
if (nameWithoutExt.endsWith('_manager') ||
|
|
58
|
+
nameWithoutExt.endsWith('_tileset_manager') ||
|
|
59
|
+
nameWithoutExt.endsWith('_map_manager')) {
|
|
60
|
+
return 'assetsManagers';
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check if a value is a class constructor.
|
|
66
|
+
*/
|
|
67
|
+
function isClassConstructor(value) {
|
|
68
|
+
return typeof value === 'function' && value.prototype && value.prototype.constructor === value;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Check if an instance is a valid Digital Twin component.
|
|
72
|
+
*/
|
|
73
|
+
function isValidComponent(instance) {
|
|
74
|
+
if (!instance || typeof instance !== 'object')
|
|
75
|
+
return false;
|
|
76
|
+
if (typeof instance.getConfiguration !== 'function')
|
|
77
|
+
return false;
|
|
78
|
+
return (isCollector(instance) ||
|
|
79
|
+
isHarvester(instance) ||
|
|
80
|
+
isHandler(instance) ||
|
|
81
|
+
isAssetsManager(instance) ||
|
|
82
|
+
isCustomTableManager(instance));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Recursively scan a directory for component files.
|
|
86
|
+
*/
|
|
87
|
+
async function scanDirectory(dir, options) {
|
|
88
|
+
const results = [];
|
|
89
|
+
try {
|
|
90
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
91
|
+
for (const entry of entries) {
|
|
92
|
+
const fullPath = path.join(dir, entry.name);
|
|
93
|
+
// Skip hidden files/directories
|
|
94
|
+
if (entry.name.startsWith('.') || entry.name.startsWith('_')) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (entry.isDirectory() && options.recursive) {
|
|
98
|
+
const subResults = await scanDirectory(fullPath, options);
|
|
99
|
+
results.push(...subResults);
|
|
100
|
+
}
|
|
101
|
+
else if (entry.isFile()) {
|
|
102
|
+
// Check extension
|
|
103
|
+
const ext = path.extname(entry.name);
|
|
104
|
+
if (!options.extensions.includes(ext)) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
// Check exclusions
|
|
108
|
+
if (matchesExcludePattern(entry.name, options.exclude)) {
|
|
109
|
+
options.log?.(`[loadComponents] Excluding ${entry.name}`);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
// Determine component type
|
|
113
|
+
const componentType = getComponentTypeFromFilename(entry.name, options.patterns);
|
|
114
|
+
if (componentType) {
|
|
115
|
+
results.push({ path: fullPath, type: componentType });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Directory doesn't exist or can't be read - return empty array
|
|
122
|
+
}
|
|
123
|
+
return results;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Convert a snake_case or kebab-case string to PascalCase.
|
|
127
|
+
*/
|
|
128
|
+
function toPascalCase(str) {
|
|
129
|
+
return str
|
|
130
|
+
.split(/[-_]/)
|
|
131
|
+
.map(part => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
132
|
+
.join('');
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Auto-discovers and loads Digital Twin components from a directory.
|
|
136
|
+
*
|
|
137
|
+
* This function scans the specified directory for component files following
|
|
138
|
+
* the naming conventions (*_collector.js, *_harvester.js, etc.), dynamically
|
|
139
|
+
* imports them, and instantiates any component classes found.
|
|
140
|
+
*
|
|
141
|
+
* ## Naming Conventions
|
|
142
|
+
*
|
|
143
|
+
* Component files should follow these naming patterns:
|
|
144
|
+
* - Collectors: `*_collector.js` (e.g., `weather_collector.js`)
|
|
145
|
+
* - Harvesters: `*_harvester.js` (e.g., `traffic_harvester.js`)
|
|
146
|
+
* - Handlers: `*_handler.js` (e.g., `api_handler.js`)
|
|
147
|
+
* - Assets Managers: `*_assets_manager.js` (e.g., `gltf_assets_manager.js`)
|
|
148
|
+
* - Custom Table Managers: `*_custom_table.js` (e.g., `wms_custom_table.js`)
|
|
149
|
+
*
|
|
150
|
+
* ## Component Export Requirements
|
|
151
|
+
*
|
|
152
|
+
* Components should be exported as default export or named export matching the class name:
|
|
153
|
+
* ```typescript
|
|
154
|
+
* // Default export (preferred)
|
|
155
|
+
* export default class WeatherCollector extends Collector { ... }
|
|
156
|
+
*
|
|
157
|
+
* // Named export matching file name
|
|
158
|
+
* export class WeatherCollector extends Collector { ... }
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
161
|
+
* @param directory - Directory path to scan for components (absolute or relative to cwd)
|
|
162
|
+
* @param options - Configuration options for discovery
|
|
163
|
+
* @returns Promise resolving to loaded components and metadata
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* import { loadComponents, DigitalTwinEngine } from 'digitaltwin-core'
|
|
168
|
+
*
|
|
169
|
+
* // Basic usage - scan compiled components
|
|
170
|
+
* const result = await loadComponents('./dist/components')
|
|
171
|
+
*
|
|
172
|
+
* console.log(`Loaded ${result.summary.total} components`)
|
|
173
|
+
*
|
|
174
|
+
* const engine = new DigitalTwinEngine({ storage, database })
|
|
175
|
+
* engine.registerComponents(result)
|
|
176
|
+
* await engine.start()
|
|
177
|
+
* ```
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* // Advanced usage with options
|
|
182
|
+
* const result = await loadComponents('./dist/components', {
|
|
183
|
+
* recursive: true,
|
|
184
|
+
* verbose: true,
|
|
185
|
+
* extensions: ['.js'],
|
|
186
|
+
* exclude: ['*.test.*', 'deprecated_*']
|
|
187
|
+
* })
|
|
188
|
+
*
|
|
189
|
+
* if (result.errors.length > 0) {
|
|
190
|
+
* console.warn('Some components failed to load:', result.errors)
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
export async function loadComponents(directory, options = {}) {
|
|
195
|
+
const patterns = { ...DEFAULT_PATTERNS, ...options.patterns };
|
|
196
|
+
const extensions = options.extensions ?? DEFAULT_EXTENSIONS;
|
|
197
|
+
const exclude = options.exclude ?? DEFAULT_EXCLUDE;
|
|
198
|
+
const recursive = options.recursive ?? true;
|
|
199
|
+
const verbose = options.verbose ?? false;
|
|
200
|
+
const log = options.logger ?? console.log;
|
|
201
|
+
const result = {
|
|
202
|
+
collectors: [],
|
|
203
|
+
harvesters: [],
|
|
204
|
+
handlers: [],
|
|
205
|
+
assetsManagers: [],
|
|
206
|
+
customTableManagers: [],
|
|
207
|
+
scannedFiles: [],
|
|
208
|
+
errors: [],
|
|
209
|
+
summary: {
|
|
210
|
+
total: 0,
|
|
211
|
+
collectors: 0,
|
|
212
|
+
harvesters: 0,
|
|
213
|
+
handlers: 0,
|
|
214
|
+
assetsManagers: 0,
|
|
215
|
+
customTableManagers: 0,
|
|
216
|
+
errors: 0
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
// Resolve directory path
|
|
220
|
+
const absoluteDir = path.isAbsolute(directory) ? directory : path.resolve(process.cwd(), directory);
|
|
221
|
+
// Check if directory exists
|
|
222
|
+
try {
|
|
223
|
+
await fs.access(absoluteDir);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
if (verbose) {
|
|
227
|
+
log(`[loadComponents] Directory not found: ${absoluteDir}`);
|
|
228
|
+
}
|
|
229
|
+
return result;
|
|
230
|
+
}
|
|
231
|
+
if (verbose) {
|
|
232
|
+
log(`[loadComponents] Loading components from ${absoluteDir}`);
|
|
233
|
+
}
|
|
234
|
+
// Scan for component files
|
|
235
|
+
const files = await scanDirectory(absoluteDir, {
|
|
236
|
+
extensions, exclude, recursive, patterns,
|
|
237
|
+
log: verbose ? log : undefined
|
|
238
|
+
});
|
|
239
|
+
result.scannedFiles = files.map(f => f.path);
|
|
240
|
+
if (verbose) {
|
|
241
|
+
log(`[loadComponents] Found ${files.length} potential component files`);
|
|
242
|
+
}
|
|
243
|
+
// Load each component file
|
|
244
|
+
for (const { path: filePath, type: expectedType } of files) {
|
|
245
|
+
try {
|
|
246
|
+
// Convert to file URL for ESM import
|
|
247
|
+
const fileUrl = pathToFileURL(filePath).href;
|
|
248
|
+
const module = await import(fileUrl);
|
|
249
|
+
// Find component class in module exports
|
|
250
|
+
let ComponentClass = null;
|
|
251
|
+
// Try default export first
|
|
252
|
+
if (module.default && isClassConstructor(module.default)) {
|
|
253
|
+
ComponentClass = module.default;
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
// Try named exports
|
|
257
|
+
const fileName = path.basename(filePath, path.extname(filePath));
|
|
258
|
+
const expectedClassName = toPascalCase(fileName);
|
|
259
|
+
if (module[expectedClassName] && isClassConstructor(module[expectedClassName])) {
|
|
260
|
+
ComponentClass = module[expectedClassName];
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
// Try to find any class export that's a valid component
|
|
264
|
+
for (const [, value] of Object.entries(module)) {
|
|
265
|
+
if (isClassConstructor(value)) {
|
|
266
|
+
try {
|
|
267
|
+
const testInstance = new value();
|
|
268
|
+
if (isValidComponent(testInstance)) {
|
|
269
|
+
ComponentClass = value;
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
// Skip if instantiation fails
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
if (!ComponentClass) {
|
|
281
|
+
result.errors.push({
|
|
282
|
+
file: filePath,
|
|
283
|
+
error: 'No valid component class found in module exports'
|
|
284
|
+
});
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
// Instantiate the component
|
|
288
|
+
const instance = new ComponentClass();
|
|
289
|
+
if (!isValidComponent(instance)) {
|
|
290
|
+
result.errors.push({
|
|
291
|
+
file: filePath,
|
|
292
|
+
error: 'Instantiated class is not a valid Digital Twin component'
|
|
293
|
+
});
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
// Add to appropriate array based on actual type (not expected type)
|
|
297
|
+
if (isCollector(instance)) {
|
|
298
|
+
result.collectors.push(instance);
|
|
299
|
+
result.summary.collectors++;
|
|
300
|
+
}
|
|
301
|
+
else if (isHarvester(instance)) {
|
|
302
|
+
result.harvesters.push(instance);
|
|
303
|
+
result.summary.harvesters++;
|
|
304
|
+
}
|
|
305
|
+
else if (isHandler(instance)) {
|
|
306
|
+
result.handlers.push(instance);
|
|
307
|
+
result.summary.handlers++;
|
|
308
|
+
}
|
|
309
|
+
else if (isCustomTableManager(instance)) {
|
|
310
|
+
result.customTableManagers.push(instance);
|
|
311
|
+
result.summary.customTableManagers++;
|
|
312
|
+
}
|
|
313
|
+
else if (isAssetsManager(instance)) {
|
|
314
|
+
result.assetsManagers.push(instance);
|
|
315
|
+
result.summary.assetsManagers++;
|
|
316
|
+
}
|
|
317
|
+
result.summary.total++;
|
|
318
|
+
if (verbose) {
|
|
319
|
+
const config = instance.getConfiguration();
|
|
320
|
+
log(`[loadComponents] Loaded: ${config.name} (${expectedType})`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
325
|
+
result.errors.push({
|
|
326
|
+
file: filePath,
|
|
327
|
+
error: `Failed to import: ${errorMessage}`
|
|
328
|
+
});
|
|
329
|
+
result.summary.errors++;
|
|
330
|
+
if (verbose) {
|
|
331
|
+
log(`[loadComponents] Error loading ${filePath}: ${errorMessage}`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
if (verbose) {
|
|
336
|
+
log(`[loadComponents] Loaded components: ${result.summary.total} total`);
|
|
337
|
+
}
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
//# sourceMappingURL=component_loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component_loader.js","sourceRoot":"","sources":["../../src/loader/component_loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview OpenAPI specification generator for Digital Twin components
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities to automatically generate OpenAPI 3.0
|
|
5
|
+
* documentation from Digital Twin components that implement OpenAPIDocumentable.
|
|
6
|
+
*/
|
|
7
|
+
import type { OpenAPIDocument, OpenAPIGeneratorOptions, OpenAPISchema } from '@cepseudo/shared';
|
|
8
|
+
/**
|
|
9
|
+
* Generates OpenAPI 3.0 specifications from Digital Twin components.
|
|
10
|
+
*
|
|
11
|
+
* The generator aggregates OpenAPI specs from all components that implement
|
|
12
|
+
* the OpenAPIDocumentable interface and produces a complete OpenAPI document.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { OpenAPIGenerator } from 'digitaltwin-core'
|
|
17
|
+
* import * as components from './src/components'
|
|
18
|
+
*
|
|
19
|
+
* const spec = OpenAPIGenerator.generate({
|
|
20
|
+
* info: {
|
|
21
|
+
* title: 'My Digital Twin API',
|
|
22
|
+
* version: '1.0.0',
|
|
23
|
+
* description: 'API documentation'
|
|
24
|
+
* },
|
|
25
|
+
* components: Object.values(components),
|
|
26
|
+
* servers: [{ url: 'http://localhost:3000' }]
|
|
27
|
+
* })
|
|
28
|
+
*
|
|
29
|
+
* // Write to file
|
|
30
|
+
* OpenAPIGenerator.writeYAML(spec, './openapi.yaml')
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare class OpenAPIGenerator {
|
|
34
|
+
/**
|
|
35
|
+
* Generates an OpenAPI document from the provided components.
|
|
36
|
+
*
|
|
37
|
+
* @param options - Generation options including components and metadata
|
|
38
|
+
* @returns Complete OpenAPI document
|
|
39
|
+
*/
|
|
40
|
+
static generate(options: OpenAPIGeneratorOptions): OpenAPIDocument;
|
|
41
|
+
/**
|
|
42
|
+
* Returns default security schemes for APISIX/Keycloak authentication.
|
|
43
|
+
*/
|
|
44
|
+
private static getDefaultSecuritySchemes;
|
|
45
|
+
/**
|
|
46
|
+
* Converts an OpenAPI document to YAML string.
|
|
47
|
+
*
|
|
48
|
+
* @param document - OpenAPI document to convert
|
|
49
|
+
* @returns YAML string representation
|
|
50
|
+
*/
|
|
51
|
+
static toYAML(document: OpenAPIDocument): string;
|
|
52
|
+
/**
|
|
53
|
+
* Converts an OpenAPI document to JSON string.
|
|
54
|
+
*
|
|
55
|
+
* @param document - OpenAPI document to convert
|
|
56
|
+
* @param pretty - Whether to format with indentation (default: true)
|
|
57
|
+
* @returns JSON string representation
|
|
58
|
+
*/
|
|
59
|
+
static toJSON(document: OpenAPIDocument, pretty?: boolean): string;
|
|
60
|
+
/**
|
|
61
|
+
* Recursively converts an object to YAML format.
|
|
62
|
+
* Simple implementation without external dependencies.
|
|
63
|
+
*/
|
|
64
|
+
private static objectToYAML;
|
|
65
|
+
/**
|
|
66
|
+
* Helper to create a simple schema reference.
|
|
67
|
+
*/
|
|
68
|
+
static schemaRef(name: string): OpenAPISchema;
|
|
69
|
+
/**
|
|
70
|
+
* Helper to create a common response for 200 OK with content.
|
|
71
|
+
*/
|
|
72
|
+
static successResponse(contentType: string, schema: OpenAPISchema, description?: string): {
|
|
73
|
+
'200': {
|
|
74
|
+
description: string;
|
|
75
|
+
content: {
|
|
76
|
+
[contentType]: {
|
|
77
|
+
schema: OpenAPISchema;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Helper to create common error responses.
|
|
84
|
+
*/
|
|
85
|
+
static errorResponses(codes?: Array<400 | 401 | 403 | 404 | 500>): Record<string, {
|
|
86
|
+
description: string;
|
|
87
|
+
}>;
|
|
88
|
+
/**
|
|
89
|
+
* Common schemas used across components.
|
|
90
|
+
*/
|
|
91
|
+
static commonSchemas: Record<string, OpenAPISchema>;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/openapi/generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACR,eAAe,EACf,uBAAuB,EAEvB,aAAa,EAGhB,MAAM,kBAAkB,CAAA;AAGzB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,gBAAgB;IACzB;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,uBAAuB,GAAG,eAAe;IAqFlE;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAWxC;;;;;OAKG;IACH,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM;IAIhD;;;;;;OAMG;IACH,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,MAAM,UAAO,GAAG,MAAM;IAI/D;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;IAoF3B;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAI7C;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,SAAwB;;;;gBAKtF,CAAC,WAAW,CAAC;;kBAAY;;;;IAMzC;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,KAAK,GAAE,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAwB;qBACnC,MAAM;;IAiBzD;;OAEG;IACH,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAuClD;CACJ"}
|