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
@@ -0,0 +1,167 @@
1
+ package main
2
+
3
+ import (
4
+ "os"
5
+ "path/filepath"
6
+ "regexp"
7
+ "sort"
8
+ "strings"
9
+ "testing"
10
+ )
11
+
12
+ // TestProtobufDiagnosticCodeTransform verifies that a rejected protobuf call
13
+ // site is named by its own API in the diagnostic code (#2285).
14
+ //
15
+ // `ProtobufFactory.Metadata` used to compose the code as `"typia.protobuf." +
16
+ // props.Method`, while the encode and decode programmers pass the whole call
17
+ // accessor (`ModuloMethodText`, the same text `TypeGuardError.method` carries).
18
+ // Sixteen of the seventeen entry points therefore reported
19
+ // `TS(typia.protobuf.typia.protobuf.encode)`; only `protobuf.message` was
20
+ // correct, because its programmer passed a bare literal. The code is the only
21
+ // machine-readable identity a typia rejection has, so a code that names no API
22
+ // is a silent loss for anyone searching it.
23
+ //
24
+ // The oracle is the fixture source, not another copy of the expected string: a
25
+ // diagnostic code is correct only when the accessor it names is literally the
26
+ // accessor written at a call site in that file. A concatenation defect cannot
27
+ // satisfy that, and neither can a misspelling.
28
+ //
29
+ // 1. Write one fixture that calls every protobuf entry point with `bigint`,
30
+ // which none of them supports.
31
+ // 2. Transform it and collect every diagnostic code the transform reported.
32
+ // 3. Require each code to be an accessor present in the fixture, and require
33
+ // every entry point to have been named.
34
+ func TestProtobufDiagnosticCodeTransform(t *testing.T) {
35
+ methods := []string{
36
+ "message",
37
+ "encode",
38
+ "decode",
39
+ "assertEncode",
40
+ "assertDecode",
41
+ "isEncode",
42
+ "isDecode",
43
+ "validateEncode",
44
+ "validateDecode",
45
+ "createEncode",
46
+ "createDecode",
47
+ "createAssertEncode",
48
+ "createAssertDecode",
49
+ "createIsEncode",
50
+ "createIsDecode",
51
+ "createValidateEncode",
52
+ "createValidateDecode",
53
+ }
54
+ project, source := protobufDiagnosticCodeProject(t, methods)
55
+ out, errText, code := ttscTypiaTestCapture(func() int {
56
+ return runTransform([]string{
57
+ "--cwd", project,
58
+ "--tsconfig", "tsconfig.json",
59
+ })
60
+ })
61
+ if code == 0 {
62
+ t.Fatalf("protobuf fixture transformed successfully, want failure:\nstdout=%s\nstderr=%s", out, errText)
63
+ }
64
+
65
+ codes := map[string]bool{}
66
+ for _, match := range protobufDiagnosticCodePattern.FindAllStringSubmatch(out, -1) {
67
+ codes[match[1]] = true
68
+ }
69
+ if len(codes) == 0 {
70
+ t.Fatalf("no typia diagnostic code was reported:\nstdout=%s\nstderr=%s", out, errText)
71
+ }
72
+
73
+ unnamed := []string{}
74
+ for reported := range codes {
75
+ if !strings.Contains(source, reported+"<") {
76
+ unnamed = append(unnamed, reported)
77
+ }
78
+ }
79
+ sort.Strings(unnamed)
80
+ if len(unnamed) != 0 {
81
+ t.Fatalf(
82
+ "diagnostic code(s) name no call site in the fixture: %s",
83
+ strings.Join(unnamed, ", "),
84
+ )
85
+ }
86
+
87
+ missing := []string{}
88
+ for _, method := range methods {
89
+ if !codes["typia.protobuf."+method] {
90
+ missing = append(missing, method)
91
+ }
92
+ }
93
+ if len(missing) != 0 {
94
+ t.Fatalf(
95
+ "no diagnostic named these entry points: %s\nstdout=%s",
96
+ strings.Join(missing, ", "),
97
+ out,
98
+ )
99
+ }
100
+ }
101
+
102
+ // The command reports diagnostics as JSON, and `code` is the field ttsc renders
103
+ // as `error TS(<code>)`; reading it here keeps the assertion on the value the
104
+ // transform produced rather than on one renderer's formatting.
105
+ var protobufDiagnosticCodePattern = regexp.MustCompile(`"code":"([^"]+)"`)
106
+
107
+ func protobufDiagnosticCodeProject(t *testing.T, methods []string) (string, string) {
108
+ t.Helper()
109
+ root := ttscTypiaTestRepoRoot(t)
110
+ base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
111
+ if err := os.MkdirAll(base, 0o755); err != nil {
112
+ t.Fatalf("mkdir temp base: %v", err)
113
+ }
114
+ dir, err := os.MkdirTemp(base, "protobuf-code-")
115
+ if err != nil {
116
+ t.Fatalf("create temp fixture: %v", err)
117
+ }
118
+ t.Cleanup(func() {
119
+ _ = os.RemoveAll(dir)
120
+ })
121
+ src := filepath.Join(dir, "src")
122
+ if err := os.MkdirAll(src, 0o755); err != nil {
123
+ t.Fatalf("mkdir fixture src: %v", err)
124
+ }
125
+ if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(protobufDiagnosticCodeTSConfig), 0o644); err != nil {
126
+ t.Fatalf("write tsconfig: %v", err)
127
+ }
128
+ lines := []string{`import typia from "typia";`, ""}
129
+ for _, method := range methods {
130
+ lines = append(lines, protobufDiagnosticCodeCall(method))
131
+ }
132
+ source := strings.Join(lines, "\n") + "\n"
133
+ if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(source), 0o644); err != nil {
134
+ t.Fatalf("write source: %v", err)
135
+ }
136
+ return dir, source
137
+ }
138
+
139
+ // protobufDiagnosticCodeCall writes the call form each entry point takes: the
140
+ // factories take no value argument, the encoders take the message, and the
141
+ // decoders take the buffer.
142
+ func protobufDiagnosticCodeCall(method string) string {
143
+ call := "typia.protobuf." + method + "<bigint>"
144
+ switch {
145
+ case method == "message" || strings.HasPrefix(method, "create"):
146
+ return call + "();"
147
+ case strings.HasSuffix(method, "Decode"):
148
+ return call + "(new Uint8Array());"
149
+ default:
150
+ return call + "(1n as any);"
151
+ }
152
+ }
153
+
154
+ const protobufDiagnosticCodeTSConfig = `{
155
+ "compilerOptions": {
156
+ "target": "ES2022",
157
+ "module": "commonjs",
158
+ "moduleResolution": "bundler",
159
+ "ignoreDeprecations": "6.0",
160
+ "types": ["*"],
161
+ "esModuleInterop": true,
162
+ "strict": true,
163
+ "skipLibCheck": true
164
+ },
165
+ "include": ["src"]
166
+ }
167
+ `
@@ -0,0 +1,98 @@
1
+ package main
2
+
3
+ import (
4
+ "os"
5
+ "path/filepath"
6
+ "strings"
7
+ "testing"
8
+ )
9
+
10
+ // TestProtobufIsEncodeFiniteNumberTransform pins protobuf.isEncode against a bare
11
+ // number leaf so a non-finite value cannot be encoded into the message (#2196).
12
+ //
13
+ // protobuf.isEncode forces Options.Finite on its inner `__is` guard, then emits
14
+ // `__is(input) ? __encode(input) : null`. A protobuf double can hold NaN and
15
+ // Infinity, so the guard is the only thing keeping them out of the wire. While
16
+ // `is` dropped `finite`, that guard accepted NaN and the encoder wrote it; the
17
+ // guard must now carry Number.isFinite on the number leaf. Because isEncode has no
18
+ // separate error-path checker, the guard is the sole place the number leaf's
19
+ // finite check can appear, so its presence in the emit is an unambiguous oracle.
20
+ //
21
+ // 1. Transform a `protobuf.isEncode<{ value: number }>` fixture with default options.
22
+ // 2. Assert the emitted `__is` guards the number leaf with Number.isFinite.
23
+ func TestProtobufIsEncodeFiniteNumberTransform(t *testing.T) {
24
+ project := protobufIsEncodeFiniteNumberProject(t)
25
+ js := protobufIsEncodeFiniteNumberTransform(t, project)
26
+ needle := "Number.isFinite(input.value)"
27
+ if !strings.Contains(js, needle) {
28
+ t.Fatalf("protobuf.isEncode did not guard the number leaf with %q:\n%s", needle, js)
29
+ }
30
+ }
31
+
32
+ func protobufIsEncodeFiniteNumberProject(t *testing.T) string {
33
+ t.Helper()
34
+ root := ttscTypiaTestRepoRoot(t)
35
+ base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
36
+ if err := os.MkdirAll(base, 0o755); err != nil {
37
+ t.Fatalf("mkdir temp base: %v", err)
38
+ }
39
+ dir, err := os.MkdirTemp(base, "protobuf-is-encode-finite-number-")
40
+ if err != nil {
41
+ t.Fatalf("create temp fixture: %v", err)
42
+ }
43
+ t.Cleanup(func() {
44
+ _ = os.RemoveAll(dir)
45
+ })
46
+ src := filepath.Join(dir, "src")
47
+ if err := os.MkdirAll(src, 0o755); err != nil {
48
+ t.Fatalf("mkdir fixture src: %v", err)
49
+ }
50
+ if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(protobufIsEncodeFiniteNumberTSConfig), 0o644); err != nil {
51
+ t.Fatalf("write tsconfig: %v", err)
52
+ }
53
+ if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(protobufIsEncodeFiniteNumberSource), 0o644); err != nil {
54
+ t.Fatalf("write source: %v", err)
55
+ }
56
+ return dir
57
+ }
58
+
59
+ func protobufIsEncodeFiniteNumberTransform(t *testing.T, project string) string {
60
+ t.Helper()
61
+ out, errText, code := ttscTypiaTestCapture(func() int {
62
+ return runTransform([]string{
63
+ "--cwd", project,
64
+ "--tsconfig", "tsconfig.json",
65
+ "--file", "src/main.ts",
66
+ "--output", "js",
67
+ })
68
+ })
69
+ if code != 0 {
70
+ t.Fatalf("protobuf isEncode finite transform failed: code=%d stderr=\n%s", code, errText)
71
+ }
72
+ return out
73
+ }
74
+
75
+ const protobufIsEncodeFiniteNumberTSConfig = `{
76
+ "compilerOptions": {
77
+ "target": "ES2022",
78
+ "module": "commonjs",
79
+ "moduleResolution": "bundler",
80
+ "ignoreDeprecations": "6.0",
81
+ "types": ["*"],
82
+ "esModuleInterop": true,
83
+ "strict": true,
84
+ "skipLibCheck": true
85
+ },
86
+ "include": ["src"]
87
+ }
88
+ `
89
+
90
+ const protobufIsEncodeFiniteNumberSource = `import typia from "typia";
91
+
92
+ interface Box {
93
+ value: number;
94
+ }
95
+
96
+ export const encode = (input: unknown): Uint8Array | null =>
97
+ typia.protobuf.isEncode<Box>(input);
98
+ `
@@ -14,47 +14,70 @@ import (
14
14
  // explicit protobuf field numbers were silently replaced by auto-numbering and
15
15
  // duplicate-sequence validation never fired.
16
16
  //
17
+ // The two messages live in separate fixtures because a duplicate-sequence
18
+ // diagnostic now withholds the whole file's artifact (samchon/typia#2117), so one
19
+ // combined source could no longer show the valid message's emitted numbers.
20
+ //
17
21
  // 1. Transform a message fixture carrying explicit `Sequence<5>` / `Sequence<7>`
18
22
  // field numbers plus an untagged property (auto-numbered after the highest
19
- // explicit number).
20
- // 2. Require the emitted proto message to carry the explicit numbers.
21
- // 3. Require a message whose two properties share `Sequence<1>` to fail the
22
- // transform, leaving the call untransformed.
23
+ // explicit number), and require the emitted proto message to carry them.
24
+ // 2. Require a message whose two properties share `Sequence<1>` to fail the
25
+ // transform with a diagnostic naming the duplicate.
26
+ // 3. Require that rejected transform to publish no artifact.
23
27
  func TestProtobufSequenceFieldNumbersTransform(t *testing.T) {
24
- project := protobufSequenceFieldNumbersProject(t)
25
- out, errText, code := ttscTypiaTestCapture(func() int {
26
- return runTransform([]string{
27
- "--cwd", project,
28
- "--tsconfig", "tsconfig.json",
29
- "--file", "src/main.ts",
30
- "--output", "js",
31
- })
32
- })
28
+ out, errText, code := protobufSequenceFieldNumbersTransform(t, "sequenced-", protobufSequenceFieldNumbersSource)
33
29
  if code != 0 {
34
30
  t.Fatalf("protobuf sequence transform failed: code=%d stderr=\n%s", code, errText)
35
31
  }
32
+ // The subject is the explicit `Sequence<5>` / `Sequence<7>` field numbers and
33
+ // the auto-numbered `8` after them; the presence label is `optional` because
34
+ // proto3 has no `required`, and emitting it would make the document reject
35
+ // under a Protobuf compiler (samchon/typia#2155). Compiler legality itself is
36
+ // pinned by TestProtobufMessageDocumentCompiles.
36
37
  for _, line := range []string{
37
- "required string id = 5;",
38
- "required double age = 7;",
39
- "required bool flag = 8;",
38
+ "optional string id = 5;",
39
+ "optional double age = 7;",
40
+ "optional bool flag = 8;",
40
41
  } {
41
42
  if !strings.Contains(out, line) {
42
43
  t.Fatalf("emitted proto message should contain %q:\n%s", line, out)
43
44
  }
44
45
  }
45
- if !strings.Contains(out, ".protobuf.message()") {
46
- t.Fatalf("duplicated sequence message should stay untransformed:\n%s", out)
46
+
47
+ dupOut, dupErr, dupCode := protobufSequenceFieldNumbersTransform(t, "duplicated-", protobufSequenceDuplicatedSource)
48
+ if dupCode != 3 {
49
+ t.Fatalf("duplicated sequence message should be rejected with code 3: code=%d stdout=\n%s\nstderr=\n%s", dupCode, dupOut, dupErr)
50
+ }
51
+ if !strings.Contains(dupErr, "error TS(typia.protobuf.message):") ||
52
+ !strings.Contains(dupErr, `The Sequence<1> tag is duplicated in two properties ("id" and "age")`) {
53
+ t.Fatalf("duplicated sequence diagnostic did not name the collision:\n%s", dupErr)
47
54
  }
55
+ if dupOut != "" {
56
+ t.Fatalf("duplicated sequence message published an artifact:\n%s", dupOut)
57
+ }
58
+ }
59
+
60
+ func protobufSequenceFieldNumbersTransform(t *testing.T, prefix string, source string) (string, string, int) {
61
+ t.Helper()
62
+ project := protobufSequenceFieldNumbersProject(t, prefix, source)
63
+ return ttscTypiaTestCapture(func() int {
64
+ return runTransform([]string{
65
+ "--cwd", project,
66
+ "--tsconfig", "tsconfig.json",
67
+ "--file", "src/main.ts",
68
+ "--output", "js",
69
+ })
70
+ })
48
71
  }
49
72
 
50
- func protobufSequenceFieldNumbersProject(t *testing.T) string {
73
+ func protobufSequenceFieldNumbersProject(t *testing.T, prefix string, source string) string {
51
74
  t.Helper()
52
75
  root := ttscTypiaTestRepoRoot(t)
53
76
  base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
54
77
  if err := os.MkdirAll(base, 0o755); err != nil {
55
78
  t.Fatalf("mkdir temp base: %v", err)
56
79
  }
57
- dir, err := os.MkdirTemp(base, "protobuf-sequence-")
80
+ dir, err := os.MkdirTemp(base, "protobuf-sequence-"+prefix)
58
81
  if err != nil {
59
82
  t.Fatalf("create temp fixture: %v", err)
60
83
  }
@@ -68,7 +91,7 @@ func protobufSequenceFieldNumbersProject(t *testing.T) string {
68
91
  if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(protobufSequenceFieldNumbersTSConfig), 0o644); err != nil {
69
92
  t.Fatalf("write tsconfig: %v", err)
70
93
  }
71
- if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(protobufSequenceFieldNumbersSource), 0o644); err != nil {
94
+ if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(source), 0o644); err != nil {
72
95
  t.Fatalf("write source: %v", err)
73
96
  }
74
97
  return dir
@@ -97,11 +120,18 @@ interface Sequenced {
97
120
  flag: boolean;
98
121
  }
99
122
 
123
+ export const sequenced = typia.protobuf.message<Sequenced>();
124
+ `
125
+
126
+ // protobufSequenceDuplicatedSource is the negative twin: the same message shape
127
+ // whose two properties claim one `Sequence<1>` number, which typia must reject
128
+ // rather than auto-renumber.
129
+ const protobufSequenceDuplicatedSource = `import typia, { tags } from "typia";
130
+
100
131
  interface Duplicated {
101
132
  id: string & tags.Sequence<1>;
102
133
  age: number & tags.Sequence<1>;
103
134
  }
104
135
 
105
- export const sequenced = typia.protobuf.message<Sequenced>();
106
136
  export const duplicated = typia.protobuf.message<Duplicated>();
107
137
  `
@@ -0,0 +1,316 @@
1
+ package main
2
+
3
+ import (
4
+ "os"
5
+ "os/exec"
6
+ "path/filepath"
7
+ "testing"
8
+ )
9
+
10
+ // TestSymbolIndexDomainTransform verifies a symbol index signature stays out
11
+ // of typia's string-keyed validation and JSON Schema shape (#2240).
12
+ //
13
+ // TypeScript keeps string and symbol index domains distinct, including when a
14
+ // symbol index key is intersected with a nominal brand. This regression pins
15
+ // that boundary through the real transform because treating every checker
16
+ // IndexInfo as a JSON string index makes unrelated Object.keys values inherit a
17
+ // symbol index's value constraint. An ordinary string index and the explicit
18
+ // symbol-member behavior fixed by #2226 are adjacent controls.
19
+ //
20
+ // 1. Compile checker-level keyof assertions for symbol and string indexes.
21
+ // 2. Execute validators over ordinary extras and symbol-valued properties.
22
+ // 3. Compare the symbol-index schema exactly with a plain-object control while
23
+ // requiring a normal string index to retain additionalProperties.
24
+ func TestSymbolIndexDomainTransform(t *testing.T) {
25
+ project := symbolIndexDomainProject(t)
26
+ js := symbolIndexDomainTransform(t, project)
27
+ symbolIndexDomainRunRuntimeCases(t, project, js)
28
+ }
29
+
30
+ func symbolIndexDomainProject(t *testing.T) string {
31
+ t.Helper()
32
+ root := ttscTypiaTestRepoRoot(t)
33
+ base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
34
+ if err := os.MkdirAll(base, 0o755); err != nil {
35
+ t.Fatalf("mkdir temp base: %v", err)
36
+ }
37
+ dir, err := os.MkdirTemp(base, "symbol-index-domain-")
38
+ if err != nil {
39
+ t.Fatalf("create temp fixture: %v", err)
40
+ }
41
+ t.Cleanup(func() {
42
+ _ = os.RemoveAll(dir)
43
+ })
44
+ src := filepath.Join(dir, "src")
45
+ if err := os.MkdirAll(src, 0o755); err != nil {
46
+ t.Fatalf("mkdir fixture src: %v", err)
47
+ }
48
+ if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(symbolIndexDomainTSConfig), 0o644); err != nil {
49
+ t.Fatalf("write tsconfig: %v", err)
50
+ }
51
+ if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(symbolIndexDomainSource), 0o644); err != nil {
52
+ t.Fatalf("write source: %v", err)
53
+ }
54
+ return dir
55
+ }
56
+
57
+ func symbolIndexDomainTransform(t *testing.T, project string) string {
58
+ t.Helper()
59
+ out, errText, code := ttscTypiaTestCapture(func() int {
60
+ return runTransform([]string{
61
+ "--cwd", project,
62
+ "--tsconfig", "tsconfig.json",
63
+ "--file", "src/main.ts",
64
+ "--output", "js",
65
+ })
66
+ })
67
+ if code != 0 {
68
+ t.Fatalf("symbol index domain transform failed: code=%d stderr=\n%s", code, errText)
69
+ }
70
+ return out
71
+ }
72
+
73
+ func symbolIndexDomainRunRuntimeCases(t *testing.T, project string, js string) {
74
+ t.Helper()
75
+ node, err := exec.LookPath("node")
76
+ if err != nil {
77
+ t.Skip("node executable not found")
78
+ }
79
+ runtimeDir := filepath.Join(project, "runtime")
80
+ if err := os.MkdirAll(runtimeDir, 0o755); err != nil {
81
+ t.Fatalf("mkdir runtime dir: %v", err)
82
+ }
83
+ ttscTypiaTestWriteCommonRuntimeStubs(t, runtimeDir)
84
+ runtimeJS := ttscTypiaTestRewriteCommonJS(t, js)
85
+ if err := os.WriteFile(filepath.Join(runtimeDir, "main.cjs"), []byte(runtimeJS), 0o644); err != nil {
86
+ t.Fatalf("write runtime module: %v", err)
87
+ }
88
+ runner := filepath.Join(runtimeDir, "run.cjs")
89
+ if err := os.WriteFile(runner, []byte(symbolIndexDomainRuntimeRunner), 0o644); err != nil {
90
+ t.Fatalf("write runtime runner: %v", err)
91
+ }
92
+ cmd := exec.Command(node, runner)
93
+ cmd.Dir = runtimeDir
94
+ if output, err := cmd.CombinedOutput(); err != nil {
95
+ t.Fatalf("symbol index domain runtime cases failed: %v\n%s", err, output)
96
+ }
97
+ }
98
+
99
+ const symbolIndexDomainTSConfig = `{
100
+ "compilerOptions": {
101
+ "target": "ES2022",
102
+ "module": "commonjs",
103
+ "moduleResolution": "bundler",
104
+ "ignoreDeprecations": "6.0",
105
+ "types": ["*"],
106
+ "esModuleInterop": true,
107
+ "strict": true,
108
+ "skipLibCheck": true
109
+ },
110
+ "include": ["src"]
111
+ }
112
+ `
113
+
114
+ const symbolIndexDomainSource = `import typia from "typia";
115
+
116
+ declare const explicitSymbol: unique symbol;
117
+
118
+ interface SymbolIndex {
119
+ name: string;
120
+ [key: symbol]: number;
121
+ }
122
+
123
+ type BrandedSymbol = symbol & {
124
+ readonly __brand: unique symbol;
125
+ };
126
+
127
+ interface BrandedSymbolIndex {
128
+ name: string;
129
+ [key: BrandedSymbol]: number;
130
+ }
131
+
132
+ interface PlainObject {
133
+ name: string;
134
+ }
135
+
136
+ interface StringIndex {
137
+ name: string;
138
+ [key: string]: string;
139
+ }
140
+
141
+ interface ExplicitSymbolMember {
142
+ name: string;
143
+ [explicitSymbol]: number;
144
+ }
145
+
146
+ type Assert<T extends true> = T;
147
+ type _SymbolIndexHasNoStringDomain = Assert<
148
+ string extends keyof SymbolIndex ? false : true
149
+ >;
150
+ type _SymbolIndexHasNoNumberDomain = Assert<
151
+ number extends keyof SymbolIndex ? false : true
152
+ >;
153
+ type _SymbolIndexHasSymbolDomain = Assert<
154
+ symbol extends keyof SymbolIndex ? true : false
155
+ >;
156
+ type _BrandedSymbolIndexHasNoStringDomain = Assert<
157
+ string extends keyof BrandedSymbolIndex ? false : true
158
+ >;
159
+ type _BrandedSymbolIndexHasNoNumberDomain = Assert<
160
+ number extends keyof BrandedSymbolIndex ? false : true
161
+ >;
162
+ type _BrandedSymbolIndexHasBrandedDomain = Assert<
163
+ BrandedSymbol extends keyof BrandedSymbolIndex ? true : false
164
+ >;
165
+ type _StringIndexHasStringDomain = Assert<
166
+ string extends keyof StringIndex ? true : false
167
+ >;
168
+ type _StringIndexHasNumberDomain = Assert<
169
+ number extends keyof StringIndex ? true : false
170
+ >;
171
+ type _StringIndexHasNoSymbolDomain = Assert<
172
+ symbol extends keyof StringIndex ? false : true
173
+ >;
174
+ type _ExplicitSymbolMemberIsPresent = Assert<
175
+ typeof explicitSymbol extends keyof ExplicitSymbolMember ? true : false
176
+ >;
177
+
178
+ export const isSymbolIndex = typia.createIs<SymbolIndex>();
179
+ export const isBrandedSymbolIndex =
180
+ typia.createIs<BrandedSymbolIndex>();
181
+ export const isPlainObject = typia.createIs<PlainObject>();
182
+ export const isStringIndex = typia.createIs<StringIndex>();
183
+ export const isExplicitSymbolMember =
184
+ typia.createIs<ExplicitSymbolMember>();
185
+ export const schemas = typia.json.schemas<[
186
+ SymbolIndex,
187
+ BrandedSymbolIndex,
188
+ PlainObject,
189
+ StringIndex,
190
+ ExplicitSymbolMember,
191
+ ]>();
192
+ `
193
+
194
+ const symbolIndexDomainRuntimeRunner = `const mod = require("./main.cjs");
195
+
196
+ const failures = [];
197
+ const expect = (label, actual, expected) => {
198
+ if (actual !== expected) {
199
+ failures.push(
200
+ label +
201
+ ": expected " +
202
+ JSON.stringify(expected) +
203
+ " but got " +
204
+ JSON.stringify(actual),
205
+ );
206
+ }
207
+ };
208
+
209
+ expect("symbol index plain", mod.isSymbolIndex({ name: "x" }), true);
210
+ expect(
211
+ "symbol index ignores a numeric string extra",
212
+ mod.isSymbolIndex({ name: "x", extra: 1 }),
213
+ true,
214
+ );
215
+ expect(
216
+ "symbol index ignores a string extra",
217
+ mod.isSymbolIndex({ name: "x", extra: "unrelated" }),
218
+ true,
219
+ );
220
+ expect(
221
+ "symbol index ignores a matching symbol value",
222
+ mod.isSymbolIndex({ name: "x", [Symbol("key")]: 1 }),
223
+ true,
224
+ );
225
+ expect(
226
+ "symbol index ignores a non-matching symbol value",
227
+ mod.isSymbolIndex({ name: "x", [Symbol("key")]: "outside-json-shape" }),
228
+ true,
229
+ );
230
+ expect("symbol index validates named properties", mod.isSymbolIndex({ name: 1 }), false);
231
+
232
+ expect(
233
+ "branded symbol index plain",
234
+ mod.isBrandedSymbolIndex({ name: "x" }),
235
+ true,
236
+ );
237
+ expect(
238
+ "branded symbol index ignores a string extra",
239
+ mod.isBrandedSymbolIndex({ name: "x", extra: "unrelated" }),
240
+ true,
241
+ );
242
+ expect(
243
+ "branded symbol index ignores a matching symbol value",
244
+ mod.isBrandedSymbolIndex({ name: "x", [Symbol("key")]: 1 }),
245
+ true,
246
+ );
247
+ expect(
248
+ "branded symbol index ignores a non-matching symbol value",
249
+ mod.isBrandedSymbolIndex({ name: "x", [Symbol("key")]: "outside-json-shape" }),
250
+ true,
251
+ );
252
+ expect(
253
+ "branded symbol index validates named properties",
254
+ mod.isBrandedSymbolIndex({ name: 1 }),
255
+ false,
256
+ );
257
+
258
+ expect("plain object ignores a string extra", mod.isPlainObject({ name: "x", extra: 1 }), true);
259
+ expect("plain object validates named properties", mod.isPlainObject({ name: 1 }), false);
260
+
261
+ expect("string index accepts matching extra", mod.isStringIndex({ name: "x", extra: "ok" }), true);
262
+ expect("string index rejects mismatching extra", mod.isStringIndex({ name: "x", extra: 1 }), false);
263
+
264
+ expect(
265
+ "explicit symbol member remains outside the JSON shape",
266
+ mod.isExplicitSymbolMember({ name: "x", [Symbol("member")]: "ignored" }),
267
+ true,
268
+ );
269
+ expect(
270
+ "explicit symbol member validates named properties",
271
+ mod.isExplicitSymbolMember({ name: 1 }),
272
+ false,
273
+ );
274
+
275
+ const schemas = mod.schemas.components.schemas;
276
+ const plain = {
277
+ type: "object",
278
+ properties: { name: { type: "string" } },
279
+ required: ["name"],
280
+ additionalProperties: false,
281
+ };
282
+ const stringIndex = {
283
+ type: "object",
284
+ properties: { name: { type: "string" } },
285
+ required: ["name"],
286
+ additionalProperties: { type: "string" },
287
+ };
288
+ expect(
289
+ "plain object exact schema",
290
+ JSON.stringify(schemas.PlainObject),
291
+ JSON.stringify(plain),
292
+ );
293
+ expect(
294
+ "symbol index exact schema",
295
+ JSON.stringify(schemas.SymbolIndex),
296
+ JSON.stringify(plain),
297
+ );
298
+ expect(
299
+ "branded symbol index exact schema",
300
+ JSON.stringify(schemas.BrandedSymbolIndex),
301
+ JSON.stringify(plain),
302
+ );
303
+ expect(
304
+ "explicit symbol member exact schema",
305
+ JSON.stringify(schemas.ExplicitSymbolMember),
306
+ JSON.stringify(plain),
307
+ );
308
+ expect(
309
+ "string index exact schema",
310
+ JSON.stringify(schemas.StringIndex),
311
+ JSON.stringify(stringIndex),
312
+ );
313
+ if (failures.length !== 0) {
314
+ throw new Error("MISMATCHES:\n" + failures.join("\n"));
315
+ }
316
+ `