@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
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/fs/server/createDatabaseFileSystem.ts"],"sourcesContent":["import * as crypto from 'node:crypto';\nimport { basename, dirname, join, normalize } from 'node:path';\nimport {\n\tCascade,\n\tCollection,\n\tEntity,\n\tManyToOne,\n\tOneToMany,\n\tOneToOne,\n\tProperty,\n\ttypes,\n\tUnique,\n\ttype Opt,\n\ttype Rel,\n} from '@mikro-orm/core';\nimport type { EntityManager } from '@mikro-orm/knex';\nimport { TenantBaseEntity } from '@wener/server/entity';\nimport { getEntityManager } from '@wener/server/mikro-orm';\nimport type { CopyOptions } from 'fs-extra';\nimport { FileSystemError, FileSystemErrorCode } from '../FileSystemError';\nimport type {\n\tCreateReadStreamOptions,\n\tCreateWriteStreamOptions,\n\tIFileStat,\n\tIFileSystem,\n\tMkdirOptions,\n\tReaddirOptions,\n\tReadFileOptions,\n\tRenameOptions,\n\tRmOptions,\n\tStatOptions,\n\tWriteFileOptions,\n} from '../IFileSystem';\nimport { FileKind } from '../types';\n\nexport function createDatabaseFileSystem(options: Partial<IDatabaseFileSystemOptions> = {}): IDatabaseFileSystem {\n\treturn new DBFS(options);\n}\n\ntype IDatabaseFileSystem = IFileSystem & {\n\tensureRootNode(): Promise<FileNodeMetaEntity>;\n};\ntype IDatabaseFileSystemOptions = {\n\tgetEntityManager: () => EntityManager;\n\tsmallFileThreshold?: number;\n};\n\nclass DBFS implements IFileSystem {\n\toptions: IDatabaseFileSystemOptions;\n\n\tconstructor(options: Partial<IDatabaseFileSystemOptions> = {}) {\n\t\tthis.options = {\n\t\t\tgetEntityManager: () => getEntityManager<EntityManager>().fork(),\n\t\t\tsmallFileThreshold: 512,\n\t\t\t...options,\n\t\t};\n\t}\n\n\tget em() {\n\t\treturn this.options.getEntityManager();\n\t}\n\n\t/**\n\t * Ensure root node exists, create it if it doesn't exist\n\t * @returns The root FileNodeMetaEntity\n\t */\n\tasync ensureRootNode(): Promise<FileNodeMetaEntity> {\n\t\tconst em = this.em;\n\t\tconst rootQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\trootQb.where({ parent: null });\n\t\tconst rootNode = await rootQb.getSingleResult();\n\n\t\tif (rootNode) {\n\t\t\treturn rootNode;\n\t\t}\n\n\t\t// Create root directory (parent is null, filename is empty string)\n\t\tconst now = new Date();\n\t\tconst rootDir = em.create(FileNodeMetaEntity, {\n\t\t\tfilename: '',\n\t\t\tparent: null,\n\t\t\tkind: FileKind.directory,\n\t\t\tsize: 0,\n\t\t\tatime: now,\n\t\t\tbtime: now,\n\t\t\tctime: now,\n\t\t\tmtime: now,\n\t\t});\n\t\ttry {\n\t\t\tawait em.persistAndFlush(rootDir);\n\t\t\treturn rootDir;\n\t\t} catch (error: any) {\n\t\t\t// If root already exists (race condition), fetch and return it\n\t\t\tif (error.message?.includes('UNIQUE constraint') || error.message?.includes('duplicate')) {\n\t\t\t\tconst existingRootQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\t\texistingRootQb.where({ parent: null });\n\t\t\t\tconst existingRoot = await existingRootQb.getSingleResult();\n\t\t\t\tif (existingRoot) {\n\t\t\t\t\treturn existingRoot;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync stat(path: string, options?: StatOptions): Promise<IFileStat> {\n\t\t// Validate input\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new FileSystemError('Invalid path', FileSystemErrorCode.EINVAL);\n\t\t}\n\n\t\tconst em = this.em;\n\t\tconst node = await this._getNodeByPath(path, em);\n\t\tif (!node) {\n\t\t\tthrow new FileSystemError(`Path not found: ${path}`, FileSystemErrorCode.ENOENT);\n\t\t}\n\t\treturn this._toFileStat(node, path);\n\t}\n\n\tasync exists(path: string): Promise<boolean> {\n\t\treturn !!(await this._getNodeByPath(path, this.em));\n\t}\n\n\tasync readdir(dir: string, options?: ReaddirOptions): Promise<IFileStat[]> {\n\t\tconst em = this.em;\n\t\tconst parentNode = await this._getNodeByPath(dir, em);\n\n\t\tif (!parentNode) {\n\t\t\tthrow new FileSystemError(`Directory not found: ${dir}`, FileSystemErrorCode.ENOENT);\n\t\t}\n\t\tif (parentNode.kind !== FileKind.directory) {\n\t\t\tthrow new FileSystemError(`Path is not a directory: ${dir}`, FileSystemErrorCode.ENOTDIR);\n\t\t}\n\n\t\t// Use QueryBuilder to avoid automatic relationship loading\n\t\tconst qb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\tqb.where({ parent: parentNode });\n\t\tconst children = await qb.getResult();\n\n\t\treturn children.map((child) => this._toFileStat(child, join(dir, child.filename)));\n\t}\n\n\tasync mkdir(path: string, options: MkdirOptions = {}): Promise<void> {\n\t\tawait this._mkdirInTransaction(path, options, this.em);\n\t}\n\n\tprivate async _mkdirInTransaction(path: string, options: MkdirOptions, em: EntityManager): Promise<void> {\n\t\tconst normalized = normalize(path);\n\n\t\t// Special handling for root directory\n\t\tif (normalized === '/') {\n\t\t\tconst rootQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\trootQb.where({ parent: null });\n\t\t\tconst rootNode = await rootQb.getSingleResult();\n\t\t\tif (rootNode) {\n\t\t\t\t// Root directory already exists\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Create root directory (parent is null, filename is empty string)\n\t\t\tconst now = new Date();\n\t\t\tconst rootDir = em.create(FileNodeMetaEntity, {\n\t\t\t\tfilename: '',\n\t\t\t\tparent: null,\n\t\t\t\tkind: FileKind.directory,\n\t\t\t\tsize: 0,\n\t\t\t\tatime: now,\n\t\t\t\tbtime: now,\n\t\t\t\tctime: now,\n\t\t\t\tmtime: now,\n\t\t\t});\n\t\t\ttry {\n\t\t\t\tawait em.persistAndFlush(rootDir);\n\t\t\t} catch (error: any) {\n\t\t\t\t// If root already exists (race condition), ignore the error\n\t\t\t\tif (!error.message?.includes('UNIQUE constraint') && !error.message?.includes('duplicate')) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst parentPath = dirname(normalized);\n\t\tconst newDirName = basename(normalized);\n\n\t\tif (!newDirName) throw new FileSystemError('Cannot create directory with empty name', FileSystemErrorCode.EINVAL);\n\n\t\tlet parentNode = await this._getNodeByPath(parentPath, em);\n\n\t\tif (!parentNode) {\n\t\t\tif (options.recursive) {\n\t\t\t\t// 递归创建父目录\n\t\t\t\tawait this._mkdirInTransaction(parentPath, options, em);\n\t\t\t\tparentNode = await this._getNodeByPath(parentPath, em);\n\t\t\t} else {\n\t\t\t\tthrow new FileSystemError(`Parent directory not found: ${parentPath}`, FileSystemErrorCode.ENOENT);\n\t\t\t}\n\t\t}\n\n\t\tif (!parentNode)\n\t\t\tthrow new FileSystemError('Failed to create parent directory structure', FileSystemErrorCode.EINVAL);\n\n\t\t// Check if directory already exists using QueryBuilder\n\t\tconst existingQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\texistingQb.where({ parent: parentNode, filename: newDirName });\n\t\tconst existing = await existingQb.getSingleResult();\n\n\t\tif (existing) {\n\t\t\tif (existing.kind === FileKind.directory) {\n\t\t\t\t// Directory already exists, return silently\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow new FileSystemError(`A file with the same name already exists: ${path}`, FileSystemErrorCode.EEXIST);\n\t\t}\n\n\t\t// Create directory using EntityManager\n\t\tconst now = new Date();\n\t\tconst newDir = em.create(FileNodeMetaEntity, {\n\t\t\ttid: parentNode.tid,\n\t\t\tparent: parentNode,\n\t\t\tfilename: newDirName,\n\t\t\tkind: FileKind.directory,\n\t\t\tsize: 0,\n\t\t\tatime: now,\n\t\t\tbtime: now,\n\t\t\tctime: now,\n\t\t\tmtime: now,\n\t\t});\n\t\tawait em.persistAndFlush(newDir);\n\t}\n\n\treadFile(path: string, options?: ReadFileOptions & { encoding: 'text' }): Promise<string>;\n\n\treadFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;\n\n\tasync readFile(\n\t\tpath: string,\n\t\toptions?: ReadFileOptions & {\n\t\t\tencoding?: 'text' | 'binary' | string;\n\t\t},\n\t): Promise<string | Uint8Array> {\n\t\tconst em = this.em;\n\t\tconst node = await this._getNodeByPath(path, em);\n\n\t\tif (!node) throw new FileSystemError(`File not found: ${path}`, FileSystemErrorCode.ENOENT);\n\t\tif (node.kind !== FileKind.file)\n\t\t\tthrow new FileSystemError(`Path is not a file: ${path}`, FileSystemErrorCode.EISDIR);\n\n\t\tlet buffer: Buffer;\n\t\tif (node.content) {\n\t\t\t// 小文件优化 - content is already loaded\n\t\t\tbuffer = node.content;\n\t\t} else {\n\t\t\t// Large file: load from file_node_content table using QueryBuilder\n\t\t\tconst fileContentQb = em.createQueryBuilder(FileNodeContentEntity, 'fc');\n\t\t\tfileContentQb.where({ node: node });\n\t\t\tconst fileContent = await fileContentQb.getSingleResult();\n\t\t\tif (!fileContent) throw new FileSystemError('File content is missing', FileSystemErrorCode.ENOENT);\n\t\t\tbuffer = fileContent.content;\n\t\t}\n\n\t\treturn options?.encoding === 'text' ? buffer.toString('utf-8') : buffer;\n\t}\n\n\tasync writeFile(path: string, data: string | Buffer, options: WriteFileOptions = {}): Promise<void> {\n\t\t// Validate input\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new FileSystemError('Invalid path', FileSystemErrorCode.EINVAL);\n\t\t}\n\t\tif (data === null || data === undefined) {\n\t\t\tthrow new FileSystemError('Invalid data', FileSystemErrorCode.EINVAL);\n\t\t}\n\n\t\tawait this.em.transactional(async (em) => {\n\t\t\tconst { overwrite = true } = options;\n\t\t\tconst bufferData = Buffer.isBuffer(data) ? data : Buffer.from(data, 'utf-8');\n\t\t\tconst size = bufferData.length;\n\n\t\t\tconst parentPath = dirname(path);\n\t\t\tconst filename = basename(path);\n\n\t\t\t// Validate filename\n\t\t\tif (!filename) {\n\t\t\t\tthrow new FileSystemError('filename cannot be empty', FileSystemErrorCode.EINVAL);\n\t\t\t}\n\n\t\t\t// 确保父目录存在 - create it within the transaction\n\t\t\tawait this._mkdirInTransaction(parentPath, { recursive: true }, em);\n\t\t\tconst parentNode = await this._getNodeByPath(parentPath, em);\n\t\t\tif (!parentNode) throw new FileSystemError('Failed to establish parent directory', FileSystemErrorCode.EINVAL);\n\n\t\t\t// Find existing node using QueryBuilder\n\t\t\tconst nodeQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\tnodeQb.where({ parent: parentNode, filename });\n\t\t\tlet node = await nodeQb.getSingleResult();\n\n\t\t\tif (node) {\n\t\t\t\t// 文件已存在\n\t\t\t\tif (!overwrite) throw new FileSystemError(`File already exists: ${path}`, FileSystemErrorCode.EEXIST);\n\t\t\t\tif (node.kind === FileKind.directory)\n\t\t\t\t\tthrow new FileSystemError(`Cannot overwrite a directory with a file: ${path}`, FileSystemErrorCode.EISDIR);\n\n\t\t\t\t// 更新节点\n\t\t\t\tnode.size = size;\n\t\t\t\tnode.mtime = new Date();\n\t\t\t\t// ... 其他时间戳\n\t\t\t} else {\n\t\t\t\t// 新建文件\n\t\t\t\tconst now = new Date();\n\t\t\t\tnode = em.create(FileNodeMetaEntity, {\n\t\t\t\t\ttid: parentNode.tid,\n\t\t\t\t\tfilename,\n\t\t\t\t\tparent: parentNode,\n\t\t\t\t\tkind: FileKind.file,\n\t\t\t\t\tsize,\n\t\t\t\t\tatime: now,\n\t\t\t\t\tbtime: now,\n\t\t\t\t\tctime: now,\n\t\t\t\t\tmtime: now,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// 处理文件内容\n\t\t\tif (size <= this.options.smallFileThreshold!) {\n\t\t\t\t// Small file: store in file_node_meta.content\n\t\t\t\tnode.content = bufferData;\n\t\t\t\t// If there was large file content, delete it\n\t\t\t\t// Use QueryBuilder to avoid relationship issues\n\t\t\t\tconst existingContentQb = em.createQueryBuilder(FileNodeContentEntity, 'fc');\n\t\t\t\texistingContentQb.where({ node: node });\n\t\t\t\tconst existingContent = await existingContentQb.getSingleResult();\n\t\t\t\tif (existingContent) {\n\t\t\t\t\tawait em.removeAndFlush(existingContent);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Large file: store in file_node_content table\n\t\t\t\tnode.content = undefined; // Clear small file content\n\t\t\t\tconst md5 = crypto.createHash('md5').update(bufferData).digest('hex');\n\t\t\t\tconst sha256 = crypto.createHash('sha256').update(bufferData).digest('hex');\n\n\t\t\t\t// Check if fileContent already exists using QueryBuilder\n\t\t\t\tconst fileContentQb = em.createQueryBuilder(FileNodeContentEntity, 'fc');\n\t\t\t\tfileContentQb.where({ node: node });\n\t\t\t\tlet fileContent = await fileContentQb.getSingleResult();\n\n\t\t\t\tif (fileContent) {\n\t\t\t\t\t// Update existing content\n\t\t\t\t\tfileContent.content = bufferData;\n\t\t\t\t\tfileContent.size = size;\n\t\t\t\t\tfileContent.md5 = md5;\n\t\t\t\t\tfileContent.sha256 = sha256;\n\t\t\t\t} else {\n\t\t\t\t\t// Create new content entity\n\t\t\t\t\tfileContent = em.create(FileNodeContentEntity, {\n\t\t\t\t\t\tnode: node, // Use node relationship as primary key\n\t\t\t\t\t\ttid: node.tid,\n\t\t\t\t\t\tcontent: bufferData,\n\t\t\t\t\t\tsize: size,\n\t\t\t\t\t\tmd5: md5,\n\t\t\t\t\t\tsha256: sha256,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait em.persistAndFlush(node);\n\t\t});\n\t}\n\n\tasync rm(path: string, options: RmOptions = {}): Promise<void> {\n\t\tawait this.em.transactional(async (em) => {\n\t\t\tconst node = await this._getNodeByPath(path, em);\n\t\t\tif (!node) {\n\t\t\t\tif (options.force) return; // force=true, 不存在也算成功\n\t\t\t\tthrow new FileSystemError(`Path not found: ${path}`, FileSystemErrorCode.ENOENT);\n\t\t\t}\n\n\t\t\tif (node.kind === FileKind.directory && !options.recursive) {\n\t\t\t\t// Check if directory has children using QueryBuilder\n\t\t\t\tconst childrenQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\t\tchildrenQb.where({ parent: node });\n\t\t\t\tchildrenQb.select('id');\n\t\t\t\tconst children = await childrenQb.getResult();\n\t\t\t\tif (children.length > 0) {\n\t\t\t\t\tthrow new FileSystemError(`Directory not empty: ${path}`, FileSystemErrorCode.ENOTEMPTY);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 使用 orphanRemoval: true, ORM会自动处理子节点和内容的删除\n\t\t\tawait em.removeAndFlush(node);\n\t\t});\n\t}\n\n\tasync rename(oldPath: string, newPath: string, options: RenameOptions = {}): Promise<void> {\n\t\tawait this.em.transactional(async (em) => {\n\t\t\tconst node = await this._getNodeByPath(oldPath, em);\n\t\t\tif (!node) throw new FileSystemError(`Source path not found: ${oldPath}`, FileSystemErrorCode.ENOENT);\n\n\t\t\tconst newParentPath = dirname(newPath);\n\t\t\tconst newFilename = basename(newPath);\n\n\t\t\tconst newParentNode = await this._getNodeByPath(newParentPath, em);\n\t\t\tif (!newParentNode)\n\t\t\t\tthrow new FileSystemError(`Destination directory not found: ${newParentPath}`, FileSystemErrorCode.ENOENT);\n\n\t\t\tconst existingDestQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\texistingDestQb.where({ parent: newParentNode, filename: newFilename });\n\t\t\tconst existingDest = await existingDestQb.getSingleResult();\n\t\t\tif (existingDest) {\n\t\t\t\tif (!options.overwrite)\n\t\t\t\t\tthrow new FileSystemError(`Destination path already exists: ${newPath}`, FileSystemErrorCode.EEXIST);\n\t\t\t\tif (node.id === existingDest.id) return; // 移动到原位置,什么都不做\n\t\t\t\tawait em.removeAndFlush(existingDest);\n\t\t\t}\n\n\t\t\tnode.parent = newParentNode;\n\t\t\tnode.filename = newFilename;\n\t\t\tnode.mtime = new Date();\n\n\t\t\tawait em.flush();\n\t\t});\n\t}\n\n\tasync copy(srcPath: string, destPath: string, options: CopyOptions = {}): Promise<void> {\n\t\tawait this.em.transactional(async (em) => {\n\t\t\tconst srcNode = await this._getNodeByPath(srcPath, em);\n\t\t\tif (!srcNode) throw new FileSystemError(`Source path not found: ${srcPath}`, FileSystemErrorCode.ENOENT);\n\n\t\t\tconst destParentPath = dirname(destPath);\n\t\t\tconst destFilename = basename(destPath);\n\n\t\t\tconst destParentNode = await this._getNodeByPath(destParentPath, em);\n\t\t\tif (!destParentNode)\n\t\t\t\tthrow new FileSystemError(`Destination directory not found: ${destParentPath}`, FileSystemErrorCode.ENOENT);\n\n\t\t\tconst existingDestQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\texistingDestQb.where({ parent: destParentNode, filename: destFilename });\n\t\t\tconst existingDest = await existingDestQb.getSingleResult();\n\t\t\tif (existingDest) {\n\t\t\t\tif (!options.overwrite)\n\t\t\t\t\tthrow new FileSystemError(`Destination path already exists: ${destPath}`, FileSystemErrorCode.EEXIST);\n\t\t\t\t// Delete existing destination within the same transaction\n\t\t\t\tawait em.removeAndFlush(existingDest);\n\t\t\t}\n\n\t\t\tawait this._copyNode(srcNode, destParentNode, destFilename, em);\n\t\t});\n\t}\n\n\tcreateReadStream(path: string, options?: CreateReadStreamOptions): never {\n\t\tthrow new Error('Streaming read is not supported by DBFS yet.');\n\t}\n\n\tcreateWriteStream(path: string, options?: CreateWriteStreamOptions): never {\n\t\tthrow new Error('Streaming write is not supported by DBFS yet.');\n\t}\n\n\tcreateReadableStream(path: string, options?: CreateReadStreamOptions): ReadableStream {\n\t\tthrow new Error('ReadableStream is not supported by DBFS yet.');\n\t}\n\n\tcreateWritableStream(path: string, options?: CreateWriteStreamOptions): WritableStream {\n\t\tthrow new Error('WritableStream is not supported by DBFS yet.');\n\t}\n\n\t/**\n\t * 将路径字符串解析为数据库中的节点。这是大部分操作的基础。\n\t * @param pathStr 绝对路径, e.g., /home/user/file.txt\n\t * @param em EntityManager 实例\n\t * @returns 找到的节点或 null\n\t */\n\tprivate async _getNodeByPath(pathStr: string, em: EntityManager): Promise<FileNodeMetaEntity | null> {\n\t\tconst normalized = normalize(pathStr);\n\n\t\tif (normalized === '/') {\n\t\t\t// Use QueryBuilder to avoid automatic relationship loading\n\t\t\tconst qb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\tqb.where({ parent: null });\n\t\t\tconst rootNode = await qb.getSingleResult();\n\t\t\treturn rootNode || null;\n\t\t}\n\n\t\tconst parts = normalized.split('/').filter((p) => p);\n\n\t\t// Get root node\n\t\tconst rootQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\trootQb.where({ parent: null });\n\t\tlet currentNode = await rootQb.getSingleResult();\n\t\tif (!currentNode) return null;\n\n\t\t// Traverse path parts\n\t\tfor (const part of parts) {\n\t\t\tconst childQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\tchildQb.where({ parent: currentNode, filename: part });\n\t\t\tconst child = await childQb.getSingleResult();\n\t\t\tif (!child) return null;\n\t\t\tcurrentNode = child;\n\t\t}\n\n\t\treturn currentNode;\n\t}\n\n\t/**\n\t * 将数据库实体转换为 IFileStat 接口\n\t */\n\tprivate _toFileStat(node: FileNodeMetaEntity, path: string): IFileStat {\n\t\t// Handle mtime - it might be a Date object or a string from raw query\n\t\tlet mtime: number;\n\t\tif (node.mtime instanceof Date) {\n\t\t\tmtime = node.mtime.getTime();\n\t\t} else if (typeof node.mtime === 'string') {\n\t\t\tmtime = new Date(node.mtime).getTime();\n\t\t} else {\n\t\t\tmtime = Date.now();\n\t\t}\n\n\t\t// Handle size - convert bigint to number if needed\n\t\tlet size: number;\n\t\tif (typeof node.size === 'bigint') {\n\t\t\tsize = Number(node.size);\n\t\t} else {\n\t\t\tsize = node.size;\n\t\t}\n\n\t\treturn {\n\t\t\tpath: path,\n\t\t\tname: node.filename,\n\t\t\tkind: node.kind,\n\t\t\tsize: size,\n\t\t\tmtime: mtime,\n\t\t\tmeta: node.metadata || {},\n\t\t\t// `directory` 字段可以根据 path 动态计算\n\t\t\tdirectory: dirname(path),\n\t\t};\n\t}\n\n\tprivate async _copyNode(\n\t\tsrcNode: FileNodeMetaEntity,\n\t\tdestParent: FileNodeMetaEntity,\n\t\tnewName: string,\n\t\tem: EntityManager,\n\t): Promise<void> {\n\t\t// 1. 复制节点本身\n\t\tconst now = new Date();\n\t\tconst newNode = em.create(FileNodeMetaEntity, {\n\t\t\ttid: srcNode.tid,\n\t\t\tfilename: newName,\n\t\t\tparent: destParent,\n\t\t\tkind: srcNode.kind,\n\t\t\tsize: srcNode.size,\n\t\t\tmetadata: srcNode.metadata, // deep copy metadata\n\t\t\tcontent: srcNode.content, // copy small file content\n\t\t\tatime: now,\n\t\t\tbtime: now,\n\t\t\tctime: now,\n\t\t\tmtime: now,\n\t\t});\n\n\t\t// 2. 复制大文件内容 (如果存在) - use QueryBuilder to avoid relationship loading\n\t\tif (!srcNode.content) {\n\t\t\tconst srcFileContentQb = em.createQueryBuilder(FileNodeContentEntity, 'fc');\n\t\t\tsrcFileContentQb.where({ node: srcNode });\n\t\t\tconst srcFileContent = await srcFileContentQb.getSingleResult();\n\t\t\tif (srcFileContent) {\n\t\t\t\tconst newContent = em.create(FileNodeContentEntity, {\n\t\t\t\t\tnode: newNode, // Use node relationship as primary key\n\t\t\t\t\ttid: srcNode.tid,\n\t\t\t\t\tcontent: srcFileContent.content,\n\t\t\t\t\tsize: srcFileContent.size,\n\t\t\t\t\tmd5: srcFileContent.md5,\n\t\t\t\t\tsha256: srcFileContent.sha256,\n\t\t\t\t\tmimeType: srcFileContent.mimeType,\n\t\t\t\t\tmetadata: srcFileContent.metadata,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tawait em.persistAndFlush(newNode);\n\n\t\t// 3. 如果是目录,递归复制子节点\n\t\tif (srcNode.kind === FileKind.directory) {\n\t\t\tconst childrenQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\tchildrenQb.where({ parent: srcNode });\n\t\t\tconst children = await childrenQb.getResult();\n\t\t\tfor (const child of children) {\n\t\t\t\tawait this._copyNode(child, newNode, child.filename, em);\n\t\t\t}\n\t\t}\n\t}\n}\n\n@Entity({ tableName: 'file_node_meta' })\n@Unique({ properties: ['tid', 'parent', 'filename'] })\nexport class FileNodeMetaEntity extends TenantBaseEntity {\n\t@Property({ type: types.string, nullable: false, comment: '文件名' })\n\tfilename!: string;\n\t@Property({ type: types.bigint, nullable: false, default: 0, comment: '文件大小' })\n\tsize!: number & Opt;\n\t@Property({ type: types.string, nullable: false, comment: '文件类型' })\n\tkind!: FileKind;\n\n\t@Property({ type: types.datetime, nullable: false, defaultRaw: 'CURRENT_TIMESTAMP' })\n\tatime!: Date & Opt;\n\t@Property({ type: types.datetime, nullable: false, defaultRaw: 'CURRENT_TIMESTAMP' })\n\tbtime!: Date & Opt;\n\t@Property({ type: types.datetime, nullable: false, defaultRaw: 'CURRENT_TIMESTAMP' })\n\tctime!: Date & Opt;\n\t@Property({ type: types.datetime, nullable: false, defaultRaw: 'CURRENT_TIMESTAMP' })\n\tmtime!: Date & Opt;\n\n\t@Property({ type: types.json, nullable: false, defaultRaw: '{}' })\n\tmetadata!: Record<string, any>;\n\n\t@ManyToOne(() => FileNodeMetaEntity, { nullable: true, cascade: [] })\n\tparent?: Rel<FileNodeMetaEntity>;\n\n\t@OneToMany({ entity: () => FileNodeMetaEntity, mappedBy: 'parent', orphanRemoval: true })\n\tchildren = new Collection<FileNodeMetaEntity>(this);\n\n\t@OneToOne({\n\t\tentity: () => FileNodeContentEntity,\n\t\tmappedBy: 'node',\n\t\torphanRemoval: true,\n\t\tnullable: true,\n\t\tcascade: [Cascade.ALL],\n\t})\n\tfileContent?: Rel<FileNodeContentEntity>;\n\t@Property({ type: types.blob, nullable: true, comment: '文件内容' })\n\tcontent?: Buffer; // for small file, e.g. < 64k\n\n\t//region content\n\n\tget parentId() {\n\t\treturn this.parent?.id as Opt<string | undefined>;\n\t}\n\n\t//endregion\n}\n\n@Entity({ tableName: 'file_node_content' })\nexport class FileNodeContentEntity extends TenantBaseEntity {\n\t@OneToOne({ entity: () => FileNodeMetaEntity, owner: true, joinColumn: 'node_id' })\n\tnode!: Rel<FileNodeMetaEntity>;\n\n\t@Property({ type: types.integer, nullable: false })\n\tsize!: number; // 保留 size 方便查询分析\n\n\t@Property({ type: types.blob, lazy: true, comment: '文件内容' })\n\tcontent!: Buffer;\n\n\t@Property({ type: types.string, nullable: true })\n\tmimeType?: string;\n\n\t@Property({ type: types.string, nullable: false })\n\tmd5?: string;\n\t@Property({ type: types.string, nullable: false })\n\tsha256?: string;\n\n\t@Property({ type: types.string, nullable: true })\n\ttext?: string;\n\t@Property({ type: types.integer, nullable: true })\n\twidth?: number;\n\t@Property({ type: types.integer, nullable: true })\n\theight?: number;\n\t// @Property({ type: types.integer, nullable: true })\n\t// length?: number;\n\n\t@Property({ type: types.json, nullable: false, defaultRaw: '{}' })\n\tmetadata!: Record<string, any>;\n}\n"],"names":["crypto","basename","dirname","join","normalize","Cascade","Collection","Entity","ManyToOne","OneToMany","OneToOne","Property","types","Unique","TenantBaseEntity","getEntityManager","FileSystemError","FileSystemErrorCode","FileKind","createDatabaseFileSystem","options","DBFS","fork","smallFileThreshold","em","ensureRootNode","rootQb","createQueryBuilder","FileNodeMetaEntity","where","parent","rootNode","getSingleResult","now","Date","rootDir","create","filename","kind","directory","size","atime","btime","ctime","mtime","persistAndFlush","error","message","includes","existingRootQb","existingRoot","stat","path","EINVAL","node","_getNodeByPath","ENOENT","_toFileStat","exists","readdir","dir","parentNode","ENOTDIR","qb","children","getResult","map","child","mkdir","_mkdirInTransaction","normalized","parentPath","newDirName","recursive","existingQb","existing","EEXIST","newDir","tid","readFile","file","EISDIR","buffer","content","fileContentQb","FileNodeContentEntity","fileContent","encoding","toString","writeFile","data","undefined","transactional","overwrite","bufferData","Buffer","isBuffer","from","length","nodeQb","existingContentQb","existingContent","removeAndFlush","md5","createHash","update","digest","sha256","rm","force","childrenQb","select","ENOTEMPTY","rename","oldPath","newPath","newParentPath","newFilename","newParentNode","existingDestQb","existingDest","id","flush","copy","srcPath","destPath","srcNode","destParentPath","destFilename","destParentNode","_copyNode","createReadStream","Error","createWriteStream","createReadableStream","createWritableStream","pathStr","parts","split","filter","p","currentNode","part","childQb","getTime","Number","name","meta","metadata","destParent","newName","newNode","srcFileContentQb","srcFileContent","newContent","mimeType","parentId","type","string","nullable","comment","bigint","default","datetime","defaultRaw","json","cascade","entity","mappedBy","orphanRemoval","ALL","blob","tableName","properties","text","width","height","owner","joinColumn","integer","lazy"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/fs/server/createDatabaseFileSystem.ts"],"sourcesContent":["import * as crypto from 'node:crypto';\nimport { basename, dirname, join, normalize } from 'node:path';\nimport {\n\tCascade,\n\tCollection,\n\tEntity,\n\tManyToOne,\n\tOneToMany,\n\tOneToOne,\n\tProperty,\n\ttypes,\n\tUnique,\n\ttype Opt,\n\ttype Rel,\n} from '@mikro-orm/core';\nimport type { EntityManager } from '@mikro-orm/knex';\nimport { TenantBaseEntity } from '@wener/server/entity';\nimport { getEntityManager } from '@wener/server/mikro-orm';\nimport type { CopyOptions } from 'fs-extra';\nimport { FileSystemError, FileSystemErrorCode } from '../FileSystemError';\nimport type {\n\tCreateReadStreamOptions,\n\tCreateWriteStreamOptions,\n\tIFileStat,\n\tIFileSystem,\n\tMkdirOptions,\n\tReaddirOptions,\n\tReadFileOptions,\n\tRenameOptions,\n\tRmOptions,\n\tStatOptions,\n\tWriteFileOptions,\n} from '../IFileSystem';\nimport { FileKind } from '../types';\n\nexport function createDatabaseFileSystem(options: Partial<IDatabaseFileSystemOptions> = {}): IDatabaseFileSystem {\n\treturn new DBFS(options);\n}\n\ntype IDatabaseFileSystem = IFileSystem & {\n\tensureRootNode(): Promise<FileNodeMetaEntity>;\n};\ntype IDatabaseFileSystemOptions = {\n\tgetEntityManager: () => EntityManager;\n\tsmallFileThreshold?: number;\n};\n\nclass DBFS implements IFileSystem {\n\toptions: IDatabaseFileSystemOptions;\n\n\tconstructor(options: Partial<IDatabaseFileSystemOptions> = {}) {\n\t\tthis.options = {\n\t\t\tgetEntityManager: () => getEntityManager<EntityManager>().fork(),\n\t\t\tsmallFileThreshold: 512,\n\t\t\t...options,\n\t\t};\n\t}\n\n\tget em() {\n\t\treturn this.options.getEntityManager();\n\t}\n\n\t/**\n\t * Ensure root node exists, create it if it doesn't exist\n\t * @returns The root FileNodeMetaEntity\n\t */\n\tasync ensureRootNode(): Promise<FileNodeMetaEntity> {\n\t\tconst em = this.em;\n\t\tconst rootQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\trootQb.where({ parent: null });\n\t\tconst rootNode = await rootQb.getSingleResult();\n\n\t\tif (rootNode) {\n\t\t\treturn rootNode;\n\t\t}\n\n\t\t// Create root directory (parent is null, filename is empty string)\n\t\tconst now = new Date();\n\t\tconst rootDir = em.create(FileNodeMetaEntity, {\n\t\t\tfilename: '',\n\t\t\tparent: null,\n\t\t\tkind: FileKind.directory,\n\t\t\tsize: 0,\n\t\t\tatime: now,\n\t\t\tbtime: now,\n\t\t\tctime: now,\n\t\t\tmtime: now,\n\t\t});\n\t\ttry {\n\t\t\tawait em.persistAndFlush(rootDir);\n\t\t\treturn rootDir;\n\t\t} catch (error: any) {\n\t\t\t// If root already exists (race condition), fetch and return it\n\t\t\tif (error.message?.includes('UNIQUE constraint') || error.message?.includes('duplicate')) {\n\t\t\t\tconst existingRootQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\t\texistingRootQb.where({ parent: null });\n\t\t\t\tconst existingRoot = await existingRootQb.getSingleResult();\n\t\t\t\tif (existingRoot) {\n\t\t\t\t\treturn existingRoot;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync stat(path: string, _options?: StatOptions): Promise<IFileStat> {\n\t\t// Validate input\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new FileSystemError('Invalid path', FileSystemErrorCode.EINVAL);\n\t\t}\n\n\t\tconst em = this.em;\n\t\tconst node = await this._getNodeByPath(path, em);\n\t\tif (!node) {\n\t\t\tthrow new FileSystemError(`Path not found: ${path}`, FileSystemErrorCode.ENOENT);\n\t\t}\n\t\treturn this._toFileStat(node, path);\n\t}\n\n\tasync exists(path: string): Promise<boolean> {\n\t\treturn !!(await this._getNodeByPath(path, this.em));\n\t}\n\n\tasync readdir(dir: string, _options?: ReaddirOptions): Promise<IFileStat[]> {\n\t\tconst em = this.em;\n\t\tconst parentNode = await this._getNodeByPath(dir, em);\n\n\t\tif (!parentNode) {\n\t\t\tthrow new FileSystemError(`Directory not found: ${dir}`, FileSystemErrorCode.ENOENT);\n\t\t}\n\t\tif (parentNode.kind !== FileKind.directory) {\n\t\t\tthrow new FileSystemError(`Path is not a directory: ${dir}`, FileSystemErrorCode.ENOTDIR);\n\t\t}\n\n\t\t// Use QueryBuilder to avoid automatic relationship loading\n\t\tconst qb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\tqb.where({ parent: parentNode });\n\t\tconst children = await qb.getResult();\n\n\t\treturn children.map((child) => this._toFileStat(child, join(dir, child.filename)));\n\t}\n\n\tasync mkdir(path: string, options: MkdirOptions = {}): Promise<void> {\n\t\tawait this._mkdirInTransaction(path, options, this.em);\n\t}\n\n\tprivate async _mkdirInTransaction(path: string, options: MkdirOptions, em: EntityManager): Promise<void> {\n\t\tconst normalized = normalize(path);\n\n\t\t// Special handling for root directory\n\t\tif (normalized === '/') {\n\t\t\tconst rootQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\trootQb.where({ parent: null });\n\t\t\tconst rootNode = await rootQb.getSingleResult();\n\t\t\tif (rootNode) {\n\t\t\t\t// Root directory already exists\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Create root directory (parent is null, filename is empty string)\n\t\t\tconst now = new Date();\n\t\t\tconst rootDir = em.create(FileNodeMetaEntity, {\n\t\t\t\tfilename: '',\n\t\t\t\tparent: null,\n\t\t\t\tkind: FileKind.directory,\n\t\t\t\tsize: 0,\n\t\t\t\tatime: now,\n\t\t\t\tbtime: now,\n\t\t\t\tctime: now,\n\t\t\t\tmtime: now,\n\t\t\t});\n\t\t\ttry {\n\t\t\t\tawait em.persistAndFlush(rootDir);\n\t\t\t} catch (error: any) {\n\t\t\t\t// If root already exists (race condition), ignore the error\n\t\t\t\tif (!error.message?.includes('UNIQUE constraint') && !error.message?.includes('duplicate')) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tconst parentPath = dirname(normalized);\n\t\tconst newDirName = basename(normalized);\n\n\t\tif (!newDirName) throw new FileSystemError('Cannot create directory with empty name', FileSystemErrorCode.EINVAL);\n\n\t\tlet parentNode = await this._getNodeByPath(parentPath, em);\n\n\t\tif (!parentNode) {\n\t\t\tif (options.recursive) {\n\t\t\t\t// 递归创建父目录\n\t\t\t\tawait this._mkdirInTransaction(parentPath, options, em);\n\t\t\t\tparentNode = await this._getNodeByPath(parentPath, em);\n\t\t\t} else {\n\t\t\t\tthrow new FileSystemError(`Parent directory not found: ${parentPath}`, FileSystemErrorCode.ENOENT);\n\t\t\t}\n\t\t}\n\n\t\tif (!parentNode)\n\t\t\tthrow new FileSystemError('Failed to create parent directory structure', FileSystemErrorCode.EINVAL);\n\n\t\t// Check if directory already exists using QueryBuilder\n\t\tconst existingQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\texistingQb.where({ parent: parentNode, filename: newDirName });\n\t\tconst existing = await existingQb.getSingleResult();\n\n\t\tif (existing) {\n\t\t\tif (existing.kind === FileKind.directory) {\n\t\t\t\t// Directory already exists, return silently\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow new FileSystemError(`A file with the same name already exists: ${path}`, FileSystemErrorCode.EEXIST);\n\t\t}\n\n\t\t// Create directory using EntityManager\n\t\tconst now = new Date();\n\t\tconst newDir = em.create(FileNodeMetaEntity, {\n\t\t\ttid: parentNode.tid,\n\t\t\tparent: parentNode,\n\t\t\tfilename: newDirName,\n\t\t\tkind: FileKind.directory,\n\t\t\tsize: 0,\n\t\t\tatime: now,\n\t\t\tbtime: now,\n\t\t\tctime: now,\n\t\t\tmtime: now,\n\t\t});\n\t\tawait em.persistAndFlush(newDir);\n\t}\n\n\treadFile(path: string, options?: ReadFileOptions & { encoding: 'text' }): Promise<string>;\n\n\treadFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;\n\n\tasync readFile(\n\t\tpath: string,\n\t\toptions?: ReadFileOptions & {\n\t\t\tencoding?: 'text' | 'binary' | string;\n\t\t},\n\t): Promise<string | Uint8Array> {\n\t\tconst em = this.em;\n\t\tconst node = await this._getNodeByPath(path, em);\n\n\t\tif (!node) throw new FileSystemError(`File not found: ${path}`, FileSystemErrorCode.ENOENT);\n\t\tif (node.kind !== FileKind.file)\n\t\t\tthrow new FileSystemError(`Path is not a file: ${path}`, FileSystemErrorCode.EISDIR);\n\n\t\tlet buffer: Buffer;\n\t\tif (node.content) {\n\t\t\t// 小文件优化 - content is already loaded\n\t\t\tbuffer = node.content;\n\t\t} else {\n\t\t\t// Large file: load from file_node_content table using QueryBuilder\n\t\t\tconst fileContentQb = em.createQueryBuilder(FileNodeContentEntity, 'fc');\n\t\t\tfileContentQb.where({ node: node });\n\t\t\tconst fileContent = await fileContentQb.getSingleResult();\n\t\t\tif (!fileContent) throw new FileSystemError('File content is missing', FileSystemErrorCode.ENOENT);\n\t\t\tbuffer = fileContent.content;\n\t\t}\n\n\t\treturn options?.encoding === 'text' ? buffer.toString('utf-8') : buffer;\n\t}\n\n\tasync writeFile(path: string, data: string | Buffer, options: WriteFileOptions = {}): Promise<void> {\n\t\t// Validate input\n\t\tif (!path || typeof path !== 'string') {\n\t\t\tthrow new FileSystemError('Invalid path', FileSystemErrorCode.EINVAL);\n\t\t}\n\t\tif (data === null || data === undefined) {\n\t\t\tthrow new FileSystemError('Invalid data', FileSystemErrorCode.EINVAL);\n\t\t}\n\n\t\tawait this.em.transactional(async (em) => {\n\t\t\tconst { overwrite = true } = options;\n\t\t\tconst bufferData = Buffer.isBuffer(data) ? data : Buffer.from(data, 'utf-8');\n\t\t\tconst size = bufferData.length;\n\n\t\t\tconst parentPath = dirname(path);\n\t\t\tconst filename = basename(path);\n\n\t\t\t// Validate filename\n\t\t\tif (!filename) {\n\t\t\t\tthrow new FileSystemError('filename cannot be empty', FileSystemErrorCode.EINVAL);\n\t\t\t}\n\n\t\t\t// 确保父目录存在 - create it within the transaction\n\t\t\tawait this._mkdirInTransaction(parentPath, { recursive: true }, em);\n\t\t\tconst parentNode = await this._getNodeByPath(parentPath, em);\n\t\t\tif (!parentNode) throw new FileSystemError('Failed to establish parent directory', FileSystemErrorCode.EINVAL);\n\n\t\t\t// Find existing node using QueryBuilder\n\t\t\tconst nodeQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\tnodeQb.where({ parent: parentNode, filename });\n\t\t\tlet node = await nodeQb.getSingleResult();\n\n\t\t\tif (node) {\n\t\t\t\t// 文件已存在\n\t\t\t\tif (!overwrite) throw new FileSystemError(`File already exists: ${path}`, FileSystemErrorCode.EEXIST);\n\t\t\t\tif (node.kind === FileKind.directory)\n\t\t\t\t\tthrow new FileSystemError(`Cannot overwrite a directory with a file: ${path}`, FileSystemErrorCode.EISDIR);\n\n\t\t\t\t// 更新节点\n\t\t\t\tnode.size = size;\n\t\t\t\tnode.mtime = new Date();\n\t\t\t\t// ... 其他时间戳\n\t\t\t} else {\n\t\t\t\t// 新建文件\n\t\t\t\tconst now = new Date();\n\t\t\t\tnode = em.create(FileNodeMetaEntity, {\n\t\t\t\t\ttid: parentNode.tid,\n\t\t\t\t\tfilename,\n\t\t\t\t\tparent: parentNode,\n\t\t\t\t\tkind: FileKind.file,\n\t\t\t\t\tsize,\n\t\t\t\t\tatime: now,\n\t\t\t\t\tbtime: now,\n\t\t\t\t\tctime: now,\n\t\t\t\t\tmtime: now,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// 处理文件内容\n\t\t\tif (size <= this.options.smallFileThreshold!) {\n\t\t\t\t// Small file: store in file_node_meta.content\n\t\t\t\tnode.content = bufferData;\n\t\t\t\t// If there was large file content, delete it\n\t\t\t\t// Use QueryBuilder to avoid relationship issues\n\t\t\t\tconst existingContentQb = em.createQueryBuilder(FileNodeContentEntity, 'fc');\n\t\t\t\texistingContentQb.where({ node: node });\n\t\t\t\tconst existingContent = await existingContentQb.getSingleResult();\n\t\t\t\tif (existingContent) {\n\t\t\t\t\tawait em.removeAndFlush(existingContent);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Large file: store in file_node_content table\n\t\t\t\tnode.content = undefined; // Clear small file content\n\t\t\t\tconst md5 = crypto.createHash('md5').update(bufferData).digest('hex');\n\t\t\t\tconst sha256 = crypto.createHash('sha256').update(bufferData).digest('hex');\n\n\t\t\t\t// Check if fileContent already exists using QueryBuilder\n\t\t\t\tconst fileContentQb = em.createQueryBuilder(FileNodeContentEntity, 'fc');\n\t\t\t\tfileContentQb.where({ node: node });\n\t\t\t\tlet fileContent = await fileContentQb.getSingleResult();\n\n\t\t\t\tif (fileContent) {\n\t\t\t\t\t// Update existing content\n\t\t\t\t\tfileContent.content = bufferData;\n\t\t\t\t\tfileContent.size = size;\n\t\t\t\t\tfileContent.md5 = md5;\n\t\t\t\t\tfileContent.sha256 = sha256;\n\t\t\t\t} else {\n\t\t\t\t\t// Create new content entity\n\t\t\t\t\tfileContent = em.create(FileNodeContentEntity, {\n\t\t\t\t\t\tnode: node, // Use node relationship as primary key\n\t\t\t\t\t\ttid: node.tid,\n\t\t\t\t\t\tcontent: bufferData,\n\t\t\t\t\t\tsize: size,\n\t\t\t\t\t\tmd5: md5,\n\t\t\t\t\t\tsha256: sha256,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait em.persistAndFlush(node);\n\t\t});\n\t}\n\n\tasync rm(path: string, options: RmOptions = {}): Promise<void> {\n\t\tawait this.em.transactional(async (em) => {\n\t\t\tconst node = await this._getNodeByPath(path, em);\n\t\t\tif (!node) {\n\t\t\t\tif (options.force) return; // force=true, 不存在也算成功\n\t\t\t\tthrow new FileSystemError(`Path not found: ${path}`, FileSystemErrorCode.ENOENT);\n\t\t\t}\n\n\t\t\tif (node.kind === FileKind.directory && !options.recursive) {\n\t\t\t\t// Check if directory has children using QueryBuilder\n\t\t\t\tconst childrenQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\t\tchildrenQb.where({ parent: node });\n\t\t\t\tchildrenQb.select('id');\n\t\t\t\tconst children = await childrenQb.getResult();\n\t\t\t\tif (children.length > 0) {\n\t\t\t\t\tthrow new FileSystemError(`Directory not empty: ${path}`, FileSystemErrorCode.ENOTEMPTY);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 使用 orphanRemoval: true, ORM会自动处理子节点和内容的删除\n\t\t\tawait em.removeAndFlush(node);\n\t\t});\n\t}\n\n\tasync rename(oldPath: string, newPath: string, options: RenameOptions = {}): Promise<void> {\n\t\tawait this.em.transactional(async (em) => {\n\t\t\tconst node = await this._getNodeByPath(oldPath, em);\n\t\t\tif (!node) throw new FileSystemError(`Source path not found: ${oldPath}`, FileSystemErrorCode.ENOENT);\n\n\t\t\tconst newParentPath = dirname(newPath);\n\t\t\tconst newFilename = basename(newPath);\n\n\t\t\tconst newParentNode = await this._getNodeByPath(newParentPath, em);\n\t\t\tif (!newParentNode)\n\t\t\t\tthrow new FileSystemError(`Destination directory not found: ${newParentPath}`, FileSystemErrorCode.ENOENT);\n\n\t\t\tconst existingDestQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\texistingDestQb.where({ parent: newParentNode, filename: newFilename });\n\t\t\tconst existingDest = await existingDestQb.getSingleResult();\n\t\t\tif (existingDest) {\n\t\t\t\tif (!options.overwrite)\n\t\t\t\t\tthrow new FileSystemError(`Destination path already exists: ${newPath}`, FileSystemErrorCode.EEXIST);\n\t\t\t\tif (node.id === existingDest.id) return; // 移动到原位置,什么都不做\n\t\t\t\tawait em.removeAndFlush(existingDest);\n\t\t\t}\n\n\t\t\tnode.parent = newParentNode;\n\t\t\tnode.filename = newFilename;\n\t\t\tnode.mtime = new Date();\n\n\t\t\tawait em.flush();\n\t\t});\n\t}\n\n\tasync copy(srcPath: string, destPath: string, options: CopyOptions = {}): Promise<void> {\n\t\tawait this.em.transactional(async (em) => {\n\t\t\tconst srcNode = await this._getNodeByPath(srcPath, em);\n\t\t\tif (!srcNode) throw new FileSystemError(`Source path not found: ${srcPath}`, FileSystemErrorCode.ENOENT);\n\n\t\t\tconst destParentPath = dirname(destPath);\n\t\t\tconst destFilename = basename(destPath);\n\n\t\t\tconst destParentNode = await this._getNodeByPath(destParentPath, em);\n\t\t\tif (!destParentNode)\n\t\t\t\tthrow new FileSystemError(`Destination directory not found: ${destParentPath}`, FileSystemErrorCode.ENOENT);\n\n\t\t\tconst existingDestQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\texistingDestQb.where({ parent: destParentNode, filename: destFilename });\n\t\t\tconst existingDest = await existingDestQb.getSingleResult();\n\t\t\tif (existingDest) {\n\t\t\t\tif (!options.overwrite)\n\t\t\t\t\tthrow new FileSystemError(`Destination path already exists: ${destPath}`, FileSystemErrorCode.EEXIST);\n\t\t\t\t// Delete existing destination within the same transaction\n\t\t\t\tawait em.removeAndFlush(existingDest);\n\t\t\t}\n\n\t\t\tawait this._copyNode(srcNode, destParentNode, destFilename, em);\n\t\t});\n\t}\n\n\tcreateReadStream(_path: string, _options?: CreateReadStreamOptions): never {\n\t\tthrow new Error('Streaming read is not supported by DBFS yet.');\n\t}\n\n\tcreateWriteStream(_path: string, _options?: CreateWriteStreamOptions): never {\n\t\tthrow new Error('Streaming write is not supported by DBFS yet.');\n\t}\n\n\tcreateReadableStream(_path: string, _options?: CreateReadStreamOptions): ReadableStream {\n\t\tthrow new Error('ReadableStream is not supported by DBFS yet.');\n\t}\n\n\tcreateWritableStream(_path: string, _options?: CreateWriteStreamOptions): WritableStream {\n\t\tthrow new Error('WritableStream is not supported by DBFS yet.');\n\t}\n\n\t/**\n\t * 将路径字符串解析为数据库中的节点。这是大部分操作的基础。\n\t * @param pathStr 绝对路径, e.g., /home/user/file.txt\n\t * @param em EntityManager 实例\n\t * @returns 找到的节点或 null\n\t */\n\tprivate async _getNodeByPath(pathStr: string, em: EntityManager): Promise<FileNodeMetaEntity | null> {\n\t\tconst normalized = normalize(pathStr);\n\n\t\tif (normalized === '/') {\n\t\t\t// Use QueryBuilder to avoid automatic relationship loading\n\t\t\tconst qb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\tqb.where({ parent: null });\n\t\t\tconst rootNode = await qb.getSingleResult();\n\t\t\treturn rootNode || null;\n\t\t}\n\n\t\tconst parts = normalized.split('/').filter((p) => p);\n\n\t\t// Get root node\n\t\tconst rootQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\trootQb.where({ parent: null });\n\t\tlet currentNode = await rootQb.getSingleResult();\n\t\tif (!currentNode) return null;\n\n\t\t// Traverse path parts\n\t\tfor (const part of parts) {\n\t\t\tconst childQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\tchildQb.where({ parent: currentNode, filename: part });\n\t\t\tconst child = await childQb.getSingleResult();\n\t\t\tif (!child) return null;\n\t\t\tcurrentNode = child;\n\t\t}\n\n\t\treturn currentNode;\n\t}\n\n\t/**\n\t * 将数据库实体转换为 IFileStat 接口\n\t */\n\tprivate _toFileStat(node: FileNodeMetaEntity, path: string): IFileStat {\n\t\t// Handle mtime - it might be a Date object or a string from raw query\n\t\tlet mtime: number;\n\t\tif (node.mtime instanceof Date) {\n\t\t\tmtime = node.mtime.getTime();\n\t\t} else if (typeof node.mtime === 'string') {\n\t\t\tmtime = new Date(node.mtime).getTime();\n\t\t} else {\n\t\t\tmtime = Date.now();\n\t\t}\n\n\t\t// Handle size - convert bigint to number if needed\n\t\tlet size: number;\n\t\tif (typeof node.size === 'bigint') {\n\t\t\tsize = Number(node.size);\n\t\t} else {\n\t\t\tsize = node.size;\n\t\t}\n\n\t\treturn {\n\t\t\tpath: path,\n\t\t\tname: node.filename,\n\t\t\tkind: node.kind,\n\t\t\tsize: size,\n\t\t\tmtime: mtime,\n\t\t\tmeta: node.metadata || {},\n\t\t\t// `directory` 字段可以根据 path 动态计算\n\t\t\tdirectory: dirname(path),\n\t\t};\n\t}\n\n\tprivate async _copyNode(\n\t\tsrcNode: FileNodeMetaEntity,\n\t\tdestParent: FileNodeMetaEntity,\n\t\tnewName: string,\n\t\tem: EntityManager,\n\t): Promise<void> {\n\t\t// 1. 复制节点本身\n\t\tconst now = new Date();\n\t\tconst newNode = em.create(FileNodeMetaEntity, {\n\t\t\ttid: srcNode.tid,\n\t\t\tfilename: newName,\n\t\t\tparent: destParent,\n\t\t\tkind: srcNode.kind,\n\t\t\tsize: srcNode.size,\n\t\t\tmetadata: srcNode.metadata, // deep copy metadata\n\t\t\tcontent: srcNode.content, // copy small file content\n\t\t\tatime: now,\n\t\t\tbtime: now,\n\t\t\tctime: now,\n\t\t\tmtime: now,\n\t\t});\n\n\t\t// 2. 复制大文件内容 (如果存在) - use QueryBuilder to avoid relationship loading\n\t\tif (!srcNode.content) {\n\t\t\tconst srcFileContentQb = em.createQueryBuilder(FileNodeContentEntity, 'fc');\n\t\t\tsrcFileContentQb.where({ node: srcNode });\n\t\t\tconst srcFileContent = await srcFileContentQb.getSingleResult();\n\t\t\tif (srcFileContent) {\n\t\t\t\tconst _newContent = em.create(FileNodeContentEntity, {\n\t\t\t\t\tnode: newNode, // Use node relationship as primary key\n\t\t\t\t\ttid: srcNode.tid,\n\t\t\t\t\tcontent: srcFileContent.content,\n\t\t\t\t\tsize: srcFileContent.size,\n\t\t\t\t\tmd5: srcFileContent.md5,\n\t\t\t\t\tsha256: srcFileContent.sha256,\n\t\t\t\t\tmimeType: srcFileContent.mimeType,\n\t\t\t\t\tmetadata: srcFileContent.metadata,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tawait em.persistAndFlush(newNode);\n\n\t\t// 3. 如果是目录,递归复制子节点\n\t\tif (srcNode.kind === FileKind.directory) {\n\t\t\tconst childrenQb = em.createQueryBuilder(FileNodeMetaEntity, 'f');\n\t\t\tchildrenQb.where({ parent: srcNode });\n\t\t\tconst children = await childrenQb.getResult();\n\t\t\tfor (const child of children) {\n\t\t\t\tawait this._copyNode(child, newNode, child.filename, em);\n\t\t\t}\n\t\t}\n\t}\n}\n\n@Entity({ tableName: 'file_node_meta' })\n@Unique({ properties: ['tid', 'parent', 'filename'] })\nexport class FileNodeMetaEntity extends TenantBaseEntity {\n\t@Property({ type: types.string, nullable: false, comment: '文件名' })\n\tfilename!: string;\n\t@Property({ type: types.bigint, nullable: false, default: 0, comment: '文件大小' })\n\tsize!: number & Opt;\n\t@Property({ type: types.string, nullable: false, comment: '文件类型' })\n\tkind!: FileKind;\n\n\t@Property({ type: types.datetime, nullable: false, defaultRaw: 'CURRENT_TIMESTAMP' })\n\tatime!: Date & Opt;\n\t@Property({ type: types.datetime, nullable: false, defaultRaw: 'CURRENT_TIMESTAMP' })\n\tbtime!: Date & Opt;\n\t@Property({ type: types.datetime, nullable: false, defaultRaw: 'CURRENT_TIMESTAMP' })\n\tctime!: Date & Opt;\n\t@Property({ type: types.datetime, nullable: false, defaultRaw: 'CURRENT_TIMESTAMP' })\n\tmtime!: Date & Opt;\n\n\t@Property({ type: types.json, nullable: false, defaultRaw: '{}' })\n\tmetadata!: Record<string, any>;\n\n\t@ManyToOne(() => FileNodeMetaEntity, { nullable: true, cascade: [] })\n\tparent?: Rel<FileNodeMetaEntity>;\n\n\t@OneToMany({ entity: () => FileNodeMetaEntity, mappedBy: 'parent', orphanRemoval: true })\n\tchildren = new Collection<FileNodeMetaEntity>(this);\n\n\t@OneToOne({\n\t\tentity: () => FileNodeContentEntity,\n\t\tmappedBy: 'node',\n\t\torphanRemoval: true,\n\t\tnullable: true,\n\t\tcascade: [Cascade.ALL],\n\t})\n\tfileContent?: Rel<FileNodeContentEntity>;\n\t@Property({ type: types.blob, nullable: true, comment: '文件内容' })\n\tcontent?: Buffer; // for small file, e.g. < 64k\n\n\t//region content\n\n\tget parentId() {\n\t\treturn this.parent?.id as Opt<string | undefined>;\n\t}\n\n\t//endregion\n}\n\n@Entity({ tableName: 'file_node_content' })\nexport class FileNodeContentEntity extends TenantBaseEntity {\n\t@OneToOne({ entity: () => FileNodeMetaEntity, owner: true, joinColumn: 'node_id' })\n\tnode!: Rel<FileNodeMetaEntity>;\n\n\t@Property({ type: types.integer, nullable: false })\n\tsize!: number; // 保留 size 方便查询分析\n\n\t@Property({ type: types.blob, lazy: true, comment: '文件内容' })\n\tcontent!: Buffer;\n\n\t@Property({ type: types.string, nullable: true })\n\tmimeType?: string;\n\n\t@Property({ type: types.string, nullable: false })\n\tmd5?: string;\n\t@Property({ type: types.string, nullable: false })\n\tsha256?: string;\n\n\t@Property({ type: types.string, nullable: true })\n\ttext?: string;\n\t@Property({ type: types.integer, nullable: true })\n\twidth?: number;\n\t@Property({ type: types.integer, nullable: true })\n\theight?: number;\n\t// @Property({ type: types.integer, nullable: true })\n\t// length?: number;\n\n\t@Property({ type: types.json, nullable: false, defaultRaw: '{}' })\n\tmetadata!: Record<string, any>;\n}\n"],"names":["crypto","basename","dirname","join","normalize","Cascade","Collection","Entity","ManyToOne","OneToMany","OneToOne","Property","types","Unique","TenantBaseEntity","getEntityManager","FileSystemError","FileSystemErrorCode","FileKind","createDatabaseFileSystem","options","DBFS","fork","smallFileThreshold","em","ensureRootNode","rootQb","createQueryBuilder","FileNodeMetaEntity","where","parent","rootNode","getSingleResult","now","Date","rootDir","create","filename","kind","directory","size","atime","btime","ctime","mtime","persistAndFlush","error","message","includes","existingRootQb","existingRoot","stat","path","_options","EINVAL","node","_getNodeByPath","ENOENT","_toFileStat","exists","readdir","dir","parentNode","ENOTDIR","qb","children","getResult","map","child","mkdir","_mkdirInTransaction","normalized","parentPath","newDirName","recursive","existingQb","existing","EEXIST","newDir","tid","readFile","file","EISDIR","buffer","content","fileContentQb","FileNodeContentEntity","fileContent","encoding","toString","writeFile","data","undefined","transactional","overwrite","bufferData","Buffer","isBuffer","from","length","nodeQb","existingContentQb","existingContent","removeAndFlush","md5","createHash","update","digest","sha256","rm","force","childrenQb","select","ENOTEMPTY","rename","oldPath","newPath","newParentPath","newFilename","newParentNode","existingDestQb","existingDest","id","flush","copy","srcPath","destPath","srcNode","destParentPath","destFilename","destParentNode","_copyNode","createReadStream","_path","Error","createWriteStream","createReadableStream","createWritableStream","pathStr","parts","split","filter","p","currentNode","part","childQb","getTime","Number","name","meta","metadata","destParent","newName","newNode","srcFileContentQb","srcFileContent","_newContent","mimeType","parentId","type","string","nullable","comment","bigint","default","datetime","defaultRaw","json","cascade","entity","mappedBy","orphanRemoval","ALL","blob","tableName","properties","text","width","height","owner","joinColumn","integer","lazy"],"mappings":"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"}