@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.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +209 -0
  3. package/dist/component_types.d.ts +92 -0
  4. package/dist/component_types.d.ts.map +1 -0
  5. package/dist/component_types.js +93 -0
  6. package/dist/component_types.js.map +1 -0
  7. package/dist/digital_twin_engine.d.ts +390 -0
  8. package/dist/digital_twin_engine.d.ts.map +1 -0
  9. package/dist/digital_twin_engine.js +1200 -0
  10. package/dist/digital_twin_engine.js.map +1 -0
  11. package/dist/endpoints.d.ts +45 -0
  12. package/dist/endpoints.d.ts.map +1 -0
  13. package/dist/endpoints.js +87 -0
  14. package/dist/endpoints.js.map +1 -0
  15. package/dist/error_handler.d.ts +20 -0
  16. package/dist/error_handler.d.ts.map +1 -0
  17. package/dist/error_handler.js +68 -0
  18. package/dist/error_handler.js.map +1 -0
  19. package/dist/global_assets_handler.d.ts +63 -0
  20. package/dist/global_assets_handler.d.ts.map +1 -0
  21. package/dist/global_assets_handler.js +127 -0
  22. package/dist/global_assets_handler.js.map +1 -0
  23. package/dist/graceful_shutdown.d.ts +44 -0
  24. package/dist/graceful_shutdown.d.ts.map +1 -0
  25. package/dist/graceful_shutdown.js +79 -0
  26. package/dist/graceful_shutdown.js.map +1 -0
  27. package/dist/health.d.ts +112 -0
  28. package/dist/health.d.ts.map +1 -0
  29. package/dist/health.js +190 -0
  30. package/dist/health.js.map +1 -0
  31. package/dist/index.d.ts +19 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +25 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/initializer.d.ts +62 -0
  36. package/dist/initializer.d.ts.map +1 -0
  37. package/dist/initializer.js +110 -0
  38. package/dist/initializer.js.map +1 -0
  39. package/dist/loader/component_loader.d.ts +133 -0
  40. package/dist/loader/component_loader.d.ts.map +1 -0
  41. package/dist/loader/component_loader.js +340 -0
  42. package/dist/loader/component_loader.js.map +1 -0
  43. package/dist/openapi/generator.d.ts +93 -0
  44. package/dist/openapi/generator.d.ts.map +1 -0
  45. package/dist/openapi/generator.js +293 -0
  46. package/dist/openapi/generator.js.map +1 -0
  47. package/dist/queue_manager.d.ts +87 -0
  48. package/dist/queue_manager.d.ts.map +1 -0
  49. package/dist/queue_manager.js +196 -0
  50. package/dist/queue_manager.js.map +1 -0
  51. package/dist/scheduler.d.ts +29 -0
  52. package/dist/scheduler.d.ts.map +1 -0
  53. package/dist/scheduler.js +375 -0
  54. package/dist/scheduler.js.map +1 -0
  55. 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"}