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