typia 13.1.1 → 13.1.19

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 (515) hide show
  1. package/README.md +3 -0
  2. package/lib/_virtual/_rolldown/runtime.mjs +1 -5
  3. package/lib/executable/FileSystemIdentity.d.ts +21 -0
  4. package/lib/executable/FileSystemIdentity.js +183 -0
  5. package/lib/executable/FileSystemIdentity.js.map +1 -0
  6. package/lib/executable/FileSystemIdentity.mjs +129 -0
  7. package/lib/executable/FileSystemIdentity.mjs.map +1 -0
  8. package/lib/executable/TypiaGenerateWizard.js +264 -104
  9. package/lib/executable/TypiaGenerateWizard.js.map +1 -1
  10. package/lib/executable/TypiaGenerateWizard.mjs +233 -93
  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 +17 -0
  16. package/lib/internal/_ProtobufReader.js +117 -45
  17. package/lib/internal/_ProtobufReader.js.map +1 -1
  18. package/lib/internal/_ProtobufReader.mjs +108 -39
  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/_notationAny.js +8 -1
  87. package/lib/internal/_notationAny.js.map +1 -1
  88. package/lib/internal/_notationAny.mjs +7 -1
  89. package/lib/internal/_notationAny.mjs.map +1 -1
  90. package/lib/internal/_notationAssign.d.ts +1 -0
  91. package/lib/internal/_notationAssign.js +18 -0
  92. package/lib/internal/_notationAssign.js.map +1 -0
  93. package/lib/internal/_notationAssign.mjs +17 -0
  94. package/lib/internal/_notationAssign.mjs.map +1 -0
  95. package/lib/internal/_notationCamel.js +30 -9
  96. package/lib/internal/_notationCamel.js.map +1 -1
  97. package/lib/internal/_notationCamel.mjs +13 -5
  98. package/lib/internal/_notationCamel.mjs.map +1 -1
  99. package/lib/internal/_notationKebab.d.ts +1 -0
  100. package/lib/internal/_notationKebab.js +15 -0
  101. package/lib/internal/_notationKebab.js.map +1 -0
  102. package/lib/internal/_notationKebab.mjs +15 -0
  103. package/lib/internal/_notationKebab.mjs.map +1 -0
  104. package/lib/internal/_notationKeyCollision.d.ts +1 -0
  105. package/lib/internal/_notationKeyCollision.js +8 -0
  106. package/lib/internal/_notationKeyCollision.js.map +1 -0
  107. package/lib/internal/_notationKeyCollision.mjs +8 -0
  108. package/lib/internal/_notationKeyCollision.mjs.map +1 -0
  109. package/lib/internal/_notationPascal.js +20 -5
  110. package/lib/internal/_notationPascal.js.map +1 -1
  111. package/lib/internal/_notationPascal.mjs +10 -5
  112. package/lib/internal/_notationPascal.mjs.map +1 -1
  113. package/lib/internal/_notationSnake.js +25 -22
  114. package/lib/internal/_notationSnake.js.map +1 -1
  115. package/lib/internal/_notationSnake.mjs +11 -11
  116. package/lib/internal/_notationSnake.mjs.map +1 -1
  117. package/lib/internal/_plainCloneAny.js +174 -38
  118. package/lib/internal/_plainCloneAny.js.map +1 -1
  119. package/lib/internal/_plainCloneAny.mjs +126 -22
  120. package/lib/internal/_plainCloneAny.mjs.map +1 -1
  121. package/lib/internal/_randomArray.d.ts +1 -1
  122. package/lib/internal/_randomArray.js +11 -4
  123. package/lib/internal/_randomArray.js.map +1 -1
  124. package/lib/internal/_randomArray.mjs +9 -3
  125. package/lib/internal/_randomArray.mjs.map +1 -1
  126. package/lib/internal/_randomFormatByte.d.ts +2 -1
  127. package/lib/internal/_randomFormatByte.js +2 -1
  128. package/lib/internal/_randomFormatByte.js.map +1 -1
  129. package/lib/internal/_randomFormatByte.mjs +2 -1
  130. package/lib/internal/_randomFormatByte.mjs.map +1 -1
  131. package/lib/internal/_randomFormatDate.d.ts +2 -0
  132. package/lib/internal/_randomFormatDate.js +3 -2
  133. package/lib/internal/_randomFormatDate.js.map +1 -1
  134. package/lib/internal/_randomFormatDate.mjs +3 -2
  135. package/lib/internal/_randomFormatDate.mjs.map +1 -1
  136. package/lib/internal/_randomFormatDatetime.d.ts +2 -0
  137. package/lib/internal/_randomFormatDatetime.js +3 -2
  138. package/lib/internal/_randomFormatDatetime.js.map +1 -1
  139. package/lib/internal/_randomFormatDatetime.mjs +3 -2
  140. package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
  141. package/lib/internal/_randomFormatDuration.d.ts +2 -1
  142. package/lib/internal/_randomFormatDuration.js +3 -2
  143. package/lib/internal/_randomFormatDuration.js.map +1 -1
  144. package/lib/internal/_randomFormatDuration.mjs +3 -2
  145. package/lib/internal/_randomFormatDuration.mjs.map +1 -1
  146. package/lib/internal/_randomFormatEmail.d.ts +2 -1
  147. package/lib/internal/_randomFormatEmail.js +8 -1
  148. package/lib/internal/_randomFormatEmail.js.map +1 -1
  149. package/lib/internal/_randomFormatEmail.mjs +5 -1
  150. package/lib/internal/_randomFormatEmail.mjs.map +1 -1
  151. package/lib/internal/_randomFormatHostname.d.ts +8 -1
  152. package/lib/internal/_randomFormatHostname.js +45 -2
  153. package/lib/internal/_randomFormatHostname.js.map +1 -1
  154. package/lib/internal/_randomFormatHostname.mjs +38 -2
  155. package/lib/internal/_randomFormatHostname.mjs.map +1 -1
  156. package/lib/internal/_randomFormatIdnEmail.d.ts +2 -1
  157. package/lib/internal/_randomFormatIdnEmail.js +16 -2
  158. package/lib/internal/_randomFormatIdnEmail.js.map +1 -1
  159. package/lib/internal/_randomFormatIdnEmail.mjs +11 -2
  160. package/lib/internal/_randomFormatIdnEmail.mjs.map +1 -1
  161. package/lib/internal/_randomFormatIdnHostname.d.ts +2 -1
  162. package/lib/internal/_randomFormatIdnHostname.js +26 -1
  163. package/lib/internal/_randomFormatIdnHostname.js.map +1 -1
  164. package/lib/internal/_randomFormatIdnHostname.mjs +25 -2
  165. package/lib/internal/_randomFormatIdnHostname.mjs.map +1 -1
  166. package/lib/internal/_randomFormatIpv4.d.ts +2 -1
  167. package/lib/internal/_randomFormatIpv4.js +2 -1
  168. package/lib/internal/_randomFormatIpv4.js.map +1 -1
  169. package/lib/internal/_randomFormatIpv4.mjs +2 -1
  170. package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
  171. package/lib/internal/_randomFormatIpv6.d.ts +2 -1
  172. package/lib/internal/_randomFormatIpv6.js +2 -1
  173. package/lib/internal/_randomFormatIpv6.js.map +1 -1
  174. package/lib/internal/_randomFormatIpv6.mjs +2 -1
  175. package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
  176. package/lib/internal/_randomFormatIri.d.ts +2 -1
  177. package/lib/internal/_randomFormatIri.js +1 -1
  178. package/lib/internal/_randomFormatIri.js.map +1 -1
  179. package/lib/internal/_randomFormatIri.mjs +1 -1
  180. package/lib/internal/_randomFormatIri.mjs.map +1 -1
  181. package/lib/internal/_randomFormatIriReference.d.ts +2 -1
  182. package/lib/internal/_randomFormatIriReference.js +1 -1
  183. package/lib/internal/_randomFormatIriReference.js.map +1 -1
  184. package/lib/internal/_randomFormatIriReference.mjs +1 -1
  185. package/lib/internal/_randomFormatIriReference.mjs.map +1 -1
  186. package/lib/internal/_randomFormatJsonPointer.d.ts +2 -1
  187. package/lib/internal/_randomFormatJsonPointer.js +8 -1
  188. package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
  189. package/lib/internal/_randomFormatJsonPointer.mjs +5 -1
  190. package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
  191. package/lib/internal/_randomFormatPassword.d.ts +2 -1
  192. package/lib/internal/_randomFormatPassword.js +7 -5
  193. package/lib/internal/_randomFormatPassword.js.map +1 -1
  194. package/lib/internal/_randomFormatPassword.mjs +5 -1
  195. package/lib/internal/_randomFormatPassword.mjs.map +1 -1
  196. package/lib/internal/_randomFormatRegex.d.ts +2 -1
  197. package/lib/internal/_randomFormatRegex.js +2 -1
  198. package/lib/internal/_randomFormatRegex.js.map +1 -1
  199. package/lib/internal/_randomFormatRegex.mjs +2 -1
  200. package/lib/internal/_randomFormatRegex.mjs.map +1 -1
  201. package/lib/internal/_randomFormatRelativeJsonPointer.d.ts +2 -1
  202. package/lib/internal/_randomFormatRelativeJsonPointer.js +3 -2
  203. package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
  204. package/lib/internal/_randomFormatRelativeJsonPointer.mjs +3 -2
  205. package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
  206. package/lib/internal/_randomFormatTime.d.ts +2 -1
  207. package/lib/internal/_randomFormatTime.js +3 -2
  208. package/lib/internal/_randomFormatTime.js.map +1 -1
  209. package/lib/internal/_randomFormatTime.mjs +3 -2
  210. package/lib/internal/_randomFormatTime.mjs.map +1 -1
  211. package/lib/internal/_randomFormatUri.d.ts +2 -1
  212. package/lib/internal/_randomFormatUri.js +1 -1
  213. package/lib/internal/_randomFormatUri.js.map +1 -1
  214. package/lib/internal/_randomFormatUri.mjs +1 -1
  215. package/lib/internal/_randomFormatUri.mjs.map +1 -1
  216. package/lib/internal/_randomFormatUriReference.d.ts +2 -1
  217. package/lib/internal/_randomFormatUriReference.js +1 -1
  218. package/lib/internal/_randomFormatUriReference.js.map +1 -1
  219. package/lib/internal/_randomFormatUriReference.mjs +1 -1
  220. package/lib/internal/_randomFormatUriReference.mjs.map +1 -1
  221. package/lib/internal/_randomFormatUriTemplate.d.ts +2 -1
  222. package/lib/internal/_randomFormatUriTemplate.js +1 -1
  223. package/lib/internal/_randomFormatUriTemplate.js.map +1 -1
  224. package/lib/internal/_randomFormatUriTemplate.mjs +1 -1
  225. package/lib/internal/_randomFormatUriTemplate.mjs.map +1 -1
  226. package/lib/internal/_randomFormatUrl.d.ts +2 -1
  227. package/lib/internal/_randomFormatUrl.js +21 -1
  228. package/lib/internal/_randomFormatUrl.js.map +1 -1
  229. package/lib/internal/_randomFormatUrl.mjs +18 -1
  230. package/lib/internal/_randomFormatUrl.mjs.map +1 -1
  231. package/lib/internal/_randomFormatUuid.d.ts +2 -1
  232. package/lib/internal/_randomFormatUuid.js +3 -2
  233. package/lib/internal/_randomFormatUuid.js.map +1 -1
  234. package/lib/internal/_randomFormatUuid.mjs +3 -2
  235. package/lib/internal/_randomFormatUuid.mjs.map +1 -1
  236. package/lib/internal/_randomInteger.js +59 -28
  237. package/lib/internal/_randomInteger.js.map +1 -1
  238. package/lib/internal/_randomInteger.mjs +56 -16
  239. package/lib/internal/_randomInteger.mjs.map +1 -1
  240. package/lib/internal/_randomMultiple.d.ts +8 -0
  241. package/lib/internal/_randomMultiple.js +168 -0
  242. package/lib/internal/_randomMultiple.js.map +1 -0
  243. package/lib/internal/_randomMultiple.mjs +158 -0
  244. package/lib/internal/_randomMultiple.mjs.map +1 -0
  245. package/lib/internal/_randomNumber.js +42 -42
  246. package/lib/internal/_randomNumber.js.map +1 -1
  247. package/lib/internal/_randomNumber.mjs +41 -27
  248. package/lib/internal/_randomNumber.mjs.map +1 -1
  249. package/lib/internal/_randomPattern.d.ts +2 -1
  250. package/lib/internal/_randomPattern.js +19 -4
  251. package/lib/internal/_randomPattern.js.map +1 -1
  252. package/lib/internal/_randomPattern.mjs +10 -4
  253. package/lib/internal/_randomPattern.mjs.map +1 -1
  254. package/lib/internal/_randomStringLength.d.ts +33 -0
  255. package/lib/internal/_randomStringLength.js +48 -0
  256. package/lib/internal/_randomStringLength.js.map +1 -0
  257. package/lib/internal/_randomStringLength.mjs +44 -0
  258. package/lib/internal/_randomStringLength.mjs.map +1 -0
  259. package/lib/internal/_stringLength.d.ts +1 -0
  260. package/lib/internal/_stringLength.js +11 -0
  261. package/lib/internal/_stringLength.js.map +1 -0
  262. package/lib/internal/_stringLength.mjs +10 -0
  263. package/lib/internal/_stringLength.mjs.map +1 -0
  264. package/lib/internal/_validateReport.js +4 -1
  265. package/lib/internal/_validateReport.js.map +1 -1
  266. package/lib/internal/_validateReport.mjs +2 -1
  267. package/lib/internal/_validateReport.mjs.map +1 -1
  268. package/lib/internal/private/__notationRename.d.ts +14 -0
  269. package/lib/internal/private/__notationRename.js +25 -0
  270. package/lib/internal/private/__notationRename.js.map +1 -0
  271. package/lib/internal/private/__notationRename.mjs +24 -0
  272. package/lib/internal/private/__notationRename.mjs.map +1 -0
  273. package/lib/json.d.ts +2 -2
  274. package/lib/json.mjs.map +1 -1
  275. package/lib/module.d.ts +2 -2
  276. package/lib/module.js.map +1 -1
  277. package/lib/module.mjs.map +1 -1
  278. package/lib/notations.d.ts +20 -4
  279. package/lib/notations.js.map +1 -1
  280. package/lib/notations.mjs.map +1 -1
  281. package/native/adapter/plugin_options.go +117 -0
  282. package/native/adapter/plugin_options_payload_matrix_test.go +181 -0
  283. package/native/cmd/ttsc-typia/any_array_type_tags_transform_test.go +63 -9
  284. package/native/cmd/ttsc-typia/assert_guard_factory_contract_test.go +152 -0
  285. package/native/cmd/ttsc-typia/build.go +81 -64
  286. package/native/cmd/ttsc-typia/build_no_emit_preserves_analysis_options_test.go +67 -0
  287. package/native/cmd/ttsc-typia/build_no_emit_transform_diagnostics_test.go +138 -0
  288. package/native/cmd/ttsc-typia/build_plugin_options_come_from_payload_test.go +48 -0
  289. package/native/cmd/ttsc-typia/build_transactional_emit_success_test.go +81 -0
  290. package/native/cmd/ttsc-typia/build_transform_failure_atomicity_test.go +138 -0
  291. package/native/cmd/ttsc-typia/command_routes_and_diagnostics_coverage_test.go +3 -1
  292. package/native/cmd/ttsc-typia/compare_less_nan_transform_test.go +98 -0
  293. package/native/cmd/ttsc-typia/compare_native_object_overmatch_transform_test.go +161 -0
  294. package/native/cmd/ttsc-typia/compare_nondiscriminable_union_transform_test.go +343 -0
  295. package/native/cmd/ttsc-typia/compare_union_discrimination_transform_test.go +289 -0
  296. package/native/cmd/ttsc-typia/escaped_property_key_path_transform_test.go +193 -0
  297. package/native/cmd/ttsc-typia/finite_option_number_leaf_transform_test.go +240 -0
  298. package/native/cmd/ttsc-typia/functional_promised_type_transform_test.go +220 -0
  299. package/native/cmd/ttsc-typia/functional_receiver_transform_test.go +232 -0
  300. package/native/cmd/ttsc-typia/is_object_function_member_transform_test.go +205 -0
  301. package/native/cmd/ttsc-typia/json_application_alias_function_validation_transform_test.go +151 -0
  302. package/native/cmd/ttsc-typia/json_is_stringify_finite_number_transform_test.go +198 -0
  303. package/native/cmd/ttsc-typia/json_stringify_special_key_transform_test.go +238 -0
  304. package/native/cmd/ttsc-typia/main_wasm.go +21 -2
  305. package/native/cmd/ttsc-typia/native_collection_identity_is_transform_test.go +234 -0
  306. package/native/cmd/ttsc-typia/native_generic_name_guard_is_transform_test.go +194 -0
  307. package/native/cmd/ttsc-typia/native_name_collision_is_transform_test.go +204 -0
  308. package/native/cmd/ttsc-typia/non_trailing_rest_tuple_transform_test.go +23 -11
  309. package/native/cmd/ttsc-typia/notation_dynamic_keys_transform_test.go +286 -0
  310. package/native/cmd/ttsc-typia/notation_kebab_case_transform_test.go +1 -1
  311. package/native/cmd/ttsc-typia/notation_literal_collision_transform_test.go +164 -0
  312. package/native/cmd/ttsc-typia/notation_pascal_case_transform_test.go +230 -0
  313. package/native/cmd/ttsc-typia/notation_unicode_key_transform_test.go +309 -0
  314. package/native/cmd/ttsc-typia/pattern_line_terminator_escape_transform_test.go +224 -0
  315. package/native/cmd/ttsc-typia/plain_prune_union_object_overmatch_transform_test.go +219 -0
  316. package/native/cmd/ttsc-typia/plugin_options_payload_helpers_test.go +181 -0
  317. package/native/cmd/ttsc-typia/private_field_filter_is_transform_test.go +278 -0
  318. package/native/cmd/ttsc-typia/project_catalog_transform_coverage_test.go +73 -27
  319. package/native/cmd/ttsc-typia/project_dependencies_barrel_reexport_transform_test.go +120 -0
  320. package/native/cmd/ttsc-typia/project_dependencies_collapsed_alias_transform_test.go +134 -0
  321. package/native/cmd/ttsc-typia/project_dependencies_custom_lib_name_transform_test.go +135 -0
  322. package/native/cmd/ttsc-typia/project_dependencies_default_barrel_transform_test.go +114 -0
  323. package/native/cmd/ttsc-typia/project_dependencies_empty_heritage_transform_test.go +100 -0
  324. package/native/cmd/ttsc-typia/project_dependencies_envelope_transform_test.go +148 -0
  325. package/native/cmd/ttsc-typia/project_dependencies_index_signature_alias_transform_test.go +139 -0
  326. package/native/cmd/ttsc-typia/project_dependencies_local_reexport_transform_test.go +122 -0
  327. package/native/cmd/ttsc-typia/project_dependencies_signature_alias_transform_test.go +125 -0
  328. package/native/cmd/ttsc-typia/project_dependencies_star_barrel_transform_test.go +112 -0
  329. package/native/cmd/ttsc-typia/project_reference_graph_envelope_transform_test.go +190 -0
  330. package/native/cmd/ttsc-typia/protobuf_is_encode_finite_number_transform_test.go +98 -0
  331. package/native/cmd/ttsc-typia/protobuf_sequence_field_numbers_transform_test.go +52 -22
  332. package/native/cmd/ttsc-typia/symbol_key_member_filter_transform_test.go +279 -0
  333. package/native/cmd/ttsc-typia/template_interpolation_type_tags_transform_test.go +86 -23
  334. package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +3 -1
  335. package/native/cmd/ttsc-typia/transform.go +228 -39
  336. package/native/cmd/ttsc-typia/{transform_declaration_source_produces_no_js_test.go → transform_declaration_source_produces_no_javascript_test.go} +10 -2
  337. package/native/cmd/ttsc-typia/transform_fixtures_emit_coverage_test.go +21 -4
  338. package/native/cmd/ttsc-typia/transform_helpers_test.go +159 -1
  339. package/native/cmd/ttsc-typia/transform_plugin_options_come_from_payload_test.go +43 -0
  340. package/native/cmd/ttsc-typia/transform_single_file_failure_atomicity_test.go +114 -0
  341. package/native/cmd/ttsc-typia/transform_single_file_failure_writes_no_stdout_test.go +43 -0
  342. package/native/cmd/ttsc-typia/transform_single_file_js_distinguishes_same_basename_sources_test.go +81 -0
  343. package/native/cmd/ttsc-typia/transform_single_file_js_empty_emit_reports_no_output_test.go +100 -0
  344. package/native/cmd/ttsc-typia/transform_single_file_js_locates_output_across_layouts_test.go +160 -0
  345. package/native/cmd/ttsc-typia/transform_single_file_success_publishes_artifact_test.go +54 -0
  346. package/native/cmd/ttsc-typia/transform_wasm_host_argv_reports_diagnostics_test.go +39 -0
  347. package/native/cmd/ttsc-typia/tuple_optional_compare_clone_transform_test.go +227 -0
  348. package/native/core/factories/FormatCheatSheet.go +40 -7
  349. package/native/core/factories/IdentifierFactory.go +131 -4
  350. package/native/core/factories/MetadataCommentTagFactory.go +83 -40
  351. package/native/core/factories/MetadataTypeTagFactory.go +13 -1
  352. package/native/core/factories/NumericRangeFactory.go +60 -17
  353. package/native/core/factories/ProtobufFactory.go +7 -4
  354. package/native/core/factories/factory_utility_coverage_test.go +8 -2
  355. package/native/core/factories/format_alias_resolves_to_cheat_sheet_test.go +57 -0
  356. package/native/core/factories/format_alias_table_targets_the_cheat_sheet_test.go +44 -0
  357. package/native/core/factories/identifier_factory_postfix_escapes_every_key_test.go +147 -0
  358. package/native/core/factories/identifier_factory_postfix_survives_every_code_point_test.go +86 -0
  359. package/native/core/factories/internal/metadata/MetadataHelper.go +60 -6
  360. package/native/core/factories/internal/metadata/emplace_metadata_object.go +116 -8
  361. package/native/core/factories/internal/metadata/iterate_metadata.go +6 -0
  362. package/native/core/factories/internal/metadata/iterate_metadata_function.go +4 -11
  363. package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +8 -6
  364. package/native/core/factories/internal/metadata/iterate_metadata_map.go +9 -0
  365. package/native/core/factories/internal/metadata/iterate_metadata_native.go +27 -2
  366. package/native/core/factories/internal/metadata/iterate_metadata_set.go +9 -0
  367. package/native/core/factories/internal/metadata/type_arguments_precondition_test.go +70 -0
  368. package/native/core/factories/metadata_comment_tag_factory_coverage_test.go +39 -0
  369. package/native/core/factories/metadata_comment_tag_factory_exclusivity_matches_interface_test.go +84 -0
  370. package/native/core/factories/metadata_type_tag_factory_accepts_legal_tag_combinations_test.go +60 -0
  371. package/native/core/factories/metadata_type_tag_factory_declarations_test.go +86 -0
  372. package/native/core/factories/metadata_type_tag_factory_keeps_bool_form_exclusivity_test.go +38 -0
  373. package/native/core/factories/metadata_type_tag_factory_rejects_cross_kind_exclusive_tags_test.go +65 -0
  374. package/native/core/factories/metadata_type_tag_factory_rejects_duplicated_array_form_tags_test.go +41 -0
  375. package/native/core/factories/numeric_range_factory_enforces_64bit_bounds_test.go +69 -0
  376. package/native/core/factories/protobuf_recovery_ownership_test.go +64 -0
  377. package/native/core/programmers/IsProgrammer.go +15 -1
  378. package/native/core/programmers/RandomProgrammer.go +51 -14
  379. package/native/core/programmers/compare/CompareEqualProgrammer.go +393 -5
  380. package/native/core/programmers/compare/CompareLessProgrammer.go +4 -2
  381. package/native/core/programmers/functional/FunctionalAssertFunctionProgrammer.go +4 -6
  382. package/native/core/programmers/functional/FunctionalAssertParametersProgrammer.go +5 -13
  383. package/native/core/programmers/functional/FunctionalAssertReturnProgrammer.go +6 -14
  384. package/native/core/programmers/functional/FunctionalIsFunctionProgrammer.go +4 -6
  385. package/native/core/programmers/functional/FunctionalIsParametersProgrammer.go +49 -14
  386. package/native/core/programmers/functional/FunctionalIsReturnProgrammer.go +5 -13
  387. package/native/core/programmers/functional/FunctionalValidateFunctionProgrammer.go +4 -6
  388. package/native/core/programmers/functional/FunctionalValidateParametersProgrammer.go +5 -13
  389. package/native/core/programmers/functional/FunctionalValidateReturnProgrammer.go +5 -13
  390. package/native/core/programmers/functional/internal/FunctionalGeneralProgrammer.go +4 -17
  391. package/native/core/programmers/helpers/CloneJoiner.go +32 -0
  392. package/native/core/programmers/helpers/NotationJoiner.go +86 -28
  393. package/native/core/programmers/helpers/StringifyJoinder.go +32 -1
  394. package/native/core/programmers/helpers/UnionExplorer.go +203 -61
  395. package/native/core/programmers/helpers/joiner_branch_coverage_test.go +5 -3
  396. package/native/core/programmers/helpers/union_explorer_coverage_test.go +1 -1
  397. package/native/core/programmers/internal/CheckerProgrammer.go +100 -48
  398. package/native/core/programmers/iterate/check_template.go +344 -32
  399. package/native/core/programmers/iterate/json_schema_discriminator.go +36 -10
  400. package/native/core/programmers/iterate/json_schema_discriminator_declaration_syntax_test.go +205 -0
  401. package/native/core/programmers/iterate/openapi_v3_downgrader.go +641 -0
  402. package/native/core/programmers/iterate/openapi_v3_downgrader_boolean_default_test.go +95 -0
  403. package/native/core/programmers/iterate/openapi_v3_downgrader_test.go +123 -0
  404. package/native/core/programmers/iterate/template_interpolation_tags_test.go +40 -8
  405. package/native/core/programmers/iterate/template_runtime_pattern.go +52 -7
  406. package/native/core/programmers/json/JsonApplicationProgrammer.go +45 -11
  407. package/native/core/programmers/json/JsonSchemasProgrammer.go +12 -2
  408. package/native/core/programmers/llm/LlmApplicationProgrammer.go +12 -10
  409. package/native/core/programmers/llm/LlmSchemaProgrammer.go +23 -6
  410. package/native/core/programmers/llm/llm_reference_codec_test.go +24 -0
  411. package/native/core/programmers/notations/NotationGeneralProgrammer.go +183 -67
  412. package/native/core/programmers/notations/notation_general_helpers_test.go +1 -3
  413. package/native/core/programmers/notations/notation_general_programmer_pascal_multiword_test.go +72 -0
  414. package/native/core/programmers/notations/notation_general_programmer_underscore_boundary_test.go +68 -0
  415. package/native/core/programmers/plain/PlainClassifyProgrammer.go +23 -15
  416. package/native/core/programmers/plain/PlainCloneProgrammer.go +20 -7
  417. package/native/core/programmers/plain/PlainPruneProgrammer.go +19 -5
  418. package/native/core/programmers/plain/plain_tuple_seed_recovery_ownership_test.go +25 -0
  419. package/native/core/programmers/protobuf/ProtobufDecodeProgrammer.go +37 -28
  420. package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +40 -21
  421. package/native/core/programmers/protobuf/protobuf_programmer_helper_coverage_test.go +26 -0
  422. package/native/core/programmers/random_programmer_length_argument_test.go +53 -0
  423. package/native/core/schemas/metadata/MetadataCollection.go +270 -20
  424. package/native/core/schemas/metadata/MetadataDependency.go +388 -0
  425. package/native/core/schemas/metadata/MetadataObjectType.go +17 -4
  426. package/native/core/schemas/metadata/metadata_collection_generic_argument_dot_test.go +122 -0
  427. package/native/core/schemas/metadata/metadata_collection_name_allocation_test.go +147 -0
  428. package/native/core/schemas/metadata/metadata_collection_openapi_name_cascade_test.go +55 -0
  429. package/native/core/schemas/metadata/metadata_collection_openapi_name_test.go +68 -0
  430. package/native/core/utils/PatternUtil.go +13 -0
  431. package/native/core/utils/PromiseTypeFactory.go +59 -0
  432. package/native/core/utils/ProtobufNameEncoder.go +8 -0
  433. package/native/core/utils/promise_type_factory_semantics_test.go +118 -0
  434. package/native/go.mod +9 -1
  435. package/native/transform/CallExpressionTransformer.go +12 -0
  436. package/native/transform/features/json/JsonApplicationTransformer.go +1 -1
  437. package/native/transform/features/json/JsonSchemaTransformer.go +1 -1
  438. package/native/transform/features/json/JsonSchemasTransformer.go +5 -4
  439. package/package.json +16 -4
  440. package/src/executable/FileSystemIdentity.ts +189 -0
  441. package/src/executable/TypiaGenerateWizard.ts +377 -110
  442. package/src/functional.ts +30 -60
  443. package/src/internal/_ProtobufReader.ts +129 -43
  444. package/src/internal/_createStandardSchema.ts +15 -1
  445. package/src/internal/_decimal.ts +69 -0
  446. package/src/internal/_httpQueryParseURLSearchParams.ts +24 -2
  447. package/src/internal/_isFormatByte.ts +2 -5
  448. package/src/internal/_isFormatDate.ts +15 -2
  449. package/src/internal/_isFormatDateTime.ts +28 -2
  450. package/src/internal/_isFormatIri.ts +5 -2
  451. package/src/internal/_isFormatIriReference.ts +11 -3
  452. package/src/internal/_isFormatUriReference.ts +1 -1
  453. package/src/internal/_isMultipleOf.ts +8 -0
  454. package/src/internal/_isTypeFloat.ts +1 -1
  455. package/src/internal/_isTypeInt64.ts +1 -0
  456. package/src/internal/_isTypeInt64Bigint.ts +12 -0
  457. package/src/internal/_isTypeUint64.ts +1 -0
  458. package/src/internal/_isTypeUint64Bigint.ts +7 -0
  459. package/src/internal/_isUniqueItems.ts +134 -132
  460. package/src/internal/_notationAny.ts +9 -4
  461. package/src/internal/_notationAssign.ts +20 -0
  462. package/src/internal/_notationCamel.ts +31 -10
  463. package/src/internal/_notationKebab.ts +11 -0
  464. package/src/internal/_notationKeyCollision.ts +9 -0
  465. package/src/internal/_notationPascal.ts +19 -6
  466. package/src/internal/_notationSnake.ts +24 -21
  467. package/src/internal/_plainCloneAny.ts +208 -33
  468. package/src/internal/_randomArray.ts +13 -4
  469. package/src/internal/_randomFormatByte.ts +4 -1
  470. package/src/internal/_randomFormatDate.ts +17 -12
  471. package/src/internal/_randomFormatDatetime.ts +15 -10
  472. package/src/internal/_randomFormatDuration.ts +16 -14
  473. package/src/internal/_randomFormatEmail.ts +8 -2
  474. package/src/internal/_randomFormatHostname.ts +48 -1
  475. package/src/internal/_randomFormatIdnEmail.ts +18 -2
  476. package/src/internal/_randomFormatIdnHostname.ts +34 -2
  477. package/src/internal/_randomFormatIpv4.ts +3 -2
  478. package/src/internal/_randomFormatIpv6.ts +3 -2
  479. package/src/internal/_randomFormatIri.ts +3 -1
  480. package/src/internal/_randomFormatIriReference.ts +3 -1
  481. package/src/internal/_randomFormatJsonPointer.ts +8 -2
  482. package/src/internal/_randomFormatPassword.ts +11 -6
  483. package/src/internal/_randomFormatRegex.ts +4 -1
  484. package/src/internal/_randomFormatRelativeJsonPointer.ts +13 -6
  485. package/src/internal/_randomFormatTime.ts +13 -10
  486. package/src/internal/_randomFormatUri.ts +3 -1
  487. package/src/internal/_randomFormatUriReference.ts +3 -1
  488. package/src/internal/_randomFormatUriTemplate.ts +3 -1
  489. package/src/internal/_randomFormatUrl.ts +25 -2
  490. package/src/internal/_randomFormatUuid.ts +10 -6
  491. package/src/internal/_randomInteger.ts +87 -40
  492. package/src/internal/_randomMultiple.ts +245 -0
  493. package/src/internal/_randomNumber.ts +72 -55
  494. package/src/internal/_randomPattern.ts +26 -4
  495. package/src/internal/_randomStringLength.ts +72 -0
  496. package/src/internal/_stringLength.ts +5 -0
  497. package/src/internal/_validateReport.ts +5 -1
  498. package/src/internal/private/__notationRename.ts +24 -0
  499. package/src/json.ts +2 -2
  500. package/src/module.ts +4 -6
  501. package/src/notations.ts +20 -4
  502. package/lib/internal/private/__notationCapitalize.d.ts +0 -1
  503. package/lib/internal/private/__notationCapitalize.js +0 -6
  504. package/lib/internal/private/__notationCapitalize.js.map +0 -1
  505. package/lib/internal/private/__notationCapitalize.mjs +0 -6
  506. package/lib/internal/private/__notationCapitalize.mjs.map +0 -1
  507. package/lib/internal/private/__notationUnsnake.d.ts +0 -4
  508. package/lib/internal/private/__notationUnsnake.js +0 -26
  509. package/lib/internal/private/__notationUnsnake.js.map +0 -1
  510. package/lib/internal/private/__notationUnsnake.mjs +0 -15
  511. package/lib/internal/private/__notationUnsnake.mjs.map +0 -1
  512. package/native/cmd/ttsc-typia/plugin_options_missing_config_test.go +0 -26
  513. package/native/cmd/ttsc-typia/plugin_options_undefined_false_test.go +0 -36
  514. package/src/internal/private/__notationCapitalize.ts +0 -2
  515. package/src/internal/private/__notationUnsnake.ts +0 -24
@@ -2,6 +2,7 @@ import { createCommand } from "commander";
2
2
  import fs from "fs";
3
3
  import inquirer from "inquirer";
4
4
  import { createRequire } from "module";
5
+ import os from "os";
5
6
  import path from "path";
6
7
  import { glob, isDynamicPattern } from "tinyglobby";
7
8
  import type {
@@ -9,6 +10,8 @@ import type {
9
10
  ITtscCompilerTransformation,
10
11
  } from "ttsc";
11
12
 
13
+ import { FileSystemIdentity } from "./FileSystemIdentity";
14
+
12
15
  export namespace TypiaGenerateWizard {
13
16
  export async function generate(): Promise<void> {
14
17
  console.log("----------------------------------------");
@@ -98,24 +101,61 @@ export namespace TypiaGenerateWizard {
98
101
  location.output = path.resolve(location.output);
99
102
  location.project = resolveProjectConfigFile(location.project);
100
103
 
104
+ const policy = new FileSystemIdentity.Policy();
105
+ const outputProbe: string = await nearestExistingAncestor(location.output);
106
+ await ensureExistingDirectoryPath({
107
+ label: "output parent path",
108
+ directory: outputProbe,
109
+ });
110
+ policy.observe(
111
+ await FileSystemIdentity.probeDirectory(outputProbe),
112
+ outputProbe,
113
+ );
114
+ policy.observe(
115
+ await FileSystemIdentity.inspectDirectory(path.dirname(location.project)),
116
+ path.dirname(location.project),
117
+ );
118
+
101
119
  const entries: IInputFile[] =
102
120
  location.files.length === 0
103
- ? await prepareDirectoryInput(location)
104
- : await prepareFileInputs(location);
121
+ ? await prepareDirectoryInput(location, policy)
122
+ : await prepareFileInputs(location, policy);
123
+ const identity: FileSystemIdentity.IIdentity = policy.get();
124
+ await inspectTargetDirectories({
125
+ identity,
126
+ output: location.output,
127
+ targets: entries.map((entry) => entry.target),
128
+ });
105
129
 
106
130
  const binary = resolveTsgoBinary();
107
131
  const cwd = path.dirname(location.project);
108
- const transformed = transformProject({
109
- binary,
110
- cwd,
111
- tsconfig: location.project,
132
+ const temporaryProject: ITemporaryProject = await createTemporaryProject({
133
+ entries,
134
+ project: location.project,
112
135
  });
113
- const outputByKey: Map<string, string> =
114
- indexTransformedOutputs(transformed);
136
+ let transformed: Record<string, string>;
137
+ try {
138
+ transformed = transformProject({
139
+ binary,
140
+ cwd,
141
+ projectRoot: cwd,
142
+ tsconfig: temporaryProject.config,
143
+ });
144
+ } finally {
145
+ await fs.promises.rm(temporaryProject.directory, {
146
+ force: true,
147
+ recursive: true,
148
+ });
149
+ }
150
+ const outputByKey: Map<string, string> = indexTransformedOutputs(
151
+ transformed,
152
+ identity,
153
+ );
115
154
  const outputs: IOutputFile[] = entries.map((entry) => {
116
155
  const output = getTransformedOutput({
117
156
  cwd,
118
157
  entry,
158
+ identity,
119
159
  outputByKey,
120
160
  });
121
161
  if (output === undefined) {
@@ -128,14 +168,19 @@ export namespace TypiaGenerateWizard {
128
168
 
129
169
  await ensureOutputDirectory(location.output);
130
170
  await ensureTargetDirectories({
171
+ identity,
131
172
  output: location.output,
132
173
  targets: outputs.map(({ entry }) => entry.target),
133
174
  });
134
175
  await ensurePhysicalTargets({
176
+ identity,
135
177
  output: location.output,
136
178
  entries: outputs.map(({ entry }) => entry),
137
179
  });
138
- await ensureTargetFiles(outputs.map(({ entry }) => entry));
180
+ await ensureTargetFiles(
181
+ outputs.map(({ entry }) => entry),
182
+ identity,
183
+ );
139
184
  for (const { entry, output } of outputs) {
140
185
  await fs.promises.writeFile(entry.target, formatOutput(output), "utf8");
141
186
  }
@@ -151,6 +196,45 @@ export namespace TypiaGenerateWizard {
151
196
  output: string;
152
197
  }
153
198
 
199
+ interface ITraversalEntry {
200
+ file: string;
201
+ name: string;
202
+ stat: fs.Stats;
203
+ }
204
+
205
+ interface ITemporaryProject {
206
+ config: string;
207
+ directory: string;
208
+ }
209
+
210
+ async function createTemporaryProject(props: {
211
+ entries: IInputFile[];
212
+ project: string;
213
+ }): Promise<ITemporaryProject> {
214
+ const directory: string = await fs.promises.mkdtemp(
215
+ path.join(os.tmpdir(), "typia-generate-project-"),
216
+ );
217
+ const config: string = path.join(directory, "tsconfig.json");
218
+ try {
219
+ await fs.promises.writeFile(
220
+ config,
221
+ JSON.stringify({
222
+ extends: props.project,
223
+ exclude: [],
224
+ files: props.entries.map((entry) => compilerInputPath(entry.file)),
225
+ include: [],
226
+ }),
227
+ "utf8",
228
+ );
229
+ return { config, directory };
230
+ } catch (error) {
231
+ await fs.promises.rm(directory, { force: true, recursive: true });
232
+ throw new URIError(
233
+ `Error on TypiaGenerateWizard.generate(): unable to prepare the bounded input project: ${formatUnknownError(error)}`,
234
+ );
235
+ }
236
+ }
237
+
154
238
  async function ensureOutputDirectory(output: string): Promise<void> {
155
239
  if (fs.existsSync(output) === false) {
156
240
  await ensureCreatableDirectory(output);
@@ -164,17 +248,36 @@ export namespace TypiaGenerateWizard {
164
248
  }
165
249
 
166
250
  async function ensureTargetDirectories(props: {
251
+ identity: FileSystemIdentity.IIdentity;
167
252
  output: string;
168
253
  targets: string[];
169
254
  }): Promise<void> {
170
- const directories: Map<string, string> = new Map();
171
- for (const target of props.targets) {
172
- const directory: string = path.dirname(target);
173
- directories.set(filesystemKey(directory), directory);
255
+ await inspectTargetDirectories(props);
256
+ const directories: Map<string, string> = targetDirectories(props);
257
+ for (const directory of directories.values()) {
258
+ try {
259
+ await fs.promises.mkdir(directory, { recursive: true });
260
+ } catch (exp) {
261
+ throw new URIError(
262
+ `Error on TypiaGenerateWizard.generate(): unable to create output parent directory ${directory}: ${formatUnknownError(exp)}`,
263
+ );
264
+ }
265
+ await ensureExistingDirectory({
266
+ label: "output parent path",
267
+ directory,
268
+ });
174
269
  }
270
+ }
175
271
 
272
+ async function inspectTargetDirectories(props: {
273
+ identity: FileSystemIdentity.IIdentity;
274
+ output: string;
275
+ targets: string[];
276
+ }): Promise<void> {
277
+ const directories: Map<string, string> = targetDirectories(props);
176
278
  for (const directory of directories.values()) {
177
279
  await ensureOutputAncestorDirectories({
280
+ identity: props.identity,
178
281
  output: props.output,
179
282
  directory,
180
283
  });
@@ -185,19 +288,18 @@ export namespace TypiaGenerateWizard {
185
288
  });
186
289
  }
187
290
  }
188
- for (const directory of directories.values()) {
189
- try {
190
- await fs.promises.mkdir(directory, { recursive: true });
191
- } catch (exp) {
192
- throw new URIError(
193
- `Error on TypiaGenerateWizard.generate(): unable to create output parent directory ${directory}: ${formatUnknownError(exp)}`,
194
- );
195
- }
196
- await ensureExistingDirectory({
197
- label: "output parent path",
198
- directory,
199
- });
291
+ }
292
+
293
+ function targetDirectories(props: {
294
+ identity: FileSystemIdentity.IIdentity;
295
+ targets: string[];
296
+ }): Map<string, string> {
297
+ const directories: Map<string, string> = new Map();
298
+ for (const target of props.targets) {
299
+ const directory: string = path.dirname(target);
300
+ directories.set(props.identity.filesystemKey(directory), directory);
200
301
  }
302
+ return directories;
201
303
  }
202
304
 
203
305
  async function ensureCreatableDirectory(directory: string): Promise<void> {
@@ -223,12 +325,13 @@ export namespace TypiaGenerateWizard {
223
325
  }
224
326
 
225
327
  async function ensureOutputAncestorDirectories(props: {
328
+ identity: FileSystemIdentity.IIdentity;
226
329
  output: string;
227
330
  directory: string;
228
331
  }): Promise<void> {
229
332
  const output: string = path.resolve(props.output);
230
333
  const directory: string = path.resolve(props.directory);
231
- if (isSameOrChildPath(directory, output) === false) {
334
+ if (props.identity.contains(directory, output) === false) {
232
335
  throw new URIError(
233
336
  `Error on TypiaGenerateWizard.generate(): output parent path escapes output directory: ${props.directory}`,
234
337
  );
@@ -285,7 +388,7 @@ export namespace TypiaGenerateWizard {
285
388
  current = path.join(current, segment);
286
389
  await ensureExistingDirectorySegment({
287
390
  label:
288
- filesystemKey(current) === filesystemKey(directory)
391
+ path.normalize(current) === path.normalize(directory)
289
392
  ? props.label
290
393
  : `${props.label} ancestor`,
291
394
  directory: current,
@@ -311,26 +414,29 @@ export namespace TypiaGenerateWizard {
311
414
  }
312
415
 
313
416
  async function ensurePhysicalTargets(props: {
417
+ identity: FileSystemIdentity.IIdentity;
314
418
  output: string;
315
419
  entries: IInputFile[];
316
420
  }): Promise<void> {
317
421
  const output: string = await fs.promises.realpath(props.output);
318
422
  const inputs: Set<string> = new Set();
319
423
  for (const entry of props.entries) {
320
- inputs.add(filesystemKey(await fs.promises.realpath(entry.file)));
424
+ inputs.add(
425
+ props.identity.filesystemKey(await fs.promises.realpath(entry.file)),
426
+ );
321
427
  }
322
428
 
323
429
  for (const entry of props.entries) {
324
430
  const parent: string = path.dirname(entry.target);
325
431
  const directory: string = await fs.promises.realpath(parent);
326
- if (isSameOrChildPath(directory, output) === false) {
432
+ if (props.identity.contains(directory, output) === false) {
327
433
  throw new URIError(
328
434
  `Error on TypiaGenerateWizard.generate(): output parent path escapes output directory through a symbolic link: ${parent}`,
329
435
  );
330
436
  }
331
437
 
332
438
  const target: string = path.join(directory, path.basename(entry.target));
333
- if (inputs.has(filesystemKey(target))) {
439
+ if (inputs.has(props.identity.filesystemKey(target))) {
334
440
  throw new URIError(
335
441
  `Error on TypiaGenerateWizard.generate(): output file would overwrite input file through a symbolic link: ${entry.target}`,
336
442
  );
@@ -338,12 +444,20 @@ export namespace TypiaGenerateWizard {
338
444
  }
339
445
  }
340
446
 
341
- async function ensureTargetFiles(entries: IInputFile[]): Promise<void> {
447
+ async function ensureTargetFiles(
448
+ entries: IInputFile[],
449
+ identity: FileSystemIdentity.IIdentity,
450
+ ): Promise<void> {
342
451
  const inputs: Set<string> = new Set();
343
452
  const files: Map<string, IInputFile> = new Map();
344
453
  for (const entry of entries) {
345
- inputs.add(fileIdentityKey(await fs.promises.stat(entry.file)));
346
- files.set(filesystemKey(entry.target), entry);
454
+ inputs.add(
455
+ fileIdentityKey(
456
+ await fs.promises.stat(entry.file),
457
+ await fs.promises.realpath(entry.file),
458
+ ),
459
+ );
460
+ files.set(identity.filesystemKey(entry.target), entry);
347
461
  }
348
462
 
349
463
  for (const entry of files.values()) {
@@ -363,7 +477,11 @@ export namespace TypiaGenerateWizard {
363
477
  `Error on TypiaGenerateWizard.generate(): output file path is not a regular file: ${entry.target}`,
364
478
  );
365
479
  }
366
- if (inputs.has(fileIdentityKey(stat))) {
480
+ if (
481
+ inputs.has(
482
+ fileIdentityKey(stat, await fs.promises.realpath(entry.target)),
483
+ )
484
+ ) {
367
485
  throw new URIError(
368
486
  `Error on TypiaGenerateWizard.generate(): output file would overwrite input file through a physical file alias: ${entry.target}`,
369
487
  );
@@ -378,6 +496,7 @@ export namespace TypiaGenerateWizard {
378
496
 
379
497
  async function prepareDirectoryInput(
380
498
  location: IArguments,
499
+ policy: FileSystemIdentity.Policy,
381
500
  ): Promise<IInputFile[]> {
382
501
  if (location.input === undefined) {
383
502
  throw new URIError(
@@ -396,15 +515,19 @@ export namespace TypiaGenerateWizard {
396
515
  );
397
516
  }
398
517
 
518
+ const inputReal: string = await fs.promises.realpath(input);
519
+ const outputReal: string | undefined = await optionalRealPath(
520
+ location.output,
521
+ );
399
522
  const files: string[] = [];
400
523
  await gather({
401
- location: {
402
- input,
403
- output: location.output,
404
- },
405
524
  container: files,
406
525
  from: input,
407
- to: location.output,
526
+ inputReal,
527
+ outputReal,
528
+ policy,
529
+ visitedDirectories: new Set(),
530
+ visitedFiles: new Set(),
408
531
  });
409
532
  return files.map((file) => ({
410
533
  file,
@@ -414,14 +537,21 @@ export namespace TypiaGenerateWizard {
414
537
 
415
538
  async function prepareFileInputs(
416
539
  location: IArguments,
540
+ policy: FileSystemIdentity.Policy,
417
541
  ): Promise<IInputFile[]> {
418
542
  const targets: Set<string> = new Set();
419
543
  const output: IInputFile[] = [];
420
544
  for (const input of await expandFileInputs(
421
545
  location.files,
422
546
  location.output,
547
+ policy,
423
548
  )) {
424
549
  const file: string = path.resolve(input);
550
+ policy.observe(
551
+ await FileSystemIdentity.inspectDirectory(path.dirname(file)),
552
+ path.dirname(file),
553
+ );
554
+ const identity: FileSystemIdentity.IIdentity = policy.get();
425
555
  if (fs.existsSync(file) === false) {
426
556
  throw new URIError(
427
557
  `Error on TypiaGenerateWizard.generate(): input file does not exist: ${input}`,
@@ -430,21 +560,21 @@ export namespace TypiaGenerateWizard {
430
560
  throw new URIError(
431
561
  `Error on TypiaGenerateWizard.generate(): input path is not a file: ${input}`,
432
562
  );
433
- } else if (isDeclarationFile(file)) {
563
+ } else if (identity.isDeclarationFile(file)) {
434
564
  continue;
435
- } else if (isSupportedExtension(file) === false) {
565
+ } else if (identity.isSupportedExtension(file) === false) {
436
566
  throw new URIError(
437
567
  `Error on TypiaGenerateWizard.generate(): input file is not a supported TypeScript source: ${input}`,
438
568
  );
439
569
  }
440
570
 
441
571
  const target: string = path.join(location.output, path.basename(file));
442
- if (isSamePath(file, target)) {
572
+ if (identity.isSamePath(file, target)) {
443
573
  throw new URIError(
444
574
  `Error on TypiaGenerateWizard.generate(): output file would overwrite input file: ${input}`,
445
575
  );
446
576
  }
447
- const key: string = filesystemKey(target);
577
+ const key: string = identity.filesystemKey(target);
448
578
  if (targets.has(key)) {
449
579
  throw new URIError(
450
580
  `Error on TypiaGenerateWizard.generate(): duplicate output filename for ${target}`,
@@ -464,14 +594,25 @@ export namespace TypiaGenerateWizard {
464
594
  async function expandFileInputs(
465
595
  inputs: string[],
466
596
  directory: string,
597
+ policy: FileSystemIdentity.Policy,
467
598
  ): Promise<string[]> {
468
599
  const output: string[] = [];
469
600
  for (const input of inputs) {
470
601
  const pattern: string = toGlobPattern(input);
471
602
  if (isDynamicPattern(pattern, { caseSensitiveMatch: true })) {
603
+ const searchDirectory: string = await globSearchDirectory(input);
604
+ const caseSensitive: boolean | undefined =
605
+ await FileSystemIdentity.inspectDirectory(searchDirectory);
606
+ if (caseSensitive === undefined) {
607
+ throw new URIError(
608
+ `Error on TypiaGenerateWizard.generate(): unable to determine filesystem case behavior for input pattern base ${searchDirectory}.`,
609
+ );
610
+ }
611
+ policy.observe(caseSensitive, searchDirectory);
612
+ const identity: FileSystemIdentity.IIdentity = policy.get();
472
613
  const matches: string[] = await glob(pattern, {
473
614
  absolute: true,
474
- caseSensitiveMatch: isCaseSensitive(),
615
+ caseSensitiveMatch: identity.caseSensitive,
475
616
  cwd: process.cwd(),
476
617
  onlyFiles: true,
477
618
  });
@@ -481,13 +622,17 @@ export namespace TypiaGenerateWizard {
481
622
  );
482
623
  }
483
624
  output.push(
484
- ...excludeOutputFiles(matches, directory).filter(
485
- isSupportedExtension,
625
+ ...excludeOutputFiles(matches, directory, identity).filter((file) =>
626
+ identity.isSupportedExtension(file),
486
627
  ),
487
628
  );
488
629
  } else {
489
630
  const file: string = path.resolve(input);
490
- if (isSameOrChildPath(file, directory) === false) {
631
+ policy.observe(
632
+ await FileSystemIdentity.inspectDirectory(path.dirname(file)),
633
+ path.dirname(file),
634
+ );
635
+ if (policy.get().contains(file, directory) === false) {
491
636
  output.push(file);
492
637
  }
493
638
  }
@@ -495,8 +640,25 @@ export namespace TypiaGenerateWizard {
495
640
  return output;
496
641
  }
497
642
 
498
- function excludeOutputFiles(files: string[], directory: string): string[] {
499
- return files.filter((file) => isSameOrChildPath(file, directory) === false);
643
+ function excludeOutputFiles(
644
+ files: string[],
645
+ directory: string,
646
+ identity: FileSystemIdentity.IIdentity,
647
+ ): string[] {
648
+ return files.filter((file) => identity.contains(file, directory) === false);
649
+ }
650
+
651
+ async function globSearchDirectory(input: string): Promise<string> {
652
+ let current: string = path.resolve(input);
653
+ while (
654
+ isDynamicPattern(toGlobPattern(current), { caseSensitiveMatch: true })
655
+ ) {
656
+ const parent: string = path.dirname(current);
657
+ if (parent === current) break;
658
+ current = parent;
659
+ }
660
+ if (fs.existsSync(current) && (await isDirectory(current))) return current;
661
+ return nearestExistingAncestor(path.dirname(current));
500
662
  }
501
663
 
502
664
  function toGlobPattern(input: string): string {
@@ -506,12 +668,14 @@ export namespace TypiaGenerateWizard {
506
668
  function transformProject(props: {
507
669
  binary: string;
508
670
  cwd: string;
671
+ projectRoot: string;
509
672
  tsconfig: string;
510
673
  }): Record<string, string> {
511
674
  const TtscCompiler = loadTtscCompiler();
512
675
  const result: ITtscCompilerTransformation = new TtscCompiler({
513
676
  binary: props.binary,
514
677
  cwd: props.cwd,
678
+ projectRoot: props.projectRoot,
515
679
  tsconfig: props.tsconfig,
516
680
  }).transform();
517
681
  if (result.type === "success") {
@@ -671,7 +835,7 @@ export namespace TypiaGenerateWizard {
671
835
  function resolveFromRoots(request: string, roots: string[]): string | null {
672
836
  for (const root of roots) {
673
837
  try {
674
- return require.resolve(request, { paths: [root] });
838
+ return createRequire(path.join(root, "package.json")).resolve(request);
675
839
  } catch {
676
840
  continue;
677
841
  }
@@ -690,47 +854,100 @@ export namespace TypiaGenerateWizard {
690
854
  }
691
855
 
692
856
  async function gather(props: {
693
- location: {
694
- input: string;
695
- output: string;
696
- };
697
857
  container: string[];
698
858
  from: string;
699
- to: string;
859
+ inputReal: string;
860
+ outputReal: string | undefined;
861
+ policy: FileSystemIdentity.Policy;
862
+ visitedDirectories: Set<string>;
863
+ visitedFiles: Set<string>;
700
864
  }): Promise<void> {
701
- if (isSamePath(props.from, props.location.output)) return;
865
+ const currentReal: string = await resolveTraversalPath(props.from);
866
+ if (
867
+ props.outputReal !== undefined &&
868
+ isPhysicalSameOrChildPath(currentReal, props.outputReal)
869
+ )
870
+ return;
871
+ ensurePhysicalInputContainment({
872
+ file: props.from,
873
+ input: props.inputReal,
874
+ real: currentReal,
875
+ });
876
+
877
+ const currentStat: fs.Stats = await fs.promises.stat(props.from);
878
+ const directoryIdentity: string = fileIdentityKey(currentStat, currentReal);
879
+ if (props.visitedDirectories.has(directoryIdentity)) {
880
+ const lexicalStat: fs.Stats = await fs.promises.lstat(props.from);
881
+ if (lexicalStat.isSymbolicLink()) {
882
+ throw new URIError(
883
+ `Error on TypiaGenerateWizard.generate(): input directory link revisits a physical directory: ${props.from}.`,
884
+ );
885
+ }
886
+ return;
887
+ }
888
+ props.visitedDirectories.add(directoryIdentity);
889
+
890
+ props.policy.observe(
891
+ await FileSystemIdentity.inspectDirectory(props.from),
892
+ props.from,
893
+ );
894
+ const identity: FileSystemIdentity.IIdentity = props.policy.get();
895
+ const entries: ITraversalEntry[] = await Promise.all(
896
+ (await fs.promises.readdir(props.from)).map(async (name) => {
897
+ const file: string = path.join(props.from, name);
898
+ try {
899
+ return { file, name, stat: await fs.promises.lstat(file) };
900
+ } catch (error) {
901
+ throw new URIError(
902
+ `Error on TypiaGenerateWizard.generate(): unable to inspect input path ${file}: ${formatUnknownError(error)}`,
903
+ );
904
+ }
905
+ }),
906
+ );
907
+ entries.sort((x, y) => {
908
+ const linkOrder: number =
909
+ Number(x.stat.isSymbolicLink()) - Number(y.stat.isSymbolicLink());
910
+ return linkOrder !== 0 ? linkOrder : x.name.localeCompare(y.name);
911
+ });
702
912
 
703
- for (const file of await fs.promises.readdir(props.from)) {
704
- const next: string = path.join(props.from, file);
705
- const stat: fs.Stats = await fs.promises.stat(next);
913
+ for (const entry of entries) {
914
+ let stat: fs.Stats;
915
+ let real: string;
916
+ try {
917
+ stat = await fs.promises.stat(entry.file);
918
+ real = await fs.promises.realpath(entry.file);
919
+ } catch (error) {
920
+ throw new URIError(
921
+ `Error on TypiaGenerateWizard.generate(): input link target is missing or unreadable: ${entry.file}: ${formatUnknownError(error)}`,
922
+ );
923
+ }
924
+
925
+ if (
926
+ props.outputReal !== undefined &&
927
+ isPhysicalSameOrChildPath(real, props.outputReal)
928
+ )
929
+ continue;
930
+ ensurePhysicalInputContainment({
931
+ file: entry.file,
932
+ input: props.inputReal,
933
+ real,
934
+ });
706
935
 
707
936
  if (stat.isDirectory()) {
708
- await gather({
709
- location: props.location,
710
- container: props.container,
711
- from: next,
712
- to: path.join(props.to, file),
713
- });
937
+ await gather({ ...props, from: entry.file });
714
938
  continue;
715
939
  }
716
- if (isSupportedExtension(file)) {
717
- props.container.push(next);
718
- }
719
- }
720
- }
721
-
722
- function isSupportedExtension(filename: string): boolean {
723
- const normalized: string = isCaseSensitive()
724
- ? filename
725
- : filename.toLowerCase();
726
- return TS_PATTERN.test(normalized) && !DTS_PATTERN.test(normalized);
727
- }
940
+ if (
941
+ stat.isFile() === false ||
942
+ identity.isSupportedExtension(entry.name) === false
943
+ )
944
+ continue;
728
945
 
729
- function isDeclarationFile(filename: string): boolean {
730
- const normalized: string = isCaseSensitive()
731
- ? filename
732
- : filename.toLowerCase();
733
- return DTS_PATTERN.test(normalized);
946
+ const fileIdentity: string = fileIdentityKey(stat, real);
947
+ if (props.visitedFiles.has(fileIdentity)) continue;
948
+ props.visitedFiles.add(fileIdentity);
949
+ props.container.push(entry.file);
950
+ }
734
951
  }
735
952
 
736
953
  function formatOutput(output: string): string {
@@ -741,10 +958,17 @@ export namespace TypiaGenerateWizard {
741
958
 
742
959
  function indexTransformedOutputs(
743
960
  outputs: Record<string, string>,
961
+ identity: FileSystemIdentity.IIdentity,
744
962
  ): Map<string, string> {
745
963
  const map: Map<string, string> = new Map();
746
964
  for (const [file, output] of Object.entries(outputs)) {
747
- map.set(projectFileKey(file), output);
965
+ const key: string = identity.projectFileKey(file);
966
+ if (map.has(key)) {
967
+ throw new URIError(
968
+ `Error on TypiaGenerateWizard.generate(): transformed outputs have ambiguous filesystem identities: ${file}.`,
969
+ );
970
+ }
971
+ map.set(key, output);
748
972
  }
749
973
  return map;
750
974
  }
@@ -752,33 +976,43 @@ export namespace TypiaGenerateWizard {
752
976
  function getTransformedOutput(props: {
753
977
  cwd: string;
754
978
  entry: IInputFile;
979
+ identity: FileSystemIdentity.IIdentity;
755
980
  outputByKey: Map<string, string>;
756
981
  }): string | undefined {
757
982
  const output = props.outputByKey.get(
758
- projectFileKey(projectKey(props.cwd, props.entry.file)),
983
+ props.identity.projectFileKey(projectKey(props.cwd, props.entry.file)),
759
984
  );
760
985
  if (output !== undefined) {
761
986
  return output;
762
987
  }
763
988
 
989
+ const compilerFile: string = compilerInputPath(props.entry.file);
990
+ if (
991
+ props.identity.isSamePath(compilerFile, props.entry.file) === false &&
992
+ props.identity.contains(compilerFile, props.cwd)
993
+ ) {
994
+ const compiled: string | undefined = props.outputByKey.get(
995
+ props.identity.projectFileKey(projectKey(props.cwd, compilerFile)),
996
+ );
997
+ if (compiled !== undefined) return compiled;
998
+ }
999
+
764
1000
  const real: string = resolveRealPath(props.entry.file);
765
1001
  if (
766
- isSamePath(real, props.entry.file) ||
767
- isSameOrChildPath(real, props.cwd) === false
1002
+ props.identity.isSamePath(real, props.entry.file) ||
1003
+ props.identity.contains(real, props.cwd) === false
768
1004
  ) {
769
1005
  return undefined;
770
1006
  }
771
- return props.outputByKey.get(projectFileKey(projectKey(props.cwd, real)));
1007
+ return props.outputByKey.get(
1008
+ props.identity.projectFileKey(projectKey(props.cwd, real)),
1009
+ );
772
1010
  }
773
1011
 
774
1012
  function projectKey(root: string, file: string): string {
775
1013
  return path.relative(root, file).replace(/\\/g, "/");
776
1014
  }
777
1015
 
778
- function projectFileKey(file: string): string {
779
- return isCaseSensitive() ? file : file.toLowerCase();
780
- }
781
-
782
1016
  function resolveRealPath(file: string): string {
783
1017
  try {
784
1018
  return fs.realpathSync(file);
@@ -787,26 +1021,60 @@ export namespace TypiaGenerateWizard {
787
1021
  }
788
1022
  }
789
1023
 
790
- function isSamePath(x: string, y: string): boolean {
791
- return filesystemKey(x) === filesystemKey(y);
1024
+ function compilerInputPath(file: string): string {
1025
+ try {
1026
+ if (fs.lstatSync(file).isSymbolicLink()) {
1027
+ return path.join(
1028
+ resolveRealPath(path.dirname(file)),
1029
+ path.basename(file),
1030
+ );
1031
+ }
1032
+ } catch {
1033
+ return file;
1034
+ }
1035
+ return resolveRealPath(file);
1036
+ }
1037
+
1038
+ async function optionalRealPath(file: string): Promise<string | undefined> {
1039
+ try {
1040
+ return await fs.promises.realpath(file);
1041
+ } catch (error) {
1042
+ if (isMissingFileError(error)) return undefined;
1043
+ throw new URIError(
1044
+ `Error on TypiaGenerateWizard.generate(): unable to resolve path ${file}: ${formatUnknownError(error)}`,
1045
+ );
1046
+ }
792
1047
  }
793
1048
 
794
- function isSameOrChildPath(file: string, directory: string): boolean {
795
- const fileKey: string = filesystemKey(path.resolve(file));
796
- const directoryKey: string = filesystemKey(path.resolve(directory));
797
- const directoryPrefix: string = directoryKey.endsWith(path.sep)
798
- ? directoryKey
799
- : `${directoryKey}${path.sep}`;
800
- return fileKey === directoryKey || fileKey.startsWith(directoryPrefix);
1049
+ async function resolveTraversalPath(file: string): Promise<string> {
1050
+ try {
1051
+ return await fs.promises.realpath(file);
1052
+ } catch (error) {
1053
+ throw new URIError(
1054
+ `Error on TypiaGenerateWizard.generate(): unable to resolve input path ${file}: ${formatUnknownError(error)}`,
1055
+ );
1056
+ }
801
1057
  }
802
1058
 
803
- function filesystemKey(file: string): string {
804
- const normalized: string = path.normalize(file);
805
- return isCaseSensitive() ? normalized : normalized.toLowerCase();
1059
+ function ensurePhysicalInputContainment(props: {
1060
+ file: string;
1061
+ input: string;
1062
+ real: string;
1063
+ }): void {
1064
+ if (isPhysicalSameOrChildPath(props.real, props.input)) return;
1065
+ throw new URIError(
1066
+ `Error on TypiaGenerateWizard.generate(): input path resolves outside the input directory: ${props.file}.`,
1067
+ );
806
1068
  }
807
1069
 
808
- function isCaseSensitive(): boolean {
809
- return process.platform !== "win32" && process.platform !== "darwin";
1070
+ function isPhysicalSameOrChildPath(file: string, directory: string): boolean {
1071
+ const relative: string = path.relative(directory, file);
1072
+ return (
1073
+ relative === "" ||
1074
+ (relative !== ".." &&
1075
+ relative.startsWith(`..${path.sep}`) === false &&
1076
+ path.isAbsolute(relative) === false)
1077
+ );
810
1078
  }
811
1079
 
812
1080
  function isMissingFileError(exp: unknown): boolean {
@@ -818,8 +1086,10 @@ export namespace TypiaGenerateWizard {
818
1086
  );
819
1087
  }
820
1088
 
821
- function fileIdentityKey(stat: fs.Stats): string {
822
- return `${stat.dev}:${stat.ino}`;
1089
+ function fileIdentityKey(stat: fs.Stats, realpath: string): string {
1090
+ return stat.ino === 0
1091
+ ? `path:${path.normalize(realpath)}`
1092
+ : `inode:${stat.dev}:${stat.ino}`;
823
1093
  }
824
1094
 
825
1095
  function formatDiagnostics(diagnostics: ITtscCompilerDiagnostic[]): string {
@@ -855,6 +1125,3 @@ export namespace TypiaGenerateWizard {
855
1125
  return String(error);
856
1126
  }
857
1127
  }
858
-
859
- const TS_PATTERN = /\.[cm]?tsx?$/;
860
- const DTS_PATTERN = /\.d\.[cm]?tsx?$/;