@villedemontreal/workit-core
Version:
This package provides default and no-op implementations of the WorkIt types for client packages.
197 lines • 7.21 kB
JavaScript
"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