@codefast/di 0.10.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +3 -2
  3. package/dist/ambient/active-container.d.ts +6 -9
  4. package/dist/ambient/active-container.js +2 -5
  5. package/dist/container/binding-builders.d.ts +7 -7
  6. package/dist/container/binding-builders.js +36 -27
  7. package/dist/container/container.d.ts +8 -8
  8. package/dist/container/container.js +20 -20
  9. package/dist/core/binding-scope.d.ts +2 -2
  10. package/dist/core/binding.d.ts +6 -6
  11. package/dist/core/binding.js +1 -1
  12. package/dist/core/constraint-requirement.d.ts +1 -1
  13. package/dist/core/module.d.ts +3 -3
  14. package/dist/core/registry.d.ts +6 -6
  15. package/dist/core/registry.js +36 -24
  16. package/dist/core/token.d.ts +1 -1
  17. package/dist/core/types.d.ts +5 -5
  18. package/dist/decorators/inject.d.ts +3 -3
  19. package/dist/decorators/inject.js +5 -5
  20. package/dist/decorators/injectable.d.ts +2 -2
  21. package/dist/decorators/injectable.js +2 -2
  22. package/dist/decorators/lifecycle-decorators.js +2 -2
  23. package/dist/errors/errors.d.ts +8 -11
  24. package/dist/errors/errors.js +7 -10
  25. package/dist/index.d.ts +35 -35
  26. package/dist/index.js +19 -19
  27. package/dist/injection/descriptor.d.ts +3 -3
  28. package/dist/injection/resolve-options.d.ts +3 -3
  29. package/dist/injection/resolve-options.js +1 -1
  30. package/dist/introspection/dependency-graph.d.ts +3 -3
  31. package/dist/introspection/dependency-graph.js +5 -5
  32. package/dist/introspection/graph-adapters/cytoscape.d.ts +1 -1
  33. package/dist/introspection/graph-adapters/dot.d.ts +1 -1
  34. package/dist/introspection/graph-adapters/mermaid.d.ts +1 -1
  35. package/dist/introspection/graph-adapters/reactflow.d.ts +1 -1
  36. package/dist/introspection/inspector.d.ts +4 -4
  37. package/dist/introspection/inspector.js +3 -3
  38. package/dist/lifecycle/lifecycle-manager.d.ts +4 -4
  39. package/dist/lifecycle/lifecycle-manager.js +4 -4
  40. package/dist/lifecycle/scope-manager.d.ts +2 -2
  41. package/dist/lifecycle/scope-manager.js +3 -3
  42. package/dist/metadata/metadata-reader-token.d.ts +2 -2
  43. package/dist/metadata/metadata-reader-token.js +1 -1
  44. package/dist/metadata/metadata-types.d.ts +3 -3
  45. package/dist/metadata/symbol-metadata-reader.d.ts +3 -3
  46. package/dist/metadata/symbol-metadata-reader.js +1 -1
  47. package/dist/metadata/verifying-metadata-reader.d.ts +1 -1
  48. package/dist/metadata/verifying-metadata-reader.js +2 -2
  49. package/dist/resolution/cache/activation-need.d.ts +4 -4
  50. package/dist/resolution/cache/binding-lookup-cache.d.ts +5 -5
  51. package/dist/resolution/cache/binding-lookup-cache.js +2 -2
  52. package/dist/resolution/cache/class-introspector.d.ts +5 -5
  53. package/dist/resolution/cache/class-introspector.js +55 -56
  54. package/dist/resolution/context.d.ts +3 -3
  55. package/dist/resolution/context.js +1 -1
  56. package/dist/resolution/path/resolution-path.d.ts +1 -1
  57. package/dist/resolution/path/resolution-path.js +1 -1
  58. package/dist/resolution/plan/instantiation-plan.d.ts +5 -5
  59. package/dist/resolution/plan/instantiation-plan.js +5 -5
  60. package/dist/resolution/plan/plan-codegen.d.ts +3 -3
  61. package/dist/resolution/plan/plan-codegen.js +2 -2
  62. package/dist/resolution/resolver.d.ts +12 -12
  63. package/dist/resolution/resolver.js +33 -20
  64. package/dist/resolution/select/binding-select.d.ts +6 -5
  65. package/dist/resolution/select/binding-select.js +5 -4
  66. package/dist/resolution/select/constraints.d.ts +3 -3
  67. package/dist/resolution/select/constraints.js +4 -4
  68. package/package.json +3 -3
@@ -1,4 +1,4 @@
1
- import { slotName } from "#/core/tag";
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,15 +316,6 @@ export class MissingContainerContextError extends DiError {
316
316
  this.accessorName = accessorName;
317
317
  }
318
318
  }
319
- /**
320
- * A fluent chain was refined before a `to*()` call gave it a binding to refine.
321
- *
322
- * @remarks The builder types make this unreachable from TypeScript — `bind()` returns
323
- * `BindToBuilder`, which exposes only `to*()`. It exists for JavaScript callers and for anyone who
324
- * casts past the types, so the misuse fails loudly instead of mutating nothing.
325
- *
326
- * @since 0.5.0-canary.8
327
- */
328
319
  /**
329
320
  * A second `to*()` on a chain that already registered its binding.
330
321
  *
@@ -358,6 +349,12 @@ export class ManyBindingSlotError extends DiError {
358
349
  }
359
350
  }
360
351
  /**
352
+ * A fluent chain was refined before a `to*()` call gave it a binding to refine.
353
+ *
354
+ * @remarks The builder types make this unreachable from TypeScript — `bind()` returns
355
+ * `BindToBuilder`, which exposes only `to*()`. It exists for JavaScript callers and for anyone who
356
+ * casts past the types, so the misuse fails loudly instead of mutating nothing.
357
+ *
361
358
  * @since 0.10.0
362
359
  */
363
360
  export class ChainNotRegisteredError extends DiError {
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 "#/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";
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 "#/core/token";
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 "#/core/tag";
4
+ export { coversTagKeys, NO_TAG_KEYS, slotName, tag, tagKeyMaskOf } from "#core/tag";
5
5
  // Container
6
- export { Container } from "#/container/container";
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 "#/ambient/active-container";
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 "#/injection/resolve-options";
12
+ export { bindingSlotToResolveOptions, injectionSlotToResolveOptions, resolveOptionsForSlot, } from "#injection/resolve-options";
13
13
  // Module
14
- export { AsyncModule, isSyncModule, Module, SyncModule } from "#/core/module";
14
+ export { AsyncModule, isSyncModule, Module, SyncModule } from "#core/module";
15
15
  // Decorators
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";
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 "#/decorators/injectable";
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 "#/metadata/metadata-reader-token";
24
- export { defaultMetadataReader, SymbolMetadataReader } from "#/metadata/symbol-metadata-reader";
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 "#/resolution/select/constraints";
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, ChainAlreadyRegisteredError, ChainNotRegisteredError, ManyBindingSlotError, CircularDependencyError, DiError, DisposedContainerError, InternalError, InvalidMetadataError, MissingContainerContextError, MissingMetadataError, MissingScopeContextError, NoMatchingBindingError, RebindUnboundTokenError, ScopeViolationError, SelfBindingRequiresClassError, StaticMemberDecoratorError, SyncDisposalNotSupportedError, EmptyTagCriteriaError, TokenNotBoundError, UnreachableConstraintError, UnreachableLifecycleHookError, } from "#/errors/errors";
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 "#/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";
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 "#/core/token";
3
- import type { BindingTag, Constructor, TokenValue } from "#/core/types";
4
- import type { DependencySlot } from "#/injection/resolve-options";
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
  *
@@ -1,6 +1,6 @@
1
- import type { BindingTag } from "#/core/tag";
2
- import type { Token } from "#/core/token";
3
- import type { Constructor, ResolveOptions } from "#/core/types";
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
  *
@@ -1,4 +1,4 @@
1
- import { slotName, slotNameCriterionOf } from "#/core/tag";
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.
@@ -1,6 +1,6 @@
1
- import type { BindingRegistry } from "#/core/registry";
2
- import type { BindingKind, BindingScope } from "#/core/types";
3
- import type { MetadataReader } from "#/metadata/metadata-types";
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 "#/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";
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.
@@ -1,4 +1,4 @@
1
- import type { ContainerGraphJson, GraphNode } from "#/introspection/dependency-graph";
1
+ import type { ContainerGraphJson, GraphNode } from "#introspection/dependency-graph";
2
2
  /**
3
3
  * A dependency-graph node in Cytoscape's element format.
4
4
  *
@@ -1,4 +1,4 @@
1
- import type { ContainerGraphJson } from "#/introspection/dependency-graph";
1
+ import type { ContainerGraphJson } from "#introspection/dependency-graph";
2
2
  /**
3
3
  * Renders a container's dependency graph as Graphviz DOT source.
4
4
  *
@@ -1,4 +1,4 @@
1
- import type { ContainerGraphJson } from "#/introspection/dependency-graph";
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.
@@ -1,4 +1,4 @@
1
- import type { ContainerGraphJson, GraphNode } from "#/introspection/dependency-graph";
1
+ import type { ContainerGraphJson, GraphNode } from "#introspection/dependency-graph";
2
2
  /**
3
3
  * A dependency-graph node in React Flow's node format.
4
4
  *
@@ -1,7 +1,7 @@
1
- import type { BindingRegistry } from "#/core/registry";
2
- import type { Token } from "#/core/token";
3
- import type { BindingIdentifier, BindingKind, BindingScope, BindingTag, Constructor, ResolveOptions } from "#/core/types";
4
- import type { ScopeManager } from "#/lifecycle/scope-manager";
1
+ import type { BindingRegistry } from "#core/registry";
2
+ import type { Token } from "#core/token";
3
+ import type { BindingIdentifier, BindingKind, BindingScope, BindingTag, Constructor, ResolveOptions } from "#core/types";
4
+ import type { ScopeManager } from "#lifecycle/scope-manager";
5
5
  /**
6
6
  * A read-only view of one binding: token, kind, scope, slot, and id.
7
7
  *
@@ -1,6 +1,6 @@
1
- import { effectiveBindingScope } from "#/core/binding-scope";
2
- import { tokenName } from "#/core/token";
3
- import { selectAllBindings } from "#/resolution/select/binding-select";
1
+ import { effectiveBindingScope } from "#core/binding-scope";
2
+ import { tokenName } from "#core/token";
3
+ import { selectAllBindings } from "#resolution/select/binding-select";
4
4
  // ── Inspector ────────────────────────────────────────────────────────────────────────────────────────────────────────
5
5
  /**
6
6
  * The read-only introspection surface behind a container's `inspect()`.
@@ -1,7 +1,7 @@
1
- import type { Binding } from "#/core/binding";
2
- import type { Token } from "#/core/token";
3
- import type { ActivationHandler, Constructor, DeactivationHandler, DependencyKey, ResolutionContext } from "#/core/types";
4
- import type { MetadataReader } from "#/metadata/metadata-types";
1
+ import type { Binding } from "#core/binding";
2
+ import type { Token } from "#core/token";
3
+ import type { ActivationHandler, Constructor, DeactivationHandler, DependencyKey, ResolutionContext } from "#core/types";
4
+ import type { MetadataReader } from "#metadata/metadata-types";
5
5
  /**
6
6
  * One container's registry of container-level activation and deactivation hooks, keyed by token.
7
7
  *
@@ -1,7 +1,7 @@
1
- import { getOrInsert } from "#/core/map-upsert";
2
- import { advanceStateEpoch } from "#/core/state-epoch";
3
- import { tokenName } from "#/core/token";
4
- import { AsyncActivationError, AsyncDeactivationError, InvalidMetadataError } from "#/errors/errors";
1
+ import { getOrInsert } from "#core/map-upsert";
2
+ import { advanceStateEpoch } from "#core/state-epoch";
3
+ import { tokenName } from "#core/token";
4
+ import { AsyncActivationError, AsyncDeactivationError, InvalidMetadataError } from "#errors/errors";
5
5
  /**
6
6
  * One container's registry of container-level activation and deactivation hooks, keyed by token.
7
7
  *
@@ -1,5 +1,5 @@
1
- import type { Binding } from "#/core/binding";
2
- import type { BindingIdentifier } from "#/core/types";
1
+ import type { Binding } from "#core/binding";
2
+ import type { BindingIdentifier } from "#core/types";
3
3
  /**
4
4
  * One container's instance caches — singletons, in-flight async creations, and the scoped cache.
5
5
  *
@@ -1,6 +1,6 @@
1
- import { NO_INSTANCE } from "#/core/binding";
2
- import { tokenName } from "#/core/token";
3
- import { MissingScopeContextError } from "#/errors/errors";
1
+ import { NO_INSTANCE } from "#core/binding";
2
+ import { tokenName } from "#core/token";
3
+ import { MissingScopeContextError } from "#errors/errors";
4
4
  /**
5
5
  * One container's instance caches — singletons, in-flight async creations, and the scoped cache.
6
6
  *
@@ -1,5 +1,5 @@
1
- import type { Token } from "#/core/token";
2
- import type { MetadataReader } from "#/metadata/metadata-types";
1
+ import type { Token } from "#core/token";
2
+ import type { MetadataReader } from "#metadata/metadata-types";
3
3
  /**
4
4
  * The token a custom `MetadataReader` is bound to for a container to pick up.
5
5
  *
@@ -1,4 +1,4 @@
1
- import { token } from "#/core/token";
1
+ import { token } from "#core/token";
2
2
  /**
3
3
  * The token a custom `MetadataReader` is bound to for a container to pick up.
4
4
  *
@@ -1,6 +1,6 @@
1
- import type { Constructor } from "#/core/types";
2
- import type { InjectionDescriptor } from "#/injection/descriptor";
3
- import type { DependencySlot } from "#/injection/resolve-options";
1
+ import type { Constructor } from "#core/types";
2
+ import type { InjectionDescriptor } from "#injection/descriptor";
3
+ import type { DependencySlot } from "#injection/resolve-options";
4
4
  /**
5
5
  * One constructor parameter's declaration.
6
6
  *
@@ -1,6 +1,6 @@
1
- import type { Constructor } from "#/core/types";
2
- import type { InjectionDescriptor } from "#/injection/descriptor";
3
- import type { ConstructorMetadata, LifecycleMetadata, MetadataReader } from "#/metadata/metadata-types";
1
+ import type { Constructor } from "#core/types";
2
+ import type { InjectionDescriptor } from "#injection/descriptor";
3
+ import type { ConstructorMetadata, LifecycleMetadata, MetadataReader } from "#metadata/metadata-types";
4
4
  type AccessorEntry = {
5
5
  readonly key: string | symbol;
6
6
  readonly descriptor: InjectionDescriptor;
@@ -1,4 +1,4 @@
1
- import { INJECT_ACCESSOR_KEY, INJECTABLE_KEY, LIFECYCLE_KEY, METADATA_SYMBOL } from "#/metadata/metadata-keys";
1
+ import { INJECT_ACCESSOR_KEY, INJECTABLE_KEY, LIFECYCLE_KEY, METADATA_SYMBOL } from "#metadata/metadata-keys";
2
2
  /**
3
3
  * The default `MetadataReader`, reading decorator metadata stored under `Symbol.metadata`.
4
4
  *
@@ -2,7 +2,7 @@
2
2
  * Wraps a foreign {@link MetadataReader} so its answers are verified before anything dereferences
3
3
  * them.
4
4
  */
5
- import type { MetadataReader } from "#/metadata/metadata-types";
5
+ import type { MetadataReader } from "#metadata/metadata-types";
6
6
  /**
7
7
  * The reader a container should hand its resolver: verified when it came from outside.
8
8
  *
@@ -2,8 +2,8 @@
2
2
  * Wraps a foreign {@link MetadataReader} so its answers are verified before anything dereferences
3
3
  * them.
4
4
  */
5
- import { defaultMetadataReader } from "#/metadata/symbol-metadata-reader";
6
- import { verifyAccessorMetadata, verifyConstructorMetadata, verifyLifecycleMetadata, } from "#/resolution/cache/class-introspector";
5
+ import { defaultMetadataReader } from "#metadata/symbol-metadata-reader";
6
+ import { verifyAccessorMetadata, verifyConstructorMetadata, verifyLifecycleMetadata, } from "#resolution/cache/class-introspector";
7
7
  // Wrapping a wrapper would stack a layer per child container, so each one is remembered.
8
8
  const verifyingReaders = new WeakSet();
9
9
  /**
@@ -4,10 +4,10 @@
4
4
  * @remarks Versioned on the lifecycle manager plus the own registry, since `onActivation` can be
5
5
  * registered at any time and a rebind mints binding ids the memo must not keep forever.
6
6
  */
7
- import type { Binding } from "#/core/binding";
8
- import type { BindingRegistry } from "#/core/registry";
9
- import type { LifecycleManager } from "#/lifecycle/lifecycle-manager";
10
- import type { ClassIntrospector } from "#/resolution/cache/class-introspector";
7
+ import type { Binding } from "#core/binding";
8
+ import type { BindingRegistry } from "#core/registry";
9
+ import type { LifecycleManager } from "#lifecycle/lifecycle-manager";
10
+ import type { ClassIntrospector } from "#resolution/cache/class-introspector";
11
11
  /**
12
12
  * A per-binding cache of whether activation work — hooks or `@postConstruct` — is needed on resolve.
13
13
  *
@@ -4,11 +4,11 @@
4
4
  * @remarks Each cache links to its parent's, so a child answers from its own chain without walking
5
5
  * the container hierarchy again.
6
6
  */
7
- import type { Binding } from "#/core/binding";
8
- import type { BindingRegistry } from "#/core/registry";
9
- import type { BindingTag } from "#/core/tag";
10
- import type { Token } from "#/core/token";
11
- import type { Constructor } from "#/core/types";
7
+ import type { Binding } from "#core/binding";
8
+ import type { BindingRegistry } from "#core/registry";
9
+ import type { BindingTag } from "#core/tag";
10
+ import type { Token } from "#core/token";
11
+ import type { Constructor } from "#core/types";
12
12
  /**
13
13
  * A token's terminal binding with alias hops already folded, plus the container that owns it.
14
14
  *
@@ -1,5 +1,5 @@
1
- import { getOrInsertComputed } from "#/core/map-upsert";
2
- import { stateEpoch } from "#/core/state-epoch";
1
+ import { getOrInsertComputed } from "#core/map-upsert";
2
+ import { stateEpoch } from "#core/state-epoch";
3
3
  /**
4
4
  * Alias folding gives up past this many hops and defers to the full resolve loop, whose
5
5
  * Set-based traversal detects genuine cycles exactly rather than by an arbitrary cap.
@@ -3,11 +3,11 @@
3
3
  *
4
4
  * @remarks Metadata cannot change once a class is defined, so nothing here needs version stamping.
5
5
  */
6
- import type { AmbientResolution } from "#/ambient/active-container";
7
- import type { Container } from "#/container/container";
8
- import type { Constructor } from "#/core/types";
9
- import type { InjectionDescriptor } from "#/injection/descriptor";
10
- import type { ConstructorMetadata, LifecycleMetadata, MetadataReader } from "#/metadata/metadata-types";
6
+ import type { AmbientResolution } from "#ambient/active-container";
7
+ import type { Container } from "#container/container";
8
+ import type { Constructor } from "#core/types";
9
+ import type { InjectionDescriptor } from "#injection/descriptor";
10
+ import type { ConstructorMetadata, LifecycleMetadata, MetadataReader } from "#metadata/metadata-types";
11
11
  /**
12
12
  * A reader's constructor metadata for a class, verified the first time this process asks.
13
13
  *
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * @remarks Metadata cannot change once a class is defined, so nothing here needs version stamping.
5
5
  */
6
- import { constructWithAmbientResolution, runWithAmbientResolution } from "#/ambient/active-container";
7
- import { InvalidMetadataError } from "#/errors/errors";
6
+ import { constructWithAmbientResolution, runWithAmbientResolution } from "#ambient/active-container";
7
+ import { InvalidMetadataError } from "#errors/errors";
8
8
  // Verified pairs, not verified classes: two readers may disagree about the same class, and a reader
9
9
  // that goes out of scope takes its record with it.
10
10
  const verifiedTargets = new WeakMap();
@@ -21,6 +21,20 @@ function markVerified(cache, reader, target) {
21
21
  }
22
22
  verified.add(target);
23
23
  }
24
+ /**
25
+ * Runs `validate` against a reader's metadata the first time this process sees the pair, then remembers it.
26
+ *
27
+ * @remarks An absent metadata answer needs no check; a verified pair is returned untouched, so the
28
+ * shape assertion runs once per `(reader, target)` rather than per container.
29
+ */
30
+ function verifyOnce(cache, reader, target, metadata, validate) {
31
+ if (metadata === undefined || isVerified(cache, reader, target)) {
32
+ return metadata;
33
+ }
34
+ validate(metadata);
35
+ markVerified(cache, reader, target);
36
+ return metadata;
37
+ }
24
38
  /**
25
39
  * A reader's constructor metadata for a class, verified the first time this process asks.
26
40
  *
@@ -31,16 +45,9 @@ function markVerified(cache, reader, target) {
31
45
  * @since 0.6.0
32
46
  */
33
47
  export function verifyConstructorMetadata(reader, target) {
34
- const metadata = reader.getConstructorMetadata(target);
35
- if (metadata === undefined) {
36
- return undefined;
37
- }
38
- if (isVerified(verifiedTargets, reader, target)) {
39
- return metadata;
40
- }
41
- assertConstructorMetadata(metadata, target);
42
- markVerified(verifiedTargets, reader, target);
43
- return metadata;
48
+ return verifyOnce(verifiedTargets, reader, target, reader.getConstructorMetadata(target), (metadata) => {
49
+ assertConstructorMetadata(metadata, target);
50
+ });
44
51
  }
45
52
  /**
46
53
  * Verifies what a reader claims about a class, since a `MetadataReader` is a public seam.
@@ -81,29 +88,25 @@ export function assertConstructorMetadata(metadata, target) {
81
88
  * @since 0.6.0
82
89
  */
83
90
  export function verifyLifecycleMetadata(reader, target) {
84
- const metadata = reader.getLifecycleMetadata(target);
85
- if (metadata === undefined || isVerified(verifiedLifecycleTargets, reader, target)) {
86
- return metadata;
87
- }
88
- if (typeof metadata !== "object" || metadata === null) {
89
- throw new InvalidMetadataError(target.name, `lifecycle metadata: expected an object, received ${typeof metadata}`);
90
- }
91
- for (const phase of ["postConstruct", "preDestroy"]) {
92
- const methods = Reflect.get(metadata, phase);
93
- if (methods === undefined) {
94
- continue;
91
+ return verifyOnce(verifiedLifecycleTargets, reader, target, reader.getLifecycleMetadata(target), (metadata) => {
92
+ if (typeof metadata !== "object" || metadata === null) {
93
+ throw new InvalidMetadataError(target.name, `lifecycle metadata: expected an object, received ${typeof metadata}`);
95
94
  }
96
- if (!Array.isArray(methods)) {
97
- throw new InvalidMetadataError(target.name, `lifecycle metadata: ${phase} is not an array`);
98
- }
99
- for (const [position, name] of methods.entries()) {
100
- if (typeof name !== "string") {
101
- throw new InvalidMetadataError(target.name, `lifecycle metadata: ${phase}[${String(position)}] is not a string`);
95
+ for (const phase of ["postConstruct", "preDestroy"]) {
96
+ const methods = Reflect.get(metadata, phase);
97
+ if (methods === undefined) {
98
+ continue;
99
+ }
100
+ if (!Array.isArray(methods)) {
101
+ throw new InvalidMetadataError(target.name, `lifecycle metadata: ${phase} is not an array`);
102
+ }
103
+ for (const [position, name] of methods.entries()) {
104
+ if (typeof name !== "string") {
105
+ throw new InvalidMetadataError(target.name, `lifecycle metadata: ${phase}[${String(position)}] is not a string`);
106
+ }
102
107
  }
103
108
  }
104
- }
105
- markVerified(verifiedLifecycleTargets, reader, target);
106
- return metadata;
109
+ });
107
110
  }
108
111
  /**
109
112
  * A reader's accessor metadata for a class, verified the first time this process asks.
@@ -111,32 +114,28 @@ export function verifyLifecycleMetadata(reader, target) {
111
114
  * @since 0.6.0
112
115
  */
113
116
  export function verifyAccessorMetadata(reader, target) {
114
- const metadata = reader.getAccessorMetadata?.(target);
115
- if (metadata === undefined || isVerified(verifiedAccessorTargets, reader, target)) {
116
- return metadata;
117
- }
118
- if (!Array.isArray(metadata)) {
119
- throw new InvalidMetadataError(target.name, "accessor metadata: expected an array");
120
- }
121
- for (const [position, entry] of metadata.entries()) {
122
- if (typeof entry !== "object" || entry === null) {
123
- throw new InvalidMetadataError(target.name, `accessor metadata: [${String(position)}] is not an object`);
124
- }
125
- const key = Reflect.get(entry, "key");
126
- if (typeof key !== "string" && typeof key !== "symbol") {
127
- throw new InvalidMetadataError(target.name, `accessor metadata: [${String(position)}].key is not a string or symbol`);
117
+ return verifyOnce(verifiedAccessorTargets, reader, target, reader.getAccessorMetadata?.(target), (metadata) => {
118
+ if (!Array.isArray(metadata)) {
119
+ throw new InvalidMetadataError(target.name, "accessor metadata: expected an array");
128
120
  }
129
- const descriptor = Reflect.get(entry, "descriptor");
130
- if (typeof descriptor !== "object" || descriptor === null) {
131
- throw new InvalidMetadataError(target.name, `accessor metadata: [${String(position)}].descriptor is not an object`);
132
- }
133
- const dependency = Reflect.get(descriptor, "token");
134
- if (typeof dependency !== "object" && typeof dependency !== "function") {
135
- throw new InvalidMetadataError(target.name, `accessor metadata: [${String(position)}].descriptor.token is not a token or a class`);
121
+ for (const [position, entry] of metadata.entries()) {
122
+ if (typeof entry !== "object" || entry === null) {
123
+ throw new InvalidMetadataError(target.name, `accessor metadata: [${String(position)}] is not an object`);
124
+ }
125
+ const key = Reflect.get(entry, "key");
126
+ if (typeof key !== "string" && typeof key !== "symbol") {
127
+ throw new InvalidMetadataError(target.name, `accessor metadata: [${String(position)}].key is not a string or symbol`);
128
+ }
129
+ const descriptor = Reflect.get(entry, "descriptor");
130
+ if (typeof descriptor !== "object" || descriptor === null) {
131
+ throw new InvalidMetadataError(target.name, `accessor metadata: [${String(position)}].descriptor is not an object`);
132
+ }
133
+ const dependency = Reflect.get(descriptor, "token");
134
+ if (typeof dependency !== "object" && typeof dependency !== "function") {
135
+ throw new InvalidMetadataError(target.name, `accessor metadata: [${String(position)}].descriptor.token is not a token or a class`);
136
+ }
136
137
  }
137
- }
138
- markVerified(verifiedAccessorTargets, reader, target);
139
- return metadata;
138
+ });
140
139
  }
141
140
  const cachesByReader = new WeakMap();
142
141
  function cachesFor(reader) {