@nextrush/di 3.0.6 → 4.0.0-beta.0

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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import 'reflect-metadata';
2
- import { container as container$1, singleton, injectable, inject as inject$1, delay as delay$1 } from 'tsyringe';
2
+ import { Lifecycle, singleton, injectable, inject as inject$1, delay as delay$1, container as container$1 } from 'tsyringe';
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
5
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
@@ -66,42 +66,6 @@ Strategies to break the cycle:
66
66
  this.cycle = cycle;
67
67
  }
68
68
  };
69
- var TypeInferenceError = class extends DIError {
70
- static {
71
- __name(this, "TypeInferenceError");
72
- }
73
- className;
74
- parameterIndex;
75
- constructor(className, parameterIndex) {
76
- super(`
77
- \u274C Cannot Resolve Constructor Parameter
78
-
79
- ${className} constructor parameter at index ${parameterIndex} has no type information.
80
-
81
- This usually means:
82
- 1. Missing type annotation on the parameter
83
- 2. emitDecoratorMetadata is not enabled in tsconfig.json
84
-
85
- Fix option 1 - Add explicit type annotation:
86
- constructor(private service: ServiceClass) {}
87
- ^^^^^^^^^^^^
88
-
89
- Fix option 2 - Update tsconfig.json:
90
- {
91
- "compilerOptions": {
92
- "experimentalDecorators": true,
93
- "emitDecoratorMetadata": true
94
- }
95
- }
96
-
97
- Fix option 3 - Use explicit @inject():
98
- constructor(@inject(ServiceClass) private service: ServiceClass) {}
99
- `);
100
- this.name = "TypeInferenceError";
101
- this.className = className;
102
- this.parameterIndex = parameterIndex;
103
- }
104
- };
105
69
  var InvalidProviderError = class extends DIError {
106
70
  static {
107
71
  __name(this, "InvalidProviderError");
@@ -120,51 +84,130 @@ A provider must have one of:
120
84
 
121
85
  Example:
122
86
  container.register(MyService, { useClass: MyService });
123
- container.register('CONFIG', { useValue: { port: 3000 } });
87
+ container.register('CONFIG', { useValue: { port: 8080 } });
124
88
  container.register(Logger, { useFactory: () => new Logger() });
125
89
  `);
126
90
  this.name = "InvalidProviderError";
127
91
  this.token = token;
128
92
  }
129
93
  };
130
- var ContainerDisposedError = class extends DIError {
131
- static {
132
- __name(this, "ContainerDisposedError");
133
- }
134
- constructor() {
135
- super(`
136
- \u274C Container Has Been Disposed
137
-
138
- The container has been reset or disposed and cannot resolve dependencies.
139
94
 
140
- If you're in a test environment, ensure you're creating a fresh container
141
- for each test or using container.clearInstances() between tests.
142
- `);
143
- this.name = "ContainerDisposedError";
144
- }
95
+ // src/types.ts
96
+ var METADATA_KEYS = {
97
+ SERVICE_TYPE: "di:type",
98
+ SERVICE_SCOPE: "di:scope",
99
+ INJECT_TOKEN: "di:inject",
100
+ PARAM_TYPES: "design:paramtypes",
101
+ CONFIG_PREFIX: "di:config:prefix",
102
+ OPTIONAL_PARAMS: "di:optional"
145
103
  };
146
- var MissingDependencyError = class extends DIError {
147
- static {
148
- __name(this, "MissingDependencyError");
149
- }
150
- token;
151
- constructor(token) {
152
- super(`
153
- \u274C Missing Required Dependency
154
-
155
- Token: "${token}"
156
104
 
157
- The requested dependency is not registered in the container.
158
-
159
- Make sure to:
160
- 1. Register the dependency before resolving
161
- 2. Check spelling of the token
162
- 3. Verify the service has @Service() or @Repository() decorator
163
- `);
164
- this.name = "MissingDependencyError";
165
- this.token = token;
105
+ // src/service-decorators.ts
106
+ function Service(options = {}) {
107
+ const scope = options.scope ?? "singleton";
108
+ return (target) => {
109
+ Reflect.defineMetadata(METADATA_KEYS.SERVICE_TYPE, "service", target);
110
+ Reflect.defineMetadata(METADATA_KEYS.SERVICE_SCOPE, scope, target);
111
+ if (scope === "singleton") {
112
+ singleton()(target);
113
+ } else {
114
+ injectable()(target);
115
+ }
116
+ };
117
+ }
118
+ __name(Service, "Service");
119
+ function Repository(options = {}) {
120
+ const scope = options.scope ?? "singleton";
121
+ return (target) => {
122
+ Reflect.defineMetadata(METADATA_KEYS.SERVICE_TYPE, "repository", target);
123
+ Reflect.defineMetadata(METADATA_KEYS.SERVICE_SCOPE, scope, target);
124
+ if (scope === "singleton") {
125
+ singleton()(target);
126
+ } else {
127
+ injectable()(target);
128
+ }
129
+ };
130
+ }
131
+ __name(Repository, "Repository");
132
+ function Config(options = {}) {
133
+ return (target) => {
134
+ Reflect.defineMetadata(METADATA_KEYS.SERVICE_TYPE, "config", target);
135
+ Reflect.defineMetadata(METADATA_KEYS.SERVICE_SCOPE, "singleton", target);
136
+ if (options.prefix) {
137
+ Reflect.defineMetadata(METADATA_KEYS.CONFIG_PREFIX, options.prefix, target);
138
+ }
139
+ singleton()(target);
140
+ };
141
+ }
142
+ __name(Config, "Config");
143
+ function inject(token) {
144
+ return inject$1(token);
145
+ }
146
+ __name(inject, "inject");
147
+ function delay(tokenFactory) {
148
+ return delay$1(tokenFactory);
149
+ }
150
+ __name(delay, "delay");
151
+ function Injectable() {
152
+ return (target) => {
153
+ Reflect.defineMetadata(METADATA_KEYS.SERVICE_TYPE, "service", target);
154
+ injectable()(target);
155
+ };
156
+ }
157
+ __name(Injectable, "Injectable");
158
+ function markInjectable(target) {
159
+ injectable()(target);
160
+ }
161
+ __name(markInjectable, "markInjectable");
162
+ function markTsyringeParamOptional(target, parameterIndex) {
163
+ const TSYRINGE_INJECTION_KEY = "injectionTokens";
164
+ try {
165
+ const descriptors = Reflect.getOwnMetadata(TSYRINGE_INJECTION_KEY, target) ?? {};
166
+ const descriptor = descriptors[parameterIndex];
167
+ if (descriptor && typeof descriptor === "object" && "token" in descriptor) {
168
+ descriptor.isOptional = true;
169
+ Reflect.defineMetadata(TSYRINGE_INJECTION_KEY, descriptors, target);
170
+ }
171
+ } catch {
166
172
  }
167
- };
173
+ }
174
+ __name(markTsyringeParamOptional, "markTsyringeParamOptional");
175
+ function Optional() {
176
+ return (target, _propertyKey, parameterIndex) => {
177
+ const existing = Reflect.getOwnMetadata(METADATA_KEYS.OPTIONAL_PARAMS, target) ?? /* @__PURE__ */ new Set();
178
+ existing.add(parameterIndex);
179
+ Reflect.defineMetadata(METADATA_KEYS.OPTIONAL_PARAMS, existing, target);
180
+ markTsyringeParamOptional(target, parameterIndex);
181
+ };
182
+ }
183
+ __name(Optional, "Optional");
184
+ function isParameterOptional(target, parameterIndex) {
185
+ const optional = Reflect.getOwnMetadata(METADATA_KEYS.OPTIONAL_PARAMS, target);
186
+ return optional?.has(parameterIndex) ?? false;
187
+ }
188
+ __name(isParameterOptional, "isParameterOptional");
189
+ function getOptionalParams(target) {
190
+ return Reflect.getOwnMetadata(METADATA_KEYS.OPTIONAL_PARAMS, target) ?? /* @__PURE__ */ new Set();
191
+ }
192
+ __name(getOptionalParams, "getOptionalParams");
193
+
194
+ // src/service-metadata.ts
195
+ function hasServiceMetadata(target) {
196
+ return Reflect.hasMetadata(METADATA_KEYS.SERVICE_TYPE, target);
197
+ }
198
+ __name(hasServiceMetadata, "hasServiceMetadata");
199
+ function getServiceType(target) {
200
+ return Reflect.getMetadata(METADATA_KEYS.SERVICE_TYPE, target);
201
+ }
202
+ __name(getServiceType, "getServiceType");
203
+ function getServiceScope(target) {
204
+ return Reflect.getMetadata(METADATA_KEYS.SERVICE_SCOPE, target) ?? "singleton";
205
+ }
206
+ __name(getServiceScope, "getServiceScope");
207
+ function getConfigPrefix(target) {
208
+ return Reflect.getMetadata(METADATA_KEYS.CONFIG_PREFIX, target);
209
+ }
210
+ __name(getConfigPrefix, "getConfigPrefix");
168
211
 
169
212
  // src/container.ts
170
213
  function getTokenName(token) {
@@ -186,23 +229,55 @@ function isFactoryProvider(provider) {
186
229
  return "useFactory" in provider && typeof provider.useFactory === "function";
187
230
  }
188
231
  __name(isFactoryProvider, "isFactoryProvider");
189
- function createContainerWrapper(tsyInstance) {
190
- const resolutionStack = /* @__PURE__ */ new Set();
191
- const factoryTokens = /* @__PURE__ */ new Set();
192
- const bootstrappedValues = /* @__PURE__ */ new Map();
232
+ function createContainerWrapper(tsyInstance, sharedState) {
233
+ const resolutionStack = sharedState?.resolutionStack ?? /* @__PURE__ */ new Set();
234
+ const factoryTokens = sharedState?.factoryTokens ?? /* @__PURE__ */ new Set();
235
+ const bootstrappedValues = sharedState?.bootstrappedValues ?? /* @__PURE__ */ new Map();
236
+ const guardedTokens = sharedState?.guardedTokens ?? /* @__PURE__ */ new Set();
237
+ function registerCycleGuard(token, tsyToken) {
238
+ if (guardedTokens.has(token)) return;
239
+ guardedTokens.add(token);
240
+ const tokenName = getTokenName(token);
241
+ tsyInstance.beforeResolution(tsyToken, () => {
242
+ if (resolutionStack.has(tokenName)) {
243
+ const cycle = [
244
+ ...resolutionStack,
245
+ tokenName
246
+ ];
247
+ throw new CircularDependencyError(cycle);
248
+ }
249
+ resolutionStack.add(tokenName);
250
+ }, {
251
+ frequency: "Always"
252
+ });
253
+ tsyInstance.afterResolution(tsyToken, () => {
254
+ resolutionStack.delete(tokenName);
255
+ }, {
256
+ frequency: "Always"
257
+ });
258
+ }
259
+ __name(registerCycleGuard, "registerCycleGuard");
193
260
  const wrapper = {
194
261
  register(token, provider, options) {
195
262
  const tokenName = getTokenName(token);
196
263
  const tsyToken = token;
197
264
  bootstrappedValues.delete(token);
198
265
  if (isClassProvider(provider)) {
199
- if (options?.scope === "singleton") {
266
+ const scope = options?.scope ?? getServiceScope(provider.useClass);
267
+ if (scope === "singleton") {
200
268
  tsyInstance.registerSingleton(tsyToken, provider.useClass);
269
+ } else if (scope === "request") {
270
+ tsyInstance.register(tsyToken, {
271
+ useClass: provider.useClass
272
+ }, {
273
+ lifecycle: Lifecycle.ContainerScoped
274
+ });
201
275
  } else {
202
276
  tsyInstance.register(tsyToken, {
203
277
  useClass: provider.useClass
204
278
  });
205
279
  }
280
+ registerCycleGuard(token, tsyToken);
206
281
  } else if (isValueProvider(provider)) {
207
282
  tsyInstance.register(tsyToken, {
208
283
  useValue: provider.useValue
@@ -236,46 +311,44 @@ function createContainerWrapper(tsyInstance) {
236
311
  }
237
312
  const tokenName = getTokenName(token);
238
313
  const tsyToken = token;
239
- if (resolutionStack.has(tokenName)) {
240
- const cycle = [
241
- ...resolutionStack,
242
- tokenName
243
- ];
244
- throw new CircularDependencyError(cycle);
314
+ const guardedByInterceptor = guardedTokens.has(token);
315
+ const stackSnapshot = [
316
+ ...resolutionStack
317
+ ];
318
+ if (!guardedByInterceptor) {
319
+ if (resolutionStack.has(tokenName)) {
320
+ const cycle = [
321
+ ...resolutionStack,
322
+ tokenName
323
+ ];
324
+ throw new CircularDependencyError(cycle);
325
+ }
326
+ resolutionStack.add(tokenName);
245
327
  }
246
- resolutionStack.add(tokenName);
247
328
  try {
248
- const instance = tsyInstance.resolve(tsyToken);
249
- resolutionStack.delete(tokenName);
250
- return instance;
329
+ return tsyInstance.resolve(tsyToken);
251
330
  } catch (error) {
252
- resolutionStack.delete(tokenName);
253
331
  if (error instanceof CircularDependencyError) {
254
332
  throw error;
255
333
  }
256
- if (error instanceof RangeError && error.message.includes("Maximum call stack")) {
257
- const cycle = [
258
- ...resolutionStack,
259
- tokenName
260
- ];
261
- throw new CircularDependencyError(cycle);
334
+ const message = error instanceof Error ? error.message.toLowerCase() : "";
335
+ if (error instanceof Error && (message.includes("not registered") || message.includes("cannot resolve") || message.includes("unregistered"))) {
336
+ throw new DependencyResolutionError([
337
+ ...resolutionStack
338
+ ], tokenName);
262
339
  }
263
- if (error instanceof Error && error.message.includes("Cannot inject the dependency")) {
340
+ const isStackOverflow = error instanceof RangeError && error.message.includes("Maximum call stack") || message.includes("maximum call stack");
341
+ if (isStackOverflow || message.includes("circular") || message.includes("cyclic") || message.includes("cannot inject the dependency")) {
264
342
  const cycle = [
265
343
  ...resolutionStack,
266
344
  tokenName
267
345
  ];
268
346
  throw new CircularDependencyError(cycle);
269
347
  }
270
- if (error instanceof Error) {
271
- const message = error.message.toLowerCase();
272
- if (message.includes("not registered") || message.includes("cannot resolve") || message.includes("unregistered dependency")) {
273
- throw new DependencyResolutionError([
274
- ...resolutionStack
275
- ], tokenName);
276
- }
277
- }
278
348
  throw error;
349
+ } finally {
350
+ resolutionStack.clear();
351
+ for (const name of stackSnapshot) resolutionStack.add(name);
279
352
  }
280
353
  },
281
354
  async resolveAsync(token) {
@@ -283,16 +356,17 @@ function createContainerWrapper(tsyInstance) {
283
356
  return bootstrappedValues.get(token);
284
357
  }
285
358
  const result = wrapper.resolve(token);
286
- return result instanceof Promise ? result : result;
359
+ return await result;
287
360
  },
288
361
  async bootstrap() {
289
- for (const token of factoryTokens) {
362
+ for (const token of [
363
+ ...factoryTokens
364
+ ]) {
290
365
  if (bootstrappedValues.has(token)) continue;
291
366
  const result = wrapper.resolve(token);
292
367
  const value = result instanceof Promise ? await result : result;
293
368
  bootstrappedValues.set(token, value);
294
369
  }
295
- factoryTokens.clear();
296
370
  },
297
371
  resolveAll(token) {
298
372
  const tsyToken = token;
@@ -319,10 +393,16 @@ function createContainerWrapper(tsyInstance) {
319
393
  bootstrappedValues.clear();
320
394
  factoryTokens.clear();
321
395
  resolutionStack.clear();
396
+ guardedTokens.clear();
322
397
  },
323
398
  createChild() {
324
399
  const childTsy = tsyInstance.createChildContainer();
325
- return createContainerWrapper(childTsy);
400
+ return createContainerWrapper(childTsy, {
401
+ resolutionStack,
402
+ factoryTokens,
403
+ bootstrappedValues,
404
+ guardedTokens
405
+ });
326
406
  }
327
407
  };
328
408
  return wrapper;
@@ -336,115 +416,6 @@ function createContainer() {
336
416
  }
337
417
  __name(createContainer, "createContainer");
338
418
 
339
- // src/types.ts
340
- var METADATA_KEYS = {
341
- SERVICE_TYPE: "di:type",
342
- SERVICE_SCOPE: "di:scope",
343
- INJECT_TOKEN: "di:inject",
344
- PARAM_TYPES: "design:paramtypes",
345
- CONFIG_PREFIX: "di:config:prefix",
346
- OPTIONAL_PARAMS: "di:optional"
347
- };
348
-
349
- // src/decorators.ts
350
- function Service(options = {}) {
351
- const scope = options.scope ?? "singleton";
352
- return (target) => {
353
- Reflect.defineMetadata(METADATA_KEYS.SERVICE_TYPE, "service", target);
354
- Reflect.defineMetadata(METADATA_KEYS.SERVICE_SCOPE, scope, target);
355
- if (scope === "singleton") {
356
- singleton()(target);
357
- } else {
358
- injectable()(target);
359
- }
360
- };
361
- }
362
- __name(Service, "Service");
363
- function Repository(options = {}) {
364
- const scope = options.scope ?? "singleton";
365
- return (target) => {
366
- Reflect.defineMetadata(METADATA_KEYS.SERVICE_TYPE, "repository", target);
367
- Reflect.defineMetadata(METADATA_KEYS.SERVICE_SCOPE, scope, target);
368
- if (scope === "singleton") {
369
- singleton()(target);
370
- } else {
371
- injectable()(target);
372
- }
373
- };
374
- }
375
- __name(Repository, "Repository");
376
- function inject(token) {
377
- return inject$1(token);
378
- }
379
- __name(inject, "inject");
380
- function Injectable() {
381
- return (target) => {
382
- Reflect.defineMetadata(METADATA_KEYS.SERVICE_TYPE, "service", target);
383
- injectable()(target);
384
- };
385
- }
386
- __name(Injectable, "Injectable");
387
- var AutoInjectable = Injectable;
388
- function markInjectable(target) {
389
- injectable()(target);
390
- }
391
- __name(markInjectable, "markInjectable");
392
- function delay(tokenFactory) {
393
- return delay$1(tokenFactory);
394
- }
395
- __name(delay, "delay");
396
- function hasServiceMetadata(target) {
397
- return Reflect.hasMetadata(METADATA_KEYS.SERVICE_TYPE, target);
398
- }
399
- __name(hasServiceMetadata, "hasServiceMetadata");
400
- function getServiceType(target) {
401
- return Reflect.getMetadata(METADATA_KEYS.SERVICE_TYPE, target);
402
- }
403
- __name(getServiceType, "getServiceType");
404
- function getServiceScope(target) {
405
- return Reflect.getMetadata(METADATA_KEYS.SERVICE_SCOPE, target);
406
- }
407
- __name(getServiceScope, "getServiceScope");
408
- function Config(options = {}) {
409
- return (target) => {
410
- Reflect.defineMetadata(METADATA_KEYS.SERVICE_TYPE, "config", target);
411
- Reflect.defineMetadata(METADATA_KEYS.SERVICE_SCOPE, "singleton", target);
412
- if (options.prefix) {
413
- Reflect.defineMetadata(METADATA_KEYS.CONFIG_PREFIX, options.prefix, target);
414
- }
415
- singleton()(target);
416
- };
417
- }
418
- __name(Config, "Config");
419
- function getConfigPrefix(target) {
420
- return Reflect.getMetadata(METADATA_KEYS.CONFIG_PREFIX, target);
421
- }
422
- __name(getConfigPrefix, "getConfigPrefix");
423
- function Optional() {
424
- return (target, _propertyKey, parameterIndex) => {
425
- const existing = Reflect.getOwnMetadata(METADATA_KEYS.OPTIONAL_PARAMS, target) ?? /* @__PURE__ */ new Set();
426
- existing.add(parameterIndex);
427
- Reflect.defineMetadata(METADATA_KEYS.OPTIONAL_PARAMS, existing, target);
428
- const TSYRINGE_INJECTION_KEY = "injectionTokens";
429
- const descriptors = Reflect.getOwnMetadata(TSYRINGE_INJECTION_KEY, target) ?? {};
430
- const descriptor = descriptors[parameterIndex];
431
- if (descriptor && typeof descriptor === "object" && "token" in descriptor) {
432
- descriptor.isOptional = true;
433
- }
434
- Reflect.defineMetadata(TSYRINGE_INJECTION_KEY, descriptors, target);
435
- };
436
- }
437
- __name(Optional, "Optional");
438
- function isParameterOptional(target, parameterIndex) {
439
- const optional = Reflect.getOwnMetadata(METADATA_KEYS.OPTIONAL_PARAMS, target);
440
- return optional?.has(parameterIndex) ?? false;
441
- }
442
- __name(isParameterOptional, "isParameterOptional");
443
- function getOptionalParams(target) {
444
- return Reflect.getOwnMetadata(METADATA_KEYS.OPTIONAL_PARAMS, target) ?? /* @__PURE__ */ new Set();
445
- }
446
- __name(getOptionalParams, "getOptionalParams");
447
-
448
- export { AutoInjectable, CircularDependencyError, Config, ContainerDisposedError, DIError, DependencyResolutionError, Injectable, InvalidProviderError, METADATA_KEYS, MissingDependencyError, Optional, Repository, Service, TypeInferenceError, container, createContainer, delay, getConfigPrefix, getOptionalParams, getServiceScope, getServiceType, hasServiceMetadata, inject, isParameterOptional, markInjectable };
419
+ export { CircularDependencyError, Config, DIError, DependencyResolutionError, Injectable, InvalidProviderError, METADATA_KEYS, Optional, Repository, Service, container, createContainer, delay, getConfigPrefix, getOptionalParams, getServiceScope, getServiceType, hasServiceMetadata, inject, isParameterOptional, markInjectable };
449
420
  //# sourceMappingURL=index.js.map
450
421
  //# sourceMappingURL=index.js.map