@navios/core 0.1.14 → 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 +124 -49
- package/dist/_tsup-dts-rollup.d.ts +124 -49
- package/dist/index.d.mts +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +537 -471
- package/dist/index.mjs +531 -470
- 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/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/sync-injector.mts +14 -0
- package/src/services/controller-adapter.service.mts +59 -240
- package/src/services/execution-context.mts +4 -3
|
@@ -4,14 +4,14 @@ import type {
|
|
|
4
4
|
ClassTypeWithInstance,
|
|
5
5
|
InjectionToken,
|
|
6
6
|
} from '../service-locator/index.mjs'
|
|
7
|
-
import type {
|
|
7
|
+
import type { HandlerMetadata } from './handler.metadata.mjs'
|
|
8
8
|
|
|
9
|
-
import { getAllEndpointMetadata } from './
|
|
9
|
+
import { getAllEndpointMetadata } from './handler.metadata.mjs'
|
|
10
10
|
|
|
11
11
|
export const ControllerMetadataKey = Symbol('ControllerMetadataKey')
|
|
12
12
|
|
|
13
13
|
export interface ControllerMetadata {
|
|
14
|
-
endpoints: Set<
|
|
14
|
+
endpoints: Set<HandlerMetadata>
|
|
15
15
|
guards: Set<
|
|
16
16
|
ClassTypeWithInstance<CanActivate> | InjectionToken<CanActivate, undefined>
|
|
17
17
|
>
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
BaseEndpointConfig,
|
|
3
|
-
BaseStreamConfig,
|
|
4
|
-
HttpMethod,
|
|
5
|
-
} from '@navios/common'
|
|
1
|
+
import type { HttpMethod } from '@navios/common'
|
|
6
2
|
import type { HttpHeader } from 'fastify/types/utils.js'
|
|
7
3
|
|
|
4
|
+
import type { HandlerAdapterInterface } from '../adapters/index.mjs'
|
|
8
5
|
import type { CanActivate } from '../interfaces/index.mjs'
|
|
9
6
|
import type {
|
|
10
7
|
ClassTypeWithInstance,
|
|
@@ -13,22 +10,17 @@ import type {
|
|
|
13
10
|
|
|
14
11
|
export const EndpointMetadataKey = Symbol('EndpointMetadataKey')
|
|
15
12
|
|
|
16
|
-
export
|
|
17
|
-
Unknown = 'unknown',
|
|
18
|
-
Endpoint = 'endpoint',
|
|
19
|
-
Stream = 'stream',
|
|
20
|
-
Multipart = 'multipart',
|
|
21
|
-
Handler = 'handler',
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface EndpointMetadata {
|
|
13
|
+
export interface HandlerMetadata<Config = null> {
|
|
25
14
|
classMethod: string
|
|
26
15
|
url: string
|
|
27
16
|
successStatusCode: number
|
|
28
|
-
|
|
17
|
+
adapterToken:
|
|
18
|
+
| InjectionToken<HandlerAdapterInterface, undefined>
|
|
19
|
+
| ClassTypeWithInstance<HandlerAdapterInterface>
|
|
20
|
+
| null
|
|
29
21
|
headers: Partial<Record<HttpHeader, number | string | string[] | undefined>>
|
|
30
22
|
httpMethod: HttpMethod
|
|
31
|
-
config:
|
|
23
|
+
config: Config
|
|
32
24
|
guards: Set<
|
|
33
25
|
ClassTypeWithInstance<CanActivate> | InjectionToken<CanActivate, undefined>
|
|
34
26
|
>
|
|
@@ -37,25 +29,25 @@ export interface EndpointMetadata {
|
|
|
37
29
|
|
|
38
30
|
export function getAllEndpointMetadata(
|
|
39
31
|
context: ClassMethodDecoratorContext | ClassDecoratorContext,
|
|
40
|
-
): Set<
|
|
32
|
+
): Set<HandlerMetadata<any>> {
|
|
41
33
|
if (context.metadata) {
|
|
42
34
|
const metadata = context.metadata[EndpointMetadataKey] as
|
|
43
|
-
| Set<
|
|
35
|
+
| Set<HandlerMetadata>
|
|
44
36
|
| undefined
|
|
45
37
|
if (metadata) {
|
|
46
38
|
return metadata
|
|
47
39
|
} else {
|
|
48
|
-
context.metadata[EndpointMetadataKey] = new Set<
|
|
49
|
-
return context.metadata[EndpointMetadataKey] as Set<
|
|
40
|
+
context.metadata[EndpointMetadataKey] = new Set<HandlerMetadata<any>>()
|
|
41
|
+
return context.metadata[EndpointMetadataKey] as Set<HandlerMetadata<any>>
|
|
50
42
|
}
|
|
51
43
|
}
|
|
52
44
|
throw new Error('[Navios] Wrong environment.')
|
|
53
45
|
}
|
|
54
46
|
|
|
55
|
-
export function getEndpointMetadata(
|
|
47
|
+
export function getEndpointMetadata<Config = any>(
|
|
56
48
|
target: Function,
|
|
57
49
|
context: ClassMethodDecoratorContext,
|
|
58
|
-
):
|
|
50
|
+
): HandlerMetadata<Config> {
|
|
59
51
|
if (context.metadata) {
|
|
60
52
|
const metadata = getAllEndpointMetadata(context)
|
|
61
53
|
if (metadata) {
|
|
@@ -65,13 +57,14 @@ export function getEndpointMetadata(
|
|
|
65
57
|
if (endpointMetadata) {
|
|
66
58
|
return endpointMetadata
|
|
67
59
|
} else {
|
|
68
|
-
const newMetadata:
|
|
60
|
+
const newMetadata: HandlerMetadata<Config> = {
|
|
69
61
|
classMethod: target.name,
|
|
70
62
|
url: '',
|
|
71
63
|
successStatusCode: 200,
|
|
64
|
+
adapterToken: null,
|
|
72
65
|
headers: {},
|
|
73
|
-
type: EndpointType.Unknown,
|
|
74
66
|
httpMethod: 'GET',
|
|
67
|
+
// @ts-expect-error We are using a generic type here
|
|
75
68
|
config: null,
|
|
76
69
|
guards: new Set<
|
|
77
70
|
| ClassTypeWithInstance<CanActivate>
|
package/src/metadata/index.mts
CHANGED
|
@@ -149,7 +149,7 @@ export class NaviosApplication {
|
|
|
149
149
|
message: 'Not Found',
|
|
150
150
|
error: 'NotFound',
|
|
151
151
|
}
|
|
152
|
-
this.logger.error(`Route not found: ${req.url}`)
|
|
152
|
+
this.logger.error(`Route not found: [${req.method}] ${req.url}`)
|
|
153
153
|
return reply.status(404).send(response)
|
|
154
154
|
})
|
|
155
155
|
}
|
|
@@ -178,15 +178,14 @@ export class NaviosApplication {
|
|
|
178
178
|
}
|
|
179
179
|
promises.push(
|
|
180
180
|
this.server!.register(
|
|
181
|
-
(instance, opts
|
|
181
|
+
async (instance, opts) => {
|
|
182
182
|
for (const controller of moduleMetadata.controllers) {
|
|
183
|
-
this.controllerAdapter.setupController(
|
|
183
|
+
await this.controllerAdapter.setupController(
|
|
184
184
|
controller,
|
|
185
185
|
instance,
|
|
186
186
|
moduleMetadata,
|
|
187
187
|
)
|
|
188
188
|
}
|
|
189
|
-
done()
|
|
190
189
|
},
|
|
191
190
|
{
|
|
192
191
|
prefix: this.globalPrefix ?? '',
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
|
|
4
|
+
import type {
|
|
5
|
+
Factory,
|
|
6
|
+
FactoryWithArgs,
|
|
7
|
+
} from '../interfaces/factory.interface.mjs'
|
|
8
|
+
|
|
4
9
|
import { Injectable, InjectableType } from '../decorators/index.mjs'
|
|
5
10
|
import { inject } from '../inject.mjs'
|
|
6
11
|
import { InjectionToken } from '../injection-token.mjs'
|
|
@@ -39,13 +44,13 @@ describe('InjectToken', () => {
|
|
|
39
44
|
})
|
|
40
45
|
|
|
41
46
|
it('should work with factory', async () => {
|
|
42
|
-
const token = InjectionToken.create('Test')
|
|
47
|
+
const token = InjectionToken.create<string>('Test')
|
|
43
48
|
@Injectable({
|
|
44
49
|
token,
|
|
45
50
|
type: InjectableType.Factory,
|
|
46
51
|
})
|
|
47
|
-
class Test {
|
|
48
|
-
create() {
|
|
52
|
+
class Test implements Factory<string> {
|
|
53
|
+
async create() {
|
|
49
54
|
return 'foo'
|
|
50
55
|
}
|
|
51
56
|
}
|
|
@@ -64,8 +69,8 @@ describe('InjectToken', () => {
|
|
|
64
69
|
token,
|
|
65
70
|
type: InjectableType.Factory,
|
|
66
71
|
})
|
|
67
|
-
class Test {
|
|
68
|
-
create(ctx: any, args: { test: string }) {
|
|
72
|
+
class Test implements FactoryWithArgs<string, typeof schema> {
|
|
73
|
+
async create(ctx: any, args: { test: string }) {
|
|
69
74
|
return args.test
|
|
70
75
|
}
|
|
71
76
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
+
import type { AnyZodObject } from 'zod'
|
|
2
|
+
|
|
1
3
|
import { NaviosException } from '@navios/common'
|
|
2
4
|
|
|
3
|
-
import type { ClassType } from '../injection-token.mjs'
|
|
5
|
+
import type { ClassType, ClassTypeWithInstance } from '../injection-token.mjs'
|
|
6
|
+
import type {
|
|
7
|
+
Factory,
|
|
8
|
+
FactoryWithArgs,
|
|
9
|
+
} from '../interfaces/factory.interface.mjs'
|
|
4
10
|
|
|
5
11
|
import { InjectableScope } from '../enums/index.mjs'
|
|
6
12
|
import { InjectionToken } from '../injection-token.mjs'
|
|
@@ -18,14 +24,55 @@ export interface InjectableOptions {
|
|
|
18
24
|
token?: InjectionToken<any, any>
|
|
19
25
|
}
|
|
20
26
|
|
|
21
|
-
export const InjectableTokenMeta = Symbol('InjectableTokenMeta')
|
|
27
|
+
export const InjectableTokenMeta = Symbol.for('InjectableTokenMeta')
|
|
22
28
|
|
|
29
|
+
export function Injectable(): <T extends ClassType>(
|
|
30
|
+
target: T,
|
|
31
|
+
context: ClassDecoratorContext,
|
|
32
|
+
) => T & { [InjectableTokenMeta]: InjectionToken<InstanceType<T>, undefined> }
|
|
33
|
+
export function Injectable<T extends ClassType>(options: {
|
|
34
|
+
scope?: InjectableScope
|
|
35
|
+
token: InjectionToken<T, undefined>
|
|
36
|
+
}): (
|
|
37
|
+
target: T,
|
|
38
|
+
context: ClassDecoratorContext,
|
|
39
|
+
) => T & {
|
|
40
|
+
[InjectableTokenMeta]: InjectionToken<InstanceType<T>, undefined>
|
|
41
|
+
}
|
|
42
|
+
export function Injectable<R>(options: {
|
|
43
|
+
scope?: InjectableScope
|
|
44
|
+
type: InjectableType.Factory
|
|
45
|
+
}): <T extends ClassTypeWithInstance<Factory<R>>>(
|
|
46
|
+
target: T,
|
|
47
|
+
context: ClassDecoratorContext,
|
|
48
|
+
) => T & { [InjectableTokenMeta]: InjectionToken<R, undefined> }
|
|
49
|
+
export function Injectable<R, S extends AnyZodObject>(options: {
|
|
50
|
+
scope?: InjectableScope
|
|
51
|
+
type: InjectableType.Factory
|
|
52
|
+
token: InjectionToken<R, S>
|
|
53
|
+
}): <T extends ClassTypeWithInstance<FactoryWithArgs<R, S>>>(
|
|
54
|
+
target: T,
|
|
55
|
+
context: ClassDecoratorContext,
|
|
56
|
+
) => T & { [InjectableTokenMeta]: InjectionToken<R, S> }
|
|
57
|
+
export function Injectable<R>(options: {
|
|
58
|
+
scope?: InjectableScope
|
|
59
|
+
type: InjectableType.Factory
|
|
60
|
+
token: InjectionToken<R, undefined>
|
|
61
|
+
}): <T extends ClassTypeWithInstance<Factory<R>>>(
|
|
62
|
+
target: T,
|
|
63
|
+
context: ClassDecoratorContext,
|
|
64
|
+
) => T & { [InjectableTokenMeta]: InjectionToken<R, undefined> }
|
|
23
65
|
export function Injectable({
|
|
24
66
|
scope = InjectableScope.Singleton,
|
|
25
67
|
type = InjectableType.Class,
|
|
26
68
|
token,
|
|
27
69
|
}: InjectableOptions = {}) {
|
|
28
|
-
return
|
|
70
|
+
return <T extends ClassType>(
|
|
71
|
+
target: T,
|
|
72
|
+
context: ClassDecoratorContext,
|
|
73
|
+
): T & {
|
|
74
|
+
[InjectableTokenMeta]: InjectionToken<any, any>
|
|
75
|
+
} => {
|
|
29
76
|
if (context.kind !== 'class') {
|
|
30
77
|
throw new Error(
|
|
31
78
|
'[ServiceLocator] @Injectable decorator can only be used on classes.',
|
|
@@ -59,6 +106,8 @@ export function Injectable({
|
|
|
59
106
|
// @ts-expect-error
|
|
60
107
|
target[InjectableTokenMeta] = injectableToken
|
|
61
108
|
|
|
62
|
-
return target
|
|
109
|
+
return target as T & {
|
|
110
|
+
[InjectableTokenMeta]: InjectionToken<any, any>
|
|
111
|
+
}
|
|
63
112
|
}
|
|
64
113
|
}
|
|
@@ -7,6 +7,20 @@ import { InjectionToken } from './injection-token.mjs'
|
|
|
7
7
|
import { getServiceLocator } from './injector.mjs'
|
|
8
8
|
|
|
9
9
|
export function inject<T extends ClassType>(token: T): Promise<InstanceType<T>>
|
|
10
|
+
// Not supported by TypeScript yet
|
|
11
|
+
// export function inject<
|
|
12
|
+
// R,
|
|
13
|
+
// T extends ClassType & {
|
|
14
|
+
// [InjectableTokenMeta]: InjectionToken<R, undefined>
|
|
15
|
+
// },
|
|
16
|
+
// >(token: T): Promise<R>
|
|
17
|
+
// export function inject<
|
|
18
|
+
// R,
|
|
19
|
+
// S extends AnyZodObject,
|
|
20
|
+
// T extends ClassType & {
|
|
21
|
+
// [InjectableTokenMeta]: InjectionToken<R, S>
|
|
22
|
+
// },
|
|
23
|
+
// >(token: T, args: z.input<S>): Promise<R>
|
|
10
24
|
export function inject<T, S extends AnyZodObject>(
|
|
11
25
|
token: InjectionToken<T, S>,
|
|
12
26
|
args: z.input<S>,
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import type { AnyZodObject } from 'zod'
|
|
2
|
+
|
|
3
|
+
import { z } from 'zod'
|
|
4
|
+
|
|
1
5
|
export interface Factory<T> {
|
|
2
|
-
create(ctx
|
|
6
|
+
create(ctx?: any): Promise<T> | T
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface FactoryWithArgs<T, A extends AnyZodObject> {
|
|
10
|
+
create(ctx: any, args: z.output<A>): Promise<T> | T
|
|
3
11
|
}
|
|
@@ -9,6 +9,20 @@ import { getServiceLocator } from './injector.mjs'
|
|
|
9
9
|
let promiseCollector: null | ((promise: Promise<any>) => void) = null
|
|
10
10
|
|
|
11
11
|
export function syncInject<T extends ClassType>(token: T): InstanceType<T>
|
|
12
|
+
// Not supported by TypeScript yet
|
|
13
|
+
// export function syncInject<
|
|
14
|
+
// R,
|
|
15
|
+
// T extends ClassType & {
|
|
16
|
+
// [InjectableTokenMeta]: InjectionToken<R, undefined>
|
|
17
|
+
// },
|
|
18
|
+
// >(token: T): R
|
|
19
|
+
// export function syncInject<
|
|
20
|
+
// R,
|
|
21
|
+
// S extends AnyZodObject,
|
|
22
|
+
// T extends ClassType & {
|
|
23
|
+
// [InjectableTokenMeta]: InjectionToken<R, S>
|
|
24
|
+
// },
|
|
25
|
+
// >(token: T, args: z.input<S>): R
|
|
12
26
|
export function syncInject<T, S extends AnyZodObject>(
|
|
13
27
|
token: InjectionToken<T, S>,
|
|
14
28
|
args: z.input<S>,
|
|
@@ -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
|
}
|