typia 13.1.1 → 13.2.0

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 (581) hide show
  1. package/README.md +3 -0
  2. package/lib/_virtual/_rolldown/runtime.mjs +1 -5
  3. package/lib/executable/FileSystemIdentity.d.ts +44 -0
  4. package/lib/executable/FileSystemIdentity.js +213 -0
  5. package/lib/executable/FileSystemIdentity.js.map +1 -0
  6. package/lib/executable/FileSystemIdentity.mjs +133 -0
  7. package/lib/executable/FileSystemIdentity.mjs.map +1 -0
  8. package/lib/executable/TypiaGenerateWizard.js +272 -106
  9. package/lib/executable/TypiaGenerateWizard.js.map +1 -1
  10. package/lib/executable/TypiaGenerateWizard.mjs +239 -95
  11. package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
  12. package/lib/functional.d.ts +15 -12
  13. package/lib/functional.js.map +1 -1
  14. package/lib/functional.mjs.map +1 -1
  15. package/lib/internal/_ProtobufReader.d.ts +32 -0
  16. package/lib/internal/_ProtobufReader.js +148 -48
  17. package/lib/internal/_ProtobufReader.js.map +1 -1
  18. package/lib/internal/_ProtobufReader.mjs +137 -41
  19. package/lib/internal/_ProtobufReader.mjs.map +1 -1
  20. package/lib/internal/_createStandardSchema.js +18 -1
  21. package/lib/internal/_createStandardSchema.js.map +1 -1
  22. package/lib/internal/_createStandardSchema.mjs +12 -1
  23. package/lib/internal/_createStandardSchema.mjs.map +1 -1
  24. package/lib/internal/_decimal.d.ts +14 -0
  25. package/lib/internal/_decimal.js +61 -0
  26. package/lib/internal/_decimal.js.map +1 -0
  27. package/lib/internal/_decimal.mjs +49 -0
  28. package/lib/internal/_decimal.mjs.map +1 -0
  29. package/lib/internal/_httpQueryParseURLSearchParams.js +23 -2
  30. package/lib/internal/_httpQueryParseURLSearchParams.js.map +1 -1
  31. package/lib/internal/_httpQueryParseURLSearchParams.mjs +20 -2
  32. package/lib/internal/_httpQueryParseURLSearchParams.mjs.map +1 -1
  33. package/lib/internal/_isFormatByte.js +2 -5
  34. package/lib/internal/_isFormatByte.js.map +1 -1
  35. package/lib/internal/_isFormatByte.mjs +2 -5
  36. package/lib/internal/_isFormatByte.mjs.map +1 -1
  37. package/lib/internal/_isFormatDate.js +15 -2
  38. package/lib/internal/_isFormatDate.js.map +1 -1
  39. package/lib/internal/_isFormatDate.mjs +22 -2
  40. package/lib/internal/_isFormatDate.mjs.map +1 -1
  41. package/lib/internal/_isFormatDateTime.js +21 -2
  42. package/lib/internal/_isFormatDateTime.js.map +1 -1
  43. package/lib/internal/_isFormatDateTime.mjs +13 -2
  44. package/lib/internal/_isFormatDateTime.mjs.map +1 -1
  45. package/lib/internal/_isFormatIri.js +3 -2
  46. package/lib/internal/_isFormatIri.js.map +1 -1
  47. package/lib/internal/_isFormatIri.mjs +3 -2
  48. package/lib/internal/_isFormatIri.mjs.map +1 -1
  49. package/lib/internal/_isFormatIriReference.js +10 -2
  50. package/lib/internal/_isFormatIriReference.js.map +1 -1
  51. package/lib/internal/_isFormatIriReference.mjs +9 -2
  52. package/lib/internal/_isFormatIriReference.mjs.map +1 -1
  53. package/lib/internal/_isFormatUriReference.js +1 -1
  54. package/lib/internal/_isFormatUriReference.js.map +1 -1
  55. package/lib/internal/_isFormatUriReference.mjs +1 -1
  56. package/lib/internal/_isFormatUriReference.mjs.map +1 -1
  57. package/lib/internal/_isMultipleOf.d.ts +1 -0
  58. package/lib/internal/_isMultipleOf.js +13 -0
  59. package/lib/internal/_isMultipleOf.js.map +1 -0
  60. package/lib/internal/_isMultipleOf.mjs +12 -0
  61. package/lib/internal/_isMultipleOf.mjs.map +1 -0
  62. package/lib/internal/_isTypeFloat.js +1 -1
  63. package/lib/internal/_isTypeFloat.js.map +1 -1
  64. package/lib/internal/_isTypeFloat.mjs +1 -1
  65. package/lib/internal/_isTypeFloat.mjs.map +1 -1
  66. package/lib/internal/_isTypeInt64.js +1 -0
  67. package/lib/internal/_isTypeInt64.js.map +1 -1
  68. package/lib/internal/_isTypeInt64.mjs.map +1 -1
  69. package/lib/internal/_isTypeInt64Bigint.d.ts +1 -0
  70. package/lib/internal/_isTypeInt64Bigint.js +15 -0
  71. package/lib/internal/_isTypeInt64Bigint.js.map +1 -0
  72. package/lib/internal/_isTypeInt64Bigint.mjs +8 -0
  73. package/lib/internal/_isTypeInt64Bigint.mjs.map +1 -0
  74. package/lib/internal/_isTypeUint64.js +1 -0
  75. package/lib/internal/_isTypeUint64.js.map +1 -1
  76. package/lib/internal/_isTypeUint64.mjs.map +1 -1
  77. package/lib/internal/_isTypeUint64Bigint.d.ts +1 -0
  78. package/lib/internal/_isTypeUint64Bigint.js +10 -0
  79. package/lib/internal/_isTypeUint64Bigint.js.map +1 -0
  80. package/lib/internal/_isTypeUint64Bigint.mjs +8 -0
  81. package/lib/internal/_isTypeUint64Bigint.mjs.map +1 -0
  82. package/lib/internal/_isUniqueItems.js +96 -109
  83. package/lib/internal/_isUniqueItems.js.map +1 -1
  84. package/lib/internal/_isUniqueItems.mjs +62 -50
  85. package/lib/internal/_isUniqueItems.mjs.map +1 -1
  86. package/lib/internal/_jsonStringifyArray.d.ts +1 -0
  87. package/lib/internal/_jsonStringifyArray.js +48 -0
  88. package/lib/internal/_jsonStringifyArray.js.map +1 -0
  89. package/lib/internal/_jsonStringifyArray.mjs +40 -0
  90. package/lib/internal/_jsonStringifyArray.mjs.map +1 -0
  91. package/lib/internal/_jsonStringifyElement.d.ts +1 -0
  92. package/lib/internal/_jsonStringifyElement.js +23 -0
  93. package/lib/internal/_jsonStringifyElement.js.map +1 -0
  94. package/lib/internal/_jsonStringifyElement.mjs +23 -0
  95. package/lib/internal/_jsonStringifyElement.mjs.map +1 -0
  96. package/lib/internal/_jsonStringifyProperty.d.ts +1 -0
  97. package/lib/internal/_jsonStringifyProperty.js +31 -0
  98. package/lib/internal/_jsonStringifyProperty.js.map +1 -0
  99. package/lib/internal/_jsonStringifyProperty.mjs +31 -0
  100. package/lib/internal/_jsonStringifyProperty.mjs.map +1 -0
  101. package/lib/internal/_llmApplicationFinalize.js +1 -1
  102. package/lib/internal/_llmApplicationFinalize.js.map +1 -1
  103. package/lib/internal/_llmApplicationFinalize.mjs +1 -1
  104. package/lib/internal/_llmApplicationFinalize.mjs.map +1 -1
  105. package/lib/internal/_notationAny.js +8 -1
  106. package/lib/internal/_notationAny.js.map +1 -1
  107. package/lib/internal/_notationAny.mjs +7 -1
  108. package/lib/internal/_notationAny.mjs.map +1 -1
  109. package/lib/internal/_notationAssign.d.ts +1 -0
  110. package/lib/internal/_notationAssign.js +18 -0
  111. package/lib/internal/_notationAssign.js.map +1 -0
  112. package/lib/internal/_notationAssign.mjs +17 -0
  113. package/lib/internal/_notationAssign.mjs.map +1 -0
  114. package/lib/internal/_notationCamel.js +30 -9
  115. package/lib/internal/_notationCamel.js.map +1 -1
  116. package/lib/internal/_notationCamel.mjs +13 -5
  117. package/lib/internal/_notationCamel.mjs.map +1 -1
  118. package/lib/internal/_notationKebab.d.ts +1 -0
  119. package/lib/internal/_notationKebab.js +15 -0
  120. package/lib/internal/_notationKebab.js.map +1 -0
  121. package/lib/internal/_notationKebab.mjs +15 -0
  122. package/lib/internal/_notationKebab.mjs.map +1 -0
  123. package/lib/internal/_notationKeyCollision.d.ts +1 -0
  124. package/lib/internal/_notationKeyCollision.js +8 -0
  125. package/lib/internal/_notationKeyCollision.js.map +1 -0
  126. package/lib/internal/_notationKeyCollision.mjs +8 -0
  127. package/lib/internal/_notationKeyCollision.mjs.map +1 -0
  128. package/lib/internal/_notationPascal.js +20 -5
  129. package/lib/internal/_notationPascal.js.map +1 -1
  130. package/lib/internal/_notationPascal.mjs +10 -5
  131. package/lib/internal/_notationPascal.mjs.map +1 -1
  132. package/lib/internal/_notationSnake.js +25 -22
  133. package/lib/internal/_notationSnake.js.map +1 -1
  134. package/lib/internal/_notationSnake.mjs +11 -11
  135. package/lib/internal/_notationSnake.mjs.map +1 -1
  136. package/lib/internal/_plainCloneAny.js +174 -38
  137. package/lib/internal/_plainCloneAny.js.map +1 -1
  138. package/lib/internal/_plainCloneAny.mjs +126 -22
  139. package/lib/internal/_plainCloneAny.mjs.map +1 -1
  140. package/lib/internal/_randomArray.d.ts +1 -1
  141. package/lib/internal/_randomArray.js +11 -4
  142. package/lib/internal/_randomArray.js.map +1 -1
  143. package/lib/internal/_randomArray.mjs +9 -3
  144. package/lib/internal/_randomArray.mjs.map +1 -1
  145. package/lib/internal/_randomFormatByte.d.ts +2 -1
  146. package/lib/internal/_randomFormatByte.js +25 -1
  147. package/lib/internal/_randomFormatByte.js.map +1 -1
  148. package/lib/internal/_randomFormatByte.mjs +20 -1
  149. package/lib/internal/_randomFormatByte.mjs.map +1 -1
  150. package/lib/internal/_randomFormatDate.d.ts +3 -4
  151. package/lib/internal/_randomFormatDate.js +3 -10
  152. package/lib/internal/_randomFormatDate.js.map +1 -1
  153. package/lib/internal/_randomFormatDate.mjs +3 -6
  154. package/lib/internal/_randomFormatDate.mjs.map +1 -1
  155. package/lib/internal/_randomFormatDatetime.d.ts +3 -4
  156. package/lib/internal/_randomFormatDatetime.js +26 -8
  157. package/lib/internal/_randomFormatDatetime.js.map +1 -1
  158. package/lib/internal/_randomFormatDatetime.mjs +17 -6
  159. package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
  160. package/lib/internal/_randomFormatDuration.d.ts +2 -1
  161. package/lib/internal/_randomFormatDuration.js +23 -14
  162. package/lib/internal/_randomFormatDuration.js.map +1 -1
  163. package/lib/internal/_randomFormatDuration.mjs +22 -13
  164. package/lib/internal/_randomFormatDuration.mjs.map +1 -1
  165. package/lib/internal/_randomFormatEmail.d.ts +2 -1
  166. package/lib/internal/_randomFormatEmail.js +8 -1
  167. package/lib/internal/_randomFormatEmail.js.map +1 -1
  168. package/lib/internal/_randomFormatEmail.mjs +5 -1
  169. package/lib/internal/_randomFormatEmail.mjs.map +1 -1
  170. package/lib/internal/_randomFormatHostname.d.ts +8 -1
  171. package/lib/internal/_randomFormatHostname.js +45 -2
  172. package/lib/internal/_randomFormatHostname.js.map +1 -1
  173. package/lib/internal/_randomFormatHostname.mjs +38 -2
  174. package/lib/internal/_randomFormatHostname.mjs.map +1 -1
  175. package/lib/internal/_randomFormatIdnEmail.d.ts +2 -1
  176. package/lib/internal/_randomFormatIdnEmail.js +16 -2
  177. package/lib/internal/_randomFormatIdnEmail.js.map +1 -1
  178. package/lib/internal/_randomFormatIdnEmail.mjs +11 -2
  179. package/lib/internal/_randomFormatIdnEmail.mjs.map +1 -1
  180. package/lib/internal/_randomFormatIdnHostname.d.ts +2 -1
  181. package/lib/internal/_randomFormatIdnHostname.js +26 -1
  182. package/lib/internal/_randomFormatIdnHostname.js.map +1 -1
  183. package/lib/internal/_randomFormatIdnHostname.mjs +25 -2
  184. package/lib/internal/_randomFormatIdnHostname.mjs.map +1 -1
  185. package/lib/internal/_randomFormatIpv4.d.ts +2 -1
  186. package/lib/internal/_randomFormatIpv4.js +32 -1
  187. package/lib/internal/_randomFormatIpv4.js.map +1 -1
  188. package/lib/internal/_randomFormatIpv4.mjs +23 -1
  189. package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
  190. package/lib/internal/_randomFormatIpv6.d.ts +2 -1
  191. package/lib/internal/_randomFormatIpv6.js +58 -1
  192. package/lib/internal/_randomFormatIpv6.js.map +1 -1
  193. package/lib/internal/_randomFormatIpv6.mjs +45 -1
  194. package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
  195. package/lib/internal/_randomFormatIri.d.ts +2 -1
  196. package/lib/internal/_randomFormatIri.js +1 -1
  197. package/lib/internal/_randomFormatIri.js.map +1 -1
  198. package/lib/internal/_randomFormatIri.mjs +1 -1
  199. package/lib/internal/_randomFormatIri.mjs.map +1 -1
  200. package/lib/internal/_randomFormatIriReference.d.ts +2 -1
  201. package/lib/internal/_randomFormatIriReference.js +1 -1
  202. package/lib/internal/_randomFormatIriReference.js.map +1 -1
  203. package/lib/internal/_randomFormatIriReference.mjs +1 -1
  204. package/lib/internal/_randomFormatIriReference.mjs.map +1 -1
  205. package/lib/internal/_randomFormatJsonPointer.d.ts +2 -1
  206. package/lib/internal/_randomFormatJsonPointer.js +20 -1
  207. package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
  208. package/lib/internal/_randomFormatJsonPointer.mjs +15 -1
  209. package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
  210. package/lib/internal/_randomFormatPassword.d.ts +2 -1
  211. package/lib/internal/_randomFormatPassword.js +7 -5
  212. package/lib/internal/_randomFormatPassword.js.map +1 -1
  213. package/lib/internal/_randomFormatPassword.mjs +5 -1
  214. package/lib/internal/_randomFormatPassword.mjs.map +1 -1
  215. package/lib/internal/_randomFormatRegex.d.ts +2 -1
  216. package/lib/internal/_randomFormatRegex.js +15 -1
  217. package/lib/internal/_randomFormatRegex.js.map +1 -1
  218. package/lib/internal/_randomFormatRegex.mjs +14 -1
  219. package/lib/internal/_randomFormatRegex.mjs.map +1 -1
  220. package/lib/internal/_randomFormatRelativeJsonPointer.d.ts +2 -1
  221. package/lib/internal/_randomFormatRelativeJsonPointer.js +20 -5
  222. package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
  223. package/lib/internal/_randomFormatRelativeJsonPointer.mjs +21 -5
  224. package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
  225. package/lib/internal/_randomFormatTime.d.ts +2 -1
  226. package/lib/internal/_randomFormatTime.js +34 -7
  227. package/lib/internal/_randomFormatTime.js.map +1 -1
  228. package/lib/internal/_randomFormatTime.mjs +37 -4
  229. package/lib/internal/_randomFormatTime.mjs.map +1 -1
  230. package/lib/internal/_randomFormatUri.d.ts +2 -1
  231. package/lib/internal/_randomFormatUri.js +1 -1
  232. package/lib/internal/_randomFormatUri.js.map +1 -1
  233. package/lib/internal/_randomFormatUri.mjs +1 -1
  234. package/lib/internal/_randomFormatUri.mjs.map +1 -1
  235. package/lib/internal/_randomFormatUriReference.d.ts +2 -1
  236. package/lib/internal/_randomFormatUriReference.js +1 -1
  237. package/lib/internal/_randomFormatUriReference.js.map +1 -1
  238. package/lib/internal/_randomFormatUriReference.mjs +1 -1
  239. package/lib/internal/_randomFormatUriReference.mjs.map +1 -1
  240. package/lib/internal/_randomFormatUriTemplate.d.ts +2 -1
  241. package/lib/internal/_randomFormatUriTemplate.js +1 -1
  242. package/lib/internal/_randomFormatUriTemplate.js.map +1 -1
  243. package/lib/internal/_randomFormatUriTemplate.mjs +1 -1
  244. package/lib/internal/_randomFormatUriTemplate.mjs.map +1 -1
  245. package/lib/internal/_randomFormatUrl.d.ts +2 -1
  246. package/lib/internal/_randomFormatUrl.js +21 -1
  247. package/lib/internal/_randomFormatUrl.js.map +1 -1
  248. package/lib/internal/_randomFormatUrl.mjs +18 -1
  249. package/lib/internal/_randomFormatUrl.mjs.map +1 -1
  250. package/lib/internal/_randomFormatUuid.d.ts +2 -1
  251. package/lib/internal/_randomFormatUuid.js +3 -2
  252. package/lib/internal/_randomFormatUuid.js.map +1 -1
  253. package/lib/internal/_randomFormatUuid.mjs +3 -2
  254. package/lib/internal/_randomFormatUuid.mjs.map +1 -1
  255. package/lib/internal/_randomInteger.js +59 -28
  256. package/lib/internal/_randomInteger.js.map +1 -1
  257. package/lib/internal/_randomInteger.mjs +56 -16
  258. package/lib/internal/_randomInteger.mjs.map +1 -1
  259. package/lib/internal/_randomMultiple.d.ts +8 -0
  260. package/lib/internal/_randomMultiple.js +168 -0
  261. package/lib/internal/_randomMultiple.js.map +1 -0
  262. package/lib/internal/_randomMultiple.mjs +158 -0
  263. package/lib/internal/_randomMultiple.mjs.map +1 -0
  264. package/lib/internal/_randomNumber.js +42 -42
  265. package/lib/internal/_randomNumber.js.map +1 -1
  266. package/lib/internal/_randomNumber.mjs +41 -27
  267. package/lib/internal/_randomNumber.mjs.map +1 -1
  268. package/lib/internal/_randomPattern.d.ts +2 -1
  269. package/lib/internal/_randomPattern.js +19 -4
  270. package/lib/internal/_randomPattern.js.map +1 -1
  271. package/lib/internal/_randomPattern.mjs +10 -4
  272. package/lib/internal/_randomPattern.mjs.map +1 -1
  273. package/lib/internal/_randomStringLength.d.ts +64 -0
  274. package/lib/internal/_randomStringLength.js +84 -0
  275. package/lib/internal/_randomStringLength.js.map +1 -0
  276. package/lib/internal/_randomStringLength.mjs +79 -0
  277. package/lib/internal/_randomStringLength.mjs.map +1 -0
  278. package/lib/internal/_stringLength.d.ts +1 -0
  279. package/lib/internal/_stringLength.js +11 -0
  280. package/lib/internal/_stringLength.js.map +1 -0
  281. package/lib/internal/_stringLength.mjs +10 -0
  282. package/lib/internal/_stringLength.mjs.map +1 -0
  283. package/lib/internal/_validateReport.js +4 -1
  284. package/lib/internal/_validateReport.js.map +1 -1
  285. package/lib/internal/_validateReport.mjs +2 -1
  286. package/lib/internal/_validateReport.mjs.map +1 -1
  287. package/lib/internal/private/__notationRename.d.ts +14 -0
  288. package/lib/internal/private/__notationRename.js +25 -0
  289. package/lib/internal/private/__notationRename.js.map +1 -0
  290. package/lib/internal/private/__notationRename.mjs +24 -0
  291. package/lib/internal/private/__notationRename.mjs.map +1 -0
  292. package/lib/internal/private/__randomComposition.d.ts +23 -0
  293. package/lib/internal/private/__randomComposition.js +48 -0
  294. package/lib/internal/private/__randomComposition.js.map +1 -0
  295. package/lib/internal/private/__randomComposition.mjs +54 -0
  296. package/lib/internal/private/__randomComposition.mjs.map +1 -0
  297. package/lib/internal/private/__randomEpoch.d.ts +19 -0
  298. package/lib/internal/private/__randomEpoch.js +31 -0
  299. package/lib/internal/private/__randomEpoch.js.map +1 -0
  300. package/lib/internal/private/__randomEpoch.mjs +28 -0
  301. package/lib/internal/private/__randomEpoch.mjs.map +1 -0
  302. package/lib/json.d.ts +2 -2
  303. package/lib/json.mjs.map +1 -1
  304. package/lib/module.d.ts +2 -2
  305. package/lib/module.js.map +1 -1
  306. package/lib/module.mjs.map +1 -1
  307. package/lib/notations.d.ts +20 -4
  308. package/lib/notations.js.map +1 -1
  309. package/lib/notations.mjs.map +1 -1
  310. package/native/adapter/plugin_options.go +117 -0
  311. package/native/adapter/plugin_options_payload_matrix_test.go +181 -0
  312. package/native/cmd/ttsc-typia/any_array_type_tags_transform_test.go +63 -9
  313. package/native/cmd/ttsc-typia/assert_guard_factory_contract_test.go +152 -0
  314. package/native/cmd/ttsc-typia/build.go +84 -64
  315. package/native/cmd/ttsc-typia/build_no_emit_preserves_analysis_options_test.go +67 -0
  316. package/native/cmd/ttsc-typia/build_no_emit_transform_diagnostics_test.go +138 -0
  317. package/native/cmd/ttsc-typia/build_plugin_options_come_from_payload_test.go +48 -0
  318. package/native/cmd/ttsc-typia/build_transactional_emit_success_test.go +81 -0
  319. package/native/cmd/ttsc-typia/build_transform_failure_atomicity_test.go +138 -0
  320. package/native/cmd/ttsc-typia/callable_interface_function_semantics_transform_test.go +331 -0
  321. package/native/cmd/ttsc-typia/callable_type_literal_boundaries_transform_test.go +1184 -0
  322. package/native/cmd/ttsc-typia/command_routes_and_diagnostics_coverage_test.go +3 -1
  323. package/native/cmd/ttsc-typia/compare_functional_union_membership_transform_test.go +434 -0
  324. package/native/cmd/ttsc-typia/compare_less_nan_transform_test.go +98 -0
  325. package/native/cmd/ttsc-typia/compare_native_object_overmatch_transform_test.go +161 -0
  326. package/native/cmd/ttsc-typia/compare_nondiscriminable_union_transform_test.go +343 -0
  327. package/native/cmd/ttsc-typia/compare_template_literal_union_transform_test.go +241 -0
  328. package/native/cmd/ttsc-typia/compare_union_discrimination_transform_test.go +289 -0
  329. package/native/cmd/ttsc-typia/default_library_spoof_native_identity_transform_test.go +216 -0
  330. package/native/cmd/ttsc-typia/escaped_property_key_path_transform_test.go +193 -0
  331. package/native/cmd/ttsc-typia/finite_option_number_leaf_transform_test.go +240 -0
  332. package/native/cmd/ttsc-typia/functional_promised_type_transform_test.go +220 -0
  333. package/native/cmd/ttsc-typia/functional_receiver_transform_test.go +232 -0
  334. package/native/cmd/ttsc-typia/is_object_function_member_transform_test.go +205 -0
  335. package/native/cmd/ttsc-typia/json_application_alias_function_validation_transform_test.go +151 -0
  336. package/native/cmd/ttsc-typia/json_is_stringify_finite_number_transform_test.go +198 -0
  337. package/native/cmd/ttsc-typia/json_schema_dynamic_key_determinism_transform_test.go +246 -0
  338. package/native/cmd/ttsc-typia/json_stringify_contextual_undefined_transform_test.go +556 -0
  339. package/native/cmd/ttsc-typia/json_stringify_special_key_transform_test.go +238 -0
  340. package/native/cmd/ttsc-typia/lib_replacement_native_identity_transform_test.go +277 -0
  341. package/native/cmd/ttsc-typia/main_wasm.go +21 -2
  342. package/native/cmd/ttsc-typia/native_collection_identity_is_transform_test.go +234 -0
  343. package/native/cmd/ttsc-typia/native_generic_name_guard_is_transform_test.go +194 -0
  344. package/native/cmd/ttsc-typia/native_name_collision_is_transform_test.go +204 -0
  345. package/native/cmd/ttsc-typia/native_named_intersection_union_transform_test.go +390 -0
  346. package/native/cmd/ttsc-typia/node_buffer_native_exports_is_transform_test.go +526 -0
  347. package/native/cmd/ttsc-typia/non_trailing_rest_tuple_transform_test.go +23 -11
  348. package/native/cmd/ttsc-typia/notation_dynamic_keys_transform_test.go +286 -0
  349. package/native/cmd/ttsc-typia/notation_kebab_case_transform_test.go +1 -1
  350. package/native/cmd/ttsc-typia/notation_literal_collision_transform_test.go +164 -0
  351. package/native/cmd/ttsc-typia/notation_pascal_case_transform_test.go +230 -0
  352. package/native/cmd/ttsc-typia/notation_unicode_key_transform_test.go +309 -0
  353. package/native/cmd/ttsc-typia/package_declaration_native_identity_is_transform_test.go +293 -0
  354. package/native/cmd/ttsc-typia/pattern_line_terminator_escape_transform_test.go +224 -0
  355. package/native/cmd/ttsc-typia/plain_prune_union_object_overmatch_transform_test.go +219 -0
  356. package/native/cmd/ttsc-typia/plugin_options_payload_helpers_test.go +181 -0
  357. package/native/cmd/ttsc-typia/private_field_filter_is_transform_test.go +278 -0
  358. package/native/cmd/ttsc-typia/project_catalog_transform_coverage_test.go +73 -27
  359. package/native/cmd/ttsc-typia/project_dependencies_barrel_reexport_transform_test.go +120 -0
  360. package/native/cmd/ttsc-typia/project_dependencies_collapsed_alias_transform_test.go +134 -0
  361. package/native/cmd/ttsc-typia/project_dependencies_custom_lib_name_transform_test.go +135 -0
  362. package/native/cmd/ttsc-typia/project_dependencies_default_barrel_transform_test.go +114 -0
  363. package/native/cmd/ttsc-typia/project_dependencies_empty_heritage_transform_test.go +100 -0
  364. package/native/cmd/ttsc-typia/project_dependencies_envelope_transform_test.go +148 -0
  365. package/native/cmd/ttsc-typia/project_dependencies_index_signature_alias_transform_test.go +139 -0
  366. package/native/cmd/ttsc-typia/project_dependencies_local_reexport_transform_test.go +122 -0
  367. package/native/cmd/ttsc-typia/project_dependencies_signature_alias_transform_test.go +125 -0
  368. package/native/cmd/ttsc-typia/project_dependencies_star_barrel_transform_test.go +112 -0
  369. package/native/cmd/ttsc-typia/project_reference_graph_envelope_transform_test.go +190 -0
  370. package/native/cmd/ttsc-typia/protobuf_diagnostic_code_transform_test.go +167 -0
  371. package/native/cmd/ttsc-typia/protobuf_is_encode_finite_number_transform_test.go +98 -0
  372. package/native/cmd/ttsc-typia/protobuf_sequence_field_numbers_transform_test.go +52 -22
  373. package/native/cmd/ttsc-typia/symbol_index_domain_transform_test.go +316 -0
  374. package/native/cmd/ttsc-typia/symbol_key_member_filter_transform_test.go +279 -0
  375. package/native/cmd/ttsc-typia/template_interpolation_type_tags_transform_test.go +86 -23
  376. package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +3 -1
  377. package/native/cmd/ttsc-typia/transform.go +251 -39
  378. package/native/cmd/ttsc-typia/{transform_declaration_source_produces_no_js_test.go → transform_declaration_source_produces_no_javascript_test.go} +10 -2
  379. package/native/cmd/ttsc-typia/transform_fixtures_emit_coverage_test.go +21 -4
  380. package/native/cmd/ttsc-typia/transform_helpers_test.go +236 -3
  381. package/native/cmd/ttsc-typia/transform_plugin_options_come_from_payload_test.go +43 -0
  382. package/native/cmd/ttsc-typia/transform_single_file_failure_atomicity_test.go +114 -0
  383. package/native/cmd/ttsc-typia/transform_single_file_failure_writes_no_stdout_test.go +43 -0
  384. package/native/cmd/ttsc-typia/transform_single_file_js_distinguishes_same_basename_sources_test.go +81 -0
  385. package/native/cmd/ttsc-typia/transform_single_file_js_empty_emit_reports_no_output_test.go +100 -0
  386. package/native/cmd/ttsc-typia/transform_single_file_js_locates_output_across_layouts_test.go +160 -0
  387. package/native/cmd/ttsc-typia/transform_single_file_success_publishes_artifact_test.go +54 -0
  388. package/native/cmd/ttsc-typia/transform_wasm_host_argv_reports_diagnostics_test.go +39 -0
  389. package/native/cmd/ttsc-typia/tuple_optional_compare_clone_transform_test.go +227 -0
  390. package/native/cmd/ttsc-typia/user_global_native_identity_transform_test.go +484 -0
  391. package/native/core/factories/FormatCheatSheet.go +40 -7
  392. package/native/core/factories/IdentifierFactory.go +131 -4
  393. package/native/core/factories/MetadataCommentTagFactory.go +83 -40
  394. package/native/core/factories/MetadataTypeTagFactory.go +13 -1
  395. package/native/core/factories/NumericRangeFactory.go +60 -17
  396. package/native/core/factories/ProtobufFactory.go +13 -5
  397. package/native/core/factories/factory_utility_coverage_test.go +8 -2
  398. package/native/core/factories/format_alias_resolves_to_cheat_sheet_test.go +57 -0
  399. package/native/core/factories/format_alias_table_targets_the_cheat_sheet_test.go +44 -0
  400. package/native/core/factories/identifier_factory_postfix_escapes_every_key_test.go +147 -0
  401. package/native/core/factories/identifier_factory_postfix_survives_every_code_point_test.go +86 -0
  402. package/native/core/factories/internal/metadata/MetadataHelper.go +226 -17
  403. package/native/core/factories/internal/metadata/emplace_metadata_object.go +141 -8
  404. package/native/core/factories/internal/metadata/iterate_metadata.go +6 -0
  405. package/native/core/factories/internal/metadata/iterate_metadata_function.go +5 -12
  406. package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +111 -29
  407. package/native/core/factories/internal/metadata/iterate_metadata_map.go +5 -0
  408. package/native/core/factories/internal/metadata/iterate_metadata_native.go +45 -2
  409. package/native/core/factories/internal/metadata/iterate_metadata_set.go +5 -0
  410. package/native/core/factories/internal/metadata/type_arguments_precondition_test.go +70 -0
  411. package/native/core/factories/metadata_comment_tag_factory_coverage_test.go +39 -0
  412. package/native/core/factories/metadata_comment_tag_factory_exclusivity_matches_interface_test.go +84 -0
  413. package/native/core/factories/metadata_type_tag_factory_accepts_legal_tag_combinations_test.go +60 -0
  414. package/native/core/factories/metadata_type_tag_factory_declarations_test.go +86 -0
  415. package/native/core/factories/metadata_type_tag_factory_keeps_bool_form_exclusivity_test.go +38 -0
  416. package/native/core/factories/metadata_type_tag_factory_rejects_cross_kind_exclusive_tags_test.go +65 -0
  417. package/native/core/factories/metadata_type_tag_factory_rejects_duplicated_array_form_tags_test.go +41 -0
  418. package/native/core/factories/numeric_range_factory_enforces_64bit_bounds_test.go +69 -0
  419. package/native/core/factories/protobuf_recovery_ownership_test.go +64 -0
  420. package/native/core/programmers/IsProgrammer.go +15 -1
  421. package/native/core/programmers/RandomProgrammer.go +51 -14
  422. package/native/core/programmers/compare/CompareEqualProgrammer.go +410 -8
  423. package/native/core/programmers/compare/CompareLessProgrammer.go +4 -2
  424. package/native/core/programmers/functional/FunctionalAssertFunctionProgrammer.go +4 -6
  425. package/native/core/programmers/functional/FunctionalAssertParametersProgrammer.go +5 -13
  426. package/native/core/programmers/functional/FunctionalAssertReturnProgrammer.go +6 -14
  427. package/native/core/programmers/functional/FunctionalIsFunctionProgrammer.go +4 -6
  428. package/native/core/programmers/functional/FunctionalIsParametersProgrammer.go +49 -14
  429. package/native/core/programmers/functional/FunctionalIsReturnProgrammer.go +5 -13
  430. package/native/core/programmers/functional/FunctionalValidateFunctionProgrammer.go +4 -6
  431. package/native/core/programmers/functional/FunctionalValidateParametersProgrammer.go +5 -13
  432. package/native/core/programmers/functional/FunctionalValidateReturnProgrammer.go +5 -13
  433. package/native/core/programmers/functional/internal/FunctionalGeneralProgrammer.go +4 -17
  434. package/native/core/programmers/helpers/CloneJoiner.go +32 -0
  435. package/native/core/programmers/helpers/FunctionProgrammer.go +6 -13
  436. package/native/core/programmers/helpers/NotationJoiner.go +86 -28
  437. package/native/core/programmers/helpers/StringifyJoinder.go +161 -51
  438. package/native/core/programmers/helpers/UnionExplorer.go +203 -61
  439. package/native/core/programmers/helpers/joiner_branch_coverage_test.go +116 -118
  440. package/native/core/programmers/helpers/union_explorer_coverage_test.go +1 -1
  441. package/native/core/programmers/internal/CheckerProgrammer.go +100 -48
  442. package/native/core/programmers/iterate/check_template.go +344 -32
  443. package/native/core/programmers/iterate/iterate_check_coverage_test.go +76 -158
  444. package/native/core/programmers/iterate/iterate_utility_coverage_test.go +231 -270
  445. package/native/core/programmers/iterate/json_schema_discriminator.go +36 -10
  446. package/native/core/programmers/iterate/json_schema_discriminator_declaration_syntax_test.go +205 -0
  447. package/native/core/programmers/iterate/json_schema_object.go +49 -7
  448. package/native/core/programmers/iterate/json_schema_pattern_property_order_test.go +44 -0
  449. package/native/core/programmers/iterate/openapi_v3_downgrader.go +674 -0
  450. package/native/core/programmers/iterate/openapi_v3_downgrader_boolean_default_test.go +95 -0
  451. package/native/core/programmers/iterate/openapi_v3_downgrader_test.go +123 -0
  452. package/native/core/programmers/iterate/template_interpolation_tags_test.go +40 -8
  453. package/native/core/programmers/iterate/template_runtime_pattern.go +63 -7
  454. package/native/core/programmers/json/JsonApplicationProgrammer.go +45 -11
  455. package/native/core/programmers/json/JsonSchemasProgrammer.go +12 -2
  456. package/native/core/programmers/json/JsonStringifyProgrammer.go +47 -6
  457. package/native/core/programmers/llm/LlmApplicationProgrammer.go +21 -11
  458. package/native/core/programmers/llm/LlmSchemaProgrammer.go +23 -6
  459. package/native/core/programmers/llm/llm_reference_codec_test.go +24 -0
  460. package/native/core/programmers/notations/NotationGeneralProgrammer.go +183 -67
  461. package/native/core/programmers/notations/notation_general_helpers_test.go +1 -3
  462. package/native/core/programmers/notations/notation_general_programmer_pascal_multiword_test.go +72 -0
  463. package/native/core/programmers/notations/notation_general_programmer_underscore_boundary_test.go +68 -0
  464. package/native/core/programmers/plain/PlainClassifyProgrammer.go +23 -15
  465. package/native/core/programmers/plain/PlainCloneProgrammer.go +20 -7
  466. package/native/core/programmers/plain/PlainPruneProgrammer.go +19 -5
  467. package/native/core/programmers/plain/plain_tuple_seed_recovery_ownership_test.go +25 -0
  468. package/native/core/programmers/protobuf/ProtobufDecodeProgrammer.go +37 -28
  469. package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +41 -22
  470. package/native/core/programmers/protobuf/protobuf_programmer_helper_coverage_test.go +26 -0
  471. package/native/core/programmers/random_programmer_length_argument_test.go +53 -0
  472. package/native/core/schemas/metadata/MetadataCollection.go +266 -25
  473. package/native/core/schemas/metadata/MetadataDefaultLibrary.go +81 -0
  474. package/native/core/schemas/metadata/MetadataDependency.go +388 -0
  475. package/native/core/schemas/metadata/MetadataObjectType.go +24 -22
  476. package/native/core/schemas/metadata/metadata_collection_generic_argument_dot_test.go +122 -0
  477. package/native/core/schemas/metadata/metadata_collection_name_allocation_test.go +147 -0
  478. package/native/core/schemas/metadata/metadata_collection_openapi_name_cascade_test.go +55 -0
  479. package/native/core/schemas/metadata/metadata_collection_openapi_name_test.go +68 -0
  480. package/native/core/utils/PatternUtil.go +13 -0
  481. package/native/core/utils/PromiseTypeFactory.go +59 -0
  482. package/native/core/utils/ProtobufNameEncoder.go +8 -0
  483. package/native/core/utils/promise_type_factory_semantics_test.go +118 -0
  484. package/native/go.mod +9 -1
  485. package/native/transform/CallExpressionTransformer.go +12 -0
  486. package/native/transform/features/json/JsonApplicationTransformer.go +1 -1
  487. package/native/transform/features/json/JsonSchemaTransformer.go +1 -1
  488. package/native/transform/features/json/JsonSchemasTransformer.go +5 -4
  489. package/native/transform/features/protobuf/ProtobufMessageTransformer.go +1 -1
  490. package/package.json +12 -4
  491. package/src/executable/FileSystemIdentity.ts +222 -0
  492. package/src/executable/TypiaGenerateWizard.ts +386 -113
  493. package/src/functional.ts +30 -60
  494. package/src/internal/_ProtobufReader.ts +161 -46
  495. package/src/internal/_createStandardSchema.ts +15 -1
  496. package/src/internal/_decimal.ts +69 -0
  497. package/src/internal/_httpQueryParseURLSearchParams.ts +24 -2
  498. package/src/internal/_isFormatByte.ts +2 -5
  499. package/src/internal/_isFormatDate.ts +15 -2
  500. package/src/internal/_isFormatDateTime.ts +28 -2
  501. package/src/internal/_isFormatIri.ts +5 -2
  502. package/src/internal/_isFormatIriReference.ts +11 -3
  503. package/src/internal/_isFormatUriReference.ts +1 -1
  504. package/src/internal/_isMultipleOf.ts +8 -0
  505. package/src/internal/_isTypeFloat.ts +1 -1
  506. package/src/internal/_isTypeInt64.ts +1 -0
  507. package/src/internal/_isTypeInt64Bigint.ts +12 -0
  508. package/src/internal/_isTypeUint64.ts +1 -0
  509. package/src/internal/_isTypeUint64Bigint.ts +7 -0
  510. package/src/internal/_isUniqueItems.ts +134 -132
  511. package/src/internal/_jsonStringifyArray.ts +50 -0
  512. package/src/internal/_jsonStringifyElement.ts +19 -0
  513. package/src/internal/_jsonStringifyProperty.ts +30 -0
  514. package/src/internal/_llmApplicationFinalize.ts +6 -1
  515. package/src/internal/_notationAny.ts +9 -4
  516. package/src/internal/_notationAssign.ts +20 -0
  517. package/src/internal/_notationCamel.ts +31 -10
  518. package/src/internal/_notationKebab.ts +11 -0
  519. package/src/internal/_notationKeyCollision.ts +9 -0
  520. package/src/internal/_notationPascal.ts +19 -6
  521. package/src/internal/_notationSnake.ts +24 -21
  522. package/src/internal/_plainCloneAny.ts +208 -33
  523. package/src/internal/_randomArray.ts +13 -4
  524. package/src/internal/_randomFormatByte.ts +31 -1
  525. package/src/internal/_randomFormatDate.ts +6 -17
  526. package/src/internal/_randomFormatDatetime.ts +34 -15
  527. package/src/internal/_randomFormatDuration.ts +30 -13
  528. package/src/internal/_randomFormatEmail.ts +8 -2
  529. package/src/internal/_randomFormatHostname.ts +48 -1
  530. package/src/internal/_randomFormatIdnEmail.ts +18 -2
  531. package/src/internal/_randomFormatIdnHostname.ts +34 -2
  532. package/src/internal/_randomFormatIpv4.ts +43 -2
  533. package/src/internal/_randomFormatIpv6.ts +67 -2
  534. package/src/internal/_randomFormatIri.ts +3 -1
  535. package/src/internal/_randomFormatIriReference.ts +3 -1
  536. package/src/internal/_randomFormatJsonPointer.ts +28 -2
  537. package/src/internal/_randomFormatPassword.ts +11 -6
  538. package/src/internal/_randomFormatRegex.ts +22 -1
  539. package/src/internal/_randomFormatRelativeJsonPointer.ts +26 -6
  540. package/src/internal/_randomFormatTime.ts +46 -10
  541. package/src/internal/_randomFormatUri.ts +3 -1
  542. package/src/internal/_randomFormatUriReference.ts +3 -1
  543. package/src/internal/_randomFormatUriTemplate.ts +3 -1
  544. package/src/internal/_randomFormatUrl.ts +25 -2
  545. package/src/internal/_randomFormatUuid.ts +10 -6
  546. package/src/internal/_randomInteger.ts +87 -40
  547. package/src/internal/_randomMultiple.ts +245 -0
  548. package/src/internal/_randomNumber.ts +72 -55
  549. package/src/internal/_randomPattern.ts +29 -4
  550. package/src/internal/_randomStringLength.ts +116 -0
  551. package/src/internal/_stringLength.ts +5 -0
  552. package/src/internal/_validateReport.ts +5 -1
  553. package/src/internal/private/__notationRename.ts +21 -0
  554. package/src/internal/private/__randomComposition.ts +50 -0
  555. package/src/internal/private/__randomEpoch.ts +34 -0
  556. package/src/json.ts +2 -2
  557. package/src/module.ts +4 -6
  558. package/src/notations.ts +20 -4
  559. package/lib/internal/private/__notationCapitalize.d.ts +0 -1
  560. package/lib/internal/private/__notationCapitalize.js +0 -6
  561. package/lib/internal/private/__notationCapitalize.js.map +0 -1
  562. package/lib/internal/private/__notationCapitalize.mjs +0 -6
  563. package/lib/internal/private/__notationCapitalize.mjs.map +0 -1
  564. package/lib/internal/private/__notationUnsnake.d.ts +0 -4
  565. package/lib/internal/private/__notationUnsnake.js +0 -26
  566. package/lib/internal/private/__notationUnsnake.js.map +0 -1
  567. package/lib/internal/private/__notationUnsnake.mjs +0 -15
  568. package/lib/internal/private/__notationUnsnake.mjs.map +0 -1
  569. package/native/adapter/visit.go +0 -173
  570. package/native/adapter/visit_property_chain_edges_test.go +0 -129
  571. package/native/cmd/ttsc-typia/plugin_options_missing_config_test.go +0 -26
  572. package/native/cmd/ttsc-typia/plugin_options_undefined_false_test.go +0 -36
  573. package/native/core/programmers/helpers/disable_function_programmer_declare.go +0 -10
  574. package/native/core/programmers/iterate/check_union_array_like.go +0 -422
  575. package/native/core/programmers/iterate/prune_object_properties.go +0 -105
  576. package/native/core/programmers/iterate/stringify_dynamic_properties.go +0 -219
  577. package/native/core/programmers/iterate/stringify_native.go +0 -14
  578. package/native/core/programmers/iterate/stringify_regular_properties.go +0 -112
  579. package/native/core/schemas/metadata/MetadataApplication.go +0 -41
  580. package/src/internal/private/__notationCapitalize.ts +0 -2
  581. package/src/internal/private/__notationUnsnake.ts +0 -24
@@ -3,12 +3,27 @@ package main
3
3
  import (
4
4
  "bytes"
5
5
  "os"
6
+ "os/exec"
6
7
  "path/filepath"
7
8
  "runtime"
9
+ "sort"
8
10
  "strings"
9
11
  "testing"
10
12
  )
11
13
 
14
+ func ttscTypiaTestTypecheck(t *testing.T, project string) {
15
+ t.Helper()
16
+ pnpm, err := exec.LookPath("pnpm")
17
+ if err != nil {
18
+ t.Skip("pnpm executable not found")
19
+ }
20
+ cmd := exec.Command(pnpm, "exec", "ttsc", "--noEmit", "-p", "tsconfig.json")
21
+ cmd.Dir = project
22
+ if output, err := cmd.CombinedOutput(); err != nil {
23
+ t.Fatalf("fixture typecheck failed: %v\n%s", err, output)
24
+ }
25
+ }
26
+
12
27
  func ttscTypiaTestRepoRoot(t *testing.T) string {
13
28
  t.Helper()
14
29
  _, file, _, ok := runtime.Caller(0)
@@ -50,7 +65,15 @@ func ttscTypiaTestWriteCommonRuntimeStubs(t *testing.T, runtimeDir string) {
50
65
  "validate-report-stub.cjs": ttscTypiaTestValidateReportStub,
51
66
  "standard-schema-stub.cjs": ttscTypiaTestStandardSchemaStub,
52
67
  "assert-guard-stub.cjs": ttscTypiaTestAssertGuardStub,
68
+ "functional-error-stub.cjs": ttscTypiaTestFunctionalErrorStub,
53
69
  "access-expression-stub.cjs": ttscTypiaTestAccessExpressionStub,
70
+ "string-length-stub.cjs": ttscTypiaTestStringLengthStub,
71
+ "notation-stub.cjs": ttscTypiaTestNotationStub,
72
+ "json-stringify-array-stub.cjs": ttscTypiaTestJsonStringifyArrayStub,
73
+ "json-stringify-property-stub.cjs": ttscTypiaTestJsonStringifyPropertyStub,
74
+ "json-stringify-element-stub.cjs": ttscTypiaTestJsonStringifyElementStub,
75
+ "json-stringify-tail-stub.cjs": ttscTypiaTestJsonStringifyTailStub,
76
+ "random-string-stub.cjs": ttscTypiaTestRandomStringStub,
54
77
  }
55
78
  for name, content := range files {
56
79
  if err := os.WriteFile(filepath.Join(runtimeDir, name), []byte(content), 0o644); err != nil {
@@ -65,20 +88,58 @@ func ttscTypiaTestRewriteCommonJS(t *testing.T, js string) string {
65
88
  runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_validateReport")`, `require("./validate-report-stub.cjs")`)
66
89
  runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_createStandardSchema")`, `require("./standard-schema-stub.cjs")`)
67
90
  runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_assertGuard")`, `require("./assert-guard-stub.cjs")`)
91
+ runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_functionalTypeGuardErrorFactory")`, `require("./functional-error-stub.cjs")`)
68
92
  runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_accessExpressionAsString")`, `require("./access-expression-stub.cjs")`)
93
+ runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_stringLength")`, `require("./string-length-stub.cjs")`)
94
+ runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_jsonStringifyArray")`, `require("./json-stringify-array-stub.cjs")`)
95
+ runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_jsonStringifyProperty")`, `require("./json-stringify-property-stub.cjs")`)
96
+ runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_jsonStringifyElement")`, `require("./json-stringify-element-stub.cjs")`)
97
+ runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_jsonStringifyTail")`, `require("./json-stringify-tail-stub.cjs")`)
98
+ runtimeJS = strings.ReplaceAll(runtimeJS, `require("typia/lib/internal/_randomString")`, `require("./random-string-stub.cjs")`)
99
+ for _, helper := range []string{"_notationAssign", "_notationCamel", "_notationKebab", "_notationKeyCollision", "_notationPascal", "_notationSnake"} {
100
+ runtimeJS = strings.ReplaceAll(
101
+ runtimeJS,
102
+ `require("typia/lib/internal/`+helper+`")`,
103
+ `require("./notation-stub.cjs")`,
104
+ )
105
+ }
69
106
  for _, needle := range []string{`require("typia")`, `require('typia')`, `from "typia"`, `from 'typia'`, `typia/lib/internal/`} {
70
- if strings.Contains(runtimeJS, needle) {
71
- t.Fatalf("runtime module still contains unresolved typia import %q", needle)
107
+ if !strings.Contains(runtimeJS, needle) {
108
+ continue
72
109
  }
110
+ // Name the modules that are actually unmapped. Reporting only the needle
111
+ // makes every new internal helper look like the same failure and sends the
112
+ // reader hunting through the emit for it.
113
+ if needle == `typia/lib/internal/` {
114
+ unresolved := map[string]bool{}
115
+ for _, part := range strings.Split(runtimeJS, needle)[1:] {
116
+ end := strings.IndexAny(part, "\"')")
117
+ if end < 0 {
118
+ end = len(part)
119
+ }
120
+ unresolved[part[:end]] = true
121
+ }
122
+ names := make([]string, 0, len(unresolved))
123
+ for name := range unresolved {
124
+ names = append(names, name)
125
+ }
126
+ sort.Strings(names)
127
+ t.Fatalf("runtime module has no stub for typia internal helpers: %s", strings.Join(names, ", "))
128
+ }
129
+ t.Fatalf("runtime module still contains unresolved typia import %q", needle)
73
130
  }
74
131
  return runtimeJS
75
132
  }
76
133
 
77
134
  const ttscTypiaTestValidateReportStub = `module.exports._validateReport = (array) => {
135
+ const isAncestor = (ancestor, descendant) =>
136
+ descendant === ancestor ||
137
+ descendant.startsWith(ancestor + ".") ||
138
+ descendant.startsWith(ancestor + "[");
78
139
  const reportable = (path) => {
79
140
  if (array.length === 0) return true;
80
141
  const last = array[array.length - 1].path;
81
- return path.length > last.length || last.substring(0, path.length) !== path;
142
+ return !isAncestor(path, last) && !isAncestor(last, path);
82
143
  };
83
144
  return (exceptable, error) => {
84
145
  if (exceptable && reportable(error.path)) {
@@ -108,6 +169,61 @@ const ttscTypiaTestAssertGuardStub = `module.exports._assertGuard = (exceptionab
108
169
  };
109
170
  `
110
171
 
172
+ const ttscTypiaTestFunctionalErrorStub = `module.exports._functionalTypeGuardErrorFactory = (props) =>
173
+ Object.assign(new Error(props.expected), props);
174
+ `
175
+
176
+ // The two JSON stringify stubs mirror packages/typia/src/internal exactly. They
177
+ // are runtime doubles for the emit these tests execute; the shipped helpers
178
+ // themselves are exercised by the TypeScript suites against the real package.
179
+ const ttscTypiaTestJsonStringifyArrayStub = `module.exports._jsonStringifyArray = (elements, mapper) => {
180
+ const length = Math.min(
181
+ Math.max(Math.trunc(elements.length) || 0, 0),
182
+ Number.MAX_SAFE_INTEGER,
183
+ );
184
+ let output = "";
185
+ for (let i = 0; i < length; ++i) {
186
+ const elem = elements[i];
187
+ const text = elem === undefined ? undefined : mapper(elem, i);
188
+ output += (i === 0 ? "" : ",") + (text === undefined ? "null" : text);
189
+ }
190
+ return output;
191
+ };
192
+ `
193
+
194
+ const ttscTypiaTestJsonStringifyPropertyStub = `module.exports._jsonStringifyProperty = (head, text, tail) =>
195
+ text === undefined ? "" : head + text + tail;
196
+ `
197
+
198
+ const ttscTypiaTestJsonStringifyElementStub = `module.exports._jsonStringifyElement = (text) =>
199
+ text === undefined ? "null" : text;
200
+ `
201
+
202
+ // Deterministic rather than random: these runtimes assert observable behavior
203
+ // of the emitted validators, so a generated string only has to satisfy the
204
+ // declared bounds, and a stable one keeps a failure reproducible.
205
+ const ttscTypiaTestJsonStringifyTailStub = `module.exports._jsonStringifyTail = (str) =>
206
+ str[str.length - 1] === "," ? str.substring(0, str.length - 1) : str;
207
+ `
208
+
209
+ const ttscTypiaTestRandomStringStub = `module.exports._randomString = (props) => {
210
+ const minimum =
211
+ props.minLength !== undefined
212
+ ? props.minLength
213
+ : Math.min(props.maxLength !== undefined ? props.maxLength : 5, 5);
214
+ const maximum = props.maxLength !== undefined ? props.maxLength : minimum + 5;
215
+ const length = Math.max(minimum, Math.min(minimum, maximum));
216
+ return "a".repeat(length);
217
+ };
218
+ `
219
+
220
+ const ttscTypiaTestStringLengthStub = `module.exports._stringLength = (value) => {
221
+ let count = 0;
222
+ for (const _ of value) ++count;
223
+ return count;
224
+ };
225
+ `
226
+
111
227
  const ttscTypiaTestAccessExpressionStub = `const reserved = new Set([
112
228
  "break",
113
229
  "case",
@@ -153,3 +269,120 @@ module.exports._accessExpressionAsString = (key) => {
153
269
  : "[" + JSON.stringify(key) + "]";
154
270
  };
155
271
  `
272
+
273
+ // ttscTypiaTestNotationStub stands in for typia/lib/internal/_notation*, which
274
+ // the emitted converter requires for dynamic (index-signature) keys.
275
+ //
276
+ // These tests assert that the statically emitted key and the runtime helper
277
+ // agree, so this stub is that assertion's oracle and has to stay a faithful
278
+ // transcription of packages/typia/src/internal/_notation{Camel,Pascal,Snake,
279
+ // Kebab}.ts and private/__notationRename.ts — an approximation turns "emit ==
280
+ // runtime" into "emit == whatever this file happens to say". Keep it a direct
281
+ // transcription: same routing on underscore presence (not on segment count),
282
+ // the same CamelizeSnakeString/PascalizeSnakeString recursions, and the same
283
+ // per-segment case-boundary walk in snake. It deliberately uses string
284
+ // concatenation rather than template literals because it is embedded in a Go
285
+ // raw string literal, which is backtick-delimited.
286
+ const ttscTypiaTestNotationStub = `const __notationRename = (props) => (str) => {
287
+ let prefix = "";
288
+ while (str.startsWith("_")) {
289
+ prefix += "_";
290
+ str = str.substring(1);
291
+ }
292
+ if (str.length === 0) return prefix;
293
+ return prefix + (str.includes("_") ? props.snake(str) : props.plain(str));
294
+ };
295
+
296
+ const _notationCamelSnake = (str) => {
297
+ while (str.startsWith("_")) str = str.substring(1);
298
+ if (str.length === 0) return "";
299
+ const index = str.indexOf("_");
300
+ if (index < 0) return str.toLowerCase();
301
+ const middle = str[index + 1];
302
+ if (middle === undefined) return str.toLowerCase();
303
+ return middle === "_"
304
+ ? _notationCamelSnake(str.substring(0, index) + "_" + str.substring(index + 2))
305
+ : str.substring(0, index).toLowerCase() +
306
+ middle.toUpperCase() +
307
+ _notationCamelSnake(str.substring(index + 2));
308
+ };
309
+
310
+ const _notationPascalSnake = (str) => {
311
+ while (str.startsWith("_")) str = str.substring(1);
312
+ if (str.length === 0) return "";
313
+ const index = str.indexOf("_");
314
+ return index < 0
315
+ ? str[0].toUpperCase() + str.substring(1).toLowerCase()
316
+ : str[0].toUpperCase() +
317
+ str.substring(1, index).toLowerCase() +
318
+ _notationPascalSnake(str.substring(index + 1));
319
+ };
320
+
321
+ const _notationSnakeWord = (str) => {
322
+ const indexes = [];
323
+ for (let i = 0; i < str.length; i++) {
324
+ const code = str.charCodeAt(i);
325
+ if (65 <= code && code <= 90) indexes.push(i);
326
+ }
327
+ for (let i = indexes.length - 1; i > 0; --i)
328
+ if (indexes[i] - indexes[i - 1] === 1) indexes.splice(i, 1);
329
+ if (indexes.length !== 0 && indexes[0] === 0) indexes.splice(0, 1);
330
+ if (indexes.length === 0) return str.toLowerCase();
331
+ let ret = "";
332
+ for (let i = 0; i < indexes.length; i++) {
333
+ ret += str.substring(i === 0 ? 0 : indexes[i - 1], indexes[i]).toLowerCase();
334
+ ret += "_";
335
+ }
336
+ ret += str.substring(indexes[indexes.length - 1]).toLowerCase();
337
+ return ret;
338
+ };
339
+
340
+ module.exports._notationCamel = __notationRename({
341
+ plain: (str) =>
342
+ str === str.toUpperCase()
343
+ ? str.toLowerCase()
344
+ : str[0].toLowerCase() + str.substring(1),
345
+ snake: _notationCamelSnake,
346
+ });
347
+ module.exports._notationPascal = __notationRename({
348
+ plain: (str) => str[0].toUpperCase() + str.substring(1),
349
+ snake: _notationPascalSnake,
350
+ });
351
+ module.exports._notationSnake = (str) => {
352
+ if (str.length === 0) return str;
353
+ let prefix = "";
354
+ for (let i = 0; i < str.length; i++) {
355
+ if (str[i] === "_") prefix += "_";
356
+ else break;
357
+ }
358
+ if (prefix.length !== 0) str = str.substring(prefix.length);
359
+ return prefix + str.split("_").map(_notationSnakeWord).join("_");
360
+ };
361
+ module.exports._notationKebab = (str) => {
362
+ let snaked = module.exports._notationSnake(str);
363
+ let prefix = "";
364
+ while (snaked.startsWith("_")) {
365
+ prefix += "_";
366
+ snaked = snaked.substring(1);
367
+ }
368
+ return prefix + snaked.replaceAll("_", "-");
369
+ };
370
+ module.exports._notationAssign = (output, sources, source, value, rename) => {
371
+ const destination = rename(source);
372
+ if (Object.hasOwn(output, destination))
373
+ module.exports._notationKeyCollision(sources[destination], source, destination);
374
+ Object.defineProperty(output, destination, {
375
+ configurable: true,
376
+ enumerable: true,
377
+ value,
378
+ writable: true,
379
+ });
380
+ sources[destination] = source;
381
+ };
382
+ module.exports._notationKeyCollision = (first, second, destination) => {
383
+ throw new Error(
384
+ "typia.notations cannot rename both " + JSON.stringify(first) +
385
+ " and " + JSON.stringify(second) + " to " + JSON.stringify(destination) + ".",
386
+ );
387
+ };
388
+ `
@@ -0,0 +1,43 @@
1
+ package main
2
+
3
+ import (
4
+ "path/filepath"
5
+ "testing"
6
+ )
7
+
8
+ // TestTransformPluginOptionsComeFromPayload verifies the transform host takes
9
+ // typia's options from ttsc's resolved plugin entry, not from tsconfig text.
10
+ //
11
+ // This host owns its own `--plugins-json` flag and its own option read, so it
12
+ // needs its own proof: the build host passing does not show that this one is
13
+ // wired. Every row writes a tsconfig whose raw text disagrees with the resolved
14
+ // entry, which is exactly what samchon/typia#1887 could not tell apart -- the
15
+ // old reader regex-matched option names over the leaf file's bytes, so it
16
+ // enabled options the user had commented out, adopted a sibling plugin's
17
+ // options, and ignored options inherited through `extends`.
18
+ //
19
+ // 1. Materialize each matrix row as a project plus the payload ttsc resolves it into.
20
+ // 2. Run the transform host over it.
21
+ // 3. Assert the emitted validator honors the entry, not the file text.
22
+ func TestTransformPluginOptionsComeFromPayload(t *testing.T) {
23
+ for _, tc := range pluginOptionsPayloadCases() {
24
+ t.Run(tc.name, func(t *testing.T) {
25
+ project := pluginOptionsPayloadProject(t, tc)
26
+ out, errText, code := ttscTypiaTestCapture(func() int {
27
+ return runTransform([]string{
28
+ "--cwd", project,
29
+ "--tsconfig", "tsconfig.json",
30
+ "--file", filepath.Join("src", "main.ts"),
31
+ "--output", "ts",
32
+ // `=`-joined, the exact shape ttsc's createNativeBuildArgs and the
33
+ // wasm hosts put on the wire.
34
+ "--plugins-json=" + tc.payload,
35
+ })
36
+ })
37
+ if code != 0 {
38
+ t.Fatalf("transform failed with code %d\nstdout=%s\nstderr=%s", code, out, errText)
39
+ }
40
+ pluginOptionsPayloadAssert(t, tc, out)
41
+ })
42
+ }
43
+ }
@@ -0,0 +1,114 @@
1
+ package main
2
+
3
+ import (
4
+ "os"
5
+ "path/filepath"
6
+ "reflect"
7
+ "strings"
8
+ "testing"
9
+ )
10
+
11
+ // TestTransformSingleFileFailurePreservesArtifacts verifies single-file atomicity.
12
+ //
13
+ // The project host returns 3 when typia's analysis produced diagnostics, but both
14
+ // single-file hosts used to publish `--out` and exit 0 regardless, shipping the
15
+ // untransformed `typia.is<T>(input)` call behind a success code. Publication must
16
+ // follow the same decision as the exit code in both output modes, and a failed
17
+ // transform must not destroy an artifact a previous run left behind.
18
+ //
19
+ // 1. Seed `--out` with a byte-sensitive prior artifact beside an unrelated file.
20
+ // 2. Run the single-file transform over a typia-invalid source in `ts` and `js`.
21
+ // 3. Require exit 3, the diagnostic on stderr, and a byte-identical output tree.
22
+ // 4. Require a fresh `--out` parent to stay uncreated, since publishing nothing
23
+ // must also mean creating no directory for it.
24
+ func TestTransformSingleFileFailurePreservesArtifacts(t *testing.T) {
25
+ for _, output := range []string{"ts", "js"} {
26
+ t.Run(output, func(t *testing.T) {
27
+ project := transformSingleFileProject(t, transformDiagnosticSource)
28
+ dist := filepath.Join(project, "dist")
29
+ outPath := filepath.Join(dist, "main."+output)
30
+ seeds := map[string]string{
31
+ outPath: "previous artifact\n",
32
+ filepath.Join(dist, "keep.txt"): "unrelated output\n",
33
+ }
34
+ for path, body := range seeds {
35
+ if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
36
+ t.Fatalf("mkdir seed parent: %v", err)
37
+ }
38
+ if err := os.WriteFile(path, []byte(body), 0o644); err != nil {
39
+ t.Fatalf("write seed %s: %v", path, err)
40
+ }
41
+ }
42
+ before := buildReadTree(t, dist)
43
+
44
+ _, errText, code := ttscTypiaTestCapture(func() int {
45
+ return runTransform([]string{
46
+ "--cwd", project,
47
+ "--tsconfig", "tsconfig.json",
48
+ "--file", filepath.Join("src", "main.ts"),
49
+ "--output", output,
50
+ "--out", outPath,
51
+ })
52
+ })
53
+ if code != 3 {
54
+ t.Fatalf("invalid single-file transform should fail with code 3, got %d\nstderr=%s", code, errText)
55
+ }
56
+ normalized := filepath.ToSlash(errText)
57
+ if !strings.Contains(normalized, "src/main.ts:3:9 - error TS(typia.is):") ||
58
+ !strings.Contains(normalized, "non-specified generic argument") {
59
+ t.Fatalf("single-file diagnostic did not preserve location/code/message:\n%s", errText)
60
+ }
61
+ if after := buildReadTree(t, dist); !reflect.DeepEqual(after, before) {
62
+ t.Fatalf("failed single-file transform mutated output tree:\nbefore=%q\nafter=%q", before, after)
63
+ }
64
+
65
+ // writeSingleOutput mkdirs its parent, so a guard placed after publication
66
+ // would leave the directory behind even with no artifact in it.
67
+ fresh := filepath.Join(project, "fresh", "nested")
68
+ _, _, code = ttscTypiaTestCapture(func() int {
69
+ return runTransform([]string{
70
+ "--cwd", project,
71
+ "--tsconfig", "tsconfig.json",
72
+ "--file", filepath.Join("src", "main.ts"),
73
+ "--output", output,
74
+ "--out", filepath.Join(fresh, "main."+output),
75
+ })
76
+ })
77
+ if code != 3 {
78
+ t.Fatalf("invalid single-file transform should fail with code 3, got %d", code)
79
+ }
80
+ if _, err := os.Stat(filepath.Join(project, "fresh")); !os.IsNotExist(err) {
81
+ t.Fatalf("failed single-file transform created the --out directory: %v", err)
82
+ }
83
+ })
84
+ }
85
+ }
86
+
87
+ // transformSingleFileProject writes a one-source project whose `src/main.ts`
88
+ // carries the given body, sharing the typia stub the other transform diagnostic
89
+ // fixtures use.
90
+ func transformSingleFileProject(t *testing.T, source string) string {
91
+ t.Helper()
92
+ project := t.TempDir()
93
+ src := filepath.Join(project, "src")
94
+ if err := os.MkdirAll(src, 0o755); err != nil {
95
+ t.Fatalf("mkdir fixture src: %v", err)
96
+ }
97
+ if err := os.WriteFile(filepath.Join(project, "tsconfig.json"), []byte(transformDiagnosticTSConfig), 0o644); err != nil {
98
+ t.Fatalf("write tsconfig: %v", err)
99
+ }
100
+ transformDiagnosticWriteTypiaStub(t, project)
101
+ if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(source), 0o644); err != nil {
102
+ t.Fatalf("write source: %v", err)
103
+ }
104
+ return project
105
+ }
106
+
107
+ // transformSingleFileValidSource is the negative twin of
108
+ // transformDiagnosticSource: the same call shape with a resolved generic
109
+ // argument, which typia can lower without a diagnostic.
110
+ const transformSingleFileValidSource = `import typia from "typia";
111
+ export function check(input: unknown): boolean {
112
+ return typia.is<{ value: number }>(input);
113
+ }
114
+ `
@@ -0,0 +1,43 @@
1
+ package main
2
+
3
+ import (
4
+ "path/filepath"
5
+ "strings"
6
+ "testing"
7
+ )
8
+
9
+ // TestTransformSingleFileFailureWritesNoStdout verifies the stdout publication path.
10
+ //
11
+ // Without `--out` the artifact is stdout, so withholding a file is not enough:
12
+ // the untransformed source must not reach the stream a caller pipes into a file.
13
+ // This is also the shape the wasm host reaches through `jsTransform`, whose
14
+ // `{ code, stdout, stderr }` response is exactly these three values.
15
+ //
16
+ // 1. Transform a typia-invalid source in `ts` and `js` with no `--out`.
17
+ // 2. Require exit 3 and the diagnostic on stderr.
18
+ // 3. Require stdout to be empty rather than carrying the untransformed call.
19
+ func TestTransformSingleFileFailureWritesNoStdout(t *testing.T) {
20
+ for _, output := range []string{"ts", "js"} {
21
+ t.Run(output, func(t *testing.T) {
22
+ project := transformSingleFileProject(t, transformDiagnosticSource)
23
+ outText, errText, code := ttscTypiaTestCapture(func() int {
24
+ return runTransform([]string{
25
+ "--cwd", project,
26
+ "--tsconfig", "tsconfig.json",
27
+ "--file", filepath.Join("src", "main.ts"),
28
+ "--output", output,
29
+ })
30
+ })
31
+ if code != 3 {
32
+ t.Fatalf("invalid single-file transform should fail with code 3, got %d\nstdout=%s\nstderr=%s", code, outText, errText)
33
+ }
34
+ if !strings.Contains(errText, "error TS(typia.is):") {
35
+ t.Fatalf("single-file diagnostic missing from stderr:\n%s", errText)
36
+ }
37
+ // Before the fix this carried the untransformed `typia.is<T>(input)` call.
38
+ if outText != "" {
39
+ t.Fatalf("failed single-file transform published an artifact on stdout:\n%s", outText)
40
+ }
41
+ })
42
+ }
43
+ }
@@ -0,0 +1,81 @@
1
+ package main
2
+
3
+ import (
4
+ "os"
5
+ "path/filepath"
6
+ "strings"
7
+ "testing"
8
+ )
9
+
10
+ // TestTransformSingleFileJSDistinguishesSameBasenameSources verifies the
11
+ // collision boundary of the `--output js` artifact match.
12
+ //
13
+ // The comment on the old whole-path-stem match named the intended repair --
14
+ // "match on basename stem" -- and a basename match would indeed have unblocked
15
+ // `outDir`. It would also have made `src/alpha/main.ts` and `src/beta/main.ts`
16
+ // indistinguishable, so whichever emitted `main.js` arrived last would win and
17
+ // the command would publish another file's validator under an exit 0. Resolving
18
+ // the expected output path through the compiler keeps the two apart by
19
+ // construction, since they resolve to different artifacts.
20
+ //
21
+ // 1. Give one project two sources that share a basename in different
22
+ // directories, each lowering a differently shaped validator.
23
+ // 2. Transform each with `--output js --out` under a `rootDir`/`outDir` layout.
24
+ // 3. Require each published artifact to carry its own validator and not its
25
+ // namesake's.
26
+ func TestTransformSingleFileJSDistinguishesSameBasenameSources(t *testing.T) {
27
+ const alphaSource = `import typia from "typia";
28
+ export function check(input: unknown): boolean {
29
+ return typia.is<{ alpha: number }>(input);
30
+ }
31
+ `
32
+ const betaSource = `import typia from "typia";
33
+ export function check(input: unknown): boolean {
34
+ return typia.is<{ beta: string }>(input);
35
+ }
36
+ `
37
+ project := transformSingleFileLayoutProject(
38
+ t,
39
+ []string{`"rootDir": "src"`, `"outDir": "dist"`},
40
+ map[string]string{
41
+ "src/alpha/main.ts": alphaSource,
42
+ "src/beta/main.ts": betaSource,
43
+ },
44
+ )
45
+ for _, probe := range []struct {
46
+ name string
47
+ file string
48
+ carries string
49
+ rejects string
50
+ }{
51
+ {name: "alpha", file: "src/alpha/main.ts", carries: "alpha", rejects: "beta"},
52
+ {name: "beta", file: "src/beta/main.ts", carries: "beta", rejects: "alpha"},
53
+ } {
54
+ t.Run(probe.name, func(t *testing.T) {
55
+ outPath := filepath.Join(project, "artifact", probe.name+".js")
56
+ _, errText, code := ttscTypiaTestCapture(func() int {
57
+ return runTransform([]string{
58
+ "--cwd", project,
59
+ "--tsconfig", "tsconfig.json",
60
+ "--file", filepath.FromSlash(probe.file),
61
+ "--output", "js",
62
+ "--out", outPath,
63
+ })
64
+ })
65
+ if code != 0 {
66
+ t.Fatalf("`--output js` should publish %s, got %d\nstderr=%s", probe.file, code, errText)
67
+ }
68
+ data, err := os.ReadFile(outPath)
69
+ if err != nil {
70
+ t.Fatalf("`--output js` published no artifact for %s: %v", probe.file, err)
71
+ }
72
+ text := string(data)
73
+ if !strings.Contains(text, probe.carries) {
74
+ t.Fatalf("published artifact does not carry %s's validator:\n%s", probe.file, text)
75
+ }
76
+ if strings.Contains(text, probe.rejects) {
77
+ t.Fatalf("published artifact carries the same-basename sibling's validator:\n%s", text)
78
+ }
79
+ })
80
+ }
81
+ }
@@ -0,0 +1,100 @@
1
+ package main
2
+
3
+ import (
4
+ "os"
5
+ "path/filepath"
6
+ "strings"
7
+ "testing"
8
+ )
9
+
10
+ // TestTransformSingleFileJSEmptyEmitReportsNoOutput verifies the negative twin
11
+ // of the `--output js` artifact match.
12
+ //
13
+ // Teaching the match where an `outDir` puts an artifact must not turn it into a
14
+ // match that always succeeds. "No output produced" is a real outcome: a source
15
+ // can belong to the program and still have no JavaScript of its own, and the
16
+ // caller needs exit 3 rather than an empty file behind exit 0. Every probe puts
17
+ // a real artifact for a sibling source through the same write callback, so a
18
+ // check that stopped discriminating would capture that neighbor and report
19
+ // success. The three probes reach the outcome by different routes -- an emit
20
+ // that skips the file, an emit that withholds it, and a file the resolution
21
+ // gives no output path at all -- so no one of them stands in for the others.
22
+ //
23
+ // 1. Ask for the JavaScript of a declaration source, which the emit skips.
24
+ // 2. Ask for the JavaScript of a source outside `rootDir`, whose output would
25
+ // land outside `outDir` and is therefore withheld by the emit.
26
+ // 3. Ask for the JavaScript of a JSON module that would be emitted over
27
+ // itself, which resolves to no JavaScript output path.
28
+ // 4. Require exit 3, the "no output produced" report, and an unwritten `--out`
29
+ // in all three.
30
+ func TestTransformSingleFileJSEmptyEmitReportsNoOutput(t *testing.T) {
31
+ for _, probe := range []struct {
32
+ name string
33
+ extra []string
34
+ sources map[string]string
35
+ file string
36
+ }{
37
+ // A declaration source is in the program but never emitted, so no write
38
+ // ever arrives for the path it resolves to.
39
+ {
40
+ name: "declaration_source",
41
+ extra: []string{`"rootDir": "src"`, `"outDir": "dist"`},
42
+ sources: map[string]string{
43
+ "src/types.d.ts": "export declare const value: string;\n",
44
+ "src/main.ts": transformSingleFileValidSource,
45
+ },
46
+ file: "src/types.d.ts",
47
+ },
48
+ // A source outside `rootDir` resolves to an output outside `outDir`, which
49
+ // the emit refuses to write rather than escaping the output tree. The
50
+ // source is ordinary TypeScript that transforms fine, so only the absent
51
+ // write distinguishes it -- exactly the state the check exists to report.
52
+ {
53
+ name: "output_escapes_out_dir",
54
+ extra: []string{`"rootDir": "src/deep"`, `"outDir": "dist"`},
55
+ sources: map[string]string{
56
+ "src/deep/main.ts": transformSingleFileValidSource,
57
+ "src/stray.ts": transformSingleFileValidSource,
58
+ },
59
+ file: "src/stray.ts",
60
+ },
61
+ // A JSON module with no `outDir` would be emitted over its own source, so
62
+ // the compiler resolves it to no JavaScript output path at all. This is the
63
+ // one route that reaches the empty-path guard rather than an absent write.
64
+ {
65
+ name: "json_module_emitted_over_itself",
66
+ extra: []string{`"resolveJsonModule": true`},
67
+ sources: map[string]string{
68
+ "src/data.json": "{ \"value\": 1 }\n",
69
+ "src/main.ts": "import data from \"./data.json\";\nexport const value = data.value;\n",
70
+ },
71
+ file: "src/data.json",
72
+ },
73
+ } {
74
+ t.Run(probe.name, func(t *testing.T) {
75
+ project := transformSingleFileLayoutProject(t, probe.extra, probe.sources)
76
+ outPath := filepath.Join(project, "artifact", "main.js")
77
+ _, errText, code := ttscTypiaTestCapture(func() int {
78
+ return runTransform([]string{
79
+ "--cwd", project,
80
+ "--tsconfig", "tsconfig.json",
81
+ "--file", filepath.FromSlash(probe.file),
82
+ "--output", "js",
83
+ "--out", outPath,
84
+ })
85
+ })
86
+ if code != 3 {
87
+ t.Fatalf("an empty emit must still fail with code 3, got %d\nstderr=%s", code, errText)
88
+ }
89
+ if !strings.Contains(errText, "no output produced") {
90
+ t.Fatalf("an empty emit must still report the cause:\n%s", errText)
91
+ }
92
+ // An empty emit leaves runTransformSingle through `if code != 0`, a
93
+ // different branch than the diagnostic route the atomicity case pins, so
94
+ // withholding the artifact needs its own check here.
95
+ if _, err := os.Stat(outPath); !os.IsNotExist(err) {
96
+ t.Fatalf("an empty emit must publish nothing, but --out exists: %v", err)
97
+ }
98
+ })
99
+ }
100
+ }