typia 4.2.3-dev.20230814 → 4.3.0-dev.20230821

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 (260) hide show
  1. package/README.md +1 -1
  2. package/lib/factories/ExpressionFactory.d.ts +1 -0
  3. package/lib/factories/ExpressionFactory.js +3 -0
  4. package/lib/factories/ExpressionFactory.js.map +1 -1
  5. package/lib/factories/MetadataTagFactory.js +10 -4
  6. package/lib/factories/MetadataTagFactory.js.map +1 -1
  7. package/lib/metadata/IMetadataTag.d.ts +1 -1
  8. package/lib/metadata/MetadataTuple.js.map +1 -1
  9. package/lib/programmers/CheckerProgrammer.js +2 -2
  10. package/lib/programmers/CheckerProgrammer.js.map +1 -1
  11. package/lib/programmers/LiteralsProgrammer.js +2 -1
  12. package/lib/programmers/LiteralsProgrammer.js.map +1 -1
  13. package/lib/programmers/RandomProgrammer.js +19 -10
  14. package/lib/programmers/RandomProgrammer.js.map +1 -1
  15. package/lib/programmers/helpers/RandomRanger.js +2 -2
  16. package/lib/programmers/helpers/RandomRanger.js.map +1 -1
  17. package/lib/programmers/helpers/UnionExplorer.js +11 -7
  18. package/lib/programmers/helpers/UnionExplorer.js.map +1 -1
  19. package/lib/programmers/internal/application_number.js +10 -3
  20. package/lib/programmers/internal/application_number.js.map +1 -1
  21. package/lib/programmers/internal/check_bigint.js +16 -12
  22. package/lib/programmers/internal/check_bigint.js.map +1 -1
  23. package/lib/programmers/internal/check_number.js +38 -5
  24. package/lib/programmers/internal/check_number.js.map +1 -1
  25. package/package.json +2 -2
  26. package/src/CustomValidatorMap.ts +126 -126
  27. package/src/IRandomGenerator.ts +34 -34
  28. package/src/IValidation.ts +21 -21
  29. package/src/Primitive.ts +131 -131
  30. package/src/TypeGuardError.ts +36 -36
  31. package/src/executable/TypiaGenerateWizard.ts +85 -85
  32. package/src/executable/TypiaSetupWizard.ts +153 -153
  33. package/src/executable/setup/ArgumentParser.ts +45 -45
  34. package/src/executable/setup/CommandExecutor.ts +8 -8
  35. package/src/executable/setup/FileRetriever.ts +22 -22
  36. package/src/executable/setup/PackageManager.ts +71 -71
  37. package/src/executable/setup/PluginConfigurator.ts +70 -70
  38. package/src/executable/typia.ts +52 -52
  39. package/src/factories/CommentFactory.ts +84 -84
  40. package/src/factories/ExpressionFactory.ts +77 -70
  41. package/src/factories/IdentifierFactory.ts +59 -59
  42. package/src/factories/LiteralFactory.ts +39 -39
  43. package/src/factories/MetadataCollection.ts +269 -269
  44. package/src/factories/MetadataFactory.ts +34 -34
  45. package/src/factories/MetadataTagFactory.ts +361 -355
  46. package/src/factories/StatementFactory.ts +24 -24
  47. package/src/factories/TemplateFactory.ts +58 -58
  48. package/src/factories/TypeFactory.ts +124 -124
  49. package/src/factories/ValueFactory.ts +12 -12
  50. package/src/factories/internal/metadata/MetadataHelper.ts +12 -12
  51. package/src/factories/internal/metadata/emend_metadata_atomics.ts +33 -33
  52. package/src/factories/internal/metadata/emplace_metadata_alias.ts +40 -40
  53. package/src/factories/internal/metadata/emplace_metadata_array.ts +34 -34
  54. package/src/factories/internal/metadata/emplace_metadata_object.ts +136 -136
  55. package/src/factories/internal/metadata/emplace_metadata_tuple.ts +50 -50
  56. package/src/factories/internal/metadata/explore_metadata.ts +38 -38
  57. package/src/factories/internal/metadata/iterate_metadata.ts +81 -81
  58. package/src/factories/internal/metadata/iterate_metadata_alias.ts +30 -30
  59. package/src/factories/internal/metadata/iterate_metadata_array.ts +24 -24
  60. package/src/factories/internal/metadata/iterate_metadata_atomic.ts +59 -59
  61. package/src/factories/internal/metadata/iterate_metadata_coalesce.ts +33 -33
  62. package/src/factories/internal/metadata/iterate_metadata_collection.ts +133 -133
  63. package/src/factories/internal/metadata/iterate_metadata_constant.ts +58 -58
  64. package/src/factories/internal/metadata/iterate_metadata_intersection.ts +84 -84
  65. package/src/factories/internal/metadata/iterate_metadata_map.ts +41 -41
  66. package/src/factories/internal/metadata/iterate_metadata_native.ts +219 -219
  67. package/src/factories/internal/metadata/iterate_metadata_object.ts +43 -43
  68. package/src/factories/internal/metadata/iterate_metadata_resolve.ts +49 -49
  69. package/src/factories/internal/metadata/iterate_metadata_set.ts +33 -33
  70. package/src/factories/internal/metadata/iterate_metadata_sort.ts +69 -69
  71. package/src/factories/internal/metadata/iterate_metadata_tag.ts +31 -31
  72. package/src/factories/internal/metadata/iterate_metadata_template.ts +38 -38
  73. package/src/factories/internal/metadata/iterate_metadata_tuple.ts +24 -24
  74. package/src/factories/internal/metadata/iterate_metadata_union.ts +24 -24
  75. package/src/functional/$any.ts +2 -2
  76. package/src/functional/$dictionary.ts +25 -25
  77. package/src/functional/$every.ts +11 -11
  78. package/src/functional/$guard.ts +35 -35
  79. package/src/functional/$is_between.ts +2 -2
  80. package/src/functional/$is_custom.ts +14 -14
  81. package/src/functional/$is_date.ts +3 -3
  82. package/src/functional/$is_datetime.ts +2 -2
  83. package/src/functional/$is_email.ts +4 -4
  84. package/src/functional/$is_ipv4.ts +4 -4
  85. package/src/functional/$is_ipv6.ts +4 -4
  86. package/src/functional/$is_url.ts +4 -4
  87. package/src/functional/$is_uuid.ts +4 -4
  88. package/src/functional/$join.ts +46 -46
  89. package/src/functional/$number.ts +12 -12
  90. package/src/functional/$report.ts +15 -15
  91. package/src/functional/$rest.ts +3 -3
  92. package/src/functional/$string.ts +50 -50
  93. package/src/functional/$tail.ts +5 -5
  94. package/src/functional/Namespace.ts +127 -127
  95. package/src/index.ts +4 -4
  96. package/src/metadata/ICommentTag.ts +4 -4
  97. package/src/metadata/IJsDocTagInfo.ts +10 -10
  98. package/src/metadata/IMetadata.ts +28 -28
  99. package/src/metadata/IMetadataAlias.ts +14 -14
  100. package/src/metadata/IMetadataApplication.ts +7 -7
  101. package/src/metadata/IMetadataArray.ts +10 -10
  102. package/src/metadata/IMetadataCollection.ts +11 -11
  103. package/src/metadata/IMetadataConstant.ts +16 -16
  104. package/src/metadata/IMetadataDictionary.ts +14 -14
  105. package/src/metadata/IMetadataEntry.ts +6 -6
  106. package/src/metadata/IMetadataObject.ts +18 -18
  107. package/src/metadata/IMetadataProperty.ts +11 -11
  108. package/src/metadata/IMetadataResolved.ts +6 -6
  109. package/src/metadata/IMetadataTag.ts +112 -105
  110. package/src/metadata/IMetadataTuple.ts +10 -10
  111. package/src/metadata/Metadata.ts +607 -607
  112. package/src/metadata/MetadataAlias.ts +66 -66
  113. package/src/metadata/MetadataArray.ts +55 -55
  114. package/src/metadata/MetadataConstant.ts +3 -3
  115. package/src/metadata/MetadataObject.ts +129 -129
  116. package/src/metadata/MetadataProperty.ts +64 -64
  117. package/src/metadata/MetadataResolved.ts +51 -51
  118. package/src/metadata/MetadataTuple.ts +58 -53
  119. package/src/module.ts +2038 -2038
  120. package/src/programmers/ApplicationProgrammer.ts +47 -47
  121. package/src/programmers/AssertCloneProgrammer.ts +71 -71
  122. package/src/programmers/AssertParseProgrammer.ts +66 -66
  123. package/src/programmers/AssertProgrammer.ts +279 -279
  124. package/src/programmers/AssertPruneProgrammer.ts +68 -68
  125. package/src/programmers/AssertStringifyProgrammer.ts +66 -66
  126. package/src/programmers/CheckerProgrammer.ts +1173 -1173
  127. package/src/programmers/CloneProgrammer.ts +587 -587
  128. package/src/programmers/FeatureProgrammer.ts +495 -495
  129. package/src/programmers/IsCloneProgrammer.ts +78 -78
  130. package/src/programmers/IsParseProgrammer.ts +72 -72
  131. package/src/programmers/IsProgrammer.ts +239 -239
  132. package/src/programmers/IsPruneProgrammer.ts +73 -73
  133. package/src/programmers/IsStringifyProgrammer.ts +76 -76
  134. package/src/programmers/LiteralsProgrammer.ts +64 -63
  135. package/src/programmers/PruneProgrammer.ts +542 -542
  136. package/src/programmers/RandomProgrammer.ts +578 -579
  137. package/src/programmers/StringifyProgrammer.ts +986 -986
  138. package/src/programmers/TypiaProgrammer.ts +129 -129
  139. package/src/programmers/ValidateCloneProgrammer.ts +85 -85
  140. package/src/programmers/ValidateParseProgrammer.ts +70 -70
  141. package/src/programmers/ValidateProgrammer.ts +305 -305
  142. package/src/programmers/ValidatePruneProgrammer.ts +78 -78
  143. package/src/programmers/ValidateStringifyProgrammer.ts +84 -84
  144. package/src/programmers/helpers/AtomicPredicator.ts +31 -31
  145. package/src/programmers/helpers/CloneJoiner.ts +131 -131
  146. package/src/programmers/helpers/FunctionImporeter.ts +78 -78
  147. package/src/programmers/helpers/ICheckEntry.ts +12 -12
  148. package/src/programmers/helpers/IExpressionEntry.ts +12 -12
  149. package/src/programmers/helpers/OptionPredicator.ts +15 -15
  150. package/src/programmers/helpers/PruneJoiner.ts +143 -143
  151. package/src/programmers/helpers/RandomJoiner.ts +173 -173
  152. package/src/programmers/helpers/RandomRanger.ts +208 -216
  153. package/src/programmers/helpers/StringifyJoinder.ts +113 -113
  154. package/src/programmers/helpers/StringifyPredicator.ts +13 -13
  155. package/src/programmers/helpers/UnionExplorer.ts +305 -301
  156. package/src/programmers/helpers/UnionPredicator.ts +81 -81
  157. package/src/programmers/helpers/disable_function_importer_declare.ts +26 -26
  158. package/src/programmers/internal/JSON_SCHEMA_PREFIX.ts +1 -1
  159. package/src/programmers/internal/application_alias.ts +66 -66
  160. package/src/programmers/internal/application_array.ts +30 -30
  161. package/src/programmers/internal/application_boolean.ts +15 -15
  162. package/src/programmers/internal/application_constant.ts +26 -26
  163. package/src/programmers/internal/application_default.ts +17 -17
  164. package/src/programmers/internal/application_default_string.ts +33 -33
  165. package/src/programmers/internal/application_native.ts +39 -39
  166. package/src/programmers/internal/application_number.ts +80 -74
  167. package/src/programmers/internal/application_object.ts +165 -165
  168. package/src/programmers/internal/application_resolved.ts +55 -55
  169. package/src/programmers/internal/application_schema.ts +157 -157
  170. package/src/programmers/internal/application_string.ts +44 -44
  171. package/src/programmers/internal/application_templates.ts +25 -25
  172. package/src/programmers/internal/application_tuple.ts +57 -57
  173. package/src/programmers/internal/check_array.ts +30 -30
  174. package/src/programmers/internal/check_array_length.ts +35 -35
  175. package/src/programmers/internal/check_bigint.ts +113 -82
  176. package/src/programmers/internal/check_custom.ts +31 -31
  177. package/src/programmers/internal/check_dynamic_properties.ts +195 -195
  178. package/src/programmers/internal/check_everything.ts +28 -28
  179. package/src/programmers/internal/check_native.ts +21 -21
  180. package/src/programmers/internal/check_number.ts +258 -177
  181. package/src/programmers/internal/check_object.ts +55 -55
  182. package/src/programmers/internal/check_string.ts +25 -25
  183. package/src/programmers/internal/check_string_tags.ts +67 -67
  184. package/src/programmers/internal/check_template.ts +56 -56
  185. package/src/programmers/internal/check_union_array_like.ts +329 -329
  186. package/src/programmers/internal/decode_union_object.ts +73 -73
  187. package/src/programmers/internal/feature_object_entries.ts +63 -63
  188. package/src/programmers/internal/get_comment_tags.ts +23 -23
  189. package/src/programmers/internal/metadata_to_pattern.ts +34 -34
  190. package/src/programmers/internal/prune_object_properties.ts +60 -60
  191. package/src/programmers/internal/random_custom.ts +29 -29
  192. package/src/programmers/internal/stringify_dynamic_properties.ts +171 -171
  193. package/src/programmers/internal/stringify_native.ts +7 -7
  194. package/src/programmers/internal/stringify_regular_properties.ts +83 -83
  195. package/src/programmers/internal/template_to_pattern.ts +15 -15
  196. package/src/programmers/internal/wrap_metadata_rest_tuple.ts +16 -16
  197. package/src/schemas/IJsonApplication.ts +8 -8
  198. package/src/schemas/IJsonComponents.ts +33 -33
  199. package/src/schemas/IJsonSchema.ts +133 -133
  200. package/src/transform.ts +27 -27
  201. package/src/transformers/CallExpressionTransformer.ts +179 -179
  202. package/src/transformers/FileTransformer.ts +47 -47
  203. package/src/transformers/IProject.ts +11 -11
  204. package/src/transformers/ITransformOptions.ts +62 -62
  205. package/src/transformers/ImportTransformer.ts +66 -66
  206. package/src/transformers/NodeTransformer.ts +13 -13
  207. package/src/transformers/features/miscellaneous/ApplicationTransformer.ts +112 -112
  208. package/src/transformers/features/miscellaneous/AssertCloneTransformer.ts +9 -9
  209. package/src/transformers/features/miscellaneous/AssertPruneTransformer.ts +9 -9
  210. package/src/transformers/features/miscellaneous/CloneTransformer.ts +9 -9
  211. package/src/transformers/features/miscellaneous/CreateAssertCloneTransformer.ts +9 -9
  212. package/src/transformers/features/miscellaneous/CreateAssertPruneTransformer.ts +9 -9
  213. package/src/transformers/features/miscellaneous/CreateCloneTransformer.ts +9 -9
  214. package/src/transformers/features/miscellaneous/CreateIsCloneTransformer.ts +9 -9
  215. package/src/transformers/features/miscellaneous/CreateIsPruneTransformer.ts +9 -9
  216. package/src/transformers/features/miscellaneous/CreatePruneTransformer.ts +9 -9
  217. package/src/transformers/features/miscellaneous/CreateRandomTransformer.ts +39 -39
  218. package/src/transformers/features/miscellaneous/CreateValidateCloneTransformer.ts +9 -9
  219. package/src/transformers/features/miscellaneous/CreateValidatePruneTransformer.ts +9 -9
  220. package/src/transformers/features/miscellaneous/IsCloneTransformer.ts +9 -9
  221. package/src/transformers/features/miscellaneous/IsPruneTransformer.ts +9 -9
  222. package/src/transformers/features/miscellaneous/LiteralsTransformer.ts +28 -28
  223. package/src/transformers/features/miscellaneous/MetadataTransformer.ts +53 -53
  224. package/src/transformers/features/miscellaneous/PruneTransformer.ts +9 -9
  225. package/src/transformers/features/miscellaneous/RandomTransformer.ts +42 -42
  226. package/src/transformers/features/miscellaneous/ValidateCloneTransformer.ts +9 -9
  227. package/src/transformers/features/miscellaneous/ValidatePruneTransformer.ts +9 -9
  228. package/src/transformers/features/parsers/AssertParseTransformer.ts +9 -9
  229. package/src/transformers/features/parsers/CreateAssertParseTransformer.ts +9 -9
  230. package/src/transformers/features/parsers/CreateIsParseTransformer.ts +9 -9
  231. package/src/transformers/features/parsers/CreateValidateParseTransformer.ts +9 -9
  232. package/src/transformers/features/parsers/IsParseTransformer.ts +9 -9
  233. package/src/transformers/features/parsers/ValidateParseTransformer.ts +9 -9
  234. package/src/transformers/features/stringifiers/AssertStringifyTransformer.ts +10 -10
  235. package/src/transformers/features/stringifiers/CreateAssertStringifyTransformer.ts +12 -12
  236. package/src/transformers/features/stringifiers/CreateIsStringifyTransformer.ts +9 -9
  237. package/src/transformers/features/stringifiers/CreateStringifyTransformer.ts +9 -9
  238. package/src/transformers/features/stringifiers/CreateValidateStringifyProgrammer.ts +12 -12
  239. package/src/transformers/features/stringifiers/IsStringifyTransformer.ts +9 -9
  240. package/src/transformers/features/stringifiers/StringifyTransformer.ts +9 -9
  241. package/src/transformers/features/stringifiers/ValidateStringifyTransformer.ts +10 -10
  242. package/src/transformers/features/validators/AssertTransformer.ts +11 -11
  243. package/src/transformers/features/validators/CreateAssertTransformer.ts +13 -13
  244. package/src/transformers/features/validators/CreateIsTransformer.ts +11 -11
  245. package/src/transformers/features/validators/CreateValidateTransformer.ts +13 -13
  246. package/src/transformers/features/validators/IsTransformer.ts +11 -11
  247. package/src/transformers/features/validators/ValidateTransformer.ts +11 -11
  248. package/src/transformers/internal/GenericTransformer.ts +97 -97
  249. package/src/typings/Atomic.ts +17 -17
  250. package/src/typings/ClassProperties.ts +5 -5
  251. package/src/typings/Customizable.ts +5 -5
  252. package/src/typings/OmitNever.ts +3 -3
  253. package/src/typings/SpecialFields.ts +3 -3
  254. package/src/typings/Writable.ts +11 -11
  255. package/src/utils/ArrayUtil.ts +45 -45
  256. package/src/utils/Escaper.ts +46 -46
  257. package/src/utils/MapUtil.ts +12 -12
  258. package/src/utils/PatternUtil.ts +33 -33
  259. package/src/utils/RandomGenerator.ts +81 -81
  260. package/src/utils/Singleton.ts +17 -17
@@ -1,1173 +1,1173 @@
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 { IJsDocTagInfo } from "../metadata/IJsDocTagInfo";
12
- import { IMetadataTag } from "../metadata/IMetadataTag";
13
- import { Metadata } from "../metadata/Metadata";
14
- import { MetadataArray } from "../metadata/MetadataArray";
15
- import { MetadataObject } from "../metadata/MetadataObject";
16
- import { MetadataTuple } from "../metadata/MetadataTuple";
17
-
18
- import { IProject } from "../transformers/IProject";
19
-
20
- import { FeatureProgrammer } from "./FeatureProgrammer";
21
- import { AtomicPredicator } from "./helpers/AtomicPredicator";
22
- import { FunctionImporter } from "./helpers/FunctionImporeter";
23
- import { ICheckEntry } from "./helpers/ICheckEntry";
24
- import { IExpressionEntry } from "./helpers/IExpressionEntry";
25
- import { OptionPredicator } from "./helpers/OptionPredicator";
26
- import { UnionExplorer } from "./helpers/UnionExplorer";
27
- import { check_array } from "./internal/check_array";
28
- import { check_array_length } from "./internal/check_array_length";
29
- import { check_bigint } from "./internal/check_bigint";
30
- import { check_native } from "./internal/check_native";
31
- import { check_number } from "./internal/check_number";
32
- import { check_string } from "./internal/check_string";
33
- import { check_template } from "./internal/check_template";
34
- import { decode_union_object } from "./internal/decode_union_object";
35
- import { wrap_metadata_rest_tuple } from "./internal/wrap_metadata_rest_tuple";
36
-
37
- export namespace CheckerProgrammer {
38
- export interface IConfig {
39
- prefix: string;
40
- path: boolean;
41
- trace: boolean;
42
- equals: boolean;
43
- numeric: boolean;
44
- addition?: () => ts.Statement[];
45
- decoder?: () => FeatureProgrammer.Decoder<Metadata, ts.Expression>;
46
- combiner: IConfig.Combiner;
47
- atomist: (
48
- explore: IExplore,
49
- ) => (check: ICheckEntry) => (input: ts.Expression) => ts.Expression;
50
- joiner: IConfig.IJoiner;
51
- success: ts.Expression;
52
- }
53
- export namespace IConfig {
54
- export interface Combiner {
55
- (explorer: IExplore): {
56
- (logic: "and" | "or"): {
57
- (
58
- input: ts.Expression,
59
- binaries: IBinary[],
60
- expected: string,
61
- ): ts.Expression;
62
- };
63
- };
64
- }
65
- export interface IJoiner {
66
- object(
67
- input: ts.Expression,
68
- entries: IExpressionEntry[],
69
- ): ts.Expression;
70
- array(input: ts.Expression, arrow: ts.ArrowFunction): ts.Expression;
71
- tuple?(exprs: ts.Expression[]): ts.Expression;
72
-
73
- failure(
74
- value: ts.Expression,
75
- expected: string,
76
- explore?: FeatureProgrammer.IExplore,
77
- ): ts.Expression;
78
- is?(expression: ts.Expression): ts.Expression;
79
- required?(exp: ts.Expression): ts.Expression;
80
- full?: (
81
- condition: ts.Expression,
82
- ) => (
83
- input: ts.Expression,
84
- expected: string,
85
- explore: IExplore,
86
- ) => ts.Expression;
87
- }
88
- }
89
- export type IExplore = FeatureProgrammer.IExplore;
90
-
91
- export interface IBinary {
92
- expression: ts.Expression;
93
- combined: boolean;
94
- }
95
-
96
- /* -----------------------------------------------------------
97
- WRITERS
98
- ----------------------------------------------------------- */
99
- export const write =
100
- (project: IProject) =>
101
- (config: IConfig) =>
102
- (importer: FunctionImporter) =>
103
- FeatureProgrammer.write(project)(
104
- configure(project)(config)(importer),
105
- )(importer);
106
-
107
- export const write_object_functions =
108
- (project: IProject) =>
109
- (config: IConfig) =>
110
- (importer: FunctionImporter) =>
111
- FeatureProgrammer.write_object_functions(
112
- configure(project)(config)(importer),
113
- )(importer);
114
-
115
- export const write_union_functions =
116
- (project: IProject) =>
117
- (config: IConfig) =>
118
- (importer: FunctionImporter) =>
119
- FeatureProgrammer.write_union_functions(
120
- configure(project)({ ...config, numeric: false })(importer),
121
- );
122
-
123
- export const write_array_functions =
124
- (project: IProject) =>
125
- (config: IConfig) =>
126
- (importer: FunctionImporter) =>
127
- (collection: MetadataCollection): ts.VariableStatement[] =>
128
- collection
129
- .arrays()
130
- .filter((a) => a.recursive)
131
- .map((array, i) =>
132
- StatementFactory.constant(
133
- `${config.prefix}a${i}`,
134
- ts.factory.createArrowFunction(
135
- undefined,
136
- undefined,
137
- FeatureProgrammer.parameterDeclarations(config)(
138
- TypeFactory.keyword("any"),
139
- )(ts.factory.createIdentifier("input")),
140
- TypeFactory.keyword("any"),
141
- undefined,
142
- decode_array_inline(project)(config)(importer)(
143
- ts.factory.createIdentifier("input"),
144
- array,
145
- {
146
- tracable: config.trace,
147
- source: "function",
148
- from: "array",
149
- postfix: "",
150
- },
151
- [],
152
- [],
153
- ),
154
- ),
155
- ),
156
- );
157
-
158
- export const write_tuple_functions =
159
- (project: IProject) =>
160
- (config: IConfig) =>
161
- (importer: FunctionImporter) =>
162
- (collection: MetadataCollection): ts.VariableStatement[] =>
163
- collection
164
- .tuples()
165
- .filter((t) => t.recursive)
166
- .map((tuple, i) =>
167
- StatementFactory.constant(
168
- `${config.prefix}t${i}`,
169
- ts.factory.createArrowFunction(
170
- undefined,
171
- undefined,
172
- FeatureProgrammer.parameterDeclarations(config)(
173
- TypeFactory.keyword("any"),
174
- )(ts.factory.createIdentifier("input")),
175
- TypeFactory.keyword("any"),
176
- undefined,
177
- decode_tuple_inline(project)(config)(importer)(
178
- ts.factory.createIdentifier("input"),
179
- tuple,
180
- {
181
- tracable: config.trace,
182
- source: "function",
183
- from: "array",
184
- postfix: "",
185
- },
186
- [],
187
- [],
188
- ),
189
- ),
190
- ),
191
- );
192
-
193
- const configure =
194
- (project: IProject) =>
195
- (config: IConfig) =>
196
- (importer: FunctionImporter): FeatureProgrammer.IConfig => ({
197
- types: {
198
- input: () => TypeFactory.keyword("any"),
199
- output: (type, name) =>
200
- ts.factory.createTypePredicateNode(
201
- undefined,
202
- "input",
203
- ts.factory.createTypeReferenceNode(
204
- name ??
205
- TypeFactory.getFullName(project.checker)(type),
206
- ),
207
- ),
208
- },
209
- trace: config.trace,
210
- path: config.path,
211
- prefix: config.prefix,
212
- initializer:
213
- ({ checker }) =>
214
- (type) => {
215
- const collection: MetadataCollection =
216
- new MetadataCollection();
217
- const meta: Metadata = MetadataFactory.analyze(checker)({
218
- resolve: false,
219
- constant: true,
220
- absorb: true,
221
- })(collection)(type);
222
- return [collection, meta];
223
- },
224
- addition: config.addition,
225
- decoder: () =>
226
- config.decoder?.() ?? decode(project)(config)(importer),
227
- objector: {
228
- checker: () =>
229
- config.decoder?.() ?? decode(project)(config)(importer),
230
- decoder: () => decode_object(config)(importer),
231
- joiner: config.joiner.object,
232
- unionizer: config.equals
233
- ? decode_union_object(decode_object(config)(importer))(
234
- (input, obj, explore) =>
235
- decode_object(config)(importer)(input, obj, {
236
- ...explore,
237
- tracable: true,
238
- }),
239
- )(config.joiner.is ?? ((expr) => expr))(
240
- (value, expected) =>
241
- ts.factory.createReturnStatement(
242
- config.joiner.failure(value, expected),
243
- ),
244
- )
245
- : (input, targets, explore) =>
246
- config.combiner(explore)("or")(
247
- input,
248
- targets.map((obj) => ({
249
- expression: decode_object(config)(importer)(
250
- input,
251
- obj,
252
- explore,
253
- ),
254
- combined: true,
255
- })),
256
- `(${targets.map((t) => t.name).join(" | ")})`,
257
- ),
258
- failure: (value, expected) =>
259
- ts.factory.createReturnStatement(
260
- config.joiner.failure(value, expected),
261
- ),
262
- is: config.joiner.is,
263
- required: config.joiner.required,
264
- full: config.joiner.full,
265
- type: TypeFactory.keyword("boolean"),
266
- },
267
- generator: {
268
- unions: config.numeric
269
- ? () =>
270
- FeatureProgrammer.write_union_functions(
271
- configure(project)({ ...config, numeric: false })(
272
- importer,
273
- ),
274
- )
275
- : undefined,
276
- arrays: () => write_array_functions(project)(config)(importer),
277
- tuples: () => write_tuple_functions(project)(config)(importer),
278
- },
279
- });
280
-
281
- /* -----------------------------------------------------------
282
- DECODERS
283
- ----------------------------------------------------------- */
284
- /**
285
- * @internal
286
- */
287
- export const decode =
288
- (project: IProject) =>
289
- (config: IConfig) =>
290
- (importer: FunctionImporter) =>
291
- (
292
- input: ts.Expression,
293
- meta: Metadata,
294
- explore: IExplore,
295
- metaTags: IMetadataTag[],
296
- jsDocTags: ts.JSDocTagInfo[],
297
- ): ts.Expression => {
298
- if (meta.any) return config.success;
299
-
300
- const top: IBinary[] = [];
301
- const binaries: IBinary[] = [];
302
- const add = create_add(binaries)(input);
303
- const getConstantValue = (
304
- value: number | string | bigint | boolean,
305
- ) =>
306
- typeof value === "string"
307
- ? ts.factory.createStringLiteral(value)
308
- : ts.factory.createIdentifier(value.toString());
309
-
310
- //----
311
- // CHECK OPTIONAL
312
- //----
313
- // @todo -> should be elaborated
314
- const checkOptional: boolean = meta.empty() || meta.isUnionBucket();
315
-
316
- // NULLABLE
317
- if (checkOptional || meta.nullable)
318
- (meta.nullable ? add : create_add(top)(input))(
319
- meta.nullable,
320
- ValueFactory.NULL(),
321
- );
322
-
323
- // UNDEFINDABLE
324
- if (checkOptional || !meta.isRequired())
325
- (meta.isRequired() ? create_add(top)(input) : add)(
326
- !meta.isRequired(),
327
- ValueFactory.UNDEFINED(),
328
- );
329
-
330
- // FUNCTIONAL
331
- if (meta.functional === true)
332
- if (
333
- OptionPredicator.functional(project.options) ||
334
- meta.size() !== 1
335
- )
336
- add(
337
- true,
338
- ts.factory.createStringLiteral("function"),
339
- ValueFactory.TYPEOF(input),
340
- );
341
- else
342
- binaries.push({
343
- combined: false,
344
- expression: config.success,
345
- });
346
-
347
- //----
348
- // VALUES
349
- //----
350
- // CONSTANT VALUES
351
- for (const constant of meta.constants)
352
- if (AtomicPredicator.constant(meta)(constant.type))
353
- for (const val of constant.values)
354
- add(true, getConstantValue(val));
355
-
356
- // ATOMIC VALUES
357
- for (const type of meta.atomics)
358
- if (AtomicPredicator.atomic(meta)(type) === false) continue;
359
- else if (type === "number")
360
- binaries.push({
361
- expression: config.atomist(explore)(
362
- check_number(project, config.numeric)(importer)(
363
- metaTags,
364
- )(jsDocTags)(input),
365
- )(input),
366
- combined: false,
367
- });
368
- else if (type === "bigint")
369
- binaries.push({
370
- expression: config.atomist(explore)(
371
- check_bigint(importer)(metaTags)(jsDocTags)(input),
372
- )(input),
373
- combined: false,
374
- });
375
- else if (type === "string")
376
- binaries.push({
377
- expression: config.atomist(explore)(
378
- check_string(importer)(metaTags)(jsDocTags)(input),
379
- )(input),
380
- combined: false,
381
- });
382
- else
383
- add(
384
- true,
385
- ts.factory.createStringLiteral(type),
386
- ValueFactory.TYPEOF(input),
387
- );
388
-
389
- // TEMPLATE LITERAL VALUES
390
- if (meta.templates.length)
391
- if (AtomicPredicator.template(meta))
392
- binaries.push({
393
- expression: config.atomist(explore)(
394
- check_template(importer)(metaTags)(jsDocTags)(
395
- meta.templates,
396
- )(input),
397
- )(input),
398
- combined: false,
399
- });
400
-
401
- // NATIVE CLASSES
402
- for (const native of meta.natives)
403
- binaries.push({
404
- expression: check_native(native)(input),
405
- combined: false,
406
- });
407
-
408
- //----
409
- // INSTANCES
410
- //----
411
- interface IInstance {
412
- pre: ts.Expression;
413
- body: ts.Expression | null;
414
- expected: string;
415
- }
416
- const instances: IInstance[] = [];
417
- const prepare =
418
- (pre: ts.Expression, expected: string) =>
419
- (body: ts.Expression | null) =>
420
- instances.push({
421
- pre,
422
- expected,
423
- body,
424
- });
425
-
426
- // SETS
427
- if (meta.sets.length) {
428
- const install = prepare(
429
- check_native("Set")(input),
430
- meta.sets
431
- .map((elem) => `Set<${elem.getName()}>`)
432
- .join(" | "),
433
- );
434
- if (meta.sets.some((elem) => elem.any)) install(null);
435
- else
436
- install(
437
- explore_sets(project)(config)(importer)(
438
- input,
439
- meta.sets,
440
- {
441
- ...explore,
442
- from: "array",
443
- },
444
- [],
445
- [],
446
- ),
447
- );
448
- }
449
-
450
- // MAPS
451
- if (meta.maps.length) {
452
- const install = prepare(
453
- check_native("Map")(input),
454
- meta.maps
455
- .map(({ key, value }) => `Map<${key}, ${value}>`)
456
- .join(" | "),
457
- );
458
- if (meta.maps.some((elem) => elem.key.any && elem.value.any))
459
- install(null);
460
- else
461
- install(
462
- explore_maps(project)(config)(importer)(
463
- input,
464
- meta.maps,
465
- {
466
- ...explore,
467
- from: "array",
468
- },
469
- [],
470
- [],
471
- ),
472
- );
473
- }
474
-
475
- // ARRAYS AND TUPLES
476
- if (meta.tuples.length + meta.arrays.length > 0) {
477
- const install = prepare(
478
- config.atomist(explore)(
479
- check_array(importer)(
480
- meta.tuples.length === 0 ? metaTags : [],
481
- )(jsDocTags)(input),
482
- )(input),
483
- [...meta.tuples, ...meta.arrays]
484
- .map((elem) => elem.name)
485
- .join(" | "),
486
- );
487
- if (meta.arrays.length === 0)
488
- if (meta.tuples.length === 1)
489
- install(
490
- decode_tuple(project)(config)(importer)(
491
- input,
492
- meta.tuples[0]!,
493
- {
494
- ...explore,
495
- from: "array",
496
- },
497
- metaTags,
498
- jsDocTags,
499
- ),
500
- );
501
- // TUPLE ONLY
502
- else
503
- install(
504
- explore_tuples(project)(config)(importer)(
505
- input,
506
- meta.tuples,
507
- {
508
- ...explore,
509
- from: "array",
510
- },
511
- metaTags,
512
- jsDocTags,
513
- ),
514
- );
515
- else if (meta.arrays.some((elem) => elem.value.any))
516
- install(null);
517
- else if (meta.tuples.length === 0)
518
- if (meta.arrays.length === 1)
519
- // ARRAY ONLY
520
- install(
521
- decode_array(project)(config)(importer)(
522
- input,
523
- meta.arrays[0]!,
524
- {
525
- ...explore,
526
- from: "array",
527
- },
528
- metaTags,
529
- jsDocTags,
530
- ),
531
- );
532
- else
533
- install(
534
- explore_arrays(project)(config)(importer)(
535
- input,
536
- meta.arrays,
537
- {
538
- ...explore,
539
- from: "array",
540
- },
541
- metaTags,
542
- jsDocTags,
543
- ),
544
- );
545
- else
546
- install(
547
- explore_arrays_and_tuples(project)(config)(importer)(
548
- input,
549
- [...meta.tuples, ...meta.arrays],
550
- explore,
551
- metaTags,
552
- jsDocTags,
553
- ),
554
- );
555
- }
556
-
557
- // OBJECT
558
- if (meta.objects.length > 0)
559
- prepare(
560
- ExpressionFactory.isObject({
561
- checkNull: true,
562
- checkArray: meta.objects.some((obj) =>
563
- obj.properties.every(
564
- (prop) =>
565
- !prop.key.isSoleLiteral() ||
566
- !prop.value.isRequired(),
567
- ),
568
- ),
569
- })(input),
570
- meta.objects.map((obj) => obj.name).join(" | "),
571
- )(
572
- explore_objects(config)(importer)(input, meta, {
573
- ...explore,
574
- from: "object",
575
- }),
576
- );
577
-
578
- if (instances.length) {
579
- const transformer =
580
- (
581
- merger: (
582
- x: ts.Expression,
583
- y: ts.Expression,
584
- ) => ts.Expression,
585
- ) =>
586
- (ins: IInstance) =>
587
- ins.body
588
- ? {
589
- expression: merger(ins.pre, ins.body),
590
- combined: true,
591
- }
592
- : {
593
- expression: ins.pre,
594
- combined: false,
595
- };
596
- if (instances.length === 1)
597
- binaries.push(
598
- transformer((pre, body) =>
599
- config.combiner(explore)("and")(
600
- input,
601
- [pre, body].map((expression) => ({
602
- expression,
603
- combined: expression !== pre,
604
- })),
605
- meta.getName(),
606
- ),
607
- )(instances[0]!),
608
- );
609
- else
610
- binaries.push({
611
- expression: config.combiner(explore)("or")(
612
- input,
613
- instances.map(
614
- transformer(ts.factory.createLogicalAnd),
615
- ),
616
- meta.getName(),
617
- ),
618
- combined: true,
619
- });
620
- }
621
-
622
- //----
623
- // COMBINE CONDITIONS
624
- //----
625
- return top.length && binaries.length
626
- ? config.combiner(explore)("and")(
627
- input,
628
- [
629
- ...top,
630
- {
631
- expression: config.combiner(explore)("or")(
632
- input,
633
- binaries,
634
- meta.getName(),
635
- ),
636
- combined: true,
637
- },
638
- ],
639
- meta.getName(),
640
- )
641
- : binaries.length
642
- ? config.combiner(explore)("or")(
643
- input,
644
- binaries,
645
- meta.getName(),
646
- )
647
- : config.success;
648
- };
649
-
650
- export const decode_object =
651
- (config: IConfig) => (importer: FunctionImporter) => {
652
- const func = FeatureProgrammer.decode_object(config)(importer);
653
- return (
654
- input: ts.Expression,
655
- obj: MetadataObject,
656
- explore: IExplore,
657
- ) => {
658
- obj.validated = true;
659
- return func(input, obj, explore);
660
- };
661
- };
662
-
663
- const decode_array =
664
- (project: IProject) =>
665
- (config: IConfig) =>
666
- (importer: FunctionImporter) =>
667
- (
668
- input: ts.Expression,
669
- array: MetadataArray,
670
- explore: IExplore,
671
- metaTags: IMetadataTag[],
672
- jsDocTags: IJsDocTagInfo[],
673
- ) => {
674
- if (array.recursive === false)
675
- return decode_array_inline(project)(config)(importer)(
676
- input,
677
- array,
678
- explore,
679
- metaTags,
680
- jsDocTags,
681
- );
682
-
683
- explore = {
684
- ...explore,
685
- source: "function",
686
- from: "array",
687
- };
688
- return ts.factory.createLogicalOr(
689
- ts.factory.createCallExpression(
690
- ts.factory.createIdentifier(
691
- importer.useLocal(`${config.prefix}a${array.index}`),
692
- ),
693
- undefined,
694
- FeatureProgrammer.argumentsArray(config)({
695
- ...explore,
696
- source: "function",
697
- from: "array",
698
- })(input),
699
- ),
700
- config.joiner.failure(input, array.name, explore),
701
- );
702
- };
703
-
704
- const decode_array_inline =
705
- (project: IProject) =>
706
- (config: IConfig) =>
707
- (importer: FunctionImporter) =>
708
- FeatureProgrammer.decode_array({
709
- prefix: config.prefix,
710
- trace: config.trace,
711
- path: config.path,
712
- decoder: () => decode(project)(config)(importer),
713
- })(importer)(config.joiner.array);
714
-
715
- const decode_tuple =
716
- (project: IProject) =>
717
- (config: IConfig) =>
718
- (importer: FunctionImporter) =>
719
- (
720
- input: ts.Expression,
721
- tuple: MetadataTuple,
722
- explore: IExplore,
723
- tagList: IMetadataTag[],
724
- jsDocTags: ts.JSDocTagInfo[],
725
- ): ts.Expression => {
726
- if (tuple.recursive === false)
727
- return decode_tuple_inline(project)(config)(importer)(
728
- input,
729
- tuple,
730
- explore,
731
- tagList,
732
- jsDocTags,
733
- );
734
- explore = {
735
- ...explore,
736
- source: "function",
737
- from: "array",
738
- };
739
- return ts.factory.createLogicalOr(
740
- ts.factory.createCallExpression(
741
- ts.factory.createIdentifier(
742
- importer.useLocal(`${config.prefix}t${tuple.index}`),
743
- ),
744
- undefined,
745
- FeatureProgrammer.argumentsArray(config)({
746
- ...explore,
747
- source: "function",
748
- })(input),
749
- ),
750
- config.joiner.failure(input, tuple.name, explore),
751
- );
752
- };
753
-
754
- const decode_tuple_inline =
755
- (project: IProject) =>
756
- (config: IConfig) =>
757
- (importer: FunctionImporter) =>
758
- (
759
- input: ts.Expression,
760
- tuple: MetadataTuple,
761
- explore: IExplore,
762
- tagList: IMetadataTag[],
763
- jsDocTags: ts.JSDocTagInfo[],
764
- ): ts.Expression => {
765
- const binaries: ts.Expression[] = tuple.elements
766
- .filter((meta) => meta.rest === null)
767
- .map((meta, index) =>
768
- decode(project)(config)(importer)(
769
- ts.factory.createElementAccessExpression(input, index),
770
- meta,
771
- {
772
- ...explore,
773
- from: "array",
774
- postfix: explore.postfix.length
775
- ? `${explore.postfix.slice(0, -1)}[${index}]"`
776
- : `"[${index}]"`,
777
- },
778
- tagList,
779
- jsDocTags,
780
- ),
781
- );
782
- const rest: ts.Expression | null =
783
- tuple.elements.length && tuple.elements.at(-1)!.rest !== null
784
- ? decode(project)(config)(importer)(
785
- ts.factory.createCallExpression(
786
- IdentifierFactory.access(input)("slice"),
787
- undefined,
788
- [
789
- ts.factory.createNumericLiteral(
790
- tuple.elements.length - 1,
791
- ),
792
- ],
793
- ),
794
- wrap_metadata_rest_tuple(
795
- tuple.elements.at(-1)!.rest!,
796
- ),
797
- {
798
- ...explore,
799
- start: tuple.elements.length - 1,
800
- },
801
- tagList,
802
- jsDocTags,
803
- )
804
- : null;
805
-
806
- const arrayLength = ts.factory.createPropertyAccessExpression(
807
- input,
808
- "length",
809
- );
810
- return config.combiner(explore)("and")(
811
- input,
812
- [
813
- ...(rest === null
814
- ? tuple.elements.every((t) => t.optional === false)
815
- ? [
816
- {
817
- combined: false,
818
- expression:
819
- ts.factory.createStrictEquality(
820
- arrayLength,
821
- ts.factory.createNumericLiteral(
822
- tuple.elements.length,
823
- ),
824
- ),
825
- },
826
- ]
827
- : [
828
- {
829
- combined: false,
830
- expression: ts.factory.createLogicalAnd(
831
- ts.factory.createLessThanEquals(
832
- ts.factory.createNumericLiteral(
833
- tuple.elements.filter(
834
- (t) =>
835
- t.optional === false,
836
- ).length,
837
- ),
838
- arrayLength,
839
- ),
840
- ts.factory.createGreaterThanEquals(
841
- ts.factory.createNumericLiteral(
842
- tuple.elements.length,
843
- ),
844
- arrayLength,
845
- ),
846
- ),
847
- },
848
- ]
849
- : []),
850
- ...(config.joiner.tuple
851
- ? [
852
- {
853
- expression: config.joiner.tuple(binaries),
854
- combined: true,
855
- },
856
- ]
857
- : binaries.map((expression) => ({
858
- expression,
859
- combined: true,
860
- }))),
861
- ...(rest !== null
862
- ? [
863
- {
864
- expression: rest,
865
- combined: true,
866
- },
867
- ]
868
- : []),
869
- ],
870
- `[${tuple.elements.map((t) => t.getName()).join(", ")}]`,
871
- );
872
- };
873
-
874
- /* -----------------------------------------------------------
875
- UNION TYPE EXPLORERS
876
- ----------------------------------------------------------- */
877
- const explore_sets =
878
- (project: IProject) =>
879
- (config: IConfig) =>
880
- (importer: FunctionImporter) =>
881
- (
882
- input: ts.Expression,
883
- sets: Metadata[],
884
- explore: IExplore,
885
- tags: IMetadataTag[],
886
- jsDocTags: IJsDocTagInfo[],
887
- ): ts.Expression =>
888
- ts.factory.createCallExpression(
889
- UnionExplorer.set({
890
- checker: decode(project)(config)(importer),
891
- decoder: decode_array(project)(config)(importer),
892
- empty: config.success,
893
- success: config.success,
894
- failure: (input, expected, explore) =>
895
- ts.factory.createReturnStatement(
896
- config.joiner.failure(input, expected, explore),
897
- ),
898
- })([])(input, sets, explore, tags, jsDocTags),
899
- undefined,
900
- undefined,
901
- );
902
-
903
- const explore_maps =
904
- (project: IProject) =>
905
- (config: IConfig) =>
906
- (importer: FunctionImporter) =>
907
- (
908
- input: ts.Expression,
909
- maps: Metadata.Entry[],
910
- explore: IExplore,
911
- tags: IMetadataTag[],
912
- jsDocTags: IJsDocTagInfo[],
913
- ): ts.Expression =>
914
- ts.factory.createCallExpression(
915
- UnionExplorer.map({
916
- checker: (input, entry, explore) => {
917
- const func = decode(project)(config)(importer);
918
- return ts.factory.createLogicalAnd(
919
- func(
920
- ts.factory.createElementAccessExpression(
921
- input,
922
- 0,
923
- ),
924
- entry[0],
925
- {
926
- ...explore,
927
- postfix: `${explore.postfix}[0]`,
928
- },
929
- [],
930
- [],
931
- ),
932
- func(
933
- ts.factory.createElementAccessExpression(
934
- input,
935
- 1,
936
- ),
937
- entry[1],
938
- {
939
- ...explore,
940
- postfix: `${explore.postfix}[1]`,
941
- },
942
- [],
943
- [],
944
- ),
945
- );
946
- },
947
- decoder: decode_array(project)(config)(importer),
948
- empty: config.success,
949
- success: config.success,
950
- failure: (input, expected, explore) =>
951
- ts.factory.createReturnStatement(
952
- config.joiner.failure(input, expected, explore),
953
- ),
954
- })([])(input, maps, explore, tags, jsDocTags),
955
- undefined,
956
- undefined,
957
- );
958
-
959
- const explore_tuples =
960
- (project: IProject) =>
961
- (config: IConfig) =>
962
- (importer: FunctionImporter) =>
963
- (
964
- input: ts.Expression,
965
- tuples: MetadataTuple[],
966
- explore: IExplore,
967
- tags: IMetadataTag[],
968
- jsDocTags: IJsDocTagInfo[],
969
- ): ts.Expression =>
970
- explore_array_like_union_types(config)(importer)(
971
- UnionExplorer.tuple({
972
- checker: decode_tuple(project)(config)(importer),
973
- decoder: decode_tuple(project)(config)(importer),
974
- empty: config.success,
975
- success: config.success,
976
- failure: (input, expected, explore) =>
977
- ts.factory.createReturnStatement(
978
- config.joiner.failure(input, expected, explore),
979
- ),
980
- }),
981
- )(input, tuples, explore, tags, jsDocTags);
982
-
983
- const explore_arrays =
984
- (project: IProject) =>
985
- (config: IConfig) =>
986
- (importer: FunctionImporter) =>
987
- (
988
- input: ts.Expression,
989
- arrays: MetadataArray[],
990
- explore: IExplore,
991
- tags: IMetadataTag[],
992
- jsDocTags: IJsDocTagInfo[],
993
- ): ts.Expression =>
994
- explore_array_like_union_types(config)(importer)(
995
- UnionExplorer.array({
996
- checker: decode(project)(config)(importer),
997
- decoder: decode_array(project)(config)(importer),
998
- empty: config.success,
999
- success: config.success,
1000
- failure: (input, expected, explore) =>
1001
- ts.factory.createReturnStatement(
1002
- config.joiner.failure(input, expected, explore),
1003
- ),
1004
- }),
1005
- )(input, arrays, explore, tags, jsDocTags);
1006
-
1007
- const explore_arrays_and_tuples =
1008
- (project: IProject) =>
1009
- (config: IConfig) =>
1010
- (importer: FunctionImporter) =>
1011
- (
1012
- input: ts.Expression,
1013
- elements: Array<MetadataArray | MetadataTuple>,
1014
- explore: IExplore,
1015
- tags: IMetadataTag[],
1016
- jsDocTags: IJsDocTagInfo[],
1017
- ): ts.Expression =>
1018
- explore_array_like_union_types(config)(importer)(
1019
- UnionExplorer.array_or_tuple({
1020
- checker: (front, target, explore, tags, jsDocTags, array) =>
1021
- target instanceof MetadataTuple
1022
- ? decode_tuple(project)(config)(importer)(
1023
- front,
1024
- target,
1025
- explore,
1026
- tags,
1027
- jsDocTags,
1028
- )
1029
- : config.atomist(explore)({
1030
- expression: decode(project)(config)(importer)(
1031
- front,
1032
- target,
1033
- explore,
1034
- tags,
1035
- jsDocTags,
1036
- ),
1037
- tags: check_array_length(tags)(array),
1038
- })(array),
1039
- decoder: (input, target, explore, tags, jsDocTags) =>
1040
- target instanceof MetadataTuple
1041
- ? decode_tuple(project)(config)(importer)(
1042
- input,
1043
- target,
1044
- explore,
1045
- tags,
1046
- jsDocTags,
1047
- )
1048
- : decode_array(project)(config)(importer)(
1049
- input,
1050
- target,
1051
- explore,
1052
- tags,
1053
- jsDocTags,
1054
- ),
1055
- empty: config.success,
1056
- success: config.success,
1057
- failure: (input, expected, explore) =>
1058
- ts.factory.createReturnStatement(
1059
- config.joiner.failure(input, expected, explore),
1060
- ),
1061
- }),
1062
- )(input, elements, explore, tags, jsDocTags);
1063
-
1064
- const explore_array_like_union_types =
1065
- (config: IConfig) =>
1066
- (importer: FunctionImporter) =>
1067
- <T extends MetadataArray | MetadataTuple>(
1068
- factory: (
1069
- parameters: ts.ParameterDeclaration[],
1070
- ) => (
1071
- input: ts.Expression,
1072
- elements: T[],
1073
- explore: IExplore,
1074
- tags: IMetadataTag[],
1075
- jsDocTags: IJsDocTagInfo[],
1076
- ) => ts.ArrowFunction,
1077
- ) =>
1078
- (
1079
- input: ts.Expression,
1080
- elements: T[],
1081
- explore: IExplore,
1082
- tags: IMetadataTag[],
1083
- jsDocTags: IJsDocTagInfo[],
1084
- ): ts.Expression => {
1085
- const arrow =
1086
- (parameters: ts.ParameterDeclaration[]) =>
1087
- (explore: IExplore) =>
1088
- (input: ts.Expression): ts.ArrowFunction =>
1089
- factory(parameters)(
1090
- input,
1091
- elements,
1092
- explore,
1093
- tags,
1094
- jsDocTags,
1095
- );
1096
- if (elements.every((e) => e.recursive === false))
1097
- ts.factory.createCallExpression(
1098
- arrow([])(explore)(input),
1099
- undefined,
1100
- [],
1101
- );
1102
- explore = {
1103
- ...explore,
1104
- source: "function",
1105
- from: "array",
1106
- };
1107
- return ts.factory.createLogicalOr(
1108
- ts.factory.createCallExpression(
1109
- ts.factory.createIdentifier(
1110
- importer.emplaceUnion(
1111
- config.prefix,
1112
- elements.map((e) => e.name).join(" | "),
1113
- () =>
1114
- arrow(
1115
- FeatureProgrammer.parameterDeclarations(
1116
- config,
1117
- )(TypeFactory.keyword("any"))(
1118
- ts.factory.createIdentifier("input"),
1119
- ),
1120
- )({
1121
- ...explore,
1122
- postfix: "",
1123
- })(ts.factory.createIdentifier("input")),
1124
- ),
1125
- ),
1126
- undefined,
1127
- FeatureProgrammer.argumentsArray(config)(explore)(input),
1128
- ),
1129
- config.joiner.failure(
1130
- input,
1131
- elements.map((e) => e.name).join(" | "),
1132
- explore,
1133
- ),
1134
- );
1135
- };
1136
-
1137
- const explore_objects =
1138
- (config: IConfig) =>
1139
- (importer: FunctionImporter) =>
1140
- (input: ts.Expression, meta: Metadata, explore: IExplore) =>
1141
- meta.objects.length === 1
1142
- ? decode_object(config)(importer)(
1143
- input,
1144
- meta.objects[0]!,
1145
- explore,
1146
- )
1147
- : ts.factory.createCallExpression(
1148
- ts.factory.createIdentifier(
1149
- importer.useLocal(
1150
- `${config.prefix}u${meta.union_index!}`,
1151
- ),
1152
- ),
1153
- undefined,
1154
- FeatureProgrammer.argumentsArray(config)(explore)(input),
1155
- );
1156
- }
1157
-
1158
- const create_add =
1159
- (binaries: CheckerProgrammer.IBinary[]) =>
1160
- (defaultInput: ts.Expression) =>
1161
- (
1162
- exact: boolean,
1163
- left: ts.Expression,
1164
- right: ts.Expression = defaultInput,
1165
- ) => {
1166
- const factory = exact
1167
- ? ts.factory.createStrictEquality
1168
- : ts.factory.createStrictInequality;
1169
- binaries.push({
1170
- expression: factory(left, right),
1171
- combined: false,
1172
- });
1173
- };
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 { IJsDocTagInfo } from "../metadata/IJsDocTagInfo";
12
+ import { IMetadataTag } from "../metadata/IMetadataTag";
13
+ import { Metadata } from "../metadata/Metadata";
14
+ import { MetadataArray } from "../metadata/MetadataArray";
15
+ import { MetadataObject } from "../metadata/MetadataObject";
16
+ import { MetadataTuple } from "../metadata/MetadataTuple";
17
+
18
+ import { IProject } from "../transformers/IProject";
19
+
20
+ import { FeatureProgrammer } from "./FeatureProgrammer";
21
+ import { AtomicPredicator } from "./helpers/AtomicPredicator";
22
+ import { FunctionImporter } from "./helpers/FunctionImporeter";
23
+ import { ICheckEntry } from "./helpers/ICheckEntry";
24
+ import { IExpressionEntry } from "./helpers/IExpressionEntry";
25
+ import { OptionPredicator } from "./helpers/OptionPredicator";
26
+ import { UnionExplorer } from "./helpers/UnionExplorer";
27
+ import { check_array } from "./internal/check_array";
28
+ import { check_array_length } from "./internal/check_array_length";
29
+ import { check_bigint } from "./internal/check_bigint";
30
+ import { check_native } from "./internal/check_native";
31
+ import { check_number } from "./internal/check_number";
32
+ import { check_string } from "./internal/check_string";
33
+ import { check_template } from "./internal/check_template";
34
+ import { decode_union_object } from "./internal/decode_union_object";
35
+ import { wrap_metadata_rest_tuple } from "./internal/wrap_metadata_rest_tuple";
36
+
37
+ export namespace CheckerProgrammer {
38
+ export interface IConfig {
39
+ prefix: string;
40
+ path: boolean;
41
+ trace: boolean;
42
+ equals: boolean;
43
+ numeric: boolean;
44
+ addition?: () => ts.Statement[];
45
+ decoder?: () => FeatureProgrammer.Decoder<Metadata, ts.Expression>;
46
+ combiner: IConfig.Combiner;
47
+ atomist: (
48
+ explore: IExplore,
49
+ ) => (check: ICheckEntry) => (input: ts.Expression) => ts.Expression;
50
+ joiner: IConfig.IJoiner;
51
+ success: ts.Expression;
52
+ }
53
+ export namespace IConfig {
54
+ export interface Combiner {
55
+ (explorer: IExplore): {
56
+ (logic: "and" | "or"): {
57
+ (
58
+ input: ts.Expression,
59
+ binaries: IBinary[],
60
+ expected: string,
61
+ ): ts.Expression;
62
+ };
63
+ };
64
+ }
65
+ export interface IJoiner {
66
+ object(
67
+ input: ts.Expression,
68
+ entries: IExpressionEntry[],
69
+ ): ts.Expression;
70
+ array(input: ts.Expression, arrow: ts.ArrowFunction): ts.Expression;
71
+ tuple?(exprs: ts.Expression[]): ts.Expression;
72
+
73
+ failure(
74
+ value: ts.Expression,
75
+ expected: string,
76
+ explore?: FeatureProgrammer.IExplore,
77
+ ): ts.Expression;
78
+ is?(expression: ts.Expression): ts.Expression;
79
+ required?(exp: ts.Expression): ts.Expression;
80
+ full?: (
81
+ condition: ts.Expression,
82
+ ) => (
83
+ input: ts.Expression,
84
+ expected: string,
85
+ explore: IExplore,
86
+ ) => ts.Expression;
87
+ }
88
+ }
89
+ export type IExplore = FeatureProgrammer.IExplore;
90
+
91
+ export interface IBinary {
92
+ expression: ts.Expression;
93
+ combined: boolean;
94
+ }
95
+
96
+ /* -----------------------------------------------------------
97
+ WRITERS
98
+ ----------------------------------------------------------- */
99
+ export const write =
100
+ (project: IProject) =>
101
+ (config: IConfig) =>
102
+ (importer: FunctionImporter) =>
103
+ FeatureProgrammer.write(project)(
104
+ configure(project)(config)(importer),
105
+ )(importer);
106
+
107
+ export const write_object_functions =
108
+ (project: IProject) =>
109
+ (config: IConfig) =>
110
+ (importer: FunctionImporter) =>
111
+ FeatureProgrammer.write_object_functions(
112
+ configure(project)(config)(importer),
113
+ )(importer);
114
+
115
+ export const write_union_functions =
116
+ (project: IProject) =>
117
+ (config: IConfig) =>
118
+ (importer: FunctionImporter) =>
119
+ FeatureProgrammer.write_union_functions(
120
+ configure(project)({ ...config, numeric: false })(importer),
121
+ );
122
+
123
+ export const write_array_functions =
124
+ (project: IProject) =>
125
+ (config: IConfig) =>
126
+ (importer: FunctionImporter) =>
127
+ (collection: MetadataCollection): ts.VariableStatement[] =>
128
+ collection
129
+ .arrays()
130
+ .filter((a) => a.recursive)
131
+ .map((array, i) =>
132
+ StatementFactory.constant(
133
+ `${config.prefix}a${i}`,
134
+ ts.factory.createArrowFunction(
135
+ undefined,
136
+ undefined,
137
+ FeatureProgrammer.parameterDeclarations(config)(
138
+ TypeFactory.keyword("any"),
139
+ )(ts.factory.createIdentifier("input")),
140
+ TypeFactory.keyword("any"),
141
+ undefined,
142
+ decode_array_inline(project)(config)(importer)(
143
+ ts.factory.createIdentifier("input"),
144
+ array,
145
+ {
146
+ tracable: config.trace,
147
+ source: "function",
148
+ from: "array",
149
+ postfix: "",
150
+ },
151
+ [],
152
+ [],
153
+ ),
154
+ ),
155
+ ),
156
+ );
157
+
158
+ export const write_tuple_functions =
159
+ (project: IProject) =>
160
+ (config: IConfig) =>
161
+ (importer: FunctionImporter) =>
162
+ (collection: MetadataCollection): ts.VariableStatement[] =>
163
+ collection
164
+ .tuples()
165
+ .filter((t) => t.recursive)
166
+ .map((tuple, i) =>
167
+ StatementFactory.constant(
168
+ `${config.prefix}t${i}`,
169
+ ts.factory.createArrowFunction(
170
+ undefined,
171
+ undefined,
172
+ FeatureProgrammer.parameterDeclarations(config)(
173
+ TypeFactory.keyword("any"),
174
+ )(ts.factory.createIdentifier("input")),
175
+ TypeFactory.keyword("any"),
176
+ undefined,
177
+ decode_tuple_inline(project)(config)(importer)(
178
+ ts.factory.createIdentifier("input"),
179
+ tuple,
180
+ {
181
+ tracable: config.trace,
182
+ source: "function",
183
+ from: "array",
184
+ postfix: "",
185
+ },
186
+ [],
187
+ [],
188
+ ),
189
+ ),
190
+ ),
191
+ );
192
+
193
+ const configure =
194
+ (project: IProject) =>
195
+ (config: IConfig) =>
196
+ (importer: FunctionImporter): FeatureProgrammer.IConfig => ({
197
+ types: {
198
+ input: () => TypeFactory.keyword("any"),
199
+ output: (type, name) =>
200
+ ts.factory.createTypePredicateNode(
201
+ undefined,
202
+ "input",
203
+ ts.factory.createTypeReferenceNode(
204
+ name ??
205
+ TypeFactory.getFullName(project.checker)(type),
206
+ ),
207
+ ),
208
+ },
209
+ trace: config.trace,
210
+ path: config.path,
211
+ prefix: config.prefix,
212
+ initializer:
213
+ ({ checker }) =>
214
+ (type) => {
215
+ const collection: MetadataCollection =
216
+ new MetadataCollection();
217
+ const meta: Metadata = MetadataFactory.analyze(checker)({
218
+ resolve: false,
219
+ constant: true,
220
+ absorb: true,
221
+ })(collection)(type);
222
+ return [collection, meta];
223
+ },
224
+ addition: config.addition,
225
+ decoder: () =>
226
+ config.decoder?.() ?? decode(project)(config)(importer),
227
+ objector: {
228
+ checker: () =>
229
+ config.decoder?.() ?? decode(project)(config)(importer),
230
+ decoder: () => decode_object(config)(importer),
231
+ joiner: config.joiner.object,
232
+ unionizer: config.equals
233
+ ? decode_union_object(decode_object(config)(importer))(
234
+ (input, obj, explore) =>
235
+ decode_object(config)(importer)(input, obj, {
236
+ ...explore,
237
+ tracable: true,
238
+ }),
239
+ )(config.joiner.is ?? ((expr) => expr))(
240
+ (value, expected) =>
241
+ ts.factory.createReturnStatement(
242
+ config.joiner.failure(value, expected),
243
+ ),
244
+ )
245
+ : (input, targets, explore) =>
246
+ config.combiner(explore)("or")(
247
+ input,
248
+ targets.map((obj) => ({
249
+ expression: decode_object(config)(importer)(
250
+ input,
251
+ obj,
252
+ explore,
253
+ ),
254
+ combined: true,
255
+ })),
256
+ `(${targets.map((t) => t.name).join(" | ")})`,
257
+ ),
258
+ failure: (value, expected) =>
259
+ ts.factory.createReturnStatement(
260
+ config.joiner.failure(value, expected),
261
+ ),
262
+ is: config.joiner.is,
263
+ required: config.joiner.required,
264
+ full: config.joiner.full,
265
+ type: TypeFactory.keyword("boolean"),
266
+ },
267
+ generator: {
268
+ unions: config.numeric
269
+ ? () =>
270
+ FeatureProgrammer.write_union_functions(
271
+ configure(project)({ ...config, numeric: false })(
272
+ importer,
273
+ ),
274
+ )
275
+ : undefined,
276
+ arrays: () => write_array_functions(project)(config)(importer),
277
+ tuples: () => write_tuple_functions(project)(config)(importer),
278
+ },
279
+ });
280
+
281
+ /* -----------------------------------------------------------
282
+ DECODERS
283
+ ----------------------------------------------------------- */
284
+ /**
285
+ * @internal
286
+ */
287
+ export const decode =
288
+ (project: IProject) =>
289
+ (config: IConfig) =>
290
+ (importer: FunctionImporter) =>
291
+ (
292
+ input: ts.Expression,
293
+ meta: Metadata,
294
+ explore: IExplore,
295
+ metaTags: IMetadataTag[],
296
+ jsDocTags: ts.JSDocTagInfo[],
297
+ ): ts.Expression => {
298
+ if (meta.any) return config.success;
299
+
300
+ const top: IBinary[] = [];
301
+ const binaries: IBinary[] = [];
302
+ const add = create_add(binaries)(input);
303
+ const getConstantValue = (
304
+ value: number | string | bigint | boolean,
305
+ ) =>
306
+ typeof value === "string"
307
+ ? ts.factory.createStringLiteral(value)
308
+ : ts.factory.createIdentifier(value.toString());
309
+
310
+ //----
311
+ // CHECK OPTIONAL
312
+ //----
313
+ // @todo -> should be elaborated
314
+ const checkOptional: boolean = meta.empty() || meta.isUnionBucket();
315
+
316
+ // NULLABLE
317
+ if (checkOptional || meta.nullable)
318
+ (meta.nullable ? add : create_add(top)(input))(
319
+ meta.nullable,
320
+ ValueFactory.NULL(),
321
+ );
322
+
323
+ // UNDEFINDABLE
324
+ if (checkOptional || !meta.isRequired())
325
+ (meta.isRequired() ? create_add(top)(input) : add)(
326
+ !meta.isRequired(),
327
+ ValueFactory.UNDEFINED(),
328
+ );
329
+
330
+ // FUNCTIONAL
331
+ if (meta.functional === true)
332
+ if (
333
+ OptionPredicator.functional(project.options) ||
334
+ meta.size() !== 1
335
+ )
336
+ add(
337
+ true,
338
+ ts.factory.createStringLiteral("function"),
339
+ ValueFactory.TYPEOF(input),
340
+ );
341
+ else
342
+ binaries.push({
343
+ combined: false,
344
+ expression: config.success,
345
+ });
346
+
347
+ //----
348
+ // VALUES
349
+ //----
350
+ // CONSTANT VALUES
351
+ for (const constant of meta.constants)
352
+ if (AtomicPredicator.constant(meta)(constant.type))
353
+ for (const val of constant.values)
354
+ add(true, getConstantValue(val));
355
+
356
+ // ATOMIC VALUES
357
+ for (const type of meta.atomics)
358
+ if (AtomicPredicator.atomic(meta)(type) === false) continue;
359
+ else if (type === "number")
360
+ binaries.push({
361
+ expression: config.atomist(explore)(
362
+ check_number(project, config.numeric)(importer)(
363
+ metaTags,
364
+ )(jsDocTags)(input),
365
+ )(input),
366
+ combined: false,
367
+ });
368
+ else if (type === "bigint")
369
+ binaries.push({
370
+ expression: config.atomist(explore)(
371
+ check_bigint(importer)(metaTags)(jsDocTags)(input),
372
+ )(input),
373
+ combined: false,
374
+ });
375
+ else if (type === "string")
376
+ binaries.push({
377
+ expression: config.atomist(explore)(
378
+ check_string(importer)(metaTags)(jsDocTags)(input),
379
+ )(input),
380
+ combined: false,
381
+ });
382
+ else
383
+ add(
384
+ true,
385
+ ts.factory.createStringLiteral(type),
386
+ ValueFactory.TYPEOF(input),
387
+ );
388
+
389
+ // TEMPLATE LITERAL VALUES
390
+ if (meta.templates.length)
391
+ if (AtomicPredicator.template(meta))
392
+ binaries.push({
393
+ expression: config.atomist(explore)(
394
+ check_template(importer)(metaTags)(jsDocTags)(
395
+ meta.templates,
396
+ )(input),
397
+ )(input),
398
+ combined: false,
399
+ });
400
+
401
+ // NATIVE CLASSES
402
+ for (const native of meta.natives)
403
+ binaries.push({
404
+ expression: check_native(native)(input),
405
+ combined: false,
406
+ });
407
+
408
+ //----
409
+ // INSTANCES
410
+ //----
411
+ interface IInstance {
412
+ pre: ts.Expression;
413
+ body: ts.Expression | null;
414
+ expected: string;
415
+ }
416
+ const instances: IInstance[] = [];
417
+ const prepare =
418
+ (pre: ts.Expression, expected: string) =>
419
+ (body: ts.Expression | null) =>
420
+ instances.push({
421
+ pre,
422
+ expected,
423
+ body,
424
+ });
425
+
426
+ // SETS
427
+ if (meta.sets.length) {
428
+ const install = prepare(
429
+ check_native("Set")(input),
430
+ meta.sets
431
+ .map((elem) => `Set<${elem.getName()}>`)
432
+ .join(" | "),
433
+ );
434
+ if (meta.sets.some((elem) => elem.any)) install(null);
435
+ else
436
+ install(
437
+ explore_sets(project)(config)(importer)(
438
+ input,
439
+ meta.sets,
440
+ {
441
+ ...explore,
442
+ from: "array",
443
+ },
444
+ [],
445
+ [],
446
+ ),
447
+ );
448
+ }
449
+
450
+ // MAPS
451
+ if (meta.maps.length) {
452
+ const install = prepare(
453
+ check_native("Map")(input),
454
+ meta.maps
455
+ .map(({ key, value }) => `Map<${key}, ${value}>`)
456
+ .join(" | "),
457
+ );
458
+ if (meta.maps.some((elem) => elem.key.any && elem.value.any))
459
+ install(null);
460
+ else
461
+ install(
462
+ explore_maps(project)(config)(importer)(
463
+ input,
464
+ meta.maps,
465
+ {
466
+ ...explore,
467
+ from: "array",
468
+ },
469
+ metaTags,
470
+ jsDocTags,
471
+ ),
472
+ );
473
+ }
474
+
475
+ // ARRAYS AND TUPLES
476
+ if (meta.tuples.length + meta.arrays.length > 0) {
477
+ const install = prepare(
478
+ config.atomist(explore)(
479
+ check_array(importer)(
480
+ meta.tuples.length === 0 ? metaTags : [],
481
+ )(jsDocTags)(input),
482
+ )(input),
483
+ [...meta.tuples, ...meta.arrays]
484
+ .map((elem) => elem.name)
485
+ .join(" | "),
486
+ );
487
+ if (meta.arrays.length === 0)
488
+ if (meta.tuples.length === 1)
489
+ install(
490
+ decode_tuple(project)(config)(importer)(
491
+ input,
492
+ meta.tuples[0]!,
493
+ {
494
+ ...explore,
495
+ from: "array",
496
+ },
497
+ metaTags,
498
+ jsDocTags,
499
+ ),
500
+ );
501
+ // TUPLE ONLY
502
+ else
503
+ install(
504
+ explore_tuples(project)(config)(importer)(
505
+ input,
506
+ meta.tuples,
507
+ {
508
+ ...explore,
509
+ from: "array",
510
+ },
511
+ metaTags,
512
+ jsDocTags,
513
+ ),
514
+ );
515
+ else if (meta.arrays.some((elem) => elem.value.any))
516
+ install(null);
517
+ else if (meta.tuples.length === 0)
518
+ if (meta.arrays.length === 1)
519
+ // ARRAY ONLY
520
+ install(
521
+ decode_array(project)(config)(importer)(
522
+ input,
523
+ meta.arrays[0]!,
524
+ {
525
+ ...explore,
526
+ from: "array",
527
+ },
528
+ metaTags,
529
+ jsDocTags,
530
+ ),
531
+ );
532
+ else
533
+ install(
534
+ explore_arrays(project)(config)(importer)(
535
+ input,
536
+ meta.arrays,
537
+ {
538
+ ...explore,
539
+ from: "array",
540
+ },
541
+ metaTags,
542
+ jsDocTags,
543
+ ),
544
+ );
545
+ else
546
+ install(
547
+ explore_arrays_and_tuples(project)(config)(importer)(
548
+ input,
549
+ [...meta.tuples, ...meta.arrays],
550
+ explore,
551
+ metaTags,
552
+ jsDocTags,
553
+ ),
554
+ );
555
+ }
556
+
557
+ // OBJECT
558
+ if (meta.objects.length > 0)
559
+ prepare(
560
+ ExpressionFactory.isObject({
561
+ checkNull: true,
562
+ checkArray: meta.objects.some((obj) =>
563
+ obj.properties.every(
564
+ (prop) =>
565
+ !prop.key.isSoleLiteral() ||
566
+ !prop.value.isRequired(),
567
+ ),
568
+ ),
569
+ })(input),
570
+ meta.objects.map((obj) => obj.name).join(" | "),
571
+ )(
572
+ explore_objects(config)(importer)(input, meta, {
573
+ ...explore,
574
+ from: "object",
575
+ }),
576
+ );
577
+
578
+ if (instances.length) {
579
+ const transformer =
580
+ (
581
+ merger: (
582
+ x: ts.Expression,
583
+ y: ts.Expression,
584
+ ) => ts.Expression,
585
+ ) =>
586
+ (ins: IInstance) =>
587
+ ins.body
588
+ ? {
589
+ expression: merger(ins.pre, ins.body),
590
+ combined: true,
591
+ }
592
+ : {
593
+ expression: ins.pre,
594
+ combined: false,
595
+ };
596
+ if (instances.length === 1)
597
+ binaries.push(
598
+ transformer((pre, body) =>
599
+ config.combiner(explore)("and")(
600
+ input,
601
+ [pre, body].map((expression) => ({
602
+ expression,
603
+ combined: expression !== pre,
604
+ })),
605
+ meta.getName(),
606
+ ),
607
+ )(instances[0]!),
608
+ );
609
+ else
610
+ binaries.push({
611
+ expression: config.combiner(explore)("or")(
612
+ input,
613
+ instances.map(
614
+ transformer(ts.factory.createLogicalAnd),
615
+ ),
616
+ meta.getName(),
617
+ ),
618
+ combined: true,
619
+ });
620
+ }
621
+
622
+ //----
623
+ // COMBINE CONDITIONS
624
+ //----
625
+ return top.length && binaries.length
626
+ ? config.combiner(explore)("and")(
627
+ input,
628
+ [
629
+ ...top,
630
+ {
631
+ expression: config.combiner(explore)("or")(
632
+ input,
633
+ binaries,
634
+ meta.getName(),
635
+ ),
636
+ combined: true,
637
+ },
638
+ ],
639
+ meta.getName(),
640
+ )
641
+ : binaries.length
642
+ ? config.combiner(explore)("or")(
643
+ input,
644
+ binaries,
645
+ meta.getName(),
646
+ )
647
+ : config.success;
648
+ };
649
+
650
+ export const decode_object =
651
+ (config: IConfig) => (importer: FunctionImporter) => {
652
+ const func = FeatureProgrammer.decode_object(config)(importer);
653
+ return (
654
+ input: ts.Expression,
655
+ obj: MetadataObject,
656
+ explore: IExplore,
657
+ ) => {
658
+ obj.validated = true;
659
+ return func(input, obj, explore);
660
+ };
661
+ };
662
+
663
+ const decode_array =
664
+ (project: IProject) =>
665
+ (config: IConfig) =>
666
+ (importer: FunctionImporter) =>
667
+ (
668
+ input: ts.Expression,
669
+ array: MetadataArray,
670
+ explore: IExplore,
671
+ metaTags: IMetadataTag[],
672
+ jsDocTags: IJsDocTagInfo[],
673
+ ) => {
674
+ if (array.recursive === false)
675
+ return decode_array_inline(project)(config)(importer)(
676
+ input,
677
+ array,
678
+ explore,
679
+ metaTags,
680
+ jsDocTags,
681
+ );
682
+
683
+ explore = {
684
+ ...explore,
685
+ source: "function",
686
+ from: "array",
687
+ };
688
+ return ts.factory.createLogicalOr(
689
+ ts.factory.createCallExpression(
690
+ ts.factory.createIdentifier(
691
+ importer.useLocal(`${config.prefix}a${array.index}`),
692
+ ),
693
+ undefined,
694
+ FeatureProgrammer.argumentsArray(config)({
695
+ ...explore,
696
+ source: "function",
697
+ from: "array",
698
+ })(input),
699
+ ),
700
+ config.joiner.failure(input, array.name, explore),
701
+ );
702
+ };
703
+
704
+ const decode_array_inline =
705
+ (project: IProject) =>
706
+ (config: IConfig) =>
707
+ (importer: FunctionImporter) =>
708
+ FeatureProgrammer.decode_array({
709
+ prefix: config.prefix,
710
+ trace: config.trace,
711
+ path: config.path,
712
+ decoder: () => decode(project)(config)(importer),
713
+ })(importer)(config.joiner.array);
714
+
715
+ const decode_tuple =
716
+ (project: IProject) =>
717
+ (config: IConfig) =>
718
+ (importer: FunctionImporter) =>
719
+ (
720
+ input: ts.Expression,
721
+ tuple: MetadataTuple,
722
+ explore: IExplore,
723
+ tagList: IMetadataTag[],
724
+ jsDocTags: ts.JSDocTagInfo[],
725
+ ): ts.Expression => {
726
+ if (tuple.recursive === false)
727
+ return decode_tuple_inline(project)(config)(importer)(
728
+ input,
729
+ tuple,
730
+ explore,
731
+ tagList,
732
+ jsDocTags,
733
+ );
734
+ explore = {
735
+ ...explore,
736
+ source: "function",
737
+ from: "array",
738
+ };
739
+ return ts.factory.createLogicalOr(
740
+ ts.factory.createCallExpression(
741
+ ts.factory.createIdentifier(
742
+ importer.useLocal(`${config.prefix}t${tuple.index}`),
743
+ ),
744
+ undefined,
745
+ FeatureProgrammer.argumentsArray(config)({
746
+ ...explore,
747
+ source: "function",
748
+ })(input),
749
+ ),
750
+ config.joiner.failure(input, tuple.name, explore),
751
+ );
752
+ };
753
+
754
+ const decode_tuple_inline =
755
+ (project: IProject) =>
756
+ (config: IConfig) =>
757
+ (importer: FunctionImporter) =>
758
+ (
759
+ input: ts.Expression,
760
+ tuple: MetadataTuple,
761
+ explore: IExplore,
762
+ tagList: IMetadataTag[],
763
+ jsDocTags: ts.JSDocTagInfo[],
764
+ ): ts.Expression => {
765
+ const binaries: ts.Expression[] = tuple.elements
766
+ .filter((meta) => meta.rest === null)
767
+ .map((meta, index) =>
768
+ decode(project)(config)(importer)(
769
+ ts.factory.createElementAccessExpression(input, index),
770
+ meta,
771
+ {
772
+ ...explore,
773
+ from: "array",
774
+ postfix: explore.postfix.length
775
+ ? `${explore.postfix.slice(0, -1)}[${index}]"`
776
+ : `"[${index}]"`,
777
+ },
778
+ tuple.of_map === true && index !== 1 ? [] : tagList,
779
+ tuple.of_map === true && index !== 1 ? [] : jsDocTags,
780
+ ),
781
+ );
782
+ const rest: ts.Expression | null =
783
+ tuple.elements.length && tuple.elements.at(-1)!.rest !== null
784
+ ? decode(project)(config)(importer)(
785
+ ts.factory.createCallExpression(
786
+ IdentifierFactory.access(input)("slice"),
787
+ undefined,
788
+ [
789
+ ts.factory.createNumericLiteral(
790
+ tuple.elements.length - 1,
791
+ ),
792
+ ],
793
+ ),
794
+ wrap_metadata_rest_tuple(
795
+ tuple.elements.at(-1)!.rest!,
796
+ ),
797
+ {
798
+ ...explore,
799
+ start: tuple.elements.length - 1,
800
+ },
801
+ tagList,
802
+ jsDocTags,
803
+ )
804
+ : null;
805
+
806
+ const arrayLength = ts.factory.createPropertyAccessExpression(
807
+ input,
808
+ "length",
809
+ );
810
+ return config.combiner(explore)("and")(
811
+ input,
812
+ [
813
+ ...(rest === null
814
+ ? tuple.elements.every((t) => t.optional === false)
815
+ ? [
816
+ {
817
+ combined: false,
818
+ expression:
819
+ ts.factory.createStrictEquality(
820
+ arrayLength,
821
+ ts.factory.createNumericLiteral(
822
+ tuple.elements.length,
823
+ ),
824
+ ),
825
+ },
826
+ ]
827
+ : [
828
+ {
829
+ combined: false,
830
+ expression: ts.factory.createLogicalAnd(
831
+ ts.factory.createLessThanEquals(
832
+ ts.factory.createNumericLiteral(
833
+ tuple.elements.filter(
834
+ (t) =>
835
+ t.optional === false,
836
+ ).length,
837
+ ),
838
+ arrayLength,
839
+ ),
840
+ ts.factory.createGreaterThanEquals(
841
+ ts.factory.createNumericLiteral(
842
+ tuple.elements.length,
843
+ ),
844
+ arrayLength,
845
+ ),
846
+ ),
847
+ },
848
+ ]
849
+ : []),
850
+ ...(config.joiner.tuple
851
+ ? [
852
+ {
853
+ expression: config.joiner.tuple(binaries),
854
+ combined: true,
855
+ },
856
+ ]
857
+ : binaries.map((expression) => ({
858
+ expression,
859
+ combined: true,
860
+ }))),
861
+ ...(rest !== null
862
+ ? [
863
+ {
864
+ expression: rest,
865
+ combined: true,
866
+ },
867
+ ]
868
+ : []),
869
+ ],
870
+ `[${tuple.elements.map((t) => t.getName()).join(", ")}]`,
871
+ );
872
+ };
873
+
874
+ /* -----------------------------------------------------------
875
+ UNION TYPE EXPLORERS
876
+ ----------------------------------------------------------- */
877
+ const explore_sets =
878
+ (project: IProject) =>
879
+ (config: IConfig) =>
880
+ (importer: FunctionImporter) =>
881
+ (
882
+ input: ts.Expression,
883
+ sets: Metadata[],
884
+ explore: IExplore,
885
+ tags: IMetadataTag[],
886
+ jsDocTags: IJsDocTagInfo[],
887
+ ): ts.Expression =>
888
+ ts.factory.createCallExpression(
889
+ UnionExplorer.set({
890
+ checker: decode(project)(config)(importer),
891
+ decoder: decode_array(project)(config)(importer),
892
+ empty: config.success,
893
+ success: config.success,
894
+ failure: (input, expected, explore) =>
895
+ ts.factory.createReturnStatement(
896
+ config.joiner.failure(input, expected, explore),
897
+ ),
898
+ })([])(input, sets, explore, tags, jsDocTags),
899
+ undefined,
900
+ undefined,
901
+ );
902
+
903
+ const explore_maps =
904
+ (project: IProject) =>
905
+ (config: IConfig) =>
906
+ (importer: FunctionImporter) =>
907
+ (
908
+ input: ts.Expression,
909
+ maps: Metadata.Entry[],
910
+ explore: IExplore,
911
+ tags: IMetadataTag[],
912
+ jsDocTags: IJsDocTagInfo[],
913
+ ): ts.Expression =>
914
+ ts.factory.createCallExpression(
915
+ UnionExplorer.map({
916
+ checker: (input, entry, explore) => {
917
+ const func = decode(project)(config)(importer);
918
+ return ts.factory.createLogicalAnd(
919
+ func(
920
+ ts.factory.createElementAccessExpression(
921
+ input,
922
+ 0,
923
+ ),
924
+ entry[0],
925
+ {
926
+ ...explore,
927
+ postfix: `${explore.postfix}[0]`,
928
+ },
929
+ [],
930
+ [],
931
+ ),
932
+ func(
933
+ ts.factory.createElementAccessExpression(
934
+ input,
935
+ 1,
936
+ ),
937
+ entry[1],
938
+ {
939
+ ...explore,
940
+ postfix: `${explore.postfix}[1]`,
941
+ },
942
+ [],
943
+ [],
944
+ ),
945
+ );
946
+ },
947
+ decoder: decode_array(project)(config)(importer),
948
+ empty: config.success,
949
+ success: config.success,
950
+ failure: (input, expected, explore) =>
951
+ ts.factory.createReturnStatement(
952
+ config.joiner.failure(input, expected, explore),
953
+ ),
954
+ })([])(input, maps, explore, tags, jsDocTags),
955
+ undefined,
956
+ undefined,
957
+ );
958
+
959
+ const explore_tuples =
960
+ (project: IProject) =>
961
+ (config: IConfig) =>
962
+ (importer: FunctionImporter) =>
963
+ (
964
+ input: ts.Expression,
965
+ tuples: MetadataTuple[],
966
+ explore: IExplore,
967
+ tags: IMetadataTag[],
968
+ jsDocTags: IJsDocTagInfo[],
969
+ ): ts.Expression =>
970
+ explore_array_like_union_types(config)(importer)(
971
+ UnionExplorer.tuple({
972
+ checker: decode_tuple(project)(config)(importer),
973
+ decoder: decode_tuple(project)(config)(importer),
974
+ empty: config.success,
975
+ success: config.success,
976
+ failure: (input, expected, explore) =>
977
+ ts.factory.createReturnStatement(
978
+ config.joiner.failure(input, expected, explore),
979
+ ),
980
+ }),
981
+ )(input, tuples, explore, tags, jsDocTags);
982
+
983
+ const explore_arrays =
984
+ (project: IProject) =>
985
+ (config: IConfig) =>
986
+ (importer: FunctionImporter) =>
987
+ (
988
+ input: ts.Expression,
989
+ arrays: MetadataArray[],
990
+ explore: IExplore,
991
+ tags: IMetadataTag[],
992
+ jsDocTags: IJsDocTagInfo[],
993
+ ): ts.Expression =>
994
+ explore_array_like_union_types(config)(importer)(
995
+ UnionExplorer.array({
996
+ checker: decode(project)(config)(importer),
997
+ decoder: decode_array(project)(config)(importer),
998
+ empty: config.success,
999
+ success: config.success,
1000
+ failure: (input, expected, explore) =>
1001
+ ts.factory.createReturnStatement(
1002
+ config.joiner.failure(input, expected, explore),
1003
+ ),
1004
+ }),
1005
+ )(input, arrays, explore, tags, jsDocTags);
1006
+
1007
+ const explore_arrays_and_tuples =
1008
+ (project: IProject) =>
1009
+ (config: IConfig) =>
1010
+ (importer: FunctionImporter) =>
1011
+ (
1012
+ input: ts.Expression,
1013
+ elements: Array<MetadataArray | MetadataTuple>,
1014
+ explore: IExplore,
1015
+ tags: IMetadataTag[],
1016
+ jsDocTags: IJsDocTagInfo[],
1017
+ ): ts.Expression =>
1018
+ explore_array_like_union_types(config)(importer)(
1019
+ UnionExplorer.array_or_tuple({
1020
+ checker: (front, target, explore, tags, jsDocTags, array) =>
1021
+ target instanceof MetadataTuple
1022
+ ? decode_tuple(project)(config)(importer)(
1023
+ front,
1024
+ target,
1025
+ explore,
1026
+ tags,
1027
+ jsDocTags,
1028
+ )
1029
+ : config.atomist(explore)({
1030
+ expression: decode(project)(config)(importer)(
1031
+ front,
1032
+ target,
1033
+ explore,
1034
+ tags,
1035
+ jsDocTags,
1036
+ ),
1037
+ tags: check_array_length(tags)(array),
1038
+ })(array),
1039
+ decoder: (input, target, explore, tags, jsDocTags) =>
1040
+ target instanceof MetadataTuple
1041
+ ? decode_tuple(project)(config)(importer)(
1042
+ input,
1043
+ target,
1044
+ explore,
1045
+ tags,
1046
+ jsDocTags,
1047
+ )
1048
+ : decode_array(project)(config)(importer)(
1049
+ input,
1050
+ target,
1051
+ explore,
1052
+ tags,
1053
+ jsDocTags,
1054
+ ),
1055
+ empty: config.success,
1056
+ success: config.success,
1057
+ failure: (input, expected, explore) =>
1058
+ ts.factory.createReturnStatement(
1059
+ config.joiner.failure(input, expected, explore),
1060
+ ),
1061
+ }),
1062
+ )(input, elements, explore, tags, jsDocTags);
1063
+
1064
+ const explore_array_like_union_types =
1065
+ (config: IConfig) =>
1066
+ (importer: FunctionImporter) =>
1067
+ <T extends MetadataArray | MetadataTuple>(
1068
+ factory: (
1069
+ parameters: ts.ParameterDeclaration[],
1070
+ ) => (
1071
+ input: ts.Expression,
1072
+ elements: T[],
1073
+ explore: IExplore,
1074
+ tags: IMetadataTag[],
1075
+ jsDocTags: IJsDocTagInfo[],
1076
+ ) => ts.ArrowFunction,
1077
+ ) =>
1078
+ (
1079
+ input: ts.Expression,
1080
+ elements: T[],
1081
+ explore: IExplore,
1082
+ tags: IMetadataTag[],
1083
+ jsDocTags: IJsDocTagInfo[],
1084
+ ): ts.Expression => {
1085
+ const arrow =
1086
+ (parameters: ts.ParameterDeclaration[]) =>
1087
+ (explore: IExplore) =>
1088
+ (input: ts.Expression): ts.ArrowFunction =>
1089
+ factory(parameters)(
1090
+ input,
1091
+ elements,
1092
+ explore,
1093
+ tags,
1094
+ jsDocTags,
1095
+ );
1096
+ if (elements.every((e) => e.recursive === false))
1097
+ ts.factory.createCallExpression(
1098
+ arrow([])(explore)(input),
1099
+ undefined,
1100
+ [],
1101
+ );
1102
+ explore = {
1103
+ ...explore,
1104
+ source: "function",
1105
+ from: "array",
1106
+ };
1107
+ return ts.factory.createLogicalOr(
1108
+ ts.factory.createCallExpression(
1109
+ ts.factory.createIdentifier(
1110
+ importer.emplaceUnion(
1111
+ config.prefix,
1112
+ elements.map((e) => e.name).join(" | "),
1113
+ () =>
1114
+ arrow(
1115
+ FeatureProgrammer.parameterDeclarations(
1116
+ config,
1117
+ )(TypeFactory.keyword("any"))(
1118
+ ts.factory.createIdentifier("input"),
1119
+ ),
1120
+ )({
1121
+ ...explore,
1122
+ postfix: "",
1123
+ })(ts.factory.createIdentifier("input")),
1124
+ ),
1125
+ ),
1126
+ undefined,
1127
+ FeatureProgrammer.argumentsArray(config)(explore)(input),
1128
+ ),
1129
+ config.joiner.failure(
1130
+ input,
1131
+ elements.map((e) => e.name).join(" | "),
1132
+ explore,
1133
+ ),
1134
+ );
1135
+ };
1136
+
1137
+ const explore_objects =
1138
+ (config: IConfig) =>
1139
+ (importer: FunctionImporter) =>
1140
+ (input: ts.Expression, meta: Metadata, explore: IExplore) =>
1141
+ meta.objects.length === 1
1142
+ ? decode_object(config)(importer)(
1143
+ input,
1144
+ meta.objects[0]!,
1145
+ explore,
1146
+ )
1147
+ : ts.factory.createCallExpression(
1148
+ ts.factory.createIdentifier(
1149
+ importer.useLocal(
1150
+ `${config.prefix}u${meta.union_index!}`,
1151
+ ),
1152
+ ),
1153
+ undefined,
1154
+ FeatureProgrammer.argumentsArray(config)(explore)(input),
1155
+ );
1156
+ }
1157
+
1158
+ const create_add =
1159
+ (binaries: CheckerProgrammer.IBinary[]) =>
1160
+ (defaultInput: ts.Expression) =>
1161
+ (
1162
+ exact: boolean,
1163
+ left: ts.Expression,
1164
+ right: ts.Expression = defaultInput,
1165
+ ) => {
1166
+ const factory = exact
1167
+ ? ts.factory.createStrictEquality
1168
+ : ts.factory.createStrictInequality;
1169
+ binaries.push({
1170
+ expression: factory(left, right),
1171
+ combined: false,
1172
+ });
1173
+ };