@nestjs/common 12.0.0-alpha.4 → 12.0.0-alpha.6
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 +25 -45
- package/decorators/http/create-route-param-metadata.decorator.js +5 -10
- package/decorators/http/index.d.ts +1 -0
- package/decorators/http/index.js +1 -0
- package/decorators/http/request-mapping.decorator.d.ts +11 -0
- package/decorators/http/request-mapping.decorator.js +11 -0
- package/decorators/http/route-params.decorator.d.ts +28 -2
- package/decorators/http/route-params.decorator.js +56 -32
- package/decorators/http/sse-signal.decorator.d.ts +47 -0
- package/decorators/http/sse-signal.decorator.js +52 -0
- package/enums/request-method.enum.d.ts +2 -1
- package/enums/request-method.enum.js +1 -0
- package/exceptions/misdirected.exception.d.ts +1 -1
- package/exceptions/misdirected.exception.js +1 -1
- package/exceptions/not-acceptable.exception.d.ts +2 -2
- package/exceptions/not-acceptable.exception.js +2 -2
- package/index.d.ts +1 -1
- package/interfaces/http/http-server.interface.d.ts +3 -0
- package/interfaces/http/message-event.interface.d.ts +2 -1
- package/interfaces/index.d.ts +2 -0
- package/interfaces/index.js +2 -0
- package/interfaces/microservices/transport-server.interface.d.ts +18 -0
- package/interfaces/microservices/transport-server.interface.js +1 -0
- package/interfaces/nest-application-options.interface.d.ts +15 -0
- package/interfaces/nest-microservice.interface.d.ts +7 -0
- package/interfaces/router-options.interface.d.ts +28 -0
- package/interfaces/router-options.interface.js +1 -0
- package/internal.d.ts +1 -0
- package/internal.js +1 -0
- package/package.json +4 -3
- package/pipes/file/file-type.validator.d.ts +8 -0
- package/pipes/file/file-type.validator.js +17 -5
- package/pipes/parse-array.pipe.d.ts +5 -3
- package/pipes/parse-date.pipe.d.ts +6 -0
- package/pipes/parse-date.pipe.js +3 -0
- package/pipes/parse-enum.pipe.js +7 -1
- package/pipes/parse-float.pipe.js +14 -3
- package/pipes/standard-schema-validation.pipe.d.ts +5 -0
- package/pipes/standard-schema-validation.pipe.js +13 -1
- package/pipes/validation.pipe.js +10 -5
- package/serializer/standard-schema-serializer.interceptor.js +2 -2
- package/services/console-logger.service.js +7 -1
- package/utils/http-error-by-code.util.d.ts +1 -1
- package/utils/http-error-by-code.util.js +3 -1
- package/utils/load-package.util.d.ts +1 -1
- package/utils/load-package.util.js +7 -1
- package/utils/parameter-decorator-options.util.d.ts +13 -0
- package/utils/parameter-decorator-options.util.js +22 -0
package/Readme.md
CHANGED
|
@@ -59,11 +59,11 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
|
|
59
59
|
|
|
60
60
|
<table style="text-align:center;">
|
|
61
61
|
<tr>
|
|
62
|
-
<td><a href="https://trilon.io" target="_blank"><img src="https://nestjs.com/img/trilon.svg" width="200" valign="middle" /></a></td>
|
|
63
|
-
<td><a href="https://microsoft.com/" target="_blank"><img src="https://nestjs.com/img/
|
|
64
|
-
<td><a href="https://mojam.co" target="_blank"><img src="https://
|
|
62
|
+
<td><a href="https://trilon.io" target="_blank"><img src="https://nestjs.com/img/github/trilon-logo.svg" width="200" valign="middle" /></a></td>
|
|
63
|
+
<td><a href="https://microsoft.com/" target="_blank"><img src="https://nestjs.com/img/github/microsoft-logo.png" width="180" valign="middle" /></a></td>
|
|
64
|
+
<td><a href="https://mojam.co" target="_blank"><img src="https://images.opencollective.com/mojamco/981e9de/logo/256.png?height=256" width="80" valign="middle" /></a></td>
|
|
65
65
|
<td><a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td>
|
|
66
|
-
<td><a href="https://serpapi.com/" target="_blank"><img src="https://nestjs.com/img/
|
|
66
|
+
<td><a href="https://serpapi.com/" target="_blank"><img src="https://nestjs.com/img/github/serpapi-logo.png" width="150" valign="middle" /></a></td>
|
|
67
67
|
</tr>
|
|
68
68
|
</table>
|
|
69
69
|
|
|
@@ -71,15 +71,15 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
|
|
71
71
|
|
|
72
72
|
<table style="text-align:center;">
|
|
73
73
|
<tr>
|
|
74
|
-
<td><a href="https://www.redhat.com" target="_blank"><img src="https://nestjs.com/img/
|
|
75
|
-
<td><a href="https://github.com/Sanofi-IADC" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/sanofi.png" width="
|
|
76
|
-
<td><a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/
|
|
77
|
-
<td><a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/
|
|
78
|
-
<td><a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/
|
|
74
|
+
<td><a href="https://www.redhat.com" target="_blank"><img src="https://nestjs.com/img/github/red-hat-logo.svg" width="150" valign="middle" /></a></td>
|
|
75
|
+
<td><a href="https://github.com/Sanofi-IADC" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/sanofi.png" width="120" valign="middle" /></a></td>
|
|
76
|
+
<td><a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/github/nx-logo.png" height="45" valign="middle" /></a></td>
|
|
77
|
+
<td><a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/github/intrinisic-logo.png" width="150" valign="middle" /></a></td>
|
|
78
|
+
<td><a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/github/jetbrains-logo.svg" width="70" valign="middle" /></a></td>
|
|
79
79
|
</tr>
|
|
80
80
|
<tr>
|
|
81
|
-
<td><a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/
|
|
82
|
-
<td><a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://
|
|
81
|
+
<td><a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/github/snyk-logo-black.png" width="125" valign="middle" /></a></td>
|
|
82
|
+
<td align="center"><a href="https://www.movavi.com/imovie-for-windows.html" target="_blank"><img src="https://images.opencollective.com/movavi/1fb15e5/avatar/256.png?height=256" width="60" valign="middle" /></a></td>
|
|
83
83
|
</tr>
|
|
84
84
|
</table>
|
|
85
85
|
|
|
@@ -87,15 +87,15 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
|
|
87
87
|
|
|
88
88
|
<table style="text-align:center;">
|
|
89
89
|
<tr>
|
|
90
|
-
<td><a href="https://www.mercedes-benz.com/" target="_blank"><img src="https://nestjs.com/img/
|
|
91
|
-
<td><a href="https://
|
|
92
|
-
<td><a href="https://
|
|
93
|
-
<td align="center" valign="middle"><a href="https://
|
|
94
|
-
<td align="center" valign="middle"><a href="https://
|
|
95
|
-
<td align="center" valign="middle"><a href="https://crawljobs.com" target="_blank"><img src="https://nestjs.com/img/logos/crawljobs-logo.svg" width="130" valign="middle" /></a></td>
|
|
90
|
+
<td><a href="https://www.mercedes-benz.com/" target="_blank"><img src="https://nestjs.com/img/github/mercedes-logo.png" width="100" valign="middle" /></a></td>
|
|
91
|
+
<td><a href="https://handsontable.com/docs/react-data-grid/?utm_source=NestJS_GH&utm_medium=sponsorship&utm_campaign=library_sponsorship_2024" target="_blank"><img src="https://nestjs.com/img/github/handsontable-dark-logo.svg#2" width="150" valign="middle" /></a></td>
|
|
92
|
+
<td align="center" valign="middle"><a href="https://www.itflashcards.com/" target="_blank"><img src="https://nestjs.com/img/github/it_flashcards-logo.png" width="170" valign="middle" /></a></td>
|
|
93
|
+
<td align="center" valign="middle"><a href="https://arcjet.com/?ref=nestjs" target="_blank"><img src="https://nestjs.com/img/github/arcjet-logo.svg" width="170" valign="middle" /></a></td>
|
|
94
|
+
<td align="center" valign="middle"><a href="https://pandektes.com" target="_blank"><img src="https://nestjs.com/img/github/pandektes-logo.png" width="65" valign="middle" /></a></td>
|
|
96
95
|
</tr><tr>
|
|
97
|
-
<td align="center" valign="middle"><a href="https://
|
|
98
|
-
<td align="center" valign="middle"><a href="https://
|
|
96
|
+
<td align="center" valign="middle"><a href="https://www.fintechcrafts.com/" target="_blank"><img src="https://opencollective-production.s3.us-west-1.amazonaws.com/account-avatar/935813df-48a9-4b41-b923-7d70b5621c6b/2026-05-06%2010%2021%2033.png" width="65" valign="middle" /></a></td>
|
|
97
|
+
<td align="center" valign="middle"><a href="https://talordata.com/?campaignid=Ya5Xpw2gmhyee6Tg&utm_source=nestjs&utm_term=nestjs" target="_blank"><img src="https://images.opencollective.com/elowen/9ccac7f/avatar/512.png" width="65" valign="middle" /></a></td>
|
|
98
|
+
<td align="center" valign="middle"><a href="https://memory2.co/" target="_blank"><img src="https://images.opencollective.com/memory-squared/bbe37f5/avatar/256.png?height=50" width="65" valign="middle" /></a></td>
|
|
99
99
|
</tr>
|
|
100
100
|
</table>
|
|
101
101
|
|
|
@@ -103,32 +103,12 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
|
|
103
103
|
|
|
104
104
|
<table>
|
|
105
105
|
<tr>
|
|
106
|
-
<td align="center" valign="middle"><a href="https://
|
|
107
|
-
<td align="center" valign="middle"><a href="https://
|
|
108
|
-
<td align="center" valign="middle"><a href="https://
|
|
109
|
-
<td align="center" valign="middle"><a href="https://
|
|
110
|
-
<td align="center" valign="middle"><a href="https://
|
|
111
|
-
<td align="center" valign="middle"><a href="https://
|
|
112
|
-
</tr>
|
|
113
|
-
<tr>
|
|
114
|
-
<td align="center" valign="middle"><a href="https://vpn-review.com/vpn-for-torrenting" target="_blank"><img src="https://nestjs.com/img/logos/vpn-review-logo.png" width="85" valign="middle" /></a></td>
|
|
115
|
-
<td align="center" valign="middle"><a href="https://lambda-it.ch/" target="_blank"><img src="https://nestjs.com/img/logos/lambda-it-logo.svg" width="115" valign="middle" /></a></td>
|
|
116
|
-
<td align="center" valign="middle"><a href="https://rocketech.it/cases/?utm_source=google&utm_medium=badge&utm_campaign=nestjs" target="_blank"><img src="https://nestjs.com/img/logos/rocketech-logo.svg" width="110" valign="middle" /></a></td>
|
|
117
|
-
<td align="center" valign="middle"><a href="https://www.anonymistic.com/" target="_blank"><img src="https://nestjs.com/img/logos/anonymistic-logo.png" width="125" valign="middle" /></a></td>
|
|
118
|
-
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/logos/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
|
119
|
-
<td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/logos/triplecore-logo.svg" width="50" valign="middle" /></a></td>
|
|
120
|
-
</tr>
|
|
121
|
-
<tr>
|
|
122
|
-
<td align="center" valign="middle"><a href="https://polygon-software.ch/" target="_blank"><img src="https://nestjs.com/img/logos/polygon-logo.svg" width="120" valign="middle" /></a></td>
|
|
123
|
-
<td align="center" valign="middle"><a href="https://boringowl.io/" target="_blank"><img src="https://nestjs.com/img/logos/boringowl-logo.svg" width="120" valign="middle" /></a></td>
|
|
124
|
-
<td align="center" valign="middle"><a href="https://nordbot.app/" target="_blank"><img src="https://nestjs.com/img/logos/nordbot-logo.png" width="120" valign="middle" /></a></td>
|
|
125
|
-
<td align="center" valign="middle"><a href="https://doppio.sh/" target="_blank"><img src="https://nestjs.com/img/logos/dopiosh-logo.png" width="50" valign="middle" /></a></td>
|
|
126
|
-
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/logos/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
|
127
|
-
<td align="center" valign="middle"><a href="https://www.tripoffice.com/" target="_blank"><img src="https://nestjs.com/img/logos/tripoffice-logo.png" width="140" valign="middle" /></a></td>
|
|
128
|
-
</tr>
|
|
129
|
-
<tr>
|
|
130
|
-
<td align="center" valign="middle"><a href="https://solcellsforetag.se/" target="_blank"><img src="https://nestjs.com/img/logos/solcellsforetag-logo.svg" width="140" valign="middle" /></a></td>
|
|
131
|
-
<td align="center" valign="middle"><a href="https://www.route4me.com/" target="_blank"><img src="https://nestjs.com/img/logos/route4me-logo.svg" width="100" valign="middle" /></a></td>
|
|
106
|
+
<td align="center" valign="middle"><a href="https://mantro.net/" target="_blank"><img src="https://nestjs.com/img/github/mantro-logo.svg" width="95" valign="middle" /></a></td>
|
|
107
|
+
<td align="center" valign="middle"><a href="https://triplebyte.com/" target="_blank"><img src="https://nestjs.com/img/github/triplebyte-logo.png" width="107" valign="middle" /></a></td>
|
|
108
|
+
<td align="center" valign="middle"><a href="https://nearpod.com/" target="_blank"><img src="https://nestjs.com/img/github/nearpod-logo.svg" width="100" valign="middle" /></a></td>
|
|
109
|
+
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/github/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
|
110
|
+
<td align="center" valign="middle"><a href="https://triplecore.io" target="_blank"><img src="https://nestjs.com/img/github/triplecore-logo.svg" width="50" valign="middle" /></a>
|
|
111
|
+
<td align="center" valign="middle"><a href="https://www.hingehealth.com/" target="_blank"><img src="https://nestjs.com/img/github/hinge-health-logo.svg" width="100" valign="middle" /></a></td>
|
|
132
112
|
</tr>
|
|
133
113
|
</table>
|
|
134
114
|
|
|
@@ -2,6 +2,7 @@ import { uid } from 'uid';
|
|
|
2
2
|
import { ROUTE_ARGS_METADATA } from '../../constants.js';
|
|
3
3
|
import { assignCustomParameterMetadata } from '../../utils/assign-custom-metadata.util.js';
|
|
4
4
|
import { isFunction, isNil } from '../../utils/shared.utils.js';
|
|
5
|
+
import { isParameterDecoratorOptions } from '../../utils/parameter-decorator-options.util.js';
|
|
5
6
|
/**
|
|
6
7
|
* Defines route param decorator
|
|
7
8
|
*
|
|
@@ -20,18 +21,11 @@ export function createParamDecorator(factory, enhancers = []) {
|
|
|
20
21
|
pipe.prototype &&
|
|
21
22
|
isFunction(pipe.prototype.transform)) ||
|
|
22
23
|
isFunction(pipe.transform));
|
|
23
|
-
const isParameterDecoratorOptions = (value) => value &&
|
|
24
|
-
typeof value === 'object' &&
|
|
25
|
-
!isPipe(value) &&
|
|
26
|
-
('schema' in value || 'pipes' in value);
|
|
27
24
|
const hasParamData = isNil(data) || !isPipe(data);
|
|
28
25
|
const paramData = hasParamData ? data : undefined;
|
|
29
26
|
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
|
30
|
-
// Check if data itself is an options object (when used as the first
|
|
31
|
-
const isDataOptions = hasParamData &&
|
|
32
|
-
!isNil(data) &&
|
|
33
|
-
paramPipes.length === 0 &&
|
|
34
|
-
isParameterDecoratorOptions(data);
|
|
27
|
+
// Check if data itself is an options object (when used as the first argument)
|
|
28
|
+
const isDataOptions = hasParamData && !isNil(data) && isParameterDecoratorOptions(data);
|
|
35
29
|
// Check if the last pipe argument is actually an options object
|
|
36
30
|
const lastPipeArg = paramPipes.length > 0 ? paramPipes[paramPipes.length - 1] : undefined;
|
|
37
31
|
const isLastPipeOptions = !isDataOptions && isParameterDecoratorOptions(lastPipeArg);
|
|
@@ -42,7 +36,8 @@ export function createParamDecorator(factory, enhancers = []) {
|
|
|
42
36
|
const opts = data;
|
|
43
37
|
finalData = undefined;
|
|
44
38
|
finalSchema = opts.schema;
|
|
45
|
-
|
|
39
|
+
// Merge positional pipes passed after the options object
|
|
40
|
+
finalPipes = [...(opts.pipes ?? []), ...paramPipes];
|
|
46
41
|
}
|
|
47
42
|
else if (isLastPipeOptions) {
|
|
48
43
|
const opts = lastPipeArg;
|
package/decorators/http/index.js
CHANGED
|
@@ -76,6 +76,17 @@ export declare const All: (path?: string | string[]) => MethodDecorator;
|
|
|
76
76
|
* @publicApi
|
|
77
77
|
*/
|
|
78
78
|
export declare const Search: (path?: string | string[]) => MethodDecorator;
|
|
79
|
+
/**
|
|
80
|
+
* Route handler (method) Decorator. Routes HTTP QUERY requests to the specified path.
|
|
81
|
+
*
|
|
82
|
+
* **Note**: this is named `QueryMethod` (rather than `Query`) to avoid a name clash
|
|
83
|
+
* with the `@Query()` parameter decorator used to extract query-string params.
|
|
84
|
+
*
|
|
85
|
+
* @see [Routing](https://docs.nestjs.com/controllers#routing)
|
|
86
|
+
*
|
|
87
|
+
* @publicApi
|
|
88
|
+
*/
|
|
89
|
+
export declare const QueryMethod: (path?: string | string[]) => MethodDecorator;
|
|
79
90
|
/**
|
|
80
91
|
* Route handler (method) Decorator. Routes Webdav PROPFIND requests to the specified path.
|
|
81
92
|
*
|
|
@@ -92,6 +92,17 @@ export const All = createMappingDecorator(RequestMethod.ALL);
|
|
|
92
92
|
* @publicApi
|
|
93
93
|
*/
|
|
94
94
|
export const Search = createMappingDecorator(RequestMethod.SEARCH);
|
|
95
|
+
/**
|
|
96
|
+
* Route handler (method) Decorator. Routes HTTP QUERY requests to the specified path.
|
|
97
|
+
*
|
|
98
|
+
* **Note**: this is named `QueryMethod` (rather than `Query`) to avoid a name clash
|
|
99
|
+
* with the `@Query()` parameter decorator used to extract query-string params.
|
|
100
|
+
*
|
|
101
|
+
* @see [Routing](https://docs.nestjs.com/controllers#routing)
|
|
102
|
+
*
|
|
103
|
+
* @publicApi
|
|
104
|
+
*/
|
|
105
|
+
export const QueryMethod = createMappingDecorator(RequestMethod.QUERY);
|
|
95
106
|
/**
|
|
96
107
|
* Route handler (method) Decorator. Routes Webdav PROPFIND requests to the specified path.
|
|
97
108
|
*
|
|
@@ -34,9 +34,9 @@ export interface RouteParamMetadata {
|
|
|
34
34
|
index: number;
|
|
35
35
|
data?: ParamData;
|
|
36
36
|
}
|
|
37
|
-
export declare function assignMetadata<TParamtype = any, TArgs = any>(args: TArgs, paramtype: TParamtype, index: number, options
|
|
37
|
+
export declare function assignMetadata<TParamtype = any, TArgs = any>(args: TArgs, paramtype: TParamtype, index: number, options?: ({
|
|
38
38
|
data?: ParamData;
|
|
39
|
-
} & ParameterDecoratorOptions): TArgs & {
|
|
39
|
+
} & ParameterDecoratorOptions) | ParamData, ...legacyPipes: (Type<PipeTransform> | PipeTransform)[]): TArgs & {
|
|
40
40
|
[x: string]: {
|
|
41
41
|
schema?: StandardSchemaV1<unknown, unknown> | undefined;
|
|
42
42
|
index: number;
|
|
@@ -591,5 +591,31 @@ export declare function HostParam(): ParameterDecorator;
|
|
|
591
591
|
* @publicApi
|
|
592
592
|
*/
|
|
593
593
|
export declare function HostParam(property: string): ParameterDecorator;
|
|
594
|
+
/**
|
|
595
|
+
* Route handler parameter decorator. Extracts the `Request`
|
|
596
|
+
* object from the underlying platform and populates the decorated
|
|
597
|
+
* parameter with the value of `Request`.
|
|
598
|
+
*
|
|
599
|
+
* Alias for @Request().
|
|
600
|
+
*
|
|
601
|
+
* Example: `logout(@Req() req)`
|
|
602
|
+
*
|
|
603
|
+
* @see [Request object](https://docs.nestjs.com/controllers#request-object)
|
|
604
|
+
*
|
|
605
|
+
* @publicApi
|
|
606
|
+
*/
|
|
594
607
|
export declare const Req: () => ParameterDecorator;
|
|
608
|
+
/**
|
|
609
|
+
* Route handler parameter decorator. Extracts the `Response`
|
|
610
|
+
* object from the underlying platform and populates the decorated
|
|
611
|
+
* parameter with the value of `Response`.
|
|
612
|
+
*
|
|
613
|
+
* Alias for @Response().
|
|
614
|
+
*
|
|
615
|
+
* Example: `logout(@Res() res)`
|
|
616
|
+
*
|
|
617
|
+
* @see [Response object](https://docs.nestjs.com/controllers#response-object)
|
|
618
|
+
*
|
|
619
|
+
* @publicApi
|
|
620
|
+
*/
|
|
595
621
|
export declare const Res: (options?: ResponseDecoratorOptions) => ParameterDecorator;
|
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
import { RESPONSE_PASSTHROUGH_METADATA, ROUTE_ARGS_METADATA, } from '../../constants.js';
|
|
2
2
|
import { RouteParamtypes } from '../../enums/route-paramtypes.enum.js';
|
|
3
3
|
import { isNil, isString } from '../../utils/shared.utils.js';
|
|
4
|
-
|
|
4
|
+
import { isParameterDecoratorOptions } from '../../utils/parameter-decorator-options.util.js';
|
|
5
|
+
export function assignMetadata(args, paramtype, index, options, ...legacyPipes) {
|
|
6
|
+
// Callers built against the pre-v12 signature
|
|
7
|
+
// `assignMetadata(args, paramtype, index, data?, ...pipes)` pass the raw
|
|
8
|
+
// `data` value (and pipes positionally); detect that shape and normalize it
|
|
9
|
+
// instead of silently misreading `data` as the options object.
|
|
10
|
+
const isOptionsObject = options !== null &&
|
|
11
|
+
typeof options === 'object' &&
|
|
12
|
+
(isParameterDecoratorOptions(options) || 'data' in options) &&
|
|
13
|
+
!('transform' in options) &&
|
|
14
|
+
legacyPipes.length === 0;
|
|
15
|
+
const normalizedOptions = isOptionsObject
|
|
16
|
+
? options
|
|
17
|
+
: { data: options, pipes: legacyPipes };
|
|
5
18
|
return {
|
|
6
19
|
...args,
|
|
7
20
|
[`${paramtype}:${index}`]: {
|
|
8
21
|
index,
|
|
9
|
-
data:
|
|
10
|
-
pipes:
|
|
11
|
-
...(
|
|
22
|
+
data: normalizedOptions.data,
|
|
23
|
+
pipes: normalizedOptions.pipes ?? [],
|
|
24
|
+
...(normalizedOptions.schema !== undefined && {
|
|
25
|
+
schema: normalizedOptions.schema,
|
|
26
|
+
}),
|
|
12
27
|
},
|
|
13
28
|
};
|
|
14
29
|
}
|
|
@@ -166,21 +181,16 @@ export const Headers = createRouteParamDecorator(RouteParamtypes.HEADERS);
|
|
|
166
181
|
* @publicApi
|
|
167
182
|
*/
|
|
168
183
|
export function Query(property, optionsOrPipe, ...pipes) {
|
|
169
|
-
const isPropertyOptions = property
|
|
170
|
-
typeof property === 'object' &&
|
|
171
|
-
!('transform' in property) &&
|
|
172
|
-
('schema' in property || 'pipes' in property);
|
|
184
|
+
const isPropertyOptions = isParameterDecoratorOptions(property);
|
|
173
185
|
if (isPropertyOptions) {
|
|
174
186
|
return createPipesRouteParamDecorator(RouteParamtypes.QUERY)({
|
|
175
187
|
pipes: property.pipes,
|
|
176
188
|
schema: property.schema,
|
|
177
189
|
});
|
|
178
190
|
}
|
|
179
|
-
const isOptions = optionsOrPipe
|
|
180
|
-
typeof optionsOrPipe === 'object' &&
|
|
181
|
-
('schema' in optionsOrPipe || 'pipes' in optionsOrPipe);
|
|
191
|
+
const isOptions = isParameterDecoratorOptions(optionsOrPipe);
|
|
182
192
|
const actualPipes = isOptions
|
|
183
|
-
? optionsOrPipe.pipes
|
|
193
|
+
? [...(optionsOrPipe.pipes ?? []), ...pipes]
|
|
184
194
|
: [optionsOrPipe, ...pipes].filter(Boolean);
|
|
185
195
|
return createPipesRouteParamDecorator(RouteParamtypes.QUERY)({
|
|
186
196
|
data: property,
|
|
@@ -210,21 +220,16 @@ export function Query(property, optionsOrPipe, ...pipes) {
|
|
|
210
220
|
* @publicApi
|
|
211
221
|
*/
|
|
212
222
|
export function Body(property, optionsOrPipe, ...pipes) {
|
|
213
|
-
const isPropertyOptions = property
|
|
214
|
-
typeof property === 'object' &&
|
|
215
|
-
!('transform' in property) &&
|
|
216
|
-
('schema' in property || 'pipes' in property);
|
|
223
|
+
const isPropertyOptions = isParameterDecoratorOptions(property);
|
|
217
224
|
if (isPropertyOptions) {
|
|
218
225
|
return createPipesRouteParamDecorator(RouteParamtypes.BODY)({
|
|
219
226
|
pipes: property.pipes,
|
|
220
227
|
schema: property.schema,
|
|
221
228
|
});
|
|
222
229
|
}
|
|
223
|
-
const isOptions = optionsOrPipe
|
|
224
|
-
typeof optionsOrPipe === 'object' &&
|
|
225
|
-
('schema' in optionsOrPipe || 'pipes' in optionsOrPipe);
|
|
230
|
+
const isOptions = isParameterDecoratorOptions(optionsOrPipe);
|
|
226
231
|
const actualPipes = isOptions
|
|
227
|
-
? optionsOrPipe.pipes
|
|
232
|
+
? [...(optionsOrPipe.pipes ?? []), ...pipes]
|
|
228
233
|
: [optionsOrPipe, ...pipes].filter(Boolean);
|
|
229
234
|
return createPipesRouteParamDecorator(RouteParamtypes.BODY)({
|
|
230
235
|
data: property,
|
|
@@ -253,11 +258,9 @@ export function Body(property, optionsOrPipe, ...pipes) {
|
|
|
253
258
|
* @publicApi
|
|
254
259
|
*/
|
|
255
260
|
export function RawBody(optionsOrPipe, ...pipes) {
|
|
256
|
-
const isOptions = optionsOrPipe
|
|
257
|
-
typeof optionsOrPipe === 'object' &&
|
|
258
|
-
('schema' in optionsOrPipe || 'pipes' in optionsOrPipe);
|
|
261
|
+
const isOptions = isParameterDecoratorOptions(optionsOrPipe);
|
|
259
262
|
const actualPipes = isOptions
|
|
260
|
-
? optionsOrPipe.pipes
|
|
263
|
+
? [...(optionsOrPipe.pipes ?? []), ...pipes]
|
|
261
264
|
: [optionsOrPipe, ...pipes].filter(Boolean);
|
|
262
265
|
return createPipesRouteParamDecorator(RouteParamtypes.RAW_BODY)({
|
|
263
266
|
pipes: actualPipes,
|
|
@@ -290,21 +293,16 @@ export function RawBody(optionsOrPipe, ...pipes) {
|
|
|
290
293
|
* @publicApi
|
|
291
294
|
*/
|
|
292
295
|
export function Param(property, optionsOrPipe, ...pipes) {
|
|
293
|
-
const isPropertyOptions = property
|
|
294
|
-
typeof property === 'object' &&
|
|
295
|
-
!('transform' in property) &&
|
|
296
|
-
('schema' in property || 'pipes' in property);
|
|
296
|
+
const isPropertyOptions = isParameterDecoratorOptions(property);
|
|
297
297
|
if (isPropertyOptions) {
|
|
298
298
|
return createPipesRouteParamDecorator(RouteParamtypes.PARAM)({
|
|
299
299
|
pipes: property.pipes,
|
|
300
300
|
schema: property.schema,
|
|
301
301
|
});
|
|
302
302
|
}
|
|
303
|
-
const isOptions = optionsOrPipe
|
|
304
|
-
typeof optionsOrPipe === 'object' &&
|
|
305
|
-
('schema' in optionsOrPipe || 'pipes' in optionsOrPipe);
|
|
303
|
+
const isOptions = isParameterDecoratorOptions(optionsOrPipe);
|
|
306
304
|
const actualPipes = isOptions
|
|
307
|
-
? optionsOrPipe.pipes
|
|
305
|
+
? [...(optionsOrPipe.pipes ?? []), ...pipes]
|
|
308
306
|
: [optionsOrPipe, ...pipes].filter(Boolean);
|
|
309
307
|
return createPipesRouteParamDecorator(RouteParamtypes.PARAM)({
|
|
310
308
|
data: property,
|
|
@@ -336,5 +334,31 @@ export function Param(property, optionsOrPipe, ...pipes) {
|
|
|
336
334
|
export function HostParam(property) {
|
|
337
335
|
return createRouteParamDecorator(RouteParamtypes.HOST)(property);
|
|
338
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* Route handler parameter decorator. Extracts the `Request`
|
|
339
|
+
* object from the underlying platform and populates the decorated
|
|
340
|
+
* parameter with the value of `Request`.
|
|
341
|
+
*
|
|
342
|
+
* Alias for @Request().
|
|
343
|
+
*
|
|
344
|
+
* Example: `logout(@Req() req)`
|
|
345
|
+
*
|
|
346
|
+
* @see [Request object](https://docs.nestjs.com/controllers#request-object)
|
|
347
|
+
*
|
|
348
|
+
* @publicApi
|
|
349
|
+
*/
|
|
339
350
|
export const Req = Request;
|
|
351
|
+
/**
|
|
352
|
+
* Route handler parameter decorator. Extracts the `Response`
|
|
353
|
+
* object from the underlying platform and populates the decorated
|
|
354
|
+
* parameter with the value of `Response`.
|
|
355
|
+
*
|
|
356
|
+
* Alias for @Response().
|
|
357
|
+
*
|
|
358
|
+
* Example: `logout(@Res() res)`
|
|
359
|
+
*
|
|
360
|
+
* @see [Response object](https://docs.nestjs.com/controllers#response-object)
|
|
361
|
+
*
|
|
362
|
+
* @publicApi
|
|
363
|
+
*/
|
|
340
364
|
export const Res = Response;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Symbol used to carry the per-request SSE `AbortController` on the request object.
|
|
3
|
+
*
|
|
4
|
+
* The controller is attached by the framework before the route handler runs and is
|
|
5
|
+
* aborted when the client disconnects. Its signal is exposed to route handlers
|
|
6
|
+
* through the `@SseSignal()` parameter decorator.
|
|
7
|
+
*
|
|
8
|
+
* @publicApi
|
|
9
|
+
*/
|
|
10
|
+
export declare const SSE_ABORT_CONTROLLER: unique symbol;
|
|
11
|
+
/**
|
|
12
|
+
* Route handler parameter decorator that injects the `AbortSignal` associated
|
|
13
|
+
* with a Server-Sent-Events (SSE) request.
|
|
14
|
+
*
|
|
15
|
+
* The signal represents the lifetime of the SSE response: it is aborted once the
|
|
16
|
+
* stream terminates, whether because the client disconnected, the `Observable`
|
|
17
|
+
* completed, or it errored. Tying setup-phase resources to the signal therefore
|
|
18
|
+
* releases them exactly once on every exit path, including resources allocated
|
|
19
|
+
* before the returned `Observable` exists — which would otherwise leak, since the
|
|
20
|
+
* producer is never subscribed once the client has disconnected.
|
|
21
|
+
*
|
|
22
|
+
* Because the signal also aborts on normal completion, `signal.aborted` is only
|
|
23
|
+
* meaningful as a "did the client go away?" check *during setup*, before the
|
|
24
|
+
* `Observable` is returned; at that point the stream cannot have completed yet.
|
|
25
|
+
* Cleanup wired to the `abort` event should be idempotent, as it may run
|
|
26
|
+
* alongside the `Observable`'s own teardown.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* @Sse('stream')
|
|
31
|
+
* async stream(@SseSignal() signal: AbortSignal): Promise<Observable<MessageEvent>> {
|
|
32
|
+
* const session = await createSession();
|
|
33
|
+
* if (signal.aborted) {
|
|
34
|
+
* await session.close();
|
|
35
|
+
* return EMPTY;
|
|
36
|
+
* }
|
|
37
|
+
* return new Observable(subscriber => {
|
|
38
|
+
* const stream = startGeneration(session);
|
|
39
|
+
* signal.addEventListener('abort', () => stream.stop(), { once: true });
|
|
40
|
+
* return () => stream.stop();
|
|
41
|
+
* });
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* @publicApi
|
|
46
|
+
*/
|
|
47
|
+
export declare const SseSignal: () => ParameterDecorator;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createParamDecorator } from './create-route-param-metadata.decorator.js';
|
|
2
|
+
/**
|
|
3
|
+
* Symbol used to carry the per-request SSE `AbortController` on the request object.
|
|
4
|
+
*
|
|
5
|
+
* The controller is attached by the framework before the route handler runs and is
|
|
6
|
+
* aborted when the client disconnects. Its signal is exposed to route handlers
|
|
7
|
+
* through the `@SseSignal()` parameter decorator.
|
|
8
|
+
*
|
|
9
|
+
* @publicApi
|
|
10
|
+
*/
|
|
11
|
+
export const SSE_ABORT_CONTROLLER = Symbol('SSE_ABORT_CONTROLLER');
|
|
12
|
+
/**
|
|
13
|
+
* Route handler parameter decorator that injects the `AbortSignal` associated
|
|
14
|
+
* with a Server-Sent-Events (SSE) request.
|
|
15
|
+
*
|
|
16
|
+
* The signal represents the lifetime of the SSE response: it is aborted once the
|
|
17
|
+
* stream terminates, whether because the client disconnected, the `Observable`
|
|
18
|
+
* completed, or it errored. Tying setup-phase resources to the signal therefore
|
|
19
|
+
* releases them exactly once on every exit path, including resources allocated
|
|
20
|
+
* before the returned `Observable` exists — which would otherwise leak, since the
|
|
21
|
+
* producer is never subscribed once the client has disconnected.
|
|
22
|
+
*
|
|
23
|
+
* Because the signal also aborts on normal completion, `signal.aborted` is only
|
|
24
|
+
* meaningful as a "did the client go away?" check *during setup*, before the
|
|
25
|
+
* `Observable` is returned; at that point the stream cannot have completed yet.
|
|
26
|
+
* Cleanup wired to the `abort` event should be idempotent, as it may run
|
|
27
|
+
* alongside the `Observable`'s own teardown.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* @Sse('stream')
|
|
32
|
+
* async stream(@SseSignal() signal: AbortSignal): Promise<Observable<MessageEvent>> {
|
|
33
|
+
* const session = await createSession();
|
|
34
|
+
* if (signal.aborted) {
|
|
35
|
+
* await session.close();
|
|
36
|
+
* return EMPTY;
|
|
37
|
+
* }
|
|
38
|
+
* return new Observable(subscriber => {
|
|
39
|
+
* const stream = startGeneration(session);
|
|
40
|
+
* signal.addEventListener('abort', () => stream.stop(), { once: true });
|
|
41
|
+
* return () => stream.stop();
|
|
42
|
+
* });
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @publicApi
|
|
47
|
+
*/
|
|
48
|
+
export const SseSignal = createParamDecorator((_data, ctx) => {
|
|
49
|
+
const request = ctx.switchToHttp().getRequest();
|
|
50
|
+
const controller = request?.[SSE_ABORT_CONTROLLER];
|
|
51
|
+
return controller?.signal;
|
|
52
|
+
});
|
|
@@ -16,4 +16,5 @@ export var RequestMethod;
|
|
|
16
16
|
RequestMethod[RequestMethod["MOVE"] = 13] = "MOVE";
|
|
17
17
|
RequestMethod[RequestMethod["LOCK"] = 14] = "LOCK";
|
|
18
18
|
RequestMethod[RequestMethod["UNLOCK"] = 15] = "UNLOCK";
|
|
19
|
+
RequestMethod[RequestMethod["QUERY"] = 16] = "QUERY";
|
|
19
20
|
})(RequestMethod || (RequestMethod = {}));
|
|
@@ -20,7 +20,7 @@ export declare class MisdirectedException extends HttpException {
|
|
|
20
20
|
*
|
|
21
21
|
* By default, the JSON response body contains two properties:
|
|
22
22
|
* - `statusCode`: this will be the value 421.
|
|
23
|
-
* - `message`: the string `'
|
|
23
|
+
* - `message`: the string `'Misdirected'` by default; override this by supplying
|
|
24
24
|
* a string in the `objectOrError` parameter.
|
|
25
25
|
*
|
|
26
26
|
* If the parameter `objectOrError` is a string, the response body will contain an
|
|
@@ -21,7 +21,7 @@ export class MisdirectedException extends HttpException {
|
|
|
21
21
|
*
|
|
22
22
|
* By default, the JSON response body contains two properties:
|
|
23
23
|
* - `statusCode`: this will be the value 421.
|
|
24
|
-
* - `message`: the string `'
|
|
24
|
+
* - `message`: the string `'Misdirected'` by default; override this by supplying
|
|
25
25
|
* a string in the `objectOrError` parameter.
|
|
26
26
|
*
|
|
27
27
|
* If the parameter `objectOrError` is a string, the response body will contain an
|
|
@@ -20,8 +20,8 @@ export declare class NotAcceptableException extends HttpException {
|
|
|
20
20
|
*
|
|
21
21
|
* By default, the JSON response body contains two properties:
|
|
22
22
|
* - `statusCode`: this will be the value 406.
|
|
23
|
-
* - `
|
|
24
|
-
* a string in the `
|
|
23
|
+
* - `message`: the string `'Not Acceptable'` by default; override this by supplying
|
|
24
|
+
* a string in the `objectOrError` parameter.
|
|
25
25
|
*
|
|
26
26
|
* If the parameter `objectOrError` is a string, the response body will contain an
|
|
27
27
|
* additional property, `error`, with a short description of the HTTP error. To override the
|
|
@@ -21,8 +21,8 @@ export class NotAcceptableException extends HttpException {
|
|
|
21
21
|
*
|
|
22
22
|
* By default, the JSON response body contains two properties:
|
|
23
23
|
* - `statusCode`: this will be the value 406.
|
|
24
|
-
* - `
|
|
25
|
-
* a string in the `
|
|
24
|
+
* - `message`: the string `'Not Acceptable'` by default; override this by supplying
|
|
25
|
+
* a string in the `objectOrError` parameter.
|
|
26
26
|
*
|
|
27
27
|
* If the parameter `objectOrError` is a string, the response body will contain an
|
|
28
28
|
* additional property, `error`, with a short description of the HTTP error. To override the
|
package/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export * from './decorators/index.js';
|
|
|
3
3
|
export * from './enums/index.js';
|
|
4
4
|
export * from './exceptions/index.js';
|
|
5
5
|
export * from './file-stream/index.js';
|
|
6
|
-
export { Abstract, ArgumentMetadata, ArgumentsHost, BeforeApplicationShutdown, CallHandler, CanActivate, ClassProvider, ContextType, DynamicModule, ExceptionFilter, ExecutionContext, ExistingProvider, FactoryProvider, ForwardReference, HttpServer, HttpExceptionBody, HttpExceptionBodyMessage, HttpRedirectResponse, INestApplication, INestApplicationContext, INestMicroservice, InjectionToken, IntrospectionResult, MessageEvent, MiddlewareConsumer, ModuleMetadata, NestApplicationOptions, NestHybridApplicationOptions, NestInterceptor, NestMiddleware, PreRequestHook, NestModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy, OnModuleInit, OptionalFactoryDependency, Paramtype, PipeTransform, Provider, RawBodyRequest, RpcExceptionFilter, Scope, ScopeOptions, Type, ValidationError, ValueProvider, VersioningOptions, VERSION_NEUTRAL, WebSocketAdapter, WsExceptionFilter, WsMessageHandler, } from './interfaces/index.js';
|
|
6
|
+
export { Abstract, ArgumentMetadata, ArgumentsHost, BeforeApplicationShutdown, CallHandler, CanActivate, ClassProvider, ContextType, DynamicModule, ExceptionFilter, ExecutionContext, ExistingProvider, FactoryProvider, ForwardReference, HttpServer, HttpExceptionBody, HttpExceptionBodyMessage, HttpRedirectResponse, INestApplication, INestApplicationContext, INestMicroservice, ITransportServer, InjectionToken, IntrospectionResult, MessageEvent, MiddlewareConsumer, ModuleMetadata, NestApplicationOptions, NestHybridApplicationOptions, NestInterceptor, NestMiddleware, PreRequestHook, NestModule, OnApplicationBootstrap, OnApplicationShutdown, OnModuleDestroy, OnModuleInit, OptionalFactoryDependency, Paramtype, PipeTransform, Provider, RawBodyRequest, RouteConflictPolicy, RouteConflictPolicyLevel, RouteResolutionStrategy, RpcExceptionFilter, Scope, ScopeOptions, Type, ValidationError, ValueProvider, VersioningOptions, VERSION_NEUTRAL, WebSocketAdapter, WsExceptionFilter, WsMessageHandler, } from './interfaces/index.js';
|
|
7
7
|
export * from './module-utils/index.js';
|
|
8
8
|
export * from './pipes/index.js';
|
|
9
9
|
export * from './serializer/index.js';
|
|
@@ -39,6 +39,8 @@ export interface HttpServer<TRequest = any, TResponse = any, ServerInstance = an
|
|
|
39
39
|
options(path: string, handler: RequestHandler<TRequest, TResponse>): any;
|
|
40
40
|
search?(handler: RequestHandler<TRequest, TResponse>): any;
|
|
41
41
|
search?(path: string, handler: RequestHandler<TRequest, TResponse>): any;
|
|
42
|
+
query?(handler: RequestHandler<TRequest, TResponse>): any;
|
|
43
|
+
query?(path: string, handler: RequestHandler<TRequest, TResponse>): any;
|
|
42
44
|
listen(port: number | string, callback?: () => void): any;
|
|
43
45
|
listen(port: number | string, hostname: string, callback?: () => void): any;
|
|
44
46
|
reply(response: any, body: any, statusCode?: number): any;
|
|
@@ -68,4 +70,5 @@ export interface HttpServer<TRequest = any, TResponse = any, ServerInstance = an
|
|
|
68
70
|
init?(): Promise<void>;
|
|
69
71
|
applyVersionFilter(handler: Function, version: VersionValue, versioningOptions: VersioningOptions): (req: TRequest, res: TResponse, next: () => void) => Function;
|
|
70
72
|
normalizePath?(path: string): string;
|
|
73
|
+
isRouteOrderSensitive?(): boolean;
|
|
71
74
|
}
|
package/interfaces/index.d.ts
CHANGED
|
@@ -18,12 +18,14 @@ export * from './http/index.js';
|
|
|
18
18
|
export * from './injectable.interface.js';
|
|
19
19
|
export * from './microservices/nest-hybrid-application-options.interface.js';
|
|
20
20
|
export * from './microservices/pre-request-hook.interface.js';
|
|
21
|
+
export * from './microservices/transport-server.interface.js';
|
|
21
22
|
export * from './middleware/index.js';
|
|
22
23
|
export * from './modules/index.js';
|
|
23
24
|
export * from './nest-application-context.interface.js';
|
|
24
25
|
export * from './nest-application-options.interface.js';
|
|
25
26
|
export * from './nest-application.interface.js';
|
|
26
27
|
export * from './nest-microservice.interface.js';
|
|
28
|
+
export * from './router-options.interface.js';
|
|
27
29
|
export * from './scope-options.interface.js';
|
|
28
30
|
export * from './shutdown-hooks-options.interface.js';
|
|
29
31
|
export * from './type.interface.js';
|
package/interfaces/index.js
CHANGED
|
@@ -18,12 +18,14 @@ export * from './http/index.js';
|
|
|
18
18
|
export * from './injectable.interface.js';
|
|
19
19
|
export * from './microservices/nest-hybrid-application-options.interface.js';
|
|
20
20
|
export * from './microservices/pre-request-hook.interface.js';
|
|
21
|
+
export * from './microservices/transport-server.interface.js';
|
|
21
22
|
export * from './middleware/index.js';
|
|
22
23
|
export * from './modules/index.js';
|
|
23
24
|
export * from './nest-application-context.interface.js';
|
|
24
25
|
export * from './nest-application-options.interface.js';
|
|
25
26
|
export * from './nest-application.interface.js';
|
|
26
27
|
export * from './nest-microservice.interface.js';
|
|
28
|
+
export * from './router-options.interface.js';
|
|
27
29
|
export * from './scope-options.interface.js';
|
|
28
30
|
export * from './shutdown-hooks-options.interface.js';
|
|
29
31
|
export * from './type.interface.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface describing the shape of a transport server.
|
|
3
|
+
* Used as the return type of `getTransportServer()` to provide
|
|
4
|
+
* autocomplete without creating circular dependencies.
|
|
5
|
+
*
|
|
6
|
+
* @publicApi
|
|
7
|
+
*/
|
|
8
|
+
export interface ITransportServer {
|
|
9
|
+
/**
|
|
10
|
+
* Starts the transport server.
|
|
11
|
+
* @param callback Function to be called upon initialization
|
|
12
|
+
*/
|
|
13
|
+
listen(callback: (...optionalParams: unknown[]) => any): any;
|
|
14
|
+
/**
|
|
15
|
+
* Closes the transport server (stops listening on port/connection).
|
|
16
|
+
*/
|
|
17
|
+
close(): any;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CorsOptions, CorsOptionsDelegate } from './external/cors-options.interface.js';
|
|
2
2
|
import { HttpsOptions } from './external/https-options.interface.js';
|
|
3
3
|
import { NestApplicationContextOptions } from './nest-application-context-options.interface.js';
|
|
4
|
+
import { RouteConflictPolicy, RouteResolutionStrategy } from './router-options.interface.js';
|
|
4
5
|
/**
|
|
5
6
|
* @publicApi
|
|
6
7
|
*/
|
|
@@ -32,4 +33,18 @@ export interface NestApplicationOptions extends NestApplicationContextOptions {
|
|
|
32
33
|
* @default false
|
|
33
34
|
*/
|
|
34
35
|
return503OnClosing?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Per-kind policy for overlapping HTTP routes detected at bootstrap.
|
|
38
|
+
* Distinguishes `duplicate` (identical method+path+host+version) from
|
|
39
|
+
* `shadow` (patterns that can match the same request, e.g. `/users/me`
|
|
40
|
+
* vs `/users/:id`). Each kind defaults to `'off'`.
|
|
41
|
+
*/
|
|
42
|
+
routeConflictPolicy?: RouteConflictPolicy;
|
|
43
|
+
/**
|
|
44
|
+
* Order in which HTTP routes are registered on the underlying adapter.
|
|
45
|
+
* `'specificity'` registers literal segments before parametric and
|
|
46
|
+
* wildcard ones on order-sensitive adapters (such as Express). Defaults
|
|
47
|
+
* to `'declaration'`.
|
|
48
|
+
*/
|
|
49
|
+
routeResolutionStrategy?: RouteResolutionStrategy;
|
|
35
50
|
}
|
|
@@ -3,6 +3,7 @@ import { ExceptionFilter } from './exceptions/exception-filter.interface.js';
|
|
|
3
3
|
import { CanActivate } from './features/can-activate.interface.js';
|
|
4
4
|
import { NestInterceptor } from './features/nest-interceptor.interface.js';
|
|
5
5
|
import { PipeTransform } from './features/pipe-transform.interface.js';
|
|
6
|
+
import { ITransportServer } from './microservices/transport-server.interface.js';
|
|
6
7
|
import { PreRequestHook } from './microservices/pre-request-hook.interface.js';
|
|
7
8
|
import { INestApplicationContext } from './nest-application-context.interface.js';
|
|
8
9
|
import { WebSocketAdapter } from './websockets/web-socket-adapter.interface.js';
|
|
@@ -81,4 +82,10 @@ export interface INestMicroservice extends INestApplicationContext {
|
|
|
81
82
|
* or a group of servers if there are more than one.
|
|
82
83
|
*/
|
|
83
84
|
unwrap<T>(): T;
|
|
85
|
+
/**
|
|
86
|
+
* Returns the underlying transport server instance.
|
|
87
|
+
* Use this to close only the transport (port/connection) without
|
|
88
|
+
* triggering the full application shutdown lifecycle.
|
|
89
|
+
*/
|
|
90
|
+
getTransportServer(): ITransportServer;
|
|
84
91
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Severity level applied to a single kind of route conflict detected at
|
|
3
|
+
* bootstrap.
|
|
4
|
+
*
|
|
5
|
+
* @publicApi
|
|
6
|
+
*/
|
|
7
|
+
export type RouteConflictPolicyLevel = 'off' | 'warn' | 'error';
|
|
8
|
+
/**
|
|
9
|
+
* Per-kind policy for overlapping routes detected at bootstrap.
|
|
10
|
+
* `duplicate` covers identical (method, path, host, version) registrations.
|
|
11
|
+
* `shadow` covers patterns that can match the same request (for example
|
|
12
|
+
* `/users/me` vs `/users/:id`). Each kind defaults to `'off'`.
|
|
13
|
+
*
|
|
14
|
+
* @publicApi
|
|
15
|
+
*/
|
|
16
|
+
export interface RouteConflictPolicy {
|
|
17
|
+
duplicate?: RouteConflictPolicyLevel;
|
|
18
|
+
shadow?: RouteConflictPolicyLevel;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Order in which routes are registered on the underlying HTTP adapter.
|
|
22
|
+
* `'specificity'` registers literal segments before parametric and
|
|
23
|
+
* wildcard ones on order-sensitive adapters (such as Express). Defaults
|
|
24
|
+
* to `'declaration'`.
|
|
25
|
+
*
|
|
26
|
+
* @publicApi
|
|
27
|
+
*/
|
|
28
|
+
export type RouteResolutionStrategy = 'declaration' | 'specificity';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/internal.d.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
export * from './constants.js';
|
|
9
9
|
export { RouteParamtypes } from './enums/route-paramtypes.enum.js';
|
|
10
10
|
export * from './utils/shared.utils.js';
|
|
11
|
+
export * from './utils/parameter-decorator-options.util.js';
|
|
11
12
|
export * from './utils/load-package.util.js';
|
|
12
13
|
export * from './utils/cli-colors.util.js';
|
|
13
14
|
export * from './utils/random-string-generator.util.js';
|
package/internal.js
CHANGED
|
@@ -11,6 +11,7 @@ export * from './constants.js';
|
|
|
11
11
|
export { RouteParamtypes } from './enums/route-paramtypes.enum.js';
|
|
12
12
|
// Utils
|
|
13
13
|
export * from './utils/shared.utils.js';
|
|
14
|
+
export * from './utils/parameter-decorator-options.util.js';
|
|
14
15
|
export * from './utils/load-package.util.js';
|
|
15
16
|
export * from './utils/cli-colors.util.js';
|
|
16
17
|
export * from './utils/random-string-generator.util.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nestjs/common",
|
|
3
|
-
"version": "12.0.0-alpha.
|
|
3
|
+
"version": "12.0.0-alpha.6",
|
|
4
4
|
"description": "Nest - modern, fast, powerful node.js web framework (@common)",
|
|
5
5
|
"author": "Kamil Mysliwiec",
|
|
6
6
|
"homepage": "https://nestjs.com",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"./*": "./*.js"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"
|
|
29
|
+
"@standard-schema/spec": "1.1.0",
|
|
30
|
+
"file-type": "22.0.2",
|
|
30
31
|
"iterare": "1.2.1",
|
|
31
32
|
"load-esm": "1.0.3",
|
|
32
33
|
"tslib": "2.8.1",
|
|
@@ -46,5 +47,5 @@
|
|
|
46
47
|
"optional": true
|
|
47
48
|
}
|
|
48
49
|
},
|
|
49
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "4c38a5ab100f1d2a0d50602998968a25509525c7"
|
|
50
51
|
}
|
|
@@ -45,6 +45,13 @@ export type FileTypeValidatorOptions = {
|
|
|
45
45
|
* @default false
|
|
46
46
|
*/
|
|
47
47
|
fallbackToMimetype?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* If `true`, replaces the client-provided mimetype with the mimetype
|
|
50
|
+
* detected from the file content using magic number validation.
|
|
51
|
+
*
|
|
52
|
+
* @default false
|
|
53
|
+
*/
|
|
54
|
+
overrideMimeType?: boolean;
|
|
48
55
|
};
|
|
49
56
|
/**
|
|
50
57
|
* Defines the built-in FileTypeValidator. It validates incoming files by examining
|
|
@@ -58,5 +65,6 @@ export type FileTypeValidatorOptions = {
|
|
|
58
65
|
export declare class FileTypeValidator extends FileValidator<FileTypeValidatorOptions, IFile> {
|
|
59
66
|
buildErrorMessage(file?: IFile): string;
|
|
60
67
|
isValid(file?: IFile): Promise<boolean>;
|
|
68
|
+
private matchesFileType;
|
|
61
69
|
}
|
|
62
70
|
export {};
|
|
@@ -53,13 +53,13 @@ export class FileTypeValidator extends FileValidator {
|
|
|
53
53
|
const isFileValid = !!file && 'mimetype' in file;
|
|
54
54
|
// Skip magic number validation if set
|
|
55
55
|
if (this.validationOptions.skipMagicNumbersValidation) {
|
|
56
|
-
return
|
|
56
|
+
return isFileValid && this.matchesFileType(file.mimetype);
|
|
57
57
|
}
|
|
58
58
|
if (!isFileValid)
|
|
59
59
|
return false;
|
|
60
60
|
if (!file.buffer) {
|
|
61
61
|
if (this.validationOptions.fallbackToMimetype) {
|
|
62
|
-
return
|
|
62
|
+
return this.matchesFileType(file.mimetype);
|
|
63
63
|
}
|
|
64
64
|
return false;
|
|
65
65
|
}
|
|
@@ -67,8 +67,11 @@ export class FileTypeValidator extends FileValidator {
|
|
|
67
67
|
const { fileTypeFromBuffer } = await import('file-type');
|
|
68
68
|
const fileType = await fileTypeFromBuffer(file.buffer);
|
|
69
69
|
if (fileType) {
|
|
70
|
+
if (this.validationOptions.overrideMimeType) {
|
|
71
|
+
file.mimetype = fileType.mime;
|
|
72
|
+
}
|
|
70
73
|
// Match detected mime type against allowed type
|
|
71
|
-
return
|
|
74
|
+
return this.matchesFileType(fileType.mime);
|
|
72
75
|
}
|
|
73
76
|
/**
|
|
74
77
|
* Fallback logic: If file-type cannot detect magic number (e.g. file too small),
|
|
@@ -76,7 +79,7 @@ export class FileTypeValidator extends FileValidator {
|
|
|
76
79
|
* This is useful for plain text, CSVs, or files without recognizable signatures.
|
|
77
80
|
*/
|
|
78
81
|
if (this.validationOptions.fallbackToMimetype) {
|
|
79
|
-
return
|
|
82
|
+
return this.matchesFileType(file.mimetype);
|
|
80
83
|
}
|
|
81
84
|
return false;
|
|
82
85
|
}
|
|
@@ -92,9 +95,18 @@ export class FileTypeValidator extends FileValidator {
|
|
|
92
95
|
}
|
|
93
96
|
// Fallback to mimetype if enabled
|
|
94
97
|
if (this.validationOptions.fallbackToMimetype) {
|
|
95
|
-
return
|
|
98
|
+
return this.matchesFileType(file.mimetype);
|
|
96
99
|
}
|
|
97
100
|
return false;
|
|
98
101
|
}
|
|
99
102
|
}
|
|
103
|
+
matchesFileType(mimetype) {
|
|
104
|
+
const { fileType } = this.validationOptions;
|
|
105
|
+
// A string is coerced into a RegExp by `String#match`, so MIME types holding
|
|
106
|
+
// regex metacharacters (the `+` in `image/svg+xml`) never match themselves.
|
|
107
|
+
if (typeof fileType === 'string' && mimetype === fileType) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return !!mimetype.match(fileType);
|
|
111
|
+
}
|
|
100
112
|
}
|
|
@@ -4,7 +4,7 @@ import { ValidationPipe, ValidationPipeOptions } from './validation.pipe.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* @publicApi
|
|
6
6
|
*/
|
|
7
|
-
export interface
|
|
7
|
+
export interface ParseArrayPipeOptions extends Omit<ValidationPipeOptions, 'transform' | 'validateCustomDecorators' | 'exceptionFactory'> {
|
|
8
8
|
/**
|
|
9
9
|
* Type for items to be converted into
|
|
10
10
|
*/
|
|
@@ -27,6 +27,8 @@ export interface ParseArrayOptions extends Omit<ValidationPipeOptions, 'transfor
|
|
|
27
27
|
*/
|
|
28
28
|
exceptionFactory?: (error: any) => any;
|
|
29
29
|
}
|
|
30
|
+
/** @deprecated Use `ParseArrayPipeOptions` instead. */
|
|
31
|
+
export type ParseArrayOptions = ParseArrayPipeOptions;
|
|
30
32
|
/**
|
|
31
33
|
* Defines the built-in ParseArray Pipe
|
|
32
34
|
*
|
|
@@ -35,10 +37,10 @@ export interface ParseArrayOptions extends Omit<ValidationPipeOptions, 'transfor
|
|
|
35
37
|
* @publicApi
|
|
36
38
|
*/
|
|
37
39
|
export declare class ParseArrayPipe implements PipeTransform {
|
|
38
|
-
protected readonly options:
|
|
40
|
+
protected readonly options: ParseArrayPipeOptions;
|
|
39
41
|
protected readonly validationPipe: ValidationPipe;
|
|
40
42
|
protected exceptionFactory: (error: string) => any;
|
|
41
|
-
constructor(options?:
|
|
43
|
+
constructor(options?: ParseArrayPipeOptions);
|
|
42
44
|
/**
|
|
43
45
|
* Method that accesses and performs optional transformation on argument for
|
|
44
46
|
* in-flight requests.
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { PipeTransform } from '../interfaces/features/pipe-transform.interface.js';
|
|
2
2
|
import { ErrorHttpStatusCode } from '../utils/http-error-by-code.util.js';
|
|
3
|
+
/**
|
|
4
|
+
* @publicApi
|
|
5
|
+
*/
|
|
3
6
|
export interface ParseDatePipeOptions {
|
|
4
7
|
/**
|
|
5
8
|
* If true, the pipe will return null or undefined if the value is not provided
|
|
@@ -22,6 +25,9 @@ export interface ParseDatePipeOptions {
|
|
|
22
25
|
*/
|
|
23
26
|
exceptionFactory?: (error: string) => any;
|
|
24
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* @publicApi
|
|
30
|
+
*/
|
|
25
31
|
export declare class ParseDatePipe implements PipeTransform {
|
|
26
32
|
private readonly options;
|
|
27
33
|
protected exceptionFactory: (error: string) => any;
|
package/pipes/parse-date.pipe.js
CHANGED
|
@@ -3,6 +3,9 @@ import { Injectable } from '../decorators/core/injectable.decorator.js';
|
|
|
3
3
|
import { HttpStatus } from '../enums/http-status.enum.js';
|
|
4
4
|
import { HttpErrorByCode, } from '../utils/http-error-by-code.util.js';
|
|
5
5
|
import { isNil, isNumber, isString } from '../utils/shared.utils.js';
|
|
6
|
+
/**
|
|
7
|
+
* @publicApi
|
|
8
|
+
*/
|
|
6
9
|
let ParseDatePipe = class ParseDatePipe {
|
|
7
10
|
options;
|
|
8
11
|
exceptionFactory;
|
package/pipes/parse-enum.pipe.js
CHANGED
|
@@ -43,7 +43,13 @@ let ParseEnumPipe = class ParseEnumPipe {
|
|
|
43
43
|
return value;
|
|
44
44
|
}
|
|
45
45
|
isEnum(value) {
|
|
46
|
-
const enumValues = Object.keys(this.enumType)
|
|
46
|
+
const enumValues = Object.keys(this.enumType)
|
|
47
|
+
.filter(key => {
|
|
48
|
+
const enumValue = this.enumType[key];
|
|
49
|
+
return !(typeof enumValue === 'string' &&
|
|
50
|
+
typeof this.enumType[enumValue] === 'number');
|
|
51
|
+
})
|
|
52
|
+
.map(key => this.enumType[key]);
|
|
47
53
|
return enumValues.includes(value);
|
|
48
54
|
}
|
|
49
55
|
};
|
|
@@ -42,9 +42,20 @@ let ParseFloatPipe = class ParseFloatPipe {
|
|
|
42
42
|
* @returns `true` if `value` is a valid float number
|
|
43
43
|
*/
|
|
44
44
|
isNumeric(value) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
45
|
+
if (typeof value === 'number')
|
|
46
|
+
return Number.isFinite(value);
|
|
47
|
+
if (typeof value !== 'string' || value === '' || value !== value.trim()) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if (value.startsWith('0x') ||
|
|
51
|
+
value.startsWith('0X') ||
|
|
52
|
+
value.startsWith('0b') ||
|
|
53
|
+
value.startsWith('0B') ||
|
|
54
|
+
value.startsWith('0o') ||
|
|
55
|
+
value.startsWith('0O')) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return Number.isFinite(Number(value));
|
|
48
59
|
}
|
|
49
60
|
};
|
|
50
61
|
ParseFloatPipe = __decorate([
|
|
@@ -53,6 +53,11 @@ export declare class StandardSchemaValidationPipe implements PipeTransform {
|
|
|
53
53
|
protected validateOptions: Record<string, unknown> | undefined;
|
|
54
54
|
protected exceptionFactory: (issues: readonly StandardSchemaV1.Issue[]) => any;
|
|
55
55
|
constructor(options?: StandardSchemaValidationPipeOptions | undefined);
|
|
56
|
+
/**
|
|
57
|
+
* Formats Standard Schema validation issues into a flat list of error messages.
|
|
58
|
+
* When an issue includes a path, the path is prefixed to the message.
|
|
59
|
+
*/
|
|
60
|
+
protected formatIssueMessages(issues: readonly StandardSchemaV1.Issue[]): string[];
|
|
56
61
|
/**
|
|
57
62
|
* Method that validates the incoming value against the standard schema
|
|
58
63
|
* provided in the parameter metadata.
|
|
@@ -34,10 +34,22 @@ let StandardSchemaValidationPipe = class StandardSchemaValidationPipe {
|
|
|
34
34
|
this.exceptionFactory =
|
|
35
35
|
exceptionFactory ||
|
|
36
36
|
(issues => {
|
|
37
|
-
const messages =
|
|
37
|
+
const messages = this.formatIssueMessages(issues);
|
|
38
38
|
return new HttpErrorByCode[errorHttpStatusCode](messages);
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Formats Standard Schema validation issues into a flat list of error messages.
|
|
43
|
+
* When an issue includes a path, the path is prefixed to the message.
|
|
44
|
+
*/
|
|
45
|
+
formatIssueMessages(issues) {
|
|
46
|
+
return issues.map(issue => {
|
|
47
|
+
if (issue.path?.length) {
|
|
48
|
+
return `${issue.path.map(String).join('.')}: ${issue.message}`;
|
|
49
|
+
}
|
|
50
|
+
return issue.message;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
41
53
|
/**
|
|
42
54
|
* Method that validates the incoming value against the standard schema
|
|
43
55
|
* provided in the parameter metadata.
|
package/pipes/validation.pipe.js
CHANGED
|
@@ -31,7 +31,7 @@ let ValidationPipe = class ValidationPipe {
|
|
|
31
31
|
errorFormat;
|
|
32
32
|
constructor(options) {
|
|
33
33
|
options = options || {};
|
|
34
|
-
const { transform, disableErrorMessages, errorHttpStatusCode, expectedType, transformOptions, validateCustomDecorators, errorFormat, ...validatorOptions } = options;
|
|
34
|
+
const { transform, disableErrorMessages, errorHttpStatusCode, expectedType, transformOptions, exceptionFactory, validatorPackage, transformerPackage, validateCustomDecorators, errorFormat, ...validatorOptions } = options;
|
|
35
35
|
// @see [https://github.com/nestjs/nest/issues/10683#issuecomment-1413690508](https://github.com/nestjs/nest/issues/10683#issuecomment-1413690508)
|
|
36
36
|
this.validatorOptions = { forbidUnknownValues: false, ...validatorOptions };
|
|
37
37
|
this.isTransformEnabled = !!transform;
|
|
@@ -41,10 +41,9 @@ let ValidationPipe = class ValidationPipe {
|
|
|
41
41
|
this.errorHttpStatusCode = errorHttpStatusCode || HttpStatus.BAD_REQUEST;
|
|
42
42
|
this.expectedType = expectedType;
|
|
43
43
|
this.errorFormat = errorFormat || 'list';
|
|
44
|
-
this.exceptionFactory =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
classTransformer = this.loadTransformer(options.transformerPackage);
|
|
44
|
+
this.exceptionFactory = exceptionFactory || this.createExceptionFactory();
|
|
45
|
+
classValidator = this.loadValidator(validatorPackage);
|
|
46
|
+
classTransformer = this.loadTransformer(transformerPackage);
|
|
48
47
|
}
|
|
49
48
|
loadValidator(validatorPackage) {
|
|
50
49
|
return (validatorPackage ??
|
|
@@ -119,8 +118,14 @@ let ValidationPipe = class ValidationPipe {
|
|
|
119
118
|
}
|
|
120
119
|
if (this.errorFormat === 'grouped') {
|
|
121
120
|
const errors = this.groupValidationErrors(validationErrors);
|
|
121
|
+
// Custom (object) bodies are returned verbatim by
|
|
122
|
+
// `HttpException.createBody`, so add the standard envelope fields
|
|
123
|
+
// explicitly to match the shape of the "list" format.
|
|
124
|
+
const { message: error, statusCode } = new HttpErrorByCode[this.errorHttpStatusCode]().getResponse();
|
|
122
125
|
return new HttpErrorByCode[this.errorHttpStatusCode]({
|
|
123
126
|
message: errors,
|
|
127
|
+
error,
|
|
128
|
+
statusCode,
|
|
124
129
|
});
|
|
125
130
|
}
|
|
126
131
|
const errors = this.flattenValidationErrors(validationErrors);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate, __metadata, __param } from "tslib";
|
|
2
|
-
import {
|
|
2
|
+
import { concatMap } from 'rxjs/operators';
|
|
3
3
|
import { Inject, Injectable, Optional } from '../decorators/core/index.js';
|
|
4
4
|
import { StreamableFile } from '../file-stream/index.js';
|
|
5
5
|
import { isObject } from '../utils/shared.utils.js';
|
|
@@ -36,7 +36,7 @@ let StandardSchemaSerializerInterceptor = class StandardSchemaSerializerIntercep
|
|
|
36
36
|
const validateOptions = contextOptions?.validateOptions ?? this.defaultOptions.validateOptions;
|
|
37
37
|
return next
|
|
38
38
|
.handle()
|
|
39
|
-
.pipe(
|
|
39
|
+
.pipe(concatMap(async (res) => this.serialize(res, schema, validateOptions)));
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* Serializes responses that are non-null objects nor streamable files.
|
|
@@ -215,7 +215,13 @@ let ConsoleLogger = class ConsoleLogger {
|
|
|
215
215
|
}
|
|
216
216
|
if (options.params) {
|
|
217
217
|
if (this.options.flattenParams) {
|
|
218
|
-
|
|
218
|
+
// Framework fields win on key collisions: a param named "message" or
|
|
219
|
+
// "level" must not clobber the actual log message or severity.
|
|
220
|
+
for (const [key, value] of Object.entries(options.params)) {
|
|
221
|
+
if (!(key in logObject)) {
|
|
222
|
+
logObject[key] = value;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
219
225
|
}
|
|
220
226
|
else {
|
|
221
227
|
logObject.params = options.params;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { HttpStatus } from '../enums/index.js';
|
|
2
2
|
import { Type } from '../interfaces/index.js';
|
|
3
|
-
export type ErrorHttpStatusCode = HttpStatus.BAD_GATEWAY | HttpStatus.BAD_REQUEST | HttpStatus.CONFLICT | HttpStatus.FORBIDDEN | HttpStatus.GATEWAY_TIMEOUT | HttpStatus.GONE | HttpStatus.I_AM_A_TEAPOT | HttpStatus.INTERNAL_SERVER_ERROR | HttpStatus.METHOD_NOT_ALLOWED | HttpStatus.NOT_ACCEPTABLE | HttpStatus.NOT_FOUND | HttpStatus.NOT_IMPLEMENTED | HttpStatus.PAYLOAD_TOO_LARGE | HttpStatus.PRECONDITION_FAILED | HttpStatus.REQUEST_TIMEOUT | HttpStatus.SERVICE_UNAVAILABLE | HttpStatus.UNAUTHORIZED | HttpStatus.UNPROCESSABLE_ENTITY | HttpStatus.UNSUPPORTED_MEDIA_TYPE;
|
|
3
|
+
export type ErrorHttpStatusCode = HttpStatus.BAD_GATEWAY | HttpStatus.BAD_REQUEST | HttpStatus.CONFLICT | HttpStatus.FORBIDDEN | HttpStatus.GATEWAY_TIMEOUT | HttpStatus.GONE | HttpStatus.HTTP_VERSION_NOT_SUPPORTED | HttpStatus.I_AM_A_TEAPOT | HttpStatus.INTERNAL_SERVER_ERROR | HttpStatus.METHOD_NOT_ALLOWED | HttpStatus.MISDIRECTED | HttpStatus.NOT_ACCEPTABLE | HttpStatus.NOT_FOUND | HttpStatus.NOT_IMPLEMENTED | HttpStatus.PAYLOAD_TOO_LARGE | HttpStatus.PRECONDITION_FAILED | HttpStatus.REQUEST_TIMEOUT | HttpStatus.SERVICE_UNAVAILABLE | HttpStatus.UNAUTHORIZED | HttpStatus.UNPROCESSABLE_ENTITY | HttpStatus.UNSUPPORTED_MEDIA_TYPE;
|
|
4
4
|
export declare const HttpErrorByCode: Record<ErrorHttpStatusCode, Type<unknown>>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpStatus } from '../enums/index.js';
|
|
2
|
-
import { BadGatewayException, BadRequestException, ConflictException, ForbiddenException, GatewayTimeoutException, GoneException, ImATeapotException, InternalServerErrorException, MethodNotAllowedException, NotAcceptableException, NotFoundException, NotImplementedException, PayloadTooLargeException, PreconditionFailedException, RequestTimeoutException, ServiceUnavailableException, UnauthorizedException, UnprocessableEntityException, UnsupportedMediaTypeException, } from '../exceptions/index.js';
|
|
2
|
+
import { BadGatewayException, BadRequestException, ConflictException, ForbiddenException, GatewayTimeoutException, GoneException, HttpVersionNotSupportedException, ImATeapotException, InternalServerErrorException, MethodNotAllowedException, MisdirectedException, NotAcceptableException, NotFoundException, NotImplementedException, PayloadTooLargeException, PreconditionFailedException, RequestTimeoutException, ServiceUnavailableException, UnauthorizedException, UnprocessableEntityException, UnsupportedMediaTypeException, } from '../exceptions/index.js';
|
|
3
3
|
export const HttpErrorByCode = {
|
|
4
4
|
[HttpStatus.BAD_GATEWAY]: BadGatewayException,
|
|
5
5
|
[HttpStatus.BAD_REQUEST]: BadRequestException,
|
|
@@ -7,9 +7,11 @@ export const HttpErrorByCode = {
|
|
|
7
7
|
[HttpStatus.FORBIDDEN]: ForbiddenException,
|
|
8
8
|
[HttpStatus.GATEWAY_TIMEOUT]: GatewayTimeoutException,
|
|
9
9
|
[HttpStatus.GONE]: GoneException,
|
|
10
|
+
[HttpStatus.HTTP_VERSION_NOT_SUPPORTED]: HttpVersionNotSupportedException,
|
|
10
11
|
[HttpStatus.I_AM_A_TEAPOT]: ImATeapotException,
|
|
11
12
|
[HttpStatus.INTERNAL_SERVER_ERROR]: InternalServerErrorException,
|
|
12
13
|
[HttpStatus.METHOD_NOT_ALLOWED]: MethodNotAllowedException,
|
|
14
|
+
[HttpStatus.MISDIRECTED]: MisdirectedException,
|
|
13
15
|
[HttpStatus.NOT_ACCEPTABLE]: NotAcceptableException,
|
|
14
16
|
[HttpStatus.NOT_FOUND]: NotFoundException,
|
|
15
17
|
[HttpStatus.NOT_IMPLEMENTED]: NotImplementedException,
|
|
@@ -18,7 +18,7 @@ export declare function loadPackageSync(packageName: string, context: string, lo
|
|
|
18
18
|
* Ensure that `loadPackage()` has been `await`ed for the same package name
|
|
19
19
|
* before calling this function (typically during `init()` or `compile()`).
|
|
20
20
|
*/
|
|
21
|
-
export declare function loadPackageCached(packageName: string): any;
|
|
21
|
+
export declare function loadPackageCached(packageName: string, context?: string): any;
|
|
22
22
|
/**
|
|
23
23
|
* Attempts to load and cache a package. Returns the loaded module on success
|
|
24
24
|
* or `null` if the package is not installed.
|
|
@@ -60,9 +60,15 @@ export function loadPackageSync(packageName, context, loaderFn) {
|
|
|
60
60
|
* Ensure that `loadPackage()` has been `await`ed for the same package name
|
|
61
61
|
* before calling this function (typically during `init()` or `compile()`).
|
|
62
62
|
*/
|
|
63
|
-
export function loadPackageCached(packageName) {
|
|
63
|
+
export function loadPackageCached(packageName, context) {
|
|
64
64
|
const cached = packageCache.get(packageName);
|
|
65
65
|
if (!cached) {
|
|
66
|
+
if (context) {
|
|
67
|
+
// The package was not preloaded (typically because it is not
|
|
68
|
+
// installed). Fall back to a synchronous load so the user gets the
|
|
69
|
+
// actionable "package is missing" message instead of an internal error.
|
|
70
|
+
return loadPackageSync(packageName, context);
|
|
71
|
+
}
|
|
66
72
|
throw new Error(`Package "${packageName}" has not been loaded yet. ` +
|
|
67
73
|
`Ensure loadPackage("${packageName}", ...) has been awaited before calling loadPackageCached.`);
|
|
68
74
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ParameterDecoratorOptions } from '../decorators/http/route-params.decorator.js';
|
|
2
|
+
/**
|
|
3
|
+
* Determines whether a parameter-decorator argument is a
|
|
4
|
+
* `ParameterDecoratorOptions` object rather than a pipe (instance or class).
|
|
5
|
+
*
|
|
6
|
+
* Kept in one place so every decorator (`@Query`, `@Body`, `@Param`,
|
|
7
|
+
* `@RawBody`, `@Payload`, `@MessageBody`, custom decorators, ...) classifies
|
|
8
|
+
* arguments identically: a pipe instance that happens to expose a `schema` or
|
|
9
|
+
* `pipes` property must never be mistaken for an options object.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export declare function isParameterDecoratorOptions(value: unknown): value is ParameterDecoratorOptions;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { isFunction } from './shared.utils.js';
|
|
2
|
+
const isPipeLike = (value) => isFunction(value?.transform) ||
|
|
3
|
+
(isFunction(value) &&
|
|
4
|
+
value.prototype &&
|
|
5
|
+
isFunction(value.prototype.transform));
|
|
6
|
+
/**
|
|
7
|
+
* Determines whether a parameter-decorator argument is a
|
|
8
|
+
* `ParameterDecoratorOptions` object rather than a pipe (instance or class).
|
|
9
|
+
*
|
|
10
|
+
* Kept in one place so every decorator (`@Query`, `@Body`, `@Param`,
|
|
11
|
+
* `@RawBody`, `@Payload`, `@MessageBody`, custom decorators, ...) classifies
|
|
12
|
+
* arguments identically: a pipe instance that happens to expose a `schema` or
|
|
13
|
+
* `pipes` property must never be mistaken for an options object.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export function isParameterDecoratorOptions(value) {
|
|
18
|
+
return (!!value &&
|
|
19
|
+
typeof value === 'object' &&
|
|
20
|
+
!isPipeLike(value) &&
|
|
21
|
+
('schema' in value || 'pipes' in value));
|
|
22
|
+
}
|