UNPKG

@mdf.js/openc2-core

Version:

MMS - API Core - OpenC2

141 lines 5.52 kB
"use strict"; /** * Copyright 2024 Mytra Control S.L. All rights reserved. * * Use of this source code is governed by an MIT-style license that can be found in the LICENSE file * or at https://opensource.org/licenses/MIT. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.AdapterWrapper = void 0; const tslib_1 = require("tslib"); const core_1 = require("@mdf.js/core"); const crash_1 = require("@mdf.js/crash"); const utils_1 = require("@mdf.js/utils"); const events_1 = tslib_1.__importDefault(require("events")); const lodash_1 = require("lodash"); const uuid_1 = require("uuid"); class AdapterWrapper extends events_1.default { /** * Create a new instance of AdapterWrapper * @param adapter - adapter instance * @param retryOptions - options for job retry operations */ constructor(adapter, retryOptions) { super(); this.adapter = adapter; /** Register an error in the adapter operation */ this.onOperationError = (rawError) => { this.lastOperationError = crash_1.Crash.from(rawError, this.adapter.componentId); this.lastOperationDate = new Date(); this.emitStatus(); }; /** Register an error in the adapter operation */ this.onOperationSuccess = () => { this.lastOperationError = undefined; this.lastOperationDate = new Date(); }; /** Perform the publication of the message in the underlayer transport system */ this.publish = async (message) => { return this.wrappedOperation(this.publishOriginal, [message], this.retryOptions); }; this.retryOptions = (0, lodash_1.merge)({ logger: this.onOperationError }, retryOptions); if (!this.adapter) { throw new crash_1.Crash('AdapterWrapper requires an adapter instance'); } this.checkMandatoryMethods(); this.publishOriginal = this.adapter.publish; this.adapter.publish = this.publish; this.on('newListener', (event, listener) => { if ((0, uuid_1.validate)(event)) { this.adapter.on(event, listener); } }); this.on('removeListener', (event, listener) => { if ((0, uuid_1.validate)(event)) { this.adapter.off(event, listener); } }); } /** Component name */ get name() { return this.adapter.name; } /** Component identifier */ get componentId() { return this.adapter.componentId; } /** Connect the OpenC2 Adapter to the underlayer transport system */ start() { return this.adapter.start(); } /** Disconnect the OpenC2 Adapter to the underlayer transport system */ stop() { return this.adapter.stop(); } /** Close the OpenC2 Adapter to the underlayer transport system */ close() { return this.adapter.close(); } /** * Check if the adapter implements the mandatory methods * @throws Crash if the adapter does not implement the mandatory methods */ checkMandatoryMethods() { if (!this.adapter.publish || typeof this.adapter.publish !== 'function') { throw new crash_1.Crash(`Adapter ${this.adapter.name} does not implement the publish method`); } } /** * Perform the retry functionality for a promise * @param task - promise to execute * @param funcArgs - promise arguments * @param options - control execution options * @returns */ async wrappedOperation(task, funcArgs, options) { try { const result = await (0, utils_1.retryBind)(task, this.adapter, funcArgs, options); this.onOperationSuccess(); return result; } catch (rawError) { const error = new crash_1.Crash(`Error performing [${task.name}] operation on ${this.adapter.name} plug`, this.adapter.componentId, { cause: crash_1.Crash.from(rawError, this.adapter.componentId) }); this.onOperationError(error); throw rawError; } } /** Overall component status */ get status() { return core_1.Health.overallStatus(this.checks); } /** Emit the status if it's different from the last emitted status */ emitStatus() { if (this.lastStatusEmitted !== this.status) { this.lastStatusEmitted = this.status; this.emit('status', this.status); } } /** * Return the status of the adapter in a standard format * @returns _check object_ as defined in the draft standard * https://datatracker.ietf.org/doc/html/draft-inadarei-api-health-check-05 */ get checks() { return { ...this.adapter.checks, [`${this.adapter.name}:lastOperation`]: [ { status: this.lastOperationError ? 'fail' : 'pass', componentId: this.adapter.componentId, componentType: 'adapter', observedValue: this.lastOperationError ? 'error' : 'ok', observedUnit: 'result of last operation', time: this.lastOperationDate ? this.lastOperationDate.toISOString() : undefined, output: this.lastOperationError ? this.lastOperationError.trace() : undefined, }, ], }; } } exports.AdapterWrapper = AdapterWrapper; //# sourceMappingURL=AdapterWrapper.js.map