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