@navios/core 0.1.14 → 0.2.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 (71) hide show
  1. package/dist/_tsup-dts-rollup.d.mts +185 -434
  2. package/dist/_tsup-dts-rollup.d.ts +185 -434
  3. package/dist/index.d.mts +62 -46
  4. package/dist/index.d.ts +62 -46
  5. package/dist/index.js +482 -1328
  6. package/dist/index.mjs +484 -1292
  7. package/package.json +3 -2
  8. package/src/adapters/endpoint-adapter.service.mts +72 -0
  9. package/src/adapters/handler-adapter.interface.mts +21 -0
  10. package/src/adapters/index.mts +4 -0
  11. package/src/adapters/multipart-adapter.service.mts +131 -0
  12. package/src/adapters/stream-adapter.service.mts +91 -0
  13. package/src/attribute.factory.mts +14 -14
  14. package/src/config/config.provider.mts +16 -12
  15. package/src/decorators/controller.decorator.mts +3 -8
  16. package/src/decorators/endpoint.decorator.mts +7 -3
  17. package/src/decorators/header.decorator.mts +1 -6
  18. package/src/decorators/http-code.decorator.mts +1 -6
  19. package/src/decorators/module.decorator.mts +16 -21
  20. package/src/decorators/multipart.decorator.mts +7 -3
  21. package/src/decorators/stream.decorator.mts +7 -3
  22. package/src/decorators/use-guards.decorator.mts +3 -2
  23. package/src/index.mts +2 -1
  24. package/src/logger/console-logger.service.mts +3 -2
  25. package/src/logger/logger.factory.mts +4 -5
  26. package/src/logger/logger.service.mts +2 -2
  27. package/src/metadata/controller.metadata.mts +6 -5
  28. package/src/metadata/{endpoint.metadata.mts → handler.metadata.mts} +18 -28
  29. package/src/metadata/index.mts +1 -2
  30. package/src/metadata/module.metadata.mts +3 -2
  31. package/src/navios.application.mts +12 -12
  32. package/src/navios.factory.mts +4 -2
  33. package/src/services/controller-adapter.service.mts +65 -245
  34. package/src/services/execution-context.mts +4 -3
  35. package/src/services/guard-runner.service.mts +4 -6
  36. package/src/services/module-loader.service.mts +4 -2
  37. package/src/tokens/application.token.mts +1 -1
  38. package/src/tokens/execution-context.token.mts +2 -1
  39. package/src/tokens/reply.token.mts +1 -1
  40. package/src/tokens/request.token.mts +1 -1
  41. package/src/metadata/injectable.metadata.mts +0 -11
  42. package/src/service-locator/__tests__/injectable.spec.mts +0 -171
  43. package/src/service-locator/__tests__/injection-token.spec.mts +0 -124
  44. package/src/service-locator/decorators/get-injectable-token.mts +0 -19
  45. package/src/service-locator/decorators/index.mts +0 -2
  46. package/src/service-locator/decorators/injectable.decorator.mts +0 -64
  47. package/src/service-locator/enums/index.mts +0 -1
  48. package/src/service-locator/enums/injectable-scope.enum.mts +0 -10
  49. package/src/service-locator/errors/errors.enum.mts +0 -8
  50. package/src/service-locator/errors/factory-not-found.mts +0 -8
  51. package/src/service-locator/errors/factory-token-not-resolved.mts +0 -10
  52. package/src/service-locator/errors/index.mts +0 -7
  53. package/src/service-locator/errors/instance-destroying.mts +0 -8
  54. package/src/service-locator/errors/instance-expired.mts +0 -8
  55. package/src/service-locator/errors/instance-not-found.mts +0 -8
  56. package/src/service-locator/errors/unknown-error.mts +0 -15
  57. package/src/service-locator/event-emitter.mts +0 -107
  58. package/src/service-locator/index.mts +0 -15
  59. package/src/service-locator/inject.mts +0 -28
  60. package/src/service-locator/injection-token.mts +0 -92
  61. package/src/service-locator/injector.mts +0 -18
  62. package/src/service-locator/interfaces/factory.interface.mts +0 -3
  63. package/src/service-locator/override.mts +0 -22
  64. package/src/service-locator/proxy-service-locator.mts +0 -99
  65. package/src/service-locator/resolve-service.mts +0 -46
  66. package/src/service-locator/service-locator-abstract-factory-context.mts +0 -23
  67. package/src/service-locator/service-locator-event-bus.mts +0 -96
  68. package/src/service-locator/service-locator-instance-holder.mts +0 -63
  69. package/src/service-locator/service-locator-manager.mts +0 -89
  70. package/src/service-locator/service-locator.mts +0 -535
  71. package/src/service-locator/sync-injector.mts +0 -52
@@ -1,23 +1,20 @@
1
- import type { BaseEndpointConfig } from '@navios/common'
1
+ import type { ClassType } from '@navios/di'
2
2
  import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
3
3
  import type { ZodTypeProvider } from 'fastify-type-provider-zod'
4
- import type { AnyZodObject } from 'zod'
5
4
 
6
- import { NaviosException } from '@navios/common'
7
-
8
- import { ZodArray } from 'zod'
9
-
10
- import type { EndpointMetadata, ModuleMetadata } from '../metadata/index.mjs'
11
- import type { ClassType } from '../service-locator/index.mjs'
12
-
13
- import { Logger } from '../logger/index.mjs'
14
- import { EndpointType, extractControllerMetadata } from '../metadata/index.mjs'
15
5
  import {
16
- getServiceLocator,
6
+ getGlobalServiceLocator,
17
7
  inject,
18
8
  Injectable,
9
+ InjectionToken,
19
10
  syncInject,
20
- } from '../service-locator/index.mjs'
11
+ } from '@navios/di'
12
+
13
+ import type { HandlerAdapterInterface } from '../adapters/index.mjs'
14
+ import type { ModuleMetadata } from '../metadata/index.mjs'
15
+
16
+ import { Logger } from '../logger/index.mjs'
17
+ import { extractControllerMetadata } from '../metadata/index.mjs'
21
18
  import { ExecutionContextToken, Reply, Request } from '../tokens/index.mjs'
22
19
  import { ExecutionContext } from './execution-context.mjs'
23
20
  import { GuardRunnerService } from './guard-runner.service.mjs'
@@ -29,32 +26,51 @@ export class ControllerAdapterService {
29
26
  context: ControllerAdapterService.name,
30
27
  })
31
28
 
32
- setupController(
29
+ async setupController(
33
30
  controller: ClassType,
34
31
  instance: FastifyInstance,
35
32
  moduleMetadata: ModuleMetadata,
36
- ): void {
33
+ ) {
37
34
  const controllerMetadata = extractControllerMetadata(controller)
38
35
  for (const endpoint of controllerMetadata.endpoints) {
39
- const { classMethod, url, httpMethod } = endpoint
36
+ const { classMethod, url, httpMethod, adapterToken } = endpoint
40
37
 
41
- if (!url) {
38
+ if (!url || !adapterToken) {
42
39
  throw new Error(
43
40
  `[Navios] Malformed Endpoint ${controller.name}:${classMethod}`,
44
41
  )
45
42
  }
43
+ const adapter = await inject(
44
+ adapterToken as InjectionToken<HandlerAdapterInterface>,
45
+ )
46
46
  const executionContext = new ExecutionContext(
47
47
  moduleMetadata,
48
48
  controllerMetadata,
49
49
  endpoint,
50
50
  )
51
- instance.withTypeProvider<ZodTypeProvider>().route({
52
- method: httpMethod,
53
- url: url.replaceAll('$', ':'),
54
- schema: this.provideSchemaForConfig(endpoint),
55
- preHandler: this.providePreHandler(executionContext),
56
- handler: this.provideHandler(controller, executionContext, endpoint),
57
- })
51
+ const hasSchema = adapter.hasSchema?.(endpoint) ?? false
52
+ if (hasSchema) {
53
+ instance.withTypeProvider<ZodTypeProvider>().route({
54
+ method: httpMethod,
55
+ url: url.replaceAll('$', ':'),
56
+ schema: adapter.provideSchema?.(endpoint) ?? {},
57
+ preHandler: this.providePreHandler(executionContext),
58
+ handler: this.wrapHandler(
59
+ executionContext,
60
+ adapter.provideHandler(controller, executionContext, endpoint),
61
+ ),
62
+ })
63
+ } else {
64
+ instance.route({
65
+ method: httpMethod,
66
+ url: url.replaceAll('$', ':'),
67
+ preHandler: this.providePreHandler(executionContext),
68
+ handler: this.wrapHandler(
69
+ executionContext,
70
+ adapter.provideHandler(controller, executionContext, endpoint),
71
+ ),
72
+ })
73
+ }
58
74
 
59
75
  this.logger.debug(
60
76
  `Registered ${httpMethod} ${url} for ${controller.name}:${classMethod}`,
@@ -65,239 +81,43 @@ export class ControllerAdapterService {
65
81
  providePreHandler(executionContext: ExecutionContext) {
66
82
  const guards = this.guardRunner.makeContext(executionContext)
67
83
  return guards.size > 0
68
- ? async (request: FastifyRequest, reply: FastifyReply) => {
69
- getServiceLocator().registerInstance(Request, request)
70
- getServiceLocator().registerInstance(Reply, reply)
71
- getServiceLocator().registerInstance(
72
- ExecutionContextToken,
73
- executionContext,
74
- )
75
- executionContext.provideRequest(request)
76
- executionContext.provideReply(reply)
77
- let canActivate = true
78
- try {
84
+ ? this.wrapHandler(
85
+ executionContext,
86
+ async (request: FastifyRequest, reply: FastifyReply) => {
87
+ let canActivate = true
79
88
  canActivate = await this.guardRunner.runGuards(
80
89
  guards,
81
90
  executionContext,
82
91
  )
83
- } finally {
84
- getServiceLocator().removeInstance(Request)
85
- getServiceLocator().removeInstance(Reply)
86
- getServiceLocator().removeInstance(ExecutionContextToken)
87
- }
88
- if (!canActivate) {
89
- return reply
90
- }
91
- }
92
- : undefined
93
- }
94
-
95
- private provideSchemaForConfig(endpointMetadata: EndpointMetadata) {
96
- if (!endpointMetadata.config) {
97
- this.logger.warn(`No config found for endpoint ${endpointMetadata.url}`)
98
- return {}
99
- }
100
- const { querySchema, requestSchema, responseSchema } =
101
- endpointMetadata.config as BaseEndpointConfig
102
- const schema: Record<string, any> = {}
103
- if (querySchema) {
104
- schema.querystring = querySchema
105
- }
106
- if (requestSchema && endpointMetadata.type !== EndpointType.Multipart) {
107
- schema.body = requestSchema
108
- }
109
- if (responseSchema) {
110
- schema.response = {
111
- 200: responseSchema,
112
- }
113
- }
114
-
115
- return schema
116
- }
117
-
118
- private provideHandler(
119
- controller: ClassType,
120
- executionContext: ExecutionContext,
121
- endpointMetadata: EndpointMetadata,
122
- ): (request: FastifyRequest, reply: FastifyReply) => Promise<void> {
123
- switch (endpointMetadata.type) {
124
- case EndpointType.Unknown:
125
- this.logger.error(
126
- `Unknown endpoint type ${endpointMetadata.type} for ${controller.name}:${endpointMetadata.classMethod}`,
127
- )
128
- throw new NaviosException('Unknown endpoint type')
129
- case EndpointType.Endpoint:
130
- return this.provideHandlerForConfig(
131
- controller,
132
- executionContext,
133
- endpointMetadata,
134
- )
135
- case EndpointType.Stream:
136
- return this.provideHandlerForStream(
137
- controller,
138
- executionContext,
139
- endpointMetadata,
140
- )
141
- case EndpointType.Multipart:
142
- return this.provideHandlerForMultipart(
143
- controller,
144
- executionContext,
145
- endpointMetadata,
92
+ if (!canActivate) {
93
+ return reply
94
+ }
95
+ },
146
96
  )
147
- case EndpointType.Handler:
148
- this.logger.error('Not implemented yet')
149
- throw new NaviosException('Not implemented yet')
150
- }
151
- }
152
-
153
- private provideHandlerForConfig(
154
- controller: ClassType,
155
- executionContext: ExecutionContext,
156
- endpointMetadata: EndpointMetadata,
157
- ): (request: FastifyRequest, reply: FastifyReply) => Promise<void> {
158
- return async (request, reply) => {
159
- getServiceLocator().registerInstance(Request, request)
160
- getServiceLocator().registerInstance(Reply, reply)
161
- getServiceLocator().registerInstance(
162
- ExecutionContextToken,
163
- executionContext,
164
- )
165
- executionContext.provideRequest(request)
166
- executionContext.provideReply(reply)
167
- const controllerInstance = await inject(controller)
168
- try {
169
- const { query, params, body } = request
170
- const argument: Record<string, any> = {}
171
- if (query && Object.keys(query).length > 0) {
172
- argument.params = query
173
- }
174
- if (params && Object.keys(params).length > 0) {
175
- argument.urlParams = params
176
- }
177
- if (body) {
178
- argument.data = body
179
- }
180
- const result =
181
- await controllerInstance[endpointMetadata.classMethod](argument)
182
- reply
183
- .status(endpointMetadata.successStatusCode)
184
- .headers(endpointMetadata.headers)
185
- .send(result)
186
- } finally {
187
- getServiceLocator().removeInstance(Request)
188
- getServiceLocator().removeInstance(Reply)
189
- getServiceLocator().removeInstance(ExecutionContextToken)
190
- }
191
- }
192
- }
193
-
194
- private provideHandlerForStream(
195
- controller: ClassType,
196
- executionContext: ExecutionContext,
197
- endpointMetadata: EndpointMetadata,
198
- ): (request: FastifyRequest, reply: FastifyReply) => Promise<void> {
199
- return async (request, reply) => {
200
- getServiceLocator().registerInstance(Request, request)
201
- getServiceLocator().registerInstance(Reply, reply)
202
- getServiceLocator().registerInstance(
203
- ExecutionContextToken,
204
- executionContext,
205
- )
206
- executionContext.provideRequest(request)
207
- executionContext.provideReply(reply)
208
- const controllerInstance = await inject(controller)
209
- try {
210
- const { query, params, body } = request
211
- const argument: Record<string, any> = {}
212
- if (query && Object.keys(query).length > 0) {
213
- argument.params = query
214
- }
215
- if (params && Object.keys(params).length > 0) {
216
- argument.urlParams = params
217
- }
218
- if (body) {
219
- argument.data = body
220
- }
221
-
222
- await controllerInstance[endpointMetadata.classMethod](argument, reply)
223
- } finally {
224
- getServiceLocator().removeInstance(Request)
225
- getServiceLocator().removeInstance(Reply)
226
- getServiceLocator().removeInstance(ExecutionContextToken)
227
- }
228
- }
97
+ : undefined
229
98
  }
230
99
 
231
- private provideHandlerForMultipart(
232
- controller: ClassType,
100
+ private wrapHandler(
233
101
  executionContext: ExecutionContext,
234
- endpointMetadata: EndpointMetadata,
235
- ): (request: FastifyRequest, reply: FastifyReply) => Promise<void> {
236
- const config = endpointMetadata.config as BaseEndpointConfig
237
- const requestSchema = config.requestSchema as unknown as AnyZodObject
238
- const shape = requestSchema._def.shape()
239
- return async (request, reply) => {
240
- getServiceLocator().registerInstance(Request, request)
241
- getServiceLocator().registerInstance(Reply, reply)
242
- getServiceLocator().registerInstance(
243
- ExecutionContextToken,
244
- executionContext,
245
- )
102
+ handler: (request: FastifyRequest, reply: FastifyReply) => Promise<void>,
103
+ ) {
104
+ const locator = getGlobalServiceLocator()
105
+ return async (request: FastifyRequest, reply: FastifyReply) => {
106
+ locator.storeInstance(request, Request)
107
+ locator.storeInstance(reply, Reply)
108
+ locator.storeInstance(executionContext, ExecutionContextToken)
246
109
  executionContext.provideRequest(request)
247
110
  executionContext.provideReply(reply)
248
- const controllerInstance = await inject(controller)
249
111
  try {
250
- const parts = request.parts()
251
- const { query, params } = request
252
- const argument: Record<string, any> = {}
253
- if (query && Object.keys(query).length > 0) {
254
- argument.params = query
255
- }
256
- if (params && Object.keys(params).length > 0) {
257
- argument.urlParams = params
258
- }
259
- const req: Record<string, any> = {}
260
- for await (const part of parts) {
261
- if (!shape[part.fieldname]) {
262
- throw new NaviosException(
263
- `Invalid field name ${part.fieldname} for multipart request`,
264
- )
265
- }
266
- const schema = shape[part.fieldname]
267
- if (part.type === 'file') {
268
- const file = new File([await part.toBuffer()], part.filename, {
269
- type: part.mimetype,
270
- })
271
- if (schema instanceof ZodArray) {
272
- if (!req[part.fieldname]) {
273
- req[part.fieldname] = []
274
- }
275
- req[part.fieldname].push(file)
276
- } else {
277
- req[part.fieldname] = file
278
- }
279
- } else {
280
- if (schema instanceof ZodArray) {
281
- if (!req[part.fieldname]) {
282
- req[part.fieldname] = []
283
- }
284
- req[part.fieldname].push(part.value)
285
- } else {
286
- req[part.fieldname] = part.value
287
- }
288
- }
289
- }
290
- argument.data = requestSchema.parse(req)
291
- const result =
292
- await controllerInstance[endpointMetadata.classMethod](argument)
293
- reply
294
- .status(endpointMetadata.successStatusCode)
295
- .headers(endpointMetadata.headers)
296
- .send(result)
112
+ return await handler(request, reply)
297
113
  } finally {
298
- getServiceLocator().removeInstance(Request)
299
- getServiceLocator().removeInstance(Reply)
300
- getServiceLocator().removeInstance(ExecutionContextToken)
114
+ Promise.all([
115
+ locator.removeInstance(Request),
116
+ locator.removeInstance(Reply),
117
+ locator.removeInstance(ExecutionContextToken),
118
+ ]).catch((err) => {
119
+ this.logger.warn(`Error removing instances: ${err}`)
120
+ })
301
121
  }
302
122
  }
303
123
  }
@@ -2,7 +2,7 @@ import type { FastifyReply, FastifyRequest } from 'fastify'
2
2
 
3
3
  import type {
4
4
  ControllerMetadata,
5
- EndpointMetadata,
5
+ HandlerMetadata,
6
6
  ModuleMetadata,
7
7
  } from '../metadata/index.mjs'
8
8
 
@@ -12,7 +12,7 @@ export class ExecutionContext {
12
12
  constructor(
13
13
  private readonly module: ModuleMetadata,
14
14
  private readonly controller: ControllerMetadata,
15
- private readonly handler: EndpointMetadata,
15
+ private readonly handler: HandlerMetadata,
16
16
  ) {}
17
17
  getModule(): ModuleMetadata {
18
18
  return this.module
@@ -22,7 +22,7 @@ export class ExecutionContext {
22
22
  return this.controller
23
23
  }
24
24
 
25
- getHandler(): EndpointMetadata {
25
+ getHandler(): HandlerMetadata {
26
26
  return this.handler
27
27
  }
28
28
 
@@ -47,6 +47,7 @@ export class ExecutionContext {
47
47
  provideRequest(request: FastifyRequest): void {
48
48
  this.request = request
49
49
  }
50
+
50
51
  provideReply(reply: FastifyReply): void {
51
52
  this.reply = reply
52
53
  }
@@ -1,13 +1,11 @@
1
+ import type { ClassTypeWithInstance } from '@navios/di'
2
+
3
+ import { inject, Injectable, InjectionToken } from '@navios/di'
4
+
1
5
  import type { CanActivate } from '../interfaces/index.mjs'
2
- import type { ClassTypeWithInstance } from '../service-locator/index.mjs'
3
6
  import type { ExecutionContext } from './execution-context.mjs'
4
7
 
5
8
  import { HttpException } from '../exceptions/index.mjs'
6
- import {
7
- inject,
8
- Injectable,
9
- InjectionToken,
10
- } from '../service-locator/index.mjs'
11
9
 
12
10
  @Injectable()
13
11
  export class GuardRunnerService {
@@ -1,10 +1,12 @@
1
+ import type { ClassTypeWithInstance } from '@navios/di'
2
+
3
+ import { inject, Injectable, syncInject } from '@navios/di'
4
+
1
5
  import type { NaviosModule } from '../interfaces/index.mjs'
2
6
  import type { ModuleMetadata } from '../metadata/index.mjs'
3
- import type { ClassTypeWithInstance } from '../service-locator/index.mjs'
4
7
 
5
8
  import { Logger } from '../logger/index.mjs'
6
9
  import { extractModuleMetadata } from '../metadata/index.mjs'
7
- import { inject, Injectable, syncInject } from '../service-locator/index.mjs'
8
10
 
9
11
  @Injectable()
10
12
  export class ModuleLoaderService {
@@ -1,6 +1,6 @@
1
1
  import type { FastifyInstance } from 'fastify'
2
2
 
3
- import { InjectionToken } from '../service-locator/index.mjs'
3
+ import { InjectionToken } from '@navios/di'
4
4
 
5
5
  const ApplicationInjectionToken = 'ApplicationInjectionToken'
6
6
 
@@ -1,4 +1,5 @@
1
- import { InjectionToken } from '../service-locator/index.mjs'
1
+ import { InjectionToken } from '@navios/di'
2
+
2
3
  import { ExecutionContext } from '../services/index.mjs'
3
4
 
4
5
  export const ExecutionContextInjectionToken = 'ExecutionContextInjectionToken'
@@ -1,6 +1,6 @@
1
1
  import type { FastifyReply } from 'fastify'
2
2
 
3
- import { InjectionToken } from '../service-locator/index.mjs'
3
+ import { InjectionToken } from '@navios/di'
4
4
 
5
5
  const ReplyInjectionToken = 'ReplyInjectionToken'
6
6
 
@@ -1,6 +1,6 @@
1
1
  import type { FastifyRequest } from 'fastify'
2
2
 
3
- import { InjectionToken } from '../service-locator/index.mjs'
3
+ import { InjectionToken } from '@navios/di'
4
4
 
5
5
  const RequestInjectionToken = 'RequestInjectionToken'
6
6
 
@@ -1,11 +0,0 @@
1
- import type {
2
- InjectableScope,
3
- InjectableType,
4
- InjectionToken,
5
- } from '../index.mjs'
6
-
7
- export interface InjectableMetadata<Instance = any, Schema = any> {
8
- type: InjectableType
9
- scope: InjectableScope
10
- token: InjectionToken<Instance, Schema>
11
- }
@@ -1,171 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { z } from 'zod'
3
-
4
- import {
5
- getInjectableToken,
6
- Injectable,
7
- InjectableType,
8
- } from '../decorators/index.mjs'
9
- import { InjectableScope } from '../enums/index.mjs'
10
- import { syncInject } from '../index.mjs'
11
- import { inject } from '../inject.mjs'
12
- import { InjectionToken } from '../injection-token.mjs'
13
- import { getServiceLocator } from '../injector.mjs'
14
-
15
- describe('Injectable decorator', () => {
16
- it('should work with class', async () => {
17
- @Injectable()
18
- class Test {}
19
-
20
- const value = await inject(Test)
21
- expect(value).toBeInstanceOf(Test)
22
- })
23
-
24
- it('should work with inner inject', async () => {
25
- @Injectable()
26
- class Test {
27
- makeFoo() {
28
- return 'foo'
29
- }
30
- }
31
-
32
- @Injectable()
33
- class Test2 {
34
- fooMaker = inject(Test)
35
-
36
- async makeFoo() {
37
- const fooMaker = await this.fooMaker
38
- return fooMaker.makeFoo()
39
- }
40
- }
41
-
42
- const value = await inject(Test2)
43
- expect(value).toBeInstanceOf(Test2)
44
- const result = await value.makeFoo()
45
- expect(result).toBe('foo')
46
- })
47
-
48
- it('should work with factory', async () => {
49
- @Injectable({ type: InjectableType.Factory })
50
- class Test {
51
- create() {
52
- return 'foo'
53
- }
54
- }
55
-
56
- const value = await inject(Test)
57
- expect(value).toBe('foo')
58
- })
59
- it('should work with request scope', async () => {
60
- @Injectable({
61
- scope: InjectableScope.Instance,
62
- type: InjectableType.Factory,
63
- })
64
- class Test {
65
- create() {
66
- return Date.now()
67
- }
68
- }
69
-
70
- const value = await inject(Test)
71
- await new Promise((resolve) => setTimeout(resolve, 10))
72
- const value2 = await inject(Test)
73
- expect(value).not.toBe(value2)
74
- })
75
-
76
- it('should work with injection token', async () => {
77
- const token = InjectionToken.create('Test')
78
-
79
- @Injectable({ token })
80
- class Test {}
81
-
82
- const value = await inject(token)
83
- expect(value).toBeInstanceOf(Test)
84
- })
85
-
86
- it('should work with injection token and schema', async () => {
87
- class TestFoo {
88
- constructor(public readonly foo: string) {}
89
- }
90
- const token = InjectionToken.create(
91
- TestFoo,
92
- z.object({
93
- foo: z.string(),
94
- }),
95
- )
96
-
97
- @Injectable({ token, type: InjectableType.Factory })
98
- class Test {
99
- create(ctx: any, args: { foo: string }) {
100
- return new TestFoo(args.foo)
101
- }
102
- }
103
-
104
- const value = await inject(token, { foo: 'bar' })
105
- const differentValue = await inject(token, { foo: 'baz' })
106
- const sameValue = await inject(token, { foo: 'bar' })
107
- expect(value).toBeInstanceOf(TestFoo)
108
- expect(value.foo).toBe('bar')
109
- expect(differentValue).toBeInstanceOf(TestFoo)
110
- expect(differentValue.foo).toBe('baz')
111
- expect(value).not.toBe(differentValue)
112
- expect(value).toBe(sameValue)
113
- })
114
- it('should work with invalidation', async () => {
115
- @Injectable()
116
- class Test {
117
- value = Date.now()
118
- }
119
-
120
- @Injectable()
121
- class Test2 {
122
- test = inject(Test)
123
-
124
- async makeFoo() {
125
- const test = await this.test
126
- return test.value
127
- }
128
- }
129
- const identifier = getServiceLocator().getInstanceIdentifier(
130
- getInjectableToken(Test),
131
- undefined,
132
- )
133
- const inst1 = await inject(Test2)
134
- expect(inst1).toBeInstanceOf(Test2)
135
- const result1 = await inst1.makeFoo()
136
- const inst2 = await inject(Test2)
137
- expect(inst1).toBe(inst2)
138
- const result2 = await inst2.makeFoo()
139
- await getServiceLocator().invalidate(identifier)
140
- await new Promise((resolve) => setTimeout(resolve, 10))
141
- const inst3 = await inject(Test2)
142
- expect(inst1).not.toBe(inst3)
143
- const result3 = await inst3.makeFoo()
144
- expect(result1).not.toBe(result3)
145
- expect(result2).not.toBe(result3)
146
- expect(result1).toBe(result2)
147
- })
148
-
149
- it('should work with syncInject', async () => {
150
- @Injectable()
151
- class Test {
152
- value = Date.now()
153
- }
154
-
155
- @Injectable()
156
- class Test2 {
157
- test = syncInject(Test)
158
-
159
- makeFoo() {
160
- return this.test.value
161
- }
162
- }
163
- const inst1 = await inject(Test2)
164
- expect(inst1).toBeInstanceOf(Test2)
165
- const result1 = inst1.makeFoo()
166
- const inst2 = await inject(Test2)
167
- expect(inst1).toBe(inst2)
168
- const result2 = await inst2.makeFoo()
169
- expect(result1).toBe(result2)
170
- })
171
- })