@fluojs/di 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +89 -7
- package/README.md +89 -7
- package/dist/container.d.ts +39 -5
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +382 -48
- package/dist/errors.d.ts +2 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +3 -2
- package/dist/internal.d.ts +15 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +25 -0
- package/dist/multi-contribution-registry.d.ts +26 -0
- package/dist/multi-contribution-registry.d.ts.map +1 -0
- package/dist/multi-contribution-registry.js +29 -0
- package/dist/provider-normalization.d.ts.map +1 -1
- package/dist/provider-normalization.js +9 -4
- package/package.json +5 -5
package/dist/errors.js
CHANGED
|
@@ -85,12 +85,13 @@ export class ScopeMismatchError extends FluoCodeError {
|
|
|
85
85
|
*
|
|
86
86
|
* @remarks
|
|
87
87
|
* The formatted message includes the full dependency path plus a first-party hint that points callers toward
|
|
88
|
-
* extracting shared logic or
|
|
88
|
+
* extracting shared logic, introducing a mediator, or moving the interaction to a later boundary.
|
|
89
|
+
* `forwardRef()` only defers declaration-time token lookup and cannot resolve a true constructor cycle.
|
|
89
90
|
*/
|
|
90
91
|
export class CircularDependencyError extends FluoCodeError {
|
|
91
92
|
constructor(chain, detail) {
|
|
92
93
|
const path = chain.map(token => formatTokenName(token)).join(' -> ');
|
|
93
|
-
const hint = 'Break the cycle by extracting shared logic into a separate provider, or
|
|
94
|
+
const hint = 'Break the constructor cycle by extracting shared logic into a separate provider, introducing a mediator, or moving the interaction to a later boundary. forwardRef() only defers declaration-time token lookup and cannot resolve a true constructor cycle.';
|
|
94
95
|
super((detail ? `Circular dependency detected: ${path}. ${detail}` : `Circular dependency detected: ${path}`) + `\n Dependency chain: ${path}` + `\n Hint: ${hint}`, 'CIRCULAR_DEPENDENCY', {
|
|
95
96
|
meta: {
|
|
96
97
|
chain: chain.map(t => formatTokenName(t)),
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
import type { Token } from '@fluojs/core';
|
|
2
|
+
import { type MultiContributionResolverOwner } from './multi-contribution-registry.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves one ordered multi-provider contribution through its owning container.
|
|
5
|
+
*
|
|
6
|
+
* This integration seam is for Fluo packages such as `@fluojs/runtime` and
|
|
7
|
+
* `@fluojs/testing`; application code must use `Container.resolve(...)`.
|
|
8
|
+
*
|
|
9
|
+
* @param container Container that owns the multi-provider registration.
|
|
10
|
+
* @param token Multi-provider token.
|
|
11
|
+
* @param contributionIndex Provider-order index for the contribution.
|
|
12
|
+
* @returns The canonical container-resolved contribution instance.
|
|
13
|
+
* @throws {ContainerResolutionError} When the container has no registered internal resolver.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveMultiContribution(container: MultiContributionResolverOwner, token: Token, contributionIndex: number): Promise<unknown>;
|
|
1
16
|
export { validateProviderInputs } from './provider-normalization.js';
|
|
2
17
|
export type { Provider } from './types.js';
|
|
3
18
|
//# sourceMappingURL=internal.d.ts.map
|
package/dist/internal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAG1C,OAAO,EACL,KAAK,8BAA8B,EAEpC,MAAM,kCAAkC,CAAC;AAE1C;;;;;;;;;;;GAWG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,8BAA8B,EACzC,KAAK,EAAE,KAAK,EACZ,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,OAAO,CAAC,CAWlB;AAED,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/internal.js
CHANGED
|
@@ -1 +1,26 @@
|
|
|
1
|
+
import { ContainerResolutionError } from './errors.js';
|
|
2
|
+
import { multiContributionResolverFor } from './multi-contribution-registry.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resolves one ordered multi-provider contribution through its owning container.
|
|
6
|
+
*
|
|
7
|
+
* This integration seam is for Fluo packages such as `@fluojs/runtime` and
|
|
8
|
+
* `@fluojs/testing`; application code must use `Container.resolve(...)`.
|
|
9
|
+
*
|
|
10
|
+
* @param container Container that owns the multi-provider registration.
|
|
11
|
+
* @param token Multi-provider token.
|
|
12
|
+
* @param contributionIndex Provider-order index for the contribution.
|
|
13
|
+
* @returns The canonical container-resolved contribution instance.
|
|
14
|
+
* @throws {ContainerResolutionError} When the container has no registered internal resolver.
|
|
15
|
+
*/
|
|
16
|
+
export async function resolveMultiContribution(container, token, contributionIndex) {
|
|
17
|
+
const resolver = multiContributionResolverFor(container);
|
|
18
|
+
if (!resolver) {
|
|
19
|
+
throw new ContainerResolutionError('Container does not expose the internal multi-provider contribution resolver.', {
|
|
20
|
+
token,
|
|
21
|
+
hint: 'Create the container through the @fluojs/di Container constructor.'
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return resolver(token, contributionIndex);
|
|
25
|
+
}
|
|
1
26
|
export { validateProviderInputs } from './provider-normalization.js';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Token } from '@fluojs/core';
|
|
2
|
+
type MultiContributionResolver = (token: Token, contributionIndex: number) => Promise<unknown>;
|
|
3
|
+
/**
|
|
4
|
+
* Object identity that owns a canonical multi-provider contribution resolver.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export type MultiContributionResolverOwner = object;
|
|
9
|
+
/**
|
|
10
|
+
* Associates a container with its canonical multi-provider contribution resolver.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
* @param container Container that owns the resolver.
|
|
14
|
+
* @param resolver Container-bound resolver that preserves DI lifecycle invariants.
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerMultiContributionResolver(container: MultiContributionResolverOwner, resolver: MultiContributionResolver): void;
|
|
17
|
+
/**
|
|
18
|
+
* Retrieves the canonical multi-provider contribution resolver for a container.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
* @param container Container that owns the resolver.
|
|
22
|
+
* @returns The container-bound resolver, if the container registered one.
|
|
23
|
+
*/
|
|
24
|
+
export declare function multiContributionResolverFor(container: MultiContributionResolverOwner): MultiContributionResolver | undefined;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=multi-contribution-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-contribution-registry.d.ts","sourceRoot":"","sources":["../src/multi-contribution-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,KAAK,yBAAyB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/F;;;;GAIG;AACH,MAAM,MAAM,8BAA8B,GAAG,MAAM,CAAC;AAIpD;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,8BAA8B,EACzC,QAAQ,EAAE,yBAAyB,GAClC,IAAI,CAEN;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,8BAA8B,GACxC,yBAAyB,GAAG,SAAS,CAEvC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object identity that owns a canonical multi-provider contribution resolver.
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const multiContributionResolvers = new WeakMap();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Associates a container with its canonical multi-provider contribution resolver.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
* @param container Container that owns the resolver.
|
|
14
|
+
* @param resolver Container-bound resolver that preserves DI lifecycle invariants.
|
|
15
|
+
*/
|
|
16
|
+
export function registerMultiContributionResolver(container, resolver) {
|
|
17
|
+
multiContributionResolvers.set(container, resolver);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Retrieves the canonical multi-provider contribution resolver for a container.
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
* @param container Container that owns the resolver.
|
|
25
|
+
* @returns The container-bound resolver, if the container registered one.
|
|
26
|
+
*/
|
|
27
|
+
export function multiContributionResolverFor(container) {
|
|
28
|
+
return multiContributionResolvers.get(container);
|
|
29
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-normalization.d.ts","sourceRoot":"","sources":["../src/provider-normalization.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAA2B,kBAAkB,EAAiB,QAAQ,EAAE,MAAM,YAAY,CAAC;AA6JvG;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"provider-normalization.d.ts","sourceRoot":"","sources":["../src/provider-normalization.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAA2B,kBAAkB,EAAiB,QAAQ,EAAE,MAAM,YAAY,CAAC;AA6JvG;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,kBAAkB,CAuFxE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,CAMxE"}
|
|
@@ -37,8 +37,8 @@ function isScope(value) {
|
|
|
37
37
|
return value === 'singleton' || value === 'request' || value === 'transient';
|
|
38
38
|
}
|
|
39
39
|
function assertProviderToken(provider) {
|
|
40
|
-
if (!('provide' in provider) || provider.provide
|
|
41
|
-
throw new InvalidProviderError('Provider object must include a
|
|
40
|
+
if (!('provide' in provider) || !isToken(provider.provide)) {
|
|
41
|
+
throw new InvalidProviderError('Provider object must include a string, symbol, or constructable class provide token.');
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
function assertProviderStrategy(provider) {
|
|
@@ -138,6 +138,11 @@ export function normalizeProvider(provider) {
|
|
|
138
138
|
assertObjectProvider(objectProvider);
|
|
139
139
|
const explicitScope = normalizeProviderScope(objectProvider.scope, objectProvider.provide);
|
|
140
140
|
if ('useValue' in objectProvider) {
|
|
141
|
+
if (Object.hasOwn(objectProvider, 'inject')) {
|
|
142
|
+
throw new InvalidProviderError('Value providers must not declare inject dependencies.', {
|
|
143
|
+
token: objectProvider.provide
|
|
144
|
+
});
|
|
145
|
+
}
|
|
141
146
|
return freezeNormalizedProvider({
|
|
142
147
|
inject: [],
|
|
143
148
|
multi: objectProvider.multi,
|
|
@@ -180,8 +185,8 @@ export function normalizeProvider(provider) {
|
|
|
180
185
|
});
|
|
181
186
|
}
|
|
182
187
|
if ('useExisting' in objectProvider) {
|
|
183
|
-
if (objectProvider.useExisting
|
|
184
|
-
throw new InvalidProviderError('Alias provider useExisting must be a
|
|
188
|
+
if (!isToken(objectProvider.useExisting)) {
|
|
189
|
+
throw new InvalidProviderError('Alias provider useExisting must be a string, symbol, or constructable class token.', {
|
|
185
190
|
token: objectProvider.provide
|
|
186
191
|
});
|
|
187
192
|
}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"container",
|
|
10
10
|
"provider"
|
|
11
11
|
],
|
|
12
|
-
"version": "
|
|
12
|
+
"version": "3.0.0",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"directory": "packages/di"
|
|
19
19
|
},
|
|
20
20
|
"engines": {
|
|
21
|
-
"node": ">=
|
|
21
|
+
"node": ">=24.0.0 <27"
|
|
22
22
|
},
|
|
23
23
|
"publishConfig": {
|
|
24
24
|
"access": "public"
|
|
@@ -40,15 +40,15 @@
|
|
|
40
40
|
"dist"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@fluojs/core": "^
|
|
43
|
+
"@fluojs/core": "^2.0.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"vitest": "^
|
|
46
|
+
"vitest": "^4.1.11"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|
|
50
50
|
"build": "pnpm exec babel src --extensions .ts --ignore 'src/**/*.test.ts' --out-dir dist --config-file ../../tooling/babel/babel.config.cjs && pnpm exec tsc -p tsconfig.build.json",
|
|
51
|
-
"typecheck": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
51
|
+
"typecheck": "pnpm exec tsc -p tsconfig.typecheck.json --noEmit",
|
|
52
52
|
"test": "pnpm exec vitest run -c vitest.config.ts",
|
|
53
53
|
"test:watch": "pnpm exec vitest -c vitest.config.ts"
|
|
54
54
|
}
|