UNPKG

@villedemontreal/workit-core

Version:

This package provides default and no-op implementations of the WorkIt types for client packages.

197 lines 7.21 kB
"use strict"; /* * Copyright (c) 2025 Ville de Montreal. All rights reserved. * Licensed under the MIT license. * See LICENSE file in the project root for full license information. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.IOC = exports.Container = void 0; const inversify_1 = require("inversify"); Object.defineProperty(exports, "Container", { enumerable: true, get: function () { return inversify_1.Container; } }); const util_1 = require("util"); /** * Useful IOC (Inversion Of Control) * CORE identifier (aka name param in static method) use the following enum: SERVICE_IDENTIFIER */ class IOC { constructor(container) { this._container = container; } /** * return false if there is nothing to unbind */ unbind(name) { if (!name) { throw new Error('we need to have a name'); } try { this._container.unbind(name); return true; } catch (error) { return false; } } isServiceBound(serviceIdentifier, name) { if (!serviceIdentifier) { throw new Error('param should not be empty'); } try { if (name) { return this._container.isBoundNamed(serviceIdentifier, name); } return this._container.isBound(serviceIdentifier); } catch (e) { return false; } } /** * Bind your Class to a SERVICE_IDENTIFIER * * @param {*} ctor Constructor * @param {(string | symbol)} serviceIdentifier * @param {((symbol | string)[])} [dependencies] * @param {(string | symbol | null)} [named] * @param {boolean} [singletonMode=true] default true. */ bindTo(ctor, serviceIdentifier, dependencies, named, singletonMode = true) { IOC._inject(ctor, dependencies); const service = this._container.bind(serviceIdentifier).to(ctor); if (singletonMode) { service.inSingletonScope(); } if (named) { service.whenTargetNamed(named); } else { service.whenTargetIsDefault(); } } bindToAsDefault(ctor, serviceIdentifier, dependencies) { IOC._inject(ctor, dependencies); this._container.bind(serviceIdentifier).to(ctor).inSingletonScope().whenTargetIsDefault(); } // todo: merge with bindTo bindToObject(obj, serviceIdentifier, named) { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const newObj = IOC._overrideConfig(obj, serviceIdentifier); const service = this._container.bind(serviceIdentifier).toConstantValue(newObj); if (named) { service.whenTargetNamed(named); } } /** * @deprecated * Bind your Class to a SERVICE_IDENTIFIER * This method doesn't support dependencies * @template T * @param {string} serviceIdentifier * @param {*} ctor contstructor * @param {string} targetNamed * @param {boolean} [singletonMode=true] default true * @memberof IoC */ bind(serviceIdentifier, ctor, targetNamed, singletonMode = true) { const service = this._container.bind(serviceIdentifier).to(ctor); if (singletonMode) { service.inSingletonScope(); } service.whenTargetNamed(targetNamed); } get(serviceIdentifier, named) { if (named) { return this._container.isBoundNamed(serviceIdentifier, named) ? this._container.getNamed(serviceIdentifier, named) : this._container.get(serviceIdentifier); } return this._container.get(serviceIdentifier); } /** * Useful for getting task instance for a specific workflow. * It can check if there is a task for a specific workflow version or it will rollback to the serviceIdentifier if nothing is boundNamed. * Otherwise it will throw an error */ getTask(serviceIdentifier, workflow) { if (!workflow) { return this._container.get(serviceIdentifier); } const workflowId = workflow.bpmnProcessId; const workflowVersion = workflow.version; const pattern = this.getWorkflowNamed(workflow); if (workflowVersion && this._container.isBoundNamed(serviceIdentifier, pattern)) { return this._container.getNamed(serviceIdentifier, pattern); } if (this._container.isBoundNamed(serviceIdentifier, workflowId)) { return this._container.getNamed(serviceIdentifier, workflowId); } return this._container.get(serviceIdentifier); } bindTask(ctor, serviceIdentifier, workflow, dependencies, singletonMode = true) { const named = this.getWorkflowNamed(workflow); this.bindTo(ctor, serviceIdentifier, dependencies, named, singletonMode); } getWorkflowNamed(workflow) { IOC._validateWorkflow(workflow); const workflowId = workflow.bpmnProcessId; const workflowVersion = workflow.version; // can't be 0 if (workflowVersion) { return `${workflowId}${IOC.charSplit}${workflowVersion}`; } return workflowId; } /** * Warning: You should not use this or you know what you are doing. * Container is exposed for avoiding to block developpers. * Container is Inversify Object. * If you need to use it, please create a ticket on Github and describe your use case. * @memberof IoC */ getContainer() { return this._container; } /** * Seems Hacky, we should look to use inversify factory in order to inject config and then override. * */ static _overrideConfig(obj, serviceIdentifier) { if (!obj) { return obj; } const id = serviceIdentifier.toString(); let newObj = obj; if (id === 'camunda_external_config' || id === 'Symbol(camunda_external_config)') { newObj = { ...obj, autoPoll: false }; } return newObj; } static _inject(ctor, dependencies) { try { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument (0, inversify_1.decorate)((0, inversify_1.injectable)(), ctor); (dependencies || []).forEach((dependency, index) => { let injection; if (typeof dependency === 'string' && dependency.endsWith('[]')) { injection = (0, inversify_1.multiInject)(dependency); } else { injection = (0, inversify_1.inject)(dependency); } // eslint-disable-next-line @typescript-eslint/no-unsafe-argument (0, inversify_1.decorate)(injection, ctor, index); }); } catch { // } } static _validateWorkflow(workflow) { if (!(0, util_1.isObject)(workflow) || typeof workflow.bpmnProcessId !== 'string') { throw new Error('workflow object is required'); } } } exports.IOC = IOC; IOC.charSplit = ':'; //# sourceMappingURL=IoC.js.map