@nestia/core 2.0.0-dev.20230831-4 → 2.0.0-dev.20230831-6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/decorators/EncryptedRoute.js +10 -7
- package/lib/decorators/EncryptedRoute.js.map +1 -1
- package/lib/decorators/TypedHeaders.js +2 -2
- package/lib/decorators/TypedHeaders.js.map +1 -1
- package/lib/decorators/TypedParam.d.ts +14 -13
- package/lib/decorators/TypedParam.js +16 -48
- package/lib/decorators/TypedParam.js.map +1 -1
- package/lib/decorators/TypedQuery.d.ts +2 -3
- package/lib/decorators/TypedQuery.js +4 -5
- package/lib/decorators/TypedQuery.js.map +1 -1
- package/lib/decorators/TypedRoute.js +8 -5
- package/lib/decorators/TypedRoute.js.map +1 -1
- package/lib/decorators/internal/{TransformError.js → NoTransformConfigureError.js} +4 -4
- package/lib/decorators/internal/NoTransformConfigureError.js.map +1 -0
- package/lib/decorators/internal/get_path_and_stringify.js +2 -2
- package/lib/decorators/internal/get_path_and_stringify.js.map +1 -1
- package/lib/decorators/internal/validate_request_body.js +2 -2
- package/lib/decorators/internal/validate_request_body.js.map +1 -1
- package/lib/programmers/PlainBodyProgrammer.js +17 -13
- package/lib/programmers/PlainBodyProgrammer.js.map +1 -1
- package/lib/programmers/TypedHeadersProgrammer.d.ts +3 -0
- package/lib/programmers/TypedHeadersProgrammer.js +86 -136
- package/lib/programmers/TypedHeadersProgrammer.js.map +1 -1
- package/lib/programmers/TypedParamProgrammer.d.ts +3 -1
- package/lib/programmers/TypedParamProgrammer.js +74 -67
- package/lib/programmers/TypedParamProgrammer.js.map +1 -1
- package/lib/programmers/TypedQueryProgrammer.d.ts +3 -0
- package/lib/programmers/TypedQueryProgrammer.js +88 -149
- package/lib/programmers/TypedQueryProgrammer.js.map +1 -1
- package/lib/programmers/TypedRouteProgrammer.js +8 -8
- package/lib/programmers/TypedRouteProgrammer.js.map +1 -1
- package/lib/programmers/internal/CoreMetadataUtil.d.ts +5 -0
- package/lib/programmers/internal/CoreMetadataUtil.js +44 -0
- package/lib/programmers/internal/CoreMetadataUtil.js.map +1 -0
- package/lib/transform.d.ts +2 -1
- package/lib/transform.js +11 -3
- package/lib/transform.js.map +1 -1
- package/lib/transformers/FileTransformer.d.ts +1 -1
- package/lib/transformers/FileTransformer.js +16 -1
- package/lib/transformers/FileTransformer.js.map +1 -1
- package/lib/transformers/ParameterDecoratorTransformer.js +3 -1
- package/lib/transformers/ParameterDecoratorTransformer.js.map +1 -1
- package/package.json +5 -5
- package/src/decorators/EncryptedRoute.ts +9 -12
- package/src/decorators/TypedHeaders.ts +2 -2
- package/src/decorators/TypedParam.ts +30 -51
- package/src/decorators/TypedQuery.ts +4 -5
- package/src/decorators/TypedRoute.ts +5 -10
- package/src/decorators/internal/{TransformError.ts → NoTransformConfigureError.ts} +1 -1
- package/src/decorators/internal/get_path_and_stringify.ts +2 -2
- package/src/decorators/internal/validate_request_body.ts +2 -2
- package/src/programmers/PlainBodyProgrammer.ts +24 -19
- package/src/programmers/TypedHeadersProgrammer.ts +100 -106
- package/src/programmers/TypedParamProgrammer.ts +113 -79
- package/src/programmers/TypedQueryProgrammer.ts +115 -114
- package/src/programmers/TypedRouteProgrammer.ts +11 -8
- package/src/programmers/internal/CoreMetadataUtil.ts +21 -0
- package/src/transform.ts +14 -5
- package/src/transformers/FileTransformer.ts +7 -2
- package/src/transformers/ParameterDecoratorTransformer.ts +2 -1
- package/lib/decorators/internal/TransformError.js.map +0 -1
- /package/lib/decorators/internal/{TransformError.d.ts → NoTransformConfigureError.d.ts} +0 -0
|
@@ -1,101 +1,135 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
|
|
3
|
+
import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
|
|
3
4
|
import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
|
|
4
5
|
import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
|
|
5
|
-
import {
|
|
6
|
+
import { IsProgrammer } from "typia/lib/programmers/IsProgrammer";
|
|
7
|
+
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
8
|
+
import { TransformerError } from "typia/lib/transformers/TransformerError";
|
|
6
9
|
|
|
7
10
|
import { INestiaTransformProject } from "../options/INestiaTransformProject";
|
|
11
|
+
import { CoreMetadataUtil } from "./internal/CoreMetadataUtil";
|
|
8
12
|
|
|
9
13
|
export namespace TypedParamProgrammer {
|
|
10
14
|
export const generate =
|
|
11
|
-
(
|
|
15
|
+
(project: INestiaTransformProject) =>
|
|
16
|
+
(modulo: ts.LeftHandSideExpression) =>
|
|
12
17
|
(parameters: readonly ts.Expression[]) =>
|
|
13
18
|
(type: ts.Type): readonly ts.Expression[] => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
constant: true,
|
|
17
|
-
absorb: true,
|
|
18
|
-
})(new MetadataCollection())(type);
|
|
19
|
-
validate(metadata);
|
|
20
|
-
const [atomic] = get_atomic_types(metadata);
|
|
21
|
-
|
|
22
|
-
// AUTO TYPE SPECIFICATION
|
|
23
|
-
if (parameters.length === 1)
|
|
24
|
-
return [
|
|
25
|
-
parameters[0],
|
|
26
|
-
ts.factory.createStringLiteral(atomic),
|
|
27
|
-
metadata.nullable
|
|
28
|
-
? ts.factory.createTrue()
|
|
29
|
-
: ts.factory.createFalse(),
|
|
30
|
-
];
|
|
19
|
+
// ALREADY BEING TRANSFORMED
|
|
20
|
+
if (parameters.length !== 1) return parameters;
|
|
31
21
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
resolve: false,
|
|
22
|
+
const result = MetadataFactory.analyze(project.checker)({
|
|
23
|
+
escape: false,
|
|
35
24
|
constant: true,
|
|
36
25
|
absorb: true,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (parameters.length === 2)
|
|
44
|
-
return [
|
|
45
|
-
parameters[0],
|
|
46
|
-
parameters[1],
|
|
47
|
-
metadata.nullable
|
|
48
|
-
? ts.factory.createTrue()
|
|
49
|
-
: ts.factory.createFalse(),
|
|
50
|
-
];
|
|
51
|
-
|
|
52
|
-
// NULLABLE HAS BEEN SPECIFIED
|
|
53
|
-
const nullable: Metadata = MetadataFactory.analyze(checker)({
|
|
54
|
-
resolve: false,
|
|
55
|
-
constant: true,
|
|
56
|
-
absorb: true,
|
|
57
|
-
})(new MetadataCollection())(
|
|
58
|
-
checker.getTypeAtLocation(parameters[2]),
|
|
59
|
-
);
|
|
60
|
-
if (nullable.getName() !== "true" && nullable.getName() !== "false")
|
|
61
|
-
throw error("nullable value must be literal type");
|
|
62
|
-
else if (metadata.nullable !== (nullable.getName() === "true"))
|
|
63
|
-
throw error(
|
|
64
|
-
"different type (nullable) between parameter and variable",
|
|
26
|
+
validate,
|
|
27
|
+
})(new MetadataCollection())(type);
|
|
28
|
+
if (result.success === false)
|
|
29
|
+
throw TransformerError.from("@core.nestia.TypedParam")(
|
|
30
|
+
result.errors,
|
|
65
31
|
);
|
|
66
|
-
|
|
32
|
+
const [atomic] = [...CoreMetadataUtil.atomics(result.data)];
|
|
33
|
+
const name: string = result.data.getName();
|
|
34
|
+
const is: ts.ArrowFunction = IsProgrammer.write({
|
|
35
|
+
...project,
|
|
36
|
+
options: {
|
|
37
|
+
numeric: true,
|
|
38
|
+
},
|
|
39
|
+
})(modulo)(false)(type);
|
|
40
|
+
const cast: ts.ArrowFunction = CASTERS[atomic]();
|
|
41
|
+
|
|
42
|
+
return [
|
|
43
|
+
parameters[0],
|
|
44
|
+
ts.factory.createObjectLiteralExpression(
|
|
45
|
+
[
|
|
46
|
+
ts.factory.createPropertyAssignment(
|
|
47
|
+
"name",
|
|
48
|
+
ts.factory.createIdentifier(name),
|
|
49
|
+
),
|
|
50
|
+
ts.factory.createPropertyAssignment("is", is),
|
|
51
|
+
ts.factory.createPropertyAssignment("cast", cast),
|
|
52
|
+
],
|
|
53
|
+
true,
|
|
54
|
+
),
|
|
55
|
+
];
|
|
67
56
|
};
|
|
68
|
-
}
|
|
69
57
|
|
|
70
|
-
const validate = (meta: Metadata) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
throw error("do not allow undefindable type");
|
|
58
|
+
export const validate = (meta: Metadata): string[] => {
|
|
59
|
+
const errors: string[] = [];
|
|
60
|
+
const insert = (msg: string) => errors.push(msg);
|
|
74
61
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
meta.templates.length +
|
|
79
|
-
meta.constants.map((c) => c.values.length).reduce((a, b) => a + b, 0);
|
|
80
|
-
if (meta.size() !== expected || atomics.length === 0)
|
|
81
|
-
throw error("only atomic or constant types is allowed");
|
|
82
|
-
else if (atomics.length > 1) throw error("do not allow union type");
|
|
83
|
-
};
|
|
62
|
+
if (meta.any) insert("do not allow any type");
|
|
63
|
+
if (meta.isRequired() === false)
|
|
64
|
+
insert("do not allow undefindable type");
|
|
84
65
|
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
66
|
+
const atomics = CoreMetadataUtil.atomics(meta);
|
|
67
|
+
const expected: number =
|
|
68
|
+
meta.atomics.length +
|
|
69
|
+
meta.templates.length +
|
|
70
|
+
meta.constants
|
|
71
|
+
.map((c) => c.values.length)
|
|
72
|
+
.reduce((a, b) => a + b, 0);
|
|
73
|
+
if (meta.size() !== expected || atomics.size === 0)
|
|
74
|
+
insert("only atomic or constant types are allowed");
|
|
75
|
+
if (atomics.size > 1) insert("do not allow union type");
|
|
92
76
|
|
|
93
|
-
|
|
94
|
-
|
|
77
|
+
return errors;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
95
80
|
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
81
|
+
const CASTERS = {
|
|
82
|
+
boolean: () =>
|
|
83
|
+
ts.factory.createArrowFunction(
|
|
84
|
+
undefined,
|
|
85
|
+
undefined,
|
|
86
|
+
[IdentifierFactory.parameter("str")],
|
|
87
|
+
undefined,
|
|
88
|
+
undefined,
|
|
89
|
+
ts.factory.createLogicalOr(
|
|
90
|
+
ts.factory.createStrictEquality(
|
|
91
|
+
ts.factory.createStringLiteral("true"),
|
|
92
|
+
ts.factory.createIdentifier("str"),
|
|
93
|
+
),
|
|
94
|
+
ts.factory.createStrictEquality(
|
|
95
|
+
ts.factory.createStringLiteral("1"),
|
|
96
|
+
ts.factory.createIdentifier("str"),
|
|
97
|
+
),
|
|
98
|
+
),
|
|
99
|
+
),
|
|
100
|
+
number: () =>
|
|
101
|
+
ts.factory.createArrowFunction(
|
|
102
|
+
undefined,
|
|
103
|
+
undefined,
|
|
104
|
+
[IdentifierFactory.parameter("str")],
|
|
105
|
+
undefined,
|
|
106
|
+
undefined,
|
|
107
|
+
ts.factory.createCallExpression(
|
|
108
|
+
ts.factory.createIdentifier("Number"),
|
|
109
|
+
undefined,
|
|
110
|
+
[ts.factory.createIdentifier("str")],
|
|
111
|
+
),
|
|
112
|
+
),
|
|
113
|
+
bigint: () =>
|
|
114
|
+
ts.factory.createArrowFunction(
|
|
115
|
+
undefined,
|
|
116
|
+
undefined,
|
|
117
|
+
[IdentifierFactory.parameter("str")],
|
|
118
|
+
undefined,
|
|
119
|
+
undefined,
|
|
120
|
+
ts.factory.createCallExpression(
|
|
121
|
+
ts.factory.createIdentifier("BigInt"),
|
|
122
|
+
undefined,
|
|
123
|
+
[ts.factory.createIdentifier("str")],
|
|
124
|
+
),
|
|
125
|
+
),
|
|
126
|
+
string: () =>
|
|
127
|
+
ts.factory.createArrowFunction(
|
|
128
|
+
undefined,
|
|
129
|
+
undefined,
|
|
130
|
+
[IdentifierFactory.parameter("str")],
|
|
131
|
+
undefined,
|
|
132
|
+
undefined,
|
|
133
|
+
ts.factory.createIdentifier("str"),
|
|
134
|
+
),
|
|
101
135
|
};
|
|
@@ -4,15 +4,18 @@ import { IdentifierFactory } from "typia/lib/factories/IdentifierFactory";
|
|
|
4
4
|
import { MetadataCollection } from "typia/lib/factories/MetadataCollection";
|
|
5
5
|
import { MetadataFactory } from "typia/lib/factories/MetadataFactory";
|
|
6
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
7
|
import { AssertProgrammer } from "typia/lib/programmers/AssertProgrammer";
|
|
11
8
|
import { FunctionImporter } from "typia/lib/programmers/helpers/FunctionImporeter";
|
|
9
|
+
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
10
|
+
import { MetadataArray } from "typia/lib/schemas/metadata/MetadataArray";
|
|
11
|
+
import { MetadataObject } from "typia/lib/schemas/metadata/MetadataObject";
|
|
12
|
+
import { MetadataProperty } from "typia/lib/schemas/metadata/MetadataProperty";
|
|
13
|
+
import { TransformerError } from "typia/lib/transformers/TransformerError";
|
|
12
14
|
import { Atomic } from "typia/lib/typings/Atomic";
|
|
13
15
|
import { Escaper } from "typia/lib/utils/Escaper";
|
|
14
16
|
|
|
15
17
|
import { INestiaTransformProject } from "../options/INestiaTransformProject";
|
|
18
|
+
import { CoreMetadataUtil } from "./internal/CoreMetadataUtil";
|
|
16
19
|
|
|
17
20
|
export namespace TypedQueryProgrammer {
|
|
18
21
|
export const generate =
|
|
@@ -23,107 +26,95 @@ export namespace TypedQueryProgrammer {
|
|
|
23
26
|
return decode(project, modulo)(type, object);
|
|
24
27
|
};
|
|
25
28
|
|
|
29
|
+
export const validate = (
|
|
30
|
+
meta: Metadata,
|
|
31
|
+
explore: MetadataFactory.IExplore,
|
|
32
|
+
): string[] => {
|
|
33
|
+
const errors: string[] = [];
|
|
34
|
+
const insert = (msg: string) => errors.push(msg);
|
|
35
|
+
|
|
36
|
+
if (explore.top === true) {
|
|
37
|
+
// TOP MUST BE ONLY OBJECT
|
|
38
|
+
if (meta.objects.length !== 1 || meta.bucket() !== 1)
|
|
39
|
+
insert("only one object type is allowed.");
|
|
40
|
+
if (meta.nullable === true)
|
|
41
|
+
insert("query parameters cannot be null.");
|
|
42
|
+
if (meta.isRequired() === false)
|
|
43
|
+
insert("query parameters cannot be undefined.");
|
|
44
|
+
} else if (
|
|
45
|
+
explore.nested !== null &&
|
|
46
|
+
explore.nested instanceof MetadataArray
|
|
47
|
+
) {
|
|
48
|
+
const atomics = CoreMetadataUtil.atomics(meta);
|
|
49
|
+
const expected: number =
|
|
50
|
+
meta.atomics.length +
|
|
51
|
+
meta.templates.length +
|
|
52
|
+
meta.constants
|
|
53
|
+
.map((c) => c.values.length)
|
|
54
|
+
.reduce((a, b) => a + b, 0);
|
|
55
|
+
if (atomics.size > 1) insert("union type is not allowed in array.");
|
|
56
|
+
if (meta.nullable) insert("nullable type is not allowed in array.");
|
|
57
|
+
if (meta.isRequired() === false)
|
|
58
|
+
insert("optional type is not allowed in array.");
|
|
59
|
+
if (meta.size() !== expected)
|
|
60
|
+
insert("only atomic or constant types are allowed in array.");
|
|
61
|
+
} else if (explore.object && explore.property !== null) {
|
|
62
|
+
//----
|
|
63
|
+
// COMMON
|
|
64
|
+
//----
|
|
65
|
+
// PROPERTY MUST BE SOLE
|
|
66
|
+
if (typeof explore.property === "object")
|
|
67
|
+
insert("dynamic property is not allowed.");
|
|
68
|
+
// MUST BE LOWER-CASE
|
|
69
|
+
if (
|
|
70
|
+
typeof explore.property === "string" &&
|
|
71
|
+
explore.property !== explore.property.toLowerCase()
|
|
72
|
+
)
|
|
73
|
+
insert("property name must be lower-case.");
|
|
74
|
+
// DO NOT ALLOW TUPLE TYPE
|
|
75
|
+
if (meta.tuples.length) insert("tuple type is not allowed.");
|
|
76
|
+
// DO NOT ALLOW UNION TYPE
|
|
77
|
+
if (CoreMetadataUtil.isUnion(meta))
|
|
78
|
+
insert("union type is not allowed.");
|
|
79
|
+
// DO NOT ALLOW NESTED OBJECT
|
|
80
|
+
if (
|
|
81
|
+
meta.objects.length ||
|
|
82
|
+
meta.sets.length ||
|
|
83
|
+
meta.maps.length ||
|
|
84
|
+
meta.natives.length
|
|
85
|
+
)
|
|
86
|
+
insert("nested object type is not allowed.");
|
|
87
|
+
|
|
88
|
+
//----
|
|
89
|
+
// ARRAY CASES
|
|
90
|
+
//----
|
|
91
|
+
const isArray: boolean =
|
|
92
|
+
meta.arrays.length > 1 || meta.tuples.length > 1;
|
|
93
|
+
// ARRAY TYPE MUST BE REQUIRED
|
|
94
|
+
if (isArray && meta.isRequired() === false)
|
|
95
|
+
insert("optional type is not allowed when array.");
|
|
96
|
+
// SET-COOKIE MUST BE ARRAY
|
|
97
|
+
if (explore.property === "set-cookie" && !isArray)
|
|
98
|
+
insert("set-cookie property must be array.");
|
|
99
|
+
}
|
|
100
|
+
return errors;
|
|
101
|
+
};
|
|
102
|
+
|
|
26
103
|
const getObject =
|
|
27
104
|
(checker: ts.TypeChecker) =>
|
|
28
105
|
(type: ts.Type): MetadataObject => {
|
|
29
106
|
const collection: MetadataCollection = new MetadataCollection();
|
|
30
|
-
const
|
|
31
|
-
|
|
107
|
+
const result = MetadataFactory.analyze(checker)({
|
|
108
|
+
escape: false,
|
|
32
109
|
constant: true,
|
|
33
110
|
absorb: true,
|
|
111
|
+
validate,
|
|
34
112
|
})(collection)(type);
|
|
35
|
-
if (
|
|
36
|
-
throw
|
|
37
|
-
|
|
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
|
-
),
|
|
113
|
+
if (result.success === false)
|
|
114
|
+
throw TransformerError.from("@core.nestia.TypedHeaders")(
|
|
115
|
+
result.errors,
|
|
52
116
|
);
|
|
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 (
|
|
82
|
-
value.maps.length ||
|
|
83
|
-
value.sets.length ||
|
|
84
|
-
value.objects.length
|
|
85
|
-
)
|
|
86
|
-
throw new Error(
|
|
87
|
-
ErrorMessages.property(obj)(key)(
|
|
88
|
-
"object type is not allowed",
|
|
89
|
-
),
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
const atom: string[] = [];
|
|
93
|
-
for (const type of value.atomics) atom.push(type);
|
|
94
|
-
for (const { type } of value.constants) atom.push(type);
|
|
95
|
-
|
|
96
|
-
if (depth === 0 && (value.arrays.length || value.arrays.length)) {
|
|
97
|
-
if (atom.length)
|
|
98
|
-
throw new Error(
|
|
99
|
-
ErrorMessages.property(obj)(key)(
|
|
100
|
-
"union type is not allowed",
|
|
101
|
-
),
|
|
102
|
-
);
|
|
103
|
-
for (const array of value.arrays)
|
|
104
|
-
atom.push(...validate(obj)(key)(array.value, depth + 1));
|
|
105
|
-
for (const tuple of value.tuples)
|
|
106
|
-
for (const elem of tuple.elements)
|
|
107
|
-
atom.push(...validate(obj)(key)(elem, depth + 1));
|
|
108
|
-
} else if (value.arrays.length || value.tuples.length)
|
|
109
|
-
throw new Error(
|
|
110
|
-
ErrorMessages.property(obj)(key)(
|
|
111
|
-
"double-array type is not allowed",
|
|
112
|
-
),
|
|
113
|
-
);
|
|
114
|
-
|
|
115
|
-
const size: number = new Set(atom).size;
|
|
116
|
-
if (size === 0)
|
|
117
|
-
throw new Error(
|
|
118
|
-
ErrorMessages.property(obj)(key)("unknown type"),
|
|
119
|
-
);
|
|
120
|
-
else if (size > 1)
|
|
121
|
-
throw new Error(
|
|
122
|
-
ErrorMessages.property(obj)(key)(
|
|
123
|
-
"union type is not allowed",
|
|
124
|
-
),
|
|
125
|
-
);
|
|
126
|
-
return atom;
|
|
117
|
+
return result.data.objects[0]!;
|
|
127
118
|
};
|
|
128
119
|
|
|
129
120
|
const decode =
|
|
@@ -150,7 +141,9 @@ export namespace TypedQueryProgrammer {
|
|
|
150
141
|
})(modulo)(false)(type);
|
|
151
142
|
const output: ts.Identifier = ts.factory.createIdentifier("output");
|
|
152
143
|
|
|
153
|
-
const importer: FunctionImporter = new FunctionImporter(
|
|
144
|
+
const importer: FunctionImporter = new FunctionImporter(
|
|
145
|
+
"TypedQuery",
|
|
146
|
+
);
|
|
154
147
|
const optionalArrays: string[] = [];
|
|
155
148
|
const statements: ts.Statement[] = [
|
|
156
149
|
StatementFactory.constant(
|
|
@@ -204,14 +197,15 @@ export namespace TypedQueryProgrammer {
|
|
|
204
197
|
|
|
205
198
|
const [type, isArray]: [Atomic.Literal, boolean] = value.atomics
|
|
206
199
|
.length
|
|
207
|
-
? [value.atomics[0], false]
|
|
200
|
+
? [value.atomics[0].type, false]
|
|
208
201
|
: value.constants.length
|
|
209
202
|
? [value.constants[0]!.type, false]
|
|
210
203
|
: (() => {
|
|
211
204
|
const meta =
|
|
212
|
-
value.arrays[0]?.value ??
|
|
205
|
+
value.arrays[0]?.type.value ??
|
|
206
|
+
value.tuples[0].type.elements[0];
|
|
213
207
|
return meta.atomics.length
|
|
214
|
-
? [meta.atomics[0], true]
|
|
208
|
+
? [meta.atomics[0].type, true]
|
|
215
209
|
: [meta.constants[0]!.type, true];
|
|
216
210
|
})();
|
|
217
211
|
return ts.factory.createPropertyAssignment(
|
|
@@ -235,13 +229,16 @@ export namespace TypedQueryProgrammer {
|
|
|
235
229
|
[IdentifierFactory.parameter("elem")],
|
|
236
230
|
undefined,
|
|
237
231
|
undefined,
|
|
238
|
-
decode_value(importer)(type)(
|
|
232
|
+
decode_value(importer)(type)(false)(
|
|
239
233
|
ts.factory.createIdentifier("elem"),
|
|
240
234
|
),
|
|
241
235
|
),
|
|
242
236
|
],
|
|
243
237
|
)
|
|
244
238
|
: decode_value(importer)(type)(
|
|
239
|
+
value.nullable === false &&
|
|
240
|
+
value.isRequired() === false,
|
|
241
|
+
)(
|
|
245
242
|
ts.factory.createCallExpression(
|
|
246
243
|
ts.factory.createIdentifier("input.get"),
|
|
247
244
|
undefined,
|
|
@@ -254,17 +251,21 @@ export namespace TypedQueryProgrammer {
|
|
|
254
251
|
const decode_value =
|
|
255
252
|
(importer: FunctionImporter) =>
|
|
256
253
|
(type: Atomic.Literal) =>
|
|
257
|
-
(
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
254
|
+
(onlyUndefindable: boolean) =>
|
|
255
|
+
(value: ts.Expression) => {
|
|
256
|
+
const call = ts.factory.createCallExpression(
|
|
257
|
+
importer.use(type),
|
|
258
|
+
undefined,
|
|
259
|
+
[value],
|
|
260
|
+
);
|
|
261
|
+
return onlyUndefindable
|
|
262
|
+
? ts.factory.createBinaryExpression(
|
|
263
|
+
call,
|
|
264
|
+
ts.factory.createToken(
|
|
265
|
+
ts.SyntaxKind.QuestionQuestionToken,
|
|
266
|
+
),
|
|
267
|
+
ts.factory.createIdentifier("undefined"),
|
|
268
|
+
)
|
|
269
|
+
: call;
|
|
270
|
+
};
|
|
270
271
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { JsonAssertStringifyProgrammer } from "typia/lib/programmers/json/JsonAssertStringifyProgrammer";
|
|
4
|
+
import { JsonIsStringifyProgrammer } from "typia/lib/programmers/json/JsonIsStringifyProgrammer";
|
|
5
|
+
import { JsonStringifyProgrammer } from "typia/lib/programmers/json/JsonStringifyProgrammer";
|
|
6
|
+
import { JsonValidateStringifyProgrammer } from "typia/lib/programmers/json/JsonValidateStringifyProgrammer";
|
|
7
7
|
import { IProject } from "typia/lib/transformers/IProject";
|
|
8
8
|
|
|
9
9
|
import { INestiaTransformProject } from "../options/INestiaTransformProject";
|
|
@@ -38,15 +38,18 @@ export namespace TypedRouteProgrammer {
|
|
|
38
38
|
|
|
39
39
|
// RETURNS
|
|
40
40
|
if (project.options.stringify === "is")
|
|
41
|
-
return parameter("is",
|
|
41
|
+
return parameter("is", JsonIsStringifyProgrammer.write);
|
|
42
42
|
else if (project.options.stringify === "validate")
|
|
43
|
-
return parameter(
|
|
43
|
+
return parameter(
|
|
44
|
+
"validate",
|
|
45
|
+
JsonValidateStringifyProgrammer.write,
|
|
46
|
+
);
|
|
44
47
|
else if (project.options.stringify === "stringify")
|
|
45
|
-
return parameter("stringify",
|
|
48
|
+
return parameter("stringify", JsonStringifyProgrammer.write);
|
|
46
49
|
else if (project.options.stringify === null)
|
|
47
50
|
return ts.factory.createNull();
|
|
48
51
|
|
|
49
52
|
// ASSERT IS DEFAULT
|
|
50
|
-
return parameter("assert",
|
|
53
|
+
return parameter("assert", JsonAssertStringifyProgrammer.write);
|
|
51
54
|
};
|
|
52
55
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Metadata } from "typia/lib/schemas/metadata/Metadata";
|
|
2
|
+
|
|
3
|
+
export namespace CoreMetadataUtil {
|
|
4
|
+
export const atomics = (
|
|
5
|
+
meta: Metadata,
|
|
6
|
+
): Set<"boolean" | "bigint" | "number" | "string"> =>
|
|
7
|
+
new Set([
|
|
8
|
+
...meta.atomics.map((a) => a.type),
|
|
9
|
+
...meta.constants.map((c) => c.type),
|
|
10
|
+
...(meta.templates.length ? (["string"] as const) : []),
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
export const isUnion = (meta: Metadata): boolean =>
|
|
14
|
+
atomics(meta).size +
|
|
15
|
+
meta.arrays.length +
|
|
16
|
+
meta.tuples.length +
|
|
17
|
+
meta.natives.length +
|
|
18
|
+
meta.maps.length +
|
|
19
|
+
meta.objects.length >
|
|
20
|
+
1;
|
|
21
|
+
}
|
package/src/transform.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
|
|
3
|
+
import { IProject } from "typia/lib/transformers/IProject";
|
|
4
|
+
|
|
3
5
|
import { INestiaTransformOptions } from "./options/INestiaTransformOptions";
|
|
4
6
|
import { FileTransformer } from "./transformers/FileTransformer";
|
|
5
7
|
|
|
6
8
|
export const transform = (
|
|
7
9
|
program: ts.Program,
|
|
8
|
-
options
|
|
10
|
+
options: INestiaTransformOptions | undefined,
|
|
11
|
+
extras: IProject["extras"],
|
|
9
12
|
): ts.TransformerFactory<ts.SourceFile> => {
|
|
10
13
|
const compilerOptions: ts.CompilerOptions = program.getCompilerOptions();
|
|
11
14
|
const strict: boolean =
|
|
@@ -13,15 +16,21 @@ export const transform = (
|
|
|
13
16
|
? !!compilerOptions.strictNullChecks
|
|
14
17
|
: !!compilerOptions.strict;
|
|
15
18
|
if (strict === false)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
extras.addDiagnostic({
|
|
20
|
+
category: ts.DiagnosticCategory.Error,
|
|
21
|
+
code: "(@nestia/core)" as any,
|
|
22
|
+
file: undefined,
|
|
23
|
+
start: undefined,
|
|
24
|
+
length: undefined,
|
|
25
|
+
messageText: "strict mode is required.",
|
|
26
|
+
});
|
|
19
27
|
return FileTransformer.transform({
|
|
20
28
|
program,
|
|
21
29
|
compilerOptions,
|
|
22
30
|
checker: program.getTypeChecker(),
|
|
23
31
|
printer: ts.createPrinter(),
|
|
24
|
-
options: options
|
|
32
|
+
options: options ?? {},
|
|
33
|
+
extras,
|
|
25
34
|
});
|
|
26
35
|
};
|
|
27
36
|
export default transform;
|
|
@@ -5,12 +5,16 @@ import { NodeTransformer } from "./NodeTransformer";
|
|
|
5
5
|
|
|
6
6
|
export namespace FileTransformer {
|
|
7
7
|
export const transform =
|
|
8
|
-
(project: INestiaTransformProject) =>
|
|
8
|
+
(project: Omit<INestiaTransformProject, "context">) =>
|
|
9
9
|
(context: ts.TransformationContext) =>
|
|
10
10
|
(file: ts.SourceFile): ts.SourceFile =>
|
|
11
11
|
ts.visitEachChild(
|
|
12
12
|
file,
|
|
13
|
-
(node) =>
|
|
13
|
+
(node) =>
|
|
14
|
+
iterate_node({
|
|
15
|
+
...project,
|
|
16
|
+
context,
|
|
17
|
+
})(context)(node),
|
|
14
18
|
context,
|
|
15
19
|
);
|
|
16
20
|
|
|
@@ -27,6 +31,7 @@ export namespace FileTransformer {
|
|
|
27
31
|
const try_transform_node =
|
|
28
32
|
(project: INestiaTransformProject) =>
|
|
29
33
|
(node: ts.Node): ts.Node => {
|
|
34
|
+
if (!node) return node;
|
|
30
35
|
try {
|
|
31
36
|
return NodeTransformer.transform(project)(node);
|
|
32
37
|
} catch (exp) {
|
|
@@ -83,7 +83,8 @@ const FUNCTORS: Record<string, Programmer> = {
|
|
|
83
83
|
parameters.length
|
|
84
84
|
? parameters
|
|
85
85
|
: [TypedHeadersProgrammer.generate(project)(modulo)(type)],
|
|
86
|
-
TypedParam: (project) => () =>
|
|
86
|
+
TypedParam: (project) => (modulo) =>
|
|
87
|
+
TypedParamProgrammer.generate(project)(modulo),
|
|
87
88
|
TypedQuery: (project) => (modulo) => (parameters) => (type) =>
|
|
88
89
|
parameters.length
|
|
89
90
|
? parameters
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TransformError.js","sourceRoot":"","sources":["../../../src/decorators/internal/TransformError.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH,SAAgB,cAAc,CAAC,MAAc;IACzC,OAAO,IAAI,KAAK,CACZ,+BAAwB,MAAM,wJAAmJ,CACpL,CAAC;AACN,CAAC;AAJD,wCAIC"}
|
|
File without changes
|