@wener/common 2.0.3 → 2.0.6

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 (312) hide show
  1. package/lib/ai/qwen3vl/index.js +1 -1
  2. package/lib/ai/qwen3vl/utils.js +15 -15
  3. package/lib/ai/qwen3vl/utils.js.map +1 -1
  4. package/lib/ai/vision/DocLayoutElementTypeSchema.js +22 -22
  5. package/lib/ai/vision/ImageAnnotationSchema.js +63 -47
  6. package/lib/ai/vision/index.js +2 -2
  7. package/lib/ai/vision/resolveImageAnnotation.js +81 -95
  8. package/lib/cn/ChineseResidentIdNo.js +55 -41
  9. package/lib/cn/ChineseResidentIdNo.js.map +1 -1
  10. package/lib/cn/ChineseResidentIdNo.mod.js +6 -1
  11. package/lib/cn/ChineseResidentIdNo.test.js +22 -21
  12. package/lib/cn/DivisionCode.js +220 -235
  13. package/lib/cn/DivisionCode.mod.js +6 -1
  14. package/lib/cn/DivisionCode.test.js +92 -121
  15. package/lib/cn/Mod11.js +18 -37
  16. package/lib/cn/Mod11.js.map +1 -1
  17. package/lib/cn/Mod31.js +23 -41
  18. package/lib/cn/UnifiedSocialCreditCode.js +143 -137
  19. package/lib/cn/UnifiedSocialCreditCode.mod.js +6 -1
  20. package/lib/cn/UnifiedSocialCreditCode.test.js +21 -15
  21. package/lib/cn/formatChineseAmount.js +46 -71
  22. package/lib/cn/index.js +6 -6
  23. package/lib/cn/mod.js +5 -3
  24. package/lib/cn/parseChineseNumber.js +81 -85
  25. package/lib/cn/parseChineseNumber.test.js +183 -261
  26. package/lib/cn/pinyin/cartesianProduct.js +19 -19
  27. package/lib/cn/pinyin/cartesianProduct.test.js +78 -178
  28. package/lib/cn/pinyin/loader.js +13 -11
  29. package/lib/cn/pinyin/preload.js +2 -1
  30. package/lib/cn/pinyin/toPinyin.test.js +149 -161
  31. package/lib/cn/pinyin/toPinyinPure.js +28 -23
  32. package/lib/cn/pinyin/transform.js +11 -11
  33. package/lib/cn/types.d.js +2 -2
  34. package/lib/consola/createStandardConsolaReporter.js +14 -15
  35. package/lib/consola/formatLogObject.js +149 -133
  36. package/lib/consola/formatLogObject.js.map +1 -1
  37. package/lib/consola/formatLogObject.test.js +167 -178
  38. package/lib/consola/index.js +2 -2
  39. package/lib/data/formatSort.js +14 -12
  40. package/lib/data/formatSort.test.js +33 -33
  41. package/lib/data/index.js +3 -3
  42. package/lib/data/maybeNumber.js +23 -23
  43. package/lib/data/maybeNumber.js.map +1 -1
  44. package/lib/data/parseSort.js +75 -68
  45. package/lib/data/parseSort.test.js +196 -187
  46. package/lib/data/resolvePagination.js +38 -39
  47. package/lib/data/resolvePagination.test.js +228 -218
  48. package/lib/data/types.d.js +2 -2
  49. package/lib/data/types.d.js.map +1 -1
  50. package/lib/dayjs/dayjs.js +20 -20
  51. package/lib/dayjs/formatDuration.js +56 -56
  52. package/lib/dayjs/formatDuration.js.map +1 -1
  53. package/lib/dayjs/formatDuration.test.js +63 -77
  54. package/lib/dayjs/index.js +4 -4
  55. package/lib/dayjs/parseDuration.js +21 -26
  56. package/lib/dayjs/parseRelativeTime.js +65 -66
  57. package/lib/dayjs/parseRelativeTime.test.js +227 -243
  58. package/lib/dayjs/resolveRelativeTime.js +74 -144
  59. package/lib/dayjs/resolveRelativeTime.js.map +1 -1
  60. package/lib/dayjs/resolveRelativeTime.test.js +296 -307
  61. package/lib/decimal/index.js +1 -1
  62. package/lib/decimal/parseDecimal.js +12 -12
  63. package/lib/drain3/Drain.js +321 -0
  64. package/lib/drain3/Drain.js.map +1 -0
  65. package/lib/drain3/LogCluster.js +38 -0
  66. package/lib/drain3/LogCluster.js.map +1 -0
  67. package/lib/drain3/Node.js +39 -0
  68. package/lib/drain3/Node.js.map +1 -0
  69. package/lib/drain3/TemplateMiner.js +205 -0
  70. package/lib/drain3/TemplateMiner.js.map +1 -0
  71. package/lib/drain3/index.js +31 -0
  72. package/lib/drain3/index.js.map +1 -0
  73. package/lib/drain3/persistence/FilePersistence.js +24 -0
  74. package/lib/drain3/persistence/FilePersistence.js.map +1 -0
  75. package/lib/drain3/persistence/MemoryPersistence.js +18 -0
  76. package/lib/drain3/persistence/MemoryPersistence.js.map +1 -0
  77. package/lib/drain3/persistence/PersistenceHandler.js +5 -0
  78. package/lib/drain3/persistence/PersistenceHandler.js.map +1 -0
  79. package/lib/drain3/types.js +7 -0
  80. package/lib/drain3/types.js.map +1 -0
  81. package/lib/emittery/emitter.js +7 -7
  82. package/lib/emittery/index.js +1 -1
  83. package/lib/foundation/schema/SexType.js +15 -12
  84. package/lib/foundation/schema/index.js +1 -1
  85. package/lib/foundation/schema/parseSexType.js +15 -16
  86. package/lib/foundation/schema/types.js +8 -6
  87. package/lib/fs/FileSystemError.js +18 -18
  88. package/lib/fs/IFileSystem.d.js +2 -2
  89. package/lib/fs/IFileSystem.d.js.map +1 -1
  90. package/lib/fs/MemoryFileSystem.test.js +172 -181
  91. package/lib/fs/createBrowserFileSystem.js +222 -233
  92. package/lib/fs/createBrowserFileSystem.js.map +1 -1
  93. package/lib/fs/createMemoryFileSystem.js +473 -510
  94. package/lib/fs/createMemoryFileSystem.js.map +1 -1
  95. package/lib/fs/createSandboxFileSystem.js +102 -101
  96. package/lib/fs/createSandboxFileSystem.js.map +1 -1
  97. package/lib/fs/createWebDavFileSystem.js +162 -132
  98. package/lib/fs/createWebDavFileSystem.js.map +1 -1
  99. package/lib/fs/createWebFileSystem.js +202 -0
  100. package/lib/fs/createWebFileSystem.js.map +1 -0
  101. package/lib/fs/findMimeType.js +14 -14
  102. package/lib/fs/findMimeType.js.map +1 -1
  103. package/lib/fs/index.js +7 -7
  104. package/lib/fs/index.js.map +1 -1
  105. package/lib/fs/minio/createMinioFileSystem.js +977 -0
  106. package/lib/fs/minio/createMinioFileSystem.js.map +1 -0
  107. package/lib/fs/minio/index.js +2 -0
  108. package/lib/fs/minio/index.js.map +1 -0
  109. package/lib/fs/orpc/FileSystemContract.js +57 -57
  110. package/lib/fs/orpc/createContractClientFileSystem.js +88 -88
  111. package/lib/fs/orpc/createContractClientFileSystem.js.map +1 -1
  112. package/lib/fs/orpc/index.js +2 -2
  113. package/lib/fs/orpc/server/createFileSystemContractImpl.js +62 -60
  114. package/lib/fs/orpc/server/createFileSystemContractImpl.js.map +1 -1
  115. package/lib/fs/orpc/server/index.js +1 -1
  116. package/lib/fs/s3/createS3MiniFileSystem.js +756 -689
  117. package/lib/fs/s3/createS3MiniFileSystem.js.map +1 -1
  118. package/lib/fs/s3/index.js +1 -1
  119. package/lib/fs/s3/s3mini.test.js +524 -553
  120. package/lib/fs/scandir.js +56 -56
  121. package/lib/fs/server/createDatabaseFileSystem.js +834 -741
  122. package/lib/fs/server/createDatabaseFileSystem.js.map +1 -1
  123. package/lib/fs/server/createNodeFileSystem.js +407 -380
  124. package/lib/fs/server/createNodeFileSystem.js.map +1 -1
  125. package/lib/fs/server/dbfs.test.js +201 -214
  126. package/lib/fs/server/index.js +1 -1
  127. package/lib/fs/server/loadTestDatabase.js +40 -43
  128. package/lib/fs/tests/runFileSystemTest.js +352 -315
  129. package/lib/fs/tests/runFileSystemTest.js.map +1 -1
  130. package/lib/fs/types.js +17 -20
  131. package/lib/fs/utils/getFileUrl.js +24 -30
  132. package/lib/fs/utils.js +17 -17
  133. package/lib/fs/utils.js.map +1 -1
  134. package/lib/fs/webdav/index.js +2 -0
  135. package/lib/fs/webdav/index.js.map +1 -0
  136. package/lib/index.js +2 -2
  137. package/lib/jsonschema/JsonSchema.js +216 -155
  138. package/lib/jsonschema/JsonSchema.js.map +1 -1
  139. package/lib/jsonschema/JsonSchema.test.js +123 -124
  140. package/lib/jsonschema/forEachJsonSchema.js +41 -41
  141. package/lib/jsonschema/forEachJsonSchema.js.map +1 -1
  142. package/lib/jsonschema/index.js +2 -2
  143. package/lib/jsonschema/types.d.js +2 -2
  144. package/lib/jsonschema/types.d.js.map +1 -1
  145. package/lib/meta/defineFileType.js +32 -38
  146. package/lib/meta/defineInit.js +39 -35
  147. package/lib/meta/defineMetadata.js +37 -34
  148. package/lib/meta/defineMetadata.js.map +1 -1
  149. package/lib/meta/defineMetadata.test.js +13 -12
  150. package/lib/meta/index.js +3 -3
  151. package/lib/orpc/createOpenApiContractClient.js +26 -24
  152. package/lib/orpc/createOpenApiContractClient.js.map +1 -1
  153. package/lib/orpc/createRpcContractClient.js +37 -31
  154. package/lib/orpc/index.js +2 -2
  155. package/lib/orpc/resolveLinkPlugins.js +25 -25
  156. package/lib/password/PHC.js +187 -189
  157. package/lib/password/PHC.js.map +1 -1
  158. package/lib/password/PHC.test.js +517 -535
  159. package/lib/password/Password.js +85 -80
  160. package/lib/password/Password.test.js +330 -364
  161. package/lib/password/createArgon2PasswordAlgorithm.js +50 -51
  162. package/lib/password/createArgon2PasswordAlgorithm.js.map +1 -1
  163. package/lib/password/createBase64PasswordAlgorithm.js +11 -11
  164. package/lib/password/createBase64PasswordAlgorithm.js.map +1 -1
  165. package/lib/password/createBcryptPasswordAlgorithm.js +20 -18
  166. package/lib/password/createBcryptPasswordAlgorithm.js.map +1 -1
  167. package/lib/password/createPBKDF2PasswordAlgorithm.js +65 -52
  168. package/lib/password/createPBKDF2PasswordAlgorithm.js.map +1 -1
  169. package/lib/password/createScryptPasswordAlgorithm.js +74 -63
  170. package/lib/password/createScryptPasswordAlgorithm.js.map +1 -1
  171. package/lib/password/index.js +5 -5
  172. package/lib/password/server/index.js +1 -1
  173. package/lib/resource/Identifiable.js +2 -2
  174. package/lib/resource/ListQuery.js +42 -42
  175. package/lib/resource/ListQuery.js.map +1 -1
  176. package/lib/resource/getTitleOfResource.js +5 -5
  177. package/lib/resource/index.js +2 -2
  178. package/lib/resource/index.js.map +1 -1
  179. package/lib/resource/schema/AnyResourceSchema.js +91 -89
  180. package/lib/resource/schema/BaseResourceSchema.js +26 -26
  181. package/lib/resource/schema/ResourceActionType.js +117 -115
  182. package/lib/resource/schema/ResourceStatus.js +94 -92
  183. package/lib/resource/schema/ResourceType.js +25 -23
  184. package/lib/resource/schema/index.js +5 -5
  185. package/lib/resource/schema/types.js +86 -55
  186. package/lib/resource/schema/types.test.js +16 -13
  187. package/lib/s3/formatS3Url.js +60 -60
  188. package/lib/s3/formatS3Url.js.map +1 -1
  189. package/lib/s3/formatS3Url.test.js +238 -261
  190. package/lib/s3/index.js +2 -2
  191. package/lib/s3/parseS3Url.js +61 -60
  192. package/lib/s3/parseS3Url.js.map +1 -1
  193. package/lib/s3/parseS3Url.test.js +270 -269
  194. package/lib/schema/SchemaRegistry.js +41 -42
  195. package/lib/schema/SchemaRegistry.js.map +1 -1
  196. package/lib/schema/SchemaRegistry.mod.js +1 -1
  197. package/lib/schema/TypeSchema.d.js +2 -2
  198. package/lib/schema/TypeSchema.d.js.map +1 -1
  199. package/lib/schema/createSchemaData.js +113 -67
  200. package/lib/schema/createSchemaData.js.map +1 -1
  201. package/lib/schema/findJsonSchemaByPath.js +28 -23
  202. package/lib/schema/findJsonSchemaByPath.js.map +1 -1
  203. package/lib/schema/formatZodError.js +113 -134
  204. package/lib/schema/formatZodError.js.map +1 -1
  205. package/lib/schema/formatZodError.test.js +192 -195
  206. package/lib/schema/getSchemaCache.js +7 -7
  207. package/lib/schema/getSchemaOptions.js +17 -16
  208. package/lib/schema/index.js +6 -6
  209. package/lib/schema/toJsonSchema.js +196 -190
  210. package/lib/schema/toJsonSchema.js.map +1 -1
  211. package/lib/schema/toJsonSchema.test.js +34 -26
  212. package/lib/schema/validate.js +106 -97
  213. package/lib/schema/validate.js.map +1 -1
  214. package/lib/tools/generateSchema.js +40 -40
  215. package/lib/tools/renderJsonSchemaToMarkdownDoc.js +74 -74
  216. package/lib/utils/buildBaseUrl.js +8 -8
  217. package/lib/utils/buildRedactorFormSchema.js +55 -54
  218. package/lib/utils/buildRedactorFormSchema.js.map +1 -1
  219. package/lib/utils/getEstimateProcessTime.js +24 -19
  220. package/lib/utils/index.js +3 -3
  221. package/lib/utils/resolveFeatureOptions.js +9 -9
  222. package/package.json +37 -18
  223. package/src/ai/qwen3vl/utils.ts +1 -1
  224. package/src/ai/vision/index.ts +2 -2
  225. package/src/cn/ChineseResidentIdNo.ts +1 -1
  226. package/src/cn/Mod11.ts +1 -1
  227. package/src/cn/__snapshots__/ChineseResidentIdNo.test.ts.snap +1 -1
  228. package/src/cn/__snapshots__/UnifiedSocialCreditCode.test.ts.snap +0 -23
  229. package/src/cn/index.ts +1 -2
  230. package/src/cn/parseChineseNumber.test.ts +4 -4
  231. package/src/consola/formatLogObject.ts +6 -6
  232. package/src/consola/index.ts +1 -1
  233. package/src/data/index.ts +3 -4
  234. package/src/data/maybeNumber.ts +1 -1
  235. package/src/data/parseSort.test.ts +0 -1
  236. package/src/data/resolvePagination.ts +2 -2
  237. package/src/data/types.d.ts +2 -2
  238. package/src/dayjs/formatDuration.ts +10 -11
  239. package/src/dayjs/index.ts +1 -1
  240. package/src/dayjs/parseRelativeTime.ts +1 -1
  241. package/src/dayjs/resolveRelativeTime.ts +11 -14
  242. package/src/drain3/Drain.test.ts +378 -0
  243. package/src/drain3/Drain.ts +394 -0
  244. package/src/drain3/LogCluster.ts +46 -0
  245. package/src/drain3/Node.ts +53 -0
  246. package/src/drain3/TemplateMiner.ts +246 -0
  247. package/src/drain3/index.ts +34 -0
  248. package/src/drain3/persistence/FilePersistence.ts +24 -0
  249. package/src/drain3/persistence/MemoryPersistence.ts +23 -0
  250. package/src/drain3/persistence/PersistenceHandler.ts +19 -0
  251. package/src/drain3/types.ts +75 -0
  252. package/src/fs/IFileSystem.d.ts +1 -2
  253. package/src/fs/createBrowserFileSystem.ts +7 -5
  254. package/src/fs/createMemoryFileSystem.ts +9 -13
  255. package/src/fs/createSandboxFileSystem.ts +1 -1
  256. package/src/fs/createWebDavFileSystem.ts +30 -17
  257. package/src/fs/createWebFileSystem.ts +242 -0
  258. package/src/fs/findMimeType.ts +1 -4
  259. package/src/fs/index.ts +5 -5
  260. package/src/fs/minio/createMinioFileSystem.ts +1148 -0
  261. package/src/fs/minio/index.ts +1 -0
  262. package/src/fs/orpc/createContractClientFileSystem.ts +5 -5
  263. package/src/fs/orpc/server/createFileSystemContractImpl.ts +1 -1
  264. package/src/fs/s3/createS3MiniFileSystem.ts +120 -79
  265. package/src/fs/s3/s3fs.test.ts +441 -0
  266. package/src/fs/s3/s3mini.test.ts +2 -2
  267. package/src/fs/server/createDatabaseFileSystem.ts +78 -114
  268. package/src/fs/server/createNodeFileSystem.ts +32 -13
  269. package/src/fs/server/dbfs.test.ts +13 -8
  270. package/src/fs/server/index.ts +1 -0
  271. package/src/fs/server/loadTestDatabase.ts +8 -119
  272. package/src/fs/tests/runFileSystemTest.ts +29 -28
  273. package/src/fs/utils.ts +1 -1
  274. package/src/fs/webdav/index.ts +1 -0
  275. package/src/jsonschema/JsonSchema.ts +5 -5
  276. package/src/jsonschema/forEachJsonSchema.ts +1 -1
  277. package/src/jsonschema/index.ts +1 -1
  278. package/src/jsonschema/types.d.ts +1 -1
  279. package/src/meta/defineMetadata.ts +1 -1
  280. package/src/meta/index.ts +2 -3
  281. package/src/orm/createSqliteDialect.ts +17 -0
  282. package/src/orm/index.ts +1 -0
  283. package/src/orpc/createOpenApiContractClient.ts +3 -3
  284. package/src/orpc/index.ts +1 -1
  285. package/src/password/PHC.ts +3 -3
  286. package/src/password/createArgon2PasswordAlgorithm.ts +2 -2
  287. package/src/password/createBase64PasswordAlgorithm.ts +2 -2
  288. package/src/password/createBcryptPasswordAlgorithm.ts +4 -2
  289. package/src/password/createPBKDF2PasswordAlgorithm.ts +2 -2
  290. package/src/password/createScryptPasswordAlgorithm.ts +4 -4
  291. package/src/password/index.ts +2 -2
  292. package/src/resource/ListQuery.ts +4 -1
  293. package/src/resource/index.ts +3 -3
  294. package/src/resource/schema/index.ts +4 -4
  295. package/src/s3/formatS3Url.test.ts +1 -1
  296. package/src/s3/formatS3Url.ts +2 -2
  297. package/src/s3/index.ts +1 -1
  298. package/src/s3/parseS3Url.ts +1 -1
  299. package/src/schema/SchemaRegistry.ts +2 -2
  300. package/src/schema/TypeSchema.d.ts +6 -6
  301. package/src/schema/createSchemaData.ts +5 -5
  302. package/src/schema/findJsonSchemaByPath.ts +5 -5
  303. package/src/schema/formatZodError.test.ts +2 -1
  304. package/src/schema/formatZodError.ts +50 -62
  305. package/src/schema/index.ts +5 -5
  306. package/src/schema/toJsonSchema.ts +6 -6
  307. package/src/schema/validate.ts +2 -2
  308. package/src/utils/buildRedactorFormSchema.ts +4 -4
  309. package/src/utils/formatNumber.ts +18 -0
  310. package/src/utils/formatPercent.ts +17 -0
  311. package/src/utils/index.ts +3 -3
  312. package/src/utils/resolveFeatureOptions.ts +1 -1
@@ -10,23 +10,23 @@ import type { JsonSchemaDef } from '../jsonschema';
10
10
  export type TypeSchema<I = unknown, O = I> = TSchema | z.ZodSchema<O, I> | JsonSchemaDef | StandardSchemaV1<I, O>;
11
11
 
12
12
  export type SchemaOutput<S extends TypeSchema> =
13
- S extends StandardSchemaV1<infer I, infer O>
13
+ S extends StandardSchemaV1<infer _I, infer O>
14
14
  ? O
15
- : S extends z.ZodSchema<infer O, infer I>
15
+ : S extends z.ZodSchema<infer O, infer _I>
16
16
  ? O
17
17
  : S extends TSchema
18
18
  ? TypeBoxStaticEncode<S>
19
- : S extends JsonSchemaDef<infer I, infer O>
19
+ : S extends JsonSchemaDef<infer _I, infer O>
20
20
  ? O
21
21
  : never;
22
22
 
23
23
  export type SchemaInput<S extends TypeSchema> =
24
- S extends StandardSchemaV1<infer I, infer O>
24
+ S extends StandardSchemaV1<infer I, infer _O>
25
25
  ? I
26
- : S extends z.ZodSchema<infer O, infer I>
26
+ : S extends z.ZodSchema<infer _O, infer I>
27
27
  ? I
28
28
  : S extends TSchema
29
29
  ? TypeBoxStaticDecode<S>
30
- : S extends JsonSchemaDef<infer I, infer O>
30
+ : S extends JsonSchemaDef<infer I, infer _O>
31
31
  ? I
32
32
  : never;
@@ -1,7 +1,7 @@
1
1
  import { match, P } from 'ts-pattern';
2
2
  import type { JsonSchemaDef } from '../jsonschema';
3
- import { toJsonSchema } from './toJsonSchema';
4
3
  import type { SchemaOutput, TypeSchema } from './TypeSchema';
4
+ import { toJsonSchema } from './toJsonSchema';
5
5
 
6
6
  export function createSchemaData<S extends TypeSchema>(
7
7
  ts: S,
@@ -54,8 +54,8 @@ function _create(schema: JsonSchemaDef, options: CreateOptions, ctx: { required:
54
54
  .with({ oneOf: P.nonNullable }, (schema) => {
55
55
  return _create(schema.oneOf[0], options, { required: false });
56
56
  })
57
- .with({ type: 'string' }, (schema) => '')
58
- .with({ type: P.union('number', 'integer') }, (schema) => 0)
57
+ .with({ type: 'string' }, (_schema) => '')
58
+ .with({ type: P.union('number', 'integer') }, (_schema) => 0)
59
59
  .with({ type: 'object' }, () => {
60
60
  const out: Record<string, any> = {};
61
61
 
@@ -73,8 +73,8 @@ function _create(schema: JsonSchemaDef, options: CreateOptions, ctx: { required:
73
73
  return out;
74
74
  })
75
75
  .with({ type: 'null' }, () => null)
76
- .with({ type: 'boolean' }, (schema) => false)
77
- .with({ type: 'array' }, (schema) => [])
76
+ .with({ type: 'boolean' }, (_schema) => false)
77
+ .with({ type: 'array' }, (_schema) => [])
78
78
  .otherwise(() => {
79
79
  return undefined;
80
80
  });
@@ -1,6 +1,6 @@
1
1
  import { firstOfMaybeArray } from '@wener/utils';
2
- import { toJsonSchema } from './toJsonSchema';
3
2
  import type { TypeSchema } from './TypeSchema';
3
+ import { toJsonSchema } from './toJsonSchema';
4
4
 
5
5
  export function findJsonSchemaByPath(schema: TypeSchema, objectPath: string) {
6
6
  schema = toJsonSchema(schema);
@@ -14,10 +14,10 @@ export function findJsonSchemaByPath(schema: TypeSchema, objectPath: string) {
14
14
  for (const segment of segments) {
15
15
  // 检查当前 schema 是否是对象类型且有 properties
16
16
  if (
17
- currentSchema
18
- && typeof currentSchema === 'object'
19
- && currentSchema.properties
20
- && currentSchema.properties[segment]
17
+ currentSchema &&
18
+ typeof currentSchema === 'object' &&
19
+ currentSchema.properties &&
20
+ currentSchema.properties[segment]
21
21
  ) {
22
22
  currentSchema = currentSchema.properties[segment];
23
23
  continue;
@@ -181,10 +181,11 @@ describe('formatZodError', () => {
181
181
 
182
182
  it('should use schema description when available', () => {
183
183
  const schema = z.object({
184
- name: z.string().describe('姓名'),
184
+ name: z.string().min(1).describe('姓名'),
185
185
  email: z.string().email().describe('邮箱地址'),
186
186
  });
187
187
 
188
+ // Use empty string for name (triggers min(1) error) and invalid email
188
189
  const result = schema.safeParse({ name: '', email: 'invalid' });
189
190
  expect(result.success).toBe(false);
190
191
  if (!result.success) {
@@ -1,7 +1,16 @@
1
- import { ZodError } from 'zod/v4';
1
+ import type { core, ZodError } from 'zod/v4';
2
2
  import { findJsonSchemaByPath } from './findJsonSchemaByPath';
3
3
  import type { TypeSchema } from './TypeSchema';
4
4
 
5
+ // Zod 4 issue types with proper typing
6
+ type ZodIssue = core.$ZodIssue;
7
+ type ZodIssueInvalidType = core.$ZodIssueInvalidType;
8
+ type ZodIssueTooSmall = core.$ZodIssueTooSmall;
9
+ type ZodIssueTooBig = core.$ZodIssueTooBig;
10
+ type ZodIssueInvalidStringFormat = core.$ZodIssueInvalidStringFormat;
11
+ type ZodIssueInvalidValue = core.$ZodIssueInvalidValue;
12
+ type ZodIssueUnrecognizedKeys = core.$ZodIssueUnrecognizedKeys;
13
+
5
14
  export function formatZodError(error: ZodError, schema?: TypeSchema): string {
6
15
  if (!error.issues || error.issues.length === 0) {
7
16
  return error.message || '验证失败';
@@ -34,102 +43,81 @@ export function formatZodError(error: ZodError, schema?: TypeSchema): string {
34
43
  return messages.join(';');
35
44
  }
36
45
 
37
- function formatIssueMessage(issue: ZodError['issues'][number], schema?: TypeSchema): string {
46
+ function formatIssueMessage(issue: ZodIssue, _schema?: TypeSchema): string {
38
47
  let message = issue.message;
39
48
 
40
49
  // 处理常见的错误类型,生成更友好的消息
41
- // Use string comparison to avoid TypeScript narrowing issues with Zod v4
42
- const code = issue.code as string;
43
- switch (code) {
50
+ switch (issue.code) {
44
51
  case 'invalid_type': {
45
- const invalidTypeIssue = issue as typeof issue & {
46
- expected: string;
47
- received: string;
48
- };
49
- if (invalidTypeIssue.received === 'undefined') {
52
+ const i = issue as ZodIssueInvalidType;
53
+ // Zod v4 doesn't have 'received' field directly, extract from message
54
+ const match = issue.message.match(/received (\w+)/);
55
+ const received = match?.[1];
56
+ if (received === 'undefined') {
50
57
  message = '必填';
51
- } else if (invalidTypeIssue.received === 'null') {
58
+ } else if (received === 'null') {
52
59
  message = '不能为空';
53
60
  } else {
54
- message = issue.message || `期望类型 ${invalidTypeIssue.expected},但收到 ${invalidTypeIssue.received}`;
61
+ message = issue.message || `期望类型 ${i.expected},但收到 ${received}`;
55
62
  }
56
63
  break;
57
64
  }
58
- case 'invalid_string': {
59
- const invalidStringIssue = issue as typeof issue & {
60
- validation?: string;
61
- };
62
- if (invalidStringIssue.validation === 'email') {
65
+ case 'invalid_format': {
66
+ const i = issue as ZodIssueInvalidStringFormat;
67
+ if (i.format === 'email') {
63
68
  message = '请输入有效的邮箱地址';
64
- } else if (invalidStringIssue.validation === 'url') {
69
+ } else if (i.format === 'url') {
65
70
  message = '请输入有效的 URL';
66
- } else if (invalidStringIssue.validation === 'uuid') {
71
+ } else if (i.format === 'uuid') {
67
72
  message = '请输入有效的 UUID';
68
- } else if (invalidStringIssue.validation === 'date') {
73
+ } else if (i.format === 'date') {
69
74
  message = '请输入有效的日期';
70
75
  }
71
76
  break;
72
77
  }
73
78
  case 'too_small': {
74
- const tooSmallIssue = issue as typeof issue & {
75
- type: string;
76
- minimum: number;
77
- };
78
- if (tooSmallIssue.type === 'string' && tooSmallIssue.minimum === 1) {
79
+ const i = issue as ZodIssueTooSmall;
80
+ if (i.origin === 'string' && i.minimum === 1) {
79
81
  message = '不能为空';
80
- } else if (tooSmallIssue.type === 'number') {
81
- message = `至少需要 ${tooSmallIssue.minimum}`;
82
- } else if (tooSmallIssue.type === 'array') {
83
- message = `至少需要 ${tooSmallIssue.minimum} 项`;
82
+ } else if (i.origin === 'string') {
83
+ message = `至少需要 ${i.minimum} 个字符`;
84
+ } else if (i.origin === 'number' || i.origin === 'int') {
85
+ message = `至少需要 ${i.minimum}`;
86
+ } else if (i.origin === 'array') {
87
+ message = `至少需要 ${i.minimum} 项`;
84
88
  }
85
89
  break;
86
90
  }
87
91
  case 'too_big': {
88
- const tooBigIssue = issue as typeof issue & {
89
- type: string;
90
- maximum: number;
91
- };
92
- if (tooBigIssue.type === 'string') {
93
- message = `最多 ${tooBigIssue.maximum} 个字符`;
94
- } else if (tooBigIssue.type === 'number') {
95
- message = `最多 ${tooBigIssue.maximum}`;
96
- } else if (tooBigIssue.type === 'array') {
97
- message = `最多 ${tooBigIssue.maximum} 项`;
92
+ const i = issue as ZodIssueTooBig;
93
+ if (i.origin === 'string') {
94
+ message = `最多 ${i.maximum} 个字符`;
95
+ } else if (i.origin === 'number' || i.origin === 'int') {
96
+ message = `最多 ${i.maximum}`;
97
+ } else if (i.origin === 'array') {
98
+ message = `最多 ${i.maximum} 项`;
98
99
  }
99
100
  break;
100
101
  }
101
- case 'invalid_enum_value': {
102
- const enumIssue = issue as typeof issue & {
103
- options: readonly unknown[];
104
- };
105
- message = `必须是以下值之一: ${enumIssue.options?.map(String).join(', ') || '未知选项'}`;
102
+ case 'invalid_value': {
103
+ const i = issue as ZodIssueInvalidValue;
104
+ if (i.values.length === 1) {
105
+ // Single value means it's a literal check
106
+ message = `必须是 ${String(i.values[0])}`;
107
+ } else {
108
+ message = `必须是以下值之一: ${i.values.map(String).join(', ')}`;
109
+ }
106
110
  break;
107
111
  }
108
112
  case 'unrecognized_keys': {
109
- const unrecognizedIssue = issue as typeof issue & {
110
- keys: readonly string[];
111
- };
112
- message = `不支持的字段: ${unrecognizedIssue.keys?.join(', ') || '未知字段'}`;
113
+ const i = issue as ZodIssueUnrecognizedKeys;
114
+ message = `不支持的字段: ${i.keys.join(', ')}`;
113
115
  break;
114
116
  }
115
117
  case 'invalid_union': {
116
118
  message = '不符合任何允许的类型';
117
119
  break;
118
120
  }
119
- case 'invalid_union_discriminator': {
120
- const discriminatorIssue = issue as typeof issue & {
121
- options: readonly unknown[];
122
- };
123
- message = `必须是以下值之一: ${discriminatorIssue.options?.map(String).join(', ') || '未知选项'}`;
124
- break;
125
- }
126
- case 'invalid_literal': {
127
- const literalIssue = issue as typeof issue & {
128
- expected: unknown;
129
- };
130
- message = `必须是 ${String(literalIssue.expected)}`;
131
- break;
132
- }
133
121
  case 'custom': {
134
122
  // 保留自定义错误消息
135
123
  message = issue.message;
@@ -1,7 +1,7 @@
1
- export type * from './TypeSchema';
2
- export { isJsonSchema, isZodSchema, isTypeBoxSchema, validate, parseData, type ValidationResult } from './validate';
3
- export { getSchemaOptions, getSchemaOptionLabel } from './getSchemaOptions';
4
- export { toJsonSchema } from './toJsonSchema';
5
- export { findJsonSchemaByPath } from './findJsonSchemaByPath';
6
1
  export { createSchemaData } from './createSchemaData';
2
+ export { findJsonSchemaByPath } from './findJsonSchemaByPath';
3
+ export { getSchemaOptionLabel, getSchemaOptions } from './getSchemaOptions';
7
4
  export { SchemaRegistry } from './SchemaRegistry';
5
+ export type * from './TypeSchema';
6
+ export { toJsonSchema } from './toJsonSchema';
7
+ export { isJsonSchema, isTypeBoxSchema, isZodSchema, parseData, type ValidationResult, validate } from './validate';
@@ -33,7 +33,7 @@ export function toJsonSchema(schema: TypeSchema): JsonSchemaDef {
33
33
  // prefer nullable
34
34
  match(js)
35
35
  .with({ anyOf: [P.select(), { type: 'null' }] }, (select) => {
36
- delete js['anyOf'];
36
+ delete js.anyOf;
37
37
  Object.assign(js, select);
38
38
  js.nullable = true;
39
39
  })
@@ -70,9 +70,9 @@ function visit(js: JsonSchemaDef, f: (js: JsonSchemaDef) => void) {
70
70
  const _visit = (
71
71
  js: JsonSchemaDef,
72
72
  f: (js: JsonSchemaDef) => void,
73
- parent: JsonSchemaDef | undefined,
73
+ _parent: JsonSchemaDef | undefined,
74
74
  path: string[],
75
- k?: string,
75
+ _k?: string,
76
76
  ) => {
77
77
  if (!js) {
78
78
  return;
@@ -109,9 +109,9 @@ function visit(js: JsonSchemaDef, f: (js: JsonSchemaDef) => void) {
109
109
  _visit(js, f, undefined, []);
110
110
  }
111
111
 
112
- function resolveJsonSchemaDef(
112
+ function _resolveJsonSchemaDef(
113
113
  js: JsonSchemaDef,
114
- ctx?: {
114
+ _ctx?: {
115
115
  parent: JsonSchemaDef;
116
116
  key: string;
117
117
  },
@@ -129,7 +129,7 @@ function resolveJsonSchemaDef(
129
129
  for (const key in schema.properties) {
130
130
  const prop = schema.properties[key];
131
131
  if (prop) {
132
- schema.properties[key] = resolveJsonSchemaDef(prop, { parent: schema, key });
132
+ schema.properties[key] = _resolveJsonSchemaDef(prop, { parent: schema, key });
133
133
  }
134
134
  }
135
135
  return schema;
@@ -1,4 +1,4 @@
1
- import { Kind as TypeBoxKind, type TSchema } from '@sinclair/typebox';
1
+ import { type TSchema, Kind as TypeBoxKind } from '@sinclair/typebox';
2
2
  import '@sinclair/typebox';
3
3
  import { TypeCompiler } from '@sinclair/typebox/compiler';
4
4
  import { ifPresent } from '@wener/utils';
@@ -107,7 +107,7 @@ export function parseData<S extends TypeSchema>(schema: S, data: unknown): Schem
107
107
  );
108
108
  }
109
109
 
110
- function formatIssues(schema: TypeSchema, issues: Array<ValidationIssue>): string {
110
+ function _formatIssues(_schema: TypeSchema, _issues: Array<ValidationIssue>): string {
111
111
  return '';
112
112
  }
113
113
 
@@ -1,5 +1,5 @@
1
1
  import { forEachJsonSchema, type JsonSchemaDef } from '../jsonschema';
2
- import { toJsonSchema, type TypeSchema } from '../schema';
2
+ import { type TypeSchema, toJsonSchema } from '../schema';
3
3
 
4
4
  export const RedactedText = '[redacted]';
5
5
 
@@ -60,10 +60,10 @@ export function buildRedactorFormSchema(
60
60
  };
61
61
  }
62
62
 
63
- function buildReversibleRedactText({
63
+ function _buildReversibleRedactText({
64
64
  id,
65
- type,
66
- key,
65
+ type: _type,
66
+ key: _key,
67
67
  timestamp,
68
68
  }: {
69
69
  id?: string | number;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Format a number, removing trailing zeros
3
+ * @param value - number or string convertible to number
4
+ * @param decimals - decimal places to keep, default 2
5
+ *
6
+ * @example
7
+ * formatNumber(1.50) // "1.5"
8
+ * formatNumber(1.00) // "1"
9
+ * formatNumber(1.234) // "1.23"
10
+ */
11
+ export function formatNumber(value: number | string, decimals = 2): string {
12
+ const num = typeof value === 'string' ? Number.parseFloat(value) : value;
13
+ if (Number.isNaN(num)) return String(value);
14
+ return num
15
+ .toFixed(decimals)
16
+ .replace(/(\.\d*?)0+$/, '$1')
17
+ .replace(/\.$/, '');
18
+ }
@@ -0,0 +1,17 @@
1
+ import { formatNumber } from './formatNumber';
2
+
3
+ /**
4
+ * Format a percentage, removing trailing zeros
5
+ * @param value - number (0-1 or 0-100)
6
+ * @param decimals - decimal places to keep, default 2
7
+ * @param isRatio - whether value is a ratio (0-1), default false
8
+ *
9
+ * @example
10
+ * formatPercent(0.5, 2, true) // "50"
11
+ * formatPercent(50.00) // "50"
12
+ * formatPercent(33.33) // "33.33"
13
+ */
14
+ export function formatPercent(value: number, decimals = 2, isRatio = false): string {
15
+ const percent = isRatio ? value * 100 : value;
16
+ return formatNumber(percent, decimals);
17
+ }
@@ -1,5 +1,5 @@
1
- export { getEstimateProcessTime } from './getEstimateProcessTime';
1
+ export { buildBaseUrl } from './buildBaseUrl';
2
2
 
3
3
  export { buildRedactorFormSchema } from './buildRedactorFormSchema';
4
-
5
- export { buildBaseUrl } from './buildBaseUrl';
4
+ export { formatNumber } from './formatNumber';
5
+ export { getEstimateProcessTime } from './getEstimateProcessTime';
@@ -1,4 +1,4 @@
1
- import { maybeFunction, type MaybeFunction } from '@wener/utils';
1
+ import { type MaybeFunction, maybeFunction } from '@wener/utils';
2
2
 
3
3
  export function resolveFeatureOptions<T>(
4
4
  value: boolean | T | undefined | null,