@fragno-dev/upload 0.1.1 → 0.1.3

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 (301) hide show
  1. package/README.md +148 -12
  2. package/dist/browser/client/clients.js +17 -9
  3. package/dist/browser/client/clients.js.map +1 -1
  4. package/dist/browser/client/helpers.d.ts +15 -6
  5. package/dist/browser/client/helpers.d.ts.map +1 -1
  6. package/dist/browser/client/helpers.js +176 -30
  7. package/dist/browser/client/helpers.js.map +1 -1
  8. package/dist/browser/client/node_modules/.pnpm/{@nanostores_query@0.3.4_nanostores@1.1.0 → @nanostores_query@0.3.4_nanostores@1.2.0}/node_modules/@nanostores/query/dist/nanoquery.js +6 -6
  9. package/dist/browser/client/node_modules/.pnpm/{@nanostores_query@0.3.4_nanostores@1.1.0 → @nanostores_query@0.3.4_nanostores@1.2.0}/node_modules/@nanostores/query/dist/nanoquery.js.map +1 -1
  10. package/dist/browser/client/node_modules/.pnpm/{@nanostores_solid@1.1.1_nanostores@1.1.0_solid-js@1.9.10 → @nanostores_solid@1.1.1_nanostores@1.2.0_solid-js@1.9.10}/node_modules/@nanostores/solid/dist/index.js +2 -2
  11. package/dist/browser/client/node_modules/.pnpm/{@nanostores_solid@1.1.1_nanostores@1.1.0_solid-js@1.9.10 → @nanostores_solid@1.1.1_nanostores@1.2.0_solid-js@1.9.10}/node_modules/@nanostores/solid/dist/index.js.map +1 -1
  12. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/atom/index.js +2 -1
  13. package/dist/browser/client/node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/atom/index.js.map +1 -0
  14. package/dist/browser/client/node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/clean-stores/index.js +6 -0
  15. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/clean-stores/index.js.map +1 -1
  16. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/computed/index.js +8 -5
  17. package/dist/browser/client/node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/computed/index.js.map +1 -0
  18. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/lifecycle/index.js +1 -1
  19. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/lifecycle/index.js.map +1 -1
  20. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/listen-keys/index.js +1 -1
  21. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/listen-keys/index.js.map +1 -1
  22. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/map/index.js +1 -1
  23. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/map/index.js.map +1 -1
  24. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/task/index.js +1 -1
  25. package/dist/browser/client/node_modules/.pnpm/{nanostores@1.1.0 → nanostores@1.2.0}/node_modules/nanostores/task/index.js.map +1 -1
  26. package/dist/browser/client/node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/warn/index.js +16 -0
  27. package/dist/browser/client/node_modules/.pnpm/nanostores@1.2.0/node_modules/nanostores/warn/index.js.map +1 -0
  28. package/dist/browser/client/packages/fragment-upload/src/definition.js +1 -42
  29. package/dist/browser/client/packages/fragment-upload/src/definition.js.map +1 -1
  30. package/dist/browser/client/packages/fragment-upload/src/routes/files.js +12 -5
  31. package/dist/browser/client/packages/fragment-upload/src/routes/files.js.map +1 -1
  32. package/dist/browser/client/packages/fragment-upload/src/routes/shared.js +3 -4
  33. package/dist/browser/client/packages/fragment-upload/src/routes/shared.js.map +1 -1
  34. package/dist/browser/client/packages/fragment-upload/src/routes/uploads.js +32 -21
  35. package/dist/browser/client/packages/fragment-upload/src/routes/uploads.js.map +1 -1
  36. package/dist/browser/client/packages/fragment-upload/src/schema.js +33 -3
  37. package/dist/browser/client/packages/fragment-upload/src/schema.js.map +1 -1
  38. package/dist/browser/client/packages/fragment-upload/src/types.d.ts +1 -2
  39. package/dist/browser/client/packages/fragment-upload/src/types.d.ts.map +1 -1
  40. package/dist/browser/client/packages/fragno/dist/client/client.js +28 -12
  41. package/dist/browser/client/packages/fragno/dist/client/client.js.map +1 -1
  42. package/dist/browser/client/packages/fragno/dist/client/client.svelte.js +11 -3
  43. package/dist/browser/client/packages/fragno/dist/client/client.svelte.js.map +1 -1
  44. package/dist/browser/client/packages/fragno/dist/client/react.js +104 -12
  45. package/dist/browser/client/packages/fragno/dist/client/react.js.map +1 -1
  46. package/dist/browser/client/packages/fragno/dist/client/solid.js +25 -11
  47. package/dist/browser/client/packages/fragno/dist/client/solid.js.map +1 -1
  48. package/dist/browser/client/packages/fragno/dist/client/vanilla.js +21 -1
  49. package/dist/browser/client/packages/fragno/dist/client/vanilla.js.map +1 -1
  50. package/dist/browser/client/packages/fragno/dist/client/vue.js +19 -11
  51. package/dist/browser/client/packages/fragno/dist/client/vue.js.map +1 -1
  52. package/dist/browser/client/react.d.ts +215 -192
  53. package/dist/browser/client/react.d.ts.map +1 -1
  54. package/dist/browser/client/react.js.map +1 -1
  55. package/dist/browser/client/solid.d.ts +218 -196
  56. package/dist/browser/client/solid.d.ts.map +1 -1
  57. package/dist/browser/client/solid.js.map +1 -1
  58. package/dist/browser/client/svelte.d.ts +216 -193
  59. package/dist/browser/client/svelte.d.ts.map +1 -1
  60. package/dist/browser/client/svelte.js.map +1 -1
  61. package/dist/browser/client/vanilla.d.ts +217 -195
  62. package/dist/browser/client/vanilla.d.ts.map +1 -1
  63. package/dist/browser/client/vanilla.js.map +1 -1
  64. package/dist/browser/client/vue.d.ts +217 -194
  65. package/dist/browser/client/vue.d.ts.map +1 -1
  66. package/dist/browser/client/vue.js.map +1 -1
  67. package/dist/cli/commands/files/delete.d.ts +4 -4
  68. package/dist/cli/commands/files/delete.d.ts.map +1 -1
  69. package/dist/cli/commands/files/delete.js +8 -10
  70. package/dist/cli/commands/files/delete.js.map +1 -1
  71. package/dist/cli/commands/files/download-url.d.ts +4 -4
  72. package/dist/cli/commands/files/download-url.d.ts.map +1 -1
  73. package/dist/cli/commands/files/download-url.js +8 -10
  74. package/dist/cli/commands/files/download-url.js.map +1 -1
  75. package/dist/cli/commands/files/download.d.ts +4 -4
  76. package/dist/cli/commands/files/download.d.ts.map +1 -1
  77. package/dist/cli/commands/files/download.js +10 -12
  78. package/dist/cli/commands/files/download.js.map +1 -1
  79. package/dist/cli/commands/files/get.d.ts +4 -4
  80. package/dist/cli/commands/files/get.d.ts.map +1 -1
  81. package/dist/cli/commands/files/get.js +8 -10
  82. package/dist/cli/commands/files/get.js.map +1 -1
  83. package/dist/cli/commands/files/list.d.ts +4 -4
  84. package/dist/cli/commands/files/list.d.ts.map +1 -1
  85. package/dist/cli/commands/files/list.js +6 -8
  86. package/dist/cli/commands/files/list.js.map +1 -1
  87. package/dist/cli/commands/files/update.d.ts +4 -4
  88. package/dist/cli/commands/files/update.d.ts.map +1 -1
  89. package/dist/cli/commands/files/update.js +8 -10
  90. package/dist/cli/commands/files/update.js.map +1 -1
  91. package/dist/cli/commands/files/upload.d.ts +4 -4
  92. package/dist/cli/commands/files/upload.d.ts.map +1 -1
  93. package/dist/cli/commands/files/upload.js +10 -12
  94. package/dist/cli/commands/files/upload.js.map +1 -1
  95. package/dist/cli/commands/uploads/abort.d.ts +2 -2
  96. package/dist/cli/commands/uploads/abort.d.ts.map +1 -1
  97. package/dist/cli/commands/uploads/abort.js.map +1 -1
  98. package/dist/cli/commands/uploads/complete.d.ts +2 -2
  99. package/dist/cli/commands/uploads/complete.d.ts.map +1 -1
  100. package/dist/cli/commands/uploads/complete.js.map +1 -1
  101. package/dist/cli/commands/uploads/content.d.ts +2 -2
  102. package/dist/cli/commands/uploads/content.d.ts.map +1 -1
  103. package/dist/cli/commands/uploads/content.js +1 -1
  104. package/dist/cli/commands/uploads/content.js.map +1 -1
  105. package/dist/cli/commands/uploads/create.d.ts +4 -4
  106. package/dist/cli/commands/uploads/create.d.ts.map +1 -1
  107. package/dist/cli/commands/uploads/create.js +8 -11
  108. package/dist/cli/commands/uploads/create.js.map +1 -1
  109. package/dist/cli/commands/uploads/get.d.ts +2 -2
  110. package/dist/cli/commands/uploads/get.d.ts.map +1 -1
  111. package/dist/cli/commands/uploads/get.js.map +1 -1
  112. package/dist/cli/commands/uploads/parts-complete.d.ts +2 -2
  113. package/dist/cli/commands/uploads/parts-complete.d.ts.map +1 -1
  114. package/dist/cli/commands/uploads/parts-complete.js.map +1 -1
  115. package/dist/cli/commands/uploads/parts-list.d.ts +2 -2
  116. package/dist/cli/commands/uploads/parts-list.d.ts.map +1 -1
  117. package/dist/cli/commands/uploads/parts-list.js.map +1 -1
  118. package/dist/cli/commands/uploads/parts-urls.d.ts +2 -2
  119. package/dist/cli/commands/uploads/parts-urls.d.ts.map +1 -1
  120. package/dist/cli/commands/uploads/parts-urls.js.map +1 -1
  121. package/dist/cli/commands/uploads/progress.d.ts +2 -2
  122. package/dist/cli/commands/uploads/progress.d.ts.map +1 -1
  123. package/dist/cli/commands/uploads/progress.js.map +1 -1
  124. package/dist/cli/commands/uploads/transfer.d.ts +4 -4
  125. package/dist/cli/commands/uploads/transfer.d.ts.map +1 -1
  126. package/dist/cli/commands/uploads/transfer.js +9 -12
  127. package/dist/cli/commands/uploads/transfer.js.map +1 -1
  128. package/dist/cli/index.d.ts +13 -13
  129. package/dist/cli/index.d.ts.map +1 -1
  130. package/dist/cli/index.js +14 -14
  131. package/dist/cli/index.js.map +1 -1
  132. package/dist/cli/utils/client.js +22 -5
  133. package/dist/cli/utils/client.js.map +1 -1
  134. package/dist/cli/utils/options.js +7 -43
  135. package/dist/cli/utils/options.js.map +1 -1
  136. package/dist/node/cli/commands/files/delete.d.ts +4 -4
  137. package/dist/node/cli/commands/files/delete.d.ts.map +1 -1
  138. package/dist/node/cli/commands/files/delete.js +8 -10
  139. package/dist/node/cli/commands/files/delete.js.map +1 -1
  140. package/dist/node/cli/commands/files/download-url.d.ts +4 -4
  141. package/dist/node/cli/commands/files/download-url.d.ts.map +1 -1
  142. package/dist/node/cli/commands/files/download-url.js +8 -10
  143. package/dist/node/cli/commands/files/download-url.js.map +1 -1
  144. package/dist/node/cli/commands/files/download.d.ts +4 -4
  145. package/dist/node/cli/commands/files/download.d.ts.map +1 -1
  146. package/dist/node/cli/commands/files/download.js +9 -11
  147. package/dist/node/cli/commands/files/download.js.map +1 -1
  148. package/dist/node/cli/commands/files/get.d.ts +4 -4
  149. package/dist/node/cli/commands/files/get.d.ts.map +1 -1
  150. package/dist/node/cli/commands/files/get.js +8 -10
  151. package/dist/node/cli/commands/files/get.js.map +1 -1
  152. package/dist/node/cli/commands/files/list.d.ts +4 -4
  153. package/dist/node/cli/commands/files/list.d.ts.map +1 -1
  154. package/dist/node/cli/commands/files/list.js +6 -8
  155. package/dist/node/cli/commands/files/list.js.map +1 -1
  156. package/dist/node/cli/commands/files/update.d.ts +4 -4
  157. package/dist/node/cli/commands/files/update.d.ts.map +1 -1
  158. package/dist/node/cli/commands/files/update.js +8 -10
  159. package/dist/node/cli/commands/files/update.js.map +1 -1
  160. package/dist/node/cli/commands/files/upload.d.ts +4 -4
  161. package/dist/node/cli/commands/files/upload.d.ts.map +1 -1
  162. package/dist/node/cli/commands/files/upload.js +9 -11
  163. package/dist/node/cli/commands/files/upload.js.map +1 -1
  164. package/dist/node/cli/commands/uploads/abort.d.ts +2 -2
  165. package/dist/node/cli/commands/uploads/abort.d.ts.map +1 -1
  166. package/dist/node/cli/commands/uploads/abort.js.map +1 -1
  167. package/dist/node/cli/commands/uploads/complete.d.ts +2 -2
  168. package/dist/node/cli/commands/uploads/complete.d.ts.map +1 -1
  169. package/dist/node/cli/commands/uploads/complete.js.map +1 -1
  170. package/dist/node/cli/commands/uploads/content.d.ts +2 -2
  171. package/dist/node/cli/commands/uploads/content.d.ts.map +1 -1
  172. package/dist/node/cli/commands/uploads/content.js.map +1 -1
  173. package/dist/node/cli/commands/uploads/create.d.ts +4 -4
  174. package/dist/node/cli/commands/uploads/create.d.ts.map +1 -1
  175. package/dist/node/cli/commands/uploads/create.js +8 -11
  176. package/dist/node/cli/commands/uploads/create.js.map +1 -1
  177. package/dist/node/cli/commands/uploads/get.d.ts +2 -2
  178. package/dist/node/cli/commands/uploads/get.d.ts.map +1 -1
  179. package/dist/node/cli/commands/uploads/get.js.map +1 -1
  180. package/dist/node/cli/commands/uploads/parts-complete.d.ts +2 -2
  181. package/dist/node/cli/commands/uploads/parts-complete.d.ts.map +1 -1
  182. package/dist/node/cli/commands/uploads/parts-complete.js.map +1 -1
  183. package/dist/node/cli/commands/uploads/parts-list.d.ts +2 -2
  184. package/dist/node/cli/commands/uploads/parts-list.d.ts.map +1 -1
  185. package/dist/node/cli/commands/uploads/parts-list.js.map +1 -1
  186. package/dist/node/cli/commands/uploads/parts-urls.d.ts +2 -2
  187. package/dist/node/cli/commands/uploads/parts-urls.d.ts.map +1 -1
  188. package/dist/node/cli/commands/uploads/parts-urls.js.map +1 -1
  189. package/dist/node/cli/commands/uploads/progress.d.ts +2 -2
  190. package/dist/node/cli/commands/uploads/progress.d.ts.map +1 -1
  191. package/dist/node/cli/commands/uploads/progress.js.map +1 -1
  192. package/dist/node/cli/commands/uploads/transfer.d.ts +4 -4
  193. package/dist/node/cli/commands/uploads/transfer.d.ts.map +1 -1
  194. package/dist/node/cli/commands/uploads/transfer.js +8 -11
  195. package/dist/node/cli/commands/uploads/transfer.js.map +1 -1
  196. package/dist/node/cli/index.d.ts +13 -13
  197. package/dist/node/cli/index.d.ts.map +1 -1
  198. package/dist/node/cli/index.js +14 -14
  199. package/dist/node/cli/index.js.map +1 -1
  200. package/dist/node/cli/utils/client.js +22 -5
  201. package/dist/node/cli/utils/client.js.map +1 -1
  202. package/dist/node/cli/utils/options.js +7 -43
  203. package/dist/node/cli/utils/options.js.map +1 -1
  204. package/dist/node/client/clients.d.ts +217 -194
  205. package/dist/node/client/clients.d.ts.map +1 -1
  206. package/dist/node/client/clients.js +17 -9
  207. package/dist/node/client/clients.js.map +1 -1
  208. package/dist/node/client/helpers.d.ts +15 -6
  209. package/dist/node/client/helpers.d.ts.map +1 -1
  210. package/dist/node/client/helpers.js +176 -30
  211. package/dist/node/client/helpers.js.map +1 -1
  212. package/dist/node/client/react.d.ts +217 -194
  213. package/dist/node/client/react.d.ts.map +1 -1
  214. package/dist/node/client/react.js.map +1 -1
  215. package/dist/node/client/solid.d.ts +218 -196
  216. package/dist/node/client/solid.d.ts.map +1 -1
  217. package/dist/node/client/solid.js.map +1 -1
  218. package/dist/node/client/svelte.d.ts +216 -193
  219. package/dist/node/client/svelte.d.ts.map +1 -1
  220. package/dist/node/client/svelte.js.map +1 -1
  221. package/dist/node/client/vanilla.d.ts +217 -195
  222. package/dist/node/client/vanilla.d.ts.map +1 -1
  223. package/dist/node/client/vanilla.js.map +1 -1
  224. package/dist/node/client/vue.d.ts +217 -194
  225. package/dist/node/client/vue.d.ts.map +1 -1
  226. package/dist/node/client/vue.js.map +1 -1
  227. package/dist/node/config.d.ts +6 -6
  228. package/dist/node/config.d.ts.map +1 -1
  229. package/dist/node/config.js.map +1 -1
  230. package/dist/node/definition.d.ts +588 -219
  231. package/dist/node/definition.d.ts.map +1 -1
  232. package/dist/node/definition.js +27 -3
  233. package/dist/node/definition.js.map +1 -1
  234. package/dist/node/file-key.d.ts +19 -0
  235. package/dist/node/file-key.d.ts.map +1 -0
  236. package/dist/node/file-key.js +47 -0
  237. package/dist/node/file-key.js.map +1 -0
  238. package/dist/node/index.d.ts +582 -175
  239. package/dist/node/index.d.ts.map +1 -1
  240. package/dist/node/index.js +3 -2
  241. package/dist/node/index.js.map +1 -1
  242. package/dist/node/routes/files.js +99 -64
  243. package/dist/node/routes/files.js.map +1 -1
  244. package/dist/node/routes/index.d.ts +1497 -721
  245. package/dist/node/routes/index.d.ts.map +1 -1
  246. package/dist/node/routes/shared.js +5 -9
  247. package/dist/node/routes/shared.js.map +1 -1
  248. package/dist/node/routes/uploads.js +105 -47
  249. package/dist/node/routes/uploads.js.map +1 -1
  250. package/dist/node/schema.d.ts +6 -6
  251. package/dist/node/schema.d.ts.map +1 -1
  252. package/dist/node/schema.js +12 -3
  253. package/dist/node/schema.js.map +1 -1
  254. package/dist/node/services/files.d.ts +6 -2
  255. package/dist/node/services/files.d.ts.map +1 -1
  256. package/dist/node/services/files.js +22 -20
  257. package/dist/node/services/files.js.map +1 -1
  258. package/dist/node/services/helpers.js +37 -15
  259. package/dist/node/services/helpers.js.map +1 -1
  260. package/dist/node/services/uploads.d.ts +10 -5
  261. package/dist/node/services/uploads.d.ts.map +1 -1
  262. package/dist/node/services/uploads.js +340 -63
  263. package/dist/node/services/uploads.js.map +1 -1
  264. package/dist/node/storage/fs.d.ts.map +1 -1
  265. package/dist/node/storage/fs.js +16 -10
  266. package/dist/node/storage/fs.js.map +1 -1
  267. package/dist/node/storage/object-key.js +36 -0
  268. package/dist/node/storage/object-key.js.map +1 -0
  269. package/dist/node/storage/r2-binding.d.ts +59 -0
  270. package/dist/node/storage/r2-binding.d.ts.map +1 -0
  271. package/dist/node/storage/r2-binding.js +245 -0
  272. package/dist/node/storage/r2-binding.js.map +1 -0
  273. package/dist/node/storage/r2.d.ts +6 -5
  274. package/dist/node/storage/r2.d.ts.map +1 -1
  275. package/dist/node/storage/s3.d.ts.map +1 -1
  276. package/dist/node/storage/s3.js +16 -10
  277. package/dist/node/storage/s3.js.map +1 -1
  278. package/dist/node/storage/types.d.ts +6 -5
  279. package/dist/node/storage/types.d.ts.map +1 -1
  280. package/dist/node/types.d.ts +1 -2
  281. package/dist/node/types.d.ts.map +1 -1
  282. package/package.json +26 -46
  283. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/atom/index.js.map +0 -1
  284. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/clean-stores/index.js +0 -6
  285. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/computed/index.js.map +0 -1
  286. package/dist/browser/client/packages/fragment-upload/src/keys.d.ts +0 -7
  287. package/dist/browser/client/packages/fragment-upload/src/keys.d.ts.map +0 -1
  288. package/dist/browser/client/packages/fragment-upload/src/keys.js +0 -28
  289. package/dist/browser/client/packages/fragment-upload/src/keys.js.map +0 -1
  290. package/dist/browser/index-BdjKPO4J.d.ts +0 -177
  291. package/dist/browser/index-BdjKPO4J.d.ts.map +0 -1
  292. package/dist/browser/index.js +0 -3
  293. package/dist/browser/src-vdNJUbjT.js +0 -1982
  294. package/dist/browser/src-vdNJUbjT.js.map +0 -1
  295. package/dist/cli/keys.js +0 -32
  296. package/dist/cli/keys.js.map +0 -1
  297. package/dist/node/keys.d.ts +0 -12
  298. package/dist/node/keys.d.ts.map +0 -1
  299. package/dist/node/keys.js +0 -63
  300. package/dist/node/keys.js.map +0 -1
  301. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"uploads.js","names":["DEFAULT_VISIBILITY: FileVisibility"],"sources":["../../../src/services/uploads.ts"],"sourcesContent":["import { isDeepStrictEqual } from \"node:util\";\nimport type { TableToColumnValues } from \"@fragno-dev/db/query\";\nimport type { DatabaseServiceContext } from \"@fragno-dev/db\";\nimport type {\n FileHookPayload,\n UploadFragmentResolvedConfig,\n UploadTimeoutPayload,\n} from \"../config\";\nimport type { FileKeyEncoded, FileKeyParts } from \"../keys\";\nimport { uploadSchema } from \"../schema\";\nimport type { UploadChecksum } from \"../storage/types\";\nimport type { FileStatus, FileVisibility, UploadStatus, UploadStrategy } from \"../types\";\nimport { resolveFileKeyInput } from \"./helpers\";\n\nexport type CreateUploadInput = {\n keyParts?: FileKeyParts;\n fileKey?: FileKeyEncoded;\n filename: string;\n sizeBytes: number;\n contentType: string;\n checksum?: UploadChecksum | null;\n tags?: string[];\n visibility?: FileVisibility;\n uploaderId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type UploadProgressInput = {\n bytesUploaded?: number;\n partsUploaded?: number;\n};\n\nexport type CompletePartsInput = {\n parts: { partNumber: number; etag: string; sizeBytes: number }[];\n};\n\nexport type CreateUploadResult = {\n uploadId: string;\n fileKey: FileKeyEncoded;\n fileKeyParts: FileKeyParts;\n status: \"created\" | \"in_progress\";\n strategy: UploadStrategy;\n expiresAt: Date;\n upload: {\n mode: \"single\" | \"multipart\";\n transport: \"direct\" | \"proxy\";\n uploadUrl?: string;\n uploadHeaders?: Record<string, string>;\n partSizeBytes?: number;\n maxParts?: number;\n partsEndpoint?: string;\n completeEndpoint: string;\n contentEndpoint?: string;\n };\n};\n\ntype UploadRow = TableToColumnValues<typeof uploadSchema.tables.upload>;\n\nconst DEFAULT_VISIBILITY: FileVisibility = \"private\";\n\ntype UploadHooks = {\n onFileReady: (payload: FileHookPayload) => void | Promise<void>;\n onUploadFailed: (payload: FileHookPayload) => void | Promise<void>;\n onFileDeleted: (payload: FileHookPayload) => void | Promise<void>;\n onUploadTimeout: (payload: UploadTimeoutPayload) => void | Promise<void>;\n};\n\ntype UploadServiceContext = DatabaseServiceContext<UploadHooks>;\n\nconst isTerminalUploadStatus = (status: UploadStatus) =>\n status === \"completed\" || status === \"aborted\" || status === \"failed\" || status === \"expired\";\n\nconst toBigInt = (value: number | bigint) => (typeof value === \"bigint\" ? value : BigInt(value));\nconst MAX_SAFE_SIZE_BYTES = BigInt(Number.MAX_SAFE_INTEGER);\nconst toSafeNumber = (value: bigint) => {\n if (value > MAX_SAFE_SIZE_BYTES) {\n throw new Error(\"INVALID_REQUEST\");\n }\n return Number(value);\n};\n\nconst ensureActiveUpload = (upload: UploadRow, now: Date) => {\n if (upload.status === \"expired\") {\n throw new Error(\"UPLOAD_EXPIRED\");\n }\n\n if (isTerminalUploadStatus(upload.status as UploadStatus)) {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n\n if (upload.expiresAt.getTime() <= now.getTime()) {\n throw new Error(\"UPLOAD_EXPIRED\");\n }\n};\n\nconst ensureMultipartUpload = (upload: UploadRow) => {\n if (upload.strategy !== \"direct-multipart\") {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n\n if (!upload.storageUploadId || !upload.partSizeBytes) {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n};\n\ntype NormalizedUploadInput = {\n keyParts?: FileKeyParts;\n fileKey?: FileKeyEncoded;\n filename: string;\n sizeBytes: number;\n contentType: string;\n checksum: UploadChecksum | null;\n tags: string[] | null;\n visibility: FileVisibility;\n uploaderId: string | null;\n metadata: Record<string, unknown> | null;\n expectedSizeBytes: bigint;\n};\n\nconst normalizeUploadInput = (input: CreateUploadInput): NormalizedUploadInput => {\n return {\n ...input,\n uploaderId: input.uploaderId ?? null,\n visibility: input.visibility ?? DEFAULT_VISIBILITY,\n checksum: input.checksum ?? null,\n tags: input.tags ?? null,\n metadata: input.metadata ?? null,\n expectedSizeBytes: toBigInt(input.sizeBytes),\n };\n};\n\nconst pickActiveUpload = (uploads: UploadRow[], now: Date) => {\n const active = uploads.filter(\n (upload) =>\n !isTerminalUploadStatus(upload.status as UploadStatus) &&\n upload.expiresAt.getTime() > now.getTime(),\n );\n if (active.length === 0) {\n return null;\n }\n return active.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())[0];\n};\n\nconst uploadMetadataMatches = (upload: UploadRow, input: NormalizedUploadInput) => {\n return (\n upload.filename === input.filename &&\n upload.contentType === input.contentType &&\n upload.visibility === input.visibility &&\n (upload.uploaderId ?? null) === input.uploaderId &&\n upload.expectedSizeBytes === input.expectedSizeBytes &&\n isDeepStrictEqual(upload.checksum ?? null, input.checksum) &&\n isDeepStrictEqual(upload.tags ?? null, input.tags) &&\n isDeepStrictEqual(upload.metadata ?? null, input.metadata)\n );\n};\n\nconst buildCreateUploadResult = (\n storage: UploadFragmentResolvedConfig[\"storage\"],\n upload: UploadRow,\n): CreateUploadResult => {\n const uploadId = upload.id.toString();\n const strategy = upload.strategy as UploadStrategy;\n const resolved = resolveFileKeyInput({ fileKey: upload.fileKey });\n const uploadHeaders = upload.uploadHeaders as Record<string, string> | null;\n\n return {\n uploadId,\n fileKey: upload.fileKey,\n fileKeyParts: resolved.fileKeyParts,\n status: upload.status as CreateUploadResult[\"status\"],\n strategy,\n expiresAt: upload.expiresAt,\n upload: {\n mode: strategy === \"direct-multipart\" ? \"multipart\" : \"single\",\n transport: strategy === \"proxy\" ? \"proxy\" : \"direct\",\n uploadUrl: upload.uploadUrl ?? undefined,\n uploadHeaders: uploadHeaders ?? undefined,\n partSizeBytes: upload.partSizeBytes ?? undefined,\n maxParts: storage.limits?.maxMultipartParts,\n partsEndpoint: strategy === \"direct-multipart\" ? `/uploads/${uploadId}/parts` : undefined,\n completeEndpoint: `/uploads/${uploadId}/complete`,\n contentEndpoint: strategy === \"proxy\" ? `/uploads/${uploadId}/content` : undefined,\n },\n };\n};\n\nconst buildCreateUploadResultFromInit = (\n storage: UploadFragmentResolvedConfig[\"storage\"],\n resolved: ReturnType<typeof resolveFileKeyInput>,\n storageInit: Awaited<ReturnType<UploadFragmentResolvedConfig[\"storage\"][\"initUpload\"]>>,\n uploadId: string,\n): CreateUploadResult => {\n const strategy = storageInit.strategy;\n\n return {\n uploadId,\n fileKey: resolved.fileKey,\n fileKeyParts: resolved.fileKeyParts,\n status: \"created\",\n strategy,\n expiresAt: storageInit.expiresAt,\n upload: {\n mode: strategy === \"direct-multipart\" ? \"multipart\" : \"single\",\n transport: strategy === \"proxy\" ? \"proxy\" : \"direct\",\n uploadUrl: storageInit.uploadUrl,\n uploadHeaders: storageInit.uploadHeaders,\n partSizeBytes: storageInit.partSizeBytes,\n maxParts: storage.limits?.maxMultipartParts,\n partsEndpoint: strategy === \"direct-multipart\" ? `/uploads/${uploadId}/parts` : undefined,\n completeEndpoint: `/uploads/${uploadId}/complete`,\n contentEndpoint: strategy === \"proxy\" ? `/uploads/${uploadId}/content` : undefined,\n },\n };\n};\n\nconst buildUploadHookPayload = (upload: UploadRow, sizeBytes?: bigint): FileHookPayload => {\n const fileKeyParts = resolveFileKeyInput({ fileKey: upload.fileKey }).fileKeyParts;\n const resolvedSizeBytes = sizeBytes ?? upload.expectedSizeBytes;\n return {\n fileKey: upload.fileKey,\n fileKeyParts,\n uploadId: upload.id.toString(),\n uploaderId: upload.uploaderId ?? null,\n sizeBytes: toSafeNumber(resolvedSizeBytes),\n contentType: upload.contentType,\n };\n};\n\nexport const createUploadServices = (config: UploadFragmentResolvedConfig) => {\n const storage = config.storage;\n\n return {\n checkUploadAvailability: function (\n this: UploadServiceContext,\n input: CreateUploadInput,\n options: { allowIdempotentReuse: boolean },\n ) {\n const resolved = resolveFileKeyInput(input);\n const now = new Date();\n const normalized = normalizeUploadInput(input);\n const hasChecksum = normalized.checksum !== null;\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow\n .findFirst(\"file\", (b) =>\n b.whereIndex(\"idx_file_key\", (eb) => eb(\"fileKey\", \"=\", resolved.fileKey)),\n )\n .find(\"upload\", (b) =>\n b.whereIndex(\"idx_upload_file_key\", (eb) => eb(\"fileKey\", \"=\", resolved.fileKey)),\n ),\n )\n .transformRetrieve(([file, uploads]) => {\n if (file) {\n throw new Error(\"FILE_ALREADY_EXISTS\");\n }\n\n const activeUpload = pickActiveUpload(uploads as UploadRow[], now);\n if (!activeUpload) {\n return null;\n }\n\n if (!options.allowIdempotentReuse || !hasChecksum) {\n throw new Error(\"UPLOAD_ALREADY_ACTIVE\");\n }\n\n if (!uploadMetadataMatches(activeUpload, normalized)) {\n throw new Error(\"UPLOAD_METADATA_MISMATCH\");\n }\n\n return buildCreateUploadResult(storage, activeUpload);\n })\n .build();\n },\n\n createUploadRecord: function (\n this: UploadServiceContext,\n input: CreateUploadInput & {\n storageInit: Awaited<ReturnType<typeof storage.initUpload>>;\n allowIdempotentReuse: boolean;\n },\n ) {\n const resolved = resolveFileKeyInput(input);\n const now = new Date();\n const normalized = normalizeUploadInput(input);\n const hasChecksum = normalized.checksum !== null;\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow\n .findFirst(\"file\", (b) =>\n b.whereIndex(\"idx_file_key\", (eb) => eb(\"fileKey\", \"=\", resolved.fileKey)),\n )\n .find(\"upload\", (b) =>\n b.whereIndex(\"idx_upload_file_key\", (eb) => eb(\"fileKey\", \"=\", resolved.fileKey)),\n ),\n )\n .mutate(({ uow, retrieveResult: [existingFile, uploads] }) => {\n if (existingFile) {\n throw new Error(\"FILE_ALREADY_EXISTS\");\n }\n\n const activeUpload = pickActiveUpload(uploads as UploadRow[], now);\n if (activeUpload) {\n if (!input.allowIdempotentReuse || !hasChecksum) {\n throw new Error(\"UPLOAD_ALREADY_ACTIVE\");\n }\n\n if (!uploadMetadataMatches(activeUpload, normalized)) {\n throw new Error(\"UPLOAD_METADATA_MISMATCH\");\n }\n\n return {\n reused: true as const,\n existingUpload: activeUpload,\n };\n }\n\n const storageInit = input.storageInit;\n\n const uploadId = uow.create(\"upload\", {\n fileKey: resolved.fileKey,\n uploaderId: normalized.uploaderId,\n filename: normalized.filename,\n expectedSizeBytes: normalized.expectedSizeBytes,\n contentType: normalized.contentType,\n checksum: normalized.checksum,\n visibility: normalized.visibility,\n tags: normalized.tags,\n metadata: normalized.metadata,\n status: \"created\",\n strategy: storageInit.strategy,\n storageProvider: storage.name,\n storageKey: storageInit.storageKey,\n storageUploadId: storageInit.storageUploadId ?? null,\n uploadUrl: storageInit.uploadUrl ?? null,\n uploadHeaders: storageInit.uploadHeaders ?? null,\n bytesUploaded: 0n,\n partsUploaded: 0,\n partSizeBytes: storageInit.partSizeBytes ?? null,\n expiresAt: storageInit.expiresAt,\n createdAt: now,\n updatedAt: now,\n completedAt: null,\n errorCode: null,\n errorMessage: null,\n });\n\n uow.triggerHook(\n \"onUploadTimeout\",\n {\n uploadId: uploadId.toString(),\n fileKey: resolved.fileKey,\n fileKeyParts: resolved.fileKeyParts,\n },\n { processAt: storageInit.expiresAt },\n );\n\n return {\n reused: false as const,\n uploadId: uploadId.toString(),\n resolved,\n storageInit,\n };\n })\n .transform(({ mutateResult }) => {\n if (mutateResult.reused) {\n return {\n reused: true as const,\n result: buildCreateUploadResult(storage, mutateResult.existingUpload),\n };\n }\n\n return {\n reused: false as const,\n result: buildCreateUploadResultFromInit(\n storage,\n mutateResult.resolved,\n mutateResult.storageInit,\n mutateResult.uploadId,\n ),\n };\n })\n .build();\n },\n\n getUploadStatus: function (this: UploadServiceContext, uploadId: string) {\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId))),\n )\n .transformRetrieve(([upload]) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n return upload;\n })\n .build();\n },\n\n getUploadParts: function (this: UploadServiceContext, uploadId: string) {\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.find(\"upload_part\", (b) =>\n b.whereIndex(\"idx_upload_part_upload\", (eb) => eb(\"uploadId\", \"=\", uploadId)),\n ),\n )\n .transformRetrieve(([parts]) => parts)\n .build();\n },\n\n recordUploadProgress: function (\n this: UploadServiceContext,\n uploadId: string,\n input: UploadProgressInput,\n ) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId))),\n )\n .mutate(({ uow, retrieveResult: [upload] }) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n\n ensureActiveUpload(upload, now);\n\n const nextBytes =\n input.bytesUploaded !== undefined\n ? (() => {\n const inputBigInt = BigInt(input.bytesUploaded);\n return upload.bytesUploaded > inputBigInt ? upload.bytesUploaded : inputBigInt;\n })()\n : upload.bytesUploaded;\n const nextParts =\n input.partsUploaded !== undefined\n ? Math.max(upload.partsUploaded, input.partsUploaded)\n : upload.partsUploaded;\n\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n bytesUploaded: nextBytes,\n partsUploaded: nextParts,\n status: \"in_progress\",\n updatedAt: now,\n })\n .check(),\n );\n\n return { bytesUploaded: nextBytes, partsUploaded: nextParts };\n })\n .build();\n },\n\n recordUploadParts: function (\n this: UploadServiceContext,\n uploadId: string,\n input: CompletePartsInput,\n ) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow\n .findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId)))\n .find(\"upload_part\", (b) =>\n b.whereIndex(\"idx_upload_part_upload\", (eb) => eb(\"uploadId\", \"=\", uploadId)),\n ),\n )\n .mutate(({ uow, retrieveResult: [upload, parts] }) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n\n ensureActiveUpload(upload, now);\n ensureMultipartUpload(upload);\n\n const existing = new Set(parts.map((part) => part.partNumber));\n const existingBytes = parts.reduce((sum, part) => sum + toBigInt(part.sizeBytes), 0n);\n let addedParts = 0;\n let addedBytes = 0n;\n\n for (const part of input.parts) {\n if (existing.has(part.partNumber)) {\n continue;\n }\n existing.add(part.partNumber);\n addedParts += 1;\n addedBytes += toBigInt(part.sizeBytes);\n\n uow.create(\"upload_part\", {\n uploadId: upload.id,\n partNumber: part.partNumber,\n etag: part.etag,\n sizeBytes: toBigInt(part.sizeBytes),\n createdAt: now,\n });\n }\n\n const totalParts = existing.size;\n const totalBytes = existingBytes + addedBytes;\n const nextParts = Math.max(upload.partsUploaded, totalParts);\n const nextBytes = upload.bytesUploaded > totalBytes ? upload.bytesUploaded : totalBytes;\n\n if (addedParts > 0) {\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n partsUploaded: nextParts,\n bytesUploaded: nextBytes,\n status: \"in_progress\",\n updatedAt: now,\n })\n .check(),\n );\n }\n\n return {\n partsUploaded: nextParts,\n bytesUploaded: nextBytes,\n };\n })\n .build();\n },\n\n markUploadComplete: function (\n this: UploadServiceContext,\n uploadId: string,\n fileKey: FileKeyEncoded,\n options?: { sizeBytes?: bigint },\n ) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow\n .findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId)))\n .findFirst(\"file\", (b) =>\n b.whereIndex(\"idx_file_key\", (eb) => eb(\"fileKey\", \"=\", fileKey)),\n ),\n )\n .mutate(({ uow, retrieveResult: [upload, existingFile] }) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n\n ensureActiveUpload(upload, now);\n\n if (existingFile) {\n throw new Error(\"FILE_ALREADY_EXISTS\");\n }\n\n const finalSizeBytes = options?.sizeBytes ?? upload.expectedSizeBytes;\n\n const updatedUpload = {\n ...upload,\n status: \"completed\" as UploadStatus,\n updatedAt: now,\n completedAt: now,\n bytesUploaded: finalSizeBytes,\n };\n\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n status: updatedUpload.status,\n updatedAt: updatedUpload.updatedAt,\n completedAt: updatedUpload.completedAt,\n bytesUploaded: updatedUpload.bytesUploaded,\n })\n .check(),\n );\n\n const createdFile = {\n fileKey: upload.fileKey,\n uploaderId: upload.uploaderId ?? null,\n filename: upload.filename,\n sizeBytes: finalSizeBytes,\n contentType: upload.contentType,\n checksum: upload.checksum ?? null,\n visibility: upload.visibility,\n tags: upload.tags ?? null,\n metadata: upload.metadata ?? null,\n status: \"ready\" as FileStatus,\n storageProvider: upload.storageProvider,\n storageKey: upload.storageKey,\n createdAt: now,\n updatedAt: now,\n completedAt: now,\n deletedAt: null,\n errorCode: null,\n errorMessage: null,\n };\n\n const fileId = uow.create(\"file\", createdFile);\n\n uow.triggerHook(\"onFileReady\", buildUploadHookPayload(upload, finalSizeBytes));\n\n return {\n upload: updatedUpload,\n file: {\n id: fileId,\n ...createdFile,\n },\n };\n })\n .build();\n },\n\n markUploadFailed: function (\n this: UploadServiceContext,\n uploadId: string,\n errorCode: string,\n errorMessage?: string | null,\n ) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId))),\n )\n .mutate(({ uow, retrieveResult: [upload] }) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n\n if (isTerminalUploadStatus(upload.status as UploadStatus)) {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n\n const updatedUpload = {\n ...upload,\n status: \"failed\" as UploadStatus,\n updatedAt: now,\n errorCode,\n errorMessage: errorMessage ?? null,\n };\n\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n status: updatedUpload.status,\n updatedAt: updatedUpload.updatedAt,\n errorCode: updatedUpload.errorCode,\n errorMessage: updatedUpload.errorMessage,\n })\n .check(),\n );\n\n uow.triggerHook(\"onUploadFailed\", buildUploadHookPayload(upload));\n\n return { upload: updatedUpload };\n })\n .build();\n },\n\n markUploadAborted: function (this: UploadServiceContext, uploadId: string) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId))),\n )\n .mutate(({ uow, retrieveResult: [upload] }) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n\n if (isTerminalUploadStatus(upload.status as UploadStatus)) {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n\n const updatedUpload = {\n ...upload,\n status: \"aborted\" as UploadStatus,\n updatedAt: now,\n errorCode: \"UPLOAD_ABORTED\",\n };\n\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n status: updatedUpload.status,\n updatedAt: updatedUpload.updatedAt,\n errorCode: updatedUpload.errorCode,\n })\n .check(),\n );\n\n uow.triggerHook(\"onUploadFailed\", buildUploadHookPayload(upload));\n\n return { upload: updatedUpload };\n })\n .build();\n },\n\n getUploadStorageInfo: function (this: UploadServiceContext, uploadId: string) {\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId))),\n )\n .transformRetrieve(([upload]) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n return upload;\n })\n .build();\n },\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"uploads.js","names":["DEFAULT_VISIBILITY: FileVisibility"],"sources":["../../../src/services/uploads.ts"],"sourcesContent":["import { isDeepStrictEqual } from \"node:util\";\n\nimport type { TableToColumnValues } from \"@fragno-dev/db/query\";\n\nimport type { DatabaseServiceContext } from \"@fragno-dev/db\";\n\nimport type {\n FileHookPayload,\n UploadFragmentResolvedConfig,\n UploadTimeoutPayload,\n} from \"../config\";\nimport { uploadSchema } from \"../schema\";\nimport type { UploadChecksum } from \"../storage/types\";\nimport type { FileStatus, FileVisibility, UploadStatus, UploadStrategy } from \"../types\";\nimport { resolveFileKeyInput } from \"./helpers\";\n\nexport type CreateUploadInput = {\n provider: string;\n keyParts?: readonly (string | number)[];\n fileKey?: string;\n filename: string;\n sizeBytes: number;\n contentType: string;\n checksum?: UploadChecksum | null;\n tags?: string[];\n visibility?: FileVisibility;\n uploaderId?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type UploadProgressInput = {\n bytesUploaded?: number;\n partsUploaded?: number;\n};\n\nexport type CompletePartsInput = {\n parts: { partNumber: number; etag: string; sizeBytes: number }[];\n};\n\nexport type CreateUploadResult = {\n uploadId: string;\n fileKey: string;\n provider: string;\n status: \"created\" | \"in_progress\";\n strategy: UploadStrategy;\n expiresAt: Date;\n upload: {\n mode: \"single\" | \"multipart\";\n transport: \"direct\" | \"proxy\";\n uploadUrl?: string;\n uploadHeaders?: Record<string, string>;\n partSizeBytes?: number;\n maxParts?: number;\n statusEndpoint: string;\n progressEndpoint: string;\n partsEndpoint?: string;\n partsCompleteEndpoint?: string;\n completeEndpoint: string;\n abortEndpoint: string;\n contentEndpoint?: string;\n };\n};\n\ntype UploadRow = TableToColumnValues<typeof uploadSchema.tables.upload>;\ntype FileRow = TableToColumnValues<typeof uploadSchema.tables.file>;\n\nconst DEFAULT_VISIBILITY: FileVisibility = \"private\";\n\ntype UploadHooks = {\n onFileReady: (payload: FileHookPayload) => void | Promise<void>;\n onUploadFailed: (payload: FileHookPayload) => void | Promise<void>;\n onFileDeleted: (payload: FileHookPayload) => void | Promise<void>;\n cleanupStorageObject: (payload: FileHookPayload) => void | Promise<void>;\n onUploadTimeout: (payload: UploadTimeoutPayload) => void | Promise<void>;\n};\n\ntype UploadServiceContext = DatabaseServiceContext<UploadHooks>;\n\nconst isTerminalUploadStatus = (status: UploadStatus) =>\n status === \"completed\" || status === \"aborted\" || status === \"failed\" || status === \"expired\";\n\nconst toBigInt = (value: number | bigint) => (typeof value === \"bigint\" ? value : BigInt(value));\nconst MAX_SAFE_SIZE_BYTES = BigInt(Number.MAX_SAFE_INTEGER);\nconst toSafeNumber = (value: bigint) => {\n if (value > MAX_SAFE_SIZE_BYTES) {\n throw new Error(\"INVALID_REQUEST\");\n }\n return Number(value);\n};\n\nconst ensureActiveUpload = (upload: UploadRow, now: Date) => {\n if (upload.status === \"expired\") {\n throw new Error(\"UPLOAD_EXPIRED\");\n }\n\n if (isTerminalUploadStatus(upload.status as UploadStatus)) {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n\n if (upload.expiresAt.getTime() <= now.getTime()) {\n throw new Error(\"UPLOAD_EXPIRED\");\n }\n};\n\nconst ensureMultipartUpload = (upload: UploadRow) => {\n if (upload.strategy !== \"direct-multipart\") {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n\n if (!upload.storageUploadId || !upload.partSizeBytes) {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n};\n\ntype NormalizedUploadInput = {\n provider: string;\n keyParts?: readonly (string | number)[];\n fileKey?: string;\n filename: string;\n sizeBytes: number;\n contentType: string;\n checksum: UploadChecksum | null;\n tags: string[] | null;\n visibility: FileVisibility;\n uploaderId: string | null;\n metadata: Record<string, unknown> | null;\n expectedSizeBytes: bigint;\n};\n\nconst normalizeUploadInput = (input: CreateUploadInput): NormalizedUploadInput => {\n return {\n ...input,\n provider: input.provider,\n uploaderId: input.uploaderId ?? null,\n visibility: input.visibility ?? DEFAULT_VISIBILITY,\n checksum: input.checksum ?? null,\n tags: input.tags ?? null,\n metadata: input.metadata ?? null,\n expectedSizeBytes: toBigInt(input.sizeBytes),\n };\n};\n\nconst pickActiveUpload = (uploads: UploadRow[], now: Date) => {\n const active = uploads.filter(\n (upload) =>\n !isTerminalUploadStatus(upload.status as UploadStatus) &&\n upload.expiresAt.getTime() > now.getTime(),\n );\n if (active.length === 0) {\n return null;\n }\n return active.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime())[0];\n};\n\nconst uploadMetadataMatches = (upload: UploadRow, input: NormalizedUploadInput) => {\n return (\n upload.filename === input.filename &&\n upload.contentType === input.contentType &&\n upload.visibility === input.visibility &&\n (upload.uploaderId ?? null) === input.uploaderId &&\n upload.expectedSizeBytes === input.expectedSizeBytes &&\n isDeepStrictEqual(upload.checksum ?? null, input.checksum) &&\n isDeepStrictEqual(upload.tags ?? null, input.tags) &&\n isDeepStrictEqual(upload.metadata ?? null, input.metadata)\n );\n};\n\ntype BuildUploadSessionRouteDataInput = {\n uploadId: string;\n provider: string;\n strategy: UploadStrategy;\n uploadUrl?: string;\n uploadHeaders?: Record<string, string>;\n partSizeBytes?: number;\n};\n\nconst buildProviderStickyUploadEndpoint = (uploadId: string, provider: string, suffix = \"\") => {\n const query = new URLSearchParams({ provider }).toString();\n return `/uploads/${uploadId}${suffix}?${query}`;\n};\n\nexport const buildUploadSessionRouteData = (\n storage: UploadFragmentResolvedConfig[\"storage\"],\n input: BuildUploadSessionRouteDataInput,\n): Pick<CreateUploadResult, \"provider\" | \"upload\"> => {\n const { uploadId, provider, strategy } = input;\n\n return {\n provider,\n upload: {\n mode: strategy === \"direct-multipart\" ? \"multipart\" : \"single\",\n transport: strategy === \"proxy\" ? \"proxy\" : \"direct\",\n uploadUrl: input.uploadUrl,\n uploadHeaders: input.uploadHeaders,\n partSizeBytes: input.partSizeBytes,\n maxParts: storage.limits?.maxMultipartParts,\n statusEndpoint: buildProviderStickyUploadEndpoint(uploadId, provider),\n progressEndpoint: buildProviderStickyUploadEndpoint(uploadId, provider, \"/progress\"),\n partsEndpoint:\n strategy === \"direct-multipart\"\n ? buildProviderStickyUploadEndpoint(uploadId, provider, \"/parts\")\n : undefined,\n partsCompleteEndpoint:\n strategy === \"direct-multipart\"\n ? buildProviderStickyUploadEndpoint(uploadId, provider, \"/parts/complete\")\n : undefined,\n completeEndpoint: buildProviderStickyUploadEndpoint(uploadId, provider, \"/complete\"),\n abortEndpoint: buildProviderStickyUploadEndpoint(uploadId, provider, \"/abort\"),\n contentEndpoint:\n strategy === \"proxy\"\n ? buildProviderStickyUploadEndpoint(uploadId, provider, \"/content\")\n : undefined,\n },\n };\n};\n\nconst buildCreateUploadResult = (\n storage: UploadFragmentResolvedConfig[\"storage\"],\n upload: UploadRow,\n): CreateUploadResult => {\n const uploadId = upload.id.toString();\n const strategy = upload.strategy as UploadStrategy;\n const uploadHeaders = upload.uploadHeaders as Record<string, string> | null;\n\n return {\n uploadId,\n fileKey: upload.key,\n ...buildUploadSessionRouteData(storage, {\n uploadId,\n provider: upload.provider,\n strategy,\n uploadUrl: upload.uploadUrl ?? undefined,\n uploadHeaders: uploadHeaders ?? undefined,\n partSizeBytes: upload.partSizeBytes ?? undefined,\n }),\n status: upload.status as CreateUploadResult[\"status\"],\n strategy,\n expiresAt: upload.expiresAt,\n };\n};\n\nconst buildCreateUploadResultFromInit = (\n storage: UploadFragmentResolvedConfig[\"storage\"],\n provider: string,\n resolved: ReturnType<typeof resolveFileKeyInput>,\n storageInit: Awaited<ReturnType<UploadFragmentResolvedConfig[\"storage\"][\"initUpload\"]>>,\n uploadId: string,\n): CreateUploadResult => {\n const strategy = storageInit.strategy;\n\n return {\n uploadId,\n fileKey: resolved.fileKey,\n ...buildUploadSessionRouteData(storage, {\n uploadId,\n provider,\n strategy,\n uploadUrl: storageInit.uploadUrl,\n uploadHeaders: storageInit.uploadHeaders,\n partSizeBytes: storageInit.partSizeBytes,\n }),\n status: \"created\",\n strategy,\n expiresAt: storageInit.expiresAt,\n };\n};\n\nconst buildUploadHookPayload = (upload: UploadRow, sizeBytes?: bigint): FileHookPayload => {\n const resolvedSizeBytes = sizeBytes ?? upload.expectedSizeBytes;\n return {\n provider: upload.provider,\n fileKey: upload.key,\n objectKey: upload.objectKey,\n uploadId: upload.id.toString(),\n uploaderId: upload.uploaderId ?? null,\n sizeBytes: toSafeNumber(resolvedSizeBytes),\n contentType: upload.contentType,\n };\n};\n\nconst buildFileHookPayload = (file: FileRow): FileHookPayload => ({\n provider: file.provider,\n fileKey: file.key,\n objectKey: file.objectKey,\n uploaderId: file.uploaderId ?? null,\n sizeBytes: toSafeNumber(file.sizeBytes),\n contentType: file.contentType,\n});\n\nconst ensureReplacementUsesDistinctObjectKey = (\n file: Pick<FileRow, \"objectKey\">,\n nextObjectKey: string,\n) => {\n if (file.objectKey === nextObjectKey) {\n throw new Error(\"STORAGE_ERROR\");\n }\n};\n\nconst shouldCleanupSupersededObject = (\n file: Pick<FileRow, \"status\" | \"objectKey\">,\n nextObjectKey: string,\n) => file.status !== \"deleted\" && file.objectKey !== nextObjectKey;\n\nexport const createUploadServices = (config: UploadFragmentResolvedConfig) => {\n const storage = config.storage;\n\n return {\n checkUploadAvailability: function (\n this: UploadServiceContext,\n input: CreateUploadInput,\n options: { allowIdempotentReuse: boolean },\n ) {\n const resolved = resolveFileKeyInput(input);\n const now = new Date();\n const normalized = normalizeUploadInput(input);\n const hasChecksum = normalized.checksum !== null;\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.find(\"upload\", (b) =>\n b.whereIndex(\"idx_upload_provider_key\", (eb) =>\n eb.and(eb(\"provider\", \"=\", normalized.provider), eb(\"key\", \"=\", resolved.fileKey)),\n ),\n ),\n )\n .transformRetrieve(([uploads]) => {\n const activeUpload = pickActiveUpload(uploads as UploadRow[], now);\n if (\n activeUpload &&\n options.allowIdempotentReuse &&\n hasChecksum &&\n uploadMetadataMatches(activeUpload, normalized)\n ) {\n return buildCreateUploadResult(storage, activeUpload);\n }\n\n return null;\n })\n .build();\n },\n\n createUploadRecord: function (\n this: UploadServiceContext,\n input: CreateUploadInput & {\n storageInit: Awaited<ReturnType<typeof storage.initUpload>>;\n allowIdempotentReuse: boolean;\n },\n ) {\n const resolved = resolveFileKeyInput(input);\n const now = new Date();\n const normalized = normalizeUploadInput(input);\n const hasChecksum = normalized.checksum !== null;\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.find(\"upload\", (b) =>\n b.whereIndex(\"idx_upload_provider_key\", (eb) =>\n eb.and(eb(\"provider\", \"=\", normalized.provider), eb(\"key\", \"=\", resolved.fileKey)),\n ),\n ),\n )\n .mutate(({ uow, retrieveResult: [uploads] }) => {\n const activeUpload = pickActiveUpload(uploads as UploadRow[], now);\n if (activeUpload) {\n if (\n input.allowIdempotentReuse &&\n hasChecksum &&\n uploadMetadataMatches(activeUpload, normalized)\n ) {\n return {\n reused: true as const,\n existingUpload: activeUpload,\n };\n }\n\n throw new Error(\"UPLOAD_ALREADY_ACTIVE\");\n }\n\n const storageInit = input.storageInit;\n\n const uploadId = uow.create(\"upload\", {\n key: resolved.fileKey,\n provider: normalized.provider,\n uploaderId: normalized.uploaderId,\n filename: normalized.filename,\n expectedSizeBytes: normalized.expectedSizeBytes,\n contentType: normalized.contentType,\n checksum: normalized.checksum,\n visibility: normalized.visibility,\n tags: normalized.tags,\n metadata: normalized.metadata,\n status: \"created\",\n strategy: storageInit.strategy,\n objectKey: storageInit.storageKey,\n storageUploadId: storageInit.storageUploadId ?? null,\n uploadUrl: storageInit.uploadUrl ?? null,\n uploadHeaders: storageInit.uploadHeaders ?? null,\n bytesUploaded: 0n,\n partsUploaded: 0,\n partSizeBytes: storageInit.partSizeBytes ?? null,\n expiresAt: storageInit.expiresAt,\n createdAt: now,\n updatedAt: now,\n completedAt: null,\n errorCode: null,\n errorMessage: null,\n });\n\n uow.triggerHook(\n \"onUploadTimeout\",\n {\n uploadId: uploadId.toString(),\n provider: normalized.provider,\n fileKey: resolved.fileKey,\n },\n { processAt: storageInit.expiresAt },\n );\n\n return {\n reused: false as const,\n uploadId: uploadId.toString(),\n provider: normalized.provider,\n resolved,\n storageInit,\n };\n })\n .transform(({ mutateResult }) => {\n if (mutateResult.reused) {\n return {\n reused: true as const,\n result: buildCreateUploadResult(storage, mutateResult.existingUpload),\n };\n }\n\n return {\n reused: false as const,\n result: buildCreateUploadResultFromInit(\n storage,\n mutateResult.provider,\n mutateResult.resolved,\n mutateResult.storageInit,\n mutateResult.uploadId,\n ),\n };\n })\n .build();\n },\n\n createCompletedUpload: function (\n this: UploadServiceContext,\n input: CreateUploadInput & {\n storageInit: Awaited<ReturnType<typeof storage.initUpload>>;\n completedSizeBytes: bigint;\n },\n ) {\n const resolved = resolveFileKeyInput(input);\n const now = new Date();\n const normalized = normalizeUploadInput(input);\n const storageInit = input.storageInit;\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"file\", (b) =>\n b.whereIndex(\"idx_file_provider_key\", (eb) =>\n eb.and(eb(\"provider\", \"=\", normalized.provider), eb(\"key\", \"=\", resolved.fileKey)),\n ),\n ),\n )\n .mutate(({ uow, retrieveResult: [existingFile] }) => {\n if (existingFile) {\n ensureReplacementUsesDistinctObjectKey(existingFile, storageInit.storageKey);\n }\n\n const finalSizeBytes = input.completedSizeBytes;\n\n const uploadId = uow.create(\"upload\", {\n key: resolved.fileKey,\n provider: normalized.provider,\n uploaderId: normalized.uploaderId,\n filename: normalized.filename,\n expectedSizeBytes: normalized.expectedSizeBytes,\n contentType: normalized.contentType,\n checksum: normalized.checksum,\n visibility: normalized.visibility,\n tags: normalized.tags,\n metadata: normalized.metadata,\n status: \"completed\",\n strategy: storageInit.strategy,\n objectKey: storageInit.storageKey,\n storageUploadId: storageInit.storageUploadId ?? null,\n uploadUrl: storageInit.uploadUrl ?? null,\n uploadHeaders: storageInit.uploadHeaders ?? null,\n bytesUploaded: finalSizeBytes,\n partsUploaded: 0,\n partSizeBytes: storageInit.partSizeBytes ?? null,\n expiresAt: storageInit.expiresAt,\n createdAt: now,\n updatedAt: now,\n completedAt: now,\n errorCode: null,\n errorMessage: null,\n });\n\n const fileRecord = {\n key: resolved.fileKey,\n provider: normalized.provider,\n uploaderId: normalized.uploaderId,\n filename: normalized.filename,\n sizeBytes: finalSizeBytes,\n contentType: normalized.contentType,\n checksum: normalized.checksum,\n visibility: normalized.visibility,\n tags: normalized.tags,\n metadata: normalized.metadata,\n status: \"ready\" as FileStatus,\n objectKey: storageInit.storageKey,\n createdAt: now,\n updatedAt: now,\n completedAt: now,\n deletedAt: null,\n errorCode: null,\n errorMessage: null,\n };\n\n const persistedFile = existingFile\n ? (() => {\n uow.update(\"file\", existingFile.id, (b) =>\n b\n .set({\n key: fileRecord.key,\n provider: fileRecord.provider,\n uploaderId: fileRecord.uploaderId,\n filename: fileRecord.filename,\n sizeBytes: fileRecord.sizeBytes,\n contentType: fileRecord.contentType,\n checksum: fileRecord.checksum,\n visibility: fileRecord.visibility,\n tags: fileRecord.tags,\n metadata: fileRecord.metadata,\n status: fileRecord.status,\n objectKey: fileRecord.objectKey,\n createdAt: fileRecord.createdAt,\n updatedAt: fileRecord.updatedAt,\n completedAt: fileRecord.completedAt,\n deletedAt: fileRecord.deletedAt,\n errorCode: fileRecord.errorCode,\n errorMessage: fileRecord.errorMessage,\n })\n .check(),\n );\n\n if (shouldCleanupSupersededObject(existingFile, fileRecord.objectKey)) {\n uow.triggerHook(\"cleanupStorageObject\", buildFileHookPayload(existingFile));\n }\n\n return {\n id: existingFile.id,\n ...fileRecord,\n };\n })()\n : (() => {\n const fileId = uow.create(\"file\", fileRecord);\n return {\n id: fileId,\n ...fileRecord,\n };\n })();\n\n const uploadRow = {\n id: uploadId,\n key: resolved.fileKey,\n provider: normalized.provider,\n uploaderId: normalized.uploaderId,\n filename: normalized.filename,\n expectedSizeBytes: normalized.expectedSizeBytes,\n contentType: normalized.contentType,\n checksum: normalized.checksum,\n visibility: normalized.visibility,\n tags: normalized.tags,\n metadata: normalized.metadata,\n status: \"completed\" as UploadStatus,\n strategy: storageInit.strategy,\n objectKey: storageInit.storageKey,\n storageUploadId: storageInit.storageUploadId ?? null,\n uploadUrl: storageInit.uploadUrl ?? null,\n uploadHeaders: storageInit.uploadHeaders ?? null,\n bytesUploaded: finalSizeBytes,\n partsUploaded: 0,\n partSizeBytes: storageInit.partSizeBytes ?? null,\n expiresAt: storageInit.expiresAt,\n createdAt: now,\n updatedAt: now,\n completedAt: now,\n errorCode: null,\n errorMessage: null,\n } as UploadRow;\n\n uow.triggerHook(\"onFileReady\", buildUploadHookPayload(uploadRow, finalSizeBytes));\n\n return {\n upload: uploadRow,\n file: persistedFile,\n };\n })\n .build();\n },\n\n createFailedUpload: function (\n this: UploadServiceContext,\n input: CreateUploadInput & {\n storageInit: Awaited<ReturnType<typeof storage.initUpload>>;\n errorCode: string;\n errorMessage?: string | null;\n },\n ) {\n const resolved = resolveFileKeyInput(input);\n const now = new Date();\n const normalized = normalizeUploadInput(input);\n const storageInit = input.storageInit;\n\n return this.serviceTx(uploadSchema)\n .mutate(({ uow }) => {\n const uploadId = uow.create(\"upload\", {\n key: resolved.fileKey,\n provider: normalized.provider,\n uploaderId: normalized.uploaderId,\n filename: normalized.filename,\n expectedSizeBytes: normalized.expectedSizeBytes,\n contentType: normalized.contentType,\n checksum: normalized.checksum,\n visibility: normalized.visibility,\n tags: normalized.tags,\n metadata: normalized.metadata,\n status: \"failed\",\n strategy: storageInit.strategy,\n objectKey: storageInit.storageKey,\n storageUploadId: storageInit.storageUploadId ?? null,\n uploadUrl: storageInit.uploadUrl ?? null,\n uploadHeaders: storageInit.uploadHeaders ?? null,\n bytesUploaded: 0n,\n partsUploaded: 0,\n partSizeBytes: storageInit.partSizeBytes ?? null,\n expiresAt: storageInit.expiresAt,\n createdAt: now,\n updatedAt: now,\n completedAt: null,\n errorCode: input.errorCode,\n errorMessage: input.errorMessage ?? null,\n });\n\n const uploadRow = {\n id: uploadId,\n key: resolved.fileKey,\n provider: normalized.provider,\n uploaderId: normalized.uploaderId,\n filename: normalized.filename,\n expectedSizeBytes: normalized.expectedSizeBytes,\n contentType: normalized.contentType,\n checksum: normalized.checksum,\n visibility: normalized.visibility,\n tags: normalized.tags,\n metadata: normalized.metadata,\n status: \"failed\" as UploadStatus,\n strategy: storageInit.strategy,\n objectKey: storageInit.storageKey,\n storageUploadId: storageInit.storageUploadId ?? null,\n uploadUrl: storageInit.uploadUrl ?? null,\n uploadHeaders: storageInit.uploadHeaders ?? null,\n bytesUploaded: 0n,\n partsUploaded: 0,\n partSizeBytes: storageInit.partSizeBytes ?? null,\n expiresAt: storageInit.expiresAt,\n createdAt: now,\n updatedAt: now,\n completedAt: null,\n errorCode: input.errorCode,\n errorMessage: input.errorMessage ?? null,\n } as UploadRow;\n\n uow.triggerHook(\"onUploadFailed\", buildUploadHookPayload(uploadRow));\n\n return { upload: uploadRow };\n })\n .build();\n },\n\n getUploadStatus: function (this: UploadServiceContext, uploadId: string) {\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId))),\n )\n .transformRetrieve(([upload]) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n return upload;\n })\n .build();\n },\n\n getUploadParts: function (this: UploadServiceContext, uploadId: string) {\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.find(\"upload_part\", (b) =>\n b.whereIndex(\"idx_upload_part_upload\", (eb) => eb(\"uploadId\", \"=\", uploadId)),\n ),\n )\n .transformRetrieve(([parts]) => parts)\n .build();\n },\n\n recordUploadProgress: function (\n this: UploadServiceContext,\n uploadId: string,\n input: UploadProgressInput,\n ) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId))),\n )\n .mutate(({ uow, retrieveResult: [upload] }) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n\n ensureActiveUpload(upload, now);\n\n const nextBytes =\n input.bytesUploaded !== undefined\n ? (() => {\n const inputBigInt = BigInt(input.bytesUploaded);\n return upload.bytesUploaded > inputBigInt ? upload.bytesUploaded : inputBigInt;\n })()\n : upload.bytesUploaded;\n const nextParts =\n input.partsUploaded !== undefined\n ? Math.max(upload.partsUploaded, input.partsUploaded)\n : upload.partsUploaded;\n\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n bytesUploaded: nextBytes,\n partsUploaded: nextParts,\n status: \"in_progress\",\n updatedAt: now,\n })\n .check(),\n );\n\n return { bytesUploaded: nextBytes, partsUploaded: nextParts };\n })\n .build();\n },\n\n recordUploadParts: function (\n this: UploadServiceContext,\n uploadId: string,\n input: CompletePartsInput,\n ) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow\n .findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId)))\n .find(\"upload_part\", (b) =>\n b.whereIndex(\"idx_upload_part_upload\", (eb) => eb(\"uploadId\", \"=\", uploadId)),\n ),\n )\n .mutate(({ uow, retrieveResult: [upload, parts] }) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n\n ensureActiveUpload(upload, now);\n ensureMultipartUpload(upload);\n\n const existing = new Set(parts.map((part) => part.partNumber));\n const existingBytes = parts.reduce((sum, part) => sum + toBigInt(part.sizeBytes), 0n);\n let addedParts = 0;\n let addedBytes = 0n;\n\n for (const part of input.parts) {\n if (existing.has(part.partNumber)) {\n continue;\n }\n existing.add(part.partNumber);\n addedParts += 1;\n addedBytes += toBigInt(part.sizeBytes);\n\n uow.create(\"upload_part\", {\n uploadId: upload.id,\n partNumber: part.partNumber,\n etag: part.etag,\n sizeBytes: toBigInt(part.sizeBytes),\n createdAt: now,\n });\n }\n\n const totalParts = existing.size;\n const totalBytes = existingBytes + addedBytes;\n const nextParts = Math.max(upload.partsUploaded, totalParts);\n const nextBytes = upload.bytesUploaded > totalBytes ? upload.bytesUploaded : totalBytes;\n\n if (addedParts > 0) {\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n partsUploaded: nextParts,\n bytesUploaded: nextBytes,\n status: \"in_progress\",\n updatedAt: now,\n })\n .check(),\n );\n }\n\n return {\n partsUploaded: nextParts,\n bytesUploaded: nextBytes,\n };\n })\n .build();\n },\n\n markUploadCompleteFromSnapshot: function (\n this: UploadServiceContext,\n upload: UploadRow,\n options?: { sizeBytes?: bigint },\n ) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"file\", (b) =>\n b.whereIndex(\"idx_file_provider_key\", (eb) =>\n eb.and(eb(\"provider\", \"=\", upload.provider), eb(\"key\", \"=\", upload.key)),\n ),\n ),\n )\n .mutate(({ uow, retrieveResult: [existingFile] }) => {\n ensureActiveUpload(upload, now);\n\n if (existingFile) {\n ensureReplacementUsesDistinctObjectKey(existingFile, upload.objectKey);\n }\n\n const finalSizeBytes = options?.sizeBytes ?? upload.expectedSizeBytes;\n\n const updatedUpload = {\n ...upload,\n status: \"completed\" as UploadStatus,\n updatedAt: now,\n completedAt: now,\n bytesUploaded: finalSizeBytes,\n };\n\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n status: updatedUpload.status,\n updatedAt: updatedUpload.updatedAt,\n completedAt: updatedUpload.completedAt,\n bytesUploaded: updatedUpload.bytesUploaded,\n })\n .check(),\n );\n\n const completedFile = {\n key: upload.key,\n provider: upload.provider,\n uploaderId: upload.uploaderId ?? null,\n filename: upload.filename,\n sizeBytes: finalSizeBytes,\n contentType: upload.contentType,\n checksum: upload.checksum ?? null,\n visibility: upload.visibility,\n tags: upload.tags ?? null,\n metadata: upload.metadata ?? null,\n status: \"ready\" as FileStatus,\n objectKey: upload.objectKey,\n createdAt: now,\n updatedAt: now,\n completedAt: now,\n deletedAt: null,\n errorCode: null,\n errorMessage: null,\n };\n\n const persistedFile = existingFile\n ? (() => {\n uow.update(\"file\", existingFile.id, (b) =>\n b\n .set({\n key: completedFile.key,\n provider: completedFile.provider,\n uploaderId: completedFile.uploaderId,\n filename: completedFile.filename,\n sizeBytes: completedFile.sizeBytes,\n contentType: completedFile.contentType,\n checksum: completedFile.checksum,\n visibility: completedFile.visibility,\n tags: completedFile.tags,\n metadata: completedFile.metadata,\n status: completedFile.status,\n objectKey: completedFile.objectKey,\n createdAt: completedFile.createdAt,\n updatedAt: completedFile.updatedAt,\n completedAt: completedFile.completedAt,\n deletedAt: completedFile.deletedAt,\n errorCode: completedFile.errorCode,\n errorMessage: completedFile.errorMessage,\n })\n .check(),\n );\n\n if (shouldCleanupSupersededObject(existingFile, completedFile.objectKey)) {\n uow.triggerHook(\"cleanupStorageObject\", buildFileHookPayload(existingFile));\n }\n\n return {\n id: existingFile.id,\n ...completedFile,\n };\n })()\n : (() => {\n const fileId = uow.create(\"file\", completedFile);\n return {\n id: fileId,\n ...completedFile,\n };\n })();\n\n uow.triggerHook(\"onFileReady\", buildUploadHookPayload(upload, finalSizeBytes));\n\n return {\n upload: updatedUpload,\n file: persistedFile,\n };\n })\n .build();\n },\n\n markUploadFailed: function (\n this: UploadServiceContext,\n uploadId: string,\n errorCode: string,\n errorMessage?: string | null,\n ) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId))),\n )\n .mutate(({ uow, retrieveResult: [upload] }) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n\n if (isTerminalUploadStatus(upload.status as UploadStatus)) {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n\n const updatedUpload = {\n ...upload,\n status: \"failed\" as UploadStatus,\n updatedAt: now,\n errorCode,\n errorMessage: errorMessage ?? null,\n };\n\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n status: updatedUpload.status,\n updatedAt: updatedUpload.updatedAt,\n errorCode: updatedUpload.errorCode,\n errorMessage: updatedUpload.errorMessage,\n })\n .check(),\n );\n\n uow.triggerHook(\"onUploadFailed\", buildUploadHookPayload(upload));\n\n return { upload: updatedUpload };\n })\n .build();\n },\n\n markUploadFailedFromSnapshot: function (\n this: UploadServiceContext,\n upload: UploadRow,\n errorCode: string,\n errorMessage?: string | null,\n ) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .mutate(({ uow }) => {\n if (isTerminalUploadStatus(upload.status as UploadStatus)) {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n\n const updatedUpload = {\n ...upload,\n status: \"failed\" as UploadStatus,\n updatedAt: now,\n errorCode,\n errorMessage: errorMessage ?? null,\n };\n\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n status: updatedUpload.status,\n updatedAt: updatedUpload.updatedAt,\n errorCode: updatedUpload.errorCode,\n errorMessage: updatedUpload.errorMessage,\n })\n .check(),\n );\n\n uow.triggerHook(\"onUploadFailed\", buildUploadHookPayload(upload));\n\n return { upload: updatedUpload };\n })\n .build();\n },\n\n markUploadAborted: function (this: UploadServiceContext, uploadId: string) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId))),\n )\n .mutate(({ uow, retrieveResult: [upload] }) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n\n if (isTerminalUploadStatus(upload.status as UploadStatus)) {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n\n const updatedUpload = {\n ...upload,\n status: \"aborted\" as UploadStatus,\n updatedAt: now,\n errorCode: \"UPLOAD_ABORTED\",\n };\n\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n status: updatedUpload.status,\n updatedAt: updatedUpload.updatedAt,\n errorCode: updatedUpload.errorCode,\n })\n .check(),\n );\n\n uow.triggerHook(\"onUploadFailed\", buildUploadHookPayload(upload));\n\n return { upload: updatedUpload };\n })\n .build();\n },\n\n markUploadAbortedFromSnapshot: function (this: UploadServiceContext, upload: UploadRow) {\n const now = new Date();\n\n return this.serviceTx(uploadSchema)\n .mutate(({ uow }) => {\n if (isTerminalUploadStatus(upload.status as UploadStatus)) {\n throw new Error(\"UPLOAD_INVALID_STATE\");\n }\n\n const updatedUpload = {\n ...upload,\n status: \"aborted\" as UploadStatus,\n updatedAt: now,\n errorCode: \"UPLOAD_ABORTED\",\n };\n\n uow.update(\"upload\", upload.id, (b) =>\n b\n .set({\n status: updatedUpload.status,\n updatedAt: updatedUpload.updatedAt,\n errorCode: updatedUpload.errorCode,\n })\n .check(),\n );\n\n uow.triggerHook(\"onUploadFailed\", buildUploadHookPayload(upload));\n\n return { upload: updatedUpload };\n })\n .build();\n },\n\n getUploadStorageInfo: function (this: UploadServiceContext, uploadId: string) {\n return this.serviceTx(uploadSchema)\n .retrieve((uow) =>\n uow.findFirst(\"upload\", (b) => b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", uploadId))),\n )\n .transformRetrieve(([upload]) => {\n if (!upload) {\n throw new Error(\"UPLOAD_NOT_FOUND\");\n }\n return upload;\n })\n .build();\n },\n };\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"fs.d.ts","names":[],"sources":["../../../src/storage/fs.ts"],"sourcesContent":[],"mappings":";;;KAYY,+BAAA;;EAAA,gBAAA,CAAA,EAAA,MAAA;EA+BI,sBAAA,CAAA,EAAA,MAAA;EAA8B,wBAAA,CAAA,EAAA,MAAA;oBACnC,CAAA,EAAA,MAAA;;AACM,iBAFD,8BAAA,CAEC,OAAA,EADN,+BACM,CAAA,EAAd,cAAc"}
1
+ {"version":3,"file":"fs.d.ts","names":[],"sources":["../../../src/storage/fs.ts"],"sourcesContent":[],"mappings":";;;KAcY,+BAAA;;EAAA,gBAAA,CAAA,EAAA,MAAA;EAsCI,sBAAA,CAAA,EAAA,MAAA;EAA8B,wBAAA,CAAA,EAAA,MAAA;oBACnC,CAAA,EAAA,MAAA;;AACM,iBAFD,8BAAA,CAEC,OAAA,EADN,+BACM,CAAA,EAAd,cAAc"}
@@ -1,4 +1,5 @@
1
- import { encodeFileKey } from "../keys.js";
1
+ import { assertFileKey } from "../file-key.js";
2
+ import { appendStorageObjectKeyVersionSegment } from "./object-key.js";
2
3
  import { createReadStream, createWriteStream, promises } from "node:fs";
3
4
  import path from "node:path";
4
5
  import { Readable } from "node:stream";
@@ -14,9 +15,10 @@ const normalizePrefix = (prefix) => {
14
15
  for (const segment of segments) if (segment === "." || segment === "..") throw new Error("Storage key prefix cannot include '.' or '..' segments");
15
16
  return segments.join("/");
16
17
  };
17
- const resolveStorageKeyFromParts = (input) => {
18
- const encoded = input.fileKeyParts.length > 0 ? encodeFileKey(input.fileKeyParts) : input.fileKey;
19
- return encoded.length > 0 ? encoded.split(".").join("/") : "";
18
+ const normalizeProvider = (provider) => {
19
+ const normalized = provider.trim();
20
+ if (normalized.length === 0 || normalized === "." || normalized === ".." || normalized.includes("/") || normalized.includes("\\")) throw new Error("Invalid provider");
21
+ return normalized;
20
22
  };
21
23
  function createFilesystemStorageAdapter(options) {
22
24
  const rootDir = path.resolve(options.rootDir);
@@ -25,7 +27,11 @@ function createFilesystemStorageAdapter(options) {
25
27
  const uploadExpiresInSeconds = options.uploadExpiresInSeconds ?? DEFAULT_UPLOAD_EXPIRES_IN_SECONDS;
26
28
  const defaultContentType = options.defaultContentType ?? DEFAULT_CONTENT_TYPE;
27
29
  const resolveStorageKey = (input) => {
28
- const storageKey = [storageKeyPrefix, resolveStorageKeyFromParts(input)].filter(Boolean).join("/");
30
+ const storageKey = [
31
+ storageKeyPrefix,
32
+ normalizeProvider(input.provider),
33
+ assertFileKey(input.fileKey)
34
+ ].filter(Boolean).join("/");
29
35
  if (storageKey.length === 0) throw new Error("Storage key cannot be empty");
30
36
  if (Buffer.byteLength(storageKey, "utf8") > maxStorageKeyLengthBytes) throw new Error("Storage key exceeds maximum length");
31
37
  return storageKey;
@@ -50,11 +56,11 @@ function createFilesystemStorageAdapter(options) {
50
56
  limits: { maxStorageKeyLengthBytes },
51
57
  recommendations: { uploadExpiresInSeconds },
52
58
  resolveStorageKey,
53
- initUpload: async ({ fileKey, fileKeyParts }) => {
54
- const storageKey = resolveStorageKey({
55
- fileKey,
56
- fileKeyParts
57
- });
59
+ initUpload: async ({ provider, fileKey, objectKeyVersionSegment }) => {
60
+ const storageKey = appendStorageObjectKeyVersionSegment(resolveStorageKey({
61
+ provider,
62
+ fileKey
63
+ }), objectKeyVersionSegment, maxStorageKeyLengthBytes);
58
64
  await promises.mkdir(rootDir, { recursive: true });
59
65
  return {
60
66
  strategy: "proxy",
@@ -1 +1 @@
1
- {"version":3,"file":"fs.js","names":["fs"],"sources":["../../../src/storage/fs.ts"],"sourcesContent":["import { createReadStream, createWriteStream, promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport type { ReadableStream as NodeReadableStream } from \"node:stream/web\";\nimport { pipeline } from \"node:stream/promises\";\nimport { encodeFileKey, type FileKeyEncoded, type FileKeyParts } from \"../keys\";\nimport type { StorageAdapter } from \"./types\";\n\nconst DEFAULT_MAX_STORAGE_KEY_LENGTH_BYTES = 1024;\nconst DEFAULT_UPLOAD_EXPIRES_IN_SECONDS = 60 * 60;\nconst DEFAULT_CONTENT_TYPE = \"application/octet-stream\";\n\nexport type FilesystemStorageAdapterOptions = {\n rootDir: string;\n storageKeyPrefix?: string;\n uploadExpiresInSeconds?: number;\n maxStorageKeyLengthBytes?: number;\n defaultContentType?: string;\n};\n\nconst normalizePrefix = (prefix: string): string => {\n if (!prefix) {\n return \"\";\n }\n\n const segments = prefix.split(\"/\").filter(Boolean);\n for (const segment of segments) {\n if (segment === \".\" || segment === \"..\") {\n throw new Error(\"Storage key prefix cannot include '.' or '..' segments\");\n }\n }\n\n return segments.join(\"/\");\n};\n\nconst resolveStorageKeyFromParts = (input: {\n fileKey: FileKeyEncoded;\n fileKeyParts: FileKeyParts;\n}): string => {\n const encoded = input.fileKeyParts.length > 0 ? encodeFileKey(input.fileKeyParts) : input.fileKey;\n return encoded.length > 0 ? encoded.split(\".\").join(\"/\") : \"\";\n};\n\nexport function createFilesystemStorageAdapter(\n options: FilesystemStorageAdapterOptions,\n): StorageAdapter {\n const rootDir = path.resolve(options.rootDir);\n const storageKeyPrefix = normalizePrefix(options.storageKeyPrefix ?? \"\");\n const maxStorageKeyLengthBytes =\n options.maxStorageKeyLengthBytes ?? DEFAULT_MAX_STORAGE_KEY_LENGTH_BYTES;\n const uploadExpiresInSeconds =\n options.uploadExpiresInSeconds ?? DEFAULT_UPLOAD_EXPIRES_IN_SECONDS;\n const defaultContentType = options.defaultContentType ?? DEFAULT_CONTENT_TYPE;\n\n const resolveStorageKey = (input: { fileKey: FileKeyEncoded; fileKeyParts: FileKeyParts }) => {\n const baseKey = resolveStorageKeyFromParts(input);\n const storageKey = [storageKeyPrefix, baseKey].filter(Boolean).join(\"/\");\n\n if (storageKey.length === 0) {\n throw new Error(\"Storage key cannot be empty\");\n }\n\n if (Buffer.byteLength(storageKey, \"utf8\") > maxStorageKeyLengthBytes) {\n throw new Error(\"Storage key exceeds maximum length\");\n }\n\n return storageKey;\n };\n\n const resolveFilePath = (storageKey: string) => {\n if (storageKey.includes(\"\\\\\")) {\n throw new Error(\"Storage key must use forward slashes\");\n }\n\n const segments = storageKey.split(\"/\").filter(Boolean);\n if (segments.length === 0) {\n throw new Error(\"Storage key cannot be empty\");\n }\n\n const filePath = path.resolve(rootDir, ...segments);\n const rootWithSep = rootDir.endsWith(path.sep) ? rootDir : `${rootDir}${path.sep}`;\n if (filePath !== rootDir && !filePath.startsWith(rootWithSep)) {\n throw new Error(\"Storage key resolves outside the root directory\");\n }\n\n return filePath;\n };\n\n return {\n name: \"filesystem\",\n capabilities: {\n directUpload: false,\n multipartUpload: false,\n signedDownload: false,\n proxyUpload: true,\n },\n limits: {\n maxStorageKeyLengthBytes,\n },\n recommendations: {\n uploadExpiresInSeconds,\n },\n resolveStorageKey,\n initUpload: async ({ fileKey, fileKeyParts }) => {\n const storageKey = resolveStorageKey({ fileKey, fileKeyParts });\n await fs.mkdir(rootDir, { recursive: true });\n\n return {\n strategy: \"proxy\",\n storageKey,\n expiresAt: new Date(Date.now() + uploadExpiresInSeconds * 1000),\n };\n },\n writeStream: async ({ storageKey, body }) => {\n const filePath = resolveFilePath(storageKey);\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n\n const readable = Readable.fromWeb(body as unknown as NodeReadableStream);\n await pipeline(readable, createWriteStream(filePath));\n const stats = await fs.stat(filePath);\n\n return { sizeBytes: BigInt(stats.size) };\n },\n deleteObject: async ({ storageKey }) => {\n const filePath = resolveFilePath(storageKey);\n try {\n await fs.unlink(filePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n },\n getDownloadStream: async ({ storageKey }) => {\n const filePath = resolveFilePath(storageKey);\n const stats = await fs.stat(filePath);\n const stream = Readable.toWeb(createReadStream(filePath)) as unknown as ReadableStream;\n\n return new Response(stream, {\n headers: {\n \"Content-Type\": defaultContentType,\n \"Content-Length\": stats.size.toString(),\n },\n });\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fs.js","names":["fs"],"sources":["../../../src/storage/fs.ts"],"sourcesContent":["import { createReadStream, createWriteStream, promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { ReadableStream as NodeReadableStream } from \"node:stream/web\";\n\nimport { assertFileKey } from \"../file-key\";\nimport { appendStorageObjectKeyVersionSegment } from \"./object-key\";\nimport type { StorageAdapter } from \"./types\";\n\nconst DEFAULT_MAX_STORAGE_KEY_LENGTH_BYTES = 1024;\nconst DEFAULT_UPLOAD_EXPIRES_IN_SECONDS = 60 * 60;\nconst DEFAULT_CONTENT_TYPE = \"application/octet-stream\";\n\nexport type FilesystemStorageAdapterOptions = {\n rootDir: string;\n storageKeyPrefix?: string;\n uploadExpiresInSeconds?: number;\n maxStorageKeyLengthBytes?: number;\n defaultContentType?: string;\n};\n\nconst normalizePrefix = (prefix: string): string => {\n if (!prefix) {\n return \"\";\n }\n\n const segments = prefix.split(\"/\").filter(Boolean);\n for (const segment of segments) {\n if (segment === \".\" || segment === \"..\") {\n throw new Error(\"Storage key prefix cannot include '.' or '..' segments\");\n }\n }\n\n return segments.join(\"/\");\n};\n\nconst normalizeProvider = (provider: string): string => {\n const normalized = provider.trim();\n if (\n normalized.length === 0 ||\n normalized === \".\" ||\n normalized === \"..\" ||\n normalized.includes(\"/\") ||\n normalized.includes(\"\\\\\")\n ) {\n throw new Error(\"Invalid provider\");\n }\n\n return normalized;\n};\n\nexport function createFilesystemStorageAdapter(\n options: FilesystemStorageAdapterOptions,\n): StorageAdapter {\n const rootDir = path.resolve(options.rootDir);\n const storageKeyPrefix = normalizePrefix(options.storageKeyPrefix ?? \"\");\n const maxStorageKeyLengthBytes =\n options.maxStorageKeyLengthBytes ?? DEFAULT_MAX_STORAGE_KEY_LENGTH_BYTES;\n const uploadExpiresInSeconds =\n options.uploadExpiresInSeconds ?? DEFAULT_UPLOAD_EXPIRES_IN_SECONDS;\n const defaultContentType = options.defaultContentType ?? DEFAULT_CONTENT_TYPE;\n\n const resolveStorageKey = (input: { provider: string; fileKey: string }) => {\n const provider = normalizeProvider(input.provider);\n const fileKey = assertFileKey(input.fileKey);\n const storageKey = [storageKeyPrefix, provider, fileKey].filter(Boolean).join(\"/\");\n\n if (storageKey.length === 0) {\n throw new Error(\"Storage key cannot be empty\");\n }\n\n if (Buffer.byteLength(storageKey, \"utf8\") > maxStorageKeyLengthBytes) {\n throw new Error(\"Storage key exceeds maximum length\");\n }\n\n return storageKey;\n };\n\n const resolveFilePath = (storageKey: string) => {\n if (storageKey.includes(\"\\\\\")) {\n throw new Error(\"Storage key must use forward slashes\");\n }\n\n const segments = storageKey.split(\"/\").filter(Boolean);\n if (segments.length === 0) {\n throw new Error(\"Storage key cannot be empty\");\n }\n\n const filePath = path.resolve(rootDir, ...segments);\n const rootWithSep = rootDir.endsWith(path.sep) ? rootDir : `${rootDir}${path.sep}`;\n if (filePath !== rootDir && !filePath.startsWith(rootWithSep)) {\n throw new Error(\"Storage key resolves outside the root directory\");\n }\n\n return filePath;\n };\n\n return {\n name: \"filesystem\",\n capabilities: {\n directUpload: false,\n multipartUpload: false,\n signedDownload: false,\n proxyUpload: true,\n },\n limits: {\n maxStorageKeyLengthBytes,\n },\n recommendations: {\n uploadExpiresInSeconds,\n },\n resolveStorageKey,\n initUpload: async ({ provider, fileKey, objectKeyVersionSegment }) => {\n const storageKey = appendStorageObjectKeyVersionSegment(\n resolveStorageKey({ provider, fileKey }),\n objectKeyVersionSegment,\n maxStorageKeyLengthBytes,\n );\n await fs.mkdir(rootDir, { recursive: true });\n\n return {\n strategy: \"proxy\",\n storageKey,\n expiresAt: new Date(Date.now() + uploadExpiresInSeconds * 1000),\n };\n },\n writeStream: async ({ storageKey, body }) => {\n const filePath = resolveFilePath(storageKey);\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n\n const readable = Readable.fromWeb(body as unknown as NodeReadableStream);\n await pipeline(readable, createWriteStream(filePath));\n const stats = await fs.stat(filePath);\n\n return { sizeBytes: BigInt(stats.size) };\n },\n deleteObject: async ({ storageKey }) => {\n const filePath = resolveFilePath(storageKey);\n try {\n await fs.unlink(filePath);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n },\n getDownloadStream: async ({ storageKey }) => {\n const filePath = resolveFilePath(storageKey);\n const stats = await fs.stat(filePath);\n const stream = Readable.toWeb(createReadStream(filePath)) as unknown as ReadableStream;\n\n return new Response(stream, {\n headers: {\n \"Content-Type\": defaultContentType,\n \"Content-Length\": stats.size.toString(),\n },\n });\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ //#region src/storage/object-key.ts
2
+ const OBJECT_KEY_VERSION_SEGMENT_PATTERN = /^[0-9TZ-]+$/;
3
+ const padNumber = (value, width) => value.toString().padStart(width, "0");
4
+ const formatUtcBasicTimestamp = (value) => {
5
+ const date = new Date(value);
6
+ return [
7
+ padNumber(date.getUTCFullYear(), 4),
8
+ padNumber(date.getUTCMonth() + 1, 2),
9
+ padNumber(date.getUTCDate(), 2),
10
+ "T",
11
+ padNumber(date.getUTCHours(), 2),
12
+ padNumber(date.getUTCMinutes(), 2),
13
+ padNumber(date.getUTCSeconds(), 2),
14
+ padNumber(date.getUTCMilliseconds(), 3),
15
+ "Z"
16
+ ].join("");
17
+ };
18
+ const normalizeObjectKeyVersionSegment = (value) => {
19
+ const normalized = value.trim();
20
+ if (!normalized || !OBJECT_KEY_VERSION_SEGMENT_PATTERN.test(normalized)) throw new Error("Invalid storage object key version segment");
21
+ return normalized;
22
+ };
23
+ const buildStorageObjectVersionSegment = (now = Date.now()) => {
24
+ if (!Number.isFinite(now)) throw new Error("Invalid storage object key version timestamp");
25
+ return formatUtcBasicTimestamp(Math.trunc(now));
26
+ };
27
+ const appendStorageObjectKeyVersionSegment = (storageKey, versionSegment, maxStorageKeyLengthBytes) => {
28
+ if (!versionSegment) return storageKey;
29
+ const versionedStorageKey = `${storageKey.replace(/\/+$/g, "")}/${normalizeObjectKeyVersionSegment(versionSegment)}`;
30
+ if (maxStorageKeyLengthBytes !== void 0 && Buffer.byteLength(versionedStorageKey, "utf8") > maxStorageKeyLengthBytes) throw new Error("Storage key exceeds maximum length");
31
+ return versionedStorageKey;
32
+ };
33
+
34
+ //#endregion
35
+ export { appendStorageObjectKeyVersionSegment, buildStorageObjectVersionSegment };
36
+ //# sourceMappingURL=object-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-key.js","names":[],"sources":["../../../src/storage/object-key.ts"],"sourcesContent":["const OBJECT_KEY_VERSION_SEGMENT_PATTERN = /^[0-9TZ-]+$/;\n\nconst padNumber = (value: number, width: number) => value.toString().padStart(width, \"0\");\n\nconst formatUtcBasicTimestamp = (value: number) => {\n const date = new Date(value);\n return [\n padNumber(date.getUTCFullYear(), 4),\n padNumber(date.getUTCMonth() + 1, 2),\n padNumber(date.getUTCDate(), 2),\n \"T\",\n padNumber(date.getUTCHours(), 2),\n padNumber(date.getUTCMinutes(), 2),\n padNumber(date.getUTCSeconds(), 2),\n padNumber(date.getUTCMilliseconds(), 3),\n \"Z\",\n ].join(\"\");\n};\n\nconst normalizeObjectKeyVersionSegment = (value: string) => {\n const normalized = value.trim();\n if (!normalized || !OBJECT_KEY_VERSION_SEGMENT_PATTERN.test(normalized)) {\n throw new Error(\"Invalid storage object key version segment\");\n }\n return normalized;\n};\n\nexport const buildStorageObjectVersionSegment = (now = Date.now()) => {\n if (!Number.isFinite(now)) {\n throw new Error(\"Invalid storage object key version timestamp\");\n }\n\n return formatUtcBasicTimestamp(Math.trunc(now));\n};\n\nexport const appendStorageObjectKeyVersionSegment = (\n storageKey: string,\n versionSegment?: string,\n maxStorageKeyLengthBytes?: number,\n) => {\n if (!versionSegment) {\n return storageKey;\n }\n\n const normalizedStorageKey = storageKey.replace(/\\/+$/g, \"\");\n const versionedStorageKey = `${normalizedStorageKey}/${normalizeObjectKeyVersionSegment(versionSegment)}`;\n\n if (\n maxStorageKeyLengthBytes !== undefined &&\n Buffer.byteLength(versionedStorageKey, \"utf8\") > maxStorageKeyLengthBytes\n ) {\n throw new Error(\"Storage key exceeds maximum length\");\n }\n\n return versionedStorageKey;\n};\n"],"mappings":";AAAA,MAAM,qCAAqC;AAE3C,MAAM,aAAa,OAAe,UAAkB,MAAM,UAAU,CAAC,SAAS,OAAO,IAAI;AAEzF,MAAM,2BAA2B,UAAkB;CACjD,MAAM,OAAO,IAAI,KAAK,MAAM;AAC5B,QAAO;EACL,UAAU,KAAK,gBAAgB,EAAE,EAAE;EACnC,UAAU,KAAK,aAAa,GAAG,GAAG,EAAE;EACpC,UAAU,KAAK,YAAY,EAAE,EAAE;EAC/B;EACA,UAAU,KAAK,aAAa,EAAE,EAAE;EAChC,UAAU,KAAK,eAAe,EAAE,EAAE;EAClC,UAAU,KAAK,eAAe,EAAE,EAAE;EAClC,UAAU,KAAK,oBAAoB,EAAE,EAAE;EACvC;EACD,CAAC,KAAK,GAAG;;AAGZ,MAAM,oCAAoC,UAAkB;CAC1D,MAAM,aAAa,MAAM,MAAM;AAC/B,KAAI,CAAC,cAAc,CAAC,mCAAmC,KAAK,WAAW,CACrE,OAAM,IAAI,MAAM,6CAA6C;AAE/D,QAAO;;AAGT,MAAa,oCAAoC,MAAM,KAAK,KAAK,KAAK;AACpE,KAAI,CAAC,OAAO,SAAS,IAAI,CACvB,OAAM,IAAI,MAAM,+CAA+C;AAGjE,QAAO,wBAAwB,KAAK,MAAM,IAAI,CAAC;;AAGjD,MAAa,wCACX,YACA,gBACA,6BACG;AACH,KAAI,CAAC,eACH,QAAO;CAIT,MAAM,sBAAsB,GADC,WAAW,QAAQ,SAAS,GAAG,CACR,GAAG,iCAAiC,eAAe;AAEvG,KACE,6BAA6B,UAC7B,OAAO,WAAW,qBAAqB,OAAO,GAAG,yBAEjD,OAAM,IAAI,MAAM,qCAAqC;AAGvD,QAAO"}
@@ -0,0 +1,59 @@
1
+ import { StorageAdapter } from "./types.js";
2
+
3
+ //#region src/storage/r2-binding.d.ts
4
+ type R2BindingPutResult = {
5
+ httpEtag?: string;
6
+ etag?: string;
7
+ size?: number;
8
+ };
9
+ type R2BindingGetResult = {
10
+ body: ReadableStream<Uint8Array> | null;
11
+ size: number;
12
+ httpEtag: string;
13
+ httpMetadata?: {
14
+ contentType?: string;
15
+ };
16
+ };
17
+ type R2BindingUploadedPart = {
18
+ etag: string;
19
+ partNumber: number;
20
+ };
21
+ type R2BindingMultipartUpload = {
22
+ uploadId: string;
23
+ uploadPart: (partNumber: number, value: unknown) => Promise<R2BindingUploadedPart>;
24
+ complete: (parts: R2BindingUploadedPart[]) => Promise<R2BindingPutResult>;
25
+ abort: () => Promise<void>;
26
+ };
27
+ type R2BindingBucket = {
28
+ put: (key: string, value: unknown, options?: {
29
+ httpMetadata?: {
30
+ contentType?: string;
31
+ };
32
+ }) => Promise<R2BindingPutResult>;
33
+ get: (key: string) => Promise<R2BindingGetResult | null>;
34
+ delete: (key: string) => Promise<void>;
35
+ createMultipartUpload: (key: string, options?: {
36
+ httpMetadata?: {
37
+ contentType?: string;
38
+ };
39
+ }) => Promise<R2BindingMultipartUpload>;
40
+ };
41
+ type R2BindingStorageAdapterOptions = {
42
+ bucket: R2BindingBucket;
43
+ storageKeyPrefix?: string;
44
+ directUploadThresholdBytes?: number;
45
+ multipartThresholdBytes?: number;
46
+ multipartPartSizeBytes?: number;
47
+ uploadExpiresInSeconds?: number;
48
+ signedUrlExpiresInSeconds?: number;
49
+ maxSingleUploadBytes?: number;
50
+ maxMultipartUploadBytes?: number;
51
+ maxStorageKeyLengthBytes?: number;
52
+ maxMetadataBytes?: number;
53
+ defaultContentType?: string;
54
+ };
55
+ declare function createR2BindingStorageAdapter(options: R2BindingStorageAdapterOptions): StorageAdapter;
56
+ declare const resolveR2BindingBucket: (bindings: Record<string, unknown>, bindingName: string) => R2BindingBucket;
57
+ //#endregion
58
+ export { R2BindingBucket, R2BindingStorageAdapterOptions, createR2BindingStorageAdapter, resolveR2BindingBucket };
59
+ //# sourceMappingURL=r2-binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r2-binding.d.ts","names":[],"sources":["../../../src/storage/r2-binding.ts"],"sourcesContent":[],"mappings":";;;KAcK,kBAAA;;EAAA,IAAA,CAAA,EAAA,MAAA;EAMA,IAAA,CAAA,EAAA,MAAA;CAAkB;KAAlB,kBAAA,GACkB;MAAf,EAAA,cAAA,CAAe,UAAf,CAAA,GAAA,IAAA;EAAc,IAAA,EAAA,MAAA;EAQjB,QAAA,EAAA,MAAA;EAKA,YAAA,CAAA,EAAA;IAAwB,WAAA,CAAA,EAAA,MAAA;;;KALxB,qBAAA,GAQe;MAAoC,EAAA,MAAA;YAAR,EAAA,MAAA;;KAH3C,wBAAA,GAIiB;EAGV,QAAA,EAAA,MAAA;EAAe,UAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,KAAA,EAAA,OAAA,EAAA,GAL2B,OAK3B,CALmC,qBAKnC,CAAA;UASZ,EAAA,CAAA,KAAA,EAbK,qBAaL,EAAA,EAAA,GAbiC,OAajC,CAbyC,kBAazC,CAAA;OAAR,EAAA,GAAA,GAZQ,OAYR,CAAA,IAAA,CAAA;;AACiB,KAVZ,eAAA,GAUY;KACG,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,KAAA,EAAA,OAAA,EAAA,OAWf,CAXe,EAAA;IAQZ,YAAA,CAAA,EAAA;MAAR,WAAA,CAAA,EAAA,MAAA;IAAO,CAAA;EAGF,CAAA,EAAA,GAbL,OAaK,CAbG,kBAaH,CAA8B;EAqH1B,GAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAjIQ,OAiIR,CAjIgB,kBAiIa,GAAA,IAAA,CAAA;EAAA,MAAA,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,GAhIlB,OAgIkB,CAAA,IAAA,CAAA;uBAClC,EAAA,CAAA,GAAA,EAAA,MAAA,EAAA,OA0SV,CA1SU,EAAA;IACR,YAAA,CAAA,EAAA;MAAc,WAAA,CAAA,EAAA,MAAA;IAgSJ,CAAA;EASZ,CAAA,EAAA,GAnaM,OAmaN,CAnac,wBAmad,CAAA;;AANE,KA1ZS,8BAAA,GA0ZT;EAMF,MAAA,EA/ZS,eA+ZT;;;;;;;;;;;;;iBA3Se,6BAAA,UACL,iCACR;cAgSU,mCACD,iDAET"}