typia 5.0.0-dev.20230829-5 → 5.0.0-dev.20230830
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/programmers/internal/random_custom.js +7 -1
- package/lib/programmers/internal/random_custom.js.map +1 -1
- package/lib/protobuf.d.ts +34 -34
- package/package.json +1 -1
- package/src/factories/MetadataFactory.ts +214 -214
- package/src/factories/ProtobufFactory.ts +272 -272
- package/src/programmers/helpers/ProtobufUtil.ts +125 -125
- package/src/programmers/internal/random_custom.ts +9 -1
- package/src/programmers/protobuf/ProtobufDecodeProgrammer.ts +655 -655
- package/src/programmers/protobuf/ProtobufEncodeProgrammer.ts +883 -883
- package/src/programmers/protobuf/ProtobufMessageProgrammer.ts +165 -165
- package/src/protobuf.ts +34 -34
|
@@ -11,7 +11,13 @@ var random_custom = function (accessor) {
|
|
|
11
11
|
return function (type) {
|
|
12
12
|
return function (tags) {
|
|
13
13
|
return function (expression) {
|
|
14
|
-
return ExpressionFactory_1.ExpressionFactory.coalesce(typescript_1.default.factory.createCallChain(typescript_1.default.factory.createPropertyAccessChain(accessor("customs"), typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.QuestionDotToken), typescript_1.default.factory.createIdentifier(type)), typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.QuestionDotToken), undefined, [
|
|
14
|
+
return ExpressionFactory_1.ExpressionFactory.coalesce(typescript_1.default.factory.createCallChain(typescript_1.default.factory.createPropertyAccessChain(accessor("customs"), typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.QuestionDotToken), typescript_1.default.factory.createIdentifier(type)), typescript_1.default.factory.createToken(typescript_1.default.SyntaxKind.QuestionDotToken), undefined, [
|
|
15
|
+
LiteralFactory_1.LiteralFactory.generate(tags.map(function (t) { return ({
|
|
16
|
+
name: t.name,
|
|
17
|
+
kind: t.kind,
|
|
18
|
+
value: t.value,
|
|
19
|
+
}); })),
|
|
20
|
+
]))(expression);
|
|
15
21
|
};
|
|
16
22
|
};
|
|
17
23
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"random_custom.js","sourceRoot":"","sources":["../../../src/programmers/internal/random_custom.ts"],"names":[],"mappings":";;;;;;AAAA,0DAA4B;AAE5B,uEAAsE;AACtE,iEAAgE;AASzD,IAAM,aAAa,GACtB,UAAC,QAAyC;IAC1C,OAAA,UAAC,IAAwB;QACzB,OAAA,UAAC,IAAwB;YACzB,OAAA,UAAC,UAAyB;gBACtB,OAAA,qCAAiB,CAAC,QAAQ,CACtB,oBAAE,CAAC,OAAO,CAAC,eAAe,CACtB,oBAAE,CAAC,OAAO,CAAC,yBAAyB,CAChC,QAAQ,CAAC,SAAS,CAAC,EACnB,oBAAE,CAAC,OAAO,CAAC,WAAW,CAAC,oBAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EACtD,oBAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CACpC,EACD,oBAAE,CAAC,OAAO,CAAC,WAAW,CAAC,oBAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EACtD,SAAS,EACT
|
|
1
|
+
{"version":3,"file":"random_custom.js","sourceRoot":"","sources":["../../../src/programmers/internal/random_custom.ts"],"names":[],"mappings":";;;;;;AAAA,0DAA4B;AAE5B,uEAAsE;AACtE,iEAAgE;AASzD,IAAM,aAAa,GACtB,UAAC,QAAyC;IAC1C,OAAA,UAAC,IAAwB;QACzB,OAAA,UAAC,IAAwB;YACzB,OAAA,UAAC,UAAyB;gBACtB,OAAA,qCAAiB,CAAC,QAAQ,CACtB,oBAAE,CAAC,OAAO,CAAC,eAAe,CACtB,oBAAE,CAAC,OAAO,CAAC,yBAAyB,CAChC,QAAQ,CAAC,SAAS,CAAC,EACnB,oBAAE,CAAC,OAAO,CAAC,WAAW,CAAC,oBAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EACtD,oBAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,CACpC,EACD,oBAAE,CAAC,OAAO,CAAC,WAAW,CAAC,oBAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EACtD,SAAS,EACT;oBACI,+BAAc,CAAC,QAAQ,CACnB,IAAI,CAAC,GAAG,CAAC,UAAC,CAAC,IAAK,OAAA,CAAC;wBACb,IAAI,EAAE,CAAC,CAAC,IAAI;wBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;wBACZ,KAAK,EAAE,CAAC,CAAC,KAAK;qBACjB,CAAC,EAJc,CAId,CAAC,CACN;iBACJ,CACJ,CACJ,CAAC,UAAU,CAAC;YAnBb,CAmBa;QApBjB,CAoBiB;IArBjB,CAqBiB;AAtBjB,CAsBiB,CAAC;AAxBT,QAAA,aAAa,iBAwBJ"}
|
package/lib/protobuf.d.ts
CHANGED
|
@@ -51,17 +51,17 @@ export declare function message<T>(): string;
|
|
|
51
51
|
* For reference, as Protocol Buffer handles binary data directly, there's no way
|
|
52
52
|
* when `input` binary data was not encoded from the `T` typed value. In that case,
|
|
53
53
|
* unexpected behavior or internal error would be occured. Therefore, I recommend you
|
|
54
|
-
* to encode binary data of Protocol Buffer from type safe encode
|
|
54
|
+
* to encode binary data of Protocol Buffer from type safe encode functions like below.
|
|
55
55
|
* Use {@link encode} function only when you can ensure it.
|
|
56
56
|
*
|
|
57
57
|
* - {@link assertEncode}
|
|
58
58
|
* - {@link isEncode}
|
|
59
59
|
* - {@link validateEncode}
|
|
60
60
|
*
|
|
61
|
-
* Also, `typia` is providing
|
|
62
|
-
* is just for additional validation like
|
|
63
|
-
*
|
|
64
|
-
* [
|
|
61
|
+
* Also, `typia` is providing type safe decoders like {@link assertDecode}, but it
|
|
62
|
+
* is just for additional type validation like `number & Minimum<7>` or
|
|
63
|
+
* `string & Format<"uuid">` cases, that are represented by
|
|
64
|
+
* [custom tags](https://typia.io/docs/validators/tags). Thus, I repeat that,
|
|
65
65
|
* you've to ensure the type safety when using decoder functions.
|
|
66
66
|
*
|
|
67
67
|
* @tempate Expected type of decoded value
|
|
@@ -80,17 +80,17 @@ export declare function decode(input: Uint8Array): never;
|
|
|
80
80
|
* For reference, as Protocol Buffer handles binary data directly, there's no way
|
|
81
81
|
* when `input` binary data was not encoded from the `T` typed value. In that case,
|
|
82
82
|
* unexpected behavior or internal error would be occured. Therefore, I recommend you
|
|
83
|
-
* to encode binary data of Protocol Buffer from type safe encode
|
|
83
|
+
* to encode binary data of Protocol Buffer from type safe encode functions like below.
|
|
84
84
|
* Use {@link encode} function only when you can ensure it.
|
|
85
85
|
*
|
|
86
86
|
* - {@link assertEncode}
|
|
87
87
|
* - {@link isEncode}
|
|
88
88
|
* - {@link validateEncode}
|
|
89
89
|
*
|
|
90
|
-
* Also, `typia` is providing
|
|
91
|
-
* is just for additional validation like
|
|
92
|
-
*
|
|
93
|
-
* [
|
|
90
|
+
* Also, `typia` is providing type safe decoders like {@link assertDecode}, but it
|
|
91
|
+
* is just for additional type validation like `number & Minimum<7>` or
|
|
92
|
+
* `string & Format<"uuid">` cases, that are represented by
|
|
93
|
+
* [custom tags](https://typia.io/docs/validators/tags). Thus, I repeat that,
|
|
94
94
|
* you've to ensure the type safety when using decoder functions.
|
|
95
95
|
*
|
|
96
96
|
* @tempate Expected type of decoded value
|
|
@@ -112,10 +112,10 @@ export declare function decode<T>(input: Uint8Array): Resolved<T>;
|
|
|
112
112
|
* {@link TypeGuardError} instead.
|
|
113
113
|
*
|
|
114
114
|
* However, note that, this validation is not always safe. It just performs additional
|
|
115
|
-
* type
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
115
|
+
* type assertion like `number & Minimum<7>` or `string & Format<"uuid">` cases,
|
|
116
|
+
* that are represented by [custom tags](https://typia.io/docs/validators/tags).
|
|
117
|
+
* Therefore, when using `typia.protobuf.assertDecode<T>()` function, you have to
|
|
118
|
+
* ensure the type safety by yourself.
|
|
119
119
|
*
|
|
120
120
|
* In such type safety reason, I recommend you to use type safe encode functions.
|
|
121
121
|
*
|
|
@@ -140,10 +140,10 @@ export declare function assertDecode(input: Uint8Array): never;
|
|
|
140
140
|
* {@link TypeGuardError} instead.
|
|
141
141
|
*
|
|
142
142
|
* However, note that, this validation is not always safe. It just performs additional
|
|
143
|
-
* type
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
143
|
+
* type assertion like `number & Minimum<7>` or `string & Format<"uuid">` cases,
|
|
144
|
+
* that are represented by [custom tags](https://typia.io/docs/validators/tags).
|
|
145
|
+
* Therefore, when using `typia.protobuf.assertDecode<T>()` function, you have to
|
|
146
|
+
* ensure the type safety by yourself.
|
|
147
147
|
*
|
|
148
148
|
* In such type safety reason, I recommend you to use type safe encode functions.
|
|
149
149
|
*
|
|
@@ -170,10 +170,10 @@ export declare function assertDecode<T>(input: Uint8Array): Resolved<T>;
|
|
|
170
170
|
* `null` value instead.
|
|
171
171
|
*
|
|
172
172
|
* However, note that, this validation is not always safe. It just performs additional
|
|
173
|
-
* type checking like
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
173
|
+
* type checking like `number & Minimum<7>` or `string & Format<"uuid">` cases,
|
|
174
|
+
* that are represented by [custom tags](https://typia.io/docs/validators/tags).
|
|
175
|
+
* Therefore, when using `typia.protobuf.isDecode<T>()` function, you have to
|
|
176
|
+
* ensure the type safety by yourself.
|
|
177
177
|
*
|
|
178
178
|
* In such type safety reason, I recommend you to use type safe encode functions.
|
|
179
179
|
*
|
|
@@ -198,10 +198,10 @@ export declare function isDecode(input: Uint8Array): never;
|
|
|
198
198
|
* `null` value instead.
|
|
199
199
|
*
|
|
200
200
|
* However, note that, this validation is not always safe. It just performs additional
|
|
201
|
-
* type checking like
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
201
|
+
* type checking like `number & Minimum<7>` or `string & Format<"uuid">` cases,
|
|
202
|
+
* that are represented by [custom tags](https://typia.io/docs/validators/tags).
|
|
203
|
+
* Therefore, when using `typia.protobuf.isDecode<T>()` function, you have to
|
|
204
|
+
* ensure the type safety by yourself.
|
|
205
205
|
*
|
|
206
206
|
* In such type safety reason, I recommend you to use type safe encode functions.
|
|
207
207
|
*
|
|
@@ -229,10 +229,10 @@ export declare function isDecode<T>(input: Uint8Array): Resolved<T> | null;
|
|
|
229
229
|
* {@link IValidation.IFailure} value instead with detailed error reasons.
|
|
230
230
|
*
|
|
231
231
|
* However, note that, this validation is not always safe. It just performs additional
|
|
232
|
-
* type
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
232
|
+
* type validation like `number & Minimum<7>` or `string & Format<"uuid">` cases,
|
|
233
|
+
* that are represented by [custom tags](https://typia.io/docs/validators/tags).
|
|
234
|
+
* Therefore, when using `typia.protobuf.validateDecode<T>()` function, you have to
|
|
235
|
+
* ensure the type safety by yourself.
|
|
236
236
|
*
|
|
237
237
|
* In such type safety reason, I recommend you to use type safe encode functions.
|
|
238
238
|
*
|
|
@@ -258,10 +258,10 @@ export declare function validateDecode(input: Uint8Array): never;
|
|
|
258
258
|
* {@link IValidation.IFailure} value instead with detailed error reasons.
|
|
259
259
|
*
|
|
260
260
|
* However, note that, this validation is not always safe. It just performs additional
|
|
261
|
-
* type
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
261
|
+
* type validation like `number & Minimum<7>` or `string & Format<"uuid">` cases,
|
|
262
|
+
* that are represented by [custom tags](https://typia.io/docs/validators/tags).
|
|
263
|
+
* Therefore, when using `typia.protobuf.validateDecode<T>()` function, you have to
|
|
264
|
+
* ensure the type safety by yourself.
|
|
265
265
|
*
|
|
266
266
|
* In such type safety reason, I recommend you to use type safe encode functions.
|
|
267
267
|
*
|
package/package.json
CHANGED
|
@@ -1,214 +1,214 @@
|
|
|
1
|
-
import ts from "typescript";
|
|
2
|
-
|
|
3
|
-
import { Metadata } from "../schemas/metadata/Metadata";
|
|
4
|
-
import { MetadataAlias } from "../schemas/metadata/MetadataAlias";
|
|
5
|
-
import { MetadataArrayType } from "../schemas/metadata/MetadataArrayType";
|
|
6
|
-
import { MetadataObject } from "../schemas/metadata/MetadataObject";
|
|
7
|
-
import { MetadataTupleType } from "../schemas/metadata/MetadataTupleType";
|
|
8
|
-
import { explore_metadata } from "./internal/metadata/explore_metadata";
|
|
9
|
-
import { iterate_metadata_collection } from "./internal/metadata/iterate_metadata_collection";
|
|
10
|
-
import { iterate_metadata_sort } from "./internal/metadata/iterate_metadata_sort";
|
|
11
|
-
|
|
12
|
-
import { ValidationPipe } from "../typings/ValidationPipe";
|
|
13
|
-
|
|
14
|
-
import { MetadataCollection } from "./MetadataCollection";
|
|
15
|
-
|
|
16
|
-
export namespace MetadataFactory {
|
|
17
|
-
export type Validator = (meta: Metadata, explore: IExplore) => string[];
|
|
18
|
-
|
|
19
|
-
export interface IOptions {
|
|
20
|
-
escape: boolean;
|
|
21
|
-
constant: boolean;
|
|
22
|
-
absorb: boolean;
|
|
23
|
-
validate?: Validator;
|
|
24
|
-
onError?: (node: ts.Node | undefined, message: string) => void;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface IExplore {
|
|
28
|
-
top: boolean;
|
|
29
|
-
object: MetadataObject | null;
|
|
30
|
-
property: string | object | null;
|
|
31
|
-
nested: null | MetadataAlias | MetadataArrayType | MetadataTupleType;
|
|
32
|
-
escaped: boolean;
|
|
33
|
-
aliased: boolean;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface IError {
|
|
37
|
-
name: string;
|
|
38
|
-
explore: IExplore;
|
|
39
|
-
messages: string[];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const analyze =
|
|
43
|
-
(checker: ts.TypeChecker) =>
|
|
44
|
-
(options: IOptions) =>
|
|
45
|
-
(collection: MetadataCollection) =>
|
|
46
|
-
(type: ts.Type | null): ValidationPipe<Metadata, IError> => {
|
|
47
|
-
const errors: IError[] = [];
|
|
48
|
-
const meta: Metadata = explore_metadata(checker)(options)(
|
|
49
|
-
collection,
|
|
50
|
-
)(errors)(type, {
|
|
51
|
-
top: true,
|
|
52
|
-
object: null,
|
|
53
|
-
property: null,
|
|
54
|
-
nested: null,
|
|
55
|
-
escaped: false,
|
|
56
|
-
aliased: false,
|
|
57
|
-
});
|
|
58
|
-
iterate_metadata_collection(errors)(collection);
|
|
59
|
-
iterate_metadata_sort(collection)(meta);
|
|
60
|
-
|
|
61
|
-
if (options.validate)
|
|
62
|
-
errors.push(...validate(options)(options.validate)(meta));
|
|
63
|
-
return errors.length
|
|
64
|
-
? {
|
|
65
|
-
success: false,
|
|
66
|
-
errors,
|
|
67
|
-
}
|
|
68
|
-
: {
|
|
69
|
-
success: true,
|
|
70
|
-
data: meta,
|
|
71
|
-
};
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @internal
|
|
76
|
-
*/
|
|
77
|
-
export const soleLiteral = (value: string): Metadata => {
|
|
78
|
-
const meta: Metadata = Metadata.initialize();
|
|
79
|
-
meta.constants.push({
|
|
80
|
-
values: [value],
|
|
81
|
-
type: "string",
|
|
82
|
-
});
|
|
83
|
-
return meta;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const validate =
|
|
87
|
-
(options: IOptions) =>
|
|
88
|
-
(functor: Validator) =>
|
|
89
|
-
(meta: Metadata): IError[] => {
|
|
90
|
-
const visitor: IValidationVisitor = {
|
|
91
|
-
functor,
|
|
92
|
-
errors: [],
|
|
93
|
-
objects: new Set(),
|
|
94
|
-
arrays: new Set(),
|
|
95
|
-
tuples: new Set(),
|
|
96
|
-
aliases: new Set(),
|
|
97
|
-
};
|
|
98
|
-
validateMeta(options)(visitor)(meta, {
|
|
99
|
-
object: null,
|
|
100
|
-
property: null,
|
|
101
|
-
nested: null,
|
|
102
|
-
top: true,
|
|
103
|
-
aliased: false,
|
|
104
|
-
escaped: false,
|
|
105
|
-
});
|
|
106
|
-
return visitor.errors;
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const validateMeta =
|
|
110
|
-
(options: IOptions) =>
|
|
111
|
-
(visitor: IValidationVisitor) =>
|
|
112
|
-
(meta: Metadata, explore: IExplore) => {
|
|
113
|
-
const result: Set<string> = new Set(visitor.functor(meta, explore));
|
|
114
|
-
if (result.size)
|
|
115
|
-
visitor.errors.push({
|
|
116
|
-
name: meta.getName(),
|
|
117
|
-
explore: { ...explore },
|
|
118
|
-
messages: [...result],
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
for (const alias of meta.aliases)
|
|
122
|
-
validateAlias(options)(visitor)(alias, explore);
|
|
123
|
-
for (const array of meta.arrays)
|
|
124
|
-
validateArray(options)(visitor)(array.type, explore);
|
|
125
|
-
for (const tuple of meta.tuples)
|
|
126
|
-
validateTuple(options)(visitor)(tuple.type, explore);
|
|
127
|
-
for (const obj of meta.objects)
|
|
128
|
-
validateObject(options)(visitor)(obj);
|
|
129
|
-
for (const set of meta.sets)
|
|
130
|
-
validateMeta(options)(visitor)(set, explore);
|
|
131
|
-
for (const map of meta.maps) {
|
|
132
|
-
validateMeta(options)(visitor)(map.key, explore);
|
|
133
|
-
validateMeta(options)(visitor)(map.value, explore);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (options.escape === true && meta.escaped !== null)
|
|
137
|
-
validateMeta(options)(visitor)(meta.escaped.returns, {
|
|
138
|
-
...explore,
|
|
139
|
-
escaped: true,
|
|
140
|
-
});
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const validateAlias =
|
|
144
|
-
(options: IOptions) =>
|
|
145
|
-
(visitor: IValidationVisitor) =>
|
|
146
|
-
(alias: MetadataAlias, explore: IExplore) => {
|
|
147
|
-
if (visitor.aliases.has(alias)) return;
|
|
148
|
-
visitor.aliases.add(alias);
|
|
149
|
-
|
|
150
|
-
validateMeta(options)(visitor)(alias.value, {
|
|
151
|
-
...explore,
|
|
152
|
-
nested: alias,
|
|
153
|
-
aliased: true,
|
|
154
|
-
});
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
const validateArray =
|
|
158
|
-
(options: IOptions) =>
|
|
159
|
-
(visitor: IValidationVisitor) =>
|
|
160
|
-
(array: MetadataArrayType, explore: IExplore) => {
|
|
161
|
-
if (visitor.arrays.has(array)) return;
|
|
162
|
-
visitor.arrays.add(array);
|
|
163
|
-
|
|
164
|
-
validateMeta(options)(visitor)(array.value, {
|
|
165
|
-
...explore,
|
|
166
|
-
nested: array,
|
|
167
|
-
top: false,
|
|
168
|
-
});
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
const validateTuple =
|
|
172
|
-
(options: IOptions) =>
|
|
173
|
-
(visitor: IValidationVisitor) =>
|
|
174
|
-
(tuple: MetadataTupleType, explore: IExplore) => {
|
|
175
|
-
if (visitor.tuples.has(tuple)) return;
|
|
176
|
-
visitor.tuples.add(tuple);
|
|
177
|
-
|
|
178
|
-
for (const elem of tuple.elements)
|
|
179
|
-
validateMeta(options)(visitor)(elem, {
|
|
180
|
-
...explore,
|
|
181
|
-
nested: tuple,
|
|
182
|
-
top: false,
|
|
183
|
-
});
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
const validateObject =
|
|
187
|
-
(options: IOptions) =>
|
|
188
|
-
(visitor: IValidationVisitor) =>
|
|
189
|
-
(object: MetadataObject) => {
|
|
190
|
-
if (visitor.objects.has(object)) return;
|
|
191
|
-
visitor.objects.add(object);
|
|
192
|
-
|
|
193
|
-
for (const property of object.properties)
|
|
194
|
-
validateMeta(options)(visitor)(property.value, {
|
|
195
|
-
object,
|
|
196
|
-
property: property.key.isSoleLiteral()
|
|
197
|
-
? property.key.getSoleLiteral()!
|
|
198
|
-
: {},
|
|
199
|
-
nested: null,
|
|
200
|
-
top: false,
|
|
201
|
-
aliased: false,
|
|
202
|
-
escaped: false,
|
|
203
|
-
});
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
interface IValidationVisitor {
|
|
207
|
-
functor: Validator;
|
|
208
|
-
errors: IError[];
|
|
209
|
-
objects: Set<MetadataObject>;
|
|
210
|
-
arrays: Set<MetadataArrayType>;
|
|
211
|
-
tuples: Set<MetadataTupleType>;
|
|
212
|
-
aliases: Set<MetadataAlias>;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
|
|
3
|
+
import { Metadata } from "../schemas/metadata/Metadata";
|
|
4
|
+
import { MetadataAlias } from "../schemas/metadata/MetadataAlias";
|
|
5
|
+
import { MetadataArrayType } from "../schemas/metadata/MetadataArrayType";
|
|
6
|
+
import { MetadataObject } from "../schemas/metadata/MetadataObject";
|
|
7
|
+
import { MetadataTupleType } from "../schemas/metadata/MetadataTupleType";
|
|
8
|
+
import { explore_metadata } from "./internal/metadata/explore_metadata";
|
|
9
|
+
import { iterate_metadata_collection } from "./internal/metadata/iterate_metadata_collection";
|
|
10
|
+
import { iterate_metadata_sort } from "./internal/metadata/iterate_metadata_sort";
|
|
11
|
+
|
|
12
|
+
import { ValidationPipe } from "../typings/ValidationPipe";
|
|
13
|
+
|
|
14
|
+
import { MetadataCollection } from "./MetadataCollection";
|
|
15
|
+
|
|
16
|
+
export namespace MetadataFactory {
|
|
17
|
+
export type Validator = (meta: Metadata, explore: IExplore) => string[];
|
|
18
|
+
|
|
19
|
+
export interface IOptions {
|
|
20
|
+
escape: boolean;
|
|
21
|
+
constant: boolean;
|
|
22
|
+
absorb: boolean;
|
|
23
|
+
validate?: Validator;
|
|
24
|
+
onError?: (node: ts.Node | undefined, message: string) => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface IExplore {
|
|
28
|
+
top: boolean;
|
|
29
|
+
object: MetadataObject | null;
|
|
30
|
+
property: string | object | null;
|
|
31
|
+
nested: null | MetadataAlias | MetadataArrayType | MetadataTupleType;
|
|
32
|
+
escaped: boolean;
|
|
33
|
+
aliased: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface IError {
|
|
37
|
+
name: string;
|
|
38
|
+
explore: IExplore;
|
|
39
|
+
messages: string[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const analyze =
|
|
43
|
+
(checker: ts.TypeChecker) =>
|
|
44
|
+
(options: IOptions) =>
|
|
45
|
+
(collection: MetadataCollection) =>
|
|
46
|
+
(type: ts.Type | null): ValidationPipe<Metadata, IError> => {
|
|
47
|
+
const errors: IError[] = [];
|
|
48
|
+
const meta: Metadata = explore_metadata(checker)(options)(
|
|
49
|
+
collection,
|
|
50
|
+
)(errors)(type, {
|
|
51
|
+
top: true,
|
|
52
|
+
object: null,
|
|
53
|
+
property: null,
|
|
54
|
+
nested: null,
|
|
55
|
+
escaped: false,
|
|
56
|
+
aliased: false,
|
|
57
|
+
});
|
|
58
|
+
iterate_metadata_collection(errors)(collection);
|
|
59
|
+
iterate_metadata_sort(collection)(meta);
|
|
60
|
+
|
|
61
|
+
if (options.validate)
|
|
62
|
+
errors.push(...validate(options)(options.validate)(meta));
|
|
63
|
+
return errors.length
|
|
64
|
+
? {
|
|
65
|
+
success: false,
|
|
66
|
+
errors,
|
|
67
|
+
}
|
|
68
|
+
: {
|
|
69
|
+
success: true,
|
|
70
|
+
data: meta,
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @internal
|
|
76
|
+
*/
|
|
77
|
+
export const soleLiteral = (value: string): Metadata => {
|
|
78
|
+
const meta: Metadata = Metadata.initialize();
|
|
79
|
+
meta.constants.push({
|
|
80
|
+
values: [value],
|
|
81
|
+
type: "string",
|
|
82
|
+
});
|
|
83
|
+
return meta;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const validate =
|
|
87
|
+
(options: IOptions) =>
|
|
88
|
+
(functor: Validator) =>
|
|
89
|
+
(meta: Metadata): IError[] => {
|
|
90
|
+
const visitor: IValidationVisitor = {
|
|
91
|
+
functor,
|
|
92
|
+
errors: [],
|
|
93
|
+
objects: new Set(),
|
|
94
|
+
arrays: new Set(),
|
|
95
|
+
tuples: new Set(),
|
|
96
|
+
aliases: new Set(),
|
|
97
|
+
};
|
|
98
|
+
validateMeta(options)(visitor)(meta, {
|
|
99
|
+
object: null,
|
|
100
|
+
property: null,
|
|
101
|
+
nested: null,
|
|
102
|
+
top: true,
|
|
103
|
+
aliased: false,
|
|
104
|
+
escaped: false,
|
|
105
|
+
});
|
|
106
|
+
return visitor.errors;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const validateMeta =
|
|
110
|
+
(options: IOptions) =>
|
|
111
|
+
(visitor: IValidationVisitor) =>
|
|
112
|
+
(meta: Metadata, explore: IExplore) => {
|
|
113
|
+
const result: Set<string> = new Set(visitor.functor(meta, explore));
|
|
114
|
+
if (result.size)
|
|
115
|
+
visitor.errors.push({
|
|
116
|
+
name: meta.getName(),
|
|
117
|
+
explore: { ...explore },
|
|
118
|
+
messages: [...result],
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
for (const alias of meta.aliases)
|
|
122
|
+
validateAlias(options)(visitor)(alias, explore);
|
|
123
|
+
for (const array of meta.arrays)
|
|
124
|
+
validateArray(options)(visitor)(array.type, explore);
|
|
125
|
+
for (const tuple of meta.tuples)
|
|
126
|
+
validateTuple(options)(visitor)(tuple.type, explore);
|
|
127
|
+
for (const obj of meta.objects)
|
|
128
|
+
validateObject(options)(visitor)(obj);
|
|
129
|
+
for (const set of meta.sets)
|
|
130
|
+
validateMeta(options)(visitor)(set, explore);
|
|
131
|
+
for (const map of meta.maps) {
|
|
132
|
+
validateMeta(options)(visitor)(map.key, explore);
|
|
133
|
+
validateMeta(options)(visitor)(map.value, explore);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (options.escape === true && meta.escaped !== null)
|
|
137
|
+
validateMeta(options)(visitor)(meta.escaped.returns, {
|
|
138
|
+
...explore,
|
|
139
|
+
escaped: true,
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const validateAlias =
|
|
144
|
+
(options: IOptions) =>
|
|
145
|
+
(visitor: IValidationVisitor) =>
|
|
146
|
+
(alias: MetadataAlias, explore: IExplore) => {
|
|
147
|
+
if (visitor.aliases.has(alias)) return;
|
|
148
|
+
visitor.aliases.add(alias);
|
|
149
|
+
|
|
150
|
+
validateMeta(options)(visitor)(alias.value, {
|
|
151
|
+
...explore,
|
|
152
|
+
nested: alias,
|
|
153
|
+
aliased: true,
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const validateArray =
|
|
158
|
+
(options: IOptions) =>
|
|
159
|
+
(visitor: IValidationVisitor) =>
|
|
160
|
+
(array: MetadataArrayType, explore: IExplore) => {
|
|
161
|
+
if (visitor.arrays.has(array)) return;
|
|
162
|
+
visitor.arrays.add(array);
|
|
163
|
+
|
|
164
|
+
validateMeta(options)(visitor)(array.value, {
|
|
165
|
+
...explore,
|
|
166
|
+
nested: array,
|
|
167
|
+
top: false,
|
|
168
|
+
});
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const validateTuple =
|
|
172
|
+
(options: IOptions) =>
|
|
173
|
+
(visitor: IValidationVisitor) =>
|
|
174
|
+
(tuple: MetadataTupleType, explore: IExplore) => {
|
|
175
|
+
if (visitor.tuples.has(tuple)) return;
|
|
176
|
+
visitor.tuples.add(tuple);
|
|
177
|
+
|
|
178
|
+
for (const elem of tuple.elements)
|
|
179
|
+
validateMeta(options)(visitor)(elem, {
|
|
180
|
+
...explore,
|
|
181
|
+
nested: tuple,
|
|
182
|
+
top: false,
|
|
183
|
+
});
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const validateObject =
|
|
187
|
+
(options: IOptions) =>
|
|
188
|
+
(visitor: IValidationVisitor) =>
|
|
189
|
+
(object: MetadataObject) => {
|
|
190
|
+
if (visitor.objects.has(object)) return;
|
|
191
|
+
visitor.objects.add(object);
|
|
192
|
+
|
|
193
|
+
for (const property of object.properties)
|
|
194
|
+
validateMeta(options)(visitor)(property.value, {
|
|
195
|
+
object,
|
|
196
|
+
property: property.key.isSoleLiteral()
|
|
197
|
+
? property.key.getSoleLiteral()!
|
|
198
|
+
: {},
|
|
199
|
+
nested: null,
|
|
200
|
+
top: false,
|
|
201
|
+
aliased: false,
|
|
202
|
+
escaped: false,
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
interface IValidationVisitor {
|
|
207
|
+
functor: Validator;
|
|
208
|
+
errors: IError[];
|
|
209
|
+
objects: Set<MetadataObject>;
|
|
210
|
+
arrays: Set<MetadataArrayType>;
|
|
211
|
+
tuples: Set<MetadataTupleType>;
|
|
212
|
+
aliases: Set<MetadataAlias>;
|
|
213
|
+
}
|
|
214
|
+
}
|