@tsed/platform-http 8.0.0 → 8.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/.barrelsby.json +1 -1
- package/lib/esm/common/index.js +0 -1
- package/lib/esm/common/index.js.map +1 -1
- package/lib/types/common/fn/adapter.d.ts +1 -1
- package/lib/types/common/index.d.ts +0 -1
- package/package.json +19 -17
- package/src/common/builder/PlatformBuilder.spec.ts +331 -0
- package/src/common/builder/PlatformBuilder.ts +426 -0
- package/src/common/builder/__fixtures__/PlatformCustom.ts +39 -0
- package/src/common/config/interfaces/PlatformJsonMapperSettings.ts +11 -0
- package/src/common/config/interfaces/PlatformMulterSettings.ts +21 -0
- package/src/common/config/interfaces/PlatformRouterSettings.ts +11 -0
- package/src/common/config/interfaces/PlatformStaticsSettings.ts +23 -0
- package/src/common/config/services/PlatformConfiguration.spec.ts +181 -0
- package/src/common/config/services/PlatformConfiguration.ts +157 -0
- package/src/common/constants/routerOptions.ts +1 -0
- package/src/common/decorators/PlatformProvider.ts +14 -0
- package/src/common/decorators/multer/multerFileSize.spec.ts +22 -0
- package/src/common/decorators/multer/multerFileSize.ts +32 -0
- package/src/common/decorators/multer/multerOptions.spec.ts +21 -0
- package/src/common/decorators/multer/multerOptions.ts +53 -0
- package/src/common/decorators/multer/multipartFile.spec.ts +259 -0
- package/src/common/decorators/multer/multipartFile.ts +88 -0
- package/src/common/decorators/params/error.spec.ts +15 -0
- package/src/common/decorators/params/error.ts +16 -0
- package/src/common/decorators/params/next.spec.ts +15 -0
- package/src/common/decorators/params/next.ts +31 -0
- package/src/common/decorators/params/request.spec.ts +49 -0
- package/src/common/decorators/params/request.ts +85 -0
- package/src/common/decorators/params/response.spec.ts +36 -0
- package/src/common/decorators/params/response.ts +73 -0
- package/src/common/domain/AnyToPromiseWithCtx.spec.ts +20 -0
- package/src/common/domain/AnyToPromiseWithCtx.ts +30 -0
- package/src/common/domain/EndpointMetadata.ts +1 -0
- package/src/common/domain/PlatformContext.spec.ts +124 -0
- package/src/common/domain/PlatformContext.ts +135 -0
- package/src/common/domain/PlatformRouteDetails.ts +7 -0
- package/src/common/exports.ts +4 -0
- package/src/common/fn/adapter.ts +23 -0
- package/src/common/fn/application.ts +11 -0
- package/src/common/index.ts +62 -0
- package/src/common/interfaces/AfterInit.ts +3 -0
- package/src/common/interfaces/AfterListen.ts +3 -0
- package/src/common/interfaces/AfterRoutesInit.ts +3 -0
- package/src/common/interfaces/BeforeInit.ts +3 -0
- package/src/common/interfaces/BeforeListen.ts +3 -0
- package/src/common/interfaces/BeforeRoutesInit.ts +3 -0
- package/src/common/interfaces/HandlerType.ts +12 -0
- package/src/common/interfaces/IncomingEvent.ts +6 -0
- package/src/common/interfaces/OnReady.ts +3 -0
- package/src/common/interfaces/OnRequest.ts +5 -0
- package/src/common/interfaces/OnResponse.ts +5 -0
- package/src/common/interfaces/OnRoutesInit.ts +3 -0
- package/src/common/interfaces/PlatformRouteOptions.ts +17 -0
- package/src/common/interfaces/ResponseErrorObject.ts +8 -0
- package/src/common/interfaces/Route.ts +12 -0
- package/src/common/middlewares/PlatformAcceptMimesMiddleware.spec.ts +215 -0
- package/src/common/middlewares/PlatformAcceptMimesMiddleware.ts +24 -0
- package/src/common/middlewares/PlatformMulterMiddleware.spec.ts +97 -0
- package/src/common/middlewares/PlatformMulterMiddleware.ts +59 -0
- package/src/common/services/Platform.spec.ts +145 -0
- package/src/common/services/Platform.ts +79 -0
- package/src/common/services/PlatformAdapter.ts +89 -0
- package/src/common/services/PlatformApplication.spec.ts +101 -0
- package/src/common/services/PlatformApplication.ts +54 -0
- package/src/common/services/PlatformHandler.spec.ts +152 -0
- package/src/common/services/PlatformHandler.ts +140 -0
- package/src/common/services/PlatformMiddlewaresChain.spec.ts +96 -0
- package/src/common/services/PlatformMiddlewaresChain.ts +55 -0
- package/src/common/services/PlatformRequest.spec.ts +185 -0
- package/src/common/services/PlatformRequest.ts +181 -0
- package/src/common/services/PlatformResponse.spec.ts +344 -0
- package/src/common/services/PlatformResponse.ts +388 -0
- package/src/common/utils/closeServer.spec.ts +11 -0
- package/src/common/utils/closeServer.ts +7 -0
- package/src/common/utils/createContext.spec.ts +111 -0
- package/src/common/utils/createContext.ts +52 -0
- package/src/common/utils/createHttpServer.spec.ts +74 -0
- package/src/common/utils/createHttpServer.ts +15 -0
- package/src/common/utils/createHttpsServer.spec.ts +73 -0
- package/src/common/utils/createHttpsServer.ts +16 -0
- package/src/common/utils/createInjector.spec.ts +42 -0
- package/src/common/utils/createInjector.ts +55 -0
- package/src/common/utils/createServer.ts +51 -0
- package/src/common/utils/ensureContext.spec.ts +41 -0
- package/src/common/utils/ensureContext.ts +17 -0
- package/src/common/utils/getConfiguration.spec.ts +163 -0
- package/src/common/utils/getConfiguration.ts +34 -0
- package/src/common/utils/getStaticsOptions.spec.ts +27 -0
- package/src/common/utils/getStaticsOptions.ts +24 -0
- package/src/common/utils/listenServer.ts +17 -0
- package/src/common/utils/mapReturnedResponse.spec.ts +35 -0
- package/src/common/utils/mapReturnedResponse.ts +10 -0
- package/src/common/utils/printRoutes.spec.ts +19 -0
- package/src/common/utils/printRoutes.ts +40 -0
- package/src/common/utils/resolveControllers.spec.ts +40 -0
- package/src/common/utils/resolveControllers.ts +54 -0
- package/src/common/utils/setResponseHeaders.spec.ts +84 -0
- package/src/common/utils/setResponseHeaders.ts +31 -0
- package/src/index.ts +2 -0
- package/src/testing/FakeAdapter.ts +69 -0
- package/src/testing/FakeResponse.ts +72 -0
- package/src/testing/PlatformTest.spec.ts +53 -0
- package/src/testing/PlatformTest.ts +157 -0
- package/src/testing/index.ts +5 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import "../../index.js";
|
|
2
|
+
|
|
3
|
+
import {descriptorOf, Metadata, Store} from "@tsed/core";
|
|
4
|
+
import {ParamTypes} from "@tsed/platform-params";
|
|
5
|
+
import {getSpec, JsonParameterStore, Post, SpecTypes} from "@tsed/schema";
|
|
6
|
+
|
|
7
|
+
import {PlatformMulterMiddleware} from "../../middlewares/PlatformMulterMiddleware.js";
|
|
8
|
+
import {MultipartFile} from "./multipartFile.js";
|
|
9
|
+
|
|
10
|
+
class Test {
|
|
11
|
+
test() {}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe("@MultipartFile()", () => {
|
|
15
|
+
describe("one file", () => {
|
|
16
|
+
// WHEN
|
|
17
|
+
class TestController {
|
|
18
|
+
@Post("/")
|
|
19
|
+
test(@MultipartFile("file1", 1) file: any) {}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// THEN
|
|
23
|
+
const store = Store.fromMethod(TestController, "test");
|
|
24
|
+
const param = JsonParameterStore.get(TestController, "test", 0);
|
|
25
|
+
|
|
26
|
+
it("should set params properly", () => {
|
|
27
|
+
expect(store.get(PlatformMulterMiddleware)).toEqual({
|
|
28
|
+
fields: [
|
|
29
|
+
{
|
|
30
|
+
maxCount: 1,
|
|
31
|
+
name: "file1"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
});
|
|
35
|
+
expect(param.expression).toEqual("file1.0");
|
|
36
|
+
expect(param.paramType).toEqual(ParamTypes.FILES);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should set endpoint metadata - OS3", () => {
|
|
40
|
+
expect(getSpec(TestController, {specType: SpecTypes.OPENAPI})).toEqual({
|
|
41
|
+
paths: {
|
|
42
|
+
"/": {
|
|
43
|
+
post: {
|
|
44
|
+
operationId: "testControllerTest",
|
|
45
|
+
parameters: [],
|
|
46
|
+
responses: {
|
|
47
|
+
"400": {
|
|
48
|
+
content: {"application/json": {schema: {$ref: "#/components/schemas/BadRequest"}}},
|
|
49
|
+
description:
|
|
50
|
+
"<File too long | Too many parts | Too many files | Field name too long | Field value too long | Too many fields | Unexpected field> [fieldName] Example: File too long file1"
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
requestBody: {
|
|
54
|
+
required: false,
|
|
55
|
+
content: {
|
|
56
|
+
"multipart/form-data": {
|
|
57
|
+
schema: {
|
|
58
|
+
properties: {file1: {type: "string", format: "binary"}},
|
|
59
|
+
type: "object"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
tags: ["TestController"]
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
tags: [{name: "TestController"}],
|
|
69
|
+
components: {
|
|
70
|
+
schemas: {
|
|
71
|
+
GenericError: {
|
|
72
|
+
additionalProperties: true,
|
|
73
|
+
properties: {
|
|
74
|
+
message: {
|
|
75
|
+
description: "An error message",
|
|
76
|
+
minLength: 1,
|
|
77
|
+
type: "string"
|
|
78
|
+
},
|
|
79
|
+
name: {
|
|
80
|
+
description: "The error name",
|
|
81
|
+
minLength: 1,
|
|
82
|
+
type: "string"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
required: ["name", "message"],
|
|
86
|
+
type: "object"
|
|
87
|
+
},
|
|
88
|
+
BadRequest: {
|
|
89
|
+
type: "object",
|
|
90
|
+
properties: {
|
|
91
|
+
name: {
|
|
92
|
+
type: "string",
|
|
93
|
+
minLength: 1,
|
|
94
|
+
description: "The error name",
|
|
95
|
+
example: "BAD_REQUEST",
|
|
96
|
+
default: "BAD_REQUEST"
|
|
97
|
+
},
|
|
98
|
+
message: {type: "string", minLength: 1, description: "An error message"},
|
|
99
|
+
status: {type: "number", description: "The status code of the exception", example: 400, default: 400},
|
|
100
|
+
errors: {
|
|
101
|
+
type: "array",
|
|
102
|
+
items: {
|
|
103
|
+
$ref: "#/components/schemas/GenericError"
|
|
104
|
+
},
|
|
105
|
+
description: "A list of related errors"
|
|
106
|
+
},
|
|
107
|
+
stack: {
|
|
108
|
+
type: "string",
|
|
109
|
+
description: "The stack trace (only in development mode)"
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
required: ["name", "message", "status"]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe("multiple file schema", () => {
|
|
121
|
+
// WHEN
|
|
122
|
+
class TestController {
|
|
123
|
+
@Post("/")
|
|
124
|
+
test(@MultipartFile("file1", 4) file: any[]) {}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// THEN
|
|
128
|
+
const store = Store.fromMethod(TestController, "test");
|
|
129
|
+
const param = JsonParameterStore.get(TestController, "test", 0);
|
|
130
|
+
|
|
131
|
+
it("should set params properly", () => {
|
|
132
|
+
expect(store.get(PlatformMulterMiddleware)).toEqual({
|
|
133
|
+
fields: [
|
|
134
|
+
{
|
|
135
|
+
maxCount: 4,
|
|
136
|
+
name: "file1"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
});
|
|
140
|
+
expect(param.expression).toEqual("file1");
|
|
141
|
+
expect(param.paramType).toEqual(ParamTypes.FILES);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("should set endpoint metadata - OS3", () => {
|
|
145
|
+
expect(getSpec(TestController, {specType: SpecTypes.OPENAPI})).toEqual({
|
|
146
|
+
paths: {
|
|
147
|
+
"/": {
|
|
148
|
+
post: {
|
|
149
|
+
operationId: "testControllerTest",
|
|
150
|
+
parameters: [],
|
|
151
|
+
responses: {
|
|
152
|
+
"400": {
|
|
153
|
+
content: {"application/json": {schema: {$ref: "#/components/schemas/BadRequest"}}},
|
|
154
|
+
description:
|
|
155
|
+
"<File too long | Too many parts | Too many files | Field name too long | Field value too long | Too many fields | Unexpected field> [fieldName] Example: File too long file1"
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
requestBody: {
|
|
159
|
+
required: false,
|
|
160
|
+
content: {
|
|
161
|
+
"multipart/form-data": {
|
|
162
|
+
schema: {
|
|
163
|
+
properties: {file1: {type: "array", items: {type: "string", format: "binary"}}},
|
|
164
|
+
type: "object"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
tags: ["TestController"]
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
tags: [{name: "TestController"}],
|
|
174
|
+
components: {
|
|
175
|
+
schemas: {
|
|
176
|
+
GenericError: {
|
|
177
|
+
additionalProperties: true,
|
|
178
|
+
properties: {
|
|
179
|
+
message: {
|
|
180
|
+
description: "An error message",
|
|
181
|
+
minLength: 1,
|
|
182
|
+
type: "string"
|
|
183
|
+
},
|
|
184
|
+
name: {
|
|
185
|
+
description: "The error name",
|
|
186
|
+
minLength: 1,
|
|
187
|
+
type: "string"
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
required: ["name", "message"],
|
|
191
|
+
type: "object"
|
|
192
|
+
},
|
|
193
|
+
BadRequest: {
|
|
194
|
+
type: "object",
|
|
195
|
+
properties: {
|
|
196
|
+
name: {
|
|
197
|
+
type: "string",
|
|
198
|
+
minLength: 1,
|
|
199
|
+
description: "The error name",
|
|
200
|
+
example: "BAD_REQUEST",
|
|
201
|
+
default: "BAD_REQUEST"
|
|
202
|
+
},
|
|
203
|
+
message: {
|
|
204
|
+
type: "string",
|
|
205
|
+
minLength: 1,
|
|
206
|
+
description: "An error message"
|
|
207
|
+
},
|
|
208
|
+
status: {type: "number", description: "The status code of the exception", example: 400, default: 400},
|
|
209
|
+
errors: {
|
|
210
|
+
type: "array",
|
|
211
|
+
items: {
|
|
212
|
+
$ref: "#/components/schemas/GenericError"
|
|
213
|
+
},
|
|
214
|
+
description: "A list of related errors"
|
|
215
|
+
},
|
|
216
|
+
stack: {
|
|
217
|
+
type: "string",
|
|
218
|
+
description: "The stack trace (only in development mode)"
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
required: ["name", "message", "status"]
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
describe("multiple files", () => {
|
|
230
|
+
afterAll(() => {
|
|
231
|
+
vi.clearAllMocks();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it("should set params metadata", () => {
|
|
235
|
+
const store = Store.from(Test.prototype, "test", descriptorOf(Test.prototype, "test"));
|
|
236
|
+
store.delete("multipartAdded");
|
|
237
|
+
|
|
238
|
+
// @ts-ignore
|
|
239
|
+
store.delete(PlatformMulterMiddleware);
|
|
240
|
+
vi.spyOn(Store, "fromMethod").mockReturnValue(store);
|
|
241
|
+
vi.spyOn(Metadata, "getParamTypes").mockReturnValue([Array]);
|
|
242
|
+
|
|
243
|
+
MultipartFile("file1", 8)(Test.prototype, "test", 0);
|
|
244
|
+
|
|
245
|
+
expect(store.get(PlatformMulterMiddleware)).toEqual({
|
|
246
|
+
fields: [
|
|
247
|
+
{
|
|
248
|
+
maxCount: 8,
|
|
249
|
+
name: "file1"
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
const param = JsonParameterStore.get(Test, "test", 0);
|
|
255
|
+
expect(param.expression).toEqual("file1");
|
|
256
|
+
expect(param.paramType).toEqual(ParamTypes.FILES);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {DecoratorParameters, Metadata, StoreMerge, useDecorators, useMethodDecorators} from "@tsed/core";
|
|
2
|
+
import {ParamTypes, UseParam} from "@tsed/platform-params";
|
|
3
|
+
import {InFile} from "@tsed/schema";
|
|
4
|
+
|
|
5
|
+
import {PlatformMulterFile} from "../../config/interfaces/PlatformMulterSettings.js";
|
|
6
|
+
import {MulterInputOptions, PlatformMulterMiddleware} from "../../middlewares/PlatformMulterMiddleware.js";
|
|
7
|
+
|
|
8
|
+
function mapOptions(name: string, maxCount: number | undefined): MulterInputOptions {
|
|
9
|
+
return {
|
|
10
|
+
fields: [
|
|
11
|
+
{
|
|
12
|
+
name,
|
|
13
|
+
maxCount
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Define a parameter as Multipart file.
|
|
21
|
+
*
|
|
22
|
+
* ```typescript
|
|
23
|
+
* import {Post} from "@tsed/schema";
|
|
24
|
+
* import {Controller, MulterOptions, MultipartFile} from "@tsed/platform-http";
|
|
25
|
+
* import {Controller} from "@tsed/di";
|
|
26
|
+
* import {Multer} from "@types/multer";
|
|
27
|
+
*
|
|
28
|
+
* type MulterFile = Express.Multer.File;
|
|
29
|
+
*
|
|
30
|
+
* @Controller('/')
|
|
31
|
+
* class MyCtrl {
|
|
32
|
+
* @Post('/file')
|
|
33
|
+
* private uploadFile(@MultipartFile("file1") file: MulterFile) {
|
|
34
|
+
*
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* @Post('/file')
|
|
38
|
+
* @MulterOptions({dest: "/other-dir"})
|
|
39
|
+
* private uploadFile(@MultipartFile("file1") file: MulterFile) {
|
|
40
|
+
*
|
|
41
|
+
* }
|
|
42
|
+
*
|
|
43
|
+
* @Post('/file2')
|
|
44
|
+
* @MulterOptions({dest: "/other-dir"})
|
|
45
|
+
* private uploadFile(@MultipartFile("file1") file: MulterFile, @MultipartFile("file2") file2: MulterFile) {
|
|
46
|
+
*
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* @Post('/files')
|
|
50
|
+
* private uploadFile(@MultipartFile("file1") files: MulterFile[]) {
|
|
51
|
+
*
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* > See the tutorial on the [multer configuration](/docs/upload-files.md).
|
|
57
|
+
*
|
|
58
|
+
* @param name
|
|
59
|
+
* @param maxCount
|
|
60
|
+
* @returns Function
|
|
61
|
+
* @decorator
|
|
62
|
+
* @input
|
|
63
|
+
*/
|
|
64
|
+
export function MultipartFile(name: string, maxCount?: number): ParameterDecorator {
|
|
65
|
+
return (...args: DecoratorParameters): void => {
|
|
66
|
+
const [target, propertyKey, index] = args;
|
|
67
|
+
const multiple = Metadata.getParamTypes(target, propertyKey)[index as number] === Array;
|
|
68
|
+
|
|
69
|
+
name = (typeof name === "object" ? undefined : name)!;
|
|
70
|
+
|
|
71
|
+
const expression = [name, !multiple && "0"].filter(Boolean).join(".");
|
|
72
|
+
|
|
73
|
+
const decorators = useDecorators(
|
|
74
|
+
InFile(name),
|
|
75
|
+
useMethodDecorators(StoreMerge(PlatformMulterMiddleware, mapOptions(name, maxCount))),
|
|
76
|
+
UseParam({
|
|
77
|
+
paramType: ParamTypes.FILES,
|
|
78
|
+
dataPath: "$ctx.request.files",
|
|
79
|
+
expression,
|
|
80
|
+
useValidation: true
|
|
81
|
+
})
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
decorators(...args);
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type MultipartFile = PlatformMulterFile;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {ParamTypes} from "@tsed/platform-params";
|
|
2
|
+
import {JsonParameterStore} from "@tsed/schema";
|
|
3
|
+
|
|
4
|
+
import {Err} from "./error.js";
|
|
5
|
+
|
|
6
|
+
describe("@Err", () => {
|
|
7
|
+
it("should register a new parameter instance with the correct property", () => {
|
|
8
|
+
class Ctrl {
|
|
9
|
+
test(@Err() arg: unknown) {}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const param = JsonParameterStore.get(Ctrl, "test", 0);
|
|
13
|
+
expect(param.paramType).toEqual(ParamTypes.ERR);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {ParamTypes, UseParam} from "@tsed/platform-params";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @returns {Function}
|
|
5
|
+
* @decorator
|
|
6
|
+
* @operation
|
|
7
|
+
* @input
|
|
8
|
+
*/
|
|
9
|
+
export function Err(): Function {
|
|
10
|
+
return UseParam({
|
|
11
|
+
paramType: ParamTypes.ERR,
|
|
12
|
+
dataPath: "$ctx.error",
|
|
13
|
+
useValidation: false,
|
|
14
|
+
useMapper: false
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {ParamTypes} from "@tsed/platform-params";
|
|
2
|
+
import {JsonParameterStore} from "@tsed/schema";
|
|
3
|
+
|
|
4
|
+
import {Next} from "./next.js";
|
|
5
|
+
|
|
6
|
+
describe("@Next", () => {
|
|
7
|
+
it("should register a new parameter instance with the correct property", () => {
|
|
8
|
+
class Ctrl {
|
|
9
|
+
test(@Next() arg: any) {}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const param = JsonParameterStore.get(Ctrl, "test", 0);
|
|
13
|
+
expect(param.paramType).toEqual(ParamTypes.NEXT_FN);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {ParamTypes, UseParam} from "@tsed/platform-params";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get the Next function (for express application and middleware).
|
|
5
|
+
*
|
|
6
|
+
* @decorator
|
|
7
|
+
* @operation
|
|
8
|
+
* @input
|
|
9
|
+
*/
|
|
10
|
+
export function Next(): ParameterDecorator {
|
|
11
|
+
return UseParam({
|
|
12
|
+
paramType: ParamTypes.NEXT_FN,
|
|
13
|
+
dataPath: "next",
|
|
14
|
+
useMapper: false,
|
|
15
|
+
useValidation: false
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare global {
|
|
20
|
+
namespace TsED {
|
|
21
|
+
export interface NextFunction extends Function {}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get the Next function (for express application and middleware).
|
|
26
|
+
*
|
|
27
|
+
* @decorator
|
|
28
|
+
* @operation
|
|
29
|
+
* @input
|
|
30
|
+
*/
|
|
31
|
+
export type Next = TsED.NextFunction;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {ParamTypes} from "@tsed/platform-params";
|
|
2
|
+
import {JsonParameterStore} from "@tsed/schema";
|
|
3
|
+
import {IncomingMessage} from "http";
|
|
4
|
+
|
|
5
|
+
import {PlatformRequest} from "../../services/PlatformRequest.js";
|
|
6
|
+
import {Req, Request} from "./request.js";
|
|
7
|
+
|
|
8
|
+
describe("@Req", () => {
|
|
9
|
+
it("should register a new parameter instance with the correct property (RawRequest)", () => {
|
|
10
|
+
class Ctrl {
|
|
11
|
+
test(@Request() arg: Req) {}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const param = JsonParameterStore.get(Ctrl, "test", 0);
|
|
15
|
+
expect(param.paramType).toEqual(ParamTypes.REQUEST);
|
|
16
|
+
expect(param.type).toEqual(Req);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("should register a new parameter instance with the correct property (RawRequest with expression)", () => {
|
|
20
|
+
class Ctrl {
|
|
21
|
+
test(@Req("user") arg: Req) {}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const param = JsonParameterStore.get(Ctrl, "test", 0);
|
|
25
|
+
expect(param.paramType).toEqual(ParamTypes.REQUEST);
|
|
26
|
+
expect(param.expression).toEqual("user");
|
|
27
|
+
expect(param.type).toEqual(Req);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should register a new parameter instance with the correct property (PlatformRequest)", () => {
|
|
31
|
+
class Ctrl {
|
|
32
|
+
test(@Req() arg: PlatformRequest) {}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const param = JsonParameterStore.get(Ctrl, "test", 0);
|
|
36
|
+
expect(param.paramType).toEqual(ParamTypes.PLATFORM_REQUEST);
|
|
37
|
+
expect(param.type).toEqual(PlatformRequest);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should register a new parameter instance with the correct property (IncomingMessage)", () => {
|
|
41
|
+
class Ctrl {
|
|
42
|
+
test(@Req() arg: IncomingMessage) {}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const param = JsonParameterStore.get(Ctrl, "test", 0);
|
|
46
|
+
expect(param.paramType).toEqual(ParamTypes.NODE_REQUEST);
|
|
47
|
+
expect(param.type).toEqual(IncomingMessage);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {isClass, Metadata, nameOf, Type} from "@tsed/core";
|
|
2
|
+
import {mapParamsOptions, ParamOptions, ParamTypes, UseParam} from "@tsed/platform-params";
|
|
3
|
+
import {IncomingMessage} from "http";
|
|
4
|
+
|
|
5
|
+
function getParamType(target: Object, propertyKey: string | symbol | undefined, parameterIndex: number) {
|
|
6
|
+
const type = Metadata.getOwnParamTypes(target, propertyKey)[parameterIndex];
|
|
7
|
+
|
|
8
|
+
if (isClass(type)) {
|
|
9
|
+
if (nameOf(type) === "PlatformRequest") {
|
|
10
|
+
return {paramType: ParamTypes.PLATFORM_REQUEST, dataPath: "$ctx.request"};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (type === IncomingMessage) {
|
|
14
|
+
return {paramType: ParamTypes.NODE_REQUEST, dataPath: "$ctx.request.req"};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return {paramType: ParamTypes.REQUEST, dataPath: "$ctx.request.request"};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Request service.
|
|
23
|
+
*
|
|
24
|
+
* @decorator
|
|
25
|
+
* @operation
|
|
26
|
+
* @input
|
|
27
|
+
*/
|
|
28
|
+
export function Request(expression: string, useType: Type<any>): ParameterDecorator;
|
|
29
|
+
export function Request(expression: string): ParameterDecorator;
|
|
30
|
+
export function Request(useType: Type<any>): ParameterDecorator;
|
|
31
|
+
export function Request(options: ParamOptions<any>): ParameterDecorator;
|
|
32
|
+
export function Request(): ParameterDecorator;
|
|
33
|
+
export function Request(...args: any[]): ParameterDecorator {
|
|
34
|
+
// @ts-ignore
|
|
35
|
+
return Req(...args);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Request service.
|
|
40
|
+
*
|
|
41
|
+
* @alias Request
|
|
42
|
+
* @decorator
|
|
43
|
+
* @operation
|
|
44
|
+
* @input
|
|
45
|
+
*/
|
|
46
|
+
export function Req(expression: string, useType: Type<any>): ParameterDecorator;
|
|
47
|
+
export function Req(expression: string): ParameterDecorator;
|
|
48
|
+
export function Req(useType: Type<any>): ParameterDecorator;
|
|
49
|
+
export function Req(options: Partial<ParamOptions>): ParameterDecorator;
|
|
50
|
+
export function Req(): ParameterDecorator;
|
|
51
|
+
export function Req(...args: any[]): ParameterDecorator {
|
|
52
|
+
const {expression, useType, useMapper = false, useValidation = false} = mapParamsOptions(args);
|
|
53
|
+
|
|
54
|
+
return (target, propertyKey, parameterIndex) => {
|
|
55
|
+
const {paramType, dataPath} = getParamType(target, propertyKey, parameterIndex);
|
|
56
|
+
|
|
57
|
+
UseParam({
|
|
58
|
+
paramType,
|
|
59
|
+
dataPath,
|
|
60
|
+
expression,
|
|
61
|
+
useType,
|
|
62
|
+
useMapper,
|
|
63
|
+
useValidation
|
|
64
|
+
})(target, propertyKey, parameterIndex);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Request service.
|
|
70
|
+
*
|
|
71
|
+
* @decorator
|
|
72
|
+
* @operation
|
|
73
|
+
* @input
|
|
74
|
+
*/
|
|
75
|
+
export interface Request extends TsED.Request {}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Request service.
|
|
79
|
+
*
|
|
80
|
+
* @alias Request
|
|
81
|
+
* @decorator
|
|
82
|
+
* @operation
|
|
83
|
+
* @input
|
|
84
|
+
*/
|
|
85
|
+
export interface Req extends Request {}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {ParamTypes} from "@tsed/platform-params";
|
|
2
|
+
import {JsonParameterStore} from "@tsed/schema";
|
|
3
|
+
import {ServerResponse} from "http";
|
|
4
|
+
|
|
5
|
+
import {PlatformResponse} from "../../services/PlatformResponse.js";
|
|
6
|
+
import {Res, Response} from "./response.js";
|
|
7
|
+
|
|
8
|
+
describe("@Res", () => {
|
|
9
|
+
it("should register a new parameter instance with the correct property (RawRes)", () => {
|
|
10
|
+
class Ctrl {
|
|
11
|
+
test(@Response() arg: Response) {}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const param = JsonParameterStore.get(Ctrl, "test", 0);
|
|
15
|
+
expect(param.paramType).toEqual(ParamTypes.RESPONSE);
|
|
16
|
+
expect(param.type).toEqual(Response);
|
|
17
|
+
});
|
|
18
|
+
it("should register a new parameter instance with the correct property (PlatformResponse)", () => {
|
|
19
|
+
class Ctrl {
|
|
20
|
+
test(@Response() arg: PlatformResponse) {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const param = JsonParameterStore.get(Ctrl, "test", 0);
|
|
24
|
+
expect(param.paramType).toEqual(ParamTypes.PLATFORM_RESPONSE);
|
|
25
|
+
expect(param.type).toEqual(PlatformResponse);
|
|
26
|
+
});
|
|
27
|
+
it("should register a new parameter instance with the correct property (ServerResponse)", () => {
|
|
28
|
+
class Ctrl {
|
|
29
|
+
test(@Response() arg: ServerResponse) {}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const param = JsonParameterStore.get(Ctrl, "test", 0);
|
|
33
|
+
expect(param.paramType).toEqual(ParamTypes.NODE_RESPONSE);
|
|
34
|
+
expect(param.type).toEqual(ServerResponse);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {isClass, Metadata, nameOf} from "@tsed/core";
|
|
2
|
+
import {ParamTypes, UseParam} from "@tsed/platform-params";
|
|
3
|
+
import {ServerResponse} from "http";
|
|
4
|
+
|
|
5
|
+
function getParamType(target: Object, propertyKey: string | symbol | undefined, parameterIndex: number) {
|
|
6
|
+
const type = Metadata.getOwnParamTypes(target, propertyKey)[parameterIndex];
|
|
7
|
+
|
|
8
|
+
if (isClass(type)) {
|
|
9
|
+
if (nameOf(type) === "PlatformResponse") {
|
|
10
|
+
return {paramType: ParamTypes.PLATFORM_RESPONSE, dataPath: "$ctx.response"};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (type === ServerResponse) {
|
|
14
|
+
return {paramType: ParamTypes.NODE_RESPONSE, dataPath: "$ctx.response.res"};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return {paramType: ParamTypes.RESPONSE, dataPath: "$ctx.response.response"};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Response service.
|
|
23
|
+
*
|
|
24
|
+
* @decorator
|
|
25
|
+
* @operation
|
|
26
|
+
* @input
|
|
27
|
+
* @response
|
|
28
|
+
*/
|
|
29
|
+
export function Response(): ParameterDecorator;
|
|
30
|
+
export function Response(): ParameterDecorator {
|
|
31
|
+
return Res();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Request service.
|
|
36
|
+
*
|
|
37
|
+
* @alias Response
|
|
38
|
+
* @decorator
|
|
39
|
+
* @operation
|
|
40
|
+
* @input
|
|
41
|
+
* @response
|
|
42
|
+
*/
|
|
43
|
+
export function Res(): ParameterDecorator;
|
|
44
|
+
export function Res(): ParameterDecorator {
|
|
45
|
+
return (target, propertyKey, parameterIndex) => {
|
|
46
|
+
const {paramType, dataPath} = getParamType(target, propertyKey, parameterIndex);
|
|
47
|
+
UseParam({
|
|
48
|
+
paramType,
|
|
49
|
+
dataPath
|
|
50
|
+
})(target, propertyKey, parameterIndex);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Response service.
|
|
56
|
+
*
|
|
57
|
+
* @decorator
|
|
58
|
+
* @operation
|
|
59
|
+
* @input
|
|
60
|
+
* @response
|
|
61
|
+
*/
|
|
62
|
+
export interface Response extends TsED.Response {}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Response service.
|
|
66
|
+
*
|
|
67
|
+
* @alias Response
|
|
68
|
+
* @decorator
|
|
69
|
+
* @operation
|
|
70
|
+
* @input
|
|
71
|
+
* @response
|
|
72
|
+
*/
|
|
73
|
+
export interface Res extends Response {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {PlatformTest} from "../../testing/PlatformTest.js";
|
|
2
|
+
import {AnyToPromiseWithCtx} from "./AnyToPromiseWithCtx.js";
|
|
3
|
+
|
|
4
|
+
describe("AnyToPromiseWithCtx", () => {
|
|
5
|
+
beforeEach(() => PlatformTest.create());
|
|
6
|
+
afterEach(() => PlatformTest.reset());
|
|
7
|
+
|
|
8
|
+
it("should return value", async () => {
|
|
9
|
+
const $ctx = PlatformTest.createRequestContext();
|
|
10
|
+
const resolver = new AnyToPromiseWithCtx($ctx);
|
|
11
|
+
|
|
12
|
+
const result = await resolver.call(() => "hello");
|
|
13
|
+
|
|
14
|
+
expect(result).toEqual({
|
|
15
|
+
data: "hello",
|
|
16
|
+
state: "RESOLVED",
|
|
17
|
+
type: "DATA"
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
});
|