@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.
- package/CHANGELOG.md +47 -0
- package/lib/{index-BDNl7j1G.d.cts → index-D9MNh6Tx.d.mts} +36 -13
- package/lib/index-D9MNh6Tx.d.mts.map +1 -0
- package/lib/{index-BoP0cWT6.d.mts → index-Db1d3cwD.d.cts} +36 -13
- package/lib/index-Db1d3cwD.d.cts.map +1 -0
- package/lib/index.cjs +2 -2
- package/lib/index.d.cts +2 -2
- package/lib/index.d.mts +2 -2
- package/lib/index.mjs +2 -2
- package/lib/legacy-compat/index.cjs +1 -1
- package/lib/legacy-compat/index.cjs.map +1 -1
- package/lib/legacy-compat/index.d.cts +3 -3
- package/lib/legacy-compat/index.d.cts.map +1 -1
- package/lib/legacy-compat/index.d.mts +3 -3
- package/lib/legacy-compat/index.d.mts.map +1 -1
- package/lib/legacy-compat/index.mjs +1 -1
- package/lib/legacy-compat/index.mjs.map +1 -1
- package/lib/{src-B6eISODM.cjs → src-BRPtJ9fG.cjs} +12 -9
- package/lib/src-BRPtJ9fG.cjs.map +1 -0
- package/lib/{src-gBAChVRL.mjs → src-Bo23RIo-.mjs} +13 -10
- package/lib/src-Bo23RIo-.mjs.map +1 -0
- package/lib/testing/index.cjs +346 -29
- package/lib/testing/index.cjs.map +1 -1
- package/lib/testing/index.d.cts +299 -63
- package/lib/testing/index.d.cts.map +1 -1
- package/lib/testing/index.d.mts +299 -63
- package/lib/testing/index.d.mts.map +1 -1
- package/lib/testing/index.mjs +347 -31
- package/lib/testing/index.mjs.map +1 -1
- package/lib/{use-guards.decorator-COR-9mZY.cjs → use-guards.decorator-Bs8oDHOi.cjs} +13 -9
- package/lib/use-guards.decorator-Bs8oDHOi.cjs.map +1 -0
- package/lib/{use-guards.decorator-CUww54Nt.mjs → use-guards.decorator-CzVXuLkz.mjs} +12 -8
- package/lib/use-guards.decorator-CzVXuLkz.mjs.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/controller-resolver.spec.mts +19 -13
- package/src/__tests__/testing-module.spec.mts +459 -0
- package/src/__tests__/unit-testing-module.spec.mts +424 -0
- package/src/decorators/controller.decorator.mts +19 -2
- package/src/decorators/module.decorator.mts +23 -5
- package/src/legacy-compat/__type-tests__/legacy-decorators.spec-d.mts +2 -6
- package/src/legacy-compat/decorators/multipart.decorator.mts +4 -4
- package/src/legacy-compat/decorators/stream.decorator.mts +4 -4
- package/src/navios.application.mts +9 -9
- package/src/navios.environment.mts +3 -1
- package/src/navios.factory.mts +9 -27
- package/src/services/instance-resolver.service.mts +8 -7
- package/src/services/module-loader.service.mts +3 -2
- package/src/testing/index.mts +1 -0
- package/src/testing/testing-module.mts +255 -93
- package/src/testing/unit-testing-module.mts +298 -0
- package/lib/index-BDNl7j1G.d.cts.map +0 -1
- package/lib/index-BoP0cWT6.d.mts.map +0 -1
- package/lib/src-B6eISODM.cjs.map +0 -1
- package/lib/src-gBAChVRL.mjs.map +0 -1
- package/lib/use-guards.decorator-COR-9mZY.cjs.map +0 -1
- package/lib/use-guards.decorator-CUww54Nt.mjs.map +0 -1
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import { Injectable, InjectionToken } from '@navios/di'
|
|
2
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
3
|
+
|
|
4
|
+
import { UnitTestingModule } from '../testing/unit-testing-module.mjs'
|
|
5
|
+
|
|
6
|
+
describe('UnitTestingModule', () => {
|
|
7
|
+
let unitTestingModule: UnitTestingModule | null = null
|
|
8
|
+
|
|
9
|
+
afterEach(async () => {
|
|
10
|
+
if (unitTestingModule) {
|
|
11
|
+
await unitTestingModule.close()
|
|
12
|
+
unitTestingModule = null
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
describe('create', () => {
|
|
17
|
+
it('should create a unit testing module with providers', async () => {
|
|
18
|
+
@Injectable()
|
|
19
|
+
class TestService {
|
|
20
|
+
getValue() {
|
|
21
|
+
return 'test'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
unitTestingModule = UnitTestingModule.create({
|
|
26
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
expect(unitTestingModule).toBeInstanceOf(UnitTestingModule)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should create with useValue provider', async () => {
|
|
33
|
+
const TOKEN = InjectionToken.create<string>('test-token')
|
|
34
|
+
|
|
35
|
+
unitTestingModule = UnitTestingModule.create({
|
|
36
|
+
providers: [{ token: TOKEN, useValue: 'test-value' }],
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
const value = await unitTestingModule.get(TOKEN)
|
|
40
|
+
expect(value).toBe('test-value')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('should create with useClass provider', async () => {
|
|
44
|
+
@Injectable()
|
|
45
|
+
class OriginalService {
|
|
46
|
+
getValue() {
|
|
47
|
+
return 'original'
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@Injectable()
|
|
52
|
+
class MockService {
|
|
53
|
+
getValue() {
|
|
54
|
+
return 'mock'
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
unitTestingModule = UnitTestingModule.create({
|
|
59
|
+
providers: [{ token: OriginalService, useClass: MockService }],
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
const service = await unitTestingModule.get(OriginalService)
|
|
63
|
+
expect(service.getValue()).toBe('mock')
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it('should create with useFactory provider', async () => {
|
|
67
|
+
const TOKEN = InjectionToken.create<{ value: string }>('factory-token')
|
|
68
|
+
|
|
69
|
+
unitTestingModule = UnitTestingModule.create({
|
|
70
|
+
providers: [
|
|
71
|
+
{
|
|
72
|
+
token: TOKEN,
|
|
73
|
+
useFactory: () => ({ value: 'from-factory' }),
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const instance = await unitTestingModule.get(TOKEN)
|
|
79
|
+
expect(instance.value).toBe('from-factory')
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
describe('get', () => {
|
|
84
|
+
it('should resolve registered providers', async () => {
|
|
85
|
+
@Injectable()
|
|
86
|
+
class TestService {
|
|
87
|
+
getValue() {
|
|
88
|
+
return 'test'
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
unitTestingModule = UnitTestingModule.create({
|
|
93
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
const service = await unitTestingModule.get(TestService)
|
|
97
|
+
expect(service.getValue()).toBe('test')
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('should throw for unregistered providers in strict mode', async () => {
|
|
101
|
+
@Injectable()
|
|
102
|
+
class RegisteredService {}
|
|
103
|
+
|
|
104
|
+
@Injectable()
|
|
105
|
+
class UnregisteredService {}
|
|
106
|
+
|
|
107
|
+
unitTestingModule = UnitTestingModule.create({
|
|
108
|
+
providers: [{ token: RegisteredService, useClass: RegisteredService }],
|
|
109
|
+
allowUnregistered: false,
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
await expect(unitTestingModule.get(UnregisteredService)).rejects.toThrow()
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('should auto-mock unregistered providers when allowUnregistered is true', async () => {
|
|
116
|
+
@Injectable()
|
|
117
|
+
class RegisteredService {}
|
|
118
|
+
|
|
119
|
+
@Injectable()
|
|
120
|
+
class UnregisteredService {}
|
|
121
|
+
|
|
122
|
+
unitTestingModule = UnitTestingModule.create({
|
|
123
|
+
providers: [{ token: RegisteredService, useClass: RegisteredService }],
|
|
124
|
+
allowUnregistered: true,
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
const unregistered = await unitTestingModule.get(UnregisteredService)
|
|
128
|
+
|
|
129
|
+
// Auto-mocked service should exist but throw on method access
|
|
130
|
+
expect(unregistered).toBeDefined()
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
describe('auto-mocking', () => {
|
|
135
|
+
it('should enable auto-mocking with enableAutoMocking()', async () => {
|
|
136
|
+
@Injectable()
|
|
137
|
+
class UnregisteredService {}
|
|
138
|
+
|
|
139
|
+
unitTestingModule = UnitTestingModule.create({
|
|
140
|
+
providers: [],
|
|
141
|
+
allowUnregistered: false,
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
unitTestingModule.enableAutoMocking()
|
|
145
|
+
|
|
146
|
+
const service = await unitTestingModule.get(UnregisteredService)
|
|
147
|
+
expect(service).toBeDefined()
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
it('should disable auto-mocking with disableAutoMocking()', async () => {
|
|
151
|
+
@Injectable()
|
|
152
|
+
class UnregisteredService {}
|
|
153
|
+
|
|
154
|
+
unitTestingModule = UnitTestingModule.create({
|
|
155
|
+
providers: [],
|
|
156
|
+
allowUnregistered: true,
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
unitTestingModule.disableAutoMocking()
|
|
160
|
+
|
|
161
|
+
await expect(unitTestingModule.get(UnregisteredService)).rejects.toThrow()
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it('should track auto-mocked services', async () => {
|
|
165
|
+
@Injectable()
|
|
166
|
+
class UnregisteredService {}
|
|
167
|
+
|
|
168
|
+
unitTestingModule = UnitTestingModule.create({
|
|
169
|
+
providers: [],
|
|
170
|
+
allowUnregistered: true,
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
await unitTestingModule.get(UnregisteredService)
|
|
174
|
+
|
|
175
|
+
expect(() => unitTestingModule!.expectAutoMocked(UnregisteredService)).not.toThrow()
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
describe('automatic method call tracking', () => {
|
|
180
|
+
it('should automatically track method calls via proxy', async () => {
|
|
181
|
+
@Injectable()
|
|
182
|
+
class TestService {
|
|
183
|
+
greet(name: string) {
|
|
184
|
+
return `Hello, ${name}!`
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
unitTestingModule = UnitTestingModule.create({
|
|
189
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
const service = await unitTestingModule.get(TestService)
|
|
193
|
+
service.greet('World')
|
|
194
|
+
|
|
195
|
+
expect(() => unitTestingModule!.expectCalled(TestService, 'greet')).not.toThrow()
|
|
196
|
+
expect(() =>
|
|
197
|
+
unitTestingModule!.expectCalledWith(TestService, 'greet', ['World']),
|
|
198
|
+
).not.toThrow()
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
it('should track multiple method calls', async () => {
|
|
202
|
+
@Injectable()
|
|
203
|
+
class TestService {
|
|
204
|
+
methodA() {
|
|
205
|
+
return 'a'
|
|
206
|
+
}
|
|
207
|
+
methodB(x: number, y: number) {
|
|
208
|
+
return x + y
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
unitTestingModule = UnitTestingModule.create({
|
|
213
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
const service = await unitTestingModule.get(TestService)
|
|
217
|
+
service.methodA()
|
|
218
|
+
service.methodB(1, 2)
|
|
219
|
+
service.methodB(3, 4)
|
|
220
|
+
|
|
221
|
+
expect(() => unitTestingModule!.expectCallCount(TestService, 'methodA', 1)).not.toThrow()
|
|
222
|
+
expect(() => unitTestingModule!.expectCallCount(TestService, 'methodB', 2)).not.toThrow()
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
it('should track async method calls', async () => {
|
|
226
|
+
@Injectable()
|
|
227
|
+
class AsyncService {
|
|
228
|
+
async fetchData(id: string) {
|
|
229
|
+
return { id, data: 'fetched' }
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
unitTestingModule = UnitTestingModule.create({
|
|
234
|
+
providers: [{ token: AsyncService, useClass: AsyncService }],
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
const service = await unitTestingModule.get(AsyncService)
|
|
238
|
+
await service.fetchData('123')
|
|
239
|
+
|
|
240
|
+
expect(() => unitTestingModule!.expectCalled(AsyncService, 'fetchData')).not.toThrow()
|
|
241
|
+
expect(() =>
|
|
242
|
+
unitTestingModule!.expectCalledWith(AsyncService, 'fetchData', ['123']),
|
|
243
|
+
).not.toThrow()
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
it('should expose getMethodCalls for custom assertions', async () => {
|
|
247
|
+
@Injectable()
|
|
248
|
+
class TestService {
|
|
249
|
+
process(value: string) {
|
|
250
|
+
return value.toUpperCase()
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
unitTestingModule = UnitTestingModule.create({
|
|
255
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
const service = await unitTestingModule.get(TestService)
|
|
259
|
+
service.process('hello')
|
|
260
|
+
service.process('world')
|
|
261
|
+
|
|
262
|
+
const calls = unitTestingModule.getMethodCalls(TestService)
|
|
263
|
+
|
|
264
|
+
expect(calls).toHaveLength(2)
|
|
265
|
+
expect(calls[0].args).toEqual(['hello'])
|
|
266
|
+
expect(calls[0].result).toBe('HELLO')
|
|
267
|
+
expect(calls[1].args).toEqual(['world'])
|
|
268
|
+
expect(calls[1].result).toBe('WORLD')
|
|
269
|
+
})
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
describe('assertion helpers', () => {
|
|
273
|
+
it('should expose expectResolved', async () => {
|
|
274
|
+
@Injectable()
|
|
275
|
+
class TestService {}
|
|
276
|
+
|
|
277
|
+
unitTestingModule = UnitTestingModule.create({
|
|
278
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
await unitTestingModule.get(TestService)
|
|
282
|
+
|
|
283
|
+
expect(() => unitTestingModule!.expectResolved(TestService)).not.toThrow()
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
it('should expose expectNotResolved', async () => {
|
|
287
|
+
@Injectable()
|
|
288
|
+
class TestService {}
|
|
289
|
+
|
|
290
|
+
unitTestingModule = UnitTestingModule.create({
|
|
291
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
292
|
+
})
|
|
293
|
+
|
|
294
|
+
expect(() => unitTestingModule!.expectNotResolved(TestService)).not.toThrow()
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
it('should expose expectNotCalled', async () => {
|
|
298
|
+
@Injectable()
|
|
299
|
+
class TestService {
|
|
300
|
+
method() {
|
|
301
|
+
return 'test'
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
unitTestingModule = UnitTestingModule.create({
|
|
306
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
await unitTestingModule.get(TestService)
|
|
310
|
+
// Method not called
|
|
311
|
+
|
|
312
|
+
expect(() => unitTestingModule!.expectNotCalled(TestService, 'method')).not.toThrow()
|
|
313
|
+
})
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
describe('service stats', () => {
|
|
317
|
+
it('should get service stats', async () => {
|
|
318
|
+
@Injectable()
|
|
319
|
+
class TestService {
|
|
320
|
+
doWork() {
|
|
321
|
+
return 'done'
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
unitTestingModule = UnitTestingModule.create({
|
|
326
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
const service = await unitTestingModule.get(TestService)
|
|
330
|
+
service.doWork()
|
|
331
|
+
service.doWork()
|
|
332
|
+
|
|
333
|
+
const stats = unitTestingModule.getServiceStats(TestService)
|
|
334
|
+
|
|
335
|
+
expect(stats.methodCalls).toHaveLength(2)
|
|
336
|
+
expect(stats.methodCalls[0].method).toBe('doWork')
|
|
337
|
+
})
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
describe('clearMethodCalls', () => {
|
|
341
|
+
it('should clear all method calls', async () => {
|
|
342
|
+
@Injectable()
|
|
343
|
+
class TestService {
|
|
344
|
+
method() {
|
|
345
|
+
return 'test'
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
unitTestingModule = UnitTestingModule.create({
|
|
350
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
const service = await unitTestingModule.get(TestService)
|
|
354
|
+
service.method()
|
|
355
|
+
service.method()
|
|
356
|
+
|
|
357
|
+
expect(unitTestingModule.getMethodCalls(TestService)).toHaveLength(2)
|
|
358
|
+
|
|
359
|
+
unitTestingModule.clearMethodCalls()
|
|
360
|
+
|
|
361
|
+
expect(unitTestingModule.getMethodCalls(TestService)).toHaveLength(0)
|
|
362
|
+
})
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
describe('registered and auto-mocked token tracking', () => {
|
|
366
|
+
it('should track registered token IDs', async () => {
|
|
367
|
+
@Injectable()
|
|
368
|
+
class ServiceA {}
|
|
369
|
+
|
|
370
|
+
@Injectable()
|
|
371
|
+
class ServiceB {}
|
|
372
|
+
|
|
373
|
+
unitTestingModule = UnitTestingModule.create({
|
|
374
|
+
providers: [
|
|
375
|
+
{ token: ServiceA, useClass: ServiceA },
|
|
376
|
+
{ token: ServiceB, useClass: ServiceB },
|
|
377
|
+
],
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
const registeredIds = unitTestingModule.getRegisteredTokenIds()
|
|
381
|
+
|
|
382
|
+
expect(registeredIds.size).toBe(2)
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
it('should track auto-mocked token IDs', async () => {
|
|
386
|
+
@Injectable()
|
|
387
|
+
class UnregisteredA {}
|
|
388
|
+
|
|
389
|
+
@Injectable()
|
|
390
|
+
class UnregisteredB {}
|
|
391
|
+
|
|
392
|
+
unitTestingModule = UnitTestingModule.create({
|
|
393
|
+
providers: [],
|
|
394
|
+
allowUnregistered: true,
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
await unitTestingModule.get(UnregisteredA)
|
|
398
|
+
await unitTestingModule.get(UnregisteredB)
|
|
399
|
+
|
|
400
|
+
const autoMockedIds = unitTestingModule.getAutoMockedTokenIds()
|
|
401
|
+
|
|
402
|
+
expect(autoMockedIds.size).toBe(2)
|
|
403
|
+
})
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
describe('close', () => {
|
|
407
|
+
it('should clean up resources', async () => {
|
|
408
|
+
@Injectable()
|
|
409
|
+
class TestService {}
|
|
410
|
+
|
|
411
|
+
unitTestingModule = UnitTestingModule.create({
|
|
412
|
+
providers: [{ token: TestService, useClass: TestService }],
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
await unitTestingModule.get(TestService)
|
|
416
|
+
await unitTestingModule.close()
|
|
417
|
+
|
|
418
|
+
// After close, method calls should be cleared
|
|
419
|
+
expect(unitTestingModule.getMethodCalls(TestService)).toHaveLength(0)
|
|
420
|
+
|
|
421
|
+
unitTestingModule = null // Prevent afterEach from calling close again
|
|
422
|
+
})
|
|
423
|
+
})
|
|
424
|
+
})
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClassType } from '@navios/di'
|
|
1
|
+
import type { ClassType, InjectableScope } from '@navios/di'
|
|
2
2
|
|
|
3
3
|
import { Injectable, InjectionToken, Registry } from '@navios/di'
|
|
4
4
|
|
|
@@ -18,6 +18,16 @@ export interface ControllerOptions {
|
|
|
18
18
|
* Registry is used to store the controller and its endpoints.
|
|
19
19
|
*/
|
|
20
20
|
registry?: Registry
|
|
21
|
+
/**
|
|
22
|
+
* Priority to use for the controller.
|
|
23
|
+
* Priority is used to sort the controller in the registry.
|
|
24
|
+
*/
|
|
25
|
+
priority?: number
|
|
26
|
+
/**
|
|
27
|
+
* Scope to use for the controller.
|
|
28
|
+
* Scope is used to determine the scope of the controller.
|
|
29
|
+
*/
|
|
30
|
+
scope?: InjectableScope
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
/**
|
|
@@ -40,7 +50,12 @@ export interface ControllerOptions {
|
|
|
40
50
|
* }
|
|
41
51
|
* ```
|
|
42
52
|
*/
|
|
43
|
-
export function Controller({
|
|
53
|
+
export function Controller({
|
|
54
|
+
guards,
|
|
55
|
+
registry,
|
|
56
|
+
priority,
|
|
57
|
+
scope,
|
|
58
|
+
}: ControllerOptions = {}) {
|
|
44
59
|
return function (target: ClassType, context: ClassDecoratorContext) {
|
|
45
60
|
if (context.kind !== 'class') {
|
|
46
61
|
throw new Error(
|
|
@@ -59,6 +74,8 @@ export function Controller({ guards, registry }: ControllerOptions = {}) {
|
|
|
59
74
|
return Injectable({
|
|
60
75
|
token,
|
|
61
76
|
registry,
|
|
77
|
+
priority,
|
|
78
|
+
scope,
|
|
62
79
|
})(target, context)
|
|
63
80
|
}
|
|
64
81
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClassType } from '@navios/di'
|
|
1
|
+
import type { ClassType, Registry } from '@navios/di'
|
|
2
2
|
|
|
3
3
|
import { Injectable, InjectableScope, InjectionToken } from '@navios/di'
|
|
4
4
|
|
|
@@ -23,17 +23,27 @@ export interface ModuleOptions {
|
|
|
23
23
|
* Guards are executed in reverse order (last guard first).
|
|
24
24
|
*/
|
|
25
25
|
guards?: ClassType[] | Set<ClassType>
|
|
26
|
+
/**
|
|
27
|
+
* Priority to use for the module.
|
|
28
|
+
* Priority is used to sort the module in the registry.
|
|
29
|
+
*/
|
|
30
|
+
priority?: number
|
|
31
|
+
/**
|
|
32
|
+
* Registry to use for the module.
|
|
33
|
+
* Registry is used to store the module and its controllers.
|
|
34
|
+
*/
|
|
35
|
+
registry?: Registry
|
|
26
36
|
}
|
|
27
37
|
|
|
28
38
|
/**
|
|
29
39
|
* Decorator that marks a class as a Navios module.
|
|
30
|
-
*
|
|
40
|
+
*
|
|
31
41
|
* Modules are the basic building blocks of a Navios application.
|
|
32
42
|
* They organize controllers, services, and other modules into logical units.
|
|
33
|
-
*
|
|
43
|
+
*
|
|
34
44
|
* @param options - Module configuration options
|
|
35
45
|
* @returns A class decorator
|
|
36
|
-
*
|
|
46
|
+
*
|
|
37
47
|
* @example
|
|
38
48
|
* ```typescript
|
|
39
49
|
* @Module({
|
|
@@ -45,7 +55,13 @@ export interface ModuleOptions {
|
|
|
45
55
|
* ```
|
|
46
56
|
*/
|
|
47
57
|
export function Module(
|
|
48
|
-
{
|
|
58
|
+
{
|
|
59
|
+
controllers = [],
|
|
60
|
+
imports = [],
|
|
61
|
+
guards = [],
|
|
62
|
+
priority,
|
|
63
|
+
registry,
|
|
64
|
+
}: ModuleOptions = {
|
|
49
65
|
controllers: [],
|
|
50
66
|
imports: [],
|
|
51
67
|
guards: [],
|
|
@@ -71,6 +87,8 @@ export function Module(
|
|
|
71
87
|
return Injectable({
|
|
72
88
|
token,
|
|
73
89
|
scope: InjectableScope.Singleton,
|
|
90
|
+
priority,
|
|
91
|
+
registry,
|
|
74
92
|
})(target, context)
|
|
75
93
|
}
|
|
76
94
|
}
|
|
@@ -138,9 +138,7 @@ describe('Legacy Decorators Type Safety', () => {
|
|
|
138
138
|
// - request.urlParams.userId: string | number
|
|
139
139
|
// - request.params.page: number
|
|
140
140
|
// - request.params.limit: number
|
|
141
|
-
expectTypeOf(request.urlParams.userId).toEqualTypeOf<
|
|
142
|
-
string | number
|
|
143
|
-
>()
|
|
141
|
+
expectTypeOf(request.urlParams.userId).toEqualTypeOf<string>()
|
|
144
142
|
expectTypeOf(request.params.page).toEqualTypeOf<number>()
|
|
145
143
|
expectTypeOf(request.params.limit).toEqualTypeOf<number>()
|
|
146
144
|
return {
|
|
@@ -270,9 +268,7 @@ describe('Legacy Decorators Type Safety', () => {
|
|
|
270
268
|
// - request.urlParams.fileId: string | number
|
|
271
269
|
// - request.params.page: number
|
|
272
270
|
// - request.params.limit: number
|
|
273
|
-
expectTypeOf(request.urlParams.fileId).toEqualTypeOf<
|
|
274
|
-
string | number
|
|
275
|
-
>()
|
|
271
|
+
expectTypeOf(request.urlParams.fileId).toEqualTypeOf<string>()
|
|
276
272
|
expectTypeOf(request.params.page).toEqualTypeOf<number>()
|
|
277
273
|
expectTypeOf(request.params.limit).toEqualTypeOf<number>()
|
|
278
274
|
}
|
|
@@ -22,11 +22,11 @@ type MultipartMethodDescriptor<
|
|
|
22
22
|
(
|
|
23
23
|
params: QuerySchema extends ZodObject
|
|
24
24
|
? RequestSchema extends ZodType
|
|
25
|
-
? EndpointFunctionArgs<Url, QuerySchema, RequestSchema>
|
|
26
|
-
: EndpointFunctionArgs<Url, QuerySchema, undefined>
|
|
25
|
+
? EndpointFunctionArgs<Url, QuerySchema, RequestSchema, true>
|
|
26
|
+
: EndpointFunctionArgs<Url, QuerySchema, undefined, true>
|
|
27
27
|
: RequestSchema extends ZodType
|
|
28
|
-
? EndpointFunctionArgs<Url, undefined, RequestSchema>
|
|
29
|
-
: EndpointFunctionArgs<Url, undefined, undefined>,
|
|
28
|
+
? EndpointFunctionArgs<Url, undefined, RequestSchema, true>
|
|
29
|
+
: EndpointFunctionArgs<Url, undefined, undefined, true>,
|
|
30
30
|
) => Promise<z.input<ResponseSchema>>
|
|
31
31
|
>
|
|
32
32
|
|
|
@@ -21,11 +21,11 @@ type StreamMethodDescriptor<
|
|
|
21
21
|
(
|
|
22
22
|
params: QuerySchema extends ZodObject
|
|
23
23
|
? RequestSchema extends ZodType
|
|
24
|
-
? EndpointFunctionArgs<Url, QuerySchema, RequestSchema>
|
|
25
|
-
: EndpointFunctionArgs<Url, QuerySchema, undefined>
|
|
24
|
+
? EndpointFunctionArgs<Url, QuerySchema, RequestSchema, true>
|
|
25
|
+
: EndpointFunctionArgs<Url, QuerySchema, undefined, true>
|
|
26
26
|
: RequestSchema extends ZodType
|
|
27
|
-
? EndpointFunctionArgs<Url, undefined, RequestSchema>
|
|
28
|
-
: EndpointFunctionArgs<Url, undefined, undefined>,
|
|
27
|
+
? EndpointFunctionArgs<Url, undefined, RequestSchema, true>
|
|
28
|
+
: EndpointFunctionArgs<Url, undefined, undefined, true>,
|
|
29
29
|
reply: any,
|
|
30
30
|
) => Promise<void>
|
|
31
31
|
>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ClassTypeWithInstance } from '@navios/di'
|
|
1
|
+
import type { ClassTypeWithInstance, Registry } from '@navios/di'
|
|
2
2
|
|
|
3
3
|
import { Container, inject, Injectable } from '@navios/di'
|
|
4
4
|
|
|
@@ -19,9 +19,9 @@ import { ModuleLoaderService } from './services/index.mjs'
|
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Options for configuring the Navios application context.
|
|
22
|
-
* These options control
|
|
22
|
+
* These options control the application configuration.
|
|
23
23
|
*/
|
|
24
|
-
export interface
|
|
24
|
+
export interface NaviosApplicationOptions {
|
|
25
25
|
/**
|
|
26
26
|
* Specifies the logger to use. Pass `false` to turn off logging.
|
|
27
27
|
*
|
|
@@ -31,18 +31,18 @@ export interface NaviosApplicationContextOptions {
|
|
|
31
31
|
*/
|
|
32
32
|
logger?: LoggerService | LogLevel[] | false
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Specifies a custom registry to use. Useful for testing.
|
|
36
|
+
* If not provided, a new Registry will be created.
|
|
37
|
+
*/
|
|
38
|
+
registry?: Registry
|
|
39
|
+
|
|
34
40
|
/**
|
|
35
41
|
* Specifies a custom container to use. Useful for testing.
|
|
36
42
|
* If not provided, a new Container will be created.
|
|
37
43
|
*/
|
|
38
44
|
container?: Container
|
|
39
|
-
}
|
|
40
45
|
|
|
41
|
-
/**
|
|
42
|
-
* Complete options for creating a Navios application.
|
|
43
|
-
* Extends NaviosApplicationContextOptions with adapter configuration.
|
|
44
|
-
*/
|
|
45
|
-
export interface NaviosApplicationOptions extends NaviosApplicationContextOptions {
|
|
46
46
|
/**
|
|
47
47
|
* HTTP adapter environment(s) to use for the application.
|
|
48
48
|
* Can be a single adapter or an array of adapters.
|
|
@@ -17,7 +17,9 @@ export class NaviosEnvironment {
|
|
|
17
17
|
setupHttpEnvironment(
|
|
18
18
|
tokens: Map<InjectionToken<any, undefined>, AnyInjectableType>,
|
|
19
19
|
) {
|
|
20
|
-
|
|
20
|
+
for (const [token, value] of tokens) {
|
|
21
|
+
this.httpTokens.set(token, value)
|
|
22
|
+
}
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
getHttpToken(token: InjectionToken<any, undefined>) {
|