@codefast/di 0.6.2 → 0.7.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 (149) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +3 -4
  3. package/dist/ambient/active-container.d.ts +4 -0
  4. package/dist/ambient/active-container.d.ts.map +1 -1
  5. package/dist/ambient/active-container.js +4 -0
  6. package/dist/ambient/active-container.js.map +1 -1
  7. package/dist/container/container.d.ts +6 -0
  8. package/dist/container/container.d.ts.map +1 -1
  9. package/dist/container/container.js +5 -1
  10. package/dist/container/container.js.map +1 -1
  11. package/dist/core/map-upsert.d.ts +29 -0
  12. package/dist/core/map-upsert.d.ts.map +1 -0
  13. package/dist/core/map-upsert.js +44 -0
  14. package/dist/core/map-upsert.js.map +1 -0
  15. package/dist/core/module.d.ts +16 -0
  16. package/dist/core/module.d.ts.map +1 -1
  17. package/dist/core/module.js +8 -0
  18. package/dist/core/module.js.map +1 -1
  19. package/dist/core/registry.d.ts +2 -0
  20. package/dist/core/registry.d.ts.map +1 -1
  21. package/dist/core/registry.js +10 -4
  22. package/dist/core/registry.js.map +1 -1
  23. package/dist/core/token.d.ts +6 -0
  24. package/dist/core/token.d.ts.map +1 -1
  25. package/dist/core/token.js +4 -0
  26. package/dist/core/token.js.map +1 -1
  27. package/dist/core/types.d.ts +20 -0
  28. package/dist/core/types.d.ts.map +1 -1
  29. package/dist/decorators/inject.d.ts +2 -0
  30. package/dist/decorators/inject.d.ts.map +1 -1
  31. package/dist/decorators/inject.js +2 -0
  32. package/dist/decorators/inject.js.map +1 -1
  33. package/dist/decorators/injectable.d.ts +6 -0
  34. package/dist/decorators/injectable.d.ts.map +1 -1
  35. package/dist/decorators/injectable.js +4 -0
  36. package/dist/decorators/injectable.js.map +1 -1
  37. package/dist/decorators/lifecycle-decorators.d.ts +4 -0
  38. package/dist/decorators/lifecycle-decorators.d.ts.map +1 -1
  39. package/dist/decorators/lifecycle-decorators.js +4 -0
  40. package/dist/decorators/lifecycle-decorators.js.map +1 -1
  41. package/dist/errors/errors.d.ts +34 -0
  42. package/dist/errors/errors.d.ts.map +1 -1
  43. package/dist/errors/errors.js +32 -0
  44. package/dist/errors/errors.js.map +1 -1
  45. package/dist/injection/descriptor.d.ts +12 -0
  46. package/dist/injection/descriptor.d.ts.map +1 -1
  47. package/dist/injection/descriptor.js +8 -0
  48. package/dist/injection/descriptor.js.map +1 -1
  49. package/dist/introspection/dependency-graph.d.ts +6 -0
  50. package/dist/introspection/dependency-graph.d.ts.map +1 -1
  51. package/dist/introspection/dependency-graph.js +2 -0
  52. package/dist/introspection/dependency-graph.js.map +1 -1
  53. package/dist/introspection/graph-adapters/cytoscape.d.ts +8 -0
  54. package/dist/introspection/graph-adapters/cytoscape.d.ts.map +1 -1
  55. package/dist/introspection/graph-adapters/cytoscape.js +2 -0
  56. package/dist/introspection/graph-adapters/cytoscape.js.map +1 -1
  57. package/dist/introspection/graph-adapters/dot.d.ts +2 -0
  58. package/dist/introspection/graph-adapters/dot.d.ts.map +1 -1
  59. package/dist/introspection/graph-adapters/dot.js +2 -0
  60. package/dist/introspection/graph-adapters/dot.js.map +1 -1
  61. package/dist/introspection/graph-adapters/reactflow.d.ts +8 -0
  62. package/dist/introspection/graph-adapters/reactflow.d.ts.map +1 -1
  63. package/dist/introspection/graph-adapters/reactflow.js +2 -0
  64. package/dist/introspection/graph-adapters/reactflow.js.map +1 -1
  65. package/dist/introspection/inspector.d.ts +6 -0
  66. package/dist/introspection/inspector.d.ts.map +1 -1
  67. package/dist/introspection/inspector.js +2 -0
  68. package/dist/introspection/inspector.js.map +1 -1
  69. package/dist/lifecycle/lifecycle-manager.d.ts +2 -0
  70. package/dist/lifecycle/lifecycle-manager.d.ts.map +1 -1
  71. package/dist/lifecycle/lifecycle-manager.js +7 -2
  72. package/dist/lifecycle/lifecycle-manager.js.map +1 -1
  73. package/dist/lifecycle/scope-manager.d.ts +2 -0
  74. package/dist/lifecycle/scope-manager.d.ts.map +1 -1
  75. package/dist/lifecycle/scope-manager.js +2 -0
  76. package/dist/lifecycle/scope-manager.js.map +1 -1
  77. package/dist/metadata/metadata-keys.d.ts +6 -0
  78. package/dist/metadata/metadata-keys.d.ts.map +1 -1
  79. package/dist/metadata/metadata-keys.js +6 -0
  80. package/dist/metadata/metadata-keys.js.map +1 -1
  81. package/dist/metadata/metadata-reader-token.d.ts +2 -0
  82. package/dist/metadata/metadata-reader-token.d.ts.map +1 -1
  83. package/dist/metadata/metadata-reader-token.js +2 -0
  84. package/dist/metadata/metadata-reader-token.js.map +1 -1
  85. package/dist/metadata/metadata-types.d.ts +6 -0
  86. package/dist/metadata/metadata-types.d.ts.map +1 -1
  87. package/dist/metadata/symbol-metadata-reader.d.ts +4 -0
  88. package/dist/metadata/symbol-metadata-reader.d.ts.map +1 -1
  89. package/dist/metadata/symbol-metadata-reader.js +4 -0
  90. package/dist/metadata/symbol-metadata-reader.js.map +1 -1
  91. package/dist/resolution/cache/activation-need.d.ts +2 -0
  92. package/dist/resolution/cache/activation-need.d.ts.map +1 -1
  93. package/dist/resolution/cache/activation-need.js +2 -0
  94. package/dist/resolution/cache/activation-need.js.map +1 -1
  95. package/dist/resolution/cache/binding-lookup-cache.d.ts +2 -0
  96. package/dist/resolution/cache/binding-lookup-cache.d.ts.map +1 -1
  97. package/dist/resolution/cache/binding-lookup-cache.js +7 -4
  98. package/dist/resolution/cache/binding-lookup-cache.js.map +1 -1
  99. package/dist/resolution/cache/class-introspector.d.ts +2 -0
  100. package/dist/resolution/cache/class-introspector.d.ts.map +1 -1
  101. package/dist/resolution/cache/class-introspector.js +2 -0
  102. package/dist/resolution/cache/class-introspector.js.map +1 -1
  103. package/dist/resolution/context.d.ts +6 -0
  104. package/dist/resolution/context.d.ts.map +1 -1
  105. package/dist/resolution/context.js +4 -0
  106. package/dist/resolution/context.js.map +1 -1
  107. package/dist/resolution/plan/instantiation-plan.d.ts +2 -0
  108. package/dist/resolution/plan/instantiation-plan.d.ts.map +1 -1
  109. package/dist/resolution/plan/instantiation-plan.js +2 -0
  110. package/dist/resolution/plan/instantiation-plan.js.map +1 -1
  111. package/dist/resolution/resolver.d.ts +2 -0
  112. package/dist/resolution/resolver.d.ts.map +1 -1
  113. package/dist/resolution/resolver.js +2 -0
  114. package/dist/resolution/resolver.js.map +1 -1
  115. package/dist/resolution/select/constraints.d.ts +16 -0
  116. package/dist/resolution/select/constraints.d.ts.map +1 -1
  117. package/dist/resolution/select/constraints.js +16 -0
  118. package/dist/resolution/select/constraints.js.map +1 -1
  119. package/package.json +18 -6
  120. package/src/ambient/active-container.ts +4 -0
  121. package/src/container/container.ts +11 -3
  122. package/src/core/map-upsert.ts +53 -0
  123. package/src/core/module.ts +16 -0
  124. package/src/core/registry.ts +10 -4
  125. package/src/core/token.ts +6 -0
  126. package/src/core/types.ts +20 -0
  127. package/src/decorators/inject.ts +2 -0
  128. package/src/decorators/injectable.ts +8 -0
  129. package/src/decorators/lifecycle-decorators.ts +4 -0
  130. package/src/errors/errors.ts +34 -0
  131. package/src/injection/descriptor.ts +12 -0
  132. package/src/introspection/dependency-graph.ts +6 -0
  133. package/src/introspection/graph-adapters/cytoscape.ts +8 -0
  134. package/src/introspection/graph-adapters/dot.ts +2 -0
  135. package/src/introspection/graph-adapters/reactflow.ts +8 -0
  136. package/src/introspection/inspector.ts +6 -0
  137. package/src/lifecycle/lifecycle-manager.ts +7 -2
  138. package/src/lifecycle/scope-manager.ts +4 -2
  139. package/src/metadata/metadata-keys.ts +6 -0
  140. package/src/metadata/metadata-reader-token.ts +2 -0
  141. package/src/metadata/metadata-types.ts +6 -0
  142. package/src/metadata/symbol-metadata-reader.ts +6 -2
  143. package/src/resolution/cache/activation-need.ts +2 -0
  144. package/src/resolution/cache/binding-lookup-cache.ts +7 -4
  145. package/src/resolution/cache/class-introspector.ts +8 -3
  146. package/src/resolution/context.ts +6 -0
  147. package/src/resolution/plan/instantiation-plan.ts +2 -0
  148. package/src/resolution/resolver.ts +2 -0
  149. package/src/resolution/select/constraints.ts +16 -0
@@ -1,10 +1,13 @@
1
1
  import type { Binding } from "#/core/binding";
2
2
  import { bindingSlotEquals, bindingSlotToString } from "#/core/binding";
3
+ import { getOrInsert } from "#/core/map-upsert";
3
4
  import type { BindingTag } from "#/core/tag";
4
5
  import type { Token } from "#/core/token";
5
6
  import type { BindingIdentifier, Constructor, DependencyKey } from "#/core/types";
6
7
 
7
8
  /**
9
+ * One container's binding store, indexed by token, binding id, and slot for fast lookup.
10
+ *
8
11
  * @since 0.3.16-canary.0
9
12
  */
10
13
  export class BindingRegistry {
@@ -235,7 +238,8 @@ export class BindingRegistry {
235
238
  if (criterion === undefined) {
236
239
  return;
237
240
  }
238
- const byCriterion = (this.#simpleTagged ??= new Map()).getOrInsert(tokenKey, new Map<BindingTag, Binding>());
241
+ this.#simpleTagged ??= new Map();
242
+ const byCriterion = getOrInsert(this.#simpleTagged, tokenKey, new Map<BindingTag, Binding>());
239
243
  byCriterion.set(criterion, binding);
240
244
  }
241
245
 
@@ -261,8 +265,9 @@ export class BindingRegistry {
261
265
  if (firstCriterion === undefined) {
262
266
  return;
263
267
  }
264
- const buckets = (this.#multiTagged ??= new Map()).getOrInsert(tokenKey, new Map<BindingTag, Array<Binding>>());
265
- buckets.getOrInsert(firstCriterion, []).push(binding);
268
+ this.#multiTagged ??= new Map();
269
+ const buckets = getOrInsert(this.#multiTagged, tokenKey, new Map<BindingTag, Array<Binding>>());
270
+ getOrInsert(buckets, firstCriterion, []).push(binding);
266
271
  }
267
272
 
268
273
  #deindexMultiTaggedBinding(tokenKey: DependencyKey, binding: Binding): void {
@@ -287,7 +292,8 @@ export class BindingRegistry {
287
292
  if (name === undefined) {
288
293
  return;
289
294
  }
290
- const bindingsByName = (this.#simpleNamed ??= new Map()).getOrInsert(tokenKey, new Map<string, Binding>());
295
+ this.#simpleNamed ??= new Map();
296
+ const bindingsByName = getOrInsert(this.#simpleNamed, tokenKey, new Map<string, Binding>());
291
297
  bindingsByName.set(name, binding);
292
298
  }
293
299
 
package/src/core/token.ts CHANGED
@@ -3,6 +3,8 @@ import type { Constructor } from "#/core/constructor-type";
3
3
  declare const TOKEN_BRAND: unique symbol;
4
4
 
5
5
  /**
6
+ * A branded identifier carrying the value type its bindings resolve to.
7
+ *
6
8
  * @since 0.3.16-canary.0
7
9
  */
8
10
  export interface Token<out Value> {
@@ -11,6 +13,8 @@ export interface Token<out Value> {
11
13
  }
12
14
 
13
15
  /**
16
+ * Creates a named `Token` for the given value type.
17
+ *
14
18
  * @since 0.3.16-canary.0
15
19
  */
16
20
  export function token<Value>(name: string): Token<Value> {
@@ -18,6 +22,8 @@ export function token<Value>(name: string): Token<Value> {
18
22
  }
19
23
 
20
24
  /**
25
+ * Returns the display name of a token or class used as a dependency key.
26
+ *
21
27
  * @since 0.3.16-canary.0
22
28
  */
23
29
  export function tokenName(dependency: Token<unknown> | Constructor): string {
package/src/core/types.ts CHANGED
@@ -16,6 +16,8 @@ export type DependencyKey = Token<unknown> | Constructor;
16
16
  // ── BindingScope ─────────────────────────────────────────────────────────────────────────────────────────────────────
17
17
 
18
18
  /**
19
+ * The lifetime a binding's instances are cached under.
20
+ *
19
21
  * @since 0.3.16-canary.0
20
22
  */
21
23
  export type BindingScope = "singleton" | "transient" | "scoped";
@@ -24,6 +26,8 @@ export type BindingScope = "singleton" | "transient" | "scoped";
24
26
 
25
27
  declare const BINDING_ID_BRAND: unique symbol;
26
28
  /**
29
+ * A branded string that uniquely identifies one binding.
30
+ *
27
31
  * @since 0.3.16-canary.0
28
32
  */
29
33
  export type BindingIdentifier = string & { readonly [BINDING_ID_BRAND]: true };
@@ -31,6 +35,8 @@ export type BindingIdentifier = string & { readonly [BINDING_ID_BRAND]: true };
31
35
  // ── BindingKind ──────────────────────────────────────────────────────────────────────────────────────────────────────
32
36
 
33
37
  /**
38
+ * The strategy a binding produces values with, set by the `to*()` call that created it.
39
+ *
34
40
  * @since 0.3.16-canary.0
35
41
  */
36
42
  export type BindingKind = "class" | "dynamic" | "dynamic-async" | "resolved" | "resolved-async" | "constant" | "alias";
@@ -38,11 +44,15 @@ export type BindingKind = "class" | "dynamic" | "dynamic-async" | "resolved" | "
38
44
  // ── Handlers ─────────────────────────────────────────────────────────────────────────────────────────────────────────
39
45
 
40
46
  /**
47
+ * A hook that runs after an instance is created and returns the instance to hand out.
48
+ *
41
49
  * @since 0.3.16-canary.0
42
50
  */
43
51
  export type ActivationHandler<Value> = (ctx: ResolutionContext, instance: Value) => Value | Promise<Value>;
44
52
 
45
53
  /**
54
+ * A hook that runs when a cached instance is released from its scope.
55
+ *
46
56
  * @since 0.3.16-canary.0
47
57
  */
48
58
  export type DeactivationHandler<Value> = (instance: Value) => void | Promise<void>;
@@ -50,6 +60,8 @@ export type DeactivationHandler<Value> = (instance: Value) => void | Promise<voi
50
60
  // ── ResolveOptions ───────────────────────────────────────────────────────────────────────────────────────────────────
51
61
 
52
62
  /**
63
+ * Slot-selection criteria — a name and tags — that narrow which binding a resolve call matches.
64
+ *
53
65
  * @since 0.3.16-canary.0
54
66
  */
55
67
  export interface ResolveOptions {
@@ -67,6 +79,8 @@ export interface ResolveOptions {
67
79
  // ── ResolutionFrame ──────────────────────────────────────────────────────────────────────────────────────────────────
68
80
 
69
81
  /**
82
+ * One entry of the resolution stack: the token, scope, binding, and slot being resolved.
83
+ *
70
84
  * @since 0.3.16-canary.0
71
85
  */
72
86
  export interface ResolutionFrame {
@@ -84,6 +98,8 @@ export interface ResolutionFrame {
84
98
  // ── ConstraintContext ────────────────────────────────────────────────────────────────────────────────────────────────
85
99
 
86
100
  /**
101
+ * The resolution-time view — path, stack, parent, and ancestors — a `BindingConstraint` inspects.
102
+ *
87
103
  * @since 0.3.16-canary.0
88
104
  */
89
105
  export interface ConstraintContext {
@@ -105,6 +121,8 @@ export type BindingConstraint = (ctx: ConstraintContext) => boolean;
105
121
  // ── ResolutionContext ────────────────────────────────────────────────────────────────────────────────────────────────
106
122
 
107
123
  /**
124
+ * The container view a dynamic factory or activation handler resolves further dependencies through.
125
+ *
108
126
  * @since 0.3.16-canary.0
109
127
  */
110
128
  export interface ResolutionContext {
@@ -123,6 +141,8 @@ export interface ResolutionContext {
123
141
  // ── TokenValue ───────────────────────────────────────────────────────────────────────────────────────────────────────
124
142
 
125
143
  /**
144
+ * The value type a token or class constructor resolves to.
145
+ *
126
146
  * @since 0.3.16-canary.0
127
147
  */
128
148
  export type TokenValue<Type> =
@@ -35,6 +35,8 @@ type ClassAccessorDecorator<This, Value> = (
35
35
  ) => ClassAccessorDecoratorResult<This, Value> | void;
36
36
 
37
37
  /**
38
+ * Creates a dual-role value: an injection descriptor that also works as a class accessor decorator.
39
+ *
38
40
  * @since 0.3.16-canary.0
39
41
  */
40
42
  export function inject<Value>(
@@ -7,6 +7,8 @@ import type { ParamMetadata } from "#/metadata/metadata-types";
7
7
  // ── AutoRegisterRegistry ─────────────────────────────────────────────────────────────────────────────────────────────
8
8
 
9
9
  /**
10
+ * The collector `@injectable` registers a class into, for a container to bind later.
11
+ *
10
12
  * @since 0.3.16-canary.0
11
13
  */
12
14
  export interface AutoRegisterRegistry {
@@ -15,6 +17,8 @@ export interface AutoRegisterRegistry {
15
17
  }
16
18
 
17
19
  /**
20
+ * Creates an empty auto-register registry.
21
+ *
18
22
  * @since 0.3.16-canary.0
19
23
  */
20
24
  export function createAutoRegisterRegistry(): AutoRegisterRegistry {
@@ -32,6 +36,8 @@ export function createAutoRegisterRegistry(): AutoRegisterRegistry {
32
36
  // ── InjectableOptions ────────────────────────────────────────────────────────────────────────────────────────────────
33
37
 
34
38
  /**
39
+ * Auto-registration options `@injectable` accepts alongside its deps list.
40
+ *
35
41
  * @since 0.3.16-canary.0
36
42
  */
37
43
  export interface InjectableOptions {
@@ -83,6 +89,8 @@ export function injectable<const Deps extends ReadonlyArray<InjectableDependency
83
89
  ) => void;
84
90
 
85
91
  /**
92
+ * Writes the declared dependencies into the class's metadata and optionally auto-registers it.
93
+ *
86
94
  * @since 0.6.0
87
95
  */
88
96
  export function injectable(
@@ -25,6 +25,8 @@ function recordLifecycleMethod(phase: "postConstruct" | "preDestroy"): MethodDec
25
25
  }
26
26
 
27
27
  /**
28
+ * Marks an instance method to run after the container constructs and wires the instance.
29
+ *
28
30
  * @since 0.3.16-canary.0
29
31
  */
30
32
  export function postConstruct(): MethodDecorator {
@@ -32,6 +34,8 @@ export function postConstruct(): MethodDecorator {
32
34
  }
33
35
 
34
36
  /**
37
+ * Marks an instance method to run when the instance's container or scope is disposed.
38
+ *
35
39
  * @since 0.3.16-canary.0
36
40
  */
37
41
  export function preDestroy(): MethodDecorator {
@@ -1,6 +1,8 @@
1
1
  import type { BindingIdentifier, BindingScope, ResolveOptions } from "#/core/types";
2
2
 
3
3
  /**
4
+ * Base class for every error the library throws, each carrying a machine-readable `code`.
5
+ *
4
6
  * @since 0.3.16-canary.0
5
7
  */
6
8
  export abstract class DiError extends Error {
@@ -13,6 +15,8 @@ export abstract class DiError extends Error {
13
15
  }
14
16
 
15
17
  /**
18
+ * An internal assertion failure — a library bug, never caller misuse.
19
+ *
16
20
  * @since 0.3.16-canary.0
17
21
  */
18
22
  export class InternalError extends DiError {
@@ -24,6 +28,8 @@ export class InternalError extends DiError {
24
28
  }
25
29
 
26
30
  /**
31
+ * A token with no binding at all, even after walking the parent container chain.
32
+ *
27
33
  * @since 0.3.16-canary.0
28
34
  */
29
35
  export class TokenNotBoundError extends DiError {
@@ -50,6 +56,8 @@ function describeResolveOptions(options: ResolveOptions): string {
50
56
  }
51
57
 
52
58
  /**
59
+ * A token that has bindings, none of whose slots match the given `ResolveOptions`.
60
+ *
53
61
  * @since 0.3.16-canary.0
54
62
  */
55
63
  export class NoMatchingBindingError extends DiError {
@@ -69,6 +77,8 @@ export class NoMatchingBindingError extends DiError {
69
77
  }
70
78
 
71
79
  /**
80
+ * Two or more candidate bindings that matched without the more-specific rule deciding a winner.
81
+ *
72
82
  * @since 0.3.16-canary.0
73
83
  */
74
84
  export class AmbiguousBindingError extends DiError {
@@ -86,6 +96,8 @@ export class AmbiguousBindingError extends DiError {
86
96
  }
87
97
 
88
98
  /**
99
+ * A dependency cycle detected along the resolution path, alias chains included.
100
+ *
89
101
  * @since 0.3.16-canary.0
90
102
  */
91
103
  export class CircularDependencyError extends DiError {
@@ -99,6 +111,8 @@ export class CircularDependencyError extends DiError {
99
111
  }
100
112
 
101
113
  /**
114
+ * A sync `resolve()` of a token whose factory — or a dependency's factory — is async.
115
+ *
102
116
  * @since 0.3.16-canary.0
103
117
  */
104
118
  export class AsyncResolutionError extends DiError {
@@ -120,6 +134,8 @@ export class AsyncResolutionError extends DiError {
120
134
  }
121
135
 
122
136
  /**
137
+ * A sync `unbind()` of a binding whose `onDeactivation` handler is async.
138
+ *
123
139
  * @since 0.3.16-canary.0
124
140
  */
125
141
  export class AsyncDeactivationError extends DiError {
@@ -133,6 +149,8 @@ export class AsyncDeactivationError extends DiError {
133
149
  }
134
150
 
135
151
  /**
152
+ * The tokens, scopes, and resolution path describing a captive-dependency violation.
153
+ *
136
154
  * @since 0.3.16-canary.0
137
155
  */
138
156
  export interface ScopeViolationDetails {
@@ -144,6 +162,8 @@ export interface ScopeViolationDetails {
144
162
  }
145
163
 
146
164
  /**
165
+ * A captive dependency — a longer-lived binding depending on a shorter-lived one.
166
+ *
147
167
  * @since 0.3.16-canary.0
148
168
  */
149
169
  export class ScopeViolationError extends DiError {
@@ -251,6 +271,8 @@ export class InvalidMetadataError extends DiError {
251
271
  }
252
272
 
253
273
  /**
274
+ * A class the container must construct but that carries no `@injectable()` metadata.
275
+ *
254
276
  * @since 0.3.16-canary.0
255
277
  */
256
278
  export class MissingMetadataError extends DiError {
@@ -266,6 +288,8 @@ export class MissingMetadataError extends DiError {
266
288
  }
267
289
 
268
290
  /**
291
+ * A sync `load()` given a module that needs async setup.
292
+ *
269
293
  * @since 0.3.16-canary.0
270
294
  */
271
295
  export class AsyncModuleLoadError extends DiError {
@@ -279,6 +303,8 @@ export class AsyncModuleLoadError extends DiError {
279
303
  }
280
304
 
281
305
  /**
306
+ * A synchronous disposal attempt on a container whose `onDeactivation` handlers may be async.
307
+ *
282
308
  * @since 0.3.16-canary.0
283
309
  */
284
310
  export class SyncDisposalNotSupportedError extends DiError {
@@ -292,6 +318,8 @@ export class SyncDisposalNotSupportedError extends DiError {
292
318
  }
293
319
 
294
320
  /**
321
+ * A `scoped` binding resolved from a container with no child scope context.
322
+ *
295
323
  * @since 0.3.16-canary.0
296
324
  */
297
325
  export class MissingScopeContextError extends DiError {
@@ -355,6 +383,8 @@ export class ChainNotRegisteredError extends DiError {
355
383
  }
356
384
 
357
385
  /**
386
+ * A `rebind()` of a token that has no own binding in this container.
387
+ *
358
388
  * @since 0.3.16-canary.0
359
389
  */
360
390
  export class RebindUnboundTokenError extends DiError {
@@ -410,6 +440,8 @@ export class StaticMemberDecoratorError extends DiError {
410
440
  }
411
441
 
412
442
  /**
443
+ * An operation attempted on a container that has already been disposed.
444
+ *
413
445
  * @since 0.3.16-canary.0
414
446
  */
415
447
  export class DisposedContainerError extends DiError {
@@ -421,6 +453,8 @@ export class DisposedContainerError extends DiError {
421
453
  }
422
454
 
423
455
  /**
456
+ * A `@postConstruct` or `onActivation` hook that returned a `Promise` on a sync resolution path.
457
+ *
424
458
  * @since 0.3.16-canary.0
425
459
  */
426
460
  export class AsyncActivationError extends DiError {
@@ -4,6 +4,8 @@ import type { BindingTag, Constructor, TokenValue } from "#/core/types";
4
4
  import type { DependencySlot } from "#/injection/resolve-options";
5
5
 
6
6
  /**
7
+ * Slot-selection options — a name and tags — a declared dependency narrows its binding with.
8
+ *
7
9
  * @since 0.3.16-canary.0
8
10
  */
9
11
  export interface InjectOptions {
@@ -31,6 +33,8 @@ export interface InjectionDescriptor<out Value = unknown> extends DependencySlot
31
33
  }
32
34
 
33
35
  /**
36
+ * A dependency as declared: a bare token, a class, or a full injection descriptor.
37
+ *
34
38
  * @since 0.3.16-canary.0
35
39
  */
36
40
  export type InjectableDependency<Value = unknown> = Token<Value> | Constructor<Value> | InjectionDescriptor<Value>;
@@ -60,6 +64,8 @@ export type ResolvedDependencyValue<Dependency> = Dependency extends { readonly
60
64
  type DescribedValue<Dependency> = Dependency extends InjectionDescriptor<infer Value> ? Value : TokenValue<Dependency>;
61
65
 
62
66
  /**
67
+ * Returns whether the value is an `InjectionDescriptor`, dual-role `inject()` functions included.
68
+ *
63
69
  * @since 0.3.16-canary.0
64
70
  */
65
71
  export function isInjectionDescriptor(value: unknown): value is InjectionDescriptor {
@@ -81,6 +87,8 @@ export function isInjectionDescriptor(value: unknown): value is InjectionDescrip
81
87
  }
82
88
 
83
89
  /**
90
+ * Normalises a declared dependency to a plain `InjectionDescriptor`.
91
+ *
84
92
  * @since 0.3.16-canary.0
85
93
  */
86
94
  export function normalizeToDescriptor(dependency: InjectableDependency): InjectionDescriptor {
@@ -172,6 +180,8 @@ export function buildInjectionDescriptor<Value>(
172
180
  }
173
181
 
174
182
  /**
183
+ * Creates a descriptor that resolves to `undefined` instead of throwing when no binding matches.
184
+ *
175
185
  * @since 0.3.16-canary.0
176
186
  */
177
187
  export function optional<Value>(
@@ -189,6 +199,8 @@ export function optional<Value>(
189
199
  }
190
200
 
191
201
  /**
202
+ * Creates a descriptor that resolves every matching binding for the token into an array.
203
+ *
192
204
  * @since 0.3.16-canary.0
193
205
  */
194
206
  export function injectAll<Value>(
@@ -43,6 +43,8 @@ export interface GraphEdge {
43
43
  }
44
44
 
45
45
  /**
46
+ * A container's dependency graph as plain JSON — nodes, edges, and whether the parent is included.
47
+ *
46
48
  * @since 0.3.16-canary.0
47
49
  */
48
50
  export interface ContainerGraphJson {
@@ -52,6 +54,8 @@ export interface ContainerGraphJson {
52
54
  }
53
55
 
54
56
  /**
57
+ * Options controlling what a dependency graph includes.
58
+ *
55
59
  * @since 0.3.16-canary.0
56
60
  */
57
61
  export interface GraphOptions {
@@ -255,6 +259,8 @@ function addRegistryBindings(
255
259
  }
256
260
 
257
261
  /**
262
+ * Builds the JSON dependency graph of a registry's bindings, optionally including the parent's.
263
+ *
258
264
  * @since 0.3.16-canary.0
259
265
  */
260
266
  export function buildDependencyGraph(
@@ -1,6 +1,8 @@
1
1
  import type { ContainerGraphJson, GraphNode } from "#/introspection/dependency-graph";
2
2
 
3
3
  /**
4
+ * A dependency-graph node in Cytoscape's element format.
5
+ *
4
6
  * @since 0.3.16-canary.0
5
7
  */
6
8
  export interface CytoscapeNode {
@@ -15,6 +17,8 @@ export interface CytoscapeNode {
15
17
  }
16
18
 
17
19
  /**
20
+ * A dependency-graph edge in Cytoscape's element format.
21
+ *
18
22
  * @since 0.3.16-canary.0
19
23
  */
20
24
  export interface CytoscapeEdge {
@@ -29,11 +33,15 @@ export interface CytoscapeEdge {
29
33
  }
30
34
 
31
35
  /**
36
+ * The flat node-and-edge list Cytoscape takes as its `elements` input.
37
+ *
32
38
  * @since 0.3.16-canary.0
33
39
  */
34
40
  export type CytoscapeElements = ReadonlyArray<CytoscapeNode | CytoscapeEdge>;
35
41
 
36
42
  /**
43
+ * Converts a container's dependency graph into Cytoscape's element list.
44
+ *
37
45
  * @since 0.3.16-canary.0
38
46
  */
39
47
  export function toCytoscapeGraph(graph: ContainerGraphJson): CytoscapeElements {
@@ -7,6 +7,8 @@ function escapeDotString(value: string): string {
7
7
  }
8
8
 
9
9
  /**
10
+ * Renders a container's dependency graph as Graphviz DOT source.
11
+ *
10
12
  * @since 0.3.16-canary.0
11
13
  */
12
14
  export function toDotGraph(graph: ContainerGraphJson): string {
@@ -1,6 +1,8 @@
1
1
  import type { ContainerGraphJson, GraphNode } from "#/introspection/dependency-graph";
2
2
 
3
3
  /**
4
+ * A dependency-graph node in React Flow's node format.
5
+ *
4
6
  * @since 0.3.16-canary.0
5
7
  */
6
8
  export interface ReactFlowNode {
@@ -16,6 +18,8 @@ export interface ReactFlowNode {
16
18
  }
17
19
 
18
20
  /**
21
+ * A dependency-graph edge in React Flow's edge format.
22
+ *
19
23
  * @since 0.3.16-canary.0
20
24
  */
21
25
  export interface ReactFlowEdge {
@@ -28,6 +32,8 @@ export interface ReactFlowEdge {
28
32
  }
29
33
 
30
34
  /**
35
+ * The nodes-and-edges pair a React Flow viewer renders.
36
+ *
31
37
  * @since 0.3.16-canary.0
32
38
  */
33
39
  export interface ReactFlowGraph {
@@ -45,6 +51,8 @@ const GRID_CELL_WIDTH_PX = 200;
45
51
  const GRID_CELL_HEIGHT_PX = 100;
46
52
 
47
53
  /**
54
+ * Converts a container's dependency graph into React Flow nodes and edges on an initial grid.
55
+ *
48
56
  * @since 0.5.0-canary.7
49
57
  */
50
58
  export function toReactFlowGraph(graph: ContainerGraphJson): ReactFlowGraph {
@@ -18,6 +18,8 @@ import { selectAllBindings } from "#/resolution/select/binding-select";
18
18
  // ── Public types ─────────────────────────────────────────────────────────────────────────────────────────────────────
19
19
 
20
20
  /**
21
+ * A read-only view of one binding: token, kind, scope, slot, and id.
22
+ *
21
23
  * @since 0.3.16-canary.0
22
24
  */
23
25
  export interface BindingSnapshot {
@@ -32,6 +34,8 @@ export interface BindingSnapshot {
32
34
  }
33
35
 
34
36
  /**
37
+ * A read-only view of one container's own bindings and state.
38
+ *
35
39
  * @since 0.3.16-canary.0
36
40
  */
37
41
  export interface ContainerSnapshot {
@@ -44,6 +48,8 @@ export interface ContainerSnapshot {
44
48
  // ── Inspector ────────────────────────────────────────────────────────────────────────────────────────────────────────
45
49
 
46
50
  /**
51
+ * The read-only introspection surface behind a container's `inspect()`.
52
+ *
47
53
  * @since 0.3.16-canary.0
48
54
  */
49
55
  export class Inspector {
@@ -1,4 +1,5 @@
1
1
  import type { Binding } from "#/core/binding";
2
+ import { getOrInsert } from "#/core/map-upsert";
2
3
  import type { Token } from "#/core/token";
3
4
  import { tokenName } from "#/core/token";
4
5
  import type {
@@ -12,6 +13,8 @@ import { AsyncActivationError, AsyncDeactivationError, InvalidMetadataError } fr
12
13
  import type { MetadataReader } from "#/metadata/metadata-types";
13
14
 
14
15
  /**
16
+ * One container's registry of container-level activation and deactivation hooks, keyed by token.
17
+ *
15
18
  * @since 0.3.16-canary.0
16
19
  */
17
20
  export class LifecycleManager {
@@ -30,7 +33,8 @@ export class LifecycleManager {
30
33
  this.#activationVersion += 1;
31
34
  this.#cachedToken = undefined;
32
35
  this.#cachedHooks = undefined;
33
- const list = (this.#activationHooks ??= new Map()).getOrInsert(token, []);
36
+ this.#activationHooks ??= new Map();
37
+ const list = getOrInsert(this.#activationHooks, token, []);
34
38
  list.push(handler as ActivationHandler<unknown>);
35
39
  }
36
40
 
@@ -62,7 +66,8 @@ export class LifecycleManager {
62
66
  }
63
67
 
64
68
  registerDeactivation<Value>(token: Token<Value> | Constructor<Value>, handler: DeactivationHandler<Value>): void {
65
- const list = (this.#deactivationHooks ??= new Map()).getOrInsert(token, []);
69
+ this.#deactivationHooks ??= new Map();
70
+ const list = getOrInsert(this.#deactivationHooks, token, []);
66
71
  list.push(handler as DeactivationHandler<unknown>);
67
72
  }
68
73
 
@@ -5,6 +5,8 @@ import type { BindingIdentifier } from "#/core/types";
5
5
  import { MissingScopeContextError } from "#/errors/errors";
6
6
 
7
7
  /**
8
+ * One container's instance caches — singletons, in-flight async creations, and the scoped cache.
9
+ *
8
10
  * @since 0.3.16-canary.0
9
11
  */
10
12
  export class ScopeManager {
@@ -84,7 +86,7 @@ export class ScopeManager {
84
86
  }
85
87
 
86
88
  setInflight(id: BindingIdentifier, promise: Promise<unknown>): void {
87
- (this.#inflight ??= new Map()).set(id, promise);
89
+ (this.#inflight ??= new Map<BindingIdentifier, Promise<unknown>>()).set(id, promise);
88
90
  }
89
91
 
90
92
  clearInflight(id: BindingIdentifier): void {
@@ -114,7 +116,7 @@ export class ScopeManager {
114
116
  if (!this.isChild) {
115
117
  throw new MissingScopeContextError(tokenName(binding.token));
116
118
  }
117
- (this.#scoped ??= new Map()).set(binding.id, instance);
119
+ (this.#scoped ??= new Map<BindingIdentifier, unknown>()).set(binding.id, instance);
118
120
  }
119
121
 
120
122
  /** Releases a removed binding's scoped instance. A scoped instance has no deactivation. */
@@ -1,12 +1,18 @@
1
1
  /**
2
+ * The metadata key `@injectable` writes a class's constructor dependencies under.
3
+ *
2
4
  * @since 0.3.16-canary.0
3
5
  */
4
6
  export const INJECTABLE_KEY: unique symbol = Symbol("di:injectable");
5
7
  /**
8
+ * The metadata key `@postConstruct` and `@preDestroy` record method names under.
9
+ *
6
10
  * @since 0.3.16-canary.0
7
11
  */
8
12
  export const LIFECYCLE_KEY: unique symbol = Symbol("di:lifecycle");
9
13
  /**
14
+ * The metadata key `@inject` accessors record their injection descriptors under.
15
+ *
10
16
  * @since 0.3.16-canary.0
11
17
  */
12
18
  export const INJECT_ACCESSOR_KEY: unique symbol = Symbol("di:inject-accessor");
@@ -3,6 +3,8 @@ import type { Token } from "#/core/token";
3
3
  import type { MetadataReader } from "#/metadata/metadata-types";
4
4
 
5
5
  /**
6
+ * The token a custom `MetadataReader` is bound to for a container to pick up.
7
+ *
6
8
  * @since 0.3.16-canary.0
7
9
  */
8
10
  export const MetadataReaderToken: Token<MetadataReader> = token<MetadataReader>("MetadataReader");
@@ -15,6 +15,8 @@ export interface ParamMetadata extends DependencySlot {
15
15
  }
16
16
 
17
17
  /**
18
+ * A class's declared constructor dependencies, as a `MetadataReader` reports them.
19
+ *
18
20
  * @since 0.3.16-canary.0
19
21
  */
20
22
  export interface ConstructorMetadata {
@@ -22,6 +24,8 @@ export interface ConstructorMetadata {
22
24
  }
23
25
 
24
26
  /**
27
+ * The `postConstruct` and `preDestroy` method names a class declares.
28
+ *
25
29
  * @since 0.3.16-canary.0
26
30
  */
27
31
  export interface LifecycleMetadata {
@@ -40,6 +44,8 @@ export interface MutableLifecycleMetadata {
40
44
  }
41
45
 
42
46
  /**
47
+ * The port a container reads class metadata through — constructor deps, lifecycle, and accessors.
48
+ *
43
49
  * @since 0.3.16-canary.0
44
50
  */
45
51
  export interface MetadataReader {