@codefast/di 0.3.16-canary.2 → 0.3.16-canary.3

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 (60) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/binding.d.mts +24 -24
  3. package/dist/constraints.d.mts +3 -3
  4. package/dist/container.mjs +82 -150
  5. package/dist/decorators/inject.d.mts +3 -2
  6. package/dist/decorators/inject.mjs +13 -40
  7. package/dist/decorators/injectable.mjs +4 -12
  8. package/dist/decorators/lifecycle-decorators.mjs +11 -72
  9. package/dist/dependency-graph.mjs +6 -4
  10. package/dist/graph-adapters/cytoscape.d.mts +12 -12
  11. package/dist/graph-adapters/cytoscape.mjs +7 -7
  12. package/dist/graph-adapters/reactflow.d.mts +15 -15
  13. package/dist/graph-adapters/reactflow.mjs +6 -9
  14. package/dist/index.d.mts +3 -3
  15. package/dist/inspector.d.mts +3 -2
  16. package/dist/inspector.mjs +7 -10
  17. package/dist/lifecycle.mjs +2 -12
  18. package/dist/metadata/metadata-keys.d.mts +8 -33
  19. package/dist/metadata/metadata-keys.mjs +8 -21
  20. package/dist/metadata/metadata-types.d.mts +5 -0
  21. package/dist/metadata/symbol-metadata-reader.d.mts +1 -0
  22. package/dist/metadata/symbol-metadata-reader.mjs +11 -33
  23. package/dist/registry.mjs +3 -22
  24. package/dist/resolve-options.d.mts +2 -2
  25. package/dist/resolve-options.mjs +10 -8
  26. package/dist/resolver.d.mts +5 -0
  27. package/dist/resolver.mjs +15 -21
  28. package/dist/types.d.mts +10 -4
  29. package/package.json +39 -13
  30. package/src/binding-scope.ts +26 -0
  31. package/src/binding-select.ts +167 -0
  32. package/src/binding.ts +281 -0
  33. package/src/constraints.ts +149 -0
  34. package/src/constructor-type.ts +19 -0
  35. package/src/container.ts +1213 -0
  36. package/src/decorators/inject.ts +233 -0
  37. package/src/decorators/injectable.ts +85 -0
  38. package/src/decorators/lifecycle-decorators.ts +55 -0
  39. package/src/dependency-graph.ts +116 -0
  40. package/src/environment.ts +232 -0
  41. package/src/errors.ts +262 -0
  42. package/src/graph-adapters/cytoscape.ts +64 -0
  43. package/src/graph-adapters/dot.ts +22 -0
  44. package/src/graph-adapters/reactflow.ts +58 -0
  45. package/src/index.ts +101 -0
  46. package/src/inspector.ts +133 -0
  47. package/src/lifecycle.ts +238 -0
  48. package/src/metadata/metadata-keys.ts +25 -0
  49. package/src/metadata/metadata-reader-token.ts +8 -0
  50. package/src/metadata/metadata-types.ts +53 -0
  51. package/src/metadata/symbol-metadata-reader.ts +57 -0
  52. package/src/module.ts +93 -0
  53. package/src/registry.ts +241 -0
  54. package/src/resolve-options.ts +42 -0
  55. package/src/resolver.ts +1837 -0
  56. package/src/scope.ts +77 -0
  57. package/src/token.ts +40 -0
  58. package/src/types.ts +145 -0
  59. package/dist/graph-adapters/types.d.mts +0 -2
  60. package/dist/graph-adapters/types.mjs +0 -1
@@ -1,26 +1,9 @@
1
1
  import { InternalError } from "../errors.mjs";
2
- import { LIFECYCLE_KEY, lifecycleByConstructorMetadataMap, lifecycleMetadataMap } from "../metadata/metadata-keys.mjs";
2
+ import { LIFECYCLE_KEY } from "../metadata/metadata-keys.mjs";
3
3
  //#region src/decorators/lifecycle-decorators.ts
4
4
  function appendUniqueMethod(metadata, phase, methodName) {
5
5
  if (!metadata[phase].includes(methodName)) metadata[phase].push(methodName);
6
6
  }
7
- function resolveConstructorFromDecoratorTarget(target) {
8
- if (typeof target === "function") return target;
9
- if (typeof target === "object" && target !== null) {
10
- const ctor = target.constructor;
11
- if (typeof ctor === "function") return ctor;
12
- }
13
- }
14
- function registerByConstructor(target, phase, methodName) {
15
- const ctor = resolveConstructorFromDecoratorTarget(target);
16
- if (ctor === void 0) return;
17
- const ctorExisting = lifecycleByConstructorMetadataMap.get(ctor);
18
- if (ctorExisting !== void 0) appendUniqueMethod(ctorExisting, phase, methodName);
19
- else lifecycleByConstructorMetadataMap.set(ctor, {
20
- postConstruct: phase === "postConstruct" ? [methodName] : [],
21
- preDestroy: phase === "preDestroy" ? [methodName] : []
22
- });
23
- }
24
7
  /**
25
8
  * @since 0.3.16-canary.0
26
9
  */
@@ -28,34 +11,12 @@ function postConstruct() {
28
11
  return function(target, context) {
29
12
  if (context.static === true) throw new InternalError("@postConstruct() applies to instance methods only; static methods are not invoked during instance lifecycle.");
30
13
  const methodName = String(context.name);
31
- registerByConstructor(target, "postConstruct", methodName);
32
- const existing = lifecycleMetadataMap.get(context.metadata);
33
- if (existing !== void 0) appendUniqueMethod(existing, "postConstruct", methodName);
34
- else lifecycleMetadataMap.set(context.metadata, {
35
- postConstruct: [methodName],
14
+ const meta = context.metadata;
15
+ if (!meta[LIFECYCLE_KEY]) meta[LIFECYCLE_KEY] = {
16
+ postConstruct: [],
36
17
  preDestroy: []
37
- });
38
- context.addInitializer(function() {
39
- const targetOrInstance = this;
40
- const ctor = typeof targetOrInstance === "function" ? targetOrInstance : targetOrInstance.constructor;
41
- const ctorExisting = lifecycleByConstructorMetadataMap.get(ctor);
42
- if (ctorExisting !== void 0) appendUniqueMethod(ctorExisting, "postConstruct", methodName);
43
- else lifecycleByConstructorMetadataMap.set(ctor, {
44
- postConstruct: [methodName],
45
- preDestroy: []
46
- });
47
- });
48
- try {
49
- const meta = context.metadata;
50
- if (meta !== null && typeof meta === "object") {
51
- if (!meta[LIFECYCLE_KEY]) meta[LIFECYCLE_KEY] = {
52
- postConstruct: [],
53
- preDestroy: []
54
- };
55
- const lifecycle = meta[LIFECYCLE_KEY];
56
- appendUniqueMethod(lifecycle, "postConstruct", methodName);
57
- }
58
- } catch {}
18
+ };
19
+ appendUniqueMethod(meta[LIFECYCLE_KEY], "postConstruct", methodName);
59
20
  };
60
21
  }
61
22
  /**
@@ -65,34 +26,12 @@ function preDestroy() {
65
26
  return function(target, context) {
66
27
  if (context.static === true) throw new InternalError("@preDestroy() applies to instance methods only; static methods are not invoked during instance teardown.");
67
28
  const methodName = String(context.name);
68
- registerByConstructor(target, "preDestroy", methodName);
69
- const existing = lifecycleMetadataMap.get(context.metadata);
70
- if (existing !== void 0) appendUniqueMethod(existing, "preDestroy", methodName);
71
- else lifecycleMetadataMap.set(context.metadata, {
29
+ const meta = context.metadata;
30
+ if (!meta[LIFECYCLE_KEY]) meta[LIFECYCLE_KEY] = {
72
31
  postConstruct: [],
73
- preDestroy: [methodName]
74
- });
75
- context.addInitializer(function() {
76
- const targetOrInstance = this;
77
- const ctor = typeof targetOrInstance === "function" ? targetOrInstance : targetOrInstance.constructor;
78
- const ctorExisting = lifecycleByConstructorMetadataMap.get(ctor);
79
- if (ctorExisting !== void 0) appendUniqueMethod(ctorExisting, "preDestroy", methodName);
80
- else lifecycleByConstructorMetadataMap.set(ctor, {
81
- postConstruct: [],
82
- preDestroy: [methodName]
83
- });
84
- });
85
- try {
86
- const meta = context.metadata;
87
- if (meta !== null && typeof meta === "object") {
88
- if (!meta[LIFECYCLE_KEY]) meta[LIFECYCLE_KEY] = {
89
- postConstruct: [],
90
- preDestroy: []
91
- };
92
- const lifecycle = meta[LIFECYCLE_KEY];
93
- appendUniqueMethod(lifecycle, "preDestroy", methodName);
94
- }
95
- } catch {}
32
+ preDestroy: []
33
+ };
34
+ appendUniqueMethod(meta[LIFECYCLE_KEY], "preDestroy", methodName);
96
35
  };
97
36
  }
98
37
  //#endregion
@@ -20,15 +20,17 @@ function buildDependencyGraph(registry, metadataReader, options, parentRegistry)
20
20
  });
21
21
  if (binding.kind === "class") {
22
22
  const meta = metadataReader.getConstructorMetadata(binding.target);
23
- if (meta !== void 0) meta.params.forEach((param, index) => {
23
+ if (meta !== void 0) for (let index = 0; index < meta.params.length; index += 1) {
24
+ const param = meta.params[index];
24
25
  const dependencyBinding = sourceRegistry.getAll(param.token)[0];
25
26
  if (dependencyBinding !== void 0) edges.push({
26
27
  from: binding.id,
27
28
  to: dependencyBinding.id,
28
29
  label: `[${index}]`
29
30
  });
30
- });
31
- } else if (binding.kind === "resolved" || binding.kind === "resolved-async") binding.deps.forEach((dependency, index) => {
31
+ }
32
+ } else if (binding.kind === "resolved" || binding.kind === "resolved-async") for (let index = 0; index < binding.deps.length; index += 1) {
33
+ const dependency = binding.deps[index];
32
34
  const dependencyBindings = sourceRegistry.getAll(dependency.token);
33
35
  if (dependencyBindings.length > 0 && dependencyBindings[0] !== void 0) {
34
36
  const label = dependency.name !== void 0 ? `name:${dependency.name}` : dependency.tags !== void 0 && dependency.tags.length > 0 ? `tag:${dependency.tags[0]?.[0]}=${String(dependency.tags[0]?.[1])}` : `[${index}]`;
@@ -38,7 +40,7 @@ function buildDependencyGraph(registry, metadataReader, options, parentRegistry)
38
40
  label
39
41
  });
40
42
  }
41
- });
43
+ }
42
44
  else if (binding.kind === "alias") {
43
45
  const targetBindings = sourceRegistry.getAll(binding.target);
44
46
  if (targetBindings.length > 0 && targetBindings[0] !== void 0) edges.push({
@@ -5,29 +5,29 @@ import { ContainerGraphJson } from "../dependency-graph.mjs";
5
5
  * @since 0.3.16-canary.0
6
6
  */
7
7
  interface CytoscapeNode {
8
- data: {
9
- id: string;
10
- label: string;
11
- kind: string;
12
- scope: string;
13
- fromParent: boolean;
8
+ readonly data: {
9
+ readonly id: string;
10
+ readonly label: string;
11
+ readonly kind: string;
12
+ readonly scope: string;
13
+ readonly fromParent: boolean;
14
14
  };
15
15
  }
16
16
  /**
17
17
  * @since 0.3.16-canary.0
18
18
  */
19
19
  interface CytoscapeEdge {
20
- data: {
21
- id: string;
22
- source: string;
23
- target: string;
24
- label?: string;
20
+ readonly data: {
21
+ readonly id: string;
22
+ readonly source: string;
23
+ readonly target: string;
24
+ readonly label?: string;
25
25
  };
26
26
  }
27
27
  /**
28
28
  * @since 0.3.16-canary.0
29
29
  */
30
- type CytoscapeElements = Array<CytoscapeNode | CytoscapeEdge>;
30
+ type CytoscapeElements = ReadonlyArray<CytoscapeNode | CytoscapeEdge>;
31
31
  /**
32
32
  * @since 0.3.16-canary.0
33
33
  */
@@ -11,15 +11,15 @@ function toCytoscapeGraph(graph) {
11
11
  scope: node.scope,
12
12
  fromParent: node.fromParent
13
13
  } });
14
- graph.edges.forEach((edge, idx) => {
15
- const data = {
14
+ for (let idx = 0; idx < graph.edges.length; idx += 1) {
15
+ const edge = graph.edges[idx];
16
+ elements.push({ data: {
16
17
  id: `edge-${idx}`,
17
18
  source: edge.from,
18
- target: edge.to
19
- };
20
- if (edge.label !== void 0) data.label = edge.label;
21
- elements.push({ data });
22
- });
19
+ target: edge.to,
20
+ ...edge.label !== void 0 ? { label: edge.label } : {}
21
+ } });
22
+ }
23
23
  return elements;
24
24
  }
25
25
  //#endregion
@@ -5,33 +5,33 @@ import { ContainerGraphJson } from "../dependency-graph.mjs";
5
5
  * @since 0.3.16-canary.0
6
6
  */
7
7
  interface ReactFlowNode {
8
- id: string;
9
- data: {
10
- label: string;
11
- kind: string;
12
- scope: string;
13
- fromParent: boolean;
8
+ readonly id: string;
9
+ readonly data: {
10
+ readonly label: string;
11
+ readonly kind: string;
12
+ readonly scope: string;
13
+ readonly fromParent: boolean;
14
14
  };
15
- position: {
16
- x: number;
17
- y: number;
15
+ readonly position: {
16
+ readonly x: number;
17
+ readonly y: number;
18
18
  };
19
19
  }
20
20
  /**
21
21
  * @since 0.3.16-canary.0
22
22
  */
23
23
  interface ReactFlowEdge {
24
- id: string;
25
- source: string;
26
- target: string;
27
- label?: string;
24
+ readonly id: string;
25
+ readonly source: string;
26
+ readonly target: string;
27
+ readonly label?: string;
28
28
  }
29
29
  /**
30
30
  * @since 0.3.16-canary.0
31
31
  */
32
32
  interface ReactFlowGraph {
33
- nodes: Array<ReactFlowNode>;
34
- edges: Array<ReactFlowEdge>;
33
+ readonly nodes: ReadonlyArray<ReactFlowNode>;
34
+ readonly edges: ReadonlyArray<ReactFlowEdge>;
35
35
  }
36
36
  /**
37
37
  * @since 0.3.16-canary.0
@@ -17,15 +17,12 @@ function toReactFlowGraph(graph) {
17
17
  y: Math.floor(idx / 5) * 100
18
18
  }
19
19
  })),
20
- edges: graph.edges.map((edge, idx) => {
21
- const reactFlowEdge = {
22
- id: `edge-${idx}`,
23
- source: edge.from,
24
- target: edge.to
25
- };
26
- if (edge.label !== void 0) reactFlowEdge.label = edge.label;
27
- return reactFlowEdge;
28
- })
20
+ edges: graph.edges.map((edge, idx) => ({
21
+ id: `edge-${idx}`,
22
+ source: edge.from,
23
+ target: edge.to,
24
+ ...edge.label !== void 0 ? { label: edge.label } : {}
25
+ }))
29
26
  };
30
27
  }
31
28
  //#endregion
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Constructor } from "./constructor-type.mjs";
2
2
  import { Token, isToken, token, tokenName } from "./token.mjs";
3
- import { ActivationHandler, BindingIdentifier, BindingKind, BindingScope, ConstraintContext, DeactivationHandler, DependencyKey, ResolutionContext, ResolutionFrame, ResolveOptions, TokenValue } from "./types.mjs";
3
+ import { ActivationHandler, BindingIdentifier, BindingKind, BindingScope, BindingTag, ConstraintContext, DeactivationHandler, DependencyKey, ResolutionContext, ResolutionFrame, ResolveOptions, TokenValue } from "./types.mjs";
4
4
  import { InjectOptions, InjectableDependency, InjectionDescriptor, inject, injectAll, isInjectionDescriptor, optional } from "./decorators/inject.mjs";
5
- import { AliasBindingBuilder, BindToBuilder, BindingBuilder, ConstantBindingBuilder, ScopedBindingBuilder, SingletonBindingBuilder, SingletonLifecycleBuilder, TransientBindingBuilder } from "./binding.mjs";
5
+ import { AliasBindingBuilder, BindToBuilder, BindingBuilder, ConstantBindingBuilder, ScopedBindingBuilder, SingletonBindingBuilder, SingletonLifecycleBuilder, SlotConstrainedBuilder, TransientBindingBuilder } from "./binding.mjs";
6
6
  import { effectiveBindingScope } from "./binding-scope.mjs";
7
7
  import { whenAnyAncestorIs, whenAnyAncestorNamed, whenAnyAncestorTagged, whenAnyAncestorTaggedAll, whenNoAncestorIs, whenNoParentIs, whenParentIs, whenParentNamed, whenParentTagged, whenParentTaggedAll } from "./constraints.mjs";
8
8
  import { AsyncModule, AsyncModuleBuilder, Module, ModuleBuilder, SyncModule, isSyncModule } from "./module.mjs";
@@ -15,4 +15,4 @@ import { postConstruct, preDestroy } from "./decorators/lifecycle-decorators.mjs
15
15
  import { AmbiguousBindingError, AsyncActivationError, AsyncDeactivationError, AsyncModuleLoadError, AsyncResolutionError, CircularDependencyError, DiError, DisposedContainerError, InternalError, MissingContainerContextError, MissingMetadataError, MissingScopeContextError, NoMatchingBindingError, RebindUnboundTokenError, ScopeViolationDetails, ScopeViolationError, SyncDisposalNotSupportedError, TokenNotBoundError } from "./errors.mjs";
16
16
  import { bindingSlotToResolveOptions, injectionSlotToResolveOptions } from "./resolve-options.mjs";
17
17
  import { MetadataReaderToken } from "./metadata/metadata-reader-token.mjs";
18
- export { type ActivationHandler, type AliasBindingBuilder, AmbiguousBindingError, AsyncActivationError, AsyncDeactivationError, AsyncModule, type AsyncModuleBuilder, AsyncModuleLoadError, AsyncResolutionError, type AutoRegisterRegistry, type BindToBuilder, type BindingBuilder, type BindingIdentifier, type BindingKind, type BindingScope, type BindingSnapshot, CircularDependencyError, type ConstantBindingBuilder, type ConstraintContext, type Constructor, Container, type ContainerGraphJson, type Container as ContainerInterface, type ContainerSnapshot, type ContainerStatic, type DeactivationHandler, type DependencyKey, DiError, DisposedContainerError, type GraphEdge, type GraphNode, type GraphOptions, type InjectOptions, type InjectableDependency, type InjectableOptions, type InjectionDescriptor, InternalError, type MetadataReader, MetadataReaderToken, MissingContainerContextError, MissingMetadataError, MissingScopeContextError, Module, type ModuleBuilder, type MutableLifecycleMetadata, NoMatchingBindingError, RebindUnboundTokenError, type ResolutionContext, type ResolutionFrame, type ResolveOptions, type ScopeViolationDetails, ScopeViolationError, type ScopedBindingBuilder, type SingletonBindingBuilder, type SingletonLifecycleBuilder, SyncDisposalNotSupportedError, SyncModule, type Token, TokenNotBoundError, type TokenValue, type TransientBindingBuilder, bindingSlotToResolveOptions, createAutoRegisterRegistry, effectiveBindingScope, inject, injectAll, injectable, injectionSlotToResolveOptions, isInjectionDescriptor, isSyncModule, isToken, optional, postConstruct, preDestroy, token, tokenName, whenAnyAncestorIs, whenAnyAncestorNamed, whenAnyAncestorTagged, whenAnyAncestorTaggedAll, whenNoAncestorIs, whenNoParentIs, whenParentIs, whenParentNamed, whenParentTagged, whenParentTaggedAll };
18
+ export { type ActivationHandler, type AliasBindingBuilder, AmbiguousBindingError, AsyncActivationError, AsyncDeactivationError, AsyncModule, type AsyncModuleBuilder, AsyncModuleLoadError, AsyncResolutionError, type AutoRegisterRegistry, type BindToBuilder, type BindingBuilder, type BindingIdentifier, type BindingKind, type BindingScope, type BindingSnapshot, type BindingTag, CircularDependencyError, type ConstantBindingBuilder, type ConstraintContext, type Constructor, Container, type ContainerGraphJson, type Container as ContainerInterface, type ContainerSnapshot, type ContainerStatic, type DeactivationHandler, type DependencyKey, DiError, DisposedContainerError, type GraphEdge, type GraphNode, type GraphOptions, type InjectOptions, type InjectableDependency, type InjectableOptions, type InjectionDescriptor, InternalError, type MetadataReader, MetadataReaderToken, MissingContainerContextError, MissingMetadataError, MissingScopeContextError, Module, type ModuleBuilder, type MutableLifecycleMetadata, NoMatchingBindingError, RebindUnboundTokenError, type ResolutionContext, type ResolutionFrame, type ResolveOptions, type ScopeViolationDetails, ScopeViolationError, type ScopedBindingBuilder, type SingletonBindingBuilder, type SingletonLifecycleBuilder, type SlotConstrainedBuilder, SyncDisposalNotSupportedError, SyncModule, type Token, TokenNotBoundError, type TokenValue, type TransientBindingBuilder, bindingSlotToResolveOptions, createAutoRegisterRegistry, effectiveBindingScope, inject, injectAll, injectable, injectionSlotToResolveOptions, isInjectionDescriptor, isSyncModule, isToken, optional, postConstruct, preDestroy, token, tokenName, whenAnyAncestorIs, whenAnyAncestorNamed, whenAnyAncestorTagged, whenAnyAncestorTaggedAll, whenNoAncestorIs, whenNoParentIs, whenParentIs, whenParentNamed, whenParentTagged, whenParentTaggedAll };
@@ -1,6 +1,6 @@
1
1
  import { Constructor } from "./constructor-type.mjs";
2
2
  import { Token } from "./token.mjs";
3
- import { BindingIdentifier, BindingKind, BindingScope, ResolveOptions } from "./types.mjs";
3
+ import { BindingIdentifier, BindingKind, BindingScope, BindingTag, ResolveOptions } from "./types.mjs";
4
4
  import { BindingRegistry } from "./registry.mjs";
5
5
  import { ScopeManager } from "./scope.mjs";
6
6
 
@@ -14,7 +14,7 @@ interface BindingSnapshot {
14
14
  readonly scope: BindingScope;
15
15
  readonly slot: {
16
16
  readonly name?: string;
17
- readonly tags: ReadonlyArray<readonly [string, unknown]>;
17
+ readonly tags: ReadonlyArray<BindingTag>;
18
18
  };
19
19
  readonly id: BindingIdentifier;
20
20
  }
@@ -40,6 +40,7 @@ declare class Inspector {
40
40
  lookupBindings<Value>(token: Token<Value> | Constructor<Value>): ReadonlyArray<BindingSnapshot>;
41
41
  has(token: Token<unknown> | Constructor, hint?: ResolveOptions, parentHas?: () => boolean): boolean;
42
42
  hasOwn(token: Token<unknown> | Constructor, hint?: ResolveOptions): boolean;
43
+ private _makeHintContext;
43
44
  private allBindingSnapshots;
44
45
  private _toSnapshot;
45
46
  }
@@ -30,27 +30,24 @@ var Inspector = class {
30
30
  has(token, hint, parentHas) {
31
31
  const bindings = this._registry.getAll(token);
32
32
  if (bindings.length > 0) if (hint !== void 0) {
33
- if (selectBinding(bindings, hint, {
34
- resolutionPath: [],
35
- resolutionStack: [],
36
- parent: void 0,
37
- ancestors: [],
38
- currentResolveHint: hint
39
- }, tokenName(token)) !== void 0) return true;
33
+ if (selectBinding(bindings, hint, this._makeHintContext(hint), tokenName(token)) !== void 0) return true;
40
34
  } else return true;
41
35
  return parentHas?.() ?? false;
42
36
  }
43
37
  hasOwn(token, hint) {
44
38
  const bindings = this._registry.getAll(token);
45
39
  if (bindings.length === 0) return false;
46
- if (hint !== void 0) return selectBinding(bindings, hint, {
40
+ if (hint !== void 0) return selectBinding(bindings, hint, this._makeHintContext(hint), tokenName(token)) !== void 0;
41
+ return true;
42
+ }
43
+ _makeHintContext(hint) {
44
+ return {
47
45
  resolutionPath: [],
48
46
  resolutionStack: [],
49
47
  parent: void 0,
50
48
  ancestors: [],
51
49
  currentResolveHint: hint
52
- }, tokenName(token)) !== void 0;
53
- return true;
50
+ };
54
51
  }
55
52
  allBindingSnapshots() {
56
53
  return this._registry.allBindings().map((binding) => this._toSnapshot(binding));
@@ -10,12 +10,7 @@ var LifecycleManager = class {
10
10
  _activationVersion = 0;
11
11
  registerActivation(token, handler) {
12
12
  this._activationVersion += 1;
13
- let list = this._activationHooks.get(token);
14
- if (list === void 0) {
15
- list = [];
16
- this._activationHooks.set(token, list);
17
- }
18
- list.push(handler);
13
+ this._activationHooks.getOrInsert(token, []).push(handler);
19
14
  }
20
15
  hasActivationHandlers(token) {
21
16
  if (this._activationHooks.size === 0) return false;
@@ -26,12 +21,7 @@ var LifecycleManager = class {
26
21
  return this._activationVersion;
27
22
  }
28
23
  registerDeactivation(token, handler) {
29
- let list = this._deactivationHooks.get(token);
30
- if (list === void 0) {
31
- list = [];
32
- this._deactivationHooks.set(token, list);
33
- }
34
- list.push(handler);
24
+ this._deactivationHooks.getOrInsert(token, []).push(handler);
35
25
  }
36
26
  async runActivation(resolutionContext, binding, instance, metadataReader) {
37
27
  let activatedInstance = instance;
@@ -1,16 +1,4 @@
1
- import { ConstructorMetadata, MutableLifecycleMetadata } from "./metadata-types.mjs";
2
-
3
1
  //#region src/metadata/metadata-keys.d.ts
4
- /**
5
- * Accessor injection entries mirrored from `Symbol.metadata` for toolchains where
6
- * resolver reads stable metadata via the same object identity as `context.metadata`.
7
- *
8
- * @since 0.3.16-canary.0
9
- */
10
- type AccessorInjectionEntryList = Array<{
11
- key: string | symbol;
12
- descriptor: unknown;
13
- }>;
14
2
  /**
15
3
  * @since 0.3.16-canary.0
16
4
  */
@@ -24,29 +12,16 @@ declare const LIFECYCLE_KEY: unique symbol;
24
12
  */
25
13
  declare const INJECT_ACCESSOR_KEY: unique symbol;
26
14
  /**
27
- * @since 0.3.16-canary.0
28
- */
29
- declare const constructorMetadataMap: WeakMap<object, ConstructorMetadata>;
30
- /**
31
- * @since 0.3.16-canary.0
32
- */
33
- declare const lifecycleMetadataMap: WeakMap<object, MutableLifecycleMetadata>;
34
- /**
35
- * @since 0.3.16-canary.0
36
- */
37
- declare const lifecycleByConstructorMetadataMap: WeakMap<object, MutableLifecycleMetadata>;
38
- /**
39
- * Fallback keyed by the class metadata object (`context.metadata` / `ctor[Symbol.metadata]`).
15
+ * The well-known symbol used by TC39 Stage 3 decorator transforms to store class metadata.
40
16
  *
41
- * @since 0.3.16-canary.0
42
- */
43
- declare const accessorMetadataByMetadataObjectMap: WeakMap<object, AccessorInjectionEntryList>;
44
- /**
45
- * Populated from `@injectable()` after field decorators have written `INJECT_ACCESSOR_KEY`
46
- * onto `context.metadata` — same timing as {@link constructorMetadataMap}.
17
+ * `Symbol.metadata` is defined natively once the runtime ships the full TC39 decorator
18
+ * proposal. Until then (current Node.js / browsers), Babel and esbuild both fall back to
19
+ * `Symbol.for("Symbol.metadata")` — a global-registry symbol with the same string key.
20
+ * Resolving it here once keeps the reader and the decorator transforms in sync regardless
21
+ * of which path is taken.
47
22
  *
48
23
  * @since 0.3.16-canary.0
49
24
  */
50
- declare const accessorMetadataByConstructorMap: WeakMap<object, AccessorInjectionEntryList>;
25
+ declare const METADATA_SYMBOL: symbol;
51
26
  //#endregion
52
- export { AccessorInjectionEntryList, INJECTABLE_KEY, INJECT_ACCESSOR_KEY, LIFECYCLE_KEY, accessorMetadataByConstructorMap, accessorMetadataByMetadataObjectMap, constructorMetadataMap, lifecycleByConstructorMetadataMap, lifecycleMetadataMap };
27
+ export { INJECTABLE_KEY, INJECT_ACCESSOR_KEY, LIFECYCLE_KEY, METADATA_SYMBOL };
@@ -12,29 +12,16 @@ const LIFECYCLE_KEY = Symbol("di:lifecycle");
12
12
  */
13
13
  const INJECT_ACCESSOR_KEY = Symbol("di:inject-accessor");
14
14
  /**
15
- * @since 0.3.16-canary.0
16
- */
17
- const constructorMetadataMap = /* @__PURE__ */ new WeakMap();
18
- /**
19
- * @since 0.3.16-canary.0
20
- */
21
- const lifecycleMetadataMap = /* @__PURE__ */ new WeakMap();
22
- /**
23
- * @since 0.3.16-canary.0
24
- */
25
- const lifecycleByConstructorMetadataMap = /* @__PURE__ */ new WeakMap();
26
- /**
27
- * Fallback keyed by the class metadata object (`context.metadata` / `ctor[Symbol.metadata]`).
15
+ * The well-known symbol used by TC39 Stage 3 decorator transforms to store class metadata.
28
16
  *
29
- * @since 0.3.16-canary.0
30
- */
31
- const accessorMetadataByMetadataObjectMap = /* @__PURE__ */ new WeakMap();
32
- /**
33
- * Populated from `@injectable()` after field decorators have written `INJECT_ACCESSOR_KEY`
34
- * onto `context.metadata` — same timing as {@link constructorMetadataMap}.
17
+ * `Symbol.metadata` is defined natively once the runtime ships the full TC39 decorator
18
+ * proposal. Until then (current Node.js / browsers), Babel and esbuild both fall back to
19
+ * `Symbol.for("Symbol.metadata")` — a global-registry symbol with the same string key.
20
+ * Resolving it here once keeps the reader and the decorator transforms in sync regardless
21
+ * of which path is taken.
35
22
  *
36
23
  * @since 0.3.16-canary.0
37
24
  */
38
- const accessorMetadataByConstructorMap = /* @__PURE__ */ new WeakMap();
25
+ const METADATA_SYMBOL = Symbol.metadata ?? Symbol.for("Symbol.metadata");
39
26
  //#endregion
40
- export { INJECTABLE_KEY, INJECT_ACCESSOR_KEY, LIFECYCLE_KEY, accessorMetadataByConstructorMap, accessorMetadataByMetadataObjectMap, constructorMetadataMap, lifecycleByConstructorMetadataMap, lifecycleMetadataMap };
27
+ export { INJECTABLE_KEY, INJECT_ACCESSOR_KEY, LIFECYCLE_KEY, METADATA_SYMBOL };
@@ -1,5 +1,6 @@
1
1
  import { Constructor } from "../constructor-type.mjs";
2
2
  import { Token } from "../token.mjs";
3
+ import { InjectionDescriptor } from "../decorators/inject.mjs";
3
4
 
4
5
  //#region src/metadata/metadata-types.d.ts
5
6
  /**
@@ -41,6 +42,10 @@ interface MutableLifecycleMetadata {
41
42
  interface MetadataReader {
42
43
  getConstructorMetadata(target: Constructor): ConstructorMetadata | undefined;
43
44
  getLifecycleMetadata(target: Constructor): LifecycleMetadata | undefined;
45
+ getAccessorMetadata?(target: Constructor): ReadonlyArray<{
46
+ readonly key: string | symbol;
47
+ readonly descriptor: InjectionDescriptor;
48
+ }> | undefined;
44
49
  }
45
50
  //#endregion
46
51
  export { ConstructorMetadata, LifecycleMetadata, MetadataReader, MutableLifecycleMetadata, ParamMetadata };
@@ -7,6 +7,7 @@ import { ConstructorMetadata, LifecycleMetadata, MetadataReader } from "./metada
7
7
  * @since 0.3.16-canary.0
8
8
  */
9
9
  declare class SymbolMetadataReader implements MetadataReader {
10
+ private _getMetadataRecord;
10
11
  getConstructorMetadata(target: Constructor): ConstructorMetadata | undefined;
11
12
  getLifecycleMetadata(target: Constructor): LifecycleMetadata | undefined;
12
13
  getAccessorMetadata(target: Constructor): Array<{
@@ -1,46 +1,24 @@
1
- import { INJECTABLE_KEY, INJECT_ACCESSOR_KEY, LIFECYCLE_KEY, accessorMetadataByConstructorMap, accessorMetadataByMetadataObjectMap, constructorMetadataMap, lifecycleByConstructorMetadataMap, lifecycleMetadataMap } from "./metadata-keys.mjs";
1
+ import { INJECTABLE_KEY, INJECT_ACCESSOR_KEY, LIFECYCLE_KEY, METADATA_SYMBOL } from "./metadata-keys.mjs";
2
2
  //#region src/metadata/symbol-metadata-reader.ts
3
3
  /**
4
4
  * @since 0.3.16-canary.0
5
5
  */
6
6
  var SymbolMetadataReader = class {
7
+ _getMetadataRecord(target, key) {
8
+ const descriptor = Object.getOwnPropertyDescriptor(target, METADATA_SYMBOL);
9
+ if (descriptor === void 0) return;
10
+ const record = descriptor.value;
11
+ if (!record || typeof record !== "object" || !Object.hasOwn(record, key)) return;
12
+ return record;
13
+ }
7
14
  getConstructorMetadata(target) {
8
- const weakMapMetadata = constructorMetadataMap.get(target);
9
- if (weakMapMetadata !== void 0) return weakMapMetadata;
10
- const metadataDescriptor = Object.getOwnPropertyDescriptor(target, Symbol.metadata);
11
- if (metadataDescriptor === void 0) return;
12
- const metadataRecord = metadataDescriptor.value;
13
- if (!metadataRecord || typeof metadataRecord !== "object" || !Object.hasOwn(metadataRecord, INJECTABLE_KEY)) return;
14
- return metadataRecord[INJECTABLE_KEY];
15
+ return this._getMetadataRecord(target, INJECTABLE_KEY)?.[INJECTABLE_KEY];
15
16
  }
16
17
  getLifecycleMetadata(target) {
17
- const lifecycleMetadataByConstructor = lifecycleByConstructorMetadataMap.get(target);
18
- if (lifecycleMetadataByConstructor !== void 0) return lifecycleMetadataByConstructor;
19
- const metadataDescriptor = Object.getOwnPropertyDescriptor(target, Symbol.metadata);
20
- if (metadataDescriptor !== void 0) {
21
- const metadataRecord = metadataDescriptor.value;
22
- if (metadataRecord && typeof metadataRecord === "object" && Object.hasOwn(metadataRecord, LIFECYCLE_KEY)) return metadataRecord[LIFECYCLE_KEY];
23
- }
24
- const classMetadataObject = target[Symbol.metadata];
25
- if (classMetadataObject !== void 0) {
26
- const weakMapMetadata = lifecycleMetadataMap.get(classMetadataObject);
27
- if (weakMapMetadata !== void 0) return weakMapMetadata;
28
- }
18
+ return this._getMetadataRecord(target, LIFECYCLE_KEY)?.[LIFECYCLE_KEY];
29
19
  }
30
20
  getAccessorMetadata(target) {
31
- const byConstructor = accessorMetadataByConstructorMap.get(target);
32
- if (byConstructor !== void 0) return byConstructor;
33
- const metadataObject = target[Symbol.metadata];
34
- if (metadataObject !== void 0) {
35
- const fromWeakMap = accessorMetadataByMetadataObjectMap.get(metadataObject);
36
- if (fromWeakMap !== void 0) return fromWeakMap;
37
- }
38
- const metadataDescriptor = Object.getOwnPropertyDescriptor(target, Symbol.metadata);
39
- if (metadataDescriptor === void 0) return;
40
- const metadataRecord = metadataDescriptor.value;
41
- if (!metadataRecord || typeof metadataRecord !== "object") return;
42
- if (!Object.hasOwn(metadataRecord, INJECT_ACCESSOR_KEY)) return;
43
- return metadataRecord[INJECT_ACCESSOR_KEY];
21
+ return this._getMetadataRecord(target, INJECT_ACCESSOR_KEY)?.[INJECT_ACCESSOR_KEY];
44
22
  }
45
23
  };
46
24
  /**
package/dist/registry.mjs CHANGED
@@ -12,11 +12,7 @@ var BindingRegistry = class {
12
12
  /** Add or replace binding using slot-aware last-wins. */
13
13
  add(binding) {
14
14
  const key = binding.token;
15
- let bindingsForToken = this._bindings.get(key);
16
- if (bindingsForToken === void 0) {
17
- bindingsForToken = [];
18
- this._bindings.set(key, bindingsForToken);
19
- }
15
+ const bindingsForToken = this._bindings.getOrInsert(key, []);
20
16
  if (!this._isPurePredicateBinding(binding)) {
21
17
  const existingIndex = bindingsForToken.findIndex((candidate) => !this._isPurePredicateBinding(candidate) && bindingSlotEquals(candidate.slot, binding.slot));
22
18
  if (existingIndex !== -1) {
@@ -110,17 +106,7 @@ var BindingRegistry = class {
110
106
  const slot = binding.slot;
111
107
  if (slot.name !== void 0 || slot.tags.length !== 1 || binding.predicate !== void 0) return;
112
108
  const [tagKey, tagValue] = slot.tags[0];
113
- let byTagKey = this._simpleTagged.get(tokenKey);
114
- if (byTagKey === void 0) {
115
- byTagKey = /* @__PURE__ */ new Map();
116
- this._simpleTagged.set(tokenKey, byTagKey);
117
- }
118
- let byTagValue = byTagKey.get(tagKey);
119
- if (byTagValue === void 0) {
120
- byTagValue = /* @__PURE__ */ new Map();
121
- byTagKey.set(tagKey, byTagValue);
122
- }
123
- byTagValue.set(tagValue, binding);
109
+ this._simpleTagged.getOrInsert(tokenKey, /* @__PURE__ */ new Map()).getOrInsert(tagKey, /* @__PURE__ */ new Map()).set(tagValue, binding);
124
110
  }
125
111
  _deindexSimpleTaggedBinding(tokenKey, binding) {
126
112
  const slot = binding.slot;
@@ -147,12 +133,7 @@ var BindingRegistry = class {
147
133
  _indexSimpleNamedBinding(tokenKey, binding) {
148
134
  const slot = binding.slot;
149
135
  if (slot.name === void 0 || slot.tags.length > 0) return;
150
- let bindingsByName = this._simpleNamed.get(tokenKey);
151
- if (bindingsByName === void 0) {
152
- bindingsByName = /* @__PURE__ */ new Map();
153
- this._simpleNamed.set(tokenKey, bindingsByName);
154
- }
155
- bindingsByName.set(slot.name, binding);
136
+ this._simpleNamed.getOrInsert(tokenKey, /* @__PURE__ */ new Map()).set(slot.name, binding);
156
137
  }
157
138
  _deindexSimpleNamedBinding(tokenKey, binding) {
158
139
  const slot = binding.slot;
@@ -1,4 +1,4 @@
1
- import { ResolveOptions } from "./types.mjs";
1
+ import { BindingTag, ResolveOptions } from "./types.mjs";
2
2
  import { BindingSlot } from "./binding.mjs";
3
3
 
4
4
  //#region src/resolve-options.d.ts
@@ -10,7 +10,7 @@ import { BindingSlot } from "./binding.mjs";
10
10
  */
11
11
  declare function injectionSlotToResolveOptions(injectionSlot: {
12
12
  readonly name?: string;
13
- readonly tags?: ReadonlyArray<readonly [string, unknown]>;
13
+ readonly tags?: ReadonlyArray<BindingTag>;
14
14
  }): ResolveOptions | undefined;
15
15
  /**
16
16
  * Hint from a binding {@link BindingSlot} (tags may be empty; omits when nothing to match).