typia 5.0.0-dev.20230829 → 5.0.0-dev.20230829-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.
@@ -1,272 +1,272 @@
1
- import ts from "typescript";
2
-
3
- import { Metadata } from "../schemas/metadata/Metadata";
4
- import { MetadataObject } from "../schemas/metadata/MetadataObject";
5
-
6
- import { ProtobufUtil } from "../programmers/helpers/ProtobufUtil";
7
-
8
- import { TransformerError } from "../transformers/TransformerError";
9
-
10
- import { ValidationPipe } from "../typings/ValidationPipe";
11
-
12
- import { Escaper } from "../utils/Escaper";
13
-
14
- import { MetadataCollection } from "./MetadataCollection";
15
- import { MetadataFactory } from "./MetadataFactory";
16
-
17
- export namespace ProtobufFactory {
18
- export const metadata =
19
- (method: string) =>
20
- (checker: ts.TypeChecker) =>
21
- (collection: MetadataCollection) =>
22
- (type: ts.Type): Metadata => {
23
- // COMPOSE METADATA WITH INDIVIDUAL VALIDATIONS
24
- const result: ValidationPipe<Metadata, MetadataFactory.IError> =
25
- MetadataFactory.analyze(checker)({
26
- escape: false,
27
- constant: true,
28
- absorb: true,
29
- validate,
30
- })(collection)(type);
31
- if (result.success === false)
32
- throw TransformerError.from(`typia.protobuf.${method}`)(
33
- result.errors,
34
- );
35
- return result.data;
36
- };
37
-
38
- const validate = (
39
- meta: Metadata,
40
- explore: MetadataFactory.IExplore,
41
- ): string[] => {
42
- const errors: string[] = [];
43
- const insert = (msg: string) => errors.push(msg);
44
-
45
- if (explore.top === true) {
46
- const onlyObject: boolean =
47
- meta.size() === 1 &&
48
- meta.objects.length === 1 &&
49
- meta.objects[0]!.properties.every((p) =>
50
- p.key.isSoleLiteral(),
51
- ) &&
52
- meta.isRequired() === true &&
53
- meta.nullable === false;
54
- if (onlyObject === false)
55
- insert("target type must be a sole and static object type");
56
- }
57
-
58
- //----
59
- // NOT SUPPORTED TYPES
60
- //----
61
- const noSupport = (msg: string) => insert(`does not support ${msg}`);
62
-
63
- // PROHIBIT ANY TYPE
64
- if (meta.any) noSupport("any type");
65
- // PROHIBIT FUNCTIONAL TYPE
66
- if (meta.functional) noSupport("functional type");
67
- // PROHIBIT TUPLE TYPE
68
- if (meta.tuples.length) noSupport("tuple type");
69
- // PROHIBIT SET TYPE
70
- if (meta.sets.length) noSupport("Set type");
71
- // NATIVE TYPE, BUT NOT Uint8Array
72
- if (meta.natives.length)
73
- for (const native of meta.natives) {
74
- if (native === "Uint8Array") continue;
75
-
76
- const instead = BANNED_NATIVE_TYPES.get(native);
77
- if (instead === undefined) noSupport(`${native} type`);
78
- else noSupport(`${native} type. Use ${instead} type instead.`);
79
- }
80
- //----
81
- // ATOMIC CASES
82
- //----
83
- if (meta.atomics.length) {
84
- const numbers = ProtobufUtil.getNumbers(meta);
85
- const bigints = ProtobufUtil.getBigints(meta);
86
-
87
- for (const type of ["int64", "uint64"])
88
- if (
89
- numbers.some((n) => n === type) &&
90
- bigints.some((b) => b === type)
91
- )
92
- insert(
93
- `tags.Type<"${type}"> cannot be used in both number and bigint types. Recommend to remove from number type`,
94
- );
95
- }
96
- //----
97
- // ARRRAY CASES
98
- //----
99
- // DO NOT ALLOW MULTI-DIMENTIONAL ARRAY
100
- if (
101
- meta.arrays.length &&
102
- meta.arrays.some((array) => !!array.type.value.arrays.length)
103
- )
104
- noSupport("over two dimenstional array type");
105
- // CHILD OF ARRAY TYPE MUST BE REQUIRED
106
- if (
107
- meta.arrays.length &&
108
- meta.arrays.some(
109
- (array) =>
110
- array.type.value.isRequired() === false ||
111
- array.type.value.nullable === true,
112
- )
113
- )
114
- noSupport("optional type in array");
115
- // UNION IN ARRAY
116
- if (
117
- meta.arrays.length &&
118
- meta.arrays.some((a) => a.type.value.size() > 1)
119
- )
120
- noSupport("union type in array");
121
- // DO DYNAMIC OBJECT IN ARRAY
122
- if (
123
- meta.arrays.length &&
124
- meta.arrays.some(
125
- (a) =>
126
- a.type.value.maps.length ||
127
- (a.type.value.objects.length &&
128
- a.type.value.objects.some(
129
- (o) => ProtobufUtil.isStaticObject(o) === false,
130
- )),
131
- )
132
- )
133
- noSupport("dynamic object in array");
134
- // UNION WITH ARRAY
135
- if (meta.size() > 1 && meta.arrays.length)
136
- noSupport("union type with array type");
137
- //----
138
- // OBJECT CASES
139
- //----
140
- // EMPTY PROPERTY
141
- if (
142
- meta.objects.length &&
143
- meta.objects.some((obj) => obj.properties.length === 0)
144
- )
145
- noSupport("empty object type");
146
- // MULTIPLE DYNAMIC KEY TYPED PROPERTIES
147
- if (
148
- meta.objects.length &&
149
- meta.objects.some(
150
- (obj) =>
151
- obj.properties.filter((p) => !p.key.isSoleLiteral())
152
- .length > 1,
153
- )
154
- )
155
- noSupport(
156
- "object type with multiple dynamic key typed properties. Keep only one.",
157
- );
158
- // STATIC AND DYNAMIC PROPERTIES ARE COMPATIBLE
159
- if (
160
- meta.objects.length &&
161
- meta.objects.some(
162
- (obj) =>
163
- obj.properties.some((p) => p.key.isSoleLiteral()) &&
164
- obj.properties.some((p) => !p.key.isSoleLiteral()),
165
- )
166
- )
167
- noSupport(
168
- "object type with mixed static and dynamic key typed properties. Keep statics or dynamic only.",
169
- );
170
- // STATIC PROPERTY, BUT INVALID KEY NAME
171
- if (
172
- meta.objects.length &&
173
- meta.objects.some((obj) =>
174
- obj.properties.some(
175
- (p) =>
176
- p.key.isSoleLiteral() === true &&
177
- Escaper.variable(p.key.getSoleLiteral()!) === false,
178
- ),
179
- )
180
- )
181
- noSupport(`object type with invalid static key name.`);
182
- // DYNAMIC OBJECT, BUT PROPERTY VALUE TYPE IS ARRAY
183
- if (
184
- meta.objects.length &&
185
- isDynamicObject(meta.objects[0]!) &&
186
- meta.objects[0]!.properties.some((p) => !!p.value.arrays.length)
187
- )
188
- noSupport("dynamic object with array value type");
189
- // UNION WITH DYNAMIC OBJECT
190
- if (
191
- meta.size() > 1 &&
192
- meta.objects.length &&
193
- isDynamicObject(meta.objects[0]!)
194
- )
195
- noSupport("union type with dynamic object type");
196
- // UNION IN DYNAMIC PROPERTY VALUE
197
- if (
198
- meta.objects.length &&
199
- meta.objects.some(
200
- (obj) =>
201
- isDynamicObject(obj) &&
202
- obj.properties.some((p) => ProtobufUtil.isUnion(p.value)),
203
- )
204
- )
205
- noSupport("union type in dynamic property");
206
- //----
207
- // MAP CASES
208
- //----
209
- // KEY TYPE IS UNION
210
- if (
211
- meta.maps.length &&
212
- meta.maps.some((m) => ProtobufUtil.isUnion(m.key))
213
- )
214
- noSupport("union key typed map");
215
- // KEY TYPE IS NOT ATOMIC
216
- if (
217
- meta.maps.length &&
218
- meta.maps.some((m) => ProtobufUtil.getAtomics(m.key).length !== 1)
219
- )
220
- noSupport("non-atomic key typed map");
221
- // MAP TYPE, BUT PROPERTY KEY TYPE IS OPTIONAL
222
- if (
223
- meta.maps.length &&
224
- meta.maps.some(
225
- (m) => m.key.isRequired() === false || m.key.nullable,
226
- )
227
- )
228
- noSupport("optional key typed map");
229
- // MAP TYPE, BUT VALUE TYPE IS ARRAY
230
- if (meta.maps.length && meta.maps.some((m) => !!m.value.arrays.length))
231
- noSupport("map type with array value type");
232
- // UNION WITH MAP
233
- if (meta.size() > 1 && meta.maps.length)
234
- noSupport("union type with map type");
235
- // UNION IN MAP
236
- if (
237
- meta.maps.length &&
238
- meta.maps.some((m) => ProtobufUtil.isUnion(m.value))
239
- )
240
- noSupport("union type in map value type");
241
- return errors;
242
- };
243
- }
244
-
245
- const isDynamicObject = (obj: MetadataObject): boolean =>
246
- obj.properties[0]!.key.isSoleLiteral() === false;
247
-
248
- const BANNED_NATIVE_TYPES: Map<string, string | null> = new Map([
249
- ["Date", "string"],
250
- ["Boolean", "boolean"],
251
- ["BigInt", "bigint"],
252
- ["Number", "number"],
253
- ["String", "string"],
254
- ...[
255
- "Buffer",
256
- "Uint8ClampedArray",
257
- "Uint16Array",
258
- "Uint32Array",
259
- "BigUint64Array",
260
- "Int8Array",
261
- "Int16Array",
262
- "Int32Array",
263
- "BigInt64Array",
264
- "Float32Array",
265
- "Float64Array",
266
- "DataView",
267
- "ArrayBuffer",
268
- "SharedArrayBuffer",
269
- ].map((name) => [name, "Uint8Array"] as const),
270
- ["WeakSet", "Array"],
271
- ["WeakMap", "Map"],
272
- ]);
1
+ import ts from "typescript";
2
+
3
+ import { Metadata } from "../schemas/metadata/Metadata";
4
+ import { MetadataObject } from "../schemas/metadata/MetadataObject";
5
+
6
+ import { ProtobufUtil } from "../programmers/helpers/ProtobufUtil";
7
+
8
+ import { TransformerError } from "../transformers/TransformerError";
9
+
10
+ import { ValidationPipe } from "../typings/ValidationPipe";
11
+
12
+ import { Escaper } from "../utils/Escaper";
13
+
14
+ import { MetadataCollection } from "./MetadataCollection";
15
+ import { MetadataFactory } from "./MetadataFactory";
16
+
17
+ export namespace ProtobufFactory {
18
+ export const metadata =
19
+ (method: string) =>
20
+ (checker: ts.TypeChecker) =>
21
+ (collection: MetadataCollection) =>
22
+ (type: ts.Type): Metadata => {
23
+ // COMPOSE METADATA WITH INDIVIDUAL VALIDATIONS
24
+ const result: ValidationPipe<Metadata, MetadataFactory.IError> =
25
+ MetadataFactory.analyze(checker)({
26
+ escape: false,
27
+ constant: true,
28
+ absorb: true,
29
+ validate,
30
+ })(collection)(type);
31
+ if (result.success === false)
32
+ throw TransformerError.from(`typia.protobuf.${method}`)(
33
+ result.errors,
34
+ );
35
+ return result.data;
36
+ };
37
+
38
+ const validate = (
39
+ meta: Metadata,
40
+ explore: MetadataFactory.IExplore,
41
+ ): string[] => {
42
+ const errors: string[] = [];
43
+ const insert = (msg: string) => errors.push(msg);
44
+
45
+ if (explore.top === true) {
46
+ const onlyObject: boolean =
47
+ meta.size() === 1 &&
48
+ meta.objects.length === 1 &&
49
+ meta.objects[0]!.properties.every((p) =>
50
+ p.key.isSoleLiteral(),
51
+ ) &&
52
+ meta.isRequired() === true &&
53
+ meta.nullable === false;
54
+ if (onlyObject === false)
55
+ insert("target type must be a sole and static object type");
56
+ }
57
+
58
+ //----
59
+ // NOT SUPPORTED TYPES
60
+ //----
61
+ const noSupport = (msg: string) => insert(`does not support ${msg}`);
62
+
63
+ // PROHIBIT ANY TYPE
64
+ if (meta.any) noSupport("any type");
65
+ // PROHIBIT FUNCTIONAL TYPE
66
+ if (meta.functional) noSupport("functional type");
67
+ // PROHIBIT TUPLE TYPE
68
+ if (meta.tuples.length) noSupport("tuple type");
69
+ // PROHIBIT SET TYPE
70
+ if (meta.sets.length) noSupport("Set type");
71
+ // NATIVE TYPE, BUT NOT Uint8Array
72
+ if (meta.natives.length)
73
+ for (const native of meta.natives) {
74
+ if (native === "Uint8Array") continue;
75
+
76
+ const instead = BANNED_NATIVE_TYPES.get(native);
77
+ if (instead === undefined) noSupport(`${native} type`);
78
+ else noSupport(`${native} type. Use ${instead} type instead.`);
79
+ }
80
+ //----
81
+ // ATOMIC CASES
82
+ //----
83
+ if (meta.atomics.length) {
84
+ const numbers = ProtobufUtil.getNumbers(meta);
85
+ const bigints = ProtobufUtil.getBigints(meta);
86
+
87
+ for (const type of ["int64", "uint64"])
88
+ if (
89
+ numbers.some((n) => n === type) &&
90
+ bigints.some((b) => b === type)
91
+ )
92
+ insert(
93
+ `tags.Type<"${type}"> cannot be used in both number and bigint types. Recommend to remove from number type`,
94
+ );
95
+ }
96
+ //----
97
+ // ARRRAY CASES
98
+ //----
99
+ // DO NOT ALLOW MULTI-DIMENTIONAL ARRAY
100
+ if (
101
+ meta.arrays.length &&
102
+ meta.arrays.some((array) => !!array.type.value.arrays.length)
103
+ )
104
+ noSupport("over two dimenstional array type");
105
+ // CHILD OF ARRAY TYPE MUST BE REQUIRED
106
+ if (
107
+ meta.arrays.length &&
108
+ meta.arrays.some(
109
+ (array) =>
110
+ array.type.value.isRequired() === false ||
111
+ array.type.value.nullable === true,
112
+ )
113
+ )
114
+ noSupport("optional type in array");
115
+ // UNION IN ARRAY
116
+ if (
117
+ meta.arrays.length &&
118
+ meta.arrays.some((a) => a.type.value.size() > 1)
119
+ )
120
+ noSupport("union type in array");
121
+ // DO DYNAMIC OBJECT IN ARRAY
122
+ if (
123
+ meta.arrays.length &&
124
+ meta.arrays.some(
125
+ (a) =>
126
+ a.type.value.maps.length ||
127
+ (a.type.value.objects.length &&
128
+ a.type.value.objects.some(
129
+ (o) => ProtobufUtil.isStaticObject(o) === false,
130
+ )),
131
+ )
132
+ )
133
+ noSupport("dynamic object in array");
134
+ // UNION WITH ARRAY
135
+ if (meta.size() > 1 && meta.arrays.length)
136
+ noSupport("union type with array type");
137
+ //----
138
+ // OBJECT CASES
139
+ //----
140
+ // EMPTY PROPERTY
141
+ if (
142
+ meta.objects.length &&
143
+ meta.objects.some((obj) => obj.properties.length === 0)
144
+ )
145
+ noSupport("empty object type");
146
+ // MULTIPLE DYNAMIC KEY TYPED PROPERTIES
147
+ if (
148
+ meta.objects.length &&
149
+ meta.objects.some(
150
+ (obj) =>
151
+ obj.properties.filter((p) => !p.key.isSoleLiteral())
152
+ .length > 1,
153
+ )
154
+ )
155
+ noSupport(
156
+ "object type with multiple dynamic key typed properties. Keep only one.",
157
+ );
158
+ // STATIC AND DYNAMIC PROPERTIES ARE COMPATIBLE
159
+ if (
160
+ meta.objects.length &&
161
+ meta.objects.some(
162
+ (obj) =>
163
+ obj.properties.some((p) => p.key.isSoleLiteral()) &&
164
+ obj.properties.some((p) => !p.key.isSoleLiteral()),
165
+ )
166
+ )
167
+ noSupport(
168
+ "object type with mixed static and dynamic key typed properties. Keep statics or dynamic only.",
169
+ );
170
+ // STATIC PROPERTY, BUT INVALID KEY NAME
171
+ if (
172
+ meta.objects.length &&
173
+ meta.objects.some((obj) =>
174
+ obj.properties.some(
175
+ (p) =>
176
+ p.key.isSoleLiteral() === true &&
177
+ Escaper.variable(p.key.getSoleLiteral()!) === false,
178
+ ),
179
+ )
180
+ )
181
+ noSupport(`object type with invalid static key name.`);
182
+ // DYNAMIC OBJECT, BUT PROPERTY VALUE TYPE IS ARRAY
183
+ if (
184
+ meta.objects.length &&
185
+ isDynamicObject(meta.objects[0]!) &&
186
+ meta.objects[0]!.properties.some((p) => !!p.value.arrays.length)
187
+ )
188
+ noSupport("dynamic object with array value type");
189
+ // UNION WITH DYNAMIC OBJECT
190
+ if (
191
+ meta.size() > 1 &&
192
+ meta.objects.length &&
193
+ isDynamicObject(meta.objects[0]!)
194
+ )
195
+ noSupport("union type with dynamic object type");
196
+ // UNION IN DYNAMIC PROPERTY VALUE
197
+ if (
198
+ meta.objects.length &&
199
+ meta.objects.some(
200
+ (obj) =>
201
+ isDynamicObject(obj) &&
202
+ obj.properties.some((p) => ProtobufUtil.isUnion(p.value)),
203
+ )
204
+ )
205
+ noSupport("union type in dynamic property");
206
+ //----
207
+ // MAP CASES
208
+ //----
209
+ // KEY TYPE IS UNION
210
+ if (
211
+ meta.maps.length &&
212
+ meta.maps.some((m) => ProtobufUtil.isUnion(m.key))
213
+ )
214
+ noSupport("union key typed map");
215
+ // KEY TYPE IS NOT ATOMIC
216
+ if (
217
+ meta.maps.length &&
218
+ meta.maps.some((m) => ProtobufUtil.getAtomics(m.key).length !== 1)
219
+ )
220
+ noSupport("non-atomic key typed map");
221
+ // MAP TYPE, BUT PROPERTY KEY TYPE IS OPTIONAL
222
+ if (
223
+ meta.maps.length &&
224
+ meta.maps.some(
225
+ (m) => m.key.isRequired() === false || m.key.nullable,
226
+ )
227
+ )
228
+ noSupport("optional key typed map");
229
+ // MAP TYPE, BUT VALUE TYPE IS ARRAY
230
+ if (meta.maps.length && meta.maps.some((m) => !!m.value.arrays.length))
231
+ noSupport("map type with array value type");
232
+ // UNION WITH MAP
233
+ if (meta.size() > 1 && meta.maps.length)
234
+ noSupport("union type with map type");
235
+ // UNION IN MAP
236
+ if (
237
+ meta.maps.length &&
238
+ meta.maps.some((m) => ProtobufUtil.isUnion(m.value))
239
+ )
240
+ noSupport("union type in map value type");
241
+ return errors;
242
+ };
243
+ }
244
+
245
+ const isDynamicObject = (obj: MetadataObject): boolean =>
246
+ obj.properties[0]!.key.isSoleLiteral() === false;
247
+
248
+ const BANNED_NATIVE_TYPES: Map<string, string | null> = new Map([
249
+ ["Date", "string"],
250
+ ["Boolean", "boolean"],
251
+ ["BigInt", "bigint"],
252
+ ["Number", "number"],
253
+ ["String", "string"],
254
+ ...[
255
+ "Buffer",
256
+ "Uint8ClampedArray",
257
+ "Uint16Array",
258
+ "Uint32Array",
259
+ "BigUint64Array",
260
+ "Int8Array",
261
+ "Int16Array",
262
+ "Int32Array",
263
+ "BigInt64Array",
264
+ "Float32Array",
265
+ "Float64Array",
266
+ "DataView",
267
+ "ArrayBuffer",
268
+ "SharedArrayBuffer",
269
+ ].map((name) => [name, "Uint8Array"] as const),
270
+ ["WeakSet", "Array"],
271
+ ["WeakMap", "Map"],
272
+ ]);