express-service-bootstrap
Version:
This is a convenience package for starting a express API with security, health checks, process exits etc.
154 lines • 8.17 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DisposableSingletonContainer = void 0;
const bootstrap_constructor_1 = require("./bootstrap-constructor");
/**
* DisposableSingletonContainer is a class that is used to create instances of classes and manage their lifecycle via singleton methods.
*/
class DisposableSingletonContainer {
/**
* Creates an instance of DisposableSingletonContainer.
* @param singletonContainer The singleton container map(defaults to an empty map)
* @param disposeSequenceMap The dispose sequence map(defaults to an empty map, to be filled if singletonContainer is not empty)
* @param disposeSequence The dispose sequence number(defaults to 0, to be incremented appropriately if singletonContainer is not empty)
* @param bootstrap The bootstrap constructor.
*/
constructor(singletonContainer = new Map(), disposeSequenceMap = new Map(), disposeSequence = 0, bootstrap = new bootstrap_constructor_1.BootstrapConstructor()) {
this.singletonContainer = singletonContainer;
this.disposeSequenceMap = disposeSequenceMap;
this.disposeSequence = disposeSequence;
this.bootstrap = bootstrap;
}
/**
* Creates a new instance of a class with a constructor or returns an existing one based on name.
* @param {string} name The name of the instance, has to be unique across all instances.
* @param typeConstructor The class constructor
* @param constructorArguments The arguments to pass to the constructor(optional)
* @param {number} disposeSequence The dispose sequence number(optional)
* @returns The instance of the class
*/
createInstance(name, typeConstructor, constructorArguments, disposeSequence) {
if (!this.singletonContainer.has(name)) {
const newInstance = this.bootstrap.createInstance(typeConstructor, constructorArguments);
this.registerInstance(name, newInstance, disposeSequence, true);
}
return this.singletonContainer.get(name);
}
/**
* Creates a new instance of a class without a constructor asynchronously or returns an existing one based on name.
* @param {string} name The name of the instance, has to be unique across all instances.
* @param typeConstructorFunction The class constructor ASYNC function.
* @param constructorFunctionArguments The arguments to pass to the constructor(optional)
* @param {number} disposeSequence The dispose sequence number(optional)
* @returns The instance of the class
*/
createAsyncInstanceWithoutConstructor(name, typeConstructorFunction, constructorFunctionArguments, disposeSequence) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.singletonContainer.has(name)) {
const newInstance = yield this.bootstrap.createAsyncInstanceWithoutConstructor(typeConstructorFunction, constructorFunctionArguments);
this.registerInstance(name, newInstance, disposeSequence, true);
}
return this.singletonContainer.get(name);
});
}
/**
* Creates a new instance of a class without a constructor or returns an existing one based on name.
* @param {string} name The name of the instance, has to be unique across all instances.
* @param typeConstructorFunction The class constructor
* @param constructorFunctionArguments The arguments to pass to the constructor(optional)
* @param {number} disposeSequence The dispose sequence number(optional)
* @returns The instance of the class
* @template InstanceType The type of the instance
* @returns {InstanceType} The instance of the class
*/
createInstanceWithoutConstructor(name, typeConstructorFunction, constructorFunctionArguments, disposeSequence) {
if (!this.singletonContainer.has(name)) {
const newInstance = this.bootstrap.createInstanceWithoutConstructor(typeConstructorFunction, constructorFunctionArguments);
this.registerInstance(name, newInstance, disposeSequence, true);
}
return this.singletonContainer.get(name);
}
/**
* Fetches an existing instance based on name.
* @param {string} name The name of the instance
* @returns The instance of the class or undefined if it does not exist
* @template InstanceType The type of the instance
* @returns {InstanceType | undefined} The instance of the class or undefined if it does not exist
*/
fetchInstance(name) {
return this.singletonContainer.get(name);
}
/**
* Registers an existing instance based on name.
* @param {string} name The name of the instance
* @param {InstanceType} instance The instance of the class
* @param {number} disposeSequence The dispose sequence number(optional)
* @template InstanceType The type of the instance
* @returns {void} void
*/
registerInstance(name, instance, disposeSequence, overrideExistingInstance = true) {
//throw new Error('Not implemented');
if (overrideExistingInstance === false && this.singletonContainer.has(name)) {
return false;
}
this.disposeSequence++;
disposeSequence = disposeSequence || this.disposeSequence;
const existingMembers = this.disposeSequenceMap.get(disposeSequence) || new Set();
existingMembers.add(name);
this.disposeSequenceMap.set(disposeSequence, existingMembers);
this.singletonContainer.set(name, instance);
return true;
}
/**
* Disposes an existing instance based on name.
* @param {string} name The name of the instance
* @returns {Promise<void>} void
*/
disposeInstance(name) {
return __awaiter(this, void 0, void 0, function* () {
if (this.singletonContainer.has(name)) {
if (this.singletonContainer.get(name)[Symbol.dispose] != null) {
this.singletonContainer.get(name)[Symbol.dispose]();
}
if (this.singletonContainer.get(name)[Symbol.asyncDispose] != null) {
yield this.singletonContainer.get(name)[Symbol.asyncDispose]();
}
this.singletonContainer.delete(name);
this.disposeSequenceMap.forEach((setOfNames, sequence) => {
if (setOfNames.has(name)) {
setOfNames.delete(name);
if (setOfNames.size === 0) {
this.disposeSequenceMap.delete(sequence);
}
}
});
}
});
}
/**
* Disposes all existing instances based on the dispose sequence.
* @returns {Promise<void>} void
*/
disposeAll() {
return __awaiter(this, void 0, void 0, function* () {
//Sort descending order of dispose sequence
const sortedDisposeSequence = Array.from(this.disposeSequenceMap.keys()).sort((a, b) => b - a);
for (const sequence of sortedDisposeSequence) {
for (const instanceName of (this.disposeSequenceMap.get(sequence) || new Set())) {
yield this.disposeInstance(instanceName);
}
}
});
}
}
exports.DisposableSingletonContainer = DisposableSingletonContainer;
//# sourceMappingURL=disposable-singleton-container.js.map