typia 13.1.19 → 13.3.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 (235) hide show
  1. package/lib/executable/FileSystemIdentity.d.ts +23 -0
  2. package/lib/executable/FileSystemIdentity.js +30 -0
  3. package/lib/executable/FileSystemIdentity.js.map +1 -1
  4. package/lib/executable/FileSystemIdentity.mjs +4 -0
  5. package/lib/executable/FileSystemIdentity.mjs.map +1 -1
  6. package/lib/executable/TypiaGenerateWizard.js +15 -9
  7. package/lib/executable/TypiaGenerateWizard.js.map +1 -1
  8. package/lib/executable/TypiaGenerateWizard.mjs +11 -7
  9. package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
  10. package/lib/http.d.ts +3 -3
  11. package/lib/http.js.map +1 -1
  12. package/lib/http.mjs.map +1 -1
  13. package/lib/internal/_ProtobufReader.d.ts +18 -3
  14. package/lib/internal/_ProtobufReader.js +39 -11
  15. package/lib/internal/_ProtobufReader.js.map +1 -1
  16. package/lib/internal/_ProtobufReader.mjs +37 -10
  17. package/lib/internal/_ProtobufReader.mjs.map +1 -1
  18. package/lib/internal/_assertGuard.js +13 -3
  19. package/lib/internal/_assertGuard.js.map +1 -1
  20. package/lib/internal/_assertGuard.mjs +4 -2
  21. package/lib/internal/_assertGuard.mjs.map +1 -1
  22. package/lib/internal/_isFormatIdnHostname.js +5 -1
  23. package/lib/internal/_isFormatIdnHostname.js.map +1 -1
  24. package/lib/internal/_isFormatIdnHostname.mjs +1 -1
  25. package/lib/internal/_isFormatIdnHostname.mjs.map +1 -1
  26. package/lib/internal/_isFormatTime.js +19 -2
  27. package/lib/internal/_isFormatTime.js.map +1 -1
  28. package/lib/internal/_isFormatTime.mjs +9 -2
  29. package/lib/internal/_isFormatTime.mjs.map +1 -1
  30. package/lib/internal/_jsonStringifyArray.d.ts +1 -0
  31. package/lib/internal/_jsonStringifyArray.js +48 -0
  32. package/lib/internal/_jsonStringifyArray.js.map +1 -0
  33. package/lib/internal/_jsonStringifyArray.mjs +40 -0
  34. package/lib/internal/_jsonStringifyArray.mjs.map +1 -0
  35. package/lib/internal/_jsonStringifyElement.d.ts +1 -0
  36. package/lib/internal/_jsonStringifyElement.js +23 -0
  37. package/lib/internal/_jsonStringifyElement.js.map +1 -0
  38. package/lib/internal/_jsonStringifyElement.mjs +23 -0
  39. package/lib/internal/_jsonStringifyElement.mjs.map +1 -0
  40. package/lib/internal/_jsonStringifyProperty.d.ts +1 -0
  41. package/lib/internal/_jsonStringifyProperty.js +31 -0
  42. package/lib/internal/_jsonStringifyProperty.js.map +1 -0
  43. package/lib/internal/_jsonStringifyProperty.mjs +31 -0
  44. package/lib/internal/_jsonStringifyProperty.mjs.map +1 -0
  45. package/lib/internal/_llmApplicationFinalize.js +1 -1
  46. package/lib/internal/_llmApplicationFinalize.js.map +1 -1
  47. package/lib/internal/_llmApplicationFinalize.mjs +1 -1
  48. package/lib/internal/_llmApplicationFinalize.mjs.map +1 -1
  49. package/lib/internal/_randomArray.js +37 -4
  50. package/lib/internal/_randomArray.js.map +1 -1
  51. package/lib/internal/_randomArray.mjs +16 -3
  52. package/lib/internal/_randomArray.mjs.map +1 -1
  53. package/lib/internal/_randomFormatByte.js +28 -2
  54. package/lib/internal/_randomFormatByte.js.map +1 -1
  55. package/lib/internal/_randomFormatByte.mjs +22 -3
  56. package/lib/internal/_randomFormatByte.mjs.map +1 -1
  57. package/lib/internal/_randomFormatDate.d.ts +3 -6
  58. package/lib/internal/_randomFormatDate.js +2 -10
  59. package/lib/internal/_randomFormatDate.js.map +1 -1
  60. package/lib/internal/_randomFormatDate.mjs +2 -6
  61. package/lib/internal/_randomFormatDate.mjs.map +1 -1
  62. package/lib/internal/_randomFormatDatetime.d.ts +3 -6
  63. package/lib/internal/_randomFormatDatetime.js +25 -8
  64. package/lib/internal/_randomFormatDatetime.js.map +1 -1
  65. package/lib/internal/_randomFormatDatetime.mjs +17 -7
  66. package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
  67. package/lib/internal/_randomFormatDuration.js +23 -15
  68. package/lib/internal/_randomFormatDuration.js.map +1 -1
  69. package/lib/internal/_randomFormatDuration.mjs +23 -15
  70. package/lib/internal/_randomFormatDuration.mjs.map +1 -1
  71. package/lib/internal/_randomFormatHostname.d.ts +2 -2
  72. package/lib/internal/_randomFormatHostname.js +2 -2
  73. package/lib/internal/_randomFormatHostname.mjs +2 -2
  74. package/lib/internal/_randomFormatHostname.mjs.map +1 -1
  75. package/lib/internal/_randomFormatIdnHostname.js +9 -10
  76. package/lib/internal/_randomFormatIdnHostname.js.map +1 -1
  77. package/lib/internal/_randomFormatIdnHostname.mjs +3 -4
  78. package/lib/internal/_randomFormatIdnHostname.mjs.map +1 -1
  79. package/lib/internal/_randomFormatIpv4.js +31 -1
  80. package/lib/internal/_randomFormatIpv4.js.map +1 -1
  81. package/lib/internal/_randomFormatIpv4.mjs +23 -2
  82. package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
  83. package/lib/internal/_randomFormatIpv6.js +57 -1
  84. package/lib/internal/_randomFormatIpv6.js.map +1 -1
  85. package/lib/internal/_randomFormatIpv6.mjs +45 -2
  86. package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
  87. package/lib/internal/_randomFormatJsonPointer.js +14 -2
  88. package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
  89. package/lib/internal/_randomFormatJsonPointer.mjs +13 -3
  90. package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
  91. package/lib/internal/_randomFormatRegex.js +15 -2
  92. package/lib/internal/_randomFormatRegex.js.map +1 -1
  93. package/lib/internal/_randomFormatRegex.mjs +14 -3
  94. package/lib/internal/_randomFormatRegex.mjs.map +1 -1
  95. package/lib/internal/_randomFormatRelativeJsonPointer.js +19 -5
  96. package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
  97. package/lib/internal/_randomFormatRelativeJsonPointer.mjs +21 -6
  98. package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
  99. package/lib/internal/_randomFormatTime.js +38 -7
  100. package/lib/internal/_randomFormatTime.js.map +1 -1
  101. package/lib/internal/_randomFormatTime.mjs +40 -5
  102. package/lib/internal/_randomFormatTime.mjs.map +1 -1
  103. package/lib/internal/_randomPattern.js.map +1 -1
  104. package/lib/internal/_randomPattern.mjs.map +1 -1
  105. package/lib/internal/_randomStringLength.d.ts +41 -10
  106. package/lib/internal/_randomStringLength.js +49 -13
  107. package/lib/internal/_randomStringLength.js.map +1 -1
  108. package/lib/internal/_randomStringLength.mjs +48 -13
  109. package/lib/internal/_randomStringLength.mjs.map +1 -1
  110. package/lib/internal/private/__notationRename.js.map +1 -1
  111. package/lib/internal/private/__notationRename.mjs.map +1 -1
  112. package/lib/internal/private/__randomComposition.d.ts +31 -0
  113. package/lib/internal/private/__randomComposition.js +68 -0
  114. package/lib/internal/private/__randomComposition.js.map +1 -0
  115. package/lib/internal/private/__randomComposition.mjs +71 -0
  116. package/lib/internal/private/__randomComposition.mjs.map +1 -0
  117. package/lib/internal/private/__randomEpoch.d.ts +19 -0
  118. package/lib/internal/private/__randomEpoch.js +31 -0
  119. package/lib/internal/private/__randomEpoch.js.map +1 -0
  120. package/lib/internal/private/__randomEpoch.mjs +28 -0
  121. package/lib/internal/private/__randomEpoch.mjs.map +1 -0
  122. package/lib/json.d.ts +2 -2
  123. package/lib/json.js.map +1 -1
  124. package/lib/json.mjs.map +1 -1
  125. package/lib/module.d.ts +28 -13
  126. package/lib/module.js.map +1 -1
  127. package/lib/module.mjs.map +1 -1
  128. package/lib/notations.d.ts +4 -4
  129. package/lib/notations.js.map +1 -1
  130. package/lib/notations.mjs.map +1 -1
  131. package/lib/plain.d.ts +3 -3
  132. package/lib/plain.js.map +1 -1
  133. package/lib/plain.mjs.map +1 -1
  134. package/lib/protobuf.d.ts +2 -2
  135. package/lib/protobuf.js.map +1 -1
  136. package/lib/protobuf.mjs.map +1 -1
  137. package/native/cmd/ttsc-typia/assert_guard_factory_contract_test.go +17 -4
  138. package/native/cmd/ttsc-typia/build.go +3 -0
  139. package/native/cmd/ttsc-typia/callable_interface_function_semantics_transform_test.go +331 -0
  140. package/native/cmd/ttsc-typia/callable_type_literal_boundaries_transform_test.go +1184 -0
  141. package/native/cmd/ttsc-typia/compare_functional_union_membership_transform_test.go +434 -0
  142. package/native/cmd/ttsc-typia/compare_template_literal_union_transform_test.go +241 -0
  143. package/native/cmd/ttsc-typia/create_assert_error_factory_arity_test.go +309 -0
  144. package/native/cmd/ttsc-typia/default_library_spoof_native_identity_transform_test.go +216 -0
  145. package/native/cmd/ttsc-typia/json_schema_dynamic_key_determinism_transform_test.go +246 -0
  146. package/native/cmd/ttsc-typia/json_stringify_contextual_undefined_transform_test.go +556 -0
  147. package/native/cmd/ttsc-typia/lib_replacement_native_identity_transform_test.go +277 -0
  148. package/native/cmd/ttsc-typia/local_function_named_like_typia_operation_transform_test.go +185 -0
  149. package/native/cmd/ttsc-typia/native_named_intersection_union_transform_test.go +390 -0
  150. package/native/cmd/ttsc-typia/node_buffer_native_exports_is_transform_test.go +526 -0
  151. package/native/cmd/ttsc-typia/package_declaration_native_identity_is_transform_test.go +293 -0
  152. package/native/cmd/ttsc-typia/protobuf_diagnostic_code_transform_test.go +167 -0
  153. package/native/cmd/ttsc-typia/recursive_conditional_alias_name_transform_test.go +307 -0
  154. package/native/cmd/ttsc-typia/shadowed_typia_module_declaration_diagnostic_test.go +152 -0
  155. package/native/cmd/ttsc-typia/symbol_index_domain_transform_test.go +316 -0
  156. package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +1 -3
  157. package/native/cmd/ttsc-typia/transform.go +23 -0
  158. package/native/cmd/ttsc-typia/transform_helpers_test.go +166 -25
  159. package/native/cmd/ttsc-typia/user_global_native_identity_transform_test.go +484 -0
  160. package/native/core/factories/FormatCheatSheet.go +2 -2
  161. package/native/core/factories/MetadataCommentTagFactory.go +26 -11
  162. package/native/core/factories/ProtobufFactory.go +6 -1
  163. package/native/core/factories/factory_utility_coverage_test.go +896 -907
  164. package/native/core/factories/internal/metadata/MetadataHelper.go +190 -58
  165. package/native/core/factories/internal/metadata/emplace_metadata_object.go +25 -0
  166. package/native/core/factories/internal/metadata/iterate_metadata_function.go +1 -1
  167. package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +103 -23
  168. package/native/core/factories/internal/metadata/iterate_metadata_map.go +3 -7
  169. package/native/core/factories/internal/metadata/iterate_metadata_native.go +32 -14
  170. package/native/core/factories/internal/metadata/iterate_metadata_set.go +3 -7
  171. package/native/core/factories/metadata_comment_tag_factory_coverage_test.go +2 -2
  172. package/native/core/programmers/RandomProgrammer.go +5 -2
  173. package/native/core/programmers/compare/CompareEqualProgrammer.go +27 -13
  174. package/native/core/programmers/helpers/FunctionProgrammer.go +6 -13
  175. package/native/core/programmers/helpers/StringifyJoinder.go +129 -50
  176. package/native/core/programmers/helpers/joiner_branch_coverage_test.go +116 -120
  177. package/native/core/programmers/iterate/iterate_check_coverage_test.go +76 -158
  178. package/native/core/programmers/iterate/iterate_utility_coverage_test.go +231 -270
  179. package/native/core/programmers/iterate/json_schema_object.go +49 -7
  180. package/native/core/programmers/iterate/json_schema_pattern_property_order_test.go +44 -0
  181. package/native/core/programmers/iterate/openapi_v3_downgrader.go +34 -1
  182. package/native/core/programmers/iterate/template_runtime_pattern.go +11 -0
  183. package/native/core/programmers/json/JsonStringifyProgrammer.go +47 -6
  184. package/native/core/programmers/llm/LlmApplicationProgrammer.go +9 -1
  185. package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +1 -1
  186. package/native/core/schemas/metadata/MetadataCollection.go +47 -14
  187. package/native/core/schemas/metadata/MetadataDefaultLibrary.go +81 -0
  188. package/native/core/schemas/metadata/MetadataObjectType.go +7 -18
  189. package/native/go.mod +4 -4
  190. package/native/transform/CallExpressionTransformer.go +167 -0
  191. package/native/transform/features/protobuf/ProtobufMessageTransformer.go +1 -1
  192. package/package.json +3 -7
  193. package/src/executable/FileSystemIdentity.ts +33 -0
  194. package/src/executable/TypiaGenerateWizard.ts +18 -12
  195. package/src/http.ts +18 -4
  196. package/src/internal/_ProtobufReader.ts +40 -11
  197. package/src/internal/_assertGuard.ts +13 -2
  198. package/src/internal/_isFormatIdnHostname.ts +5 -1
  199. package/src/internal/_isFormatTime.ts +19 -2
  200. package/src/internal/_jsonStringifyArray.ts +50 -0
  201. package/src/internal/_jsonStringifyElement.ts +19 -0
  202. package/src/internal/_jsonStringifyProperty.ts +30 -0
  203. package/src/internal/_llmApplicationFinalize.ts +6 -1
  204. package/src/internal/_randomArray.ts +42 -6
  205. package/src/internal/_randomFormatByte.ts +36 -4
  206. package/src/internal/_randomFormatDate.ts +4 -20
  207. package/src/internal/_randomFormatDatetime.ts +34 -20
  208. package/src/internal/_randomFormatDuration.ts +19 -4
  209. package/src/internal/_randomFormatHostname.ts +2 -2
  210. package/src/internal/_randomFormatIdnHostname.ts +8 -9
  211. package/src/internal/_randomFormatIpv4.ts +43 -3
  212. package/src/internal/_randomFormatIpv6.ts +67 -3
  213. package/src/internal/_randomFormatJsonPointer.ts +23 -3
  214. package/src/internal/_randomFormatRegex.ts +22 -6
  215. package/src/internal/_randomFormatRelativeJsonPointer.ts +23 -10
  216. package/src/internal/_randomFormatTime.ts +50 -12
  217. package/src/internal/_randomPattern.ts +4 -1
  218. package/src/internal/_randomStringLength.ts +61 -17
  219. package/src/internal/private/__notationRename.ts +1 -4
  220. package/src/internal/private/__randomComposition.ts +74 -0
  221. package/src/internal/private/__randomEpoch.ts +34 -0
  222. package/src/json.ts +16 -4
  223. package/src/module.ts +56 -22
  224. package/src/notations.ts +16 -4
  225. package/src/plain.ts +12 -3
  226. package/src/protobuf.ts +16 -4
  227. package/native/adapter/visit.go +0 -173
  228. package/native/adapter/visit_property_chain_edges_test.go +0 -129
  229. package/native/core/programmers/helpers/disable_function_programmer_declare.go +0 -10
  230. package/native/core/programmers/iterate/check_union_array_like.go +0 -422
  231. package/native/core/programmers/iterate/prune_object_properties.go +0 -105
  232. package/native/core/programmers/iterate/stringify_dynamic_properties.go +0 -219
  233. package/native/core/programmers/iterate/stringify_native.go +0 -14
  234. package/native/core/programmers/iterate/stringify_regular_properties.go +0 -112
  235. package/native/core/schemas/metadata/MetadataApplication.go +0 -41
@@ -20,7 +20,7 @@ func (protobufMessageTransformerNamespace) Transform(props nativetransform.ITran
20
20
  typ := props.Context.Checker.GetTypeFromTypeNode(props.Expression.TypeArguments.Nodes[0])
21
21
  if typ != nil && typ.IsTypeParameter() {
22
22
  panic(nativetransform.NewTransformerError(nativetransform.TransformerError_IProps{
23
- Code: "tyipa.protobuf.message",
23
+ Code: "typia.protobuf.message",
24
24
  Message: "non-specified generic argument.",
25
25
  }))
26
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typia",
3
- "version": "13.1.19",
3
+ "version": "13.3.0",
4
4
  "description": "Superfast runtime validators with only one line",
5
5
  "main": "lib/index.js",
6
6
  "exports": {
@@ -50,17 +50,13 @@
50
50
  "inquirer": "^8.2.5",
51
51
  "randexp": "^0.5.3",
52
52
  "tinyglobby": "^0.2.12",
53
- "@typia/interface": "^13.1.19",
54
- "@typia/utils": "^13.1.19"
53
+ "@typia/interface": "^13.3.0",
54
+ "@typia/utils": "^13.3.0"
55
55
  },
56
56
  "peerDependencies": {
57
- "@ttsc/unplugin": ">=0.19.2",
58
57
  "ttsc": ">=0.19.2"
59
58
  },
60
59
  "peerDependenciesMeta": {
61
- "@ttsc/unplugin": {
62
- "optional": true
63
- },
64
60
  "ttsc": {
65
61
  "optional": true
66
62
  }
@@ -147,6 +147,39 @@ export namespace FileSystemIdentity {
147
147
  );
148
148
  }
149
149
 
150
+ /**
151
+ * Builds the key that decides whether two paths are the same filesystem
152
+ * object.
153
+ *
154
+ * The identity is read from `fs.BigIntStats` rather than `fs.Stats`, because
155
+ * `fs.Stats.ino` is a JavaScript number. An NTFS file ID is `(sequenceNumber
156
+ * << 48) | mftRecordIndex` and routinely exceeds `Number.MAX_SAFE_INTEGER` —
157
+ * in a 4000-directory probe, 1879 of them did — where the spacing between
158
+ * representable doubles is 8 or more. Two entries sharing a sequence number
159
+ * with MFT record indices within that spacing round to one double. The
160
+ * traversal callers would then treat a distinct directory or file as already
161
+ * visited and skip it with no diagnostic, and the overwrite guard would
162
+ * refuse a legitimate output (samchon/typia#2269).
163
+ *
164
+ * A filesystem that reports no inode at all keeps the canonical path
165
+ * fallback, which is the only identity available there.
166
+ *
167
+ * @param stat Stats read with `{ bigint: true }`.
168
+ * @param realpath Canonical path of the same object.
169
+ * @returns Key that is equal for two paths only when they are one object.
170
+ */
171
+ export function identityKey(
172
+ stat: Pick<fs.BigIntStats, "dev" | "ino">,
173
+ realpath: string,
174
+ ): string {
175
+ // `BigInt(0)` rather than `0n`: this package compiles at ES2016, where a
176
+ // BigInt literal is a syntax error, while the constructor and the `bigint`
177
+ // type are fine.
178
+ return stat.ino === BigInt(0)
179
+ ? `path:${path.normalize(realpath)}`
180
+ : `inode:${stat.dev}:${stat.ino}`;
181
+ }
182
+
150
183
  function alternateCase(name: string): string | undefined {
151
184
  let changed: boolean = false;
152
185
  let output: string = "";
@@ -453,7 +453,7 @@ export namespace TypiaGenerateWizard {
453
453
  for (const entry of entries) {
454
454
  inputs.add(
455
455
  fileIdentityKey(
456
- await fs.promises.stat(entry.file),
456
+ await fs.promises.stat(entry.file, { bigint: true }),
457
457
  await fs.promises.realpath(entry.file),
458
458
  ),
459
459
  );
@@ -461,9 +461,9 @@ export namespace TypiaGenerateWizard {
461
461
  }
462
462
 
463
463
  for (const entry of files.values()) {
464
- let stat: fs.Stats;
464
+ let stat: fs.BigIntStats;
465
465
  try {
466
- stat = await fs.promises.lstat(entry.target);
466
+ stat = await fs.promises.lstat(entry.target, { bigint: true });
467
467
  } catch (exp) {
468
468
  if (isMissingFileError(exp)) {
469
469
  continue;
@@ -486,7 +486,7 @@ export namespace TypiaGenerateWizard {
486
486
  `Error on TypiaGenerateWizard.generate(): output file would overwrite input file through a physical file alias: ${entry.target}`,
487
487
  );
488
488
  }
489
- if (stat.nlink > 1) {
489
+ if (stat.nlink > BigInt(1)) {
490
490
  throw new URIError(
491
491
  `Error on TypiaGenerateWizard.generate(): output file has multiple hard links: ${entry.target}`,
492
492
  );
@@ -874,7 +874,9 @@ export namespace TypiaGenerateWizard {
874
874
  real: currentReal,
875
875
  });
876
876
 
877
- const currentStat: fs.Stats = await fs.promises.stat(props.from);
877
+ const currentStat: fs.BigIntStats = await fs.promises.stat(props.from, {
878
+ bigint: true,
879
+ });
878
880
  const directoryIdentity: string = fileIdentityKey(currentStat, currentReal);
879
881
  if (props.visitedDirectories.has(directoryIdentity)) {
880
882
  const lexicalStat: fs.Stats = await fs.promises.lstat(props.from);
@@ -907,14 +909,16 @@ export namespace TypiaGenerateWizard {
907
909
  entries.sort((x, y) => {
908
910
  const linkOrder: number =
909
911
  Number(x.stat.isSymbolicLink()) - Number(y.stat.isSymbolicLink());
910
- return linkOrder !== 0 ? linkOrder : x.name.localeCompare(y.name);
912
+ return linkOrder !== 0
913
+ ? linkOrder
914
+ : Buffer.compare(Buffer.from(x.name), Buffer.from(y.name));
911
915
  });
912
916
 
913
917
  for (const entry of entries) {
914
- let stat: fs.Stats;
918
+ let stat: fs.BigIntStats;
915
919
  let real: string;
916
920
  try {
917
- stat = await fs.promises.stat(entry.file);
921
+ stat = await fs.promises.stat(entry.file, { bigint: true });
918
922
  real = await fs.promises.realpath(entry.file);
919
923
  } catch (error) {
920
924
  throw new URIError(
@@ -1086,10 +1090,12 @@ export namespace TypiaGenerateWizard {
1086
1090
  );
1087
1091
  }
1088
1092
 
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}`;
1093
+ /**
1094
+ * Delegates to {@link FileSystemIdentity.identityKey}, which owns the rule and
1095
+ * carries the reasoning for reading the identity as a `bigint`.
1096
+ */
1097
+ function fileIdentityKey(stat: fs.BigIntStats, realpath: string): string {
1098
+ return FileSystemIdentity.identityKey(stat, realpath);
1093
1099
  }
1094
1100
 
1095
1101
  function formatDiagnostics(diagnostics: ITtscCompilerDiagnostic[]): string {
package/src/http.ts CHANGED
@@ -550,10 +550,16 @@ export function createAssertFormData(
550
550
  */
551
551
  export function createAssertFormData<T extends object>(
552
552
  errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error),
553
- ): (input: FormData) => T;
553
+ ): (
554
+ input: FormData,
555
+ errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error),
556
+ ) => T;
554
557
 
555
558
  /** @internal */
556
- export function createAssertFormData<T>(): (input: FormData) => T {
559
+ export function createAssertFormData<T>(): (
560
+ input: FormData,
561
+ errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error),
562
+ ) => T {
557
563
  NoTransformConfigurationError("http.createAssertFormData");
558
564
  }
559
565
 
@@ -652,11 +658,15 @@ export function createAssertQuery(
652
658
  */
653
659
  export function createAssertQuery<T extends object>(
654
660
  errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error),
655
- ): (input: string | IReadableURLSearchParams) => T;
661
+ ): (
662
+ input: string | IReadableURLSearchParams,
663
+ errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error),
664
+ ) => T;
656
665
 
657
666
  /** @internal */
658
667
  export function createAssertQuery<T>(): (
659
668
  input: string | IReadableURLSearchParams,
669
+ errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error),
660
670
  ) => T {
661
671
  NoTransformConfigurationError("http.createAssertQuery");
662
672
  }
@@ -758,11 +768,15 @@ export function createAssertHeaders(
758
768
  */
759
769
  export function createAssertHeaders<T extends object>(
760
770
  errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error),
761
- ): (input: Record<string, string | string[] | undefined>) => T;
771
+ ): (
772
+ input: Record<string, string | string[] | undefined>,
773
+ errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error),
774
+ ) => T;
762
775
 
763
776
  /** @internal */
764
777
  export function createAssertHeaders<T>(): (
765
778
  input: Record<string, string | string[] | undefined>,
779
+ errorFactory?: undefined | ((props: TypeGuardError.IProps) => Error),
766
780
  ) => T {
767
781
  NoTransformConfigurationError("http.createAssertHeaders");
768
782
  }
@@ -110,15 +110,19 @@ export class _ProtobufReader {
110
110
  * Advance by exactly one varint, which carries no length prefix.
111
111
  *
112
112
  * A varint terminates at its first byte without the continuation bit, and may
113
- * occupy no more than {@link VARINT_MAX_BYTES}. Reading past that limit would
114
- * accept a varint that `varint32` and `varint64` could not, making the limit
115
- * depend on which method happens to consume the value.
113
+ * occupy no more than {@link VARINT_MAX_BYTES}. Its tenth byte is bounded
114
+ * twice over, by {@link lastVarintByte}: it may neither continue into an
115
+ * eleventh byte nor carry payload above bit 63. Skipping is where that is
116
+ * easiest to get wrong, because this path discards the bytes it reads and so
117
+ * never notices a value it could not have represented. Relaxing either bound
118
+ * here would accept a varint that `varint32` and `varint64` reject, making
119
+ * the limit depend on which method happens to consume the value.
116
120
  */
117
121
  public skipVarint(): void {
118
122
  this.atomic(() => {
119
- for (let i: number = 0; i < VARINT_MAX_BYTES; ++i)
123
+ for (let i: number = 1; i < VARINT_MAX_BYTES; ++i)
120
124
  if ((this.u8() & 0x80) === 0) return;
121
- throw error(`varint exceeds ${VARINT_MAX_BYTES} bytes.`);
125
+ this.lastVarintByte();
122
126
  });
123
127
  }
124
128
 
@@ -172,8 +176,7 @@ export class _ProtobufReader {
172
176
  if (this.u8() < 0x80) return value;
173
177
  if (this.u8() < 0x80) return value;
174
178
  if (this.u8() < 0x80) return value;
175
- if (this.u8() < 0x80) return value;
176
-
179
+ this.lastVarintByte();
177
180
  return value;
178
181
  }
179
182
 
@@ -208,10 +211,28 @@ export class _ProtobufReader {
208
211
  value |= ((loaded = this.u8n()) & BigInt(0x7f)) << BigInt(56);
209
212
  if (loaded < BigInt(0x80)) return value;
210
213
 
211
- value |= (this.u8n() & BigInt(0x01)) << BigInt(63);
214
+ value |= BigInt(this.lastVarintByte()) << BigInt(63);
212
215
  return BigInt.asUintN(64, value);
213
216
  }
214
217
 
218
+ /**
219
+ * Read the only byte whose varint payload is limited to bit 63.
220
+ *
221
+ * Two distinct faults meet on this byte, and each is named for what it is. A
222
+ * continuation bit means the varint would occupy an eleventh byte, which no
223
+ * 64-bit value can reach. Any other payload bit means the varint terminates
224
+ * within its ten bytes but carries a value bit above 63. Reporting the second
225
+ * as a length fault would tell the caller something untrue about a payload
226
+ * that is exactly ten bytes long.
227
+ */
228
+ private lastVarintByte(): number {
229
+ const loaded: number = this.u8();
230
+ if ((loaded & 0x80) !== 0)
231
+ throw error(`varint exceeds ${VARINT_MAX_BYTES} bytes.`);
232
+ if (loaded > 0x01) throw error(`varint exceeds ${VARINT_MAX_BITS} bits.`);
233
+ return loaded;
234
+ }
235
+
215
236
  private u8(): number {
216
237
  return this.view.getUint8(this.take(1));
217
238
  }
@@ -262,12 +283,20 @@ const error = (message: string): Error =>
262
283
  /**
263
284
  * The most bytes a varint may occupy: a 64-bit value in seven-bit groups.
264
285
  *
265
- * `varint32` and `varint64` hold this same limit structurally, by reading no
266
- * further than their tenth byte. This constant is what a loop-driven consumer
267
- * holds it by.
286
+ * Every path reads no further than its tenth byte and accepts only bit 63 from
287
+ * that byte. This constant keeps the loop-driven skip path on the same limit.
268
288
  */
269
289
  const VARINT_MAX_BYTES = 10;
270
290
 
291
+ /**
292
+ * The widest value a varint may carry: the 64-bit Protocol Buffer wire domain.
293
+ *
294
+ * The tenth byte reaches only bit 63, so a payload bit above it belongs to no
295
+ * representable value. This names the overflow fault apart from the length
296
+ * one.
297
+ */
298
+ const VARINT_MAX_BITS = 64;
299
+
271
300
  const utf8 = new Singleton(
272
301
  () => new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }),
273
302
  );
@@ -6,8 +6,19 @@ export const _assertGuard = (
6
6
  factory?: (props: TypeGuardError.IProps) => Error,
7
7
  ): false => {
8
8
  if (exceptionable === true) {
9
- if (factory) throw factory(props);
10
- else throw new TypeGuardError(props);
9
+ // `factory` arrives from the generated function's second parameter, which
10
+ // a pointwise hand-off fills with something that is not a factory at all:
11
+ // `rows.map(assertUser)` passes the element index. A truthiness test then
12
+ // called a number and reported `factory is not a function`, hiding the
13
+ // real assertion failure — and only for indices other than 0. Require a
14
+ // callable, and fall back to TypeGuardError for everything else.
15
+ //
16
+ // A create-time factory is the default of that same parameter, so a
17
+ // non-callable argument has already overridden it by the time this runs
18
+ // and cannot be recovered here. TypeGuardError still names the property
19
+ // that failed, which `factory is not a function` never did.
20
+ if (typeof factory === "function") throw factory(props);
21
+ throw new TypeGuardError(props);
11
22
  }
12
23
  return false;
13
24
  };
@@ -1,4 +1,8 @@
1
1
  export const _isFormatIdnHostname = (str: string): boolean => PATTERN.test(str);
2
2
 
3
+ // The ASCII `hostname` structure with the label character class extended by the
4
+ // non-ASCII range: every valid host name is a valid IDN host name, so this must
5
+ // accept a single label, a one-to-63-character label in any position, and a
6
+ // name up to 253 characters, exactly as `_isFormatHostname` does (issue #2317).
3
7
  const PATTERN =
4
- /^([a-z0-9\u00a1-\uffff0-9]+(-[a-z0-9\u00a1-\uffff0-9]+)*\.)+[a-z\u00a1-\uffff]{2,}$/i;
8
+ /^(?=.{1,253}\.?$)[a-z0-9\u00a1-\uffff](?:[a-z0-9\u00a1-\uffff-]{0,61}[a-z0-9\u00a1-\uffff])?(?:\.[a-z0-9\u00a1-\uffff](?:[a-z0-9\u00a1-\uffff-]{0,61}[a-z0-9\u00a1-\uffff])?)*\.?$/i;
@@ -1,4 +1,21 @@
1
- export const _isFormatTime = (str: string): boolean => PATTERN.test(str);
1
+ export const _isFormatTime = (str: string): boolean => {
2
+ const match: RegExpExecArray | null = PATTERN.exec(str);
3
+ if (match === null) return false;
4
+ if (match[3] !== "60") return true;
5
+
6
+ // RFC 3339 admits `:60` only where a leap second is inserted, which is
7
+ // always 23:59:60 UTC. `date-time` decides that from the instant it can
8
+ // build; a clock carries no date, so it shifts itself by its own offset and
9
+ // asks the same question, wrapping the result back into the day.
10
+ const offset: number =
11
+ match[4] === undefined
12
+ ? 0
13
+ : (match[4] === "+" ? 1 : -1) *
14
+ (Number(match[5]) * 60 + Number(match[6]));
15
+ const minutes: number = Number(match[1]) * 60 + Number(match[2]) - offset;
16
+ return ((minutes % DAY) + DAY) % DAY === DAY - 1;
17
+ };
2
18
 
3
19
  const PATTERN =
4
- /^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](?:\.[0-9]{1,9})?(Z|[+-]([01][0-9]|2[0-3]):[0-5][0-9])$/i;
20
+ /^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(?:\.[0-9]+)?(?:[Zz]|([+-])((?:[01][0-9]|2[0-3])):([0-5][0-9]))$/;
21
+ const DAY = 24 * 60;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Serializes the elements of an array the way ECMAScript `JSON.stringify` does.
3
+ *
4
+ * `SerializeJSONArray` walks index `0` to `LengthOfArrayLike(value) - 1` and
5
+ * writes `null` wherever the element serializes to `undefined`. Neither
6
+ * `Array.prototype.map` nor `Array.prototype.join` reproduces that:
7
+ *
8
+ * - `map` never visits a hole and leaves one behind, and `join` renders a hole as
9
+ * empty text, so a sparse array joined into malformed text such as `[,1]`. A
10
+ * hole exists at runtime whatever the element type declares, so this is not
11
+ * an `any` concern.
12
+ * - `join` renders a mapped `undefined` as empty text too, which is what an `any`
13
+ * or `unknown` element holding a function, a symbol, or a `toJSON` that
14
+ * returns nothing serializes to.
15
+ *
16
+ * The length is converted with `ToLength` and read once, which is both what
17
+ * `JSON.stringify` does and what `Array.prototype.every` - the traversal
18
+ * typia's own array checkers emit - does, so the checker and the serializer
19
+ * walk one index range rather than two that merely usually coincide.
20
+ *
21
+ * @param elements Array being serialized.
22
+ * @param mapper Serializer of one element, emitted by the transform.
23
+ * @returns Comma separated element text, without the enclosing brackets.
24
+ * @internal
25
+ */
26
+ export const _jsonStringifyArray = <T>(
27
+ elements: ArrayLike<T>,
28
+ mapper: (elem: T, index: number) => string,
29
+ ): string => {
30
+ const length: number = Math.min(
31
+ Math.max(Math.trunc(elements.length) || 0, 0),
32
+ Number.MAX_SAFE_INTEGER,
33
+ );
34
+ let output: string = "";
35
+ for (let i: number = 0; i < length; ++i) {
36
+ const elem: T | undefined = elements[i];
37
+ // A hole and an explicit `undefined` are answered without calling the
38
+ // mapper, because the mapper is the element type's own serializer and a
39
+ // typed one has no answer for a missing value. Everything else is answered
40
+ // from the mapper's *result*: an element that is present but serializes to
41
+ // nothing — a function, a symbol, or a `toJSON` returning nothing in an
42
+ // `any` slot — is `null` in an array position, exactly as
43
+ // SerializeJSONArray specifies, and testing the input instead would let its
44
+ // text become the literal `undefined`.
45
+ const text: string | undefined =
46
+ elem === undefined ? undefined : mapper(elem, i);
47
+ output += (i === 0 ? "" : ",") + (text === undefined ? "null" : text);
48
+ }
49
+ return output;
50
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Writes one array or tuple element the way ECMAScript `JSON.stringify` writes
3
+ * it.
4
+ *
5
+ * `SerializeJSONArray` writes `null` wherever an element serializes to
6
+ * `undefined`, because an array position cannot be omitted without shifting
7
+ * every element after it. A present value with no serialization — a function, a
8
+ * symbol, or a `toJSON` returning nothing — is therefore `null`, not the
9
+ * literal text `undefined` and not an empty slot.
10
+ *
11
+ * This is the fixed-position counterpart of `_jsonStringifyArray`, which
12
+ * answers the same question while walking an array's own index range.
13
+ *
14
+ * @param text Serialized element value, or `undefined` when it has none.
15
+ * @returns Element text, or `null` when the element has no serialization.
16
+ * @internal
17
+ */
18
+ export const _jsonStringifyElement = (text: string | undefined): string =>
19
+ text === undefined ? "null" : text;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Writes one object member the way ECMAScript `JSON.stringify` writes it.
3
+ *
4
+ * `SerializeJSONObject` serializes each member first and drops the member
5
+ * entirely when that result is `undefined`. Deciding omission from the _input_
6
+ * instead cannot reach the same answer: a symbol and a `toJSON` returning
7
+ * nothing are both present, non-`undefined`, non-function values whose
8
+ * serialization is `undefined`, so the member's text became the literal
9
+ * `"k":undefined` — output that is not JSON at all.
10
+ *
11
+ * The serialized text is passed in already evaluated, so the member's value is
12
+ * serialized exactly once. Testing the input and then serializing would
13
+ * evaluate a `toJSON` twice, and a `toJSON` is free to answer differently each
14
+ * call.
15
+ *
16
+ * The trailing separator belongs to the member because a dropped member must
17
+ * take its comma with it; `_jsonStringifyTail` removes the one that is left
18
+ * behind when the last written member is the one that dropped.
19
+ *
20
+ * @param head Quoted key and colon, emitted by the transform.
21
+ * @param text Serialized member value, or `undefined` when it has none.
22
+ * @param tail Separator following this member, empty for the last one.
23
+ * @returns Member text, or an empty string when the member is omitted.
24
+ * @internal
25
+ */
26
+ export const _jsonStringifyProperty = (
27
+ head: string,
28
+ text: string | undefined,
29
+ tail: string,
30
+ ): string => (text === undefined ? "" : head + text + tail);
@@ -7,7 +7,12 @@ export const _llmApplicationFinalize = <Class extends object = any>(
7
7
  ): ILlmApplication<Class> => ({
8
8
  ...app,
9
9
  config: {
10
- ...LlmSchemaConverter.getConfig(),
10
+ // The schema configuration comes from the emitted application, which is
11
+ // where the `Config` generic was resolved. Rebuilding it from the
12
+ // converter's defaults reported `strict: false` for a strict build, and
13
+ // `@typia/mcp` then inverted a strict output schema without strict, which
14
+ // drops every constraint it carries as a description tag (issue #2293).
15
+ ...LlmSchemaConverter.getConfig(app.config),
11
16
  validate: config?.validate ?? null,
12
17
  },
13
18
  functions: app.functions.map((func) => ({
@@ -7,6 +7,16 @@ const DEFAULT_MIN_ITEMS = 1;
7
7
  const DEFAULT_RANGE = 5;
8
8
  const DEFAULT_RECURSIVE_RANGE = 2;
9
9
 
10
+ /**
11
+ * Consecutive duplicates that end a unique draw once its floor is satisfied.
12
+ *
13
+ * The worst case a domain can still hide is one value left among a handful:
14
+ * with one of four remaining, sixty-four misses in a row is a `0.75 ** 64`
15
+ * event, about one in a hundred million. Below the floor this limit does not
16
+ * apply at all, so it can never fail a request the domain could satisfy.
17
+ */
18
+ const STALE_LIMIT = 64;
19
+
10
20
  export const _randomArray = <T>(
11
21
  props: Omit<OpenApi.IJsonSchema.IArray, "items"> & {
12
22
  element: (index: number, count: number) => T;
@@ -28,16 +38,42 @@ export const _randomArray = <T>(
28
38
  });
29
39
  if (props.uniqueItems !== true)
30
40
  return new Array(count).fill(null).map((_, i) => props.element(i, count));
41
+ // How many distinct values the element can take is not knowable from here --
42
+ // `element` is a closure over whatever the transform emitted, from `boolean`
43
+ // to a recursive object -- so the count above is a preference, not a
44
+ // contract. Draw until the budget says the domain has nothing new left, then
45
+ // keep what was reached.
46
+ //
47
+ // Failing on that budget instead is what made `Array<boolean> &
48
+ // UniqueItems` throw on two draws in three: `[true, false]` satisfies the
49
+ // declaration at every count, and a count of five is unreachable for a
50
+ // domain of two however many times it is redrawn. Only a result below the
51
+ // floor is a real failure, which is still the honest outcome for a window
52
+ // like `MinItems<3>` over a domain of two.
53
+ //
54
+ // Below the floor the whole budget is spent, because stopping early there
55
+ // would fail a request the domain can still satisfy. Above it every further
56
+ // attempt is only buying length, so a run of `STALE_LIMIT` duplicates is
57
+ // taken as the domain saying it has nothing left. Without that, each nesting
58
+ // level of a small-domain unique array multiplies the full budget into the
59
+ // level above it.
31
60
  const elements: T[] = [];
32
61
  const maximumAttempts: number = count * 100 + 1000;
33
- for (let attempts = 0; elements.length !== count; attempts++) {
34
- if (attempts === maximumAttempts)
35
- throw new Error(
36
- "Unable to generate enough unique items; the element domain may be too small.",
37
- );
62
+ let stale: number = 0;
63
+ for (
64
+ let attempts = 0;
65
+ elements.length !== count && attempts !== maximumAttempts;
66
+ attempts++
67
+ ) {
38
68
  const candidate: T = props.element(elements.length, count);
39
- if (elements.every((element) => _isUniqueItems([element, candidate])))
69
+ if (elements.every((element) => _isUniqueItems([element, candidate]))) {
40
70
  elements.push(candidate);
71
+ stale = 0;
72
+ } else if (elements.length >= minimum && ++stale === STALE_LIMIT) break;
41
73
  }
74
+ if (elements.length < minimum)
75
+ throw new Error(
76
+ "Unable to generate enough unique items; the element domain may be too small.",
77
+ );
42
78
  return elements;
43
79
  };
@@ -1,6 +1,38 @@
1
- import { _ILengthProps, _randomFormatLength } from "./_randomStringLength";
1
+ import { _randomInteger } from "./_randomInteger";
2
+ import {
3
+ _ILengthProps,
4
+ _RANDOM_LENGTH_ERROR,
5
+ _randomLengthPick,
6
+ _randomLengthWindow,
7
+ } from "./_randomStringLength";
8
+ import { __randomBase64 } from "./private/__randomComposition";
2
9
 
3
- export const _randomFormatByte = (props?: _ILengthProps): string =>
4
- _randomFormatLength(props, () => FIXED);
10
+ export const _randomFormatByte = (props?: _ILengthProps): string => {
11
+ // Base64 encodes three bytes as four characters, so a valid length is always
12
+ // a multiple of four; an unconstrained draw spends between four and twelve
13
+ // groups, and a constrained one raises the window to the first multiple it
14
+ // contains and steps by four from there.
15
+ if (props?.minLength === undefined && props?.maxLength === undefined)
16
+ return __randomBase64(
17
+ 4 *
18
+ _randomInteger({
19
+ type: "integer",
20
+ minimum: DEFAULT_GROUP_MIN,
21
+ maximum: DEFAULT_GROUP_MAX,
22
+ }),
23
+ );
24
+ const window = _randomLengthWindow(props, { minimum: 0, spread: 16 });
25
+ const low: number = Math.ceil(window.low / 4) * 4;
26
+ if (low > window.high) throw new Error(_RANDOM_LENGTH_ERROR);
27
+ const length: number =
28
+ low +
29
+ 4 *
30
+ _randomLengthPick({
31
+ low: 0,
32
+ high: Math.floor((window.high - low) / 4),
33
+ });
34
+ return __randomBase64(length);
35
+ };
5
36
 
6
- const FIXED = "vt7ekz4lIoNTTS9sDQYdWKharxIFAR54+z/umIxSgUM=";
37
+ const DEFAULT_GROUP_MIN = 4;
38
+ const DEFAULT_GROUP_MAX = 12;
@@ -1,23 +1,7 @@
1
- import { _randomInteger } from "./_randomInteger";
2
- import { _randomFormatLength } from "./_randomStringLength";
1
+ import { _ILengthProps, _randomFormatLength } from "./_randomStringLength";
2
+ import { __IEpochProps, __randomEpoch } from "./private/__randomEpoch";
3
3
 
4
- export const _randomFormatDate = (props?: {
5
- minimum?: number;
6
- maximum?: number;
7
- minLength?: number;
8
- maxLength?: number;
9
- }) =>
4
+ export const _randomFormatDate = (props?: __IEpochProps & _ILengthProps) =>
10
5
  _randomFormatLength(props, () =>
11
- new Date(
12
- _randomInteger({
13
- type: "integer",
14
- minimum: props?.minimum ?? 0,
15
- maximum:
16
- (props?.maximum ?? props?.minimum === undefined)
17
- ? Date.now()
18
- : props.minimum + 365 * 24 * 60 * 60 * 1_000,
19
- }),
20
- )
21
- .toISOString()
22
- .substring(0, 10),
6
+ new Date(__randomEpoch(props)).toISOString().substring(0, 10),
23
7
  );