UNPKG

digitaltwin-core

Version:

Minimalist framework to collect and handle data in a Digital Twin project

159 lines 4.99 kB
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