@navios/core 0.3.0 → 0.5.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/README.md +96 -3
- package/docs/README.md +310 -3
- package/docs/adapters.md +308 -0
- package/docs/application-setup.md +524 -0
- package/docs/attributes.md +689 -0
- package/docs/controllers.md +373 -0
- package/docs/endpoints.md +444 -0
- package/docs/exceptions.md +316 -0
- package/docs/guards.md +550 -0
- package/docs/modules.md +251 -0
- package/docs/quick-start.md +295 -0
- package/docs/services.md +428 -0
- package/docs/testing.md +704 -0
- package/lib/_tsup-dts-rollup.d.mts +313 -280
- package/lib/_tsup-dts-rollup.d.ts +313 -280
- package/lib/index.d.mts +47 -26
- package/lib/index.d.ts +47 -26
- package/lib/index.js +633 -1068
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +632 -1061
- package/lib/index.mjs.map +1 -1
- package/package.json +11 -12
- package/project.json +17 -4
- package/src/__tests__/config.service.spec.mts +11 -9
- package/src/__tests__/controller.spec.mts +1 -2
- package/src/attribute.factory.mts +1 -1
- package/src/config/config.provider.mts +2 -2
- package/src/config/config.service.mts +4 -4
- package/src/decorators/controller.decorator.mts +1 -1
- package/src/decorators/endpoint.decorator.mts +9 -10
- package/src/decorators/header.decorator.mts +1 -1
- package/src/decorators/multipart.decorator.mts +5 -5
- package/src/decorators/stream.decorator.mts +5 -6
- package/src/factories/endpoint-adapter.factory.mts +21 -0
- package/src/factories/http-adapter.factory.mts +20 -0
- package/src/factories/index.mts +6 -0
- package/src/factories/multipart-adapter.factory.mts +21 -0
- package/src/factories/reply.factory.mts +21 -0
- package/src/factories/request.factory.mts +21 -0
- package/src/factories/stream-adapter.factory.mts +20 -0
- package/src/index.mts +1 -1
- package/src/interfaces/abstract-execution-context.inteface.mts +13 -0
- package/src/interfaces/abstract-http-adapter.interface.mts +20 -0
- package/src/interfaces/abstract-http-cors-options.interface.mts +59 -0
- package/src/interfaces/abstract-http-handler-adapter.interface.mts +13 -0
- package/src/interfaces/abstract-http-listen-options.interface.mts +4 -0
- package/src/interfaces/can-activate.mts +4 -2
- package/src/interfaces/http-header.mts +18 -0
- package/src/interfaces/index.mts +6 -0
- package/src/logger/console-logger.service.mts +28 -44
- package/src/logger/index.mts +1 -2
- package/src/logger/logger.service.mts +9 -128
- package/src/logger/logger.tokens.mts +21 -0
- package/src/metadata/handler.metadata.mts +7 -5
- package/src/navios.application.mts +65 -172
- package/src/navios.environment.mts +30 -0
- package/src/navios.factory.mts +53 -12
- package/src/services/guard-runner.service.mts +19 -9
- package/src/services/index.mts +0 -2
- package/src/services/module-loader.service.mts +4 -3
- package/src/tokens/endpoint-adapter.token.mts +8 -0
- package/src/tokens/execution-context.token.mts +2 -2
- package/src/tokens/http-adapter.token.mts +8 -0
- package/src/tokens/index.mts +4 -1
- package/src/tokens/multipart-adapter.token.mts +8 -0
- package/src/tokens/reply.token.mts +1 -5
- package/src/tokens/request.token.mts +1 -7
- package/src/tokens/stream-adapter.token.mts +8 -0
- package/tsconfig.json +6 -1
- package/tsconfig.lib.json +8 -0
- package/tsconfig.spec.json +12 -0
- package/tsup.config.mts +1 -0
- package/docs/recipes/prisma.md +0 -60
- package/examples/simple-test/api/index.mts +0 -64
- package/examples/simple-test/config/config.service.mts +0 -14
- package/examples/simple-test/config/configuration.mts +0 -7
- package/examples/simple-test/index.mts +0 -16
- package/examples/simple-test/src/acl/acl-modern.guard.mts +0 -15
- package/examples/simple-test/src/acl/acl.guard.mts +0 -14
- package/examples/simple-test/src/acl/app.guard.mts +0 -27
- package/examples/simple-test/src/acl/one-more.guard.mts +0 -15
- package/examples/simple-test/src/acl/public.attribute.mts +0 -21
- package/examples/simple-test/src/app.module.mts +0 -9
- package/examples/simple-test/src/user/user.controller.mts +0 -72
- package/examples/simple-test/src/user/user.module.mts +0 -14
- package/examples/simple-test/src/user/user.service.mts +0 -14
- package/src/adapters/endpoint-adapter.service.mts +0 -72
- package/src/adapters/handler-adapter.interface.mts +0 -21
- package/src/adapters/index.mts +0 -4
- package/src/adapters/multipart-adapter.service.mts +0 -131
- package/src/adapters/stream-adapter.service.mts +0 -91
- package/src/logger/logger.factory.mts +0 -36
- package/src/logger/pino-wrapper.mts +0 -64
- package/src/services/controller-adapter.service.mts +0 -124
- package/src/services/execution-context.mts +0 -54
- package/src/tokens/application.token.mts +0 -9
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
EndpointParams,
|
|
3
|
-
EndpointResult,
|
|
4
|
-
MultipartParams,
|
|
5
|
-
} from '../../../../src/index.mjs'
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
Controller,
|
|
9
|
-
Endpoint,
|
|
10
|
-
Logger,
|
|
11
|
-
Multipart,
|
|
12
|
-
syncInject,
|
|
13
|
-
UseGuards,
|
|
14
|
-
} from '../../../../src/index.mjs'
|
|
15
|
-
import {
|
|
16
|
-
discriminatorEndpoint,
|
|
17
|
-
multipartEndpoint,
|
|
18
|
-
patchUserEndpoint,
|
|
19
|
-
userEndpoint,
|
|
20
|
-
} from '../../api/index.mjs'
|
|
21
|
-
import { AclGuard } from '../acl/acl.guard.mjs'
|
|
22
|
-
import { OneMoreGuard } from '../acl/one-more.guard.mjs'
|
|
23
|
-
import { Public } from '../acl/public.attribute.mjs'
|
|
24
|
-
import { UserService } from './user.service.mjs'
|
|
25
|
-
|
|
26
|
-
@UseGuards(AclGuard)
|
|
27
|
-
@Controller()
|
|
28
|
-
export class UserController {
|
|
29
|
-
userService = syncInject(UserService)
|
|
30
|
-
logger = syncInject(Logger, {
|
|
31
|
-
context: UserController.name,
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
@Public()
|
|
35
|
-
@UseGuards(OneMoreGuard)
|
|
36
|
-
@Endpoint(userEndpoint)
|
|
37
|
-
async me(params: EndpointParams<typeof userEndpoint>) {
|
|
38
|
-
this.logger.log(params)
|
|
39
|
-
return this.userService.getUser()
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
@Endpoint(patchUserEndpoint)
|
|
43
|
-
async patchMe(params: EndpointParams<typeof patchUserEndpoint>) {
|
|
44
|
-
this.logger.log(params)
|
|
45
|
-
return {
|
|
46
|
-
...this.userService.getUser(),
|
|
47
|
-
...params.data,
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@Endpoint(discriminatorEndpoint)
|
|
52
|
-
async discriminator(
|
|
53
|
-
params: EndpointParams<typeof discriminatorEndpoint>,
|
|
54
|
-
): EndpointResult<typeof discriminatorEndpoint> {
|
|
55
|
-
this.logger.log(params)
|
|
56
|
-
return {
|
|
57
|
-
success: true,
|
|
58
|
-
data: {
|
|
59
|
-
id: '123',
|
|
60
|
-
name: 'John Doe',
|
|
61
|
-
email: 'test@example.com',
|
|
62
|
-
},
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
@Multipart(multipartEndpoint)
|
|
67
|
-
async multipart(params: MultipartParams<typeof multipartEndpoint>) {
|
|
68
|
-
this.logger.log(params)
|
|
69
|
-
// params.data.
|
|
70
|
-
return {}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Logger, Module, syncInject } from '../../../../src/index.mjs'
|
|
2
|
-
import { AclModernGuard } from '../acl/acl-modern.guard.mjs'
|
|
3
|
-
import { UserController } from './user.controller.mjs'
|
|
4
|
-
|
|
5
|
-
@Module({
|
|
6
|
-
controllers: [UserController],
|
|
7
|
-
guards: [AclModernGuard],
|
|
8
|
-
})
|
|
9
|
-
export class UserModule {
|
|
10
|
-
logger = syncInject(Logger)
|
|
11
|
-
onModuleInit() {
|
|
12
|
-
this.logger.debug('Inside UserModule.onModuleInit')
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto'
|
|
2
|
-
|
|
3
|
-
import { Injectable } from '../../../../src/index.mjs'
|
|
4
|
-
|
|
5
|
-
@Injectable()
|
|
6
|
-
export class UserService {
|
|
7
|
-
getUser() {
|
|
8
|
-
return {
|
|
9
|
-
id: randomUUID() as string,
|
|
10
|
-
name: 'John Doe',
|
|
11
|
-
email: 'test@example.com',
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import type { BaseEndpointConfig } from '@navios/builder'
|
|
2
|
-
import type { ClassType } from '@navios/di'
|
|
3
|
-
import type { FastifyReply, FastifyRequest } from 'fastify'
|
|
4
|
-
|
|
5
|
-
import { inject, Injectable, InjectionToken } from '@navios/di'
|
|
6
|
-
|
|
7
|
-
import type { HandlerMetadata } from '../metadata/index.mjs'
|
|
8
|
-
import type { ExecutionContext } from '../services/index.mjs'
|
|
9
|
-
|
|
10
|
-
import { StreamAdapterService } from './stream-adapter.service.mjs'
|
|
11
|
-
|
|
12
|
-
export const EndpointAdapterToken =
|
|
13
|
-
InjectionToken.create<EndpointAdapterService>(
|
|
14
|
-
Symbol.for('EndpointAdapterService'),
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
@Injectable({
|
|
18
|
-
token: EndpointAdapterToken,
|
|
19
|
-
})
|
|
20
|
-
export class EndpointAdapterService extends StreamAdapterService {
|
|
21
|
-
override hasSchema(
|
|
22
|
-
handlerMetadata: HandlerMetadata<BaseEndpointConfig>,
|
|
23
|
-
): boolean {
|
|
24
|
-
const config = handlerMetadata.config
|
|
25
|
-
return super.hasSchema(handlerMetadata) || !!config.responseSchema
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
override provideSchema(
|
|
29
|
-
handlerMetadata: HandlerMetadata<BaseEndpointConfig>,
|
|
30
|
-
): Record<string, any> {
|
|
31
|
-
const config = handlerMetadata.config
|
|
32
|
-
const schema = super.provideSchema(handlerMetadata)
|
|
33
|
-
if (config.responseSchema) {
|
|
34
|
-
schema.response = {
|
|
35
|
-
200: config.responseSchema,
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return schema
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
override provideHandler(
|
|
43
|
-
controller: ClassType,
|
|
44
|
-
executionContext: ExecutionContext,
|
|
45
|
-
handlerMetadata: HandlerMetadata<BaseEndpointConfig>,
|
|
46
|
-
): (request: FastifyRequest, reply: FastifyReply) => Promise<any> {
|
|
47
|
-
const getters = this.prepareArguments(handlerMetadata)
|
|
48
|
-
const formatArguments = async (request: FastifyRequest) => {
|
|
49
|
-
const argument: Record<string, any> = {}
|
|
50
|
-
const promises: Promise<void>[] = []
|
|
51
|
-
for (const getter of getters) {
|
|
52
|
-
const res = getter(argument, request)
|
|
53
|
-
if (res instanceof Promise) {
|
|
54
|
-
promises.push(res)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
await Promise.all(promises)
|
|
58
|
-
return argument
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return async function (request, reply) {
|
|
62
|
-
const controllerInstance = await inject(controller)
|
|
63
|
-
const argument = await formatArguments(request)
|
|
64
|
-
const result =
|
|
65
|
-
await controllerInstance[handlerMetadata.classMethod](argument)
|
|
66
|
-
reply
|
|
67
|
-
.status(handlerMetadata.successStatusCode)
|
|
68
|
-
.headers(handlerMetadata.headers)
|
|
69
|
-
.send(result)
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { ClassType } from '@navios/di'
|
|
2
|
-
import type { FastifyReply, FastifyRequest } from 'fastify'
|
|
3
|
-
|
|
4
|
-
import type { HandlerMetadata } from '../metadata/index.mjs'
|
|
5
|
-
import type { ExecutionContext } from '../services/index.mjs'
|
|
6
|
-
|
|
7
|
-
export interface HandlerAdapterInterface {
|
|
8
|
-
provideSchema?: (handlerMetadata: HandlerMetadata<any>) => Record<string, any>
|
|
9
|
-
hasSchema?: (handlerMetadata: HandlerMetadata<any>) => boolean
|
|
10
|
-
prepareArguments?: (
|
|
11
|
-
handlerMetadata: HandlerMetadata<any>,
|
|
12
|
-
) => ((
|
|
13
|
-
target: Record<string, any>,
|
|
14
|
-
request: FastifyRequest,
|
|
15
|
-
) => Promise<void> | void)[]
|
|
16
|
-
provideHandler: (
|
|
17
|
-
controller: ClassType,
|
|
18
|
-
executionContext: ExecutionContext,
|
|
19
|
-
handlerMetadata: HandlerMetadata<any>,
|
|
20
|
-
) => (request: FastifyRequest, reply: FastifyReply) => Promise<any>
|
|
21
|
-
}
|
package/src/adapters/index.mts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import type { MultipartFile, MultipartValue } from '@fastify/multipart'
|
|
2
|
-
import type { BaseEndpointConfig } from '@navios/builder'
|
|
3
|
-
import type { FastifyRequest } from 'fastify'
|
|
4
|
-
import type { AnyZodObject, ZodRawShape } from 'zod'
|
|
5
|
-
|
|
6
|
-
import { Injectable, InjectionToken } from '@navios/di'
|
|
7
|
-
|
|
8
|
-
import { ZodArray, ZodObject, ZodOptional } from 'zod'
|
|
9
|
-
|
|
10
|
-
import type { HandlerMetadata } from '../metadata/index.mjs'
|
|
11
|
-
|
|
12
|
-
import { EndpointAdapterService } from './endpoint-adapter.service.mjs'
|
|
13
|
-
|
|
14
|
-
export const MultipartAdapterToken =
|
|
15
|
-
InjectionToken.create<MultipartAdapterService>(
|
|
16
|
-
Symbol.for('MultipartAdapterService'),
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
@Injectable({
|
|
20
|
-
token: MultipartAdapterToken,
|
|
21
|
-
})
|
|
22
|
-
export class MultipartAdapterService extends EndpointAdapterService {
|
|
23
|
-
prepareArguments(
|
|
24
|
-
handlerMetadata: HandlerMetadata<BaseEndpointConfig>,
|
|
25
|
-
): ((target: Record<string, any>, request: FastifyRequest) => void)[] {
|
|
26
|
-
const config = handlerMetadata.config
|
|
27
|
-
const getters: ((
|
|
28
|
-
target: Record<string, any>,
|
|
29
|
-
request: FastifyRequest,
|
|
30
|
-
) => void | Promise<void>)[] = []
|
|
31
|
-
if (config.querySchema) {
|
|
32
|
-
getters.push((target, request) => {
|
|
33
|
-
target.params = request.query
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
if (config.url.includes('$')) {
|
|
37
|
-
getters.push((target, request) => {
|
|
38
|
-
target.urlParams = request.params
|
|
39
|
-
})
|
|
40
|
-
}
|
|
41
|
-
const requestSchema = config.requestSchema as unknown as AnyZodObject
|
|
42
|
-
const shape = requestSchema._def.shape()
|
|
43
|
-
const structure = this.analyzeSchema(shape)
|
|
44
|
-
getters.push(async (target, request) => {
|
|
45
|
-
const req: Record<string, any> = {}
|
|
46
|
-
for await (const part of request.parts()) {
|
|
47
|
-
await this.populateRequest(structure, part, req)
|
|
48
|
-
}
|
|
49
|
-
target.data = requestSchema.parse(req)
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
return getters
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private async populateRequest(
|
|
56
|
-
structure: {
|
|
57
|
-
[p: string]: { isArray: boolean; isOptional: boolean; isObject: boolean }
|
|
58
|
-
},
|
|
59
|
-
part: MultipartFile | MultipartValue<unknown>,
|
|
60
|
-
req: Record<string, any>,
|
|
61
|
-
) {
|
|
62
|
-
const { isArray, isObject } = structure[part.fieldname] ?? {}
|
|
63
|
-
if (isArray && !req[part.fieldname]) {
|
|
64
|
-
req[part.fieldname] = []
|
|
65
|
-
}
|
|
66
|
-
let value
|
|
67
|
-
if (part.type === 'file') {
|
|
68
|
-
value = new File([await part.toBuffer()], part.filename, {
|
|
69
|
-
type: part.mimetype,
|
|
70
|
-
})
|
|
71
|
-
} else {
|
|
72
|
-
value = part.value
|
|
73
|
-
if (isObject && typeof value === 'string') {
|
|
74
|
-
value = JSON.parse(value)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (isArray) {
|
|
79
|
-
req[part.fieldname].push(value)
|
|
80
|
-
} else {
|
|
81
|
-
req[part.fieldname] = value
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
private analyzeSchema(shape: ZodRawShape) {
|
|
86
|
-
return Object.keys(shape).reduce(
|
|
87
|
-
(target, key) => {
|
|
88
|
-
let schema = shape[key]
|
|
89
|
-
const isOptional = schema instanceof ZodOptional
|
|
90
|
-
if (isOptional) {
|
|
91
|
-
schema = (schema as ZodOptional<any>).unwrap()
|
|
92
|
-
}
|
|
93
|
-
const isArray = schema instanceof ZodArray
|
|
94
|
-
if (isArray) {
|
|
95
|
-
schema = (schema as ZodArray<any>).element
|
|
96
|
-
}
|
|
97
|
-
const isObject = schema instanceof ZodObject
|
|
98
|
-
return {
|
|
99
|
-
...target,
|
|
100
|
-
[key]: {
|
|
101
|
-
isArray,
|
|
102
|
-
isOptional,
|
|
103
|
-
isObject,
|
|
104
|
-
},
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
{} as Record<
|
|
108
|
-
string,
|
|
109
|
-
{ isArray: boolean; isOptional: boolean; isObject: boolean }
|
|
110
|
-
>,
|
|
111
|
-
)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
override provideSchema(
|
|
115
|
-
handlerMetadata: HandlerMetadata<BaseEndpointConfig>,
|
|
116
|
-
): Record<string, any> {
|
|
117
|
-
const schema: Record<string, any> = {}
|
|
118
|
-
const { querySchema, responseSchema } = handlerMetadata.config
|
|
119
|
-
|
|
120
|
-
if (querySchema) {
|
|
121
|
-
schema.querystring = querySchema
|
|
122
|
-
}
|
|
123
|
-
if (responseSchema) {
|
|
124
|
-
schema.response = {
|
|
125
|
-
200: responseSchema,
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return schema
|
|
130
|
-
}
|
|
131
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import type { BaseStreamConfig } from '@navios/builder'
|
|
2
|
-
import type { ClassType } from '@navios/di'
|
|
3
|
-
import type { FastifyReply, FastifyRequest } from 'fastify'
|
|
4
|
-
|
|
5
|
-
import { inject, Injectable, InjectionToken } from '@navios/di'
|
|
6
|
-
|
|
7
|
-
import type { HandlerMetadata } from '../metadata/index.mjs'
|
|
8
|
-
import type { ExecutionContext } from '../services/index.mjs'
|
|
9
|
-
import type { HandlerAdapterInterface } from './handler-adapter.interface.mjs'
|
|
10
|
-
|
|
11
|
-
export const StreamAdapterToken = InjectionToken.create<StreamAdapterService>(
|
|
12
|
-
Symbol.for('StreamAdapterService'),
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
@Injectable({
|
|
16
|
-
token: StreamAdapterToken,
|
|
17
|
-
})
|
|
18
|
-
export class StreamAdapterService implements HandlerAdapterInterface {
|
|
19
|
-
hasSchema(handlerMetadata: HandlerMetadata<BaseStreamConfig>): boolean {
|
|
20
|
-
const config = handlerMetadata.config
|
|
21
|
-
return !!config.requestSchema || !!config.querySchema
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
prepareArguments(handlerMetadata: HandlerMetadata<BaseStreamConfig>) {
|
|
25
|
-
const config = handlerMetadata.config
|
|
26
|
-
const getters: ((
|
|
27
|
-
target: Record<string, any>,
|
|
28
|
-
request: FastifyRequest,
|
|
29
|
-
) => void | Promise<void>)[] = []
|
|
30
|
-
if (config.querySchema) {
|
|
31
|
-
getters.push((target, request) => {
|
|
32
|
-
target.params = request.query
|
|
33
|
-
})
|
|
34
|
-
}
|
|
35
|
-
if (config.requestSchema) {
|
|
36
|
-
getters.push((target, request) => {
|
|
37
|
-
target.data = request.body
|
|
38
|
-
})
|
|
39
|
-
}
|
|
40
|
-
if (config.url.includes('$')) {
|
|
41
|
-
getters.push((target, request) => {
|
|
42
|
-
target.urlParams = request.params
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return getters
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
provideHandler(
|
|
50
|
-
controller: ClassType,
|
|
51
|
-
executionContext: ExecutionContext,
|
|
52
|
-
handlerMetadata: HandlerMetadata<BaseStreamConfig>,
|
|
53
|
-
): (request: FastifyRequest, reply: FastifyReply) => Promise<any> {
|
|
54
|
-
const getters = this.prepareArguments(handlerMetadata)
|
|
55
|
-
const formatArguments = async (request: FastifyRequest) => {
|
|
56
|
-
const argument: Record<string, any> = {}
|
|
57
|
-
const promises: Promise<void>[] = []
|
|
58
|
-
for (const getter of getters) {
|
|
59
|
-
const res = getter(argument, request)
|
|
60
|
-
if (res instanceof Promise) {
|
|
61
|
-
promises.push(res)
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
await Promise.all(promises)
|
|
65
|
-
return argument
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return async function (request: FastifyRequest, reply: FastifyReply) {
|
|
69
|
-
const controllerInstance = await inject(controller)
|
|
70
|
-
const argument = await formatArguments(request)
|
|
71
|
-
|
|
72
|
-
await controllerInstance[handlerMetadata.classMethod](argument, reply)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
provideSchema(
|
|
77
|
-
handlerMetadata: HandlerMetadata<BaseStreamConfig>,
|
|
78
|
-
): Record<string, any> {
|
|
79
|
-
const schema: Record<string, any> = {}
|
|
80
|
-
const { querySchema, requestSchema } = handlerMetadata.config
|
|
81
|
-
|
|
82
|
-
if (querySchema) {
|
|
83
|
-
schema.querystring = querySchema
|
|
84
|
-
}
|
|
85
|
-
if (requestSchema) {
|
|
86
|
-
schema.body = requestSchema
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return schema
|
|
90
|
-
}
|
|
91
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { Injectable, InjectableType, InjectionToken } from '@navios/di'
|
|
2
|
-
|
|
3
|
-
import { z } from 'zod'
|
|
4
|
-
|
|
5
|
-
import type { LoggerService } from './logger-service.interface.mjs'
|
|
6
|
-
|
|
7
|
-
import { LoggerInstance } from './logger.service.mjs'
|
|
8
|
-
|
|
9
|
-
export const LoggerInjectionToken = 'LoggerInjectionToken'
|
|
10
|
-
|
|
11
|
-
export const LoggerOptions = z
|
|
12
|
-
.object({
|
|
13
|
-
context: z.string().optional(),
|
|
14
|
-
options: z
|
|
15
|
-
.object({
|
|
16
|
-
timestamp: z.boolean().optional(),
|
|
17
|
-
})
|
|
18
|
-
.optional(),
|
|
19
|
-
})
|
|
20
|
-
.optional()
|
|
21
|
-
|
|
22
|
-
export const Logger = InjectionToken.create<
|
|
23
|
-
LoggerInstance,
|
|
24
|
-
typeof LoggerOptions
|
|
25
|
-
>(LoggerInjectionToken, LoggerOptions)
|
|
26
|
-
|
|
27
|
-
@Injectable({
|
|
28
|
-
type: InjectableType.Factory,
|
|
29
|
-
token: Logger,
|
|
30
|
-
})
|
|
31
|
-
export class LoggerFactory {
|
|
32
|
-
create(ctx: any, args: z.infer<typeof LoggerOptions>) {
|
|
33
|
-
// @ts-expect-error We don't need to support this in the current version
|
|
34
|
-
return new LoggerInstance(args?.context, args?.options)
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import type { LoggerService } from './logger-service.interface.mjs'
|
|
2
|
-
|
|
3
|
-
import { LoggerInstance } from './logger.service.mjs'
|
|
4
|
-
|
|
5
|
-
export class PinoWrapper {
|
|
6
|
-
constructor(protected readonly logger: LoggerService) {}
|
|
7
|
-
|
|
8
|
-
fatal(message: any, ...optionalParams: any[]) {
|
|
9
|
-
if (this.logger.fatal === undefined) {
|
|
10
|
-
return this.error(message, ...optionalParams)
|
|
11
|
-
}
|
|
12
|
-
this.logger.fatal(message, ...optionalParams)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
error(message: any, ...optionalParams: any[]) {
|
|
16
|
-
this.logger.error(message, ...optionalParams)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
warn(message: any, ...optionalParams: any[]) {
|
|
20
|
-
this.logger.warn(message, ...optionalParams)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
info() {
|
|
24
|
-
// We don't want to populate the logs with the original fastify logs
|
|
25
|
-
// this.logger.debug?.('INFO', message, ...optionalParams)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
debug(message: any, ...optionalParams: any[]) {
|
|
29
|
-
this.logger.debug?.(message, ...optionalParams)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
trace(message: any, ...optionalParams: any[]) {
|
|
33
|
-
this.logger.verbose?.(message, ...optionalParams)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
silent() {
|
|
37
|
-
// noop
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
child(options: any) {
|
|
41
|
-
const keys = Object.keys(options)
|
|
42
|
-
// @ts-expect-error We don't need to support this in the current version
|
|
43
|
-
let newContext = this.logger['context'] ?? ''
|
|
44
|
-
if (keys.length > 1) {
|
|
45
|
-
// @ts-expect-error We don't need to support this in the current version
|
|
46
|
-
newContext = `${this.logger['context'] ?? ''}:${JSON.stringify(options)}`
|
|
47
|
-
}
|
|
48
|
-
return new PinoWrapper(
|
|
49
|
-
// @ts-expect-error We don't need to support this in the current version
|
|
50
|
-
new LoggerInstance(newContext, this.logger['options']),
|
|
51
|
-
)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
get level(): any {
|
|
55
|
-
if ('level' in this.logger && this.logger.level) {
|
|
56
|
-
return this.logger.level
|
|
57
|
-
}
|
|
58
|
-
const levels = LoggerInstance['logLevels']
|
|
59
|
-
if (levels) {
|
|
60
|
-
return levels.find((level) => level !== 'verbose')
|
|
61
|
-
}
|
|
62
|
-
return 'warn'
|
|
63
|
-
}
|
|
64
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import type { ClassType } from '@navios/di'
|
|
2
|
-
import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
|
|
3
|
-
import type { ZodTypeProvider } from 'fastify-type-provider-zod'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
getGlobalServiceLocator,
|
|
7
|
-
inject,
|
|
8
|
-
Injectable,
|
|
9
|
-
InjectionToken,
|
|
10
|
-
syncInject,
|
|
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'
|
|
18
|
-
import { ExecutionContextToken, Reply, Request } from '../tokens/index.mjs'
|
|
19
|
-
import { ExecutionContext } from './execution-context.mjs'
|
|
20
|
-
import { GuardRunnerService } from './guard-runner.service.mjs'
|
|
21
|
-
|
|
22
|
-
@Injectable()
|
|
23
|
-
export class ControllerAdapterService {
|
|
24
|
-
guardRunner = syncInject(GuardRunnerService)
|
|
25
|
-
private logger = syncInject(Logger, {
|
|
26
|
-
context: ControllerAdapterService.name,
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
async setupController(
|
|
30
|
-
controller: ClassType,
|
|
31
|
-
instance: FastifyInstance,
|
|
32
|
-
moduleMetadata: ModuleMetadata,
|
|
33
|
-
) {
|
|
34
|
-
const controllerMetadata = extractControllerMetadata(controller)
|
|
35
|
-
for (const endpoint of controllerMetadata.endpoints) {
|
|
36
|
-
const { classMethod, url, httpMethod, adapterToken } = endpoint
|
|
37
|
-
|
|
38
|
-
if (!url || !adapterToken) {
|
|
39
|
-
throw new Error(
|
|
40
|
-
`[Navios] Malformed Endpoint ${controller.name}:${classMethod}`,
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
const adapter = await inject(
|
|
44
|
-
adapterToken as InjectionToken<HandlerAdapterInterface>,
|
|
45
|
-
)
|
|
46
|
-
const executionContext = new ExecutionContext(
|
|
47
|
-
moduleMetadata,
|
|
48
|
-
controllerMetadata,
|
|
49
|
-
endpoint,
|
|
50
|
-
)
|
|
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
|
-
}
|
|
74
|
-
|
|
75
|
-
this.logger.debug(
|
|
76
|
-
`Registered ${httpMethod} ${url} for ${controller.name}:${classMethod}`,
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
providePreHandler(executionContext: ExecutionContext) {
|
|
82
|
-
const guards = this.guardRunner.makeContext(executionContext)
|
|
83
|
-
return guards.size > 0
|
|
84
|
-
? this.wrapHandler(
|
|
85
|
-
executionContext,
|
|
86
|
-
async (request: FastifyRequest, reply: FastifyReply) => {
|
|
87
|
-
let canActivate = true
|
|
88
|
-
canActivate = await this.guardRunner.runGuards(
|
|
89
|
-
guards,
|
|
90
|
-
executionContext,
|
|
91
|
-
)
|
|
92
|
-
if (!canActivate) {
|
|
93
|
-
return reply
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
)
|
|
97
|
-
: undefined
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
private wrapHandler(
|
|
101
|
-
executionContext: ExecutionContext,
|
|
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)
|
|
109
|
-
executionContext.provideRequest(request)
|
|
110
|
-
executionContext.provideReply(reply)
|
|
111
|
-
try {
|
|
112
|
-
return await handler(request, reply)
|
|
113
|
-
} finally {
|
|
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
|
-
})
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|