typia 3.5.8 → 3.6.0-dev.20230225

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