From 86a34ca367a13cbfa62def2a98bca0a5d0fdd180 Mon Sep 17 00:00:00 2001 From: Nicolas Froidure Date: Wed, 16 Aug 2023 09:24:01 +0200 Subject: [PATCH] refactor(core): better naming and undefined/null services --- ARCHITECTURE.md | 8 +- src/index.test.ts | 196 ++++++++++++++++++--- src/index.ts | 439 +++++++++++++++++++++++----------------------- 3 files changed, 395 insertions(+), 248 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 6d0f3f3..116f42a 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -37,7 +37,7 @@ It is designed to have a low footprint on services code. In fact, the Knifecycle API is aimed to allow to statically build its services load/unload code once in production. -[See in context](./src/index.ts#L193-L212) +[See in context](./src/index.ts#L192-L211) @@ -52,7 +52,7 @@ A service provider is full of state since its concern is [encapsulate](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)) your application global states. -[See in context](./src/index.ts#L214-L223) +[See in context](./src/index.ts#L213-L222) @@ -121,7 +121,7 @@ Initializers can be of three types: instanciated once for all for each executions silos using them (we will cover this topic later on). -[See in context](./src/index.ts#L302-L326) +[See in context](./src/index.ts#L301-L325) @@ -137,7 +137,7 @@ Depending on your application design, you could run it in only one execution silo or into several ones according to the isolation level your wish to reach. -[See in context](./src/index.ts#L612-L622) +[See in context](./src/index.ts#L613-L623) diff --git a/src/index.test.ts b/src/index.test.ts index 7a0978d..966037a 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -14,8 +14,8 @@ import { service, provider, singleton, - FatalErrorService, } from './index.js'; +import type { Provider, FatalErrorService } from './index.js'; import { ALLOWED_INITIALIZER_TYPES } from './util.js'; describe('Knifecycle', () => { @@ -35,6 +35,55 @@ describe('Knifecycle', () => { }; } + const nullService = service<{ time: any }, null>( + async function nullService({ time }: { time: any }): Promise { + // service run for its side effect only + time(); + return null; + }, + 'nullService', + ['time'], + ); + const undefinedService = service<{ time: any }, undefined>( + async function undefinedService({ + time, + }: { + time: any; + }): Promise { + // service run for its side effect only + time(); + return undefined; + }, + 'undefinedService', + ['time'], + ); + const nullProvider = provider<{ time: any }, null>( + async function nullProvider({ + time, + }: { + time: any; + }): Promise> { + // provider run for its side effect only + time(); + return { service: null }; + }, + 'nullProvider', + ['time'], + ); + const undefinedProvider = provider<{ time: any }, undefined>( + async function undefinedProvider({ + time, + }: { + time: any; + }): Promise> { + // service run for its side effect only + time(); + return { service: undefined }; + }, + 'undefinedProvider', + ['time'], + ); + beforeEach(() => { $ = new Knifecycle(); }); @@ -485,16 +534,7 @@ describe('Knifecycle', () => { test('should work with null service dependencies', async () => { const time = jest.fn(); - const nullService = service<{ time: any }, null>( - async function nullService({ time }: { time: any }): Promise { - // service run for its side effect only - time(); - return null; - }, - 'nullService', - ['time'], - ); - $.register(service(nullService, 'nullService')); + $.register(nullService); $.register(constant('time', time)); const dependencies = await $.run(['nullService']); @@ -505,30 +545,39 @@ describe('Knifecycle', () => { }); }); - test('should work with undefined service dependencies', async () => { + test('should work with null provider dependencies', async () => { const time = jest.fn(); - const undefinedService = service<{ time: any }, undefined>( - async function undefinedService({ - time, - }: { - time: any; - }): Promise { - // service run for its side effect only - time(); - return undefined; - }, - 'undefinedService', - ['time'], - ); - $.register(service(undefinedService, 'undefinedService')); + $.register(nullProvider); $.register(constant('time', time)); - const dependencies = await $.run(['undefinedService']); + const dependencies = await $.run(['nullProvider']); - assert.deepEqual(Object.keys(dependencies), ['undefinedService']); + assert.deepEqual(Object.keys(dependencies), ['nullProvider']); + assert.deepEqual(dependencies, { + nullProvider: null, + }); + }); + + test('should work with undefined dependencies', async () => { + const time = jest.fn(); + + $.register(undefinedService); + $.register(undefinedProvider); + $.register(constant('time', time)); + + const dependencies = await $.run([ + 'undefinedService', + 'undefinedProvider', + ]); + + assert.deepEqual(Object.keys(dependencies), [ + 'undefinedService', + 'undefinedProvider', + ]); assert.deepEqual(dependencies, { undefinedService: undefined, + undefinedProvider: undefined, }); }); @@ -915,6 +964,97 @@ describe('Knifecycle', () => { assert.deepEqual(Object.keys(dependencies), ['hash', 'hash_', 'hash3']); }); + test('should work with null service dependencies', async () => { + const time = jest.fn(); + + $.register(constant('time', time)); + + $.register( + initializer( + { + name: '$autoload', + type: 'service', + singleton: true, + }, + async () => async (serviceName) => ({ + path: `/path/to/${serviceName}`, + initializer: nullService, + }), + ), + ); + + const dependencies = await $.run(['nullService']); + + assert.deepEqual(Object.keys(dependencies), ['nullService']); + assert.deepEqual(dependencies, { + nullService: null, + }); + }); + + test('should work with null provider dependencies', async () => { + const time = jest.fn(); + + $.register(constant('time', time)); + + $.register( + initializer( + { + name: '$autoload', + type: 'service', + singleton: true, + }, + async () => async (serviceName) => ({ + path: `/path/to/${serviceName}`, + initializer: nullProvider, + }), + ), + ); + + const dependencies = await $.run(['nullProvider']); + + assert.deepEqual(Object.keys(dependencies), ['nullProvider']); + assert.deepEqual(dependencies, { + nullProvider: null, + }); + }); + + test('should work with undefined dependencies', async () => { + const time = jest.fn(); + + $.register( + initializer( + { + name: '$autoload', + type: 'service', + singleton: true, + }, + async () => async (serviceName) => ({ + path: `/path/to/${serviceName}`, + initializer: + serviceName === 'undefinedService' + ? undefinedService + : undefinedProvider, + }), + ), + ); + + $.register(constant('time', time)); + + const dependencies = await $.run([ + 'undefinedService', + 'undefinedProvider', + ]); + + assert.deepEqual(Object.keys(dependencies), [ + 'undefinedService', + 'undefinedProvider', + ]); + assert.deepEqual(dependencies, { + undefinedService: undefined, + undefinedProvider: null, + }); + }); + test('should fail when autoload does not exists', async () => { try { await $.run(['test']); diff --git a/src/index.ts b/src/index.ts index 71b65af..efa0262 100644 --- a/src/index.ts +++ b/src/index.ts @@ -102,6 +102,7 @@ export const RUN_DEPENDENT_NAME = '__run__'; export const SYSTEM_DEPENDENT_NAME = '__system__'; export const AUTOLOAD_DEPENDENT_NAME = '__autoloader__'; export const INJECTOR_DEPENDENT_NAME = '__injector__'; +export const NO_PROVIDER = Symbol('NO_PROVIDER'); export interface Injector> { (dependencies: DependencyDeclaration[]): Promise; @@ -133,11 +134,9 @@ export type SiloedInitializerStateDescriptor< SiloIndex, { dependency?: ServiceName; - instance?: S; - instanceLoadPromise?: Promise; + provider?: NonNullable | typeof NO_PROVIDER>; + providerLoadPromise?: Promise; instanceDisposePromise?: Promise; - disposer?: Disposer; - fatalErrorPromise?: FatalErrorPromise; } >; }; @@ -145,8 +144,8 @@ export type SingletonInitializerStateDescriptor< S, D extends Dependencies, > = BaseInitializerStateDescriptor & { - singletonInstance?: S; - instanceLoadPromise?: Promise; + singletonProvider?: NonNullable | typeof NO_PROVIDER>; + singletonProviderLoadPromise?: Promise; disposer?: Disposer; fatalErrorPromise?: FatalErrorPromise; }; @@ -344,8 +343,10 @@ class Knifecycle { if (initializer[SPECIAL_PROPS.TYPE] === 'constant') { this._initializersStates[initializer[SPECIAL_PROPS.NAME]] = { initializer, - singletonInstance: initializer[SPECIAL_PROPS.VALUE], - instanceLoadPromise: Promise.resolve(initializer[SPECIAL_PROPS.VALUE]), + singletonProvider: { service: initializer[SPECIAL_PROPS.VALUE] }, + singletonProviderLoadPromise: Promise.resolve( + initializer[SPECIAL_PROPS.VALUE], + ), autoloaded: false, dependents: [], }; @@ -662,13 +663,15 @@ class Knifecycle { Dependencies > ).silosInstances[siloIndex] = { - instance: { - promise: new Promise((_resolve, reject) => { - siloContext.throwFatalError = (err) => { - debug('Handled a fatal error', err); - reject(err); - }; - }), + provider: { + service: { + promise: new Promise((_resolve, reject) => { + siloContext.throwFatalError = (err) => { + debug('Handled a fatal error', err); + reject(err); + }; + }), + }, }, }; @@ -678,7 +681,7 @@ class Knifecycle { SILO_CONTEXT ] as SiloedInitializerStateDescriptor> ).silosInstances[siloIndex] = { - instance: siloContext, + provider: { service: siloContext }, }; // Create a provider for the shutdown special dependency ( @@ -687,124 +690,134 @@ class Knifecycle { Dependencies > ).silosInstances[siloIndex] = { - instance: async () => { - const _this = this; - siloContext._shutdownPromise = - siloContext._shutdownPromise || - _shutdownNextServices(siloContext.loadingSequences.concat()); - await siloContext._shutdownPromise; - delete this._silosContexts[siloContext.index]; - - // Shutdown services in their instanciation order - async function _shutdownNextServices( - serviceLoadSequences: ServiceName[][], - ) { - if (0 === serviceLoadSequences.length) { - return; - } - const currentServiceLoadSequence = serviceLoadSequences.pop() || []; - - // First ensure to remove services that are depend on - // by another service loaded in the same batch (may - // happen depending on the load sequence) - const dependendedByAServiceInTheSameBatch = - currentServiceLoadSequence.filter((serviceName) => { - if ( - currentServiceLoadSequence - .filter( - (anotherServiceName) => anotherServiceName !== serviceName, - ) - .some((anotherServiceName) => - ( - _this._initializersStates[anotherServiceName] - ?.initializer?.[SPECIAL_PROPS.INJECT] || [] + provider: { + service: async () => { + const _this = this; + siloContext._shutdownPromise = + siloContext._shutdownPromise || + _shutdownNextServices(siloContext.loadingSequences.concat()); + await siloContext._shutdownPromise; + delete this._silosContexts[siloContext.index]; + + // Shutdown services in their instanciation order + async function _shutdownNextServices( + serviceLoadSequences: ServiceName[][], + ) { + if (0 === serviceLoadSequences.length) { + return; + } + const currentServiceLoadSequence = serviceLoadSequences.pop() || []; + + // First ensure to remove services that are depend on + // by another service loaded in the same batch (may + // happen depending on the load sequence) + const dependendedByAServiceInTheSameBatch = + currentServiceLoadSequence.filter((serviceName) => { + if ( + currentServiceLoadSequence + .filter( + (anotherServiceName) => + anotherServiceName !== serviceName, ) - .map(_pickServiceNameFromDeclaration) - .includes(serviceName), - ) - ) { - debug( - `Delaying service "${serviceName}" dependencies shutdown to a dedicated batch.'`, - ); - return true; - } - }); - - await Promise.all( - currentServiceLoadSequence - .filter( - (serviceName) => - !dependendedByAServiceInTheSameBatch.includes(serviceName), - ) - .map(async (serviceName) => { - const initializeState = _this._initializersStates[serviceName]; - - if ('silosInstances' in initializeState) { - const provider = _this._getServiceProvider( - siloContext, - serviceName, - ); - - if ( - serviceLoadSequences.some((servicesLoadSequence) => - servicesLoadSequence.includes(serviceName), + .some((anotherServiceName) => + ( + _this._initializersStates[anotherServiceName] + ?.initializer?.[SPECIAL_PROPS.INJECT] || [] + ) + .map(_pickServiceNameFromDeclaration) + .includes(serviceName), ) - ) { - debug( - 'Delaying service shutdown to another batch:', - serviceName, - ); - return Promise.resolve(); - } - if ( - !initializeState.silosInstances[siloContext.index] - .instanceDisposePromise - ) { - debug('Shutting down a service:', serviceName); - initializeState.silosInstances[ - siloContext.index - ].instanceDisposePromise = - provider && 'dispose' in provider && provider.dispose - ? provider.dispose() - : Promise.resolve(); - } else { - debug('Reusing a service shutdown promise:', serviceName); - } - await initializeState.silosInstances[siloContext.index] - .instanceDisposePromise; - } else if ('singletonInstance' in initializeState) { - initializeState.dependents = - initializeState.dependents.filter( - ({ silo }) => silo !== siloContext.index, - ); + ) { + debug( + `Delaying service "${serviceName}" dependencies shutdown to a dedicated batch.'`, + ); + return true; + } + }); - if (initializeState.dependents.length) { - debug( - `Will not shut down the ${serviceName} singleton service (still used ${initializeState.dependents.length} times).`, - initializeState.dependents, - ); - } else { + await Promise.all( + currentServiceLoadSequence + .filter( + (serviceName) => + !dependendedByAServiceInTheSameBatch.includes(serviceName), + ) + .map(async (serviceName) => { + const initializeState = + _this._initializersStates[serviceName]; + + if ('silosInstances' in initializeState) { const provider = _this._getServiceProvider( siloContext, serviceName, ); - debug('Shutting down a singleton service:', serviceName); - delete initializeState.instanceLoadPromise; - delete initializeState.singletonInstance; - return provider && 'dispose' in provider && provider.dispose - ? provider.dispose() - : Promise.resolve(); + + if ( + serviceLoadSequences.some((servicesLoadSequence) => + servicesLoadSequence.includes(serviceName), + ) + ) { + debug( + 'Delaying service shutdown to another batch:', + serviceName, + ); + return Promise.resolve(); + } + if ( + !initializeState.silosInstances[siloContext.index] + .instanceDisposePromise + ) { + debug('Shutting down a service:', serviceName); + initializeState.silosInstances[ + siloContext.index + ].instanceDisposePromise = + provider && + provider !== NO_PROVIDER && + 'dispose' in provider && + provider.dispose + ? provider.dispose() + : Promise.resolve(); + } else { + debug('Reusing a service shutdown promise:', serviceName); + } + await initializeState.silosInstances[siloContext.index] + .instanceDisposePromise; + } else if ('singletonProvider' in initializeState) { + initializeState.dependents = + initializeState.dependents.filter( + ({ silo }) => silo !== siloContext.index, + ); + + if (initializeState.dependents.length) { + debug( + `Will not shut down the ${serviceName} singleton service (still used ${initializeState.dependents.length} times).`, + initializeState.dependents, + ); + } else { + const provider = _this._getServiceProvider( + siloContext, + serviceName, + ); + debug('Shutting down a singleton service:', serviceName); + delete initializeState.singletonProviderLoadPromise; + delete initializeState.singletonProvider; + return provider && + provider !== NO_PROVIDER && + 'dispose' in provider && + provider.dispose + ? provider.dispose() + : Promise.resolve(); + } } - } - }), - ); - if (dependendedByAServiceInTheSameBatch.length) { - serviceLoadSequences.unshift(dependendedByAServiceInTheSameBatch); + }), + ); + if (dependendedByAServiceInTheSameBatch.length) { + serviceLoadSequences.unshift(dependendedByAServiceInTheSameBatch); + } + await _shutdownNextServices(serviceLoadSequences); } - await _shutdownNextServices(serviceLoadSequences); - } + }, + dispose: Promise.resolve.bind(Promise), }, - disposer: Promise.resolve.bind(Promise), }; this._silosContexts[siloContext.index] = siloContext; @@ -831,10 +844,10 @@ class Knifecycle { return this._initializersStates[serviceName]?.initializer; } - _getServiceProvider( + _getServiceProvider( siloContext: SiloContext, serviceName: ServiceName, - ): Provider | undefined { + ): Provider | typeof NO_PROVIDER | undefined { const initializerState = this._initializersStates[serviceName]; // This method expect the initialized to have a state @@ -843,26 +856,26 @@ class Knifecycle { throw new YError('E_UNEXPECTED_SERVICE_READ'); } if ('initializer' in initializerState) { - if ('singletonInstance' in initializerState) { - return { - service: initializerState.singletonInstance as S, - }; + if ('singletonProvider' in initializerState) { + const provider = initializerState.singletonProvider; + + if (provider) { + return provider; + } } if ( 'silosInstances' in initializerState && initializerState.silosInstances && initializerState.silosInstances[siloContext.index] && - 'instance' in initializerState.silosInstances[siloContext.index] + 'provider' in initializerState.silosInstances[siloContext.index] ) { - return { - service: initializerState.silosInstances[siloContext.index] - .instance as S, - dispose: initializerState.silosInstances[siloContext.index].disposer, - fatalErrorPromise: - initializerState.silosInstances[siloContext.index] - .fatalErrorPromise, - }; + const provider = + initializerState.silosInstances[siloContext.index].provider; + + if (provider) { + return provider; + } } } @@ -951,10 +964,7 @@ class Knifecycle { ); } - if ( - !optional && - (!('service' in provider) || 'undefined' === typeof provider.service) - ) { + if (!optional && provider === NO_PROVIDER) { throw new YError( 'E_UNMATCHED_DEPENDENCY', ...parentsNames, @@ -962,10 +972,7 @@ class Knifecycle { ); } - if ( - !('service' in provider) || - 'undefined' === typeof provider.service - ) { + if (provider === NO_PROVIDER) { debug( `${[...parentsNames, serviceName].join( '->', @@ -973,7 +980,7 @@ class Knifecycle { ); } - finalHash[serviceName] = provider?.service; + finalHash[serviceName] = (provider as Provider).service; return finalHash; }, {}, @@ -1003,6 +1010,8 @@ class Knifecycle { [], ); + let providerPromise: Promise>; + if (initializerState.initializer[SPECIAL_PROPS.TYPE] === 'service') { const servicePromise = ( initializerState.initializer as ServiceInitializer< @@ -1016,21 +1025,11 @@ class Knifecycle { throw new YError('E_BAD_SERVICE_PROMISE', serviceName); } - const service = await servicePromise; - - if (initializerState.initializer[SPECIAL_PROPS.SINGLETON]) { - ( - initializerState as SingletonInitializerStateDescriptor - ).singletonInstance = service; - } else { - ( - initializerState as SiloedInitializerStateDescriptor - ).silosInstances[siloContext.index] = { instance: service }; - } + providerPromise = servicePromise.then((service) => ({ service })); } else if ( initializerState.initializer[SPECIAL_PROPS.TYPE] === 'provider' ) { - const providerPromise = ( + providerPromise = ( initializerState.initializer as ProviderInitializer< Dependencies, Service @@ -1041,42 +1040,49 @@ class Knifecycle { debug('Provider initializer did not return a promise:', serviceName); throw new YError('E_BAD_SERVICE_PROVIDER', serviceName); } + } else { + providerPromise = Promise.reject( + new YError('E_UNEXPECTED_STATE', serviceName, initializer), + ); + } - const provider = await providerPromise; + if (initializerState.initializer[SPECIAL_PROPS.SINGLETON]) { + ( + initializerState as SingletonInitializerStateDescriptor + ).singletonProviderLoadPromise = + providerPromise as unknown as Promise; + } else { + ( + initializerState as SiloedInitializerStateDescriptor + ).silosInstances[siloContext.index] = { + providerLoadPromise: providerPromise as unknown as Promise, + }; + } - if ( - !provider || - !(typeof provider === 'object') || - !('service' in provider) - ) { - debug('Provider has no `service` property:', serviceName); - throw new YError('E_BAD_SERVICE_PROVIDER', serviceName); - } + const provider = await providerPromise; - if (provider.fatalErrorPromise) { - debug('Registering service descriptor error promise:', serviceName); - siloContext.errorsPromises.push(provider.fatalErrorPromise); - } + if ( + !provider || + !(typeof provider === 'object') || + !('service' in provider) + ) { + debug('Provider has no `service` property:', serviceName); + throw new YError('E_BAD_SERVICE_PROVIDER', serviceName); + } - if (initializerState.initializer[SPECIAL_PROPS.SINGLETON]) { - ( - initializerState as SingletonInitializerStateDescriptor - ).singletonInstance = provider.service; - ( - initializerState as SingletonInitializerStateDescriptor - ).disposer = provider.dispose; - ( - initializerState as SingletonInitializerStateDescriptor - ).fatalErrorPromise = provider.fatalErrorPromise; - } else { - ( - initializerState as SiloedInitializerStateDescriptor - ).silosInstances[siloContext.index] = { - instance: provider.service, - disposer: provider.dispose, - fatalErrorPromise: provider.fatalErrorPromise, - }; - } + if (provider.fatalErrorPromise) { + debug('Registering service descriptor error promise:', serviceName); + siloContext.errorsPromises.push(provider.fatalErrorPromise); + } + + if (initializerState.initializer[SPECIAL_PROPS.SINGLETON]) { + ( + initializerState as SingletonInitializerStateDescriptor + ).singletonProvider = provider; + } else { + ( + initializerState as SiloedInitializerStateDescriptor + ).silosInstances[siloContext.index] = { provider }; } } @@ -1137,18 +1143,20 @@ class Knifecycle { this._initializersStates[serviceName].initializer = undefined; return; } else { - if (!('instanceLoadPromise' in autoloaderState)) { + if (!('singletonProviderLoadPromise' in autoloaderState)) { debug( `${[...parentsNames, serviceName].join( '->', )}: Instanciating the autoloader...`, ); - // Trick to ensure the instanceLoadPromise is set + // Trick to ensure the singletonProviderLoadPromise is set let resolve; - autoloaderState.instanceLoadPromise = new Promise((_resolve) => { - resolve = _resolve; - }); + autoloaderState.singletonProviderLoadPromise = new Promise( + (_resolve) => { + resolve = _resolve; + }, + ); debug( `${[...parentsNames, serviceName].join( @@ -1160,12 +1168,12 @@ class Knifecycle { await this._loadProvider(siloContext, AUTOLOAD, parentsNames), ); } - await autoloaderState.instanceLoadPromise; + await autoloaderState.singletonProviderLoadPromise; - const autoloader = await this._getServiceProvider>( + const autoloader = (await this._getServiceProvider( siloContext, AUTOLOAD, - ); + )) as Provider>; if (!autoloader) { throw new YError('E_UNEXPECTED_AUTOLOADER'); @@ -1220,19 +1228,18 @@ class Knifecycle { } if (initializer[SPECIAL_PROPS.TYPE] === 'constant') { + const provider = initializer[SPECIAL_PROPS.VALUE]; this._initializersStates[serviceName].initializer = initializer; ( this._initializersStates[ initializer[SPECIAL_PROPS.NAME] ] as SingletonInitializerStateDescriptor - ).singletonInstance = initializer[SPECIAL_PROPS.VALUE]; + ).singletonProvider = provider; ( this._initializersStates[ initializer[SPECIAL_PROPS.NAME] ] as SingletonInitializerStateDescriptor - ).instanceLoadPromise = Promise.resolve( - initializer[SPECIAL_PROPS.VALUE], - ); + ).singletonProviderLoadPromise = Promise.resolve(provider); } else { this._checkInitializerDependencies(initializer); this._initializersStates[serviceName].initializer = initializer; @@ -1279,7 +1286,7 @@ class Knifecycle { initializerState.initializer = undefined; ( initializerState as SingletonInitializerStateDescriptor - ).singletonInstance = undefined; + ).singletonProvider = NO_PROVIDER; } else if ('initializer' in initializerState) { debug( `${[...parentsNames, serviceName].join('->')}: Initializer ready...`, @@ -1288,21 +1295,18 @@ class Knifecycle { const singletonInitializerState = initializerState as SingletonInitializerStateDescriptor; - if (!('instanceLoadPromise' in singletonInitializerState)) { - singletonInitializerState.instanceLoadPromise = this._loadProvider( - siloContext, - serviceName, - parentsNames, - ); + if (!('singletonProviderLoadPromise' in singletonInitializerState)) { + singletonInitializerState.singletonProviderLoadPromise = + this._loadProvider(siloContext, serviceName, parentsNames); } - await singletonInitializerState.instanceLoadPromise; + await singletonInitializerState.singletonProviderLoadPromise; } else { const siloedInitializerState = initializerState as SiloedInitializerStateDescriptor; if (!siloedInitializerState.silosInstances[siloContext.index]) { siloedInitializerState.silosInstances[siloContext.index] = { - instanceLoadPromise: this._loadProvider( + providerLoadPromise: this._loadProvider( siloContext, serviceName, parentsNames, @@ -1310,7 +1314,7 @@ class Knifecycle { }; } await siloedInitializerState.silosInstances[siloContext.index] - .instanceLoadPromise; + .providerLoadPromise; } } } @@ -1356,8 +1360,11 @@ class Knifecycle { Object.keys(this._silosContexts).map(async (siloIndex) => { const siloContext = this._silosContexts[siloIndex]; const $dispose = ( - await this._getServiceProvider(siloContext, DISPOSE) - )?.service as Disposer; + (await this._getServiceProvider( + siloContext, + DISPOSE, + )) as Provider + )?.service; return $dispose(); }),