@navios/di 0.1.9 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -1,795 +1,1027 @@
1
1
  "use strict";
2
- //#region rolldown:runtime
3
- var __create = Object.create;
4
2
  var __defProp = Object.defineProperty;
5
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getProtoOf = Object.getPrototypeOf;
8
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
9
10
  var __copyProps = (to, from, except, desc) => {
10
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
- key = keys[i];
12
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
- get: ((k) => from[k]).bind(null, key),
14
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
- });
16
- }
17
- return to;
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
18
17
  };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
- value: mod,
21
- enumerable: true
22
- }) : target, mod));
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.mts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BoundInjectionToken: () => BoundInjectionToken,
24
+ ErrorsEnum: () => ErrorsEnum,
25
+ EventEmitter: () => EventEmitter,
26
+ FactoryInjectionToken: () => FactoryInjectionToken,
27
+ FactoryNotFound: () => FactoryNotFound,
28
+ FactoryTokenNotResolved: () => FactoryTokenNotResolved,
29
+ Injectable: () => Injectable,
30
+ InjectableScope: () => InjectableScope,
31
+ InjectableTokenMeta: () => InjectableTokenMeta,
32
+ InjectableType: () => InjectableType,
33
+ InjectionToken: () => InjectionToken,
34
+ InjectorsBase: () => InjectorsBase,
35
+ InstanceDestroying: () => InstanceDestroying,
36
+ InstanceExpired: () => InstanceExpired,
37
+ InstanceNotFound: () => InstanceNotFound,
38
+ ProxyServiceLocator: () => ProxyServiceLocator,
39
+ Registry: () => Registry,
40
+ ServiceLocator: () => ServiceLocator,
41
+ ServiceLocatorEventBus: () => ServiceLocatorEventBus,
42
+ ServiceLocatorInstanceHolderKind: () => ServiceLocatorInstanceHolderKind,
43
+ ServiceLocatorInstanceHolderStatus: () => ServiceLocatorInstanceHolderStatus,
44
+ ServiceLocatorManager: () => ServiceLocatorManager,
45
+ UnknownError: () => UnknownError,
46
+ getGlobalServiceLocator: () => getGlobalServiceLocator,
47
+ getInjectableToken: () => getInjectableToken,
48
+ getInjectors: () => getInjectors,
49
+ globalRegistry: () => globalRegistry,
50
+ inject: () => inject,
51
+ makeProxyServiceLocator: () => makeProxyServiceLocator,
52
+ provideServiceLocator: () => provideServiceLocator,
53
+ resolveService: () => resolveService,
54
+ syncInject: () => syncInject,
55
+ wrapSyncInit: () => wrapSyncInit
56
+ });
57
+ module.exports = __toCommonJS(index_exports);
23
58
 
24
- //#endregion
25
- require("zod");
59
+ // src/decorators/injectable.decorator.mts
60
+ var import_zod3 = require("zod");
26
61
 
27
- //#region src/enums/injectable-scope.enum.mts
28
- let InjectableScope = /* @__PURE__ */ function(InjectableScope$1) {
29
- /**
30
- * Singleton scope: The instance is created once and shared across the application.
31
- */
32
- InjectableScope$1["Singleton"] = "Singleton";
33
- /**
34
- * Instance scope: A new instance is created for each injection.
35
- */
36
- InjectableScope$1["Instance"] = "Instance";
37
- return InjectableScope$1;
38
- }({});
62
+ // src/enums/injectable-scope.enum.mts
63
+ var InjectableScope = /* @__PURE__ */ ((InjectableScope3) => {
64
+ InjectableScope3["Singleton"] = "Singleton";
65
+ InjectableScope3["Instance"] = "Instance";
66
+ return InjectableScope3;
67
+ })(InjectableScope || {});
39
68
 
40
- //#endregion
41
- //#region src/enums/injectable-type.enum.mts
42
- let InjectableType = /* @__PURE__ */ function(InjectableType$1) {
43
- InjectableType$1["Class"] = "Class";
44
- InjectableType$1["Factory"] = "Factory";
45
- return InjectableType$1;
46
- }({});
69
+ // src/enums/injectable-type.enum.mts
70
+ var InjectableType = /* @__PURE__ */ ((InjectableType2) => {
71
+ InjectableType2["Class"] = "Class";
72
+ InjectableType2["Factory"] = "Factory";
73
+ return InjectableType2;
74
+ })(InjectableType || {});
47
75
 
48
- //#endregion
49
- //#region src/injection-token.mts
50
- const Optional = Symbol("Optional");
51
- const Required = Symbol("Required");
52
- var InjectionToken = class InjectionToken {
53
- id = globalThis.crypto.randomUUID();
54
- formattedName = null;
55
- constructor(name, schema) {
56
- this.name = name;
57
- this.schema = schema;
58
- }
59
- static create(name, schema) {
60
- return new InjectionToken(name, schema);
61
- }
62
- static bound(token, value) {
63
- return new BoundInjectionToken(token, value);
64
- }
65
- static factory(token, factory) {
66
- return new FactoryInjectionToken(token, factory);
67
- }
68
- static refineType(token) {
69
- return token;
70
- }
71
- toString() {
72
- if (this.formattedName) return this.formattedName;
73
- const { name } = this;
74
- if (typeof name === "function") {
75
- const className = name.name;
76
- this.formattedName = `${className}(${this.id})`;
77
- } else if (typeof name === "symbol") this.formattedName = `${name.toString()}(${this.id})`;
78
- else this.formattedName = `${name}(${this.id})`;
79
- return this.formattedName;
80
- }
76
+ // src/injection-token.mts
77
+ var import_zod = require("zod");
78
+ var InjectionToken = class _InjectionToken {
79
+ constructor(name, schema) {
80
+ this.name = name;
81
+ this.schema = schema;
82
+ }
83
+ id = globalThis.crypto.randomUUID();
84
+ formattedName = null;
85
+ static create(name, schema) {
86
+ return new _InjectionToken(name, schema);
87
+ }
88
+ static bound(token, value) {
89
+ return new BoundInjectionToken(token, value);
90
+ }
91
+ static factory(token, factory) {
92
+ return new FactoryInjectionToken(token, factory);
93
+ }
94
+ static refineType(token) {
95
+ return token;
96
+ }
97
+ toString() {
98
+ if (this.formattedName) {
99
+ return this.formattedName;
100
+ }
101
+ const { name } = this;
102
+ if (typeof name === "function") {
103
+ const className = name.name;
104
+ this.formattedName = `${className}(${this.id})`;
105
+ } else if (typeof name === "symbol") {
106
+ this.formattedName = `${name.toString()}(${this.id})`;
107
+ } else {
108
+ this.formattedName = `${name}(${this.id})`;
109
+ }
110
+ return this.formattedName;
111
+ }
81
112
  };
82
113
  var BoundInjectionToken = class {
83
- id;
84
- name;
85
- schema;
86
- constructor(token, value) {
87
- this.token = token;
88
- this.value = value;
89
- this.name = token.name;
90
- this.id = token.id;
91
- this.schema = token.schema;
92
- }
93
- toString() {
94
- return this.token.toString();
95
- }
114
+ constructor(token, value) {
115
+ this.token = token;
116
+ this.value = value;
117
+ this.name = token.name;
118
+ this.id = token.id;
119
+ this.schema = token.schema;
120
+ }
121
+ id;
122
+ name;
123
+ schema;
124
+ toString() {
125
+ return this.token.toString();
126
+ }
96
127
  };
97
128
  var FactoryInjectionToken = class {
98
- value;
99
- resolved = false;
100
- id;
101
- name;
102
- schema;
103
- constructor(token, factory) {
104
- this.token = token;
105
- this.factory = factory;
106
- this.name = token.name;
107
- this.id = token.id;
108
- this.schema = token.schema;
109
- }
110
- async resolve() {
111
- if (!this.value) {
112
- this.value = await this.factory();
113
- this.resolved = true;
114
- }
115
- return this.value;
116
- }
117
- toString() {
118
- return this.token.toString();
119
- }
129
+ constructor(token, factory) {
130
+ this.token = token;
131
+ this.factory = factory;
132
+ this.name = token.name;
133
+ this.id = token.id;
134
+ this.schema = token.schema;
135
+ }
136
+ value;
137
+ resolved = false;
138
+ id;
139
+ name;
140
+ schema;
141
+ async resolve() {
142
+ if (!this.value) {
143
+ this.value = await this.factory();
144
+ this.resolved = true;
145
+ }
146
+ return this.value;
147
+ }
148
+ toString() {
149
+ return this.token.toString();
150
+ }
120
151
  };
121
152
 
122
- //#endregion
123
- //#region src/registry.mts
153
+ // src/registry.mts
154
+ var import_zod2 = require("zod");
124
155
  var Registry = class {
125
- factories = new Map();
126
- constructor(parent) {
127
- this.parent = parent;
128
- }
129
- has(token) {
130
- if (this.factories.has(token.id)) return true;
131
- if (this.parent) return this.parent.has(token);
132
- return false;
133
- }
134
- get(token) {
135
- const factory = this.factories.get(token.id);
136
- if (!factory) {
137
- if (this.parent) return this.parent.get(token);
138
- throw new Error(`[Registry] No factory found for ${token.toString()}`);
139
- }
140
- return factory;
141
- }
142
- set(token, factory, scope) {
143
- this.factories.set(token.id, {
144
- factory,
145
- scope,
146
- originalToken: token
147
- });
148
- }
149
- delete(token) {
150
- this.factories.delete(token.id);
151
- }
156
+ constructor(parent) {
157
+ this.parent = parent;
158
+ }
159
+ factories = /* @__PURE__ */ new Map();
160
+ has(token) {
161
+ if (this.factories.has(token.id)) {
162
+ return true;
163
+ }
164
+ if (this.parent) {
165
+ return this.parent.has(token);
166
+ }
167
+ return false;
168
+ }
169
+ get(token) {
170
+ const factory = this.factories.get(token.id);
171
+ if (!factory) {
172
+ if (this.parent) {
173
+ return this.parent.get(token);
174
+ }
175
+ throw new Error(`[Registry] No factory found for ${token.toString()}`);
176
+ }
177
+ return factory;
178
+ }
179
+ set(token, factory, scope) {
180
+ this.factories.set(token.id, { factory, scope, originalToken: token });
181
+ }
182
+ delete(token) {
183
+ this.factories.delete(token.id);
184
+ }
152
185
  };
153
- const globalRegistry = new Registry();
186
+ var globalRegistry = new Registry();
154
187
 
155
- //#endregion
156
- //#region src/proxy-service-locator.mts
188
+ // src/proxy-service-locator.mts
157
189
  var ProxyServiceLocator = class {
158
- constructor(serviceLocator, ctx) {
159
- this.serviceLocator = serviceLocator;
160
- this.ctx = ctx;
161
- }
162
- getEventBus() {
163
- return this.serviceLocator.getEventBus();
164
- }
165
- getInstance(token, args) {
166
- return this.ctx.inject(token, args).then((instance) => {
167
- return [void 0, instance];
168
- }, (error) => {
169
- return [error];
170
- });
171
- }
172
- getOrThrowInstance(token, args) {
173
- return this.ctx.inject(token, args);
174
- }
175
- getSyncInstance(token, args) {
176
- return this.serviceLocator.getSyncInstance(token, args);
177
- }
178
- invalidate(service, round) {
179
- return this.serviceLocator.invalidate(service, round);
180
- }
181
- ready() {
182
- return this.serviceLocator.ready();
183
- }
184
- makeInstanceName(token, args) {
185
- return this.serviceLocator.makeInstanceName(token, args);
186
- }
190
+ constructor(serviceLocator, ctx) {
191
+ this.serviceLocator = serviceLocator;
192
+ this.ctx = ctx;
193
+ }
194
+ getEventBus() {
195
+ return this.serviceLocator.getEventBus();
196
+ }
197
+ // @ts-expect-error We don't need all the properties of the class
198
+ getInstance(token, args) {
199
+ return this.ctx.inject(token, args).then(
200
+ (instance) => {
201
+ return [void 0, instance];
202
+ },
203
+ (error) => {
204
+ return [error];
205
+ }
206
+ );
207
+ }
208
+ getOrThrowInstance(token, args) {
209
+ return this.ctx.inject(token, args);
210
+ }
211
+ getSyncInstance(token, args) {
212
+ return this.serviceLocator.getSyncInstance(token, args);
213
+ }
214
+ invalidate(service, round) {
215
+ return this.serviceLocator.invalidate(service, round);
216
+ }
217
+ ready() {
218
+ return this.serviceLocator.ready();
219
+ }
220
+ makeInstanceName(token, args) {
221
+ return this.serviceLocator.makeInstanceName(token, args);
222
+ }
187
223
  };
188
224
  function makeProxyServiceLocator(serviceLocator, ctx) {
189
- return new ProxyServiceLocator(serviceLocator, ctx);
225
+ return new ProxyServiceLocator(serviceLocator, ctx);
190
226
  }
191
227
 
192
- //#endregion
193
- //#region src/symbols/injectable-token.mts
194
- const InjectableTokenMeta = Symbol.for("InjectableTokenMeta");
228
+ // src/symbols/injectable-token.mts
229
+ var InjectableTokenMeta = Symbol.for("InjectableTokenMeta");
195
230
 
196
- //#endregion
197
- //#region src/utils/get-injectors.mts
198
- const InjectorsBase = new Map();
231
+ // src/utils/get-injectors.mts
232
+ var InjectorsBase = /* @__PURE__ */ new Map();
199
233
  function getInjectors({ baseLocator }) {
200
- if (InjectorsBase.has(baseLocator)) return InjectorsBase.get(baseLocator);
201
- let currentLocator = baseLocator;
202
- function getServiceLocator() {
203
- if (!currentLocator) throw new Error("[Injector] Service locator is not initialized. Please provide the service locator before using the @Injectable decorator.");
204
- return currentLocator;
205
- }
206
- function provideServiceLocator$1(locator) {
207
- const original = currentLocator;
208
- currentLocator = locator;
209
- return original;
210
- }
211
- function inject$1(token, args) {
212
- const realToken = token[InjectableTokenMeta] ?? token;
213
- return getServiceLocator().getOrThrowInstance(realToken, args);
214
- }
215
- let promiseCollector = null;
216
- function wrapSyncInit$1(cb) {
217
- return () => {
218
- const promises = [];
219
- const originalPromiseCollector = promiseCollector;
220
- promiseCollector = (promise) => {
221
- promises.push(promise);
222
- };
223
- const result = cb();
224
- promiseCollector = originalPromiseCollector;
225
- return [result, promises];
226
- };
227
- }
228
- function syncInject$1(token, args) {
229
- const realToken = token[InjectableTokenMeta] ?? token;
230
- const instance = getServiceLocator().getSyncInstance(realToken, args);
231
- if (!instance) if (promiseCollector) {
232
- const promise = getServiceLocator().getInstance(realToken, args);
233
- promiseCollector(promise);
234
- } else throw new Error(`[Injector] Cannot initiate ${realToken.toString()}`);
235
- return instance;
236
- }
237
- const injectors = {
238
- inject: inject$1,
239
- syncInject: syncInject$1,
240
- wrapSyncInit: wrapSyncInit$1,
241
- provideServiceLocator: provideServiceLocator$1
242
- };
243
- InjectorsBase.set(baseLocator, injectors);
244
- return injectors;
234
+ if (InjectorsBase.has(baseLocator)) {
235
+ return InjectorsBase.get(baseLocator);
236
+ }
237
+ let currentLocator = baseLocator;
238
+ function getServiceLocator() {
239
+ if (!currentLocator) {
240
+ throw new Error(
241
+ "[Injector] Service locator is not initialized. Please provide the service locator before using the @Injectable decorator."
242
+ );
243
+ }
244
+ return currentLocator;
245
+ }
246
+ function provideServiceLocator2(locator) {
247
+ const original = currentLocator;
248
+ currentLocator = locator;
249
+ return original;
250
+ }
251
+ function inject2(token, args) {
252
+ const realToken = token[InjectableTokenMeta] ?? token;
253
+ return getServiceLocator().getOrThrowInstance(realToken, args);
254
+ }
255
+ let promiseCollector = null;
256
+ function wrapSyncInit2(cb) {
257
+ return () => {
258
+ const promises = [];
259
+ const originalPromiseCollector = promiseCollector;
260
+ promiseCollector = (promise) => {
261
+ promises.push(promise);
262
+ };
263
+ const result = cb();
264
+ promiseCollector = originalPromiseCollector;
265
+ return [result, promises];
266
+ };
267
+ }
268
+ function syncInject2(token, args) {
269
+ const realToken = token[InjectableTokenMeta] ?? token;
270
+ const instance = getServiceLocator().getSyncInstance(realToken, args);
271
+ if (!instance) {
272
+ if (promiseCollector) {
273
+ const promise = getServiceLocator().getInstance(realToken, args);
274
+ promiseCollector(promise);
275
+ } else {
276
+ throw new Error(`[Injector] Cannot initiate ${realToken.toString()}`);
277
+ }
278
+ return new Proxy(
279
+ {},
280
+ {
281
+ get() {
282
+ throw new Error(
283
+ `[Injector] Trying to access ${realToken.toString()} before it's initialized, please use inject() instead of syncInject() or do not use the value outside of class methods`
284
+ );
285
+ }
286
+ }
287
+ );
288
+ }
289
+ return instance;
290
+ }
291
+ const injectors = {
292
+ inject: inject2,
293
+ syncInject: syncInject2,
294
+ wrapSyncInit: wrapSyncInit2,
295
+ provideServiceLocator: provideServiceLocator2
296
+ };
297
+ InjectorsBase.set(baseLocator, injectors);
298
+ return injectors;
245
299
  }
246
300
 
247
- //#endregion
248
- //#region src/utils/get-injectable-token.mts
301
+ // src/utils/get-injectable-token.mts
249
302
  function getInjectableToken(target) {
250
- const token = target[InjectableTokenMeta];
251
- if (!token) throw new Error(`[ServiceLocator] Class ${target.name} is not decorated with @Injectable.`);
252
- return token;
303
+ const token = target[InjectableTokenMeta];
304
+ if (!token) {
305
+ throw new Error(
306
+ `[ServiceLocator] Class ${target.name} is not decorated with @Injectable.`
307
+ );
308
+ }
309
+ return token;
253
310
  }
254
311
 
255
- //#endregion
256
- //#region src/resolve-service.mts
312
+ // src/resolve-service.mts
257
313
  async function resolveService(ctx, target, args = []) {
258
- const proxyServiceLocator = makeProxyServiceLocator(ctx.locator, ctx);
259
- const { wrapSyncInit: wrapSyncInit$1, provideServiceLocator: provideServiceLocator$1 } = getInjectors({ baseLocator: ctx.locator });
260
- const tryLoad = wrapSyncInit$1(() => {
261
- const original = provideServiceLocator$1(proxyServiceLocator);
262
- let result = new target(...args);
263
- provideServiceLocator$1(original);
264
- return result;
265
- });
266
- let [instance, promises] = tryLoad();
267
- if (promises.length > 0) {
268
- await Promise.all(promises);
269
- const newRes = tryLoad();
270
- instance = newRes[0];
271
- promises = newRes[1];
272
- }
273
- if (promises.length > 0) {
274
- console.error(`[ServiceLocator] ${target.name} has problem with it's definition.
314
+ const { wrapSyncInit: wrapSyncInit2, provideServiceLocator: provideServiceLocator2 } = getInjectors({
315
+ baseLocator: ctx.locator
316
+ });
317
+ const proxyServiceLocator = makeProxyServiceLocator(ctx.locator, ctx);
318
+ const tryLoad = wrapSyncInit2(() => {
319
+ const original = provideServiceLocator2(proxyServiceLocator);
320
+ let result = new target(...args);
321
+ provideServiceLocator2(original);
322
+ return result;
323
+ });
324
+ let [instance, promises] = tryLoad();
325
+ if (promises.length > 0) {
326
+ await Promise.allSettled(promises);
327
+ const newRes = tryLoad();
328
+ instance = newRes[0];
329
+ promises = newRes[1];
330
+ }
331
+ if (promises.length > 0) {
332
+ console.error(`[ServiceLocator] ${target.name} has problem with it's definition.
275
333
 
276
334
  One or more of the dependencies are registered as a InjectableScope.Instance and are used with syncInject.
277
335
 
278
336
  Please use inject instead of syncInject to load those dependencies.`);
279
- throw new Error(`[ServiceLocator] Service ${target.name} cannot be instantiated.`);
280
- }
281
- return instance;
337
+ throw new Error(
338
+ `[ServiceLocator] Service ${target.name} cannot be instantiated.`
339
+ );
340
+ }
341
+ return instance;
282
342
  }
283
343
 
284
- //#endregion
285
- //#region src/decorators/injectable.decorator.mts
286
- function Injectable({ scope = InjectableScope.Singleton, type = InjectableType.Class, token, registry = globalRegistry } = {}) {
287
- return (target, context) => {
288
- if (context.kind !== "class") throw new Error("[ServiceLocator] @Injectable decorator can only be used on classes.");
289
- let injectableToken = token ?? InjectionToken.create(target);
290
- if (type === InjectableType.Class) registry.set(injectableToken, async (ctx, args) => resolveService(ctx, target, [args]), scope);
291
- else if (type === InjectableType.Factory) registry.set(injectableToken, async (ctx, args) => {
292
- const builder = await resolveService(ctx, target);
293
- if (typeof builder.create !== "function") throw new Error(`[ServiceLocator] Factory ${target.name} does not implement the create method.`);
294
- return builder.create(ctx, args);
295
- }, scope);
296
- target[InjectableTokenMeta] = injectableToken;
297
- return target;
298
- };
344
+ // src/decorators/injectable.decorator.mts
345
+ function Injectable({
346
+ scope = "Singleton" /* Singleton */,
347
+ type = "Class" /* Class */,
348
+ token,
349
+ registry = globalRegistry
350
+ } = {}) {
351
+ return (target, context) => {
352
+ if (context.kind !== "class") {
353
+ throw new Error(
354
+ "[ServiceLocator] @Injectable decorator can only be used on classes."
355
+ );
356
+ }
357
+ let injectableToken = token ?? InjectionToken.create(target);
358
+ if (type === "Class" /* Class */) {
359
+ registry.set(
360
+ injectableToken,
361
+ async (ctx, args) => resolveService(ctx, target, [args]),
362
+ scope
363
+ );
364
+ } else if (type === "Factory" /* Factory */) {
365
+ registry.set(
366
+ injectableToken,
367
+ async (ctx, args) => {
368
+ const builder = await resolveService(ctx, target);
369
+ if (typeof builder.create !== "function") {
370
+ throw new Error(
371
+ `[ServiceLocator] Factory ${target.name} does not implement the create method.`
372
+ );
373
+ }
374
+ return builder.create(ctx, args);
375
+ },
376
+ scope
377
+ );
378
+ }
379
+ target[InjectableTokenMeta] = injectableToken;
380
+ return target;
381
+ };
299
382
  }
300
383
 
301
- //#endregion
302
- //#region src/errors/errors.enum.mts
303
- let ErrorsEnum = /* @__PURE__ */ function(ErrorsEnum$1) {
304
- ErrorsEnum$1["InstanceExpired"] = "InstanceExpired";
305
- ErrorsEnum$1["InstanceNotFound"] = "InstanceNotFound";
306
- ErrorsEnum$1["InstanceDestroying"] = "InstanceDestroying";
307
- ErrorsEnum$1["UnknownError"] = "UnknownError";
308
- ErrorsEnum$1["FactoryNotFound"] = "FactoryNotFound";
309
- ErrorsEnum$1["FactoryTokenNotResolved"] = "FactoryTokenNotResolved";
310
- return ErrorsEnum$1;
311
- }({});
384
+ // src/errors/errors.enum.mts
385
+ var ErrorsEnum = /* @__PURE__ */ ((ErrorsEnum2) => {
386
+ ErrorsEnum2["InstanceExpired"] = "InstanceExpired";
387
+ ErrorsEnum2["InstanceNotFound"] = "InstanceNotFound";
388
+ ErrorsEnum2["InstanceDestroying"] = "InstanceDestroying";
389
+ ErrorsEnum2["UnknownError"] = "UnknownError";
390
+ ErrorsEnum2["FactoryNotFound"] = "FactoryNotFound";
391
+ ErrorsEnum2["FactoryTokenNotResolved"] = "FactoryTokenNotResolved";
392
+ return ErrorsEnum2;
393
+ })(ErrorsEnum || {});
312
394
 
313
- //#endregion
314
- //#region src/errors/factory-not-found.mts
395
+ // src/errors/factory-not-found.mts
315
396
  var FactoryNotFound = class extends Error {
316
- code = ErrorsEnum.FactoryNotFound;
317
- constructor(name) {
318
- super(`Factory ${name} not found`);
319
- this.name = name;
320
- }
397
+ constructor(name) {
398
+ super(`Factory ${name} not found`);
399
+ this.name = name;
400
+ }
401
+ code = "FactoryNotFound" /* FactoryNotFound */;
321
402
  };
322
403
 
323
- //#endregion
324
- //#region src/errors/factory-token-not-resolved.mts
404
+ // src/errors/factory-token-not-resolved.mts
325
405
  var FactoryTokenNotResolved = class extends Error {
326
- code = ErrorsEnum.FactoryTokenNotResolved;
327
- constructor(name) {
328
- super(`Factory token not resolved: ${name.toString()}`);
329
- }
406
+ code = "FactoryTokenNotResolved" /* FactoryTokenNotResolved */;
407
+ constructor(name) {
408
+ super(`Factory token not resolved: ${name.toString()}`);
409
+ }
330
410
  };
331
411
 
332
- //#endregion
333
- //#region src/errors/instance-destroying.mts
412
+ // src/errors/instance-destroying.mts
334
413
  var InstanceDestroying = class extends Error {
335
- code = ErrorsEnum.InstanceDestroying;
336
- constructor(name) {
337
- super(`Instance ${name} destroying`);
338
- this.name = name;
339
- }
414
+ constructor(name) {
415
+ super(`Instance ${name} destroying`);
416
+ this.name = name;
417
+ }
418
+ code = "InstanceDestroying" /* InstanceDestroying */;
340
419
  };
341
420
 
342
- //#endregion
343
- //#region src/errors/instance-expired.mts
421
+ // src/errors/instance-expired.mts
344
422
  var InstanceExpired = class extends Error {
345
- code = ErrorsEnum.InstanceExpired;
346
- constructor(name) {
347
- super(`Instance ${name} expired`);
348
- this.name = name;
349
- }
423
+ constructor(name) {
424
+ super(`Instance ${name} expired`);
425
+ this.name = name;
426
+ }
427
+ code = "InstanceExpired" /* InstanceExpired */;
350
428
  };
351
429
 
352
- //#endregion
353
- //#region src/errors/instance-not-found.mts
430
+ // src/errors/instance-not-found.mts
354
431
  var InstanceNotFound = class extends Error {
355
- code = ErrorsEnum.InstanceNotFound;
356
- constructor(name) {
357
- super(`Instance ${name} not found`);
358
- this.name = name;
359
- }
432
+ constructor(name) {
433
+ super(`Instance ${name} not found`);
434
+ this.name = name;
435
+ }
436
+ code = "InstanceNotFound" /* InstanceNotFound */;
360
437
  };
361
438
 
362
- //#endregion
363
- //#region src/errors/unknown-error.mts
439
+ // src/errors/unknown-error.mts
364
440
  var UnknownError = class extends Error {
365
- code = ErrorsEnum.UnknownError;
366
- parent;
367
- constructor(message) {
368
- if (message instanceof Error) {
369
- super(message.message);
370
- this.parent = message;
371
- return;
372
- }
373
- super(message);
374
- }
441
+ code = "UnknownError" /* UnknownError */;
442
+ parent;
443
+ constructor(message) {
444
+ if (message instanceof Error) {
445
+ super(message.message);
446
+ this.parent = message;
447
+ return;
448
+ }
449
+ super(message);
450
+ }
375
451
  };
376
452
 
377
- //#endregion
378
- //#region src/event-emitter.mts
453
+ // src/interfaces/factory.interface.mts
454
+ var import_zod4 = require("zod");
455
+
456
+ // src/event-emitter.mts
379
457
  var EventEmitter = class {
380
- listeners = new Map();
381
- on(event, listener) {
382
- if (!this.listeners.has(event)) this.listeners.set(event, new Set());
383
- this.listeners.get(event).add(listener);
384
- return () => {
385
- this.off(event, listener);
386
- };
387
- }
388
- off(event, listener) {
389
- if (!this.listeners.has(event)) return;
390
- this.listeners.get(event).delete(listener);
391
- if (this.listeners.get(event).size === 0) this.listeners.delete(event);
392
- }
393
- once(event, listener) {
394
- const off = this.on(event, (...args) => {
395
- off();
396
- listener(...args);
397
- });
398
- return off;
399
- }
400
- async emit(event, ...args) {
401
- if (!this.listeners.has(event)) return;
402
- return Promise.all(Array.from(this.listeners.get(event)).map((listener) => listener(...args)));
403
- }
404
- addChannel(ns, event, target) {
405
- return this.on(event, (...args) => target.emit(ns, event, ...args));
406
- }
458
+ listeners = /* @__PURE__ */ new Map();
459
+ on(event, listener) {
460
+ if (!this.listeners.has(event)) {
461
+ this.listeners.set(event, /* @__PURE__ */ new Set());
462
+ }
463
+ this.listeners.get(event).add(listener);
464
+ return () => {
465
+ this.off(event, listener);
466
+ };
467
+ }
468
+ off(event, listener) {
469
+ if (!this.listeners.has(event)) {
470
+ return;
471
+ }
472
+ this.listeners.get(event).delete(listener);
473
+ if (this.listeners.get(event).size === 0) {
474
+ this.listeners.delete(event);
475
+ }
476
+ }
477
+ once(event, listener) {
478
+ const off = this.on(event, (...args) => {
479
+ off();
480
+ listener(...args);
481
+ });
482
+ return off;
483
+ }
484
+ async emit(event, ...args) {
485
+ if (!this.listeners.has(event)) {
486
+ return;
487
+ }
488
+ return Promise.all(Array.from(this.listeners.get(event)).map((listener) => listener(...args)));
489
+ }
490
+ addChannel(ns, event, target) {
491
+ return this.on(event, (...args) => target.emit(ns, event, ...args));
492
+ }
407
493
  };
408
494
 
409
- //#endregion
410
- //#region src/service-locator-event-bus.mts
495
+ // src/service-locator-event-bus.mts
411
496
  var ServiceLocatorEventBus = class {
412
- listeners = new Map();
413
- constructor(logger = null) {
414
- this.logger = logger;
415
- }
416
- on(ns, event, listener) {
417
- this.logger?.debug(`[ServiceLocatorEventBus]#on(): ns:${ns} event:${event}`);
418
- if (!this.listeners.has(ns)) this.listeners.set(ns, new Map());
419
- const nsEvents = this.listeners.get(ns);
420
- if (!nsEvents.has(event)) nsEvents.set(event, new Set());
421
- nsEvents.get(event).add(listener);
422
- return () => {
423
- nsEvents.get(event).delete(listener);
424
- if (nsEvents.get(event)?.size === 0) nsEvents.delete(event);
425
- if (nsEvents.size === 0) this.listeners.delete(ns);
426
- };
427
- }
428
- async emit(key, event) {
429
- if (!this.listeners.has(key)) return;
430
- const events = this.listeners.get(key);
431
- const preEvent = `pre:${event}`;
432
- const postEvent = `post:${event}`;
433
- this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${preEvent}`);
434
- await Promise.allSettled([...events.get(preEvent) ?? []].map((listener) => listener(preEvent))).then((results) => {
435
- results.filter((result) => result.status === "rejected").forEach((result) => {
436
- this.logger?.warn(`[ServiceLocatorEventBus]#emit(): ${key}:${preEvent} rejected with`, result.reason);
437
- });
438
- });
439
- this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${event}`);
440
- const res = await Promise.allSettled([...events.get(event) ?? []].map((listener) => listener(event))).then((results) => {
441
- const res$1 = results.filter((result) => result.status === "rejected").map((result) => {
442
- this.logger?.warn(`[ServiceLocatorEventBus]#emit(): ${key}:${event} rejected with`, result.reason);
443
- return result;
444
- });
445
- if (res$1.length > 0) return Promise.reject(res$1);
446
- return results;
447
- });
448
- this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${postEvent}`);
449
- await Promise.allSettled([...events.get(postEvent) ?? []].map((listener) => listener(postEvent))).then((results) => {
450
- results.filter((result) => result.status === "rejected").forEach((result) => {
451
- this.logger?.warn(`[ServiceLocatorEventBus]#emit(): ${key}:${postEvent} rejected with`, result.reason);
452
- });
453
- });
454
- return res;
455
- }
497
+ constructor(logger = null) {
498
+ this.logger = logger;
499
+ }
500
+ listeners = /* @__PURE__ */ new Map();
501
+ on(ns, event, listener) {
502
+ this.logger?.debug(`[ServiceLocatorEventBus]#on(): ns:${ns} event:${event}`);
503
+ if (!this.listeners.has(ns)) {
504
+ this.listeners.set(ns, /* @__PURE__ */ new Map());
505
+ }
506
+ const nsEvents = this.listeners.get(ns);
507
+ if (!nsEvents.has(event)) {
508
+ nsEvents.set(event, /* @__PURE__ */ new Set());
509
+ }
510
+ nsEvents.get(event).add(listener);
511
+ return () => {
512
+ nsEvents.get(event).delete(listener);
513
+ if (nsEvents.get(event)?.size === 0) {
514
+ nsEvents.delete(event);
515
+ }
516
+ if (nsEvents.size === 0) {
517
+ this.listeners.delete(ns);
518
+ }
519
+ };
520
+ }
521
+ async emit(key, event) {
522
+ if (!this.listeners.has(key)) {
523
+ return;
524
+ }
525
+ const events = this.listeners.get(key);
526
+ const preEvent = `pre:${event}`;
527
+ const postEvent = `post:${event}`;
528
+ this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${preEvent}`);
529
+ await Promise.allSettled(
530
+ [...events.get(preEvent) ?? []].map((listener) => listener(preEvent))
531
+ ).then((results) => {
532
+ results.filter((result) => result.status === "rejected").forEach((result) => {
533
+ this.logger?.warn(
534
+ `[ServiceLocatorEventBus]#emit(): ${key}:${preEvent} rejected with`,
535
+ result.reason
536
+ );
537
+ });
538
+ });
539
+ this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${event}`);
540
+ const res = await Promise.allSettled(
541
+ [...events.get(event) ?? []].map((listener) => listener(event))
542
+ ).then((results) => {
543
+ const res2 = results.filter((result) => result.status === "rejected").map((result) => {
544
+ this.logger?.warn(
545
+ `[ServiceLocatorEventBus]#emit(): ${key}:${event} rejected with`,
546
+ result.reason
547
+ );
548
+ return result;
549
+ });
550
+ if (res2.length > 0) {
551
+ return Promise.reject(res2);
552
+ }
553
+ return results;
554
+ });
555
+ this.logger?.debug(`[ServiceLocatorEventBus]#emit(): ${key}:${postEvent}`);
556
+ await Promise.allSettled(
557
+ [...events.get(postEvent) ?? []].map((listener) => listener(postEvent))
558
+ ).then((results) => {
559
+ results.filter((result) => result.status === "rejected").forEach((result) => {
560
+ this.logger?.warn(
561
+ `[ServiceLocatorEventBus]#emit(): ${key}:${postEvent} rejected with`,
562
+ result.reason
563
+ );
564
+ });
565
+ });
566
+ return res;
567
+ }
456
568
  };
457
569
 
458
- //#endregion
459
- //#region src/service-locator-instance-holder.mts
460
- let ServiceLocatorInstanceHolderKind = /* @__PURE__ */ function(ServiceLocatorInstanceHolderKind$1) {
461
- ServiceLocatorInstanceHolderKind$1["Instance"] = "instance";
462
- ServiceLocatorInstanceHolderKind$1["Factory"] = "factory";
463
- ServiceLocatorInstanceHolderKind$1["AbstractFactory"] = "abstractFactory";
464
- return ServiceLocatorInstanceHolderKind$1;
465
- }({});
466
- let ServiceLocatorInstanceHolderStatus = /* @__PURE__ */ function(ServiceLocatorInstanceHolderStatus$1) {
467
- ServiceLocatorInstanceHolderStatus$1["Created"] = "created";
468
- ServiceLocatorInstanceHolderStatus$1["Creating"] = "creating";
469
- ServiceLocatorInstanceHolderStatus$1["Destroying"] = "destroying";
470
- return ServiceLocatorInstanceHolderStatus$1;
471
- }({});
570
+ // src/service-locator-instance-holder.mts
571
+ var ServiceLocatorInstanceHolderKind = /* @__PURE__ */ ((ServiceLocatorInstanceHolderKind2) => {
572
+ ServiceLocatorInstanceHolderKind2["Instance"] = "instance";
573
+ ServiceLocatorInstanceHolderKind2["Factory"] = "factory";
574
+ ServiceLocatorInstanceHolderKind2["AbstractFactory"] = "abstractFactory";
575
+ return ServiceLocatorInstanceHolderKind2;
576
+ })(ServiceLocatorInstanceHolderKind || {});
577
+ var ServiceLocatorInstanceHolderStatus = /* @__PURE__ */ ((ServiceLocatorInstanceHolderStatus2) => {
578
+ ServiceLocatorInstanceHolderStatus2["Created"] = "created";
579
+ ServiceLocatorInstanceHolderStatus2["Creating"] = "creating";
580
+ ServiceLocatorInstanceHolderStatus2["Destroying"] = "destroying";
581
+ return ServiceLocatorInstanceHolderStatus2;
582
+ })(ServiceLocatorInstanceHolderStatus || {});
472
583
 
473
- //#endregion
474
- //#region src/service-locator-manager.mts
584
+ // src/service-locator-manager.mts
475
585
  var ServiceLocatorManager = class {
476
- instancesHolders = new Map();
477
- constructor(logger = null) {
478
- this.logger = logger;
479
- }
480
- get(name) {
481
- const holder = this.instancesHolders.get(name);
482
- if (holder) {
483
- if (holder.ttl !== Infinity) {
484
- const now = Date.now();
485
- if (now - holder.createdAt > holder.ttl) {
486
- this.logger?.log(`[ServiceLocatorManager]#getInstanceHolder() TTL expired for ${holder.name}`);
487
- return [new InstanceExpired(holder.name), holder];
488
- }
489
- } else if (holder.status === ServiceLocatorInstanceHolderStatus.Destroying) {
490
- this.logger?.log(`[ServiceLocatorManager]#getInstanceHolder() Instance ${holder.name} is destroying`);
491
- return [new InstanceDestroying(holder.name), holder];
492
- }
493
- return [void 0, holder];
494
- } else {
495
- this.logger?.log(`[ServiceLocatorManager]#getInstanceHolder() Instance ${name} not found`);
496
- return [new InstanceNotFound(name)];
497
- }
498
- }
499
- set(name, holder) {
500
- this.instancesHolders.set(name, holder);
501
- }
502
- has(name) {
503
- const [error, holder] = this.get(name);
504
- if (!error) return [void 0, true];
505
- if ([ErrorsEnum.InstanceExpired, ErrorsEnum.InstanceDestroying].includes(error.code)) return [error];
506
- return [void 0, !!holder];
507
- }
508
- delete(name) {
509
- return this.instancesHolders.delete(name);
510
- }
511
- filter(predicate) {
512
- return new Map([...this.instancesHolders].filter(([key, value]) => predicate(value, key)));
513
- }
586
+ constructor(logger = null) {
587
+ this.logger = logger;
588
+ }
589
+ instancesHolders = /* @__PURE__ */ new Map();
590
+ get(name) {
591
+ const holder = this.instancesHolders.get(name);
592
+ if (holder) {
593
+ if (holder.ttl !== Infinity) {
594
+ const now = Date.now();
595
+ if (now - holder.createdAt > holder.ttl) {
596
+ this.logger?.log(
597
+ `[ServiceLocatorManager]#getInstanceHolder() TTL expired for ${holder.name}`
598
+ );
599
+ return [new InstanceExpired(holder.name), holder];
600
+ }
601
+ } else if (holder.status === "destroying" /* Destroying */) {
602
+ this.logger?.log(
603
+ `[ServiceLocatorManager]#getInstanceHolder() Instance ${holder.name} is destroying`
604
+ );
605
+ return [new InstanceDestroying(holder.name), holder];
606
+ }
607
+ return [void 0, holder];
608
+ } else {
609
+ this.logger?.log(
610
+ `[ServiceLocatorManager]#getInstanceHolder() Instance ${name} not found`
611
+ );
612
+ return [new InstanceNotFound(name)];
613
+ }
614
+ }
615
+ set(name, holder) {
616
+ this.instancesHolders.set(name, holder);
617
+ }
618
+ has(name) {
619
+ const [error, holder] = this.get(name);
620
+ if (!error) {
621
+ return [void 0, true];
622
+ }
623
+ if (["InstanceExpired" /* InstanceExpired */, "InstanceDestroying" /* InstanceDestroying */].includes(
624
+ error.code
625
+ )) {
626
+ return [error];
627
+ }
628
+ return [void 0, !!holder];
629
+ }
630
+ delete(name) {
631
+ return this.instancesHolders.delete(name);
632
+ }
633
+ filter(predicate) {
634
+ return new Map(
635
+ [...this.instancesHolders].filter(
636
+ ([key, value]) => predicate(value, key)
637
+ )
638
+ );
639
+ }
514
640
  };
515
641
 
516
- //#endregion
517
- //#region src/service-locator.mts
642
+ // src/service-locator.mts
518
643
  var ServiceLocator = class {
519
- eventBus;
520
- manager;
521
- constructor(registry = globalRegistry, logger = null) {
522
- this.registry = registry;
523
- this.logger = logger;
524
- this.eventBus = new ServiceLocatorEventBus(logger);
525
- this.manager = new ServiceLocatorManager(logger);
526
- }
527
- getEventBus() {
528
- return this.eventBus;
529
- }
530
- storeInstance(instance, token, args) {
531
- const instanceName = this.getInstanceIdentifier(token, args);
532
- this.manager.set(instanceName, {
533
- name: instanceName,
534
- instance,
535
- status: ServiceLocatorInstanceHolderStatus.Created,
536
- kind: ServiceLocatorInstanceHolderKind.Instance,
537
- createdAt: Date.now(),
538
- ttl: Infinity,
539
- deps: [],
540
- destroyListeners: [],
541
- effects: [],
542
- destroyPromise: null,
543
- creationPromise: null
544
- });
545
- this.notifyListeners(instanceName);
546
- }
547
- removeInstance(token, args) {
548
- const instanceName = this.getInstanceIdentifier(token, args);
549
- return this.invalidate(instanceName);
550
- }
551
- resolveTokenArgs(token, args) {
552
- let realArgs = args;
553
- if (token instanceof BoundInjectionToken) realArgs = token.value;
554
- else if (token instanceof FactoryInjectionToken) if (token.resolved) realArgs = token.value;
555
- else return [new FactoryTokenNotResolved(token.name)];
556
- if (!token.schema) return [void 0, realArgs];
557
- const validatedArgs = token.schema?.safeParse(realArgs);
558
- if (validatedArgs && !validatedArgs.success) {
559
- this.logger?.error(`[ServiceLocator]#getInstance(): Error validating args for ${token.name.toString()}`, validatedArgs.error);
560
- return [new UnknownError(validatedArgs.error)];
561
- }
562
- return [void 0, validatedArgs?.data];
563
- }
564
- getInstanceIdentifier(token, args) {
565
- const [err, realArgs] = this.resolveTokenArgs(token, args);
566
- if (err) throw err;
567
- return this.makeInstanceName(token, realArgs);
568
- }
569
- async getInstance(token, args) {
570
- const [err, realArgs] = this.resolveTokenArgs(token, args);
571
- if (err instanceof UnknownError) return [err];
572
- else if (err instanceof FactoryTokenNotResolved && token instanceof FactoryInjectionToken) {
573
- await token.resolve();
574
- return this.getInstance(token, args);
575
- }
576
- const instanceName = this.makeInstanceName(token, realArgs);
577
- const [error, holder] = this.manager.get(instanceName);
578
- if (!error) {
579
- if (holder.status === ServiceLocatorInstanceHolderStatus.Creating) return holder.creationPromise;
580
- else if (holder.status === ServiceLocatorInstanceHolderStatus.Destroying) return [new UnknownError(ErrorsEnum.InstanceDestroying)];
581
- return [void 0, holder.instance];
582
- }
583
- switch (error.code) {
584
- case ErrorsEnum.InstanceDestroying:
585
- this.logger?.log(`[ServiceLocator]#getInstance() TTL expired for ${holder?.name}`);
586
- await holder?.destroyPromise;
587
- return this.getInstance(token, args);
588
- case ErrorsEnum.InstanceExpired:
589
- this.logger?.log(`[ServiceLocator]#getInstance() TTL expired for ${holder?.name}`);
590
- await this.invalidate(instanceName);
591
- return this.getInstance(token, args);
592
- case ErrorsEnum.InstanceNotFound: break;
593
- default: return [error];
594
- }
595
- return this.createInstance(instanceName, token, realArgs);
596
- }
597
- async getOrThrowInstance(token, args) {
598
- const [error, instance] = await this.getInstance(token, args);
599
- if (error) throw error;
600
- return instance;
601
- }
602
- notifyListeners(name, event = "create") {
603
- this.logger?.log(`[ServiceLocator]#notifyListeners() Notifying listeners for ${name} with event ${event}`);
604
- return this.eventBus.emit(name, event);
605
- }
606
- async createInstance(instanceName, token, args) {
607
- this.logger?.log(`[ServiceLocator]#createInstance() Creating instance for ${instanceName}`);
608
- let realToken = token instanceof BoundInjectionToken || token instanceof FactoryInjectionToken ? token.token : token;
609
- if (this.registry.has(realToken)) return this.resolveInstance(instanceName, realToken, args);
610
- else return [new FactoryNotFound(realToken.name.toString())];
611
- }
612
- async resolveInstance(instanceName, token, args) {
613
- this.logger?.log(`[ServiceLocator]#resolveInstance(): Creating instance for ${instanceName} from abstract factory`);
614
- const ctx = this.createFactoryContext(instanceName);
615
- let { factory, scope } = this.registry.get(token);
616
- const holder = {
617
- name: instanceName,
618
- instance: null,
619
- status: ServiceLocatorInstanceHolderStatus.Creating,
620
- kind: ServiceLocatorInstanceHolderKind.AbstractFactory,
621
- creationPromise: factory(ctx, args).then(async (instance) => {
622
- holder.instance = instance;
623
- holder.status = ServiceLocatorInstanceHolderStatus.Created;
624
- holder.deps = ctx.getDependencies();
625
- holder.destroyListeners = ctx.getDestroyListeners();
626
- holder.ttl = ctx.getTtl();
627
- if (holder.deps.length > 0) {
628
- this.logger?.log(`[ServiceLocator]#createInstanceFromAbstractFactory(): Adding subscriptions for ${instanceName} dependencies for their invalidations: ${holder.deps.join(", ")}`);
629
- holder.deps.forEach((dependency) => {
630
- holder.destroyListeners.push(this.eventBus.on(dependency, "destroy", () => this.invalidate(instanceName)));
631
- });
632
- }
633
- if (holder.ttl === 0 || scope === InjectableScope.Instance) await this.invalidate(instanceName);
634
- await this.notifyListeners(instanceName);
635
- return [void 0, instance];
636
- }).catch((error) => {
637
- this.logger?.error(`[ServiceLocator]#createInstanceFromAbstractFactory(): Error creating instance for ${instanceName}`, error);
638
- return [new UnknownError(error)];
639
- }),
640
- effects: [],
641
- deps: [],
642
- destroyListeners: [],
643
- createdAt: Date.now(),
644
- ttl: Infinity
645
- };
646
- if (scope === InjectableScope.Singleton) this.manager.set(instanceName, holder);
647
- return holder.creationPromise;
648
- }
649
- createFactoryContext(instanceName) {
650
- const dependencies = new Set();
651
- const destroyListeners = new Set();
652
- const self = this;
653
- function invalidate(name = instanceName) {
654
- return self.invalidate(name);
655
- }
656
- function addEffect(listener) {
657
- destroyListeners.add(listener);
658
- }
659
- let ttl = Infinity;
660
- function setTtl(value) {
661
- ttl = value;
662
- }
663
- function getTtl() {
664
- return ttl;
665
- }
666
- function on(key, event, listener) {
667
- destroyListeners.add(self.eventBus.on(key, event, listener));
668
- }
669
- return {
670
- async inject(token, args) {
671
- let injectionToken = token;
672
- if (typeof token === "function") injectionToken = getInjectableToken(token);
673
- if (injectionToken instanceof InjectionToken) {
674
- const validatedArgs = token.schema ? token.schema.safeParse(args) : void 0;
675
- const instanceName$1 = self.makeInstanceName(token, validatedArgs);
676
- dependencies.add(instanceName$1);
677
- return self.getOrThrowInstance(injectionToken, args);
678
- }
679
- throw new Error(`[ServiceLocator]#inject(): Invalid token type: ${typeof token}. Expected a class or an InjectionToken.`);
680
- },
681
- invalidate,
682
- on,
683
- getDependencies: () => Array.from(dependencies),
684
- addEffect,
685
- getDestroyListeners: () => Array.from(destroyListeners),
686
- setTtl,
687
- getTtl,
688
- locator: self
689
- };
690
- }
691
- getSyncInstance(token, args) {
692
- const [err, realArgs] = this.resolveTokenArgs(token, args);
693
- if (err) return null;
694
- const instanceName = this.makeInstanceName(token, realArgs);
695
- const [error, holder] = this.manager.get(instanceName);
696
- if (error) return null;
697
- return holder.instance;
698
- }
699
- invalidate(service, round = 1) {
700
- this.logger?.log(`[ServiceLocator]#invalidate(): Starting Invalidating process of ${service}`);
701
- const toInvalidate = this.manager.filter((holder) => holder.name === service || holder.deps.includes(service));
702
- const promises = [];
703
- for (const [key, holder] of toInvalidate.entries()) {
704
- if (holder.status === ServiceLocatorInstanceHolderStatus.Destroying) {
705
- this.logger?.trace(`[ServiceLocator]#invalidate(): ${key} is already being destroyed`);
706
- promises.push(holder.destroyPromise);
707
- continue;
708
- }
709
- if (holder.status === ServiceLocatorInstanceHolderStatus.Creating) {
710
- this.logger?.trace(`[ServiceLocator]#invalidate(): ${key} is being created, waiting for creation to finish`);
711
- promises.push(holder.creationPromise?.then(() => {
712
- if (round > 3) {
713
- this.logger?.error(`[ServiceLocator]#invalidate(): ${key} creation is triggering a new invalidation round, but it is still not created`);
714
- return;
715
- }
716
- return this.invalidate(key, round + 1);
717
- }));
718
- continue;
719
- }
720
- holder.status = ServiceLocatorInstanceHolderStatus.Destroying;
721
- this.logger?.log(`[ServiceLocator]#invalidate(): Invalidating ${key} and notifying listeners`);
722
- holder.destroyPromise = Promise.all(holder.destroyListeners.map((listener) => listener())).then(async () => {
723
- this.manager.delete(key);
724
- await this.notifyListeners(key, "destroy");
725
- });
726
- promises.push(holder.destroyPromise);
727
- }
728
- return Promise.all(promises);
729
- }
730
- async ready() {
731
- return Promise.all(Array.from(this.manager.filter(() => true)).map(([, holder]) => {
732
- if (holder.status === ServiceLocatorInstanceHolderStatus.Creating) return holder.creationPromise?.then(() => null);
733
- if (holder.status === ServiceLocatorInstanceHolderStatus.Destroying) return holder.destroyPromise.then(() => null);
734
- return Promise.resolve(null);
735
- })).then(() => null);
736
- }
737
- makeInstanceName(token, args) {
738
- const formattedArgs = args ? ":" + JSON.stringify(args, (_, value) => {
739
- if (typeof value === "function") return `function:${value.name}(${value.length})`;
740
- if (typeof value === "symbol") return value.toString();
741
- return value;
742
- }).replaceAll(/"/g, "").replaceAll(/:/g, "=").replaceAll(/,/g, "|") : "";
743
- return `${token.toString()}${formattedArgs}`;
744
- }
644
+ constructor(registry = globalRegistry, logger = null) {
645
+ this.registry = registry;
646
+ this.logger = logger;
647
+ this.eventBus = new ServiceLocatorEventBus(logger);
648
+ this.manager = new ServiceLocatorManager(logger);
649
+ }
650
+ eventBus;
651
+ manager;
652
+ getEventBus() {
653
+ return this.eventBus;
654
+ }
655
+ storeInstance(instance, token, args) {
656
+ const instanceName = this.getInstanceIdentifier(token, args);
657
+ this.manager.set(instanceName, {
658
+ name: instanceName,
659
+ instance,
660
+ status: "created" /* Created */,
661
+ kind: "instance" /* Instance */,
662
+ createdAt: Date.now(),
663
+ ttl: Infinity,
664
+ deps: [],
665
+ destroyListeners: [],
666
+ effects: [],
667
+ destroyPromise: null,
668
+ creationPromise: null
669
+ });
670
+ this.notifyListeners(instanceName);
671
+ }
672
+ removeInstance(token, args) {
673
+ const instanceName = this.getInstanceIdentifier(token, args);
674
+ return this.invalidate(instanceName);
675
+ }
676
+ resolveTokenArgs(token, args) {
677
+ let realArgs = args;
678
+ if (token instanceof BoundInjectionToken) {
679
+ realArgs = token.value;
680
+ } else if (token instanceof FactoryInjectionToken) {
681
+ if (token.resolved) {
682
+ realArgs = token.value;
683
+ } else {
684
+ return [new FactoryTokenNotResolved(token.name)];
685
+ }
686
+ }
687
+ if (!token.schema) {
688
+ return [void 0, realArgs];
689
+ }
690
+ const validatedArgs = token.schema?.safeParse(realArgs);
691
+ if (validatedArgs && !validatedArgs.success) {
692
+ this.logger?.error(
693
+ `[ServiceLocator]#resolveTokenArgs(): Error validating args for ${token.name.toString()}`,
694
+ validatedArgs.error
695
+ );
696
+ return [new UnknownError(validatedArgs.error)];
697
+ }
698
+ return [void 0, validatedArgs?.data];
699
+ }
700
+ getInstanceIdentifier(token, args) {
701
+ const [err, realArgs] = this.resolveTokenArgs(
702
+ token,
703
+ args
704
+ );
705
+ if (err) {
706
+ throw err;
707
+ }
708
+ return this.makeInstanceName(token, realArgs);
709
+ }
710
+ async getInstance(token, args) {
711
+ const [err, realArgs] = this.resolveTokenArgs(token, args);
712
+ if (err instanceof UnknownError) {
713
+ return [err];
714
+ } else if (err instanceof FactoryTokenNotResolved && token instanceof FactoryInjectionToken) {
715
+ this.logger?.log(
716
+ `[ServiceLocator]#getInstance() Factory token not resolved, resolving it`
717
+ );
718
+ await token.resolve();
719
+ return this.getInstance(token);
720
+ }
721
+ const instanceName = this.makeInstanceName(token, realArgs);
722
+ const [error, holder] = this.manager.get(instanceName);
723
+ if (!error) {
724
+ if (holder.status === "creating" /* Creating */) {
725
+ return holder.creationPromise;
726
+ } else if (holder.status === "destroying" /* Destroying */) {
727
+ return [new UnknownError("InstanceDestroying" /* InstanceDestroying */)];
728
+ }
729
+ return [void 0, holder.instance];
730
+ }
731
+ switch (error.code) {
732
+ case "InstanceDestroying" /* InstanceDestroying */:
733
+ this.logger?.log(
734
+ `[ServiceLocator]#getInstance() TTL expired for ${holder?.name}`
735
+ );
736
+ await holder?.destroyPromise;
737
+ return this.getInstance(token, args);
738
+ case "InstanceExpired" /* InstanceExpired */:
739
+ this.logger?.log(
740
+ `[ServiceLocator]#getInstance() TTL expired for ${holder?.name}`
741
+ );
742
+ await this.invalidate(instanceName);
743
+ return this.getInstance(token, args);
744
+ case "InstanceNotFound" /* InstanceNotFound */:
745
+ break;
746
+ default:
747
+ return [error];
748
+ }
749
+ return this.createInstance(instanceName, token, realArgs);
750
+ }
751
+ async getOrThrowInstance(token, args) {
752
+ const [error, instance] = await this.getInstance(token, args);
753
+ if (error) {
754
+ throw error;
755
+ }
756
+ return instance;
757
+ }
758
+ notifyListeners(name, event = "create") {
759
+ this.logger?.log(
760
+ `[ServiceLocator]#notifyListeners() Notifying listeners for ${name} with event ${event}`
761
+ );
762
+ return this.eventBus.emit(name, event);
763
+ }
764
+ async createInstance(instanceName, token, args) {
765
+ this.logger?.log(
766
+ `[ServiceLocator]#createInstance() Creating instance for ${instanceName}`
767
+ );
768
+ let realToken = token instanceof BoundInjectionToken || token instanceof FactoryInjectionToken ? token.token : token;
769
+ if (this.registry.has(realToken)) {
770
+ return this.resolveInstance(instanceName, realToken, args);
771
+ } else {
772
+ return [new FactoryNotFound(realToken.name.toString())];
773
+ }
774
+ }
775
+ resolveInstance(instanceName, token, args) {
776
+ this.logger?.log(
777
+ `[ServiceLocator]#resolveInstance(): Creating instance for ${instanceName} from abstract factory`
778
+ );
779
+ const ctx = this.createFactoryContext(instanceName);
780
+ let { factory, scope } = this.registry.get(token);
781
+ const holder = {
782
+ name: instanceName,
783
+ instance: null,
784
+ status: "creating" /* Creating */,
785
+ kind: "abstractFactory" /* AbstractFactory */,
786
+ // @ts-expect-error TS2322 This is correct type
787
+ creationPromise: factory(ctx, args).then(async (instance) => {
788
+ holder.instance = instance;
789
+ holder.status = "created" /* Created */;
790
+ holder.deps = ctx.getDependencies();
791
+ holder.destroyListeners = ctx.getDestroyListeners();
792
+ holder.ttl = ctx.getTtl();
793
+ if (holder.deps.length > 0) {
794
+ this.logger?.log(
795
+ `[ServiceLocator]#createInstanceFromAbstractFactory(): Adding subscriptions for ${instanceName} dependencies for their invalidations: ${holder.deps.join(
796
+ ", "
797
+ )}`
798
+ );
799
+ holder.deps.forEach((dependency) => {
800
+ holder.destroyListeners.push(
801
+ this.eventBus.on(
802
+ dependency,
803
+ "destroy",
804
+ () => this.invalidate(instanceName)
805
+ )
806
+ );
807
+ });
808
+ }
809
+ if (holder.ttl === 0 || scope === "Instance" /* Instance */) {
810
+ await this.invalidate(instanceName);
811
+ }
812
+ await this.notifyListeners(instanceName);
813
+ return [void 0, instance];
814
+ }).catch((error) => {
815
+ this.logger?.error(
816
+ `[ServiceLocator]#createInstanceFromAbstractFactory(): Error creating instance for ${instanceName}`,
817
+ error
818
+ );
819
+ return [new UnknownError(error)];
820
+ }),
821
+ effects: [],
822
+ deps: [],
823
+ destroyListeners: [],
824
+ createdAt: Date.now(),
825
+ ttl: Infinity
826
+ };
827
+ if (scope === "Singleton" /* Singleton */) {
828
+ this.logger?.debug(
829
+ `[ServiceLocator]#resolveInstance(): Setting instance for ${instanceName}`
830
+ );
831
+ this.manager.set(instanceName, holder);
832
+ }
833
+ return holder.creationPromise;
834
+ }
835
+ createFactoryContext(instanceName) {
836
+ const dependencies = /* @__PURE__ */ new Set();
837
+ const destroyListeners = /* @__PURE__ */ new Set();
838
+ const self = this;
839
+ function invalidate(name = instanceName) {
840
+ return self.invalidate(name);
841
+ }
842
+ function addEffect(listener) {
843
+ destroyListeners.add(listener);
844
+ }
845
+ let ttl = Infinity;
846
+ function setTtl(value) {
847
+ ttl = value;
848
+ }
849
+ function getTtl() {
850
+ return ttl;
851
+ }
852
+ function on(key, event, listener) {
853
+ destroyListeners.add(self.eventBus.on(key, event, listener));
854
+ }
855
+ return {
856
+ // @ts-expect-error This is correct type
857
+ async inject(token, args) {
858
+ let injectionToken = token;
859
+ if (typeof token === "function") {
860
+ injectionToken = getInjectableToken(token);
861
+ }
862
+ if (injectionToken) {
863
+ const [err, validatedArgs] = self.resolveTokenArgs(
864
+ injectionToken,
865
+ args
866
+ );
867
+ if (err) {
868
+ throw err;
869
+ }
870
+ const instanceName2 = self.makeInstanceName(token, validatedArgs);
871
+ dependencies.add(instanceName2);
872
+ return self.getOrThrowInstance(injectionToken, args);
873
+ }
874
+ throw new Error(
875
+ `[ServiceLocator]#inject(): Invalid token type: ${typeof token}. Expected a class or an InjectionToken.`
876
+ );
877
+ },
878
+ invalidate,
879
+ on,
880
+ getDependencies: () => Array.from(dependencies),
881
+ addEffect,
882
+ getDestroyListeners: () => Array.from(destroyListeners),
883
+ setTtl,
884
+ getTtl,
885
+ locator: self
886
+ };
887
+ }
888
+ getSyncInstance(token, args) {
889
+ const [err, realArgs] = this.resolveTokenArgs(token, args);
890
+ if (err) {
891
+ return null;
892
+ }
893
+ const instanceName = this.makeInstanceName(token, realArgs);
894
+ const [error, holder] = this.manager.get(instanceName);
895
+ if (error) {
896
+ return null;
897
+ }
898
+ return holder.instance;
899
+ }
900
+ invalidate(service, round = 1) {
901
+ this.logger?.log(
902
+ `[ServiceLocator]#invalidate(): Starting Invalidating process of ${service}`
903
+ );
904
+ const toInvalidate = this.manager.filter(
905
+ (holder) => holder.name === service || holder.deps.includes(service)
906
+ );
907
+ const promises = [];
908
+ for (const [key, holder] of toInvalidate.entries()) {
909
+ if (holder.status === "destroying" /* Destroying */) {
910
+ this.logger?.trace(
911
+ `[ServiceLocator]#invalidate(): ${key} is already being destroyed`
912
+ );
913
+ promises.push(holder.destroyPromise);
914
+ continue;
915
+ }
916
+ if (holder.status === "creating" /* Creating */) {
917
+ this.logger?.trace(
918
+ `[ServiceLocator]#invalidate(): ${key} is being created, waiting for creation to finish`
919
+ );
920
+ promises.push(
921
+ holder.creationPromise?.then(() => {
922
+ if (round > 3) {
923
+ this.logger?.error(
924
+ `[ServiceLocator]#invalidate(): ${key} creation is triggering a new invalidation round, but it is still not created`
925
+ );
926
+ return;
927
+ }
928
+ return this.invalidate(key, round + 1);
929
+ })
930
+ );
931
+ continue;
932
+ }
933
+ holder.status = "destroying" /* Destroying */;
934
+ this.logger?.log(
935
+ `[ServiceLocator]#invalidate(): Invalidating ${key} and notifying listeners`
936
+ );
937
+ holder.destroyPromise = Promise.all(
938
+ holder.destroyListeners.map((listener) => listener())
939
+ ).then(async () => {
940
+ this.manager.delete(key);
941
+ await this.notifyListeners(key, "destroy");
942
+ });
943
+ promises.push(holder.destroyPromise);
944
+ }
945
+ return Promise.all(promises);
946
+ }
947
+ async ready() {
948
+ return Promise.all(
949
+ Array.from(this.manager.filter(() => true)).map(([, holder]) => {
950
+ if (holder.status === "creating" /* Creating */) {
951
+ return holder.creationPromise?.then(() => null);
952
+ }
953
+ if (holder.status === "destroying" /* Destroying */) {
954
+ return holder.destroyPromise.then(() => null);
955
+ }
956
+ return Promise.resolve(null);
957
+ })
958
+ ).then(() => null);
959
+ }
960
+ makeInstanceName(token, args) {
961
+ const formattedArgs = args ? ":" + Object.entries(args ?? {}).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)).map(([key, value]) => {
962
+ if (typeof value === "function") {
963
+ return `${key}=fn_${value.name}(${value.length})`;
964
+ }
965
+ if (typeof value === "symbol") {
966
+ return `${key}=${value.toString()}`;
967
+ }
968
+ return `${key}=${JSON.stringify(value).slice(0, 40)}`;
969
+ }).join(",").replaceAll(/"/g, "").replaceAll(/:/g, "=") : "";
970
+ return `${token.toString()}${formattedArgs}`;
971
+ }
745
972
  };
746
973
 
747
- //#endregion
748
- //#region src/injector.mts
749
- const globalServiceLocator = new ServiceLocator();
974
+ // src/injector.mts
975
+ var globalServiceLocator = new ServiceLocator(globalRegistry);
750
976
  function getGlobalServiceLocator() {
751
- if (!globalServiceLocator) throw new Error("[ServiceLocator] Service locator is not initialized. Please provide the service locator before using the @Injectable decorator.");
752
- return globalServiceLocator;
977
+ if (!globalServiceLocator) {
978
+ throw new Error(
979
+ "[ServiceLocator] Service locator is not initialized. Please provide the service locator before using the @Injectable decorator."
980
+ );
981
+ }
982
+ return globalServiceLocator;
753
983
  }
754
- const values = getInjectors({ baseLocator: globalServiceLocator });
755
- const inject = values.inject;
756
- const syncInject = values.syncInject;
757
- const wrapSyncInit = values.wrapSyncInit;
758
- const provideServiceLocator = values.provideServiceLocator;
759
-
760
- //#endregion
761
- exports.BoundInjectionToken = BoundInjectionToken;
762
- exports.ErrorsEnum = ErrorsEnum;
763
- exports.EventEmitter = EventEmitter;
764
- exports.FactoryInjectionToken = FactoryInjectionToken;
765
- exports.FactoryNotFound = FactoryNotFound;
766
- exports.FactoryTokenNotResolved = FactoryTokenNotResolved;
767
- exports.Injectable = Injectable;
768
- exports.InjectableScope = InjectableScope;
769
- exports.InjectableTokenMeta = InjectableTokenMeta;
770
- exports.InjectableType = InjectableType;
771
- exports.InjectionToken = InjectionToken;
772
- exports.InjectorsBase = InjectorsBase;
773
- exports.InstanceDestroying = InstanceDestroying;
774
- exports.InstanceExpired = InstanceExpired;
775
- exports.InstanceNotFound = InstanceNotFound;
776
- exports.Optional = Optional;
777
- exports.ProxyServiceLocator = ProxyServiceLocator;
778
- exports.Registry = Registry;
779
- exports.Required = Required;
780
- exports.ServiceLocator = ServiceLocator;
781
- exports.ServiceLocatorEventBus = ServiceLocatorEventBus;
782
- exports.ServiceLocatorInstanceHolderKind = ServiceLocatorInstanceHolderKind;
783
- exports.ServiceLocatorInstanceHolderStatus = ServiceLocatorInstanceHolderStatus;
784
- exports.ServiceLocatorManager = ServiceLocatorManager;
785
- exports.UnknownError = UnknownError;
786
- exports.getGlobalServiceLocator = getGlobalServiceLocator;
787
- exports.getInjectableToken = getInjectableToken;
788
- exports.getInjectors = getInjectors;
789
- exports.globalRegistry = globalRegistry;
790
- exports.inject = inject;
791
- exports.makeProxyServiceLocator = makeProxyServiceLocator;
792
- exports.provideServiceLocator = provideServiceLocator;
793
- exports.resolveService = resolveService;
794
- exports.syncInject = syncInject;
795
- exports.wrapSyncInit = wrapSyncInit;
984
+ var values = getInjectors({
985
+ baseLocator: globalServiceLocator
986
+ });
987
+ var inject = values.inject;
988
+ var syncInject = values.syncInject;
989
+ var wrapSyncInit = values.wrapSyncInit;
990
+ var provideServiceLocator = values.provideServiceLocator;
991
+ // Annotate the CommonJS export names for ESM import in node:
992
+ 0 && (module.exports = {
993
+ BoundInjectionToken,
994
+ ErrorsEnum,
995
+ EventEmitter,
996
+ FactoryInjectionToken,
997
+ FactoryNotFound,
998
+ FactoryTokenNotResolved,
999
+ Injectable,
1000
+ InjectableScope,
1001
+ InjectableTokenMeta,
1002
+ InjectableType,
1003
+ InjectionToken,
1004
+ InjectorsBase,
1005
+ InstanceDestroying,
1006
+ InstanceExpired,
1007
+ InstanceNotFound,
1008
+ ProxyServiceLocator,
1009
+ Registry,
1010
+ ServiceLocator,
1011
+ ServiceLocatorEventBus,
1012
+ ServiceLocatorInstanceHolderKind,
1013
+ ServiceLocatorInstanceHolderStatus,
1014
+ ServiceLocatorManager,
1015
+ UnknownError,
1016
+ getGlobalServiceLocator,
1017
+ getInjectableToken,
1018
+ getInjectors,
1019
+ globalRegistry,
1020
+ inject,
1021
+ makeProxyServiceLocator,
1022
+ provideServiceLocator,
1023
+ resolveService,
1024
+ syncInject,
1025
+ wrapSyncInit
1026
+ });
1027
+ //# sourceMappingURL=index.js.map