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,560 +1,560 @@
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 { FeatureProgrammer } from "../FeatureProgrammer";
19
- import { IsProgrammer } from "../IsProgrammer";
20
- import { FunctionImporter } from "../helpers/FunctionImporter";
21
- import { PruneJoiner } from "../helpers/PruneJoiner";
22
- import { UnionExplorer } from "../helpers/UnionExplorer";
23
- import { decode_union_object } from "../internal/decode_union_object";
24
- import { postfix_of_tuple } from "../internal/postfix_of_tuple";
25
- import { wrap_metadata_rest_tuple } from "../internal/wrap_metadata_rest_tuple";
26
-
27
- export namespace MiscPruneProgrammer {
28
- export const decompose = (props: {
29
- validated: boolean;
30
- project: IProject;
31
- importer: FunctionImporter;
32
- type: ts.Type;
33
- name?: string;
34
- }): FeatureProgrammer.IDecomposed => {
35
- const config = configure(props.project)(props.importer);
36
- if (props.validated === false)
37
- config.addition = (collection) =>
38
- IsProgrammer.write_function_statements(props.project)(props.importer)(
39
- collection,
40
- );
41
- const composed: FeatureProgrammer.IComposed = FeatureProgrammer.compose({
42
- ...props,
43
- config,
44
- });
45
- return {
46
- functions: composed.functions,
47
- statements: composed.statements,
48
- arrow: ts.factory.createArrowFunction(
49
- undefined,
50
- undefined,
51
- composed.parameters,
52
- composed.response,
53
- undefined,
54
- composed.body,
55
- ),
56
- };
57
- };
58
-
59
- export const write =
60
- (project: IProject) =>
61
- (modulo: ts.LeftHandSideExpression) =>
62
- (type: ts.Type, name?: string): ts.CallExpression => {
63
- const importer: FunctionImporter = new FunctionImporter(modulo.getText());
64
- const result: FeatureProgrammer.IDecomposed = decompose({
65
- validated: false,
66
- project,
67
- importer,
68
- type,
69
- name,
70
- });
71
- return FeatureProgrammer.writeDecomposed({
72
- modulo,
73
- importer,
74
- result,
75
- });
76
- };
77
-
78
- const write_array_functions =
79
- (config: FeatureProgrammer.IConfig) =>
80
- (importer: FunctionImporter) =>
81
- (collection: MetadataCollection): ts.VariableStatement[] =>
82
- collection
83
- .arrays()
84
- .filter((a) => a.recursive)
85
- .map((type, i) =>
86
- StatementFactory.constant(
87
- `${config.prefix}a${i}`,
88
- ts.factory.createArrowFunction(
89
- undefined,
90
- undefined,
91
- FeatureProgrammer.parameterDeclarations(config)(
92
- TypeFactory.keyword("any"),
93
- )(ts.factory.createIdentifier("input")),
94
- TypeFactory.keyword("any"),
95
- undefined,
96
- decode_array_inline(config)(importer)(
97
- ts.factory.createIdentifier("input"),
98
- MetadataArray.create({
99
- type,
100
- tags: [],
101
- }),
102
- {
103
- tracable: config.trace,
104
- source: "function",
105
- from: "array",
106
- postfix: "",
107
- },
108
- ),
109
- ),
110
- ),
111
- );
112
-
113
- const write_tuple_functions =
114
- (project: IProject) =>
115
- (config: FeatureProgrammer.IConfig) =>
116
- (importer: FunctionImporter) =>
117
- (collection: MetadataCollection): ts.VariableStatement[] =>
118
- collection
119
- .tuples()
120
- .filter((t) => t.recursive)
121
- .map((tuple, i) =>
122
- StatementFactory.constant(
123
- `${config.prefix}t${i}`,
124
- ts.factory.createArrowFunction(
125
- undefined,
126
- undefined,
127
- FeatureProgrammer.parameterDeclarations(config)(
128
- TypeFactory.keyword("any"),
129
- )(ts.factory.createIdentifier("input")),
130
- TypeFactory.keyword("any"),
131
- undefined,
132
- decode_tuple_inline(project)(config)(importer)(
133
- ts.factory.createIdentifier("input"),
134
- tuple,
135
- {
136
- tracable: config.trace,
137
- source: "function",
138
- from: "array",
139
- postfix: "",
140
- },
141
- ),
142
- ),
143
- ),
144
- );
145
-
146
- /* -----------------------------------------------------------
147
- DECODERS
148
- ----------------------------------------------------------- */
149
- const decode =
150
- (project: IProject) =>
151
- (config: FeatureProgrammer.IConfig) =>
152
- (importer: FunctionImporter) =>
153
- (
154
- input: ts.Expression,
155
- meta: Metadata,
156
- explore: FeatureProgrammer.IExplore,
157
- ): ts.ConciseBody => {
158
- if (filter(meta) === false) return ts.factory.createBlock([]);
159
-
160
- interface IUnion {
161
- type: string;
162
- is: () => ts.Expression;
163
- value: () => ts.Expression | ts.Block | ts.ReturnStatement;
164
- }
165
- const unions: IUnion[] = [];
166
-
167
- //----
168
- // LIST UP UNION TYPES
169
- //----
170
- // TUPLES
171
- for (const tuple of meta.tuples.filter((tuple) =>
172
- tuple.type.elements.some((e) => filter(e.rest ?? e)),
173
- ))
174
- unions.push({
175
- type: "tuple",
176
- is: () =>
177
- IsProgrammer.decode(project)(importer)(
178
- input,
179
- (() => {
180
- const partial = Metadata.initialize();
181
- partial.tuples.push(tuple);
182
- return partial;
183
- })(),
184
- explore,
185
- ),
186
- value: () =>
187
- decode_tuple(project)(config)(importer)(input, tuple, explore),
188
- });
189
-
190
- // ARRAYS
191
- if (meta.arrays.filter((a) => filter(a.type.value)).length)
192
- unions.push({
193
- type: "array",
194
- is: () => ExpressionFactory.isArray(input),
195
- value: () =>
196
- explore_arrays(project)(config)(importer)(input, meta.arrays, {
197
- ...explore,
198
- from: "array",
199
- }),
200
- });
201
-
202
- // BUILT-IN CLASSES
203
- if (meta.natives.length)
204
- for (const native of meta.natives)
205
- unions.push({
206
- type: "native",
207
- is: () => ExpressionFactory.isInstanceOf(native)(input),
208
- value: () => ts.factory.createReturnStatement(),
209
- });
210
- if (meta.sets.length)
211
- unions.push({
212
- type: "set",
213
- is: () => ExpressionFactory.isInstanceOf("Set")(input),
214
- value: () => ts.factory.createReturnStatement(),
215
- });
216
- if (meta.maps.length)
217
- unions.push({
218
- type: "map",
219
- is: () => ExpressionFactory.isInstanceOf("Map")(input),
220
- value: () => ts.factory.createReturnStatement(),
221
- });
222
-
223
- // OBJECTS
224
- if (meta.objects.length)
225
- unions.push({
226
- type: "object",
227
- is: () =>
228
- ExpressionFactory.isObject({
229
- checkNull: true,
230
- checkArray: false,
231
- })(input),
232
- value: () =>
233
- explore_objects(config)(importer)(input, meta, {
234
- ...explore,
235
- from: "object",
236
- }),
237
- });
238
-
239
- //----
240
- // STATEMENTS
241
- //----
242
- const converter = (v: ts.Expression | ts.Block | ts.ReturnStatement) =>
243
- ts.isReturnStatement(v) || ts.isBlock(v)
244
- ? v
245
- : ts.factory.createExpressionStatement(v);
246
-
247
- const statements: ts.Statement[] = unions.map((u) =>
248
- ts.factory.createIfStatement(u.is(), converter(u.value())),
249
- );
250
- return ts.factory.createBlock(statements, true);
251
- };
252
-
253
- const decode_object = (importer: FunctionImporter) =>
254
- FeatureProgrammer.decode_object({
255
- trace: false,
256
- path: false,
257
- prefix: PREFIX,
258
- })(importer);
259
-
260
- const decode_array =
261
- (config: FeatureProgrammer.IConfig) =>
262
- (importer: FunctionImporter) =>
263
- (
264
- input: ts.Expression,
265
- array: MetadataArray,
266
- explore: FeatureProgrammer.IExplore,
267
- ) =>
268
- array.type.recursive
269
- ? ts.factory.createCallExpression(
270
- ts.factory.createIdentifier(
271
- importer.useLocal(`${config.prefix}a${array.type.index}`),
272
- ),
273
- undefined,
274
- FeatureProgrammer.argumentsArray(config)({
275
- ...explore,
276
- source: "function",
277
- from: "array",
278
- })(input),
279
- )
280
- : decode_array_inline(config)(importer)(input, array, explore);
281
-
282
- const decode_array_inline =
283
- (config: FeatureProgrammer.IConfig) =>
284
- (importer: FunctionImporter) =>
285
- (
286
- input: ts.Expression,
287
- array: MetadataArray,
288
- explore: FeatureProgrammer.IExplore,
289
- ): ts.Expression =>
290
- FeatureProgrammer.decode_array(config)(importer)(PruneJoiner.array)(
291
- input,
292
- array,
293
- explore,
294
- );
295
-
296
- const decode_tuple =
297
- (project: IProject) =>
298
- (config: FeatureProgrammer.IConfig) =>
299
- (importer: FunctionImporter) =>
300
- (
301
- input: ts.Expression,
302
- tuple: MetadataTuple,
303
- explore: FeatureProgrammer.IExplore,
304
- ): ts.Expression | ts.Block =>
305
- tuple.type.recursive
306
- ? ts.factory.createCallExpression(
307
- ts.factory.createIdentifier(
308
- importer.useLocal(`${config.prefix}t${tuple.type.index}`),
309
- ),
310
- undefined,
311
- FeatureProgrammer.argumentsArray(config)({
312
- ...explore,
313
- source: "function",
314
- })(input),
315
- )
316
- : decode_tuple_inline(project)(config)(importer)(
317
- input,
318
- tuple.type,
319
- explore,
320
- );
321
-
322
- const decode_tuple_inline =
323
- (project: IProject) =>
324
- (config: FeatureProgrammer.IConfig) =>
325
- (importer: FunctionImporter) =>
326
- (
327
- input: ts.Expression,
328
- tuple: MetadataTupleType,
329
- explore: FeatureProgrammer.IExplore,
330
- ): ts.Block => {
331
- const children: ts.ConciseBody[] = tuple.elements
332
- .map((elem, index) => [elem, index] as const)
333
- .filter(([elem]) => filter(elem) && elem.rest === null)
334
- .map(([elem, index]) =>
335
- decode(project)(config)(importer)(
336
- ts.factory.createElementAccessExpression(input, index),
337
- elem,
338
- {
339
- ...explore,
340
- from: "array",
341
- postfix: explore.postfix.length
342
- ? `${postfix_of_tuple(explore.postfix)}[${index}]"`
343
- : `"[${index}]"`,
344
- },
345
- ),
346
- );
347
- const rest = (() => {
348
- if (tuple.elements.length === 0) return null;
349
-
350
- const last: Metadata = tuple.elements.at(-1)!;
351
- const rest: Metadata | null = last.rest;
352
- if (rest === null || filter(rest) === false) return null;
353
-
354
- return decode(project)(config)(importer)(
355
- ts.factory.createCallExpression(
356
- IdentifierFactory.access(input)("slice"),
357
- undefined,
358
- [ExpressionFactory.number(tuple.elements.length - 1)],
359
- ),
360
- wrap_metadata_rest_tuple(tuple.elements.at(-1)!.rest!),
361
- {
362
- ...explore,
363
- start: tuple.elements.length - 1,
364
- },
365
- );
366
- })();
367
- return PruneJoiner.tuple(children, rest);
368
- };
369
-
370
- /* -----------------------------------------------------------
371
- UNION TYPE EXPLORERS
372
- ----------------------------------------------------------- */
373
- const explore_objects =
374
- (config: FeatureProgrammer.IConfig) =>
375
- (importer: FunctionImporter) =>
376
- (
377
- input: ts.Expression,
378
- meta: Metadata,
379
- explore: FeatureProgrammer.IExplore,
380
- ) => {
381
- if (meta.objects.length === 1)
382
- return decode_object(importer)(input, meta.objects[0]!, explore);
383
-
384
- return ts.factory.createCallExpression(
385
- ts.factory.createIdentifier(
386
- importer.useLocal(`${PREFIX}u${meta.union_index!}`),
387
- ),
388
- undefined,
389
- FeatureProgrammer.argumentsArray(config)(explore)(input),
390
- );
391
- };
392
-
393
- const explore_arrays =
394
- (project: IProject) =>
395
- (config: FeatureProgrammer.IConfig) =>
396
- (importer: FunctionImporter) =>
397
- (
398
- input: ts.Expression,
399
- elements: MetadataArray[],
400
- explore: FeatureProgrammer.IExplore,
401
- ): ts.Expression =>
402
- explore_array_like_union_types(config)(importer)(
403
- UnionExplorer.array({
404
- checker: IsProgrammer.decode(project)(importer),
405
- decoder: decode_array(config)(importer),
406
- empty: ts.factory.createStringLiteral("[]"),
407
- success: ts.factory.createTrue(),
408
- failure: (input, expected) =>
409
- create_throw_error(importer)(expected)(input),
410
- }),
411
- )(input, elements, explore);
412
-
413
- const explore_array_like_union_types =
414
- (config: FeatureProgrammer.IConfig) =>
415
- (importer: FunctionImporter) =>
416
- <T extends MetadataArray | MetadataTuple>(
417
- factory: (
418
- parameters: ts.ParameterDeclaration[],
419
- ) => (
420
- input: ts.Expression,
421
- elements: T[],
422
- explore: FeatureProgrammer.IExplore,
423
- ) => ts.ArrowFunction,
424
- ) =>
425
- (
426
- input: ts.Expression,
427
- elements: T[],
428
- explore: FeatureProgrammer.IExplore,
429
- ): ts.Expression => {
430
- const arrow =
431
- (parameters: ts.ParameterDeclaration[]) =>
432
- (explore: FeatureProgrammer.IExplore) =>
433
- (input: ts.Expression): ts.ArrowFunction =>
434
- factory(parameters)(input, elements, explore);
435
- if (elements.every((e) => e.type.recursive === false))
436
- ts.factory.createCallExpression(
437
- arrow([])(explore)(input),
438
- undefined,
439
- [],
440
- );
441
-
442
- explore = {
443
- ...explore,
444
- source: "function",
445
- from: "array",
446
- };
447
- return ts.factory.createCallExpression(
448
- ts.factory.createIdentifier(
449
- importer.emplaceUnion(
450
- config.prefix,
451
- elements.map((e) => e.type.name).join(" | "),
452
- () =>
453
- arrow(
454
- FeatureProgrammer.parameterDeclarations(config)(
455
- TypeFactory.keyword("any"),
456
- )(ts.factory.createIdentifier("input")),
457
- )({
458
- ...explore,
459
- postfix: "",
460
- })(ts.factory.createIdentifier("input")),
461
- ),
462
- ),
463
- undefined,
464
- FeatureProgrammer.argumentsArray(config)(explore)(input),
465
- );
466
- };
467
-
468
- // @todo -> must filter out recursive visit
469
- const filter = (meta: Metadata): boolean =>
470
- meta.any === false &&
471
- (meta.objects.length !== 0 ||
472
- meta.tuples.some(
473
- (t) =>
474
- !!t.type.elements.length &&
475
- t.type.elements.some((e) => filter(e.rest ?? e)),
476
- ) ||
477
- meta.arrays.some((e) => filter(e.type.value)));
478
-
479
- /* -----------------------------------------------------------
480
- CONFIGURATIONS
481
- ----------------------------------------------------------- */
482
- const PREFIX = "$p";
483
-
484
- const configure =
485
- (project: IProject) =>
486
- (importer: FunctionImporter): FeatureProgrammer.IConfig => {
487
- const config: FeatureProgrammer.IConfig = {
488
- types: {
489
- input: (type, name) =>
490
- ts.factory.createTypeReferenceNode(
491
- name ?? TypeFactory.getFullName(project.checker)(type),
492
- ),
493
- output: () => TypeFactory.keyword("void"),
494
- },
495
- prefix: PREFIX,
496
- trace: false,
497
- path: false,
498
- initializer,
499
- decoder: () => decode(project)(config)(importer),
500
- objector: {
501
- checker: () => IsProgrammer.decode(project)(importer),
502
- decoder: () => decode_object(importer),
503
- joiner: PruneJoiner.object,
504
- unionizer: decode_union_object(
505
- IsProgrammer.decode_object(project)(importer),
506
- )(decode_object(importer))((exp) => exp)((value, expected) =>
507
- create_throw_error(importer)(expected)(value),
508
- ),
509
- failure: (input, expected) =>
510
- create_throw_error(importer)(expected)(input),
511
- },
512
- generator: {
513
- arrays: () => write_array_functions(config)(importer),
514
- tuples: () => write_tuple_functions(project)(config)(importer),
515
- },
516
- };
517
- return config;
518
- };
519
-
520
- const initializer: FeatureProgrammer.IConfig["initializer"] =
521
- (project) => (importer) => (type) => {
522
- const collection = new MetadataCollection();
523
- const result = MetadataFactory.analyze(
524
- project.checker,
525
- project.context,
526
- )({
527
- escape: false,
528
- constant: true,
529
- absorb: true,
530
- })(collection)(type);
531
- if (result.success === false)
532
- throw TransformerError.from(`typia.misc.${importer.method}`)(
533
- result.errors,
534
- );
535
- return [collection, result.data];
536
- };
537
-
538
- const create_throw_error =
539
- (importer: FunctionImporter) =>
540
- (expected: string) =>
541
- (value: ts.Expression) =>
542
- ts.factory.createExpressionStatement(
543
- ts.factory.createCallExpression(
544
- importer.use("throws"),
545
- [],
546
- [
547
- ts.factory.createObjectLiteralExpression(
548
- [
549
- ts.factory.createPropertyAssignment(
550
- "expected",
551
- ts.factory.createStringLiteral(expected),
552
- ),
553
- ts.factory.createPropertyAssignment("value", value),
554
- ],
555
- true,
556
- ),
557
- ],
558
- ),
559
- );
560
- }
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 { FeatureProgrammer } from "../FeatureProgrammer";
19
+ import { IsProgrammer } from "../IsProgrammer";
20
+ import { FunctionImporter } from "../helpers/FunctionImporter";
21
+ import { PruneJoiner } from "../helpers/PruneJoiner";
22
+ import { UnionExplorer } from "../helpers/UnionExplorer";
23
+ import { decode_union_object } from "../internal/decode_union_object";
24
+ import { postfix_of_tuple } from "../internal/postfix_of_tuple";
25
+ import { wrap_metadata_rest_tuple } from "../internal/wrap_metadata_rest_tuple";
26
+
27
+ export namespace MiscPruneProgrammer {
28
+ export const decompose = (props: {
29
+ validated: boolean;
30
+ project: IProject;
31
+ importer: FunctionImporter;
32
+ type: ts.Type;
33
+ name: string | undefined;
34
+ }): FeatureProgrammer.IDecomposed => {
35
+ const config = configure(props.project)(props.importer);
36
+ if (props.validated === false)
37
+ config.addition = (collection) =>
38
+ IsProgrammer.write_function_statements(props.project)(props.importer)(
39
+ collection,
40
+ );
41
+ const composed: FeatureProgrammer.IComposed = FeatureProgrammer.compose({
42
+ ...props,
43
+ config,
44
+ });
45
+ return {
46
+ functions: composed.functions,
47
+ statements: composed.statements,
48
+ arrow: ts.factory.createArrowFunction(
49
+ undefined,
50
+ undefined,
51
+ composed.parameters,
52
+ composed.response,
53
+ undefined,
54
+ composed.body,
55
+ ),
56
+ };
57
+ };
58
+
59
+ export const write =
60
+ (project: IProject) =>
61
+ (modulo: ts.LeftHandSideExpression) =>
62
+ (type: ts.Type, name?: string): ts.CallExpression => {
63
+ const importer: FunctionImporter = new FunctionImporter(modulo.getText());
64
+ const result: FeatureProgrammer.IDecomposed = decompose({
65
+ validated: false,
66
+ project,
67
+ importer,
68
+ type,
69
+ name,
70
+ });
71
+ return FeatureProgrammer.writeDecomposed({
72
+ modulo,
73
+ importer,
74
+ result,
75
+ });
76
+ };
77
+
78
+ const write_array_functions =
79
+ (config: FeatureProgrammer.IConfig) =>
80
+ (importer: FunctionImporter) =>
81
+ (collection: MetadataCollection): ts.VariableStatement[] =>
82
+ collection
83
+ .arrays()
84
+ .filter((a) => a.recursive)
85
+ .map((type, i) =>
86
+ StatementFactory.constant(
87
+ `${config.prefix}a${i}`,
88
+ ts.factory.createArrowFunction(
89
+ undefined,
90
+ undefined,
91
+ FeatureProgrammer.parameterDeclarations(config)(
92
+ TypeFactory.keyword("any"),
93
+ )(ts.factory.createIdentifier("input")),
94
+ TypeFactory.keyword("any"),
95
+ undefined,
96
+ decode_array_inline(config)(importer)(
97
+ ts.factory.createIdentifier("input"),
98
+ MetadataArray.create({
99
+ type,
100
+ tags: [],
101
+ }),
102
+ {
103
+ tracable: config.trace,
104
+ source: "function",
105
+ from: "array",
106
+ postfix: "",
107
+ },
108
+ ),
109
+ ),
110
+ ),
111
+ );
112
+
113
+ const write_tuple_functions =
114
+ (project: IProject) =>
115
+ (config: FeatureProgrammer.IConfig) =>
116
+ (importer: FunctionImporter) =>
117
+ (collection: MetadataCollection): ts.VariableStatement[] =>
118
+ collection
119
+ .tuples()
120
+ .filter((t) => t.recursive)
121
+ .map((tuple, i) =>
122
+ StatementFactory.constant(
123
+ `${config.prefix}t${i}`,
124
+ ts.factory.createArrowFunction(
125
+ undefined,
126
+ undefined,
127
+ FeatureProgrammer.parameterDeclarations(config)(
128
+ TypeFactory.keyword("any"),
129
+ )(ts.factory.createIdentifier("input")),
130
+ TypeFactory.keyword("any"),
131
+ undefined,
132
+ decode_tuple_inline(project)(config)(importer)(
133
+ ts.factory.createIdentifier("input"),
134
+ tuple,
135
+ {
136
+ tracable: config.trace,
137
+ source: "function",
138
+ from: "array",
139
+ postfix: "",
140
+ },
141
+ ),
142
+ ),
143
+ ),
144
+ );
145
+
146
+ /* -----------------------------------------------------------
147
+ DECODERS
148
+ ----------------------------------------------------------- */
149
+ const decode =
150
+ (project: IProject) =>
151
+ (config: FeatureProgrammer.IConfig) =>
152
+ (importer: FunctionImporter) =>
153
+ (
154
+ input: ts.Expression,
155
+ meta: Metadata,
156
+ explore: FeatureProgrammer.IExplore,
157
+ ): ts.ConciseBody => {
158
+ if (filter(meta) === false) return ts.factory.createBlock([]);
159
+
160
+ interface IUnion {
161
+ type: string;
162
+ is: () => ts.Expression;
163
+ value: () => ts.Expression | ts.Block | ts.ReturnStatement;
164
+ }
165
+ const unions: IUnion[] = [];
166
+
167
+ //----
168
+ // LIST UP UNION TYPES
169
+ //----
170
+ // TUPLES
171
+ for (const tuple of meta.tuples.filter((tuple) =>
172
+ tuple.type.elements.some((e) => filter(e.rest ?? e)),
173
+ ))
174
+ unions.push({
175
+ type: "tuple",
176
+ is: () =>
177
+ IsProgrammer.decode(project)(importer)(
178
+ input,
179
+ (() => {
180
+ const partial = Metadata.initialize();
181
+ partial.tuples.push(tuple);
182
+ return partial;
183
+ })(),
184
+ explore,
185
+ ),
186
+ value: () =>
187
+ decode_tuple(project)(config)(importer)(input, tuple, explore),
188
+ });
189
+
190
+ // ARRAYS
191
+ if (meta.arrays.filter((a) => filter(a.type.value)).length)
192
+ unions.push({
193
+ type: "array",
194
+ is: () => ExpressionFactory.isArray(input),
195
+ value: () =>
196
+ explore_arrays(project)(config)(importer)(input, meta.arrays, {
197
+ ...explore,
198
+ from: "array",
199
+ }),
200
+ });
201
+
202
+ // BUILT-IN CLASSES
203
+ if (meta.natives.length)
204
+ for (const native of meta.natives)
205
+ unions.push({
206
+ type: "native",
207
+ is: () => ExpressionFactory.isInstanceOf(native)(input),
208
+ value: () => ts.factory.createReturnStatement(),
209
+ });
210
+ if (meta.sets.length)
211
+ unions.push({
212
+ type: "set",
213
+ is: () => ExpressionFactory.isInstanceOf("Set")(input),
214
+ value: () => ts.factory.createReturnStatement(),
215
+ });
216
+ if (meta.maps.length)
217
+ unions.push({
218
+ type: "map",
219
+ is: () => ExpressionFactory.isInstanceOf("Map")(input),
220
+ value: () => ts.factory.createReturnStatement(),
221
+ });
222
+
223
+ // OBJECTS
224
+ if (meta.objects.length)
225
+ unions.push({
226
+ type: "object",
227
+ is: () =>
228
+ ExpressionFactory.isObject({
229
+ checkNull: true,
230
+ checkArray: false,
231
+ })(input),
232
+ value: () =>
233
+ explore_objects(config)(importer)(input, meta, {
234
+ ...explore,
235
+ from: "object",
236
+ }),
237
+ });
238
+
239
+ //----
240
+ // STATEMENTS
241
+ //----
242
+ const converter = (v: ts.Expression | ts.Block | ts.ReturnStatement) =>
243
+ ts.isReturnStatement(v) || ts.isBlock(v)
244
+ ? v
245
+ : ts.factory.createExpressionStatement(v);
246
+
247
+ const statements: ts.Statement[] = unions.map((u) =>
248
+ ts.factory.createIfStatement(u.is(), converter(u.value())),
249
+ );
250
+ return ts.factory.createBlock(statements, true);
251
+ };
252
+
253
+ const decode_object = (importer: FunctionImporter) =>
254
+ FeatureProgrammer.decode_object({
255
+ trace: false,
256
+ path: false,
257
+ prefix: PREFIX,
258
+ })(importer);
259
+
260
+ const decode_array =
261
+ (config: FeatureProgrammer.IConfig) =>
262
+ (importer: FunctionImporter) =>
263
+ (
264
+ input: ts.Expression,
265
+ array: MetadataArray,
266
+ explore: FeatureProgrammer.IExplore,
267
+ ) =>
268
+ array.type.recursive
269
+ ? ts.factory.createCallExpression(
270
+ ts.factory.createIdentifier(
271
+ importer.useLocal(`${config.prefix}a${array.type.index}`),
272
+ ),
273
+ undefined,
274
+ FeatureProgrammer.argumentsArray(config)({
275
+ ...explore,
276
+ source: "function",
277
+ from: "array",
278
+ })(input),
279
+ )
280
+ : decode_array_inline(config)(importer)(input, array, explore);
281
+
282
+ const decode_array_inline =
283
+ (config: FeatureProgrammer.IConfig) =>
284
+ (importer: FunctionImporter) =>
285
+ (
286
+ input: ts.Expression,
287
+ array: MetadataArray,
288
+ explore: FeatureProgrammer.IExplore,
289
+ ): ts.Expression =>
290
+ FeatureProgrammer.decode_array(config)(importer)(PruneJoiner.array)(
291
+ input,
292
+ array,
293
+ explore,
294
+ );
295
+
296
+ const decode_tuple =
297
+ (project: IProject) =>
298
+ (config: FeatureProgrammer.IConfig) =>
299
+ (importer: FunctionImporter) =>
300
+ (
301
+ input: ts.Expression,
302
+ tuple: MetadataTuple,
303
+ explore: FeatureProgrammer.IExplore,
304
+ ): ts.Expression | ts.Block =>
305
+ tuple.type.recursive
306
+ ? ts.factory.createCallExpression(
307
+ ts.factory.createIdentifier(
308
+ importer.useLocal(`${config.prefix}t${tuple.type.index}`),
309
+ ),
310
+ undefined,
311
+ FeatureProgrammer.argumentsArray(config)({
312
+ ...explore,
313
+ source: "function",
314
+ })(input),
315
+ )
316
+ : decode_tuple_inline(project)(config)(importer)(
317
+ input,
318
+ tuple.type,
319
+ explore,
320
+ );
321
+
322
+ const decode_tuple_inline =
323
+ (project: IProject) =>
324
+ (config: FeatureProgrammer.IConfig) =>
325
+ (importer: FunctionImporter) =>
326
+ (
327
+ input: ts.Expression,
328
+ tuple: MetadataTupleType,
329
+ explore: FeatureProgrammer.IExplore,
330
+ ): ts.Block => {
331
+ const children: ts.ConciseBody[] = tuple.elements
332
+ .map((elem, index) => [elem, index] as const)
333
+ .filter(([elem]) => filter(elem) && elem.rest === null)
334
+ .map(([elem, index]) =>
335
+ decode(project)(config)(importer)(
336
+ ts.factory.createElementAccessExpression(input, index),
337
+ elem,
338
+ {
339
+ ...explore,
340
+ from: "array",
341
+ postfix: explore.postfix.length
342
+ ? `${postfix_of_tuple(explore.postfix)}[${index}]"`
343
+ : `"[${index}]"`,
344
+ },
345
+ ),
346
+ );
347
+ const rest = (() => {
348
+ if (tuple.elements.length === 0) return null;
349
+
350
+ const last: Metadata = tuple.elements.at(-1)!;
351
+ const rest: Metadata | null = last.rest;
352
+ if (rest === null || filter(rest) === false) return null;
353
+
354
+ return decode(project)(config)(importer)(
355
+ ts.factory.createCallExpression(
356
+ IdentifierFactory.access(input)("slice"),
357
+ undefined,
358
+ [ExpressionFactory.number(tuple.elements.length - 1)],
359
+ ),
360
+ wrap_metadata_rest_tuple(tuple.elements.at(-1)!.rest!),
361
+ {
362
+ ...explore,
363
+ start: tuple.elements.length - 1,
364
+ },
365
+ );
366
+ })();
367
+ return PruneJoiner.tuple(children, rest);
368
+ };
369
+
370
+ /* -----------------------------------------------------------
371
+ UNION TYPE EXPLORERS
372
+ ----------------------------------------------------------- */
373
+ const explore_objects =
374
+ (config: FeatureProgrammer.IConfig) =>
375
+ (importer: FunctionImporter) =>
376
+ (
377
+ input: ts.Expression,
378
+ meta: Metadata,
379
+ explore: FeatureProgrammer.IExplore,
380
+ ) => {
381
+ if (meta.objects.length === 1)
382
+ return decode_object(importer)(input, meta.objects[0]!, explore);
383
+
384
+ return ts.factory.createCallExpression(
385
+ ts.factory.createIdentifier(
386
+ importer.useLocal(`${PREFIX}u${meta.union_index!}`),
387
+ ),
388
+ undefined,
389
+ FeatureProgrammer.argumentsArray(config)(explore)(input),
390
+ );
391
+ };
392
+
393
+ const explore_arrays =
394
+ (project: IProject) =>
395
+ (config: FeatureProgrammer.IConfig) =>
396
+ (importer: FunctionImporter) =>
397
+ (
398
+ input: ts.Expression,
399
+ elements: MetadataArray[],
400
+ explore: FeatureProgrammer.IExplore,
401
+ ): ts.Expression =>
402
+ explore_array_like_union_types(config)(importer)(
403
+ UnionExplorer.array({
404
+ checker: IsProgrammer.decode(project)(importer),
405
+ decoder: decode_array(config)(importer),
406
+ empty: ts.factory.createStringLiteral("[]"),
407
+ success: ts.factory.createTrue(),
408
+ failure: (input, expected) =>
409
+ create_throw_error(importer)(expected)(input),
410
+ }),
411
+ )(input, elements, explore);
412
+
413
+ const explore_array_like_union_types =
414
+ (config: FeatureProgrammer.IConfig) =>
415
+ (importer: FunctionImporter) =>
416
+ <T extends MetadataArray | MetadataTuple>(
417
+ factory: (
418
+ parameters: ts.ParameterDeclaration[],
419
+ ) => (
420
+ input: ts.Expression,
421
+ elements: T[],
422
+ explore: FeatureProgrammer.IExplore,
423
+ ) => ts.ArrowFunction,
424
+ ) =>
425
+ (
426
+ input: ts.Expression,
427
+ elements: T[],
428
+ explore: FeatureProgrammer.IExplore,
429
+ ): ts.Expression => {
430
+ const arrow =
431
+ (parameters: ts.ParameterDeclaration[]) =>
432
+ (explore: FeatureProgrammer.IExplore) =>
433
+ (input: ts.Expression): ts.ArrowFunction =>
434
+ factory(parameters)(input, elements, explore);
435
+ if (elements.every((e) => e.type.recursive === false))
436
+ ts.factory.createCallExpression(
437
+ arrow([])(explore)(input),
438
+ undefined,
439
+ [],
440
+ );
441
+
442
+ explore = {
443
+ ...explore,
444
+ source: "function",
445
+ from: "array",
446
+ };
447
+ return ts.factory.createCallExpression(
448
+ ts.factory.createIdentifier(
449
+ importer.emplaceUnion(
450
+ config.prefix,
451
+ elements.map((e) => e.type.name).join(" | "),
452
+ () =>
453
+ arrow(
454
+ FeatureProgrammer.parameterDeclarations(config)(
455
+ TypeFactory.keyword("any"),
456
+ )(ts.factory.createIdentifier("input")),
457
+ )({
458
+ ...explore,
459
+ postfix: "",
460
+ })(ts.factory.createIdentifier("input")),
461
+ ),
462
+ ),
463
+ undefined,
464
+ FeatureProgrammer.argumentsArray(config)(explore)(input),
465
+ );
466
+ };
467
+
468
+ // @todo -> must filter out recursive visit
469
+ const filter = (meta: Metadata): boolean =>
470
+ meta.any === false &&
471
+ (meta.objects.length !== 0 ||
472
+ meta.tuples.some(
473
+ (t) =>
474
+ !!t.type.elements.length &&
475
+ t.type.elements.some((e) => filter(e.rest ?? e)),
476
+ ) ||
477
+ meta.arrays.some((e) => filter(e.type.value)));
478
+
479
+ /* -----------------------------------------------------------
480
+ CONFIGURATIONS
481
+ ----------------------------------------------------------- */
482
+ const PREFIX = "$p";
483
+
484
+ const configure =
485
+ (project: IProject) =>
486
+ (importer: FunctionImporter): FeatureProgrammer.IConfig => {
487
+ const config: FeatureProgrammer.IConfig = {
488
+ types: {
489
+ input: (type, name) =>
490
+ ts.factory.createTypeReferenceNode(
491
+ name ?? TypeFactory.getFullName(project.checker)(type),
492
+ ),
493
+ output: () => TypeFactory.keyword("void"),
494
+ },
495
+ prefix: PREFIX,
496
+ trace: false,
497
+ path: false,
498
+ initializer,
499
+ decoder: () => decode(project)(config)(importer),
500
+ objector: {
501
+ checker: () => IsProgrammer.decode(project)(importer),
502
+ decoder: () => decode_object(importer),
503
+ joiner: PruneJoiner.object,
504
+ unionizer: decode_union_object(
505
+ IsProgrammer.decode_object(project)(importer),
506
+ )(decode_object(importer))((exp) => exp)((value, expected) =>
507
+ create_throw_error(importer)(expected)(value),
508
+ ),
509
+ failure: (input, expected) =>
510
+ create_throw_error(importer)(expected)(input),
511
+ },
512
+ generator: {
513
+ arrays: () => write_array_functions(config)(importer),
514
+ tuples: () => write_tuple_functions(project)(config)(importer),
515
+ },
516
+ };
517
+ return config;
518
+ };
519
+
520
+ const initializer: FeatureProgrammer.IConfig["initializer"] =
521
+ (project) => (importer) => (type) => {
522
+ const collection = new MetadataCollection();
523
+ const result = MetadataFactory.analyze(
524
+ project.checker,
525
+ project.context,
526
+ )({
527
+ escape: false,
528
+ constant: true,
529
+ absorb: true,
530
+ })(collection)(type);
531
+ if (result.success === false)
532
+ throw TransformerError.from(`typia.misc.${importer.method}`)(
533
+ result.errors,
534
+ );
535
+ return [collection, result.data];
536
+ };
537
+
538
+ const create_throw_error =
539
+ (importer: FunctionImporter) =>
540
+ (expected: string) =>
541
+ (value: ts.Expression) =>
542
+ ts.factory.createExpressionStatement(
543
+ ts.factory.createCallExpression(
544
+ importer.use("throws"),
545
+ [],
546
+ [
547
+ ts.factory.createObjectLiteralExpression(
548
+ [
549
+ ts.factory.createPropertyAssignment(
550
+ "expected",
551
+ ts.factory.createStringLiteral(expected),
552
+ ),
553
+ ts.factory.createPropertyAssignment("value", value),
554
+ ],
555
+ true,
556
+ ),
557
+ ],
558
+ ),
559
+ );
560
+ }