typia 6.7.0 → 6.7.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 (85) hide show
  1. package/lib/programmers/AssertProgrammer.d.ts +0 -1
  2. package/lib/programmers/AssertProgrammer.js.map +1 -1
  3. package/lib/programmers/CheckerProgrammer.d.ts +1 -1
  4. package/lib/programmers/FeatureProgrammer.d.ts +1 -1
  5. package/lib/programmers/IsProgrammer.d.ts +1 -1
  6. package/lib/programmers/RandomProgrammer.d.ts +10 -1
  7. package/lib/programmers/RandomProgrammer.js +62 -37
  8. package/lib/programmers/RandomProgrammer.js.map +1 -1
  9. package/lib/programmers/ValidateProgrammer.d.ts +1 -1
  10. package/lib/programmers/json/JsonIsParseProgrammer.d.ts +1 -1
  11. package/lib/programmers/json/JsonIsStringifyProgrammer.d.ts +1 -1
  12. package/lib/programmers/json/JsonStringifyProgrammer.d.ts +1 -1
  13. package/lib/programmers/json/JsonStringifyProgrammer.js +1 -3
  14. package/lib/programmers/json/JsonStringifyProgrammer.js.map +1 -1
  15. package/lib/programmers/json/JsonValidateParseProgrammer.d.ts +1 -1
  16. package/lib/programmers/json/JsonValidateStringifyProgrammer.d.ts +1 -1
  17. package/lib/programmers/misc/MiscCloneProgrammer.d.ts +1 -1
  18. package/lib/programmers/misc/MiscCloneProgrammer.js +33 -14
  19. package/lib/programmers/misc/MiscCloneProgrammer.js.map +1 -1
  20. package/lib/programmers/misc/MiscIsCloneProgrammer.d.ts +1 -1
  21. package/lib/programmers/misc/MiscIsPruneProgrammer.d.ts +1 -1
  22. package/lib/programmers/misc/MiscPruneProgrammer.d.ts +1 -1
  23. package/lib/programmers/misc/MiscValidateCloneProgrammer.d.ts +1 -1
  24. package/lib/programmers/misc/MiscValidatePruneProgrammer.d.ts +1 -1
  25. package/lib/programmers/notations/NotationGeneralProgrammer.d.ts +1 -1
  26. package/lib/programmers/notations/NotationGeneralProgrammer.js +30 -11
  27. package/lib/programmers/notations/NotationGeneralProgrammer.js.map +1 -1
  28. package/lib/programmers/notations/NotationValidateGeneralProgrammer.d.ts +1 -1
  29. package/package.json +1 -1
  30. package/src/programmers/AssertProgrammer.ts +397 -398
  31. package/src/programmers/CheckerProgrammer.ts +1138 -1138
  32. package/src/programmers/FeatureProgrammer.ts +549 -549
  33. package/src/programmers/IsProgrammer.ts +1 -1
  34. package/src/programmers/RandomProgrammer.ts +112 -77
  35. package/src/programmers/ValidateProgrammer.ts +382 -382
  36. package/src/programmers/functional/FunctionalAssertFunctionProgrammer.ts +141 -141
  37. package/src/programmers/functional/FunctionalAssertParametersProgrammer.ts +108 -108
  38. package/src/programmers/functional/FunctionalAssertReturnProgrammer.ts +98 -98
  39. package/src/programmers/functional/FunctionalIsFunctionProgrammer.ts +72 -72
  40. package/src/programmers/functional/FunctionalIsParametersProgrammer.ts +101 -101
  41. package/src/programmers/functional/FunctionalIsReturnProgrammer.ts +106 -106
  42. package/src/programmers/functional/FunctionalValidateFunctionProgrammer.ts +123 -123
  43. package/src/programmers/functional/FunctionalValidateParametersProgrammer.ts +267 -267
  44. package/src/programmers/functional/FunctionalValidateReturnProgrammer.ts +126 -126
  45. package/src/programmers/helpers/FunctionImporter.ts +97 -97
  46. package/src/programmers/http/HttpAssertFormDataProgrammer.ts +91 -91
  47. package/src/programmers/http/HttpAssertHeadersProgrammer.ts +91 -91
  48. package/src/programmers/http/HttpAssertQueryProgrammer.ts +93 -93
  49. package/src/programmers/http/HttpFormDataProgrammer.ts +278 -278
  50. package/src/programmers/http/HttpHeadersProgrammer.ts +347 -347
  51. package/src/programmers/http/HttpIsFormDataProgrammer.ts +102 -102
  52. package/src/programmers/http/HttpIsHeadersProgrammer.ts +102 -102
  53. package/src/programmers/http/HttpIsQueryProgrammer.ts +104 -104
  54. package/src/programmers/http/HttpQueryProgrammer.ts +298 -298
  55. package/src/programmers/http/HttpValidateFormDataProgrammer.ts +85 -85
  56. package/src/programmers/http/HttpValidateHeadersProgrammer.ts +85 -85
  57. package/src/programmers/http/HttpValidateQueryProgrammer.ts +87 -87
  58. package/src/programmers/json/JsonAssertParseProgrammer.ts +96 -96
  59. package/src/programmers/json/JsonAssertStringifyProgrammer.ts +104 -104
  60. package/src/programmers/json/JsonIsParseProgrammer.ts +110 -110
  61. package/src/programmers/json/JsonIsStringifyProgrammer.ts +102 -102
  62. package/src/programmers/json/JsonStringifyProgrammer.ts +909 -910
  63. package/src/programmers/json/JsonValidateParseProgrammer.ts +87 -87
  64. package/src/programmers/json/JsonValidateStringifyProgrammer.ts +111 -111
  65. package/src/programmers/misc/MiscAssertCloneProgrammer.ts +87 -87
  66. package/src/programmers/misc/MiscAssertPruneProgrammer.ts +87 -87
  67. package/src/programmers/misc/MiscCloneProgrammer.ts +781 -759
  68. package/src/programmers/misc/MiscIsCloneProgrammer.ts +93 -93
  69. package/src/programmers/misc/MiscIsPruneProgrammer.ts +94 -94
  70. package/src/programmers/misc/MiscPruneProgrammer.ts +560 -560
  71. package/src/programmers/misc/MiscValidateCloneProgrammer.ts +104 -104
  72. package/src/programmers/misc/MiscValidatePruneProgrammer.ts +98 -98
  73. package/src/programmers/notations/NotationAssertGeneralProgrammer.ts +91 -91
  74. package/src/programmers/notations/NotationGeneralProgrammer.ts +709 -685
  75. package/src/programmers/notations/NotationIsGeneralProgrammer.ts +97 -97
  76. package/src/programmers/notations/NotationValidateGeneralProgrammer.ts +107 -107
  77. package/src/programmers/protobuf/ProtobufAssertDecodeProgrammer.ts +91 -91
  78. package/src/programmers/protobuf/ProtobufAssertEncodeProgrammer.ts +95 -95
  79. package/src/programmers/protobuf/ProtobufDecodeProgrammer.ts +646 -646
  80. package/src/programmers/protobuf/ProtobufEncodeProgrammer.ts +852 -852
  81. package/src/programmers/protobuf/ProtobufIsDecodeProgrammer.ts +104 -104
  82. package/src/programmers/protobuf/ProtobufIsEncodeProgrammer.ts +93 -93
  83. package/src/programmers/protobuf/ProtobufValidateDecodeProgrammer.ts +85 -85
  84. package/src/programmers/protobuf/ProtobufValidateEncodeProgrammer.ts +109 -109
  85. package/src/transformers/internal/GenericTransformer.ts +104 -104
@@ -1,685 +1,709 @@
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 { StatementFactory } from "../../factories/StatementFactory";
8
- import { TypeFactory } from "../../factories/TypeFactory";
9
-
10
- import { Metadata } from "../../schemas/metadata/Metadata";
11
- import { MetadataArray } from "../../schemas/metadata/MetadataArray";
12
- import { MetadataTuple } from "../../schemas/metadata/MetadataTuple";
13
- import { MetadataTupleType } from "../../schemas/metadata/MetadataTupleType";
14
-
15
- import { IProject } from "../../transformers/IProject";
16
- import { TransformerError } from "../../transformers/TransformerError";
17
-
18
- import { StringUtil } from "../../utils/StringUtil";
19
-
20
- import { FeatureProgrammer } from "../FeatureProgrammer";
21
- import { IsProgrammer } from "../IsProgrammer";
22
- import { FunctionImporter } from "../helpers/FunctionImporter";
23
- import { NotationJoiner } from "../helpers/NotationJoiner";
24
- import { UnionExplorer } from "../helpers/UnionExplorer";
25
- import { decode_union_object } from "../internal/decode_union_object";
26
- import { postfix_of_tuple } from "../internal/postfix_of_tuple";
27
- import { wrap_metadata_rest_tuple } from "../internal/wrap_metadata_rest_tuple";
28
-
29
- export namespace NotationGeneralProgrammer {
30
- export const returnType =
31
- (rename: (str: string) => string) => (type: string) =>
32
- `typia.${StringUtil.capitalize(rename.name)}Case<${type}>`;
33
-
34
- export const decompose = (props: {
35
- rename: (str: string) => string;
36
- validated: boolean;
37
- project: IProject;
38
- importer: FunctionImporter;
39
- type: ts.Type;
40
- name?: string;
41
- }): FeatureProgrammer.IDecomposed => {
42
- const config = configure(props.rename)(props.project)(props.importer);
43
- if (props.validated === false)
44
- config.addition = (collection) =>
45
- IsProgrammer.write_function_statements(props.project)(props.importer)(
46
- collection,
47
- );
48
- const composed: FeatureProgrammer.IComposed = FeatureProgrammer.compose({
49
- ...props,
50
- config,
51
- });
52
- return {
53
- functions: composed.functions,
54
- statements: composed.statements,
55
- arrow: ts.factory.createArrowFunction(
56
- undefined,
57
- undefined,
58
- composed.parameters,
59
- TypeFactory.keyword("void"),
60
- undefined,
61
- composed.body,
62
- ),
63
- };
64
- };
65
-
66
- export const write =
67
- (rename: (str: string) => string) =>
68
- (project: IProject) =>
69
- (modulo: ts.LeftHandSideExpression) =>
70
- (type: ts.Type, name?: string) => {
71
- const importer: FunctionImporter = new FunctionImporter(modulo.getText());
72
- const result: FeatureProgrammer.IDecomposed = decompose({
73
- rename,
74
- validated: true,
75
- project,
76
- importer,
77
- type,
78
- name,
79
- });
80
- return FeatureProgrammer.writeDecomposed({
81
- importer,
82
- modulo,
83
- result,
84
- });
85
- };
86
-
87
- const write_array_functions =
88
- (config: FeatureProgrammer.IConfig) =>
89
- (importer: FunctionImporter) =>
90
- (collection: MetadataCollection): ts.VariableStatement[] =>
91
- collection
92
- .arrays()
93
- .filter((a) => a.recursive)
94
- .map((type, i) =>
95
- StatementFactory.constant(
96
- `${config.prefix}a${i}`,
97
- ts.factory.createArrowFunction(
98
- undefined,
99
- undefined,
100
- FeatureProgrammer.parameterDeclarations(config)(
101
- TypeFactory.keyword("any"),
102
- )(ts.factory.createIdentifier("input")),
103
- TypeFactory.keyword("any"),
104
- undefined,
105
- decode_array_inline(config)(importer)(
106
- ts.factory.createIdentifier("input"),
107
- MetadataArray.create({
108
- type,
109
- tags: [],
110
- }),
111
- {
112
- tracable: config.trace,
113
- source: "function",
114
- from: "array",
115
- postfix: "",
116
- },
117
- ),
118
- ),
119
- ),
120
- );
121
-
122
- const write_tuple_functions =
123
- (project: IProject) =>
124
- (config: FeatureProgrammer.IConfig) =>
125
- (importer: FunctionImporter) =>
126
- (collection: MetadataCollection): ts.VariableStatement[] =>
127
- collection
128
- .tuples()
129
- .filter((t) => t.recursive)
130
- .map((tuple, i) =>
131
- StatementFactory.constant(
132
- `${config.prefix}t${i}`,
133
- ts.factory.createArrowFunction(
134
- undefined,
135
- undefined,
136
- FeatureProgrammer.parameterDeclarations(config)(
137
- TypeFactory.keyword("any"),
138
- )(ts.factory.createIdentifier("input")),
139
- TypeFactory.keyword("any"),
140
- undefined,
141
- decode_tuple_inline(project)(config)(importer)(
142
- ts.factory.createIdentifier("input"),
143
- tuple,
144
- {
145
- tracable: config.trace,
146
- source: "function",
147
- from: "array",
148
- postfix: "",
149
- },
150
- ),
151
- ),
152
- ),
153
- );
154
-
155
- /* -----------------------------------------------------------
156
- DECODERS
157
- ----------------------------------------------------------- */
158
- const decode =
159
- (project: IProject) =>
160
- (config: FeatureProgrammer.IConfig) =>
161
- (importer: FunctionImporter) =>
162
- (
163
- input: ts.Expression,
164
- meta: Metadata,
165
- explore: FeatureProgrammer.IExplore,
166
- ): ts.Expression => {
167
- // ANY TYPE
168
- if (
169
- meta.any ||
170
- meta.arrays.some((a) => a.type.value.any) ||
171
- meta.tuples.some(
172
- (t) =>
173
- !!t.type.elements.length && t.type.elements.every((e) => e.any),
174
- )
175
- )
176
- return ts.factory.createCallExpression(importer.use("any"), undefined, [
177
- input,
178
- ]);
179
-
180
- interface IUnion {
181
- type: string;
182
- is: () => ts.Expression;
183
- value: () => ts.Expression;
184
- }
185
- const unions: IUnion[] = [];
186
-
187
- //----
188
- // LIST UP UNION TYPES
189
- //----
190
- // FUNCTIONAL
191
- if (meta.functional)
192
- unions.push({
193
- type: "functional",
194
- is: () =>
195
- ts.factory.createStrictEquality(
196
- ts.factory.createStringLiteral("function"),
197
- ts.factory.createTypeOfExpression(input),
198
- ),
199
- value: () => ts.factory.createIdentifier("undefined"),
200
- });
201
-
202
- // TUPLES
203
- for (const tuple of meta.tuples)
204
- unions.push({
205
- type: "tuple",
206
- is: () =>
207
- IsProgrammer.decode(project)(importer)(
208
- input,
209
- (() => {
210
- const partial = Metadata.initialize();
211
- partial.tuples.push(tuple);
212
- return partial;
213
- })(),
214
- explore,
215
- ),
216
- value: () =>
217
- decode_tuple(project)(config)(importer)(input, tuple, explore),
218
- });
219
-
220
- // ARRAYS
221
- if (meta.arrays.length)
222
- unions.push({
223
- type: "array",
224
- is: () => ExpressionFactory.isArray(input),
225
- value: () =>
226
- explore_arrays(project)(config)(importer)(input, meta.arrays, {
227
- ...explore,
228
- from: "array",
229
- }),
230
- });
231
-
232
- // NATIVE TYPES
233
- if (meta.sets.length)
234
- unions.push({
235
- type: "set",
236
- is: () => ExpressionFactory.isInstanceOf("Set")(input),
237
- value: () =>
238
- explore_sets(project)(config)(importer)(input, meta.sets, {
239
- ...explore,
240
- from: "array",
241
- }),
242
- });
243
- if (meta.maps.length)
244
- unions.push({
245
- type: "map",
246
- is: () => ExpressionFactory.isInstanceOf("Map")(input),
247
- value: () =>
248
- explore_maps(project)(config)(importer)(input, meta.maps, {
249
- ...explore,
250
- from: "array",
251
- }),
252
- });
253
- for (const native of meta.natives) {
254
- if (native === "WeakSet" || native === "WeakMap") continue;
255
- unions.push({
256
- type: "native",
257
- is: () => ExpressionFactory.isInstanceOf(native)(input),
258
- value: () =>
259
- native === "Boolean" || native === "Number" || native === "String"
260
- ? ts.factory.createCallExpression(
261
- IdentifierFactory.access(input)("valueOf"),
262
- undefined,
263
- undefined,
264
- )
265
- : decode_native(native)(input),
266
- });
267
- }
268
-
269
- // OBJECTS
270
- if (meta.objects.length)
271
- unions.push({
272
- type: "object",
273
- is: () =>
274
- ExpressionFactory.isObject({
275
- checkNull: true,
276
- checkArray: false,
277
- })(input),
278
- value: () =>
279
- explore_objects(config)(importer)(input, meta, {
280
- ...explore,
281
- from: "object",
282
- }),
283
- });
284
-
285
- // COMPOSITION
286
- let last: ts.Expression = input;
287
- for (const u of unions.reverse())
288
- last = ts.factory.createConditionalExpression(
289
- u.is(),
290
- undefined,
291
- u.value(),
292
- undefined,
293
- last,
294
- );
295
- return ts.factory.createAsExpression(last, TypeFactory.keyword("any"));
296
- };
297
-
298
- const decode_object = (importer: FunctionImporter) =>
299
- FeatureProgrammer.decode_object({
300
- trace: false,
301
- path: false,
302
- prefix: PREFIX,
303
- })(importer);
304
-
305
- const decode_array =
306
- (config: FeatureProgrammer.IConfig) =>
307
- (importer: FunctionImporter) =>
308
- (
309
- input: ts.Expression,
310
- array: MetadataArray,
311
- explore: FeatureProgrammer.IExplore,
312
- ) =>
313
- array.type.recursive
314
- ? ts.factory.createCallExpression(
315
- ts.factory.createIdentifier(
316
- importer.useLocal(`${config.prefix}a${array.type.index}`),
317
- ),
318
- undefined,
319
- FeatureProgrammer.argumentsArray(config)({
320
- ...explore,
321
- source: "function",
322
- from: "array",
323
- })(input),
324
- )
325
- : decode_array_inline(config)(importer)(input, array, explore);
326
-
327
- const decode_array_inline =
328
- (config: FeatureProgrammer.IConfig) =>
329
- (importer: FunctionImporter) =>
330
- (
331
- input: ts.Expression,
332
- array: MetadataArray,
333
- explore: FeatureProgrammer.IExplore,
334
- ) =>
335
- FeatureProgrammer.decode_array(config)(importer)(NotationJoiner.array)(
336
- input,
337
- array,
338
- explore,
339
- );
340
-
341
- const decode_tuple =
342
- (project: IProject) =>
343
- (config: FeatureProgrammer.IConfig) =>
344
- (importer: FunctionImporter) =>
345
- (
346
- input: ts.Expression,
347
- tuple: MetadataTuple,
348
- explore: FeatureProgrammer.IExplore,
349
- ): ts.Expression =>
350
- tuple.type.recursive
351
- ? ts.factory.createCallExpression(
352
- ts.factory.createIdentifier(
353
- importer.useLocal(`${config.prefix}t${tuple.type.index}`),
354
- ),
355
- undefined,
356
- FeatureProgrammer.argumentsArray(config)({
357
- ...explore,
358
- source: "function",
359
- })(input),
360
- )
361
- : decode_tuple_inline(project)(config)(importer)(
362
- input,
363
- tuple.type,
364
- explore,
365
- );
366
-
367
- const decode_tuple_inline =
368
- (project: IProject) =>
369
- (config: FeatureProgrammer.IConfig) =>
370
- (importer: FunctionImporter) =>
371
- (
372
- input: ts.Expression,
373
- tuple: MetadataTupleType,
374
- explore: FeatureProgrammer.IExplore,
375
- ): ts.Expression => {
376
- const children: ts.Expression[] = tuple.elements
377
- .filter((m) => m.rest === null)
378
- .map((elem, index) =>
379
- decode(project)(config)(importer)(
380
- ts.factory.createElementAccessExpression(input, index),
381
- elem,
382
- {
383
- ...explore,
384
- from: "array",
385
- postfix: explore.postfix.length
386
- ? `${postfix_of_tuple(explore.postfix)}[${index}]"`
387
- : `"[${index}]"`,
388
- },
389
- ),
390
- );
391
- const rest = (() => {
392
- if (tuple.elements.length === 0) return null;
393
-
394
- const last: Metadata = tuple.elements.at(-1)!;
395
- const rest: Metadata | null = last.rest;
396
- if (rest === null) return null;
397
-
398
- return decode(project)(config)(importer)(
399
- ts.factory.createCallExpression(
400
- IdentifierFactory.access(input)("slice"),
401
- undefined,
402
- [ExpressionFactory.number(tuple.elements.length - 1)],
403
- ),
404
- wrap_metadata_rest_tuple(tuple.elements.at(-1)!.rest!),
405
- {
406
- ...explore,
407
- start: tuple.elements.length - 1,
408
- },
409
- );
410
- })();
411
- return NotationJoiner.tuple(children, rest);
412
- };
413
-
414
- /* -----------------------------------------------------------
415
- NATIVE CLASSES
416
- ----------------------------------------------------------- */
417
- const decode_native = (type: string) => (input: ts.Expression) =>
418
- type === "Date"
419
- ? ts.factory.createNewExpression(
420
- ts.factory.createIdentifier(type),
421
- undefined,
422
- [input],
423
- )
424
- : input;
425
-
426
- /* -----------------------------------------------------------
427
- EXPLORERS FOR UNION TYPES
428
- ----------------------------------------------------------- */
429
- const explore_sets =
430
- (project: IProject) =>
431
- (config: FeatureProgrammer.IConfig) =>
432
- (importer: FunctionImporter) =>
433
- (
434
- input: ts.Expression,
435
- sets: Metadata[],
436
- explore: FeatureProgrammer.IExplore,
437
- ): ts.Expression =>
438
- ts.factory.createCallExpression(
439
- UnionExplorer.set({
440
- checker: IsProgrammer.decode(project)(importer),
441
- decoder: (input, array, explore) =>
442
- ts.factory.createNewExpression(
443
- ts.factory.createIdentifier("Set"),
444
- [TypeFactory.keyword("any")],
445
- [decode_array(config)(importer)(input, array, explore)],
446
- ),
447
- empty: ts.factory.createNewExpression(
448
- ts.factory.createIdentifier("Set"),
449
- [TypeFactory.keyword("any")],
450
- [],
451
- ),
452
- success: ts.factory.createTrue(),
453
- failure: (input, expected) =>
454
- create_throw_error(importer)(expected)(input),
455
- })([])(input, sets, explore),
456
- undefined,
457
- undefined,
458
- );
459
-
460
- const explore_maps =
461
- (project: IProject) =>
462
- (config: FeatureProgrammer.IConfig) =>
463
- (importer: FunctionImporter) =>
464
- (
465
- input: ts.Expression,
466
- maps: Metadata.Entry[],
467
- explore: FeatureProgrammer.IExplore,
468
- ): ts.Expression =>
469
- ts.factory.createCallExpression(
470
- UnionExplorer.map({
471
- checker: (top, entry, explore) => {
472
- const func = IsProgrammer.decode(project)(importer);
473
- return ts.factory.createLogicalAnd(
474
- func(ts.factory.createElementAccessExpression(top, 0), entry[0], {
475
- ...explore,
476
- postfix: `${explore.postfix}[0]`,
477
- }),
478
- func(ts.factory.createElementAccessExpression(top, 1), entry[1], {
479
- ...explore,
480
- postfix: `${explore.postfix}[1]`,
481
- }),
482
- );
483
- },
484
- decoder: (input, array, explore) =>
485
- ts.factory.createNewExpression(
486
- ts.factory.createIdentifier("Map"),
487
- [TypeFactory.keyword("any"), TypeFactory.keyword("any")],
488
- [decode_array(config)(importer)(input, array, explore)],
489
- ),
490
- empty: ts.factory.createNewExpression(
491
- ts.factory.createIdentifier("Map"),
492
- [TypeFactory.keyword("any"), TypeFactory.keyword("any")],
493
- [],
494
- ),
495
- success: ts.factory.createTrue(),
496
- failure: (input, expected) =>
497
- create_throw_error(importer)(expected)(input),
498
- })([])(input, maps, explore),
499
- undefined,
500
- undefined,
501
- );
502
-
503
- const explore_objects =
504
- (config: FeatureProgrammer.IConfig) =>
505
- (importer: FunctionImporter) =>
506
- (
507
- input: ts.Expression,
508
- meta: Metadata,
509
- explore: FeatureProgrammer.IExplore,
510
- ) => {
511
- if (meta.objects.length === 1)
512
- return decode_object(importer)(input, meta.objects[0]!, explore);
513
-
514
- return ts.factory.createCallExpression(
515
- ts.factory.createIdentifier(
516
- importer.useLocal(`${PREFIX}u${meta.union_index!}`),
517
- ),
518
- undefined,
519
- FeatureProgrammer.argumentsArray(config)(explore)(input),
520
- );
521
- };
522
-
523
- const explore_arrays =
524
- (project: IProject) =>
525
- (config: FeatureProgrammer.IConfig) =>
526
- (importer: FunctionImporter) =>
527
- (
528
- input: ts.Expression,
529
- elements: MetadataArray[],
530
- explore: FeatureProgrammer.IExplore,
531
- ): ts.Expression =>
532
- explore_array_like_union_types(config)(importer)(
533
- UnionExplorer.array({
534
- checker: IsProgrammer.decode(project)(importer),
535
- decoder: decode_array(config)(importer),
536
- empty: ts.factory.createIdentifier("[]"),
537
- success: ts.factory.createTrue(),
538
- failure: (input, expected) =>
539
- create_throw_error(importer)(expected)(input),
540
- }),
541
- )(input, elements, explore);
542
-
543
- const explore_array_like_union_types =
544
- (config: FeatureProgrammer.IConfig) =>
545
- (importer: FunctionImporter) =>
546
- <T extends MetadataArray | MetadataTuple>(
547
- factory: (
548
- parameters: ts.ParameterDeclaration[],
549
- ) => (
550
- input: ts.Expression,
551
- elements: T[],
552
- explore: FeatureProgrammer.IExplore,
553
- ) => ts.ArrowFunction,
554
- ) =>
555
- (
556
- input: ts.Expression,
557
- elements: T[],
558
- explore: FeatureProgrammer.IExplore,
559
- ): ts.Expression => {
560
- const arrow =
561
- (parameters: ts.ParameterDeclaration[]) =>
562
- (explore: FeatureProgrammer.IExplore) =>
563
- (input: ts.Expression): ts.ArrowFunction =>
564
- factory(parameters)(input, elements, explore);
565
- if (elements.every((e) => e.type.recursive === false))
566
- ts.factory.createCallExpression(
567
- arrow([])(explore)(input),
568
- undefined,
569
- [],
570
- );
571
-
572
- explore = {
573
- ...explore,
574
- source: "function",
575
- from: "array",
576
- };
577
- return ts.factory.createCallExpression(
578
- ts.factory.createIdentifier(
579
- importer.emplaceUnion(
580
- config.prefix,
581
- elements.map((e) => e.type.name).join(" | "),
582
- () =>
583
- arrow(
584
- FeatureProgrammer.parameterDeclarations(config)(
585
- TypeFactory.keyword("any"),
586
- )(ts.factory.createIdentifier("input")),
587
- )({
588
- ...explore,
589
- postfix: "",
590
- })(ts.factory.createIdentifier("input")),
591
- ),
592
- ),
593
- undefined,
594
- FeatureProgrammer.argumentsArray(config)(explore)(input),
595
- );
596
- };
597
-
598
- /* -----------------------------------------------------------
599
- CONFIGURATIONS
600
- ----------------------------------------------------------- */
601
- const PREFIX = "$c";
602
-
603
- const configure =
604
- (rename: (str: string) => string) =>
605
- (project: IProject) =>
606
- (importer: FunctionImporter): FeatureProgrammer.IConfig => {
607
- const config: FeatureProgrammer.IConfig = {
608
- types: {
609
- input: (type, name) =>
610
- ts.factory.createTypeReferenceNode(
611
- name ?? TypeFactory.getFullName(project.checker)(type),
612
- ),
613
- output: (type, name) =>
614
- ts.factory.createTypeReferenceNode(
615
- returnType(rename)(
616
- name ?? TypeFactory.getFullName(project.checker)(type),
617
- ),
618
- ),
619
- },
620
- prefix: PREFIX,
621
- trace: false,
622
- path: false,
623
- initializer,
624
- decoder: () => decode(project)(config)(importer),
625
- objector: {
626
- checker: () => IsProgrammer.decode(project)(importer),
627
- decoder: () => decode_object(importer),
628
- joiner: NotationJoiner.object(rename),
629
- unionizer: decode_union_object(
630
- IsProgrammer.decode_object(project)(importer),
631
- )(decode_object(importer))((exp) => exp)((input, expected) =>
632
- create_throw_error(importer)(expected)(input),
633
- ),
634
- failure: (input, expected) =>
635
- create_throw_error(importer)(expected)(input),
636
- },
637
- generator: {
638
- arrays: () => write_array_functions(config)(importer),
639
- tuples: () => write_tuple_functions(project)(config)(importer),
640
- },
641
- };
642
- return config;
643
- };
644
-
645
- const initializer: FeatureProgrammer.IConfig["initializer"] =
646
- (project) => (importer) => (type) => {
647
- const collection = new MetadataCollection();
648
- const result = MetadataFactory.analyze(
649
- project.checker,
650
- project.context,
651
- )({
652
- escape: false,
653
- constant: true,
654
- absorb: true,
655
- })(collection)(type);
656
- if (result.success === false)
657
- throw TransformerError.from(`typia.misc.${importer.method}`)(
658
- result.errors,
659
- );
660
- return [collection, result.data];
661
- };
662
-
663
- const create_throw_error =
664
- (importer: FunctionImporter) =>
665
- (expected: string) =>
666
- (value: ts.Expression) =>
667
- ts.factory.createExpressionStatement(
668
- ts.factory.createCallExpression(
669
- importer.use("throws"),
670
- [],
671
- [
672
- ts.factory.createObjectLiteralExpression(
673
- [
674
- ts.factory.createPropertyAssignment(
675
- "expected",
676
- ts.factory.createStringLiteral(expected),
677
- ),
678
- ts.factory.createPropertyAssignment("value", value),
679
- ],
680
- true,
681
- ),
682
- ],
683
- ),
684
- );
685
- }
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 { StatementFactory } from "../../factories/StatementFactory";
8
+ import { TypeFactory } from "../../factories/TypeFactory";
9
+
10
+ import { Metadata } from "../../schemas/metadata/Metadata";
11
+ import { MetadataArray } from "../../schemas/metadata/MetadataArray";
12
+ import { MetadataTuple } from "../../schemas/metadata/MetadataTuple";
13
+ import { MetadataTupleType } from "../../schemas/metadata/MetadataTupleType";
14
+
15
+ import { IProject } from "../../transformers/IProject";
16
+ import { TransformerError } from "../../transformers/TransformerError";
17
+
18
+ import { StringUtil } from "../../utils/StringUtil";
19
+
20
+ import { FeatureProgrammer } from "../FeatureProgrammer";
21
+ import { IsProgrammer } from "../IsProgrammer";
22
+ import { FunctionImporter } from "../helpers/FunctionImporter";
23
+ import { NotationJoiner } from "../helpers/NotationJoiner";
24
+ import { UnionExplorer } from "../helpers/UnionExplorer";
25
+ import { decode_union_object } from "../internal/decode_union_object";
26
+ import { postfix_of_tuple } from "../internal/postfix_of_tuple";
27
+ import { wrap_metadata_rest_tuple } from "../internal/wrap_metadata_rest_tuple";
28
+
29
+ export namespace NotationGeneralProgrammer {
30
+ export const returnType =
31
+ (rename: (str: string) => string) => (type: string) =>
32
+ `typia.${StringUtil.capitalize(rename.name)}Case<${type}>`;
33
+
34
+ export const decompose = (props: {
35
+ rename: (str: string) => string;
36
+ validated: boolean;
37
+ project: IProject;
38
+ importer: FunctionImporter;
39
+ type: ts.Type;
40
+ name: string | undefined;
41
+ }): FeatureProgrammer.IDecomposed => {
42
+ const config = configure(props.rename)(props.project)(props.importer);
43
+ if (props.validated === false)
44
+ config.addition = (collection) =>
45
+ IsProgrammer.write_function_statements(props.project)(props.importer)(
46
+ collection,
47
+ );
48
+ const composed: FeatureProgrammer.IComposed = FeatureProgrammer.compose({
49
+ ...props,
50
+ config,
51
+ });
52
+ return {
53
+ functions: composed.functions,
54
+ statements: composed.statements,
55
+ arrow: ts.factory.createArrowFunction(
56
+ undefined,
57
+ undefined,
58
+ composed.parameters,
59
+ TypeFactory.keyword("void"),
60
+ undefined,
61
+ composed.body,
62
+ ),
63
+ };
64
+ };
65
+
66
+ export const write =
67
+ (rename: (str: string) => string) =>
68
+ (project: IProject) =>
69
+ (modulo: ts.LeftHandSideExpression) =>
70
+ (type: ts.Type, name?: string) => {
71
+ const importer: FunctionImporter = new FunctionImporter(modulo.getText());
72
+ const result: FeatureProgrammer.IDecomposed = decompose({
73
+ rename,
74
+ validated: true,
75
+ project,
76
+ importer,
77
+ type,
78
+ name,
79
+ });
80
+ return FeatureProgrammer.writeDecomposed({
81
+ importer,
82
+ modulo,
83
+ result,
84
+ });
85
+ };
86
+
87
+ const write_array_functions =
88
+ (config: FeatureProgrammer.IConfig) =>
89
+ (importer: FunctionImporter) =>
90
+ (collection: MetadataCollection): ts.VariableStatement[] =>
91
+ collection
92
+ .arrays()
93
+ .filter((a) => a.recursive)
94
+ .map((type, i) =>
95
+ StatementFactory.constant(
96
+ `${config.prefix}a${i}`,
97
+ ts.factory.createArrowFunction(
98
+ undefined,
99
+ undefined,
100
+ FeatureProgrammer.parameterDeclarations(config)(
101
+ TypeFactory.keyword("any"),
102
+ )(ts.factory.createIdentifier("input")),
103
+ TypeFactory.keyword("any"),
104
+ undefined,
105
+ decode_array_inline(config)(importer)(
106
+ ts.factory.createIdentifier("input"),
107
+ MetadataArray.create({
108
+ type,
109
+ tags: [],
110
+ }),
111
+ {
112
+ tracable: config.trace,
113
+ source: "function",
114
+ from: "array",
115
+ postfix: "",
116
+ },
117
+ ),
118
+ ),
119
+ ),
120
+ );
121
+
122
+ const write_tuple_functions =
123
+ (project: IProject) =>
124
+ (config: FeatureProgrammer.IConfig) =>
125
+ (importer: FunctionImporter) =>
126
+ (collection: MetadataCollection): ts.VariableStatement[] =>
127
+ collection
128
+ .tuples()
129
+ .filter((t) => t.recursive)
130
+ .map((tuple, i) =>
131
+ StatementFactory.constant(
132
+ `${config.prefix}t${i}`,
133
+ ts.factory.createArrowFunction(
134
+ undefined,
135
+ undefined,
136
+ FeatureProgrammer.parameterDeclarations(config)(
137
+ TypeFactory.keyword("any"),
138
+ )(ts.factory.createIdentifier("input")),
139
+ TypeFactory.keyword("any"),
140
+ undefined,
141
+ decode_tuple_inline(project)(config)(importer)(
142
+ ts.factory.createIdentifier("input"),
143
+ tuple,
144
+ {
145
+ tracable: config.trace,
146
+ source: "function",
147
+ from: "array",
148
+ postfix: "",
149
+ },
150
+ ),
151
+ ),
152
+ ),
153
+ );
154
+
155
+ /* -----------------------------------------------------------
156
+ DECODERS
157
+ ----------------------------------------------------------- */
158
+ const decode =
159
+ (project: IProject) =>
160
+ (config: FeatureProgrammer.IConfig) =>
161
+ (importer: FunctionImporter) =>
162
+ (
163
+ input: ts.Expression,
164
+ meta: Metadata,
165
+ explore: FeatureProgrammer.IExplore,
166
+ ): ts.Expression => {
167
+ // ANY TYPE
168
+ if (
169
+ meta.any ||
170
+ meta.arrays.some((a) => a.type.value.any) ||
171
+ meta.tuples.some(
172
+ (t) =>
173
+ !!t.type.elements.length && t.type.elements.every((e) => e.any),
174
+ )
175
+ )
176
+ return ts.factory.createCallExpression(importer.use("any"), undefined, [
177
+ input,
178
+ ]);
179
+
180
+ interface IUnion {
181
+ type: string;
182
+ is: () => ts.Expression;
183
+ value: () => ts.Expression;
184
+ }
185
+ const unions: IUnion[] = [];
186
+
187
+ //----
188
+ // LIST UP UNION TYPES
189
+ //----
190
+ // FUNCTIONAL
191
+ if (meta.functional)
192
+ unions.push({
193
+ type: "functional",
194
+ is: () =>
195
+ ts.factory.createStrictEquality(
196
+ ts.factory.createStringLiteral("function"),
197
+ ts.factory.createTypeOfExpression(input),
198
+ ),
199
+ value: () => ts.factory.createIdentifier("undefined"),
200
+ });
201
+
202
+ // TUPLES
203
+ for (const tuple of meta.tuples)
204
+ unions.push({
205
+ type: "tuple",
206
+ is: () =>
207
+ IsProgrammer.decode(project)(importer)(
208
+ input,
209
+ (() => {
210
+ const partial = Metadata.initialize();
211
+ partial.tuples.push(tuple);
212
+ return partial;
213
+ })(),
214
+ explore,
215
+ ),
216
+ value: () =>
217
+ decode_tuple(project)(config)(importer)(input, tuple, explore),
218
+ });
219
+
220
+ // ARRAYS
221
+ if (meta.arrays.length)
222
+ unions.push({
223
+ type: "array",
224
+ is: () => ExpressionFactory.isArray(input),
225
+ value: () =>
226
+ explore_arrays(project)(config)(importer)(input, meta.arrays, {
227
+ ...explore,
228
+ from: "array",
229
+ }),
230
+ });
231
+
232
+ // NATIVE TYPES
233
+ if (meta.sets.length)
234
+ unions.push({
235
+ type: "set",
236
+ is: () => ExpressionFactory.isInstanceOf("Set")(input),
237
+ value: () =>
238
+ explore_sets(project)(config)(importer)(input, meta.sets, {
239
+ ...explore,
240
+ from: "array",
241
+ }),
242
+ });
243
+ if (meta.maps.length)
244
+ unions.push({
245
+ type: "map",
246
+ is: () => ExpressionFactory.isInstanceOf("Map")(input),
247
+ value: () =>
248
+ explore_maps(project)(config)(importer)(input, meta.maps, {
249
+ ...explore,
250
+ from: "array",
251
+ }),
252
+ });
253
+ for (const native of meta.natives) {
254
+ if (native === "WeakSet" || native === "WeakMap") continue;
255
+ unions.push({
256
+ type: "native",
257
+ is: () => ExpressionFactory.isInstanceOf(native)(input),
258
+ value: () =>
259
+ native === "Boolean" || native === "Number" || native === "String"
260
+ ? ts.factory.createCallExpression(
261
+ IdentifierFactory.access(input)("valueOf"),
262
+ undefined,
263
+ undefined,
264
+ )
265
+ : decode_native(native)(input),
266
+ });
267
+ }
268
+
269
+ // OBJECTS
270
+ if (meta.objects.length)
271
+ unions.push({
272
+ type: "object",
273
+ is: () =>
274
+ ExpressionFactory.isObject({
275
+ checkNull: true,
276
+ checkArray: false,
277
+ })(input),
278
+ value: () =>
279
+ explore_objects(config)(importer)(input, meta, {
280
+ ...explore,
281
+ from: "object",
282
+ }),
283
+ });
284
+
285
+ // COMPOSITION
286
+ if (unions.length === 0) return input;
287
+ else if (unions.length === 1 && meta.size() === 1) {
288
+ const value: ts.Expression =
289
+ (meta.nullable || meta.isRequired() === false) && is_instance(meta)
290
+ ? ts.factory.createConditionalExpression(
291
+ input,
292
+ undefined,
293
+ unions[0]!.value(),
294
+ undefined,
295
+ input,
296
+ )
297
+ : unions[0]!.value();
298
+ return ts.factory.createAsExpression(value, TypeFactory.keyword("any"));
299
+ } else {
300
+ let last: ts.Expression = input;
301
+ for (const u of unions.reverse())
302
+ last = ts.factory.createConditionalExpression(
303
+ u.is(),
304
+ undefined,
305
+ u.value(),
306
+ undefined,
307
+ last,
308
+ );
309
+ return ts.factory.createAsExpression(last, TypeFactory.keyword("any"));
310
+ }
311
+ };
312
+
313
+ const decode_object = (importer: FunctionImporter) =>
314
+ FeatureProgrammer.decode_object({
315
+ trace: false,
316
+ path: false,
317
+ prefix: PREFIX,
318
+ })(importer);
319
+
320
+ const decode_array =
321
+ (config: FeatureProgrammer.IConfig) =>
322
+ (importer: FunctionImporter) =>
323
+ (
324
+ input: ts.Expression,
325
+ array: MetadataArray,
326
+ explore: FeatureProgrammer.IExplore,
327
+ ) =>
328
+ array.type.recursive
329
+ ? ts.factory.createCallExpression(
330
+ ts.factory.createIdentifier(
331
+ importer.useLocal(`${config.prefix}a${array.type.index}`),
332
+ ),
333
+ undefined,
334
+ FeatureProgrammer.argumentsArray(config)({
335
+ ...explore,
336
+ source: "function",
337
+ from: "array",
338
+ })(input),
339
+ )
340
+ : decode_array_inline(config)(importer)(input, array, explore);
341
+
342
+ const decode_array_inline =
343
+ (config: FeatureProgrammer.IConfig) =>
344
+ (importer: FunctionImporter) =>
345
+ (
346
+ input: ts.Expression,
347
+ array: MetadataArray,
348
+ explore: FeatureProgrammer.IExplore,
349
+ ) =>
350
+ FeatureProgrammer.decode_array(config)(importer)(NotationJoiner.array)(
351
+ input,
352
+ array,
353
+ explore,
354
+ );
355
+
356
+ const decode_tuple =
357
+ (project: IProject) =>
358
+ (config: FeatureProgrammer.IConfig) =>
359
+ (importer: FunctionImporter) =>
360
+ (
361
+ input: ts.Expression,
362
+ tuple: MetadataTuple,
363
+ explore: FeatureProgrammer.IExplore,
364
+ ): ts.Expression =>
365
+ tuple.type.recursive
366
+ ? ts.factory.createCallExpression(
367
+ ts.factory.createIdentifier(
368
+ importer.useLocal(`${config.prefix}t${tuple.type.index}`),
369
+ ),
370
+ undefined,
371
+ FeatureProgrammer.argumentsArray(config)({
372
+ ...explore,
373
+ source: "function",
374
+ })(input),
375
+ )
376
+ : decode_tuple_inline(project)(config)(importer)(
377
+ input,
378
+ tuple.type,
379
+ explore,
380
+ );
381
+
382
+ const decode_tuple_inline =
383
+ (project: IProject) =>
384
+ (config: FeatureProgrammer.IConfig) =>
385
+ (importer: FunctionImporter) =>
386
+ (
387
+ input: ts.Expression,
388
+ tuple: MetadataTupleType,
389
+ explore: FeatureProgrammer.IExplore,
390
+ ): ts.Expression => {
391
+ const children: ts.Expression[] = tuple.elements
392
+ .filter((m) => m.rest === null)
393
+ .map((elem, index) =>
394
+ decode(project)(config)(importer)(
395
+ ts.factory.createElementAccessExpression(input, index),
396
+ elem,
397
+ {
398
+ ...explore,
399
+ from: "array",
400
+ postfix: explore.postfix.length
401
+ ? `${postfix_of_tuple(explore.postfix)}[${index}]"`
402
+ : `"[${index}]"`,
403
+ },
404
+ ),
405
+ );
406
+ const rest = (() => {
407
+ if (tuple.elements.length === 0) return null;
408
+
409
+ const last: Metadata = tuple.elements.at(-1)!;
410
+ const rest: Metadata | null = last.rest;
411
+ if (rest === null) return null;
412
+
413
+ return decode(project)(config)(importer)(
414
+ ts.factory.createCallExpression(
415
+ IdentifierFactory.access(input)("slice"),
416
+ undefined,
417
+ [ExpressionFactory.number(tuple.elements.length - 1)],
418
+ ),
419
+ wrap_metadata_rest_tuple(tuple.elements.at(-1)!.rest!),
420
+ {
421
+ ...explore,
422
+ start: tuple.elements.length - 1,
423
+ },
424
+ );
425
+ })();
426
+ return NotationJoiner.tuple(children, rest);
427
+ };
428
+
429
+ /* -----------------------------------------------------------
430
+ NATIVE CLASSES
431
+ ----------------------------------------------------------- */
432
+ const decode_native = (type: string) => (input: ts.Expression) =>
433
+ type === "Date"
434
+ ? ts.factory.createNewExpression(
435
+ ts.factory.createIdentifier(type),
436
+ undefined,
437
+ [input],
438
+ )
439
+ : input;
440
+
441
+ /* -----------------------------------------------------------
442
+ EXPLORERS FOR UNION TYPES
443
+ ----------------------------------------------------------- */
444
+ const explore_sets =
445
+ (project: IProject) =>
446
+ (config: FeatureProgrammer.IConfig) =>
447
+ (importer: FunctionImporter) =>
448
+ (
449
+ input: ts.Expression,
450
+ sets: Metadata[],
451
+ explore: FeatureProgrammer.IExplore,
452
+ ): ts.Expression =>
453
+ ts.factory.createCallExpression(
454
+ UnionExplorer.set({
455
+ checker: IsProgrammer.decode(project)(importer),
456
+ decoder: (input, array, explore) =>
457
+ ts.factory.createNewExpression(
458
+ ts.factory.createIdentifier("Set"),
459
+ [TypeFactory.keyword("any")],
460
+ [decode_array(config)(importer)(input, array, explore)],
461
+ ),
462
+ empty: ts.factory.createNewExpression(
463
+ ts.factory.createIdentifier("Set"),
464
+ [TypeFactory.keyword("any")],
465
+ [],
466
+ ),
467
+ success: ts.factory.createTrue(),
468
+ failure: (input, expected) =>
469
+ create_throw_error(importer)(expected)(input),
470
+ })([])(input, sets, explore),
471
+ undefined,
472
+ undefined,
473
+ );
474
+
475
+ const explore_maps =
476
+ (project: IProject) =>
477
+ (config: FeatureProgrammer.IConfig) =>
478
+ (importer: FunctionImporter) =>
479
+ (
480
+ input: ts.Expression,
481
+ maps: Metadata.Entry[],
482
+ explore: FeatureProgrammer.IExplore,
483
+ ): ts.Expression =>
484
+ ts.factory.createCallExpression(
485
+ UnionExplorer.map({
486
+ checker: (top, entry, explore) => {
487
+ const func = IsProgrammer.decode(project)(importer);
488
+ return ts.factory.createLogicalAnd(
489
+ func(ts.factory.createElementAccessExpression(top, 0), entry[0], {
490
+ ...explore,
491
+ postfix: `${explore.postfix}[0]`,
492
+ }),
493
+ func(ts.factory.createElementAccessExpression(top, 1), entry[1], {
494
+ ...explore,
495
+ postfix: `${explore.postfix}[1]`,
496
+ }),
497
+ );
498
+ },
499
+ decoder: (input, array, explore) =>
500
+ ts.factory.createNewExpression(
501
+ ts.factory.createIdentifier("Map"),
502
+ [TypeFactory.keyword("any"), TypeFactory.keyword("any")],
503
+ [decode_array(config)(importer)(input, array, explore)],
504
+ ),
505
+ empty: ts.factory.createNewExpression(
506
+ ts.factory.createIdentifier("Map"),
507
+ [TypeFactory.keyword("any"), TypeFactory.keyword("any")],
508
+ [],
509
+ ),
510
+ success: ts.factory.createTrue(),
511
+ failure: (input, expected) =>
512
+ create_throw_error(importer)(expected)(input),
513
+ })([])(input, maps, explore),
514
+ undefined,
515
+ undefined,
516
+ );
517
+
518
+ const explore_objects =
519
+ (config: FeatureProgrammer.IConfig) =>
520
+ (importer: FunctionImporter) =>
521
+ (
522
+ input: ts.Expression,
523
+ meta: Metadata,
524
+ explore: FeatureProgrammer.IExplore,
525
+ ) => {
526
+ if (meta.objects.length === 1)
527
+ return decode_object(importer)(input, meta.objects[0]!, explore);
528
+
529
+ return ts.factory.createCallExpression(
530
+ ts.factory.createIdentifier(
531
+ importer.useLocal(`${PREFIX}u${meta.union_index!}`),
532
+ ),
533
+ undefined,
534
+ FeatureProgrammer.argumentsArray(config)(explore)(input),
535
+ );
536
+ };
537
+
538
+ const explore_arrays =
539
+ (project: IProject) =>
540
+ (config: FeatureProgrammer.IConfig) =>
541
+ (importer: FunctionImporter) =>
542
+ (
543
+ input: ts.Expression,
544
+ elements: MetadataArray[],
545
+ explore: FeatureProgrammer.IExplore,
546
+ ): ts.Expression =>
547
+ explore_array_like_union_types(config)(importer)(
548
+ UnionExplorer.array({
549
+ checker: IsProgrammer.decode(project)(importer),
550
+ decoder: decode_array(config)(importer),
551
+ empty: ts.factory.createIdentifier("[]"),
552
+ success: ts.factory.createTrue(),
553
+ failure: (input, expected) =>
554
+ create_throw_error(importer)(expected)(input),
555
+ }),
556
+ )(input, elements, explore);
557
+
558
+ const explore_array_like_union_types =
559
+ (config: FeatureProgrammer.IConfig) =>
560
+ (importer: FunctionImporter) =>
561
+ <T extends MetadataArray | MetadataTuple>(
562
+ factory: (
563
+ parameters: ts.ParameterDeclaration[],
564
+ ) => (
565
+ input: ts.Expression,
566
+ elements: T[],
567
+ explore: FeatureProgrammer.IExplore,
568
+ ) => ts.ArrowFunction,
569
+ ) =>
570
+ (
571
+ input: ts.Expression,
572
+ elements: T[],
573
+ explore: FeatureProgrammer.IExplore,
574
+ ): ts.Expression => {
575
+ const arrow =
576
+ (parameters: ts.ParameterDeclaration[]) =>
577
+ (explore: FeatureProgrammer.IExplore) =>
578
+ (input: ts.Expression): ts.ArrowFunction =>
579
+ factory(parameters)(input, elements, explore);
580
+ if (elements.every((e) => e.type.recursive === false))
581
+ ts.factory.createCallExpression(
582
+ arrow([])(explore)(input),
583
+ undefined,
584
+ [],
585
+ );
586
+
587
+ explore = {
588
+ ...explore,
589
+ source: "function",
590
+ from: "array",
591
+ };
592
+ return ts.factory.createCallExpression(
593
+ ts.factory.createIdentifier(
594
+ importer.emplaceUnion(
595
+ config.prefix,
596
+ elements.map((e) => e.type.name).join(" | "),
597
+ () =>
598
+ arrow(
599
+ FeatureProgrammer.parameterDeclarations(config)(
600
+ TypeFactory.keyword("any"),
601
+ )(ts.factory.createIdentifier("input")),
602
+ )({
603
+ ...explore,
604
+ postfix: "",
605
+ })(ts.factory.createIdentifier("input")),
606
+ ),
607
+ ),
608
+ undefined,
609
+ FeatureProgrammer.argumentsArray(config)(explore)(input),
610
+ );
611
+ };
612
+
613
+ /* -----------------------------------------------------------
614
+ CONFIGURATIONS
615
+ ----------------------------------------------------------- */
616
+ const PREFIX = "$c";
617
+
618
+ const configure =
619
+ (rename: (str: string) => string) =>
620
+ (project: IProject) =>
621
+ (importer: FunctionImporter): FeatureProgrammer.IConfig => {
622
+ const config: FeatureProgrammer.IConfig = {
623
+ types: {
624
+ input: (type, name) =>
625
+ ts.factory.createTypeReferenceNode(
626
+ name ?? TypeFactory.getFullName(project.checker)(type),
627
+ ),
628
+ output: (type, name) =>
629
+ ts.factory.createTypeReferenceNode(
630
+ returnType(rename)(
631
+ name ?? TypeFactory.getFullName(project.checker)(type),
632
+ ),
633
+ ),
634
+ },
635
+ prefix: PREFIX,
636
+ trace: false,
637
+ path: false,
638
+ initializer,
639
+ decoder: () => decode(project)(config)(importer),
640
+ objector: {
641
+ checker: () => IsProgrammer.decode(project)(importer),
642
+ decoder: () => decode_object(importer),
643
+ joiner: NotationJoiner.object(rename),
644
+ unionizer: decode_union_object(
645
+ IsProgrammer.decode_object(project)(importer),
646
+ )(decode_object(importer))((exp) => exp)((input, expected) =>
647
+ create_throw_error(importer)(expected)(input),
648
+ ),
649
+ failure: (input, expected) =>
650
+ create_throw_error(importer)(expected)(input),
651
+ },
652
+ generator: {
653
+ arrays: () => write_array_functions(config)(importer),
654
+ tuples: () => write_tuple_functions(project)(config)(importer),
655
+ },
656
+ };
657
+ return config;
658
+ };
659
+
660
+ const initializer: FeatureProgrammer.IConfig["initializer"] =
661
+ (project) => (importer) => (type) => {
662
+ const collection = new MetadataCollection();
663
+ const result = MetadataFactory.analyze(
664
+ project.checker,
665
+ project.context,
666
+ )({
667
+ escape: false,
668
+ constant: true,
669
+ absorb: true,
670
+ })(collection)(type);
671
+ if (result.success === false)
672
+ throw TransformerError.from(`typia.misc.${importer.method}`)(
673
+ result.errors,
674
+ );
675
+ return [collection, result.data];
676
+ };
677
+
678
+ const create_throw_error =
679
+ (importer: FunctionImporter) =>
680
+ (expected: string) =>
681
+ (value: ts.Expression) =>
682
+ ts.factory.createExpressionStatement(
683
+ ts.factory.createCallExpression(
684
+ importer.use("throws"),
685
+ [],
686
+ [
687
+ ts.factory.createObjectLiteralExpression(
688
+ [
689
+ ts.factory.createPropertyAssignment(
690
+ "expected",
691
+ ts.factory.createStringLiteral(expected),
692
+ ),
693
+ ts.factory.createPropertyAssignment("value", value),
694
+ ],
695
+ true,
696
+ ),
697
+ ],
698
+ ),
699
+ );
700
+
701
+ const is_instance = (meta: Metadata): boolean =>
702
+ !!meta.objects.length ||
703
+ !!meta.arrays.length ||
704
+ !!meta.tuples.length ||
705
+ !!meta.sets.length ||
706
+ !!meta.maps.length ||
707
+ !!meta.natives.length ||
708
+ (meta.rest !== null && is_instance(meta.rest));
709
+ }