@navios/core 0.6.0 → 0.7.1
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/CHANGELOG.md +115 -0
- package/README.md +18 -1
- package/docs/README.md +1 -0
- package/docs/legacy-compat.md +320 -0
- package/docs/testing.md +140 -17
- package/lib/index-DW9EPAE6.d.mts +2156 -0
- package/lib/index-DW9EPAE6.d.mts.map +1 -0
- package/lib/index-pHp-dIGt.d.cts +2156 -0
- package/lib/index-pHp-dIGt.d.cts.map +1 -0
- package/lib/index.cjs +157 -0
- package/lib/index.d.cts +3 -0
- package/lib/index.d.mts +3 -190
- package/lib/index.mjs +4 -1459
- package/lib/legacy-compat/index.cjs +315 -0
- package/lib/legacy-compat/index.cjs.map +1 -0
- package/lib/legacy-compat/index.d.cts +219 -0
- package/lib/legacy-compat/index.d.cts.map +1 -0
- package/lib/legacy-compat/index.d.mts +219 -0
- package/lib/legacy-compat/index.d.mts.map +1 -0
- package/lib/legacy-compat/index.mjs +308 -0
- package/lib/legacy-compat/index.mjs.map +1 -0
- package/lib/src-DyvCDuKO.mjs +5443 -0
- package/lib/src-DyvCDuKO.mjs.map +1 -0
- package/lib/src-QnxR5b7c.cjs +5800 -0
- package/lib/src-QnxR5b7c.cjs.map +1 -0
- package/lib/testing/index.cjs +106 -0
- package/lib/testing/index.cjs.map +1 -0
- package/lib/testing/index.d.cts +156 -0
- package/lib/testing/index.d.cts.map +1 -0
- package/lib/testing/index.d.mts +156 -0
- package/lib/testing/index.d.mts.map +1 -0
- package/lib/testing/index.mjs +100 -0
- package/lib/testing/index.mjs.map +1 -0
- package/lib/use-guards.decorator-B6q_N0sf.cjs +622 -0
- package/lib/use-guards.decorator-B6q_N0sf.cjs.map +1 -0
- package/lib/use-guards.decorator-kZ3lNK8v.mjs +454 -0
- package/lib/use-guards.decorator-kZ3lNK8v.mjs.map +1 -0
- package/package.json +28 -8
- package/project.json +2 -2
- package/src/attribute.factory.mts +154 -0
- package/src/config/config-service.interface.mts +31 -0
- package/src/config/config.provider.mts +36 -0
- package/src/config/config.service.mts +94 -4
- package/src/decorators/controller.decorator.mts +28 -0
- package/src/decorators/endpoint.decorator.mts +76 -0
- package/src/decorators/header.decorator.mts +19 -0
- package/src/decorators/http-code.decorator.mts +20 -0
- package/src/decorators/module.decorator.mts +34 -0
- package/src/decorators/multipart.decorator.mts +41 -0
- package/src/decorators/stream.decorator.mts +33 -0
- package/src/decorators/use-guards.decorator.mts +29 -0
- package/src/exceptions/bad-request.exception.mts +21 -0
- package/src/exceptions/conflict.exception.mts +24 -0
- package/src/exceptions/forbidden.exception.mts +23 -0
- package/src/exceptions/http.exception.mts +26 -0
- package/src/exceptions/internal-server-error.exception.mts +26 -0
- package/src/exceptions/not-found.exception.mts +23 -0
- package/src/exceptions/unauthorized.exception.mts +23 -0
- package/src/index.mts +1 -0
- package/src/interfaces/abstract-execution-context.inteface.mts +35 -0
- package/src/interfaces/abstract-http-adapter.interface.mts +52 -0
- package/src/interfaces/abstract-http-handler-adapter.interface.mts +2 -2
- package/src/interfaces/can-activate.mts +31 -0
- package/src/interfaces/index.mts +1 -0
- package/src/interfaces/navios-module.mts +25 -0
- package/src/interfaces/plugin.interface.mts +105 -0
- package/src/legacy-compat/__type-tests__/legacy-decorators.spec-d.mts +420 -0
- package/src/legacy-compat/__type-tests__/tsconfig.json +15 -0
- package/src/legacy-compat/context-compat.mts +93 -0
- package/src/legacy-compat/decorators/controller.decorator.mts +31 -0
- package/src/legacy-compat/decorators/endpoint.decorator.mts +99 -0
- package/src/legacy-compat/decorators/header.decorator.mts +42 -0
- package/src/legacy-compat/decorators/http-code.decorator.mts +38 -0
- package/src/legacy-compat/decorators/index.mts +9 -0
- package/src/legacy-compat/decorators/module.decorator.mts +37 -0
- package/src/legacy-compat/decorators/multipart.decorator.mts +93 -0
- package/src/legacy-compat/decorators/stream.decorator.mts +76 -0
- package/src/legacy-compat/decorators/use-guards.decorator.mts +80 -0
- package/src/legacy-compat/index.mts +40 -0
- package/src/logger/console-logger.service.mts +15 -2
- package/src/logger/log-levels.mts +9 -0
- package/src/logger/logger.service.mts +21 -0
- package/src/logger/logger.tokens.mts +23 -0
- package/src/navios.application.mts +228 -4
- package/src/navios.factory.mts +60 -1
- package/src/services/guard-runner.service.mts +12 -11
- package/src/services/module-loader.service.mts +118 -12
- package/src/stores/index.mts +1 -0
- package/src/stores/request-id.store.mts +43 -0
- package/src/testing/index.mts +2 -0
- package/src/testing/testing-module.mts +231 -0
- package/tsconfig.lib.json +1 -1
- package/tsconfig.spec.json +3 -0
- package/tsdown.config.mts +35 -0
- package/vitest.config.mts +6 -0
- package/lib/_tsup-dts-rollup.d.mts +0 -1365
- package/lib/_tsup-dts-rollup.d.ts +0 -1365
- package/lib/index.d.ts +0 -190
- package/lib/index.js +0 -1540
- package/lib/index.js.map +0 -1
- package/lib/index.mjs.map +0 -1
- package/tsup.config.mts +0 -13
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility layer for converting legacy decorator signatures to Stage 3 format.
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities to create mock Stage 3 decorator contexts
|
|
5
|
+
* from legacy decorator arguments, and manages metadata storage using WeakMap.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ClassType } from '@navios/di'
|
|
9
|
+
|
|
10
|
+
// WeakMap to store metadata for legacy decorators
|
|
11
|
+
// Keyed by class constructor for class decorators
|
|
12
|
+
// For method decorators, we use the class constructor (extracted from the prototype)
|
|
13
|
+
const classMetadataMap = new WeakMap<ClassType, Record<string | symbol, any>>()
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Gets the constructor from a prototype (for method decorators).
|
|
17
|
+
*/
|
|
18
|
+
function getConstructor(prototype: any): ClassType | null {
|
|
19
|
+
if (!prototype || typeof prototype !== 'object') {
|
|
20
|
+
return null
|
|
21
|
+
}
|
|
22
|
+
// In legacy decorators, target is the prototype
|
|
23
|
+
// The constructor is typically available via prototype.constructor
|
|
24
|
+
const constructor = prototype.constructor
|
|
25
|
+
if (constructor && typeof constructor === 'function') {
|
|
26
|
+
return constructor as ClassType
|
|
27
|
+
}
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Creates a mock ClassDecoratorContext for legacy class decorators.
|
|
33
|
+
*/
|
|
34
|
+
export function createClassContext(target: ClassType): ClassDecoratorContext {
|
|
35
|
+
// Get or create metadata storage for this class
|
|
36
|
+
if (!classMetadataMap.has(target)) {
|
|
37
|
+
classMetadataMap.set(target, {})
|
|
38
|
+
}
|
|
39
|
+
const metadata = classMetadataMap.get(target)!
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
kind: 'class',
|
|
43
|
+
name: target.name,
|
|
44
|
+
metadata,
|
|
45
|
+
addInitializer() {
|
|
46
|
+
// Legacy decorators don't support initializers
|
|
47
|
+
},
|
|
48
|
+
} as ClassDecoratorContext
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates a mock ClassMethodDecoratorContext for legacy method decorators.
|
|
53
|
+
*
|
|
54
|
+
* Note: Method decorators need to share metadata with the class context
|
|
55
|
+
* because endpoint metadata is stored at the class level.
|
|
56
|
+
*/
|
|
57
|
+
export function createMethodContext(
|
|
58
|
+
target: any,
|
|
59
|
+
propertyKey: string | symbol,
|
|
60
|
+
descriptor: PropertyDescriptor,
|
|
61
|
+
): ClassMethodDecoratorContext {
|
|
62
|
+
// For method decorators, target is the prototype
|
|
63
|
+
// We need to get the class constructor to access class-level metadata
|
|
64
|
+
const constructor = getConstructor(target)
|
|
65
|
+
if (!constructor) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
'[Navios] Could not determine class constructor from method decorator target.',
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Get or create metadata storage for the class
|
|
72
|
+
// Method decorators share metadata with the class
|
|
73
|
+
if (!classMetadataMap.has(constructor)) {
|
|
74
|
+
classMetadataMap.set(constructor, {})
|
|
75
|
+
}
|
|
76
|
+
const metadata = classMetadataMap.get(constructor)!
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
kind: 'method',
|
|
80
|
+
name: propertyKey,
|
|
81
|
+
metadata,
|
|
82
|
+
static: false, // We can't determine this from legacy decorators
|
|
83
|
+
private: false, // We can't determine this from legacy decorators
|
|
84
|
+
access: {
|
|
85
|
+
has: () => true,
|
|
86
|
+
get: () => descriptor.value,
|
|
87
|
+
set: () => {},
|
|
88
|
+
},
|
|
89
|
+
addInitializer() {
|
|
90
|
+
// Legacy decorators don't support initializers
|
|
91
|
+
},
|
|
92
|
+
} as ClassMethodDecoratorContext
|
|
93
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ClassType } from '@navios/di'
|
|
2
|
+
|
|
3
|
+
import type { ControllerOptions } from '../../decorators/controller.decorator.mjs'
|
|
4
|
+
|
|
5
|
+
import { Controller as OriginalController } from '../../decorators/controller.decorator.mjs'
|
|
6
|
+
import { createClassContext } from '../context-compat.mjs'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Legacy-compatible Controller decorator.
|
|
10
|
+
*
|
|
11
|
+
* Works with TypeScript experimental decorators (legacy API).
|
|
12
|
+
*
|
|
13
|
+
* @param options - Controller configuration options
|
|
14
|
+
* @returns A class decorator compatible with legacy decorator API
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* @Controller({ guards: [AuthGuard] })
|
|
19
|
+
* export class UserController {
|
|
20
|
+
* @Endpoint(getUserEndpoint)
|
|
21
|
+
* async getUser() { }
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function Controller(options: ControllerOptions = {}) {
|
|
26
|
+
return function (target: ClassType) {
|
|
27
|
+
const context = createClassContext(target)
|
|
28
|
+
const originalDecorator = OriginalController(options)
|
|
29
|
+
return originalDecorator(target, context)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BaseEndpointConfig,
|
|
3
|
+
EndpointFunctionArgs,
|
|
4
|
+
HttpMethod,
|
|
5
|
+
} from '@navios/builder'
|
|
6
|
+
import type { z, ZodType } from 'zod/v4'
|
|
7
|
+
|
|
8
|
+
import { Endpoint as OriginalEndpoint } from '../../decorators/endpoint.decorator.mjs'
|
|
9
|
+
import { createMethodContext } from '../context-compat.mjs'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Type helper to constrain a PropertyDescriptor's value to match an endpoint signature.
|
|
13
|
+
* Note: In legacy decorators, type constraints are checked when the decorator is applied,
|
|
14
|
+
* but may not be preserved perfectly when decorators are stacked.
|
|
15
|
+
*/
|
|
16
|
+
type EndpointMethodDescriptor<
|
|
17
|
+
Url extends string,
|
|
18
|
+
QuerySchema,
|
|
19
|
+
RequestSchema,
|
|
20
|
+
ResponseSchema extends ZodType,
|
|
21
|
+
> = TypedPropertyDescriptor<
|
|
22
|
+
(
|
|
23
|
+
params: QuerySchema extends ZodType
|
|
24
|
+
? RequestSchema extends ZodType
|
|
25
|
+
? EndpointFunctionArgs<Url, QuerySchema, RequestSchema, true>
|
|
26
|
+
: EndpointFunctionArgs<Url, QuerySchema, undefined, true>
|
|
27
|
+
: RequestSchema extends ZodType
|
|
28
|
+
? EndpointFunctionArgs<Url, undefined, RequestSchema, true>
|
|
29
|
+
: EndpointFunctionArgs<Url, undefined, undefined, true>,
|
|
30
|
+
) => Promise<z.input<ResponseSchema>>
|
|
31
|
+
>
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Legacy-compatible Endpoint decorator.
|
|
35
|
+
*
|
|
36
|
+
* Works with TypeScript experimental decorators (legacy API).
|
|
37
|
+
* Provides type safety by ensuring method signatures match the endpoint configuration.
|
|
38
|
+
*
|
|
39
|
+
* @param endpoint - The endpoint declaration from @navios/builder
|
|
40
|
+
* @returns A method decorator compatible with legacy decorator API
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* @Controller()
|
|
45
|
+
* export class UserController {
|
|
46
|
+
* @Endpoint(getUserEndpoint)
|
|
47
|
+
* async getUser(request: EndpointParams<typeof getUserEndpoint>): EndpointResult<typeof getUserEndpoint> {
|
|
48
|
+
* return { id: '1', name: 'John' }
|
|
49
|
+
* }
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export function Endpoint<
|
|
54
|
+
Method extends HttpMethod = HttpMethod,
|
|
55
|
+
Url extends string = string,
|
|
56
|
+
QuerySchema = undefined,
|
|
57
|
+
ResponseSchema extends ZodType = ZodType,
|
|
58
|
+
RequestSchema = ZodType,
|
|
59
|
+
>(endpoint: {
|
|
60
|
+
config: BaseEndpointConfig<
|
|
61
|
+
Method,
|
|
62
|
+
Url,
|
|
63
|
+
QuerySchema,
|
|
64
|
+
ResponseSchema,
|
|
65
|
+
RequestSchema
|
|
66
|
+
>
|
|
67
|
+
}) {
|
|
68
|
+
return function (
|
|
69
|
+
target: any,
|
|
70
|
+
propertyKey: string | symbol,
|
|
71
|
+
descriptor: EndpointMethodDescriptor<
|
|
72
|
+
Url,
|
|
73
|
+
QuerySchema,
|
|
74
|
+
RequestSchema,
|
|
75
|
+
ResponseSchema
|
|
76
|
+
>,
|
|
77
|
+
): PropertyDescriptor | void {
|
|
78
|
+
if (!descriptor) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
'[Navios] @Endpoint decorator requires a method descriptor. Make sure experimentalDecorators is enabled.',
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
// Type check the descriptor value matches expected signature
|
|
84
|
+
const typedDescriptor = descriptor as EndpointMethodDescriptor<
|
|
85
|
+
Url,
|
|
86
|
+
QuerySchema,
|
|
87
|
+
RequestSchema,
|
|
88
|
+
ResponseSchema
|
|
89
|
+
>
|
|
90
|
+
const context = createMethodContext(target, propertyKey, typedDescriptor)
|
|
91
|
+
const originalDecorator = OriginalEndpoint(endpoint)
|
|
92
|
+
// @ts-expect-error - we don't need to type the value
|
|
93
|
+
const result = originalDecorator(typedDescriptor.value, context)
|
|
94
|
+
if (result !== typedDescriptor.value) {
|
|
95
|
+
typedDescriptor.value = result
|
|
96
|
+
}
|
|
97
|
+
return typedDescriptor
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { HttpHeader } from '../../interfaces/index.mjs'
|
|
2
|
+
|
|
3
|
+
import { Header as OriginalHeader } from '../../decorators/header.decorator.mjs'
|
|
4
|
+
import { createMethodContext } from '../context-compat.mjs'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Legacy-compatible Header decorator.
|
|
8
|
+
*
|
|
9
|
+
* Works with TypeScript experimental decorators (legacy API).
|
|
10
|
+
*
|
|
11
|
+
* @param name - The header name (e.g., 'Content-Type', 'Cache-Control')
|
|
12
|
+
* @param value - The header value (string, number, or array of strings)
|
|
13
|
+
* @returns A method decorator compatible with legacy decorator API
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* @Controller()
|
|
18
|
+
* export class UserController {
|
|
19
|
+
* @Endpoint(getUserEndpoint)
|
|
20
|
+
* @Header('Cache-Control', 'max-age=3600')
|
|
21
|
+
* async getUser() {
|
|
22
|
+
* return { id: '1', name: 'John' }
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function Header(name: HttpHeader, value: string | number | string[]) {
|
|
28
|
+
return function <T extends object>(
|
|
29
|
+
target: T,
|
|
30
|
+
propertyKey: string | symbol,
|
|
31
|
+
descriptor: PropertyDescriptor,
|
|
32
|
+
) {
|
|
33
|
+
const context = createMethodContext(target, propertyKey, descriptor)
|
|
34
|
+
const originalDecorator = OriginalHeader(name, value)
|
|
35
|
+
const result = originalDecorator(descriptor.value, context)
|
|
36
|
+
if (result !== descriptor.value) {
|
|
37
|
+
descriptor.value = result
|
|
38
|
+
}
|
|
39
|
+
return descriptor
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { HttpCode as OriginalHttpCode } from '../../decorators/http-code.decorator.mjs'
|
|
2
|
+
import { createMethodContext } from '../context-compat.mjs'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Legacy-compatible HttpCode decorator.
|
|
6
|
+
*
|
|
7
|
+
* Works with TypeScript experimental decorators (legacy API).
|
|
8
|
+
*
|
|
9
|
+
* @param code - The HTTP status code to return (e.g., 201, 204, 202)
|
|
10
|
+
* @returns A method decorator compatible with legacy decorator API
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* @Controller()
|
|
15
|
+
* export class UserController {
|
|
16
|
+
* @Endpoint(createUserEndpoint)
|
|
17
|
+
* @HttpCode(201)
|
|
18
|
+
* async createUser() {
|
|
19
|
+
* return { id: '1', name: 'John' }
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export function HttpCode(code: number) {
|
|
25
|
+
return function <T extends object>(
|
|
26
|
+
target: T,
|
|
27
|
+
propertyKey: string | symbol,
|
|
28
|
+
descriptor: PropertyDescriptor,
|
|
29
|
+
) {
|
|
30
|
+
const context = createMethodContext(target, propertyKey, descriptor)
|
|
31
|
+
const originalDecorator = OriginalHttpCode(code)
|
|
32
|
+
const result = originalDecorator(descriptor.value, context)
|
|
33
|
+
if (result !== descriptor.value) {
|
|
34
|
+
descriptor.value = result
|
|
35
|
+
}
|
|
36
|
+
return descriptor
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './module.decorator.mjs'
|
|
2
|
+
export * from './controller.decorator.mjs'
|
|
3
|
+
export * from './endpoint.decorator.mjs'
|
|
4
|
+
export * from './use-guards.decorator.mjs'
|
|
5
|
+
export * from './header.decorator.mjs'
|
|
6
|
+
export * from './http-code.decorator.mjs'
|
|
7
|
+
export * from './multipart.decorator.mjs'
|
|
8
|
+
export * from './stream.decorator.mjs'
|
|
9
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ClassType } from '@navios/di'
|
|
2
|
+
|
|
3
|
+
import { Module as OriginalModule, type ModuleOptions } from '../../decorators/module.decorator.mjs'
|
|
4
|
+
import { createClassContext } from '../context-compat.mjs'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Legacy-compatible Module decorator.
|
|
8
|
+
*
|
|
9
|
+
* Works with TypeScript experimental decorators (legacy API).
|
|
10
|
+
*
|
|
11
|
+
* @param options - Module configuration options
|
|
12
|
+
* @returns A class decorator compatible with legacy decorator API
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* @Module({
|
|
17
|
+
* controllers: [UserController, AuthController],
|
|
18
|
+
* imports: [DatabaseModule],
|
|
19
|
+
* guards: [AuthGuard],
|
|
20
|
+
* })
|
|
21
|
+
* export class AppModule {}
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export function Module(
|
|
25
|
+
options: ModuleOptions = {
|
|
26
|
+
controllers: [],
|
|
27
|
+
imports: [],
|
|
28
|
+
guards: [],
|
|
29
|
+
},
|
|
30
|
+
) {
|
|
31
|
+
return function (target: ClassType) {
|
|
32
|
+
const context = createClassContext(target)
|
|
33
|
+
const originalDecorator = OriginalModule(options)
|
|
34
|
+
return originalDecorator(target, context)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BaseEndpointConfig,
|
|
3
|
+
EndpointFunctionArgs,
|
|
4
|
+
HttpMethod,
|
|
5
|
+
} from '@navios/builder'
|
|
6
|
+
import type { z, ZodObject, ZodType } from 'zod/v4'
|
|
7
|
+
|
|
8
|
+
import { Multipart as OriginalMultipart } from '../../decorators/multipart.decorator.mjs'
|
|
9
|
+
import { createMethodContext } from '../context-compat.mjs'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Type helper to constrain a PropertyDescriptor's value to match a multipart endpoint signature.
|
|
13
|
+
* Note: In legacy decorators, type constraints are checked when the decorator is applied,
|
|
14
|
+
* but may not be preserved perfectly when decorators are stacked.
|
|
15
|
+
*/
|
|
16
|
+
type MultipartMethodDescriptor<
|
|
17
|
+
Url extends string,
|
|
18
|
+
QuerySchema,
|
|
19
|
+
RequestSchema,
|
|
20
|
+
ResponseSchema extends ZodType,
|
|
21
|
+
> = TypedPropertyDescriptor<
|
|
22
|
+
(
|
|
23
|
+
params: QuerySchema extends ZodObject
|
|
24
|
+
? RequestSchema extends ZodType
|
|
25
|
+
? EndpointFunctionArgs<Url, QuerySchema, RequestSchema>
|
|
26
|
+
: EndpointFunctionArgs<Url, QuerySchema, undefined>
|
|
27
|
+
: RequestSchema extends ZodType
|
|
28
|
+
? EndpointFunctionArgs<Url, undefined, RequestSchema>
|
|
29
|
+
: EndpointFunctionArgs<Url, undefined, undefined>,
|
|
30
|
+
) => Promise<z.input<ResponseSchema>>
|
|
31
|
+
>
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Legacy-compatible Multipart decorator.
|
|
35
|
+
*
|
|
36
|
+
* Works with TypeScript experimental decorators (legacy API).
|
|
37
|
+
* Provides type safety by ensuring method signatures match the endpoint configuration.
|
|
38
|
+
*
|
|
39
|
+
* @param endpoint - The multipart endpoint declaration from @navios/builder
|
|
40
|
+
* @returns A method decorator compatible with legacy decorator API
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* @Controller()
|
|
45
|
+
* export class FileController {
|
|
46
|
+
* @Multipart(uploadFileEndpoint)
|
|
47
|
+
* async uploadFile(request: MultipartParams<typeof uploadFileEndpoint>): MultipartResult<typeof uploadFileEndpoint> {
|
|
48
|
+
* const { file } = request.data
|
|
49
|
+
* return { url: 'https://example.com/file.jpg' }
|
|
50
|
+
* }
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export function Multipart<
|
|
55
|
+
Method extends HttpMethod = HttpMethod,
|
|
56
|
+
Url extends string = string,
|
|
57
|
+
QuerySchema = undefined,
|
|
58
|
+
ResponseSchema extends ZodType = ZodType,
|
|
59
|
+
RequestSchema = ZodType,
|
|
60
|
+
>(endpoint: {
|
|
61
|
+
config: BaseEndpointConfig<
|
|
62
|
+
Method,
|
|
63
|
+
Url,
|
|
64
|
+
QuerySchema,
|
|
65
|
+
ResponseSchema,
|
|
66
|
+
RequestSchema
|
|
67
|
+
>
|
|
68
|
+
}) {
|
|
69
|
+
return function <T extends object>(
|
|
70
|
+
target: T,
|
|
71
|
+
propertyKey: string | symbol,
|
|
72
|
+
descriptor: MultipartMethodDescriptor<
|
|
73
|
+
Url,
|
|
74
|
+
QuerySchema,
|
|
75
|
+
RequestSchema,
|
|
76
|
+
ResponseSchema
|
|
77
|
+
>,
|
|
78
|
+
): PropertyDescriptor | void {
|
|
79
|
+
if (!descriptor) {
|
|
80
|
+
throw new Error(
|
|
81
|
+
'[Navios] @Multipart decorator requires a method descriptor. Make sure experimentalDecorators is enabled.',
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
const context = createMethodContext(target, propertyKey, descriptor)
|
|
85
|
+
const originalDecorator = OriginalMultipart(endpoint)
|
|
86
|
+
// @ts-expect-error - we don't need to type the value
|
|
87
|
+
const result = originalDecorator(descriptor.value, context)
|
|
88
|
+
if (result !== descriptor.value) {
|
|
89
|
+
descriptor.value = result
|
|
90
|
+
}
|
|
91
|
+
return descriptor
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BaseStreamConfig,
|
|
3
|
+
EndpointFunctionArgs,
|
|
4
|
+
HttpMethod,
|
|
5
|
+
} from '@navios/builder'
|
|
6
|
+
import type { ZodObject, ZodType } from 'zod/v4'
|
|
7
|
+
|
|
8
|
+
import { Stream as OriginalStream } from '../../decorators/stream.decorator.mjs'
|
|
9
|
+
import { createMethodContext } from '../context-compat.mjs'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Type helper to constrain a PropertyDescriptor's value to match a stream endpoint signature.
|
|
13
|
+
* Note: In legacy decorators, type constraints are checked when the decorator is applied,
|
|
14
|
+
* but may not be preserved perfectly when decorators are stacked.
|
|
15
|
+
*/
|
|
16
|
+
type StreamMethodDescriptor<
|
|
17
|
+
Url extends string,
|
|
18
|
+
QuerySchema,
|
|
19
|
+
RequestSchema,
|
|
20
|
+
> = TypedPropertyDescriptor<
|
|
21
|
+
(
|
|
22
|
+
params: QuerySchema extends ZodObject
|
|
23
|
+
? RequestSchema extends ZodType
|
|
24
|
+
? EndpointFunctionArgs<Url, QuerySchema, RequestSchema>
|
|
25
|
+
: EndpointFunctionArgs<Url, QuerySchema, undefined>
|
|
26
|
+
: RequestSchema extends ZodType
|
|
27
|
+
? EndpointFunctionArgs<Url, undefined, RequestSchema>
|
|
28
|
+
: EndpointFunctionArgs<Url, undefined, undefined>,
|
|
29
|
+
reply: any,
|
|
30
|
+
) => Promise<void>
|
|
31
|
+
>
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Legacy-compatible Stream decorator.
|
|
35
|
+
*
|
|
36
|
+
* Works with TypeScript experimental decorators (legacy API).
|
|
37
|
+
* Provides type safety by ensuring method signatures match the endpoint configuration.
|
|
38
|
+
*
|
|
39
|
+
* @param endpoint - The stream endpoint declaration from @navios/builder
|
|
40
|
+
* @returns A method decorator compatible with legacy decorator API
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* @Controller()
|
|
45
|
+
* export class FileController {
|
|
46
|
+
* @Stream(downloadFileEndpoint)
|
|
47
|
+
* async downloadFile(request: StreamParams<typeof downloadFileEndpoint>, reply: any) {
|
|
48
|
+
* const { fileId } = request.urlParams
|
|
49
|
+
* // Stream file data to reply
|
|
50
|
+
* }
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export function Stream<
|
|
55
|
+
Method extends HttpMethod = HttpMethod,
|
|
56
|
+
Url extends string = string,
|
|
57
|
+
QuerySchema = undefined,
|
|
58
|
+
RequestSchema = ZodType,
|
|
59
|
+
>(endpoint: {
|
|
60
|
+
config: BaseStreamConfig<Method, Url, QuerySchema, RequestSchema>
|
|
61
|
+
}) {
|
|
62
|
+
return function <T extends object>(
|
|
63
|
+
target: T,
|
|
64
|
+
propertyKey: string | symbol,
|
|
65
|
+
descriptor: StreamMethodDescriptor<Url, QuerySchema, RequestSchema>,
|
|
66
|
+
) {
|
|
67
|
+
const context = createMethodContext(target, propertyKey, descriptor)
|
|
68
|
+
const originalDecorator = OriginalStream(endpoint)
|
|
69
|
+
// @ts-expect-error - we don't need to type the value
|
|
70
|
+
const result = originalDecorator(descriptor.value, context)
|
|
71
|
+
if (result !== descriptor.value) {
|
|
72
|
+
descriptor.value = result
|
|
73
|
+
}
|
|
74
|
+
return descriptor
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ClassType,
|
|
3
|
+
ClassTypeWithInstance,
|
|
4
|
+
InjectionToken,
|
|
5
|
+
} from '@navios/di'
|
|
6
|
+
|
|
7
|
+
import type { CanActivate } from '../../interfaces/index.mjs'
|
|
8
|
+
|
|
9
|
+
import { UseGuards as OriginalUseGuards } from '../../decorators/use-guards.decorator.mjs'
|
|
10
|
+
import { createClassContext, createMethodContext } from '../context-compat.mjs'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Legacy-compatible UseGuards decorator.
|
|
14
|
+
*
|
|
15
|
+
* Works with TypeScript experimental decorators (legacy API).
|
|
16
|
+
* Can be applied to classes or methods.
|
|
17
|
+
*
|
|
18
|
+
* @param guards - Guard classes or injection tokens to apply
|
|
19
|
+
* @returns A class or method decorator compatible with legacy decorator API
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // Apply to a controller
|
|
24
|
+
* @Controller()
|
|
25
|
+
* @UseGuards(AuthGuard, RoleGuard)
|
|
26
|
+
* export class UserController { }
|
|
27
|
+
*
|
|
28
|
+
* // Apply to a specific endpoint
|
|
29
|
+
* @Controller()
|
|
30
|
+
* export class UserController {
|
|
31
|
+
* @Endpoint(getUserEndpoint)
|
|
32
|
+
* @UseGuards(AuthGuard)
|
|
33
|
+
* async getUser() { }
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function UseGuards(
|
|
38
|
+
...guards: (
|
|
39
|
+
| ClassTypeWithInstance<CanActivate>
|
|
40
|
+
| InjectionToken<CanActivate, undefined>
|
|
41
|
+
)[]
|
|
42
|
+
) {
|
|
43
|
+
// Create the decorator function
|
|
44
|
+
// Note: TypeScript's legacy decorator system has strict type checking for decorators
|
|
45
|
+
// We use a flexible implementation that works for both class and method decorators
|
|
46
|
+
function decoratorImpl(
|
|
47
|
+
target: ClassType | Function,
|
|
48
|
+
propertyKey?: string | symbol,
|
|
49
|
+
descriptor?: PropertyDescriptor,
|
|
50
|
+
): any {
|
|
51
|
+
// Determine if this is a class or method decorator
|
|
52
|
+
if (propertyKey !== undefined && descriptor !== undefined) {
|
|
53
|
+
// Method decorator
|
|
54
|
+
const context = createMethodContext(
|
|
55
|
+
target as Function,
|
|
56
|
+
propertyKey,
|
|
57
|
+
descriptor,
|
|
58
|
+
)
|
|
59
|
+
const originalDecorator = OriginalUseGuards(...guards)
|
|
60
|
+
const result = originalDecorator(descriptor.value, context)
|
|
61
|
+
if (result !== descriptor.value) {
|
|
62
|
+
descriptor.value = result
|
|
63
|
+
}
|
|
64
|
+
return descriptor
|
|
65
|
+
} else {
|
|
66
|
+
// Class decorator
|
|
67
|
+
const context = createClassContext(target as ClassType)
|
|
68
|
+
const originalDecorator = OriginalUseGuards(...guards)
|
|
69
|
+
return originalDecorator(target as ClassType, context)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Return with 'any' type to work around TypeScript's strict decorator checking
|
|
74
|
+
// TypeScript's legacy decorator system cannot properly type-check decorators
|
|
75
|
+
// that work as both class and method decorators. The runtime behavior is correct.
|
|
76
|
+
// When used as a class decorator, it returns the class (preserving type at runtime)
|
|
77
|
+
// When used as a method decorator, it returns the PropertyDescriptor
|
|
78
|
+
// @ts-ignore - TypeScript limitation with dual-purpose legacy decorators
|
|
79
|
+
return decoratorImpl as any
|
|
80
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Legacy-compatible decorators for projects that cannot use Stage 3 decorators.
|
|
3
|
+
*
|
|
4
|
+
* These decorators use the TypeScript experimental decorator API and convert
|
|
5
|
+
* the arguments to Stage 3 format internally.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { Module, Controller, Endpoint } from '@navios/core/legacy-compat'
|
|
10
|
+
*
|
|
11
|
+
* @Module({
|
|
12
|
+
* controllers: [UserController],
|
|
13
|
+
* })
|
|
14
|
+
* export class AppModule {}
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Re-export types
|
|
19
|
+
export type {
|
|
20
|
+
ModuleOptions,
|
|
21
|
+
ControllerOptions,
|
|
22
|
+
EndpointParams,
|
|
23
|
+
EndpointResult,
|
|
24
|
+
MultipartParams,
|
|
25
|
+
MultipartResult,
|
|
26
|
+
StreamParams,
|
|
27
|
+
} from '../decorators/index.mjs'
|
|
28
|
+
|
|
29
|
+
// Export legacy-compatible decorators
|
|
30
|
+
export {
|
|
31
|
+
Module,
|
|
32
|
+
Controller,
|
|
33
|
+
Endpoint,
|
|
34
|
+
UseGuards,
|
|
35
|
+
Header,
|
|
36
|
+
HttpCode,
|
|
37
|
+
Multipart,
|
|
38
|
+
Stream,
|
|
39
|
+
} from './decorators/index.mjs'
|
|
40
|
+
|
|
@@ -7,6 +7,7 @@ import { Injectable } from '@navios/di'
|
|
|
7
7
|
import type { LogLevel } from './log-levels.mjs'
|
|
8
8
|
import type { LoggerService } from './logger-service.interface.mjs'
|
|
9
9
|
|
|
10
|
+
import { getRequestId } from '../stores/request-id.store.mjs'
|
|
10
11
|
import { LoggerOutput } from './logger.tokens.mjs'
|
|
11
12
|
import {
|
|
12
13
|
clc,
|
|
@@ -312,6 +313,17 @@ export class ConsoleLogger implements LoggerService {
|
|
|
312
313
|
return isLogLevelEnabled(level, logLevels)
|
|
313
314
|
}
|
|
314
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Gets the current request ID from the AsyncLocalStorage store.
|
|
318
|
+
* Only returns a value if the requestId option is enabled.
|
|
319
|
+
*/
|
|
320
|
+
protected getCurrentRequestId(): string | undefined {
|
|
321
|
+
if (!this.options.requestId) {
|
|
322
|
+
return undefined
|
|
323
|
+
}
|
|
324
|
+
return getRequestId()
|
|
325
|
+
}
|
|
326
|
+
|
|
315
327
|
protected getTimestamp(): string {
|
|
316
328
|
return dateTimeFormatter.format(Date.now())
|
|
317
329
|
}
|
|
@@ -324,6 +336,7 @@ export class ConsoleLogger implements LoggerService {
|
|
|
324
336
|
writeStreamType?: 'stdout' | 'stderr',
|
|
325
337
|
errorStack?: unknown,
|
|
326
338
|
) {
|
|
339
|
+
const resolvedRequestId = requestId ?? this.getCurrentRequestId()
|
|
327
340
|
messages.forEach((message) => {
|
|
328
341
|
if (this.options.json) {
|
|
329
342
|
this.printAsJson(message, {
|
|
@@ -331,7 +344,7 @@ export class ConsoleLogger implements LoggerService {
|
|
|
331
344
|
logLevel,
|
|
332
345
|
writeStreamType,
|
|
333
346
|
errorStack,
|
|
334
|
-
requestId,
|
|
347
|
+
requestId: resolvedRequestId,
|
|
335
348
|
})
|
|
336
349
|
return
|
|
337
350
|
}
|
|
@@ -346,7 +359,7 @@ export class ConsoleLogger implements LoggerService {
|
|
|
346
359
|
formattedLogLevel,
|
|
347
360
|
contextMessage,
|
|
348
361
|
timestampDiff,
|
|
349
|
-
|
|
362
|
+
resolvedRequestId,
|
|
350
363
|
)
|
|
351
364
|
|
|
352
365
|
process[writeStreamType ?? 'stdout'].write(formattedMessage)
|