knifecycle
Advanced tools
Comparing version 17.1.0 to 17.2.0
@@ -0,1 +1,10 @@ | ||
# [17.2.0](https://github.com/nfroidure/knifecycle/compare/v17.1.0...v17.2.0) (2024-11-14) | ||
### Features | ||
* **core:** allow to override some services ([e17daed](https://github.com/nfroidure/knifecycle/commit/e17daed4b5ec952eae1e484d0fa7b86127045e57)), closes [#127](https://github.com/nfroidure/knifecycle/issues/127) | ||
# [17.1.0](https://github.com/nfroidure/knifecycle/compare/v17.0.3...v17.1.0) (2024-11-07) | ||
@@ -2,0 +11,0 @@ |
@@ -1,2 +0,2 @@ | ||
import type { Autoloader } from './index.js'; | ||
import { type Autoloader } from './index.js'; | ||
import type { DependencyDeclaration, Initializer } from './util.js'; | ||
@@ -3,0 +3,0 @@ export declare const MANAGED_SERVICES: string[]; |
@@ -1,6 +0,6 @@ | ||
import { SPECIAL_PROPS, parseDependencyDeclaration, initializer, } from './util.js'; | ||
import { SPECIAL_PROPS, INSTANCE, AUTOLOAD, parseDependencyDeclaration, initializer, } from './util.js'; | ||
import { buildInitializationSequence } from './sequence.js'; | ||
import { FATAL_ERROR } from './fatalError.js'; | ||
import { DISPOSE } from './dispose.js'; | ||
export const MANAGED_SERVICES = [FATAL_ERROR, DISPOSE, '$instance']; | ||
export const MANAGED_SERVICES = [FATAL_ERROR, DISPOSE, INSTANCE]; | ||
/* Architecture Note #2: Build | ||
@@ -25,3 +25,3 @@ | ||
type: 'service', | ||
inject: ['$autoload'], | ||
inject: [AUTOLOAD], | ||
}, initInitializerBuilder); | ||
@@ -28,0 +28,0 @@ /** |
@@ -160,4 +160,2 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
$.register(initInitializerBuilder); | ||
$.register(constant('$fatalError', {})); | ||
$.register(constant('$instance', {})); | ||
const { buildInitializer } = await $.run(['buildInitializer']); | ||
@@ -164,0 +162,0 @@ const content = await buildInitializer([ |
@@ -1,2 +0,2 @@ | ||
import { NO_PROVIDER, SPECIAL_PROPS, parseDependencyDeclaration, service, } from './util.js'; | ||
import { INSTANCE, NO_PROVIDER, SILO_CONTEXT, SPECIAL_PROPS, parseDependencyDeclaration, service, } from './util.js'; | ||
import initDebug from 'debug'; | ||
@@ -85,3 +85,3 @@ const debug = initDebug('knifecycle'); | ||
} | ||
export default service(initDispose, DISPOSE, ['$instance', '$siloContext']); | ||
export default service(initDispose, DISPOSE, [INSTANCE, SILO_CONTEXT]); | ||
//# sourceMappingURL=dispose.js.map |
@@ -1,4 +0,5 @@ | ||
import { NO_PROVIDER, SPECIAL_PROPS, SPECIAL_PROPS_PREFIX, DECLARATION_SEPARATOR, OPTIONAL_FLAG, ALLOWED_INITIALIZER_TYPES, ALLOWED_SPECIAL_PROPS, parseInjections, readFunctionName, reuseSpecialProps, parseName, name, autoName, inject, useInject, mergeInject, autoInject, alsoInject, unInject, type, extra, singleton, initializer, constant, service, autoService, provider, autoProvider, wrapInitializer, handler, autoHandler, parseDependencyDeclaration, stringifyDependencyDeclaration, unwrapInitializerProperties } from './util.js'; | ||
import { NO_PROVIDER, INSTANCE, SILO_CONTEXT, AUTOLOAD, SPECIAL_PROPS, SPECIAL_PROPS_PREFIX, DECLARATION_SEPARATOR, OPTIONAL_FLAG, ALLOWED_INITIALIZER_TYPES, ALLOWED_SPECIAL_PROPS, parseInjections, readFunctionName, reuseSpecialProps, parseName, name, autoName, inject, useInject, mergeInject, autoInject, alsoInject, unInject, type, extra, singleton, initializer, constant, service, autoService, provider, autoProvider, wrapInitializer, handler, autoHandler, parseDependencyDeclaration, stringifyDependencyDeclaration, unwrapInitializerProperties } from './util.js'; | ||
import initFatalError, { FATAL_ERROR } from './fatalError.js'; | ||
import initDispose, { DISPOSE } from './dispose.js'; | ||
import { type Overrides, OVERRIDES } from './overrides.js'; | ||
import initInitializerBuilder from './build.js'; | ||
@@ -9,3 +10,3 @@ import type { ServiceName, Service, Disposer, FatalErrorPromise, Provider, Dependencies, DependencyDeclaration, ExtraInformations, ParsedDependencyDeclaration, ConstantProperties, ConstantInitializer, ProviderInitializerBuilder, ProviderProperties, ProviderInitializer, ProviderInputProperties, ServiceInitializerBuilder, ServiceProperties, ServiceInitializer, ServiceInputProperties, AsyncInitializerBuilder, AsyncInitializer, PartialAsyncInitializer, Initializer, ServiceInitializerWrapper, ProviderInitializerWrapper, HandlerFunction, Parameters } from './util.js'; | ||
export { initFatalError, initDispose }; | ||
export type { ServiceName, Service, Disposer, FatalErrorPromise, Provider, Dependencies, DependencyDeclaration, ExtraInformations, ParsedDependencyDeclaration, ConstantProperties, ConstantInitializer, ProviderInitializerBuilder, ProviderProperties, ProviderInitializer, ProviderInputProperties, ServiceInitializerBuilder, ServiceProperties, ServiceInitializer, ServiceInputProperties, AsyncInitializerBuilder, AsyncInitializer, PartialAsyncInitializer, Initializer, ServiceInitializerWrapper, ProviderInitializerWrapper, HandlerFunction, Parameters, BuildInitializer, FatalErrorService, }; | ||
export type { ServiceName, Service, Disposer, FatalErrorPromise, Provider, Dependencies, DependencyDeclaration, ExtraInformations, ParsedDependencyDeclaration, ConstantProperties, ConstantInitializer, ProviderInitializerBuilder, ProviderProperties, ProviderInitializer, ProviderInputProperties, ServiceInitializerBuilder, ServiceProperties, ServiceInitializer, ServiceInputProperties, AsyncInitializerBuilder, AsyncInitializer, PartialAsyncInitializer, Initializer, ServiceInitializerWrapper, ProviderInitializerWrapper, HandlerFunction, Parameters, BuildInitializer, FatalErrorService, Overrides, }; | ||
export declare const RUN_DEPENDENT_NAME = "__run__"; | ||
@@ -71,7 +72,4 @@ export declare const SYSTEM_DEPENDENT_NAME = "__system__"; | ||
}; | ||
export { DISPOSE, FATAL_ERROR }; | ||
export declare const AUTOLOAD = "$autoload"; | ||
export { DISPOSE, FATAL_ERROR, INSTANCE, SILO_CONTEXT, AUTOLOAD, OVERRIDES }; | ||
export declare const INJECTOR = "$injector"; | ||
export declare const INSTANCE = "$instance"; | ||
export declare const SILO_CONTEXT = "$siloContext"; | ||
export declare const UNBUILDABLE_SERVICES: string[]; | ||
@@ -78,0 +76,0 @@ declare class Knifecycle { |
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
/* eslint max-len: ["warn", { "ignoreComments": true }] @typescript-eslint/no-this-alias: "warn" */ | ||
import { NO_PROVIDER, SPECIAL_PROPS, SPECIAL_PROPS_PREFIX, DECLARATION_SEPARATOR, OPTIONAL_FLAG, ALLOWED_INITIALIZER_TYPES, ALLOWED_SPECIAL_PROPS, parseInjections, readFunctionName, reuseSpecialProps, parseName, name, autoName, inject, useInject, mergeInject, autoInject, alsoInject, unInject, type, extra, singleton, initializer, constant, service, autoService, provider, autoProvider, wrapInitializer, handler, autoHandler, parseDependencyDeclaration, stringifyDependencyDeclaration, unwrapInitializerProperties, } from './util.js'; | ||
import { NO_PROVIDER, INSTANCE, SILO_CONTEXT, AUTOLOAD, SPECIAL_PROPS, SPECIAL_PROPS_PREFIX, DECLARATION_SEPARATOR, OPTIONAL_FLAG, ALLOWED_INITIALIZER_TYPES, ALLOWED_SPECIAL_PROPS, parseInjections, readFunctionName, reuseSpecialProps, parseName, name, autoName, inject, useInject, mergeInject, autoInject, alsoInject, unInject, type, extra, singleton, initializer, constant, service, autoService, provider, autoProvider, wrapInitializer, handler, autoHandler, parseDependencyDeclaration, stringifyDependencyDeclaration, unwrapInitializerProperties, } from './util.js'; | ||
import initFatalError, { FATAL_ERROR } from './fatalError.js'; | ||
import initDispose, { DISPOSE } from './dispose.js'; | ||
import { OVERRIDES, pickOverridenName } from './overrides.js'; | ||
import initInitializerBuilder from './build.js'; | ||
@@ -16,7 +17,4 @@ import { YError, printStackTrace } from 'yerror'; | ||
const debug = initDebug('knifecycle'); | ||
export { DISPOSE, FATAL_ERROR }; | ||
export const AUTOLOAD = '$autoload'; | ||
export { DISPOSE, FATAL_ERROR, INSTANCE, SILO_CONTEXT, AUTOLOAD, OVERRIDES }; | ||
export const INJECTOR = '$injector'; | ||
export const INSTANCE = '$instance'; | ||
export const SILO_CONTEXT = '$siloContext'; | ||
export const UNBUILDABLE_SERVICES = [ | ||
@@ -80,4 +78,2 @@ AUTOLOAD, | ||
this._options = options || {}; | ||
this._silosCounter = 0; | ||
this._silosContexts = {}; | ||
this._initializersStates = { | ||
@@ -105,2 +101,3 @@ [FATAL_ERROR]: { | ||
this.register(constant(INSTANCE, this)); | ||
this.register(constant(OVERRIDES, {})); | ||
const initInjectorProvider = provider(async ({ $siloContext, $instance, }) => ({ | ||
@@ -116,2 +113,4 @@ service: async (dependenciesDeclarations) => { | ||
this.register(initInjectorProvider); | ||
this._silosCounter = 0; | ||
this._silosContexts = {}; | ||
} | ||
@@ -154,2 +153,10 @@ /* Architecture Note #1.3: Registering initializers | ||
} | ||
if (this._silosContexts && | ||
[INSTANCE, INJECTOR, SILO_CONTEXT, DISPOSE].includes(initializer[SPECIAL_PROPS.NAME])) { | ||
throw new YError('E_IMMUTABLE_SERVICE_NAME', initializer[SPECIAL_PROPS.NAME]); | ||
} | ||
if (initializer[SPECIAL_PROPS.NAME] === OVERRIDES && | ||
initializer[SPECIAL_PROPS.TYPE] !== 'constant') { | ||
throw new YError('E_CONSTANT_SERVICE_NAME', initializer[SPECIAL_PROPS.NAME], initializer[SPECIAL_PROPS.TYPE]); | ||
} | ||
const initializerState = { | ||
@@ -195,2 +202,4 @@ initializer, | ||
_checkInitializerDependencies(initializer) { | ||
// Here, we do not have to take in count the overrides since it | ||
// won't impact the checking | ||
const initializerDependsOfItself = initializer[SPECIAL_PROPS.INJECT] | ||
@@ -398,2 +407,3 @@ .map((dependencyDeclaration) => { | ||
async _loadInitializerDependencies(siloContext, parentsNames, dependenciesDeclarations, additionalDeclarations) { | ||
const overrides = this._initializersStates[OVERRIDES].initializer.$value; | ||
debug(`${[...parentsNames].join('->')}: Gathering the dependencies (${dependenciesDeclarations.join(', ')}).`); | ||
@@ -407,7 +417,14 @@ const allDependenciesDeclarations = [ | ||
const { mappedName, optional } = parseDependencyDeclaration(serviceDeclaration); | ||
const initializerState = this._initializersStates[mappedName] || { | ||
const finalName = pickOverridenName(overrides, [ | ||
...parentsNames, | ||
mappedName, | ||
]); | ||
if (finalName !== mappedName) { | ||
debug(`${[...parentsNames, mappedName].join('->')}: Mapping a dependency (${mappedName} => ${finalName}).`); | ||
} | ||
const initializerState = this._initializersStates[finalName] || { | ||
dependents: [], | ||
autoloaded: true, | ||
}; | ||
this._initializersStates[mappedName] = initializerState; | ||
this._initializersStates[finalName] = initializerState; | ||
initializerState.dependents.push({ | ||
@@ -418,3 +435,3 @@ silo: siloContext.index, | ||
}); | ||
dependencies.push(mappedName); | ||
dependencies.push(finalName); | ||
} | ||
@@ -442,3 +459,7 @@ do { | ||
const { serviceName, mappedName, optional } = parseDependencyDeclaration(dependencyDeclaration); | ||
const provider = this._getServiceProvider(siloContext, mappedName); | ||
const finalName = pickOverridenName(overrides, [ | ||
...parentsNames, | ||
mappedName, | ||
]); | ||
const provider = this._getServiceProvider(siloContext, finalName); | ||
// We expect a provider here since everything | ||
@@ -461,2 +482,6 @@ // should be resolved | ||
debug(`${[...parentsNames, serviceName].join('->')}: Loading the provider...`); | ||
if (parentsNames.includes(serviceName)) { | ||
// At that point there should be an initialiser property | ||
throw new YError('E_CIRCULAR_DEPENDENCY', ...parentsNames, serviceName); | ||
} | ||
const initializerState = this._initializersStates[serviceName]; | ||
@@ -463,0 +488,0 @@ if (!('initializer' in initializerState) || !initializerState.initializer) { |
export declare const NO_PROVIDER: unique symbol; | ||
export declare const INSTANCE = "$instance"; | ||
export declare const SILO_CONTEXT = "$siloContext"; | ||
export declare const AUTOLOAD = "$autoload"; | ||
export declare const DECLARATION_SEPARATOR = ">"; | ||
@@ -3,0 +6,0 @@ export declare const OPTIONAL_FLAG = "?"; |
@@ -7,2 +7,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
export const NO_PROVIDER = Symbol('NO_PROVIDER'); | ||
export const INSTANCE = '$instance'; | ||
export const SILO_CONTEXT = '$siloContext'; | ||
export const AUTOLOAD = '$autoload'; | ||
/* Architecture Note #1.2: Creating initializers | ||
@@ -308,3 +311,5 @@ | ||
const originalDependencies = (initializer[SPECIAL_PROPS.INJECT] || []).map(parseDependencyDeclaration); | ||
return inject(originalDependencies.filter(({ serviceName }) => filteredDependencies.every(({ serviceName: filteredServiceName }) => serviceName !== filteredServiceName)).map(stringifyDependencyDeclaration), initializer); | ||
return inject(originalDependencies | ||
.filter(({ serviceName }) => filteredDependencies.every(({ serviceName: filteredServiceName }) => serviceName !== filteredServiceName)) | ||
.map(stringifyDependencyDeclaration), initializer); | ||
} | ||
@@ -311,0 +316,0 @@ export function useInject(from, to) { |
@@ -28,3 +28,3 @@ { | ||
"name": "knifecycle", | ||
"version": "17.1.0", | ||
"version": "17.2.0", | ||
"description": "Manage your NodeJS processes's lifecycle automatically with an unobtrusive dependency injection implementation.", | ||
@@ -31,0 +31,0 @@ "main": "dist/index.js", |
@@ -180,4 +180,2 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
$.register(initInitializerBuilder); | ||
$.register(constant('$fatalError', {})); | ||
$.register(constant('$instance', {})); | ||
@@ -184,0 +182,0 @@ const { buildInitializer } = await $.run<any>(['buildInitializer']); |
import { | ||
SPECIAL_PROPS, | ||
INSTANCE, | ||
AUTOLOAD, | ||
parseDependencyDeclaration, | ||
@@ -9,3 +11,3 @@ initializer, | ||
import { DISPOSE } from './dispose.js'; | ||
import type { Autoloader } from './index.js'; | ||
import { type Autoloader } from './index.js'; | ||
import type { | ||
@@ -17,3 +19,3 @@ DependencyDeclaration, | ||
export const MANAGED_SERVICES = [FATAL_ERROR, DISPOSE, '$instance']; | ||
export const MANAGED_SERVICES = [FATAL_ERROR, DISPOSE, INSTANCE]; | ||
@@ -55,3 +57,3 @@ type DependencyTreeNode = { | ||
type: 'service', | ||
inject: ['$autoload'], | ||
inject: [AUTOLOAD], | ||
}, | ||
@@ -58,0 +60,0 @@ initInitializerBuilder, |
import { | ||
INSTANCE, | ||
NO_PROVIDER, | ||
SILO_CONTEXT, | ||
SPECIAL_PROPS, | ||
@@ -148,2 +150,2 @@ parseDependencyDeclaration, | ||
export default service(initDispose, DISPOSE, ['$instance', '$siloContext']); | ||
export default service(initDispose, DISPOSE, [INSTANCE, SILO_CONTEXT]); |
@@ -125,2 +125,20 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
}); | ||
test('should fail when overriding a reserved service', async () => { | ||
try { | ||
$.register(constant('$dispose', 2)); | ||
throw new YError('E_UNEXPECTED_SUCCESS'); | ||
} catch (err) { | ||
assert.equal((err as YError).code, 'E_IMMUTABLE_SERVICE_NAME'); | ||
} | ||
}); | ||
test('should fail when overriding a constant service with anything else', async () => { | ||
try { | ||
$.register(service(timeService, '$overrides')); | ||
throw new YError('E_UNEXPECTED_SUCCESS'); | ||
} catch (err) { | ||
assert.equal((err as YError).code, 'E_CONSTANT_SERVICE_NAME'); | ||
} | ||
}); | ||
}); | ||
@@ -156,2 +174,46 @@ | ||
}); | ||
test('should work with services names overrides', async () => { | ||
$.register( | ||
service( | ||
async ({ test2 }) => | ||
() => | ||
test2(), | ||
'test', | ||
['test2'], | ||
), | ||
); | ||
$.register(service(async () => () => 2, 'test2')); | ||
$.register(service(async () => () => 3, 'test3')); | ||
$.register(constant('$overrides', { test2: 'test3' })); | ||
const { test } = await $.run<any>(['test']); | ||
assert.deepEqual(test(), 3); | ||
}); | ||
test('should work with complex services names overrides', async () => { | ||
$.register( | ||
service( | ||
async ({ log }) => | ||
() => | ||
log('from debugLog'), | ||
'debugLog', | ||
['log'], | ||
), | ||
); | ||
$.register(service(async () => (str) => 'log ' + str, 'log')); | ||
$.register( | ||
constant('$overrides', { | ||
log: 'debugLog', | ||
debugLog: { | ||
log: 'log', | ||
}, | ||
}), | ||
); | ||
const { log } = await $.run<any>(['log']); | ||
assert.deepEqual(log(), 'log from debugLog'); | ||
}); | ||
}); | ||
@@ -264,5 +326,49 @@ | ||
}); | ||
test('should work with provider names overrides', async () => { | ||
$.register( | ||
initializer( | ||
{ | ||
type: 'provider', | ||
name: 'test', | ||
inject: ['test2'], | ||
}, | ||
async ({ test2 }) => ({ | ||
service: test2, | ||
}), | ||
), | ||
); | ||
$.register( | ||
initializer( | ||
{ | ||
type: 'provider', | ||
name: 'test2', | ||
inject: [], | ||
}, | ||
async () => ({ | ||
service: 2, | ||
}), | ||
), | ||
); | ||
$.register( | ||
initializer( | ||
{ | ||
type: 'provider', | ||
name: 'test3', | ||
inject: [], | ||
}, | ||
async () => ({ | ||
service: 3, | ||
}), | ||
), | ||
); | ||
$.register(constant('$overrides', { test2: 'test3' })); | ||
const { test } = await $.run<any>(['test']); | ||
assert.deepEqual(test, 3); | ||
}); | ||
}); | ||
test('should fail when intitializer is no a function', () => { | ||
test('should fail when initializer is no a function', () => { | ||
assert.throws( | ||
@@ -353,3 +459,3 @@ () => { | ||
test('should fail with special autoload intitializer that is not a singleton', () => { | ||
test('should fail with special autoload initializer that is not a singleton', () => { | ||
assert.throws( | ||
@@ -720,2 +826,3 @@ () => { | ||
}); | ||
describe('should fail', () => { | ||
@@ -786,2 +893,47 @@ test('with bad service', async () => { | ||
test('with indirect circular dependencies', async () => { | ||
$.register( | ||
service( | ||
async () => { | ||
return () => 'human'; | ||
}, | ||
'human', | ||
['tree'], | ||
), | ||
); | ||
$.register( | ||
service( | ||
async () => { | ||
return () => 'tree'; | ||
}, | ||
'tree', | ||
['earth'], | ||
), | ||
); | ||
$.register( | ||
service( | ||
async () => { | ||
return () => 'earth'; | ||
}, | ||
'earth', | ||
['person'], | ||
), | ||
); | ||
$.register(constant('$overrides', { person: 'human' })); | ||
try { | ||
await $.run<any>(['human']); | ||
throw new Error('E_UNEXPECTED_SUCCESS'); | ||
} catch (err) { | ||
assert.deepEqual((err as YError).code, 'E_CIRCULAR_DEPENDENCY'); | ||
assert.deepEqual((err as YError).params, [ | ||
'__run__', | ||
'human', | ||
'tree', | ||
'earth', | ||
'human', | ||
]); | ||
} | ||
}); | ||
test('and provide a fatal error handler', async () => { | ||
@@ -986,3 +1138,3 @@ $.register(constant('ENV', ENV)); | ||
test('and instanciate services once', async () => { | ||
test('and instantiate services once', async () => { | ||
$.register( | ||
@@ -1228,2 +1380,60 @@ initializer( | ||
test('when autoloaded dependencies are circularly dependent', async () => { | ||
$.register( | ||
service( | ||
async () => { | ||
return 'mainService'; | ||
}, | ||
'mainService', | ||
['parentService1'], | ||
), | ||
); | ||
$.register( | ||
service( | ||
async () => { | ||
return 'parentService1'; | ||
}, | ||
'parentService1', | ||
['parentService2'], | ||
), | ||
); | ||
$.register( | ||
initializer( | ||
{ | ||
type: 'service', | ||
name: '$autoload', | ||
inject: ['?ENV', '?log'], | ||
singleton: true, | ||
}, | ||
async () => async (serviceName) => ({ | ||
path: `/path/of/${serviceName}`, | ||
initializer: initializer( | ||
{ | ||
type: 'service', | ||
name: serviceName, | ||
inject: ['parentService1'], | ||
}, | ||
async () => `THE_${serviceName.toUpperCase()}:` + serviceName, | ||
), | ||
}), | ||
), | ||
); | ||
try { | ||
await $.run<any>(['test', 'log']); | ||
throw new YError('E_UNEXPECTED_SUCCESS'); | ||
} catch (err) { | ||
assert.equal((err as YError).code, 'E_BAD_AUTOLOADED_INITIALIZER'); | ||
assert.deepEqual((err as YError).params, ['parentService2']); | ||
assert.equal( | ||
((err as YError).wrappedErrors[0] as YError).code, | ||
'E_CIRCULAR_DEPENDENCY', | ||
); | ||
assert.deepEqual( | ||
((err as YError).wrappedErrors[0] as YError).params, | ||
['parentService2', 'parentService1', 'parentService2'], | ||
); | ||
} | ||
}); | ||
test('when the autoloader returns bad data', async () => { | ||
@@ -1506,3 +1716,3 @@ $.register( | ||
test('should work when trigered from several silos simultaneously', async () => { | ||
test('should work when triggered from several silos simultaneously', async () => { | ||
$.register(constant('ENV', ENV)); | ||
@@ -1560,3 +1770,3 @@ $.register(constant('time', time)); | ||
await $.run<any>(['ENV', 'hash', 'hash1']); | ||
throw new YError('E_UNEXPECTED_SUCCES'); | ||
throw new YError('E_UNEXPECTED_SUCCESS'); | ||
} catch (err) { | ||
@@ -1563,0 +1773,0 @@ assert.equal((err as YError).code, 'E_INSTANCE_DESTROYED'); |
@@ -5,2 +5,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
NO_PROVIDER, | ||
INSTANCE, | ||
SILO_CONTEXT, | ||
AUTOLOAD, | ||
SPECIAL_PROPS, | ||
@@ -42,2 +45,3 @@ SPECIAL_PROPS_PREFIX, | ||
import initDispose, { DISPOSE } from './dispose.js'; | ||
import { type Overrides, OVERRIDES, pickOverridenName } from './overrides.js'; | ||
import initInitializerBuilder from './build.js'; | ||
@@ -108,2 +112,3 @@ import { YError, printStackTrace } from 'yerror'; | ||
FatalErrorService, | ||
Overrides, | ||
}; | ||
@@ -193,7 +198,4 @@ | ||
export { DISPOSE, FATAL_ERROR }; | ||
export const AUTOLOAD = '$autoload'; | ||
export { DISPOSE, FATAL_ERROR, INSTANCE, SILO_CONTEXT, AUTOLOAD, OVERRIDES }; | ||
export const INJECTOR = '$injector'; | ||
export const INSTANCE = '$instance'; | ||
export const SILO_CONTEXT = '$siloContext'; | ||
export const UNBUILDABLE_SERVICES = [ | ||
@@ -263,4 +265,2 @@ AUTOLOAD, | ||
this._options = options || {}; | ||
this._silosCounter = 0; | ||
this._silosContexts = {}; | ||
this._initializersStates = { | ||
@@ -288,2 +288,3 @@ [FATAL_ERROR]: { | ||
this.register(constant(INSTANCE, this)); | ||
this.register(constant(OVERRIDES, {})); | ||
@@ -316,2 +317,4 @@ const initInjectorProvider = provider( | ||
this.register(initInjectorProvider); | ||
this._silosCounter = 0; | ||
this._silosContexts = {}; | ||
} | ||
@@ -356,2 +359,23 @@ | ||
} | ||
if ( | ||
this._silosContexts && | ||
[INSTANCE, INJECTOR, SILO_CONTEXT, DISPOSE].includes( | ||
initializer[SPECIAL_PROPS.NAME], | ||
) | ||
) { | ||
throw new YError( | ||
'E_IMMUTABLE_SERVICE_NAME', | ||
initializer[SPECIAL_PROPS.NAME], | ||
); | ||
} | ||
if ( | ||
initializer[SPECIAL_PROPS.NAME] === OVERRIDES && | ||
initializer[SPECIAL_PROPS.TYPE] !== 'constant' | ||
) { | ||
throw new YError( | ||
'E_CONSTANT_SERVICE_NAME', | ||
initializer[SPECIAL_PROPS.NAME], | ||
initializer[SPECIAL_PROPS.TYPE], | ||
); | ||
} | ||
@@ -416,2 +440,4 @@ const initializerState: InitializerStateDescriptor<any, any> = { | ||
_checkInitializerDependencies(initializer: Initializer<any, any>) { | ||
// Here, we do not have to take in count the overrides since it | ||
// won't impact the checking | ||
const initializerDependsOfItself = initializer[SPECIAL_PROPS.INJECT] | ||
@@ -771,2 +797,8 @@ .map((dependencyDeclaration) => { | ||
): Promise<Dependencies> { | ||
const overrides = ( | ||
this._initializersStates[OVERRIDES].initializer as ConstantInitializer< | ||
Record<string, string> | ||
> | ||
).$value as Overrides; | ||
debug( | ||
@@ -786,3 +818,16 @@ `${[...parentsNames].join( | ||
parseDependencyDeclaration(serviceDeclaration); | ||
const initializerState = this._initializersStates[mappedName] || { | ||
const finalName = pickOverridenName(overrides, [ | ||
...parentsNames, | ||
mappedName, | ||
]); | ||
if (finalName !== mappedName) { | ||
debug( | ||
`${[...parentsNames, mappedName].join( | ||
'->', | ||
)}: Mapping a dependency (${mappedName} => ${finalName}).`, | ||
); | ||
} | ||
const initializerState = this._initializersStates[finalName] || { | ||
dependents: [], | ||
@@ -792,3 +837,3 @@ autoloaded: true, | ||
this._initializersStates[mappedName] = initializerState; | ||
this._initializersStates[finalName] = initializerState; | ||
initializerState.dependents.push({ | ||
@@ -800,3 +845,3 @@ silo: siloContext.index, | ||
dependencies.push(mappedName); | ||
dependencies.push(finalName); | ||
} | ||
@@ -839,4 +884,9 @@ | ||
parseDependencyDeclaration(dependencyDeclaration); | ||
const provider = this._getServiceProvider(siloContext, mappedName); | ||
const finalName = pickOverridenName(overrides, [ | ||
...parentsNames, | ||
mappedName, | ||
]); | ||
const provider = this._getServiceProvider(siloContext, finalName); | ||
// We expect a provider here since everything | ||
@@ -884,2 +934,7 @@ // should be resolved | ||
if (parentsNames.includes(serviceName)) { | ||
// At that point there should be an initialiser property | ||
throw new YError('E_CIRCULAR_DEPENDENCY', ...parentsNames, serviceName); | ||
} | ||
const initializerState = this._initializersStates[serviceName]; | ||
@@ -886,0 +941,0 @@ |
@@ -10,2 +10,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
export const NO_PROVIDER = Symbol('NO_PROVIDER'); | ||
export const INSTANCE = '$instance'; | ||
export const SILO_CONTEXT = '$siloContext'; | ||
export const AUTOLOAD = '$autoload'; | ||
@@ -677,8 +680,10 @@ /* Architecture Note #1.2: Creating initializers | ||
return inject<D, S>( | ||
originalDependencies.filter(({ serviceName }) => | ||
filteredDependencies.every( | ||
({ serviceName: filteredServiceName }) => | ||
serviceName !== filteredServiceName, | ||
), | ||
).map(stringifyDependencyDeclaration), | ||
originalDependencies | ||
.filter(({ serviceName }) => | ||
filteredDependencies.every( | ||
({ serviceName: filteredServiceName }) => | ||
serviceName !== filteredServiceName, | ||
), | ||
) | ||
.map(stringifyDependencyDeclaration), | ||
initializer as ServiceInitializerBuilder<D, S>, | ||
@@ -685,0 +690,0 @@ ); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
659641
52
11849