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

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