typia 4.0.0-dev.20230520 → 4.0.0-dev.20230527

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