@tsed/platform-params 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/package.json +14 -13
- package/src/builder/PlatformParams.spec.ts +431 -0
- package/src/builder/PlatformParams.ts +86 -0
- package/src/decorators/bodyParams.spec.ts +121 -0
- package/src/decorators/bodyParams.ts +93 -0
- package/src/decorators/context.spec.ts +16 -0
- package/src/decorators/context.ts +70 -0
- package/src/decorators/cookies.spec.ts +19 -0
- package/src/decorators/cookies.ts +102 -0
- package/src/decorators/headerParams.spec.ts +16 -0
- package/src/decorators/headerParams.ts +49 -0
- package/src/decorators/locals.spec.ts +16 -0
- package/src/decorators/locals.ts +57 -0
- package/src/decorators/paramFn.ts +14 -0
- package/src/decorators/pathParams.spec.ts +58 -0
- package/src/decorators/pathParams.ts +97 -0
- package/src/decorators/queryParams.spec.ts +58 -0
- package/src/decorators/queryParams.ts +102 -0
- package/src/decorators/session.spec.ts +47 -0
- package/src/decorators/session.ts +51 -0
- package/src/decorators/useDeserialization.ts +14 -0
- package/src/decorators/useParam.spec.ts +82 -0
- package/src/decorators/useParam.ts +38 -0
- package/src/decorators/useParamExpression.ts +16 -0
- package/src/decorators/useParamType.ts +36 -0
- package/src/decorators/usePipe.ts +21 -0
- package/src/decorators/useType.ts +35 -0
- package/src/decorators/useValidation.ts +18 -0
- package/src/domain/ParamMetadata.ts +1 -0
- package/src/domain/ParamOptions.ts +12 -0
- package/src/domain/ParamTypes.ts +37 -0
- package/src/errors/ParamValidationError.spec.ts +152 -0
- package/src/errors/ParamValidationError.ts +38 -0
- package/src/errors/RequiredValidationError.spec.ts +49 -0
- package/src/errors/RequiredValidationError.ts +30 -0
- package/src/errors/ValidationError.spec.ts +18 -0
- package/src/errors/ValidationError.ts +11 -0
- package/src/exports.ts +1 -0
- package/src/index.ts +31 -0
- package/src/pipes/DeserializerPipe.spec.ts +39 -0
- package/src/pipes/DeserializerPipe.ts +15 -0
- package/src/pipes/ParseExpressionPipe.spec.ts +242 -0
- package/src/pipes/ParseExpressionPipe.ts +33 -0
- package/src/pipes/ValidationPipe.spec.ts +645 -0
- package/src/pipes/ValidationPipe.ts +112 -0
- package/src/utils/mapParamsOptions.spec.ts +28 -0
- package/src/utils/mapParamsOptions.ts +34 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {nameOf} from "@tsed/core";
|
|
2
|
+
import {BadRequest} from "@tsed/exceptions";
|
|
3
|
+
import {JsonParameterStore} from "@tsed/schema";
|
|
4
|
+
|
|
5
|
+
import {ValidationError} from "./ValidationError.js";
|
|
6
|
+
|
|
7
|
+
export class ParamValidationError extends BadRequest {
|
|
8
|
+
public name: string = "PARAM_VALIDATION_ERROR";
|
|
9
|
+
public dataPath: string;
|
|
10
|
+
public requestType: string;
|
|
11
|
+
|
|
12
|
+
static from(metadata: JsonParameterStore, origin: any = {}) {
|
|
13
|
+
if (origin instanceof ValidationError || origin instanceof BadRequest) {
|
|
14
|
+
const name = nameOf(metadata.paramType)
|
|
15
|
+
.toLowerCase()
|
|
16
|
+
.replace(/parse|params|filter/gi, "");
|
|
17
|
+
const expression = metadata.expression;
|
|
18
|
+
const dataPath = `${name}${expression ? "." + expression : ""}`;
|
|
19
|
+
const message = `Bad request on parameter "request.${dataPath}".\n${origin.message}`.trim();
|
|
20
|
+
|
|
21
|
+
const error = new ParamValidationError(message);
|
|
22
|
+
error.dataPath = String(metadata.expression) || "";
|
|
23
|
+
error.requestType = nameOf(metadata.paramType);
|
|
24
|
+
error.origin = origin.origin || origin;
|
|
25
|
+
|
|
26
|
+
if (error.origin?.errors) {
|
|
27
|
+
error.origin?.errors.forEach((error: any) => {
|
|
28
|
+
error.requestPath = name;
|
|
29
|
+
error.dataPath = error.dataPath || (expression ? `.${expression}` : "");
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return error;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return origin;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {RequiredValidationError} from "./RequiredValidationError.js";
|
|
2
|
+
|
|
3
|
+
describe("RequiredValidationError", () => {
|
|
4
|
+
it("should have a message", () => {
|
|
5
|
+
const error = RequiredValidationError.from({
|
|
6
|
+
paramType: "name",
|
|
7
|
+
expression: "expression"
|
|
8
|
+
} as any);
|
|
9
|
+
expect(error.message).toEqual("It should have required parameter 'expression'");
|
|
10
|
+
expect(error.name).toEqual("REQUIRED_VALIDATION_ERROR");
|
|
11
|
+
expect({
|
|
12
|
+
name: error.name,
|
|
13
|
+
status: error.status,
|
|
14
|
+
headers: error.headers,
|
|
15
|
+
type: error.type,
|
|
16
|
+
message: error.message,
|
|
17
|
+
errors: [
|
|
18
|
+
{
|
|
19
|
+
dataPath: error.errors[0].dataPath,
|
|
20
|
+
keyword: error.errors[0].keyword,
|
|
21
|
+
message: error.errors[0].message,
|
|
22
|
+
modelName: error.errors[0].modelName,
|
|
23
|
+
params: {
|
|
24
|
+
missingProperty: error.errors[0].params.missingProperty
|
|
25
|
+
},
|
|
26
|
+
schemaPath: error.errors[0].schemaPath
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}).toEqual({
|
|
30
|
+
name: "REQUIRED_VALIDATION_ERROR",
|
|
31
|
+
status: 400,
|
|
32
|
+
headers: {},
|
|
33
|
+
type: "HTTP_EXCEPTION",
|
|
34
|
+
message: "It should have required parameter 'expression'",
|
|
35
|
+
errors: [
|
|
36
|
+
{
|
|
37
|
+
dataPath: "",
|
|
38
|
+
keyword: "required",
|
|
39
|
+
message: "It should have required parameter 'expression'",
|
|
40
|
+
modelName: "name",
|
|
41
|
+
params: {
|
|
42
|
+
missingProperty: "expression"
|
|
43
|
+
},
|
|
44
|
+
schemaPath: "#/required"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {nameOf} from "@tsed/core";
|
|
2
|
+
import {JsonParameterStore} from "@tsed/schema";
|
|
3
|
+
|
|
4
|
+
import {ValidationError} from "./ValidationError.js";
|
|
5
|
+
|
|
6
|
+
export class RequiredValidationError extends ValidationError {
|
|
7
|
+
public name: string = "REQUIRED_VALIDATION_ERROR";
|
|
8
|
+
|
|
9
|
+
static from(metadata: JsonParameterStore) {
|
|
10
|
+
const name = nameOf(metadata.paramType);
|
|
11
|
+
const expression = metadata.expression;
|
|
12
|
+
const type = name.toLowerCase().replace(/parse|params|filter/gi, "");
|
|
13
|
+
const message = `It should have required parameter '${expression}'`;
|
|
14
|
+
|
|
15
|
+
const errors = [
|
|
16
|
+
{
|
|
17
|
+
dataPath: "",
|
|
18
|
+
keyword: "required",
|
|
19
|
+
message,
|
|
20
|
+
modelName: type,
|
|
21
|
+
params: {
|
|
22
|
+
missingProperty: expression
|
|
23
|
+
},
|
|
24
|
+
schemaPath: "#/required"
|
|
25
|
+
}
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
return new RequiredValidationError(message, errors);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {ValidationError} from "./ValidationError.js";
|
|
2
|
+
|
|
3
|
+
describe("ValidationError", () => {
|
|
4
|
+
it("should return error", () => {
|
|
5
|
+
const error = new ValidationError("should have required property", [
|
|
6
|
+
{
|
|
7
|
+
dataPath: "hello"
|
|
8
|
+
}
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
expect(error.errors).toEqual([
|
|
12
|
+
{
|
|
13
|
+
dataPath: "hello"
|
|
14
|
+
}
|
|
15
|
+
]);
|
|
16
|
+
expect(error.message).toEqual("should have required property");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {BadRequest} from "@tsed/exceptions";
|
|
2
|
+
|
|
3
|
+
export class ValidationError extends BadRequest {
|
|
4
|
+
public name: string = "VALIDATION_ERROR";
|
|
5
|
+
public errors: any[];
|
|
6
|
+
|
|
7
|
+
constructor(message: string, errors: any[] = []) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.errors = errors;
|
|
10
|
+
}
|
|
11
|
+
}
|
package/src/exports.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {PipeMethods} from "@tsed/schema";
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Automatically generated by @tsed/barrels.
|
|
3
|
+
*/
|
|
4
|
+
export * from "./builder/PlatformParams.js";
|
|
5
|
+
export * from "./decorators/bodyParams.js";
|
|
6
|
+
export * from "./decorators/context.js";
|
|
7
|
+
export * from "./decorators/cookies.js";
|
|
8
|
+
export * from "./decorators/headerParams.js";
|
|
9
|
+
export * from "./decorators/locals.js";
|
|
10
|
+
export * from "./decorators/paramFn.js";
|
|
11
|
+
export * from "./decorators/pathParams.js";
|
|
12
|
+
export * from "./decorators/queryParams.js";
|
|
13
|
+
export * from "./decorators/session.js";
|
|
14
|
+
export * from "./decorators/useDeserialization.js";
|
|
15
|
+
export * from "./decorators/useParam.js";
|
|
16
|
+
export * from "./decorators/useParamExpression.js";
|
|
17
|
+
export * from "./decorators/useParamType.js";
|
|
18
|
+
export * from "./decorators/usePipe.js";
|
|
19
|
+
export * from "./decorators/useType.js";
|
|
20
|
+
export * from "./decorators/useValidation.js";
|
|
21
|
+
export * from "./domain/ParamMetadata.js";
|
|
22
|
+
export * from "./domain/ParamOptions.js";
|
|
23
|
+
export * from "./domain/ParamTypes.js";
|
|
24
|
+
export * from "./errors/ParamValidationError.js";
|
|
25
|
+
export * from "./errors/RequiredValidationError.js";
|
|
26
|
+
export * from "./errors/ValidationError.js";
|
|
27
|
+
export * from "./exports.js";
|
|
28
|
+
export * from "./pipes/DeserializerPipe.js";
|
|
29
|
+
export * from "./pipes/ParseExpressionPipe.js";
|
|
30
|
+
export * from "./pipes/ValidationPipe.js";
|
|
31
|
+
export * from "./utils/mapParamsOptions.js";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {PlatformTest} from "@tsed/platform-http/testing";
|
|
2
|
+
import {JsonParameterStore} from "@tsed/schema";
|
|
3
|
+
|
|
4
|
+
import {BodyParams} from "../decorators/bodyParams.js";
|
|
5
|
+
import {QueryParams} from "../decorators/queryParams.js";
|
|
6
|
+
import {DeserializerPipe} from "./DeserializerPipe.js";
|
|
7
|
+
|
|
8
|
+
describe("DeserializerPipe", () => {
|
|
9
|
+
beforeEach(PlatformTest.create);
|
|
10
|
+
afterEach(PlatformTest.reset);
|
|
11
|
+
it("should transform an object to a model", async () => {
|
|
12
|
+
const pipe = await PlatformTest.get<DeserializerPipe>(DeserializerPipe);
|
|
13
|
+
|
|
14
|
+
class Test {
|
|
15
|
+
test(@BodyParams(String) input: string[]) {}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const param = JsonParameterStore.get(Test, "test", 0);
|
|
19
|
+
|
|
20
|
+
// WHEN
|
|
21
|
+
const result = pipe.transform(["test"], param);
|
|
22
|
+
|
|
23
|
+
expect(result).toEqual(["test"]);
|
|
24
|
+
});
|
|
25
|
+
it("should transform an object to a model (Query)", async () => {
|
|
26
|
+
const pipe = await PlatformTest.get<DeserializerPipe>(DeserializerPipe);
|
|
27
|
+
|
|
28
|
+
class Test {
|
|
29
|
+
test(@QueryParams("test", String) input: string[]) {}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const param = JsonParameterStore.get(Test, "test", 0);
|
|
33
|
+
|
|
34
|
+
// WHEN
|
|
35
|
+
const result = pipe.transform(["test"], param);
|
|
36
|
+
|
|
37
|
+
expect(result).toEqual(["test"]);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {Injectable, injectable} from "@tsed/di";
|
|
2
|
+
import {deserialize} from "@tsed/json-mapper";
|
|
3
|
+
import {JsonParameterStore, PipeMethods} from "@tsed/schema";
|
|
4
|
+
|
|
5
|
+
export class DeserializerPipe implements PipeMethods {
|
|
6
|
+
transform(value: any, param: JsonParameterStore) {
|
|
7
|
+
return deserialize(value, {
|
|
8
|
+
useAlias: true,
|
|
9
|
+
store: param,
|
|
10
|
+
...(param.store.get(DeserializerPipe) || {})
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
injectable(DeserializerPipe);
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import {DecoratorTypes} from "@tsed/core";
|
|
2
|
+
import {PlatformTest} from "@tsed/platform-http/testing";
|
|
3
|
+
import {JsonParameterStore} from "@tsed/schema";
|
|
4
|
+
|
|
5
|
+
import {ParamTypes} from "../../src/index.js";
|
|
6
|
+
import {ParseExpressionPipe} from "./ParseExpressionPipe.js";
|
|
7
|
+
|
|
8
|
+
describe("ParseExpressionPipe", () => {
|
|
9
|
+
beforeEach(PlatformTest.create);
|
|
10
|
+
beforeEach(PlatformTest.reset);
|
|
11
|
+
it(
|
|
12
|
+
"should parse expression",
|
|
13
|
+
PlatformTest.inject([ParseExpressionPipe], (pipe: ParseExpressionPipe) => {
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
class Test {}
|
|
16
|
+
|
|
17
|
+
const param: any = new JsonParameterStore({
|
|
18
|
+
index: 0,
|
|
19
|
+
target: Test,
|
|
20
|
+
propertyKey: "test",
|
|
21
|
+
expression: "test",
|
|
22
|
+
paramType: ParamTypes.REQUEST,
|
|
23
|
+
dataPath: "$ctx.request",
|
|
24
|
+
decoratorType: DecoratorTypes.PARAM
|
|
25
|
+
});
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
param._type = String;
|
|
28
|
+
param.collectionType = Array;
|
|
29
|
+
|
|
30
|
+
const scope: any = {
|
|
31
|
+
$ctx: {
|
|
32
|
+
request: {
|
|
33
|
+
test: "value"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// WHEN
|
|
39
|
+
const value = pipe.transform(scope, param);
|
|
40
|
+
|
|
41
|
+
expect(value).toEqual("value");
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
it(
|
|
45
|
+
"should return empty value",
|
|
46
|
+
PlatformTest.inject([ParseExpressionPipe], (pipe: ParseExpressionPipe) => {
|
|
47
|
+
// @ts-ignore
|
|
48
|
+
class Test {}
|
|
49
|
+
|
|
50
|
+
const param: any = new JsonParameterStore({
|
|
51
|
+
index: 0,
|
|
52
|
+
target: Test,
|
|
53
|
+
propertyKey: "test",
|
|
54
|
+
expression: "test",
|
|
55
|
+
paramType: ParamTypes.REQUEST,
|
|
56
|
+
dataPath: "$ctx.request",
|
|
57
|
+
decoratorType: DecoratorTypes.PARAM
|
|
58
|
+
});
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
param._type = String;
|
|
61
|
+
param.collectionType = Array;
|
|
62
|
+
|
|
63
|
+
const scope: any = {
|
|
64
|
+
$ctx: {
|
|
65
|
+
request: {}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// WHEN
|
|
70
|
+
const value = pipe.transform(scope, param);
|
|
71
|
+
|
|
72
|
+
expect(value).toEqual(undefined);
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
it(
|
|
76
|
+
"should parse expression (for HEADER)",
|
|
77
|
+
PlatformTest.inject([ParseExpressionPipe], (pipe: ParseExpressionPipe) => {
|
|
78
|
+
// @ts-ignore
|
|
79
|
+
class Test {}
|
|
80
|
+
|
|
81
|
+
const param: any = new JsonParameterStore({
|
|
82
|
+
index: 0,
|
|
83
|
+
target: Test,
|
|
84
|
+
propertyKey: "test",
|
|
85
|
+
expression: "Content-Type",
|
|
86
|
+
paramType: ParamTypes.HEADER,
|
|
87
|
+
dataPath: "$ctx.request.headers",
|
|
88
|
+
decoratorType: DecoratorTypes.PARAM
|
|
89
|
+
});
|
|
90
|
+
// @ts-ignore
|
|
91
|
+
param._type = String;
|
|
92
|
+
param.collectionType = Array;
|
|
93
|
+
|
|
94
|
+
const scope: any = {
|
|
95
|
+
$ctx: {
|
|
96
|
+
request: {
|
|
97
|
+
headers: {
|
|
98
|
+
"content-type": "application/json"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
// WHEN
|
|
104
|
+
const value = pipe.transform(scope, param);
|
|
105
|
+
|
|
106
|
+
expect(value).toEqual("application/json");
|
|
107
|
+
})
|
|
108
|
+
);
|
|
109
|
+
it(
|
|
110
|
+
"should return undefined when value is empty and Boolean (for QUERY)",
|
|
111
|
+
PlatformTest.inject([ParseExpressionPipe], (pipe: ParseExpressionPipe) => {
|
|
112
|
+
// @ts-ignore
|
|
113
|
+
class Test {}
|
|
114
|
+
|
|
115
|
+
const param = new JsonParameterStore({
|
|
116
|
+
index: 0,
|
|
117
|
+
target: Test,
|
|
118
|
+
propertyKey: "test",
|
|
119
|
+
expression: "test",
|
|
120
|
+
paramType: ParamTypes.QUERY,
|
|
121
|
+
dataPath: "$ctx.request.query",
|
|
122
|
+
decoratorType: DecoratorTypes.PARAM
|
|
123
|
+
});
|
|
124
|
+
// @ts-ignore
|
|
125
|
+
param._type = Boolean;
|
|
126
|
+
|
|
127
|
+
const scope: any = {
|
|
128
|
+
$ctx: {
|
|
129
|
+
request: {
|
|
130
|
+
query: {
|
|
131
|
+
test: ""
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
// WHEN
|
|
138
|
+
const value = pipe.transform(scope, param);
|
|
139
|
+
|
|
140
|
+
expect(value).toEqual(undefined);
|
|
141
|
+
})
|
|
142
|
+
);
|
|
143
|
+
it(
|
|
144
|
+
"should return empty when value is empty and String (for QUERY)",
|
|
145
|
+
PlatformTest.inject([ParseExpressionPipe], (pipe: ParseExpressionPipe) => {
|
|
146
|
+
// @ts-ignore
|
|
147
|
+
class Test {}
|
|
148
|
+
|
|
149
|
+
const param = new JsonParameterStore({
|
|
150
|
+
index: 0,
|
|
151
|
+
target: Test,
|
|
152
|
+
propertyKey: "test",
|
|
153
|
+
expression: "test",
|
|
154
|
+
paramType: ParamTypes.QUERY,
|
|
155
|
+
dataPath: "$ctx.request.query",
|
|
156
|
+
decoratorType: DecoratorTypes.PARAM
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const scope: any = {
|
|
160
|
+
$ctx: {
|
|
161
|
+
request: {
|
|
162
|
+
query: {
|
|
163
|
+
test: ""
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
// @ts-ignore
|
|
169
|
+
param._type = String;
|
|
170
|
+
// WHEN
|
|
171
|
+
const value = pipe.transform(scope, param);
|
|
172
|
+
|
|
173
|
+
expect(value).toEqual("");
|
|
174
|
+
})
|
|
175
|
+
);
|
|
176
|
+
it(
|
|
177
|
+
"should return undefined when value is empty and Boolean (for PATH)",
|
|
178
|
+
PlatformTest.inject([ParseExpressionPipe], (pipe: ParseExpressionPipe) => {
|
|
179
|
+
// @ts-ignore
|
|
180
|
+
class Test {}
|
|
181
|
+
|
|
182
|
+
const param = new JsonParameterStore({
|
|
183
|
+
index: 0,
|
|
184
|
+
target: Test,
|
|
185
|
+
propertyKey: "test",
|
|
186
|
+
expression: "test",
|
|
187
|
+
paramType: ParamTypes.PATH,
|
|
188
|
+
dataPath: "$ctx.request.params",
|
|
189
|
+
decoratorType: DecoratorTypes.PARAM
|
|
190
|
+
});
|
|
191
|
+
// @ts-ignore
|
|
192
|
+
param._type = Boolean;
|
|
193
|
+
|
|
194
|
+
const scope: any = {
|
|
195
|
+
$ctx: {
|
|
196
|
+
request: {
|
|
197
|
+
params: {
|
|
198
|
+
test: ""
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
// WHEN
|
|
204
|
+
const value = pipe.transform(scope, param);
|
|
205
|
+
|
|
206
|
+
expect(value).toEqual(undefined);
|
|
207
|
+
})
|
|
208
|
+
);
|
|
209
|
+
it(
|
|
210
|
+
"should return empty when value is empty and String (for PATH)",
|
|
211
|
+
PlatformTest.inject([ParseExpressionPipe], (pipe: ParseExpressionPipe) => {
|
|
212
|
+
// @ts-ignore
|
|
213
|
+
class Test {}
|
|
214
|
+
|
|
215
|
+
const param = new JsonParameterStore({
|
|
216
|
+
index: 0,
|
|
217
|
+
target: Test,
|
|
218
|
+
propertyKey: "test",
|
|
219
|
+
expression: "test",
|
|
220
|
+
paramType: ParamTypes.PATH,
|
|
221
|
+
dataPath: "$ctx.request.params",
|
|
222
|
+
decoratorType: DecoratorTypes.PARAM
|
|
223
|
+
});
|
|
224
|
+
// @ts-ignore
|
|
225
|
+
param._type = String;
|
|
226
|
+
|
|
227
|
+
const scope: any = {
|
|
228
|
+
$ctx: {
|
|
229
|
+
request: {
|
|
230
|
+
params: {
|
|
231
|
+
test: ""
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
// WHEN
|
|
237
|
+
const value = pipe.transform(scope, param);
|
|
238
|
+
|
|
239
|
+
expect(value).toEqual("");
|
|
240
|
+
})
|
|
241
|
+
);
|
|
242
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {getValue} from "@tsed/core";
|
|
2
|
+
import {Injectable, injectable} from "@tsed/di";
|
|
3
|
+
import {JsonParameterStore, PipeMethods} from "@tsed/schema";
|
|
4
|
+
|
|
5
|
+
import {PlatformParamsScope} from "../builder/PlatformParams.js";
|
|
6
|
+
import {ParamTypes} from "../domain/ParamTypes.js";
|
|
7
|
+
|
|
8
|
+
export class ParseExpressionPipe implements PipeMethods {
|
|
9
|
+
transform(scope: PlatformParamsScope, param: JsonParameterStore) {
|
|
10
|
+
const {paramType, type} = param;
|
|
11
|
+
|
|
12
|
+
const value = getValue(scope, this.getKey(param));
|
|
13
|
+
|
|
14
|
+
if ([ParamTypes.QUERY, ParamTypes.PATH].includes(paramType as ParamTypes) && value === "" && type !== String) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
protected getKey(param: JsonParameterStore) {
|
|
22
|
+
let {expression, paramType, dataPath} = param;
|
|
23
|
+
paramType = paramType || param.parameter.get("in").toUpperCase();
|
|
24
|
+
|
|
25
|
+
if (expression && paramType === ParamTypes.HEADER) {
|
|
26
|
+
expression = String(expression).toLowerCase();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return [dataPath, expression].filter(Boolean).join(".");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
injectable(ParseExpressionPipe).priority(-1000);
|