typia 4.0.0 → 4.0.1

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.
Files changed (87) hide show
  1. package/lib/programmers/ApplicationProgrammer.js +1 -1
  2. package/lib/programmers/internal/application_array.js +19 -41
  3. package/lib/programmers/internal/application_array.js.map +1 -1
  4. package/lib/programmers/internal/application_definition.d.ts +1 -1
  5. package/lib/programmers/internal/application_definition.js +8 -8
  6. package/lib/programmers/internal/application_definition.js.map +1 -1
  7. package/lib/programmers/internal/application_native.js +3 -3
  8. package/lib/programmers/internal/application_object.js +4 -4
  9. package/lib/programmers/internal/application_schema.js +3 -3
  10. package/lib/programmers/internal/application_schema.js.map +1 -1
  11. package/lib/programmers/internal/application_tuple.js +8 -30
  12. package/lib/programmers/internal/application_tuple.js.map +1 -1
  13. package/lib/schemas/IJsonComponents.d.ts +1 -12
  14. package/lib/schemas/IJsonSchema.d.ts +1 -1
  15. package/package.json +1 -1
  16. package/src/IRandomGenerator.ts +34 -34
  17. package/src/factories/IdentifierFactory.ts +65 -65
  18. package/src/factories/MetadataCollection.ts +254 -254
  19. package/src/factories/MetadataFactory.ts +40 -40
  20. package/src/factories/MetadataTagFactory.ts +300 -300
  21. package/src/factories/internal/metadata/emplace_metadata_array.ts +34 -34
  22. package/src/factories/internal/metadata/emplace_metadata_definition.ts +35 -35
  23. package/src/factories/internal/metadata/emplace_metadata_object.ts +142 -142
  24. package/src/factories/internal/metadata/emplace_metadata_tuple.ts +50 -50
  25. package/src/factories/internal/metadata/explore_metadata.ts +66 -66
  26. package/src/factories/internal/metadata/iterate_metadata.ts +77 -77
  27. package/src/factories/internal/metadata/iterate_metadata_array.ts +25 -25
  28. package/src/factories/internal/metadata/iterate_metadata_collection.ts +130 -130
  29. package/src/factories/internal/metadata/iterate_metadata_definition.ts +30 -30
  30. package/src/factories/internal/metadata/iterate_metadata_object.ts +49 -49
  31. package/src/factories/internal/metadata/iterate_metadata_sort.ts +68 -68
  32. package/src/factories/internal/metadata/iterate_metadata_tuple.ts +24 -24
  33. package/src/factories/internal/metadata/iterate_metadata_union.ts +68 -68
  34. package/src/metadata/IMetadata.ts +27 -27
  35. package/src/metadata/IMetadataAlias.ts +12 -12
  36. package/src/metadata/IMetadataApplication.ts +7 -7
  37. package/src/metadata/IMetadataArray.ts +10 -10
  38. package/src/metadata/IMetadataCollection.ts +11 -11
  39. package/src/metadata/IMetadataDictionary.ts +14 -14
  40. package/src/metadata/IMetadataObject.ts +18 -18
  41. package/src/metadata/IMetadataProperty.ts +11 -11
  42. package/src/metadata/IMetadataTuple.ts +10 -10
  43. package/src/metadata/Metadata.ts +585 -585
  44. package/src/metadata/MetadataAlias.ts +61 -61
  45. package/src/metadata/MetadataArray.ts +52 -52
  46. package/src/metadata/MetadataObject.ts +114 -114
  47. package/src/metadata/MetadataProperty.ts +64 -64
  48. package/src/metadata/MetadataTuple.ts +53 -53
  49. package/src/programmers/ApplicationProgrammer.ts +55 -55
  50. package/src/programmers/AssertProgrammer.ts +291 -291
  51. package/src/programmers/CheckerProgrammer.ts +1182 -1182
  52. package/src/programmers/CloneProgrammer.ts +595 -595
  53. package/src/programmers/FeatureProgrammer.ts +495 -495
  54. package/src/programmers/IsProgrammer.ts +250 -250
  55. package/src/programmers/LiteralsProgrammer.ts +66 -66
  56. package/src/programmers/PruneProgrammer.ts +550 -550
  57. package/src/programmers/RandomProgrammer.ts +589 -589
  58. package/src/programmers/StringifyProgrammer.ts +990 -990
  59. package/src/programmers/ValidateProgrammer.ts +313 -313
  60. package/src/programmers/helpers/FunctionImporeter.ts +78 -78
  61. package/src/programmers/helpers/RandomJoiner.ts +173 -173
  62. package/src/programmers/helpers/UnionExplorer.ts +301 -301
  63. package/src/programmers/helpers/UnionPredicator.ts +81 -81
  64. package/src/programmers/helpers/disable_function_importer_declare.ts +26 -26
  65. package/src/programmers/internal/JSON_SCHEMA_PREFIX.ts +1 -1
  66. package/src/programmers/internal/application_array.ts +30 -64
  67. package/src/programmers/internal/application_boolean.ts +15 -15
  68. package/src/programmers/internal/application_constant.ts +26 -26
  69. package/src/programmers/internal/application_default.ts +17 -17
  70. package/src/programmers/internal/application_definition.ts +45 -45
  71. package/src/programmers/internal/application_native.ts +39 -39
  72. package/src/programmers/internal/application_number.ts +74 -74
  73. package/src/programmers/internal/application_object.ts +167 -167
  74. package/src/programmers/internal/application_schema.ts +156 -164
  75. package/src/programmers/internal/application_tuple.ts +47 -77
  76. package/src/programmers/internal/check_union_array_like.ts +329 -329
  77. package/src/programmers/internal/feature_object_entries.ts +63 -63
  78. package/src/programmers/internal/wrap_metadata_rest_tuple.ts +16 -16
  79. package/src/schemas/IJsonApplication.ts +8 -8
  80. package/src/schemas/IJsonComponents.ts +34 -45
  81. package/src/schemas/IJsonSchema.ts +134 -134
  82. package/src/transformers/CallExpressionTransformer.ts +179 -179
  83. package/src/transformers/FileTransformer.ts +47 -47
  84. package/src/transformers/features/miscellaneous/ApplicationTransformer.ts +104 -104
  85. package/src/transformers/features/miscellaneous/MetadataTransformer.ts +53 -53
  86. package/src/utils/ArrayUtil.ts +45 -45
  87. package/src/utils/RandomGenerator.ts +81 -81
@@ -1,300 +1,300 @@
1
- import ts from "typescript";
2
-
3
- import { IMetadataTag } from "../metadata/IMetadataTag";
4
- import { Metadata } from "../metadata/Metadata";
5
-
6
- export namespace MetadataTagFactory {
7
- export const generate =
8
- (metadata: Metadata) =>
9
- (tagList: ts.JSDocTagInfo[]) =>
10
- (identifier: () => string): IMetadataTag[] => {
11
- const output: IMetadataTag[] = [];
12
- for (const tag of tagList) {
13
- const elem: IMetadataTag | null = parse(
14
- identifier,
15
- metadata,
16
- tag,
17
- output,
18
- );
19
- if (elem !== null) output.push(elem);
20
- }
21
- return output;
22
- };
23
-
24
- const parse = (
25
- identifier: () => string,
26
- metadata: Metadata,
27
- tag: ts.JSDocTagInfo,
28
- output: IMetadataTag[],
29
- ): IMetadataTag | null => {
30
- const closure = _PARSER[tag.name];
31
- if (closure === undefined) return null;
32
-
33
- const text = (tag.text || [])[0]?.text;
34
- if (text === undefined)
35
- throw new Error(`${LABEL}: no tag value on ${identifier()}`);
36
-
37
- return closure(identifier, metadata, text, output);
38
- };
39
-
40
- /**
41
- * @internal
42
- */
43
- export const _PARSER: Record<
44
- string,
45
- (
46
- identifier: () => string,
47
- metadata: Metadata,
48
- text: string,
49
- output: IMetadataTag[],
50
- ) => IMetadataTag | null
51
- > = {
52
- /* -----------------------------------------------------------
53
- ARRAY
54
- ----------------------------------------------------------- */
55
- items: (identifier, metadata, text, output) => {
56
- validate(identifier, metadata, output, "items", "array", [
57
- "minItems",
58
- ]);
59
- return {
60
- kind: "items",
61
- value: parse_number(identifier, text),
62
- };
63
- },
64
- minItems: (identifier, metadata, text, output) => {
65
- validate(identifier, metadata, output, "minItems", "array", [
66
- "items",
67
- ]);
68
- return {
69
- kind: "minItems",
70
- value: parse_number(identifier, text),
71
- };
72
- },
73
- maxItems: (identifier, metadata, text, output) => {
74
- validate(identifier, metadata, output, "maxItems", "array", [
75
- "items",
76
- ]);
77
- return {
78
- kind: "maxItems",
79
- value: parse_number(identifier, text),
80
- };
81
- },
82
-
83
- /* -----------------------------------------------------------
84
- NUMBER
85
- ----------------------------------------------------------- */
86
- type: (_identifier, metadata, text, _output) => {
87
- return has_atomic(metadata)("number") &&
88
- (text === "int" || text === "uint")
89
- ? { kind: "type", value: text }
90
- : text === "{int}" || text === "{uint}"
91
- ? { kind: "type", value: text.slice(1, -1) as "int" | "uint" }
92
- : null;
93
- },
94
- minimum: (identifier, metadata, text, output) => {
95
- validate(identifier, metadata, output, "minimum", "number", [
96
- "exclusiveMinimum",
97
- ]);
98
- return {
99
- kind: "minimum",
100
- value: parse_number(identifier, text),
101
- };
102
- },
103
- maximum: (identifier, metadata, text, output) => {
104
- validate(identifier, metadata, output, "maximum", "number", [
105
- "exclusiveMaximum",
106
- ]);
107
- return {
108
- kind: "maximum",
109
- value: parse_number(identifier, text),
110
- };
111
- },
112
- exclusiveMinimum: (identifier, metadata, text, output) => {
113
- validate(
114
- identifier,
115
- metadata,
116
- output,
117
- "exclusiveMinimum",
118
- "number",
119
- ["minimum"],
120
- );
121
- return {
122
- kind: "exclusiveMinimum",
123
- value: parse_number(identifier, text),
124
- };
125
- },
126
- exclusiveMaximum: (identifier, metadata, text, output) => {
127
- validate(
128
- identifier,
129
- metadata,
130
- output,
131
- "exclusiveMaximum",
132
- "number",
133
- ["maximum"],
134
- );
135
- return {
136
- kind: "exclusiveMaximum",
137
- value: parse_number(identifier, text),
138
- };
139
- },
140
- multipleOf: (identifier, metadata, text, output) => {
141
- validate(identifier, metadata, output, "multipleOf", "number", [
142
- "step",
143
- ]);
144
- return {
145
- kind: "multipleOf",
146
- value: parse_number(identifier, text),
147
- };
148
- },
149
- step: (identifier, metadata, text, output) => {
150
- validate(identifier, metadata, output, "step", "number", [
151
- "multipleOf",
152
- ]);
153
-
154
- const minimum: boolean = output.some(
155
- (tag) =>
156
- tag.kind === "minimum" || tag.kind === "exclusiveMinimum",
157
- );
158
- if (minimum === undefined)
159
- throw new Error(
160
- `${LABEL}: step requires minimum or exclusiveMinimum tag on "${identifier()}".`,
161
- );
162
-
163
- return {
164
- kind: "step",
165
- value: parse_number(identifier, text),
166
- };
167
- },
168
-
169
- /* -----------------------------------------------------------
170
- STRING
171
- ----------------------------------------------------------- */
172
- format: (identifier, metadata, str, output) => {
173
- validate(identifier, metadata, output, "format", "string", [
174
- "pattern",
175
- ]);
176
-
177
- // Ignore arbitrary @format values in the internal metadata,
178
- // these are currently only supported on the typia.application() API.
179
- const value: IMetadataTag.IFormat["value"] | undefined =
180
- FORMATS.get(str);
181
- if (value === undefined) return null;
182
- return {
183
- kind: "format",
184
- value,
185
- };
186
- },
187
- pattern: (identifier, metadata, value, output) => {
188
- validate(identifier, metadata, output, "pattern", "string", [
189
- "format",
190
- ]);
191
- return {
192
- kind: "pattern",
193
- value,
194
- };
195
- },
196
- length: (identifier, metadata, text, output) => {
197
- validate(identifier, metadata, output, "length", "string", [
198
- "minLength",
199
- "maxLength",
200
- ]);
201
- return {
202
- kind: "length",
203
- value: parse_number(identifier, text),
204
- };
205
- },
206
- minLength: (identifier, metadata, text, output) => {
207
- validate(identifier, metadata, output, "minLength", "string", [
208
- "length",
209
- ]);
210
- return {
211
- kind: "minLength",
212
- value: parse_number(identifier, text),
213
- };
214
- },
215
- maxLength: (identifier, metadata, text, output) => {
216
- validate(identifier, metadata, output, "maxLength", "string", [
217
- "length",
218
- ]);
219
- return {
220
- kind: "maxLength",
221
- value: parse_number(identifier, text),
222
- };
223
- },
224
- };
225
- }
226
-
227
- const parse_number = (identifier: () => string, str: string): number => {
228
- const value: number = Number(str);
229
- if (isNaN(value) === true)
230
- throw new Error(`${LABEL}: invalid number on "${identifier()}".`);
231
- return value;
232
- };
233
-
234
- const LABEL = "Error on typia.MetadataTagFactory.generate()";
235
- const FORMATS: Map<string, IMetadataTag.IFormat["value"]> = new Map([
236
- ["uuid", "uuid"],
237
- ["email", "email"],
238
- ["url", "url"],
239
- ["ipv4", "ipv4"],
240
- ["ipv6", "ipv6"],
241
- ["date", "date"],
242
- ["datetime", "datetime"],
243
- ["date-time", "datetime"],
244
- ["dateTime", "datetime"],
245
- ]);
246
-
247
- const WRONG_TYPE = (
248
- tag: string,
249
- type: "string" | "number" | "array",
250
- identifier: () => string,
251
- ) => `${LABEL}: ${tag} requires ${type} type, but no "${identifier()}".`;
252
-
253
- const validate = (
254
- identifier: () => string,
255
- metadata: Metadata,
256
- output: IMetadataTag[],
257
- kind: IMetadataTag["kind"],
258
- type: "array" | "string" | "number",
259
- neighbors: IMetadataTag["kind"][],
260
- ): void => {
261
- // TYPE CHECKING
262
- if (type === "array") {
263
- if (has_array(metadata) === false)
264
- throw new Error(WRONG_TYPE(kind, "array", identifier));
265
- } else if (has_atomic(metadata)(type) === false)
266
- throw new Error(WRONG_TYPE(kind, type, identifier));
267
-
268
- // DUPLICATED TAG
269
- if (output.some((tag) => tag.kind === kind))
270
- throw new Error(
271
- `${LABEL}: duplicated ${kind} tags on "${identifier()}".`,
272
- );
273
-
274
- // NEIGHBOR TAG
275
- for (const name of neighbors)
276
- if (output.some((tag) => tag.kind === name))
277
- throw new Error(
278
- `${LABEL}: ${kind} and ${name} tags on "${identifier()}".`,
279
- );
280
- };
281
-
282
- // @todo: must block repeated array and tuple type
283
- const has_atomic =
284
- (metadata: Metadata) =>
285
- (type: "string" | "number"): boolean =>
286
- metadata.atomics.find(
287
- type === "number"
288
- ? (atom: string) => atom === type || atom === "bigint"
289
- : (atom: string) => atom === type,
290
- ) !== undefined ||
291
- metadata.arrays.some((child) => has_atomic(child.value)(type)) ||
292
- metadata.tuples.some((tuple) =>
293
- tuple.elements.some((child) => has_atomic(child)(type)),
294
- );
295
-
296
- const has_array = (metadata: Metadata): boolean =>
297
- metadata.arrays.length !== 0 ||
298
- metadata.tuples.some((tuple) =>
299
- tuple.elements.some((child) => has_array(child)),
300
- );
1
+ import ts from "typescript";
2
+
3
+ import { IMetadataTag } from "../metadata/IMetadataTag";
4
+ import { Metadata } from "../metadata/Metadata";
5
+
6
+ export namespace MetadataTagFactory {
7
+ export const generate =
8
+ (metadata: Metadata) =>
9
+ (tagList: ts.JSDocTagInfo[]) =>
10
+ (identifier: () => string): IMetadataTag[] => {
11
+ const output: IMetadataTag[] = [];
12
+ for (const tag of tagList) {
13
+ const elem: IMetadataTag | null = parse(
14
+ identifier,
15
+ metadata,
16
+ tag,
17
+ output,
18
+ );
19
+ if (elem !== null) output.push(elem);
20
+ }
21
+ return output;
22
+ };
23
+
24
+ const parse = (
25
+ identifier: () => string,
26
+ metadata: Metadata,
27
+ tag: ts.JSDocTagInfo,
28
+ output: IMetadataTag[],
29
+ ): IMetadataTag | null => {
30
+ const closure = _PARSER[tag.name];
31
+ if (closure === undefined) return null;
32
+
33
+ const text = (tag.text || [])[0]?.text;
34
+ if (text === undefined)
35
+ throw new Error(`${LABEL}: no tag value on ${identifier()}`);
36
+
37
+ return closure(identifier, metadata, text, output);
38
+ };
39
+
40
+ /**
41
+ * @internal
42
+ */
43
+ export const _PARSER: Record<
44
+ string,
45
+ (
46
+ identifier: () => string,
47
+ metadata: Metadata,
48
+ text: string,
49
+ output: IMetadataTag[],
50
+ ) => IMetadataTag | null
51
+ > = {
52
+ /* -----------------------------------------------------------
53
+ ARRAY
54
+ ----------------------------------------------------------- */
55
+ items: (identifier, metadata, text, output) => {
56
+ validate(identifier, metadata, output, "items", "array", [
57
+ "minItems",
58
+ ]);
59
+ return {
60
+ kind: "items",
61
+ value: parse_number(identifier, text),
62
+ };
63
+ },
64
+ minItems: (identifier, metadata, text, output) => {
65
+ validate(identifier, metadata, output, "minItems", "array", [
66
+ "items",
67
+ ]);
68
+ return {
69
+ kind: "minItems",
70
+ value: parse_number(identifier, text),
71
+ };
72
+ },
73
+ maxItems: (identifier, metadata, text, output) => {
74
+ validate(identifier, metadata, output, "maxItems", "array", [
75
+ "items",
76
+ ]);
77
+ return {
78
+ kind: "maxItems",
79
+ value: parse_number(identifier, text),
80
+ };
81
+ },
82
+
83
+ /* -----------------------------------------------------------
84
+ NUMBER
85
+ ----------------------------------------------------------- */
86
+ type: (_identifier, metadata, text, _output) => {
87
+ return has_atomic(metadata)("number") &&
88
+ (text === "int" || text === "uint")
89
+ ? { kind: "type", value: text }
90
+ : text === "{int}" || text === "{uint}"
91
+ ? { kind: "type", value: text.slice(1, -1) as "int" | "uint" }
92
+ : null;
93
+ },
94
+ minimum: (identifier, metadata, text, output) => {
95
+ validate(identifier, metadata, output, "minimum", "number", [
96
+ "exclusiveMinimum",
97
+ ]);
98
+ return {
99
+ kind: "minimum",
100
+ value: parse_number(identifier, text),
101
+ };
102
+ },
103
+ maximum: (identifier, metadata, text, output) => {
104
+ validate(identifier, metadata, output, "maximum", "number", [
105
+ "exclusiveMaximum",
106
+ ]);
107
+ return {
108
+ kind: "maximum",
109
+ value: parse_number(identifier, text),
110
+ };
111
+ },
112
+ exclusiveMinimum: (identifier, metadata, text, output) => {
113
+ validate(
114
+ identifier,
115
+ metadata,
116
+ output,
117
+ "exclusiveMinimum",
118
+ "number",
119
+ ["minimum"],
120
+ );
121
+ return {
122
+ kind: "exclusiveMinimum",
123
+ value: parse_number(identifier, text),
124
+ };
125
+ },
126
+ exclusiveMaximum: (identifier, metadata, text, output) => {
127
+ validate(
128
+ identifier,
129
+ metadata,
130
+ output,
131
+ "exclusiveMaximum",
132
+ "number",
133
+ ["maximum"],
134
+ );
135
+ return {
136
+ kind: "exclusiveMaximum",
137
+ value: parse_number(identifier, text),
138
+ };
139
+ },
140
+ multipleOf: (identifier, metadata, text, output) => {
141
+ validate(identifier, metadata, output, "multipleOf", "number", [
142
+ "step",
143
+ ]);
144
+ return {
145
+ kind: "multipleOf",
146
+ value: parse_number(identifier, text),
147
+ };
148
+ },
149
+ step: (identifier, metadata, text, output) => {
150
+ validate(identifier, metadata, output, "step", "number", [
151
+ "multipleOf",
152
+ ]);
153
+
154
+ const minimum: boolean = output.some(
155
+ (tag) =>
156
+ tag.kind === "minimum" || tag.kind === "exclusiveMinimum",
157
+ );
158
+ if (minimum === undefined)
159
+ throw new Error(
160
+ `${LABEL}: step requires minimum or exclusiveMinimum tag on "${identifier()}".`,
161
+ );
162
+
163
+ return {
164
+ kind: "step",
165
+ value: parse_number(identifier, text),
166
+ };
167
+ },
168
+
169
+ /* -----------------------------------------------------------
170
+ STRING
171
+ ----------------------------------------------------------- */
172
+ format: (identifier, metadata, str, output) => {
173
+ validate(identifier, metadata, output, "format", "string", [
174
+ "pattern",
175
+ ]);
176
+
177
+ // Ignore arbitrary @format values in the internal metadata,
178
+ // these are currently only supported on the typia.application() API.
179
+ const value: IMetadataTag.IFormat["value"] | undefined =
180
+ FORMATS.get(str);
181
+ if (value === undefined) return null;
182
+ return {
183
+ kind: "format",
184
+ value,
185
+ };
186
+ },
187
+ pattern: (identifier, metadata, value, output) => {
188
+ validate(identifier, metadata, output, "pattern", "string", [
189
+ "format",
190
+ ]);
191
+ return {
192
+ kind: "pattern",
193
+ value,
194
+ };
195
+ },
196
+ length: (identifier, metadata, text, output) => {
197
+ validate(identifier, metadata, output, "length", "string", [
198
+ "minLength",
199
+ "maxLength",
200
+ ]);
201
+ return {
202
+ kind: "length",
203
+ value: parse_number(identifier, text),
204
+ };
205
+ },
206
+ minLength: (identifier, metadata, text, output) => {
207
+ validate(identifier, metadata, output, "minLength", "string", [
208
+ "length",
209
+ ]);
210
+ return {
211
+ kind: "minLength",
212
+ value: parse_number(identifier, text),
213
+ };
214
+ },
215
+ maxLength: (identifier, metadata, text, output) => {
216
+ validate(identifier, metadata, output, "maxLength", "string", [
217
+ "length",
218
+ ]);
219
+ return {
220
+ kind: "maxLength",
221
+ value: parse_number(identifier, text),
222
+ };
223
+ },
224
+ };
225
+ }
226
+
227
+ const parse_number = (identifier: () => string, str: string): number => {
228
+ const value: number = Number(str);
229
+ if (isNaN(value) === true)
230
+ throw new Error(`${LABEL}: invalid number on "${identifier()}".`);
231
+ return value;
232
+ };
233
+
234
+ const LABEL = "Error on typia.MetadataTagFactory.generate()";
235
+ const FORMATS: Map<string, IMetadataTag.IFormat["value"]> = new Map([
236
+ ["uuid", "uuid"],
237
+ ["email", "email"],
238
+ ["url", "url"],
239
+ ["ipv4", "ipv4"],
240
+ ["ipv6", "ipv6"],
241
+ ["date", "date"],
242
+ ["datetime", "datetime"],
243
+ ["date-time", "datetime"],
244
+ ["dateTime", "datetime"],
245
+ ]);
246
+
247
+ const WRONG_TYPE = (
248
+ tag: string,
249
+ type: "string" | "number" | "array",
250
+ identifier: () => string,
251
+ ) => `${LABEL}: ${tag} requires ${type} type, but no "${identifier()}".`;
252
+
253
+ const validate = (
254
+ identifier: () => string,
255
+ metadata: Metadata,
256
+ output: IMetadataTag[],
257
+ kind: IMetadataTag["kind"],
258
+ type: "array" | "string" | "number",
259
+ neighbors: IMetadataTag["kind"][],
260
+ ): void => {
261
+ // TYPE CHECKING
262
+ if (type === "array") {
263
+ if (has_array(metadata) === false)
264
+ throw new Error(WRONG_TYPE(kind, "array", identifier));
265
+ } else if (has_atomic(metadata)(type) === false)
266
+ throw new Error(WRONG_TYPE(kind, type, identifier));
267
+
268
+ // DUPLICATED TAG
269
+ if (output.some((tag) => tag.kind === kind))
270
+ throw new Error(
271
+ `${LABEL}: duplicated ${kind} tags on "${identifier()}".`,
272
+ );
273
+
274
+ // NEIGHBOR TAG
275
+ for (const name of neighbors)
276
+ if (output.some((tag) => tag.kind === name))
277
+ throw new Error(
278
+ `${LABEL}: ${kind} and ${name} tags on "${identifier()}".`,
279
+ );
280
+ };
281
+
282
+ // @todo: must block repeated array and tuple type
283
+ const has_atomic =
284
+ (metadata: Metadata) =>
285
+ (type: "string" | "number"): boolean =>
286
+ metadata.atomics.find(
287
+ type === "number"
288
+ ? (atom: string) => atom === type || atom === "bigint"
289
+ : (atom: string) => atom === type,
290
+ ) !== undefined ||
291
+ metadata.arrays.some((child) => has_atomic(child.value)(type)) ||
292
+ metadata.tuples.some((tuple) =>
293
+ tuple.elements.some((child) => has_atomic(child)(type)),
294
+ );
295
+
296
+ const has_array = (metadata: Metadata): boolean =>
297
+ metadata.arrays.length !== 0 ||
298
+ metadata.tuples.some((tuple) =>
299
+ tuple.elements.some((child) => has_array(child)),
300
+ );
@@ -1,34 +1,34 @@
1
- import ts from "typescript";
2
-
3
- import { Metadata } from "../../../metadata/Metadata";
4
- import { MetadataArray } from "../../../metadata/MetadataArray";
5
-
6
- import { ArrayUtil } from "../../../utils/ArrayUtil";
7
-
8
- import { MetadataCollection } from "../../MetadataCollection";
9
- import { MetadataFactory } from "../../MetadataFactory";
10
- import { explore_metadata } from "./explore_metadata";
11
-
12
- export const emplace_metadata_array =
13
- (checker: ts.TypeChecker) =>
14
- (options: MetadataFactory.IOptions) =>
15
- (collection: MetadataCollection) =>
16
- (type: ts.Type, nullable: boolean): MetadataArray => {
17
- // CHECK EXISTENCE
18
- const [array, newbie, setValue] = collection.emplaceArray(
19
- checker,
20
- type,
21
- );
22
- ArrayUtil.add(array.nullables, nullable);
23
- if (newbie === false) return array;
24
-
25
- // CONSTRUCT VALUE TYPE
26
- const value: Metadata = explore_metadata(checker)(options)(collection)(
27
- type.getNumberIndexType()!,
28
- false,
29
- false,
30
- );
31
- setValue(value);
32
-
33
- return array;
34
- };
1
+ import ts from "typescript";
2
+
3
+ import { Metadata } from "../../../metadata/Metadata";
4
+ import { MetadataArray } from "../../../metadata/MetadataArray";
5
+
6
+ import { ArrayUtil } from "../../../utils/ArrayUtil";
7
+
8
+ import { MetadataCollection } from "../../MetadataCollection";
9
+ import { MetadataFactory } from "../../MetadataFactory";
10
+ import { explore_metadata } from "./explore_metadata";
11
+
12
+ export const emplace_metadata_array =
13
+ (checker: ts.TypeChecker) =>
14
+ (options: MetadataFactory.IOptions) =>
15
+ (collection: MetadataCollection) =>
16
+ (type: ts.Type, nullable: boolean): MetadataArray => {
17
+ // CHECK EXISTENCE
18
+ const [array, newbie, setValue] = collection.emplaceArray(
19
+ checker,
20
+ type,
21
+ );
22
+ ArrayUtil.add(array.nullables, nullable);
23
+ if (newbie === false) return array;
24
+
25
+ // CONSTRUCT VALUE TYPE
26
+ const value: Metadata = explore_metadata(checker)(options)(collection)(
27
+ type.getNumberIndexType()!,
28
+ false,
29
+ false,
30
+ );
31
+ setValue(value);
32
+
33
+ return array;
34
+ };