@navios/core 0.8.0 → 0.9.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/lib/{index-BDNl7j1G.d.cts → index-D9MNh6Tx.d.mts} +36 -13
  3. package/lib/index-D9MNh6Tx.d.mts.map +1 -0
  4. package/lib/{index-BoP0cWT6.d.mts → index-Db1d3cwD.d.cts} +36 -13
  5. package/lib/index-Db1d3cwD.d.cts.map +1 -0
  6. package/lib/index.cjs +2 -2
  7. package/lib/index.d.cts +2 -2
  8. package/lib/index.d.mts +2 -2
  9. package/lib/index.mjs +2 -2
  10. package/lib/legacy-compat/index.cjs +1 -1
  11. package/lib/legacy-compat/index.cjs.map +1 -1
  12. package/lib/legacy-compat/index.d.cts +3 -3
  13. package/lib/legacy-compat/index.d.cts.map +1 -1
  14. package/lib/legacy-compat/index.d.mts +3 -3
  15. package/lib/legacy-compat/index.d.mts.map +1 -1
  16. package/lib/legacy-compat/index.mjs +1 -1
  17. package/lib/legacy-compat/index.mjs.map +1 -1
  18. package/lib/{src-B6eISODM.cjs → src-BRPtJ9fG.cjs} +12 -9
  19. package/lib/src-BRPtJ9fG.cjs.map +1 -0
  20. package/lib/{src-gBAChVRL.mjs → src-Bo23RIo-.mjs} +13 -10
  21. package/lib/src-Bo23RIo-.mjs.map +1 -0
  22. package/lib/testing/index.cjs +346 -29
  23. package/lib/testing/index.cjs.map +1 -1
  24. package/lib/testing/index.d.cts +299 -63
  25. package/lib/testing/index.d.cts.map +1 -1
  26. package/lib/testing/index.d.mts +299 -63
  27. package/lib/testing/index.d.mts.map +1 -1
  28. package/lib/testing/index.mjs +347 -31
  29. package/lib/testing/index.mjs.map +1 -1
  30. package/lib/{use-guards.decorator-COR-9mZY.cjs → use-guards.decorator-Bs8oDHOi.cjs} +13 -9
  31. package/lib/use-guards.decorator-Bs8oDHOi.cjs.map +1 -0
  32. package/lib/{use-guards.decorator-CUww54Nt.mjs → use-guards.decorator-CzVXuLkz.mjs} +12 -8
  33. package/lib/use-guards.decorator-CzVXuLkz.mjs.map +1 -0
  34. package/package.json +2 -2
  35. package/src/__tests__/controller-resolver.spec.mts +19 -13
  36. package/src/__tests__/testing-module.spec.mts +459 -0
  37. package/src/__tests__/unit-testing-module.spec.mts +424 -0
  38. package/src/decorators/controller.decorator.mts +19 -2
  39. package/src/decorators/module.decorator.mts +23 -5
  40. package/src/legacy-compat/__type-tests__/legacy-decorators.spec-d.mts +2 -6
  41. package/src/legacy-compat/decorators/multipart.decorator.mts +4 -4
  42. package/src/legacy-compat/decorators/stream.decorator.mts +4 -4
  43. package/src/navios.application.mts +9 -9
  44. package/src/navios.environment.mts +3 -1
  45. package/src/navios.factory.mts +9 -27
  46. package/src/services/instance-resolver.service.mts +8 -7
  47. package/src/services/module-loader.service.mts +3 -2
  48. package/src/testing/index.mts +1 -0
  49. package/src/testing/testing-module.mts +255 -93
  50. package/src/testing/unit-testing-module.mts +298 -0
  51. package/lib/index-BDNl7j1G.d.cts.map +0 -1
  52. package/lib/index-BoP0cWT6.d.mts.map +0 -1
  53. package/lib/src-B6eISODM.cjs.map +0 -1
  54. package/lib/src-gBAChVRL.mjs.map +0 -1
  55. package/lib/use-guards.decorator-COR-9mZY.cjs.map +0 -1
  56. package/lib/use-guards.decorator-CUww54Nt.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
- import { t as NaviosFactory } from "../src-gBAChVRL.mjs";
2
- import "../use-guards.decorator-CUww54Nt.mjs";
3
- import { TestContainer } from "@navios/di/testing";
1
+ import { t as NaviosFactory } from "../src-Bo23RIo-.mjs";
2
+ import "../use-guards.decorator-CzVXuLkz.mjs";
3
+ import { TestContainer, UnitTestContainer } from "@navios/di/testing";
4
4
 
5
5
  export * from "@navios/di/testing"
6
6
 
@@ -8,32 +8,85 @@ export * from "@navios/di/testing"
8
8
  /**
9
9
  * A testing-optimized wrapper around NaviosApplication.
10
10
  * Provides utilities for setting up test environments with mock dependencies.
11
- */ var TestingModule = class {
11
+ *
12
+ * When `init()` is called, a request scope is automatically started.
13
+ * This means `get()` calls will resolve request-scoped services correctly,
14
+ * simulating a real HTTP request context.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const module = await TestingModule.create(AppModule)
19
+ * .overrideProvider(DatabaseService)
20
+ * .useValue(mockDatabase)
21
+ * .init()
22
+ *
23
+ * const userService = await module.get(UserService)
24
+ * // ... run tests ...
25
+ *
26
+ * await module.close()
27
+ * ```
28
+ */ var TestingModule = class TestingModule {
12
29
  appModule;
13
30
  container;
14
31
  options;
15
32
  app = null;
33
+ scopedContainer = null;
34
+ requestId = `test-request-${Date.now()}-${Math.random().toString(36).slice(2)}`;
16
35
  constructor(appModule, container, options) {
17
36
  this.appModule = appModule;
18
37
  this.container = container;
19
38
  this.options = options;
20
39
  }
21
40
  /**
22
- * Compiles the testing module and returns the NaviosApplication.
23
- * Call this after setting up all overrides.
41
+ * Creates a new TestingModule for the given app module.
42
+ * This is the main entry point for setting up integration tests.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const module = await TestingModule.create(AppModule)
47
+ * .overrideProvider(DatabaseService)
48
+ * .useValue(mockDatabase)
49
+ * .init()
50
+ * ```
51
+ */ static create(appModule, options = { adapter: [] }) {
52
+ const container = options.container ?? new TestContainer({ parentRegistry: options.registry });
53
+ if (options.overrides) {
54
+ for (const override of options.overrides) if (override.useValue !== void 0) container.bind(override.token).toValue(override.useValue);
55
+ else if (override.useClass) container.bind(override.token).toClass(override.useClass);
56
+ }
57
+ return new TestingModule(appModule, container, options);
58
+ }
59
+ /**
60
+ * Compiles the testing module without initializing it.
61
+ * Call this if you need to access the app before initialization.
62
+ *
63
+ * @returns this for chaining
24
64
  */ async compile() {
25
- this.app = await NaviosFactory.create(this.appModule, {
65
+ if (!this.app) this.app = await NaviosFactory.create(this.appModule, {
26
66
  ...this.options,
27
67
  container: this.container
28
68
  });
29
- return this.app;
69
+ return this;
30
70
  }
31
71
  /**
32
- * Initializes the application (loads modules, sets up HTTP if configured).
33
- * This is equivalent to calling app.init() on the compiled application.
72
+ * Initializes the application and starts a request scope.
73
+ *
74
+ * This is equivalent to calling `compile()` followed by `app.init()`,
75
+ * plus starting a request context for proper request-scoped service resolution.
76
+ *
77
+ * @returns this for chaining
34
78
  */ async init() {
35
79
  if (!this.app) await this.compile();
36
80
  await this.app.init();
81
+ this.scopedContainer = this.container.beginRequest(this.requestId, { testingModule: true });
82
+ return this;
83
+ }
84
+ /**
85
+ * Gets the compiled application.
86
+ *
87
+ * @throws Error if the module has not been compiled yet
88
+ */ getApp() {
89
+ if (!this.app) throw new Error("TestingModule not compiled. Call compile() or init() first.");
37
90
  return this.app;
38
91
  }
39
92
  /**
@@ -42,13 +95,17 @@ export * from "@navios/di/testing"
42
95
  return this.container;
43
96
  }
44
97
  /**
45
- * Gets the compiled application. Throws if not yet compiled.
46
- */ getApplication() {
47
- if (!this.app) throw new Error("TestingModule not compiled. Call compile() or init() first.");
48
- return this.app;
98
+ * Gets the scoped container for the current test request.
99
+ * Only available after calling `init()`.
100
+ *
101
+ * @throws Error if init() has not been called
102
+ */ getScopedContainer() {
103
+ if (!this.scopedContainer) throw new Error("No scoped container available. Call init() first.");
104
+ return this.scopedContainer;
49
105
  }
50
106
  /**
51
- * Override a provider with a mock value.
107
+ * Override a provider with a mock value or class.
108
+ * Must be called before `compile()` or `init()`.
52
109
  */ overrideProvider(token) {
53
110
  return {
54
111
  useValue: (value) => {
@@ -63,38 +120,297 @@ export * from "@navios/di/testing"
63
120
  }
64
121
  /**
65
122
  * Gets an instance from the container.
123
+ *
124
+ * If `init()` has been called, this uses the scoped container
125
+ * which properly resolves request-scoped services.
126
+ *
127
+ * If only `compile()` was called, this uses the root container
128
+ * and request-scoped services will throw.
66
129
  */ async get(token) {
130
+ if (this.scopedContainer) return this.scopedContainer.get(token);
67
131
  return this.container.get(token);
68
132
  }
69
133
  /**
70
- * Disposes the testing module and cleans up resources.
134
+ * Disposes the testing module and cleans up all resources.
135
+ *
136
+ * This will:
137
+ * 1. End the request scope (if started)
138
+ * 2. Close the application (if initialized)
139
+ * 3. Dispose the container
71
140
  */ async close() {
72
- if (this.app) await this.app.close();
141
+ if (this.scopedContainer) {
142
+ await this.scopedContainer.endRequest();
143
+ this.scopedContainer = null;
144
+ }
145
+ if (this.app) {
146
+ await this.app.close();
147
+ this.app = null;
148
+ }
73
149
  await this.container.dispose();
74
150
  }
151
+ /**
152
+ * Asserts that a service has been resolved at least once.
153
+ */ expectResolved(token) {
154
+ this.container.expectResolved(token);
155
+ }
156
+ /**
157
+ * Asserts that a service has NOT been resolved.
158
+ */ expectNotResolved(token) {
159
+ this.container.expectNotResolved(token);
160
+ }
161
+ /**
162
+ * Asserts that a service is registered as singleton scope.
163
+ */ expectSingleton(token) {
164
+ this.container.expectSingleton(token);
165
+ }
166
+ /**
167
+ * Asserts that a service is registered as transient scope.
168
+ */ expectTransient(token) {
169
+ this.container.expectTransient(token);
170
+ }
171
+ /**
172
+ * Asserts that a service is registered as request scope.
173
+ */ expectRequestScoped(token) {
174
+ this.container.expectRequestScoped(token);
175
+ }
176
+ /**
177
+ * Asserts that a method was called on a service.
178
+ * Note: You must use `recordMethodCall()` in your mocks for this to work.
179
+ */ expectCalled(token, method) {
180
+ this.container.expectCalled(token, method);
181
+ }
182
+ /**
183
+ * Asserts that a method was called with specific arguments.
184
+ * Note: You must use `recordMethodCall()` in your mocks for this to work.
185
+ */ expectCalledWith(token, method, expectedArgs) {
186
+ this.container.expectCalledWith(token, method, expectedArgs);
187
+ }
188
+ /**
189
+ * Asserts that a method was called a specific number of times.
190
+ * Note: You must use `recordMethodCall()` in your mocks for this to work.
191
+ */ expectCallCount(token, method, count) {
192
+ this.container.expectCallCount(token, method, count);
193
+ }
194
+ /**
195
+ * Records a method call for tracking.
196
+ * Call this from your mock implementations to enable call assertions.
197
+ */ recordMethodCall(token, method, args, result, error) {
198
+ this.container.recordMethodCall(token, method, args, result, error);
199
+ }
200
+ /**
201
+ * Gets all recorded method calls for a service.
202
+ */ getMethodCalls(token) {
203
+ return this.container.getMethodCalls(token);
204
+ }
205
+ /**
206
+ * Gets the dependency graph for debugging or snapshot testing.
207
+ */ getDependencyGraph() {
208
+ return this.container.getDependencyGraph();
209
+ }
210
+ /**
211
+ * Gets a simplified dependency graph showing only token relationships.
212
+ */ getSimplifiedDependencyGraph() {
213
+ return this.container.getSimplifiedDependencyGraph();
214
+ }
75
215
  };
76
216
  /**
77
217
  * Creates a testing module for the given app module.
78
- * This is the main entry point for setting up tests.
218
+ *
219
+ * @deprecated Use `TestingModule.create()` instead.
79
220
  *
80
221
  * @example
81
222
  * ```typescript
82
- * const testingModule = await createTestingModule(AppModule, {
83
- * adapter: [],
84
- * })
85
- * .overrideProvider(DatabaseService)
86
- * .useValue(mockDatabaseService)
87
- * .compile()
223
+ * // Old way (deprecated)
224
+ * const module = createTestingModule(AppModule)
225
+ *
226
+ * // New way
227
+ * const module = TestingModule.create(AppModule)
88
228
  * ```
89
229
  */ function createTestingModule(appModule, options = { adapter: [] }) {
90
- const container = new TestContainer();
91
- if (options.overrides) {
92
- for (const override of options.overrides) if (override.useValue !== void 0) container.bind(override.token).toValue(override.useValue);
93
- else if (override.useClass) container.bind(override.token).toClass(override.useClass);
94
- }
95
- return new TestingModule(appModule, container, options);
230
+ return TestingModule.create(appModule, options);
96
231
  }
97
232
 
98
233
  //#endregion
99
- export { TestingModule, createTestingModule };
234
+ //#region src/testing/unit-testing-module.mts
235
+ /**
236
+ * A lightweight testing module for isolated unit tests.
237
+ *
238
+ * Unlike `TestingModule`, this does NOT load Navios modules or create an application.
239
+ * It uses `UnitTestContainer` which:
240
+ * - Only allows explicitly provided services
241
+ * - Automatically tracks all method calls via proxies
242
+ * - Can auto-mock unregistered dependencies
243
+ *
244
+ * This is ideal for testing services in isolation without the overhead
245
+ * of full module loading.
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * const module = UnitTestingModule.create({
250
+ * providers: [
251
+ * { token: UserService, useClass: UserService },
252
+ * { token: DatabaseService, useValue: mockDatabase },
253
+ * ],
254
+ * })
255
+ *
256
+ * const userService = await module.get(UserService)
257
+ * await userService.findUser('123')
258
+ *
259
+ * // Method calls are automatically tracked
260
+ * module.expectCalled(UserService, 'findUser')
261
+ * module.expectCalledWith(UserService, 'findUser', ['123'])
262
+ *
263
+ * await module.close()
264
+ * ```
265
+ */ var UnitTestingModule = class UnitTestingModule {
266
+ container;
267
+ constructor(container) {
268
+ this.container = container;
269
+ }
270
+ /**
271
+ * Creates a new UnitTestingModule with the given providers.
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * const module = UnitTestingModule.create({
276
+ * providers: [
277
+ * { token: UserService, useClass: UserService },
278
+ * { token: ConfigToken, useValue: { apiUrl: 'test' } },
279
+ * ],
280
+ * })
281
+ * ```
282
+ */ static create(options) {
283
+ return new UnitTestingModule(options.container ?? new UnitTestContainer({
284
+ providers: options.providers,
285
+ allowUnregistered: options.allowUnregistered,
286
+ logger: options.logger
287
+ }));
288
+ }
289
+ /**
290
+ * Gets the underlying UnitTestContainer for direct manipulation.
291
+ */ getContainer() {
292
+ return this.container;
293
+ }
294
+ /**
295
+ * Gets an instance from the container.
296
+ *
297
+ * All resolved instances are wrapped in tracking proxies,
298
+ * so method calls are automatically recorded.
299
+ *
300
+ * @throws Error if the token is not in the providers list
301
+ * and `allowUnregistered` is false
302
+ */ async get(token) {
303
+ return this.container.get(token);
304
+ }
305
+ /**
306
+ * Disposes the module and cleans up all resources.
307
+ */ async close() {
308
+ await this.container.clear();
309
+ }
310
+ /**
311
+ * Enables auto-mocking for unregistered dependencies.
312
+ * Unregistered services will return a proxy that throws on method access.
313
+ */ enableAutoMocking() {
314
+ this.container.enableAutoMocking();
315
+ return this;
316
+ }
317
+ /**
318
+ * Disables auto-mocking (strict mode).
319
+ * Unregistered dependencies will throw immediately on resolution.
320
+ */ disableAutoMocking() {
321
+ this.container.disableAutoMocking();
322
+ return this;
323
+ }
324
+ /**
325
+ * Asserts that a service has been resolved at least once.
326
+ */ expectResolved(token) {
327
+ this.container.expectResolved(token);
328
+ }
329
+ /**
330
+ * Asserts that a service has NOT been resolved.
331
+ */ expectNotResolved(token) {
332
+ this.container.expectNotResolved(token);
333
+ }
334
+ /**
335
+ * Asserts that a service was auto-mocked (not in providers list).
336
+ */ expectAutoMocked(token) {
337
+ this.container.expectAutoMocked(token);
338
+ }
339
+ /**
340
+ * Asserts that a service was NOT auto-mocked (is in providers list).
341
+ */ expectNotAutoMocked(token) {
342
+ this.container.expectNotAutoMocked(token);
343
+ }
344
+ /**
345
+ * Asserts that a method was called on a service.
346
+ * Method calls are automatically tracked via proxy.
347
+ */ expectCalled(token, method) {
348
+ this.container.expectCalled(token, method);
349
+ }
350
+ /**
351
+ * Asserts that a method was NOT called on a service.
352
+ */ expectNotCalled(token, method) {
353
+ this.container.expectNotCalled(token, method);
354
+ }
355
+ /**
356
+ * Asserts that a method was called with specific arguments.
357
+ */ expectCalledWith(token, method, expectedArgs) {
358
+ this.container.expectCalledWith(token, method, expectedArgs);
359
+ }
360
+ /**
361
+ * Asserts that a method was called a specific number of times.
362
+ */ expectCallCount(token, method, count) {
363
+ this.container.expectCallCount(token, method, count);
364
+ }
365
+ /**
366
+ * Gets all recorded method calls for a service.
367
+ */ getMethodCalls(token) {
368
+ return this.container.getMethodCalls(token);
369
+ }
370
+ /**
371
+ * Gets statistics about a service (instance count, method calls, lifecycle events).
372
+ */ getServiceStats(token) {
373
+ return this.container.getServiceStats(token);
374
+ }
375
+ /**
376
+ * Clears all recorded method calls.
377
+ * Useful for resetting state between test assertions.
378
+ */ clearMethodCalls() {
379
+ this.container.clearMethodCalls();
380
+ }
381
+ /**
382
+ * Gets list of all registered provider token IDs.
383
+ */ getRegisteredTokenIds() {
384
+ return this.container.getRegisteredTokenIds();
385
+ }
386
+ /**
387
+ * Gets list of all auto-mocked token IDs.
388
+ */ getAutoMockedTokenIds() {
389
+ return this.container.getAutoMockedTokenIds();
390
+ }
391
+ /**
392
+ * Asserts that a service's onServiceInit was called.
393
+ */ expectInitialized(token) {
394
+ this.container.expectInitialized(token);
395
+ }
396
+ /**
397
+ * Asserts that a service's onServiceDestroy was called.
398
+ */ expectDestroyed(token) {
399
+ this.container.expectDestroyed(token);
400
+ }
401
+ /**
402
+ * Asserts that a service has NOT been destroyed.
403
+ */ expectNotDestroyed(token) {
404
+ this.container.expectNotDestroyed(token);
405
+ }
406
+ /**
407
+ * Records a lifecycle event for tracking.
408
+ * Call this from your mock implementations if needed.
409
+ */ recordLifecycleEvent(token, event, instanceName) {
410
+ this.container.recordLifecycleEvent(token, event, instanceName);
411
+ }
412
+ };
413
+
414
+ //#endregion
415
+ export { TestingModule, UnitTestingModule, createTestingModule };
100
416
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["TestContainer","NaviosFactory","TestingModule","app","appModule","container","options","compile","create","init","getContainer","getApplication","Error","overrideProvider","token","useValue","value","bind","toValue","useClass","target","toClass","get","close","dispose","createTestingModule","adapter","overrides","override","undefined"],"sources":["../../src/testing/testing-module.mts"],"sourcesContent":["import type { ClassType, ClassTypeWithInstance, InjectionToken } from '@navios/di'\nimport type { NaviosModule } from '../interfaces/index.mjs'\nimport type { NaviosApplicationOptions } from '../navios.application.mjs'\n\nimport { TestContainer } from '@navios/di/testing'\n\nimport { NaviosApplication } from '../navios.application.mjs'\nimport { NaviosFactory } from '../navios.factory.mjs'\n\n/**\n * Configuration for overriding a provider in the testing module.\n * \n * @typeParam T - The type of the provider being overridden\n */\nexport interface TestingModuleOverride<T = any> {\n /**\n * The injection token or class to override.\n */\n token: ClassType | InjectionToken<T, any>\n /**\n * Value to use instead of the original provider.\n */\n useValue?: T\n /**\n * Class to use instead of the original provider.\n */\n useClass?: ClassType\n}\n\n/**\n * Options for creating a testing module.\n * \n * Extends NaviosApplicationOptions but excludes the container option,\n * as TestingModule manages its own TestContainer.\n */\nexport interface TestingModuleOptions\n extends Omit<NaviosApplicationOptions, 'container'> {\n /**\n * Initial provider overrides to apply when creating the testing module.\n * \n * You can also use `overrideProvider()` method for a fluent API.\n */\n overrides?: TestingModuleOverride[]\n}\n\n/**\n * A testing-optimized wrapper around NaviosApplication.\n * Provides utilities for setting up test environments with mock dependencies.\n */\nexport class TestingModule {\n private app: NaviosApplication | null = null\n\n constructor(\n private readonly appModule: ClassTypeWithInstance<NaviosModule>,\n private readonly container: TestContainer,\n private readonly options: TestingModuleOptions,\n ) {}\n\n /**\n * Compiles the testing module and returns the NaviosApplication.\n * Call this after setting up all overrides.\n */\n async compile(): Promise<NaviosApplication> {\n this.app = await NaviosFactory.create(this.appModule, {\n ...this.options,\n container: this.container,\n })\n return this.app\n }\n\n /**\n * Initializes the application (loads modules, sets up HTTP if configured).\n * This is equivalent to calling app.init() on the compiled application.\n */\n async init(): Promise<NaviosApplication> {\n if (!this.app) {\n await this.compile()\n }\n await this.app!.init()\n return this.app!\n }\n\n /**\n * Gets the underlying TestContainer for direct manipulation.\n */\n getContainer(): TestContainer {\n return this.container\n }\n\n /**\n * Gets the compiled application. Throws if not yet compiled.\n */\n getApplication(): NaviosApplication {\n if (!this.app) {\n throw new Error(\n 'TestingModule not compiled. Call compile() or init() first.',\n )\n }\n return this.app\n }\n\n /**\n * Override a provider with a mock value.\n */\n overrideProvider<T>(token: ClassType | InjectionToken<T, any>): {\n useValue: (value: T) => TestingModule\n useClass: (target: ClassType) => TestingModule\n } {\n return {\n useValue: (value: T) => {\n this.container.bind(token as any).toValue(value)\n return this\n },\n useClass: (target: ClassType) => {\n this.container.bind(token as any).toClass(target)\n return this\n },\n }\n }\n\n /**\n * Gets an instance from the container.\n */\n async get<T>(token: ClassTypeWithInstance<T> | InjectionToken<T, any>): Promise<T> {\n return this.container.get(token as any)\n }\n\n /**\n * Disposes the testing module and cleans up resources.\n */\n async close(): Promise<void> {\n if (this.app) {\n await this.app.close()\n }\n await this.container.dispose()\n }\n}\n\n/**\n * Fluent builder interface for TestingModule.\n * \n * Provides a chainable API for configuring and using a testing module.\n */\nexport interface TestingModuleBuilder {\n /**\n * Override a provider with a mock value or class.\n * \n * @param token - The injection token or class to override\n * @returns An object with `useValue` and `useClass` methods for chaining\n * \n * @example\n * ```typescript\n * const testingModule = await createTestingModule(AppModule)\n * .overrideProvider(DatabaseService)\n * .useValue(mockDatabaseService)\n * .compile()\n * ```\n */\n overrideProvider<T>(token: ClassType | InjectionToken<T, any>): {\n useValue: (value: T) => TestingModuleBuilder\n useClass: (target: ClassType) => TestingModuleBuilder\n }\n\n /**\n * Compiles the testing module and returns the NaviosApplication.\n * \n * This creates the application instance but does not initialize it.\n * Call `init()` if you need the application to be fully initialized.\n */\n compile(): Promise<NaviosApplication>\n\n /**\n * Initializes the application (loads modules, sets up HTTP if configured).\n * \n * This is equivalent to calling `compile()` followed by `app.init()`.\n */\n init(): Promise<NaviosApplication>\n\n /**\n * Gets the underlying TestContainer for direct manipulation.\n */\n getContainer(): TestContainer\n\n /**\n * Gets an instance from the container.\n * \n * @typeParam T - The type of the instance to retrieve\n * @param token - The injection token or class\n * @returns The resolved instance\n */\n get<T>(token: ClassTypeWithInstance<T> | InjectionToken<T, any>): Promise<T>\n\n /**\n * Disposes the testing module and cleans up resources.\n */\n close(): Promise<void>\n}\n\n/**\n * Creates a testing module for the given app module.\n * This is the main entry point for setting up tests.\n *\n * @example\n * ```typescript\n * const testingModule = await createTestingModule(AppModule, {\n * adapter: [],\n * })\n * .overrideProvider(DatabaseService)\n * .useValue(mockDatabaseService)\n * .compile()\n * ```\n */\nexport function createTestingModule(\n appModule: ClassTypeWithInstance<NaviosModule>,\n options: TestingModuleOptions = { adapter: [] },\n): TestingModule {\n const container = new TestContainer()\n\n // Apply initial overrides if provided\n if (options.overrides) {\n for (const override of options.overrides) {\n if (override.useValue !== undefined) {\n container.bind(override.token as any).toValue(override.useValue)\n } else if (override.useClass) {\n container.bind(override.token as any).toClass(override.useClass)\n }\n }\n }\n\n return new TestingModule(appModule, container, options)\n}\n"],"mappings":";;;;;;;;;;GAiDA,IAAaE,gBAAb,MAAaA;;;;CACHC,MAAgC;CAExC,YACE,WACA,WACA,SACA;OAHiBC,YAAAA;OACAC,YAAAA;OACAC,UAAAA;;;;;IAOnB,MAAMC,UAAsC;AAC1C,OAAKJ,MAAM,MAAMF,cAAcO,OAAO,KAAKJ,WAAW;GACpD,GAAG,KAAKE;GACRD,WAAW,KAAKA;GAClB,CAAA;AACA,SAAO,KAAKF;;;;;IAOd,MAAMM,OAAmC;AACvC,MAAI,CAAC,KAAKN,IACR,OAAM,KAAKI,SAAO;AAEpB,QAAM,KAAKJ,IAAKM,MAAI;AACpB,SAAO,KAAKN;;;;IAMdO,eAA8B;AAC5B,SAAO,KAAKL;;;;IAMdM,iBAAoC;AAClC,MAAI,CAAC,KAAKR,IACR,OAAM,IAAIS,MACR,8DAAA;AAGJ,SAAO,KAAKT;;;;IAMdU,iBAAoBC,OAGlB;AACA,SAAO;GACLC,WAAWC,UAAAA;AACT,SAAKX,UAAUY,KAAKH,MAAAA,CAAcI,QAAQF,MAAAA;AAC1C,WAAO;;GAETG,WAAWC,WAAAA;AACT,SAAKf,UAAUY,KAAKH,MAAAA,CAAcO,QAAQD,OAAAA;AAC1C,WAAO;;GAEX;;;;IAMF,MAAME,IAAOR,OAAsE;AACjF,SAAO,KAAKT,UAAUiB,IAAIR,MAAAA;;;;IAM5B,MAAMS,QAAuB;AAC3B,MAAI,KAAKpB,IACP,OAAM,KAAKA,IAAIoB,OAAK;AAEtB,QAAM,KAAKlB,UAAUmB,SAAO;;;;;;;;;;;;;;;;GA8EhC,SAAgBC,oBACdrB,WACAE,UAAgC,EAAEoB,SAAS,EAAE,EAAE,EAAA;CAE/C,MAAMrB,YAAY,IAAIL,eAAAA;AAGtB,KAAIM,QAAQqB,WACV;OAAK,MAAMC,YAAYtB,QAAQqB,UAC7B,KAAIC,SAASb,aAAac,OACxBxB,WAAUY,KAAKW,SAASd,MAAK,CAASI,QAAQU,SAASb,SAAQ;WACtDa,SAAST,SAClBd,WAAUY,KAAKW,SAASd,MAAK,CAASO,QAAQO,SAAST,SAAQ;;AAKrE,QAAO,IAAIjB,cAAcE,WAAWC,WAAWC,QAAAA"}
1
+ {"version":3,"file":"index.mjs","names":["TestContainer","NaviosFactory","TestingModule","app","scopedContainer","requestId","Date","now","Math","random","toString","slice","appModule","container","options","create","adapter","parentRegistry","registry","overrides","override","useValue","undefined","bind","token","toValue","useClass","toClass","compile","init","beginRequest","testingModule","getApp","Error","getContainer","getScopedContainer","overrideProvider","value","target","get","close","endRequest","dispose","expectResolved","expectNotResolved","expectSingleton","expectTransient","expectRequestScoped","expectCalled","method","expectCalledWith","expectedArgs","expectCallCount","count","recordMethodCall","args","result","error","getMethodCalls","getDependencyGraph","getSimplifiedDependencyGraph","createTestingModule","UnitTestContainer","UnitTestingModule","container","create","options","providers","allowUnregistered","logger","getContainer","get","token","close","clear","enableAutoMocking","disableAutoMocking","expectResolved","expectNotResolved","expectAutoMocked","expectNotAutoMocked","expectCalled","method","expectNotCalled","expectCalledWith","expectedArgs","expectCallCount","count","getMethodCalls","getServiceStats","clearMethodCalls","getRegisteredTokenIds","getAutoMockedTokenIds","expectInitialized","expectDestroyed","expectNotDestroyed","recordLifecycleEvent","event","instanceName"],"sources":["../../src/testing/testing-module.mts","../../src/testing/unit-testing-module.mts"],"sourcesContent":["import type {\n ClassType,\n ClassTypeWithInstance,\n InjectionToken,\n ScopedContainer,\n} from '@navios/di'\n\nimport { TestContainer } from '@navios/di/testing'\n\nimport type { NaviosModule } from '../interfaces/index.mjs'\nimport type { NaviosApplicationOptions } from '../navios.application.mjs'\n\nimport { NaviosApplication } from '../navios.application.mjs'\nimport { NaviosFactory } from '../navios.factory.mjs'\n\n/**\n * Configuration for overriding a provider in the testing module.\n *\n * @typeParam T - The type of the provider being overridden\n */\nexport interface TestingModuleOverride<T = any> {\n /**\n * The injection token or class to override.\n */\n token: ClassType | InjectionToken<T, any>\n /**\n * Value to use instead of the original provider.\n */\n useValue?: T\n /**\n * Class to use instead of the original provider.\n */\n useClass?: ClassType\n}\n\n/**\n * Options for creating a testing module.\n *\n * Extends NaviosApplicationOptions but excludes the container option,\n * as TestingModule manages its own TestContainer.\n */\nexport interface TestingModuleOptions extends Omit<\n NaviosApplicationOptions,\n 'container'\n> {\n /**\n * Initial provider overrides to apply when creating the testing module.\n *\n * You can also use `overrideProvider()` method for a fluent API.\n */\n overrides?: TestingModuleOverride[]\n /**\n * Container to use for the testing module.\n * If not provided, a new TestContainer will be created.\n */\n container?: TestContainer\n}\n\n/**\n * A testing-optimized wrapper around NaviosApplication.\n * Provides utilities for setting up test environments with mock dependencies.\n *\n * When `init()` is called, a request scope is automatically started.\n * This means `get()` calls will resolve request-scoped services correctly,\n * simulating a real HTTP request context.\n *\n * @example\n * ```typescript\n * const module = await TestingModule.create(AppModule)\n * .overrideProvider(DatabaseService)\n * .useValue(mockDatabase)\n * .init()\n *\n * const userService = await module.get(UserService)\n * // ... run tests ...\n *\n * await module.close()\n * ```\n */\nexport class TestingModule {\n private app: NaviosApplication | null = null\n private scopedContainer: ScopedContainer | null = null\n private requestId = `test-request-${Date.now()}-${Math.random().toString(36).slice(2)}`\n\n private constructor(\n private readonly appModule: ClassTypeWithInstance<NaviosModule>,\n private readonly container: TestContainer,\n private readonly options: TestingModuleOptions,\n ) {}\n\n /**\n * Creates a new TestingModule for the given app module.\n * This is the main entry point for setting up integration tests.\n *\n * @example\n * ```typescript\n * const module = await TestingModule.create(AppModule)\n * .overrideProvider(DatabaseService)\n * .useValue(mockDatabase)\n * .init()\n * ```\n */\n static create(\n appModule: ClassTypeWithInstance<NaviosModule>,\n options: TestingModuleOptions = { adapter: [] },\n ): TestingModule {\n const container =\n options.container ??\n new TestContainer({\n parentRegistry: options.registry,\n })\n\n // Apply initial overrides if provided\n if (options.overrides) {\n for (const override of options.overrides) {\n if (override.useValue !== undefined) {\n container.bind(override.token as any).toValue(override.useValue)\n } else if (override.useClass) {\n container.bind(override.token as any).toClass(override.useClass)\n }\n }\n }\n\n return new TestingModule(appModule, container, options)\n }\n\n /**\n * Compiles the testing module without initializing it.\n * Call this if you need to access the app before initialization.\n *\n * @returns this for chaining\n */\n async compile(): Promise<this> {\n if (!this.app) {\n this.app = await NaviosFactory.create(this.appModule, {\n ...this.options,\n container: this.container,\n })\n }\n return this\n }\n\n /**\n * Initializes the application and starts a request scope.\n *\n * This is equivalent to calling `compile()` followed by `app.init()`,\n * plus starting a request context for proper request-scoped service resolution.\n *\n * @returns this for chaining\n */\n async init(): Promise<this> {\n if (!this.app) {\n await this.compile()\n }\n await this.app!.init()\n\n // Begin a request scope so get() can resolve request-scoped services\n this.scopedContainer = this.container.beginRequest(this.requestId, {\n testingModule: true,\n })\n\n return this\n }\n\n /**\n * Gets the compiled application.\n *\n * @throws Error if the module has not been compiled yet\n */\n getApp(): NaviosApplication {\n if (!this.app) {\n throw new Error(\n 'TestingModule not compiled. Call compile() or init() first.',\n )\n }\n return this.app\n }\n\n /**\n * Gets the underlying TestContainer for direct manipulation.\n */\n getContainer(): TestContainer {\n return this.container\n }\n\n /**\n * Gets the scoped container for the current test request.\n * Only available after calling `init()`.\n *\n * @throws Error if init() has not been called\n */\n getScopedContainer(): ScopedContainer {\n if (!this.scopedContainer) {\n throw new Error('No scoped container available. Call init() first.')\n }\n return this.scopedContainer\n }\n\n /**\n * Override a provider with a mock value or class.\n * Must be called before `compile()` or `init()`.\n */\n overrideProvider<T>(token: ClassType | InjectionToken<T, any>): {\n useValue: (value: T) => TestingModule\n useClass: (target: ClassType) => TestingModule\n } {\n return {\n useValue: (value: T) => {\n this.container.bind(token as any).toValue(value)\n return this\n },\n useClass: (target: ClassType) => {\n this.container.bind(token as any).toClass(target)\n return this\n },\n }\n }\n\n /**\n * Gets an instance from the container.\n *\n * If `init()` has been called, this uses the scoped container\n * which properly resolves request-scoped services.\n *\n * If only `compile()` was called, this uses the root container\n * and request-scoped services will throw.\n */\n async get<T>(\n token: ClassTypeWithInstance<T> | InjectionToken<T, any>,\n ): Promise<T> {\n // Use scoped container if available (after init)\n if (this.scopedContainer) {\n return this.scopedContainer.get(token as any)\n }\n // Fall back to root container (after compile only)\n return this.container.get(token as any)\n }\n\n /**\n * Disposes the testing module and cleans up all resources.\n *\n * This will:\n * 1. End the request scope (if started)\n * 2. Close the application (if initialized)\n * 3. Dispose the container\n */\n async close(): Promise<void> {\n // End the request scope first\n if (this.scopedContainer) {\n await this.scopedContainer.endRequest()\n this.scopedContainer = null\n }\n\n // Close the app\n if (this.app) {\n await this.app.close()\n this.app = null\n }\n\n // Dispose the container\n await this.container.dispose()\n }\n\n // ===========================================================================\n // ASSERTION HELPERS (delegated to TestContainer)\n // ===========================================================================\n\n /**\n * Asserts that a service has been resolved at least once.\n */\n expectResolved(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectResolved(token)\n }\n\n /**\n * Asserts that a service has NOT been resolved.\n */\n expectNotResolved(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectNotResolved(token)\n }\n\n /**\n * Asserts that a service is registered as singleton scope.\n */\n expectSingleton(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectSingleton(token)\n }\n\n /**\n * Asserts that a service is registered as transient scope.\n */\n expectTransient(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectTransient(token)\n }\n\n /**\n * Asserts that a service is registered as request scope.\n */\n expectRequestScoped(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectRequestScoped(token)\n }\n\n /**\n * Asserts that a method was called on a service.\n * Note: You must use `recordMethodCall()` in your mocks for this to work.\n */\n expectCalled(\n token: ClassType | InjectionToken<any, any>,\n method: string,\n ): void {\n this.container.expectCalled(token, method)\n }\n\n /**\n * Asserts that a method was called with specific arguments.\n * Note: You must use `recordMethodCall()` in your mocks for this to work.\n */\n expectCalledWith(\n token: ClassType | InjectionToken<any, any>,\n method: string,\n expectedArgs: unknown[],\n ): void {\n this.container.expectCalledWith(token, method, expectedArgs)\n }\n\n /**\n * Asserts that a method was called a specific number of times.\n * Note: You must use `recordMethodCall()` in your mocks for this to work.\n */\n expectCallCount(\n token: ClassType | InjectionToken<any, any>,\n method: string,\n count: number,\n ): void {\n this.container.expectCallCount(token, method, count)\n }\n\n /**\n * Records a method call for tracking.\n * Call this from your mock implementations to enable call assertions.\n */\n recordMethodCall(\n token: ClassType | InjectionToken<any, any>,\n method: string,\n args: unknown[],\n result?: unknown,\n error?: Error,\n ): void {\n this.container.recordMethodCall(token, method, args, result, error)\n }\n\n /**\n * Gets all recorded method calls for a service.\n */\n getMethodCalls(token: ClassType | InjectionToken<any, any>) {\n return this.container.getMethodCalls(token)\n }\n\n /**\n * Gets the dependency graph for debugging or snapshot testing.\n */\n getDependencyGraph() {\n return this.container.getDependencyGraph()\n }\n\n /**\n * Gets a simplified dependency graph showing only token relationships.\n */\n getSimplifiedDependencyGraph() {\n return this.container.getSimplifiedDependencyGraph()\n }\n}\n\n/**\n * Creates a testing module for the given app module.\n *\n * @deprecated Use `TestingModule.create()` instead.\n *\n * @example\n * ```typescript\n * // Old way (deprecated)\n * const module = createTestingModule(AppModule)\n *\n * // New way\n * const module = TestingModule.create(AppModule)\n * ```\n */\nexport function createTestingModule(\n appModule: ClassTypeWithInstance<NaviosModule>,\n options: TestingModuleOptions = { adapter: [] },\n): TestingModule {\n return TestingModule.create(appModule, options)\n}\n","import type {\n ClassType,\n ClassTypeWithInstance,\n InjectionToken,\n} from '@navios/di'\nimport type {\n MethodCallRecord,\n MockServiceStats,\n ProviderConfig,\n} from '@navios/di/testing'\n\nimport { UnitTestContainer } from '@navios/di/testing'\n\n/**\n * Options for creating a UnitTestingModule.\n */\nexport interface UnitTestingModuleOptions {\n /**\n * List of providers to register. Only these services can be resolved.\n */\n providers: ProviderConfig[]\n\n /**\n * If true, unregistered dependencies will be auto-mocked instead of throwing.\n * Default: false (throws on unregistered dependencies)\n */\n allowUnregistered?: boolean\n\n /**\n * Logger for debugging.\n */\n logger?: Console | null\n\n /**\n * Container to use for the testing module.\n * If not provided, a new UnitTestContainer will be created.\n */\n container?: UnitTestContainer\n}\n\n/**\n * A lightweight testing module for isolated unit tests.\n *\n * Unlike `TestingModule`, this does NOT load Navios modules or create an application.\n * It uses `UnitTestContainer` which:\n * - Only allows explicitly provided services\n * - Automatically tracks all method calls via proxies\n * - Can auto-mock unregistered dependencies\n *\n * This is ideal for testing services in isolation without the overhead\n * of full module loading.\n *\n * @example\n * ```typescript\n * const module = UnitTestingModule.create({\n * providers: [\n * { token: UserService, useClass: UserService },\n * { token: DatabaseService, useValue: mockDatabase },\n * ],\n * })\n *\n * const userService = await module.get(UserService)\n * await userService.findUser('123')\n *\n * // Method calls are automatically tracked\n * module.expectCalled(UserService, 'findUser')\n * module.expectCalledWith(UserService, 'findUser', ['123'])\n *\n * await module.close()\n * ```\n */\nexport class UnitTestingModule {\n private constructor(private readonly container: UnitTestContainer) {}\n\n /**\n * Creates a new UnitTestingModule with the given providers.\n *\n * @example\n * ```typescript\n * const module = UnitTestingModule.create({\n * providers: [\n * { token: UserService, useClass: UserService },\n * { token: ConfigToken, useValue: { apiUrl: 'test' } },\n * ],\n * })\n * ```\n */\n static create(options: UnitTestingModuleOptions): UnitTestingModule {\n const container =\n options.container ??\n new UnitTestContainer({\n providers: options.providers,\n allowUnregistered: options.allowUnregistered,\n logger: options.logger,\n })\n\n return new UnitTestingModule(container)\n }\n\n /**\n * Gets the underlying UnitTestContainer for direct manipulation.\n */\n getContainer(): UnitTestContainer {\n return this.container\n }\n\n /**\n * Gets an instance from the container.\n *\n * All resolved instances are wrapped in tracking proxies,\n * so method calls are automatically recorded.\n *\n * @throws Error if the token is not in the providers list\n * and `allowUnregistered` is false\n */\n async get<T>(\n token: ClassTypeWithInstance<T> | InjectionToken<T, any>,\n ): Promise<T> {\n return this.container.get(token as any)\n }\n\n /**\n * Disposes the module and cleans up all resources.\n */\n async close(): Promise<void> {\n await this.container.clear()\n }\n\n /**\n * Enables auto-mocking for unregistered dependencies.\n * Unregistered services will return a proxy that throws on method access.\n */\n enableAutoMocking(): this {\n this.container.enableAutoMocking()\n return this\n }\n\n /**\n * Disables auto-mocking (strict mode).\n * Unregistered dependencies will throw immediately on resolution.\n */\n disableAutoMocking(): this {\n this.container.disableAutoMocking()\n return this\n }\n\n // ===========================================================================\n // ASSERTION HELPERS (delegated to UnitTestContainer)\n // ===========================================================================\n\n /**\n * Asserts that a service has been resolved at least once.\n */\n expectResolved(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectResolved(token)\n }\n\n /**\n * Asserts that a service has NOT been resolved.\n */\n expectNotResolved(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectNotResolved(token)\n }\n\n /**\n * Asserts that a service was auto-mocked (not in providers list).\n */\n expectAutoMocked(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectAutoMocked(token)\n }\n\n /**\n * Asserts that a service was NOT auto-mocked (is in providers list).\n */\n expectNotAutoMocked(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectNotAutoMocked(token)\n }\n\n /**\n * Asserts that a method was called on a service.\n * Method calls are automatically tracked via proxy.\n */\n expectCalled(\n token: ClassType | InjectionToken<any, any>,\n method: string,\n ): void {\n this.container.expectCalled(token, method)\n }\n\n /**\n * Asserts that a method was NOT called on a service.\n */\n expectNotCalled(\n token: ClassType | InjectionToken<any, any>,\n method: string,\n ): void {\n this.container.expectNotCalled(token, method)\n }\n\n /**\n * Asserts that a method was called with specific arguments.\n */\n expectCalledWith(\n token: ClassType | InjectionToken<any, any>,\n method: string,\n expectedArgs: unknown[],\n ): void {\n this.container.expectCalledWith(token, method, expectedArgs)\n }\n\n /**\n * Asserts that a method was called a specific number of times.\n */\n expectCallCount(\n token: ClassType | InjectionToken<any, any>,\n method: string,\n count: number,\n ): void {\n this.container.expectCallCount(token, method, count)\n }\n\n /**\n * Gets all recorded method calls for a service.\n */\n getMethodCalls(\n token: ClassType | InjectionToken<any, any>,\n ): MethodCallRecord[] {\n return this.container.getMethodCalls(token)\n }\n\n /**\n * Gets statistics about a service (instance count, method calls, lifecycle events).\n */\n getServiceStats(\n token: ClassType | InjectionToken<any, any>,\n ): MockServiceStats {\n return this.container.getServiceStats(token)\n }\n\n /**\n * Clears all recorded method calls.\n * Useful for resetting state between test assertions.\n */\n clearMethodCalls(): void {\n this.container.clearMethodCalls()\n }\n\n /**\n * Gets list of all registered provider token IDs.\n */\n getRegisteredTokenIds(): ReadonlySet<string> {\n return this.container.getRegisteredTokenIds()\n }\n\n /**\n * Gets list of all auto-mocked token IDs.\n */\n getAutoMockedTokenIds(): ReadonlySet<string> {\n return this.container.getAutoMockedTokenIds()\n }\n\n // ===========================================================================\n // LIFECYCLE ASSERTIONS\n // ===========================================================================\n\n /**\n * Asserts that a service's onServiceInit was called.\n */\n expectInitialized(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectInitialized(token)\n }\n\n /**\n * Asserts that a service's onServiceDestroy was called.\n */\n expectDestroyed(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectDestroyed(token)\n }\n\n /**\n * Asserts that a service has NOT been destroyed.\n */\n expectNotDestroyed(token: ClassType | InjectionToken<any, any>): void {\n this.container.expectNotDestroyed(token)\n }\n\n /**\n * Records a lifecycle event for tracking.\n * Call this from your mock implementations if needed.\n */\n recordLifecycleEvent(\n token: ClassType | InjectionToken<any, any>,\n event: 'created' | 'initialized' | 'destroyed',\n instanceName: string,\n ): void {\n this.container.recordLifecycleEvent(token, event, instanceName)\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- const require_src = require('./src-B6eISODM.cjs');
1
+ const require_src = require('./src-BRPtJ9fG.cjs');
2
2
  let _navios_di = require("@navios/di");
3
3
 
4
4
  //#region src/metadata/handler.metadata.mts
@@ -120,7 +120,7 @@ function hasModuleMetadata(target) {
120
120
  * }
121
121
  * }
122
122
  * ```
123
- */ function Controller({ guards, registry } = {}) {
123
+ */ function Controller({ guards, registry, priority, scope } = {}) {
124
124
  return function(target, context) {
125
125
  if (context.kind !== "class") throw new Error("[Navios] @Controller decorator can only be used on classes.");
126
126
  const token = _navios_di.InjectionToken.create(target);
@@ -130,7 +130,9 @@ function hasModuleMetadata(target) {
130
130
  }
131
131
  return (0, _navios_di.Injectable)({
132
132
  token,
133
- registry
133
+ registry,
134
+ priority,
135
+ scope
134
136
  })(target, context);
135
137
  };
136
138
  }
@@ -254,13 +256,13 @@ function Endpoint(endpoint) {
254
256
  //#region src/decorators/module.decorator.mts
255
257
  /**
256
258
  * Decorator that marks a class as a Navios module.
257
- *
259
+ *
258
260
  * Modules are the basic building blocks of a Navios application.
259
261
  * They organize controllers, services, and other modules into logical units.
260
- *
262
+ *
261
263
  * @param options - Module configuration options
262
264
  * @returns A class decorator
263
- *
265
+ *
264
266
  * @example
265
267
  * ```typescript
266
268
  * @Module({
@@ -270,7 +272,7 @@ function Endpoint(endpoint) {
270
272
  * })
271
273
  * export class AppModule {}
272
274
  * ```
273
- */ function Module({ controllers = [], imports = [], guards = [] } = {
275
+ */ function Module({ controllers = [], imports = [], guards = [], priority, registry } = {
274
276
  controllers: [],
275
277
  imports: [],
276
278
  guards: []
@@ -284,7 +286,9 @@ function Endpoint(endpoint) {
284
286
  for (const guard of Array.from(guards).reverse()) moduleMetadata.guards.add(guard);
285
287
  return (0, _navios_di.Injectable)({
286
288
  token,
287
- scope: _navios_di.InjectableScope.Singleton
289
+ scope: _navios_di.InjectableScope.Singleton,
290
+ priority,
291
+ registry
288
292
  })(target, context);
289
293
  };
290
294
  }
@@ -545,4 +549,4 @@ Object.defineProperty(exports, 'hasModuleMetadata', {
545
549
  return hasModuleMetadata;
546
550
  }
547
551
  });
548
- //# sourceMappingURL=use-guards.decorator-COR-9mZY.cjs.map
552
+ //# sourceMappingURL=use-guards.decorator-Bs8oDHOi.cjs.map