@wener/common 2.0.2 → 2.0.5

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 (410) hide show
  1. package/lib/ai/qwen3vl/index.js +2 -0
  2. package/lib/ai/qwen3vl/index.js.map +1 -0
  3. package/lib/ai/qwen3vl/utils.js +31 -0
  4. package/lib/ai/qwen3vl/utils.js.map +1 -0
  5. package/lib/ai/vision/DocLayoutElementTypeSchema.js +28 -0
  6. package/lib/ai/vision/DocLayoutElementTypeSchema.js.map +1 -0
  7. package/lib/ai/vision/ImageAnnotationSchema.js +50 -0
  8. package/lib/ai/vision/ImageAnnotationSchema.js.map +1 -0
  9. package/lib/ai/vision/index.js +3 -0
  10. package/lib/ai/vision/index.js.map +1 -0
  11. package/lib/ai/vision/resolveImageAnnotation.js +105 -0
  12. package/lib/ai/vision/resolveImageAnnotation.js.map +1 -0
  13. package/lib/cn/ChineseResidentIdNo.js +22 -15
  14. package/lib/cn/ChineseResidentIdNo.js.map +1 -0
  15. package/lib/cn/ChineseResidentIdNo.test.js +1 -1
  16. package/lib/cn/DivisionCode.js +30 -25
  17. package/lib/cn/DivisionCode.js.map +1 -0
  18. package/lib/cn/DivisionCode.test.js +1 -1
  19. package/lib/cn/Mod11.js +38 -81
  20. package/lib/cn/Mod11.js.map +1 -0
  21. package/lib/cn/Mod31.js +41 -90
  22. package/lib/cn/Mod31.js.map +1 -0
  23. package/lib/cn/UnifiedSocialCreditCode.js +43 -34
  24. package/lib/cn/UnifiedSocialCreditCode.js.map +1 -0
  25. package/lib/cn/UnifiedSocialCreditCode.test.js +1 -1
  26. package/lib/cn/formatChineseAmount.js +77 -0
  27. package/lib/cn/formatChineseAmount.js.map +1 -0
  28. package/lib/cn/index.js +7 -1
  29. package/lib/cn/index.js.map +1 -0
  30. package/lib/cn/parseChineseNumber.js +94 -0
  31. package/lib/cn/parseChineseNumber.js.map +1 -0
  32. package/lib/cn/parseChineseNumber.test.js +278 -0
  33. package/lib/cn/pinyin/cartesianProduct.js +22 -0
  34. package/lib/cn/pinyin/cartesianProduct.js.map +1 -0
  35. package/lib/cn/pinyin/cartesianProduct.test.js +179 -0
  36. package/lib/cn/pinyin/data.json +23573 -0
  37. package/lib/cn/pinyin/loader.js +14 -0
  38. package/lib/cn/pinyin/loader.js.map +1 -0
  39. package/lib/cn/pinyin/preload.js +3 -0
  40. package/lib/cn/pinyin/preload.js.map +1 -0
  41. package/lib/cn/pinyin/toPinyin.test.js +167 -0
  42. package/lib/cn/pinyin/toPinyinPure.js +33 -0
  43. package/lib/cn/pinyin/toPinyinPure.js.map +1 -0
  44. package/lib/cn/pinyin/transform.js +14 -0
  45. package/lib/cn/pinyin/transform.js.map +1 -0
  46. package/lib/cn/types.d.js +2 -0
  47. package/lib/cn/types.d.js.map +1 -0
  48. package/lib/consola/createStandardConsolaReporter.js +6 -6
  49. package/lib/consola/createStandardConsolaReporter.js.map +1 -0
  50. package/lib/consola/formatLogObject.js +66 -146
  51. package/lib/consola/formatLogObject.js.map +1 -0
  52. package/lib/consola/formatLogObject.test.js +184 -0
  53. package/lib/consola/index.js +1 -0
  54. package/lib/consola/index.js.map +1 -0
  55. package/lib/data/formatSort.js +6 -5
  56. package/lib/data/formatSort.js.map +1 -0
  57. package/lib/data/index.js +1 -0
  58. package/lib/data/index.js.map +1 -0
  59. package/lib/data/maybeNumber.js +6 -8
  60. package/lib/data/maybeNumber.js.map +1 -0
  61. package/lib/data/parseSort.js +22 -28
  62. package/lib/data/parseSort.js.map +1 -0
  63. package/lib/data/resolvePagination.js +13 -17
  64. package/lib/data/resolvePagination.js.map +1 -0
  65. package/lib/data/types.d.js +2 -0
  66. package/lib/data/types.d.js.map +1 -0
  67. package/lib/dayjs/dayjs.js +21 -19
  68. package/lib/dayjs/dayjs.js.map +1 -0
  69. package/lib/dayjs/formatDuration.js +15 -14
  70. package/lib/dayjs/formatDuration.js.map +1 -0
  71. package/lib/dayjs/index.js +2 -0
  72. package/lib/dayjs/index.js.map +1 -0
  73. package/lib/dayjs/parseDuration.js +5 -8
  74. package/lib/dayjs/parseDuration.js.map +1 -0
  75. package/lib/dayjs/parseRelativeTime.js +90 -0
  76. package/lib/dayjs/parseRelativeTime.js.map +1 -0
  77. package/lib/dayjs/parseRelativeTime.test.js +247 -0
  78. package/lib/dayjs/resolveRelativeTime.js +87 -0
  79. package/lib/dayjs/resolveRelativeTime.js.map +1 -0
  80. package/lib/dayjs/resolveRelativeTime.test.js +310 -0
  81. package/lib/decimal/index.js +1 -0
  82. package/lib/decimal/index.js.map +1 -0
  83. package/lib/decimal/parseDecimal.js +3 -1
  84. package/lib/decimal/parseDecimal.js.map +1 -0
  85. package/lib/drain3/Drain.js +356 -0
  86. package/lib/drain3/Drain.js.map +1 -0
  87. package/lib/drain3/LogCluster.js +38 -0
  88. package/lib/drain3/LogCluster.js.map +1 -0
  89. package/lib/drain3/Node.js +39 -0
  90. package/lib/drain3/Node.js.map +1 -0
  91. package/lib/drain3/TemplateMiner.js +204 -0
  92. package/lib/drain3/TemplateMiner.js.map +1 -0
  93. package/lib/drain3/index.js +31 -0
  94. package/lib/drain3/index.js.map +1 -0
  95. package/lib/drain3/persistence/FilePersistence.js +24 -0
  96. package/lib/drain3/persistence/FilePersistence.js.map +1 -0
  97. package/lib/drain3/persistence/MemoryPersistence.js +18 -0
  98. package/lib/drain3/persistence/MemoryPersistence.js.map +1 -0
  99. package/lib/drain3/persistence/PersistenceHandler.js +5 -0
  100. package/lib/drain3/persistence/PersistenceHandler.js.map +1 -0
  101. package/lib/drain3/types.js +7 -0
  102. package/lib/drain3/types.js.map +1 -0
  103. package/lib/emittery/emitter.js +10 -0
  104. package/lib/emittery/emitter.js.map +1 -0
  105. package/lib/emittery/index.js +2 -0
  106. package/lib/emittery/index.js.map +1 -0
  107. package/lib/foundation/schema/SexType.js +5 -3
  108. package/lib/foundation/schema/SexType.js.map +1 -0
  109. package/lib/foundation/schema/index.js +1 -0
  110. package/lib/foundation/schema/index.js.map +1 -0
  111. package/lib/foundation/schema/parseSexType.js +1 -0
  112. package/lib/foundation/schema/parseSexType.js.map +1 -0
  113. package/lib/foundation/schema/types.js +4 -2
  114. package/lib/foundation/schema/types.js.map +1 -0
  115. package/lib/fs/FileSystemError.js +23 -0
  116. package/lib/fs/FileSystemError.js.map +1 -0
  117. package/lib/fs/IFileSystem.d.js +3 -0
  118. package/lib/fs/IFileSystem.d.js.map +1 -0
  119. package/lib/fs/MemoryFileSystem.test.js +188 -0
  120. package/lib/fs/createBrowserFileSystem.js +250 -0
  121. package/lib/fs/createBrowserFileSystem.js.map +1 -0
  122. package/lib/fs/createMemoryFileSystem.js +517 -0
  123. package/lib/fs/createMemoryFileSystem.js.map +1 -0
  124. package/lib/fs/createSandboxFileSystem.js +108 -0
  125. package/lib/fs/createSandboxFileSystem.js.map +1 -0
  126. package/lib/fs/createWebDavFileSystem.js +154 -0
  127. package/lib/fs/createWebDavFileSystem.js.map +1 -0
  128. package/lib/fs/createWebFileSystem.js +225 -0
  129. package/lib/fs/createWebFileSystem.js.map +1 -0
  130. package/lib/fs/findMimeType.js +17 -0
  131. package/lib/fs/findMimeType.js.map +1 -0
  132. package/lib/fs/index.js +8 -0
  133. package/lib/fs/index.js.map +1 -0
  134. package/lib/fs/minio/createMinioFileSystem.js +974 -0
  135. package/lib/fs/minio/createMinioFileSystem.js.map +1 -0
  136. package/lib/fs/minio/index.js +2 -0
  137. package/lib/fs/minio/index.js.map +1 -0
  138. package/lib/fs/orpc/FileSystemContract.js +93 -0
  139. package/lib/fs/orpc/FileSystemContract.js.map +1 -0
  140. package/lib/fs/orpc/createContractClientFileSystem.js +93 -0
  141. package/lib/fs/orpc/createContractClientFileSystem.js.map +1 -0
  142. package/lib/fs/orpc/index.js +3 -0
  143. package/lib/fs/orpc/index.js.map +1 -0
  144. package/lib/fs/orpc/server/createFileSystemContractImpl.js +63 -0
  145. package/lib/fs/orpc/server/createFileSystemContractImpl.js.map +1 -0
  146. package/lib/fs/orpc/server/index.js +2 -0
  147. package/lib/fs/orpc/server/index.js.map +1 -0
  148. package/lib/fs/s3/createS3MiniFileSystem.js +753 -0
  149. package/lib/fs/s3/createS3MiniFileSystem.js.map +1 -0
  150. package/lib/fs/s3/index.js +2 -0
  151. package/lib/fs/s3/index.js.map +1 -0
  152. package/lib/fs/s3/s3mini.test.js +584 -0
  153. package/lib/fs/scandir.js +59 -0
  154. package/lib/fs/scandir.js.map +1 -0
  155. package/lib/fs/server/createDatabaseFileSystem.js +750 -0
  156. package/lib/fs/server/createDatabaseFileSystem.js.map +1 -0
  157. package/lib/fs/server/createNodeFileSystem.js +426 -0
  158. package/lib/fs/server/createNodeFileSystem.js.map +1 -0
  159. package/lib/fs/server/dbfs.test.js +221 -0
  160. package/lib/fs/server/index.js +2 -0
  161. package/lib/fs/server/index.js.map +1 -0
  162. package/lib/fs/server/loadTestDatabase.js +127 -0
  163. package/lib/fs/server/loadTestDatabase.js.map +1 -0
  164. package/lib/fs/tests/runFileSystemTest.js +319 -0
  165. package/lib/fs/tests/runFileSystemTest.js.map +1 -0
  166. package/lib/fs/types.js +27 -0
  167. package/lib/fs/types.js.map +1 -0
  168. package/lib/fs/utils/getFileUrl.js +35 -0
  169. package/lib/fs/utils/getFileUrl.js.map +1 -0
  170. package/lib/fs/utils.js +22 -0
  171. package/lib/fs/utils.js.map +1 -0
  172. package/lib/fs/webdav/index.js +2 -0
  173. package/lib/fs/webdav/index.js.map +1 -0
  174. package/lib/index.js +1 -0
  175. package/lib/index.js.map +1 -0
  176. package/lib/jsonschema/JsonSchema.js +146 -172
  177. package/lib/jsonschema/JsonSchema.js.map +1 -0
  178. package/lib/jsonschema/forEachJsonSchema.js +44 -0
  179. package/lib/jsonschema/forEachJsonSchema.js.map +1 -0
  180. package/lib/jsonschema/index.js +2 -0
  181. package/lib/jsonschema/index.js.map +1 -0
  182. package/lib/jsonschema/types.d.js +2 -0
  183. package/lib/jsonschema/types.d.js.map +1 -0
  184. package/lib/meta/defineFileType.js +20 -103
  185. package/lib/meta/defineFileType.js.map +1 -0
  186. package/lib/meta/defineInit.js +31 -250
  187. package/lib/meta/defineInit.js.map +1 -0
  188. package/lib/meta/defineMetadata.js +24 -140
  189. package/lib/meta/defineMetadata.js.map +1 -0
  190. package/lib/meta/index.js +1 -0
  191. package/lib/meta/index.js.map +1 -0
  192. package/lib/orpc/createOpenApiContractClient.js +27 -0
  193. package/lib/orpc/createOpenApiContractClient.js.map +1 -0
  194. package/lib/orpc/createRpcContractClient.js +34 -0
  195. package/lib/orpc/createRpcContractClient.js.map +1 -0
  196. package/lib/orpc/index.js +3 -0
  197. package/lib/orpc/index.js.map +1 -0
  198. package/lib/orpc/resolveLinkPlugins.js +28 -0
  199. package/lib/orpc/resolveLinkPlugins.js.map +1 -0
  200. package/lib/password/PHC.js +63 -87
  201. package/lib/password/PHC.js.map +1 -0
  202. package/lib/password/PHC.test.js +11 -3
  203. package/lib/password/Password.js +29 -294
  204. package/lib/password/Password.js.map +1 -0
  205. package/lib/password/Password.test.js +35 -22
  206. package/lib/password/createArgon2PasswordAlgorithm.js +35 -191
  207. package/lib/password/createArgon2PasswordAlgorithm.js.map +1 -0
  208. package/lib/password/createBase64PasswordAlgorithm.js +8 -141
  209. package/lib/password/createBase64PasswordAlgorithm.js.map +1 -0
  210. package/lib/password/createBcryptPasswordAlgorithm.js +13 -168
  211. package/lib/password/createBcryptPasswordAlgorithm.js.map +1 -0
  212. package/lib/password/createPBKDF2PasswordAlgorithm.js +46 -228
  213. package/lib/password/createPBKDF2PasswordAlgorithm.js.map +1 -0
  214. package/lib/password/createScryptPasswordAlgorithm.js +55 -211
  215. package/lib/password/createScryptPasswordAlgorithm.js.map +1 -0
  216. package/lib/password/index.js +1 -0
  217. package/lib/password/index.js.map +1 -0
  218. package/lib/password/server/index.js +1 -0
  219. package/lib/password/server/index.js.map +1 -0
  220. package/lib/resource/Identifiable.js +2 -0
  221. package/lib/resource/Identifiable.js.map +1 -0
  222. package/lib/resource/ListQuery.js +21 -93
  223. package/lib/resource/ListQuery.js.map +1 -0
  224. package/lib/resource/getTitleOfResource.js +3 -5
  225. package/lib/resource/getTitleOfResource.js.map +1 -0
  226. package/lib/resource/index.js +1 -0
  227. package/lib/resource/index.js.map +1 -0
  228. package/lib/resource/schema/AnyResourceSchema.js +2 -1
  229. package/lib/resource/schema/AnyResourceSchema.js.map +1 -0
  230. package/lib/resource/schema/BaseResourceSchema.js +2 -1
  231. package/lib/resource/schema/BaseResourceSchema.js.map +1 -0
  232. package/lib/resource/schema/ResourceActionType.js +6 -4
  233. package/lib/resource/schema/ResourceActionType.js.map +1 -0
  234. package/lib/resource/schema/ResourceStatus.js +5 -3
  235. package/lib/resource/schema/ResourceStatus.js.map +1 -0
  236. package/lib/resource/schema/ResourceType.js +5 -3
  237. package/lib/resource/schema/ResourceType.js.map +1 -0
  238. package/lib/resource/schema/index.js +1 -0
  239. package/lib/resource/schema/index.js.map +1 -0
  240. package/lib/resource/schema/types.js +16 -20
  241. package/lib/resource/schema/types.js.map +1 -0
  242. package/lib/s3/formatS3Url.js +65 -0
  243. package/lib/s3/formatS3Url.js.map +1 -0
  244. package/lib/s3/formatS3Url.test.js +262 -0
  245. package/lib/s3/index.js +3 -0
  246. package/lib/s3/index.js.map +1 -0
  247. package/lib/s3/parseS3Url.js +65 -0
  248. package/lib/s3/parseS3Url.js.map +1 -0
  249. package/lib/s3/parseS3Url.test.js +270 -0
  250. package/lib/schema/SchemaRegistry.js +38 -38
  251. package/lib/schema/SchemaRegistry.js.map +1 -0
  252. package/lib/schema/TypeSchema.d.js +2 -0
  253. package/lib/schema/TypeSchema.d.js.map +1 -0
  254. package/lib/schema/createSchemaData.js +26 -125
  255. package/lib/schema/createSchemaData.js.map +1 -0
  256. package/lib/schema/findJsonSchemaByPath.js +13 -36
  257. package/lib/schema/findJsonSchemaByPath.js.map +1 -0
  258. package/lib/schema/formatZodError.js +138 -0
  259. package/lib/schema/formatZodError.js.map +1 -0
  260. package/lib/schema/formatZodError.test.js +196 -0
  261. package/lib/schema/getSchemaCache.js +5 -5
  262. package/lib/schema/getSchemaCache.js.map +1 -0
  263. package/lib/schema/getSchemaOptions.js +8 -11
  264. package/lib/schema/getSchemaOptions.js.map +1 -0
  265. package/lib/schema/index.js +2 -1
  266. package/lib/schema/index.js.map +1 -0
  267. package/lib/schema/toJsonSchema.js +50 -293
  268. package/lib/schema/toJsonSchema.js.map +1 -0
  269. package/lib/schema/validate.js +34 -46
  270. package/lib/schema/validate.js.map +1 -0
  271. package/lib/tools/generateSchema.js +39 -197
  272. package/lib/tools/generateSchema.js.map +1 -0
  273. package/lib/tools/renderJsonSchemaToMarkdownDoc.js +55 -143
  274. package/lib/tools/renderJsonSchemaToMarkdownDoc.js.map +1 -0
  275. package/lib/utils/buildBaseUrl.js +13 -0
  276. package/lib/utils/buildBaseUrl.js.map +1 -0
  277. package/lib/utils/buildRedactorFormSchema.js +59 -0
  278. package/lib/utils/buildRedactorFormSchema.js.map +1 -0
  279. package/lib/utils/getEstimateProcessTime.js +12 -11
  280. package/lib/utils/getEstimateProcessTime.js.map +1 -0
  281. package/lib/utils/index.js +3 -0
  282. package/lib/utils/index.js.map +1 -0
  283. package/lib/utils/resolveFeatureOptions.js +12 -0
  284. package/lib/utils/resolveFeatureOptions.js.map +1 -0
  285. package/package.json +80 -13
  286. package/src/ai/qwen3vl/index.ts +1 -0
  287. package/src/ai/qwen3vl/utils.ts +36 -0
  288. package/src/ai/vision/DocLayoutElementTypeSchema.ts +30 -0
  289. package/src/ai/vision/ImageAnnotationSchema.ts +60 -0
  290. package/src/ai/vision/index.ts +2 -0
  291. package/src/ai/vision/resolveImageAnnotation.ts +135 -0
  292. package/src/cn/ChineseResidentIdNo.test.ts +1 -1
  293. package/src/cn/ChineseResidentIdNo.ts +9 -1
  294. package/src/cn/DivisionCode.test.ts +1 -1
  295. package/src/cn/DivisionCode.ts +8 -0
  296. package/src/cn/Mod11.ts +1 -1
  297. package/src/cn/UnifiedSocialCreditCode.test.ts +1 -1
  298. package/src/cn/UnifiedSocialCreditCode.ts +15 -0
  299. package/src/cn/__snapshots__/ChineseResidentIdNo.test.ts.snap +1 -1
  300. package/src/cn/formatChineseAmount.ts +61 -0
  301. package/src/cn/index.ts +7 -1
  302. package/src/cn/parseChineseNumber.test.ts +159 -0
  303. package/src/cn/parseChineseNumber.ts +97 -0
  304. package/src/cn/pinyin/cartesianProduct.test.ts +64 -0
  305. package/src/cn/pinyin/cartesianProduct.ts +24 -0
  306. package/src/cn/pinyin/data.json +23573 -0
  307. package/src/cn/pinyin/loader.ts +12 -0
  308. package/src/cn/pinyin/preload.ts +3 -0
  309. package/src/cn/pinyin/toPinyin.test.ts +12 -0
  310. package/src/cn/pinyin/toPinyinPure.ts +43 -0
  311. package/src/cn/pinyin/transform.ts +12 -0
  312. package/src/consola/formatLogObject.test.ts +27 -0
  313. package/src/consola/formatLogObject.ts +40 -12
  314. package/src/data/maybeNumber.ts +1 -1
  315. package/src/data/parseSort.test.ts +0 -1
  316. package/src/data/types.d.ts +2 -2
  317. package/src/dayjs/dayjs.ts +18 -18
  318. package/src/dayjs/formatDuration.ts +2 -2
  319. package/src/dayjs/index.ts +3 -1
  320. package/src/dayjs/parseRelativeTime.test.ts +185 -0
  321. package/src/dayjs/parseRelativeTime.ts +115 -0
  322. package/src/dayjs/resolveRelativeTime.test.ts +357 -0
  323. package/src/dayjs/resolveRelativeTime.ts +164 -0
  324. package/src/drain3/Drain.test.ts +378 -0
  325. package/src/drain3/Drain.ts +394 -0
  326. package/src/drain3/LogCluster.ts +46 -0
  327. package/src/drain3/Node.ts +53 -0
  328. package/src/drain3/TemplateMiner.ts +246 -0
  329. package/src/drain3/index.ts +36 -0
  330. package/src/drain3/persistence/FilePersistence.ts +24 -0
  331. package/src/drain3/persistence/MemoryPersistence.ts +23 -0
  332. package/src/drain3/persistence/PersistenceHandler.ts +19 -0
  333. package/src/drain3/types.ts +75 -0
  334. package/src/emittery/emitter.ts +9 -0
  335. package/src/emittery/index.ts +1 -0
  336. package/src/fs/FileSystemError.ts +26 -0
  337. package/src/fs/IFileSystem.d.ts +101 -0
  338. package/src/fs/MemoryFileSystem.test.ts +37 -0
  339. package/src/fs/createBrowserFileSystem.ts +293 -0
  340. package/src/fs/createMemoryFileSystem.ts +600 -0
  341. package/src/fs/createSandboxFileSystem.ts +136 -0
  342. package/src/fs/createWebDavFileSystem.ts +190 -0
  343. package/src/fs/createWebFileSystem.ts +242 -0
  344. package/src/fs/findMimeType.ts +20 -0
  345. package/src/fs/index.ts +8 -0
  346. package/src/fs/minio/createMinioFileSystem.ts +1148 -0
  347. package/src/fs/minio/index.ts +1 -0
  348. package/src/fs/orpc/FileSystemContract.ts +92 -0
  349. package/src/fs/orpc/createContractClientFileSystem.ts +115 -0
  350. package/src/fs/orpc/index.ts +2 -0
  351. package/src/fs/orpc/server/createFileSystemContractImpl.ts +64 -0
  352. package/src/fs/orpc/server/index.ts +1 -0
  353. package/src/fs/s3/createS3MiniFileSystem.ts +871 -0
  354. package/src/fs/s3/index.ts +1 -0
  355. package/src/fs/s3/s3fs.test.ts +441 -0
  356. package/src/fs/s3/s3mini.test.ts +264 -0
  357. package/src/fs/scandir.ts +75 -0
  358. package/src/fs/server/createDatabaseFileSystem.ts +668 -0
  359. package/src/fs/server/createNodeFileSystem.ts +518 -0
  360. package/src/fs/server/dbfs.test.ts +48 -0
  361. package/src/fs/server/index.ts +1 -0
  362. package/src/fs/server/loadTestDatabase.ts +131 -0
  363. package/src/fs/tests/runFileSystemTest.ts +289 -0
  364. package/src/fs/types.ts +29 -0
  365. package/src/fs/utils/getFileUrl.ts +44 -0
  366. package/src/fs/utils.ts +23 -0
  367. package/src/fs/webdav/index.ts +1 -0
  368. package/src/jsonschema/JsonSchema.ts +118 -110
  369. package/src/jsonschema/forEachJsonSchema.ts +50 -0
  370. package/src/jsonschema/index.ts +1 -0
  371. package/src/jsonschema/types.d.ts +1 -1
  372. package/src/meta/defineMetadata.ts +1 -1
  373. package/src/orpc/createOpenApiContractClient.ts +52 -0
  374. package/src/orpc/createRpcContractClient.ts +50 -0
  375. package/src/orpc/index.ts +2 -0
  376. package/src/orpc/resolveLinkPlugins.ts +29 -0
  377. package/src/password/PHC.ts +6 -6
  378. package/src/password/Password.test.ts +1 -1
  379. package/src/password/createArgon2PasswordAlgorithm.ts +1 -1
  380. package/src/password/createBase64PasswordAlgorithm.ts +2 -2
  381. package/src/password/createBcryptPasswordAlgorithm.ts +4 -2
  382. package/src/password/createPBKDF2PasswordAlgorithm.ts +4 -4
  383. package/src/password/createScryptPasswordAlgorithm.ts +4 -4
  384. package/src/resource/ListQuery.ts +4 -1
  385. package/src/resource/index.ts +2 -2
  386. package/src/resource/schema/AnyResourceSchema.ts +16 -2
  387. package/src/s3/formatS3Url.test.ts +254 -0
  388. package/src/s3/formatS3Url.ts +84 -0
  389. package/src/s3/index.ts +2 -0
  390. package/src/s3/parseS3Url.test.ts +258 -0
  391. package/src/s3/parseS3Url.ts +88 -0
  392. package/src/schema/SchemaRegistry.ts +35 -33
  393. package/src/schema/TypeSchema.d.ts +6 -6
  394. package/src/schema/createSchemaData.ts +4 -4
  395. package/src/schema/findJsonSchemaByPath.ts +4 -4
  396. package/src/schema/formatZodError.test.ts +197 -0
  397. package/src/schema/formatZodError.ts +139 -0
  398. package/src/schema/getSchemaOptions.ts +2 -2
  399. package/src/schema/index.ts +1 -1
  400. package/src/schema/toJsonSchema.ts +6 -6
  401. package/src/schema/validate.ts +1 -1
  402. package/src/utils/buildBaseUrl.ts +12 -0
  403. package/src/utils/buildRedactorFormSchema.ts +85 -0
  404. package/src/utils/index.ts +4 -0
  405. package/src/utils/resolveFeatureOptions.ts +14 -0
  406. package/src/cn/ChineseResidentIdNo.mod.ts +0 -7
  407. package/src/cn/DivisionCode.mod.ts +0 -7
  408. package/src/cn/UnifiedSocialCreditCode.mod.ts +0 -7
  409. package/src/cn/mod.ts +0 -3
  410. package/src/schema/SchemaRegistry.mod.ts +0 -1
@@ -0,0 +1,289 @@
1
+ import { expect } from 'vitest';
2
+ import { FileSystemError, FileSystemErrorCode } from '../FileSystemError';
3
+ import type { IFileSystem, IServerFileSystem } from '../IFileSystem';
4
+
5
+ export type RunFileSystemTestOptions = {
6
+ writableStream?: boolean;
7
+ readableStream?: boolean;
8
+ readStream?: boolean;
9
+ writeStream?: boolean;
10
+ abort?: boolean;
11
+ };
12
+
13
+ export async function runFileSystemTest(fs: IFileSystem | IServerFileSystem, options: RunFileSystemTestOptions = {}) {
14
+ const { writableStream = true, readableStream = true, readStream = true, writeStream = true, abort = true } = options;
15
+ // should be implemented
16
+ const stat = await fs.stat('/README.txt');
17
+ expect(stat).toMatchObject({
18
+ path: '/README.txt',
19
+ directory: '/',
20
+ name: 'README.txt',
21
+ kind: 'file',
22
+ size: 5,
23
+ });
24
+ await fs.mkdir('/');
25
+ const entries = await fs.readdir('/');
26
+ expect(entries.some((e) => e.name === 'README.txt')).toBe(true);
27
+ await fs.mkdir('/test');
28
+
29
+ if (fs.getUrl) {
30
+ expect(fs.getUrl(await fs.stat('/README.txt'))).toBeTypeOf('string');
31
+ }
32
+
33
+ // should handle AbortSignal
34
+ if (abort) {
35
+ const controller = new AbortController();
36
+ controller.abort();
37
+
38
+ await expect(fs.stat('/README.txt', { signal: controller.signal })).rejects.toThrow(Error);
39
+ await expect(fs.readdir('/', { signal: controller.signal })).rejects.toThrow(Error);
40
+ await expect(fs.mkdir('/test', { signal: controller.signal })).rejects.toThrow(Error);
41
+ await expect(fs.readFile('/README.txt', { signal: controller.signal })).rejects.toThrow(Error);
42
+ await expect(fs.writeFile('/test.txt', 'test', { signal: controller.signal })).rejects.toThrow(Error);
43
+ await expect(fs.rm('/README.txt', { signal: controller.signal })).rejects.toThrow(Error);
44
+ await expect(fs.rename('/README.txt', '/new.txt', { signal: controller.signal })).rejects.toThrow(Error);
45
+ await expect(fs.copy('/README.txt', '/copy.txt', { signal: controller.signal })).rejects.toThrow(Error);
46
+ }
47
+
48
+ // should validate input parameters
49
+ await expect(fs.stat('')).rejects.toThrow(FileSystemError);
50
+ await expect(fs.stat('')).rejects.toMatchObject({ code: FileSystemErrorCode.EINVAL });
51
+ await expect(fs.stat(null as any)).rejects.toThrow(FileSystemError);
52
+ await expect(fs.stat(null as any)).rejects.toMatchObject({ code: FileSystemErrorCode.EINVAL });
53
+ await expect(fs.stat(undefined as any)).rejects.toThrow(FileSystemError);
54
+ await expect(fs.stat(undefined as any)).rejects.toMatchObject({ code: FileSystemErrorCode.EINVAL });
55
+ await expect(fs.stat(123 as any)).rejects.toThrow(FileSystemError);
56
+ await expect(fs.stat(123 as any)).rejects.toMatchObject({ code: FileSystemErrorCode.EINVAL });
57
+
58
+ await expect(fs.writeFile('', 'test')).rejects.toThrow(FileSystemError);
59
+ await expect(fs.writeFile('', 'test')).rejects.toMatchObject({ code: FileSystemErrorCode.EINVAL });
60
+ await expect(fs.writeFile('/test', null as any)).rejects.toThrow(FileSystemError);
61
+ await expect(fs.writeFile('/test', null as any)).rejects.toMatchObject({ code: FileSystemErrorCode.EINVAL });
62
+ await expect(fs.writeFile('/test', undefined as any)).rejects.toThrow(FileSystemError);
63
+ await expect(fs.writeFile('/test', undefined as any)).rejects.toMatchObject({ code: FileSystemErrorCode.EINVAL });
64
+ await expect(fs.writeFile('/', 'test')).rejects.toThrow(FileSystemError);
65
+ await expect(fs.writeFile('/', 'test')).rejects.toMatchObject({ code: FileSystemErrorCode.EINVAL });
66
+
67
+ // should support streaming operations
68
+ const serverFs = fs as IServerFileSystem;
69
+ if (readStream && 'createReadStream' in fs) {
70
+ await fs.writeFile('/stream.txt', 'Hello, World!');
71
+
72
+ // Test createReadStream
73
+ const readStreamObj = serverFs.createReadStream('/stream.txt');
74
+ expect(readStreamObj).toBeDefined();
75
+
76
+ const chunks: Buffer[] = [];
77
+ for await (const chunk of readStreamObj) {
78
+ chunks.push(chunk);
79
+ }
80
+ expect(Buffer.concat(chunks).toString()).toBe('Hello, World!');
81
+
82
+ // Test createReadStream with range
83
+ const rangeStream = serverFs.createReadStream('/stream.txt', { range: { start: 0, end: 4 } });
84
+ const rangeChunks: Buffer[] = [];
85
+ for await (const chunk of rangeStream) {
86
+ rangeChunks.push(chunk);
87
+ }
88
+ expect(Buffer.concat(rangeChunks).toString()).toBe('Hello');
89
+ }
90
+
91
+ if (writeStream && 'createWriteStream' in fs) {
92
+ // Test createWriteStream
93
+ const writeStreamObj = serverFs.createWriteStream('/write-test.txt');
94
+ expect(writeStreamObj).toBeDefined();
95
+
96
+ writeStreamObj.write('Test content');
97
+ writeStreamObj.end();
98
+
99
+ await new Promise((resolve) => writeStreamObj.on('finish', resolve));
100
+ expect(await fs.readFile('/write-test.txt', { encoding: 'text' })).toBe('Test content');
101
+ }
102
+
103
+ // should support Web Streams API
104
+ if (readableStream && fs.createReadableStream) {
105
+ await fs.writeFile('/webstream.txt', 'Web Stream Test');
106
+
107
+ // Test createReadableStream
108
+ const readableStreamObj = fs.createReadableStream('/webstream.txt');
109
+ expect(readableStreamObj).toBeDefined();
110
+
111
+ const reader = readableStreamObj.getReader();
112
+ const { value } = await reader.read();
113
+ expect(value?.toString()).toBe('Web Stream Test');
114
+ }
115
+
116
+ if (writableStream && fs.createWritableStream) {
117
+ // Test createWritableStream
118
+ const writableStreamObj = fs.createWritableStream('/web-write-test.txt');
119
+ expect(writableStreamObj).toBeDefined();
120
+
121
+ const writer = writableStreamObj.getWriter();
122
+ await writer.write(Buffer.from('Web Stream Write Test'));
123
+ await writer.close();
124
+
125
+ expect(await fs.readFile('/web-write-test.txt', { encoding: 'text' })).toBe('Web Stream Write Test');
126
+ }
127
+
128
+ // should handle streaming errors
129
+ if (abort && readStream && 'createReadStream' in fs) {
130
+ const controller2 = new AbortController();
131
+
132
+ // Test read stream with abort
133
+ const readStreamObj = serverFs.createReadStream('/README.txt', { signal: controller2.signal });
134
+ controller2.abort();
135
+
136
+ await expect(
137
+ new Promise((_, reject) => {
138
+ readStreamObj.on('error', reject);
139
+ }),
140
+ ).rejects.toThrow(Error);
141
+ }
142
+
143
+ if (abort && writeStream && 'createWriteStream' in fs) {
144
+ // Test write stream with abort
145
+ const controller3 = new AbortController();
146
+ const writeStreamObj = serverFs.createWriteStream('/abort-test.txt', { signal: controller3.signal });
147
+ controller3.abort();
148
+
149
+ await expect(
150
+ new Promise((_, reject) => {
151
+ writeStreamObj.on('error', reject);
152
+ writeStreamObj.write('test');
153
+ }),
154
+ ).rejects.toThrow(Error);
155
+ }
156
+
157
+ // should handle file operations correctly
158
+ // Test file creation
159
+ await fs.writeFile('/newfile.txt', 'New content');
160
+ expect(await fs.exists('/newfile.txt')).toBe(true);
161
+
162
+ const stat2 = await fs.stat('/newfile.txt');
163
+ expect(stat2.kind).toBe('file');
164
+ expect(stat2.size).toBe(11); // "New content" is 11 bytes
165
+
166
+ // Test file reading
167
+ const content = await fs.readFile('/newfile.txt', { encoding: 'text' });
168
+ expect(content).toBe('New content');
169
+
170
+ // Test file reading as binary
171
+ const binary = await fs.readFile('/newfile.txt');
172
+ expect(Buffer.from(binary).toString()).toBe('New content');
173
+
174
+ // Test file overwrite
175
+ await fs.writeFile('/newfile.txt', 'Updated content');
176
+ expect(await fs.readFile('/newfile.txt', { encoding: 'text' })).toBe('Updated content');
177
+
178
+ // Test file overwrite protection
179
+ await expect(fs.writeFile('/newfile.txt', 'Should fail', { overwrite: false })).rejects.toThrow(FileSystemError);
180
+ await expect(fs.writeFile('/newfile.txt', 'Should fail', { overwrite: false })).rejects.toMatchObject({
181
+ code: FileSystemErrorCode.EEXIST,
182
+ });
183
+
184
+ // Test large file write (should use file_node_content table)
185
+ // Create ~1KB data to test large file handling
186
+ const largeData = 'x'.repeat(1024); // 1KB of data
187
+ await fs.writeFile('/largefile.txt', largeData);
188
+ const largeFileStat = await fs.stat('/largefile.txt');
189
+ expect(largeFileStat.size).toBe(1024);
190
+ const largeFileContent = await fs.readFile('/largefile.txt', { encoding: 'text' });
191
+ expect(largeFileContent).toBe(largeData);
192
+ expect(largeFileContent.length).toBe(1024);
193
+
194
+ // should handle directory operations correctly
195
+ // Test directory creation
196
+ await fs.mkdir('/newdir');
197
+ expect(await fs.exists('/newdir')).toBe(true);
198
+
199
+ const stat3 = await fs.stat('/newdir');
200
+ expect(stat3.kind).toBe('directory');
201
+
202
+ // Test recursive directory creation
203
+ await fs.mkdir('/deep/nested/dir', { recursive: true });
204
+ expect(await fs.exists('/deep/nested/dir')).toBe(true);
205
+
206
+ // Test non-recursive directory creation failure
207
+ await expect(fs.mkdir('/another/deep/dir')).rejects.toThrow(FileSystemError);
208
+ await expect(fs.mkdir('/another/deep/dir')).rejects.toMatchObject({ code: FileSystemErrorCode.ENOENT });
209
+
210
+ // Test directory listing
211
+ await fs.writeFile('/newdir/file1.txt', 'File 1');
212
+ await fs.writeFile('/newdir/file2.txt', 'File 2');
213
+
214
+ const contents = await fs.readdir('/newdir');
215
+ expect(contents).toHaveLength(2);
216
+ expect(contents.map((f) => f.name)).toContain('file1.txt');
217
+ expect(contents.map((f) => f.name)).toContain('file2.txt');
218
+
219
+ // should handle file removal correctly
220
+ await fs.writeFile('/toremove.txt', 'Remove me');
221
+ expect(await fs.exists('/toremove.txt')).toBe(true);
222
+
223
+ await fs.rm('/toremove.txt');
224
+ expect(await fs.exists('/toremove.txt')).toBe(false);
225
+
226
+ // Test force removal
227
+ await expect(fs.rm('/nonexistent.txt')).rejects.toThrow(FileSystemError);
228
+ await expect(fs.rm('/nonexistent.txt')).rejects.toMatchObject({ code: FileSystemErrorCode.ENOENT });
229
+ await fs.rm('/nonexistent.txt', { force: true }); // Should not throw
230
+
231
+ // Test recursive removal
232
+ await fs.mkdir('/dirwithfiles', { recursive: true });
233
+ await fs.writeFile('/dirwithfiles/file.txt', 'content');
234
+ await expect(fs.rm('/dirwithfiles')).rejects.toThrow(FileSystemError);
235
+ await expect(fs.rm('/dirwithfiles')).rejects.toMatchObject({ code: FileSystemErrorCode.ENOTEMPTY });
236
+ await fs.rm('/dirwithfiles', { recursive: true });
237
+ expect(await fs.exists('/dirwithfiles')).toBe(false);
238
+
239
+ // should handle file rename correctly
240
+ await fs.writeFile('/rename.txt', 'Original content');
241
+ expect(await fs.exists('/rename.txt')).toBe(true);
242
+
243
+ await fs.rename('/rename.txt', '/renamed.txt');
244
+ expect(await fs.exists('/rename.txt')).toBe(false);
245
+ expect(await fs.exists('/renamed.txt')).toBe(true);
246
+ expect(await fs.readFile('/renamed.txt', { encoding: 'text' })).toBe('Original content');
247
+
248
+ // should handle file copy correctly
249
+ await fs.writeFile('/copy.txt', 'Copy me');
250
+ expect(await fs.exists('/copy.txt')).toBe(true);
251
+
252
+ await fs.copy('/copy.txt', '/copied.txt');
253
+ expect(await fs.exists('/copy.txt')).toBe(true);
254
+ expect(await fs.exists('/copied.txt')).toBe(true);
255
+ expect(await fs.readFile('/copied.txt', { encoding: 'text' })).toBe('Copy me');
256
+
257
+ // Test copy overwrite
258
+ await fs.writeFile('/target2.txt', 'Target content');
259
+ await expect(fs.copy('/copy.txt', '/target2.txt')).rejects.toThrow(FileSystemError);
260
+ await expect(fs.copy('/copy.txt', '/target2.txt')).rejects.toMatchObject({ code: FileSystemErrorCode.EEXIST });
261
+ await fs.copy('/copy.txt', '/target2.txt', { overwrite: true });
262
+ expect(await fs.readFile('/target2.txt', { encoding: 'text' })).toBe('Copy me');
263
+
264
+ // should handle edge cases correctly
265
+ // Test root directory operations
266
+ await expect(fs.stat('/')).resolves.toBeDefined();
267
+ await expect(fs.readdir('/')).resolves.toBeDefined();
268
+ await fs.mkdir('/'); // Should not throw
269
+
270
+ // Test path normalization
271
+ await fs.writeFile('/normalize.txt', 'test');
272
+ expect(await fs.exists('/normalize.txt')).toBe(true);
273
+ expect(await fs.exists('/./normalize.txt')).toBe(true);
274
+ // Note: the exists method may return true for files with trailing slashes due to normalization
275
+
276
+ // Test error cases
277
+ await expect(fs.stat('/nonexistent')).rejects.toThrow(FileSystemError);
278
+ await expect(fs.stat('/nonexistent')).rejects.toMatchObject({ code: FileSystemErrorCode.ENOENT });
279
+ await expect(fs.readdir('/nonexistent')).rejects.toThrow(FileSystemError);
280
+ await expect(fs.readdir('/nonexistent')).rejects.toMatchObject({ code: FileSystemErrorCode.ENOENT });
281
+ await expect(fs.readFile('/nonexistent')).rejects.toThrow(FileSystemError);
282
+ await expect(fs.readFile('/nonexistent')).rejects.toMatchObject({ code: FileSystemErrorCode.ENOENT });
283
+ await expect(fs.rm('/nonexistent')).rejects.toThrow(FileSystemError);
284
+ await expect(fs.rm('/nonexistent')).rejects.toMatchObject({ code: FileSystemErrorCode.ENOENT });
285
+ await expect(fs.rename('/nonexistent', '/new')).rejects.toThrow(FileSystemError);
286
+ await expect(fs.rename('/nonexistent', '/new')).rejects.toMatchObject({ code: FileSystemErrorCode.ENOENT });
287
+ await expect(fs.copy('/nonexistent', '/new')).rejects.toThrow(FileSystemError);
288
+ await expect(fs.copy('/nonexistent', '/new')).rejects.toMatchObject({ code: FileSystemErrorCode.ENOENT });
289
+ }
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod/v4';
2
+
3
+ type EnumValues<T> = T[Exclude<keyof T, '__proto__'>];
4
+ export const FileKind = Object.freeze({
5
+ __proto__: null,
6
+ directory: 'directory',
7
+ file: 'file',
8
+ });
9
+ export type FileKind = EnumValues<typeof FileKind>;
10
+ export const FileKindSchema = z.enum(['directory', 'file']);
11
+
12
+ export type ReaddirOptions = z.infer<typeof ReaddirOptionsSchema>;
13
+ export const ReaddirOptionsSchema = z.object({
14
+ recursive: z.boolean().optional(),
15
+ depth: z.number().optional(),
16
+ glob: z.string().optional(),
17
+ kind: FileKindSchema.optional(),
18
+ cursor: z.string().optional(),
19
+ hidden: z.boolean().default(false),
20
+ });
21
+
22
+ export type FileUrlOptions = z.infer<typeof FileUrlOptionsSchema>;
23
+ export const FileUrlOptionsSchema = z.object({
24
+ size: z.coerce.number().optional(),
25
+ width: z.number().optional(),
26
+ height: z.number().optional(),
27
+ quality: z.number().optional(),
28
+ thumbnail: z.boolean().optional(),
29
+ });
@@ -0,0 +1,44 @@
1
+ import type { IFileStat, IFileSystem } from '../IFileSystem';
2
+ import type { FileUrlOptions } from '../types';
3
+
4
+ export function getFileUrl(
5
+ fs: IFileSystem,
6
+ needle?: IFileStat | string,
7
+ {
8
+ ...options
9
+ }: FileUrlOptions & {
10
+ fs?: IFileSystem;
11
+ } = {},
12
+ ) {
13
+ const [file, path] = resolveFilePath(needle);
14
+ if (!path || !needle) return;
15
+
16
+ let out: string | undefined;
17
+ if (fs?.getUrl) {
18
+ try {
19
+ out = fs.getUrl(needle, options);
20
+ } catch (e) {
21
+ console.error(`failed to get file url`, needle, e);
22
+ }
23
+ }
24
+ if (!out && file) {
25
+ out = file.meta?.url || (file as any).url;
26
+ }
27
+ return out;
28
+ }
29
+
30
+ export function resolveFilePath(needle: IFileStat): [IFileStat, string];
31
+ export function resolveFilePath(needle: string): [undefined, string];
32
+ export function resolveFilePath(needle?: IFileStat | string): [IFileStat | undefined, string | undefined];
33
+ export function resolveFilePath(needle?: IFileStat | string): [IFileStat | undefined, string | undefined] {
34
+ if (!needle) {
35
+ return [undefined, undefined];
36
+ }
37
+ let file = typeof needle === 'string' ? undefined : needle;
38
+ let path = typeof needle === 'string' ? needle : needle.path;
39
+
40
+ if (file && !path) {
41
+ path = file.path;
42
+ }
43
+ return [file, path];
44
+ }
@@ -0,0 +1,23 @@
1
+ import { ArrayBuffers, classOf } from '@wener/utils';
2
+ import type { IFileStat, WritableData } from './IFileSystem';
3
+
4
+ export function resolveData(data: WritableData) {
5
+ let buf: Uint8Array;
6
+ if (typeof data === 'string') {
7
+ buf = ArrayBuffers.toUint8Array(ArrayBuffers.from(data, 'utf8') as BufferSource);
8
+ } else if (data instanceof ArrayBuffer) {
9
+ buf = new Uint8Array(data);
10
+ } else if (data instanceof Uint8Array) {
11
+ buf = data;
12
+ } else {
13
+ throw new Error(`unable to resolve data: ${typeof data} ${classOf(data)}`);
14
+ }
15
+ return buf;
16
+ }
17
+
18
+ export function getPath(f: IFileStat | string) {
19
+ if (typeof f === 'string') {
20
+ return f;
21
+ }
22
+ return f.path;
23
+ }
@@ -0,0 +1 @@
1
+ export { createWebDavFileSystem } from '../createWebDavFileSystem';
@@ -1,26 +1,25 @@
1
1
  import type { Static, TSchema } from '@sinclair/typebox';
2
+ import { isNil } from '@wener/utils';
2
3
  import Ajv, { type ErrorObject, type Options } from 'ajv';
3
4
  import addFormats from 'ajv-formats';
4
- // import localize from 'ajv-i18n/localize/zh';
5
5
  import addKeywords from 'ajv-keywords';
6
- import { isNil } from 'es-toolkit';
7
6
  import { match, P } from 'ts-pattern';
8
7
  import type { JsonSchemaDef } from './types';
9
8
 
10
- function _createAjv(opt: Options) {
9
+ function _createValidator(opt: Options) {
11
10
  const ajv = new Ajv(opt);
12
11
  addKeywords(ajv);
13
12
  addFormats(ajv);
14
13
  return ajv;
15
14
  }
16
15
 
17
- type ValidateOptions = { mutate?: boolean; clone?: boolean; ajv?: Ajv };
16
+ type ValidateOptions = { mutate?: boolean; clone?: boolean; validator?: Ajv };
18
17
 
19
18
  type ValidateResult<T> =
20
19
  | { data: T; success: true; message: undefined }
21
20
  | { data: undefined; success: false; message: string; errors: ErrorObject[] };
22
21
 
23
- function validate({ schema, data, mutate, clone, ajv }: ValidateOptions & { schema: any; data: any }) {
22
+ function validate({ schema, data, mutate, clone, validator }: ValidateOptions & { schema: any; data: any }) {
24
23
  let opts: Options = {
25
24
  // strict: 'log',
26
25
  strict: true,
@@ -35,11 +34,11 @@ function validate({ schema, data, mutate, clone, ajv }: ValidateOptions & { sche
35
34
  data = structuredClone(data);
36
35
  }
37
36
 
38
- if (!ajv) {
39
- ajv = JsonSchema.createAjv(opts);
37
+ if (!validator) {
38
+ validator = JsonSchema.createValidator(opts);
40
39
  }
41
40
 
42
- const validate = ajv.compile(schema);
41
+ const validate = validator.compile(schema);
43
42
 
44
43
  // consider reusing validate instance
45
44
 
@@ -47,119 +46,128 @@ function validate({ schema, data, mutate, clone, ajv }: ValidateOptions & { sche
47
46
  const errors = validate.errors;
48
47
  // localize(errors);
49
48
 
50
- return { data, success: valid, message: ajv.errorsText(errors), errors: errors };
49
+ return { data, success: valid, message: validator.errorsText(errors), errors: errors };
51
50
  }
52
51
 
53
52
  type TypeOfSchema<S> = S extends TSchema ? Static<S> : any;
54
53
 
55
- export namespace JsonSchema {
56
- export let schemas: JsonSchemaDef[] = [];
57
-
58
- export let createAjv = _createAjv;
59
-
60
- export function addSchema(
61
- schema: JsonSchemaDef,
62
- {
63
- onConflict = 'throw',
64
- }: {
65
- onConflict?: 'throw' | 'ignore' | 'replace' | ((old: JsonSchemaDef, neo: JsonSchemaDef) => JsonSchemaDef);
66
- } = {},
67
- ) {
68
- if (!schema.$id) throw new Error('Schema must have $id');
69
- switch (onConflict) {
70
- case 'ignore':
71
- onConflict = (old) => old;
72
- break;
73
- case 'replace':
74
- onConflict = (_, neo) => neo;
75
- break;
76
- case 'throw':
77
- onConflict = (old, neo) => {
78
- throw new Error(`Schema ${neo.$id} already exists`);
79
- };
80
- break;
81
- }
82
- let idx = schemas.findIndex((s) => s.$id === schema.$id);
83
- if (idx >= 0) {
84
- schemas[idx] = onConflict(schemas[idx], schema);
85
- } else {
86
- schemas.push(schema);
87
- }
54
+ let schemas: JsonSchemaDef[] = [];
55
+
56
+ let createValidator = _createValidator;
57
+
58
+ function addSchema(
59
+ schema: JsonSchemaDef,
60
+ {
61
+ onConflict = 'throw',
62
+ }: {
63
+ onConflict?: 'throw' | 'ignore' | 'replace' | ((old: JsonSchemaDef, neo: JsonSchemaDef) => JsonSchemaDef);
64
+ } = {},
65
+ ) {
66
+ if (!schema.$id) throw new Error('Schema must have $id');
67
+ switch (onConflict) {
68
+ case 'ignore':
69
+ onConflict = (old) => old;
70
+ break;
71
+ case 'replace':
72
+ onConflict = (_, neo) => neo;
73
+ break;
74
+ case 'throw':
75
+ onConflict = (_old, neo) => {
76
+ throw new Error(`Schema ${neo.$id} already exists`);
77
+ };
78
+ break;
88
79
  }
89
-
90
- /**
91
- * Check data is valid, will not use default
92
- */
93
- export function check<S>(schema: S, data: any): ValidateResult<TypeOfSchema<S>> {
94
- return validate({ schema, data, mutate: false, clone: true }) as any;
80
+ let idx = schemas.findIndex((s) => s.$id === schema.$id);
81
+ if (idx >= 0) {
82
+ schemas[idx] = onConflict(schemas[idx], schema);
83
+ } else {
84
+ schemas.push(schema);
95
85
  }
86
+ }
96
87
 
97
- /**
98
- * Parse data with default value and coerceTypes
99
- */
100
- export function safeParse<S>(schema: S, data: any): ValidateResult<TypeOfSchema<S>> {
101
- return validate({ schema, data, mutate: true, clone: true }) as any;
102
- }
88
+ /**
89
+ * Check data is valid, will not use default
90
+ */
91
+ function check<S>(schema: S, data: any): ValidateResult<TypeOfSchema<S>> {
92
+ return validate({ schema, data, mutate: false, clone: true }) as any;
93
+ }
103
94
 
104
- export function parse<S>(schema: S, data: any): TypeOfSchema<S> {
105
- const { data: out, message, errors } = validate({ schema, data, mutate: true, clone: true });
106
- if (errors) {
107
- throw new Error(message);
108
- }
109
- return out;
95
+ /**
96
+ * Parse data with default value and coerceTypes
97
+ */
98
+ function safeParse<S>(schema: S, data: any): ValidateResult<TypeOfSchema<S>> {
99
+ return validate({ schema, data, mutate: true, clone: true }) as any;
100
+ }
101
+
102
+ function parse<S>(schema: S, data: any): TypeOfSchema<S> {
103
+ const { data: out, message, errors } = validate({ schema, data, mutate: true, clone: true });
104
+ if (errors) {
105
+ throw new Error(message);
110
106
  }
107
+ return out;
108
+ }
111
109
 
112
- export function create<S>(schema: S, data?: any): TypeOfSchema<S> {
113
- // will not ensure value match the rule
114
- return match(schema as JsonSchemaDef)
115
- .returnType<any>()
116
- .with({ const: P.nonNullable }, (v) => v)
117
- .with({ default: P.select() }, (v) => v)
118
- .with({ anyOf: P.nonNullable }, (schema) => {
119
- return create(schema.anyOf[0]);
120
- })
121
- .with({ oneOf: P.nonNullable }, (schema) => {
122
- return create(schema.oneOf[0]);
123
- })
124
- .with({ type: 'string' }, (schema) => '')
125
- .with({ type: P.union('number', 'integer') }, (schema) => 0)
126
- .with({ type: 'object' }, (schema) => {
127
- let out = validate({ schema, data: data ?? {}, mutate: true });
128
- if (!out.success) {
129
- // fallback
130
- let obj = data || {};
131
- schema.required?.forEach((key) => {
132
- if (!(key in obj)) {
133
- let last = obj[key];
134
- let prop = schema.properties?.[key];
135
- if (prop && isNil(last)) obj[key] = JsonSchema.create(prop, last);
136
- }
137
- });
138
- out = validate({ schema, data: obj, mutate: true });
139
- if (!out.success) {
140
- console.warn(`Failed to create object with schema: ${out.message}`);
110
+ function create<S>(schema: S, data?: any): TypeOfSchema<S> {
111
+ // will not ensure value match the rule
112
+ return match(schema as JsonSchemaDef)
113
+ .returnType<any>()
114
+ .with({ const: P.nonNullable }, (v) => v)
115
+ .with({ default: P.select() }, (v) => v)
116
+ .with({ anyOf: P.nonNullable }, (schema) => {
117
+ return create(schema.anyOf[0]);
118
+ })
119
+ .with({ oneOf: P.nonNullable }, (schema) => {
120
+ return create(schema.oneOf[0]);
121
+ })
122
+ .with({ type: 'string' }, (_schema) => '')
123
+ .with({ type: P.union('number', 'integer') }, (_schema) => 0)
124
+ .with({ type: 'object' }, (schema: JsonSchemaDef) => {
125
+ let out = validate({ schema, data: data ?? {}, mutate: true });
126
+ if (!out.success) {
127
+ // fallback
128
+ let obj = data || {};
129
+ schema.required?.forEach((key) => {
130
+ if (!(key in obj)) {
131
+ let last = obj[key];
132
+ let prop = schema.properties?.[key];
133
+ if (prop && isNil(last)) obj[key] = JsonSchema.create(prop, last);
141
134
  }
135
+ });
136
+ out = validate({ schema, data: obj, mutate: true });
137
+ if (!out.success) {
138
+ console.warn(`Failed to create object with schema: ${out.message}`);
142
139
  }
143
- return out.data;
144
- })
145
- .with({ type: 'null' }, () => null)
146
- .with({ type: 'boolean' }, (schema) => false)
147
- .with({ type: 'array' }, (schema) => [])
148
- .otherwise(() => {
149
- return undefined;
150
- });
151
- }
140
+ }
141
+ return out.data;
142
+ })
143
+ .with({ type: 'null' }, () => null)
144
+ .with({ type: 'boolean' }, (_schema) => false)
145
+ .with({ type: 'array' }, (_schema) => [])
146
+ .otherwise(() => {
147
+ return undefined;
148
+ });
149
+ }
152
150
 
153
- export function isPrimitiveType(schema: any): boolean {
154
- return match(schema as JsonSchemaDef)
155
- .returnType<boolean>()
156
- .with({ type: P.union('number', 'integer', 'string', 'boolean') }, () => true)
157
- .with({ anyOf: P.nonNullable }, (schema) => {
158
- return isPrimitiveType(schema.anyOf[0]);
159
- })
160
- .with({ oneOf: P.nonNullable }, (schema) => {
161
- return isPrimitiveType(schema.oneOf[0]);
162
- })
163
- .otherwise(() => false);
164
- }
151
+ function isPrimitiveType(schema: any): boolean {
152
+ return match(schema as JsonSchemaDef)
153
+ .returnType<boolean>()
154
+ .with({ type: P.union('number', 'integer', 'string', 'boolean') }, () => true)
155
+ .with({ anyOf: P.nonNullable }, (schema) => {
156
+ return isPrimitiveType(schema.anyOf[0]);
157
+ })
158
+ .with({ oneOf: P.nonNullable }, (schema) => {
159
+ return isPrimitiveType(schema.oneOf[0]);
160
+ })
161
+ .otherwise(() => false);
165
162
  }
163
+
164
+ export const JsonSchema = {
165
+ createValidator,
166
+ addSchema,
167
+ schemas,
168
+ check,
169
+ safeParse,
170
+ parse,
171
+ create,
172
+ isPrimitiveType,
173
+ } as const;