target-supabase-sdk 0.2.0 → 0.2.2

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 (484) hide show
  1. package/README.md +130 -11
  2. package/dist/browser.d.ts +44 -36
  3. package/dist/browser.d.ts.map +1 -1
  4. package/dist/browser.js +6 -45
  5. package/dist/browser.js.map +1 -1
  6. package/dist/chunks/create-logger-DyH3mZ8p.js +1028 -0
  7. package/dist/chunks/create-logger-DyH3mZ8p.js.map +1 -0
  8. package/dist/chunks/enable-log-persist-BH-tbKEj.js +1481 -0
  9. package/dist/chunks/enable-log-persist-BH-tbKEj.js.map +1 -0
  10. package/dist/chunks/word.interface-DLgRobKV.js +1973 -0
  11. package/dist/chunks/word.interface-DLgRobKV.js.map +1 -0
  12. package/dist/command/command.api.d.ts +1 -1
  13. package/dist/command/command.api.d.ts.map +1 -1
  14. package/dist/command/command.interface.d.ts +1 -1
  15. package/dist/command/command.interface.d.ts.map +1 -1
  16. package/dist/core.api.d.ts +10 -6
  17. package/dist/core.api.d.ts.map +1 -1
  18. package/dist/core.interface.d.ts +3 -2
  19. package/dist/core.interface.d.ts.map +1 -1
  20. package/dist/core.utils.d.ts +1 -1
  21. package/dist/core.utils.d.ts.map +1 -1
  22. package/dist/idea/idea.interface.d.ts +1 -1
  23. package/dist/idea/idea.interface.d.ts.map +1 -1
  24. package/dist/link/link.api.d.ts +1 -1
  25. package/dist/link/link.api.d.ts.map +1 -1
  26. package/dist/link/link.interface.d.ts +2 -2
  27. package/dist/link/link.interface.d.ts.map +1 -1
  28. package/dist/list/list.api.d.ts +3 -1
  29. package/dist/list/list.api.d.ts.map +1 -1
  30. package/dist/list/list.interface.d.ts +2 -2
  31. package/dist/list/list.interface.d.ts.map +1 -1
  32. package/dist/node/env/env-parsers.d.ts +19 -0
  33. package/dist/node/env/env-parsers.d.ts.map +1 -0
  34. package/dist/node/env/index.d.ts +11 -0
  35. package/dist/node/env/index.d.ts.map +1 -0
  36. package/dist/node/env/init-supabase-from-env.d.ts +17 -0
  37. package/dist/node/env/init-supabase-from-env.d.ts.map +1 -0
  38. package/dist/node/env/load-env.d.ts +20 -0
  39. package/dist/node/env/load-env.d.ts.map +1 -0
  40. package/dist/node/env/project-root.d.ts +11 -0
  41. package/dist/node/env/project-root.d.ts.map +1 -0
  42. package/dist/node/env/public-base-url.d.ts +10 -0
  43. package/dist/node/env/public-base-url.d.ts.map +1 -0
  44. package/dist/node/env/require-env.d.ts +3 -0
  45. package/dist/node/env/require-env.d.ts.map +1 -0
  46. package/dist/node/fs/json-state-store.d.ts +19 -0
  47. package/dist/node/fs/json-state-store.d.ts.map +1 -0
  48. package/dist/node/fs/read-source-file.d.ts +19 -0
  49. package/dist/node/fs/read-source-file.d.ts.map +1 -0
  50. package/dist/node/node-liveness.d.ts +30 -0
  51. package/dist/node/node-liveness.d.ts.map +1 -0
  52. package/dist/node/node-runtime.base.d.ts +21 -3
  53. package/dist/node/node-runtime.base.d.ts.map +1 -1
  54. package/dist/node/node.api.d.ts +1 -1
  55. package/dist/node/node.api.d.ts.map +1 -1
  56. package/dist/node/node.interface.d.ts +1 -6
  57. package/dist/node/node.interface.d.ts.map +1 -1
  58. package/dist/node/preload/run-service-preload.d.ts +14 -0
  59. package/dist/node/preload/run-service-preload.d.ts.map +1 -0
  60. package/dist/node/preload/service-preload.interface.d.ts +15 -0
  61. package/dist/node/preload/service-preload.interface.d.ts.map +1 -0
  62. package/dist/node/process/index.d.ts +5 -0
  63. package/dist/node/process/index.d.ts.map +1 -0
  64. package/dist/node/process/managed-child-processes.d.ts +37 -0
  65. package/dist/node/process/managed-child-processes.d.ts.map +1 -0
  66. package/dist/node/process/process-spawn.d.ts +27 -0
  67. package/dist/node/process/process-spawn.d.ts.map +1 -0
  68. package/dist/node/readiness/index.d.ts +9 -0
  69. package/dist/node/readiness/index.d.ts.map +1 -0
  70. package/dist/node/readiness/poll-until.d.ts +11 -0
  71. package/dist/node/readiness/poll-until.d.ts.map +1 -0
  72. package/dist/node/readiness/readiness-checks.d.ts +22 -0
  73. package/dist/node/readiness/readiness-checks.d.ts.map +1 -0
  74. package/dist/node/readiness/readiness.types.d.ts +12 -0
  75. package/dist/node/readiness/readiness.types.d.ts.map +1 -0
  76. package/dist/node/readiness/run-readiness-checks.d.ts +4 -0
  77. package/dist/node/readiness/run-readiness-checks.d.ts.map +1 -0
  78. package/dist/node/readiness/service-ready-gate.d.ts +26 -0
  79. package/dist/node/readiness/service-ready-gate.d.ts.map +1 -0
  80. package/dist/node.d.ts +26 -12
  81. package/dist/node.d.ts.map +1 -1
  82. package/dist/node.js +2482 -18
  83. package/dist/node.js.map +1 -1
  84. package/dist/parcel/chunk-fetch-registry.d.ts +14 -0
  85. package/dist/parcel/chunk-fetch-registry.d.ts.map +1 -0
  86. package/dist/parcel/chunk-url.utils.d.ts +9 -0
  87. package/dist/parcel/chunk-url.utils.d.ts.map +1 -0
  88. package/dist/parcel/parcel-manager.d.ts +44 -20
  89. package/dist/parcel/parcel-manager.d.ts.map +1 -1
  90. package/dist/parcel/parcel.api.d.ts +306 -0
  91. package/dist/parcel/parcel.api.d.ts.map +1 -0
  92. package/dist/parcel/parcel.interface.d.ts +26 -5
  93. package/dist/parcel/parcel.interface.d.ts.map +1 -1
  94. package/dist/parcel/parcel.service.d.ts +38 -0
  95. package/dist/parcel/parcel.service.d.ts.map +1 -0
  96. package/dist/parcel/storage-provider-registry.d.ts +17 -0
  97. package/dist/parcel/storage-provider-registry.d.ts.map +1 -0
  98. package/dist/parcel/storage-provider.types.d.ts +31 -0
  99. package/dist/parcel/storage-provider.types.d.ts.map +1 -0
  100. package/dist/preload.d.ts +7 -0
  101. package/dist/preload.d.ts.map +1 -0
  102. package/dist/preload.js +47 -0
  103. package/dist/preload.js.map +1 -0
  104. package/dist/repo/repo-context.utils.d.ts.map +1 -1
  105. package/dist/repo/repo-manager.d.ts +1 -1
  106. package/dist/repo/repo-manager.d.ts.map +1 -1
  107. package/dist/repo/repo.api.d.ts +1 -1
  108. package/dist/repo/repo.api.d.ts.map +1 -1
  109. package/dist/repo/repo.interface.d.ts +1 -1
  110. package/dist/repo/repo.interface.d.ts.map +1 -1
  111. package/dist/repo/repo.script-loader.d.ts +3 -3
  112. package/dist/repo/repo.script-loader.d.ts.map +1 -1
  113. package/dist/service/base.interface.d.ts +54 -57
  114. package/dist/service/base.interface.d.ts.map +1 -1
  115. package/dist/service/index.d.ts +21 -0
  116. package/dist/service/index.d.ts.map +1 -0
  117. package/dist/service/service.api.d.ts +503 -0
  118. package/dist/service/service.api.d.ts.map +1 -0
  119. package/dist/service/service.interface.d.ts +36 -9
  120. package/dist/service/service.interface.d.ts.map +1 -1
  121. package/dist/shared/http/fetch-retry.d.ts +21 -0
  122. package/dist/shared/http/fetch-retry.d.ts.map +1 -0
  123. package/dist/shared/log/create-logger.d.ts +27 -0
  124. package/dist/shared/log/create-logger.d.ts.map +1 -0
  125. package/dist/shared/log/enable-log-persist.d.ts +28 -0
  126. package/dist/shared/log/enable-log-persist.d.ts.map +1 -0
  127. package/dist/shared/log/index.d.ts +6 -6
  128. package/dist/shared/log/index.d.ts.map +1 -1
  129. package/dist/shared/log/log-manager.d.ts +25 -27
  130. package/dist/shared/log/log-manager.d.ts.map +1 -1
  131. package/dist/shared/log/log-persist-batch-id.d.ts +13 -0
  132. package/dist/shared/log/log-persist-batch-id.d.ts.map +1 -0
  133. package/dist/shared/log/log-persist-flush.d.ts +8 -0
  134. package/dist/shared/log/log-persist-flush.d.ts.map +1 -0
  135. package/dist/shared/log/log-persist-hook.d.ts +6 -0
  136. package/dist/shared/log/log-persist-hook.d.ts.map +1 -0
  137. package/dist/shared/log/log-persist-logger.d.ts +15 -0
  138. package/dist/shared/log/log-persist-logger.d.ts.map +1 -0
  139. package/dist/shared/log/log-persist-registry.d.ts +18 -0
  140. package/dist/shared/log/log-persist-registry.d.ts.map +1 -0
  141. package/dist/shared/log/log-persist.config.d.ts +10 -0
  142. package/dist/shared/log/log-persist.config.d.ts.map +1 -0
  143. package/dist/shared/log/log-persist.d.ts +55 -0
  144. package/dist/shared/log/log-persist.d.ts.map +1 -0
  145. package/dist/shared/log/log-persist.interface.d.ts +116 -0
  146. package/dist/shared/log/log-persist.interface.d.ts.map +1 -0
  147. package/dist/shared/log/log-scope.d.ts +25 -18
  148. package/dist/shared/log/log-scope.d.ts.map +1 -1
  149. package/dist/shared/utils/fetch-url.d.ts +3 -0
  150. package/dist/shared/utils/fetch-url.d.ts.map +1 -0
  151. package/dist/shared/utils/network-error.d.ts +14 -0
  152. package/dist/shared/utils/network-error.d.ts.map +1 -0
  153. package/dist/shared/utils/safe-file-name.d.ts +14 -0
  154. package/dist/shared/utils/safe-file-name.d.ts.map +1 -0
  155. package/dist/shared/utils/sha256.d.ts +3 -0
  156. package/dist/shared/utils/sha256.d.ts.map +1 -0
  157. package/dist/supabase.d.ts +7 -2
  158. package/dist/supabase.d.ts.map +1 -1
  159. package/dist/task/index.d.ts +8 -7
  160. package/dist/task/index.d.ts.map +1 -1
  161. package/dist/task/local-task-registry.d.ts +1 -1
  162. package/dist/task/local-task-registry.d.ts.map +1 -1
  163. package/dist/task/task-manager.d.ts +7 -9
  164. package/dist/task/task-manager.d.ts.map +1 -1
  165. package/dist/{node → task}/task-node.d.ts +2 -3
  166. package/dist/task/task-node.d.ts.map +1 -0
  167. package/dist/task/task-post-validated.api.d.ts +19 -0
  168. package/dist/task/task-post-validated.api.d.ts.map +1 -0
  169. package/dist/task/task-post.api.d.ts +10 -5
  170. package/dist/task/task-post.api.d.ts.map +1 -1
  171. package/dist/task/task-queue.d.ts +7 -0
  172. package/dist/task/task-queue.d.ts.map +1 -0
  173. package/dist/task/task-repo-context.d.ts.map +1 -1
  174. package/dist/task/task-repo-validation.d.ts +2 -2
  175. package/dist/task/task-repo-validation.d.ts.map +1 -1
  176. package/dist/task/task.api.d.ts +13 -13
  177. package/dist/task/task.api.d.ts.map +1 -1
  178. package/dist/task/task.constant.d.ts +4 -0
  179. package/dist/task/task.constant.d.ts.map +1 -0
  180. package/dist/task/task.interface.d.ts +1 -1
  181. package/dist/task/task.interface.d.ts.map +1 -1
  182. package/dist/trigger/trigger-manager.d.ts +25 -0
  183. package/dist/trigger/trigger-manager.d.ts.map +1 -0
  184. package/dist/trigger/trigger-node.d.ts +23 -0
  185. package/dist/trigger/trigger-node.d.ts.map +1 -0
  186. package/dist/trigger/trigger.api.d.ts +4 -4
  187. package/dist/trigger/trigger.api.d.ts.map +1 -1
  188. package/dist/trigger/trigger.constant.d.ts +8 -0
  189. package/dist/trigger/trigger.constant.d.ts.map +1 -0
  190. package/dist/trigger/trigger.interface.d.ts +46 -2
  191. package/dist/trigger/trigger.interface.d.ts.map +1 -1
  192. package/dist/word/word.api.d.ts +1 -1
  193. package/dist/word/word.api.d.ts.map +1 -1
  194. package/dist/word/word.interface.d.ts +2 -2
  195. package/dist/word/word.interface.d.ts.map +1 -1
  196. package/package.json +84 -74
  197. package/src/browser.ts +144 -79
  198. package/src/command/command.api.ts +19 -17
  199. package/src/command/command.interface.ts +2 -3
  200. package/src/core.api.ts +466 -477
  201. package/src/core.interface.ts +63 -62
  202. package/src/core.utils.ts +64 -64
  203. package/src/idea/idea.interface.ts +3 -3
  204. package/src/link/link.api.ts +28 -30
  205. package/src/link/link.interface.ts +3 -4
  206. package/src/list/list.api.ts +50 -29
  207. package/src/list/list.interface.ts +3 -4
  208. package/src/node/env/env-parsers.ts +77 -0
  209. package/src/node/env/index.ts +10 -0
  210. package/src/node/env/init-supabase-from-env.ts +38 -0
  211. package/src/node/env/load-env.ts +67 -0
  212. package/src/node/env/project-root.ts +34 -0
  213. package/src/node/env/public-base-url.ts +18 -0
  214. package/src/node/env/require-env.ts +15 -0
  215. package/src/node/fs/json-state-store.ts +97 -0
  216. package/src/node/fs/read-source-file.ts +75 -0
  217. package/src/node/node-liveness.ts +80 -0
  218. package/src/node/node-runtime.base.ts +135 -104
  219. package/src/node/node.api.ts +11 -10
  220. package/src/node/node.interface.ts +1 -8
  221. package/src/node/node.utils.ts +1 -1
  222. package/src/node/preload/run-service-preload.ts +48 -0
  223. package/src/node/preload/service-preload.interface.ts +14 -0
  224. package/src/node/process/index.ts +8 -0
  225. package/src/node/process/managed-child-processes.ts +121 -0
  226. package/src/node/process/process-spawn.ts +61 -0
  227. package/src/node/readiness/index.ts +20 -0
  228. package/src/node/readiness/poll-until.ts +27 -0
  229. package/src/node/readiness/readiness-checks.ts +79 -0
  230. package/src/node/readiness/readiness.types.ts +13 -0
  231. package/src/node/readiness/run-readiness-checks.ts +20 -0
  232. package/src/node/readiness/service-ready-gate.ts +65 -0
  233. package/src/node.ts +138 -47
  234. package/src/parcel/chunk-fetch-registry.ts +96 -0
  235. package/src/parcel/chunk-url.utils.ts +30 -0
  236. package/src/parcel/parcel-manager.ts +431 -173
  237. package/src/parcel/parcel.api.ts +103 -0
  238. package/src/parcel/parcel.interface.ts +44 -23
  239. package/src/parcel/parcel.service.ts +79 -0
  240. package/src/parcel/storage-provider-registry.ts +49 -0
  241. package/src/parcel/storage-provider.types.ts +45 -0
  242. package/src/preload.ts +7 -0
  243. package/src/repo/repo-context.utils.ts +3 -4
  244. package/src/repo/repo-manager.ts +7 -20
  245. package/src/repo/repo.api.ts +5 -5
  246. package/src/repo/repo.interface.ts +1 -2
  247. package/src/repo/repo.script-loader.ts +4 -8
  248. package/src/service/base.interface.ts +81 -90
  249. package/src/service/index.ts +173 -0
  250. package/src/service/service.api.ts +294 -0
  251. package/src/service/service.interface.ts +49 -17
  252. package/src/shared/http/fetch-retry.ts +145 -0
  253. package/src/shared/log/create-logger.ts +51 -0
  254. package/src/shared/log/enable-log-persist.ts +225 -0
  255. package/src/shared/log/index.ts +19 -11
  256. package/src/shared/log/log-manager.ts +65 -69
  257. package/src/shared/log/log-persist-batch-id.ts +43 -0
  258. package/src/shared/log/log-persist-flush.ts +128 -0
  259. package/src/shared/log/log-persist-hook.ts +13 -0
  260. package/src/shared/log/log-persist-logger.ts +33 -0
  261. package/src/shared/log/log-persist-registry.ts +252 -0
  262. package/src/shared/log/log-persist.config.ts +97 -0
  263. package/src/shared/log/log-persist.interface.ts +132 -0
  264. package/src/shared/log/log-persist.ts +704 -0
  265. package/src/shared/log/log-scope.ts +46 -46
  266. package/src/shared/utils/config-path.utils.ts +1 -1
  267. package/src/shared/utils/fetch-url.ts +13 -0
  268. package/src/shared/utils/network-error.ts +152 -0
  269. package/src/shared/utils/safe-file-name.ts +37 -0
  270. package/src/shared/utils/sha256.ts +15 -0
  271. package/src/supabase.ts +125 -119
  272. package/src/task/index.ts +31 -34
  273. package/src/task/local-task-registry.ts +9 -17
  274. package/src/task/task-manager.ts +34 -35
  275. package/src/{node → task}/task-node.ts +91 -73
  276. package/src/task/task-post-validated.api.ts +47 -0
  277. package/src/task/task-post.api.ts +81 -98
  278. package/src/task/task-queue.ts +18 -0
  279. package/src/task/task-repo-context.ts +2 -1
  280. package/src/task/task-repo-validation.ts +6 -8
  281. package/src/task/task.api.ts +61 -25
  282. package/src/task/task.constant.ts +4 -0
  283. package/src/task/task.interface.ts +4 -7
  284. package/src/trigger/trigger-manager.ts +287 -0
  285. package/src/trigger/trigger-node.ts +80 -0
  286. package/src/trigger/trigger.api.ts +11 -11
  287. package/src/trigger/trigger.constant.ts +10 -0
  288. package/src/trigger/trigger.interface.ts +52 -2
  289. package/src/trigger/trigger.utils.ts +1 -1
  290. package/src/word/word.api.ts +28 -30
  291. package/src/word/word.interface.ts +3 -4
  292. package/dist/auth/auth.api.d.ts +0 -28
  293. package/dist/auth/auth.api.d.ts.map +0 -1
  294. package/dist/auth/auth.api.js +0 -51
  295. package/dist/auth/auth.api.js.map +0 -1
  296. package/dist/command/command.api.js +0 -58
  297. package/dist/command/command.api.js.map +0 -1
  298. package/dist/command/command.interface.js +0 -9
  299. package/dist/command/command.interface.js.map +0 -1
  300. package/dist/core.api.js +0 -412
  301. package/dist/core.api.js.map +0 -1
  302. package/dist/core.interface.js +0 -46
  303. package/dist/core.interface.js.map +0 -1
  304. package/dist/core.utils.js +0 -81
  305. package/dist/core.utils.js.map +0 -1
  306. package/dist/feed/feed.interface.d.ts +0 -27
  307. package/dist/feed/feed.interface.d.ts.map +0 -1
  308. package/dist/feed/feed.interface.js +0 -17
  309. package/dist/feed/feed.interface.js.map +0 -1
  310. package/dist/file/file-manager.d.ts +0 -24
  311. package/dist/file/file-manager.d.ts.map +0 -1
  312. package/dist/file/file-manager.js +0 -109
  313. package/dist/file/file-manager.js.map +0 -1
  314. package/dist/file/file.api.d.ts +0 -15
  315. package/dist/file/file.api.d.ts.map +0 -1
  316. package/dist/file/file.api.js +0 -30
  317. package/dist/file/file.api.js.map +0 -1
  318. package/dist/file/file.interface.d.ts +0 -25
  319. package/dist/file/file.interface.d.ts.map +0 -1
  320. package/dist/file/file.interface.js +0 -9
  321. package/dist/file/file.interface.js.map +0 -1
  322. package/dist/file-list/file-list.api.d.ts +0 -15
  323. package/dist/file-list/file-list.api.d.ts.map +0 -1
  324. package/dist/file-list/file-list.api.js +0 -54
  325. package/dist/file-list/file-list.api.js.map +0 -1
  326. package/dist/file-list/file-list.interface.d.ts +0 -22
  327. package/dist/file-list/file-list.interface.d.ts.map +0 -1
  328. package/dist/file-list/file-list.interface.js +0 -5
  329. package/dist/file-list/file-list.interface.js.map +0 -1
  330. package/dist/idea/idea.interface.js +0 -15
  331. package/dist/idea/idea.interface.js.map +0 -1
  332. package/dist/index.js +0 -3
  333. package/dist/index.js.map +0 -1
  334. package/dist/link/link.api.js +0 -30
  335. package/dist/link/link.api.js.map +0 -1
  336. package/dist/link/link.interface.js +0 -7
  337. package/dist/link/link.interface.js.map +0 -1
  338. package/dist/list/list.api.js +0 -30
  339. package/dist/list/list.api.js.map +0 -1
  340. package/dist/list/list.interface.js +0 -6
  341. package/dist/list/list.interface.js.map +0 -1
  342. package/dist/node/node-log-scope.d.ts +0 -11
  343. package/dist/node/node-log-scope.d.ts.map +0 -1
  344. package/dist/node/node-log-scope.js +0 -7
  345. package/dist/node/node-log-scope.js.map +0 -1
  346. package/dist/node/node-runtime.base.js +0 -397
  347. package/dist/node/node-runtime.base.js.map +0 -1
  348. package/dist/node/node-task.preset.d.ts +0 -1
  349. package/dist/node/node-task.preset.d.ts.map +0 -1
  350. package/dist/node/node-task.preset.js +0 -14
  351. package/dist/node/node-task.preset.js.map +0 -1
  352. package/dist/node/node.api.js +0 -100
  353. package/dist/node/node.api.js.map +0 -1
  354. package/dist/node/node.interface.js +0 -19
  355. package/dist/node/node.interface.js.map +0 -1
  356. package/dist/node/node.utils.js +0 -36
  357. package/dist/node/node.utils.js.map +0 -1
  358. package/dist/node/task-node.d.ts.map +0 -1
  359. package/dist/node/task-node.js +0 -245
  360. package/dist/node/task-node.js.map +0 -1
  361. package/dist/node/trigger-node.d.ts +0 -18
  362. package/dist/node/trigger-node.d.ts.map +0 -1
  363. package/dist/node/trigger-node.js +0 -150
  364. package/dist/node/trigger-node.js.map +0 -1
  365. package/dist/parcel/parcel-manager.js +0 -156
  366. package/dist/parcel/parcel-manager.js.map +0 -1
  367. package/dist/parcel/parcel.interface.js +0 -11
  368. package/dist/parcel/parcel.interface.js.map +0 -1
  369. package/dist/question-list/question-list.api.d.ts +0 -13
  370. package/dist/question-list/question-list.api.d.ts.map +0 -1
  371. package/dist/question-list/question-list.api.js +0 -35
  372. package/dist/question-list/question-list.api.js.map +0 -1
  373. package/dist/question-list/question-list.interface.d.ts +0 -18
  374. package/dist/question-list/question-list.interface.d.ts.map +0 -1
  375. package/dist/question-list/question-list.interface.js +0 -5
  376. package/dist/question-list/question-list.interface.js.map +0 -1
  377. package/dist/repo/repo-context.utils.js +0 -81
  378. package/dist/repo/repo-context.utils.js.map +0 -1
  379. package/dist/repo/repo-manager.js +0 -166
  380. package/dist/repo/repo-manager.js.map +0 -1
  381. package/dist/repo/repo.api.js +0 -40
  382. package/dist/repo/repo.api.js.map +0 -1
  383. package/dist/repo/repo.interface.js +0 -8
  384. package/dist/repo/repo.interface.js.map +0 -1
  385. package/dist/repo/repo.script-loader.js +0 -108
  386. package/dist/repo/repo.script-loader.js.map +0 -1
  387. package/dist/review/review.api.d.ts +0 -14
  388. package/dist/review/review.api.d.ts.map +0 -1
  389. package/dist/review/review.api.js +0 -133
  390. package/dist/review/review.api.js.map +0 -1
  391. package/dist/review/review.interface.d.ts +0 -24
  392. package/dist/review/review.interface.d.ts.map +0 -1
  393. package/dist/review/review.interface.js +0 -10
  394. package/dist/review/review.interface.js.map +0 -1
  395. package/dist/review-v2/apis/post-review-setting.api.d.ts +0 -12
  396. package/dist/review-v2/apis/post-review-setting.api.d.ts.map +0 -1
  397. package/dist/review-v2/apis/post-review-setting.api.js +0 -27
  398. package/dist/review-v2/apis/post-review-setting.api.js.map +0 -1
  399. package/dist/review-v2/apis/post-review.api.d.ts +0 -13
  400. package/dist/review-v2/apis/post-review.api.d.ts.map +0 -1
  401. package/dist/review-v2/apis/post-review.api.js +0 -46
  402. package/dist/review-v2/apis/post-review.api.js.map +0 -1
  403. package/dist/review-v2/review-setting.interface.d.ts +0 -23
  404. package/dist/review-v2/review-setting.interface.d.ts.map +0 -1
  405. package/dist/review-v2/review-setting.interface.js +0 -5
  406. package/dist/review-v2/review-setting.interface.js.map +0 -1
  407. package/dist/review-v2/review.interface.d.ts +0 -20
  408. package/dist/review-v2/review.interface.d.ts.map +0 -1
  409. package/dist/review-v2/review.interface.js +0 -5
  410. package/dist/review-v2/review.interface.js.map +0 -1
  411. package/dist/service/api.interface.d.ts +0 -35
  412. package/dist/service/api.interface.d.ts.map +0 -1
  413. package/dist/service/api.interface.js +0 -12
  414. package/dist/service/api.interface.js.map +0 -1
  415. package/dist/service/base.interface.js +0 -7
  416. package/dist/service/base.interface.js.map +0 -1
  417. package/dist/service/service.interface.js +0 -11
  418. package/dist/service/service.interface.js.map +0 -1
  419. package/dist/shared/log/create-api-logger.d.ts +0 -21
  420. package/dist/shared/log/create-api-logger.d.ts.map +0 -1
  421. package/dist/shared/log/create-api-logger.js +0 -19
  422. package/dist/shared/log/create-api-logger.js.map +0 -1
  423. package/dist/shared/log/index.js +0 -10
  424. package/dist/shared/log/index.js.map +0 -1
  425. package/dist/shared/log/log-manager.js +0 -237
  426. package/dist/shared/log/log-manager.js.map +0 -1
  427. package/dist/shared/log/log-scope.js +0 -70
  428. package/dist/shared/log/log-scope.js.map +0 -1
  429. package/dist/shared/utils/config-path.utils.js +0 -85
  430. package/dist/shared/utils/config-path.utils.js.map +0 -1
  431. package/dist/shared/utils/error.utils.js +0 -15
  432. package/dist/shared/utils/error.utils.js.map +0 -1
  433. package/dist/shared/utils/id.utils.js +0 -5
  434. package/dist/shared/utils/id.utils.js.map +0 -1
  435. package/dist/supabase.js +0 -100
  436. package/dist/supabase.js.map +0 -1
  437. package/dist/task/index.js +0 -14
  438. package/dist/task/index.js.map +0 -1
  439. package/dist/task/local-task-registry.js +0 -214
  440. package/dist/task/local-task-registry.js.map +0 -1
  441. package/dist/task/task-manager.js +0 -196
  442. package/dist/task/task-manager.js.map +0 -1
  443. package/dist/task/task-post.api.js +0 -91
  444. package/dist/task/task-post.api.js.map +0 -1
  445. package/dist/task/task-repo-context.js +0 -12
  446. package/dist/task/task-repo-context.js.map +0 -1
  447. package/dist/task/task-repo-validation.js +0 -96
  448. package/dist/task/task-repo-validation.js.map +0 -1
  449. package/dist/task/task.api.js +0 -303
  450. package/dist/task/task.api.js.map +0 -1
  451. package/dist/task/task.interface.js +0 -36
  452. package/dist/task/task.interface.js.map +0 -1
  453. package/dist/task/task.utils.js +0 -2
  454. package/dist/task/task.utils.js.map +0 -1
  455. package/dist/trigger/trigger.api.js +0 -125
  456. package/dist/trigger/trigger.api.js.map +0 -1
  457. package/dist/trigger/trigger.interface.js +0 -11
  458. package/dist/trigger/trigger.interface.js.map +0 -1
  459. package/dist/trigger/trigger.utils.js +0 -39
  460. package/dist/trigger/trigger.utils.js.map +0 -1
  461. package/dist/word/word.api.js +0 -30
  462. package/dist/word/word.api.js.map +0 -1
  463. package/dist/word/word.interface.js +0 -6
  464. package/dist/word/word.interface.js.map +0 -1
  465. package/src/auth/auth.api.ts +0 -87
  466. package/src/feed/feed.interface.ts +0 -33
  467. package/src/file/file-manager.ts +0 -145
  468. package/src/file/file.api.ts +0 -43
  469. package/src/file/file.interface.ts +0 -30
  470. package/src/file-list/file-list.api.ts +0 -64
  471. package/src/file-list/file-list.interface.ts +0 -24
  472. package/src/node/node-log-scope.ts +0 -15
  473. package/src/node/node-task.preset.ts +0 -13
  474. package/src/node/trigger-node.ts +0 -180
  475. package/src/question-list/question-list.api.ts +0 -42
  476. package/src/question-list/question-list.interface.ts +0 -21
  477. package/src/review/review.api.ts +0 -145
  478. package/src/review/review.interface.ts +0 -26
  479. package/src/review-v2/apis/post-review-setting.api.ts +0 -35
  480. package/src/review-v2/apis/post-review.api.ts +0 -59
  481. package/src/review-v2/review-setting.interface.ts +0 -26
  482. package/src/review-v2/review.interface.ts +0 -23
  483. package/src/service/api.interface.ts +0 -47
  484. package/src/shared/log/create-api-logger.ts +0 -36
@@ -1,209 +1,467 @@
1
- import type { Chunk, Parcel, ParcelDetails } from "./parcel.interface";
1
+ import type { TargetDraft } from "../core.interface";
2
+ import { sha256Hex } from "../shared/utils/sha256";
3
+ import { CategoryParcel, type Chunk, type Parcel, type ParcelCrypto, type ParcelDetails } from "./parcel.interface";
2
4
 
3
5
  const MANIFEST_VERSION = 1;
4
- const DEFAULT_CHUNK_SIZE = 256 * 1024; // 256KB
6
+ const DEFAULT_CHUNK_SIZE = 2 * 1024 * 1024; // 2MB - fallback for empty input only
7
+ const MB = 1024 * 1024;
8
+ /** Source files at or below this size use at most 2 chunks */
9
+ const SMALL_FILE_MAX_BYTES = 50 * MB;
10
+ /** Target per-chunk size for larger files */
11
+ const PREFERRED_CHUNK_BYTES = 16 * MB;
12
+ /** Cap chunk count for very large files */
13
+ const MAX_CHUNK_COUNT = 64;
14
+ const AES_GCM_ALGORITHM = "AES-GCM-256";
15
+ const KEY_DERIVATION_PBKDF2 = "PBKDF2-SHA256";
16
+ const PBKDF2_ITERATIONS = 100_000;
5
17
  const AES_GCM_IV_LENGTH = 12;
6
18
  const AES_GCM_TAG_LENGTH = 128;
19
+ /** Auth tag bytes Web Crypto appends to AES-GCM ciphertext */
20
+ const AES_GCM_AUTH_TAG_BYTES = AES_GCM_TAG_LENGTH / 8;
7
21
 
8
- /** IV 存在 Parcel.extra 中的 JSON 键 */
9
- const EXTRA_IV_KEY = "iv";
22
+ /** @deprecated Legacy IV in Target.extra - read only for old parcels */
23
+ const LEGACY_EXTRA_IV_KEY = "iv";
10
24
 
11
- /** 可插拔的存储适配器:不同文件系统 */
25
+ /** Pluggable storage backend; chunks are round-robin distributed across adapters */
12
26
  export interface StorageAdapter {
13
- /** 上传一段数据,返回可下载的 URL */
14
- upload(data: ArrayBuffer, pathOrKey: string): Promise<{ url: string }>;
27
+ /** Written to {@link Chunk.provider} (e.g. `"s3"`, `"ipfs"`) */
28
+ provider?: string;
29
+ upload(data: ArrayBuffer, pathOrKey: string): Promise<{ url: string }>;
15
30
  }
16
31
 
17
- interface CreateOptions {
18
- /** 每个 chunk 的字节数,默认 256KB */
19
- chunkSize?: number;
20
- /** AES-GCM 加密密钥;不传则生成并返回 */
21
- key?: CryptoKey;
32
+ export interface CreateOptions {
33
+ /**
34
+ * Bytes per chunk after split (plaintext or ciphertext).
35
+ * When omitted, derived from source file size — see {@link resolveChunkSize}.
36
+ */
37
+ chunkSize?: number;
38
+ /**
39
+ * When `true`, encrypt the whole file before chunking.
40
+ * Default `false` — plaintext shards across platforms (anti single-platform review).
41
+ */
42
+ encrypt?: boolean;
43
+ /** User passphrase (e.g. `"apple"`); derives AES key via PBKDF2 when `encrypt` is true */
44
+ passphrase?: string;
45
+ /** Raw AES-GCM key; mutually exclusive with `passphrase` */
46
+ key?: CryptoKey;
22
47
  }
23
48
 
24
- interface CreateResult {
25
- /** 元数据,chunk 的 url 由 save 填充 */
26
- details: ParcelDetails;
27
- /** 已加密的 chunk 数据,供 save 上传 */
28
- chunks: ArrayBuffer[];
29
- /** Base64 编码的 IV,需在 save 时写入 Parcel.extra 供 reassembly 使用 */
30
- ivBase64: string;
31
- /** 若 create 时未传 key,则返回此处,调用方需妥善保存 */
32
- key?: CryptoKey;
49
+ export interface ReassembleOptions {
50
+ /** Raw AES-GCM key (parcels without passphrase-based KDF) */
51
+ key?: CryptoKey;
52
+ /** Passphrase when `details.crypto.keyDerivation` is PBKDF2 */
53
+ passphrase?: string;
33
54
  }
34
55
 
35
- /** 调用方提供的 Target 基础字段,用于拼成完整 Parcel */
36
- export type ParcelTargetBase = Pick<Parcel, "id" | "category" | "name" | "value" | "tagList" | "created_at">;
56
+ export interface CreateResult {
57
+ details: ParcelDetails;
58
+ /** Chunk payloads to upload (plaintext or ciphertext per `details.crypto`) */
59
+ chunks: ArrayBuffer[];
60
+ /** Present when `encrypt` and key was generated — caller must persist */
61
+ key?: CryptoKey;
62
+ }
63
+
64
+ /** Identity fields for {@link save} — `id` / `created_at` come from {@link postParcel}. */
65
+ export interface ParcelSaveInput {
66
+ name: string;
67
+ value: string;
68
+ tagList?: string[];
69
+ }
37
70
 
38
71
  function getCrypto(): Crypto {
39
- if (typeof globalThis !== "undefined" && globalThis.crypto) return globalThis.crypto;
40
- throw new Error("ParcelManager: crypto not available");
72
+ if (typeof globalThis !== "undefined" && globalThis.crypto) return globalThis.crypto;
73
+ throw new Error("ParcelManager: crypto not available");
74
+ }
75
+
76
+ function bytesToBase64(bytes: Uint8Array): string {
77
+ return btoa(String.fromCharCode(...bytes));
41
78
  }
42
79
 
43
- /** 计算 ArrayBuffer 的 SHA-256,返回 hex 字符串 */
44
- async function sha256Hex(buffer: ArrayBuffer): Promise<string> {
45
- const crypto = getCrypto();
46
- const hash = await crypto.subtle.digest("SHA-256", buffer);
47
- return Array.from(new Uint8Array(hash))
48
- .map((b) => b.toString(16).padStart(2, "0"))
49
- .join("");
80
+ function base64ToBytes(base64: string): Uint8Array {
81
+ return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
50
82
  }
51
83
 
52
- /** AES-GCM 加密 */
53
84
  async function encrypt(data: ArrayBuffer, key: CryptoKey, iv: Uint8Array): Promise<ArrayBuffer> {
54
- const crypto = getCrypto();
55
- const ivCopy = new Uint8Array(iv);
56
- return crypto.subtle.encrypt({ name: "AES-GCM", iv: ivCopy, tagLength: AES_GCM_TAG_LENGTH }, key, data);
85
+ const crypto = getCrypto();
86
+ return crypto.subtle.encrypt({ name: "AES-GCM", iv: new Uint8Array(iv), tagLength: AES_GCM_TAG_LENGTH }, key, data);
57
87
  }
58
88
 
59
- /** AES-GCM 解密 */
60
89
  async function decrypt(data: ArrayBuffer, key: CryptoKey, iv: Uint8Array): Promise<ArrayBuffer> {
61
- const crypto = getCrypto();
62
- const ivCopy = new Uint8Array(iv);
63
- return crypto.subtle.decrypt({ name: "AES-GCM", iv: ivCopy, tagLength: AES_GCM_TAG_LENGTH }, key, data);
90
+ const crypto = getCrypto();
91
+ return crypto.subtle.decrypt({ name: "AES-GCM", iv: new Uint8Array(iv), tagLength: AES_GCM_TAG_LENGTH }, key, data);
92
+ }
93
+
94
+ function isDecryptAuthFailure(error: unknown): boolean {
95
+ if (error instanceof DOMException && error.name === "OperationError") {
96
+ return true;
97
+ }
98
+ if (error instanceof Error) {
99
+ return /operation failed|operation-specific|decrypt|OperationError/i.test(error.message);
100
+ }
101
+ return false;
102
+ }
103
+
104
+ async function decryptPayload(
105
+ data: ArrayBuffer,
106
+ key: CryptoKey,
107
+ iv: Uint8Array,
108
+ usedPassphrase: boolean,
109
+ ): Promise<ArrayBuffer> {
110
+ try {
111
+ return await decrypt(data, key, iv);
112
+ } catch (error) {
113
+ if (isDecryptAuthFailure(error)) {
114
+ throw new Error(
115
+ usedPassphrase
116
+ ? "ParcelManager.reassemble: 解密失败,口令错误或密文已损坏"
117
+ : "ParcelManager.reassemble: 解密失败,密钥错误或密文已损坏",
118
+ );
119
+ }
120
+ throw error;
121
+ }
64
122
  }
65
123
 
66
- /** 生成 AES-GCM 密钥(256 位) */
67
124
  async function generateKey(): Promise<CryptoKey> {
68
- const crypto = getCrypto();
69
- return crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);
125
+ const crypto = getCrypto();
126
+ return crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);
127
+ }
128
+
129
+ async function deriveKeyFromPassphrase(passphrase: string, salt: Uint8Array, iterations: number): Promise<CryptoKey> {
130
+ const crypto = getCrypto();
131
+ const keyMaterial = await crypto.subtle.importKey("raw", new TextEncoder().encode(passphrase), "PBKDF2", false, [
132
+ "deriveKey",
133
+ ]);
134
+ return crypto.subtle.deriveKey(
135
+ {
136
+ name: "PBKDF2",
137
+ salt: new Uint8Array(salt),
138
+ iterations,
139
+ hash: "SHA-256",
140
+ },
141
+ keyMaterial,
142
+ { name: "AES-GCM", length: 256 },
143
+ false,
144
+ ["encrypt", "decrypt"],
145
+ );
146
+ }
147
+
148
+ function usesPassphraseDerivation(crypto: ParcelCrypto): boolean {
149
+ return crypto.keyDerivation === KEY_DERIVATION_PBKDF2;
150
+ }
151
+
152
+ async function resolveDecryptionKey(crypto: ParcelCrypto, options: ReassembleOptions): Promise<CryptoKey> {
153
+ if (usesPassphraseDerivation(crypto)) {
154
+ if (options.passphrase == null || options.passphrase === "") {
155
+ throw new Error("ParcelManager.reassemble: 口令加密 Parcel 需要提供 passphrase");
156
+ }
157
+ if (crypto.salt == null || crypto.salt === "") {
158
+ throw new Error("ParcelManager.reassemble: 缺少 details.crypto.salt");
159
+ }
160
+ const iterations = crypto.pbkdf2Iterations ?? PBKDF2_ITERATIONS;
161
+ const salt = base64ToBytes(crypto.salt);
162
+ return deriveKeyFromPassphrase(options.passphrase, salt, iterations);
163
+ }
164
+ if (options.key != null) {
165
+ return options.key;
166
+ }
167
+ throw new Error("ParcelManager.reassemble: 加密 Parcel 需要提供 key");
168
+ }
169
+
170
+ async function buildChunkList(
171
+ payload: ArrayBuffer,
172
+ chunkSize: number,
173
+ ): Promise<{ chunks: ArrayBuffer[]; chunkList: Chunk[] }> {
174
+ const chunks: ArrayBuffer[] = [];
175
+ const chunkList: Chunk[] = [];
176
+ let offset = 0;
177
+ let index = 0;
178
+
179
+ while (offset < payload.byteLength) {
180
+ const end = Math.min(offset + chunkSize, payload.byteLength);
181
+ const chunkBuffer = payload.slice(offset, end);
182
+ const checksum = await sha256Hex(chunkBuffer);
183
+ chunks.push(chunkBuffer);
184
+ chunkList.push({
185
+ index,
186
+ size: chunkBuffer.byteLength,
187
+ checksum,
188
+ url: "",
189
+ });
190
+ offset = end;
191
+ index += 1;
192
+ }
193
+
194
+ return { chunks, chunkList };
195
+ }
196
+
197
+ /**
198
+ * Derive per-chunk byte size from the buffer that will be split.
199
+ *
200
+ * | Payload size | Policy |
201
+ * |--------------|--------|
202
+ * | ≤50 MB | At most **2** chunks (`ceil(size / 2)` per chunk) |
203
+ * | > 50 MB | Target ~16 MB per chunk; chunk count capped at **64** |
204
+ *
205
+ * For encrypted parcels, pass plaintext size + {@link AES_GCM_AUTH_TAG_BYTES}
206
+ * (GCM auth tag is appended before split).
207
+ *
208
+ * Explicit `chunkSize` in {@link CreateOptions} overrides this table.
209
+ */
210
+ function resolveChunkSize(fileSize: number, override?: number): number {
211
+ if (override != null) {
212
+ if (!Number.isFinite(override) || override <= 0) {
213
+ throw new Error("ParcelManager.create: chunkSize must be a positive number");
214
+ }
215
+ return override;
216
+ }
217
+ if (fileSize <= 0) {
218
+ return DEFAULT_CHUNK_SIZE;
219
+ }
220
+ if (fileSize <= SMALL_FILE_MAX_BYTES) {
221
+ return Math.ceil(fileSize / 2);
222
+ }
223
+ const targetChunks = Math.min(MAX_CHUNK_COUNT, Math.max(2, Math.ceil(fileSize / PREFERRED_CHUNK_BYTES)));
224
+ return Math.ceil(fileSize / targetChunks);
225
+ }
226
+
227
+ function concatBuffers(buffers: ArrayBuffer[]): ArrayBuffer {
228
+ const total = buffers.reduce((sum, buffer) => sum + buffer.byteLength, 0);
229
+ const merged = new Uint8Array(total);
230
+ let offset = 0;
231
+ for (const buffer of buffers) {
232
+ merged.set(new Uint8Array(buffer), offset);
233
+ offset += buffer.byteLength;
234
+ }
235
+ return merged.buffer;
236
+ }
237
+
238
+ function isEncryptionEnabled(details: ParcelDetails, parcelExtra?: string): boolean {
239
+ if (details.crypto != null) {
240
+ return details.crypto.enabled === true;
241
+ }
242
+ if (parcelExtra == null || parcelExtra.trim() === "") {
243
+ return false;
244
+ }
245
+ try {
246
+ const legacy = JSON.parse(parcelExtra) as Record<string, unknown>;
247
+ return typeof legacy[LEGACY_EXTRA_IV_KEY] === "string";
248
+ } catch {
249
+ return false;
250
+ }
70
251
  }
71
252
 
72
- /** 将文件加密后拆分成多个 chunk */
253
+ function resolveCrypto(details: ParcelDetails, parcelExtra?: string): ParcelCrypto | null {
254
+ if (details.crypto?.enabled === true) {
255
+ return details.crypto;
256
+ }
257
+ if (parcelExtra == null || parcelExtra.trim() === "") {
258
+ return null;
259
+ }
260
+ try {
261
+ const legacy = JSON.parse(parcelExtra) as Record<string, unknown>;
262
+ const iv = legacy[LEGACY_EXTRA_IV_KEY];
263
+ if (typeof iv !== "string" || iv === "") {
264
+ return null;
265
+ }
266
+ return { enabled: true, algorithm: AES_GCM_ALGORITHM, iv };
267
+ } catch {
268
+ return null;
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Split a file into chunks. Default: plaintext shards; optional whole-file AES-GCM before split.
274
+ */
73
275
  async function create(file: ArrayBuffer, options: CreateOptions = {}): Promise<CreateResult> {
74
- const chunkSize = options.chunkSize ?? DEFAULT_CHUNK_SIZE;
75
- let key = options.key;
76
- const generatedKey = !key;
77
- if (!key) key = await generateKey();
78
-
79
- const crypto = getCrypto();
80
- const iv = crypto.getRandomValues(new Uint8Array(AES_GCM_IV_LENGTH));
81
-
82
- const encrypted = await encrypt(file, key, iv);
83
- const totalSize = encrypted.byteLength;
84
-
85
- const chunks: ArrayBuffer[] = [];
86
- const chunkList: Chunk[] = [];
87
- let offset = 0;
88
- let index = 0;
89
-
90
- while (offset < totalSize) {
91
- const end = Math.min(offset + chunkSize, totalSize);
92
- const chunkBuffer = encrypted.slice(offset, end);
93
- chunks.push(chunkBuffer);
94
- const checksum = await sha256Hex(chunkBuffer);
95
- chunkList.push({
96
- index,
97
- size: chunkBuffer.byteLength,
98
- checksum,
99
- url: "", // 由 save 填充
100
- });
101
- offset = end;
102
- index += 1;
103
- }
104
-
105
- const checksum = await sha256Hex(file);
106
-
107
- const details: ParcelDetails = {
108
- manifestVersion: MANIFEST_VERSION,
109
- chunkList: chunkList,
110
- checksum,
111
- size: file.byteLength,
112
- };
113
-
114
- const result: CreateResult = {
115
- details,
116
- chunks,
117
- ivBase64: btoa(String.fromCharCode(...iv)),
118
- };
119
- if (generatedKey) result.key = key;
120
- return result;
121
- }
122
-
123
- /** 将 chunk 均匀分布到不同文件系统并存储 */
276
+ const encryptEnabled = options.encrypt === true;
277
+ const splitPayloadSize = encryptEnabled ? file.byteLength + AES_GCM_AUTH_TAG_BYTES : file.byteLength;
278
+ const chunkSize = resolveChunkSize(splitPayloadSize, options.chunkSize);
279
+ const plaintextChecksum = await sha256Hex(file);
280
+
281
+ if (!encryptEnabled) {
282
+ const { chunks, chunkList } = await buildChunkList(file, chunkSize);
283
+ return {
284
+ details: {
285
+ manifestVersion: MANIFEST_VERSION,
286
+ chunkList,
287
+ checksum: plaintextChecksum,
288
+ size: file.byteLength,
289
+ },
290
+ chunks,
291
+ };
292
+ }
293
+
294
+ if (options.passphrase != null && options.key != null) {
295
+ throw new Error("ParcelManager.create: passphrase 与 key 不能同時指定");
296
+ }
297
+
298
+ const cryptoApi = getCrypto();
299
+ const iv = cryptoApi.getRandomValues(new Uint8Array(AES_GCM_IV_LENGTH));
300
+ let key: CryptoKey;
301
+ let generatedKey = false;
302
+ let cryptoMeta: ParcelCrypto;
303
+
304
+ if (options.passphrase != null && options.passphrase !== "") {
305
+ const salt = cryptoApi.getRandomValues(new Uint8Array(16));
306
+ key = await deriveKeyFromPassphrase(options.passphrase, salt, PBKDF2_ITERATIONS);
307
+ cryptoMeta = {
308
+ enabled: true,
309
+ algorithm: AES_GCM_ALGORITHM,
310
+ iv: bytesToBase64(iv),
311
+ keyDerivation: KEY_DERIVATION_PBKDF2,
312
+ salt: bytesToBase64(salt),
313
+ pbkdf2Iterations: PBKDF2_ITERATIONS,
314
+ };
315
+ } else if (options.key != null) {
316
+ key = options.key;
317
+ cryptoMeta = {
318
+ enabled: true,
319
+ algorithm: AES_GCM_ALGORITHM,
320
+ iv: bytesToBase64(iv),
321
+ };
322
+ } else {
323
+ key = await generateKey();
324
+ generatedKey = true;
325
+ cryptoMeta = {
326
+ enabled: true,
327
+ algorithm: AES_GCM_ALGORITHM,
328
+ iv: bytesToBase64(iv),
329
+ };
330
+ }
331
+
332
+ const encrypted = await encrypt(file, key, iv);
333
+ const { chunks, chunkList } = await buildChunkList(encrypted, chunkSize);
334
+
335
+ const result: CreateResult = {
336
+ details: {
337
+ manifestVersion: MANIFEST_VERSION,
338
+ chunkList,
339
+ checksum: plaintextChecksum,
340
+ size: file.byteLength,
341
+ crypto: cryptoMeta,
342
+ },
343
+ chunks,
344
+ };
345
+ if (generatedKey) {
346
+ result.key = key;
347
+ }
348
+ return result;
349
+ }
350
+
351
+ /** Upload chunks round-robin across storage adapters */
124
352
  async function save(
125
- createResult: CreateResult,
126
- fileSystems: StorageAdapter[],
127
- targetBase: ParcelTargetBase
128
- ): Promise<Parcel> {
129
- if (fileSystems.length === 0) throw new Error("ParcelManager.save: fileSystems 不能为空");
130
- const { details, chunks, ivBase64 } = createResult;
131
-
132
- const chunkListWithUrls: Chunk[] = [];
133
- for (let i = 0; i < chunks.length; i++) {
134
- const fs = fileSystems[i % fileSystems.length];
135
- const pathOrKey = `chunk-${i}-${details.checksum.slice(0, 8)}`;
136
- const { url } = await fs.upload(chunks[i], pathOrKey);
137
- chunkListWithUrls.push({ ...details.chunkList[i], url });
138
- }
139
-
140
- const extra = JSON.stringify({ [EXTRA_IV_KEY]: ivBase64 });
141
-
142
- return {
143
- ...targetBase,
144
- category: "parcel" as Parcel["category"],
145
- details: {
146
- ...details,
147
- chunkList: chunkListWithUrls,
148
- },
149
- extra,
150
- };
151
- }
152
-
153
- /** 根据 Parcel 下载各 chunk,重组并校验后返回原文件 */
154
- async function reassembly(parcel: Parcel, key: CryptoKey): Promise<ArrayBuffer> {
155
- const { details } = parcel;
156
- let ivBase64: string | undefined;
157
- try {
158
- const extra = parcel.extra ? JSON.parse(parcel.extra) : {};
159
- ivBase64 = extra[EXTRA_IV_KEY];
160
- } catch {
161
- throw new Error("ParcelManager.reassembly: 无法从 extra 解析 IV");
162
- }
163
- if (!ivBase64 || typeof ivBase64 !== "string") {
164
- throw new Error("ParcelManager.reassembly: Parcel.extra 中缺少 iv");
165
- }
166
-
167
- const iv = Uint8Array.from(atob(ivBase64), (c) => c.charCodeAt(0));
168
- if (iv.length !== AES_GCM_IV_LENGTH) {
169
- throw new Error("ParcelManager.reassembly: IV 长度无效");
170
- }
171
-
172
- const sortedChunks = [...details.chunkList].sort((a, b) => a.index - b.index);
173
- const buffers: ArrayBuffer[] = [];
174
-
175
- for (const chunkMeta of sortedChunks) {
176
- const res = await fetch(chunkMeta.url);
177
- if (!res.ok) throw new Error(`ParcelManager.reassembly: 下载 chunk ${chunkMeta.index} 失败: ${res.status}`);
178
- const chunkBuffer = await res.arrayBuffer();
179
- const chunkChecksum = await sha256Hex(chunkBuffer);
180
- if (chunkChecksum !== chunkMeta.checksum) {
181
- throw new Error(`ParcelManager.reassembly: chunk ${chunkMeta.index} 校验失败 (checksum 不一致)`);
182
- }
183
- buffers.push(chunkBuffer);
184
- }
185
-
186
- const totalEncryptedLength = buffers.reduce((s, b) => s + b.byteLength, 0);
187
- const encrypted = new Uint8Array(totalEncryptedLength);
188
- let offset = 0;
189
- for (const b of buffers) {
190
- encrypted.set(new Uint8Array(b), offset);
191
- offset += b.byteLength;
192
- }
193
-
194
- const decrypted = await decrypt(encrypted.buffer, key, iv);
195
- const fileChecksum = await sha256Hex(decrypted);
196
- if (fileChecksum !== details.checksum) {
197
- throw new Error("ParcelManager.reassembly: 重组后文件校验失败 (sha256 与 details.checksum 不一致)");
198
- }
199
-
200
- return decrypted;
353
+ createResult: CreateResult,
354
+ fileSystems: StorageAdapter[],
355
+ input: ParcelSaveInput,
356
+ ): Promise<TargetDraft<Parcel>> {
357
+ if (fileSystems.length === 0) {
358
+ throw new Error("ParcelManager.save: fileSystems 不能为空");
359
+ }
360
+
361
+ const { details, chunks } = createResult;
362
+ const chunkListWithUrls: Chunk[] = [];
363
+
364
+ for (let i = 0; i < chunks.length; i++) {
365
+ const adapter = fileSystems[i % fileSystems.length];
366
+ const pathOrKey = `chunk-${i}-${details.checksum.slice(0, 8)}`;
367
+ const { url } = await adapter.upload(chunks[i], pathOrKey);
368
+ chunkListWithUrls.push({
369
+ ...details.chunkList[i],
370
+ url,
371
+ provider: adapter.provider,
372
+ });
373
+ }
374
+
375
+ return {
376
+ name: input.name,
377
+ value: input.value,
378
+ tagList: input.tagList ?? [],
379
+ category: CategoryParcel.PARCEL,
380
+ details: {
381
+ ...details,
382
+ chunkList: chunkListWithUrls,
383
+ },
384
+ };
385
+ }
386
+
387
+ async function downloadAndVerifyChunks(chunkList: Chunk[]): Promise<ArrayBuffer[]> {
388
+ const sortedChunks = [...chunkList].sort((a, b) => a.index - b.index);
389
+ const buffers: ArrayBuffer[] = [];
390
+
391
+ for (const chunkMeta of sortedChunks) {
392
+ const res = await fetch(chunkMeta.url);
393
+ if (!res.ok) {
394
+ throw new Error(`ParcelManager.reassemble: 下载 chunk ${chunkMeta.index} 失败: ${res.status}`);
395
+ }
396
+ const chunkBuffer = await res.arrayBuffer();
397
+ const chunkChecksum = await sha256Hex(chunkBuffer);
398
+ if (chunkChecksum !== chunkMeta.checksum) {
399
+ throw new Error(`ParcelManager.reassemble: chunk ${chunkMeta.index} 校验失败 (checksum 不一致`);
400
+ }
401
+ buffers.push(chunkBuffer);
402
+ }
403
+
404
+ return buffers;
405
+ }
406
+
407
+ function verifyPlaintextSize(buffer: ArrayBuffer, details: ParcelDetails): void {
408
+ if (buffer.byteLength !== details.size) {
409
+ throw new Error(
410
+ `ParcelManager.reassemble: 重组后大小与 details.size 不一致(${buffer.byteLength} !== ${details.size})`,
411
+ );
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Fetch chunks from {@link Parcel.details.chunkList}, reassemble, optionally decrypt, verify checksum.
417
+ * Encrypted parcels: pass `{ passphrase }` for PBKDF2 parcels, or `{ key }` for raw-key parcels.
418
+ */
419
+ async function reassemble(parcel: Parcel, options: ReassembleOptions = {}): Promise<ArrayBuffer> {
420
+ const { details } = parcel;
421
+ const encrypted = isEncryptionEnabled(details, parcel.extra);
422
+
423
+ const buffers = await downloadAndVerifyChunks(details.chunkList);
424
+ const merged = concatBuffers(buffers);
425
+
426
+ if (!encrypted) {
427
+ verifyPlaintextSize(merged, details);
428
+ const fileChecksum = await sha256Hex(merged);
429
+ if (fileChecksum !== details.checksum) {
430
+ throw new Error("ParcelManager.reassemble: 重组后文件校验失败 (sha256 与 details.checksum 不一致)");
431
+ }
432
+ return merged;
433
+ }
434
+
435
+ const cryptoMeta = resolveCrypto(details, parcel.extra);
436
+ if (cryptoMeta?.iv == null || cryptoMeta.iv === "") {
437
+ throw new Error("ParcelManager.reassemble: 加密 Parcel 缺少 details.crypto.iv");
438
+ }
439
+
440
+ const iv = base64ToBytes(cryptoMeta.iv);
441
+ if (iv.length !== AES_GCM_IV_LENGTH) {
442
+ throw new Error("ParcelManager.reassemble: IV 长度无效");
443
+ }
444
+
445
+ const key = await resolveDecryptionKey(cryptoMeta, options);
446
+ const usedPassphrase = usesPassphraseDerivation(cryptoMeta);
447
+ const decrypted = await decryptPayload(merged, key, iv, usedPassphrase);
448
+ verifyPlaintextSize(decrypted, details);
449
+ const fileChecksum = await sha256Hex(decrypted);
450
+ if (fileChecksum !== details.checksum) {
451
+ throw new Error(
452
+ usedPassphrase
453
+ ? "ParcelManager.reassemble: 解密后校验失败,口令错误或数据已损坏"
454
+ : "ParcelManager.reassemble: 解密后文件校验失败 (sha256 与 details.checksum 不一致)",
455
+ );
456
+ }
457
+
458
+ return decrypted;
201
459
  }
202
460
 
203
461
  const ParcelManager = {
204
- create,
205
- save,
206
- reassembly,
462
+ create,
463
+ save,
464
+ reassemble,
207
465
  };
208
466
 
209
467
  export { ParcelManager };