@nestia/core 1.4.5 → 1.5.0
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/lib/decorators/EncryptedRoute.d.ts +4 -4
- package/lib/decorators/EncryptedRoute.js +4 -4
- package/lib/decorators/TypedBody.d.ts +1 -1
- package/lib/decorators/TypedBody.js +1 -1
- package/lib/decorators/TypedHeaders.d.ts +42 -0
- package/lib/decorators/TypedHeaders.js +114 -0
- package/lib/decorators/TypedHeaders.js.map +1 -0
- package/lib/decorators/TypedQuery.d.ts +10 -3
- package/lib/decorators/TypedQuery.js +9 -2
- package/lib/decorators/TypedQuery.js.map +1 -1
- package/lib/decorators/TypedRoute.d.ts +5 -4
- package/lib/decorators/TypedRoute.js +5 -4
- package/lib/decorators/TypedRoute.js.map +1 -1
- package/lib/module.d.ts +1 -0
- package/lib/module.js +1 -0
- package/lib/module.js.map +1 -1
- package/lib/programmers/TypedHeadersProgrammer.d.ts +5 -0
- package/lib/programmers/TypedHeadersProgrammer.js +300 -0
- package/lib/programmers/TypedHeadersProgrammer.js.map +1 -0
- package/lib/programmers/TypedQueryProgrammer.js +11 -8
- package/lib/programmers/TypedQueryProgrammer.js.map +1 -1
- package/lib/transformers/ParameterDecoratorTransformer.js +6 -0
- package/lib/transformers/ParameterDecoratorTransformer.js.map +1 -1
- package/package.json +6 -6
- package/src/decorators/EncryptedRoute.ts +4 -4
- package/src/decorators/TypedBody.ts +1 -1
- package/src/decorators/TypedHeaders.ts +95 -0
- package/src/decorators/TypedQuery.ts +10 -3
- package/src/decorators/TypedRoute.ts +5 -4
- package/src/module.ts +1 -0
- package/src/programmers/TypedHeadersProgrammer.ts +304 -0
- package/src/programmers/TypedQueryProgrammer.ts +31 -25
- package/src/transformers/ParameterDecoratorTransformer.ts +5 -0
|
@@ -17,13 +17,20 @@ import { TransformError } from "./internal/TransformError";
|
|
|
17
17
|
* same with {@link nest.Query}, but it can automatically cast property type following
|
|
18
18
|
* its DTO definition. Also, `TypedQuery` performs type validation.
|
|
19
19
|
*
|
|
20
|
-
* For
|
|
21
|
-
*
|
|
20
|
+
* For reference, target type `T` must follw such restriction. Also, if actual URL
|
|
21
|
+
* query parameter values are different with their promised type `T`,
|
|
22
|
+
* `BadRequestException` error (status code: 400) would be thrown.
|
|
23
|
+
*
|
|
24
|
+
* 1. Type `T` must be an object type
|
|
25
|
+
* 2. Do not allow dynamic property
|
|
26
|
+
* 3. Prpoerty value cannot be `undefined`, but `null` is possible
|
|
27
|
+
* 4. Only `boolean`, `bigint`, `number`, `string` or their array types are allowed
|
|
28
|
+
* 5. By the way, union type never be not allowed
|
|
22
29
|
*
|
|
23
30
|
* @returns Parameter decorator
|
|
24
31
|
* @author Jeongho Nam - https://github.com/samchon
|
|
25
32
|
*/
|
|
26
|
-
export function TypedQuery<T>(
|
|
33
|
+
export function TypedQuery<T extends object>(
|
|
27
34
|
decoder?: (params: URLSearchParams) => T,
|
|
28
35
|
): ParameterDecorator {
|
|
29
36
|
if (decoder === undefined) throw TransformError("TypedQuery");
|
|
@@ -29,13 +29,14 @@ import { route_error } from "./internal/route_error";
|
|
|
29
29
|
* Type safe router decorator functions.
|
|
30
30
|
*
|
|
31
31
|
* `TypedRoute` is a module containing router decorator functions which can boost up
|
|
32
|
-
* JSON string conversion speed about
|
|
32
|
+
* JSON string conversion speed about 200x times faster than `class-transformer`.
|
|
33
33
|
* Furthermore, such JSON string conversion is even type safe through
|
|
34
34
|
* [typia](https://github.com/samchon/typia).
|
|
35
35
|
*
|
|
36
|
-
* For reference,
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* For reference, if you try to invalid data that is not following the promised
|
|
37
|
+
* type `T`, 500 internal server error would be thrown. Also, as `TypedRoute` composes
|
|
38
|
+
* JSON string through `typia.assertStringify<T>()` function, it is not possible to
|
|
39
|
+
* modify response data through interceptors.
|
|
39
40
|
*
|
|
40
41
|
* @author Jeongho Nam - https://github.com/samchon
|
|
41
42
|
*/
|
package/src/module.ts
CHANGED
|
@@ -6,6 +6,7 @@ export * from "./decorators/EncryptedRoute";
|
|
|
6
6
|
export * from "./utils/ExceptionManager";
|
|
7
7
|
export * from "./decorators/PlainBody";
|
|
8
8
|
export * from "./decorators/TypedBody";
|
|
9
|
+
export * from "./decorators/TypedHeaders";
|
|
9
10
|
export * from "./decorators/TypedParam";
|
|
10
11
|
export * from "./decorators/TypedRoute";
|
|
11
12
|
export * from "./decorators/TypedQuery";
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
|
|
4
|
+
import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
|
|
5
|
+
import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
|
|
6
|
+
import { StatementFactory } from "typia/lib/factories/StatementFactory";
|
|
7
|
+
import { Metadata } from "typia/lib/metadata/Metadata";
|
|
8
|
+
import { MetadataObject } from "typia/lib/metadata/MetadataObject";
|
|
9
|
+
import { MetadataProperty } from "typia/lib/metadata/MetadataProperty";
|
|
10
|
+
import { AssertProgrammer } from "typia/lib/programmers/AssertProgrammer";
|
|
11
|
+
import { FunctionImporter } from "typia/lib/programmers/helpers/FunctionImporeter";
|
|
12
|
+
import { Atomic } from "typia/lib/typings/Atomic";
|
|
13
|
+
import { Escaper } from "typia/lib/utils/Escaper";
|
|
14
|
+
|
|
15
|
+
import { INestiaTransformProject } from "../options/INestiaTransformProject";
|
|
16
|
+
|
|
17
|
+
export namespace TypedHeadersProgrammer {
|
|
18
|
+
export const generate =
|
|
19
|
+
(project: INestiaTransformProject) =>
|
|
20
|
+
(modulo: ts.LeftHandSideExpression) =>
|
|
21
|
+
(type: ts.Type): ts.Expression => {
|
|
22
|
+
const object: MetadataObject = getObject(project.checker)(type);
|
|
23
|
+
return decode(project, modulo)(type, object);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const getObject =
|
|
27
|
+
(checker: ts.TypeChecker) =>
|
|
28
|
+
(type: ts.Type): MetadataObject => {
|
|
29
|
+
const collection: MetadataCollection = new MetadataCollection();
|
|
30
|
+
const metadata: Metadata = MetadataFactory.analyze(checker)({
|
|
31
|
+
resolve: false,
|
|
32
|
+
constant: true,
|
|
33
|
+
absorb: true,
|
|
34
|
+
})(collection)(type);
|
|
35
|
+
if (metadata.objects.length !== 1 || metadata.bucket() !== 1)
|
|
36
|
+
throw new Error(
|
|
37
|
+
ErrorMessages.object(metadata)(
|
|
38
|
+
"only one object type is allowed.",
|
|
39
|
+
),
|
|
40
|
+
);
|
|
41
|
+
else if (metadata.nullable === true)
|
|
42
|
+
throw new Error(
|
|
43
|
+
ErrorMessages.object(metadata)(
|
|
44
|
+
"query parameter cannot be null.",
|
|
45
|
+
),
|
|
46
|
+
);
|
|
47
|
+
else if (metadata.isRequired() === false)
|
|
48
|
+
throw new Error(
|
|
49
|
+
ErrorMessages.object(metadata)(
|
|
50
|
+
"query parameter cannot be undefined.",
|
|
51
|
+
),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const object: MetadataObject = metadata.objects[0]!;
|
|
55
|
+
if (object.properties.some((p) => !(p.key as any).isSoleLiteral()))
|
|
56
|
+
throw new Error(
|
|
57
|
+
ErrorMessages.object(metadata)(
|
|
58
|
+
"dynamic property is not allowed.",
|
|
59
|
+
),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
for (const property of object.properties) {
|
|
63
|
+
const key: string = property.key.constants[0]
|
|
64
|
+
.values[0] as string;
|
|
65
|
+
const value: Metadata = property.value;
|
|
66
|
+
validate(object)(key)(value, 0);
|
|
67
|
+
}
|
|
68
|
+
return object;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const validate =
|
|
72
|
+
(obj: MetadataObject) =>
|
|
73
|
+
(key: string) =>
|
|
74
|
+
(value: Metadata, depth: number): string[] => {
|
|
75
|
+
if (depth === 1 && value.isRequired() === false)
|
|
76
|
+
throw new Error(
|
|
77
|
+
ErrorMessages.property(obj)(key)(
|
|
78
|
+
"optional type is not allowed in array.",
|
|
79
|
+
),
|
|
80
|
+
);
|
|
81
|
+
else if (value.nullable === true)
|
|
82
|
+
throw new Error(
|
|
83
|
+
ErrorMessages.property(obj)(key)(
|
|
84
|
+
"nullable type is not allowed.",
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
else if (
|
|
88
|
+
value.maps.length ||
|
|
89
|
+
value.sets.length ||
|
|
90
|
+
value.objects.length
|
|
91
|
+
)
|
|
92
|
+
throw new Error(
|
|
93
|
+
ErrorMessages.property(obj)(key)(
|
|
94
|
+
"object type is not allowed",
|
|
95
|
+
),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const atom: string[] = [];
|
|
99
|
+
for (const type of value.atomics) atom.push(type);
|
|
100
|
+
for (const { type } of value.constants) atom.push(type);
|
|
101
|
+
|
|
102
|
+
if (depth === 0 && (value.arrays.length || value.arrays.length)) {
|
|
103
|
+
if (atom.length)
|
|
104
|
+
throw new Error(
|
|
105
|
+
ErrorMessages.property(obj)(key)(
|
|
106
|
+
"union type is not allowed",
|
|
107
|
+
),
|
|
108
|
+
);
|
|
109
|
+
for (const array of value.arrays)
|
|
110
|
+
atom.push(...validate(obj)(key)(array.value, depth + 1));
|
|
111
|
+
for (const tuple of value.tuples)
|
|
112
|
+
for (const elem of tuple.elements)
|
|
113
|
+
atom.push(...validate(obj)(key)(elem, depth + 1));
|
|
114
|
+
} else if (value.arrays.length || value.tuples.length)
|
|
115
|
+
throw new Error(
|
|
116
|
+
ErrorMessages.property(obj)(key)(
|
|
117
|
+
"double-array type is not allowed",
|
|
118
|
+
),
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const size: number = new Set(atom).size;
|
|
122
|
+
if (size === 0)
|
|
123
|
+
throw new Error(
|
|
124
|
+
ErrorMessages.property(obj)(key)("unknown type"),
|
|
125
|
+
);
|
|
126
|
+
else if (size > 1)
|
|
127
|
+
throw new Error(
|
|
128
|
+
ErrorMessages.property(obj)(key)(
|
|
129
|
+
"union type is not allowed",
|
|
130
|
+
),
|
|
131
|
+
);
|
|
132
|
+
return atom;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const decode =
|
|
136
|
+
(project: INestiaTransformProject, modulo: ts.LeftHandSideExpression) =>
|
|
137
|
+
(type: ts.Type, object: MetadataObject): ts.ArrowFunction =>
|
|
138
|
+
ts.factory.createArrowFunction(
|
|
139
|
+
undefined,
|
|
140
|
+
undefined,
|
|
141
|
+
[IdentifierFactory.parameter("input")],
|
|
142
|
+
undefined,
|
|
143
|
+
undefined,
|
|
144
|
+
decode_object(project, modulo)(type, object),
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const decode_object =
|
|
148
|
+
(project: INestiaTransformProject, modulo: ts.LeftHandSideExpression) =>
|
|
149
|
+
(type: ts.Type, object: MetadataObject): ts.ConciseBody => {
|
|
150
|
+
const assert: ts.ArrowFunction = AssertProgrammer.write({
|
|
151
|
+
...project,
|
|
152
|
+
options: {
|
|
153
|
+
numeric: true,
|
|
154
|
+
finite: true,
|
|
155
|
+
},
|
|
156
|
+
})(modulo)(false)(type);
|
|
157
|
+
const output: ts.Identifier = ts.factory.createIdentifier("output");
|
|
158
|
+
|
|
159
|
+
const importer: FunctionImporter = new FunctionImporter();
|
|
160
|
+
const statements: ts.Statement[] = [
|
|
161
|
+
StatementFactory.constant(
|
|
162
|
+
"output",
|
|
163
|
+
ts.factory.createObjectLiteralExpression(
|
|
164
|
+
object.properties.map((prop) =>
|
|
165
|
+
decode_regular_property(importer)(object)(prop),
|
|
166
|
+
),
|
|
167
|
+
true,
|
|
168
|
+
),
|
|
169
|
+
),
|
|
170
|
+
ts.factory.createReturnStatement(
|
|
171
|
+
ts.factory.createCallExpression(assert, undefined, [
|
|
172
|
+
output,
|
|
173
|
+
]),
|
|
174
|
+
),
|
|
175
|
+
];
|
|
176
|
+
|
|
177
|
+
return ts.factory.createBlock(
|
|
178
|
+
[...importer.declare(modulo), ...statements],
|
|
179
|
+
true,
|
|
180
|
+
);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
const decode_regular_property =
|
|
184
|
+
(importer: FunctionImporter) =>
|
|
185
|
+
(object: MetadataObject) =>
|
|
186
|
+
(property: MetadataProperty): ts.PropertyAssignment => {
|
|
187
|
+
const key: string = property.key.constants[0]!.values[0] as string;
|
|
188
|
+
const value: Metadata = property.value;
|
|
189
|
+
|
|
190
|
+
const [type, isArray]: [Atomic.Literal, boolean] = value.atomics
|
|
191
|
+
.length
|
|
192
|
+
? [value.atomics[0], false]
|
|
193
|
+
: value.constants.length
|
|
194
|
+
? [value.constants[0]!.type, false]
|
|
195
|
+
: (() => {
|
|
196
|
+
const meta =
|
|
197
|
+
value.arrays[0]?.value ?? value.tuples[0].elements[0];
|
|
198
|
+
return meta.atomics.length
|
|
199
|
+
? [meta.atomics[0], true]
|
|
200
|
+
: [meta.constants[0]!.type, true];
|
|
201
|
+
})();
|
|
202
|
+
if (key.toLowerCase() !== key)
|
|
203
|
+
throw new Error(
|
|
204
|
+
ErrorMessages.property(object)(key)(
|
|
205
|
+
`property "${key}" must be lower case.`,
|
|
206
|
+
),
|
|
207
|
+
);
|
|
208
|
+
else if (isArray && SINGULAR.has(key))
|
|
209
|
+
throw new Error(
|
|
210
|
+
ErrorMessages.property(object)(key)(
|
|
211
|
+
`property "${key}" cannot be array.`,
|
|
212
|
+
),
|
|
213
|
+
);
|
|
214
|
+
else if (!isArray && key === "set-cookie")
|
|
215
|
+
throw new Error(
|
|
216
|
+
ErrorMessages.property(object)(key)(
|
|
217
|
+
`property "${key}" must be array.`,
|
|
218
|
+
),
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
const accessor = IdentifierFactory.access(
|
|
222
|
+
ts.factory.createIdentifier("input"),
|
|
223
|
+
)(key);
|
|
224
|
+
|
|
225
|
+
return ts.factory.createPropertyAssignment(
|
|
226
|
+
Escaper.variable(key)
|
|
227
|
+
? key
|
|
228
|
+
: ts.factory.createStringLiteral(key),
|
|
229
|
+
isArray
|
|
230
|
+
? key === "set-cookie"
|
|
231
|
+
? accessor
|
|
232
|
+
: ts.factory.createCallChain(
|
|
233
|
+
ts.factory.createPropertyAccessChain(
|
|
234
|
+
ts.factory.createCallChain(
|
|
235
|
+
ts.factory.createPropertyAccessChain(
|
|
236
|
+
accessor,
|
|
237
|
+
ts.factory.createToken(
|
|
238
|
+
ts.SyntaxKind.QuestionDotToken,
|
|
239
|
+
),
|
|
240
|
+
ts.factory.createIdentifier("split"),
|
|
241
|
+
),
|
|
242
|
+
undefined,
|
|
243
|
+
undefined,
|
|
244
|
+
[
|
|
245
|
+
ts.factory.createStringLiteral(
|
|
246
|
+
key === "cookie" ? "; " : ", ",
|
|
247
|
+
),
|
|
248
|
+
],
|
|
249
|
+
),
|
|
250
|
+
ts.factory.createToken(
|
|
251
|
+
ts.SyntaxKind.QuestionDotToken,
|
|
252
|
+
),
|
|
253
|
+
ts.factory.createIdentifier("map"),
|
|
254
|
+
),
|
|
255
|
+
undefined,
|
|
256
|
+
undefined,
|
|
257
|
+
[importer.use(type)],
|
|
258
|
+
)
|
|
259
|
+
: decode_value(importer)(type)(accessor),
|
|
260
|
+
);
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const decode_value =
|
|
264
|
+
(importer: FunctionImporter) =>
|
|
265
|
+
(type: Atomic.Literal) =>
|
|
266
|
+
(value: ts.Expression) =>
|
|
267
|
+
type === "string"
|
|
268
|
+
? value
|
|
269
|
+
: ts.factory.createCallExpression(
|
|
270
|
+
importer.use(type),
|
|
271
|
+
undefined,
|
|
272
|
+
[value],
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
namespace ErrorMessages {
|
|
277
|
+
export const object = (type: Metadata) => (message: string) =>
|
|
278
|
+
`Error on nestia.core.TypedHeaders<${type.getName()}>(): ${message}`;
|
|
279
|
+
|
|
280
|
+
export const property =
|
|
281
|
+
(obj: MetadataObject) => (key: string) => (message: string) =>
|
|
282
|
+
`Error on nestia.core.TypedHeaders<${obj.name}>(): property "${key}" - ${message}`;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const SINGULAR: Set<string> = new Set([
|
|
286
|
+
"age",
|
|
287
|
+
"authorization",
|
|
288
|
+
"content-length",
|
|
289
|
+
"content-type",
|
|
290
|
+
"etag",
|
|
291
|
+
"expires",
|
|
292
|
+
"from",
|
|
293
|
+
"host",
|
|
294
|
+
"if-modified-since",
|
|
295
|
+
"if-unmodified-since",
|
|
296
|
+
"last-modified",
|
|
297
|
+
"location",
|
|
298
|
+
"max-forwards",
|
|
299
|
+
"proxy-authorization",
|
|
300
|
+
"referer",
|
|
301
|
+
"retry-after",
|
|
302
|
+
"server",
|
|
303
|
+
"user-agent",
|
|
304
|
+
]);
|
|
@@ -10,6 +10,7 @@ import { MetadataProperty } from "typia/lib/metadata/MetadataProperty";
|
|
|
10
10
|
import { AssertProgrammer } from "typia/lib/programmers/AssertProgrammer";
|
|
11
11
|
import { FunctionImporter } from "typia/lib/programmers/helpers/FunctionImporeter";
|
|
12
12
|
import { Atomic } from "typia/lib/typings/Atomic";
|
|
13
|
+
import { Escaper } from "typia/lib/utils/Escaper";
|
|
13
14
|
|
|
14
15
|
import { INestiaTransformProject } from "../options/INestiaTransformProject";
|
|
15
16
|
|
|
@@ -50,9 +51,17 @@ export namespace TypedQueryProgrammer {
|
|
|
50
51
|
),
|
|
51
52
|
);
|
|
52
53
|
|
|
53
|
-
const object = metadata.objects[0]!;
|
|
54
|
+
const object: MetadataObject = metadata.objects[0]!;
|
|
55
|
+
if (object.properties.some((p) => !(p.key as any).isSoleLiteral()))
|
|
56
|
+
throw new Error(
|
|
57
|
+
ErrorMessages.object(metadata)(
|
|
58
|
+
"dynamic property is not allowed.",
|
|
59
|
+
),
|
|
60
|
+
);
|
|
61
|
+
|
|
54
62
|
for (const property of object.properties) {
|
|
55
|
-
const key:
|
|
63
|
+
const key: string = property.key.constants[0]
|
|
64
|
+
.values[0] as string;
|
|
56
65
|
const value: Metadata = property.value;
|
|
57
66
|
validate(object)(key)(value, 0);
|
|
58
67
|
}
|
|
@@ -61,7 +70,7 @@ export namespace TypedQueryProgrammer {
|
|
|
61
70
|
|
|
62
71
|
const validate =
|
|
63
72
|
(obj: MetadataObject) =>
|
|
64
|
-
(key:
|
|
73
|
+
(key: string) =>
|
|
65
74
|
(value: Metadata, depth: number): string[] => {
|
|
66
75
|
if (depth === 1 && value.isRequired() === false)
|
|
67
76
|
throw new Error(
|
|
@@ -139,29 +148,26 @@ export namespace TypedQueryProgrammer {
|
|
|
139
148
|
finite: true,
|
|
140
149
|
},
|
|
141
150
|
})(modulo)(false)(type);
|
|
142
|
-
const output = ts.factory.createIdentifier("output");
|
|
151
|
+
const output: ts.Identifier = ts.factory.createIdentifier("output");
|
|
143
152
|
|
|
144
|
-
const importer = new FunctionImporter();
|
|
153
|
+
const importer: FunctionImporter = new FunctionImporter();
|
|
145
154
|
const optionalArrays: string[] = [];
|
|
146
155
|
const statements: ts.Statement[] = [
|
|
147
156
|
StatementFactory.constant(
|
|
148
157
|
"output",
|
|
149
158
|
ts.factory.createObjectLiteralExpression(
|
|
150
|
-
object.properties
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
);
|
|
163
|
-
return decode_regular_property(importer)(prop);
|
|
164
|
-
}),
|
|
159
|
+
object.properties.map((prop) => {
|
|
160
|
+
if (
|
|
161
|
+
!prop.value.isRequired() &&
|
|
162
|
+
prop.value.arrays.length +
|
|
163
|
+
prop.value.tuples.length >
|
|
164
|
+
0
|
|
165
|
+
)
|
|
166
|
+
optionalArrays.push(
|
|
167
|
+
prop.key.constants[0]!.values[0] as string,
|
|
168
|
+
);
|
|
169
|
+
return decode_regular_property(importer)(prop);
|
|
170
|
+
}),
|
|
165
171
|
true,
|
|
166
172
|
),
|
|
167
173
|
),
|
|
@@ -209,7 +215,9 @@ export namespace TypedQueryProgrammer {
|
|
|
209
215
|
: [meta.constants[0]!.type, true];
|
|
210
216
|
})();
|
|
211
217
|
return ts.factory.createPropertyAssignment(
|
|
212
|
-
key
|
|
218
|
+
Escaper.variable(key)
|
|
219
|
+
? key
|
|
220
|
+
: ts.factory.createStringLiteral(key),
|
|
213
221
|
isArray
|
|
214
222
|
? ts.factory.createCallExpression(
|
|
215
223
|
IdentifierFactory.access(
|
|
@@ -257,8 +265,6 @@ namespace ErrorMessages {
|
|
|
257
265
|
`Error on nestia.core.TypedQuery<${type.getName()}>(): ${message}`;
|
|
258
266
|
|
|
259
267
|
export const property =
|
|
260
|
-
(obj: MetadataObject) => (key:
|
|
261
|
-
`Error on nestia.core.TypedQuery<${
|
|
262
|
-
obj.name
|
|
263
|
-
}>(): property ${key.getName()} - ${message}`;
|
|
268
|
+
(obj: MetadataObject) => (key: string) => (message: string) =>
|
|
269
|
+
`Error on nestia.core.TypedQuery<${obj.name}>(): property "${key}" - ${message}`;
|
|
264
270
|
}
|
|
@@ -4,6 +4,7 @@ import ts from "typescript";
|
|
|
4
4
|
import { INestiaTransformProject } from "../options/INestiaTransformProject";
|
|
5
5
|
import { PlainBodyProgrammer } from "../programmers/PlainBodyProgrammer";
|
|
6
6
|
import { TypedBodyProgrammer } from "../programmers/TypedBodyProgrammer";
|
|
7
|
+
import { TypedHeadersProgrammer } from "../programmers/TypedHeadersProgrammer";
|
|
7
8
|
import { TypedParamProgrammer } from "../programmers/TypedParamProgrammer";
|
|
8
9
|
import { TypedQueryProgrammer } from "../programmers/TypedQueryProgrammer";
|
|
9
10
|
|
|
@@ -78,6 +79,10 @@ const FUNCTORS: Record<string, Programmer> = {
|
|
|
78
79
|
parameters.length
|
|
79
80
|
? parameters
|
|
80
81
|
: [TypedBodyProgrammer.generate(project)(modulo)(type)],
|
|
82
|
+
TypedHeaders: (project) => (modulo) => (parameters) => (type) =>
|
|
83
|
+
parameters.length
|
|
84
|
+
? parameters
|
|
85
|
+
: [TypedHeadersProgrammer.generate(project)(modulo)(type)],
|
|
81
86
|
TypedParam: (project) => () => TypedParamProgrammer.generate(project),
|
|
82
87
|
TypedQuery: (project) => (modulo) => (parameters) => (type) =>
|
|
83
88
|
parameters.length
|