@codefast/di 0.7.0 → 0.8.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/CHANGELOG.md +33 -0
- package/README.md +1 -1
- package/dist/ambient/active-container.d.ts +4 -0
- package/dist/ambient/active-container.d.ts.map +1 -1
- package/dist/ambient/active-container.js +4 -0
- package/dist/ambient/active-container.js.map +1 -1
- package/dist/container/binding-builders.d.ts.map +1 -1
- package/dist/container/binding-builders.js +4 -5
- package/dist/container/binding-builders.js.map +1 -1
- package/dist/container/container.d.ts +6 -0
- package/dist/container/container.d.ts.map +1 -1
- package/dist/container/container.js +5 -4
- package/dist/container/container.js.map +1 -1
- package/dist/core/binding.d.ts +15 -2
- package/dist/core/binding.d.ts.map +1 -1
- package/dist/core/binding.js +29 -4
- package/dist/core/binding.js.map +1 -1
- package/dist/core/module.d.ts +16 -0
- package/dist/core/module.d.ts.map +1 -1
- package/dist/core/module.js +8 -0
- package/dist/core/module.js.map +1 -1
- package/dist/core/registry.d.ts +2 -3
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/registry.js +16 -61
- package/dist/core/registry.js.map +1 -1
- package/dist/core/tag.d.ts +26 -0
- package/dist/core/tag.d.ts.map +1 -1
- package/dist/core/tag.js +54 -11
- package/dist/core/tag.js.map +1 -1
- package/dist/core/token.d.ts +6 -0
- package/dist/core/token.d.ts.map +1 -1
- package/dist/core/token.js +4 -0
- package/dist/core/token.js.map +1 -1
- package/dist/core/types.d.ts +20 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/decorators/inject.d.ts +2 -0
- package/dist/decorators/inject.d.ts.map +1 -1
- package/dist/decorators/inject.js +2 -0
- package/dist/decorators/inject.js.map +1 -1
- package/dist/decorators/injectable.d.ts +6 -0
- package/dist/decorators/injectable.d.ts.map +1 -1
- package/dist/decorators/injectable.js +4 -0
- package/dist/decorators/injectable.js.map +1 -1
- package/dist/decorators/lifecycle-decorators.d.ts +4 -0
- package/dist/decorators/lifecycle-decorators.d.ts.map +1 -1
- package/dist/decorators/lifecycle-decorators.js +4 -0
- package/dist/decorators/lifecycle-decorators.js.map +1 -1
- package/dist/errors/errors.d.ts +34 -0
- package/dist/errors/errors.d.ts.map +1 -1
- package/dist/errors/errors.js +60 -3
- package/dist/errors/errors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/injection/descriptor.d.ts +12 -0
- package/dist/injection/descriptor.d.ts.map +1 -1
- package/dist/injection/descriptor.js +8 -0
- package/dist/injection/descriptor.js.map +1 -1
- package/dist/injection/resolve-options.d.ts +17 -12
- package/dist/injection/resolve-options.d.ts.map +1 -1
- package/dist/injection/resolve-options.js +69 -15
- package/dist/injection/resolve-options.js.map +1 -1
- package/dist/introspection/dependency-graph.d.ts +6 -0
- package/dist/introspection/dependency-graph.d.ts.map +1 -1
- package/dist/introspection/dependency-graph.js +24 -9
- package/dist/introspection/dependency-graph.js.map +1 -1
- package/dist/introspection/graph-adapters/cytoscape.d.ts +8 -0
- package/dist/introspection/graph-adapters/cytoscape.d.ts.map +1 -1
- package/dist/introspection/graph-adapters/cytoscape.js +2 -0
- package/dist/introspection/graph-adapters/cytoscape.js.map +1 -1
- package/dist/introspection/graph-adapters/dot.d.ts +2 -0
- package/dist/introspection/graph-adapters/dot.d.ts.map +1 -1
- package/dist/introspection/graph-adapters/dot.js +2 -0
- package/dist/introspection/graph-adapters/dot.js.map +1 -1
- package/dist/introspection/graph-adapters/reactflow.d.ts +8 -0
- package/dist/introspection/graph-adapters/reactflow.d.ts.map +1 -1
- package/dist/introspection/graph-adapters/reactflow.js +2 -0
- package/dist/introspection/graph-adapters/reactflow.js.map +1 -1
- package/dist/introspection/inspector.d.ts +6 -0
- package/dist/introspection/inspector.d.ts.map +1 -1
- package/dist/introspection/inspector.js +2 -0
- package/dist/introspection/inspector.js.map +1 -1
- package/dist/lifecycle/lifecycle-manager.d.ts +2 -0
- package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -1
- package/dist/lifecycle/lifecycle-manager.js +2 -0
- package/dist/lifecycle/lifecycle-manager.js.map +1 -1
- package/dist/lifecycle/scope-manager.d.ts +2 -0
- package/dist/lifecycle/scope-manager.d.ts.map +1 -1
- package/dist/lifecycle/scope-manager.js +2 -0
- package/dist/lifecycle/scope-manager.js.map +1 -1
- package/dist/metadata/metadata-keys.d.ts +6 -0
- package/dist/metadata/metadata-keys.d.ts.map +1 -1
- package/dist/metadata/metadata-keys.js +6 -0
- package/dist/metadata/metadata-keys.js.map +1 -1
- package/dist/metadata/metadata-reader-token.d.ts +2 -0
- package/dist/metadata/metadata-reader-token.d.ts.map +1 -1
- package/dist/metadata/metadata-reader-token.js +2 -0
- package/dist/metadata/metadata-reader-token.js.map +1 -1
- package/dist/metadata/metadata-types.d.ts +6 -0
- package/dist/metadata/metadata-types.d.ts.map +1 -1
- package/dist/metadata/symbol-metadata-reader.d.ts +4 -0
- package/dist/metadata/symbol-metadata-reader.d.ts.map +1 -1
- package/dist/metadata/symbol-metadata-reader.js +4 -0
- package/dist/metadata/symbol-metadata-reader.js.map +1 -1
- package/dist/resolution/cache/activation-need.d.ts +2 -0
- package/dist/resolution/cache/activation-need.d.ts.map +1 -1
- package/dist/resolution/cache/activation-need.js +2 -0
- package/dist/resolution/cache/activation-need.js.map +1 -1
- package/dist/resolution/cache/binding-lookup-cache.d.ts +2 -2
- package/dist/resolution/cache/binding-lookup-cache.d.ts.map +1 -1
- package/dist/resolution/cache/binding-lookup-cache.js +2 -37
- package/dist/resolution/cache/binding-lookup-cache.js.map +1 -1
- package/dist/resolution/cache/class-introspector.d.ts +2 -0
- package/dist/resolution/cache/class-introspector.d.ts.map +1 -1
- package/dist/resolution/cache/class-introspector.js +2 -0
- package/dist/resolution/cache/class-introspector.js.map +1 -1
- package/dist/resolution/context.d.ts +6 -0
- package/dist/resolution/context.d.ts.map +1 -1
- package/dist/resolution/context.js +4 -0
- package/dist/resolution/context.js.map +1 -1
- package/dist/resolution/plan/instantiation-plan.d.ts +6 -12
- package/dist/resolution/plan/instantiation-plan.d.ts.map +1 -1
- package/dist/resolution/plan/instantiation-plan.js +11 -27
- package/dist/resolution/plan/instantiation-plan.js.map +1 -1
- package/dist/resolution/resolver.d.ts +14 -5
- package/dist/resolution/resolver.d.ts.map +1 -1
- package/dist/resolution/resolver.js +108 -141
- package/dist/resolution/resolver.js.map +1 -1
- package/dist/resolution/select/binding-select.d.ts +4 -5
- package/dist/resolution/select/binding-select.d.ts.map +1 -1
- package/dist/resolution/select/binding-select.js +18 -20
- package/dist/resolution/select/binding-select.js.map +1 -1
- package/dist/resolution/select/constraints.d.ts +16 -0
- package/dist/resolution/select/constraints.d.ts.map +1 -1
- package/dist/resolution/select/constraints.js +16 -0
- package/dist/resolution/select/constraints.js.map +1 -1
- package/package.json +13 -6
- package/src/ambient/active-container.ts +4 -0
- package/src/container/binding-builders.ts +10 -5
- package/src/container/container.ts +9 -4
- package/src/core/binding.ts +33 -5
- package/src/core/module.ts +16 -0
- package/src/core/registry.ts +16 -66
- package/src/core/tag.ts +71 -17
- package/src/core/token.ts +6 -0
- package/src/core/types.ts +20 -0
- package/src/decorators/inject.ts +2 -0
- package/src/decorators/injectable.ts +8 -0
- package/src/decorators/lifecycle-decorators.ts +4 -0
- package/src/errors/errors.ts +62 -5
- package/src/index.ts +1 -1
- package/src/injection/descriptor.ts +12 -0
- package/src/injection/resolve-options.ts +75 -18
- package/src/introspection/dependency-graph.ts +29 -9
- package/src/introspection/graph-adapters/cytoscape.ts +8 -0
- package/src/introspection/graph-adapters/dot.ts +2 -0
- package/src/introspection/graph-adapters/reactflow.ts +8 -0
- package/src/introspection/inspector.ts +6 -0
- package/src/lifecycle/lifecycle-manager.ts +2 -0
- package/src/lifecycle/scope-manager.ts +2 -0
- package/src/metadata/metadata-keys.ts +6 -0
- package/src/metadata/metadata-reader-token.ts +2 -0
- package/src/metadata/metadata-types.ts +6 -0
- package/src/metadata/symbol-metadata-reader.ts +4 -0
- package/src/resolution/cache/activation-need.ts +2 -0
- package/src/resolution/cache/binding-lookup-cache.ts +2 -40
- package/src/resolution/cache/class-introspector.ts +2 -0
- package/src/resolution/context.ts +6 -0
- package/src/resolution/plan/instantiation-plan.ts +15 -38
- package/src/resolution/resolver.ts +122 -141
- package/src/resolution/select/binding-select.ts +18 -21
- package/src/resolution/select/constraints.ts +16 -0
|
@@ -6,6 +6,8 @@ import type { ConstructorMetadata, LifecycleMetadata, MetadataReader } from "#/m
|
|
|
6
6
|
type AccessorEntry = { readonly key: string | symbol; readonly descriptor: InjectionDescriptor };
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
+
* The default `MetadataReader`, reading decorator metadata stored under `Symbol.metadata`.
|
|
10
|
+
*
|
|
9
11
|
* @since 0.3.16-canary.0
|
|
10
12
|
*/
|
|
11
13
|
export class SymbolMetadataReader implements MetadataReader {
|
|
@@ -117,6 +119,8 @@ function mergeUniqueNames(lists: Array<ReadonlyArray<string>>): Array<string> {
|
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
/**
|
|
122
|
+
* The shared reader a container falls back to when given no custom `MetadataReader`.
|
|
123
|
+
*
|
|
120
124
|
* @since 0.3.16-canary.0
|
|
121
125
|
*/
|
|
122
126
|
export const defaultMetadataReader: SymbolMetadataReader = new SymbolMetadataReader();
|
|
@@ -11,6 +11,8 @@ import type { LifecycleManager } from "#/lifecycle/lifecycle-manager";
|
|
|
11
11
|
import type { ClassIntrospector } from "#/resolution/cache/class-introspector";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
+
* A per-binding cache of whether activation work — hooks or `@postConstruct` — is needed on resolve.
|
|
15
|
+
*
|
|
14
16
|
* @since 0.5.0-canary.8
|
|
15
17
|
*/
|
|
16
18
|
export class ActivationNeedCache {
|
|
@@ -31,14 +31,11 @@ export interface DefaultLookupEntry<Owner> {
|
|
|
31
31
|
*/
|
|
32
32
|
export const ALIAS_HOP_LIMIT = 32;
|
|
33
33
|
|
|
34
|
-
/**
|
|
35
|
-
* @since 0.5.0-canary.8
|
|
36
|
-
*/
|
|
37
|
-
const newNameToEntryMap = <Owner>(): Map<string, DefaultLookupEntry<Owner> | null> => new Map();
|
|
38
|
-
|
|
39
34
|
const newTagToEntryMap = <Owner>(): Map<BindingTag, DefaultLookupEntry<Owner> | null> => new Map();
|
|
40
35
|
|
|
41
36
|
/**
|
|
37
|
+
* A version-stamped cache of binding lookups by token and criterion across the container chain.
|
|
38
|
+
*
|
|
42
39
|
* @since 0.5.0-canary.9
|
|
43
40
|
*/
|
|
44
41
|
export class BindingLookupCache<Owner> {
|
|
@@ -49,8 +46,6 @@ export class BindingLookupCache<Owner> {
|
|
|
49
46
|
// is tracked by the token slot rather than by the entry.
|
|
50
47
|
#lastToken: Token<unknown> | Constructor | undefined;
|
|
51
48
|
#lastEntry: DefaultLookupEntry<Owner> | null = null;
|
|
52
|
-
readonly #byTokenAndName = new Map<Token<unknown> | Constructor, Map<string, DefaultLookupEntry<Owner> | null>>();
|
|
53
|
-
#namedVersion = -1;
|
|
54
49
|
readonly #byTokenAndTag = new Map<Token<unknown> | Constructor, Map<BindingTag, DefaultLookupEntry<Owner> | null>>();
|
|
55
50
|
#taggedVersion = -1;
|
|
56
51
|
// One entry in front of the tag map, and the map is not written until a second distinct request
|
|
@@ -99,24 +94,6 @@ export class BindingLookupCache<Owner> {
|
|
|
99
94
|
return entry;
|
|
100
95
|
}
|
|
101
96
|
|
|
102
|
-
/** `null` when the name's shape needs the full selection path. */
|
|
103
|
-
namedEntry(token: Token<unknown> | Constructor, name: string): DefaultLookupEntry<Owner> | null {
|
|
104
|
-
const version = this.chainVersion();
|
|
105
|
-
if (version !== this.#namedVersion) {
|
|
106
|
-
this.#byTokenAndName.clear();
|
|
107
|
-
this.#namedVersion = version;
|
|
108
|
-
}
|
|
109
|
-
// Computed, not eager: this runs on every named resolve, and the eager form would allocate a
|
|
110
|
-
// Map per call only to discard it on the hit that follows.
|
|
111
|
-
const byName = getOrInsertComputed(this.#byTokenAndName, token, newNameToEntryMap);
|
|
112
|
-
let entry = byName.get(name);
|
|
113
|
-
if (entry === undefined) {
|
|
114
|
-
entry = this.#findNamedInChain(token, name);
|
|
115
|
-
byName.set(name, entry);
|
|
116
|
-
}
|
|
117
|
-
return entry;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
97
|
/** `null` when the tag's shape needs the full selection path. */
|
|
121
98
|
taggedEntry(token: Token<unknown> | Constructor, tag: BindingTag): DefaultLookupEntry<Owner> | null {
|
|
122
99
|
const version = this.chainVersion();
|
|
@@ -175,21 +152,6 @@ export class BindingLookupCache<Owner> {
|
|
|
175
152
|
return this.#parent === undefined ? null : this.#parent.#findDefaultInChain(token);
|
|
176
153
|
}
|
|
177
154
|
|
|
178
|
-
#findNamedInChain(token: Token<unknown> | Constructor, name: string): DefaultLookupEntry<Owner> | null {
|
|
179
|
-
const named = this.#registry.getSimpleNamed(token, name);
|
|
180
|
-
if (named !== undefined) {
|
|
181
|
-
// Predicates need a live context; aliases carry options through the full path.
|
|
182
|
-
if (named.predicate !== undefined || named.kind === "alias") {
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
return { binding: named, owner: this.#owner };
|
|
186
|
-
}
|
|
187
|
-
if (this.#registry.has(token)) {
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
return this.#parent === undefined ? null : this.#parent.#findNamedInChain(token, name);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
155
|
#findTaggedInChain(token: Token<unknown> | Constructor, tag: BindingTag): DefaultLookupEntry<Owner> | null {
|
|
194
156
|
const tagged = this.#registry.getSimpleTagged(token, tag);
|
|
195
157
|
if (tagged !== undefined) {
|
|
@@ -16,6 +16,8 @@ import { UNOWNED_BRANCH } from "#/resolution/path/resolution-path";
|
|
|
16
16
|
// ── ResolutionContext implementation ─────────────────────────────────────────────────────────────────────────────────
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
+
* The engine surface a resolution context calls back into to resolve further dependencies.
|
|
20
|
+
*
|
|
19
21
|
* @since 0.3.16-canary.0
|
|
20
22
|
*/
|
|
21
23
|
export interface ResolverCallbacks {
|
|
@@ -60,6 +62,8 @@ export interface ResolverCallbacks {
|
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
/**
|
|
65
|
+
* The `ResolutionContext` handed to factories and hooks, backed by the engine's callbacks.
|
|
66
|
+
*
|
|
63
67
|
* @since 0.3.16-canary.0
|
|
64
68
|
*/
|
|
65
69
|
export class DefaultResolutionContext implements ResolutionContext {
|
|
@@ -312,6 +316,8 @@ class DefaultConstraintContext implements ConstraintContext {
|
|
|
312
316
|
}
|
|
313
317
|
|
|
314
318
|
/**
|
|
319
|
+
* Creates the resolution-stack frame for one in-flight resolve.
|
|
320
|
+
*
|
|
315
321
|
* @since 0.3.16-canary.0
|
|
316
322
|
*/
|
|
317
323
|
export function buildResolutionFrame(
|
|
@@ -12,7 +12,7 @@ import { tokenName } from "#/core/token";
|
|
|
12
12
|
import type { Constructor, ResolutionFrame, ResolveOptions } from "#/core/types";
|
|
13
13
|
import { AsyncResolutionError } from "#/errors/errors";
|
|
14
14
|
import type { DependencySlot } from "#/injection/resolve-options";
|
|
15
|
-
import { injectionSlotToResolveOptions
|
|
15
|
+
import { injectionSlotToResolveOptions } from "#/injection/resolve-options";
|
|
16
16
|
import type { ConstructorMetadata } from "#/metadata/metadata-types";
|
|
17
17
|
|
|
18
18
|
// Past this depth a dependency escapes to the runtime path rather than inlining further —
|
|
@@ -115,22 +115,13 @@ export interface InstantiationPlanHost {
|
|
|
115
115
|
/** Options-less lookup with alias hops folded; `null` when the fast lane can't answer. */
|
|
116
116
|
lookupDependencyEntry(token: Token<unknown> | Constructor): InstantiationPlanDependencyEntry | null;
|
|
117
117
|
/**
|
|
118
|
-
* A
|
|
118
|
+
* A single-criterion lookup a plan may bake in, or `null` when the answer is not the compiler's
|
|
119
|
+
* to make.
|
|
119
120
|
*
|
|
120
|
-
* @remarks Selection for a
|
|
121
|
+
* @remarks Selection for such a request is an index hit *and* a predicate, and a predicate reads
|
|
121
122
|
* the resolution path — so only a candidate carrying none of one can be decided ahead of time.
|
|
122
123
|
*/
|
|
123
|
-
|
|
124
|
-
token: Token<unknown> | Constructor,
|
|
125
|
-
options: ResolveOptions & { name: string },
|
|
126
|
-
): InstantiationPlanDependencyEntry | null;
|
|
127
|
-
/**
|
|
128
|
-
* The named lookup's single-tag twin, or `null` under the same rule.
|
|
129
|
-
*
|
|
130
|
-
* @remarks Optional so a host predating it stays a valid host — a compiler given none simply
|
|
131
|
-
* escapes the dependency, which is exactly the pre-settlement behavior.
|
|
132
|
-
*/
|
|
133
|
-
lookupPathIndependentTaggedEntry?(
|
|
124
|
+
lookupPathIndependentEntry(
|
|
134
125
|
token: Token<unknown> | Constructor,
|
|
135
126
|
options: ResolveOptions,
|
|
136
127
|
): InstantiationPlanDependencyEntry | null;
|
|
@@ -161,6 +152,8 @@ export interface InstantiationPlanHost {
|
|
|
161
152
|
export type EscapeArity = "all" | "optional" | "single";
|
|
162
153
|
|
|
163
154
|
/**
|
|
155
|
+
* The compiler that flattens a class or resolved binding's dependencies into an instantiation plan.
|
|
156
|
+
*
|
|
164
157
|
* @since 0.3.16-canary.1
|
|
165
158
|
*/
|
|
166
159
|
export class InstantiationPlanCompiler {
|
|
@@ -263,19 +256,11 @@ export class InstantiationPlanCompiler {
|
|
|
263
256
|
return this.#compileEscapeThunk(token, ancestors, "optional", options);
|
|
264
257
|
}
|
|
265
258
|
if (options !== undefined) {
|
|
266
|
-
// A
|
|
267
|
-
// escapes only because
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
return this.#compileDepThunk(named, compileStack, depth, ancestors, options);
|
|
272
|
-
}
|
|
273
|
-
} else {
|
|
274
|
-
// The host owns the whole single-tag decision, including whether the options qualify.
|
|
275
|
-
const tagged = this.#host.lookupPathIndependentTaggedEntry?.(token, options);
|
|
276
|
-
if (tagged !== null && tagged !== undefined) {
|
|
277
|
-
return this.#compileDepThunk(tagged, compileStack, depth, ancestors, options);
|
|
278
|
-
}
|
|
259
|
+
// A criterion the registry can settle without reading a path is a dependency like any other:
|
|
260
|
+
// it escapes only because the host cannot decide it ahead of time.
|
|
261
|
+
const indexed = this.#host.lookupPathIndependentEntry(token, options);
|
|
262
|
+
if (indexed !== null) {
|
|
263
|
+
return this.#compileDepThunk(indexed, compileStack, depth, ancestors, options);
|
|
279
264
|
}
|
|
280
265
|
return this.#compileEscapeThunk(token, ancestors, "single", options);
|
|
281
266
|
}
|
|
@@ -539,17 +524,9 @@ export class InstantiationPlanCompiler {
|
|
|
539
524
|
return this.#compileAsyncEscapeThunk(token, ancestors, "optional", options);
|
|
540
525
|
}
|
|
541
526
|
if (options !== undefined) {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
return this.#compileAsyncDepThunk(named, compileStack, depth, ancestors, options);
|
|
546
|
-
}
|
|
547
|
-
} else {
|
|
548
|
-
// The host owns the whole single-tag decision, including whether the options qualify.
|
|
549
|
-
const tagged = this.#host.lookupPathIndependentTaggedEntry?.(token, options);
|
|
550
|
-
if (tagged !== null && tagged !== undefined) {
|
|
551
|
-
return this.#compileAsyncDepThunk(tagged, compileStack, depth, ancestors, options);
|
|
552
|
-
}
|
|
527
|
+
const indexed = this.#host.lookupPathIndependentEntry(token, options);
|
|
528
|
+
if (indexed !== null) {
|
|
529
|
+
return this.#compileAsyncDepThunk(indexed, compileStack, depth, ancestors, options);
|
|
553
530
|
}
|
|
554
531
|
return this.#compileAsyncEscapeThunk(token, ancestors, "single", options);
|
|
555
532
|
}
|