typia 7.0.0-dev.20241007 → 7.0.0-dev.20241008

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