typia 7.0.0-dev.20240924 → 7.0.0-dev.20240928

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 (54) hide show
  1. package/lib/index.mjs +1 -0
  2. package/lib/index.mjs.map +1 -1
  3. package/lib/programmers/AssertProgrammer.d.ts +1 -1
  4. package/lib/programmers/AssertProgrammer.js +169 -127
  5. package/lib/programmers/AssertProgrammer.js.map +1 -1
  6. package/lib/programmers/CheckerProgrammer.d.ts +70 -15
  7. package/lib/programmers/CheckerProgrammer.js +998 -638
  8. package/lib/programmers/CheckerProgrammer.js.map +1 -1
  9. package/lib/programmers/FeatureProgrammer.d.ts +5 -1
  10. package/lib/programmers/FeatureProgrammer.js +15 -15
  11. package/lib/programmers/FeatureProgrammer.js.map +1 -1
  12. package/lib/programmers/IsProgrammer.d.ts +25 -4
  13. package/lib/programmers/IsProgrammer.js +54 -39
  14. package/lib/programmers/IsProgrammer.js.map +1 -1
  15. package/lib/programmers/ValidateProgrammer.js +110 -97
  16. package/lib/programmers/ValidateProgrammer.js.map +1 -1
  17. package/lib/programmers/helpers/UnionExplorer.d.ts +1 -1
  18. package/lib/programmers/json/JsonStringifyProgrammer.js +68 -35
  19. package/lib/programmers/json/JsonStringifyProgrammer.js.map +1 -1
  20. package/lib/programmers/llm/LlmApplicationProgrammer.js +16 -2
  21. package/lib/programmers/llm/LlmApplicationProgrammer.js.map +1 -1
  22. package/lib/programmers/misc/MiscCloneProgrammer.js +62 -15
  23. package/lib/programmers/misc/MiscCloneProgrammer.js.map +1 -1
  24. package/lib/programmers/misc/MiscPruneProgrammer.js +39 -11
  25. package/lib/programmers/misc/MiscPruneProgrammer.js.map +1 -1
  26. package/lib/programmers/notations/NotationGeneralProgrammer.js +62 -15
  27. package/lib/programmers/notations/NotationGeneralProgrammer.js.map +1 -1
  28. package/lib/programmers/protobuf/ProtobufEncodeProgrammer.js +17 -3
  29. package/lib/programmers/protobuf/ProtobufEncodeProgrammer.js.map +1 -1
  30. package/lib/tags/Example.d.ts +14 -0
  31. package/lib/tags/Example.js +3 -0
  32. package/lib/tags/Example.js.map +1 -0
  33. package/lib/tags/Examples.d.ts +10 -0
  34. package/lib/tags/Examples.js +3 -0
  35. package/lib/tags/Examples.js.map +1 -0
  36. package/lib/tags/index.d.ts +2 -0
  37. package/lib/tags/index.js +2 -0
  38. package/lib/tags/index.js.map +1 -1
  39. package/package.json +2 -2
  40. package/src/programmers/AssertProgrammer.ts +185 -143
  41. package/src/programmers/CheckerProgrammer.ts +1380 -998
  42. package/src/programmers/FeatureProgrammer.ts +37 -31
  43. package/src/programmers/IsProgrammer.ts +94 -66
  44. package/src/programmers/ValidateProgrammer.ts +149 -137
  45. package/src/programmers/helpers/UnionExplorer.ts +1 -1
  46. package/src/programmers/json/JsonStringifyProgrammer.ts +56 -35
  47. package/src/programmers/llm/LlmApplicationProgrammer.ts +51 -32
  48. package/src/programmers/misc/MiscCloneProgrammer.ts +64 -26
  49. package/src/programmers/misc/MiscPruneProgrammer.ts +34 -13
  50. package/src/programmers/notations/NotationGeneralProgrammer.ts +64 -26
  51. package/src/programmers/protobuf/ProtobufEncodeProgrammer.ts +16 -9
  52. package/src/tags/Example.ts +17 -0
  53. package/src/tags/Examples.ts +16 -0
  54. package/src/tags/index.ts +20 -18
@@ -46,28 +46,28 @@ export namespace CheckerProgrammer {
46
46
  addition?: () => ts.Statement[];
47
47
  decoder?: () => FeatureProgrammer.Decoder<Metadata, ts.Expression>;
48
48
  combiner: IConfig.Combiner;
49
- atomist: (
50
- explore: IExplore,
51
- ) => (check: ICheckEntry) => (input: ts.Expression) => ts.Expression;
49
+ atomist: (props: {
50
+ entry: ICheckEntry;
51
+ input: ts.Expression;
52
+ explore: IExplore;
53
+ }) => ts.Expression;
52
54
  joiner: IConfig.IJoiner;
53
55
  success: ts.Expression;
54
56
  }
55
57
  export namespace IConfig {
56
58
  export interface Combiner {
57
- (explorer: IExplore): {
58
- (logic: "and" | "or"): {
59
- (
60
- input: ts.Expression,
61
- binaries: IBinary[],
62
- expected: string,
63
- ): ts.Expression;
64
- };
65
- };
59
+ (props: {
60
+ explore: IExplore;
61
+ logic: "and" | "or";
62
+ input: ts.Expression;
63
+ binaries: IBinary[];
64
+ expected: string;
65
+ }): ts.Expression;
66
66
  }
67
67
  export interface IJoiner {
68
68
  object(props: {
69
69
  input: ts.Expression;
70
- entries: IExpressionEntry[];
70
+ entries: IExpressionEntry<ts.Expression>[];
71
71
  }): ts.Expression;
72
72
  array(props: {
73
73
  input: ts.Expression;
@@ -75,22 +75,21 @@ export namespace CheckerProgrammer {
75
75
  }): ts.Expression;
76
76
  tuple?: undefined | ((exprs: ts.Expression[]) => ts.Expression);
77
77
 
78
- failure(
79
- value: ts.Expression,
80
- expected: string,
81
- explore?: undefined | FeatureProgrammer.IExplore,
82
- ): ts.Expression;
78
+ failure(props: {
79
+ input: ts.Expression;
80
+ expected: string;
81
+ explore?: undefined | FeatureProgrammer.IExplore;
82
+ }): ts.Expression;
83
83
  is?(expression: ts.Expression): ts.Expression;
84
84
  required?(exp: ts.Expression): ts.Expression;
85
85
  full?:
86
86
  | undefined
87
- | ((
88
- condition: ts.Expression,
89
- ) => (
90
- input: ts.Expression,
91
- expected: string,
92
- explore: IExplore,
93
- ) => ts.Expression);
87
+ | ((props: {
88
+ condition: ts.Expression;
89
+ input: ts.Expression;
90
+ expected: string;
91
+ explore: IExplore;
92
+ }) => ts.Expression);
94
93
  }
95
94
  }
96
95
  export type IExplore = FeatureProgrammer.IExplore;
@@ -109,1080 +108,1463 @@ export namespace CheckerProgrammer {
109
108
  importer: FunctionImporter;
110
109
  type: ts.Type;
111
110
  name: string | undefined;
112
- }) =>
111
+ }): FeatureProgrammer.IComposed =>
113
112
  FeatureProgrammer.compose({
114
113
  ...props,
115
- config: configure(props.context)(props.config)(props.importer),
114
+ config: configure(props),
116
115
  });
117
116
 
118
- export const write =
119
- (project: ITypiaContext) =>
120
- (config: IConfig) =>
121
- (importer: FunctionImporter) =>
122
- FeatureProgrammer.write(project)(configure(project)(config)(importer))(
123
- importer,
124
- );
117
+ export const write = (props: {
118
+ context: ITypiaContext;
119
+ config: IConfig;
120
+ importer: FunctionImporter;
121
+ type: ts.Type;
122
+ name?: string;
123
+ }): ts.ArrowFunction =>
124
+ FeatureProgrammer.write(props.context)(configure(props))(props.importer)(
125
+ props.type,
126
+ props.name,
127
+ );
125
128
 
126
- export const write_object_functions =
127
- (project: ITypiaContext) =>
128
- (config: IConfig) =>
129
- (importer: FunctionImporter) =>
130
- FeatureProgrammer.write_object_functions(
131
- configure(project)(config)(importer),
132
- )(importer);
129
+ export const write_object_functions = (props: {
130
+ context: ITypiaContext;
131
+ config: IConfig;
132
+ importer: FunctionImporter;
133
+ collection: MetadataCollection;
134
+ }): ts.VariableStatement[] =>
135
+ FeatureProgrammer.write_object_functions({
136
+ config: configure(props),
137
+ importer: props.importer,
138
+ collection: props.collection,
139
+ });
133
140
 
134
- export const write_union_functions =
135
- (project: ITypiaContext) =>
136
- (config: IConfig) =>
137
- (importer: FunctionImporter) =>
138
- FeatureProgrammer.write_union_functions(
139
- configure(project)({ ...config, numeric: false })(importer),
140
- );
141
+ export const write_union_functions = (props: {
142
+ context: ITypiaContext;
143
+ config: IConfig;
144
+ importer: FunctionImporter;
145
+ collection: MetadataCollection;
146
+ }): ts.VariableStatement[] =>
147
+ FeatureProgrammer.write_union_functions(
148
+ configure({
149
+ context: props.context,
150
+ config: {
151
+ ...props.config,
152
+ numeric: false,
153
+ },
154
+ importer: props.importer,
155
+ }),
156
+ )(props.collection);
141
157
 
142
- export const write_array_functions =
143
- (project: ITypiaContext) =>
144
- (config: IConfig) =>
145
- (importer: FunctionImporter) =>
146
- (collection: MetadataCollection): ts.VariableStatement[] =>
147
- collection
148
- .arrays()
149
- .filter((a) => a.recursive)
150
- .map((type, i) =>
151
- StatementFactory.constant(
152
- `${config.prefix}a${i}`,
153
- ts.factory.createArrowFunction(
154
- undefined,
155
- undefined,
156
- FeatureProgrammer.parameterDeclarations(config)(
157
- TypeFactory.keyword("any"),
158
- )(ts.factory.createIdentifier("input")),
158
+ export const write_array_functions = (props: {
159
+ context: ITypiaContext;
160
+ config: IConfig;
161
+ importer: FunctionImporter;
162
+ collection: MetadataCollection;
163
+ }): ts.VariableStatement[] =>
164
+ props.collection
165
+ .arrays()
166
+ .filter((a) => a.recursive)
167
+ .map((type, i) =>
168
+ StatementFactory.constant(
169
+ `${props.config.prefix}a${i}`,
170
+ ts.factory.createArrowFunction(
171
+ undefined,
172
+ undefined,
173
+ FeatureProgrammer.parameterDeclarations(props.config)(
159
174
  TypeFactory.keyword("any"),
160
- undefined,
161
- decode_array_inline(project)(config)(importer)(
162
- ts.factory.createIdentifier("input"),
163
- MetadataArray.create({
164
- type,
165
- tags: [],
166
- }),
167
- {
168
- tracable: config.trace,
169
- source: "function",
170
- from: "array",
171
- postfix: "",
172
- },
173
- ),
174
- ),
175
+ )(ts.factory.createIdentifier("input")),
176
+ TypeFactory.keyword("any"),
177
+ undefined,
178
+ decode_array_inline({
179
+ ...props,
180
+ input: ts.factory.createIdentifier("input"),
181
+ array: MetadataArray.create({
182
+ type,
183
+ tags: [],
184
+ }),
185
+ explore: {
186
+ tracable: props.config.trace,
187
+ source: "function",
188
+ from: "array",
189
+ postfix: "",
190
+ },
191
+ }),
175
192
  ),
176
- );
193
+ ),
194
+ );
177
195
 
178
- export const write_tuple_functions =
179
- (project: ITypiaContext) =>
180
- (config: IConfig) =>
181
- (importer: FunctionImporter) =>
182
- (collection: MetadataCollection): ts.VariableStatement[] =>
183
- collection
184
- .tuples()
185
- .filter((t) => t.recursive)
186
- .map((tuple, i) =>
187
- StatementFactory.constant(
188
- `${config.prefix}t${i}`,
189
- ts.factory.createArrowFunction(
190
- undefined,
191
- undefined,
192
- FeatureProgrammer.parameterDeclarations(config)(
193
- TypeFactory.keyword("any"),
194
- )(ts.factory.createIdentifier("input")),
196
+ export const write_tuple_functions = (props: {
197
+ context: ITypiaContext;
198
+ config: IConfig;
199
+ importer: FunctionImporter;
200
+ collection: MetadataCollection;
201
+ }): ts.VariableStatement[] =>
202
+ props.collection
203
+ .tuples()
204
+ .filter((t) => t.recursive)
205
+ .map((tuple, i) =>
206
+ StatementFactory.constant(
207
+ `${props.config.prefix}t${i}`,
208
+ ts.factory.createArrowFunction(
209
+ undefined,
210
+ undefined,
211
+ FeatureProgrammer.parameterDeclarations(props.config)(
195
212
  TypeFactory.keyword("any"),
196
- undefined,
197
- decode_tuple_inline(project)(config)(importer)(
198
- ts.factory.createIdentifier("input"),
199
- tuple,
200
- {
201
- tracable: config.trace,
202
- source: "function",
203
- from: "array",
204
- postfix: "",
205
- },
206
- ),
207
- ),
213
+ )(ts.factory.createIdentifier("input")),
214
+ TypeFactory.keyword("any"),
215
+ undefined,
216
+ decode_tuple_inline({
217
+ config: props.config,
218
+ context: props.context,
219
+ importer: props.importer,
220
+ input: ts.factory.createIdentifier("input"),
221
+ tuple,
222
+ explore: {
223
+ tracable: props.config.trace,
224
+ source: "function",
225
+ from: "array",
226
+ postfix: "",
227
+ },
228
+ }),
208
229
  ),
209
- );
230
+ ),
231
+ );
210
232
 
211
- const configure =
212
- (project: ITypiaContext) =>
213
- (config: IConfig) =>
214
- (importer: FunctionImporter): FeatureProgrammer.IConfig => ({
215
- types: {
216
- input: () => TypeFactory.keyword("any"),
217
- output: (type, name) =>
218
- ts.factory.createTypePredicateNode(
219
- undefined,
220
- "input",
221
- ts.factory.createTypeReferenceNode(
222
- name ?? TypeFactory.getFullName(project.checker)(type),
223
- ),
233
+ const configure = (props: {
234
+ context: ITypiaContext;
235
+ config: IConfig;
236
+ importer: FunctionImporter;
237
+ }): FeatureProgrammer.IConfig => ({
238
+ types: {
239
+ input: () => TypeFactory.keyword("any"),
240
+ output: (type, name) =>
241
+ ts.factory.createTypePredicateNode(
242
+ undefined,
243
+ "input",
244
+ ts.factory.createTypeReferenceNode(
245
+ name ?? TypeFactory.getFullName(props.context.checker)(type),
224
246
  ),
225
- },
226
- trace: config.trace,
227
- path: config.path,
228
- prefix: config.prefix,
229
- initializer: (project) => (importer) => (type) => {
230
- const collection: MetadataCollection = new MetadataCollection();
231
- const result = MetadataFactory.analyze({
232
- checker: project.checker,
233
- transformer: project.transformer,
234
- options: {
235
- escape: false,
236
- constant: true,
237
- absorb: true,
238
- },
239
- collection,
240
- type,
241
- });
242
- if (result.success === false)
243
- throw TransformerError.from(`typia.${importer.method}`)(
244
- result.errors,
245
- );
246
- return [collection, result.data];
247
- },
248
- addition: config.addition,
249
- decoder: () => config.decoder?.() ?? decode(project)(config)(importer),
250
- objector: {
251
- checker: () => config.decoder?.() ?? decode(project)(config)(importer),
252
- decoder: () => decode_object(config)(importer),
253
- joiner: config.joiner.object,
254
- unionizer: config.equals
255
- ? decode_union_object(decode_object(config)(importer))(
256
- (input, obj, explore) =>
257
- decode_object(config)(importer)(input, obj, {
258
- ...explore,
259
- tracable: true,
247
+ ),
248
+ },
249
+ trace: props.config.trace,
250
+ path: props.config.path,
251
+ prefix: props.config.prefix,
252
+ initializer: (context) => (importer) => (type) => {
253
+ const collection: MetadataCollection = new MetadataCollection();
254
+ const result = MetadataFactory.analyze({
255
+ checker: context.checker,
256
+ transformer: context.transformer,
257
+ options: {
258
+ escape: false,
259
+ constant: true,
260
+ absorb: true,
261
+ },
262
+ collection,
263
+ type,
264
+ });
265
+ if (result.success === false)
266
+ throw TransformerError.from(`typia.${importer.method}`)(result.errors);
267
+ return [collection, result.data];
268
+ },
269
+ addition: props.config.addition,
270
+ decoder: () =>
271
+ props.config.decoder
272
+ ? (input, metadata, explore) =>
273
+ props.config.decoder!()(input, metadata, explore)
274
+ : (input, metadata, explore) =>
275
+ decode({
276
+ context: props.context,
277
+ config: props.config,
278
+ importer: props.importer,
279
+ input,
280
+ metadata,
281
+ explore,
282
+ }),
283
+ objector: {
284
+ checker: () => (input, metadata, explore) =>
285
+ props.config.decoder?.()(input, metadata, explore) ??
286
+ decode({
287
+ context: props.context,
288
+ config: props.config,
289
+ importer: props.importer,
290
+ input,
291
+ metadata,
292
+ explore,
293
+ }),
294
+ decoder: () => (input, object, explore) =>
295
+ decode_object({
296
+ config: props.config,
297
+ importer: props.importer,
298
+ input,
299
+ object,
300
+ explore,
301
+ }),
302
+ joiner: props.config.joiner.object,
303
+ unionizer: props.config.equals
304
+ ? decode_union_object((input, object, explore) =>
305
+ decode_object({
306
+ config: props.config,
307
+ importer: props.importer,
308
+ object,
309
+ input,
310
+ explore,
311
+ }),
312
+ )((input, object, explore) =>
313
+ decode_object({
314
+ config: props.config,
315
+ importer: props.importer,
316
+ input,
317
+ object,
318
+ explore: {
319
+ ...explore,
320
+ tracable: true,
321
+ },
322
+ }),
323
+ )(props.config.joiner.is ?? ((expr) => expr))((input, expected) =>
324
+ ts.factory.createReturnStatement(
325
+ props.config.joiner.failure({
326
+ input,
327
+ expected,
328
+ }),
329
+ ),
330
+ )
331
+ : (input, targets, explore) =>
332
+ props.config.combiner({
333
+ explore,
334
+ logic: "or",
335
+ input,
336
+ binaries: targets.map((object) => ({
337
+ expression: decode_object({
338
+ config: props.config,
339
+ importer: props.importer,
340
+ input,
341
+ object,
342
+ explore,
260
343
  }),
261
- )(config.joiner.is ?? ((expr) => expr))((value, expected) =>
262
- ts.factory.createReturnStatement(
263
- config.joiner.failure(value, expected),
264
- ),
344
+ combined: true,
345
+ })),
346
+ expected: `(${targets.map((t) => t.name).join(" | ")})`,
347
+ }),
348
+ failure: (input, expected) =>
349
+ ts.factory.createReturnStatement(
350
+ props.config.joiner.failure({
351
+ input,
352
+ expected,
353
+ }),
354
+ ),
355
+ is: props.config.joiner.is,
356
+ required: props.config.joiner.required,
357
+ full: props.config.joiner.full
358
+ ? (condition) => (input, expected, explore) =>
359
+ props.config.joiner.full!({
360
+ condition,
361
+ input,
362
+ expected,
363
+ explore,
364
+ })
365
+ : undefined,
366
+ type: TypeFactory.keyword("boolean"),
367
+ },
368
+ generator: {
369
+ unions: props.config.numeric
370
+ ? () =>
371
+ FeatureProgrammer.write_union_functions(
372
+ configure({
373
+ ...props,
374
+ config: {
375
+ ...props.config,
376
+ numeric: false,
377
+ },
378
+ }),
265
379
  )
266
- : (input, targets, explore) =>
267
- config.combiner(explore)("or")(
268
- input,
269
- targets.map((obj) => ({
270
- expression: decode_object(config)(importer)(
271
- input,
272
- obj,
273
- explore,
274
- ),
275
- combined: true,
276
- })),
277
- `(${targets.map((t) => t.name).join(" | ")})`,
278
- ),
279
- failure: (value, expected) =>
280
- ts.factory.createReturnStatement(
281
- config.joiner.failure(value, expected),
282
- ),
283
- is: config.joiner.is,
284
- required: config.joiner.required,
285
- full: config.joiner.full,
286
- type: TypeFactory.keyword("boolean"),
287
- },
288
- generator: {
289
- unions: config.numeric
290
- ? () =>
291
- FeatureProgrammer.write_union_functions(
292
- configure(project)({ ...config, numeric: false })(importer),
293
- )
294
- : undefined,
295
- arrays: () => write_array_functions(project)(config)(importer),
296
- tuples: () => write_tuple_functions(project)(config)(importer),
297
- },
298
- });
380
+ : undefined,
381
+ arrays: () => (collection) =>
382
+ write_array_functions({
383
+ ...props,
384
+ collection,
385
+ }),
386
+ tuples: () => (collection) =>
387
+ write_tuple_functions({
388
+ ...props,
389
+ collection,
390
+ }),
391
+ },
392
+ });
299
393
 
300
394
  /* -----------------------------------------------------------
301
395
  DECODERS
302
396
  ----------------------------------------------------------- */
303
- /**
304
- * @internal
305
- */
306
- export const decode =
307
- (project: ITypiaContext) =>
308
- (config: IConfig) =>
309
- (importer: FunctionImporter) =>
310
- (
311
- input: ts.Expression,
312
- metadata: Metadata,
313
- explore: IExplore,
314
- ): ts.Expression => {
315
- if (metadata.any) return config.success;
397
+ export const decode = (props: {
398
+ context: ITypiaContext;
399
+ config: IConfig;
400
+ importer: FunctionImporter;
401
+ input: ts.Expression;
402
+ metadata: Metadata;
403
+ explore: IExplore;
404
+ }): ts.Expression => {
405
+ if (props.metadata.any) return props.config.success;
316
406
 
317
- const top: IBinary[] = [];
318
- const binaries: IBinary[] = [];
319
- const add = create_add(binaries)(input);
320
- const getConstantValue = (value: number | string | bigint | boolean) => {
321
- if (typeof value === "string")
322
- return ts.factory.createStringLiteral(value);
323
- else if (typeof value === "bigint")
324
- return ExpressionFactory.bigint(value);
325
- return ts.factory.createIdentifier(value.toString());
326
- };
407
+ const top: IBinary[] = [];
408
+ const binaries: IBinary[] = [];
409
+ const add = (next: {
410
+ exact: boolean;
411
+ left: ts.Expression;
412
+ right?: ts.Expression;
413
+ }) =>
414
+ create_add({
415
+ binaries,
416
+ left: next.left,
417
+ right: next.right,
418
+ exact: next.exact,
419
+ default: props.input,
420
+ });
421
+ const getConstantValue = (value: number | string | bigint | boolean) => {
422
+ if (typeof value === "string")
423
+ return ts.factory.createStringLiteral(value);
424
+ else if (typeof value === "bigint")
425
+ return ExpressionFactory.bigint(value);
426
+ return ts.factory.createIdentifier(value.toString());
427
+ };
327
428
 
328
- //----
329
- // CHECK OPTIONAL
330
- //----
331
- // @todo -> should be elaborated
332
- const checkOptional: boolean =
333
- metadata.empty() || metadata.isUnionBucket();
429
+ //----
430
+ // CHECK OPTIONAL
431
+ //----
432
+ // @todo -> should be elaborated
433
+ const checkOptional: boolean =
434
+ props.metadata.empty() || props.metadata.isUnionBucket();
334
435
 
335
- // NULLABLE
336
- if (checkOptional || metadata.nullable)
337
- (metadata.nullable ? add : create_add(top)(input))(
338
- metadata.nullable,
339
- ValueFactory.NULL(),
340
- );
436
+ // NULLABLE
437
+ if (checkOptional || props.metadata.nullable)
438
+ if (props.metadata.nullable)
439
+ add({
440
+ exact: props.metadata.nullable,
441
+ left: ValueFactory.NULL(),
442
+ });
443
+ else
444
+ create_add({
445
+ binaries: top,
446
+ default: props.input,
447
+ exact: props.metadata.nullable,
448
+ left: ValueFactory.NULL(),
449
+ });
341
450
 
342
- // UNDEFINDABLE
343
- if (checkOptional || !metadata.isRequired())
344
- (metadata.isRequired() ? create_add(top)(input) : add)(
345
- !metadata.isRequired(),
346
- ValueFactory.UNDEFINED(),
347
- );
451
+ // UNDEFINDABLE
452
+ if (checkOptional || !props.metadata.isRequired())
453
+ if (props.metadata.isRequired())
454
+ create_add({
455
+ binaries: top,
456
+ default: props.input,
457
+ exact: false,
458
+ left: ValueFactory.UNDEFINED(),
459
+ });
460
+ else
461
+ add({
462
+ exact: true,
463
+ left: ValueFactory.UNDEFINED(),
464
+ });
348
465
 
349
- // FUNCTIONAL
350
- if (metadata.functions.length)
351
- if (
352
- OptionPredicator.functional(project.options) ||
353
- metadata.size() !== 1
354
- )
355
- add(
356
- true,
357
- ts.factory.createStringLiteral("function"),
358
- ValueFactory.TYPEOF(input),
359
- );
360
- else
361
- binaries.push({
362
- combined: false,
363
- expression: config.success,
364
- });
466
+ // FUNCTIONAL
467
+ if (props.metadata.functions.length)
468
+ if (
469
+ OptionPredicator.functional(props.context.options) ||
470
+ props.metadata.size() !== 1
471
+ )
472
+ add({
473
+ exact: true,
474
+ left: ts.factory.createStringLiteral("function"),
475
+ right: ValueFactory.TYPEOF(props.input),
476
+ });
477
+ else
478
+ binaries.push({
479
+ combined: false,
480
+ expression: props.config.success,
481
+ });
365
482
 
366
- //----
367
- // VALUES
368
- //----
369
- // CONSTANT VALUES
370
- const constants: MetadataConstant[] = metadata.constants.filter((c) =>
371
- AtomicPredicator.constant({
372
- metadata,
373
- name: c.type,
374
- }),
375
- );
376
- const constantLength: number = constants
377
- .map((c) => c.values.length)
378
- .reduce((a, b) => a + b, 0);
379
- if (constantLength >= 10) {
380
- const values: Array<boolean | number | string | bigint> = constants
381
- .map((c) => c.values.map((v) => v.value))
382
- .flat();
383
- add(
384
- true,
385
- ts.factory.createTrue(),
386
- ts.factory.createCallExpression(
387
- IdentifierFactory.access(
388
- importer.emplaceVariable(
389
- `${config.prefix}v${importer.increment()}`,
390
- ts.factory.createNewExpression(
391
- ts.factory.createIdentifier("Set"),
392
- undefined,
393
- [
394
- ts.factory.createArrayLiteralExpression(
395
- values.map((v) =>
396
- typeof v === "boolean"
397
- ? v === true
398
- ? ts.factory.createTrue()
399
- : ts.factory.createFalse()
400
- : typeof v === "bigint"
401
- ? ExpressionFactory.bigint(v)
402
- : typeof v === "number"
403
- ? ExpressionFactory.number(v)
404
- : ts.factory.createStringLiteral(v.toString()),
405
- ),
483
+ //----
484
+ // VALUES
485
+ //----
486
+ // CONSTANT VALUES
487
+ const constants: MetadataConstant[] = props.metadata.constants.filter((c) =>
488
+ AtomicPredicator.constant({
489
+ metadata: props.metadata,
490
+ name: c.type,
491
+ }),
492
+ );
493
+ const constantLength: number = constants
494
+ .map((c) => c.values.length)
495
+ .reduce((a, b) => a + b, 0);
496
+ if (constantLength >= 10) {
497
+ const values: Array<boolean | number | string | bigint> = constants
498
+ .map((c) => c.values.map((v) => v.value))
499
+ .flat();
500
+ add({
501
+ exact: true,
502
+ left: ts.factory.createTrue(),
503
+ right: ts.factory.createCallExpression(
504
+ IdentifierFactory.access(
505
+ props.importer.emplaceVariable(
506
+ `${props.config.prefix}v${props.importer.increment()}`,
507
+ ts.factory.createNewExpression(
508
+ ts.factory.createIdentifier("Set"),
509
+ undefined,
510
+ [
511
+ ts.factory.createArrayLiteralExpression(
512
+ values.map((v) =>
513
+ typeof v === "boolean"
514
+ ? v === true
515
+ ? ts.factory.createTrue()
516
+ : ts.factory.createFalse()
517
+ : typeof v === "bigint"
518
+ ? ExpressionFactory.bigint(v)
519
+ : typeof v === "number"
520
+ ? ExpressionFactory.number(v)
521
+ : ts.factory.createStringLiteral(v.toString()),
406
522
  ),
407
- ],
408
- ),
523
+ ),
524
+ ],
409
525
  ),
410
- )("has"),
411
- undefined,
412
- [input],
413
- ),
414
- );
415
- } else
416
- for (const c of constants)
417
- if (
418
- AtomicPredicator.constant({
419
- metadata,
420
- name: c.type,
421
- })
422
- )
423
- for (const v of c.values) add(true, getConstantValue(v.value));
424
-
425
- // ATOMIC VALUES
426
- for (const atom of metadata.atomics)
526
+ ),
527
+ )("has"),
528
+ undefined,
529
+ [props.input],
530
+ ),
531
+ });
532
+ } else
533
+ for (const c of constants)
427
534
  if (
428
- AtomicPredicator.atomic({
429
- metadata,
430
- name: atom.type,
431
- }) === false
535
+ AtomicPredicator.constant({
536
+ metadata: props.metadata,
537
+ name: c.type,
538
+ })
432
539
  )
433
- continue;
434
- else if (atom.type === "number")
435
- binaries.push({
436
- expression: config.atomist(explore)(
437
- check_number(project, config.numeric)(atom)(input),
438
- )(input),
439
- combined: false,
440
- });
441
- else if (atom.type === "bigint")
442
- binaries.push({
443
- expression: config.atomist(explore)(
444
- check_bigint(project)(atom)(input),
445
- )(input),
446
- combined: false,
447
- });
448
- else if (atom.type === "string")
449
- binaries.push({
450
- expression: config.atomist(explore)(
451
- check_string(project)(atom)(input),
452
- )(input),
453
- combined: false,
454
- });
455
- else
456
- add(
457
- true,
458
- ts.factory.createStringLiteral(atom.type),
459
- ValueFactory.TYPEOF(input),
460
- );
540
+ for (const v of c.values)
541
+ add({
542
+ exact: true,
543
+ left: getConstantValue(v.value),
544
+ });
461
545
 
462
- // TEMPLATE LITERAL VALUES
463
- if (metadata.templates.length)
464
- if (AtomicPredicator.template(metadata))
465
- binaries.push({
466
- expression: config.atomist(explore)(
467
- check_template(metadata.templates)(input),
468
- )(input),
469
- combined: false,
470
- });
546
+ // ATOMIC VALUES
547
+ for (const atom of props.metadata.atomics)
548
+ if (
549
+ AtomicPredicator.atomic({
550
+ metadata: props.metadata,
551
+ name: atom.type,
552
+ }) === false
553
+ )
554
+ continue;
555
+ else if (atom.type === "number")
556
+ binaries.push({
557
+ expression: props.config.atomist({
558
+ explore: props.explore,
559
+ entry: check_number(props.context, props.config.numeric)(atom)(
560
+ props.input,
561
+ ),
562
+ input: props.input,
563
+ }),
564
+ combined: false,
565
+ });
566
+ else if (atom.type === "bigint")
567
+ binaries.push({
568
+ expression: props.config.atomist({
569
+ explore: props.explore,
570
+ entry: check_bigint(props.context)(atom)(props.input),
571
+ input: props.input,
572
+ }),
573
+ combined: false,
574
+ });
575
+ else if (atom.type === "string")
576
+ binaries.push({
577
+ expression: props.config.atomist({
578
+ explore: props.explore,
579
+ entry: check_string(props.context)(atom)(props.input),
580
+ input: props.input,
581
+ }),
582
+ combined: false,
583
+ });
584
+ else
585
+ add({
586
+ exact: true,
587
+ left: ts.factory.createStringLiteral(atom.type),
588
+ right: ValueFactory.TYPEOF(props.input),
589
+ });
471
590
 
472
- // NATIVE CLASSES
473
- for (const native of metadata.natives)
591
+ // TEMPLATE LITERAL VALUES
592
+ if (props.metadata.templates.length)
593
+ if (AtomicPredicator.template(props.metadata))
474
594
  binaries.push({
475
- expression: check_native(native)(input),
595
+ expression: props.config.atomist({
596
+ explore: props.explore,
597
+ entry: check_template(props.metadata.templates)(props.input),
598
+ input: props.input,
599
+ }),
476
600
  combined: false,
477
601
  });
478
602
 
479
- //----
480
- // INSTANCES
481
- //----
482
- interface IInstance {
483
- pre: ts.Expression;
484
- body: ts.Expression | null;
485
- expected: string;
486
- }
487
- const instances: IInstance[] = [];
488
- const prepare =
489
- (pre: ts.Expression, expected: string) =>
490
- (body: ts.Expression | null) =>
491
- instances.push({
492
- pre,
493
- expected,
494
- body,
495
- });
603
+ // NATIVE CLASSES
604
+ for (const native of props.metadata.natives)
605
+ binaries.push({
606
+ expression: check_native(native)(props.input),
607
+ combined: false,
608
+ });
496
609
 
497
- // SETS
498
- if (metadata.sets.length) {
499
- const install = prepare(
500
- check_native("Set")(input),
501
- metadata.sets.map((elem) => `Set<${elem.getName()}>`).join(" | "),
502
- );
503
- if (metadata.sets.some((elem) => elem.any)) install(null);
504
- else
505
- install(
506
- explore_sets(project)(config)(importer)(input, metadata.sets, {
507
- ...explore,
610
+ //----
611
+ // INSTANCES
612
+ //----
613
+ interface IInstance {
614
+ knock: ts.Expression;
615
+ body: ts.Expression | null;
616
+ expected: string;
617
+ }
618
+ const instances: IInstance[] = [];
619
+ const prepare = (next: IInstance) => instances.push(next);
620
+
621
+ // SETS
622
+ if (props.metadata.sets.length) {
623
+ const install = (body: ts.Expression | null) =>
624
+ prepare({
625
+ knock: check_native("Set")(props.input),
626
+ expected: props.metadata.sets
627
+ .map((elem) => `Set<${elem.getName()}>`)
628
+ .join(" | "),
629
+ body,
630
+ });
631
+ if (props.metadata.sets.some((elem) => elem.any)) install(null);
632
+ else
633
+ install(
634
+ explore_sets({
635
+ config: props.config,
636
+ context: props.context,
637
+ importer: props.importer,
638
+ sets: props.metadata.sets,
639
+ input: props.input,
640
+ explore: {
641
+ ...props.explore,
508
642
  from: "array",
509
- }),
510
- );
511
- }
643
+ },
644
+ }),
645
+ );
646
+ }
512
647
 
513
- // MAPS
514
- if (metadata.maps.length) {
515
- const install = prepare(
516
- check_native("Map")(input),
517
- metadata.maps
648
+ // MAPS
649
+ if (props.metadata.maps.length) {
650
+ const install = (body: ts.Expression | null) =>
651
+ prepare({
652
+ knock: check_native("Map")(props.input),
653
+ expected: props.metadata.maps
518
654
  .map(({ key, value }) => `Map<${key}, ${value}>`)
519
655
  .join(" | "),
656
+ body,
657
+ });
658
+ if (props.metadata.maps.some((elem) => elem.key.any && elem.value.any))
659
+ install(null);
660
+ else
661
+ install(
662
+ explore_maps({
663
+ config: props.config,
664
+ context: props.context,
665
+ importer: props.importer,
666
+ maps: props.metadata.maps,
667
+ input: props.input,
668
+ explore: {
669
+ ...props.explore,
670
+ from: "array",
671
+ },
672
+ }),
520
673
  );
521
- if (metadata.maps.some((elem) => elem.key.any && elem.value.any))
522
- install(null);
674
+ }
675
+
676
+ // ARRAYS AND TUPLES
677
+ if (props.metadata.tuples.length + props.metadata.arrays.length > 0) {
678
+ const install = (body: ts.Expression | null) =>
679
+ prepare({
680
+ knock: props.config.atomist({
681
+ explore: props.explore,
682
+ entry: {
683
+ expected: [
684
+ ...props.metadata.tuples.map((t) => t.type.name),
685
+ ...props.metadata.arrays.map((a) => a.getName()),
686
+ ].join(" | "),
687
+ expression: ExpressionFactory.isArray(props.input),
688
+ conditions: [],
689
+ },
690
+ input: props.input,
691
+ }),
692
+ expected: [...props.metadata.tuples, ...props.metadata.arrays]
693
+ .map((elem) => elem.type.name)
694
+ .join(" | "),
695
+ body,
696
+ });
697
+ if (props.metadata.arrays.length === 0)
698
+ if (props.metadata.tuples.length === 1)
699
+ install(
700
+ decode_tuple({
701
+ config: props.config,
702
+ context: props.context,
703
+ importer: props.importer,
704
+ tuple: props.metadata.tuples[0]!,
705
+ input: props.input,
706
+ explore: {
707
+ ...props.explore,
708
+ from: "array",
709
+ },
710
+ }),
711
+ );
712
+ // TUPLE ONLY
523
713
  else
524
714
  install(
525
- explore_maps(project)(config)(importer)(input, metadata.maps, {
526
- ...explore,
527
- from: "array",
715
+ explore_tuples({
716
+ config: props.config,
717
+ context: props.context,
718
+ importer: props.importer,
719
+ tuples: props.metadata.tuples,
720
+ input: props.input,
721
+ explore: {
722
+ ...props.explore,
723
+ from: "array",
724
+ },
725
+ }),
726
+ );
727
+ else if (props.metadata.arrays.some((elem) => elem.type.value.any))
728
+ install(null);
729
+ else if (props.metadata.tuples.length === 0)
730
+ if (props.metadata.arrays.length === 1)
731
+ // ARRAY ONLY
732
+ install(
733
+ decode_array({
734
+ config: props.config,
735
+ context: props.context,
736
+ importer: props.importer,
737
+ array: props.metadata.arrays[0]!,
738
+ input: props.input,
739
+ explore: {
740
+ ...props.explore,
741
+ from: "array",
742
+ },
528
743
  }),
529
744
  );
530
- }
531
-
532
- // ARRAYS AND TUPLES
533
- if (metadata.tuples.length + metadata.arrays.length > 0) {
534
- const install = prepare(
535
- config.atomist(explore)({
536
- expected: [
537
- ...metadata.tuples.map((t) => t.type.name),
538
- ...metadata.arrays.map((a) => a.getName()),
539
- ].join(" | "),
540
- expression: ExpressionFactory.isArray(input),
541
- conditions: [],
542
- })(input),
543
- [...metadata.tuples, ...metadata.arrays]
544
- .map((elem) => elem.type.name)
545
- .join(" | "),
546
- );
547
- if (metadata.arrays.length === 0)
548
- if (metadata.tuples.length === 1)
549
- install(
550
- decode_tuple(project)(config)(importer)(
551
- input,
552
- metadata.tuples[0]!,
553
- {
554
- ...explore,
555
- from: "array",
556
- },
557
- ),
558
- );
559
- // TUPLE ONLY
560
- else
561
- install(
562
- explore_tuples(project)(config)(importer)(
563
- input,
564
- metadata.tuples,
565
- {
566
- ...explore,
567
- from: "array",
568
- },
569
- ),
570
- );
571
- else if (metadata.arrays.some((elem) => elem.type.value.any))
572
- install(null);
573
- else if (metadata.tuples.length === 0)
574
- if (metadata.arrays.length === 1)
575
- // ARRAY ONLY
576
- install(
577
- decode_array(project)(config)(importer)(
578
- input,
579
- metadata.arrays[0]!,
580
- {
581
- ...explore,
582
- from: "array",
583
- },
584
- ),
585
- );
586
- else
587
- install(
588
- explore_arrays(project)(config)(importer)(
589
- input,
590
- metadata.arrays,
591
- {
592
- ...explore,
593
- from: "array",
594
- },
595
- ),
596
- );
597
745
  else
598
746
  install(
599
- explore_arrays_and_tuples(project)(config)(importer)(
600
- input,
601
- [...metadata.tuples, ...metadata.arrays],
602
- explore,
603
- ),
747
+ explore_arrays({
748
+ config: props.config,
749
+ context: props.context,
750
+ importer: props.importer,
751
+ arrays: props.metadata.arrays,
752
+ input: props.input,
753
+ explore: {
754
+ ...props.explore,
755
+ from: "array",
756
+ },
757
+ }),
604
758
  );
605
- }
606
-
607
- // OBJECT
608
- if (metadata.objects.length > 0)
609
- prepare(
610
- ExpressionFactory.isObject({
611
- checkNull: true,
612
- checkArray: metadata.objects.some((obj) =>
613
- obj.properties.every(
614
- (prop) => !prop.key.isSoleLiteral() || !prop.value.isRequired(),
615
- ),
616
- ),
617
- })(input),
618
- metadata.objects.map((obj) => obj.name).join(" | "),
619
- )(
620
- explore_objects(config)(importer)(input, metadata, {
621
- ...explore,
622
- from: "object",
759
+ else
760
+ install(
761
+ explore_arrays_and_tuples({
762
+ config: props.config,
763
+ context: props.context,
764
+ importer: props.importer,
765
+ definitions: [...props.metadata.tuples, ...props.metadata.arrays],
766
+ input: props.input,
767
+ explore: props.explore,
623
768
  }),
624
769
  );
770
+ }
625
771
 
626
- if (instances.length) {
627
- const transformer =
628
- (merger: (x: ts.Expression, y: ts.Expression) => ts.Expression) =>
629
- (ins: IInstance) =>
630
- ins.body
631
- ? {
632
- expression: merger(ins.pre, ins.body),
633
- combined: true,
634
- }
635
- : {
636
- expression: ins.pre,
637
- combined: false,
638
- };
639
- if (instances.length === 1)
640
- binaries.push(
641
- transformer((pre, body) =>
642
- config.combiner(explore)("and")(
643
- input,
644
- [pre, body].map((expression) => ({
645
- expression,
646
- combined: expression !== pre,
647
- })),
648
- metadata.getName(),
649
- ),
650
- )(instances[0]!),
651
- );
652
- else
653
- binaries.push({
654
- expression: config.combiner(explore)("or")(
655
- input,
656
- instances.map(transformer(ts.factory.createLogicalAnd)),
657
- metadata.getName(),
772
+ // OBJECT
773
+ if (props.metadata.objects.length > 0)
774
+ prepare({
775
+ knock: ExpressionFactory.isObject({
776
+ checkNull: true,
777
+ checkArray: props.metadata.objects.some((obj) =>
778
+ obj.properties.every(
779
+ (prop) => !prop.key.isSoleLiteral() || !prop.value.isRequired(),
658
780
  ),
659
- combined: true,
660
- });
661
- }
781
+ ),
782
+ })(props.input),
783
+ expected: props.metadata.objects.map((obj) => obj.name).join(" | "),
784
+ body: explore_objects({
785
+ config: props.config,
786
+ importer: props.importer,
787
+ metadata: props.metadata,
788
+ input: props.input,
789
+ explore: {
790
+ ...props.explore,
791
+ from: "object",
792
+ },
793
+ }),
794
+ });
662
795
 
663
- // ESCAPED CASE
664
- if (metadata.escaped !== null)
665
- binaries.push({
666
- combined: false,
667
- expression:
668
- metadata.escaped.original.size() === 1 &&
669
- metadata.escaped.original.natives.length === 1
670
- ? check_native(metadata.escaped.original.natives[0]!)(input)
671
- : ts.factory.createLogicalAnd(
672
- decode(project)(config)(importer)(
673
- input,
674
- metadata.escaped.original,
675
- explore,
676
- ),
677
- ts.factory.createLogicalAnd(
678
- IsProgrammer.decode_to_json(false)(input),
679
- decode_escaped(project)(config)(importer)(
680
- input,
681
- metadata.escaped.returns,
682
- explore,
683
- ),
684
- ),
685
- ),
796
+ if (instances.length) {
797
+ const transformer =
798
+ (merger: (x: ts.Expression, y: ts.Expression) => ts.Expression) =>
799
+ (ins: IInstance) =>
800
+ ins.body
801
+ ? {
802
+ expression: merger(ins.knock, ins.body),
803
+ combined: true,
804
+ }
805
+ : {
806
+ expression: ins.knock,
807
+ combined: false,
808
+ };
809
+ if (instances.length === 1)
810
+ binaries.push(
811
+ transformer((pre, body) =>
812
+ props.config.combiner({
813
+ explore: props.explore,
814
+ logic: "and",
815
+ input: props.input,
816
+ binaries: [pre, body].map((expression) => ({
817
+ expression,
818
+ combined: expression !== pre,
819
+ })),
820
+ expected: props.metadata.getName(),
821
+ }),
822
+ )(instances[0]!),
823
+ );
824
+ else
825
+ binaries.push({
826
+ expression: props.config.combiner({
827
+ explore: props.explore,
828
+ logic: "or",
829
+ input: props.input,
830
+ binaries: instances.map(transformer(ts.factory.createLogicalAnd)),
831
+ expected: props.metadata.getName(),
832
+ }),
833
+ combined: true,
686
834
  });
835
+ }
687
836
 
688
- //----
689
- // COMBINE CONDITIONS
690
- //----
691
- return top.length && binaries.length
692
- ? config.combiner(explore)("and")(
693
- input,
694
- [
695
- ...top,
696
- {
697
- expression: config.combiner(explore)("or")(
698
- input,
699
- binaries,
700
- metadata.getName(),
837
+ // ESCAPED CASE
838
+ if (props.metadata.escaped !== null)
839
+ binaries.push({
840
+ combined: false,
841
+ expression:
842
+ props.metadata.escaped.original.size() === 1 &&
843
+ props.metadata.escaped.original.natives.length === 1
844
+ ? check_native(props.metadata.escaped.original.natives[0]!)(
845
+ props.input,
846
+ )
847
+ : ts.factory.createLogicalAnd(
848
+ decode({
849
+ context: props.context,
850
+ config: props.config,
851
+ importer: props.importer,
852
+ metadata: props.metadata.escaped.original,
853
+ input: props.input,
854
+ explore: props.explore,
855
+ }),
856
+ ts.factory.createLogicalAnd(
857
+ IsProgrammer.decode_to_json({
858
+ checkNull: false,
859
+ input: props.input,
860
+ }),
861
+ decode_escaped({
862
+ config: props.config,
863
+ context: props.context,
864
+ importer: props.importer,
865
+ metadata: props.metadata.escaped.returns,
866
+ input: props.input,
867
+ explore: props.explore,
868
+ }),
701
869
  ),
702
- combined: true,
703
- },
704
- ],
705
- metadata.getName(),
706
- )
707
- : binaries.length
708
- ? config.combiner(explore)("or")(input, binaries, metadata.getName())
709
- : config.success;
710
- };
870
+ ),
871
+ });
711
872
 
712
- export const decode_object =
713
- (config: IConfig) => (importer: FunctionImporter) => {
714
- const func = FeatureProgrammer.decode_object(config)(importer);
715
- return (input: ts.Expression, obj: MetadataObject, explore: IExplore) => {
716
- obj.validated = true;
717
- return func(input, obj, explore);
718
- };
719
- };
873
+ //----
874
+ // COMBINE CONDITIONS
875
+ //----
876
+ return top.length && binaries.length
877
+ ? props.config.combiner({
878
+ explore: props.explore,
879
+ logic: "and",
880
+ input: props.input,
881
+ binaries: [
882
+ ...top,
883
+ {
884
+ expression: props.config.combiner({
885
+ explore: props.explore,
886
+ logic: "or",
887
+ input: props.input,
888
+ binaries,
889
+ expected: props.metadata.getName(),
890
+ }),
891
+ combined: true,
892
+ },
893
+ ],
894
+ expected: props.metadata.getName(),
895
+ })
896
+ : binaries.length
897
+ ? props.config.combiner({
898
+ explore: props.explore,
899
+ logic: "or",
900
+ input: props.input,
901
+ binaries,
902
+ expected: props.metadata.getName(),
903
+ })
904
+ : props.config.success;
905
+ };
720
906
 
721
- const decode_array =
722
- (project: ITypiaContext) =>
723
- (config: IConfig) =>
724
- (importer: FunctionImporter) =>
725
- (input: ts.Expression, array: MetadataArray, explore: IExplore) => {
726
- if (array.type.recursive === false)
727
- return decode_array_inline(project)(config)(importer)(
728
- input,
729
- array,
730
- explore,
731
- );
907
+ export const decode_object = (props: {
908
+ config: IConfig;
909
+ importer: FunctionImporter;
910
+ object: MetadataObject;
911
+ input: ts.Expression;
912
+ explore: IExplore;
913
+ }) => {
914
+ props.object.validated ||= true;
915
+ return FeatureProgrammer.decode_object(props.config)(props.importer)(
916
+ props.input,
917
+ props.object,
918
+ props.explore,
919
+ );
920
+ };
732
921
 
733
- explore = {
734
- ...explore,
735
- source: "function",
736
- from: "array",
737
- };
738
- return ts.factory.createLogicalOr(
739
- ts.factory.createCallExpression(
740
- ts.factory.createIdentifier(
741
- importer.useLocal(`${config.prefix}a${array.type.index}`),
742
- ),
743
- undefined,
744
- FeatureProgrammer.argumentsArray(config)({
745
- ...explore,
746
- source: "function",
747
- from: "array",
748
- })(input),
749
- ),
750
- config.joiner.failure(input, array.type.name, explore),
751
- );
752
- };
922
+ const decode_array = (props: {
923
+ config: IConfig;
924
+ context: ITypiaContext;
925
+ importer: FunctionImporter;
926
+ array: MetadataArray;
927
+ input: ts.Expression;
928
+ explore: IExplore;
929
+ }) => {
930
+ if (props.array.type.recursive === false) return decode_array_inline(props);
753
931
 
754
- const decode_array_inline =
755
- (project: ITypiaContext) =>
756
- (config: IConfig) =>
757
- (importer: FunctionImporter) =>
758
- (
759
- input: ts.Expression,
760
- array: MetadataArray,
761
- explore: IExplore,
762
- ): ts.Expression => {
763
- const length = check_array_length(project)(array)(input);
764
- const main = FeatureProgrammer.decode_array({
765
- prefix: config.prefix,
766
- trace: config.trace,
767
- path: config.path,
768
- decoder: () => decode(project)(config)(importer),
769
- })(importer)(config.joiner.array)(input, array, explore);
770
- return length.expression === null && length.conditions.length === 0
771
- ? main
772
- : ts.factory.createLogicalAnd(
773
- config.atomist(explore)(length)(input),
774
- main,
775
- );
932
+ const arrayExplore: IExplore = {
933
+ ...props.explore,
934
+ source: "function",
935
+ from: "array",
776
936
  };
937
+ return ts.factory.createLogicalOr(
938
+ ts.factory.createCallExpression(
939
+ ts.factory.createIdentifier(
940
+ props.importer.useLocal(
941
+ `${props.config.prefix}a${props.array.type.index}`,
942
+ ),
943
+ ),
944
+ undefined,
945
+ FeatureProgrammer.argumentsArray(props.config)({
946
+ ...arrayExplore,
947
+ source: "function",
948
+ from: "array",
949
+ })(props.input),
950
+ ),
951
+ props.config.joiner.failure({
952
+ input: props.input,
953
+ expected: props.array.type.name,
954
+ explore: arrayExplore,
955
+ }),
956
+ );
957
+ };
777
958
 
778
- const decode_tuple =
779
- (project: ITypiaContext) =>
780
- (config: IConfig) =>
781
- (importer: FunctionImporter) =>
782
- (
783
- input: ts.Expression,
784
- tuple: MetadataTuple,
785
- explore: IExplore,
786
- ): ts.Expression => {
787
- if (tuple.type.recursive === false)
788
- return decode_tuple_inline(project)(config)(importer)(
959
+ const decode_array_inline = (props: {
960
+ config: IConfig;
961
+ context: ITypiaContext;
962
+ importer: FunctionImporter;
963
+ array: MetadataArray;
964
+ input: ts.Expression;
965
+ explore: IExplore;
966
+ }): ts.Expression => {
967
+ const length: ICheckEntry = check_array_length(props.context)(props.array)(
968
+ props.input,
969
+ );
970
+ const main: ts.Expression = FeatureProgrammer.decode_array({
971
+ prefix: props.config.prefix,
972
+ trace: props.config.trace,
973
+ path: props.config.path,
974
+ decoder: () => (input, metadata, explore) =>
975
+ decode({
976
+ ...props,
789
977
  input,
790
- tuple.type,
978
+ metadata,
791
979
  explore,
980
+ }),
981
+ })(props.importer)(props.config.joiner.array)(
982
+ props.input,
983
+ props.array,
984
+ props.explore,
985
+ );
986
+ return length.expression === null && length.conditions.length === 0
987
+ ? main
988
+ : ts.factory.createLogicalAnd(
989
+ props.config.atomist({
990
+ explore: props.explore,
991
+ input: props.input,
992
+ entry: length,
993
+ }),
994
+ main,
792
995
  );
793
- explore = {
794
- ...explore,
795
- source: "function",
796
- from: "array",
797
- };
798
- return ts.factory.createLogicalOr(
799
- ts.factory.createCallExpression(
800
- ts.factory.createIdentifier(
801
- importer.useLocal(`${config.prefix}t${tuple.type.index}`),
802
- ),
803
- undefined,
804
- FeatureProgrammer.argumentsArray(config)({
805
- ...explore,
806
- source: "function",
807
- })(input),
808
- ),
809
- config.joiner.failure(input, tuple.type.name, explore),
810
- );
811
- };
996
+ };
812
997
 
813
- const decode_tuple_inline =
814
- (project: ITypiaContext) =>
815
- (config: IConfig) =>
816
- (importer: FunctionImporter) =>
817
- (
818
- input: ts.Expression,
819
- tuple: MetadataTupleType,
820
- explore: IExplore,
821
- ): ts.Expression => {
822
- const binaries: ts.Expression[] = tuple.elements
823
- .filter((meta) => meta.rest === null)
824
- .map((meta, index) =>
825
- decode(project)(config)(importer)(
826
- ts.factory.createElementAccessExpression(input, index),
827
- meta,
828
- {
829
- ...explore,
830
- from: "array",
831
- postfix: explore.postfix.length
832
- ? `${postfix_of_tuple(explore.postfix)}[${index}]"`
833
- : `"[${index}]"`,
834
- },
998
+ const decode_tuple = (props: {
999
+ context: ITypiaContext;
1000
+ config: IConfig;
1001
+ importer: FunctionImporter;
1002
+ tuple: MetadataTuple;
1003
+ input: ts.Expression;
1004
+ explore: IExplore;
1005
+ }): ts.Expression => {
1006
+ if (props.tuple.type.recursive === false)
1007
+ return decode_tuple_inline({
1008
+ ...props,
1009
+ tuple: props.tuple.type,
1010
+ });
1011
+ const arrayExplore: IExplore = {
1012
+ ...props.explore,
1013
+ source: "function",
1014
+ from: "array",
1015
+ };
1016
+ return ts.factory.createLogicalOr(
1017
+ ts.factory.createCallExpression(
1018
+ ts.factory.createIdentifier(
1019
+ props.importer.useLocal(
1020
+ `${props.config.prefix}t${props.tuple.type.index}`,
835
1021
  ),
836
- );
837
- const rest: ts.Expression | null =
838
- tuple.elements.length && tuple.elements.at(-1)!.rest !== null
839
- ? decode(project)(config)(importer)(
840
- ts.factory.createCallExpression(
841
- IdentifierFactory.access(input)("slice"),
842
- undefined,
843
- [ExpressionFactory.number(tuple.elements.length - 1)],
844
- ),
845
- wrap_metadata_rest_tuple(tuple.elements.at(-1)!.rest!),
846
- {
847
- ...explore,
848
- start: tuple.elements.length - 1,
849
- },
850
- )
851
- : null;
1022
+ ),
1023
+ undefined,
1024
+ FeatureProgrammer.argumentsArray(props.config)({
1025
+ ...arrayExplore,
1026
+ source: "function",
1027
+ })(props.input),
1028
+ ),
1029
+ props.config.joiner.failure({
1030
+ input: props.input,
1031
+ expected: props.tuple.type.name,
1032
+ explore: arrayExplore,
1033
+ }),
1034
+ );
1035
+ };
852
1036
 
853
- const arrayLength = ts.factory.createPropertyAccessExpression(
854
- input,
855
- "length",
1037
+ const decode_tuple_inline = (props: {
1038
+ config: IConfig;
1039
+ context: ITypiaContext;
1040
+ importer: FunctionImporter;
1041
+ tuple: MetadataTupleType;
1042
+ input: ts.Expression;
1043
+ explore: IExplore;
1044
+ }): ts.Expression => {
1045
+ const binaries: ts.Expression[] = props.tuple.elements
1046
+ .filter((metadata) => metadata.rest === null)
1047
+ .map((metadata, index) =>
1048
+ decode({
1049
+ context: props.context,
1050
+ config: props.config,
1051
+ importer: props.importer,
1052
+ input: ts.factory.createElementAccessExpression(props.input, index),
1053
+ metadata,
1054
+ explore: {
1055
+ ...props.explore,
1056
+ from: "array",
1057
+ postfix: props.explore.postfix.length
1058
+ ? `${postfix_of_tuple(props.explore.postfix)}[${index}]"`
1059
+ : `"[${index}]"`,
1060
+ },
1061
+ }),
856
1062
  );
857
- return config.combiner(explore)("and")(
858
- input,
859
- [
860
- ...(rest === null
861
- ? tuple.elements.every((t) => t.optional === false)
862
- ? [
863
- {
864
- combined: false,
865
- expression: ts.factory.createStrictEquality(
866
- arrayLength,
867
- ExpressionFactory.number(tuple.elements.length),
868
- ),
869
- },
870
- ]
871
- : [
872
- {
873
- combined: false,
874
- expression: ts.factory.createLogicalAnd(
875
- ts.factory.createLessThanEquals(
876
- ExpressionFactory.number(
877
- tuple.elements.filter((t) => t.optional === false)
878
- .length,
879
- ),
880
- arrayLength,
881
- ),
882
- ts.factory.createGreaterThanEquals(
883
- ExpressionFactory.number(tuple.elements.length),
884
- arrayLength,
885
- ),
886
- ),
887
- },
888
- ]
889
- : []),
890
- ...(config.joiner.tuple
1063
+ const rest: ts.Expression | null =
1064
+ props.tuple.elements.length && props.tuple.elements.at(-1)!.rest !== null
1065
+ ? decode({
1066
+ config: props.config,
1067
+ context: props.context,
1068
+ importer: props.importer,
1069
+ input: ts.factory.createCallExpression(
1070
+ IdentifierFactory.access(props.input)("slice"),
1071
+ undefined,
1072
+ [ExpressionFactory.number(props.tuple.elements.length - 1)],
1073
+ ),
1074
+ metadata: wrap_metadata_rest_tuple(
1075
+ props.tuple.elements.at(-1)!.rest!,
1076
+ ),
1077
+ explore: {
1078
+ ...props.explore,
1079
+ start: props.tuple.elements.length - 1,
1080
+ },
1081
+ })
1082
+ : null;
1083
+ const arrayLength = ts.factory.createPropertyAccessExpression(
1084
+ props.input,
1085
+ "length",
1086
+ );
1087
+ return props.config.combiner({
1088
+ explore: props.explore,
1089
+ logic: "and",
1090
+ input: props.input,
1091
+ binaries: [
1092
+ ...(rest === null
1093
+ ? props.tuple.elements.every((t) => t.optional === false)
891
1094
  ? [
892
1095
  {
893
- expression: config.joiner.tuple(binaries),
894
- combined: true,
1096
+ combined: false,
1097
+ expression: ts.factory.createStrictEquality(
1098
+ arrayLength,
1099
+ ExpressionFactory.number(props.tuple.elements.length),
1100
+ ),
895
1101
  },
896
1102
  ]
897
- : binaries.map((expression) => ({
898
- expression,
899
- combined: true,
900
- }))),
901
- ...(rest !== null
902
- ? [
1103
+ : [
903
1104
  {
904
- expression: rest,
905
- combined: true,
1105
+ combined: false,
1106
+ expression: ts.factory.createLogicalAnd(
1107
+ ts.factory.createLessThanEquals(
1108
+ ExpressionFactory.number(
1109
+ props.tuple.elements.filter((t) => t.optional === false)
1110
+ .length,
1111
+ ),
1112
+ arrayLength,
1113
+ ),
1114
+ ts.factory.createGreaterThanEquals(
1115
+ ExpressionFactory.number(props.tuple.elements.length),
1116
+ arrayLength,
1117
+ ),
1118
+ ),
906
1119
  },
907
1120
  ]
908
- : []),
909
- ],
910
- `[${tuple.elements.map((t) => t.getName()).join(", ")}]`,
911
- );
912
- };
1121
+ : []),
1122
+ ...(props.config.joiner.tuple
1123
+ ? [
1124
+ {
1125
+ expression: props.config.joiner.tuple(binaries),
1126
+ combined: true,
1127
+ },
1128
+ ]
1129
+ : binaries.map((expression) => ({
1130
+ expression,
1131
+ combined: true,
1132
+ }))),
1133
+ ...(rest !== null
1134
+ ? [
1135
+ {
1136
+ expression: rest,
1137
+ combined: true,
1138
+ },
1139
+ ]
1140
+ : []),
1141
+ ],
1142
+ expected: `[${props.tuple.elements.map((t) => t.getName()).join(", ")}]`,
1143
+ });
1144
+ };
913
1145
 
914
- const decode_escaped =
915
- (project: ITypiaContext) =>
916
- (config: IConfig) =>
917
- (importer: FunctionImporter) =>
918
- (input: ts.Expression, meta: Metadata, explore: IExplore): ts.Expression =>
919
- ts.factory.createCallExpression(
920
- ts.factory.createParenthesizedExpression(
921
- ts.factory.createArrowFunction(
922
- undefined,
923
- undefined,
924
- [IdentifierFactory.parameter("input", TypeFactory.keyword("any"))],
925
- undefined,
926
- undefined,
927
- decode(project)(config)(importer)(
928
- ts.factory.createIdentifier("input"),
929
- meta,
930
- explore,
931
- ),
932
- ),
1146
+ const decode_escaped = (props: {
1147
+ config: IConfig;
1148
+ context: ITypiaContext;
1149
+ importer: FunctionImporter;
1150
+ metadata: Metadata;
1151
+ input: ts.Expression;
1152
+ explore: IExplore;
1153
+ }): ts.Expression =>
1154
+ ts.factory.createCallExpression(
1155
+ ts.factory.createParenthesizedExpression(
1156
+ ts.factory.createArrowFunction(
1157
+ undefined,
1158
+ undefined,
1159
+ [IdentifierFactory.parameter("input", TypeFactory.keyword("any"))],
1160
+ undefined,
1161
+ undefined,
1162
+ decode({
1163
+ ...props,
1164
+ input: ts.factory.createIdentifier("input"),
1165
+ }),
933
1166
  ),
934
- undefined,
935
- [
936
- ts.factory.createCallExpression(
937
- IdentifierFactory.access(input)("toJSON"),
938
- undefined,
939
- [],
940
- ),
941
- ],
942
- );
1167
+ ),
1168
+ undefined,
1169
+ [
1170
+ ts.factory.createCallExpression(
1171
+ IdentifierFactory.access(props.input)("toJSON"),
1172
+ undefined,
1173
+ [],
1174
+ ),
1175
+ ],
1176
+ );
943
1177
 
944
1178
  /* -----------------------------------------------------------
945
1179
  UNION TYPE EXPLORERS
946
1180
  ----------------------------------------------------------- */
947
- const explore_sets =
948
- (project: ITypiaContext) =>
949
- (config: IConfig) =>
950
- (importer: FunctionImporter) =>
951
- (
952
- input: ts.Expression,
953
- sets: Metadata[],
954
- explore: IExplore,
955
- ): ts.Expression =>
956
- ts.factory.createCallExpression(
957
- UnionExplorer.set({
958
- checker: decode(project)(config)(importer),
959
- decoder: decode_array(project)(config)(importer),
960
- empty: config.success,
961
- success: config.success,
962
- failure: (input, expected, explore) =>
963
- ts.factory.createReturnStatement(
964
- config.joiner.failure(input, expected, explore),
965
- ),
966
- })([])(input, sets, explore),
967
- undefined,
968
- undefined,
969
- );
1181
+ const explore_sets = (props: {
1182
+ context: ITypiaContext;
1183
+ config: IConfig;
1184
+ importer: FunctionImporter;
1185
+ sets: Metadata[];
1186
+ input: ts.Expression;
1187
+ explore: IExplore;
1188
+ }): ts.Expression =>
1189
+ ts.factory.createCallExpression(
1190
+ UnionExplorer.set({
1191
+ checker: (input, metadata, explore, _container) =>
1192
+ decode({
1193
+ context: props.context,
1194
+ config: props.config,
1195
+ importer: props.importer,
1196
+ input,
1197
+ metadata,
1198
+ explore,
1199
+ }),
1200
+ decoder: (input, array, explore) =>
1201
+ decode_array({
1202
+ config: props.config,
1203
+ context: props.context,
1204
+ importer: props.importer,
1205
+ array,
1206
+ input,
1207
+ explore,
1208
+ }),
1209
+ empty: props.config.success,
1210
+ success: props.config.success,
1211
+ failure: (input, expected, explore) =>
1212
+ ts.factory.createReturnStatement(
1213
+ props.config.joiner.failure({
1214
+ input,
1215
+ expected,
1216
+ explore,
1217
+ }),
1218
+ ),
1219
+ })([])(props.input, props.sets, props.explore),
1220
+ undefined,
1221
+ undefined,
1222
+ );
970
1223
 
971
- const explore_maps =
972
- (project: ITypiaContext) =>
973
- (config: IConfig) =>
974
- (importer: FunctionImporter) =>
975
- (
976
- input: ts.Expression,
977
- maps: Metadata.Entry[],
978
- explore: IExplore,
979
- ): ts.Expression =>
980
- ts.factory.createCallExpression(
981
- UnionExplorer.map({
982
- checker: (input, entry, explore) => {
983
- const func = decode(project)(config)(importer);
984
- return ts.factory.createLogicalAnd(
985
- func(
986
- ts.factory.createElementAccessExpression(input, 0),
987
- entry[0],
988
- {
989
- ...explore,
990
- postfix: `${explore.postfix}[0]`,
991
- },
992
- ),
993
- func(
994
- ts.factory.createElementAccessExpression(input, 1),
995
- entry[1],
996
- {
997
- ...explore,
998
- postfix: `${explore.postfix}[1]`,
999
- },
1000
- ),
1001
- );
1002
- },
1003
- decoder: decode_array(project)(config)(importer),
1004
- empty: config.success,
1005
- success: config.success,
1006
- failure: (input, expected, explore) =>
1007
- ts.factory.createReturnStatement(
1008
- config.joiner.failure(input, expected, explore),
1009
- ),
1010
- })([])(input, maps, explore),
1011
- undefined,
1012
- undefined,
1013
- );
1224
+ const explore_maps = (props: {
1225
+ context: ITypiaContext;
1226
+ config: IConfig;
1227
+ importer: FunctionImporter;
1228
+ input: ts.Expression;
1229
+ maps: Metadata.Entry[];
1230
+ explore: IExplore;
1231
+ }): ts.Expression =>
1232
+ ts.factory.createCallExpression(
1233
+ UnionExplorer.map({
1234
+ checker: (input, entry, explore) =>
1235
+ ts.factory.createLogicalAnd(
1236
+ decode({
1237
+ config: props.config,
1238
+ context: props.context,
1239
+ importer: props.importer,
1240
+ input: ts.factory.createElementAccessExpression(input, 0),
1241
+ metadata: entry[0],
1242
+ explore: {
1243
+ ...explore,
1244
+ postfix: `${explore.postfix}[0]`,
1245
+ },
1246
+ }),
1247
+ decode({
1248
+ config: props.config,
1249
+ context: props.context,
1250
+ importer: props.importer,
1251
+ input: ts.factory.createElementAccessExpression(input, 1),
1252
+ metadata: entry[1],
1253
+ explore: {
1254
+ ...explore,
1255
+ postfix: `${explore.postfix}[1]`,
1256
+ },
1257
+ }),
1258
+ ),
1259
+ decoder: (input, array, explore) =>
1260
+ decode_array({
1261
+ context: props.context,
1262
+ config: props.config,
1263
+ importer: props.importer,
1264
+ array,
1265
+ input,
1266
+ explore,
1267
+ }),
1268
+ empty: props.config.success,
1269
+ success: props.config.success,
1270
+ failure: (input, expected, explore) =>
1271
+ ts.factory.createReturnStatement(
1272
+ props.config.joiner.failure({
1273
+ input,
1274
+ expected,
1275
+ explore,
1276
+ }),
1277
+ ),
1278
+ })([])(props.input, props.maps, props.explore),
1279
+ undefined,
1280
+ undefined,
1281
+ );
1014
1282
 
1015
- const explore_tuples =
1016
- (project: ITypiaContext) =>
1017
- (config: IConfig) =>
1018
- (importer: FunctionImporter) =>
1019
- (
1020
- input: ts.Expression,
1021
- tuples: MetadataTuple[],
1022
- explore: IExplore,
1023
- ): ts.Expression =>
1024
- explore_array_like_union_types(config)(importer)(
1025
- UnionExplorer.tuple({
1026
- checker: decode_tuple(project)(config)(importer),
1027
- decoder: decode_tuple(project)(config)(importer),
1028
- empty: config.success,
1029
- success: config.success,
1030
- failure: (input, expected, explore) =>
1031
- ts.factory.createReturnStatement(
1032
- config.joiner.failure(input, expected, explore),
1033
- ),
1034
- }),
1035
- )(input, tuples, explore);
1283
+ const explore_tuples = (props: {
1284
+ config: IConfig;
1285
+ context: ITypiaContext;
1286
+ importer: FunctionImporter;
1287
+ tuples: MetadataTuple[];
1288
+ input: ts.Expression;
1289
+ explore: IExplore;
1290
+ }): ts.Expression =>
1291
+ explore_array_like_union_types<MetadataTuple>({
1292
+ config: props.config,
1293
+ importer: props.importer,
1294
+ factory: UnionExplorer.tuple({
1295
+ checker: (input, tuple, explore) =>
1296
+ decode_tuple({
1297
+ context: props.context,
1298
+ config: props.config,
1299
+ importer: props.importer,
1300
+ input,
1301
+ tuple,
1302
+ explore,
1303
+ }),
1304
+ decoder: (input, tuple, explore) =>
1305
+ decode_tuple({
1306
+ context: props.context,
1307
+ config: props.config,
1308
+ importer: props.importer,
1309
+ tuple,
1310
+ input,
1311
+ explore,
1312
+ }),
1313
+ empty: props.config.success,
1314
+ success: props.config.success,
1315
+ failure: (input, expected, explore) =>
1316
+ ts.factory.createReturnStatement(
1317
+ props.config.joiner.failure({
1318
+ input,
1319
+ expected,
1320
+ explore,
1321
+ }),
1322
+ ),
1323
+ }),
1324
+ definitions: props.tuples,
1325
+ input: props.input,
1326
+ explore: props.explore,
1327
+ });
1036
1328
 
1037
- const explore_arrays =
1038
- (project: ITypiaContext) =>
1039
- (config: IConfig) =>
1040
- (importer: FunctionImporter) =>
1041
- (
1042
- input: ts.Expression,
1043
- arrays: MetadataArray[],
1044
- explore: IExplore,
1045
- ): ts.Expression =>
1046
- explore_array_like_union_types(config)(importer)(
1047
- UnionExplorer.array({
1048
- checker: decode(project)(config)(importer),
1049
- decoder: decode_array(project)(config)(importer),
1050
- empty: config.success,
1051
- success: config.success,
1052
- failure: (input, expected, explore) =>
1053
- ts.factory.createReturnStatement(
1054
- config.joiner.failure(input, expected, explore),
1055
- ),
1056
- }),
1057
- )(input, arrays, explore);
1329
+ const explore_arrays = (props: {
1330
+ config: IConfig;
1331
+ context: ITypiaContext;
1332
+ importer: FunctionImporter;
1333
+ arrays: MetadataArray[];
1334
+ input: ts.Expression;
1335
+ explore: IExplore;
1336
+ }): ts.Expression =>
1337
+ explore_array_like_union_types<MetadataArray>({
1338
+ config: props.config,
1339
+ importer: props.importer,
1340
+ factory: UnionExplorer.array({
1341
+ checker: (input, metadata, explore) =>
1342
+ decode({
1343
+ context: props.context,
1344
+ config: props.config,
1345
+ importer: props.importer,
1346
+ metadata,
1347
+ input,
1348
+ explore,
1349
+ }),
1350
+ decoder: (input, array, explore) =>
1351
+ decode_array({
1352
+ context: props.context,
1353
+ config: props.config,
1354
+ importer: props.importer,
1355
+ array,
1356
+ input,
1357
+ explore,
1358
+ }),
1359
+ empty: props.config.success,
1360
+ success: props.config.success,
1361
+ failure: (input, expected, explore) =>
1362
+ ts.factory.createReturnStatement(
1363
+ props.config.joiner.failure({
1364
+ input,
1365
+ expected,
1366
+ explore,
1367
+ }),
1368
+ ),
1369
+ }),
1370
+ definitions: props.arrays,
1371
+ input: props.input,
1372
+ explore: props.explore,
1373
+ });
1058
1374
 
1059
- const explore_arrays_and_tuples =
1060
- (project: ITypiaContext) =>
1061
- (config: IConfig) =>
1062
- (importer: FunctionImporter) =>
1063
- (
1064
- input: ts.Expression,
1065
- elements: Array<MetadataArray | MetadataTuple>,
1066
- explore: IExplore,
1067
- ): ts.Expression =>
1068
- explore_array_like_union_types(config)(importer)(
1069
- UnionExplorer.array_or_tuple({
1070
- checker: (front, target, explore, array) =>
1071
- target instanceof MetadataTuple
1072
- ? decode_tuple(project)(config)(importer)(front, target, explore)
1073
- : config.atomist(explore)({
1074
- expected: elements
1375
+ const explore_arrays_and_tuples = (props: {
1376
+ config: IConfig;
1377
+ context: ITypiaContext;
1378
+ importer: FunctionImporter;
1379
+ definitions: Array<MetadataArray | MetadataTuple>;
1380
+ input: ts.Expression;
1381
+ explore: IExplore;
1382
+ }): ts.Expression =>
1383
+ explore_array_like_union_types<MetadataArray | MetadataTuple>({
1384
+ config: props.config,
1385
+ importer: props.importer,
1386
+ factory: UnionExplorer.array_or_tuple({
1387
+ checker: (input, definition, explore, array) =>
1388
+ definition instanceof MetadataTuple
1389
+ ? decode_tuple({
1390
+ config: props.config,
1391
+ context: props.context,
1392
+ importer: props.importer,
1393
+ input,
1394
+ tuple: definition,
1395
+ explore,
1396
+ })
1397
+ : props.config.atomist({
1398
+ explore,
1399
+ entry: {
1400
+ expected: props.definitions
1075
1401
  .map((elem) =>
1076
1402
  elem instanceof MetadataArray
1077
1403
  ? elem.getName()
1078
1404
  : elem.type.name,
1079
1405
  )
1080
1406
  .join(" | "),
1081
- expression: decode(project)(config)(importer)(
1082
- front,
1083
- target,
1407
+ expression: decode({
1408
+ importer: props.importer,
1409
+ context: props.context,
1410
+ config: props.config,
1411
+ input,
1412
+ metadata: definition,
1084
1413
  explore,
1085
- ),
1414
+ }),
1086
1415
  conditions: [],
1087
- })(array),
1088
- decoder: (input, target, explore) =>
1089
- target instanceof MetadataTuple
1090
- ? decode_tuple(project)(config)(importer)(input, target, explore)
1091
- : decode_array(project)(config)(importer)(input, target, explore),
1092
- empty: config.success,
1093
- success: config.success,
1094
- failure: (input, expected, explore) =>
1095
- ts.factory.createReturnStatement(
1096
- config.joiner.failure(input, expected, explore),
1097
- ),
1098
- }),
1099
- )(input, elements, explore);
1416
+ },
1417
+ input: array,
1418
+ }),
1419
+ decoder: (input, definition, explore) =>
1420
+ definition instanceof MetadataTuple
1421
+ ? decode_tuple({
1422
+ context: props.context,
1423
+ config: props.config,
1424
+ importer: props.importer,
1425
+ input,
1426
+ tuple: definition,
1427
+ explore,
1428
+ })
1429
+ : decode_array({
1430
+ context: props.context,
1431
+ config: props.config,
1432
+ importer: props.importer,
1433
+ input,
1434
+ array: definition,
1435
+ explore,
1436
+ }),
1437
+ empty: props.config.success,
1438
+ success: props.config.success,
1439
+ failure: (input, expected, explore) =>
1440
+ ts.factory.createReturnStatement(
1441
+ props.config.joiner.failure({
1442
+ input,
1443
+ expected,
1444
+ explore,
1445
+ }),
1446
+ ),
1447
+ }),
1448
+ input: props.input,
1449
+ definitions: props.definitions,
1450
+ explore: props.explore,
1451
+ });
1100
1452
 
1101
- const explore_array_like_union_types =
1102
- (config: IConfig) =>
1103
- (importer: FunctionImporter) =>
1104
- <T extends MetadataArray | MetadataTuple>(
1105
- factory: (
1106
- parameters: ts.ParameterDeclaration[],
1107
- ) => (
1108
- input: ts.Expression,
1109
- elements: T[],
1110
- explore: IExplore,
1111
- ) => ts.ArrowFunction,
1112
- ) =>
1113
- (input: ts.Expression, elements: T[], explore: IExplore): ts.Expression => {
1114
- const arrow =
1115
- (parameters: ts.ParameterDeclaration[]) =>
1116
- (explore: IExplore) =>
1117
- (input: ts.Expression): ts.ArrowFunction =>
1118
- factory(parameters)(input, elements, explore);
1119
- if (elements.every((e) => e.type.recursive === false))
1120
- ts.factory.createCallExpression(
1121
- arrow([])(explore)(input),
1122
- undefined,
1123
- [],
1124
- );
1125
- explore = {
1126
- ...explore,
1127
- source: "function",
1128
- from: "array",
1129
- };
1130
- return ts.factory.createLogicalOr(
1131
- ts.factory.createCallExpression(
1132
- ts.factory.createIdentifier(
1133
- importer.emplaceUnion(
1134
- config.prefix,
1135
- elements.map((e) => e.type.name).join(" | "),
1136
- () =>
1137
- arrow(
1138
- FeatureProgrammer.parameterDeclarations(config)(
1139
- TypeFactory.keyword("any"),
1140
- )(ts.factory.createIdentifier("input")),
1141
- )({
1142
- ...explore,
1453
+ const explore_array_like_union_types = <
1454
+ T extends MetadataArray | MetadataTuple,
1455
+ >(props: {
1456
+ config: IConfig;
1457
+ importer: FunctionImporter;
1458
+ factory: (
1459
+ parameters: ts.ParameterDeclaration[],
1460
+ ) => (
1461
+ input: ts.Expression,
1462
+ elements: T[],
1463
+ explore: IExplore,
1464
+ ) => ts.ArrowFunction;
1465
+ input: ts.Expression;
1466
+ definitions: T[];
1467
+ explore: IExplore;
1468
+ }): ts.Expression => {
1469
+ const arrow = (next: {
1470
+ parameters: ts.ParameterDeclaration[];
1471
+ explore: IExplore;
1472
+ input: ts.Expression;
1473
+ }): ts.ArrowFunction =>
1474
+ props.factory(next.parameters)(
1475
+ next.input,
1476
+ props.definitions,
1477
+ next.explore,
1478
+ );
1479
+ if (props.definitions.every((e) => e.type.recursive === false))
1480
+ ts.factory.createCallExpression(
1481
+ arrow({
1482
+ explore: props.explore,
1483
+ input: props.input,
1484
+ parameters: [],
1485
+ }),
1486
+ undefined,
1487
+ [],
1488
+ );
1489
+ const arrayExplore: IExplore = {
1490
+ ...props.explore,
1491
+ source: "function",
1492
+ from: "array",
1493
+ };
1494
+ return ts.factory.createLogicalOr(
1495
+ ts.factory.createCallExpression(
1496
+ ts.factory.createIdentifier(
1497
+ props.importer.emplaceUnion(
1498
+ props.config.prefix,
1499
+ props.definitions.map((e) => e.type.name).join(" | "),
1500
+ () =>
1501
+ arrow({
1502
+ parameters: FeatureProgrammer.parameterDeclarations(
1503
+ props.config,
1504
+ )(TypeFactory.keyword("any"))(
1505
+ ts.factory.createIdentifier("input"),
1506
+ ),
1507
+ explore: {
1508
+ ...arrayExplore,
1143
1509
  postfix: "",
1144
- })(ts.factory.createIdentifier("input")),
1145
- ),
1510
+ },
1511
+ input: ts.factory.createIdentifier("input"),
1512
+ }),
1146
1513
  ),
1147
- undefined,
1148
- FeatureProgrammer.argumentsArray(config)(explore)(input),
1149
1514
  ),
1150
- config.joiner.failure(
1151
- input,
1152
- elements.map((e) => e.type.name).join(" | "),
1153
- explore,
1515
+ undefined,
1516
+ FeatureProgrammer.argumentsArray(props.config)(arrayExplore)(
1517
+ props.input,
1154
1518
  ),
1155
- );
1156
- };
1519
+ ),
1520
+ props.config.joiner.failure({
1521
+ input: props.input,
1522
+ expected: props.definitions.map((e) => e.type.name).join(" | "),
1523
+ explore: arrayExplore,
1524
+ }),
1525
+ );
1526
+ };
1157
1527
 
1158
- const explore_objects =
1159
- (config: IConfig) =>
1160
- (importer: FunctionImporter) =>
1161
- (input: ts.Expression, meta: Metadata, explore: IExplore) =>
1162
- meta.objects.length === 1
1163
- ? decode_object(config)(importer)(input, meta.objects[0]!, explore)
1164
- : ts.factory.createCallExpression(
1165
- ts.factory.createIdentifier(
1166
- importer.useLocal(`${config.prefix}u${meta.union_index!}`),
1528
+ const explore_objects = (props: {
1529
+ config: IConfig;
1530
+ importer: FunctionImporter;
1531
+ input: ts.Expression;
1532
+ metadata: Metadata;
1533
+ explore: IExplore;
1534
+ }) =>
1535
+ props.metadata.objects.length === 1
1536
+ ? decode_object({
1537
+ config: props.config,
1538
+ importer: props.importer,
1539
+ object: props.metadata.objects[0]!,
1540
+ input: props.input,
1541
+ explore: props.explore,
1542
+ })
1543
+ : ts.factory.createCallExpression(
1544
+ ts.factory.createIdentifier(
1545
+ props.importer.useLocal(
1546
+ `${props.config.prefix}u${props.metadata.union_index!}`,
1167
1547
  ),
1168
- undefined,
1169
- FeatureProgrammer.argumentsArray(config)(explore)(input),
1170
- );
1548
+ ),
1549
+ undefined,
1550
+ FeatureProgrammer.argumentsArray(props.config)(props.explore)(
1551
+ props.input,
1552
+ ),
1553
+ );
1171
1554
  }
1172
1555
 
1173
- const create_add =
1174
- (binaries: CheckerProgrammer.IBinary[]) =>
1175
- (defaultInput: ts.Expression) =>
1176
- (
1177
- exact: boolean,
1178
- left: ts.Expression,
1179
- right: ts.Expression = defaultInput,
1180
- ) => {
1181
- const factory = exact
1182
- ? ts.factory.createStrictEquality
1183
- : ts.factory.createStrictInequality;
1184
- binaries.push({
1185
- expression: factory(left, right),
1186
- combined: false,
1187
- });
1188
- };
1556
+ const create_add = (props: {
1557
+ binaries: CheckerProgrammer.IBinary[];
1558
+ default: ts.Expression;
1559
+ exact: boolean;
1560
+ left: ts.Expression;
1561
+ right?: ts.Expression;
1562
+ }) => {
1563
+ const factory = props.exact
1564
+ ? ts.factory.createStrictEquality
1565
+ : ts.factory.createStrictInequality;
1566
+ props.binaries.push({
1567
+ expression: factory(props.left, props.right ?? props.default),
1568
+ combined: false,
1569
+ });
1570
+ };