@brianmcd/di 0.0.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 (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +320 -0
  3. package/dist/cjs/index.d.ts +12 -0
  4. package/dist/cjs/index.d.ts.map +1 -0
  5. package/dist/cjs/index.js +16 -0
  6. package/dist/cjs/index.js.map +1 -0
  7. package/dist/cjs/lib/container-builder.d.ts +76 -0
  8. package/dist/cjs/lib/container-builder.d.ts.map +1 -0
  9. package/dist/cjs/lib/container-builder.js +283 -0
  10. package/dist/cjs/lib/container-builder.js.map +1 -0
  11. package/dist/cjs/lib/container.d.ts +52 -0
  12. package/dist/cjs/lib/container.d.ts.map +1 -0
  13. package/dist/cjs/lib/container.js +113 -0
  14. package/dist/cjs/lib/container.js.map +1 -0
  15. package/dist/cjs/lib/scoped-container.d.ts +36 -0
  16. package/dist/cjs/lib/scoped-container.d.ts.map +1 -0
  17. package/dist/cjs/lib/scoped-container.js +119 -0
  18. package/dist/cjs/lib/scoped-container.js.map +1 -0
  19. package/dist/cjs/lib/types/factory-provider.d.ts +18 -0
  20. package/dist/cjs/lib/types/factory-provider.d.ts.map +1 -0
  21. package/dist/cjs/lib/types/factory-provider.js +3 -0
  22. package/dist/cjs/lib/types/factory-provider.js.map +1 -0
  23. package/dist/cjs/lib/types/injectable-class.d.ts +11 -0
  24. package/dist/cjs/lib/types/injectable-class.d.ts.map +1 -0
  25. package/dist/cjs/lib/types/injectable-class.js +3 -0
  26. package/dist/cjs/lib/types/injectable-class.js.map +1 -0
  27. package/dist/cjs/lib/types/lifecycle.d.ts +13 -0
  28. package/dist/cjs/lib/types/lifecycle.d.ts.map +1 -0
  29. package/dist/cjs/lib/types/lifecycle.js +3 -0
  30. package/dist/cjs/lib/types/lifecycle.js.map +1 -0
  31. package/dist/cjs/lib/types/options.d.ts +5 -0
  32. package/dist/cjs/lib/types/options.d.ts.map +1 -0
  33. package/dist/cjs/lib/types/options.js +3 -0
  34. package/dist/cjs/lib/types/options.js.map +1 -0
  35. package/dist/cjs/lib/types/resolvers.d.ts +15 -0
  36. package/dist/cjs/lib/types/resolvers.d.ts.map +1 -0
  37. package/dist/cjs/lib/types/resolvers.js +3 -0
  38. package/dist/cjs/lib/types/resolvers.js.map +1 -0
  39. package/dist/cjs/lib/types/scope.d.ts +6 -0
  40. package/dist/cjs/lib/types/scope.d.ts.map +1 -0
  41. package/dist/cjs/lib/types/scope.js +8 -0
  42. package/dist/cjs/lib/types/scope.js.map +1 -0
  43. package/dist/cjs/lib/types/tokens.d.ts +13 -0
  44. package/dist/cjs/lib/types/tokens.d.ts.map +1 -0
  45. package/dist/cjs/lib/types/tokens.js +3 -0
  46. package/dist/cjs/lib/types/tokens.js.map +1 -0
  47. package/dist/cjs/lib/utils/create-token.d.ts +10 -0
  48. package/dist/cjs/lib/utils/create-token.d.ts.map +1 -0
  49. package/dist/cjs/lib/utils/create-token.js +14 -0
  50. package/dist/cjs/lib/utils/create-token.js.map +1 -0
  51. package/dist/cjs/lib/utils/define-factory.d.ts +28 -0
  52. package/dist/cjs/lib/utils/define-factory.d.ts.map +1 -0
  53. package/dist/cjs/lib/utils/define-factory.js +31 -0
  54. package/dist/cjs/lib/utils/define-factory.js.map +1 -0
  55. package/dist/cjs/lib/utils/has-on-destroy.d.ts +6 -0
  56. package/dist/cjs/lib/utils/has-on-destroy.d.ts.map +1 -0
  57. package/dist/cjs/lib/utils/has-on-destroy.js +10 -0
  58. package/dist/cjs/lib/utils/has-on-destroy.js.map +1 -0
  59. package/dist/cjs/lib/utils/has-on-init.d.ts +6 -0
  60. package/dist/cjs/lib/utils/has-on-init.d.ts.map +1 -0
  61. package/dist/cjs/lib/utils/has-on-init.js +10 -0
  62. package/dist/cjs/lib/utils/has-on-init.js.map +1 -0
  63. package/dist/cjs/lib/utils/token-to-string.d.ts +6 -0
  64. package/dist/cjs/lib/utils/token-to-string.d.ts.map +1 -0
  65. package/dist/cjs/lib/utils/token-to-string.js +13 -0
  66. package/dist/cjs/lib/utils/token-to-string.js.map +1 -0
  67. package/dist/cjs/package.json +1 -0
  68. package/dist/esm/index.d.ts +12 -0
  69. package/dist/esm/index.d.ts.map +1 -0
  70. package/dist/esm/index.js +7 -0
  71. package/dist/esm/index.js.map +1 -0
  72. package/dist/esm/lib/container-builder.d.ts +76 -0
  73. package/dist/esm/lib/container-builder.d.ts.map +1 -0
  74. package/dist/esm/lib/container-builder.js +279 -0
  75. package/dist/esm/lib/container-builder.js.map +1 -0
  76. package/dist/esm/lib/container.d.ts +52 -0
  77. package/dist/esm/lib/container.d.ts.map +1 -0
  78. package/dist/esm/lib/container.js +109 -0
  79. package/dist/esm/lib/container.js.map +1 -0
  80. package/dist/esm/lib/scoped-container.d.ts +36 -0
  81. package/dist/esm/lib/scoped-container.d.ts.map +1 -0
  82. package/dist/esm/lib/scoped-container.js +115 -0
  83. package/dist/esm/lib/scoped-container.js.map +1 -0
  84. package/dist/esm/lib/types/factory-provider.d.ts +18 -0
  85. package/dist/esm/lib/types/factory-provider.d.ts.map +1 -0
  86. package/dist/esm/lib/types/factory-provider.js +2 -0
  87. package/dist/esm/lib/types/factory-provider.js.map +1 -0
  88. package/dist/esm/lib/types/injectable-class.d.ts +11 -0
  89. package/dist/esm/lib/types/injectable-class.d.ts.map +1 -0
  90. package/dist/esm/lib/types/injectable-class.js +2 -0
  91. package/dist/esm/lib/types/injectable-class.js.map +1 -0
  92. package/dist/esm/lib/types/lifecycle.d.ts +13 -0
  93. package/dist/esm/lib/types/lifecycle.d.ts.map +1 -0
  94. package/dist/esm/lib/types/lifecycle.js +2 -0
  95. package/dist/esm/lib/types/lifecycle.js.map +1 -0
  96. package/dist/esm/lib/types/options.d.ts +5 -0
  97. package/dist/esm/lib/types/options.d.ts.map +1 -0
  98. package/dist/esm/lib/types/options.js +2 -0
  99. package/dist/esm/lib/types/options.js.map +1 -0
  100. package/dist/esm/lib/types/resolvers.d.ts +15 -0
  101. package/dist/esm/lib/types/resolvers.d.ts.map +1 -0
  102. package/dist/esm/lib/types/resolvers.js +2 -0
  103. package/dist/esm/lib/types/resolvers.js.map +1 -0
  104. package/dist/esm/lib/types/scope.d.ts +6 -0
  105. package/dist/esm/lib/types/scope.d.ts.map +1 -0
  106. package/dist/esm/lib/types/scope.js +5 -0
  107. package/dist/esm/lib/types/scope.js.map +1 -0
  108. package/dist/esm/lib/types/tokens.d.ts +13 -0
  109. package/dist/esm/lib/types/tokens.d.ts.map +1 -0
  110. package/dist/esm/lib/types/tokens.js +2 -0
  111. package/dist/esm/lib/types/tokens.js.map +1 -0
  112. package/dist/esm/lib/utils/create-token.d.ts +10 -0
  113. package/dist/esm/lib/utils/create-token.d.ts.map +1 -0
  114. package/dist/esm/lib/utils/create-token.js +11 -0
  115. package/dist/esm/lib/utils/create-token.js.map +1 -0
  116. package/dist/esm/lib/utils/define-factory.d.ts +28 -0
  117. package/dist/esm/lib/utils/define-factory.d.ts.map +1 -0
  118. package/dist/esm/lib/utils/define-factory.js +28 -0
  119. package/dist/esm/lib/utils/define-factory.js.map +1 -0
  120. package/dist/esm/lib/utils/has-on-destroy.d.ts +6 -0
  121. package/dist/esm/lib/utils/has-on-destroy.d.ts.map +1 -0
  122. package/dist/esm/lib/utils/has-on-destroy.js +7 -0
  123. package/dist/esm/lib/utils/has-on-destroy.js.map +1 -0
  124. package/dist/esm/lib/utils/has-on-init.d.ts +6 -0
  125. package/dist/esm/lib/utils/has-on-init.d.ts.map +1 -0
  126. package/dist/esm/lib/utils/has-on-init.js +7 -0
  127. package/dist/esm/lib/utils/has-on-init.js.map +1 -0
  128. package/dist/esm/lib/utils/token-to-string.d.ts +6 -0
  129. package/dist/esm/lib/utils/token-to-string.d.ts.map +1 -0
  130. package/dist/esm/lib/utils/token-to-string.js +10 -0
  131. package/dist/esm/lib/utils/token-to-string.js.map +1 -0
  132. package/package.json +75 -0
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContainerBuilder = void 0;
4
+ const container_js_1 = require("./container.js");
5
+ const scope_js_1 = require("./types/scope.js");
6
+ const token_to_string_js_1 = require("./utils/token-to-string.js");
7
+ /**
8
+ * ContainerBuilder is the class you use to configure a Container.
9
+ *
10
+ * The ContainerBuilder has 2 main responsibilities:
11
+ * 1. Collect all provider registrations, which can be defined in any order.
12
+ * - Handled by register* methods.
13
+ * 2. Instantiate instances and register them in a new Container.
14
+ * - Handled by `.build()`.
15
+ *
16
+ * The ContainerBuilder does a topological sort to ensure that instances are created and destroyed
17
+ * in the correct order (e.g. all of a providers dependencies must be created before that
18
+ * provider's instance can be created, and destruction needs to happen in the opposite order).
19
+ */
20
+ class ContainerBuilder {
21
+ registrations = new Map();
22
+ /**
23
+ * Register a static value.
24
+ */
25
+ registerValue(token, value) {
26
+ this.addRegistration(token, { type: 'value', scope: scope_js_1.Scope.Singleton, token, value });
27
+ return this;
28
+ }
29
+ /**
30
+ * Register a class with static deps property.
31
+ * Dependencies are resolved automatically during build().
32
+ * Type safety between the deps array and constructor params is enforced at this method.
33
+ */
34
+ registerClass(Class, options) {
35
+ const token = Class;
36
+ this.addRegistration(token, {
37
+ type: 'class',
38
+ scope: options?.scope ?? scope_js_1.Scope.Singleton,
39
+ token,
40
+ Class,
41
+ deps: Class.deps,
42
+ });
43
+ return this;
44
+ }
45
+ /**
46
+ * Register a factory provider, which can be async or sync and can inject other dependencies.
47
+ */
48
+ registerFactory(provider, options) {
49
+ const token = provider.provide;
50
+ this.addRegistration(token, {
51
+ type: 'factory',
52
+ scope: options?.scope ?? scope_js_1.Scope.Singleton,
53
+ token,
54
+ provider,
55
+ deps: provider.deps,
56
+ });
57
+ return this;
58
+ }
59
+ /**
60
+ * Merge providers from another container.
61
+ *
62
+ * This is useful for creating standalone packages/libraries that export a ContainerBuilder.
63
+ * You can use `merge` to bring these standalone packages together into a single Container.
64
+ */
65
+ merge(other) {
66
+ for (const [token, registration] of other.registrations) {
67
+ this.addRegistration(token, registration);
68
+ }
69
+ return this;
70
+ }
71
+ /**
72
+ * Override an existing provider with a value; intended for mocking during tests.
73
+ */
74
+ override(token, value) {
75
+ if (!this.registrations.has(token)) {
76
+ throw new Error(`Cannot override: ${(0, token_to_string_js_1.tokenToString)(token)} is not registered`);
77
+ }
78
+ this.registrations.set(token, { type: 'value', scope: scope_js_1.Scope.Singleton, token, value });
79
+ return this;
80
+ }
81
+ /**
82
+ * Build the container - topologically sorts providers and instantiates singletons.
83
+ * Scoped providers are validated but not instantiated - they're stored for later use in Scopes.
84
+ * By default, also initializes the container (calls onInit on all services).
85
+ */
86
+ async build(options) {
87
+ const sorted = this.topologicalSort();
88
+ // Build the state that Container needs
89
+ const state = {
90
+ instances: new Map(),
91
+ factoryProviders: new Map(),
92
+ valueProviders: new Set(),
93
+ initOrder: [],
94
+ scopedClassProviders: new Map(),
95
+ scopedFactoryProviders: new Map(),
96
+ };
97
+ for (const token of sorted) {
98
+ const registration = this.registrations.get(token);
99
+ switch (registration.type) {
100
+ case 'value': {
101
+ state.instances.set(token, registration.value);
102
+ state.valueProviders.add(token);
103
+ state.initOrder.push(token);
104
+ break;
105
+ }
106
+ case 'class': {
107
+ if (registration.scope === scope_js_1.Scope.Scoped) {
108
+ // Store registration data for scope creation - don't instantiate
109
+ state.scopedClassProviders.set(token, {
110
+ Class: registration.Class,
111
+ deps: registration.deps,
112
+ });
113
+ }
114
+ else {
115
+ const resolvedDeps = this.resolveDeps(registration.deps, state.instances);
116
+ const instance = new registration.Class(...resolvedDeps);
117
+ state.instances.set(token, instance);
118
+ state.initOrder.push(token);
119
+ }
120
+ break;
121
+ }
122
+ case 'factory': {
123
+ if (registration.scope === scope_js_1.Scope.Scoped) {
124
+ // Store registration data for scope creation - don't instantiate
125
+ state.scopedFactoryProviders.set(token, registration.provider);
126
+ }
127
+ else {
128
+ const resolvedDeps = this.resolveDeps(registration.deps, state.instances);
129
+ const instance = await registration.provider.factory(...resolvedDeps);
130
+ state.instances.set(token, instance);
131
+ state.factoryProviders.set(token, registration.provider);
132
+ state.initOrder.push(token);
133
+ }
134
+ break;
135
+ }
136
+ }
137
+ }
138
+ const container = new container_js_1.Container(state);
139
+ if (options?.init !== false) {
140
+ await container.init();
141
+ }
142
+ return container;
143
+ }
144
+ /**
145
+ * Topologically sort providers by their dependencies using Kahn's algorithm.
146
+ *
147
+ * This ensures that dependent providers are created and initialized BEFORE the providers that
148
+ * depend on them, and that dependent providers are destroyed AFTER providers that depend on them.
149
+ *
150
+ * Also validates that singleton providers do not depend on scoped providers.
151
+ */
152
+ topologicalSort() {
153
+ // inDegree tracks the number of dependencies a given token has.
154
+ const inDegree = new Map();
155
+ const dependents = new Map();
156
+ // Initialize all nodes.
157
+ for (const token of this.registrations.keys()) {
158
+ inDegree.set(token, 0);
159
+ dependents.set(token, new Set());
160
+ }
161
+ // Build graph edges (dependents and inDegree maps).
162
+ for (const [token, registration] of this.registrations) {
163
+ if (!('deps' in registration)) {
164
+ continue;
165
+ }
166
+ for (const dep of registration.deps) {
167
+ if (!this.registrations.has(dep)) {
168
+ const dependent = (0, token_to_string_js_1.tokenToString)(token);
169
+ const dependency = (0, token_to_string_js_1.tokenToString)(dep);
170
+ throw new Error(`Missing dependency: ${dependent} depends on ${dependency}, which is not registered`);
171
+ }
172
+ // Validate: singleton cannot depend on scoped
173
+ const depRegistration = this.registrations.get(dep);
174
+ if (this.isSingleton(registration) && this.isScoped(depRegistration)) {
175
+ throw new Error(`Invalid dependency: singleton ${(0, token_to_string_js_1.tokenToString)(token)} cannot depend on scoped ${(0, token_to_string_js_1.tokenToString)(dep)}`);
176
+ }
177
+ // dep -> token (token depends on dep)
178
+ dependents.get(dep).add(token);
179
+ inDegree.set(token, (inDegree.get(token) ?? 0) + 1);
180
+ }
181
+ }
182
+ // Start with nodes that have no dependencies
183
+ const queue = [];
184
+ for (const [token, degree] of inDegree) {
185
+ if (degree === 0) {
186
+ queue.push(token);
187
+ }
188
+ }
189
+ const sorted = [];
190
+ // Iteratively push tokens that have no unsorted dependencies to the sorted list.
191
+ // When a token is pushed, we reduce the inDegree for any dependent providers.
192
+ while (queue.length > 0) {
193
+ const current = queue.shift();
194
+ sorted.push(current);
195
+ // Reduce in-degree of dependents.
196
+ for (const dependent of dependents.get(current) ?? []) {
197
+ const newDegree = (inDegree.get(dependent) ?? 0) - 1;
198
+ inDegree.set(dependent, newDegree);
199
+ if (newDegree === 0) {
200
+ queue.push(dependent);
201
+ }
202
+ }
203
+ }
204
+ // Check for circular dependencies.
205
+ if (sorted.length !== this.registrations.size) {
206
+ const cyclePath = this.findCyclePath();
207
+ const cycleStr = cyclePath.map((t) => (0, token_to_string_js_1.tokenToString)(t)).join(' -> ');
208
+ throw new Error(`Circular dependency detected: ${cycleStr}`);
209
+ }
210
+ return sorted;
211
+ }
212
+ /**
213
+ * Find a cycle path using DFS with coloring.
214
+ * Returns the cycle as an array of tokens ending with the repeated token.
215
+ */
216
+ findCyclePath() {
217
+ const WHITE = 0; // Unvisited
218
+ const GRAY = 1; // Currently visiting (in stack)
219
+ const BLACK = 2; // Finished visiting
220
+ const color = new Map();
221
+ for (const token of this.registrations.keys()) {
222
+ color.set(token, WHITE);
223
+ }
224
+ const path = [];
225
+ const dfs = (token) => {
226
+ color.set(token, GRAY);
227
+ path.push(token);
228
+ const registration = this.registrations.get(token);
229
+ const deps = registration && 'deps' in registration ? registration.deps : [];
230
+ for (const dep of deps) {
231
+ if (color.get(dep) === GRAY) {
232
+ // Found cycle - return path from dep to current + dep again
233
+ const cycleStart = path.indexOf(dep);
234
+ return [...path.slice(cycleStart), dep];
235
+ }
236
+ if (color.get(dep) === WHITE) {
237
+ const cycle = dfs(dep);
238
+ if (cycle) {
239
+ return cycle;
240
+ }
241
+ }
242
+ }
243
+ color.set(token, BLACK);
244
+ path.pop();
245
+ return null;
246
+ };
247
+ for (const token of this.registrations.keys()) {
248
+ if (color.get(token) === WHITE) {
249
+ const cycle = dfs(token);
250
+ if (cycle) {
251
+ return cycle;
252
+ }
253
+ }
254
+ }
255
+ return []; // Should not reach here if called after detecting a cycle
256
+ }
257
+ addRegistration(token, registration) {
258
+ if (this.registrations.has(token)) {
259
+ throw new Error(`Token already registered: ${(0, token_to_string_js_1.tokenToString)(token)}`);
260
+ }
261
+ this.registrations.set(token, registration);
262
+ }
263
+ isScoped(registration) {
264
+ return registration.scope === scope_js_1.Scope.Scoped;
265
+ }
266
+ isSingleton(registration) {
267
+ return registration.scope === scope_js_1.Scope.Singleton;
268
+ }
269
+ /**
270
+ * Resolve dependencies from the instances map.
271
+ */
272
+ resolveDeps(deps, instances) {
273
+ return deps.map((dep) => {
274
+ const instance = instances.get(dep);
275
+ if (instance === undefined) {
276
+ throw new Error(`Dependency not found: ${(0, token_to_string_js_1.tokenToString)(dep)}`);
277
+ }
278
+ return instance;
279
+ });
280
+ }
281
+ }
282
+ exports.ContainerBuilder = ContainerBuilder;
283
+ //# sourceMappingURL=container-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-builder.js","sourceRoot":"","sources":["../../../src/lib/container-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { FactoryProvider } from './types/factory-provider.js';
2
+ import type { InjectableClass } from './types/injectable-class.js';
3
+ import type { Token } from './types/tokens.js';
4
+ import { ScopedContainer } from './scoped-container.js';
5
+ /**
6
+ * Data for a scoped class registration.
7
+ */
8
+ export interface ScopedClassData<T = unknown> {
9
+ Class: InjectableClass<T>;
10
+ deps: readonly Token<unknown>[];
11
+ }
12
+ /**
13
+ * Data required to construct a Container.
14
+ * This is the "state" that ContainerBuilder prepares.
15
+ */
16
+ export interface ContainerState {
17
+ instances: Map<Token<unknown>, unknown>;
18
+ factoryProviders: Map<Token<unknown>, FactoryProvider<any, any, any>>;
19
+ valueProviders: Set<Token<unknown>>;
20
+ initOrder: Token<unknown>[];
21
+ scopedClassProviders: Map<Token<unknown>, ScopedClassData>;
22
+ scopedFactoryProviders: Map<Token<unknown>, FactoryProvider<any, any, any>>;
23
+ }
24
+ export declare class Container {
25
+ private readonly instances;
26
+ private readonly factoryProviders;
27
+ private readonly valueProviders;
28
+ private readonly initOrder;
29
+ private readonly scopedClassProviders;
30
+ private readonly scopedFactoryProviders;
31
+ private isInitialized;
32
+ constructor(state: ContainerState);
33
+ /**
34
+ * Get an instance by its token.
35
+ */
36
+ get<T>(token: Token<T>): T;
37
+ /**
38
+ * Create a new scoped container for scoped instances.
39
+ * Scoped instances are created on-demand within the container and destroyed when the scoped container is destroyed.
40
+ */
41
+ createScope(): ScopedContainer;
42
+ /**
43
+ * Initialize all instances - calls onInit() in topological order (dependencies before dependents).
44
+ * Only class-registered instances have onInit called (not values or factories).
45
+ */
46
+ init(): Promise<void>;
47
+ /**
48
+ * Destroy all instances - calls onDestroy() in reverse topological order (dependents before dependencies).
49
+ */
50
+ destroy(): Promise<void>;
51
+ }
52
+ //# sourceMappingURL=container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.d.ts","sourceRoot":"","sources":["../../../src/lib/container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAKxD;;GAEG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,EAAE,SAAS,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IACxC,gBAAgB,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IACtE,cAAc,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IACpC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;IAE5B,oBAAoB,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC;IAC3D,sBAAsB,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;CAC7E;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+B;IACzD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsD;IACvF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAuC;IAC5E,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAsD;IAC7F,OAAO,CAAC,aAAa,CAAS;gBAEX,KAAK,EAAE,cAAc;IASxC;;OAEG;IACI,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IAWjC;;;OAGG;IACI,WAAW,IAAI,eAAe;IAQrC;;;OAGG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBlC;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAiDtC"}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Container = void 0;
4
+ const scoped_container_js_1 = require("./scoped-container.js");
5
+ const has_on_destroy_js_1 = require("./utils/has-on-destroy.js");
6
+ const has_on_init_js_1 = require("./utils/has-on-init.js");
7
+ const token_to_string_js_1 = require("./utils/token-to-string.js");
8
+ class Container {
9
+ instances;
10
+ factoryProviders;
11
+ valueProviders;
12
+ initOrder;
13
+ scopedClassProviders;
14
+ scopedFactoryProviders;
15
+ isInitialized = false;
16
+ constructor(state) {
17
+ this.instances = state.instances;
18
+ this.factoryProviders = state.factoryProviders;
19
+ this.valueProviders = state.valueProviders;
20
+ this.initOrder = state.initOrder;
21
+ this.scopedClassProviders = state.scopedClassProviders;
22
+ this.scopedFactoryProviders = state.scopedFactoryProviders;
23
+ }
24
+ /**
25
+ * Get an instance by its token.
26
+ */
27
+ get(token) {
28
+ if (!this.isInitialized) {
29
+ throw new Error('Container not initialized. Call init() before getting instances.');
30
+ }
31
+ const instance = this.instances.get(token);
32
+ if (instance === undefined) {
33
+ throw new Error(`Token not registered: ${(0, token_to_string_js_1.tokenToString)(token)}`);
34
+ }
35
+ return instance;
36
+ }
37
+ /**
38
+ * Create a new scoped container for scoped instances.
39
+ * Scoped instances are created on-demand within the container and destroyed when the scoped container is destroyed.
40
+ */
41
+ createScope() {
42
+ return new scoped_container_js_1.ScopedContainer(this.instances, this.scopedClassProviders, this.scopedFactoryProviders);
43
+ }
44
+ /**
45
+ * Initialize all instances - calls onInit() in topological order (dependencies before dependents).
46
+ * Only class-registered instances have onInit called (not values or factories).
47
+ */
48
+ async init() {
49
+ if (this.isInitialized) {
50
+ throw new Error('Container already initialized');
51
+ }
52
+ for (const token of this.initOrder) {
53
+ // Skip externally-managed instances (values and factories)
54
+ if (this.valueProviders.has(token) || this.factoryProviders.has(token)) {
55
+ continue;
56
+ }
57
+ const instance = this.instances.get(token);
58
+ if ((0, has_on_init_js_1.hasOnInit)(instance)) {
59
+ await instance.onInit();
60
+ }
61
+ }
62
+ this.isInitialized = true;
63
+ }
64
+ /**
65
+ * Destroy all instances - calls onDestroy() in reverse topological order (dependents before dependencies).
66
+ */
67
+ async destroy() {
68
+ const errors = [];
69
+ for (const token of [...this.initOrder].reverse()) {
70
+ const factoryProvider = this.factoryProviders.get(token);
71
+ try {
72
+ // There's an important nuance here: if an instance was provided via a factory or value,
73
+ // then we don't want invoke onDestroy on the instance, even if it exists. There could be a
74
+ // scenario where a factory is providing an instance of a third party dependency, and that
75
+ // third party may happen to have an `onDestroy` method. We don't want to blindly invoke
76
+ // that `onDestroy`, so if an instance was provided via a factory, we never check for an
77
+ // `onDestroy` on that instance.
78
+ if (factoryProvider) {
79
+ if (factoryProvider?.onDestroy) {
80
+ const hookDeps = factoryProvider.onDestroy.deps ?? [];
81
+ const resolvedDeps = hookDeps.map((d) => this.get(d));
82
+ await factoryProvider.onDestroy.handler(...resolvedDeps);
83
+ }
84
+ continue;
85
+ }
86
+ // Skip value-provided instances - they are externally managed.
87
+ if (this.valueProviders.has(token)) {
88
+ continue;
89
+ }
90
+ // Only class-registered instances get onDestroy called.
91
+ const instance = this.instances.get(token);
92
+ if ((0, has_on_destroy_js_1.hasOnDestroy)(instance)) {
93
+ await instance.onDestroy();
94
+ }
95
+ }
96
+ catch (error) {
97
+ errors.push(error);
98
+ }
99
+ }
100
+ this.instances.clear();
101
+ this.factoryProviders.clear();
102
+ this.valueProviders.clear();
103
+ this.initOrder.length = 0;
104
+ this.scopedClassProviders.clear();
105
+ this.scopedFactoryProviders.clear();
106
+ this.isInitialized = false;
107
+ if (errors.length > 0) {
108
+ throw new AggregateError(errors, 'Errors during container destruction');
109
+ }
110
+ }
111
+ }
112
+ exports.Container = Container;
113
+ //# sourceMappingURL=container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../../../src/lib/container.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { FactoryProvider } from './types/factory-provider.js';
2
+ import type { Token } from './types/tokens.js';
3
+ import type { ScopedClassData } from './container.js';
4
+ /**
5
+ * A ScopedContainer represents a context for scoped instances.
6
+ * Scoped instances are created on-demand and cached within this container.
7
+ * When the scoped container is destroyed, all scoped instances are cleaned up.
8
+ */
9
+ export declare class ScopedContainer {
10
+ private readonly parentInstances;
11
+ private readonly scopedClassProviders;
12
+ private readonly scopedFactoryProviders;
13
+ private readonly instances;
14
+ private readonly creationOrder;
15
+ private _isDestroyed;
16
+ constructor(parentInstances: Map<Token<unknown>, unknown>, scopedClassProviders: Map<Token<unknown>, ScopedClassData>, scopedFactoryProviders: Map<Token<unknown>, FactoryProvider<any, any, any>>);
17
+ get isDestroyed(): boolean;
18
+ /**
19
+ * Get an instance by its token.
20
+ * - For scoped tokens: creates/caches instance within this scope
21
+ * - For singleton tokens: returns instance from parent container
22
+ */
23
+ get<T>(token: Token<T>): Promise<T>;
24
+ /**
25
+ * Calls onDestroy on all created instances in reverse creation order.
26
+ */
27
+ destroy(): Promise<void>;
28
+ private createScopedClassInstance;
29
+ private createScopedFactoryInstance;
30
+ /**
31
+ * Internal resolution logic shared by get() and dependency resolution.
32
+ * Does not check if scope is destroyed - caller must handle that.
33
+ */
34
+ private resolve;
35
+ }
36
+ //# sourceMappingURL=scoped-container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoped-container.d.ts","sourceRoot":"","sources":["../../../src/lib/scoped-container.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAKtD;;;;GAIG;AACH,qBAAa,eAAe;IAMxB,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,oBAAoB;IACrC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IAPzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA2C;IACrE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwB;IACtD,OAAO,CAAC,YAAY,CAAS;gBAGV,eAAe,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,EAC7C,oBAAoB,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,EAC1D,sBAAsB,EAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAG9F,IAAW,WAAW,IAAI,OAAO,CAEhC;IAED;;;;OAIG;IACU,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAOhD;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YA0CvB,yBAAyB;YAgBzB,2BAA2B;IAazC;;;OAGG;YACW,OAAO;CAuBtB"}
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScopedContainer = void 0;
4
+ const has_on_destroy_js_1 = require("./utils/has-on-destroy.js");
5
+ const has_on_init_js_1 = require("./utils/has-on-init.js");
6
+ const token_to_string_js_1 = require("./utils/token-to-string.js");
7
+ /**
8
+ * A ScopedContainer represents a context for scoped instances.
9
+ * Scoped instances are created on-demand and cached within this container.
10
+ * When the scoped container is destroyed, all scoped instances are cleaned up.
11
+ */
12
+ class ScopedContainer {
13
+ parentInstances;
14
+ scopedClassProviders;
15
+ scopedFactoryProviders;
16
+ instances = new Map();
17
+ creationOrder = [];
18
+ _isDestroyed = false;
19
+ constructor(parentInstances, scopedClassProviders, scopedFactoryProviders) {
20
+ this.parentInstances = parentInstances;
21
+ this.scopedClassProviders = scopedClassProviders;
22
+ this.scopedFactoryProviders = scopedFactoryProviders;
23
+ }
24
+ get isDestroyed() {
25
+ return this._isDestroyed;
26
+ }
27
+ /**
28
+ * Get an instance by its token.
29
+ * - For scoped tokens: creates/caches instance within this scope
30
+ * - For singleton tokens: returns instance from parent container
31
+ */
32
+ async get(token) {
33
+ if (this._isDestroyed) {
34
+ throw new Error('Scope has been destroyed');
35
+ }
36
+ return this.resolve(token);
37
+ }
38
+ /**
39
+ * Calls onDestroy on all created instances in reverse creation order.
40
+ */
41
+ async destroy() {
42
+ if (this._isDestroyed) {
43
+ return;
44
+ }
45
+ this._isDestroyed = true;
46
+ const errors = [];
47
+ // Destroy in reverse creation order
48
+ for (const token of [...this.creationOrder].reverse()) {
49
+ try {
50
+ // Check if it was a scoped factory with onDestroy hook
51
+ const factoryProvider = this.scopedFactoryProviders.get(token);
52
+ if (factoryProvider?.onDestroy) {
53
+ const hookDeps = factoryProvider.onDestroy.deps ?? [];
54
+ const resolvedDeps = await Promise.all(hookDeps.map((dep) => this.resolve(dep)));
55
+ await factoryProvider.onDestroy.handler(...resolvedDeps);
56
+ continue;
57
+ }
58
+ // For scoped class instances, call onDestroy if implemented
59
+ const instance = this.instances.get(token);
60
+ if ((0, has_on_destroy_js_1.hasOnDestroy)(instance)) {
61
+ await instance.onDestroy();
62
+ }
63
+ }
64
+ catch (error) {
65
+ errors.push(error);
66
+ }
67
+ }
68
+ this.instances.clear();
69
+ this.creationOrder.length = 0;
70
+ if (errors.length > 0) {
71
+ throw new AggregateError(errors, 'Errors during scope destruction');
72
+ }
73
+ }
74
+ async createScopedClassInstance(token) {
75
+ const registration = this.scopedClassProviders.get(token);
76
+ const resolvedDeps = await Promise.all(registration.deps.map((dep) => this.resolve(dep)));
77
+ const instance = new registration.Class(...resolvedDeps);
78
+ this.instances.set(token, instance);
79
+ this.creationOrder.push(token);
80
+ // Call onInit if implemented
81
+ if ((0, has_on_init_js_1.hasOnInit)(instance)) {
82
+ await instance.onInit();
83
+ }
84
+ return instance;
85
+ }
86
+ async createScopedFactoryInstance(token) {
87
+ const provider = this.scopedFactoryProviders.get(token);
88
+ const resolvedDeps = await Promise.all(provider.deps.map((dep) => this.resolve(dep)));
89
+ const instance = await provider.factory(...resolvedDeps);
90
+ this.instances.set(token, instance);
91
+ this.creationOrder.push(token);
92
+ return instance;
93
+ }
94
+ /**
95
+ * Internal resolution logic shared by get() and dependency resolution.
96
+ * Does not check if scope is destroyed - caller must handle that.
97
+ */
98
+ async resolve(token) {
99
+ // Check if already cached in this scope
100
+ if (this.instances.has(token)) {
101
+ return this.instances.get(token);
102
+ }
103
+ // Check if it's a scoped class
104
+ if (this.scopedClassProviders.has(token)) {
105
+ return this.createScopedClassInstance(token);
106
+ }
107
+ // Check if it's a scoped factory
108
+ if (this.scopedFactoryProviders.has(token)) {
109
+ return this.createScopedFactoryInstance(token);
110
+ }
111
+ // Fall back to parent container
112
+ if (this.parentInstances.has(token)) {
113
+ return this.parentInstances.get(token);
114
+ }
115
+ throw new Error(`Token not registered: ${(0, token_to_string_js_1.tokenToString)(token)}`);
116
+ }
117
+ }
118
+ exports.ScopedContainer = ScopedContainer;
119
+ //# sourceMappingURL=scoped-container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scoped-container.js","sourceRoot":"","sources":["../../../src/lib/scoped-container.ts"],"names":[],"mappings":"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"}