@navios/core 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_tsup-dts-rollup.d.mts +133 -49
- package/dist/_tsup-dts-rollup.d.ts +133 -49
- package/dist/index.d.mts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +1184 -1090
- package/dist/index.mjs +1179 -1090
- package/package.json +1 -1
- package/src/adapters/endpoint-adapter.service.mts +75 -0
- package/src/adapters/handler-adapter.interface.mts +21 -0
- package/src/adapters/index.mts +4 -0
- package/src/adapters/multipart-adapter.service.mts +130 -0
- package/src/adapters/stream-adapter.service.mts +95 -0
- package/src/attribute.factory.mts +13 -13
- package/src/config/config.provider.mts +8 -2
- package/src/decorators/controller.decorator.mts +0 -2
- package/src/decorators/endpoint.decorator.mts +7 -3
- package/src/decorators/header.decorator.mts +1 -6
- package/src/decorators/http-code.decorator.mts +1 -6
- package/src/decorators/module.decorator.mts +13 -15
- package/src/decorators/multipart.decorator.mts +7 -3
- package/src/decorators/stream.decorator.mts +7 -3
- package/src/index.mts +1 -0
- package/src/logger/console-logger.service.mts +41 -3
- package/src/logger/logger.service.mts +0 -1
- package/src/metadata/controller.metadata.mts +3 -3
- package/src/metadata/{endpoint.metadata.mts → handler.metadata.mts} +17 -24
- package/src/metadata/index.mts +1 -1
- package/src/navios.application.mts +3 -4
- package/src/service-locator/__tests__/injection-token.spec.mts +10 -5
- package/src/service-locator/decorators/injectable.decorator.mts +53 -4
- package/src/service-locator/inject.mts +14 -0
- package/src/service-locator/interfaces/factory.interface.mts +9 -1
- package/src/service-locator/service-locator.mts +1 -0
- package/src/service-locator/sync-injector.mts +14 -0
- package/src/services/controller-adapter.service.mts +59 -240
- package/src/services/execution-context.mts +4 -3
|
@@ -1,21 +1,17 @@
|
|
|
1
|
-
import type { BaseEndpointConfig } from '@navios/common'
|
|
2
1
|
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
|
|
3
2
|
import type { ZodTypeProvider } from 'fastify-type-provider-zod'
|
|
4
|
-
import type { AnyZodObject } from 'zod'
|
|
5
3
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
import { ZodArray } from 'zod'
|
|
9
|
-
|
|
10
|
-
import type { EndpointMetadata, ModuleMetadata } from '../metadata/index.mjs'
|
|
4
|
+
import type { HandlerAdapterInterface } from '../adapters/index.mjs'
|
|
5
|
+
import type { ModuleMetadata } from '../metadata/index.mjs'
|
|
11
6
|
import type { ClassType } from '../service-locator/index.mjs'
|
|
12
7
|
|
|
13
8
|
import { Logger } from '../logger/index.mjs'
|
|
14
|
-
import {
|
|
9
|
+
import { extractControllerMetadata } from '../metadata/index.mjs'
|
|
15
10
|
import {
|
|
16
11
|
getServiceLocator,
|
|
17
12
|
inject,
|
|
18
13
|
Injectable,
|
|
14
|
+
InjectionToken,
|
|
19
15
|
syncInject,
|
|
20
16
|
} from '../service-locator/index.mjs'
|
|
21
17
|
import { ExecutionContextToken, Reply, Request } from '../tokens/index.mjs'
|
|
@@ -29,32 +25,51 @@ export class ControllerAdapterService {
|
|
|
29
25
|
context: ControllerAdapterService.name,
|
|
30
26
|
})
|
|
31
27
|
|
|
32
|
-
setupController(
|
|
28
|
+
async setupController(
|
|
33
29
|
controller: ClassType,
|
|
34
30
|
instance: FastifyInstance,
|
|
35
31
|
moduleMetadata: ModuleMetadata,
|
|
36
|
-
)
|
|
32
|
+
) {
|
|
37
33
|
const controllerMetadata = extractControllerMetadata(controller)
|
|
38
34
|
for (const endpoint of controllerMetadata.endpoints) {
|
|
39
|
-
const { classMethod, url, httpMethod } = endpoint
|
|
35
|
+
const { classMethod, url, httpMethod, adapterToken } = endpoint
|
|
40
36
|
|
|
41
|
-
if (!url) {
|
|
37
|
+
if (!url || !adapterToken) {
|
|
42
38
|
throw new Error(
|
|
43
39
|
`[Navios] Malformed Endpoint ${controller.name}:${classMethod}`,
|
|
44
40
|
)
|
|
45
41
|
}
|
|
42
|
+
const adapter = await inject(
|
|
43
|
+
adapterToken as InjectionToken<HandlerAdapterInterface>,
|
|
44
|
+
)
|
|
46
45
|
const executionContext = new ExecutionContext(
|
|
47
46
|
moduleMetadata,
|
|
48
47
|
controllerMetadata,
|
|
49
48
|
endpoint,
|
|
50
49
|
)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
const hasSchema = adapter.hasSchema?.(endpoint) ?? false
|
|
51
|
+
if (hasSchema) {
|
|
52
|
+
instance.withTypeProvider<ZodTypeProvider>().route({
|
|
53
|
+
method: httpMethod,
|
|
54
|
+
url: url.replaceAll('$', ':'),
|
|
55
|
+
schema: adapter.provideSchema?.(endpoint) ?? {},
|
|
56
|
+
preHandler: this.providePreHandler(executionContext),
|
|
57
|
+
handler: this.wrapHandler(
|
|
58
|
+
executionContext,
|
|
59
|
+
adapter.provideHandler(controller, executionContext, endpoint),
|
|
60
|
+
),
|
|
61
|
+
})
|
|
62
|
+
} else {
|
|
63
|
+
instance.route({
|
|
64
|
+
method: httpMethod,
|
|
65
|
+
url: url.replaceAll('$', ':'),
|
|
66
|
+
preHandler: this.providePreHandler(executionContext),
|
|
67
|
+
handler: this.wrapHandler(
|
|
68
|
+
executionContext,
|
|
69
|
+
adapter.provideHandler(controller, executionContext, endpoint),
|
|
70
|
+
),
|
|
71
|
+
})
|
|
72
|
+
}
|
|
58
73
|
|
|
59
74
|
this.logger.debug(
|
|
60
75
|
`Registered ${httpMethod} ${url} for ${controller.name}:${classMethod}`,
|
|
@@ -65,239 +80,43 @@ export class ControllerAdapterService {
|
|
|
65
80
|
providePreHandler(executionContext: ExecutionContext) {
|
|
66
81
|
const guards = this.guardRunner.makeContext(executionContext)
|
|
67
82
|
return guards.size > 0
|
|
68
|
-
?
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
ExecutionContextToken,
|
|
73
|
-
executionContext,
|
|
74
|
-
)
|
|
75
|
-
executionContext.provideRequest(request)
|
|
76
|
-
executionContext.provideReply(reply)
|
|
77
|
-
let canActivate = true
|
|
78
|
-
try {
|
|
83
|
+
? this.wrapHandler(
|
|
84
|
+
executionContext,
|
|
85
|
+
async (request: FastifyRequest, reply: FastifyReply) => {
|
|
86
|
+
let canActivate = true
|
|
79
87
|
canActivate = await this.guardRunner.runGuards(
|
|
80
88
|
guards,
|
|
81
89
|
executionContext,
|
|
82
90
|
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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,
|
|
91
|
+
if (!canActivate) {
|
|
92
|
+
return reply
|
|
93
|
+
}
|
|
94
|
+
},
|
|
146
95
|
)
|
|
147
|
-
|
|
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
|
-
}
|
|
96
|
+
: undefined
|
|
229
97
|
}
|
|
230
98
|
|
|
231
|
-
private
|
|
232
|
-
controller: ClassType,
|
|
99
|
+
private wrapHandler(
|
|
233
100
|
executionContext: ExecutionContext,
|
|
234
|
-
|
|
235
|
-
)
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
getServiceLocator().registerInstance(Reply, reply)
|
|
242
|
-
getServiceLocator().registerInstance(
|
|
243
|
-
ExecutionContextToken,
|
|
244
|
-
executionContext,
|
|
245
|
-
)
|
|
101
|
+
handler: (request: FastifyRequest, reply: FastifyReply) => Promise<void>,
|
|
102
|
+
) {
|
|
103
|
+
const locator = getServiceLocator()
|
|
104
|
+
return async (request: FastifyRequest, reply: FastifyReply) => {
|
|
105
|
+
locator.registerInstance(Request, request)
|
|
106
|
+
locator.registerInstance(Reply, reply)
|
|
107
|
+
locator.registerInstance(ExecutionContextToken, executionContext)
|
|
246
108
|
executionContext.provideRequest(request)
|
|
247
109
|
executionContext.provideReply(reply)
|
|
248
|
-
const controllerInstance = await inject(controller)
|
|
249
110
|
try {
|
|
250
|
-
|
|
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)
|
|
111
|
+
return await handler(request, reply)
|
|
297
112
|
} finally {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
113
|
+
Promise.all([
|
|
114
|
+
locator.removeInstance(Request),
|
|
115
|
+
locator.removeInstance(Reply),
|
|
116
|
+
locator.removeInstance(ExecutionContextToken),
|
|
117
|
+
]).catch((err) => {
|
|
118
|
+
this.logger.warn(`Error removing instances: ${err}`)
|
|
119
|
+
})
|
|
301
120
|
}
|
|
302
121
|
}
|
|
303
122
|
}
|
|
@@ -2,7 +2,7 @@ import type { FastifyReply, FastifyRequest } from 'fastify'
|
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
4
|
ControllerMetadata,
|
|
5
|
-
|
|
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:
|
|
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():
|
|
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
|
}
|