digitaltwin-core
Version:
Minimalist framework to collect and handle data in a Digital Twin project
110 lines • 3.72 kB
JavaScript
/**
* @fileoverview Handler component base class for HTTP endpoint providers
*
* Handlers are lightweight, stateless components that expose HTTP endpoints
* for on-demand data access, computation, or utility services within the digital twin.
*/
/**
* Abstract base class for Handler components.
*
* Handlers are lightweight, stateless components that expose HTTP endpoints
* for on-demand data access, computation, or utility services. Unlike Collectors
* and Harvesters, they don't run on schedules but respond to HTTP requests.
*
* Key features:
* - Expose HTTP endpoints using the @servableEndpoint decorator
* - Stateless operation (no database or storage dependencies by default)
* - Suitable for real-time computations, data queries, or API proxies
*
* @example
* ```typescript
* class CalculatorHandler extends Handler {
* getConfiguration() {
* return {
* name: 'calculator-handler',
* type: 'handler',
* contentType: 'application/json'
* };
* }
*
* @servableEndpoint({ path: '/api/calculate/sum', method: 'post' })
* async calculateSum(req: Request) {
* const { a, b } = req.body;
* return {
* status: 200,
* content: { result: a + b }
* };
* }
* }
* ```
*/
export class Handler {
/**
* Resolves and returns HTTP endpoints defined on this handler.
*
* Automatically discovers endpoints declared with the @servableEndpoint
* decorator and creates bound handler functions for registration with
* the Express router.
*
* @returns Array of endpoint descriptors with bound handler functions
*/
getEndpoints() {
const config = this.getConfiguration();
const ctor = this.constructor;
const endpoints = ctor.__endpoints || [];
return endpoints.map(ep => {
const handlerFn = this[ep.handlerName].bind(this);
return {
method: ep.method,
path: ep.path,
responseType: ep.responseType || config.contentType,
handler: handlerFn
};
});
}
/**
* Returns the OpenAPI specification for this handler's endpoints.
*
* Generates documentation for all endpoints declared with @servableEndpoint.
* Can be overridden by subclasses for more detailed specifications.
*
* @returns {OpenAPIComponentSpec} OpenAPI paths, tags, and schemas for this handler
*/
getOpenAPISpec() {
const config = this.getConfiguration();
const endpoints = this.getEndpoints();
const tagName = config.tags?.[0] || config.name;
const paths = {};
for (const endpoint of endpoints) {
const method = endpoint.method.toLowerCase();
if (!paths[endpoint.path]) {
paths[endpoint.path] = {};
}
paths[endpoint.path][method] = {
summary: `${method.toUpperCase()} ${endpoint.path}`,
description: config.description,
tags: [tagName],
responses: {
'200': {
description: 'Successful response',
content: {
[endpoint.responseType || config.contentType]: {
schema: { type: 'object' }
}
}
}
}
};
}
return {
paths,
tags: [
{
name: tagName,
description: config.description
}
]
};
}
}
//# sourceMappingURL=handler.js.map