@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,518 @@
1
+ import {
2
+ createReadStream as nodeCreateReadStream,
3
+ createWriteStream as nodeCreateWriteStream,
4
+ type Stats,
5
+ } from 'node:fs';
6
+ import fsp from 'node:fs/promises';
7
+ import path from 'node:path';
8
+ import { Readable, type Writable } from 'node:stream';
9
+ import { pathToFileURL } from 'node:url';
10
+ import type {
11
+ CopyOptions,
12
+ CreateReadStreamOptions,
13
+ CreateWriteStreamOptions,
14
+ IFileStat,
15
+ IServerFileSystem,
16
+ MkdirOptions,
17
+ ReaddirOptions,
18
+ ReadFileOptions,
19
+ RenameOptions,
20
+ RmOptions,
21
+ StatOptions,
22
+ WritableData,
23
+ WriteFileOptions,
24
+ } from '../IFileSystem';
25
+
26
+ export type INodeFileSystem = IServerFileSystem & {
27
+ readonly root: string;
28
+ resolvePath(filePath: string): string;
29
+ };
30
+
31
+ /**
32
+ * Creates a Node.js filesystem adapter that implements the IFileSystem interface
33
+ * @param options Configuration options for the filesystem
34
+ * @param options.root Optional root directory to restrict all operations within
35
+ */
36
+ export function createNodeFileSystem(options: { root?: string } = {}): INodeFileSystem {
37
+ return new NodeFs(options);
38
+ }
39
+
40
+ type IFS = typeof import('fs/promises');
41
+
42
+ class NodeFs implements IServerFileSystem, INodeFileSystem {
43
+ readonly root: string;
44
+ private readonly fs: IFS;
45
+
46
+ constructor({
47
+ root,
48
+ fs = fsp,
49
+ }: {
50
+ root?: string;
51
+ fs?: IFS;
52
+ } = {}) {
53
+ // Normalize the root path if provided
54
+ if (root) {
55
+ this.root = path.resolve(root);
56
+ } else {
57
+ this.root = '';
58
+ }
59
+ this.fs = fs;
60
+ }
61
+
62
+ // Helper method to handle aborted signals consistently
63
+ private checkAborted(signal?: AbortSignal): void {
64
+ if (signal?.aborted) {
65
+ throw new Error('The operation was aborted');
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Resolves and secures a path by:
71
+ * 1. Normalizing the path
72
+ * 2. Prepending the root directory if one is set
73
+ * 3. Verifying the resulting path is within the root directory
74
+ *
75
+ * This prevents path traversal attacks.
76
+ */
77
+ resolvePath(filePath: string): string {
78
+ // Handle empty paths
79
+ if (!filePath) {
80
+ return this.root || '';
81
+ }
82
+
83
+ // Normalize to remove any '..' segments and handle slashes
84
+ const normalizedPath = path.normalize(filePath);
85
+
86
+ // If no root is set, just return the normalized path
87
+ if (!this.root) {
88
+ return normalizedPath;
89
+ }
90
+
91
+ // Join with root and resolve to absolute path
92
+ const resolvedPath = path.resolve(path.join(this.root, normalizedPath));
93
+
94
+ // Security check: ensure the path is within the root directory
95
+ if (!resolvedPath.startsWith(this.root)) {
96
+ throw new Error(`Security violation: Path ${filePath} attempts to access outside of the root directory`);
97
+ }
98
+
99
+ return resolvedPath;
100
+ }
101
+
102
+ /**
103
+ * Removes the root prefix from a path for external representation
104
+ */
105
+ private stripRoot(fullPath: string): string {
106
+ if (!this.root || !fullPath.startsWith(this.root)) {
107
+ return fullPath;
108
+ }
109
+
110
+ // Remove the root prefix and ensure there's a leading slash
111
+ let relativePath = fullPath.substring(this.root.length);
112
+ if (!relativePath) {
113
+ return '/';
114
+ }
115
+
116
+ if (!relativePath.startsWith('/') && !relativePath.startsWith('\\')) {
117
+ relativePath = `/${relativePath}`;
118
+ }
119
+
120
+ // Normalize to ensure consistent path separators
121
+ return path.normalize(relativePath).replace(/\\/g, '/');
122
+ }
123
+
124
+ /**
125
+ * Converts a system file stat to our IFileStat interface,
126
+ * stripping the root prefix from paths
127
+ */
128
+ private toFileStat(fullPath: string, fsStats: Stats): IFileStat {
129
+ const normalizedPath = this.stripRoot(fullPath);
130
+ const directoryPath = path.dirname(normalizedPath);
131
+ const directory = directoryPath === '.' ? '/' : directoryPath.replace(/\\/g, '/');
132
+
133
+ return {
134
+ directory,
135
+ path: normalizedPath,
136
+ name: path.basename(fullPath),
137
+ kind: fsStats.isDirectory() ? 'directory' : 'file',
138
+ mtime: fsStats.mtimeMs,
139
+ size: fsStats.size,
140
+ meta: {},
141
+ };
142
+ }
143
+
144
+ async readdir(dir: string, options: ReaddirOptions = {}): Promise<IFileStat[]> {
145
+ const { fs } = this;
146
+ const { glob, recursive, depth = 1, kind, hidden = true, signal } = options;
147
+ this.checkAborted(signal);
148
+
149
+ // Resolve the directory path with security checks
150
+ const resolvedDir = this.resolvePath(dir);
151
+
152
+ // Basic file listing
153
+ const entries = await fs.readdir(resolvedDir, { withFileTypes: true });
154
+ let results = await Promise.all(
155
+ entries
156
+ .filter((entry) => hidden || !entry.name.startsWith('.'))
157
+ .filter((entry) => !kind || (kind === 'directory' ? entry.isDirectory() : entry.isFile()))
158
+ .map(async (entry) => {
159
+ this.checkAborted(signal);
160
+
161
+ const entryFullPath = path.join(resolvedDir, entry.name);
162
+ const stat = await fs.stat(entryFullPath);
163
+
164
+ // Convert to external representation
165
+ return {
166
+ directory: this.stripRoot(resolvedDir),
167
+ path: this.stripRoot(entryFullPath),
168
+ name: entry.name,
169
+ kind: entry.isDirectory() ? 'directory' : 'file',
170
+ mtime: stat.mtimeMs,
171
+ size: stat.size,
172
+ meta: {},
173
+ } as IFileStat;
174
+ }),
175
+ );
176
+
177
+ // Handle recursive option
178
+ if (recursive || depth > 1) {
179
+ const subdirs = results.filter((entry) => entry.kind === 'directory');
180
+
181
+ for (const subdir of subdirs) {
182
+ this.checkAborted(signal);
183
+
184
+ const maxDepth = recursive ? Infinity : depth - 1;
185
+ if (maxDepth > 0) {
186
+ // Need to convert the path back to a full path for the recursive call
187
+ const _subdirFullPath = this.resolvePath(subdir.path);
188
+
189
+ const subEntries = await this.readdir(subdir.path, {
190
+ ...options,
191
+ depth: maxDepth,
192
+ });
193
+ results = [...results, ...subEntries];
194
+ }
195
+ }
196
+ }
197
+
198
+ // Handle glob filtering
199
+ if (glob) {
200
+ const { matcher } = await import('micromatch');
201
+ const match = matcher(glob);
202
+ results = results.filter((entry) => match(entry.path));
203
+ }
204
+
205
+ return results;
206
+ }
207
+
208
+ async stat(filePath: string, options: StatOptions = {}): Promise<IFileStat> {
209
+ const { fs } = this;
210
+
211
+ const { signal } = options;
212
+ this.checkAborted(signal);
213
+
214
+ const resolvedPath = this.resolvePath(filePath);
215
+
216
+ try {
217
+ const stat = await fs.stat(resolvedPath);
218
+ return this.toFileStat(resolvedPath, stat);
219
+ } catch (err: any) {
220
+ if (err.code === 'ENOENT') {
221
+ throw new Error(`File not found: ${filePath}`);
222
+ }
223
+ throw err;
224
+ }
225
+ }
226
+
227
+ async mkdir(dirPath: string, options: MkdirOptions = {}): Promise<void> {
228
+ const { fs } = this;
229
+
230
+ const { recursive = false, signal } = options;
231
+ this.checkAborted(signal);
232
+
233
+ const resolvedPath = this.resolvePath(dirPath);
234
+
235
+ try {
236
+ await fs.mkdir(resolvedPath, { recursive });
237
+ } catch (err: any) {
238
+ if (err.code === 'EEXIST' && recursive) {
239
+ // Ignore if directory exists and recursive is true
240
+ return;
241
+ }
242
+ throw err;
243
+ }
244
+ }
245
+
246
+ async readFile(path: string, options?: ReadFileOptions & { encoding: 'text' }): Promise<string>;
247
+ async readFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;
248
+ async readFile(path: string, options: ReadFileOptions = {}): Promise<string | Uint8Array> {
249
+ const { fs } = this;
250
+
251
+ const { encoding = 'binary', signal, onDownloadProgress } = options;
252
+ this.checkAborted(signal);
253
+
254
+ const resolvedPath = this.resolvePath(path);
255
+
256
+ try {
257
+ // Handle progress reporting if needed
258
+ if (onDownloadProgress) {
259
+ const stat = await fs.stat(resolvedPath);
260
+ const stream = this.createReadStream(path, { signal });
261
+
262
+ return new Promise((resolve, reject) => {
263
+ const chunks: Buffer[] = [];
264
+ let loaded = 0;
265
+
266
+ stream.on('data', (chunk) => {
267
+ chunks.push(Buffer.from(chunk));
268
+ loaded += chunk.length;
269
+ onDownloadProgress({ loaded, total: stat.size });
270
+ });
271
+
272
+ stream.on('end', () => {
273
+ const buffer = Buffer.concat(chunks);
274
+ if (encoding === 'text') {
275
+ resolve(buffer.toString('utf-8'));
276
+ } else {
277
+ resolve(buffer);
278
+ }
279
+ });
280
+
281
+ stream.on('error', reject);
282
+ });
283
+ }
284
+
285
+ // Standard file reading
286
+ if (encoding === 'text') {
287
+ return await fs.readFile(resolvedPath, { encoding: 'utf-8' });
288
+ } else {
289
+ return await fs.readFile(resolvedPath);
290
+ }
291
+ } catch (err: any) {
292
+ if (err.code === 'ENOENT') {
293
+ throw new Error(`File not found: ${path}`);
294
+ }
295
+ throw err;
296
+ }
297
+ }
298
+
299
+ async writeFile(path: string, data: WritableData, options: WriteFileOptions = {}): Promise<void> {
300
+ const { fs } = this;
301
+
302
+ const { signal, overwrite = true, onUploadProgress } = options;
303
+ this.checkAborted(signal);
304
+
305
+ const resolvedPath = this.resolvePath(path);
306
+
307
+ // Check if file exists and overwrite is false
308
+ if (!overwrite) {
309
+ const exists = await this.exists(path);
310
+ if (exists) {
311
+ throw new Error(`File already exists: ${path}`);
312
+ }
313
+ }
314
+
315
+ // Create parent directories if they don't exist
316
+ const directory = this.getDirectoryName(resolvedPath);
317
+ if (directory !== resolvedPath) {
318
+ try {
319
+ await this.mkdir(this.stripRoot(directory), { recursive: true });
320
+ } catch (err: any) {
321
+ // Ignore directory exists error
322
+ if (err?.code !== 'EEXIST') {
323
+ throw err;
324
+ }
325
+ }
326
+ }
327
+
328
+ if (data instanceof Readable) {
329
+ let _data = data;
330
+ return new Promise((resolve, reject) => {
331
+ const writeStream = this.createWriteStream(path, options);
332
+ let totalBytes = 0;
333
+
334
+ if (onUploadProgress) {
335
+ _data.on('data', (chunk) => {
336
+ totalBytes += chunk.length;
337
+ onUploadProgress({ loaded: totalBytes, total: -1 });
338
+ });
339
+ }
340
+
341
+ _data.pipe(writeStream);
342
+
343
+ writeStream.on('finish', () => resolve());
344
+ writeStream.on('error', reject);
345
+
346
+ if (signal) {
347
+ signal.addEventListener('abort', () => {
348
+ _data.destroy();
349
+ writeStream.destroy();
350
+ reject(new Error('The operation was aborted'));
351
+ });
352
+ }
353
+ });
354
+ } else if (data instanceof ReadableStream) {
355
+ // Handle web ReadableStream
356
+ const reader = data.getReader();
357
+ const chunks: Uint8Array[] = [];
358
+ let loaded = 0;
359
+ while (true) {
360
+ const { done, value } = await reader.read();
361
+ if (done) break;
362
+ if (value) {
363
+ chunks.push(value);
364
+ loaded += value.length;
365
+ if (onUploadProgress) {
366
+ onUploadProgress({ loaded, total: -1 });
367
+ }
368
+ }
369
+ }
370
+ await fs.writeFile(resolvedPath, Buffer.concat(chunks));
371
+ } else {
372
+ // Convert ArrayBuffer/ArrayBufferView to Buffer if necessary
373
+ let writeData: string | Buffer;
374
+ if (data instanceof ArrayBuffer) {
375
+ writeData = Buffer.from(data);
376
+ } else if (ArrayBuffer.isView(data)) {
377
+ writeData = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
378
+ } else {
379
+ writeData = data;
380
+ }
381
+ await fs.writeFile(resolvedPath, writeData);
382
+ }
383
+ }
384
+
385
+ async rm(path: string, options: RmOptions = {}): Promise<void> {
386
+ const { fs } = this;
387
+
388
+ const { recursive = false, force = false, signal } = options;
389
+ this.checkAborted(signal);
390
+
391
+ const resolvedPath = this.resolvePath(path);
392
+
393
+ try {
394
+ await fs.rm(resolvedPath, { recursive, force });
395
+ } catch (err: any) {
396
+ if (force && err.code === 'ENOENT') {
397
+ return;
398
+ }
399
+ throw err;
400
+ }
401
+ }
402
+
403
+ async rename(oldPath: string, newPath: string, options: RenameOptions = {}): Promise<void> {
404
+ const { fs } = this;
405
+
406
+ const { signal, overwrite = false } = options;
407
+ this.checkAborted(signal);
408
+
409
+ const resolvedOldPath = this.resolvePath(oldPath);
410
+ const resolvedNewPath = this.resolvePath(newPath);
411
+
412
+ // Check if target exists and overwrite is false
413
+ if (!overwrite) {
414
+ const exists = await this.exists(newPath);
415
+ if (exists) {
416
+ throw new Error(`Destination already exists: ${newPath}`);
417
+ }
418
+ }
419
+
420
+ try {
421
+ await fs.rename(resolvedOldPath, resolvedNewPath);
422
+ } catch (err: any) {
423
+ if (err.code === 'ENOENT') {
424
+ throw new Error(`Source file not found: ${oldPath}`);
425
+ }
426
+ throw err;
427
+ }
428
+ }
429
+
430
+ async exists(path: string): Promise<boolean> {
431
+ const { fs } = this;
432
+
433
+ try {
434
+ await fs.access(this.resolvePath(path));
435
+ return true;
436
+ } catch {
437
+ return false;
438
+ }
439
+ }
440
+
441
+ async copy(src: string, dest: string, options: CopyOptions = {}): Promise<void> {
442
+ const { fs } = this;
443
+
444
+ const { signal, overwrite = true, shallow = false } = options;
445
+ this.checkAborted(signal);
446
+
447
+ const resolvedSrc = this.resolvePath(src);
448
+ const resolvedDest = this.resolvePath(dest);
449
+
450
+ // Check if source exists
451
+ try {
452
+ const stat = await fs.stat(resolvedSrc);
453
+
454
+ // Check if destination exists and overwrite is false
455
+ if (!overwrite) {
456
+ const exists = await this.exists(dest);
457
+ if (exists) {
458
+ throw new Error(`Destination already exists: ${dest}`);
459
+ }
460
+ }
461
+
462
+ // Create parent directory if it doesn't exist
463
+ const parentDir = this.getDirectoryName(resolvedDest);
464
+ await this.mkdir(this.stripRoot(parentDir), { recursive: true });
465
+
466
+ // Copy recursively or not based on shallow and if it's a directory
467
+ await fs.cp(resolvedSrc, resolvedDest, {
468
+ recursive: !shallow && stat.isDirectory(),
469
+ force: overwrite,
470
+ });
471
+ } catch (err: any) {
472
+ if (err.code === 'ENOENT') {
473
+ throw new Error(`Source file not found: ${src}`);
474
+ }
475
+ throw err;
476
+ }
477
+ }
478
+
479
+ createReadStream(filePath: string, options: CreateReadStreamOptions = {}): Readable {
480
+ const resolvedPath = this.resolvePath(filePath);
481
+ const { signal, range } = options;
482
+ const stream = nodeCreateReadStream(resolvedPath, {
483
+ start: range?.start,
484
+ end: range?.end,
485
+ });
486
+
487
+ signal?.addEventListener('abort', () => stream.destroy(new Error('The operation was aborted')));
488
+
489
+ return stream;
490
+ }
491
+
492
+ createWriteStream(filePath: string, options: CreateWriteStreamOptions = {}): Writable {
493
+ const resolvedPath = this.resolvePath(filePath);
494
+ const { signal } = options;
495
+ const stream = nodeCreateWriteStream(resolvedPath, { flags: options.overwrite === false ? 'wx' : 'w' });
496
+
497
+ signal?.addEventListener('abort', () => stream.destroy(new Error('The operation was aborted')));
498
+
499
+ return stream;
500
+ }
501
+
502
+ // Helper to extract directory name correctly
503
+ private getDirectoryName(filePath: string): string {
504
+ return path.dirname(filePath);
505
+ }
506
+
507
+ getUrl(needle: IFileStat | string) {
508
+ if (typeof needle === 'object' && needle?.kind !== 'file') {
509
+ return;
510
+ }
511
+ let path = typeof needle === 'string' ? needle : needle.path;
512
+ if (!path) {
513
+ return;
514
+ }
515
+ // file://
516
+ return pathToFileURL(this.resolvePath(path)).toString();
517
+ }
518
+ }
@@ -0,0 +1,48 @@
1
+ import type { EntityManager } from '@mikro-orm/knex';
2
+ import { beforeEach, describe, test } from 'vitest';
3
+ import { runFileSystemTest } from '../tests/runFileSystemTest';
4
+ import { createDatabaseFileSystem, FileNodeMetaEntity } from './createDatabaseFileSystem';
5
+ import { loadTestDatabase } from './loadTestDatabase';
6
+
7
+ // Skip: createDatabaseFileSystem imports from @wener/server which is not a dependency of wener-common
8
+ describe.skip('DatabaseFileSystem', () => {
9
+ let fs: ReturnType<typeof createDatabaseFileSystem>;
10
+ let em: EntityManager;
11
+
12
+ beforeEach(async () => {
13
+ const { em: entityManager } = await loadTestDatabase();
14
+ em = entityManager as any; // Type cast to match expected EntityManager type
15
+
16
+ fs = createDatabaseFileSystem({
17
+ getEntityManager: () => em as any,
18
+ });
19
+
20
+ // Setup initial state: ensure root directory exists and create /README.txt
21
+ const rootNode = await fs.ensureRootNode();
22
+
23
+ // Create /README.txt file using EntityManager
24
+ const content = Buffer.from('Hello');
25
+ const readmeFile = em.create(FileNodeMetaEntity, {
26
+ filename: 'README.txt',
27
+ parent: rootNode,
28
+ kind: 'file',
29
+ size: content.length,
30
+ content: content,
31
+ atime: new Date(),
32
+ btime: new Date(),
33
+ ctime: new Date(),
34
+ mtime: new Date(),
35
+ });
36
+ await em.persistAndFlush(readmeFile);
37
+ }, 30000); // Increase timeout to 30 seconds
38
+
39
+ test('common tests', async () => {
40
+ await runFileSystemTest(fs, {
41
+ writableStream: false,
42
+ readableStream: false,
43
+ readStream: false,
44
+ writeStream: false,
45
+ abort: false,
46
+ });
47
+ }, 60000); // Increase timeout to 60 seconds
48
+ });
@@ -0,0 +1 @@
1
+ export { createNodeFileSystem } from './createNodeFileSystem';
@@ -0,0 +1,131 @@
1
+ import { inspect } from 'node:util';
2
+ import type { Options as BetterSqliteOptions } from '@mikro-orm/better-sqlite';
3
+ import { Errors, ulid } from '@wener/utils';
4
+ import type { Database } from 'better-sqlite3';
5
+ import { FileNodeContentEntity, FileNodeMetaEntity } from './createDatabaseFileSystem';
6
+
7
+ export async function loadTestDatabase({ options }: { options?: BetterSqliteOptions } = {}) {
8
+ const { MikroORM: SqliteMikroORM } = await import('@mikro-orm/better-sqlite');
9
+
10
+ const orm = await SqliteMikroORM.init({
11
+ dbName: ':memory:',
12
+ entities: [FileNodeContentEntity, FileNodeMetaEntity],
13
+ discovery: {
14
+ disableDynamicFileAccess: true,
15
+ requireEntitiesArray: true,
16
+ },
17
+ serialization: {
18
+ includePrimaryKeys: true,
19
+ forceObject: true,
20
+ },
21
+ findOneOrFailHandler(entityName, where) {
22
+ throw Errors.NotFound.asError(`未找到数据: ${entityName} ${inspect(where)}`);
23
+ },
24
+ findExactlyOneOrFailHandler(entityName, where) {
25
+ throw Errors.BadRequest.asError(`错误的数据数量: ${entityName} ${inspect(where)}`);
26
+ },
27
+ ...options,
28
+ });
29
+
30
+ const knex = orm.em.getKnex();
31
+ {
32
+ const db: Database = await knex.client.acquireConnection();
33
+ db.function('ulid', () => ulid());
34
+ await knex.client.releaseConnection(db);
35
+ }
36
+
37
+ // Execute schema creation
38
+ for (const stmt of FileSystemSchema.split(';')) {
39
+ const sql = stmt.trim();
40
+ if (sql) {
41
+ await knex.raw(sql);
42
+ }
43
+ }
44
+
45
+ return {
46
+ orm,
47
+ em: orm.em.fork(),
48
+ };
49
+ }
50
+
51
+ export const FileSystemSchema = `
52
+ CREATE TABLE IF NOT EXISTS "file_node_meta"
53
+ (
54
+ -- Base fields
55
+ "id" TEXT PRIMARY KEY NOT NULL DEFAULT (ulid()),
56
+ "tid" TEXT,
57
+ "uid" TEXT,
58
+ "eid" TEXT,
59
+ "created_at" TEXT NOT NULL DEFAULT (datetime('now')),
60
+ "updated_at" TEXT NOT NULL DEFAULT (datetime('now')),
61
+ "deleted_at" TEXT,
62
+ "attributes" TEXT,
63
+ "properties" TEXT,
64
+ "extensions" TEXT,
65
+
66
+ -- File identification
67
+ "filename" TEXT NOT NULL,
68
+ "size" INTEGER NOT NULL DEFAULT 0,
69
+ "kind" TEXT NOT NULL,
70
+
71
+ -- Timestamps
72
+ "atime" TEXT NOT NULL,
73
+ "btime" TEXT NOT NULL,
74
+ "ctime" TEXT NOT NULL,
75
+ "mtime" TEXT NOT NULL,
76
+
77
+ -- Metadata
78
+ "metadata" TEXT NOT NULL DEFAULT '{}',
79
+
80
+ -- Hierarchy
81
+ "parent_id" TEXT,
82
+
83
+ -- Small file content (for files < 64KB)
84
+ "content" BLOB,
85
+
86
+ FOREIGN KEY ("parent_id") REFERENCES "file_node_meta" ("id")
87
+ );
88
+
89
+ CREATE INDEX IF NOT EXISTS "idx_file_node_meta_filename" ON "file_node_meta" ("filename");
90
+ CREATE INDEX IF NOT EXISTS "idx_file_node_meta_parent_id" ON "file_node_meta" ("parent_id");
91
+ CREATE INDEX IF NOT EXISTS "idx_file_node_meta_tid_parent_filename" ON "file_node_meta" ("tid", "parent_id", "filename");
92
+
93
+ CREATE TABLE IF NOT EXISTS "file_node_content"
94
+ (
95
+ -- Base fields
96
+ "id" TEXT PRIMARY KEY NOT NULL DEFAULT (ulid()),
97
+ "node_id" TEXT NOT NULL UNIQUE,
98
+ "tid" TEXT,
99
+ "uid" TEXT,
100
+ "eid" TEXT,
101
+ "created_at" TEXT NOT NULL DEFAULT (datetime('now')),
102
+ "updated_at" TEXT NOT NULL DEFAULT (datetime('now')),
103
+ "deleted_at" TEXT,
104
+ "attributes" TEXT,
105
+ "properties" TEXT,
106
+ "extensions" TEXT,
107
+
108
+ -- Content information
109
+ "size" INTEGER NOT NULL,
110
+ "content" BLOB,
111
+
112
+ -- File properties
113
+ "mime_type" TEXT,
114
+
115
+ -- Checksums
116
+ "md5" TEXT,
117
+ "sha256" TEXT,
118
+
119
+ -- Content metadata
120
+ "text" TEXT,
121
+ "width" INTEGER,
122
+ "height" INTEGER,
123
+
124
+ -- Additional metadata
125
+ "metadata" TEXT NOT NULL DEFAULT '{}',
126
+
127
+ FOREIGN KEY ("node_id") REFERENCES "file_node_meta" ("id") ON DELETE CASCADE
128
+ );
129
+
130
+ CREATE INDEX IF NOT EXISTS "idx_file_node_content_node_id" ON "file_node_content" ("node_id");
131
+ `;