##// END OF EJS Templates
sync
sync

File last commit:

r15:3985e8405319 tip default
r15:3985e8405319 tip default
Show More
LifetimeManager.ts
97 lines | 2.9 KiB | video/mp2t | TypeScriptLexer
/ src / main / ts / LifetimeManager.ts
import { ILifetime, ILifetimeContext, ILifetimeManager, ILifetimeSlot } from "../typings/interfaces";
import { LifetimeSlot } from "./LifetimeSlot";
import { argumentNotNull } from "./traits";
const noop = () => { };
const fail = (message: string) => (): never => {
throw new Error(message);
};
const _emptySlot = Object.freeze({
has: () => false,
initialize: () => false,
get: fail("The specified item isn't registered with a lifetime manager"),
store: noop,
remove: noop,
cleanup: noop,
});
export class LifetimeManager implements ILifetimeManager {
private _destroyed = false;
private readonly _slots: Record<string, ILifetimeSlot<unknown>> = {};
slot<T>(slotId: string | number): ILifetimeSlot<T> {
if (this._destroyed)
throw new Error("The lifetime manager is destroyed");
if (slotId in this._slots)
return this._slots[slotId] as ILifetimeSlot<T>;
return this._slots[slotId] = new LifetimeSlot<T>(() => delete this._slots[slotId]);
}
destroy() {
if (!this._destroyed) {
this._destroyed = true;
Object.values(this._slots).forEach(slot => {
try {
slot.cleanup();
} catch {
// ignore
}
});
}
}
}
export const emptySlot = <T>() => _emptySlot as ILifetimeSlot<T>;
export const emptyLifetime = <T>() => emptySlot as ILifetime<T>;
export const scopeLifetime = <T>(level: number, slotId: string | number) =>
(context: ILifetimeContext) =>
context.scopeSlot<T>(level, slotId);
export const hierarchyLifetime = <T>(slotId: string | number) =>
(context: ILifetimeContext) =>
context.hierarchySlot<T>(slotId);
/**
* Creates a lifetime instance bound to the current activation context. This
* lifetime will store the service instance per activation context. Every
* top level service resolution will create a new activation context. This
* context is propagated to subsequent service resolution thus all services
* with context lifetime will be shared among their consumers.
*
* @returns The instance of the lifetime.
*/
export const contextLifetime = <T>(slotId: string | number) =>
(context: ILifetimeContext) =>
context.contextSlot<T>(slotId);
const singletons = new LifetimeManager();
/**
* Creates the lifetime for the service which will allow existence only one
* instance with the specified {@linkcode typeId}. If there will be created
* several lifetime instances with same `typeId` in the runtime, they will
* share the same service instance.
*
* @param typeId The identified for the global instance, usually this is a
* fully qualified class name
* @returns The lifetime instance
*/
export const singletonLifetime = <T>(typeId: string) => {
argumentNotNull(typeId, "typeId");
return () => singletons.slot<T>(typeId);
};