@codefast/di 0.7.1 → 0.8.1
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 +40 -0
- package/README.md +242 -159
- package/dist/ambient/active-container.d.ts +1 -2
- package/dist/ambient/active-container.js +1 -2
- package/dist/container/binding-builders.d.ts +1 -2
- package/dist/container/binding-builders.js +5 -7
- package/dist/container/container.d.ts +1 -2
- package/dist/container/container.js +4 -6
- package/dist/core/binding-scope.d.ts +1 -2
- package/dist/core/binding-scope.js +1 -2
- package/dist/core/binding.d.ts +16 -4
- package/dist/core/binding.js +30 -6
- package/dist/core/constraint-requirement.d.ts +1 -2
- package/dist/core/constraint-requirement.js +1 -2
- package/dist/core/constructor-type.d.ts +1 -2
- package/dist/core/constructor-type.js +1 -2
- package/dist/core/map-upsert.d.ts +1 -2
- package/dist/core/map-upsert.js +1 -2
- package/dist/core/module.d.ts +1 -2
- package/dist/core/module.js +1 -2
- package/dist/core/registry.d.ts +1 -5
- package/dist/core/registry.js +15 -63
- package/dist/core/tag.d.ts +27 -2
- package/dist/core/tag.js +55 -13
- package/dist/core/token.d.ts +1 -2
- package/dist/core/token.js +1 -2
- package/dist/core/types.d.ts +1 -2
- package/dist/core/types.js +1 -2
- package/dist/decorators/inject.d.ts +1 -2
- package/dist/decorators/inject.js +1 -2
- package/dist/decorators/injectable.d.ts +1 -2
- package/dist/decorators/injectable.js +1 -2
- package/dist/decorators/lifecycle-decorators.d.ts +1 -2
- package/dist/decorators/lifecycle-decorators.js +1 -2
- package/dist/errors/diagnostics.d.ts +1 -2
- package/dist/errors/diagnostics.js +1 -2
- package/dist/errors/errors.d.ts +1 -2
- package/dist/errors/errors.js +29 -5
- package/dist/index.d.ts +2 -3
- package/dist/index.js +2 -3
- package/dist/injection/descriptor.d.ts +1 -2
- package/dist/injection/descriptor.js +1 -2
- package/dist/injection/resolve-options.d.ts +18 -14
- package/dist/injection/resolve-options.js +70 -17
- package/dist/introspection/dependency-graph.d.ts +1 -2
- package/dist/introspection/dependency-graph.js +23 -11
- package/dist/introspection/graph-adapters/cytoscape.d.ts +1 -2
- package/dist/introspection/graph-adapters/cytoscape.js +1 -2
- package/dist/introspection/graph-adapters/dot.d.ts +1 -2
- package/dist/introspection/graph-adapters/dot.js +1 -2
- package/dist/introspection/graph-adapters/mermaid.d.ts +1 -2
- package/dist/introspection/graph-adapters/mermaid.js +1 -2
- package/dist/introspection/graph-adapters/reactflow.d.ts +1 -2
- package/dist/introspection/graph-adapters/reactflow.js +1 -2
- package/dist/introspection/inspector.d.ts +1 -2
- package/dist/introspection/inspector.js +1 -2
- package/dist/lifecycle/lifecycle-manager.d.ts +1 -2
- package/dist/lifecycle/lifecycle-manager.js +1 -2
- package/dist/lifecycle/scope-manager.d.ts +1 -2
- package/dist/lifecycle/scope-manager.js +1 -2
- package/dist/metadata/metadata-keys.d.ts +1 -2
- package/dist/metadata/metadata-keys.js +1 -2
- package/dist/metadata/metadata-reader-token.d.ts +1 -2
- package/dist/metadata/metadata-reader-token.js +1 -2
- package/dist/metadata/metadata-types.d.ts +1 -2
- package/dist/metadata/metadata-types.js +1 -2
- package/dist/metadata/symbol-metadata-reader.d.ts +1 -2
- package/dist/metadata/symbol-metadata-reader.js +1 -2
- package/dist/metadata/verifying-metadata-reader.d.ts +1 -2
- package/dist/metadata/verifying-metadata-reader.js +1 -2
- package/dist/resolution/cache/activation-need.d.ts +1 -2
- package/dist/resolution/cache/activation-need.js +1 -2
- package/dist/resolution/cache/binding-lookup-cache.d.ts +2 -5
- package/dist/resolution/cache/binding-lookup-cache.js +2 -40
- package/dist/resolution/cache/class-introspector.d.ts +1 -2
- package/dist/resolution/cache/class-introspector.js +1 -2
- package/dist/resolution/context.d.ts +1 -2
- package/dist/resolution/context.js +1 -2
- package/dist/resolution/path/resolution-path.d.ts +1 -2
- package/dist/resolution/path/resolution-path.js +1 -2
- package/dist/resolution/plan/instantiation-plan.d.ts +5 -14
- package/dist/resolution/plan/instantiation-plan.js +10 -29
- package/dist/resolution/resolver.d.ts +13 -7
- package/dist/resolution/resolver.js +107 -143
- package/dist/resolution/select/binding-select.d.ts +5 -7
- package/dist/resolution/select/binding-select.js +19 -22
- package/dist/resolution/select/constraints.d.ts +1 -2
- package/dist/resolution/select/constraints.js +1 -2
- package/package.json +6 -58
- package/dist/ambient/active-container.d.ts.map +0 -1
- package/dist/ambient/active-container.js.map +0 -1
- package/dist/container/binding-builders.d.ts.map +0 -1
- package/dist/container/binding-builders.js.map +0 -1
- package/dist/container/container.d.ts.map +0 -1
- package/dist/container/container.js.map +0 -1
- package/dist/core/binding-scope.d.ts.map +0 -1
- package/dist/core/binding-scope.js.map +0 -1
- package/dist/core/binding.d.ts.map +0 -1
- package/dist/core/binding.js.map +0 -1
- package/dist/core/constraint-requirement.d.ts.map +0 -1
- package/dist/core/constraint-requirement.js.map +0 -1
- package/dist/core/constructor-type.d.ts.map +0 -1
- package/dist/core/constructor-type.js.map +0 -1
- package/dist/core/map-upsert.d.ts.map +0 -1
- package/dist/core/map-upsert.js.map +0 -1
- package/dist/core/module.d.ts.map +0 -1
- package/dist/core/module.js.map +0 -1
- package/dist/core/registry.d.ts.map +0 -1
- package/dist/core/registry.js.map +0 -1
- package/dist/core/tag.d.ts.map +0 -1
- package/dist/core/tag.js.map +0 -1
- package/dist/core/token.d.ts.map +0 -1
- package/dist/core/token.js.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/decorators/inject.d.ts.map +0 -1
- package/dist/decorators/inject.js.map +0 -1
- package/dist/decorators/injectable.d.ts.map +0 -1
- package/dist/decorators/injectable.js.map +0 -1
- package/dist/decorators/lifecycle-decorators.d.ts.map +0 -1
- package/dist/decorators/lifecycle-decorators.js.map +0 -1
- package/dist/errors/diagnostics.d.ts.map +0 -1
- package/dist/errors/diagnostics.js.map +0 -1
- package/dist/errors/errors.d.ts.map +0 -1
- package/dist/errors/errors.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/injection/descriptor.d.ts.map +0 -1
- package/dist/injection/descriptor.js.map +0 -1
- package/dist/injection/resolve-options.d.ts.map +0 -1
- package/dist/injection/resolve-options.js.map +0 -1
- package/dist/introspection/dependency-graph.d.ts.map +0 -1
- package/dist/introspection/dependency-graph.js.map +0 -1
- package/dist/introspection/graph-adapters/cytoscape.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/cytoscape.js.map +0 -1
- package/dist/introspection/graph-adapters/dot.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/dot.js.map +0 -1
- package/dist/introspection/graph-adapters/mermaid.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/mermaid.js.map +0 -1
- package/dist/introspection/graph-adapters/reactflow.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/reactflow.js.map +0 -1
- package/dist/introspection/inspector.d.ts.map +0 -1
- package/dist/introspection/inspector.js.map +0 -1
- package/dist/lifecycle/lifecycle-manager.d.ts.map +0 -1
- package/dist/lifecycle/lifecycle-manager.js.map +0 -1
- package/dist/lifecycle/scope-manager.d.ts.map +0 -1
- package/dist/lifecycle/scope-manager.js.map +0 -1
- package/dist/metadata/metadata-keys.d.ts.map +0 -1
- package/dist/metadata/metadata-keys.js.map +0 -1
- package/dist/metadata/metadata-reader-token.d.ts.map +0 -1
- package/dist/metadata/metadata-reader-token.js.map +0 -1
- package/dist/metadata/metadata-types.d.ts.map +0 -1
- package/dist/metadata/metadata-types.js.map +0 -1
- package/dist/metadata/symbol-metadata-reader.d.ts.map +0 -1
- package/dist/metadata/symbol-metadata-reader.js.map +0 -1
- package/dist/metadata/verifying-metadata-reader.d.ts.map +0 -1
- package/dist/metadata/verifying-metadata-reader.js.map +0 -1
- package/dist/resolution/cache/activation-need.d.ts.map +0 -1
- package/dist/resolution/cache/activation-need.js.map +0 -1
- package/dist/resolution/cache/binding-lookup-cache.d.ts.map +0 -1
- package/dist/resolution/cache/binding-lookup-cache.js.map +0 -1
- package/dist/resolution/cache/class-introspector.d.ts.map +0 -1
- package/dist/resolution/cache/class-introspector.js.map +0 -1
- package/dist/resolution/context.d.ts.map +0 -1
- package/dist/resolution/context.js.map +0 -1
- package/dist/resolution/path/resolution-path.d.ts.map +0 -1
- package/dist/resolution/path/resolution-path.js.map +0 -1
- package/dist/resolution/plan/instantiation-plan.d.ts.map +0 -1
- package/dist/resolution/plan/instantiation-plan.js.map +0 -1
- package/dist/resolution/resolver.d.ts.map +0 -1
- package/dist/resolution/resolver.js.map +0 -1
- package/dist/resolution/select/binding-select.d.ts.map +0 -1
- package/dist/resolution/select/binding-select.js.map +0 -1
- package/dist/resolution/select/constraints.d.ts.map +0 -1
- package/dist/resolution/select/constraints.js.map +0 -1
- package/src/ambient/active-container.ts +0 -69
- package/src/container/binding-builders.ts +0 -332
- package/src/container/container.ts +0 -973
- package/src/core/binding-scope.ts +0 -15
- package/src/core/binding.ts +0 -477
- package/src/core/constraint-requirement.ts +0 -94
- package/src/core/constructor-type.ts +0 -18
- package/src/core/map-upsert.ts +0 -53
- package/src/core/module.ts +0 -117
- package/src/core/registry.ts +0 -371
- package/src/core/tag.ts +0 -158
- package/src/core/token.ts +0 -31
- package/src/core/types.ts +0 -149
- package/src/decorators/inject.ts +0 -101
- package/src/decorators/injectable.ts +0 -134
- package/src/decorators/lifecycle-decorators.ts +0 -43
- package/src/errors/diagnostics.ts +0 -45
- package/src/errors/errors.ts +0 -476
- package/src/index.ts +0 -139
- package/src/injection/descriptor.ts +0 -218
- package/src/injection/resolve-options.ts +0 -144
- package/src/introspection/dependency-graph.ts +0 -282
- package/src/introspection/graph-adapters/cytoscape.ts +0 -78
- package/src/introspection/graph-adapters/dot.ts +0 -32
- package/src/introspection/graph-adapters/mermaid.ts +0 -61
- package/src/introspection/graph-adapters/reactflow.ts +0 -84
- package/src/introspection/inspector.ts +0 -134
- package/src/lifecycle/lifecycle-manager.ts +0 -272
- package/src/lifecycle/scope-manager.ts +0 -158
- package/src/metadata/metadata-keys.ts +0 -28
- package/src/metadata/metadata-reader-token.ts +0 -10
- package/src/metadata/metadata-types.ts +0 -57
- package/src/metadata/symbol-metadata-reader.ts +0 -126
- package/src/metadata/verifying-metadata-reader.ts +0 -41
- package/src/resolution/cache/activation-need.ts +0 -87
- package/src/resolution/cache/binding-lookup-cache.ts +0 -209
- package/src/resolution/cache/class-introspector.ts +0 -256
- package/src/resolution/context.ts +0 -331
- package/src/resolution/path/resolution-path.ts +0 -167
- package/src/resolution/plan/instantiation-plan.ts +0 -617
- package/src/resolution/resolver.ts +0 -1675
- package/src/resolution/select/binding-select.ts +0 -210
- package/src/resolution/select/constraints.ts +0 -146
package/src/core/types.ts
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import type { Constructor } from "#/core/constructor-type";
|
|
2
|
-
import type { BindingTag, TagKeyMask } from "#/core/tag";
|
|
3
|
-
import type { Token } from "#/core/token";
|
|
4
|
-
|
|
5
|
-
// Re-export for consumers that import from `#/types`
|
|
6
|
-
export type { Constructor } from "#/core/constructor-type";
|
|
7
|
-
export type { BindingTag, TagKey, TagKeyMask } from "#/core/tag";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Token or class constructor used as a binding / injection / resolve key.
|
|
11
|
-
*
|
|
12
|
-
* @since 0.3.16-canary.0
|
|
13
|
-
*/
|
|
14
|
-
export type DependencyKey = Token<unknown> | Constructor;
|
|
15
|
-
|
|
16
|
-
// ── BindingScope ─────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* The lifetime a binding's instances are cached under.
|
|
20
|
-
*
|
|
21
|
-
* @since 0.3.16-canary.0
|
|
22
|
-
*/
|
|
23
|
-
export type BindingScope = "singleton" | "transient" | "scoped";
|
|
24
|
-
|
|
25
|
-
// ── BindingIdentifier ────────────────────────────────────────────────────────────────────────────────────────────────
|
|
26
|
-
|
|
27
|
-
declare const BINDING_ID_BRAND: unique symbol;
|
|
28
|
-
/**
|
|
29
|
-
* A branded string that uniquely identifies one binding.
|
|
30
|
-
*
|
|
31
|
-
* @since 0.3.16-canary.0
|
|
32
|
-
*/
|
|
33
|
-
export type BindingIdentifier = string & { readonly [BINDING_ID_BRAND]: true };
|
|
34
|
-
|
|
35
|
-
// ── BindingKind ──────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The strategy a binding produces values with, set by the `to*()` call that created it.
|
|
39
|
-
*
|
|
40
|
-
* @since 0.3.16-canary.0
|
|
41
|
-
*/
|
|
42
|
-
export type BindingKind = "class" | "dynamic" | "dynamic-async" | "resolved" | "resolved-async" | "constant" | "alias";
|
|
43
|
-
|
|
44
|
-
// ── Handlers ─────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* A hook that runs after an instance is created and returns the instance to hand out.
|
|
48
|
-
*
|
|
49
|
-
* @since 0.3.16-canary.0
|
|
50
|
-
*/
|
|
51
|
-
export type ActivationHandler<Value> = (ctx: ResolutionContext, instance: Value) => Value | Promise<Value>;
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* A hook that runs when a cached instance is released from its scope.
|
|
55
|
-
*
|
|
56
|
-
* @since 0.3.16-canary.0
|
|
57
|
-
*/
|
|
58
|
-
export type DeactivationHandler<Value> = (instance: Value) => void | Promise<void>;
|
|
59
|
-
|
|
60
|
-
// ── ResolveOptions ───────────────────────────────────────────────────────────────────────────────────────────────────
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Slot-selection criteria — a name and tags — that narrow which binding a resolve call matches.
|
|
64
|
-
*
|
|
65
|
-
* @since 0.3.16-canary.0
|
|
66
|
-
*/
|
|
67
|
-
export interface ResolveOptions {
|
|
68
|
-
name?: string | undefined;
|
|
69
|
-
/**
|
|
70
|
-
* Single-tag shorthand, equivalent to listing the one pair in `tags`.
|
|
71
|
-
*
|
|
72
|
-
* @remarks Reaches the same tagged index, so choosing it costs nothing. `InjectOptions` accepts it
|
|
73
|
-
* too and folds it into `tags`. Only `tags` expresses a request for more than one tag.
|
|
74
|
-
*/
|
|
75
|
-
tag?: BindingTag | undefined;
|
|
76
|
-
tags?: ReadonlyArray<BindingTag> | undefined;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// ── ResolutionFrame ──────────────────────────────────────────────────────────────────────────────────────────────────
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* One entry of the resolution stack: the token, scope, binding, and slot being resolved.
|
|
83
|
-
*
|
|
84
|
-
* @since 0.3.16-canary.0
|
|
85
|
-
*/
|
|
86
|
-
export interface ResolutionFrame {
|
|
87
|
-
readonly tokenName: string;
|
|
88
|
-
readonly scope: BindingScope;
|
|
89
|
-
readonly bindingId: BindingIdentifier;
|
|
90
|
-
readonly kind: BindingKind;
|
|
91
|
-
readonly slot: {
|
|
92
|
-
readonly name: string | undefined;
|
|
93
|
-
readonly tags: ReadonlyArray<BindingTag>;
|
|
94
|
-
readonly keyMask: TagKeyMask;
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// ── ConstraintContext ────────────────────────────────────────────────────────────────────────────────────────────────
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* The resolution-time view — path, stack, parent, and ancestors — a `BindingConstraint` inspects.
|
|
102
|
-
*
|
|
103
|
-
* @since 0.3.16-canary.0
|
|
104
|
-
*/
|
|
105
|
-
export interface ConstraintContext {
|
|
106
|
-
readonly resolutionPath: ReadonlyArray<string>;
|
|
107
|
-
readonly resolutionStack: ReadonlyArray<ResolutionFrame>;
|
|
108
|
-
readonly parent: ResolutionFrame | undefined;
|
|
109
|
-
readonly ancestors: ReadonlyArray<ResolutionFrame>;
|
|
110
|
-
/** Readonly because one frozen object answers every resolve of a slot — a write would throw. */
|
|
111
|
-
readonly currentResolveOptions: Readonly<ResolveOptions> | undefined;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* The predicate `when()` selects a binding by, and the shape every `when*` helper returns.
|
|
116
|
-
*
|
|
117
|
-
* @since 0.6.0
|
|
118
|
-
*/
|
|
119
|
-
export type BindingConstraint = (ctx: ConstraintContext) => boolean;
|
|
120
|
-
|
|
121
|
-
// ── ResolutionContext ────────────────────────────────────────────────────────────────────────────────────────────────
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* The container view a dynamic factory or activation handler resolves further dependencies through.
|
|
125
|
-
*
|
|
126
|
-
* @since 0.3.16-canary.0
|
|
127
|
-
*/
|
|
128
|
-
export interface ResolutionContext {
|
|
129
|
-
resolve<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): Value;
|
|
130
|
-
resolveAsync<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): Promise<Value>;
|
|
131
|
-
resolveOptional<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): Value | undefined;
|
|
132
|
-
resolveOptionalAsync<Value>(
|
|
133
|
-
token: Token<Value> | Constructor<Value>,
|
|
134
|
-
options?: ResolveOptions,
|
|
135
|
-
): Promise<Value | undefined>;
|
|
136
|
-
resolveAll<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): Array<Value>;
|
|
137
|
-
resolveAllAsync<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): Promise<Array<Value>>;
|
|
138
|
-
readonly graph: ConstraintContext;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// ── TokenValue ───────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* The value type a token or class constructor resolves to.
|
|
145
|
-
*
|
|
146
|
-
* @since 0.3.16-canary.0
|
|
147
|
-
*/
|
|
148
|
-
export type TokenValue<Type> =
|
|
149
|
-
Type extends Token<infer Value> ? Value : Type extends Constructor<infer Value> ? Value : never;
|
package/src/decorators/inject.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { getActiveContainer, getAmbientResolution } from "#/ambient/active-container";
|
|
2
|
-
/** `@inject` — the accessor-decorator channel, resolving from the ambient container. */
|
|
3
|
-
import type { Token } from "#/core/token";
|
|
4
|
-
import type { Constructor } from "#/core/types";
|
|
5
|
-
import { MissingContainerContextError, StaticMemberDecoratorError } from "#/errors/errors";
|
|
6
|
-
import type { InjectionDescriptor, InjectOptions } from "#/injection/descriptor";
|
|
7
|
-
import { buildInjectionDescriptor } from "#/injection/descriptor";
|
|
8
|
-
import { injectionSlotToResolveOptions } from "#/injection/resolve-options";
|
|
9
|
-
import { INJECT_ACCESSOR_KEY } from "#/metadata/metadata-keys";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* The name of the class being constructed, or `undefined` when there is none to report.
|
|
13
|
-
*
|
|
14
|
-
* @remarks Two ways there is none: an anonymous class expression has an empty `name`, and an
|
|
15
|
-
* instance whose prototype chain answers no `constructor` has nothing to read. Narrowed rather than
|
|
16
|
-
* asserted — the value arrives as `unknown` and the platform makes no promise about it.
|
|
17
|
-
*/
|
|
18
|
-
function classNameOf(instance: unknown): string | undefined {
|
|
19
|
-
if (typeof instance !== "object" || instance === null) {
|
|
20
|
-
return undefined;
|
|
21
|
-
}
|
|
22
|
-
const constructor: unknown = Reflect.get(instance, "constructor");
|
|
23
|
-
if (typeof constructor !== "function" || constructor.name === "") {
|
|
24
|
-
return undefined;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return constructor.name;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// ── inject() — dual-role ─────────────────────────────────────────────────────────────────────────────────────────────
|
|
31
|
-
|
|
32
|
-
type ClassAccessorDecorator<This, Value> = (
|
|
33
|
-
target: ClassAccessorDecoratorTarget<This, Value>,
|
|
34
|
-
context: ClassAccessorDecoratorContext<This, Value>,
|
|
35
|
-
) => ClassAccessorDecoratorResult<This, Value> | void;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Creates a dual-role value: an injection descriptor that also works as a class accessor decorator.
|
|
39
|
-
*
|
|
40
|
-
* @since 0.3.16-canary.0
|
|
41
|
-
*/
|
|
42
|
-
export function inject<Value>(
|
|
43
|
-
token: Token<Value> | Constructor<Value>,
|
|
44
|
-
options?: InjectOptions,
|
|
45
|
-
): InjectionDescriptor<Value> & ClassAccessorDecorator<unknown, Value> {
|
|
46
|
-
const descriptor = buildInjectionDescriptor(token, options);
|
|
47
|
-
// Derived from the descriptor, not from `options`: the descriptor is where the tag shorthand has
|
|
48
|
-
// already been folded. Built once here rather than per constructed instance.
|
|
49
|
-
const resolveOptions = injectionSlotToResolveOptions(descriptor);
|
|
50
|
-
|
|
51
|
-
const decoratorFn = (
|
|
52
|
-
_target: ClassAccessorDecoratorTarget<unknown, Value>,
|
|
53
|
-
context: ClassAccessorDecoratorContext<unknown, Value>,
|
|
54
|
-
): ClassAccessorDecoratorResult<unknown, Value> => {
|
|
55
|
-
if (context.static) {
|
|
56
|
-
throw new StaticMemberDecoratorError("inject", String(context.name));
|
|
57
|
-
}
|
|
58
|
-
const meta = context.metadata as Record<string | symbol, unknown>;
|
|
59
|
-
// Own bucket only: the metadata record inherits the base class's, and pushing into an inherited
|
|
60
|
-
// array would register this accessor on the base class instead.
|
|
61
|
-
if (!Object.hasOwn(meta, INJECT_ACCESSOR_KEY) || !Array.isArray(meta[INJECT_ACCESSOR_KEY])) {
|
|
62
|
-
meta[INJECT_ACCESSOR_KEY] = [];
|
|
63
|
-
}
|
|
64
|
-
(meta[INJECT_ACCESSOR_KEY] as Array<{ key: string | symbol; descriptor: InjectionDescriptor }>).push({
|
|
65
|
-
key: context.name,
|
|
66
|
-
descriptor,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
context.addInitializer(function (this: unknown) {
|
|
70
|
-
// Prefer the engine's path-continuing resolver: it keeps this accessor's dependencies on the
|
|
71
|
-
// live resolution path, so a cycle through an accessor is detected instead of recursing.
|
|
72
|
-
const ambient = getAmbientResolution();
|
|
73
|
-
if (ambient !== undefined) {
|
|
74
|
-
const value = descriptor.optional
|
|
75
|
-
? ambient.resolveOptional(token, resolveOptions)
|
|
76
|
-
: ambient.resolve(token, resolveOptions);
|
|
77
|
-
context.access.set(this, value as Value);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
const container = getActiveContainer();
|
|
81
|
-
if (container === undefined) {
|
|
82
|
-
throw new MissingContainerContextError(classNameOf(this), context.name);
|
|
83
|
-
}
|
|
84
|
-
const value = descriptor.optional
|
|
85
|
-
? container.resolveOptional(token, resolveOptions)
|
|
86
|
-
: container.resolve(token, resolveOptions);
|
|
87
|
-
context.access.set(this, value as Value);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
return {};
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
// Use defineProperties to handle read-only `name` property of functions
|
|
94
|
-
const props: PropertyDescriptorMap = {};
|
|
95
|
-
for (const key of Object.keys(descriptor) as Array<keyof typeof descriptor>) {
|
|
96
|
-
props[key] = { value: descriptor[key], writable: true, enumerable: true, configurable: true };
|
|
97
|
-
}
|
|
98
|
-
Object.defineProperties(decoratorFn, props);
|
|
99
|
-
|
|
100
|
-
return decoratorFn as InjectionDescriptor<Value> & ClassAccessorDecorator<unknown, Value>;
|
|
101
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import type { BindingScope, Constructor } from "#/core/types";
|
|
2
|
-
import type { InjectableDependency, ResolvedDependencyValue } from "#/injection/descriptor";
|
|
3
|
-
import { normalizeToDescriptor } from "#/injection/descriptor";
|
|
4
|
-
import { INJECTABLE_KEY } from "#/metadata/metadata-keys";
|
|
5
|
-
import type { ParamMetadata } from "#/metadata/metadata-types";
|
|
6
|
-
|
|
7
|
-
// ── AutoRegisterRegistry ─────────────────────────────────────────────────────────────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* The collector `@injectable` registers a class into, for a container to bind later.
|
|
11
|
-
*
|
|
12
|
-
* @since 0.3.16-canary.0
|
|
13
|
-
*/
|
|
14
|
-
export interface AutoRegisterRegistry {
|
|
15
|
-
register(target: Constructor, scope: BindingScope): void;
|
|
16
|
-
entries(): ReadonlyArray<{ target: Constructor; scope: BindingScope }>;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Creates an empty auto-register registry.
|
|
21
|
-
*
|
|
22
|
-
* @since 0.3.16-canary.0
|
|
23
|
-
*/
|
|
24
|
-
export function createAutoRegisterRegistry(): AutoRegisterRegistry {
|
|
25
|
-
const registeredEntries: Array<{ target: Constructor; scope: BindingScope }> = [];
|
|
26
|
-
return {
|
|
27
|
-
register(target: Constructor, scope: BindingScope): void {
|
|
28
|
-
registeredEntries.push({ target, scope });
|
|
29
|
-
},
|
|
30
|
-
entries(): ReadonlyArray<{ target: Constructor; scope: BindingScope }> {
|
|
31
|
-
return registeredEntries;
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// ── InjectableOptions ────────────────────────────────────────────────────────────────────────────────────────────────
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Auto-registration options `@injectable` accepts alongside its deps list.
|
|
40
|
-
*
|
|
41
|
-
* @since 0.3.16-canary.0
|
|
42
|
-
*/
|
|
43
|
-
export interface InjectableOptions {
|
|
44
|
-
autoRegister?: AutoRegisterRegistry | undefined;
|
|
45
|
-
scope?: BindingScope | undefined;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// ── @injectable() ────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* The parameters a constructor is handed, given what its `deps` declare.
|
|
52
|
-
*
|
|
53
|
-
* @remarks Reuses the same reading a `toResolved` factory gets, so `injectAll` arrives as an array
|
|
54
|
-
* and `optional` as possibly undefined in both places.
|
|
55
|
-
*/
|
|
56
|
-
type InjectedParameters<Deps extends ReadonlyArray<InjectableDependency>> = {
|
|
57
|
-
-readonly [Index in keyof Deps]: ResolvedDependencyValue<Deps[Index]>;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Declare a class injectable, and what its constructor is to be handed.
|
|
62
|
-
*
|
|
63
|
-
* @since 0.3.16-canary.0
|
|
64
|
-
*/
|
|
65
|
-
export function injectable(): (target: unknown, context: ClassDecoratorContext) => void;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @remarks Declaring dependencies constrains the class: the decorator only accepts one whose
|
|
69
|
-
* constructor takes exactly what `deps` resolve to, in that order — including arity, so a literal
|
|
70
|
-
* deps list longer than the constructor is a compile error rather than a resolved-and-discarded
|
|
71
|
-
* value. Optional trailing parameters admit every arity they declare, and a rest parameter admits
|
|
72
|
-
* any list. A deps *array* — one whose length the compiler cannot know — skips the arity check,
|
|
73
|
-
* which is also the deliberate spelling for declaring more dependencies than the constructor
|
|
74
|
-
* takes, e.g. for the dependency graph's edges.
|
|
75
|
-
*
|
|
76
|
-
* @since 0.3.16-canary.0
|
|
77
|
-
*/
|
|
78
|
-
export function injectable<const Deps extends ReadonlyArray<InjectableDependency>>(
|
|
79
|
-
deps: Deps,
|
|
80
|
-
options?: InjectableOptions,
|
|
81
|
-
): <Target extends abstract new (...args: InjectedParameters<Deps>) => unknown>(
|
|
82
|
-
target: Target &
|
|
83
|
-
(number extends Deps["length"]
|
|
84
|
-
? unknown
|
|
85
|
-
: Deps["length"] extends ConstructorParameters<Target>["length"]
|
|
86
|
-
? unknown
|
|
87
|
-
: never),
|
|
88
|
-
context: ClassDecoratorContext,
|
|
89
|
-
) => void;
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Writes the declared dependencies into the class's metadata and optionally auto-registers it.
|
|
93
|
-
*
|
|
94
|
-
* @since 0.6.0
|
|
95
|
-
*/
|
|
96
|
-
export function injectable(
|
|
97
|
-
deps?: ReadonlyArray<InjectableDependency>,
|
|
98
|
-
options?: InjectableOptions,
|
|
99
|
-
): (target: never, context: ClassDecoratorContext) => void {
|
|
100
|
-
return function (target: never, context: ClassDecoratorContext): void {
|
|
101
|
-
const parameterMetadataList: Array<ParamMetadata> = (deps ?? []).map((dependency, index) => {
|
|
102
|
-
const descriptor = normalizeToDescriptor(dependency);
|
|
103
|
-
const baseParameterMetadata: Pick<ParamMetadata, "index" | "token" | "optional" | "multi"> = {
|
|
104
|
-
index,
|
|
105
|
-
token: descriptor.token,
|
|
106
|
-
optional: descriptor.optional,
|
|
107
|
-
multi: descriptor.multi,
|
|
108
|
-
};
|
|
109
|
-
if (descriptor.name !== undefined && descriptor.tags !== undefined) {
|
|
110
|
-
return { ...baseParameterMetadata, name: descriptor.name, tags: descriptor.tags };
|
|
111
|
-
}
|
|
112
|
-
if (descriptor.name !== undefined) {
|
|
113
|
-
return { ...baseParameterMetadata, name: descriptor.name };
|
|
114
|
-
}
|
|
115
|
-
if (descriptor.tags !== undefined) {
|
|
116
|
-
return { ...baseParameterMetadata, tags: descriptor.tags };
|
|
117
|
-
}
|
|
118
|
-
return baseParameterMetadata;
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
// Field decorators run before the class decorator — accessor @inject entries are
|
|
122
|
-
// already on context.metadata by the time this runs.
|
|
123
|
-
(context.metadata as Record<string | symbol, unknown>)[INJECTABLE_KEY] = {
|
|
124
|
-
params: parameterMetadataList,
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
if (options?.autoRegister !== undefined) {
|
|
128
|
-
const scope: BindingScope = options.scope ?? "transient";
|
|
129
|
-
options.autoRegister.register(target as Constructor, scope);
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export type { InjectableDependency };
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { StaticMemberDecoratorError } from "#/errors/errors";
|
|
2
|
-
import { LIFECYCLE_KEY } from "#/metadata/metadata-keys";
|
|
3
|
-
import type { MutableLifecycleMetadata } from "#/metadata/metadata-types";
|
|
4
|
-
|
|
5
|
-
type MethodDecorator = (target: unknown, context: ClassMethodDecoratorContext) => void;
|
|
6
|
-
|
|
7
|
-
/** Records the decorated method under one lifecycle phase; both decorators differ only in that phase. */
|
|
8
|
-
function recordLifecycleMethod(phase: "postConstruct" | "preDestroy"): MethodDecorator {
|
|
9
|
-
return function (target: unknown, context: ClassMethodDecoratorContext): void {
|
|
10
|
-
if (context.static) {
|
|
11
|
-
throw new StaticMemberDecoratorError(phase, String(context.name));
|
|
12
|
-
}
|
|
13
|
-
const meta = context.metadata as Record<string | symbol, unknown>;
|
|
14
|
-
// Own bucket only: `context.metadata` inherits the base class's record, and writing through an
|
|
15
|
-
// inherited bucket would register this hook on the base class instead.
|
|
16
|
-
if (!Object.hasOwn(meta, LIFECYCLE_KEY)) {
|
|
17
|
-
meta[LIFECYCLE_KEY] = { postConstruct: [], preDestroy: [] };
|
|
18
|
-
}
|
|
19
|
-
const lifecycle = meta[LIFECYCLE_KEY] as MutableLifecycleMetadata;
|
|
20
|
-
const methodName = String(context.name);
|
|
21
|
-
if (!lifecycle[phase].includes(methodName)) {
|
|
22
|
-
lifecycle[phase].push(methodName);
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Marks an instance method to run after the container constructs and wires the instance.
|
|
29
|
-
*
|
|
30
|
-
* @since 0.3.16-canary.0
|
|
31
|
-
*/
|
|
32
|
-
export function postConstruct(): MethodDecorator {
|
|
33
|
-
return recordLifecycleMethod("postConstruct");
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Marks an instance method to run when the instance's container or scope is disposed.
|
|
38
|
-
*
|
|
39
|
-
* @since 0.3.16-canary.0
|
|
40
|
-
*/
|
|
41
|
-
export function preDestroy(): MethodDecorator {
|
|
42
|
-
return recordLifecycleMethod("preDestroy");
|
|
43
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Internal seam letting tests assert that an optimization is *active*, not merely that the result
|
|
3
|
-
* is correct.
|
|
4
|
-
*
|
|
5
|
-
* @remarks Timing belongs in the benchmark, which needs a quiet machine and twenty minutes; these
|
|
6
|
-
* are structural counts, so CI can hold the invariants that make the benchmark fast. Reached
|
|
7
|
-
* through a symbol from a module the package does not publish, so it is not public API.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Key for the diagnostics accessor on a container.
|
|
12
|
-
*
|
|
13
|
-
* @remarks A symbol rather than a method name, so it cannot collide with the public surface or be
|
|
14
|
-
* reached by anyone who has not imported this module.
|
|
15
|
-
*
|
|
16
|
-
* @since 0.5.0-canary.8
|
|
17
|
-
*/
|
|
18
|
-
export const RESOLUTION_DIAGNOSTICS: unique symbol = Symbol("di:resolution-diagnostics");
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Structural facts about a container's resolution caches.
|
|
22
|
-
*
|
|
23
|
-
* @since 0.5.0-canary.8
|
|
24
|
-
*/
|
|
25
|
-
export interface ResolutionDiagnostics {
|
|
26
|
-
/** Bindings with a compiled instantiation plan. */
|
|
27
|
-
readonly compiledPlanCount: number;
|
|
28
|
-
/** Bindings with a compiled async instantiation plan. */
|
|
29
|
-
readonly compiledAsyncPlanCount: number;
|
|
30
|
-
/** Contexts held by the depth-indexed sync pool. */
|
|
31
|
-
readonly syncContextPoolSize: number;
|
|
32
|
-
/** Scoped instances currently cached by this container's scope manager. */
|
|
33
|
-
readonly scopedInstanceCount: number;
|
|
34
|
-
/** Deferred collaborators this container has had to build. */
|
|
35
|
-
readonly builtSubsystems: ReadonlyArray<string>;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* A container that can report on its resolution caches.
|
|
40
|
-
*
|
|
41
|
-
* @since 0.5.0-canary.8
|
|
42
|
-
*/
|
|
43
|
-
export interface DiagnosableContainer {
|
|
44
|
-
[RESOLUTION_DIAGNOSTICS](): ResolutionDiagnostics;
|
|
45
|
-
}
|