typia 3.7.5-dev.20230413 → 3.7.6

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