digitaltwin-core
Version:
Minimalist framework to collect and handle data in a Digital Twin project
159 lines • 4.99 kB
JavaScript
import { engineEventBus } from '../engine/events.js';
/**
* Abstract base class for data collection components in the Digital Twin framework.
*
* A Collector is responsible for:
* - Fetching raw data from external sources on a scheduled basis
* - Persisting data through the StorageService
* - Indexing metadata via the DatabaseAdapter
* - Exposing HTTP endpoints for data retrieval
*
* @abstract
* @class Collector
* @implements {Component<CollectorConfiguration>}
* @implements {ScheduleRunnable}
* @implements {Servable}
*
* @example
* ```typescript
* class WeatherCollector extends Collector {
* getConfiguration(): CollectorConfiguration {
* return {
* name: 'weather-data',
* description: 'Collects weather information from API',
* contentType: 'application/json',
* endpoint: 'weather'
* }
* }
*
* getSchedule(): string {
* return '0 *\/15 * * * *' // Every 15 minutes
* }
*
* async collect(): Promise<Buffer> {
* const response = await fetch('https://api.weather.com/data')
* return Buffer.from(await response.text())
* }
* }
* ```
*/
export class Collector {
/**
* Injects required dependencies into the collector instance.
*
* Called by the Digital Twin Engine during component initialization.
*
* @param {DatabaseAdapter} db - Database adapter for metadata operations
* @param {StorageService} storage - Storage service for data persistence
*
* @example
* ```typescript
* const collector = new MyCollector()
* collector.setDependencies(databaseAdapter, storageService)
* ```
*/
setDependencies(db, storage) {
this.db = db;
this.storage = storage;
}
/**
* Executes the complete collection workflow.
*
* This method orchestrates the collection process:
* 1. Calls the collect() method to fetch data
* 2. Persists data through StorageService
* 3. Saves metadata to DatabaseAdapter
* 4. Emits completion events
*
* Called automatically by the scheduler based on getSchedule().
*
* @returns {Promise<Buffer | void>} The collected data buffer, or void if no data
* @throws {Error} When storage or database operations fail
*
* @example
* ```typescript
* // Called automatically by the framework:
* const result = await collector.run()
* if (result) {
* console.log(`Collected ${result.length} bytes`)
* }
* ```
*/
async run() {
const result = await this.collect();
if (result) {
const config = this.getConfiguration();
const now = new Date();
const url = await this.storage.save(result, config.name);
await this.db.save({
name: config.name,
type: config.contentType,
url,
date: now
});
// Emit completion event for monitoring and integration
engineEventBus.emit('component:event', {
type: 'collector:completed',
componentName: config.name,
timestamp: now,
data: { bytesCollected: result.length }
});
}
return result;
}
/**
* Defines HTTP endpoints exposed by this collector.
*
* By default, exposes a GET endpoint at the configured path that returns
* the most recently collected data.
*
* @returns {Array} Array of endpoint descriptors
*
* @example
* ```typescript
* // For a collector with endpoint: 'weather'
* // Exposes: GET /weather
* ```
*/
getEndpoints() {
return [
{
method: 'get',
path: `/${this.getConfiguration().endpoint}`,
handler: this.retrieve.bind(this),
responseType: this.getConfiguration().contentType
}
];
}
/**
* HTTP handler for retrieving the most recently collected data.
*
* Returns the latest data collected by this collector with appropriate
* content headers. Used by the framework to serve HTTP requests.
*
* @returns {Promise<DataResponse>} HTTP response with data or error status
*
* @example
* ```typescript
* // GET /weather -> Returns latest weather data
* // Response: { status: 200, content: Buffer, headers: {...} }
* ```
*/
async retrieve() {
const config = this.getConfiguration();
const record = await this.db.getLatestByName(config.name);
if (!record) {
return {
status: 404,
content: 'No data available'
};
}
const blob = await record.data();
return {
status: 200,
content: blob,
headers: { 'Content-Type': record.contentType }
};
}
}
//# sourceMappingURL=collector.js.map