@codefast/di 0.9.0 → 0.10.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 +165 -0
- package/README.md +6 -5
- package/dist/ambient/active-container.d.ts +14 -4
- package/dist/ambient/active-container.js +22 -1
- package/dist/container/binding-builders.d.ts +35 -13
- package/dist/container/binding-builders.js +174 -97
- package/dist/container/container.d.ts +10 -10
- package/dist/container/container.js +53 -36
- package/dist/core/binding-scope.d.ts +2 -2
- package/dist/core/binding.d.ts +42 -49
- package/dist/core/binding.js +12 -38
- package/dist/core/constraint-requirement.d.ts +1 -1
- package/dist/core/module.d.ts +3 -3
- package/dist/core/registry.d.ts +52 -9
- package/dist/core/registry.js +376 -162
- package/dist/core/state-epoch.d.ts +16 -0
- package/dist/core/state-epoch.js +21 -0
- package/dist/core/token.d.ts +1 -1
- package/dist/core/types.d.ts +12 -9
- package/dist/decorators/inject.d.ts +3 -3
- package/dist/decorators/inject.js +5 -5
- package/dist/decorators/injectable.d.ts +2 -2
- package/dist/decorators/injectable.js +2 -2
- package/dist/decorators/lifecycle-decorators.js +2 -2
- package/dist/errors/diagnostics.d.ts +2 -0
- package/dist/errors/errors.d.ts +29 -3
- package/dist/errors/errors.js +34 -2
- package/dist/index.d.ts +35 -35
- package/dist/index.js +19 -19
- package/dist/injection/descriptor.d.ts +9 -7
- package/dist/injection/descriptor.js +3 -1
- package/dist/injection/resolve-options.d.ts +9 -3
- package/dist/injection/resolve-options.js +17 -1
- package/dist/introspection/dependency-graph.d.ts +3 -3
- package/dist/introspection/dependency-graph.js +15 -10
- package/dist/introspection/graph-adapters/cytoscape.d.ts +1 -1
- package/dist/introspection/graph-adapters/dot.d.ts +1 -1
- package/dist/introspection/graph-adapters/mermaid.d.ts +1 -1
- package/dist/introspection/graph-adapters/reactflow.d.ts +1 -1
- package/dist/introspection/inspector.d.ts +7 -5
- package/dist/introspection/inspector.js +13 -27
- package/dist/lifecycle/lifecycle-manager.d.ts +4 -4
- package/dist/lifecycle/lifecycle-manager.js +13 -11
- package/dist/lifecycle/scope-manager.d.ts +2 -2
- package/dist/lifecycle/scope-manager.js +4 -4
- package/dist/metadata/metadata-reader-token.d.ts +2 -2
- package/dist/metadata/metadata-reader-token.js +1 -1
- package/dist/metadata/metadata-types.d.ts +3 -3
- package/dist/metadata/symbol-metadata-reader.d.ts +3 -3
- package/dist/metadata/symbol-metadata-reader.js +1 -1
- package/dist/metadata/verifying-metadata-reader.d.ts +1 -1
- package/dist/metadata/verifying-metadata-reader.js +2 -2
- package/dist/resolution/cache/activation-need.d.ts +6 -4
- package/dist/resolution/cache/activation-need.js +13 -6
- package/dist/resolution/cache/binding-lookup-cache.d.ts +39 -6
- package/dist/resolution/cache/binding-lookup-cache.js +97 -13
- package/dist/resolution/cache/class-introspector.d.ts +6 -6
- package/dist/resolution/cache/class-introspector.js +82 -69
- package/dist/resolution/context.d.ts +11 -11
- package/dist/resolution/context.js +1 -1
- package/dist/resolution/path/resolution-path.d.ts +1 -1
- package/dist/resolution/path/resolution-path.js +1 -1
- package/dist/resolution/plan/instantiation-plan.d.ts +16 -4
- package/dist/resolution/plan/instantiation-plan.js +160 -69
- package/dist/resolution/plan/plan-codegen.d.ts +100 -0
- package/dist/resolution/plan/plan-codegen.js +185 -0
- package/dist/resolution/resolver.d.ts +26 -16
- package/dist/resolution/resolver.js +401 -147
- package/dist/resolution/select/binding-select.d.ts +6 -5
- package/dist/resolution/select/binding-select.js +17 -11
- package/dist/resolution/select/constraints.d.ts +3 -3
- package/dist/resolution/select/constraints.js +4 -4
- package/package.json +11 -3
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The process-wide counter every container mutation advances, so a chain walk can be skipped while nothing moved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The current state epoch: unchanged between two reads exactly when no registry or lifecycle table
|
|
6
|
+
* in the process was mutated in between.
|
|
7
|
+
*
|
|
8
|
+
* @since 0.10.0
|
|
9
|
+
*/
|
|
10
|
+
export declare function stateEpoch(): number;
|
|
11
|
+
/**
|
|
12
|
+
* Advances the epoch; every registry version bump and every activation-hook registration calls it.
|
|
13
|
+
*
|
|
14
|
+
* @since 0.10.0
|
|
15
|
+
*/
|
|
16
|
+
export declare function advanceStateEpoch(): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The process-wide counter every container mutation advances, so a chain walk can be skipped while nothing moved.
|
|
3
|
+
*/
|
|
4
|
+
let epoch = 0;
|
|
5
|
+
/**
|
|
6
|
+
* The current state epoch: unchanged between two reads exactly when no registry or lifecycle table
|
|
7
|
+
* in the process was mutated in between.
|
|
8
|
+
*
|
|
9
|
+
* @since 0.10.0
|
|
10
|
+
*/
|
|
11
|
+
export function stateEpoch() {
|
|
12
|
+
return epoch;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Advances the epoch; every registry version bump and every activation-hook registration calls it.
|
|
16
|
+
*
|
|
17
|
+
* @since 0.10.0
|
|
18
|
+
*/
|
|
19
|
+
export function advanceStateEpoch() {
|
|
20
|
+
epoch += 1;
|
|
21
|
+
}
|
package/dist/core/token.d.ts
CHANGED
package/dist/core/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Constructor } from "
|
|
2
|
-
import type { BindingTag, TagKeyMask } from "
|
|
3
|
-
import type { Token } from "
|
|
4
|
-
export type { Constructor } from "
|
|
5
|
-
export type { BindingTag, TagKey, TagKeyMask } from "
|
|
1
|
+
import type { Constructor } from "#core/constructor-type";
|
|
2
|
+
import type { BindingTag, TagKeyMask } from "#core/tag";
|
|
3
|
+
import type { Token } from "#core/token";
|
|
4
|
+
export type { Constructor } from "#core/constructor-type";
|
|
5
|
+
export type { BindingTag, TagKey, TagKeyMask } from "#core/tag";
|
|
6
6
|
/**
|
|
7
7
|
* Token or class constructor used as a binding / injection / resolve key.
|
|
8
8
|
*
|
|
@@ -17,11 +17,14 @@ export type DependencyKey = Token<unknown> | Constructor;
|
|
|
17
17
|
export type BindingScope = "singleton" | "transient" | "scoped";
|
|
18
18
|
declare const BINDING_ID_BRAND: unique symbol;
|
|
19
19
|
/**
|
|
20
|
-
* A branded
|
|
20
|
+
* A branded number that uniquely identifies one binding for the life of the process.
|
|
21
|
+
*
|
|
22
|
+
* @remarks Minted from a counter, never parsed or displayed as an identity: the brand is what makes
|
|
23
|
+
* it opaque, and a number costs a plain bind nothing where a string cost it an allocation.
|
|
21
24
|
*
|
|
22
25
|
* @since 0.3.16-canary.0
|
|
23
26
|
*/
|
|
24
|
-
export type BindingIdentifier =
|
|
27
|
+
export type BindingIdentifier = number & {
|
|
25
28
|
readonly [BINDING_ID_BRAND]: true;
|
|
26
29
|
};
|
|
27
30
|
/**
|
|
@@ -109,8 +112,8 @@ export interface ResolutionContext {
|
|
|
109
112
|
resolveAsync<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): Promise<Value>;
|
|
110
113
|
resolveOptional<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): Value | undefined;
|
|
111
114
|
resolveOptionalAsync<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): Promise<Value | undefined>;
|
|
112
|
-
resolveAll<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions):
|
|
113
|
-
resolveAllAsync<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): Promise<
|
|
115
|
+
resolveAll<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): ReadonlyArray<Value>;
|
|
116
|
+
resolveAllAsync<Value>(token: Token<Value> | Constructor<Value>, options?: ResolveOptions): Promise<ReadonlyArray<Value>>;
|
|
114
117
|
readonly graph: ConstraintContext;
|
|
115
118
|
}
|
|
116
119
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** `@inject` — the accessor-decorator channel, resolving from the ambient container. */
|
|
2
|
-
import type { Token } from "
|
|
3
|
-
import type { Constructor } from "
|
|
4
|
-
import type { InjectionDescriptor, InjectOptions } from "
|
|
2
|
+
import type { Token } from "#core/token";
|
|
3
|
+
import type { Constructor } from "#core/types";
|
|
4
|
+
import type { InjectionDescriptor, InjectOptions } from "#injection/descriptor";
|
|
5
5
|
type ClassAccessorDecorator<This, Value> = (target: ClassAccessorDecoratorTarget<This, Value>, context: ClassAccessorDecoratorContext<This, Value>) => ClassAccessorDecoratorResult<This, Value> | void;
|
|
6
6
|
/**
|
|
7
7
|
* Creates a dual-role value: an injection descriptor that also works as a class accessor decorator.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { getActiveContainer, getAmbientResolution } from "
|
|
2
|
-
import { MissingContainerContextError, StaticMemberDecoratorError } from "
|
|
3
|
-
import { buildInjectionDescriptor } from "
|
|
4
|
-
import { injectionSlotToResolveOptions } from "
|
|
5
|
-
import { INJECT_ACCESSOR_KEY } from "
|
|
1
|
+
import { getActiveContainer, getAmbientResolution } from "#ambient/active-container";
|
|
2
|
+
import { MissingContainerContextError, StaticMemberDecoratorError } from "#errors/errors";
|
|
3
|
+
import { buildInjectionDescriptor } from "#injection/descriptor";
|
|
4
|
+
import { injectionSlotToResolveOptions } from "#injection/resolve-options";
|
|
5
|
+
import { INJECT_ACCESSOR_KEY } from "#metadata/metadata-keys";
|
|
6
6
|
/**
|
|
7
7
|
* The name of the class being constructed, or `undefined` when there is none to report.
|
|
8
8
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { BindingScope, Constructor } from "
|
|
2
|
-
import type { InjectableDependency, ResolvedDependencyValue } from "
|
|
1
|
+
import type { BindingScope, Constructor } from "#core/types";
|
|
2
|
+
import type { InjectableDependency, ResolvedDependencyValue } from "#injection/descriptor";
|
|
3
3
|
/**
|
|
4
4
|
* The collector `@injectable` registers a class into, for a container to bind later.
|
|
5
5
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { normalizeToDescriptor } from "
|
|
2
|
-
import { INJECTABLE_KEY } from "
|
|
1
|
+
import { normalizeToDescriptor } from "#injection/descriptor";
|
|
2
|
+
import { INJECTABLE_KEY } from "#metadata/metadata-keys";
|
|
3
3
|
/**
|
|
4
4
|
* Creates an empty auto-register registry.
|
|
5
5
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StaticMemberDecoratorError } from "
|
|
2
|
-
import { LIFECYCLE_KEY } from "
|
|
1
|
+
import { StaticMemberDecoratorError } from "#errors/errors";
|
|
2
|
+
import { LIFECYCLE_KEY } from "#metadata/metadata-keys";
|
|
3
3
|
/** Records the decorated method under one lifecycle phase; both decorators differ only in that phase. */
|
|
4
4
|
function recordLifecycleMethod(phase) {
|
|
5
5
|
return function (target, context) {
|
|
@@ -25,6 +25,8 @@ export interface ResolutionDiagnostics {
|
|
|
25
25
|
readonly compiledPlanCount: number;
|
|
26
26
|
/** Bindings with a compiled async instantiation plan. */
|
|
27
27
|
readonly compiledAsyncPlanCount: number;
|
|
28
|
+
/** Plans this container's resolver has generated as functions of their own. */
|
|
29
|
+
readonly generatedPlanCount: number;
|
|
28
30
|
/** Contexts held by the depth-indexed sync pool. */
|
|
29
31
|
readonly syncContextPoolSize: number;
|
|
30
32
|
/** Scoped instances currently cached by this container's scope manager. */
|
package/dist/errors/errors.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { ConstraintRequirement } from "
|
|
2
|
-
import type { BindingIdentifier, BindingScope, ResolveOptions } from "
|
|
1
|
+
import type { ConstraintRequirement } from "#core/constraint-requirement";
|
|
2
|
+
import type { BindingIdentifier, BindingScope, ResolveOptions } from "#core/types";
|
|
3
3
|
/**
|
|
4
4
|
* Base class for every error the library throws, each carrying a machine-readable `code`.
|
|
5
5
|
*
|
|
@@ -223,6 +223,32 @@ export declare class MissingContainerContextError extends DiError {
|
|
|
223
223
|
readonly accessorName: string | symbol;
|
|
224
224
|
constructor(className: string | undefined, accessorName: string | symbol);
|
|
225
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* A second `to*()` on a chain that already registered its binding.
|
|
228
|
+
*
|
|
229
|
+
* @remarks A chain is its binding, so it registers exactly once; a token bound twice is two `bind()`
|
|
230
|
+
* calls, the second of which displaces the first under slot last-wins.
|
|
231
|
+
*
|
|
232
|
+
* @since 0.10.0
|
|
233
|
+
*/
|
|
234
|
+
export declare class ChainAlreadyRegisteredError extends DiError {
|
|
235
|
+
readonly code = "CHAIN_ALREADY_REGISTERED";
|
|
236
|
+
readonly tokenName: string;
|
|
237
|
+
constructor(tokenName: string);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* `many()` on a binding with a named or tagged slot, or a slot constraint on a collection member.
|
|
241
|
+
*
|
|
242
|
+
* @remarks A collection member keeps the default slot: its membership replaces slot last-wins, and a
|
|
243
|
+
* tagged member would have no index able to return every member of the tag.
|
|
244
|
+
*
|
|
245
|
+
* @since 0.10.0
|
|
246
|
+
*/
|
|
247
|
+
export declare class ManyBindingSlotError extends DiError {
|
|
248
|
+
readonly code = "MANY_BINDING_SLOT";
|
|
249
|
+
readonly tokenName: string;
|
|
250
|
+
constructor(tokenName: string);
|
|
251
|
+
}
|
|
226
252
|
/**
|
|
227
253
|
* A fluent chain was refined before a `to*()` call gave it a binding to refine.
|
|
228
254
|
*
|
|
@@ -230,7 +256,7 @@ export declare class MissingContainerContextError extends DiError {
|
|
|
230
256
|
* `BindToBuilder`, which exposes only `to*()`. It exists for JavaScript callers and for anyone who
|
|
231
257
|
* casts past the types, so the misuse fails loudly instead of mutating nothing.
|
|
232
258
|
*
|
|
233
|
-
* @since 0.
|
|
259
|
+
* @since 0.10.0
|
|
234
260
|
*/
|
|
235
261
|
export declare class ChainNotRegisteredError extends DiError {
|
|
236
262
|
readonly code = "CHAIN_NOT_REGISTERED";
|
package/dist/errors/errors.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { slotName } from "
|
|
1
|
+
import { slotName } from "#core/tag";
|
|
2
2
|
/**
|
|
3
3
|
* Base class for every error the library throws, each carrying a machine-readable `code`.
|
|
4
4
|
*
|
|
@@ -316,6 +316,38 @@ export class MissingContainerContextError extends DiError {
|
|
|
316
316
|
this.accessorName = accessorName;
|
|
317
317
|
}
|
|
318
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* A second `to*()` on a chain that already registered its binding.
|
|
321
|
+
*
|
|
322
|
+
* @remarks A chain is its binding, so it registers exactly once; a token bound twice is two `bind()`
|
|
323
|
+
* calls, the second of which displaces the first under slot last-wins.
|
|
324
|
+
*
|
|
325
|
+
* @since 0.10.0
|
|
326
|
+
*/
|
|
327
|
+
export class ChainAlreadyRegisteredError extends DiError {
|
|
328
|
+
code = "CHAIN_ALREADY_REGISTERED";
|
|
329
|
+
tokenName;
|
|
330
|
+
constructor(tokenName) {
|
|
331
|
+
super(`The binding for token '${tokenName}' is already registered on this chain. Call bind() again to register another binding for the token.`);
|
|
332
|
+
this.tokenName = tokenName;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* `many()` on a binding with a named or tagged slot, or a slot constraint on a collection member.
|
|
337
|
+
*
|
|
338
|
+
* @remarks A collection member keeps the default slot: its membership replaces slot last-wins, and a
|
|
339
|
+
* tagged member would have no index able to return every member of the tag.
|
|
340
|
+
*
|
|
341
|
+
* @since 0.10.0
|
|
342
|
+
*/
|
|
343
|
+
export class ManyBindingSlotError extends DiError {
|
|
344
|
+
code = "MANY_BINDING_SLOT";
|
|
345
|
+
tokenName;
|
|
346
|
+
constructor(tokenName) {
|
|
347
|
+
super(`A many() binding for token '${tokenName}' keeps the default slot: it cannot also declare whenNamed() or whenTagged().`);
|
|
348
|
+
this.tokenName = tokenName;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
319
351
|
/**
|
|
320
352
|
* A fluent chain was refined before a `to*()` call gave it a binding to refine.
|
|
321
353
|
*
|
|
@@ -323,7 +355,7 @@ export class MissingContainerContextError extends DiError {
|
|
|
323
355
|
* `BindToBuilder`, which exposes only `to*()`. It exists for JavaScript callers and for anyone who
|
|
324
356
|
* casts past the types, so the misuse fails loudly instead of mutating nothing.
|
|
325
357
|
*
|
|
326
|
-
* @since 0.
|
|
358
|
+
* @since 0.10.0
|
|
327
359
|
*/
|
|
328
360
|
export class ChainNotRegisteredError extends DiError {
|
|
329
361
|
code = "CHAIN_NOT_REGISTERED";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
export type { ActivationHandler, BindingConstraint, BindingIdentifier, BindingKind, BindingScope, BindingTag, ConstraintContext, Constructor, DependencyKey, DeactivationHandler, ResolutionFrame, ResolveOptions, ResolutionContext, TokenValue, } from "
|
|
2
|
-
export { token, tokenName } from "
|
|
3
|
-
export type { SlotNamesOf, Token } from "
|
|
4
|
-
export { coversTagKeys, NO_TAG_KEYS, slotName, tag, tagKeyMaskOf } from "
|
|
5
|
-
export type { TagKey, TagKeyMask } from "
|
|
6
|
-
export type { AliasBindingBuilder, BindToBuilder, BindingBuilder, ConstantBindingBuilder, ScopedBindingBuilder, SingletonBindingBuilder, SingletonLifecycleBuilder, SlotConstrainedBuilder, TransientBindingBuilder, } from "
|
|
7
|
-
export { Container } from "
|
|
8
|
-
export type { Container as ContainerInterface, ContainerOptions, ContainerStatic } from "
|
|
9
|
-
export { getActiveContainer, runWithContainer } from "
|
|
10
|
-
export { bindingSlotToResolveOptions, injectionSlotToResolveOptions, resolveOptionsForSlot, } from "
|
|
11
|
-
export type { DependencySlot } from "
|
|
12
|
-
export type { BindingSnapshot, ContainerSnapshot } from "
|
|
13
|
-
export type { ContainerGraphJson, GraphEdge, GraphNode, GraphOptions } from "
|
|
14
|
-
export { AsyncModule, isSyncModule, Module, SyncModule } from "
|
|
15
|
-
export type { AsyncModuleBuilder, ModuleBuilder } from "
|
|
16
|
-
export { inject } from "
|
|
17
|
-
export { injectAll, isInjectionDescriptor, optional } from "
|
|
18
|
-
export type { InjectionDescriptor, InjectOptions } from "
|
|
19
|
-
export { injectable } from "
|
|
20
|
-
export type { InjectableDependency, InjectableOptions } from "
|
|
21
|
-
export { postConstruct, preDestroy } from "
|
|
22
|
-
export { createAutoRegisterRegistry } from "
|
|
23
|
-
export type { AutoRegisterRegistry } from "
|
|
24
|
-
export { MetadataReaderToken } from "
|
|
25
|
-
export type { ConstructorMetadata, LifecycleMetadata, MetadataReader, MutableLifecycleMetadata, ParamMetadata, } from "
|
|
26
|
-
export { defaultMetadataReader, SymbolMetadataReader } from "
|
|
27
|
-
export { whenAnyAncestorIs, whenAnyAncestorNamed, whenAnyAncestorTagged, whenAnyAncestorTaggedAll, whenNoAncestorIs, whenNoParentIs, whenParentIs, whenParentNamed, whenParentTagged, whenParentTaggedAll, } from "
|
|
28
|
-
export { AmbiguousBindingError, AsyncActivationError, AsyncDeactivationError, AsyncModuleLoadError, AsyncResolutionError, ChainNotRegisteredError, CircularDependencyError, DiError, DisposedContainerError, InternalError, InvalidMetadataError, MissingContainerContextError, MissingMetadataError, MissingScopeContextError, NoMatchingBindingError, RebindUnboundTokenError, ScopeViolationError, SelfBindingRequiresClassError, StaticMemberDecoratorError, SyncDisposalNotSupportedError, EmptyTagCriteriaError, TokenNotBoundError, UnreachableConstraintError, UnreachableLifecycleHookError, } from "
|
|
29
|
-
export type { ScopeViolationDetails } from "
|
|
30
|
-
export { toDotGraph } from "
|
|
31
|
-
export { toCytoscapeGraph } from "
|
|
32
|
-
export type { CytoscapeEdge, CytoscapeElements, CytoscapeNode } from "
|
|
33
|
-
export { toReactFlowGraph } from "
|
|
34
|
-
export type { ReactFlowEdge, ReactFlowGraph, ReactFlowNode } from "
|
|
35
|
-
export { toMermaidGraph } from "
|
|
1
|
+
export type { ActivationHandler, BindingConstraint, BindingIdentifier, BindingKind, BindingScope, BindingTag, ConstraintContext, Constructor, DependencyKey, DeactivationHandler, ResolutionFrame, ResolveOptions, ResolutionContext, TokenValue, } from "#core/types";
|
|
2
|
+
export { token, tokenName } from "#core/token";
|
|
3
|
+
export type { SlotNamesOf, Token } from "#core/token";
|
|
4
|
+
export { coversTagKeys, NO_TAG_KEYS, slotName, tag, tagKeyMaskOf } from "#core/tag";
|
|
5
|
+
export type { TagKey, TagKeyMask } from "#core/tag";
|
|
6
|
+
export type { AliasBindingBuilder, BindToBuilder, BindingBuilder, ConstantBindingBuilder, ScopedBindingBuilder, SingletonBindingBuilder, SingletonLifecycleBuilder, SlotConstrainedBuilder, TransientBindingBuilder, } from "#core/binding";
|
|
7
|
+
export { Container } from "#container/container";
|
|
8
|
+
export type { Container as ContainerInterface, ContainerOptions, ContainerStatic } from "#container/container";
|
|
9
|
+
export { getActiveContainer, runWithContainer } from "#ambient/active-container";
|
|
10
|
+
export { bindingSlotToResolveOptions, injectionSlotToResolveOptions, resolveOptionsForSlot, } from "#injection/resolve-options";
|
|
11
|
+
export type { DependencySlot } from "#injection/resolve-options";
|
|
12
|
+
export type { BindingSnapshot, ContainerSnapshot } from "#introspection/inspector";
|
|
13
|
+
export type { ContainerGraphJson, GraphEdge, GraphNode, GraphOptions } from "#introspection/dependency-graph";
|
|
14
|
+
export { AsyncModule, isSyncModule, Module, SyncModule } from "#core/module";
|
|
15
|
+
export type { AsyncModuleBuilder, ModuleBuilder } from "#core/module";
|
|
16
|
+
export { inject } from "#decorators/inject";
|
|
17
|
+
export { injectAll, isInjectionDescriptor, optional } from "#injection/descriptor";
|
|
18
|
+
export type { InjectionDescriptor, InjectOptions } from "#injection/descriptor";
|
|
19
|
+
export { injectable } from "#decorators/injectable";
|
|
20
|
+
export type { InjectableDependency, InjectableOptions } from "#decorators/injectable";
|
|
21
|
+
export { postConstruct, preDestroy } from "#decorators/lifecycle-decorators";
|
|
22
|
+
export { createAutoRegisterRegistry } from "#decorators/injectable";
|
|
23
|
+
export type { AutoRegisterRegistry } from "#decorators/injectable";
|
|
24
|
+
export { MetadataReaderToken } from "#metadata/metadata-reader-token";
|
|
25
|
+
export type { ConstructorMetadata, LifecycleMetadata, MetadataReader, MutableLifecycleMetadata, ParamMetadata, } from "#metadata/metadata-types";
|
|
26
|
+
export { defaultMetadataReader, SymbolMetadataReader } from "#metadata/symbol-metadata-reader";
|
|
27
|
+
export { whenAnyAncestorIs, whenAnyAncestorNamed, whenAnyAncestorTagged, whenAnyAncestorTaggedAll, whenNoAncestorIs, whenNoParentIs, whenParentIs, whenParentNamed, whenParentTagged, whenParentTaggedAll, } from "#resolution/select/constraints";
|
|
28
|
+
export { AmbiguousBindingError, AsyncActivationError, AsyncDeactivationError, AsyncModuleLoadError, AsyncResolutionError, ChainAlreadyRegisteredError, ChainNotRegisteredError, ManyBindingSlotError, CircularDependencyError, DiError, DisposedContainerError, InternalError, InvalidMetadataError, MissingContainerContextError, MissingMetadataError, MissingScopeContextError, NoMatchingBindingError, RebindUnboundTokenError, ScopeViolationError, SelfBindingRequiresClassError, StaticMemberDecoratorError, SyncDisposalNotSupportedError, EmptyTagCriteriaError, TokenNotBoundError, UnreachableConstraintError, UnreachableLifecycleHookError, } from "#errors/errors";
|
|
29
|
+
export type { ScopeViolationDetails } from "#errors/errors";
|
|
30
|
+
export { toDotGraph } from "#introspection/graph-adapters/dot";
|
|
31
|
+
export { toCytoscapeGraph } from "#introspection/graph-adapters/cytoscape";
|
|
32
|
+
export type { CytoscapeEdge, CytoscapeElements, CytoscapeNode } from "#introspection/graph-adapters/cytoscape";
|
|
33
|
+
export { toReactFlowGraph } from "#introspection/graph-adapters/reactflow";
|
|
34
|
+
export type { ReactFlowEdge, ReactFlowGraph, ReactFlowNode } from "#introspection/graph-adapters/reactflow";
|
|
35
|
+
export { toMermaidGraph } from "#introspection/graph-adapters/mermaid";
|
package/dist/index.js
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
1
|
// Token
|
|
2
|
-
export { token, tokenName } from "
|
|
2
|
+
export { token, tokenName } from "#core/token";
|
|
3
3
|
// Tag — the interned slot criteria a `whenTagged` and a resolve both take
|
|
4
|
-
export { coversTagKeys, NO_TAG_KEYS, slotName, tag, tagKeyMaskOf } from "
|
|
4
|
+
export { coversTagKeys, NO_TAG_KEYS, slotName, tag, tagKeyMaskOf } from "#core/tag";
|
|
5
5
|
// Container
|
|
6
|
-
export { Container } from "
|
|
6
|
+
export { Container } from "#container/container";
|
|
7
7
|
// Ambient container — the context an `@inject` accessor initializer resolves from. `resolution/context`
|
|
8
8
|
// stays internal: it hands out resolver callbacks, not public values.
|
|
9
|
-
export { getActiveContainer, runWithContainer } from "
|
|
9
|
+
export { getActiveContainer, runWithContainer } from "#ambient/active-container";
|
|
10
10
|
// `effectiveBindingScope` is deliberately absent: it reads a `Binding`, which is internal, and no
|
|
11
11
|
// public API hands one out. `BindingSnapshot.scope` and `GraphNode.scope` are the public answers.
|
|
12
|
-
export { bindingSlotToResolveOptions, injectionSlotToResolveOptions, resolveOptionsForSlot, } from "
|
|
12
|
+
export { bindingSlotToResolveOptions, injectionSlotToResolveOptions, resolveOptionsForSlot, } from "#injection/resolve-options";
|
|
13
13
|
// Module
|
|
14
|
-
export { AsyncModule, isSyncModule, Module, SyncModule } from "
|
|
14
|
+
export { AsyncModule, isSyncModule, Module, SyncModule } from "#core/module";
|
|
15
15
|
// Decorators
|
|
16
|
-
export { inject } from "
|
|
17
|
-
export { injectAll, isInjectionDescriptor, optional } from "
|
|
18
|
-
export { injectable } from "
|
|
19
|
-
export { postConstruct, preDestroy } from "
|
|
16
|
+
export { inject } from "#decorators/inject";
|
|
17
|
+
export { injectAll, isInjectionDescriptor, optional } from "#injection/descriptor";
|
|
18
|
+
export { injectable } from "#decorators/injectable";
|
|
19
|
+
export { postConstruct, preDestroy } from "#decorators/lifecycle-decorators";
|
|
20
20
|
// Auto-register
|
|
21
|
-
export { createAutoRegisterRegistry } from "
|
|
21
|
+
export { createAutoRegisterRegistry } from "#decorators/injectable";
|
|
22
22
|
// MetadataReader — everything a consumer needs to write one and pass it to Container.create()
|
|
23
|
-
export { MetadataReaderToken } from "
|
|
24
|
-
export { defaultMetadataReader, SymbolMetadataReader } from "
|
|
23
|
+
export { MetadataReaderToken } from "#metadata/metadata-reader-token";
|
|
24
|
+
export { defaultMetadataReader, SymbolMetadataReader } from "#metadata/symbol-metadata-reader";
|
|
25
25
|
// Constraints — contextual injection predicates for .when()
|
|
26
|
-
export { whenAnyAncestorIs, whenAnyAncestorNamed, whenAnyAncestorTagged, whenAnyAncestorTaggedAll, whenNoAncestorIs, whenNoParentIs, whenParentIs, whenParentNamed, whenParentTagged, whenParentTaggedAll, } from "
|
|
26
|
+
export { whenAnyAncestorIs, whenAnyAncestorNamed, whenAnyAncestorTagged, whenAnyAncestorTaggedAll, whenNoAncestorIs, whenNoParentIs, whenParentIs, whenParentNamed, whenParentTagged, whenParentTaggedAll, } from "#resolution/select/constraints";
|
|
27
27
|
// Errors
|
|
28
|
-
export { AmbiguousBindingError, AsyncActivationError, AsyncDeactivationError, AsyncModuleLoadError, AsyncResolutionError, ChainNotRegisteredError, CircularDependencyError, DiError, DisposedContainerError, InternalError, InvalidMetadataError, MissingContainerContextError, MissingMetadataError, MissingScopeContextError, NoMatchingBindingError, RebindUnboundTokenError, ScopeViolationError, SelfBindingRequiresClassError, StaticMemberDecoratorError, SyncDisposalNotSupportedError, EmptyTagCriteriaError, TokenNotBoundError, UnreachableConstraintError, UnreachableLifecycleHookError, } from "
|
|
28
|
+
export { AmbiguousBindingError, AsyncActivationError, AsyncDeactivationError, AsyncModuleLoadError, AsyncResolutionError, ChainAlreadyRegisteredError, ChainNotRegisteredError, ManyBindingSlotError, CircularDependencyError, DiError, DisposedContainerError, InternalError, InvalidMetadataError, MissingContainerContextError, MissingMetadataError, MissingScopeContextError, NoMatchingBindingError, RebindUnboundTokenError, ScopeViolationError, SelfBindingRequiresClassError, StaticMemberDecoratorError, SyncDisposalNotSupportedError, EmptyTagCriteriaError, TokenNotBoundError, UnreachableConstraintError, UnreachableLifecycleHookError, } from "#errors/errors";
|
|
29
29
|
// Graph adapters — render `generateDependencyGraph()` output for common viewers
|
|
30
|
-
export { toDotGraph } from "
|
|
31
|
-
export { toCytoscapeGraph } from "
|
|
32
|
-
export { toReactFlowGraph } from "
|
|
33
|
-
export { toMermaidGraph } from "
|
|
30
|
+
export { toDotGraph } from "#introspection/graph-adapters/dot";
|
|
31
|
+
export { toCytoscapeGraph } from "#introspection/graph-adapters/cytoscape";
|
|
32
|
+
export { toReactFlowGraph } from "#introspection/graph-adapters/reactflow";
|
|
33
|
+
export { toMermaidGraph } from "#introspection/graph-adapters/mermaid";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** The one shape every declared dependency is normalised to, whatever channel declared it. */
|
|
2
|
-
import type { Token } from "
|
|
3
|
-
import type { BindingTag, Constructor, TokenValue } from "
|
|
4
|
-
import type { DependencySlot } from "
|
|
2
|
+
import type { Token } from "#core/token";
|
|
3
|
+
import type { BindingTag, Constructor, TokenValue } from "#core/types";
|
|
4
|
+
import type { DependencySlot } from "#injection/resolve-options";
|
|
5
5
|
/**
|
|
6
6
|
* Slot-selection options — a name and tags — a declared dependency narrows its binding with.
|
|
7
7
|
*
|
|
@@ -51,7 +51,7 @@ export type InjectableDependency<Value = unknown> = Token<Value> | Constructor<V
|
|
|
51
51
|
*/
|
|
52
52
|
export type ResolvedDependencyValue<Dependency> = Dependency extends {
|
|
53
53
|
readonly multi: true;
|
|
54
|
-
} ?
|
|
54
|
+
} ? ReadonlyArray<DescribedValue<Dependency>> : Dependency extends {
|
|
55
55
|
readonly optional: true;
|
|
56
56
|
} ? DescribedValue<Dependency> | undefined : DescribedValue<Dependency>;
|
|
57
57
|
/**
|
|
@@ -59,7 +59,7 @@ export type ResolvedDependencyValue<Dependency> = Dependency extends {
|
|
|
59
59
|
*
|
|
60
60
|
* @remarks Split out because a hand-written descriptor states its flags and its value type
|
|
61
61
|
* separately, and only the flags are load-bearing: `{ token: Plugin, multi: true }` says `Plugin`
|
|
62
|
-
* and delivers `
|
|
62
|
+
* and delivers `ReadonlyArray<Plugin>`. `injectAll()` and `optional()` already fold their effect in, so the
|
|
63
63
|
* flags find an array or an optional there and leave it alone.
|
|
64
64
|
*/
|
|
65
65
|
type DescribedValue<Dependency> = Dependency extends InjectionDescriptor<infer Value> ? Value : TokenValue<Dependency>;
|
|
@@ -88,9 +88,11 @@ export declare function buildInjectionDescriptor<Value, Names extends string = s
|
|
|
88
88
|
*/
|
|
89
89
|
export declare function optional<Value, Names extends string = string>(token: Token<Value, Names> | Constructor<Value>, options?: NoInfer<InjectOptions<Names>>): InjectionDescriptor<Value | undefined>;
|
|
90
90
|
/**
|
|
91
|
-
* Creates a descriptor that resolves every matching binding for the token into
|
|
91
|
+
* Creates a descriptor that resolves every matching binding for the token into a read-only array.
|
|
92
|
+
*
|
|
93
|
+
* @remarks Read-only because a root-level read may hand out the engine's own cached list.
|
|
92
94
|
*
|
|
93
95
|
* @since 0.3.16-canary.0
|
|
94
96
|
*/
|
|
95
|
-
export declare function injectAll<Value, Names extends string = string>(token: Token<Value, Names> | Constructor<Value>, options?: NoInfer<InjectOptions<Names>>): InjectionDescriptor<
|
|
97
|
+
export declare function injectAll<Value, Names extends string = string>(token: Token<Value, Names> | Constructor<Value>, options?: NoInfer<InjectOptions<Names>>): InjectionDescriptor<ReadonlyArray<Value>>;
|
|
96
98
|
export {};
|
|
@@ -112,7 +112,9 @@ export function optional(token, options) {
|
|
|
112
112
|
}, options);
|
|
113
113
|
}
|
|
114
114
|
/**
|
|
115
|
-
* Creates a descriptor that resolves every matching binding for the token into
|
|
115
|
+
* Creates a descriptor that resolves every matching binding for the token into a read-only array.
|
|
116
|
+
*
|
|
117
|
+
* @remarks Read-only because a root-level read may hand out the engine's own cached list.
|
|
116
118
|
*
|
|
117
119
|
* @since 0.3.16-canary.0
|
|
118
120
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { BindingTag } from "
|
|
2
|
-
import type { Token } from "
|
|
3
|
-
import type { Constructor, ResolveOptions } from "
|
|
1
|
+
import type { BindingTag } from "#core/tag";
|
|
2
|
+
import type { Token } from "#core/token";
|
|
3
|
+
import type { Constructor, ResolveOptions } from "#core/types";
|
|
4
4
|
/**
|
|
5
5
|
* What one resolvable dependency declares.
|
|
6
6
|
*
|
|
@@ -26,6 +26,12 @@ export interface DependencySlot {
|
|
|
26
26
|
* @since 0.5.0-canary.9
|
|
27
27
|
*/
|
|
28
28
|
export declare function singleCriterionOnlyOf(options: ResolveOptions | undefined): BindingTag | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* The one tag a request carries beside its name, for the name-plus-tag lane; `undefined` for every other shape.
|
|
31
|
+
*
|
|
32
|
+
* @since 0.10.0
|
|
33
|
+
*/
|
|
34
|
+
export declare function loneTagBesideNameOf(options: ResolveOptions): BindingTag | undefined;
|
|
29
35
|
/**
|
|
30
36
|
* Builds a {@link ResolveOptions} safe for `exactOptionalPropertyTypes`:
|
|
31
37
|
* omits keys instead of assigning `undefined`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { slotName, slotNameCriterionOf } from "
|
|
1
|
+
import { slotName, slotNameCriterionOf } from "#core/tag";
|
|
2
2
|
/**
|
|
3
3
|
* The lone criterion of a request that carries exactly one, whatever its spelling — the shape the
|
|
4
4
|
* registry has a direct index for.
|
|
@@ -22,6 +22,22 @@ export function singleCriterionOnlyOf(options) {
|
|
|
22
22
|
}
|
|
23
23
|
return listed !== undefined && listed.length === 1 ? listed[0] : undefined;
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* The one tag a request carries beside its name, for the name-plus-tag lane; `undefined` for every other shape.
|
|
27
|
+
*
|
|
28
|
+
* @since 0.10.0
|
|
29
|
+
*/
|
|
30
|
+
export function loneTagBesideNameOf(options) {
|
|
31
|
+
if (options.name === undefined) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
const listed = options.tags;
|
|
35
|
+
const shorthand = options.tag;
|
|
36
|
+
if (shorthand !== undefined) {
|
|
37
|
+
return listed === undefined || listed.length === 0 ? shorthand : undefined;
|
|
38
|
+
}
|
|
39
|
+
return listed !== undefined && listed.length === 1 ? listed[0] : undefined;
|
|
40
|
+
}
|
|
25
41
|
/** The name spelling's half of the fold, kept apart so the common body stays small enough to inline. */
|
|
26
42
|
function loneNameCriterionOf(options) {
|
|
27
43
|
// A name next to any tag means the request carries two criteria, which no single index answers.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { BindingRegistry } from "
|
|
2
|
-
import type { BindingKind, BindingScope } from "
|
|
3
|
-
import type { MetadataReader } from "
|
|
1
|
+
import type { BindingRegistry } from "#core/registry";
|
|
2
|
+
import type { BindingKind, BindingScope } from "#core/types";
|
|
3
|
+
import type { MetadataReader } from "#metadata/metadata-types";
|
|
4
4
|
/**
|
|
5
5
|
* @remarks `kind`/`scope` are `"unbound"` for the placeholder node an optional, currently
|
|
6
6
|
* unsatisfied dependency points at.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { effectiveBindingScope } from "
|
|
2
|
-
import { slotName } from "
|
|
3
|
-
import { tokenName } from "
|
|
4
|
-
import { bindingSlotToResolveOptions } from "
|
|
5
|
-
import { matchesSlot } from "
|
|
1
|
+
import { effectiveBindingScope } from "#core/binding-scope";
|
|
2
|
+
import { slotName } from "#core/tag";
|
|
3
|
+
import { tokenName } from "#core/token";
|
|
4
|
+
import { bindingSlotToResolveOptions } from "#injection/resolve-options";
|
|
5
|
+
import { matchesSlot } from "#resolution/select/binding-select";
|
|
6
6
|
// ── Builder ──────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
7
7
|
// Tokens are compared by object identity, and a name is free to repeat, so the graph mints its
|
|
8
8
|
// own per-process key. Weakly held: a discarded token takes its key with it.
|
|
@@ -100,7 +100,7 @@ function addDependencyEdges(accumulator, from, ref, index, lookup) {
|
|
|
100
100
|
: label;
|
|
101
101
|
accumulator.edges.push({
|
|
102
102
|
from,
|
|
103
|
-
to: target.
|
|
103
|
+
to: String(target.identifier),
|
|
104
104
|
label: perTargetLabel,
|
|
105
105
|
optional: ref.optional,
|
|
106
106
|
...(edgeSlotName !== undefined ? { slotName: edgeSlotName } : {}),
|
|
@@ -113,21 +113,26 @@ function addBindingEdges(accumulator, binding, metadataReader, lookup) {
|
|
|
113
113
|
const meta = metadataReader.getConstructorMetadata(binding.target);
|
|
114
114
|
if (meta !== undefined) {
|
|
115
115
|
for (const [index, param] of meta.params.entries()) {
|
|
116
|
-
addDependencyEdges(accumulator, binding.
|
|
116
|
+
addDependencyEdges(accumulator, String(binding.identifier), param, index, lookup);
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
121
|
if (binding.kind === "resolved" || binding.kind === "resolved-async") {
|
|
122
122
|
for (const [index, dependency] of binding.deps.entries()) {
|
|
123
|
-
addDependencyEdges(accumulator, binding.
|
|
123
|
+
addDependencyEdges(accumulator, String(binding.identifier), dependency, index, lookup);
|
|
124
124
|
}
|
|
125
125
|
return;
|
|
126
126
|
}
|
|
127
127
|
if (binding.kind === "alias") {
|
|
128
128
|
const aliasRef = { token: binding.target, optional: false, multi: false };
|
|
129
129
|
for (const target of matchingTargets(lookup(binding.target), aliasRef)) {
|
|
130
|
-
accumulator.edges.push({
|
|
130
|
+
accumulator.edges.push({
|
|
131
|
+
from: String(binding.identifier),
|
|
132
|
+
to: String(target.identifier),
|
|
133
|
+
label: "alias",
|
|
134
|
+
optional: false,
|
|
135
|
+
});
|
|
131
136
|
}
|
|
132
137
|
}
|
|
133
138
|
}
|
|
@@ -135,7 +140,7 @@ function addRegistryBindings(accumulator, sourceRegistry, metadataReader, fromPa
|
|
|
135
140
|
const lookup = bindingLookup(sourceRegistry, fallbackRegistry);
|
|
136
141
|
for (const binding of sourceRegistry.allBindings()) {
|
|
137
142
|
accumulator.nodes.push({
|
|
138
|
-
id: binding.
|
|
143
|
+
id: String(binding.identifier),
|
|
139
144
|
tokenName: tokenName(binding.token),
|
|
140
145
|
tokenKey: tokenKeyOf(binding.token),
|
|
141
146
|
kind: binding.kind,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ContainerGraphJson } from "
|
|
1
|
+
import type { ContainerGraphJson } from "#introspection/dependency-graph";
|
|
2
2
|
/**
|
|
3
3
|
* Mermaid `flowchart TD` source for a container graph — renders anywhere Mermaid does
|
|
4
4
|
* (GitHub markdown, docs tooling, mermaid.live) with no extra library.
|