@navios/core 0.4.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 +95 -2
- 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 +300 -235
- package/lib/_tsup-dts-rollup.d.ts +300 -235
- package/lib/index.d.mts +47 -26
- package/lib/index.d.ts +47 -26
- package/lib/index.js +633 -1072
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +631 -1064
- package/lib/index.mjs.map +1 -1
- package/package.json +4 -7
- package/project.json +9 -1
- package/src/__tests__/config.service.spec.mts +11 -9
- package/src/__tests__/controller.spec.mts +0 -1
- package/src/config/config.service.mts +2 -2
- package/src/decorators/controller.decorator.mts +1 -1
- package/src/decorators/endpoint.decorator.mts +2 -2
- package/src/decorators/header.decorator.mts +1 -1
- package/src/decorators/multipart.decorator.mts +1 -1
- package/src/decorators/stream.decorator.mts +2 -3
- 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/docs/recipes/prisma.md +0 -60
- package/e2e/endpoints/get.spec.mts +0 -97
- package/e2e/endpoints/post.spec.mts +0 -113
- 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 -135
- 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,15 +0,0 @@
|
|
|
1
|
-
import type { CanActivate, ExecutionContext } from '../../../../src/index.mjs'
|
|
2
|
-
|
|
3
|
-
import { Injectable, Logger, syncInject } from '../../../../src/index.mjs'
|
|
4
|
-
|
|
5
|
-
@Injectable()
|
|
6
|
-
export class AclModernGuard implements CanActivate {
|
|
7
|
-
logger = syncInject(Logger, {
|
|
8
|
-
context: AclModernGuard.name,
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
canActivate(executionContext: ExecutionContext): Promise<boolean> | boolean {
|
|
12
|
-
this.logger.log('ACL Modern Guard activated')
|
|
13
|
-
return true
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { CanActivate, ExecutionContext } from '../../../../src/index.mjs'
|
|
2
|
-
|
|
3
|
-
import { Injectable, Logger, syncInject } from '../../../../src/index.mjs'
|
|
4
|
-
|
|
5
|
-
@Injectable()
|
|
6
|
-
export class AclGuard implements CanActivate {
|
|
7
|
-
logger = syncInject(Logger, {
|
|
8
|
-
context: AclGuard.name,
|
|
9
|
-
})
|
|
10
|
-
canActivate(executionContext: ExecutionContext): Promise<boolean> | boolean {
|
|
11
|
-
this.logger.log('ACL Guard activated')
|
|
12
|
-
return true
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { CanActivate, ExecutionContext } from '../../../../src/index.mjs'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
AttributeFactory,
|
|
5
|
-
Injectable,
|
|
6
|
-
Logger,
|
|
7
|
-
syncInject,
|
|
8
|
-
} from '../../../../src/index.mjs'
|
|
9
|
-
import { Public } from './public.attribute.mjs'
|
|
10
|
-
|
|
11
|
-
@Injectable()
|
|
12
|
-
export class AppGuard implements CanActivate {
|
|
13
|
-
logger = syncInject(Logger, {
|
|
14
|
-
context: AppGuard.name,
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
canActivate(executionContext: ExecutionContext): Promise<boolean> | boolean {
|
|
18
|
-
const isPublic = AttributeFactory.getLast(Public, [
|
|
19
|
-
executionContext.getModule(),
|
|
20
|
-
executionContext.getController(),
|
|
21
|
-
executionContext.getHandler(),
|
|
22
|
-
])
|
|
23
|
-
this.logger.log('App Guard activated')
|
|
24
|
-
this.logger.log('isPublic', isPublic)
|
|
25
|
-
return true
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { CanActivate, ExecutionContext } from '../../../../src/index.mjs'
|
|
2
|
-
|
|
3
|
-
import { Injectable, Logger, syncInject } from '../../../../src/index.mjs'
|
|
4
|
-
|
|
5
|
-
@Injectable()
|
|
6
|
-
export class OneMoreGuard implements CanActivate {
|
|
7
|
-
logger = syncInject(Logger, {
|
|
8
|
-
context: OneMoreGuard.name,
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
canActivate(executionContext: ExecutionContext): Promise<boolean> | boolean {
|
|
12
|
-
this.logger.log('One More Guard activated')
|
|
13
|
-
return true
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod/v4'
|
|
2
|
-
|
|
3
|
-
import { AttributeFactory } from '../../../../src/index.mjs'
|
|
4
|
-
|
|
5
|
-
export const PublicSymbol = Symbol.for('Public')
|
|
6
|
-
|
|
7
|
-
export const Public = AttributeFactory.createAttribute(PublicSymbol)
|
|
8
|
-
export const RolesSymbol = Symbol.for('Roles')
|
|
9
|
-
|
|
10
|
-
export const RolesSchema = z.object({
|
|
11
|
-
roles: z.array(
|
|
12
|
-
z.union([
|
|
13
|
-
z.literal('VIEWER'),
|
|
14
|
-
z.literal('USER'),
|
|
15
|
-
z.literal('ADMIN'),
|
|
16
|
-
z.literal('OWNER'),
|
|
17
|
-
]),
|
|
18
|
-
),
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
export const Roles = AttributeFactory.createAttribute(RolesSymbol, RolesSchema)
|
|
@@ -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,135 +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 { ZodRawShape } from 'zod/v4'
|
|
5
|
-
|
|
6
|
-
import { Injectable, InjectionToken } from '@navios/di'
|
|
7
|
-
|
|
8
|
-
import { ZodArray, ZodObject, ZodOptional } from 'zod/v4'
|
|
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 ZodObject
|
|
42
|
-
const shape = requestSchema._zod.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(
|
|
69
|
-
[(await part.toBuffer()) as unknown as ArrayBuffer],
|
|
70
|
-
part.filename,
|
|
71
|
-
{
|
|
72
|
-
type: part.mimetype,
|
|
73
|
-
},
|
|
74
|
-
)
|
|
75
|
-
} else {
|
|
76
|
-
value = part.value
|
|
77
|
-
if (isObject && typeof value === 'string') {
|
|
78
|
-
value = JSON.parse(value)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (isArray) {
|
|
83
|
-
req[part.fieldname].push(value)
|
|
84
|
-
} else {
|
|
85
|
-
req[part.fieldname] = value
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private analyzeSchema(shape: ZodRawShape) {
|
|
90
|
-
return Object.keys(shape).reduce(
|
|
91
|
-
(target, key) => {
|
|
92
|
-
let schema = shape[key]
|
|
93
|
-
const isOptional = schema instanceof ZodOptional
|
|
94
|
-
if (isOptional) {
|
|
95
|
-
schema = (schema as ZodOptional<any>).unwrap()
|
|
96
|
-
}
|
|
97
|
-
const isArray = schema instanceof ZodArray
|
|
98
|
-
if (isArray) {
|
|
99
|
-
schema = (schema as ZodArray<any>).element
|
|
100
|
-
}
|
|
101
|
-
const isObject = schema instanceof ZodObject
|
|
102
|
-
return {
|
|
103
|
-
...target,
|
|
104
|
-
[key]: {
|
|
105
|
-
isArray,
|
|
106
|
-
isOptional,
|
|
107
|
-
isObject,
|
|
108
|
-
},
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
{} as Record<
|
|
112
|
-
string,
|
|
113
|
-
{ isArray: boolean; isOptional: boolean; isObject: boolean }
|
|
114
|
-
>,
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
override provideSchema(
|
|
119
|
-
handlerMetadata: HandlerMetadata<BaseEndpointConfig>,
|
|
120
|
-
): Record<string, any> {
|
|
121
|
-
const schema: Record<string, any> = {}
|
|
122
|
-
const { querySchema, responseSchema } = handlerMetadata.config
|
|
123
|
-
|
|
124
|
-
if (querySchema) {
|
|
125
|
-
schema.querystring = querySchema
|
|
126
|
-
}
|
|
127
|
-
if (responseSchema) {
|
|
128
|
-
schema.response = {
|
|
129
|
-
200: responseSchema,
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return schema
|
|
134
|
-
}
|
|
135
|
-
}
|
|
@@ -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/v4'
|
|
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
|
-
}
|