@nestia/core 14.0.0 → 14.0.2
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/MIGRATION.md +20 -0
- package/README.md +1 -1
- package/lib/adaptors/McpAdaptor.d.ts +29 -3
- package/lib/adaptors/McpAdaptor.js +150 -24
- package/lib/adaptors/McpAdaptor.js.map +1 -1
- package/lib/adaptors/WebSocketAdaptor.d.ts +37 -0
- package/lib/adaptors/WebSocketAdaptor.js +184 -48
- package/lib/adaptors/WebSocketAdaptor.js.map +1 -1
- package/lib/adaptors/internal/RoutePathMatcher.d.ts +1 -0
- package/lib/adaptors/internal/RoutePathMatcher.js +88 -0
- package/lib/adaptors/internal/RoutePathMatcher.js.map +1 -0
- package/lib/adaptors/internal/external_context.d.ts +1 -0
- package/lib/adaptors/internal/external_context.js +56 -0
- package/lib/adaptors/internal/external_context.js.map +1 -0
- package/lib/decorators/DynamicModule.d.ts +12 -0
- package/lib/decorators/DynamicModule.js +12 -0
- package/lib/decorators/DynamicModule.js.map +1 -1
- package/lib/decorators/EncryptedBody.d.ts +14 -6
- package/lib/decorators/EncryptedBody.js +39 -16
- package/lib/decorators/EncryptedBody.js.map +1 -1
- package/lib/decorators/EncryptedController.d.ts +6 -1
- package/lib/decorators/EncryptedController.js +7 -2
- package/lib/decorators/EncryptedController.js.map +1 -1
- package/lib/decorators/EncryptedModule.d.ts +25 -6
- package/lib/decorators/EncryptedModule.js +87 -18
- package/lib/decorators/EncryptedModule.js.map +1 -1
- package/lib/decorators/EncryptedRoute.d.ts +20 -11
- package/lib/decorators/EncryptedRoute.js +27 -13
- package/lib/decorators/EncryptedRoute.js.map +1 -1
- package/lib/decorators/HumanRoute.d.ts +5 -0
- package/lib/decorators/HumanRoute.js +5 -0
- package/lib/decorators/HumanRoute.js.map +1 -1
- package/lib/decorators/McpRoute.d.ts +31 -19
- package/lib/decorators/McpRoute.js +12 -1
- package/lib/decorators/McpRoute.js.map +1 -1
- package/lib/decorators/PlainBody.d.ts +7 -1
- package/lib/decorators/PlainBody.js +16 -8
- package/lib/decorators/PlainBody.js.map +1 -1
- package/lib/decorators/SwaggerCustomizer.d.ts +15 -0
- package/lib/decorators/SwaggerCustomizer.js +5 -0
- package/lib/decorators/SwaggerCustomizer.js.map +1 -1
- package/lib/decorators/SwaggerExample.d.ts +51 -22
- package/lib/decorators/SwaggerExample.js +35 -22
- package/lib/decorators/SwaggerExample.js.map +1 -1
- package/lib/decorators/TypedBody.d.ts +10 -3
- package/lib/decorators/TypedBody.js +20 -10
- package/lib/decorators/TypedBody.js.map +1 -1
- package/lib/decorators/TypedException.d.ts +10 -0
- package/lib/decorators/TypedFormData.d.ts +81 -9
- package/lib/decorators/TypedFormData.js +121 -31
- package/lib/decorators/TypedFormData.js.map +1 -1
- package/lib/decorators/TypedHeaders.d.ts +5 -0
- package/lib/decorators/TypedHeaders.js +5 -0
- package/lib/decorators/TypedHeaders.js.map +1 -1
- package/lib/decorators/TypedParam.d.ts +12 -3
- package/lib/decorators/TypedParam.js +12 -3
- package/lib/decorators/TypedParam.js.map +1 -1
- package/lib/decorators/TypedQuery.d.ts +17 -1
- package/lib/decorators/TypedQuery.js +25 -4
- package/lib/decorators/TypedQuery.js.map +1 -1
- package/lib/decorators/TypedRoute.d.ts +25 -10
- package/lib/decorators/TypedRoute.js +19 -10
- package/lib/decorators/TypedRoute.js.map +1 -1
- package/lib/decorators/WebSocketRoute.d.ts +18 -1
- package/lib/decorators/WebSocketRoute.js +18 -1
- package/lib/decorators/WebSocketRoute.js.map +1 -1
- package/lib/decorators/doNotThrowTransformError.d.ts +14 -0
- package/lib/decorators/doNotThrowTransformError.js +14 -0
- package/lib/decorators/doNotThrowTransformError.js.map +1 -1
- package/lib/decorators/internal/EncryptedConstant.js +13 -2
- package/lib/decorators/internal/EncryptedConstant.js.map +1 -1
- package/lib/decorators/internal/IRequestBodyValidation.d.ts +66 -0
- package/lib/decorators/internal/IRequestBodyValidation.js +3 -0
- package/lib/decorators/internal/IRequestBodyValidation.js.map +1 -0
- package/lib/decorators/internal/IWebSocketRouteReflect.d.ts +93 -1
- package/lib/decorators/internal/get_encryption_password.d.ts +1 -0
- package/lib/decorators/internal/get_encryption_password.js +14 -0
- package/lib/decorators/internal/get_encryption_password.js.map +1 -0
- package/lib/decorators/internal/get_path_and_querify.js +23 -9
- package/lib/decorators/internal/get_path_and_querify.js.map +1 -1
- package/lib/decorators/internal/get_path_and_stringify.js +3 -7
- package/lib/decorators/internal/get_path_and_stringify.js.map +1 -1
- package/lib/decorators/internal/get_text_body.js +9 -3
- package/lib/decorators/internal/get_text_body.js.map +1 -1
- package/lib/decorators/internal/group_entries.d.ts +1 -0
- package/lib/decorators/internal/group_entries.js +19 -0
- package/lib/decorators/internal/group_entries.js.map +1 -0
- package/lib/decorators/internal/load_controller.d.ts +14 -0
- package/lib/decorators/internal/load_controller.js +14 -0
- package/lib/decorators/internal/load_controller.js.map +1 -1
- package/lib/decorators/internal/split_route_arguments.d.ts +1 -0
- package/lib/decorators/internal/split_route_arguments.js +22 -0
- package/lib/decorators/internal/split_route_arguments.js.map +1 -0
- package/lib/decorators/internal/validate_request_body.js +68 -25
- package/lib/decorators/internal/validate_request_body.js.map +1 -1
- package/lib/decorators/internal/validate_request_form_data.js +3 -1
- package/lib/decorators/internal/validate_request_form_data.js.map +1 -1
- package/lib/decorators/internal/validate_request_headers.js +2 -1
- package/lib/decorators/internal/validate_request_headers.js.map +1 -1
- package/lib/decorators/internal/validate_request_query.js +3 -1
- package/lib/decorators/internal/validate_request_query.js.map +1 -1
- package/lib/options/IRequestBodyValidator.d.ts +71 -0
- package/lib/options/IRequestFormDataProps.d.ts +80 -0
- package/lib/options/IRequestHeadersValidator.d.ts +67 -0
- package/lib/options/IRequestQueryValidator.d.ts +68 -0
- package/lib/options/IResponseBodyQuerifier.d.ts +125 -1
- package/lib/options/IResponseBodyStringifier.d.ts +107 -0
- package/lib/typings/Creator.d.ts +10 -0
- package/lib/utils/ArrayUtil.d.ts +21 -0
- package/lib/utils/ArrayUtil.js +22 -1
- package/lib/utils/ArrayUtil.js.map +1 -1
- package/lib/utils/ExceptionManager.d.ts +43 -4
- package/lib/utils/ExceptionManager.js +44 -6
- package/lib/utils/ExceptionManager.js.map +1 -1
- package/lib/utils/SourceFinder.d.ts +22 -0
- package/lib/utils/SourceFinder.js +60 -10
- package/lib/utils/SourceFinder.js.map +1 -1
- package/lib/utils/VersioningStrategy.d.ts +45 -2
- package/lib/utils/VersioningStrategy.js +40 -7
- package/lib/utils/VersioningStrategy.js.map +1 -1
- package/native/go.mod +1 -1
- package/native/go.sum +2 -2
- package/native/plugin/plan.go +68 -2
- package/native/transform/ast.go +23 -3
- package/native/transform/build.go +51 -57
- package/native/transform/buildoutput/output.go +147 -0
- package/native/transform/contributor.go +9 -0
- package/native/transform/core_querify.go +63 -9
- package/native/transform/core_transform.go +180 -98
- package/native/transform/core_websocket.go +111 -14
- package/native/transform/node_transform.go +17 -8
- package/native/transform/package.go +55 -0
- package/native/transform/printer.go +1 -3
- package/native/transform/run.go +18 -0
- package/native/transform/schemaprojection/project.go +213 -0
- package/native/transform/transform.go +29 -18
- package/native/transform/typia_fast.go +6 -0
- package/native/transform.cjs +49 -0
- package/package.json +13 -15
- package/src/adaptors/McpAdaptor.ts +215 -33
- package/src/adaptors/WebSocketAdaptor.ts +202 -52
- package/src/adaptors/internal/RoutePathMatcher.ts +91 -0
- package/src/adaptors/internal/external_context.ts +81 -0
- package/src/decorators/DynamicModule.ts +12 -0
- package/src/decorators/EncryptedBody.ts +39 -15
- package/src/decorators/EncryptedController.ts +12 -3
- package/src/decorators/EncryptedModule.ts +89 -18
- package/src/decorators/EncryptedRoute.ts +27 -16
- package/src/decorators/HumanRoute.ts +5 -0
- package/src/decorators/McpRoute.ts +31 -19
- package/src/decorators/PlainBody.ts +20 -10
- package/src/decorators/SwaggerCustomizer.ts +15 -0
- package/src/decorators/SwaggerExample.ts +51 -22
- package/src/decorators/TypedBody.ts +18 -9
- package/src/decorators/TypedException.ts +10 -0
- package/src/decorators/TypedFormData.ts +207 -45
- package/src/decorators/TypedHeaders.ts +5 -0
- package/src/decorators/TypedParam.ts +12 -3
- package/src/decorators/TypedQuery.ts +35 -7
- package/src/decorators/TypedRoute.ts +25 -10
- package/src/decorators/WebSocketRoute.ts +18 -1
- package/src/decorators/doNotThrowTransformError.ts +14 -0
- package/src/decorators/internal/EncryptedConstant.ts +14 -1
- package/src/decorators/internal/IMcpRouteReflect.ts +7 -1
- package/src/decorators/internal/IRequestBodyValidation.ts +65 -0
- package/src/decorators/internal/IWebSocketRouteReflect.ts +95 -1
- package/src/decorators/internal/get_encryption_password.ts +19 -0
- package/src/decorators/internal/get_path_and_querify.ts +31 -10
- package/src/decorators/internal/get_path_and_stringify.ts +3 -9
- package/src/decorators/internal/get_text_body.ts +8 -4
- package/src/decorators/internal/group_entries.ts +17 -0
- package/src/decorators/internal/load_controller.ts +14 -0
- package/src/decorators/internal/split_route_arguments.ts +20 -0
- package/src/decorators/internal/validate_request_body.ts +87 -34
- package/src/decorators/internal/validate_request_form_data.ts +3 -1
- package/src/decorators/internal/validate_request_headers.ts +2 -2
- package/src/decorators/internal/validate_request_query.ts +3 -2
- package/src/options/IRequestBodyValidator.ts +71 -0
- package/src/options/IRequestFormDataProps.ts +80 -0
- package/src/options/IRequestHeadersValidator.ts +67 -0
- package/src/options/IRequestQueryValidator.ts +68 -0
- package/src/options/IResponseBodyQuerifier.ts +126 -1
- package/src/options/IResponseBodyStringifier.ts +107 -0
- package/src/typings/Creator.ts +10 -0
- package/src/utils/ArrayUtil.ts +22 -3
- package/src/utils/ExceptionManager.ts +50 -6
- package/src/utils/SourceFinder.ts +62 -10
- package/src/utils/VersioningStrategy.ts +55 -11
- package/lib/transform.d.ts +0 -10
- package/lib/transform.js +0 -25
- package/lib/transform.js.map +0 -1
- package/src/transform.ts +0 -26
|
@@ -21,10 +21,13 @@
|
|
|
21
21
|
* types are allowed
|
|
22
22
|
* 4. By the way, union type never be not allowed
|
|
23
23
|
*
|
|
24
|
-
* By the way, if you're using `fastify`,
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
24
|
+
* By the way, if you're using `fastify`, pass a `fastify-multer` instance as
|
|
25
|
+
* the factory, and register a `multipart/form-data` content type parser that
|
|
26
|
+
* leaves the request stream to it when composing the NestJS application.
|
|
27
|
+
* Without the parser, Fastify rejects every multipart request with 415.
|
|
28
|
+
* `fastify-multer`'s own `contentParser` plugin declares the content type
|
|
29
|
+
* `multipart` without a subtype, which Fastify 5 (NestJS 11) refuses to
|
|
30
|
+
* register.
|
|
28
31
|
*
|
|
29
32
|
* ```typescript
|
|
30
33
|
* import { NestFactory } from "@nestjs/core";
|
|
@@ -32,19 +35,33 @@
|
|
|
32
35
|
* FastifyAdapter,
|
|
33
36
|
* NestFastifyApplication,
|
|
34
37
|
* } from "@nestjs/platform-fastify";
|
|
35
|
-
* import fastifyMulter from "fastify-multer";
|
|
36
38
|
*
|
|
37
39
|
* export async function main() {
|
|
38
40
|
* const app = await NestFactory.create<NestFastifyApplication>(
|
|
39
41
|
* AppModule,
|
|
40
42
|
* new FastifyAdapter(),
|
|
41
43
|
* );
|
|
42
|
-
* app
|
|
44
|
+
* app
|
|
45
|
+
* .getHttpAdapter()
|
|
46
|
+
* .getInstance()
|
|
47
|
+
* .addContentTypeParser("multipart/form-data", (_req, _payload, done) =>
|
|
48
|
+
* done(null),
|
|
49
|
+
* );
|
|
43
50
|
* await app.listen(3000);
|
|
44
51
|
* }
|
|
52
|
+
*
|
|
53
|
+
* // in the controller, with `import FastifyMulter from "fastify-multer"`
|
|
54
|
+
* public async upload(
|
|
55
|
+
* @TypedFormData.Body(() => FastifyMulter()) body: IMultipart,
|
|
56
|
+
* ): Promise<void> {}
|
|
45
57
|
* ```
|
|
46
58
|
*
|
|
47
59
|
* @author Jeongho Nam - https://github.com/samchon
|
|
60
|
+
* @evidence contracts/common.md#principled-implementation The body must be multipart; multer parses it through the caller's factory into a `FormData` of fields and `File` objects, uploaded temp files are read and always removed afterwards, multer limits map to 413 or 400 responses, and the assembled form is checked by the transformed validator.
|
|
61
|
+
* @evidence contracts/common.md#clear-and-simple-design One decorator with the multipart decoding, the error mapping, and the file conversion as separate module-private functions, and the multer instance created once by a `Singleton`.
|
|
62
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Errors are mapped by multer's documented codes and by exact busboy messages, and no file name is special-cased; a runtime without `File` is refused up front.
|
|
63
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the factory, the memory and disk storage requirement, and the validation.
|
|
64
|
+
* @evidence contracts/portability.md#os-neutral-implementation Uploaded disk paths come from the storage engine and are consumed directly by Node fs readFile and rm; filename is File metadata rather than a reconstructed native path. Structural multer method signatures specify middleware rather than native path spelling.
|
|
48
65
|
* @todo Change to ReadableStream through configuring storage engine of multer
|
|
49
66
|
*/
|
|
50
67
|
export declare namespace TypedFormData {
|
|
@@ -55,17 +72,72 @@ export declare namespace TypedFormData {
|
|
|
55
72
|
*
|
|
56
73
|
* Much easier and type safer than `@nest.UploadFile()` decorator.
|
|
57
74
|
*
|
|
58
|
-
* @param factory Factory function
|
|
75
|
+
* @param factory Factory function creating the `multer` or `fastify-multer`
|
|
59
76
|
* instance. In the factory function, you also can specify the multer
|
|
60
|
-
* composition options like `storage` engine
|
|
77
|
+
* composition options like `storage` engine: memory and disk storage
|
|
78
|
+
* deliver the uploaded bytes, and an engine keeping neither the buffer nor
|
|
79
|
+
* a file path is rejected.
|
|
61
80
|
*/
|
|
62
81
|
function Body<Multer extends IMulterBase>(factory: () => Multer | Promise<Multer>): ParameterDecorator;
|
|
63
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* Base type of the `multer` or `fastify-multer`.
|
|
84
|
+
*
|
|
85
|
+
* @evidence contracts/common.md#principled-implementation The interface names the multer methods that identify a multer instance structurally, so an application can pass its own instance without this package depending on a multer type at runtime.
|
|
86
|
+
* @evidence contracts/common.md#clear-and-simple-design Five method members with no behavior.
|
|
87
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
88
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states its purpose as the structural stand-in for multer.
|
|
89
|
+
* @evidence contracts/portability.md#os-neutral-implementation Uploaded disk paths come from the storage engine and are consumed directly by Node fs readFile and rm; filename is File metadata rather than a reconstructed native path. Structural multer method signatures specify middleware rather than native path spelling.
|
|
90
|
+
*/
|
|
64
91
|
interface IMulterBase {
|
|
92
|
+
/**
|
|
93
|
+
* Middleware factory for a single file field.
|
|
94
|
+
*
|
|
95
|
+
* @evidence contracts/common.md#principled-implementation The member mirrors multer's single-file middleware factory.
|
|
96
|
+
* @evidence contracts/common.md#clear-and-simple-design One method signature.
|
|
97
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
98
|
+
* @evidence contracts/common.md#meaningful-documentation The member is named after the multer method it mirrors.
|
|
99
|
+
* @evidence contracts/portability.md#os-neutral-implementation Uploaded disk paths come from the storage engine and are consumed directly by Node fs readFile and rm; filename is File metadata rather than a reconstructed native path. Structural multer method signatures specify middleware rather than native path spelling.
|
|
100
|
+
*/
|
|
65
101
|
single(fieldName: string): any;
|
|
102
|
+
/**
|
|
103
|
+
* Middleware factory for an array of files under one field.
|
|
104
|
+
*
|
|
105
|
+
* @evidence contracts/common.md#principled-implementation The member mirrors multer's array-of-files middleware factory.
|
|
106
|
+
* @evidence contracts/common.md#clear-and-simple-design One method signature.
|
|
107
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
108
|
+
* @evidence contracts/common.md#meaningful-documentation The member is named after the multer method it mirrors.
|
|
109
|
+
* @evidence contracts/portability.md#os-neutral-implementation Uploaded disk paths come from the storage engine and are consumed directly by Node fs readFile and rm; filename is File metadata rather than a reconstructed native path. Structural multer method signatures specify middleware rather than native path spelling.
|
|
110
|
+
*/
|
|
66
111
|
array(fieldName: string, maxCount?: number): any;
|
|
112
|
+
/**
|
|
113
|
+
* Middleware factory for several named file fields.
|
|
114
|
+
*
|
|
115
|
+
* @evidence contracts/common.md#principled-implementation The member mirrors multer's named-fields middleware factory, which is the one the decorator uses when the transform lists the file fields.
|
|
116
|
+
* @evidence contracts/common.md#clear-and-simple-design One method signature.
|
|
117
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
118
|
+
* @evidence contracts/common.md#meaningful-documentation The member is named after the multer method it mirrors.
|
|
119
|
+
* @evidence contracts/portability.md#os-neutral-implementation Uploaded disk paths come from the storage engine and are consumed directly by Node fs readFile and rm; filename is File metadata rather than a reconstructed native path. Structural multer method signatures specify middleware rather than native path spelling.
|
|
120
|
+
*/
|
|
67
121
|
fields(fields: readonly object[]): any;
|
|
122
|
+
/**
|
|
123
|
+
* Middleware factory that accepts every file field.
|
|
124
|
+
*
|
|
125
|
+
* @evidence contracts/common.md#principled-implementation The member mirrors multer's accept-any-file middleware factory, which the decorator uses when no transform names the file fields.
|
|
126
|
+
* @evidence contracts/common.md#clear-and-simple-design One method signature.
|
|
127
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
128
|
+
* @evidence contracts/common.md#meaningful-documentation The member is named after the multer method it mirrors.
|
|
129
|
+
* @evidence contracts/portability.md#os-neutral-implementation Uploaded disk paths come from the storage engine and are consumed directly by Node fs readFile and rm; filename is File metadata rather than a reconstructed native path. Structural multer method signatures specify middleware rather than native path spelling.
|
|
130
|
+
*/
|
|
68
131
|
any(): any;
|
|
132
|
+
/**
|
|
133
|
+
* Middleware factory that accepts text fields only.
|
|
134
|
+
*
|
|
135
|
+
* @evidence contracts/common.md#principled-implementation The member mirrors multer's text-fields-only middleware factory.
|
|
136
|
+
* @evidence contracts/common.md#clear-and-simple-design One method signature.
|
|
137
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It is a type and adds no runtime behavior.
|
|
138
|
+
* @evidence contracts/common.md#meaningful-documentation The member is named after the multer method it mirrors.
|
|
139
|
+
* @evidence contracts/portability.md#os-neutral-implementation Uploaded disk paths come from the storage engine and are consumed directly by Node fs readFile and rm; filename is File metadata rather than a reconstructed native path. Structural multer method signatures specify middleware rather than native path spelling.
|
|
140
|
+
*/
|
|
69
141
|
none(): any;
|
|
70
142
|
}
|
|
71
143
|
}
|
|
@@ -8,9 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.TypedFormData = void 0;
|
|
13
16
|
const common_1 = require("@nestjs/common");
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
14
18
|
const Singleton_1 = require("../utils/Singleton");
|
|
15
19
|
const is_media_type_1 = require("./internal/is_media_type");
|
|
16
20
|
const validate_request_form_data_1 = require("./internal/validate_request_form_data");
|
|
@@ -37,10 +41,13 @@ const validate_request_form_data_1 = require("./internal/validate_request_form_d
|
|
|
37
41
|
* types are allowed
|
|
38
42
|
* 4. By the way, union type never be not allowed
|
|
39
43
|
*
|
|
40
|
-
* By the way, if you're using `fastify`,
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
+
* By the way, if you're using `fastify`, pass a `fastify-multer` instance as
|
|
45
|
+
* the factory, and register a `multipart/form-data` content type parser that
|
|
46
|
+
* leaves the request stream to it when composing the NestJS application.
|
|
47
|
+
* Without the parser, Fastify rejects every multipart request with 415.
|
|
48
|
+
* `fastify-multer`'s own `contentParser` plugin declares the content type
|
|
49
|
+
* `multipart` without a subtype, which Fastify 5 (NestJS 11) refuses to
|
|
50
|
+
* register.
|
|
44
51
|
*
|
|
45
52
|
* ```typescript
|
|
46
53
|
* import { NestFactory } from "@nestjs/core";
|
|
@@ -48,19 +55,33 @@ const validate_request_form_data_1 = require("./internal/validate_request_form_d
|
|
|
48
55
|
* FastifyAdapter,
|
|
49
56
|
* NestFastifyApplication,
|
|
50
57
|
* } from "@nestjs/platform-fastify";
|
|
51
|
-
* import fastifyMulter from "fastify-multer";
|
|
52
58
|
*
|
|
53
59
|
* export async function main() {
|
|
54
60
|
* const app = await NestFactory.create<NestFastifyApplication>(
|
|
55
61
|
* AppModule,
|
|
56
62
|
* new FastifyAdapter(),
|
|
57
63
|
* );
|
|
58
|
-
* app
|
|
64
|
+
* app
|
|
65
|
+
* .getHttpAdapter()
|
|
66
|
+
* .getInstance()
|
|
67
|
+
* .addContentTypeParser("multipart/form-data", (_req, _payload, done) =>
|
|
68
|
+
* done(null),
|
|
69
|
+
* );
|
|
59
70
|
* await app.listen(3000);
|
|
60
71
|
* }
|
|
72
|
+
*
|
|
73
|
+
* // in the controller, with `import FastifyMulter from "fastify-multer"`
|
|
74
|
+
* public async upload(
|
|
75
|
+
* @TypedFormData.Body(() => FastifyMulter()) body: IMultipart,
|
|
76
|
+
* ): Promise<void> {}
|
|
61
77
|
* ```
|
|
62
78
|
*
|
|
63
79
|
* @author Jeongho Nam - https://github.com/samchon
|
|
80
|
+
* @evidence contracts/common.md#principled-implementation The body must be multipart; multer parses it through the caller's factory into a `FormData` of fields and `File` objects, uploaded temp files are read and always removed afterwards, multer limits map to 413 or 400 responses, and the assembled form is checked by the transformed validator.
|
|
81
|
+
* @evidence contracts/common.md#clear-and-simple-design One decorator with the multipart decoding, the error mapping, and the file conversion as separate module-private functions, and the multer instance created once by a `Singleton`.
|
|
82
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Errors are mapped by multer's documented codes and by exact busboy messages, and no file name is special-cased; a runtime without `File` is refused up front.
|
|
83
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the factory, the memory and disk storage requirement, and the validation.
|
|
84
|
+
* @evidence contracts/portability.md#os-neutral-implementation Uploaded disk paths come from the storage engine and are consumed directly by Node fs readFile and rm; filename is File metadata rather than a reconstructed native path. Structural multer method signatures specify middleware rather than native path spelling.
|
|
64
85
|
* @todo Change to ReadableStream through configuring storage engine of multer
|
|
65
86
|
*/
|
|
66
87
|
var TypedFormData;
|
|
@@ -92,39 +113,108 @@ var TypedFormData;
|
|
|
92
113
|
})(TypedFormData || (exports.TypedFormData = TypedFormData = {}));
|
|
93
114
|
/** @internal */
|
|
94
115
|
const decode = (multer, props) => {
|
|
95
|
-
|
|
116
|
+
// without the transform nothing names the file fields, so accept every file
|
|
117
|
+
const upload = props === undefined
|
|
118
|
+
? multer.any()
|
|
119
|
+
: multer.fields(props.files.map((file) => (Object.assign({ name: file.name }, (file.limit === 1 ? { maxCount: 1 } : {})))));
|
|
96
120
|
const interceptor = (request, response) => new Promise((resolve, reject) => upload(request, response, (error) => {
|
|
97
121
|
if (error)
|
|
98
|
-
reject(error);
|
|
122
|
+
reject(transformMulterError(error));
|
|
99
123
|
else
|
|
100
124
|
resolve();
|
|
101
125
|
}));
|
|
102
126
|
return (socket) => __awaiter(void 0, void 0, void 0, function* () {
|
|
103
127
|
yield interceptor(socket.request, socket.response);
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
128
|
+
const files = entries(socket.request.files);
|
|
129
|
+
try {
|
|
130
|
+
const data = new FormData();
|
|
131
|
+
for (const [key, value] of Object.entries(socket.request.body))
|
|
132
|
+
if (Array.isArray(value))
|
|
133
|
+
for (const elem of value)
|
|
134
|
+
data.append(key, String(elem));
|
|
135
|
+
else
|
|
136
|
+
data.append(key, String(value));
|
|
137
|
+
for (const [key, file] of files)
|
|
138
|
+
data.append(key, yield toFile(file));
|
|
139
|
+
return data;
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
// a disk storage engine leaves each file behind, and the handler only
|
|
143
|
+
// receives its contents as a File, never the path to remove it by
|
|
144
|
+
yield Promise.all(files.map(([, file]) => typeof file.path === "string"
|
|
145
|
+
? fs_1.default.promises.rm(file.path, { force: true })
|
|
146
|
+
: undefined));
|
|
147
|
+
}
|
|
114
148
|
});
|
|
115
149
|
};
|
|
116
|
-
/**
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
150
|
+
/**
|
|
151
|
+
* The client error NestJS's own `FileInterceptor` answers for a multipart
|
|
152
|
+
* request the multer configuration rejects: 413 for a file over
|
|
153
|
+
* `limits.fileSize`, 400 for the other limits, an unexpected field, and a
|
|
154
|
+
* malformed body. Anything else, an `HttpException` a `fileFilter` threw
|
|
155
|
+
* included, is left as it is.
|
|
156
|
+
*
|
|
157
|
+
* @internal
|
|
158
|
+
*/
|
|
159
|
+
const transformMulterError = (error) => {
|
|
160
|
+
if (!(error instanceof Error) || error instanceof common_1.HttpException)
|
|
161
|
+
return error;
|
|
162
|
+
const code = error.code;
|
|
163
|
+
const field = error.field;
|
|
164
|
+
if (code === "LIMIT_FILE_SIZE")
|
|
165
|
+
return new common_1.PayloadTooLargeException(error.message);
|
|
166
|
+
else if (typeof code === "string" && MULTER_BAD_REQUESTS.has(code))
|
|
167
|
+
return new common_1.BadRequestException(typeof field === "string" ? `${error.message} - ${field}` : error.message);
|
|
168
|
+
else if (error.message === "Multipart: Boundary not found")
|
|
169
|
+
return new common_1.BadRequestException(error.message);
|
|
170
|
+
else if (BUSBOY_BAD_REQUESTS.has(error.message) ||
|
|
171
|
+
error.message.endsWith(" terminated early due to unexpected end of multipart data"))
|
|
172
|
+
return new common_1.BadRequestException(`Multipart: ${error.message}`);
|
|
173
|
+
return error;
|
|
129
174
|
};
|
|
175
|
+
/** @internal */
|
|
176
|
+
const MULTER_BAD_REQUESTS = new Set([
|
|
177
|
+
"LIMIT_PART_COUNT",
|
|
178
|
+
"LIMIT_FILE_COUNT",
|
|
179
|
+
"LIMIT_FIELD_KEY",
|
|
180
|
+
"LIMIT_FIELD_VALUE",
|
|
181
|
+
"LIMIT_FIELD_COUNT",
|
|
182
|
+
"LIMIT_UNEXPECTED_FILE",
|
|
183
|
+
"MISSING_FIELD_NAME",
|
|
184
|
+
]);
|
|
185
|
+
/**
|
|
186
|
+
* A malformed body, as `busboy` (under `multer`) and `@fastify/busboy` (under
|
|
187
|
+
* `fastify-multer`) word it.
|
|
188
|
+
*
|
|
189
|
+
* @internal
|
|
190
|
+
*/
|
|
191
|
+
const BUSBOY_BAD_REQUESTS = new Set([
|
|
192
|
+
"Malformed part header",
|
|
193
|
+
"Unexpected end of form",
|
|
194
|
+
"Unexpected end of file",
|
|
195
|
+
"Unexpected end of multipart data",
|
|
196
|
+
]);
|
|
197
|
+
/** @internal */
|
|
198
|
+
const entries = (files) => files === undefined
|
|
199
|
+
? []
|
|
200
|
+
: Array.isArray(files)
|
|
201
|
+
? files.map((file) => [file.fieldname, file])
|
|
202
|
+
: Object.entries(files).flatMap(([key, value]) => value.map((file) => [key, file]));
|
|
203
|
+
/**
|
|
204
|
+
* The uploaded file as a `File`: memory storage keeps its bytes in `buffer`,
|
|
205
|
+
* disk storage in the file at `path`. An engine keeping neither cannot deliver
|
|
206
|
+
* it, which must not pass as an empty or placeholder file.
|
|
207
|
+
*
|
|
208
|
+
* @internal
|
|
209
|
+
*/
|
|
210
|
+
const toFile = (file) => __awaiter(void 0, void 0, void 0, function* () {
|
|
211
|
+
const bytes = file.buffer !== undefined
|
|
212
|
+
? file.buffer
|
|
213
|
+
: typeof file.path === "string"
|
|
214
|
+
? yield fs_1.default.promises.readFile(file.path)
|
|
215
|
+
: undefined;
|
|
216
|
+
if (bytes === undefined)
|
|
217
|
+
throw new Error(`Error on TypedFormData.Body(): the multer storage engine kept neither the buffer nor the path of the uploaded file ${JSON.stringify(file.fieldname)}, so it cannot be read as a File. Use memory or disk storage.`);
|
|
218
|
+
return new File([bytes], file.originalname, { type: file.mimetype });
|
|
219
|
+
});
|
|
130
220
|
//# sourceMappingURL=TypedFormData.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypedFormData.js","sourceRoot":"","sources":["../../src/decorators/TypedFormData.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TypedFormData.js","sourceRoot":"","sources":["../../src/decorators/TypedFormData.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,5 +41,10 @@ import { IRequestHeadersValidator } from "../options/IRequestHeadersValidator";
|
|
|
41
41
|
*
|
|
42
42
|
* @author Jeongho Nam - https://github.com/samchon
|
|
43
43
|
* @returns Parameter decorator
|
|
44
|
+
* @evidence contracts/common.md#principled-implementation The header record of the request is decoded by the transformed function into the typed object, whose failure is thrown as the response; header names arrive lower-cased from Node, which the generated decoder expects.
|
|
45
|
+
* @evidence contracts/common.md#clear-and-simple-design One parameter decorator built from the shared header validator runner.
|
|
46
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The decoder is generated from the type by the transform; without it the request headers are passed through only when the configuration guard is off.
|
|
47
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the decoding, the supported property types, and the validation modes.
|
|
48
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Header names and decoded values belong to the HTTP protocol and are not native filesystem identities.
|
|
44
49
|
*/
|
|
45
50
|
export declare function TypedHeaders<T extends object>(validator?: IRequestHeadersValidator<T>): ParameterDecorator;
|
|
@@ -45,6 +45,11 @@ const validate_request_headers_1 = require("./internal/validate_request_headers"
|
|
|
45
45
|
*
|
|
46
46
|
* @author Jeongho Nam - https://github.com/samchon
|
|
47
47
|
* @returns Parameter decorator
|
|
48
|
+
* @evidence contracts/common.md#principled-implementation The header record of the request is decoded by the transformed function into the typed object, whose failure is thrown as the response; header names arrive lower-cased from Node, which the generated decoder expects.
|
|
49
|
+
* @evidence contracts/common.md#clear-and-simple-design One parameter decorator built from the shared header validator runner.
|
|
50
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The decoder is generated from the type by the transform; without it the request headers are passed through only when the configuration guard is off.
|
|
51
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the decoding, the supported property types, and the validation modes.
|
|
52
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Header names and decoded values belong to the HTTP protocol and are not native filesystem identities.
|
|
48
53
|
*/
|
|
49
54
|
function TypedHeaders(validator) {
|
|
50
55
|
const checker = (0, validate_request_headers_1.validate_request_headers)(validator);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypedHeaders.js","sourceRoot":"","sources":["../../src/decorators/TypedHeaders.ts"],"names":[],"mappings":";;;AAAA,2CAAwE;AAKxE,kFAA+E;AAE/E
|
|
1
|
+
{"version":3,"file":"TypedHeaders.js","sourceRoot":"","sources":["../../src/decorators/TypedHeaders.ts"],"names":[],"mappings":";;;AAAA,2CAAwE;AAKxE,kFAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,sBACE,SAAuC;IAEvC,MAAM,OAAO,GAAG,IAAA,mDAAwB,EAAC,SAAS,CAAC,CAAC;IACpD,OAAO,IAAA,6BAAoB,EAAC,SAAS,YAAY,CAC/C,QAAa,EACb,OAAyB;QAEzB,MAAM,OAAO,GAAqC,OAAO;aACtD,YAAY,EAAE;aACd,UAAU,EAAE,CAAC;QAChB,MAAM,MAAM,GAAc,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACnD,IAAI,MAAM,YAAY,KAAK;YAAE,MAAM,MAAM,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,EAAE,CAAC;AACP,CAAC"}
|
|
@@ -11,14 +11,23 @@
|
|
|
11
11
|
*
|
|
12
12
|
* \@TypedRoute.Get("shopping/sales/:id/:no/:paused")
|
|
13
13
|
* public async pause(
|
|
14
|
-
* \@TypedParam("id"
|
|
15
|
-
* \@TypedParam("no")
|
|
16
|
-
* \@TypedParam("paused") paused: boolean | null
|
|
14
|
+
* \@TypedParam("id") id: string & tags.Format<"uuid">,
|
|
15
|
+
* \@TypedParam("no") no: number & tags.Type<"uint32">,
|
|
16
|
+
* \@TypedParam("paused") paused: boolean | null,
|
|
17
17
|
* ): Promise<void>;
|
|
18
18
|
* ```
|
|
19
19
|
*
|
|
20
20
|
* @author Jeongho Nam - https://github.com/samchon
|
|
21
21
|
* @param name URL Parameter name
|
|
22
|
+
* @param assert Conversion and assertion supplied by the compile-time transform
|
|
23
|
+
* @param validate Emit an errors array on validation failure when true;
|
|
24
|
+
* otherwise expose the first failure as flat path, reason, expected and value
|
|
25
|
+
* fields.
|
|
22
26
|
* @returns Parameter decorator
|
|
27
|
+
* @evidence contracts/common.md#principled-implementation The path parameter arrives as a string and is converted by the assertion function the transform generated for the declared type, so a value of the wrong type produces a 400 that names the parameter; the `validate` flag only changes the error body from the flat form to an `errors` array.
|
|
28
|
+
* @evidence contracts/common.md#clear-and-simple-design One decorator with one conversion function and one error-shaping branch.
|
|
29
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The conversion is generated from the declared type; without the transform the raw string is returned only when the configuration guard is off.
|
|
30
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the supported types and the two error shapes.
|
|
31
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation The named path segment is an HTTP route parameter whose text is decoded by the generated validator; no native path is resolved.
|
|
23
32
|
*/
|
|
24
33
|
export declare function TypedParam<T extends boolean | bigint | number | string | null>(name: string, assert?: (value: string) => T, validate?: boolean): ParameterDecorator;
|
|
@@ -20,15 +20,24 @@ const NoTransformConfigurationError_1 = require("./NoTransformConfigurationError
|
|
|
20
20
|
*
|
|
21
21
|
* \@TypedRoute.Get("shopping/sales/:id/:no/:paused")
|
|
22
22
|
* public async pause(
|
|
23
|
-
* \@TypedParam("id"
|
|
24
|
-
* \@TypedParam("no")
|
|
25
|
-
* \@TypedParam("paused") paused: boolean | null
|
|
23
|
+
* \@TypedParam("id") id: string & tags.Format<"uuid">,
|
|
24
|
+
* \@TypedParam("no") no: number & tags.Type<"uint32">,
|
|
25
|
+
* \@TypedParam("paused") paused: boolean | null,
|
|
26
26
|
* ): Promise<void>;
|
|
27
27
|
* ```
|
|
28
28
|
*
|
|
29
29
|
* @author Jeongho Nam - https://github.com/samchon
|
|
30
30
|
* @param name URL Parameter name
|
|
31
|
+
* @param assert Conversion and assertion supplied by the compile-time transform
|
|
32
|
+
* @param validate Emit an errors array on validation failure when true;
|
|
33
|
+
* otherwise expose the first failure as flat path, reason, expected and value
|
|
34
|
+
* fields.
|
|
31
35
|
* @returns Parameter decorator
|
|
36
|
+
* @evidence contracts/common.md#principled-implementation The path parameter arrives as a string and is converted by the assertion function the transform generated for the declared type, so a value of the wrong type produces a 400 that names the parameter; the `validate` flag only changes the error body from the flat form to an `errors` array.
|
|
37
|
+
* @evidence contracts/common.md#clear-and-simple-design One decorator with one conversion function and one error-shaping branch.
|
|
38
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The conversion is generated from the declared type; without the transform the raw string is returned only when the configuration guard is off.
|
|
39
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the supported types and the two error shapes.
|
|
40
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation The named path segment is an HTTP route parameter whose text is decoded by the generated validator; no native path is resolved.
|
|
32
41
|
*/
|
|
33
42
|
function TypedParam(name, assert, validate) {
|
|
34
43
|
if (assert === undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypedParam.js","sourceRoot":"","sources":["../../src/decorators/TypedParam.ts"],"names":[],"mappings":";;;;;;AAAA,2CAIwB;AAGxB,kDAA2D;AAE3D,mFAAgF;AAEhF
|
|
1
|
+
{"version":3,"file":"TypedParam.js","sourceRoot":"","sources":["../../src/decorators/TypedParam.ts"],"names":[],"mappings":";;;;;;AAAA,2CAIwB;AAGxB,kDAA2D;AAE3D,mFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,oBACE,IAAY,EACZ,MAA6B,EAC7B,QAAkB;IAElB,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,IAAA,6DAA6B,EAAC,YAAY,CAAC,CAAC;QAC5C,MAAM,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,KAAU,CAAC;IACjC,CAAC;IAED,OAAO,IAAA,6BAAoB,EAAC,SAAS,UAAU,CAC7C,EAAO,EACP,OAAyB;;QAEzB,MAAM,OAAO,GAAqC,OAAO;aACtD,YAAY,EAAE;aACd,UAAU,EAAE,CAAC;QAChB,MAAM,GAAG,GAAY,OAAO,CAAC,MAAc,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC;YACH,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb;;;iBAA6B,GAAG,GAAG,CAAC;gBAClC,MAAM,KAAK,GAAuB;oBAChC,IAAI,QAAE,GAAG,CAAC,IAAI,mCAAI,QAAQ;oBAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ;oBACtB,KAAK,EAAE,GAAG,CAAC,KAAK;iBACjB,CAAC;gBACF,MAAM,IAAI,4BAAmB,iBAC3B,OAAO,EAAE,mCAAmC,IAAI,IAAI,IACjD,CAAC,QAAQ,KAAK,IAAI;oBACnB,CAAC,CAAC;wBACE,MAAM,EAAE,CAAC,KAAK,CAAC;qBAChB;oBACH,CAAC,iCACM,KAAK,KACR,MAAM,EAAE,GAAG,CAAC,OAAO,GACpB,CAAC,EACN,CAAC;YACL,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -19,8 +19,24 @@ import { IResponseBodyQuerifier } from "../options/IResponseBodyQuerifier";
|
|
|
19
19
|
*
|
|
20
20
|
* @author Jeongho Nam - https://github.com/samchon
|
|
21
21
|
* @returns Parameter decorator
|
|
22
|
+
* @evidence contracts/common.md#principled-implementation The query string is read from the request URL after the first question mark, grouped by the transformed decoder into the typed object, and a failure is thrown as the 400 response; the decoder receives a `URLSearchParams`, so both Express and Fastify requests are handled by the same code.
|
|
23
|
+
* @evidence contracts/common.md#clear-and-simple-design One parameter decorator on top of the shared query validator runner.
|
|
24
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The decoder is generated from the type by the transform; without it the grouped raw query is returned only when the configuration guard is off.
|
|
25
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the supported property types and the validation modes.
|
|
26
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Query decoding and response encoding operate on URLSearchParams and HTTP route metadata rather than native filesystem paths.
|
|
22
27
|
*/
|
|
23
28
|
export declare function TypedQuery<T extends object>(validator?: IRequestQueryValidator<T>): ParameterDecorator;
|
|
29
|
+
/**
|
|
30
|
+
* Variants of {@link TypedQuery}: `TypedQuery.Body` reads an urlencoded body,
|
|
31
|
+
* and `TypedQuery.Get`, `Post`, `Put`, `Patch`, and `Delete` return the value
|
|
32
|
+
* as an urlencoded response.
|
|
33
|
+
*
|
|
34
|
+
* @evidence contracts/common.md#principled-implementation `Body` requires the `application/x-www-form-urlencoded` media type and decodes the parsed body, and the route decorators serialize the returned value through the querifier the transform chose and set the response content type.
|
|
35
|
+
* @evidence contracts/common.md#clear-and-simple-design One body decorator and one generator that creates the five route decorators, with a small adapter class for parsed bodies.
|
|
36
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The route decorators copy typia's marker properties onto themselves exactly as `TypedRoute` does, which mutates only these exported functions.
|
|
37
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the body decorator and the route decorators.
|
|
38
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Query decoding and response encoding operate on URLSearchParams and HTTP route metadata rather than native filesystem paths.
|
|
39
|
+
*/
|
|
24
40
|
export declare namespace TypedQuery {
|
|
25
41
|
/**
|
|
26
42
|
* Request body decorator.
|
|
@@ -51,7 +67,7 @@ export declare namespace TypedQuery {
|
|
|
51
67
|
<T>(path: string | string[], stringify?: IResponseBodyQuerifier<T>): MethodDecorator;
|
|
52
68
|
};
|
|
53
69
|
/**
|
|
54
|
-
* Router decorator function for the
|
|
70
|
+
* Router decorator function for the PATCH method.
|
|
55
71
|
*
|
|
56
72
|
* @param path Path of the HTTP request
|
|
57
73
|
* @returns Method decorator
|
|
@@ -5,8 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.TypedQuery = TypedQuery;
|
|
7
7
|
const common_1 = require("@nestjs/common");
|
|
8
|
-
const
|
|
8
|
+
const operators_1 = require("rxjs/operators");
|
|
9
9
|
const typia_1 = __importDefault(require("typia"));
|
|
10
|
+
const TypedRoute_1 = require("./TypedRoute");
|
|
10
11
|
const get_path_and_querify_1 = require("./internal/get_path_and_querify");
|
|
11
12
|
const is_media_type_1 = require("./internal/is_media_type");
|
|
12
13
|
const route_error_1 = require("./internal/route_error");
|
|
@@ -30,6 +31,11 @@ const validate_request_query_1 = require("./internal/validate_request_query");
|
|
|
30
31
|
*
|
|
31
32
|
* @author Jeongho Nam - https://github.com/samchon
|
|
32
33
|
* @returns Parameter decorator
|
|
34
|
+
* @evidence contracts/common.md#principled-implementation The query string is read from the request URL after the first question mark, grouped by the transformed decoder into the typed object, and a failure is thrown as the 400 response; the decoder receives a `URLSearchParams`, so both Express and Fastify requests are handled by the same code.
|
|
35
|
+
* @evidence contracts/common.md#clear-and-simple-design One parameter decorator on top of the shared query validator runner.
|
|
36
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The decoder is generated from the type by the transform; without it the grouped raw query is returned only when the configuration guard is off.
|
|
37
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the supported property types and the validation modes.
|
|
38
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Query decoding and response encoding operate on URLSearchParams and HTTP route metadata rather than native filesystem paths.
|
|
33
39
|
*/
|
|
34
40
|
function TypedQuery(validator) {
|
|
35
41
|
const checker = (0, validate_request_query_1.validate_request_query)("TypedQuery")(validator);
|
|
@@ -44,6 +50,17 @@ function TypedQuery(validator) {
|
|
|
44
50
|
return output;
|
|
45
51
|
})();
|
|
46
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Variants of {@link TypedQuery}: `TypedQuery.Body` reads an urlencoded body,
|
|
55
|
+
* and `TypedQuery.Get`, `Post`, `Put`, `Patch`, and `Delete` return the value
|
|
56
|
+
* as an urlencoded response.
|
|
57
|
+
*
|
|
58
|
+
* @evidence contracts/common.md#principled-implementation `Body` requires the `application/x-www-form-urlencoded` media type and decodes the parsed body, and the route decorators serialize the returned value through the querifier the transform chose and set the response content type.
|
|
59
|
+
* @evidence contracts/common.md#clear-and-simple-design One body decorator and one generator that creates the five route decorators, with a small adapter class for parsed bodies.
|
|
60
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The route decorators copy typia's marker properties onto themselves exactly as `TypedRoute` does, which mutates only these exported functions.
|
|
61
|
+
* @evidence contracts/common.md#meaningful-documentation The comment documents the body decorator and the route decorators.
|
|
62
|
+
* @evidenceExclude contracts/portability.md#os-neutral-implementation Query decoding and response encoding operate on URLSearchParams and HTTP route metadata rather than native filesystem paths.
|
|
63
|
+
*/
|
|
47
64
|
(function (TypedQuery) {
|
|
48
65
|
/**
|
|
49
66
|
* Request body decorator.
|
|
@@ -83,7 +100,7 @@ function TypedQuery(validator) {
|
|
|
83
100
|
*/
|
|
84
101
|
TypedQuery.Post = Generator("Post");
|
|
85
102
|
/**
|
|
86
|
-
* Router decorator function for the
|
|
103
|
+
* Router decorator function for the PATCH method.
|
|
87
104
|
*
|
|
88
105
|
* @param path Path of the HTTP request
|
|
89
106
|
* @returns Method decorator
|
|
@@ -106,7 +123,7 @@ function TypedQuery(validator) {
|
|
|
106
123
|
/** @internal */
|
|
107
124
|
function Generator(method) {
|
|
108
125
|
function route(...args) {
|
|
109
|
-
const [path, stringify] = (0, get_path_and_querify_1.get_path_and_querify)(`TypedQuery.${method}`)(...args);
|
|
126
|
+
const [path, stringify] = (0, get_path_and_querify_1.get_path_and_querify)(() => TypedRoute_1.TypedRoute.__logger)(`TypedQuery.${method}`)(...args);
|
|
110
127
|
return (0, common_1.applyDecorators)(ROUTERS[method](path), (0, common_1.UseInterceptors)(new TypedQueryRouteInterceptor(stringify)));
|
|
111
128
|
}
|
|
112
129
|
return route;
|
|
@@ -135,6 +152,9 @@ class FakeURLSearchParams {
|
|
|
135
152
|
has(key) {
|
|
136
153
|
return this.target[key] !== undefined;
|
|
137
154
|
}
|
|
155
|
+
keys() {
|
|
156
|
+
return Object.keys(this.target).filter((key) => this.has(key));
|
|
157
|
+
}
|
|
138
158
|
get(key) {
|
|
139
159
|
var _a;
|
|
140
160
|
const value = this.target[key];
|
|
@@ -156,9 +176,10 @@ class TypedQueryRouteInterceptor {
|
|
|
156
176
|
}
|
|
157
177
|
intercept(context, next) {
|
|
158
178
|
const http = context.switchToHttp();
|
|
179
|
+
const request = http.getRequest();
|
|
159
180
|
const response = http.getResponse();
|
|
160
181
|
response.header("Content-Type", "application/x-www-form-urlencoded");
|
|
161
|
-
return next.handle().pipe((0,
|
|
182
|
+
return next.handle().pipe((0, operators_1.map)((value) => this.toSearchParams(value, request.method, request.url).toString()), (0, operators_1.catchError)((err) => (0, route_error_1.route_error)(http.getRequest(), err)));
|
|
162
183
|
}
|
|
163
184
|
}
|
|
164
185
|
/** @internal */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TypedQuery.js","sourceRoot":"","sources":["../../src/decorators/TypedQuery.ts"],"names":[],"mappings":";;;;;;AAAA,2CAawB;AAIxB
|
|
1
|
+
{"version":3,"file":"TypedQuery.js","sourceRoot":"","sources":["../../src/decorators/TypedQuery.ts"],"names":[],"mappings":"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"}
|