typia 3.4.15 → 3.5.0-dev.20221222

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 (169) hide show
  1. package/README.md +48 -7
  2. package/lib/factories/MetadataCollection.d.ts +1 -9
  3. package/lib/factories/MetadataCollection.js +2 -75
  4. package/lib/factories/MetadataCollection.js.map +1 -1
  5. package/lib/factories/ProtocolFactory.d.ts +8 -0
  6. package/lib/factories/ProtocolFactory.js +119 -0
  7. package/lib/factories/ProtocolFactory.js.map +1 -0
  8. package/lib/factories/internal/protocols/ProtocolMetadataUtil.d.ts +11 -0
  9. package/lib/factories/internal/protocols/ProtocolMetadataUtil.js +76 -0
  10. package/lib/factories/internal/protocols/ProtocolMetadataUtil.js.map +1 -0
  11. package/lib/factories/internal/protocols/emplace_protocol_object.d.ts +3 -0
  12. package/lib/factories/internal/protocols/emplace_protocol_object.js +47 -0
  13. package/lib/factories/internal/protocols/emplace_protocol_object.js.map +1 -0
  14. package/lib/factories/internal/protocols/emplace_protocol_property.d.ts +4 -0
  15. package/lib/factories/internal/protocols/emplace_protocol_property.js +20 -0
  16. package/lib/factories/internal/protocols/emplace_protocol_property.js.map +1 -0
  17. package/lib/factories/internal/protocols/iterate_protocol_atomic.d.ts +3 -0
  18. package/lib/factories/internal/protocols/iterate_protocol_atomic.js +69 -0
  19. package/lib/factories/internal/protocols/iterate_protocol_atomic.js.map +1 -0
  20. package/lib/factories/internal/protocols/iterate_protocol_constant.d.ts +2 -0
  21. package/lib/factories/internal/protocols/iterate_protocol_constant.js +30 -0
  22. package/lib/factories/internal/protocols/iterate_protocol_constant.js.map +1 -0
  23. package/lib/factories/internal/protocols/iterate_protocol_main.d.ts +3 -0
  24. package/lib/factories/internal/protocols/iterate_protocol_main.js +17 -0
  25. package/lib/factories/internal/protocols/iterate_protocol_main.js.map +1 -0
  26. package/lib/factories/internal/protocols/iterate_protocol_map.d.ts +3 -0
  27. package/lib/factories/internal/protocols/iterate_protocol_map.js +71 -0
  28. package/lib/factories/internal/protocols/iterate_protocol_map.js.map +1 -0
  29. package/lib/factories/internal/protocols/iterate_protocol_metadata.d.ts +5 -0
  30. package/lib/factories/internal/protocols/iterate_protocol_metadata.js +192 -0
  31. package/lib/factories/internal/protocols/iterate_protocol_metadata.js.map +1 -0
  32. package/lib/factories/internal/protocols/iterate_protocol_native.d.ts +2 -0
  33. package/lib/factories/internal/protocols/iterate_protocol_native.js +33 -0
  34. package/lib/factories/internal/protocols/iterate_protocol_native.js.map +1 -0
  35. package/lib/factories/internal/protocols/iterate_protocol_repeated.d.ts +4 -0
  36. package/lib/factories/internal/protocols/iterate_protocol_repeated.js +24 -0
  37. package/lib/factories/internal/protocols/iterate_protocol_repeated.js.map +1 -0
  38. package/lib/factories/internal/protocols/iterate_protocol_tuple.d.ts +3 -0
  39. package/lib/factories/internal/protocols/iterate_protocol_tuple.js +46 -0
  40. package/lib/factories/internal/protocols/iterate_protocol_tuple.js.map +1 -0
  41. package/lib/functional/$proto_bytes.d.ts +2 -0
  42. package/lib/functional/$proto_bytes.js +37 -0
  43. package/lib/functional/$proto_bytes.js.map +1 -0
  44. package/lib/functional/$proto_field.d.ts +10 -0
  45. package/lib/functional/$proto_field.js +42 -0
  46. package/lib/functional/$proto_field.js.map +1 -0
  47. package/lib/functional/$proto_float.d.ts +4 -0
  48. package/lib/functional/$proto_float.js +28 -0
  49. package/lib/functional/$proto_float.js.map +1 -0
  50. package/lib/functional/$proto_i32.d.ts +2 -0
  51. package/lib/functional/$proto_i32.js +23 -0
  52. package/lib/functional/$proto_i32.js.map +1 -0
  53. package/lib/functional/$proto_i64.d.ts +2 -0
  54. package/lib/functional/$proto_i64.js +31 -0
  55. package/lib/functional/$proto_i64.js.map +1 -0
  56. package/lib/functional/$proto_size.d.ts +6 -0
  57. package/lib/functional/$proto_size.js +76 -0
  58. package/lib/functional/$proto_size.js.map +1 -0
  59. package/lib/functional/$proto_string.d.ts +2 -0
  60. package/lib/functional/$proto_string.js +34 -0
  61. package/lib/functional/$proto_string.js.map +1 -0
  62. package/lib/functional/$varint.d.ts +6 -0
  63. package/lib/functional/$varint.js +99 -0
  64. package/lib/functional/$varint.js.map +1 -0
  65. package/lib/functional/$zigzag.d.ts +4 -0
  66. package/lib/functional/$zigzag.js +34 -0
  67. package/lib/functional/$zigzag.js.map +1 -0
  68. package/lib/messages/IProtocolMessage.d.ts +5 -0
  69. package/lib/messages/IProtocolMessage.js +3 -0
  70. package/lib/messages/IProtocolMessage.js.map +1 -0
  71. package/lib/messages/IProtocolProperty.d.ts +11 -0
  72. package/lib/messages/IProtocolProperty.js +3 -0
  73. package/lib/messages/IProtocolProperty.js.map +1 -0
  74. package/lib/metadata/IMetadataTag.d.ts +7 -3
  75. package/lib/metadata/Metadata.js +1 -1
  76. package/lib/metadata/Metadata.js.map +1 -1
  77. package/lib/module.d.ts +2 -0
  78. package/lib/module.js +5 -1
  79. package/lib/module.js.map +1 -1
  80. package/lib/programmers/MessageProgrammer.d.ts +5 -0
  81. package/lib/programmers/MessageProgrammer.js +134 -0
  82. package/lib/programmers/MessageProgrammer.js.map +1 -0
  83. package/lib/programmers/internal/application_object.js +9 -9
  84. package/lib/programmers/internal/application_object.js.map +1 -1
  85. package/lib/programmers/internal/application_schema.js +5 -3
  86. package/lib/programmers/internal/application_schema.js.map +1 -1
  87. package/lib/transformers/CallExpressionTransformer.js +3 -1
  88. package/lib/transformers/CallExpressionTransformer.js.map +1 -1
  89. package/lib/transformers/features/miscellaneous/ApplicationTransformer.js +1 -3
  90. package/lib/transformers/features/miscellaneous/ApplicationTransformer.js.map +1 -1
  91. package/lib/transformers/features/protocols/MessageTransformer.d.ts +5 -0
  92. package/lib/transformers/features/protocols/MessageTransformer.js +17 -0
  93. package/lib/transformers/features/protocols/MessageTransformer.js.map +1 -0
  94. package/lib/utils/NameEncoder.d.ts +4 -0
  95. package/lib/utils/NameEncoder.js +89 -0
  96. package/lib/utils/NameEncoder.js.map +1 -0
  97. package/package.json +2 -3
  98. package/src/executable/internal/TypiaSetupWizard.ts +173 -173
  99. package/src/factories/MetadataCollection.ts +83 -122
  100. package/src/factories/MetadataFactory.ts +47 -47
  101. package/src/factories/MetadataTagFactory.ts +351 -351
  102. package/src/factories/ProtocolFactory.ts +92 -0
  103. package/src/factories/internal/metadata/MetadataHelper.ts +12 -12
  104. package/src/factories/internal/metadata/emplace_metadata_object.ts +140 -140
  105. package/src/factories/internal/metadata/explore_metadata.ts +92 -92
  106. package/src/factories/internal/metadata/iterate_metadata.ts +80 -80
  107. package/src/factories/internal/metadata/iterate_metadata_array.ts +29 -29
  108. package/src/factories/internal/metadata/iterate_metadata_atomic.ts +59 -59
  109. package/src/factories/internal/metadata/iterate_metadata_coalesce.ts +33 -33
  110. package/src/factories/internal/metadata/iterate_metadata_constant.ts +58 -58
  111. package/src/factories/internal/metadata/iterate_metadata_map.ts +41 -41
  112. package/src/factories/internal/metadata/iterate_metadata_native.ts +227 -227
  113. package/src/factories/internal/metadata/iterate_metadata_object.ts +48 -48
  114. package/src/factories/internal/metadata/iterate_metadata_resolve.ts +27 -27
  115. package/src/factories/internal/metadata/iterate_metadata_set.ts +33 -33
  116. package/src/factories/internal/metadata/iterate_metadata_template.ts +38 -38
  117. package/src/factories/internal/metadata/iterate_metadata_tuple.ts +45 -45
  118. package/src/factories/internal/metadata/iterate_metadata_union.ts +59 -59
  119. package/src/factories/internal/protocols/ProtocolMetadataUtil.ts +81 -0
  120. package/src/factories/internal/protocols/emplace_protocol_object.ts +25 -0
  121. package/src/factories/internal/protocols/emplace_protocol_property.ts +12 -0
  122. package/src/factories/internal/protocols/iterate_protocol_atomic.ts +34 -0
  123. package/src/factories/internal/protocols/iterate_protocol_constant.ts +27 -0
  124. package/src/factories/internal/protocols/iterate_protocol_main.ts +19 -0
  125. package/src/factories/internal/protocols/iterate_protocol_map.ts +38 -0
  126. package/src/factories/internal/protocols/iterate_protocol_metadata.ts +76 -0
  127. package/src/factories/internal/protocols/iterate_protocol_native.ts +34 -0
  128. package/src/factories/internal/protocols/iterate_protocol_repeated.ts +25 -0
  129. package/src/factories/internal/protocols/iterate_protocol_tuple.ts +25 -0
  130. package/src/functional/$number.ts +12 -12
  131. package/src/functional/$proto_bytes.ts +25 -0
  132. package/src/functional/$proto_field.ts +30 -0
  133. package/src/functional/$proto_float.ts +37 -0
  134. package/src/functional/$proto_i32.ts +29 -0
  135. package/src/functional/$proto_i64.ts +37 -0
  136. package/src/functional/$proto_size.ts +82 -0
  137. package/src/functional/$proto_string.ts +24 -0
  138. package/src/functional/$varint.ts +130 -0
  139. package/src/functional/$zigzag.ts +39 -0
  140. package/src/messages/IProtocolMessage.ts +6 -0
  141. package/src/messages/IProtocolProperty.ts +11 -0
  142. package/src/metadata/IMetadataTag.ts +137 -122
  143. package/src/metadata/Metadata.ts +479 -477
  144. package/src/module.ts +1547 -1535
  145. package/src/programmers/AssertParseProgrammer.ts +55 -55
  146. package/src/programmers/AssertProgrammer.ts +445 -445
  147. package/src/programmers/AssertStringifyProgrammer.ts +65 -65
  148. package/src/programmers/CheckerProgrammer.ts +810 -810
  149. package/src/programmers/IsParseProgrammer.ts +61 -61
  150. package/src/programmers/IsProgrammer.ts +175 -175
  151. package/src/programmers/IsStringifyProgrammer.ts +69 -69
  152. package/src/programmers/MessageProgrammer.ts +116 -0
  153. package/src/programmers/StringifyProgrammer.ts +762 -762
  154. package/src/programmers/ValidateParseProgrammer.ts +59 -59
  155. package/src/programmers/ValidateProgrammer.ts +237 -237
  156. package/src/programmers/ValidateStringifyProgrammer.ts +80 -80
  157. package/src/programmers/helpers/OptionPredicator.ts +15 -15
  158. package/src/programmers/internal/application_default.ts +17 -17
  159. package/src/programmers/internal/application_object.ts +5 -5
  160. package/src/programmers/internal/application_schema.ts +231 -228
  161. package/src/programmers/internal/check_bigint.ts +85 -85
  162. package/src/programmers/internal/check_number.ts +175 -175
  163. package/src/schemas/IJsonSchema.ts +90 -90
  164. package/src/transformers/CallExpressionTransformer.ts +131 -124
  165. package/src/transformers/ITransformOptions.ts +47 -47
  166. package/src/transformers/features/miscellaneous/ApplicationTransformer.ts +117 -119
  167. package/src/transformers/features/protocols/MessageTransformer.ts +32 -0
  168. package/src/transformers/features/stringifiers/StringifyTransformer.ts +46 -46
  169. package/src/utils/NameEncoder.ts +32 -0
@@ -1,810 +1,810 @@
1
- import ts from "typescript";
2
-
3
- import { ExpressionFactory } from "../factories/ExpressionFactory";
4
- import { IdentifierFactory } from "../factories/IdentifierFactory";
5
- import { MetadataCollection } from "../factories/MetadataCollection";
6
- import { MetadataFactory } from "../factories/MetadataFactory";
7
- import { ValueFactory } from "../factories/ValueFactory";
8
-
9
- import { IMetadataTag } from "../metadata/IMetadataTag";
10
- import { Metadata } from "../metadata/Metadata";
11
- import { MetadataObject } from "../metadata/MetadataObject";
12
-
13
- import { IProject } from "../transformers/IProject";
14
-
15
- import { FeatureProgrammer } from "./FeatureProgrammer";
16
- import { FunctionImporter } from "./helpers/FunctionImporeter";
17
- import { IExpressionEntry } from "./helpers/IExpressionEntry";
18
- import { OptionPredicator } from "./helpers/OptionPredicator";
19
- import { UnionExplorer } from "./helpers/UnionExplorer";
20
- import { check_array } from "./internal/check_array";
21
- import { check_bigint } from "./internal/check_bigint";
22
- import { check_native } from "./internal/check_native";
23
- import { check_number } from "./internal/check_number";
24
- import { check_string } from "./internal/check_string";
25
- import { check_template } from "./internal/check_template";
26
- import { decode_union_object } from "./internal/decode_union_object";
27
-
28
- export namespace CheckerProgrammer {
29
- export interface IConfig {
30
- functors: string;
31
- unioners: string;
32
- path: boolean;
33
- trace: boolean;
34
- equals: boolean;
35
- numeric: boolean;
36
- combiner: IConfig.Combiner;
37
- decoder?: FeatureProgrammer.Decoder<Metadata>;
38
- joiner: IConfig.IJoiner;
39
- success: ts.Expression;
40
- }
41
- export namespace IConfig {
42
- export interface Combiner {
43
- (explorer: IExplore): {
44
- (logic: "and" | "or"): {
45
- (
46
- input: ts.Expression,
47
- binaries: IBinary[],
48
- expected: string,
49
- ): ts.Expression;
50
- };
51
- };
52
- }
53
- export interface IJoiner {
54
- object(entries: IExpressionEntry[]): ts.Expression;
55
- array(input: ts.Expression, arrow: ts.ArrowFunction): ts.Expression;
56
- tuple?(exprs: ts.Expression[]): ts.Expression;
57
-
58
- failure(
59
- value: ts.Expression,
60
- expected: string,
61
- explore?: FeatureProgrammer.IExplore,
62
- ): ts.Expression;
63
- is?(expression: ts.Expression): ts.Expression;
64
- required?(exp: ts.Expression): ts.Expression;
65
- full?: (
66
- condition: ts.Expression,
67
- ) => (
68
- input: ts.Expression,
69
- expected: string,
70
- explore: IExplore,
71
- ) => ts.Expression;
72
- }
73
- }
74
- export import IExplore = FeatureProgrammer.IExplore;
75
-
76
- export interface IBinary {
77
- expression: ts.Expression;
78
- combined: boolean;
79
- }
80
-
81
- /* -----------------------------------------------------------
82
- GENERATORS
83
- ----------------------------------------------------------- */
84
- export function generate(
85
- project: IProject,
86
- config: IConfig,
87
- importer: FunctionImporter,
88
- addition?: () => ts.Statement[],
89
- ) {
90
- return FeatureProgrammer.generate(
91
- project,
92
- CONFIG(project, config, importer),
93
- importer,
94
- () => (addition ? (addition ? addition() : []) : undefined),
95
- );
96
- }
97
-
98
- export const generate_functors = (
99
- project: IProject,
100
- config: IConfig,
101
- importer: FunctionImporter,
102
- ) =>
103
- FeatureProgrammer.generate_functors(
104
- CONFIG(project, config, importer),
105
- importer,
106
- );
107
-
108
- export const generate_unioners = (
109
- project: IProject,
110
- config: IConfig,
111
- importer: FunctionImporter,
112
- ) =>
113
- FeatureProgrammer.generate_unioners(
114
- CONFIG(project, { ...config, numeric: false }, importer),
115
- );
116
-
117
- function CONFIG(
118
- project: IProject,
119
- config: IConfig,
120
- importer: FunctionImporter,
121
- ): FeatureProgrammer.IConfig {
122
- const output: FeatureProgrammer.IConfig = {
123
- trace: config.trace,
124
- path: config.path,
125
- functors: config.functors,
126
- unioners: config.unioners,
127
- initializer: ({ checker }, type) => {
128
- const collection: MetadataCollection = new MetadataCollection();
129
- const meta: Metadata = MetadataFactory.generate(
130
- checker,
131
- collection,
132
- type,
133
- {
134
- resolve: false,
135
- constant: true,
136
- },
137
- );
138
- return [collection, meta];
139
- },
140
- decoder: config.decoder || decode(project, config, importer),
141
- objector: {
142
- checker: config.decoder || decode(project, config, importer),
143
- decoder: decode_object(config),
144
- joiner: config.joiner.object,
145
- unionizer: config.equals
146
- ? decode_union_object(decode_object(config))(
147
- (input, obj, explore) =>
148
- decode_object(config)(input, obj, {
149
- ...explore,
150
- tracable: true,
151
- }),
152
- )(config.joiner.is || ((expr) => expr))(
153
- (value, expected) =>
154
- ts.factory.createReturnStatement(
155
- config.joiner.failure(value, expected),
156
- ),
157
- )
158
- : (input, targets, explore) =>
159
- config.combiner(explore)("or")(
160
- input,
161
- targets.map((obj) => ({
162
- expression: decode_object(config)(
163
- input,
164
- obj,
165
- explore,
166
- ),
167
- combined: true,
168
- })),
169
- `(${targets.map((t) => t.name).join(" | ")})`,
170
- ),
171
- failure: (value, expected) =>
172
- ts.factory.createReturnStatement(
173
- config.joiner.failure(value, expected),
174
- ),
175
- is: config.joiner.is,
176
- required: config.joiner.required,
177
- full: config.joiner.full,
178
- },
179
- };
180
- if (config.numeric === true)
181
- output.generator = {
182
- unioners: FeatureProgrammer.generate_unioners(
183
- CONFIG(project, { ...config, numeric: false }, importer),
184
- ),
185
- };
186
- return output;
187
- }
188
-
189
- /* -----------------------------------------------------------
190
- DECODERS
191
- ----------------------------------------------------------- */
192
- export function decode(
193
- project: IProject,
194
- config: IConfig,
195
- importer: FunctionImporter,
196
- ): (
197
- input: ts.Expression,
198
- meta: Metadata,
199
- explore: IExplore,
200
- tags: IMetadataTag[],
201
- ) => ts.Expression;
202
-
203
- /**
204
- * @internal
205
- */
206
- export function decode(
207
- project: IProject,
208
- config: IConfig,
209
- importer: FunctionImporter,
210
- checkTupleLength: boolean,
211
- ): (
212
- input: ts.Expression,
213
- meta: Metadata,
214
- explore: IExplore,
215
- tags: IMetadataTag[],
216
- ) => ts.Expression;
217
-
218
- /**
219
- * @internal
220
- */
221
- export function decode(
222
- project: IProject,
223
- config: IConfig,
224
- importer: FunctionImporter,
225
- checkTupleLength: boolean = true,
226
- ) {
227
- return function (
228
- input: ts.Expression,
229
- meta: Metadata,
230
- explore: IExplore,
231
- tags: IMetadataTag[],
232
- ): ts.Expression {
233
- if (meta.any) return config.success;
234
-
235
- const top: IBinary[] = [];
236
- const binaries: IBinary[] = [];
237
- const add = create_add(binaries)(input);
238
- const getConstantValue = (
239
- value: number | string | bigint | boolean,
240
- ) =>
241
- typeof value === "string"
242
- ? ts.factory.createStringLiteral(value)
243
- : ts.factory.createIdentifier(value.toString());
244
-
245
- //----
246
- // CHECK OPTIONAL
247
- //----
248
- const checkOptional: boolean = meta.empty() || meta.isUnionBucket();
249
-
250
- // NULLABLE
251
- if (
252
- checkOptional ||
253
- meta.nullable
254
- // || (meta.objects.length && meta.size() !== meta.objects.length)
255
- )
256
- (meta.nullable ? add : create_add(top)(input))(
257
- meta.nullable,
258
- ValueFactory.NULL(),
259
- );
260
-
261
- // UNDEFINDABLE
262
- if (checkOptional || !meta.required)
263
- (meta.required ? create_add(top)(input) : add)(
264
- !meta.required,
265
- ValueFactory.UNDEFINED(),
266
- );
267
-
268
- // FUNCTIONAL
269
- if (meta.functional === true)
270
- if (
271
- OptionPredicator.functional(project.options) ||
272
- meta.size() !== 1
273
- )
274
- add(
275
- true,
276
- ts.factory.createStringLiteral("function"),
277
- ValueFactory.TYPEOF(input),
278
- );
279
- else
280
- binaries.push({
281
- combined: false,
282
- expression: config.success,
283
- });
284
-
285
- //----
286
- // VALUES
287
- //----
288
- // CONSTANT VALUES
289
- for (const constant of meta.constants)
290
- for (const val of constant.values)
291
- add(true, getConstantValue(val));
292
-
293
- // ATOMIC VALUES
294
- for (const type of meta.atomics)
295
- if (type === "number")
296
- binaries.push({
297
- expression: check_number(project, config.numeric)(
298
- input,
299
- tags,
300
- ),
301
- combined: false,
302
- });
303
- else if (type === "bigint")
304
- binaries.push({
305
- expression: check_bigint(input, tags),
306
- combined: false,
307
- });
308
- else if (type === "string")
309
- binaries.push({
310
- expression: check_string(importer)(input, tags),
311
- combined: false,
312
- });
313
- else
314
- add(
315
- true,
316
- ts.factory.createStringLiteral(type),
317
- ValueFactory.TYPEOF(input),
318
- );
319
-
320
- // TEMPLATE LITERAL VALUES
321
- if (meta.templates.length)
322
- binaries.push({
323
- expression: check_template(importer)(
324
- input,
325
- meta.templates,
326
- tags,
327
- ),
328
- combined: false,
329
- });
330
-
331
- //----
332
- // INSTANCES
333
- //----
334
- // TUPLE
335
- if (meta.tuples.length > 0) {
336
- const inner: ts.Expression[] = [];
337
- for (const tuple of meta.tuples)
338
- inner.push(
339
- decode_tuple(
340
- project,
341
- config,
342
- importer,
343
- checkTupleLength,
344
- )(input, tuple, explore, tags),
345
- );
346
-
347
- // ADD
348
- binaries.push({
349
- expression: config.combiner(explore)("and")(
350
- input,
351
- [
352
- ...(checkTupleLength
353
- ? [
354
- {
355
- expression:
356
- ExpressionFactory.isArray(input),
357
- combined: false,
358
- },
359
- ]
360
- : []),
361
- ...inner.map((expression) => ({
362
- expression,
363
- combined: true,
364
- })),
365
- ],
366
- meta.getName(),
367
- ),
368
- combined: true,
369
- });
370
- }
371
-
372
- // ARRAY
373
- if (meta.arrays.length > 0)
374
- if (meta.arrays.every((elem) => elem.any))
375
- binaries.push({
376
- expression: check_array(input, tags),
377
- combined: false,
378
- });
379
- else
380
- binaries.push({
381
- expression: config.combiner(explore)("and")(
382
- input,
383
- [
384
- ...(checkTupleLength
385
- ? [
386
- {
387
- expression: check_array(
388
- input,
389
- tags,
390
- ),
391
- combined: false,
392
- },
393
- ]
394
- : []),
395
- {
396
- expression: explore_array(
397
- project,
398
- config,
399
- importer,
400
- )(
401
- input,
402
- meta.arrays,
403
- {
404
- ...explore,
405
- from: "array",
406
- },
407
- tags,
408
- ),
409
- combined: true,
410
- },
411
- ],
412
- meta.getName(),
413
- ),
414
- combined: true,
415
- });
416
-
417
- // OBJECT
418
- if (meta.objects.length > 0)
419
- binaries.push({
420
- expression: config.combiner(explore)("and")(
421
- input,
422
- [
423
- {
424
- expression: ExpressionFactory.isObject(input, {
425
- checkNull: true,
426
- checkArray: meta.objects.some((obj) =>
427
- obj.properties.every(
428
- (prop) =>
429
- !prop.key.isSoleLiteral() ||
430
- !prop.value.required,
431
- ),
432
- ),
433
- }),
434
- combined: false,
435
- },
436
- {
437
- expression: explore_objects(config)(
438
- input,
439
- meta,
440
- {
441
- ...explore,
442
- from: "object",
443
- },
444
- ),
445
- combined: true,
446
- },
447
- ],
448
- meta.getName(),
449
- ),
450
- combined: true,
451
- });
452
-
453
- // NATIVE CLASSES
454
- for (const native of meta.natives)
455
- binaries.push({
456
- expression: check_native(native)(input),
457
- combined: false,
458
- });
459
-
460
- // SETS
461
- if (meta.sets.length)
462
- if (meta.sets.every((elem) => elem.any))
463
- binaries.push({
464
- combined: false,
465
- expression: check_native("Set")(input),
466
- });
467
- else
468
- binaries.push({
469
- combined: true,
470
- expression: config.combiner(explore)("and")(
471
- input,
472
- [
473
- {
474
- combined: false,
475
- expression: check_native("Set")(input),
476
- },
477
- {
478
- combined: true,
479
- expression: explore_set(
480
- project,
481
- config,
482
- importer,
483
- )(
484
- input,
485
- meta.sets,
486
- {
487
- ...explore,
488
- from: "array",
489
- },
490
- [],
491
- ),
492
- },
493
- ],
494
- meta.getName(),
495
- ),
496
- });
497
-
498
- // MAPS
499
- if (meta.maps.length)
500
- if (meta.maps.every((elem) => elem.key.any && elem.value.any))
501
- binaries.push({
502
- expression: check_native("Map")(input),
503
- combined: false,
504
- });
505
- else
506
- binaries.push({
507
- combined: true,
508
- expression: config.combiner(explore)("and")(
509
- input,
510
- [
511
- {
512
- combined: false,
513
- expression: check_native("Map")(input),
514
- },
515
- {
516
- combined: true,
517
- expression: explore_map(
518
- project,
519
- config,
520
- importer,
521
- )(
522
- input,
523
- meta.maps.map((m) => [m.key, m.value]),
524
- {
525
- ...explore,
526
- from: "array",
527
- },
528
- [],
529
- ),
530
- },
531
- ],
532
- meta.getName(),
533
- ),
534
- });
535
-
536
- // COMBINE CONDITIONS
537
- return top.length && binaries.length
538
- ? config.combiner(explore)("and")(
539
- input,
540
- [
541
- ...top,
542
- {
543
- expression: config.combiner(explore)("or")(
544
- input,
545
- binaries,
546
- meta.getName(),
547
- ),
548
- combined: true,
549
- },
550
- ],
551
- meta.getName(),
552
- )
553
- : binaries.length
554
- ? config.combiner(explore)("or")(
555
- input,
556
- binaries,
557
- meta.getName(),
558
- )
559
- : config.success;
560
- };
561
- }
562
-
563
- function decode_tuple(
564
- project: IProject,
565
- config: IConfig,
566
- importer: FunctionImporter,
567
- checkLength: boolean,
568
- ) {
569
- return function (
570
- input: ts.Expression,
571
- tuple: Array<Metadata>,
572
- explore: IExplore,
573
- tagList: IMetadataTag[],
574
- ): ts.Expression {
575
- const binaries: ts.Expression[] = tuple
576
- .filter((meta) => meta.rest === null)
577
- .map((meta, index) =>
578
- decode(project, config, importer)(
579
- ts.factory.createElementAccessExpression(input, index),
580
- meta,
581
- {
582
- ...explore,
583
- from: "array",
584
- postfix: explore.postfix.length
585
- ? `${explore.postfix.slice(0, -1)}[${index}]"`
586
- : `[${index}]`,
587
- },
588
- tagList,
589
- ),
590
- );
591
- const rest: ts.Expression | null =
592
- tuple.length && tuple[tuple.length - 1]!.rest !== null
593
- ? decode(project, config, importer, false)(
594
- ts.factory.createCallExpression(
595
- IdentifierFactory.join(input, "slice"),
596
- undefined,
597
- [
598
- ts.factory.createNumericLiteral(
599
- tuple.length - 1,
600
- ),
601
- ],
602
- ),
603
- (() => {
604
- const wrapper: Metadata = Metadata.initialize();
605
- wrapper.arrays.push(
606
- tuple[tuple.length - 1]!.rest!,
607
- );
608
- return wrapper;
609
- })(),
610
- {
611
- ...explore,
612
- start: tuple.length - 1,
613
- },
614
- tagList,
615
- )
616
- : null;
617
-
618
- return config.combiner(explore)("and")(
619
- input,
620
- [
621
- ...(checkLength && rest === null
622
- ? [
623
- {
624
- combined: false,
625
- expression: ts.factory.createStrictEquality(
626
- ts.factory.createPropertyAccessExpression(
627
- input,
628
- "length",
629
- ),
630
- ts.factory.createNumericLiteral(
631
- tuple.length,
632
- ),
633
- ),
634
- },
635
- ]
636
- : []),
637
- ...(config.joiner.tuple
638
- ? [
639
- {
640
- expression: config.joiner.tuple(binaries),
641
- combined: true,
642
- },
643
- ]
644
- : binaries.map((expression) => ({
645
- expression,
646
- combined: true,
647
- }))),
648
- ...(rest !== null
649
- ? [
650
- {
651
- expression: rest,
652
- combined: true,
653
- },
654
- ]
655
- : []),
656
- ],
657
- `[${tuple.map((t) => t.getName()).join(", ")}]`,
658
- );
659
- };
660
- }
661
-
662
- function decode_array(
663
- project: IProject,
664
- config: IConfig,
665
- importer: FunctionImporter,
666
- checkTupleLength: boolean,
667
- ) {
668
- return FeatureProgrammer.decode_array(
669
- {
670
- trace: config.trace,
671
- path: config.path,
672
- decoder: decode(project, config, importer, checkTupleLength),
673
- },
674
- importer,
675
- config.joiner.array,
676
- );
677
- }
678
-
679
- export function decode_object(config: IConfig) {
680
- const func = FeatureProgrammer.decode_object(config);
681
- return function (
682
- input: ts.Expression,
683
- obj: MetadataObject,
684
- explore: IExplore,
685
- ) {
686
- obj.validated = true;
687
- return func(input, obj, explore);
688
- };
689
- }
690
-
691
- const explore_array = (
692
- project: IProject,
693
- config: IConfig,
694
- importer: FunctionImporter,
695
- ) =>
696
- UnionExplorer.array({
697
- checker: decode(project, config, importer),
698
- decoder: decode_array(project, config, importer, true),
699
- empty: config.success,
700
- success: config.success,
701
- failure: (input, expected, explore) =>
702
- ts.factory.createReturnStatement(
703
- config.joiner.failure(input, expected, explore),
704
- ),
705
- });
706
-
707
- const explore_set = (
708
- project: IProject,
709
- config: IConfig,
710
- importer: FunctionImporter,
711
- ) =>
712
- UnionExplorer.set({
713
- checker: decode(project, config, importer),
714
- decoder: decode_array(project, config, importer, true),
715
- empty: config.success,
716
- success: config.success,
717
- failure: (input, expected, explore) =>
718
- ts.factory.createReturnStatement(
719
- config.joiner.failure(input, expected, explore),
720
- ),
721
- });
722
-
723
- const explore_map = (
724
- project: IProject,
725
- config: IConfig,
726
- importer: FunctionImporter,
727
- ) =>
728
- UnionExplorer.map({
729
- checker: (input, entry, explore) => {
730
- const func = decode(project, config, importer);
731
- return ts.factory.createLogicalAnd(
732
- func(
733
- ts.factory.createElementAccessExpression(input, 0),
734
- entry[0],
735
- { ...explore, postfix: `${explore.postfix}[0]` },
736
- [],
737
- ),
738
- func(
739
- ts.factory.createElementAccessExpression(input, 1),
740
- entry[1],
741
- { ...explore, postfix: `${explore.postfix}[1]` },
742
- [],
743
- ),
744
- );
745
- },
746
- decoder: (input, target, explore) =>
747
- decode_array(project, config, importer, false)(
748
- input,
749
- Metadata.create({
750
- any: false,
751
- nullable: false,
752
- required: true,
753
- functional: false,
754
- resolved: null,
755
- constants: [],
756
- atomics: [],
757
- templates: [],
758
- rest: null,
759
- arrays: [],
760
- tuples: [target],
761
- objects: [],
762
- natives: [],
763
- sets: [],
764
- maps: [],
765
- }),
766
- explore,
767
- [],
768
- ),
769
- empty: config.success,
770
- success: config.success,
771
- failure: (input, expected, explore) =>
772
- ts.factory.createReturnStatement(
773
- config.joiner.failure(input, expected, explore),
774
- ),
775
- });
776
-
777
- const explore_objects = (config: IConfig) => {
778
- const objector = decode_object(config);
779
-
780
- return (input: ts.Expression, meta: Metadata, explore: IExplore) => {
781
- if (meta.objects.length === 1)
782
- return objector(input, meta.objects[0]!, explore);
783
-
784
- return ts.factory.createCallExpression(
785
- ts.factory.createIdentifier(
786
- `${config.unioners}${meta.union_index!}`,
787
- ),
788
- undefined,
789
- FeatureProgrammer.get_object_arguments(config)(explore)(input),
790
- );
791
- };
792
- };
793
- }
794
-
795
- const create_add =
796
- (binaries: CheckerProgrammer.IBinary[]) =>
797
- (defaultInput: ts.Expression) =>
798
- (
799
- exact: boolean,
800
- left: ts.Expression,
801
- right: ts.Expression = defaultInput,
802
- ) => {
803
- const factory = exact
804
- ? ts.factory.createStrictEquality
805
- : ts.factory.createStrictInequality;
806
- binaries.push({
807
- expression: factory(left, right),
808
- combined: false,
809
- });
810
- };
1
+ import ts from "typescript";
2
+
3
+ import { ExpressionFactory } from "../factories/ExpressionFactory";
4
+ import { IdentifierFactory } from "../factories/IdentifierFactory";
5
+ import { MetadataCollection } from "../factories/MetadataCollection";
6
+ import { MetadataFactory } from "../factories/MetadataFactory";
7
+ import { ValueFactory } from "../factories/ValueFactory";
8
+
9
+ import { IMetadataTag } from "../metadata/IMetadataTag";
10
+ import { Metadata } from "../metadata/Metadata";
11
+ import { MetadataObject } from "../metadata/MetadataObject";
12
+
13
+ import { IProject } from "../transformers/IProject";
14
+
15
+ import { FeatureProgrammer } from "./FeatureProgrammer";
16
+ import { FunctionImporter } from "./helpers/FunctionImporeter";
17
+ import { IExpressionEntry } from "./helpers/IExpressionEntry";
18
+ import { OptionPredicator } from "./helpers/OptionPredicator";
19
+ import { UnionExplorer } from "./helpers/UnionExplorer";
20
+ import { check_array } from "./internal/check_array";
21
+ import { check_bigint } from "./internal/check_bigint";
22
+ import { check_native } from "./internal/check_native";
23
+ import { check_number } from "./internal/check_number";
24
+ import { check_string } from "./internal/check_string";
25
+ import { check_template } from "./internal/check_template";
26
+ import { decode_union_object } from "./internal/decode_union_object";
27
+
28
+ export namespace CheckerProgrammer {
29
+ export interface IConfig {
30
+ functors: string;
31
+ unioners: string;
32
+ path: boolean;
33
+ trace: boolean;
34
+ equals: boolean;
35
+ numeric: boolean;
36
+ combiner: IConfig.Combiner;
37
+ decoder?: FeatureProgrammer.Decoder<Metadata>;
38
+ joiner: IConfig.IJoiner;
39
+ success: ts.Expression;
40
+ }
41
+ export namespace IConfig {
42
+ export interface Combiner {
43
+ (explorer: IExplore): {
44
+ (logic: "and" | "or"): {
45
+ (
46
+ input: ts.Expression,
47
+ binaries: IBinary[],
48
+ expected: string,
49
+ ): ts.Expression;
50
+ };
51
+ };
52
+ }
53
+ export interface IJoiner {
54
+ object(entries: IExpressionEntry[]): ts.Expression;
55
+ array(input: ts.Expression, arrow: ts.ArrowFunction): ts.Expression;
56
+ tuple?(exprs: ts.Expression[]): ts.Expression;
57
+
58
+ failure(
59
+ value: ts.Expression,
60
+ expected: string,
61
+ explore?: FeatureProgrammer.IExplore,
62
+ ): ts.Expression;
63
+ is?(expression: ts.Expression): ts.Expression;
64
+ required?(exp: ts.Expression): ts.Expression;
65
+ full?: (
66
+ condition: ts.Expression,
67
+ ) => (
68
+ input: ts.Expression,
69
+ expected: string,
70
+ explore: IExplore,
71
+ ) => ts.Expression;
72
+ }
73
+ }
74
+ export import IExplore = FeatureProgrammer.IExplore;
75
+
76
+ export interface IBinary {
77
+ expression: ts.Expression;
78
+ combined: boolean;
79
+ }
80
+
81
+ /* -----------------------------------------------------------
82
+ GENERATORS
83
+ ----------------------------------------------------------- */
84
+ export function generate(
85
+ project: IProject,
86
+ config: IConfig,
87
+ importer: FunctionImporter,
88
+ addition?: () => ts.Statement[],
89
+ ) {
90
+ return FeatureProgrammer.generate(
91
+ project,
92
+ CONFIG(project, config, importer),
93
+ importer,
94
+ () => (addition ? (addition ? addition() : []) : undefined),
95
+ );
96
+ }
97
+
98
+ export const generate_functors = (
99
+ project: IProject,
100
+ config: IConfig,
101
+ importer: FunctionImporter,
102
+ ) =>
103
+ FeatureProgrammer.generate_functors(
104
+ CONFIG(project, config, importer),
105
+ importer,
106
+ );
107
+
108
+ export const generate_unioners = (
109
+ project: IProject,
110
+ config: IConfig,
111
+ importer: FunctionImporter,
112
+ ) =>
113
+ FeatureProgrammer.generate_unioners(
114
+ CONFIG(project, { ...config, numeric: false }, importer),
115
+ );
116
+
117
+ function CONFIG(
118
+ project: IProject,
119
+ config: IConfig,
120
+ importer: FunctionImporter,
121
+ ): FeatureProgrammer.IConfig {
122
+ const output: FeatureProgrammer.IConfig = {
123
+ trace: config.trace,
124
+ path: config.path,
125
+ functors: config.functors,
126
+ unioners: config.unioners,
127
+ initializer: ({ checker }, type) => {
128
+ const collection: MetadataCollection = new MetadataCollection();
129
+ const meta: Metadata = MetadataFactory.generate(
130
+ checker,
131
+ collection,
132
+ type,
133
+ {
134
+ resolve: false,
135
+ constant: true,
136
+ },
137
+ );
138
+ return [collection, meta];
139
+ },
140
+ decoder: config.decoder || decode(project, config, importer),
141
+ objector: {
142
+ checker: config.decoder || decode(project, config, importer),
143
+ decoder: decode_object(config),
144
+ joiner: config.joiner.object,
145
+ unionizer: config.equals
146
+ ? decode_union_object(decode_object(config))(
147
+ (input, obj, explore) =>
148
+ decode_object(config)(input, obj, {
149
+ ...explore,
150
+ tracable: true,
151
+ }),
152
+ )(config.joiner.is || ((expr) => expr))(
153
+ (value, expected) =>
154
+ ts.factory.createReturnStatement(
155
+ config.joiner.failure(value, expected),
156
+ ),
157
+ )
158
+ : (input, targets, explore) =>
159
+ config.combiner(explore)("or")(
160
+ input,
161
+ targets.map((obj) => ({
162
+ expression: decode_object(config)(
163
+ input,
164
+ obj,
165
+ explore,
166
+ ),
167
+ combined: true,
168
+ })),
169
+ `(${targets.map((t) => t.name).join(" | ")})`,
170
+ ),
171
+ failure: (value, expected) =>
172
+ ts.factory.createReturnStatement(
173
+ config.joiner.failure(value, expected),
174
+ ),
175
+ is: config.joiner.is,
176
+ required: config.joiner.required,
177
+ full: config.joiner.full,
178
+ },
179
+ };
180
+ if (config.numeric === true)
181
+ output.generator = {
182
+ unioners: FeatureProgrammer.generate_unioners(
183
+ CONFIG(project, { ...config, numeric: false }, importer),
184
+ ),
185
+ };
186
+ return output;
187
+ }
188
+
189
+ /* -----------------------------------------------------------
190
+ DECODERS
191
+ ----------------------------------------------------------- */
192
+ export function decode(
193
+ project: IProject,
194
+ config: IConfig,
195
+ importer: FunctionImporter,
196
+ ): (
197
+ input: ts.Expression,
198
+ meta: Metadata,
199
+ explore: IExplore,
200
+ tags: IMetadataTag[],
201
+ ) => ts.Expression;
202
+
203
+ /**
204
+ * @internal
205
+ */
206
+ export function decode(
207
+ project: IProject,
208
+ config: IConfig,
209
+ importer: FunctionImporter,
210
+ checkTupleLength: boolean,
211
+ ): (
212
+ input: ts.Expression,
213
+ meta: Metadata,
214
+ explore: IExplore,
215
+ tags: IMetadataTag[],
216
+ ) => ts.Expression;
217
+
218
+ /**
219
+ * @internal
220
+ */
221
+ export function decode(
222
+ project: IProject,
223
+ config: IConfig,
224
+ importer: FunctionImporter,
225
+ checkTupleLength: boolean = true,
226
+ ) {
227
+ return function (
228
+ input: ts.Expression,
229
+ meta: Metadata,
230
+ explore: IExplore,
231
+ tags: IMetadataTag[],
232
+ ): ts.Expression {
233
+ if (meta.any) return config.success;
234
+
235
+ const top: IBinary[] = [];
236
+ const binaries: IBinary[] = [];
237
+ const add = create_add(binaries)(input);
238
+ const getConstantValue = (
239
+ value: number | string | bigint | boolean,
240
+ ) =>
241
+ typeof value === "string"
242
+ ? ts.factory.createStringLiteral(value)
243
+ : ts.factory.createIdentifier(value.toString());
244
+
245
+ //----
246
+ // CHECK OPTIONAL
247
+ //----
248
+ const checkOptional: boolean = meta.empty() || meta.isUnionBucket();
249
+
250
+ // NULLABLE
251
+ if (
252
+ checkOptional ||
253
+ meta.nullable
254
+ // || (meta.objects.length && meta.size() !== meta.objects.length)
255
+ )
256
+ (meta.nullable ? add : create_add(top)(input))(
257
+ meta.nullable,
258
+ ValueFactory.NULL(),
259
+ );
260
+
261
+ // UNDEFINDABLE
262
+ if (checkOptional || !meta.required)
263
+ (meta.required ? create_add(top)(input) : add)(
264
+ !meta.required,
265
+ ValueFactory.UNDEFINED(),
266
+ );
267
+
268
+ // FUNCTIONAL
269
+ if (meta.functional === true)
270
+ if (
271
+ OptionPredicator.functional(project.options) ||
272
+ meta.size() !== 1
273
+ )
274
+ add(
275
+ true,
276
+ ts.factory.createStringLiteral("function"),
277
+ ValueFactory.TYPEOF(input),
278
+ );
279
+ else
280
+ binaries.push({
281
+ combined: false,
282
+ expression: config.success,
283
+ });
284
+
285
+ //----
286
+ // VALUES
287
+ //----
288
+ // CONSTANT VALUES
289
+ for (const constant of meta.constants)
290
+ for (const val of constant.values)
291
+ add(true, getConstantValue(val));
292
+
293
+ // ATOMIC VALUES
294
+ for (const type of meta.atomics)
295
+ if (type === "number")
296
+ binaries.push({
297
+ expression: check_number(project, config.numeric)(
298
+ input,
299
+ tags,
300
+ ),
301
+ combined: false,
302
+ });
303
+ else if (type === "bigint")
304
+ binaries.push({
305
+ expression: check_bigint(input, tags),
306
+ combined: false,
307
+ });
308
+ else if (type === "string")
309
+ binaries.push({
310
+ expression: check_string(importer)(input, tags),
311
+ combined: false,
312
+ });
313
+ else
314
+ add(
315
+ true,
316
+ ts.factory.createStringLiteral(type),
317
+ ValueFactory.TYPEOF(input),
318
+ );
319
+
320
+ // TEMPLATE LITERAL VALUES
321
+ if (meta.templates.length)
322
+ binaries.push({
323
+ expression: check_template(importer)(
324
+ input,
325
+ meta.templates,
326
+ tags,
327
+ ),
328
+ combined: false,
329
+ });
330
+
331
+ //----
332
+ // INSTANCES
333
+ //----
334
+ // TUPLE
335
+ if (meta.tuples.length > 0) {
336
+ const inner: ts.Expression[] = [];
337
+ for (const tuple of meta.tuples)
338
+ inner.push(
339
+ decode_tuple(
340
+ project,
341
+ config,
342
+ importer,
343
+ checkTupleLength,
344
+ )(input, tuple, explore, tags),
345
+ );
346
+
347
+ // ADD
348
+ binaries.push({
349
+ expression: config.combiner(explore)("and")(
350
+ input,
351
+ [
352
+ ...(checkTupleLength
353
+ ? [
354
+ {
355
+ expression:
356
+ ExpressionFactory.isArray(input),
357
+ combined: false,
358
+ },
359
+ ]
360
+ : []),
361
+ ...inner.map((expression) => ({
362
+ expression,
363
+ combined: true,
364
+ })),
365
+ ],
366
+ meta.getName(),
367
+ ),
368
+ combined: true,
369
+ });
370
+ }
371
+
372
+ // ARRAY
373
+ if (meta.arrays.length > 0)
374
+ if (meta.arrays.every((elem) => elem.any))
375
+ binaries.push({
376
+ expression: check_array(input, tags),
377
+ combined: false,
378
+ });
379
+ else
380
+ binaries.push({
381
+ expression: config.combiner(explore)("and")(
382
+ input,
383
+ [
384
+ ...(checkTupleLength
385
+ ? [
386
+ {
387
+ expression: check_array(
388
+ input,
389
+ tags,
390
+ ),
391
+ combined: false,
392
+ },
393
+ ]
394
+ : []),
395
+ {
396
+ expression: explore_array(
397
+ project,
398
+ config,
399
+ importer,
400
+ )(
401
+ input,
402
+ meta.arrays,
403
+ {
404
+ ...explore,
405
+ from: "array",
406
+ },
407
+ tags,
408
+ ),
409
+ combined: true,
410
+ },
411
+ ],
412
+ meta.getName(),
413
+ ),
414
+ combined: true,
415
+ });
416
+
417
+ // OBJECT
418
+ if (meta.objects.length > 0)
419
+ binaries.push({
420
+ expression: config.combiner(explore)("and")(
421
+ input,
422
+ [
423
+ {
424
+ expression: ExpressionFactory.isObject(input, {
425
+ checkNull: true,
426
+ checkArray: meta.objects.some((obj) =>
427
+ obj.properties.every(
428
+ (prop) =>
429
+ !prop.key.isSoleLiteral() ||
430
+ !prop.value.required,
431
+ ),
432
+ ),
433
+ }),
434
+ combined: false,
435
+ },
436
+ {
437
+ expression: explore_objects(config)(
438
+ input,
439
+ meta,
440
+ {
441
+ ...explore,
442
+ from: "object",
443
+ },
444
+ ),
445
+ combined: true,
446
+ },
447
+ ],
448
+ meta.getName(),
449
+ ),
450
+ combined: true,
451
+ });
452
+
453
+ // NATIVE CLASSES
454
+ for (const native of meta.natives)
455
+ binaries.push({
456
+ expression: check_native(native)(input),
457
+ combined: false,
458
+ });
459
+
460
+ // SETS
461
+ if (meta.sets.length)
462
+ if (meta.sets.every((elem) => elem.any))
463
+ binaries.push({
464
+ combined: false,
465
+ expression: check_native("Set")(input),
466
+ });
467
+ else
468
+ binaries.push({
469
+ combined: true,
470
+ expression: config.combiner(explore)("and")(
471
+ input,
472
+ [
473
+ {
474
+ combined: false,
475
+ expression: check_native("Set")(input),
476
+ },
477
+ {
478
+ combined: true,
479
+ expression: explore_set(
480
+ project,
481
+ config,
482
+ importer,
483
+ )(
484
+ input,
485
+ meta.sets,
486
+ {
487
+ ...explore,
488
+ from: "array",
489
+ },
490
+ [],
491
+ ),
492
+ },
493
+ ],
494
+ meta.getName(),
495
+ ),
496
+ });
497
+
498
+ // MAPS
499
+ if (meta.maps.length)
500
+ if (meta.maps.every((elem) => elem.key.any && elem.value.any))
501
+ binaries.push({
502
+ expression: check_native("Map")(input),
503
+ combined: false,
504
+ });
505
+ else
506
+ binaries.push({
507
+ combined: true,
508
+ expression: config.combiner(explore)("and")(
509
+ input,
510
+ [
511
+ {
512
+ combined: false,
513
+ expression: check_native("Map")(input),
514
+ },
515
+ {
516
+ combined: true,
517
+ expression: explore_map(
518
+ project,
519
+ config,
520
+ importer,
521
+ )(
522
+ input,
523
+ meta.maps.map((m) => [m.key, m.value]),
524
+ {
525
+ ...explore,
526
+ from: "array",
527
+ },
528
+ [],
529
+ ),
530
+ },
531
+ ],
532
+ meta.getName(),
533
+ ),
534
+ });
535
+
536
+ // COMBINE CONDITIONS
537
+ return top.length && binaries.length
538
+ ? config.combiner(explore)("and")(
539
+ input,
540
+ [
541
+ ...top,
542
+ {
543
+ expression: config.combiner(explore)("or")(
544
+ input,
545
+ binaries,
546
+ meta.getName(),
547
+ ),
548
+ combined: true,
549
+ },
550
+ ],
551
+ meta.getName(),
552
+ )
553
+ : binaries.length
554
+ ? config.combiner(explore)("or")(
555
+ input,
556
+ binaries,
557
+ meta.getName(),
558
+ )
559
+ : config.success;
560
+ };
561
+ }
562
+
563
+ function decode_tuple(
564
+ project: IProject,
565
+ config: IConfig,
566
+ importer: FunctionImporter,
567
+ checkLength: boolean,
568
+ ) {
569
+ return function (
570
+ input: ts.Expression,
571
+ tuple: Array<Metadata>,
572
+ explore: IExplore,
573
+ tagList: IMetadataTag[],
574
+ ): ts.Expression {
575
+ const binaries: ts.Expression[] = tuple
576
+ .filter((meta) => meta.rest === null)
577
+ .map((meta, index) =>
578
+ decode(project, config, importer)(
579
+ ts.factory.createElementAccessExpression(input, index),
580
+ meta,
581
+ {
582
+ ...explore,
583
+ from: "array",
584
+ postfix: explore.postfix.length
585
+ ? `${explore.postfix.slice(0, -1)}[${index}]"`
586
+ : `[${index}]`,
587
+ },
588
+ tagList,
589
+ ),
590
+ );
591
+ const rest: ts.Expression | null =
592
+ tuple.length && tuple[tuple.length - 1]!.rest !== null
593
+ ? decode(project, config, importer, false)(
594
+ ts.factory.createCallExpression(
595
+ IdentifierFactory.join(input, "slice"),
596
+ undefined,
597
+ [
598
+ ts.factory.createNumericLiteral(
599
+ tuple.length - 1,
600
+ ),
601
+ ],
602
+ ),
603
+ (() => {
604
+ const wrapper: Metadata = Metadata.initialize();
605
+ wrapper.arrays.push(
606
+ tuple[tuple.length - 1]!.rest!,
607
+ );
608
+ return wrapper;
609
+ })(),
610
+ {
611
+ ...explore,
612
+ start: tuple.length - 1,
613
+ },
614
+ tagList,
615
+ )
616
+ : null;
617
+
618
+ return config.combiner(explore)("and")(
619
+ input,
620
+ [
621
+ ...(checkLength && rest === null
622
+ ? [
623
+ {
624
+ combined: false,
625
+ expression: ts.factory.createStrictEquality(
626
+ ts.factory.createPropertyAccessExpression(
627
+ input,
628
+ "length",
629
+ ),
630
+ ts.factory.createNumericLiteral(
631
+ tuple.length,
632
+ ),
633
+ ),
634
+ },
635
+ ]
636
+ : []),
637
+ ...(config.joiner.tuple
638
+ ? [
639
+ {
640
+ expression: config.joiner.tuple(binaries),
641
+ combined: true,
642
+ },
643
+ ]
644
+ : binaries.map((expression) => ({
645
+ expression,
646
+ combined: true,
647
+ }))),
648
+ ...(rest !== null
649
+ ? [
650
+ {
651
+ expression: rest,
652
+ combined: true,
653
+ },
654
+ ]
655
+ : []),
656
+ ],
657
+ `[${tuple.map((t) => t.getName()).join(", ")}]`,
658
+ );
659
+ };
660
+ }
661
+
662
+ function decode_array(
663
+ project: IProject,
664
+ config: IConfig,
665
+ importer: FunctionImporter,
666
+ checkTupleLength: boolean,
667
+ ) {
668
+ return FeatureProgrammer.decode_array(
669
+ {
670
+ trace: config.trace,
671
+ path: config.path,
672
+ decoder: decode(project, config, importer, checkTupleLength),
673
+ },
674
+ importer,
675
+ config.joiner.array,
676
+ );
677
+ }
678
+
679
+ export function decode_object(config: IConfig) {
680
+ const func = FeatureProgrammer.decode_object(config);
681
+ return function (
682
+ input: ts.Expression,
683
+ obj: MetadataObject,
684
+ explore: IExplore,
685
+ ) {
686
+ obj.validated = true;
687
+ return func(input, obj, explore);
688
+ };
689
+ }
690
+
691
+ const explore_array = (
692
+ project: IProject,
693
+ config: IConfig,
694
+ importer: FunctionImporter,
695
+ ) =>
696
+ UnionExplorer.array({
697
+ checker: decode(project, config, importer),
698
+ decoder: decode_array(project, config, importer, true),
699
+ empty: config.success,
700
+ success: config.success,
701
+ failure: (input, expected, explore) =>
702
+ ts.factory.createReturnStatement(
703
+ config.joiner.failure(input, expected, explore),
704
+ ),
705
+ });
706
+
707
+ const explore_set = (
708
+ project: IProject,
709
+ config: IConfig,
710
+ importer: FunctionImporter,
711
+ ) =>
712
+ UnionExplorer.set({
713
+ checker: decode(project, config, importer),
714
+ decoder: decode_array(project, config, importer, true),
715
+ empty: config.success,
716
+ success: config.success,
717
+ failure: (input, expected, explore) =>
718
+ ts.factory.createReturnStatement(
719
+ config.joiner.failure(input, expected, explore),
720
+ ),
721
+ });
722
+
723
+ const explore_map = (
724
+ project: IProject,
725
+ config: IConfig,
726
+ importer: FunctionImporter,
727
+ ) =>
728
+ UnionExplorer.map({
729
+ checker: (input, entry, explore) => {
730
+ const func = decode(project, config, importer);
731
+ return ts.factory.createLogicalAnd(
732
+ func(
733
+ ts.factory.createElementAccessExpression(input, 0),
734
+ entry[0],
735
+ { ...explore, postfix: `${explore.postfix}[0]` },
736
+ [],
737
+ ),
738
+ func(
739
+ ts.factory.createElementAccessExpression(input, 1),
740
+ entry[1],
741
+ { ...explore, postfix: `${explore.postfix}[1]` },
742
+ [],
743
+ ),
744
+ );
745
+ },
746
+ decoder: (input, target, explore) =>
747
+ decode_array(project, config, importer, false)(
748
+ input,
749
+ Metadata.create({
750
+ any: false,
751
+ nullable: false,
752
+ required: true,
753
+ functional: false,
754
+ resolved: null,
755
+ constants: [],
756
+ atomics: [],
757
+ templates: [],
758
+ rest: null,
759
+ arrays: [],
760
+ tuples: [target],
761
+ objects: [],
762
+ natives: [],
763
+ sets: [],
764
+ maps: [],
765
+ }),
766
+ explore,
767
+ [],
768
+ ),
769
+ empty: config.success,
770
+ success: config.success,
771
+ failure: (input, expected, explore) =>
772
+ ts.factory.createReturnStatement(
773
+ config.joiner.failure(input, expected, explore),
774
+ ),
775
+ });
776
+
777
+ const explore_objects = (config: IConfig) => {
778
+ const objector = decode_object(config);
779
+
780
+ return (input: ts.Expression, meta: Metadata, explore: IExplore) => {
781
+ if (meta.objects.length === 1)
782
+ return objector(input, meta.objects[0]!, explore);
783
+
784
+ return ts.factory.createCallExpression(
785
+ ts.factory.createIdentifier(
786
+ `${config.unioners}${meta.union_index!}`,
787
+ ),
788
+ undefined,
789
+ FeatureProgrammer.get_object_arguments(config)(explore)(input),
790
+ );
791
+ };
792
+ };
793
+ }
794
+
795
+ const create_add =
796
+ (binaries: CheckerProgrammer.IBinary[]) =>
797
+ (defaultInput: ts.Expression) =>
798
+ (
799
+ exact: boolean,
800
+ left: ts.Expression,
801
+ right: ts.Expression = defaultInput,
802
+ ) => {
803
+ const factory = exact
804
+ ? ts.factory.createStrictEquality
805
+ : ts.factory.createStrictInequality;
806
+ binaries.push({
807
+ expression: factory(left, right),
808
+ combined: false,
809
+ });
810
+ };