@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Axel Hoffmann
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# @cepseudo/engine
|
|
2
|
+
|
|
3
|
+
[](https://nodejs.org/)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
|
|
6
|
+
Central orchestrator for the Digital Twin Framework. Wires together components, databases, storage, authentication, queues, and HTTP serving into a single runnable application.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm add @cepseudo/engine
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
This package depends on the full stack of `@cepseudo/*` packages (shared, database, storage, auth, assets, components) and requires Redis for queue management.
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import { DigitalTwinEngine } from '@cepseudo/engine'
|
|
20
|
+
import { KnexDatabaseAdapter } from '@cepseudo/database'
|
|
21
|
+
import { StorageServiceFactory } from '@cepseudo/storage'
|
|
22
|
+
import { MyCollector } from './collectors/my_collector.js'
|
|
23
|
+
|
|
24
|
+
const database = new KnexDatabaseAdapter({
|
|
25
|
+
client: 'pg',
|
|
26
|
+
connection: process.env.DATABASE_URL
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const storage = StorageServiceFactory.create()
|
|
30
|
+
|
|
31
|
+
const engine = new DigitalTwinEngine({
|
|
32
|
+
storage,
|
|
33
|
+
database,
|
|
34
|
+
collectors: [new MyCollector()],
|
|
35
|
+
server: { port: 3000 }
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
await engine.start()
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Features
|
|
42
|
+
|
|
43
|
+
- **Component lifecycle management** -- registers, validates, and initializes collectors, harvesters, handlers, assets managers, and custom table managers
|
|
44
|
+
- **Dependency injection** -- automatically injects database, storage, and auth middleware into components
|
|
45
|
+
- **BullMQ scheduling** -- cron-based and event-driven scheduling across 4 queues (collectors, harvesters, priority, uploads)
|
|
46
|
+
- **HTTP server** -- Express-compatible server (via ultimate-express) with automatic endpoint registration from components
|
|
47
|
+
- **Health checks** -- aggregated health status for Kubernetes readiness/liveness probes (database, Redis, storage)
|
|
48
|
+
- **OpenAPI generation** -- auto-generates OpenAPI 3.0.3 specs from registered components
|
|
49
|
+
- **Graceful shutdown** -- handles SIGTERM/SIGINT with configurable timeout and ordered resource cleanup
|
|
50
|
+
- **Dynamic component loading** -- loads components from user project directories at runtime
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
The `EngineOptions` interface controls engine behavior:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
interface EngineOptions {
|
|
58
|
+
// Required
|
|
59
|
+
storage: StorageService
|
|
60
|
+
database: DatabaseAdapter
|
|
61
|
+
|
|
62
|
+
// Components (register via constructor or engine.register())
|
|
63
|
+
collectors?: Collector[]
|
|
64
|
+
harvesters?: Harvester[]
|
|
65
|
+
handlers?: Handler[]
|
|
66
|
+
assetsManagers?: AssetsManager[]
|
|
67
|
+
customTableManagers?: CustomTableManager[]
|
|
68
|
+
|
|
69
|
+
// Redis & queues
|
|
70
|
+
redis?: ConnectionOptions
|
|
71
|
+
queues?: {
|
|
72
|
+
multiQueue?: boolean // default: true
|
|
73
|
+
workers?: {
|
|
74
|
+
collectors?: number // default: 1
|
|
75
|
+
harvesters?: number // default: 1
|
|
76
|
+
}
|
|
77
|
+
options?: QueueConfig['queueOptions']
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// HTTP server
|
|
81
|
+
server?: {
|
|
82
|
+
port: number // default: 3000
|
|
83
|
+
host?: string // default: '0.0.0.0'
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Logging
|
|
87
|
+
logging?: {
|
|
88
|
+
level: LogLevel // default: LogLevel.INFO
|
|
89
|
+
format?: 'json' | 'text' // default: 'text'
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
dryRun?: boolean // default: false
|
|
93
|
+
autoMigration?: boolean // default: true
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Usage Examples
|
|
98
|
+
|
|
99
|
+
### Registering components dynamically
|
|
100
|
+
|
|
101
|
+
Components can be registered after construction, before calling `start()`:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const engine = new DigitalTwinEngine({ storage, database })
|
|
105
|
+
|
|
106
|
+
engine.register(new WeatherCollector())
|
|
107
|
+
engine.register(new AirQualityHandler())
|
|
108
|
+
engine.registerAll([new TilesetManager(), new MapManager()])
|
|
109
|
+
|
|
110
|
+
await engine.start()
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Health checks
|
|
114
|
+
|
|
115
|
+
The engine includes built-in health checks for database, Redis, and storage. Custom checks can be added:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import {
|
|
119
|
+
HealthChecker,
|
|
120
|
+
createDatabaseCheck,
|
|
121
|
+
createRedisCheck,
|
|
122
|
+
createStorageCheck
|
|
123
|
+
} from '@cepseudo/engine'
|
|
124
|
+
|
|
125
|
+
const checker = new HealthChecker()
|
|
126
|
+
checker.register('database', createDatabaseCheck(database))
|
|
127
|
+
checker.register('redis', createRedisCheck(queueManager))
|
|
128
|
+
checker.register('storage', createStorageCheck(storage))
|
|
129
|
+
|
|
130
|
+
// Returns { status: 'healthy' | 'degraded' | 'unhealthy', checks: {...} }
|
|
131
|
+
const status = await checker.check()
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The engine automatically registers health endpoints:
|
|
135
|
+
- `GET /health` -- full health status (readiness probe)
|
|
136
|
+
- `GET /health/live` -- lightweight liveness probe
|
|
137
|
+
|
|
138
|
+
### OpenAPI spec generation
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { OpenAPIGenerator } from '@cepseudo/engine'
|
|
142
|
+
|
|
143
|
+
const generator = new OpenAPIGenerator({
|
|
144
|
+
title: 'My Digital Twin API',
|
|
145
|
+
version: '1.0.0',
|
|
146
|
+
description: 'Digital twin for city infrastructure'
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
// Components expose their endpoint schemas via getConfiguration()
|
|
150
|
+
const spec = generator.generate(components)
|
|
151
|
+
// Returns an OpenAPI 3.0.3 JSON object
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Graceful shutdown
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { setupGracefulShutdown } from '@cepseudo/engine'
|
|
158
|
+
|
|
159
|
+
// Automatically handles SIGTERM and SIGINT
|
|
160
|
+
setupGracefulShutdown({
|
|
161
|
+
engine,
|
|
162
|
+
timeout: 30000 // ms before forced exit
|
|
163
|
+
})
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Dynamic component loading
|
|
167
|
+
|
|
168
|
+
Load components from a user project directory at runtime:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
import { loadComponents } from '@cepseudo/engine'
|
|
172
|
+
|
|
173
|
+
const result = await loadComponents({
|
|
174
|
+
directory: './src/components',
|
|
175
|
+
recursive: true
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
engine.registerAll([
|
|
179
|
+
...result.collectors,
|
|
180
|
+
...result.harvesters,
|
|
181
|
+
...result.handlers
|
|
182
|
+
])
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Architecture
|
|
186
|
+
|
|
187
|
+
`@cepseudo/engine` is the LAYER 3 (top layer) package in the Digital Twin Framework. It depends on all lower layers and acts as the composition root that ties everything together.
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
LAYER 3: engine -- orchestration, HTTP, scheduling, health
|
|
191
|
+
LAYER 2: assets, components -- business logic, file management
|
|
192
|
+
LAYER 1: database, storage, auth -- infrastructure adapters
|
|
193
|
+
LAYER 0: shared -- types, errors, utilities, validation
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
On `engine.start()`, the following sequence executes:
|
|
197
|
+
|
|
198
|
+
1. **Database initialization** -- runs migrations, creates component tables
|
|
199
|
+
2. **Component initialization** -- injects dependencies (database, storage, auth middleware) into active components
|
|
200
|
+
3. **Endpoint registration** -- maps component HTTP endpoints to Express routes
|
|
201
|
+
4. **Queue setup** -- creates BullMQ queues and workers backed by Redis
|
|
202
|
+
5. **Scheduling** -- registers cron schedules and event triggers for collectors/harvesters
|
|
203
|
+
6. **Server start** -- binds the HTTP server and begins accepting requests
|
|
204
|
+
|
|
205
|
+
On `engine.stop()`, resources are cleaned up in reverse order with a configurable timeout to allow in-flight requests and queue jobs to complete.
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Type definitions and guards for dynamic component registration
|
|
3
|
+
*
|
|
4
|
+
* Provides type-safe utilities for runtime component type detection and
|
|
5
|
+
* dynamic registration with the DigitalTwinEngine.
|
|
6
|
+
*/
|
|
7
|
+
import type { Collector, Harvester, Handler, CustomTableManager } from '@cepseudo/components';
|
|
8
|
+
import type { AssetsManager } from '@cepseudo/assets';
|
|
9
|
+
/**
|
|
10
|
+
* String literal union of all component type names.
|
|
11
|
+
* Used for discriminated unions and type narrowing.
|
|
12
|
+
*/
|
|
13
|
+
export type ComponentTypeName = 'collector' | 'harvester' | 'handler' | 'assets_manager' | 'custom_table_manager';
|
|
14
|
+
/**
|
|
15
|
+
* Union type of all component class instances that can be registered.
|
|
16
|
+
*/
|
|
17
|
+
export type AnyComponent = Collector | Harvester | Handler | AssetsManager | CustomTableManager;
|
|
18
|
+
/**
|
|
19
|
+
* Union type of components that can be scheduled (have run() and getSchedule()).
|
|
20
|
+
*/
|
|
21
|
+
export type SchedulableComponent = Collector | Harvester;
|
|
22
|
+
/**
|
|
23
|
+
* Union type of components that require setDependencies(db, storage).
|
|
24
|
+
*/
|
|
25
|
+
export type ActiveComponent = Collector | Harvester;
|
|
26
|
+
/**
|
|
27
|
+
* Map of component type names to their corresponding class types.
|
|
28
|
+
* Enables type-safe lookups and factory patterns.
|
|
29
|
+
*/
|
|
30
|
+
export interface ComponentTypeMap {
|
|
31
|
+
collector: Collector;
|
|
32
|
+
harvester: Harvester;
|
|
33
|
+
handler: Handler;
|
|
34
|
+
assets_manager: AssetsManager;
|
|
35
|
+
custom_table_manager: CustomTableManager;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Result of loading components from a directory.
|
|
39
|
+
*/
|
|
40
|
+
export interface LoadedComponents {
|
|
41
|
+
collectors: Collector[];
|
|
42
|
+
harvesters: Harvester[];
|
|
43
|
+
handlers: Handler[];
|
|
44
|
+
assetsManagers: AssetsManager[];
|
|
45
|
+
customTableManagers: CustomTableManager[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Type guard: Check if component is a Collector.
|
|
49
|
+
* Collectors have collect() method and getSchedule().
|
|
50
|
+
*/
|
|
51
|
+
export declare function isCollector(component: AnyComponent): component is Collector;
|
|
52
|
+
/**
|
|
53
|
+
* Type guard: Check if component is a Harvester.
|
|
54
|
+
* Harvesters have harvest() method and getUserConfiguration().
|
|
55
|
+
*/
|
|
56
|
+
export declare function isHarvester(component: AnyComponent): component is Harvester;
|
|
57
|
+
/**
|
|
58
|
+
* Type guard: Check if component is a Handler.
|
|
59
|
+
* Handlers have getEndpoints() but NOT setDependencies() by default,
|
|
60
|
+
* and don't have collect() or harvest().
|
|
61
|
+
*/
|
|
62
|
+
export declare function isHandler(component: AnyComponent): component is Handler;
|
|
63
|
+
/**
|
|
64
|
+
* Type guard: Check if component is an AssetsManager.
|
|
65
|
+
* AssetsManager has uploadAsset() and getAllAssets().
|
|
66
|
+
*/
|
|
67
|
+
export declare function isAssetsManager(component: AnyComponent): component is AssetsManager;
|
|
68
|
+
/**
|
|
69
|
+
* Type guard: Check if component is a CustomTableManager.
|
|
70
|
+
* CustomTableManager has initializeTable() and findAll().
|
|
71
|
+
*/
|
|
72
|
+
export declare function isCustomTableManager(component: AnyComponent): component is CustomTableManager;
|
|
73
|
+
/**
|
|
74
|
+
* Type guard: Check if component is an active (schedulable) component.
|
|
75
|
+
*/
|
|
76
|
+
export declare function isActiveComponent(component: AnyComponent): component is ActiveComponent;
|
|
77
|
+
/**
|
|
78
|
+
* Detect the component type from an instance.
|
|
79
|
+
* Uses type guards for accurate detection.
|
|
80
|
+
*
|
|
81
|
+
* @param component - The component instance to detect
|
|
82
|
+
* @returns The detected component type name
|
|
83
|
+
* @throws Error if component type cannot be determined
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const type = detectComponentType(myComponent)
|
|
88
|
+
* // type: 'collector' | 'harvester' | 'handler' | 'assets_manager' | 'custom_table_manager'
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare function detectComponentType(component: AnyComponent): ComponentTypeName;
|
|
92
|
+
//# sourceMappingURL=component_types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component_types.d.ts","sourceRoot":"","sources":["../src/component_types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAErD;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,sBAAsB,CAAA;AAEjH;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,GAAG,kBAAkB,CAAA;AAE/F;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,SAAS,CAAA;AAExD;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,CAAA;AAEnD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,SAAS,EAAE,SAAS,CAAA;IACpB,SAAS,EAAE,SAAS,CAAA;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,cAAc,EAAE,aAAa,CAAA;IAC7B,oBAAoB,EAAE,kBAAkB,CAAA;CAC3C;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,cAAc,EAAE,aAAa,EAAE,CAAA;IAC/B,mBAAmB,EAAE,kBAAkB,EAAE,CAAA;CAC5C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,IAAI,SAAS,CAO3E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,IAAI,SAAS,CAO3E;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,IAAI,OAAO,CASvE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,IAAI,aAAa,CAMnF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,IAAI,kBAAkB,CAO7F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,IAAI,eAAe,CAEvF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,YAAY,GAAG,iBAAiB,CAW9E"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Type definitions and guards for dynamic component registration
|
|
3
|
+
*
|
|
4
|
+
* Provides type-safe utilities for runtime component type detection and
|
|
5
|
+
* dynamic registration with the DigitalTwinEngine.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Type guard: Check if component is a Collector.
|
|
9
|
+
* Collectors have collect() method and getSchedule().
|
|
10
|
+
*/
|
|
11
|
+
export function isCollector(component) {
|
|
12
|
+
return (typeof component.collect === 'function' &&
|
|
13
|
+
typeof component.getSchedule === 'function' &&
|
|
14
|
+
typeof component.setDependencies === 'function' &&
|
|
15
|
+
typeof component.run === 'function');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Type guard: Check if component is a Harvester.
|
|
19
|
+
* Harvesters have harvest() method and getUserConfiguration().
|
|
20
|
+
*/
|
|
21
|
+
export function isHarvester(component) {
|
|
22
|
+
return (typeof component.harvest === 'function' &&
|
|
23
|
+
typeof component.getUserConfiguration === 'function' &&
|
|
24
|
+
typeof component.setDependencies === 'function' &&
|
|
25
|
+
typeof component.run === 'function');
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Type guard: Check if component is a Handler.
|
|
29
|
+
* Handlers have getEndpoints() but NOT setDependencies() by default,
|
|
30
|
+
* and don't have collect() or harvest().
|
|
31
|
+
*/
|
|
32
|
+
export function isHandler(component) {
|
|
33
|
+
return (typeof component.getEndpoints === 'function' &&
|
|
34
|
+
typeof component.getConfiguration === 'function' &&
|
|
35
|
+
!('collect' in component && typeof component.collect === 'function') &&
|
|
36
|
+
!('harvest' in component && typeof component.harvest === 'function') &&
|
|
37
|
+
!('uploadAsset' in component && typeof component.uploadAsset === 'function') &&
|
|
38
|
+
!('initializeTable' in component && typeof component.initializeTable === 'function'));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Type guard: Check if component is an AssetsManager.
|
|
42
|
+
* AssetsManager has uploadAsset() and getAllAssets().
|
|
43
|
+
*/
|
|
44
|
+
export function isAssetsManager(component) {
|
|
45
|
+
return (typeof component.uploadAsset === 'function' &&
|
|
46
|
+
typeof component.getAllAssets === 'function' &&
|
|
47
|
+
typeof component.setDependencies === 'function');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Type guard: Check if component is a CustomTableManager.
|
|
51
|
+
* CustomTableManager has initializeTable() and findAll().
|
|
52
|
+
*/
|
|
53
|
+
export function isCustomTableManager(component) {
|
|
54
|
+
return (typeof component.initializeTable === 'function' &&
|
|
55
|
+
typeof component.findAll === 'function' &&
|
|
56
|
+
typeof component.create === 'function' &&
|
|
57
|
+
typeof component.setDependencies === 'function');
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Type guard: Check if component is an active (schedulable) component.
|
|
61
|
+
*/
|
|
62
|
+
export function isActiveComponent(component) {
|
|
63
|
+
return isCollector(component) || isHarvester(component);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Detect the component type from an instance.
|
|
67
|
+
* Uses type guards for accurate detection.
|
|
68
|
+
*
|
|
69
|
+
* @param component - The component instance to detect
|
|
70
|
+
* @returns The detected component type name
|
|
71
|
+
* @throws Error if component type cannot be determined
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const type = detectComponentType(myComponent)
|
|
76
|
+
* // type: 'collector' | 'harvester' | 'handler' | 'assets_manager' | 'custom_table_manager'
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export function detectComponentType(component) {
|
|
80
|
+
// Order matters: check more specific types first
|
|
81
|
+
if (isCollector(component))
|
|
82
|
+
return 'collector';
|
|
83
|
+
if (isHarvester(component))
|
|
84
|
+
return 'harvester';
|
|
85
|
+
if (isCustomTableManager(component))
|
|
86
|
+
return 'custom_table_manager';
|
|
87
|
+
if (isAssetsManager(component))
|
|
88
|
+
return 'assets_manager';
|
|
89
|
+
if (isHandler(component))
|
|
90
|
+
return 'handler';
|
|
91
|
+
throw new Error('Unable to detect component type. Component must extend Collector, Harvester, Handler, AssetsManager, or CustomTableManager.');
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=component_types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component_types.js","sourceRoot":"","sources":["../src/component_types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiDH;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,SAAuB;IAC/C,OAAO,CACH,OAAQ,SAAuB,CAAC,OAAO,KAAK,UAAU;QACtD,OAAQ,SAAuB,CAAC,WAAW,KAAK,UAAU;QAC1D,OAAQ,SAAuB,CAAC,eAAe,KAAK,UAAU;QAC9D,OAAQ,SAAuB,CAAC,GAAG,KAAK,UAAU,CACrD,CAAA;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,SAAuB;IAC/C,OAAO,CACH,OAAQ,SAAuB,CAAC,OAAO,KAAK,UAAU;QACtD,OAAQ,SAAuB,CAAC,oBAAoB,KAAK,UAAU;QACnE,OAAQ,SAAuB,CAAC,eAAe,KAAK,UAAU;QAC9D,OAAQ,SAAuB,CAAC,GAAG,KAAK,UAAU,CACrD,CAAA;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,SAAuB;IAC7C,OAAO,CACH,OAAQ,SAAqB,CAAC,YAAY,KAAK,UAAU;QACzD,OAAQ,SAAqB,CAAC,gBAAgB,KAAK,UAAU;QAC7D,CAAC,CAAC,SAAS,IAAI,SAAS,IAAI,OAAQ,SAAiB,CAAC,OAAO,KAAK,UAAU,CAAC;QAC7E,CAAC,CAAC,SAAS,IAAI,SAAS,IAAI,OAAQ,SAAiB,CAAC,OAAO,KAAK,UAAU,CAAC;QAC7E,CAAC,CAAC,aAAa,IAAI,SAAS,IAAI,OAAQ,SAAiB,CAAC,WAAW,KAAK,UAAU,CAAC;QACrF,CAAC,CAAC,iBAAiB,IAAI,SAAS,IAAI,OAAQ,SAAiB,CAAC,eAAe,KAAK,UAAU,CAAC,CAChG,CAAA;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,SAAuB;IACnD,OAAO,CACH,OAAQ,SAA2B,CAAC,WAAW,KAAK,UAAU;QAC9D,OAAQ,SAA2B,CAAC,YAAY,KAAK,UAAU;QAC/D,OAAQ,SAA2B,CAAC,eAAe,KAAK,UAAU,CACrE,CAAA;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAuB;IACxD,OAAO,CACH,OAAQ,SAAgC,CAAC,eAAe,KAAK,UAAU;QACvE,OAAQ,SAAgC,CAAC,OAAO,KAAK,UAAU;QAC/D,OAAQ,SAAgC,CAAC,MAAM,KAAK,UAAU;QAC9D,OAAQ,SAAgC,CAAC,eAAe,KAAK,UAAU,CAC1E,CAAA;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAuB;IACrD,OAAO,WAAW,CAAC,SAAS,CAAC,IAAI,WAAW,CAAC,SAAS,CAAC,CAAA;AAC3D,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAuB;IACvD,iDAAiD;IACjD,IAAI,WAAW,CAAC,SAAS,CAAC;QAAE,OAAO,WAAW,CAAA;IAC9C,IAAI,WAAW,CAAC,SAAS,CAAC;QAAE,OAAO,WAAW,CAAA;IAC9C,IAAI,oBAAoB,CAAC,SAAS,CAAC;QAAE,OAAO,sBAAsB,CAAA;IAClE,IAAI,eAAe,CAAC,SAAS,CAAC;QAAE,OAAO,gBAAgB,CAAA;IACvD,IAAI,SAAS,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAA;IAE1C,MAAM,IAAI,KAAK,CACX,6HAA6H,CAChI,CAAA;AACL,CAAC"}
|