const destroy = Symbol('destroy'); const instanceKey = Symbol('instances'); type ServiceDependency = new (services: Services) => T & { [destroy]?: () => Promise | void; }; class Services { [instanceKey]: Map, unknown>; constructor() { this[instanceKey] = new Map(); } public get = (service: ServiceDependency) => { if (!this[instanceKey].has(service)) { this[instanceKey].set(service, new service(this)); } const instance = this[instanceKey].get(service); if (!instance) { throw new Error('Could not generate instance'); } return instance as T; }; public set = (service: ServiceDependency, instance: Partial) => { this[instanceKey].set(service, instance); }; public clone = () => { const services = new Services(); services[instanceKey] = Object.fromEntries(this[instanceKey].entries()); }; public destroy = async () => { await Promise.all( this[instanceKey].values().map(async (instance) => { if ( typeof instance === 'object' && instance && destroy in instance && typeof instance[destroy] === 'function' ) { await instance[destroy](); } }), ); }; } export { Services, destroy };