@fragno-dev/upload 0.1.1

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 (355) hide show
  1. package/LICENSE.md +16 -0
  2. package/README.md +43 -0
  3. package/bin/run.js +5 -0
  4. package/dist/browser/client/clients.js +49 -0
  5. package/dist/browser/client/clients.js.map +1 -0
  6. package/dist/browser/client/helpers.d.ts +51 -0
  7. package/dist/browser/client/helpers.d.ts.map +1 -0
  8. package/dist/browser/client/helpers.js +242 -0
  9. package/dist/browser/client/helpers.js.map +1 -0
  10. package/dist/browser/client/node_modules/.pnpm/@nanostores_query@0.3.4_nanostores@1.1.0/node_modules/@nanostores/query/dist/nanoquery.js +354 -0
  11. package/dist/browser/client/node_modules/.pnpm/@nanostores_query@0.3.4_nanostores@1.1.0/node_modules/@nanostores/query/dist/nanoquery.js.map +1 -0
  12. package/dist/browser/client/node_modules/.pnpm/@nanostores_solid@1.1.1_nanostores@1.1.0_solid-js@1.9.10/node_modules/@nanostores/solid/dist/index.js +14 -0
  13. package/dist/browser/client/node_modules/.pnpm/@nanostores_solid@1.1.1_nanostores@1.1.0_solid-js@1.9.10/node_modules/@nanostores/solid/dist/index.js.map +1 -0
  14. package/dist/browser/client/node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js +17 -0
  15. package/dist/browser/client/node_modules/.pnpm/nanoevents@9.1.0/node_modules/nanoevents/index.js.map +1 -0
  16. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/atom/index.js +62 -0
  17. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/atom/index.js.map +1 -0
  18. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/clean-stores/index.js +6 -0
  19. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/clean-stores/index.js.map +1 -0
  20. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/computed/index.js +50 -0
  21. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/computed/index.js.map +1 -0
  22. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/lifecycle/index.js +99 -0
  23. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/lifecycle/index.js.map +1 -0
  24. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/listen-keys/index.js +11 -0
  25. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/listen-keys/index.js.map +1 -0
  26. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/map/index.js +25 -0
  27. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/map/index.js.map +1 -0
  28. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/task/index.js +24 -0
  29. package/dist/browser/client/node_modules/.pnpm/nanostores@1.1.0/node_modules/nanostores/task/index.js.map +1 -0
  30. package/dist/browser/client/packages/fragment-upload/src/definition.js +49 -0
  31. package/dist/browser/client/packages/fragment-upload/src/definition.js.map +1 -0
  32. package/dist/browser/client/packages/fragment-upload/src/keys.d.ts +7 -0
  33. package/dist/browser/client/packages/fragment-upload/src/keys.d.ts.map +1 -0
  34. package/dist/browser/client/packages/fragment-upload/src/keys.js +28 -0
  35. package/dist/browser/client/packages/fragment-upload/src/keys.js.map +1 -0
  36. package/dist/browser/client/packages/fragment-upload/src/routes/files.js +98 -0
  37. package/dist/browser/client/packages/fragment-upload/src/routes/files.js.map +1 -0
  38. package/dist/browser/client/packages/fragment-upload/src/routes/index.js +9 -0
  39. package/dist/browser/client/packages/fragment-upload/src/routes/index.js.map +1 -0
  40. package/dist/browser/client/packages/fragment-upload/src/routes/shared.js +41 -0
  41. package/dist/browser/client/packages/fragment-upload/src/routes/shared.js.map +1 -0
  42. package/dist/browser/client/packages/fragment-upload/src/routes/uploads.js +186 -0
  43. package/dist/browser/client/packages/fragment-upload/src/routes/uploads.js.map +1 -0
  44. package/dist/browser/client/packages/fragment-upload/src/schema.js +8 -0
  45. package/dist/browser/client/packages/fragment-upload/src/schema.js.map +1 -0
  46. package/dist/browser/client/packages/fragment-upload/src/storage/types.d.ts +9 -0
  47. package/dist/browser/client/packages/fragment-upload/src/storage/types.d.ts.map +1 -0
  48. package/dist/browser/client/packages/fragment-upload/src/types.d.ts +31 -0
  49. package/dist/browser/client/packages/fragment-upload/src/types.d.ts.map +1 -0
  50. package/dist/browser/client/packages/fragno/dist/api/error.js +48 -0
  51. package/dist/browser/client/packages/fragno/dist/api/error.js.map +1 -0
  52. package/dist/browser/client/packages/fragno/dist/api/internal/path.js +76 -0
  53. package/dist/browser/client/packages/fragno/dist/api/internal/path.js.map +1 -0
  54. package/dist/browser/client/packages/fragno/dist/api/internal/response-stream.js +81 -0
  55. package/dist/browser/client/packages/fragno/dist/api/internal/response-stream.js.map +1 -0
  56. package/dist/browser/client/packages/fragno/dist/api/internal/route.js +10 -0
  57. package/dist/browser/client/packages/fragno/dist/api/internal/route.js.map +1 -0
  58. package/dist/browser/client/packages/fragno/dist/api/request-input-context.js +185 -0
  59. package/dist/browser/client/packages/fragno/dist/api/request-input-context.js.map +1 -0
  60. package/dist/browser/client/packages/fragno/dist/api/request-output-context.js +119 -0
  61. package/dist/browser/client/packages/fragno/dist/api/request-output-context.js.map +1 -0
  62. package/dist/browser/client/packages/fragno/dist/api/route.js +17 -0
  63. package/dist/browser/client/packages/fragno/dist/api/route.js.map +1 -0
  64. package/dist/browser/client/packages/fragno/dist/client/client-error.js +92 -0
  65. package/dist/browser/client/packages/fragno/dist/client/client-error.js.map +1 -0
  66. package/dist/browser/client/packages/fragno/dist/client/client.js +495 -0
  67. package/dist/browser/client/packages/fragno/dist/client/client.js.map +1 -0
  68. package/dist/browser/client/packages/fragno/dist/client/client.svelte.js +120 -0
  69. package/dist/browser/client/packages/fragno/dist/client/client.svelte.js.map +1 -0
  70. package/dist/browser/client/packages/fragno/dist/client/internal/fetcher-merge.js +36 -0
  71. package/dist/browser/client/packages/fragno/dist/client/internal/fetcher-merge.js.map +1 -0
  72. package/dist/browser/client/packages/fragno/dist/client/internal/ndjson-streaming.js +139 -0
  73. package/dist/browser/client/packages/fragno/dist/client/internal/ndjson-streaming.js.map +1 -0
  74. package/dist/browser/client/packages/fragno/dist/client/react.js +70 -0
  75. package/dist/browser/client/packages/fragno/dist/client/react.js.map +1 -0
  76. package/dist/browser/client/packages/fragno/dist/client/solid.js +108 -0
  77. package/dist/browser/client/packages/fragno/dist/client/solid.js.map +1 -0
  78. package/dist/browser/client/packages/fragno/dist/client/vanilla.js +96 -0
  79. package/dist/browser/client/packages/fragno/dist/client/vanilla.js.map +1 -0
  80. package/dist/browser/client/packages/fragno/dist/client/vue.js +120 -0
  81. package/dist/browser/client/packages/fragno/dist/client/vue.js.map +1 -0
  82. package/dist/browser/client/packages/fragno/dist/util/async.js +40 -0
  83. package/dist/browser/client/packages/fragno/dist/util/async.js.map +1 -0
  84. package/dist/browser/client/packages/fragno/dist/util/content-type.js +49 -0
  85. package/dist/browser/client/packages/fragno/dist/util/content-type.js.map +1 -0
  86. package/dist/browser/client/packages/fragno/dist/util/nanostores.js +31 -0
  87. package/dist/browser/client/packages/fragno/dist/util/nanostores.js.map +1 -0
  88. package/dist/browser/client/packages/fragno/dist/util/ssr.js +18 -0
  89. package/dist/browser/client/packages/fragno/dist/util/ssr.js.map +1 -0
  90. package/dist/browser/client/react.d.ts +295 -0
  91. package/dist/browser/client/react.d.ts.map +1 -0
  92. package/dist/browser/client/react.js +11 -0
  93. package/dist/browser/client/react.js.map +1 -0
  94. package/dist/browser/client/solid.d.ts +303 -0
  95. package/dist/browser/client/solid.d.ts.map +1 -0
  96. package/dist/browser/client/solid.js +11 -0
  97. package/dist/browser/client/solid.js.map +1 -0
  98. package/dist/browser/client/svelte.d.ts +295 -0
  99. package/dist/browser/client/svelte.d.ts.map +1 -0
  100. package/dist/browser/client/svelte.js +11 -0
  101. package/dist/browser/client/svelte.js.map +1 -0
  102. package/dist/browser/client/vanilla.d.ts +296 -0
  103. package/dist/browser/client/vanilla.d.ts.map +1 -0
  104. package/dist/browser/client/vanilla.js +11 -0
  105. package/dist/browser/client/vanilla.js.map +1 -0
  106. package/dist/browser/client/vue.d.ts +295 -0
  107. package/dist/browser/client/vue.d.ts.map +1 -0
  108. package/dist/browser/client/vue.js +11 -0
  109. package/dist/browser/client/vue.js.map +1 -0
  110. package/dist/browser/index-BdjKPO4J.d.ts +177 -0
  111. package/dist/browser/index-BdjKPO4J.d.ts.map +1 -0
  112. package/dist/browser/index.js +3 -0
  113. package/dist/browser/src-vdNJUbjT.js +1982 -0
  114. package/dist/browser/src-vdNJUbjT.js.map +1 -0
  115. package/dist/cli/commands/files/delete.d.ts +40 -0
  116. package/dist/cli/commands/files/delete.d.ts.map +1 -0
  117. package/dist/cli/commands/files/delete.js +31 -0
  118. package/dist/cli/commands/files/delete.js.map +1 -0
  119. package/dist/cli/commands/files/download-url.d.ts +40 -0
  120. package/dist/cli/commands/files/download-url.d.ts.map +1 -0
  121. package/dist/cli/commands/files/download-url.js +31 -0
  122. package/dist/cli/commands/files/download-url.js.map +1 -0
  123. package/dist/cli/commands/files/download.d.ts +49 -0
  124. package/dist/cli/commands/files/download.d.ts.map +1 -0
  125. package/dist/cli/commands/files/download.js +65 -0
  126. package/dist/cli/commands/files/download.js.map +1 -0
  127. package/dist/cli/commands/files/get.d.ts +40 -0
  128. package/dist/cli/commands/files/get.d.ts.map +1 -0
  129. package/dist/cli/commands/files/get.js +31 -0
  130. package/dist/cli/commands/files/get.js.map +1 -0
  131. package/dist/cli/commands/files/list.d.ts +56 -0
  132. package/dist/cli/commands/files/list.d.ts.map +1 -0
  133. package/dist/cli/commands/files/list.js +53 -0
  134. package/dist/cli/commands/files/list.js.map +1 -0
  135. package/dist/cli/commands/files/update.d.ts +56 -0
  136. package/dist/cli/commands/files/update.d.ts.map +1 -0
  137. package/dist/cli/commands/files/update.js +53 -0
  138. package/dist/cli/commands/files/update.js.map +1 -0
  139. package/dist/cli/commands/files/upload.d.ts +73 -0
  140. package/dist/cli/commands/files/upload.d.ts.map +1 -0
  141. package/dist/cli/commands/files/upload.js +87 -0
  142. package/dist/cli/commands/files/upload.js.map +1 -0
  143. package/dist/cli/commands/uploads/abort.d.ts +37 -0
  144. package/dist/cli/commands/uploads/abort.d.ts.map +1 -0
  145. package/dist/cli/commands/uploads/abort.js +26 -0
  146. package/dist/cli/commands/uploads/abort.js.map +1 -0
  147. package/dist/cli/commands/uploads/complete.d.ts +41 -0
  148. package/dist/cli/commands/uploads/complete.d.ts.map +1 -0
  149. package/dist/cli/commands/uploads/complete.js +45 -0
  150. package/dist/cli/commands/uploads/complete.js.map +1 -0
  151. package/dist/cli/commands/uploads/content.d.ts +46 -0
  152. package/dist/cli/commands/uploads/content.d.ts.map +1 -0
  153. package/dist/cli/commands/uploads/content.js +43 -0
  154. package/dist/cli/commands/uploads/content.js.map +1 -0
  155. package/dist/cli/commands/uploads/create.d.ts +72 -0
  156. package/dist/cli/commands/uploads/create.d.ts.map +1 -0
  157. package/dist/cli/commands/uploads/create.js +84 -0
  158. package/dist/cli/commands/uploads/create.js.map +1 -0
  159. package/dist/cli/commands/uploads/get.d.ts +37 -0
  160. package/dist/cli/commands/uploads/get.d.ts.map +1 -0
  161. package/dist/cli/commands/uploads/get.js +26 -0
  162. package/dist/cli/commands/uploads/get.js.map +1 -0
  163. package/dist/cli/commands/uploads/parts-complete.d.ts +41 -0
  164. package/dist/cli/commands/uploads/parts-complete.d.ts.map +1 -0
  165. package/dist/cli/commands/uploads/parts-complete.js +44 -0
  166. package/dist/cli/commands/uploads/parts-complete.js.map +1 -0
  167. package/dist/cli/commands/uploads/parts-list.d.ts +37 -0
  168. package/dist/cli/commands/uploads/parts-list.d.ts.map +1 -0
  169. package/dist/cli/commands/uploads/parts-list.js +26 -0
  170. package/dist/cli/commands/uploads/parts-list.js.map +1 -0
  171. package/dist/cli/commands/uploads/parts-urls.d.ts +46 -0
  172. package/dist/cli/commands/uploads/parts-urls.d.ts.map +1 -0
  173. package/dist/cli/commands/uploads/parts-urls.js +57 -0
  174. package/dist/cli/commands/uploads/parts-urls.js.map +1 -0
  175. package/dist/cli/commands/uploads/progress.d.ts +45 -0
  176. package/dist/cli/commands/uploads/progress.d.ts.map +1 -0
  177. package/dist/cli/commands/uploads/progress.js +40 -0
  178. package/dist/cli/commands/uploads/progress.js.map +1 -0
  179. package/dist/cli/commands/uploads/transfer.d.ts +73 -0
  180. package/dist/cli/commands/uploads/transfer.d.ts.map +1 -0
  181. package/dist/cli/commands/uploads/transfer.js +170 -0
  182. package/dist/cli/commands/uploads/transfer.js.map +1 -0
  183. package/dist/cli/index.d.ts +27 -0
  184. package/dist/cli/index.d.ts.map +1 -0
  185. package/dist/cli/index.js +198 -0
  186. package/dist/cli/index.js.map +1 -0
  187. package/dist/cli/keys.js +32 -0
  188. package/dist/cli/keys.js.map +1 -0
  189. package/dist/cli/utils/client.js +174 -0
  190. package/dist/cli/utils/client.js.map +1 -0
  191. package/dist/cli/utils/options.js +135 -0
  192. package/dist/cli/utils/options.js.map +1 -0
  193. package/dist/node/cli/commands/files/delete.d.ts +40 -0
  194. package/dist/node/cli/commands/files/delete.d.ts.map +1 -0
  195. package/dist/node/cli/commands/files/delete.js +31 -0
  196. package/dist/node/cli/commands/files/delete.js.map +1 -0
  197. package/dist/node/cli/commands/files/download-url.d.ts +40 -0
  198. package/dist/node/cli/commands/files/download-url.d.ts.map +1 -0
  199. package/dist/node/cli/commands/files/download-url.js +31 -0
  200. package/dist/node/cli/commands/files/download-url.js.map +1 -0
  201. package/dist/node/cli/commands/files/download.d.ts +49 -0
  202. package/dist/node/cli/commands/files/download.d.ts.map +1 -0
  203. package/dist/node/cli/commands/files/download.js +65 -0
  204. package/dist/node/cli/commands/files/download.js.map +1 -0
  205. package/dist/node/cli/commands/files/get.d.ts +40 -0
  206. package/dist/node/cli/commands/files/get.d.ts.map +1 -0
  207. package/dist/node/cli/commands/files/get.js +31 -0
  208. package/dist/node/cli/commands/files/get.js.map +1 -0
  209. package/dist/node/cli/commands/files/list.d.ts +56 -0
  210. package/dist/node/cli/commands/files/list.d.ts.map +1 -0
  211. package/dist/node/cli/commands/files/list.js +53 -0
  212. package/dist/node/cli/commands/files/list.js.map +1 -0
  213. package/dist/node/cli/commands/files/update.d.ts +56 -0
  214. package/dist/node/cli/commands/files/update.d.ts.map +1 -0
  215. package/dist/node/cli/commands/files/update.js +53 -0
  216. package/dist/node/cli/commands/files/update.js.map +1 -0
  217. package/dist/node/cli/commands/files/upload.d.ts +73 -0
  218. package/dist/node/cli/commands/files/upload.d.ts.map +1 -0
  219. package/dist/node/cli/commands/files/upload.js +87 -0
  220. package/dist/node/cli/commands/files/upload.js.map +1 -0
  221. package/dist/node/cli/commands/uploads/abort.d.ts +37 -0
  222. package/dist/node/cli/commands/uploads/abort.d.ts.map +1 -0
  223. package/dist/node/cli/commands/uploads/abort.js +26 -0
  224. package/dist/node/cli/commands/uploads/abort.js.map +1 -0
  225. package/dist/node/cli/commands/uploads/complete.d.ts +41 -0
  226. package/dist/node/cli/commands/uploads/complete.d.ts.map +1 -0
  227. package/dist/node/cli/commands/uploads/complete.js +45 -0
  228. package/dist/node/cli/commands/uploads/complete.js.map +1 -0
  229. package/dist/node/cli/commands/uploads/content.d.ts +46 -0
  230. package/dist/node/cli/commands/uploads/content.d.ts.map +1 -0
  231. package/dist/node/cli/commands/uploads/content.js +43 -0
  232. package/dist/node/cli/commands/uploads/content.js.map +1 -0
  233. package/dist/node/cli/commands/uploads/create.d.ts +72 -0
  234. package/dist/node/cli/commands/uploads/create.d.ts.map +1 -0
  235. package/dist/node/cli/commands/uploads/create.js +84 -0
  236. package/dist/node/cli/commands/uploads/create.js.map +1 -0
  237. package/dist/node/cli/commands/uploads/get.d.ts +37 -0
  238. package/dist/node/cli/commands/uploads/get.d.ts.map +1 -0
  239. package/dist/node/cli/commands/uploads/get.js +26 -0
  240. package/dist/node/cli/commands/uploads/get.js.map +1 -0
  241. package/dist/node/cli/commands/uploads/parts-complete.d.ts +41 -0
  242. package/dist/node/cli/commands/uploads/parts-complete.d.ts.map +1 -0
  243. package/dist/node/cli/commands/uploads/parts-complete.js +44 -0
  244. package/dist/node/cli/commands/uploads/parts-complete.js.map +1 -0
  245. package/dist/node/cli/commands/uploads/parts-list.d.ts +37 -0
  246. package/dist/node/cli/commands/uploads/parts-list.d.ts.map +1 -0
  247. package/dist/node/cli/commands/uploads/parts-list.js +26 -0
  248. package/dist/node/cli/commands/uploads/parts-list.js.map +1 -0
  249. package/dist/node/cli/commands/uploads/parts-urls.d.ts +46 -0
  250. package/dist/node/cli/commands/uploads/parts-urls.d.ts.map +1 -0
  251. package/dist/node/cli/commands/uploads/parts-urls.js +57 -0
  252. package/dist/node/cli/commands/uploads/parts-urls.js.map +1 -0
  253. package/dist/node/cli/commands/uploads/progress.d.ts +45 -0
  254. package/dist/node/cli/commands/uploads/progress.d.ts.map +1 -0
  255. package/dist/node/cli/commands/uploads/progress.js +40 -0
  256. package/dist/node/cli/commands/uploads/progress.js.map +1 -0
  257. package/dist/node/cli/commands/uploads/transfer.d.ts +73 -0
  258. package/dist/node/cli/commands/uploads/transfer.d.ts.map +1 -0
  259. package/dist/node/cli/commands/uploads/transfer.js +170 -0
  260. package/dist/node/cli/commands/uploads/transfer.js.map +1 -0
  261. package/dist/node/cli/index.d.ts +27 -0
  262. package/dist/node/cli/index.d.ts.map +1 -0
  263. package/dist/node/cli/index.js +198 -0
  264. package/dist/node/cli/index.js.map +1 -0
  265. package/dist/node/cli/utils/client.js +174 -0
  266. package/dist/node/cli/utils/client.js.map +1 -0
  267. package/dist/node/cli/utils/options.js +135 -0
  268. package/dist/node/cli/utils/options.js.map +1 -0
  269. package/dist/node/client/clients.d.ts +295 -0
  270. package/dist/node/client/clients.d.ts.map +1 -0
  271. package/dist/node/client/clients.js +49 -0
  272. package/dist/node/client/clients.js.map +1 -0
  273. package/dist/node/client/helpers.d.ts +51 -0
  274. package/dist/node/client/helpers.d.ts.map +1 -0
  275. package/dist/node/client/helpers.js +242 -0
  276. package/dist/node/client/helpers.js.map +1 -0
  277. package/dist/node/client/react.d.ts +295 -0
  278. package/dist/node/client/react.d.ts.map +1 -0
  279. package/dist/node/client/react.js +11 -0
  280. package/dist/node/client/react.js.map +1 -0
  281. package/dist/node/client/solid.d.ts +303 -0
  282. package/dist/node/client/solid.d.ts.map +1 -0
  283. package/dist/node/client/solid.js +11 -0
  284. package/dist/node/client/solid.js.map +1 -0
  285. package/dist/node/client/svelte.d.ts +295 -0
  286. package/dist/node/client/svelte.d.ts.map +1 -0
  287. package/dist/node/client/svelte.js +11 -0
  288. package/dist/node/client/svelte.js.map +1 -0
  289. package/dist/node/client/vanilla.d.ts +296 -0
  290. package/dist/node/client/vanilla.d.ts.map +1 -0
  291. package/dist/node/client/vanilla.js +11 -0
  292. package/dist/node/client/vanilla.js.map +1 -0
  293. package/dist/node/client/vue.d.ts +295 -0
  294. package/dist/node/client/vue.d.ts.map +1 -0
  295. package/dist/node/client/vue.js +11 -0
  296. package/dist/node/client/vue.js.map +1 -0
  297. package/dist/node/config.d.ts +41 -0
  298. package/dist/node/config.d.ts.map +1 -0
  299. package/dist/node/config.js +26 -0
  300. package/dist/node/config.js.map +1 -0
  301. package/dist/node/definition.d.ts +829 -0
  302. package/dist/node/definition.d.ts.map +1 -0
  303. package/dist/node/definition.js +59 -0
  304. package/dist/node/definition.js.map +1 -0
  305. package/dist/node/index.d.ts +1246 -0
  306. package/dist/node/index.d.ts.map +1 -0
  307. package/dist/node/index.js +19 -0
  308. package/dist/node/index.js.map +1 -0
  309. package/dist/node/keys.d.ts +12 -0
  310. package/dist/node/keys.d.ts.map +1 -0
  311. package/dist/node/keys.js +63 -0
  312. package/dist/node/keys.js.map +1 -0
  313. package/dist/node/routes/files.js +450 -0
  314. package/dist/node/routes/files.js.map +1 -0
  315. package/dist/node/routes/index.d.ts +2023 -0
  316. package/dist/node/routes/index.d.ts.map +1 -0
  317. package/dist/node/routes/index.js +9 -0
  318. package/dist/node/routes/index.js.map +1 -0
  319. package/dist/node/routes/shared.js +66 -0
  320. package/dist/node/routes/shared.js.map +1 -0
  321. package/dist/node/routes/uploads.js +454 -0
  322. package/dist/node/routes/uploads.js.map +1 -0
  323. package/dist/node/schema.d.ts +14 -0
  324. package/dist/node/schema.d.ts.map +1 -0
  325. package/dist/node/schema.js +30 -0
  326. package/dist/node/schema.js.map +1 -0
  327. package/dist/node/services/files.d.ts +20 -0
  328. package/dist/node/services/files.d.ts.map +1 -0
  329. package/dist/node/services/files.js +93 -0
  330. package/dist/node/services/files.js.map +1 -0
  331. package/dist/node/services/helpers.js +36 -0
  332. package/dist/node/services/helpers.js.map +1 -0
  333. package/dist/node/services/index.js +4 -0
  334. package/dist/node/services/uploads.d.ts +50 -0
  335. package/dist/node/services/uploads.d.ts.map +1 -0
  336. package/dist/node/services/uploads.js +358 -0
  337. package/dist/node/services/uploads.js.map +1 -0
  338. package/dist/node/storage/fs.d.ts +16 -0
  339. package/dist/node/storage/fs.d.ts.map +1 -0
  340. package/dist/node/storage/fs.js +94 -0
  341. package/dist/node/storage/fs.js.map +1 -0
  342. package/dist/node/storage/r2.d.ts +103 -0
  343. package/dist/node/storage/r2.d.ts.map +1 -0
  344. package/dist/node/storage/r2.js +23 -0
  345. package/dist/node/storage/r2.js.map +1 -0
  346. package/dist/node/storage/s3.d.ts +44 -0
  347. package/dist/node/storage/s3.d.ts.map +1 -0
  348. package/dist/node/storage/s3.js +398 -0
  349. package/dist/node/storage/s3.js.map +1 -0
  350. package/dist/node/storage/types.d.ts +118 -0
  351. package/dist/node/storage/types.d.ts.map +1 -0
  352. package/dist/node/types.d.ts +32 -0
  353. package/dist/node/types.d.ts.map +1 -0
  354. package/dist/tsconfig.tsbuildinfo +1 -0
  355. package/package.json +105 -0
@@ -0,0 +1,103 @@
1
+ import { FileKeyEncoded, FileKeyParts } from "../keys.js";
2
+ import { StorageAdapterCapabilities, StorageAdapterRecommendations, UploadChecksum } from "./types.js";
3
+ import { S3CompatibleStorageAdapterOptions } from "./s3.js";
4
+
5
+ //#region src/storage/r2.d.ts
6
+ type R2StorageAdapterOptions = Omit<S3CompatibleStorageAdapterOptions, "maxMetadataBytes"> & {
7
+ maxMetadataBytes?: number;
8
+ };
9
+ declare function createR2StorageAdapter(options: R2StorageAdapterOptions): {
10
+ name: string;
11
+ limits: {
12
+ maxMetadataBytes: number;
13
+ maxSingleUploadBytes?: number;
14
+ maxMultipartUploadBytes?: number;
15
+ minMultipartPartSizeBytes?: number;
16
+ maxMultipartPartSizeBytes?: number;
17
+ maxMultipartParts?: number;
18
+ maxStorageKeyLengthBytes?: number;
19
+ };
20
+ capabilities: StorageAdapterCapabilities;
21
+ recommendations?: StorageAdapterRecommendations;
22
+ resolveStorageKey(input: {
23
+ fileKey: FileKeyEncoded;
24
+ fileKeyParts: FileKeyParts;
25
+ }): string;
26
+ initUpload(input: {
27
+ fileKey: FileKeyEncoded;
28
+ fileKeyParts: FileKeyParts;
29
+ sizeBytes: bigint;
30
+ contentType: string;
31
+ checksum?: UploadChecksum | null;
32
+ metadata?: Record<string, unknown> | null;
33
+ }): Promise<{
34
+ strategy: "direct-single" | "direct-multipart" | "proxy";
35
+ storageKey: string;
36
+ storageUploadId?: string;
37
+ partSizeBytes?: number;
38
+ expiresAt: Date;
39
+ uploadUrl?: string;
40
+ uploadHeaders?: Record<string, string>;
41
+ }>;
42
+ getPartUploadUrls?(input: {
43
+ storageKey: string;
44
+ storageUploadId: string;
45
+ partNumbers: number[];
46
+ partSizeBytes: number;
47
+ }): Promise<{
48
+ partNumber: number;
49
+ url: string;
50
+ headers?: Record<string, string>;
51
+ }[]>;
52
+ completeMultipartUpload?(input: {
53
+ storageKey: string;
54
+ storageUploadId: string;
55
+ parts: {
56
+ partNumber: number;
57
+ etag: string;
58
+ }[];
59
+ }): Promise<{
60
+ etag?: string;
61
+ }>;
62
+ abortMultipartUpload?(input: {
63
+ storageKey: string;
64
+ storageUploadId: string;
65
+ }): Promise<void>;
66
+ writeStream?(input: {
67
+ storageKey: string;
68
+ body: ReadableStream<Uint8Array>;
69
+ contentType?: string | null;
70
+ sizeBytes?: bigint | null;
71
+ }): Promise<{
72
+ etag?: string;
73
+ sizeBytes?: bigint;
74
+ }>;
75
+ finalizeUpload?(input: {
76
+ storageKey: string;
77
+ expectedSizeBytes: bigint;
78
+ checksum?: UploadChecksum | null;
79
+ }): Promise<{
80
+ sizeBytes?: bigint;
81
+ etag?: string;
82
+ }>;
83
+ deleteObject(input: {
84
+ storageKey: string;
85
+ }): Promise<void>;
86
+ getDownloadUrl?(input: {
87
+ storageKey: string;
88
+ expiresInSeconds: number;
89
+ contentDisposition?: string;
90
+ contentType?: string;
91
+ }): Promise<{
92
+ url: string;
93
+ headers?: Record<string, string>;
94
+ expiresAt: Date;
95
+ }>;
96
+ getDownloadStream?(input: {
97
+ storageKey: string;
98
+ }): Promise<Response>;
99
+ };
100
+ //# sourceMappingURL=r2.d.ts.map
101
+ //#endregion
102
+ export { R2StorageAdapterOptions, createR2StorageAdapter };
103
+ //# sourceMappingURL=r2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r2.d.ts","names":[],"sources":["../../../src/storage/r2.ts"],"sourcesContent":[],"mappings":";;;;;KAIY,uBAAA,GAA0B,KACpC;;;iBAMc,sBAAA,UAAgC;EAPpC,IAAA,EAAA,MAAA;EAAuB,MAAA,EAAA;IACjC,gBAAA,EAAA,MAAA;IADoC,oBAAA,CAAA,EAAA,MAAA;IAAI,uBAAA,CAAA,EAAA,MAAA;IAO1B,yBAAsB,CAAA,EAAA,MAAA;IAAA,yBAAA,CAAA,EAAA,MAAA;IAAU,iBAAA,CAAA,EAAA,MAAA;IAAuB,wBAAA,CAAA,EAAA,MAAA;;gBAAA;;;;;MAgBwvB,MAAA;;IAAiQ,OAAA,gBAAA;;IAAsR,SAAA,EAAA,MAAA;;;eAAvhB;;;;;;;IAAunD,SAAA,CAAA,EAAA,MAAA;oBAAt3C;;;;;;;;;;cAAsR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAgmC"}
@@ -0,0 +1,23 @@
1
+ import { createS3CompatibleStorageAdapter } from "./s3.js";
2
+
3
+ //#region src/storage/r2.ts
4
+ const DEFAULT_MAX_METADATA_BYTES = 8192;
5
+ function createR2StorageAdapter(options) {
6
+ const maxMetadataBytes = options.maxMetadataBytes ?? DEFAULT_MAX_METADATA_BYTES;
7
+ const adapter = createS3CompatibleStorageAdapter({
8
+ ...options,
9
+ maxMetadataBytes
10
+ });
11
+ return {
12
+ ...adapter,
13
+ name: "r2",
14
+ limits: {
15
+ ...adapter.limits,
16
+ maxMetadataBytes
17
+ }
18
+ };
19
+ }
20
+
21
+ //#endregion
22
+ export { createR2StorageAdapter };
23
+ //# sourceMappingURL=r2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"r2.js","names":[],"sources":["../../../src/storage/r2.ts"],"sourcesContent":["import { createS3CompatibleStorageAdapter, type S3CompatibleStorageAdapterOptions } from \"./s3\";\n\nconst DEFAULT_MAX_METADATA_BYTES = 8_192;\n\nexport type R2StorageAdapterOptions = Omit<\n S3CompatibleStorageAdapterOptions,\n \"maxMetadataBytes\"\n> & {\n maxMetadataBytes?: number;\n};\n\nexport function createR2StorageAdapter(options: R2StorageAdapterOptions) {\n const maxMetadataBytes = options.maxMetadataBytes ?? DEFAULT_MAX_METADATA_BYTES;\n const adapter = createS3CompatibleStorageAdapter({\n ...options,\n maxMetadataBytes,\n });\n\n return {\n ...adapter,\n name: \"r2\",\n limits: {\n ...adapter.limits,\n maxMetadataBytes,\n },\n };\n}\n"],"mappings":";;;AAEA,MAAM,6BAA6B;AASnC,SAAgB,uBAAuB,SAAkC;CACvE,MAAM,mBAAmB,QAAQ,oBAAoB;CACrD,MAAM,UAAU,iCAAiC;EAC/C,GAAG;EACH;EACD,CAAC;AAEF,QAAO;EACL,GAAG;EACH,MAAM;EACN,QAAQ;GACN,GAAG,QAAQ;GACX;GACD;EACF"}
@@ -0,0 +1,44 @@
1
+ import { StorageAdapter } from "./types.js";
2
+
3
+ //#region src/storage/s3.d.ts
4
+ type S3SignerInput = {
5
+ method: string;
6
+ url: string;
7
+ headers?: Record<string, string>;
8
+ body?: string | Uint8Array | null;
9
+ expiresInSeconds?: number;
10
+ };
11
+ type S3Signer = {
12
+ sign: (input: S3SignerInput) => Promise<{
13
+ url: string;
14
+ headers: Record<string, string>;
15
+ }>;
16
+ presign: (input: S3SignerInput) => Promise<{
17
+ url: string;
18
+ headers?: Record<string, string>;
19
+ }>;
20
+ };
21
+ type S3CompatibleStorageAdapterOptions = {
22
+ bucket: string;
23
+ endpoint: string;
24
+ signer: S3Signer;
25
+ storageKeyPrefix?: string;
26
+ pathStyle?: boolean;
27
+ uploadExpiresInSeconds?: number;
28
+ signedUrlExpiresInSeconds?: number;
29
+ directUploadThresholdBytes?: number;
30
+ multipartThresholdBytes?: number;
31
+ multipartPartSizeBytes?: number;
32
+ maxSingleUploadBytes?: number;
33
+ maxMultipartUploadBytes?: number;
34
+ minMultipartPartSizeBytes?: number;
35
+ maxMultipartPartSizeBytes?: number;
36
+ maxMultipartParts?: number;
37
+ maxStorageKeyLengthBytes?: number;
38
+ maxMetadataBytes?: number;
39
+ };
40
+ declare function createS3CompatibleStorageAdapter(options: S3CompatibleStorageAdapterOptions): StorageAdapter;
41
+ //# sourceMappingURL=s3.d.ts.map
42
+ //#endregion
43
+ export { S3CompatibleStorageAdapterOptions, S3Signer, S3SignerInput, createS3CompatibleStorageAdapter };
44
+ //# sourceMappingURL=s3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3.d.ts","names":[],"sources":["../../../src/storage/s3.ts"],"sourcesContent":[],"mappings":";;;KAmBY,aAAA;;EAAA,GAAA,EAAA,MAAA;EAAa,OAAA,CAAA,EAGb,MAHa,CAAA,MAAA,EAAA,MAAA,CAAA;MAGb,CAAA,EAAA,MAAA,GACM,UADN,GAAA,IAAA;kBACM,CAAA,EAAA,MAAA;CAAU;AAIhB,KAAA,QAAA,GAAQ;EAAA,IAAA,EAAA,CAAA,KAAA,EACJ,aADI,EAAA,GACc,OADd,CAAA;IACJ,GAAA,EAAA,MAAA;IAAkD,OAAA,EAAA,MAAA,CAAA,MAAA,EAAA,MAAA,CAAA;;SAC/C,EAAA,CAAA,KAAA,EAAA,aAAA,EAAA,GAAkB,OAAlB,CAAA;IAAmD,GAAA,EAAA,MAAA;IAAjC,OAAA,CAAA,EAAiC,MAAjC,CAAA,MAAA,EAAA,MAAA,CAAA;EAAO,CAAA,CAAA;AAG5C,CAAA;AAqRgB,KArRJ,iCAAA,GAqRoC;EAAA,MAAA,EAAA,MAAA;UACrC,EAAA,MAAA;QACR,EApRO,QAoRP;EAAc,gBAAA,CAAA,EAAA,MAAA;;;;;;;;;;;;;;;iBAFD,gCAAA,UACL,oCACR"}
@@ -0,0 +1,398 @@
1
+ import { encodeFileKey } from "../keys.js";
2
+ import { createHash } from "node:crypto";
3
+
4
+ //#region src/storage/s3.ts
5
+ const BYTES_IN_MIB = 1024 * 1024;
6
+ const BYTES_IN_GIB = 1024 * BYTES_IN_MIB;
7
+ const BYTES_IN_TIB = 1024 * BYTES_IN_GIB;
8
+ const DEFAULT_MAX_SINGLE_UPLOAD_BYTES = 5 * BYTES_IN_GIB;
9
+ const DEFAULT_MAX_MULTIPART_UPLOAD_BYTES = 5 * BYTES_IN_TIB;
10
+ const DEFAULT_MIN_MULTIPART_PART_SIZE_BYTES = 5 * BYTES_IN_MIB;
11
+ const DEFAULT_MAX_MULTIPART_PART_SIZE_BYTES = 5 * BYTES_IN_GIB;
12
+ const DEFAULT_MAX_MULTIPART_PARTS = 1e4;
13
+ const DEFAULT_MAX_STORAGE_KEY_LENGTH_BYTES = 1024;
14
+ const DEFAULT_UPLOAD_EXPIRES_IN_SECONDS = 3600;
15
+ const DEFAULT_SIGNED_URL_EXPIRES_IN_SECONDS = 3600;
16
+ const DEFAULT_MULTIPART_PART_SIZE_BYTES = 8 * BYTES_IN_MIB;
17
+ const MAX_PRESIGNED_EXPIRES_IN_SECONDS = 3600 * 24 * 7;
18
+ const normalizePrefix = (prefix) => {
19
+ if (!prefix) return "";
20
+ const segments = prefix.split("/").filter(Boolean);
21
+ for (const segment of segments) if (segment === "." || segment === "..") throw new Error("Storage key prefix cannot include '.' or '..' segments");
22
+ return segments.join("/");
23
+ };
24
+ const resolveStorageKeyFromParts = (input) => {
25
+ const encoded = input.fileKeyParts.length > 0 ? encodeFileKey(input.fileKeyParts) : input.fileKey;
26
+ return encoded.length > 0 ? encoded.split(".").join("/") : "";
27
+ };
28
+ const encodePathSegments = (value) => value.split("/").map((segment) => encodeURIComponent(segment)).join("/");
29
+ const joinPathSegments = (...segments) => {
30
+ return segments.filter(Boolean).map((segment) => segment.replace(/^\/+|\/+$/g, "")).join("/");
31
+ };
32
+ const parseHex = (value, expectedBytes) => {
33
+ const trimmed = value.trim();
34
+ if (!/^[0-9a-f]+$/i.test(trimmed) || trimmed.length !== expectedBytes * 2) return null;
35
+ return Buffer.from(trimmed, "hex");
36
+ };
37
+ const parseBase64 = (value, expectedBytes) => {
38
+ const trimmed = value.trim();
39
+ if (!/^[A-Za-z0-9+/=]+$/.test(trimmed)) return null;
40
+ const buf = Buffer.from(trimmed, "base64");
41
+ if (buf.length !== expectedBytes) return null;
42
+ return buf;
43
+ };
44
+ const normalizeChecksum = (checksum) => {
45
+ if (!checksum) return null;
46
+ const expectedBytes = checksum.algo === "md5" ? 16 : 32;
47
+ const raw = checksum.value ?? "";
48
+ const buf = parseHex(raw, expectedBytes) ?? parseBase64(raw, expectedBytes);
49
+ if (!buf) throw new Error("INVALID_CHECKSUM");
50
+ return {
51
+ algo: checksum.algo,
52
+ hex: buf.toString("hex"),
53
+ base64: buf.toString("base64")
54
+ };
55
+ };
56
+ const resolveChecksumHeaders = (checksum) => {
57
+ const normalized = normalizeChecksum(checksum);
58
+ if (!normalized) return {};
59
+ if (normalized.algo === "md5") return { "Content-MD5": normalized.base64 };
60
+ return { "x-amz-checksum-sha256": normalized.base64 };
61
+ };
62
+ const normalizeEtag = (etag) => {
63
+ if (!etag) return null;
64
+ const trimmed = etag.trim().replace(/^W\//, "").replace(/^"|"$/g, "");
65
+ if (!/^[0-9a-f]{32}$/i.test(trimmed)) return null;
66
+ return trimmed.toLowerCase();
67
+ };
68
+ const computeChecksumFromResponse = async (response, algo) => {
69
+ if (!response.body) throw new Error("STORAGE_ERROR");
70
+ const hash = createHash(algo);
71
+ const reader = response.body.getReader();
72
+ while (true) {
73
+ const { done, value } = await reader.read();
74
+ if (done) break;
75
+ if (value) hash.update(Buffer.from(value));
76
+ }
77
+ return hash.digest("hex");
78
+ };
79
+ const parseContentLength = (value) => {
80
+ if (!value) return null;
81
+ if (!/^\d+$/.test(value)) return null;
82
+ return BigInt(value);
83
+ };
84
+ const getHeaderValue = (headers, name) => {
85
+ const direct = headers.get(name);
86
+ if (direct !== null) return direct;
87
+ const target = name.toLowerCase();
88
+ for (const [key, value] of headers.entries()) if (key.toLowerCase() === target) return value;
89
+ return null;
90
+ };
91
+ const buildObjectUrl = (input) => {
92
+ const url = new URL(input.endpoint);
93
+ const encodedKey = encodePathSegments(input.storageKey);
94
+ const basePath = url.pathname === "/" ? "" : url.pathname.replace(/\/+$/g, "");
95
+ if (input.pathStyle) {
96
+ const path$1 = joinPathSegments(basePath, input.bucket, encodedKey);
97
+ url.pathname = path$1 ? `/${path$1}` : "/";
98
+ return url;
99
+ }
100
+ url.hostname = `${input.bucket}.${url.hostname}`;
101
+ const path = joinPathSegments(basePath, encodedKey);
102
+ url.pathname = path ? `/${path}` : "/";
103
+ return url;
104
+ };
105
+ const assertExpiresInSeconds = (value) => {
106
+ if (!Number.isFinite(value) || value <= 0) throw new Error("Expiration must be a positive number of seconds");
107
+ if (value > MAX_PRESIGNED_EXPIRES_IN_SECONDS) throw new Error("Expiration exceeds SigV4 maximum of 7 days");
108
+ };
109
+ const resolveMetadataSize = (metadata) => {
110
+ if (!metadata) return 0;
111
+ const serialized = JSON.stringify(metadata);
112
+ return Buffer.byteLength(serialized, "utf8");
113
+ };
114
+ const parseUploadId = (payload) => {
115
+ const match = payload.match(/<UploadId>([^<]+)<\/UploadId>/);
116
+ if (!match) return null;
117
+ return match[1];
118
+ };
119
+ const escapeXml = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
120
+ const buildCompleteMultipartBody = (parts) => {
121
+ return `<?xml version="1.0" encoding="UTF-8"?><CompleteMultipartUpload>${[...parts].sort((a, b) => a.partNumber - b.partNumber).map((part) => `<Part><PartNumber>${part.partNumber}</PartNumber><ETag>${escapeXml(part.etag)}</ETag></Part>`).join("")}</CompleteMultipartUpload>`;
122
+ };
123
+ const resolveMultipartPartSize = (input) => {
124
+ let partSize = input.desiredPartSizeBytes;
125
+ if (partSize < input.minPartSizeBytes) partSize = input.minPartSizeBytes;
126
+ if (partSize > input.maxPartSizeBytes) throw new Error("Multipart part size exceeds maximum allowed size");
127
+ const sizeNumber = Number(input.sizeBytes);
128
+ const minimumPartSizeForLimit = Math.ceil(sizeNumber / input.maxParts);
129
+ if (minimumPartSizeForLimit > partSize) partSize = minimumPartSizeForLimit;
130
+ if (partSize < input.minPartSizeBytes) partSize = input.minPartSizeBytes;
131
+ if (partSize > input.maxPartSizeBytes) throw new Error("Multipart part size exceeds maximum allowed size");
132
+ if (Math.ceil(sizeNumber / partSize) > input.maxParts) throw new Error("Multipart upload exceeds maximum number of parts");
133
+ return partSize;
134
+ };
135
+ function createS3CompatibleStorageAdapter(options) {
136
+ const storageKeyPrefix = normalizePrefix(options.storageKeyPrefix ?? "");
137
+ const pathStyle = options.pathStyle ?? false;
138
+ const maxStorageKeyLengthBytes = options.maxStorageKeyLengthBytes ?? DEFAULT_MAX_STORAGE_KEY_LENGTH_BYTES;
139
+ const maxSingleUploadBytes = options.maxSingleUploadBytes ?? DEFAULT_MAX_SINGLE_UPLOAD_BYTES;
140
+ const maxMultipartUploadBytes = options.maxMultipartUploadBytes ?? DEFAULT_MAX_MULTIPART_UPLOAD_BYTES;
141
+ const minMultipartPartSizeBytes = options.minMultipartPartSizeBytes ?? DEFAULT_MIN_MULTIPART_PART_SIZE_BYTES;
142
+ const maxMultipartPartSizeBytes = options.maxMultipartPartSizeBytes ?? DEFAULT_MAX_MULTIPART_PART_SIZE_BYTES;
143
+ const maxMultipartParts = options.maxMultipartParts ?? DEFAULT_MAX_MULTIPART_PARTS;
144
+ const uploadExpiresInSeconds = options.uploadExpiresInSeconds ?? DEFAULT_UPLOAD_EXPIRES_IN_SECONDS;
145
+ const signedUrlExpiresInSeconds = options.signedUrlExpiresInSeconds ?? DEFAULT_SIGNED_URL_EXPIRES_IN_SECONDS;
146
+ const directUploadThresholdBytes = options.directUploadThresholdBytes ?? maxSingleUploadBytes;
147
+ const multipartThresholdBytes = options.multipartThresholdBytes ?? maxSingleUploadBytes;
148
+ const multipartPartSizeBytes = options.multipartPartSizeBytes ?? DEFAULT_MULTIPART_PART_SIZE_BYTES;
149
+ assertExpiresInSeconds(uploadExpiresInSeconds);
150
+ assertExpiresInSeconds(signedUrlExpiresInSeconds);
151
+ const resolveStorageKey = (input) => {
152
+ const storageKey = [storageKeyPrefix, resolveStorageKeyFromParts(input)].filter(Boolean).join("/");
153
+ if (storageKey.length === 0) throw new Error("Storage key cannot be empty");
154
+ if (Buffer.byteLength(storageKey, "utf8") > maxStorageKeyLengthBytes) throw new Error("Storage key exceeds maximum length");
155
+ return storageKey;
156
+ };
157
+ const buildUrl = (storageKey, queryParams = {}) => {
158
+ const url = buildObjectUrl({
159
+ endpoint: options.endpoint,
160
+ bucket: options.bucket,
161
+ storageKey,
162
+ pathStyle
163
+ });
164
+ for (const [key, value] of Object.entries(queryParams)) {
165
+ if (value === void 0) continue;
166
+ url.searchParams.set(key, value);
167
+ }
168
+ return url;
169
+ };
170
+ const validateMetadata = (metadata) => {
171
+ if (!metadata) return;
172
+ if (options.maxMetadataBytes === void 0) return;
173
+ if (resolveMetadataSize(metadata) > options.maxMetadataBytes) throw new Error("Metadata exceeds maximum size");
174
+ };
175
+ return {
176
+ name: "s3",
177
+ capabilities: {
178
+ directUpload: true,
179
+ multipartUpload: true,
180
+ signedDownload: true,
181
+ proxyUpload: false
182
+ },
183
+ limits: {
184
+ maxSingleUploadBytes,
185
+ maxMultipartUploadBytes,
186
+ minMultipartPartSizeBytes,
187
+ maxMultipartPartSizeBytes,
188
+ maxMultipartParts,
189
+ maxStorageKeyLengthBytes,
190
+ maxMetadataBytes: options.maxMetadataBytes
191
+ },
192
+ recommendations: {
193
+ uploadExpiresInSeconds,
194
+ signedUrlExpiresInSeconds,
195
+ directUploadThresholdBytes,
196
+ multipartThresholdBytes,
197
+ multipartPartSizeBytes
198
+ },
199
+ resolveStorageKey,
200
+ initUpload: async ({ fileKey, fileKeyParts, sizeBytes, contentType, metadata, checksum }) => {
201
+ validateMetadata(metadata);
202
+ const storageKey = resolveStorageKey({
203
+ fileKey,
204
+ fileKeyParts
205
+ });
206
+ const expiresAt = new Date(Date.now() + uploadExpiresInSeconds * 1e3);
207
+ const sizeNumber = Number(sizeBytes);
208
+ if (Number.isNaN(sizeNumber) || sizeNumber < 0) throw new Error("Upload size must be a non-negative number");
209
+ const canMultipart = sizeNumber <= maxMultipartUploadBytes;
210
+ const canSingle = sizeNumber <= maxSingleUploadBytes;
211
+ if (!canMultipart) throw new Error("Upload exceeds maximum multipart size");
212
+ if (sizeNumber >= multipartThresholdBytes || !(canSingle && sizeNumber <= directUploadThresholdBytes)) {
213
+ if (!canMultipart) throw new Error("Upload exceeds maximum multipart size");
214
+ const partSizeBytes = resolveMultipartPartSize({
215
+ sizeBytes,
216
+ desiredPartSizeBytes: multipartPartSizeBytes,
217
+ minPartSizeBytes: minMultipartPartSizeBytes,
218
+ maxPartSizeBytes: maxMultipartPartSizeBytes,
219
+ maxParts: maxMultipartParts
220
+ });
221
+ const createUrl = buildUrl(storageKey, { uploads: "" });
222
+ const signed$1 = await options.signer.sign({
223
+ method: "POST",
224
+ url: createUrl.toString(),
225
+ headers: { "Content-Type": contentType }
226
+ });
227
+ const response = await fetch(signed$1.url, {
228
+ method: "POST",
229
+ headers: signed$1.headers
230
+ });
231
+ if (!response.ok) throw new Error(`Failed to create multipart upload (${response.status})`);
232
+ const uploadId = parseUploadId(await response.text());
233
+ if (!uploadId) throw new Error("Failed to parse multipart upload id");
234
+ return {
235
+ strategy: "direct-multipart",
236
+ storageKey,
237
+ storageUploadId: uploadId,
238
+ partSizeBytes,
239
+ expiresAt
240
+ };
241
+ }
242
+ if (!canSingle) throw new Error("Upload exceeds maximum single upload size");
243
+ const uploadUrl = buildUrl(storageKey);
244
+ const checksumHeaders = resolveChecksumHeaders(checksum);
245
+ const signed = await options.signer.presign({
246
+ method: "PUT",
247
+ url: uploadUrl.toString(),
248
+ headers: {
249
+ "Content-Type": contentType,
250
+ ...checksumHeaders
251
+ },
252
+ expiresInSeconds: uploadExpiresInSeconds
253
+ });
254
+ return {
255
+ strategy: "direct-single",
256
+ storageKey,
257
+ expiresAt,
258
+ uploadUrl: signed.url,
259
+ uploadHeaders: signed.headers
260
+ };
261
+ },
262
+ getPartUploadUrls: async ({ storageKey, storageUploadId, partNumbers }) => {
263
+ for (const partNumber of partNumbers) if (partNumber < 1 || partNumber > maxMultipartParts) throw new Error("INVALID_REQUEST");
264
+ return await Promise.all(partNumbers.map(async (partNumber) => {
265
+ const url = buildUrl(storageKey, {
266
+ partNumber: String(partNumber),
267
+ uploadId: storageUploadId
268
+ });
269
+ const signed = await options.signer.presign({
270
+ method: "PUT",
271
+ url: url.toString(),
272
+ expiresInSeconds: uploadExpiresInSeconds
273
+ });
274
+ return {
275
+ partNumber,
276
+ url: signed.url,
277
+ headers: signed.headers
278
+ };
279
+ }));
280
+ },
281
+ completeMultipartUpload: async ({ storageKey, storageUploadId, parts }) => {
282
+ const url = buildUrl(storageKey, { uploadId: storageUploadId });
283
+ const body = buildCompleteMultipartBody(parts);
284
+ const signed = await options.signer.sign({
285
+ method: "POST",
286
+ url: url.toString(),
287
+ headers: { "Content-Type": "application/xml" },
288
+ body
289
+ });
290
+ const response = await fetch(signed.url, {
291
+ method: "POST",
292
+ headers: signed.headers,
293
+ body
294
+ });
295
+ if (!response.ok) throw new Error(`Failed to complete multipart upload (${response.status})`);
296
+ return { etag: response.headers.get("ETag") ?? void 0 };
297
+ },
298
+ abortMultipartUpload: async ({ storageKey, storageUploadId }) => {
299
+ const url = buildUrl(storageKey, { uploadId: storageUploadId });
300
+ const signed = await options.signer.sign({
301
+ method: "DELETE",
302
+ url: url.toString()
303
+ });
304
+ const response = await fetch(signed.url, {
305
+ method: "DELETE",
306
+ headers: signed.headers
307
+ });
308
+ if (!response.ok) throw new Error(`Failed to abort multipart upload (${response.status})`);
309
+ },
310
+ finalizeUpload: async ({ storageKey, expectedSizeBytes, checksum }) => {
311
+ const url = buildUrl(storageKey);
312
+ const signed = await options.signer.sign({
313
+ method: "HEAD",
314
+ url: url.toString()
315
+ });
316
+ const response = await fetch(signed.url, {
317
+ method: "HEAD",
318
+ headers: signed.headers
319
+ });
320
+ if (!response.ok) throw new Error("STORAGE_ERROR");
321
+ const sizeBytes = parseContentLength(getHeaderValue(response.headers, "content-length"));
322
+ if (sizeBytes === null) throw new Error("STORAGE_ERROR");
323
+ if (sizeBytes !== expectedSizeBytes) throw new Error("INVALID_CHECKSUM");
324
+ const normalized = normalizeChecksum(checksum);
325
+ if (normalized) if (normalized.algo === "md5") {
326
+ const etag = normalizeEtag(getHeaderValue(response.headers, "etag"));
327
+ if (etag) {
328
+ if (etag !== normalized.hex) throw new Error("INVALID_CHECKSUM");
329
+ } else {
330
+ const signedGet = await options.signer.sign({
331
+ method: "GET",
332
+ url: buildUrl(storageKey).toString()
333
+ });
334
+ const getResponse = await fetch(signedGet.url, {
335
+ method: "GET",
336
+ headers: signedGet.headers
337
+ });
338
+ if (!getResponse.ok) throw new Error("STORAGE_ERROR");
339
+ if (await computeChecksumFromResponse(getResponse, "md5") !== normalized.hex) throw new Error("INVALID_CHECKSUM");
340
+ }
341
+ } else {
342
+ const checksumHeader = getHeaderValue(response.headers, "x-amz-checksum-sha256");
343
+ if (checksumHeader) {
344
+ const remote = parseBase64(checksumHeader, 32);
345
+ if (!remote || remote.toString("base64") !== normalized.base64) throw new Error("INVALID_CHECKSUM");
346
+ } else {
347
+ const signedGet = await options.signer.sign({
348
+ method: "GET",
349
+ url: buildUrl(storageKey).toString()
350
+ });
351
+ const getResponse = await fetch(signedGet.url, {
352
+ method: "GET",
353
+ headers: signedGet.headers
354
+ });
355
+ if (!getResponse.ok) throw new Error("STORAGE_ERROR");
356
+ if (await computeChecksumFromResponse(getResponse, "sha256") !== normalized.hex) throw new Error("INVALID_CHECKSUM");
357
+ }
358
+ }
359
+ return {
360
+ sizeBytes,
361
+ etag: getHeaderValue(response.headers, "etag") ?? void 0
362
+ };
363
+ },
364
+ deleteObject: async ({ storageKey }) => {
365
+ const url = buildUrl(storageKey);
366
+ const signed = await options.signer.sign({
367
+ method: "DELETE",
368
+ url: url.toString()
369
+ });
370
+ const response = await fetch(signed.url, {
371
+ method: "DELETE",
372
+ headers: signed.headers
373
+ });
374
+ if (!response.ok) throw new Error(`Failed to delete object (${response.status})`);
375
+ },
376
+ getDownloadUrl: async ({ storageKey, expiresInSeconds, contentDisposition, contentType }) => {
377
+ assertExpiresInSeconds(expiresInSeconds);
378
+ const url = buildUrl(storageKey, {
379
+ "response-content-disposition": contentDisposition,
380
+ "response-content-type": contentType
381
+ });
382
+ const signed = await options.signer.presign({
383
+ method: "GET",
384
+ url: url.toString(),
385
+ expiresInSeconds
386
+ });
387
+ return {
388
+ url: signed.url,
389
+ headers: signed.headers,
390
+ expiresAt: new Date(Date.now() + expiresInSeconds * 1e3)
391
+ };
392
+ }
393
+ };
394
+ }
395
+
396
+ //#endregion
397
+ export { createS3CompatibleStorageAdapter };
398
+ //# sourceMappingURL=s3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"s3.js","names":["path","signed"],"sources":["../../../src/storage/s3.ts"],"sourcesContent":["import { encodeFileKey, type FileKeyEncoded, type FileKeyParts } from \"../keys\";\nimport { createHash } from \"node:crypto\";\nimport type { StorageAdapter, UploadChecksum } from \"./types\";\n\nconst BYTES_IN_MIB = 1024 * 1024;\nconst BYTES_IN_GIB = 1024 * BYTES_IN_MIB;\nconst BYTES_IN_TIB = 1024 * BYTES_IN_GIB;\n\nconst DEFAULT_MAX_SINGLE_UPLOAD_BYTES = 5 * BYTES_IN_GIB;\nconst DEFAULT_MAX_MULTIPART_UPLOAD_BYTES = 5 * BYTES_IN_TIB;\nconst DEFAULT_MIN_MULTIPART_PART_SIZE_BYTES = 5 * BYTES_IN_MIB;\nconst DEFAULT_MAX_MULTIPART_PART_SIZE_BYTES = 5 * BYTES_IN_GIB;\nconst DEFAULT_MAX_MULTIPART_PARTS = 10_000;\nconst DEFAULT_MAX_STORAGE_KEY_LENGTH_BYTES = 1024;\nconst DEFAULT_UPLOAD_EXPIRES_IN_SECONDS = 60 * 60;\nconst DEFAULT_SIGNED_URL_EXPIRES_IN_SECONDS = 60 * 60;\nconst DEFAULT_MULTIPART_PART_SIZE_BYTES = 8 * BYTES_IN_MIB;\nconst MAX_PRESIGNED_EXPIRES_IN_SECONDS = 60 * 60 * 24 * 7;\n\nexport type S3SignerInput = {\n method: string;\n url: string;\n headers?: Record<string, string>;\n body?: string | Uint8Array | null;\n expiresInSeconds?: number;\n};\n\nexport type S3Signer = {\n sign: (input: S3SignerInput) => Promise<{ url: string; headers: Record<string, string> }>;\n presign: (input: S3SignerInput) => Promise<{ url: string; headers?: Record<string, string> }>;\n};\n\nexport type S3CompatibleStorageAdapterOptions = {\n bucket: string;\n endpoint: string;\n signer: S3Signer;\n storageKeyPrefix?: string;\n pathStyle?: boolean;\n uploadExpiresInSeconds?: number;\n signedUrlExpiresInSeconds?: number;\n directUploadThresholdBytes?: number;\n multipartThresholdBytes?: number;\n multipartPartSizeBytes?: number;\n maxSingleUploadBytes?: number;\n maxMultipartUploadBytes?: number;\n minMultipartPartSizeBytes?: number;\n maxMultipartPartSizeBytes?: number;\n maxMultipartParts?: number;\n maxStorageKeyLengthBytes?: number;\n maxMetadataBytes?: number;\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\nconst encodePathSegments = (value: string) =>\n value\n .split(\"/\")\n .map((segment) => encodeURIComponent(segment))\n .join(\"/\");\n\nconst joinPathSegments = (...segments: (string | undefined)[]) => {\n const trimmed = segments.filter(Boolean).map((segment) => segment!.replace(/^\\/+|\\/+$/g, \"\"));\n return trimmed.join(\"/\");\n};\n\nconst parseHex = (value: string, expectedBytes: number) => {\n const trimmed = value.trim();\n if (!/^[0-9a-f]+$/i.test(trimmed) || trimmed.length !== expectedBytes * 2) {\n return null;\n }\n return Buffer.from(trimmed, \"hex\");\n};\n\nconst parseBase64 = (value: string, expectedBytes: number) => {\n const trimmed = value.trim();\n if (!/^[A-Za-z0-9+/=]+$/.test(trimmed)) {\n return null;\n }\n const buf = Buffer.from(trimmed, \"base64\");\n if (buf.length !== expectedBytes) {\n return null;\n }\n return buf;\n};\n\nconst normalizeChecksum = (checksum?: UploadChecksum | null) => {\n if (!checksum) {\n return null;\n }\n\n const expectedBytes = checksum.algo === \"md5\" ? 16 : 32;\n const raw = checksum.value ?? \"\";\n const buf = parseHex(raw, expectedBytes) ?? parseBase64(raw, expectedBytes);\n if (!buf) {\n throw new Error(\"INVALID_CHECKSUM\");\n }\n\n return {\n algo: checksum.algo,\n hex: buf.toString(\"hex\"),\n base64: buf.toString(\"base64\"),\n };\n};\n\nconst resolveChecksumHeaders = (checksum?: UploadChecksum | null): Record<string, string> => {\n const normalized = normalizeChecksum(checksum);\n if (!normalized) {\n return {};\n }\n\n if (normalized.algo === \"md5\") {\n return { \"Content-MD5\": normalized.base64 };\n }\n\n return { \"x-amz-checksum-sha256\": normalized.base64 };\n};\n\nconst normalizeEtag = (etag: string | null) => {\n if (!etag) {\n return null;\n }\n\n const trimmed = etag.trim().replace(/^W\\//, \"\").replace(/^\"|\"$/g, \"\");\n if (!/^[0-9a-f]{32}$/i.test(trimmed)) {\n return null;\n }\n\n return trimmed.toLowerCase();\n};\n\nconst computeChecksumFromResponse = async (\n response: Response,\n algo: \"md5\" | \"sha256\",\n): Promise<string> => {\n if (!response.body) {\n throw new Error(\"STORAGE_ERROR\");\n }\n\n const hash = createHash(algo);\n const reader = response.body.getReader();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (value) {\n hash.update(Buffer.from(value));\n }\n }\n\n return hash.digest(\"hex\");\n};\n\nconst parseContentLength = (value: string | null) => {\n if (!value) {\n return null;\n }\n if (!/^\\d+$/.test(value)) {\n return null;\n }\n return BigInt(value);\n};\n\nconst getHeaderValue = (headers: Headers, name: string) => {\n const direct = headers.get(name);\n if (direct !== null) {\n return direct;\n }\n const target = name.toLowerCase();\n for (const [key, value] of headers.entries()) {\n if (key.toLowerCase() === target) {\n return value;\n }\n }\n return null;\n};\n\nconst buildObjectUrl = (input: {\n endpoint: string;\n bucket: string;\n storageKey: string;\n pathStyle: boolean;\n}) => {\n const url = new URL(input.endpoint);\n const encodedKey = encodePathSegments(input.storageKey);\n const basePath = url.pathname === \"/\" ? \"\" : url.pathname.replace(/\\/+$/g, \"\");\n\n if (input.pathStyle) {\n const path = joinPathSegments(basePath, input.bucket, encodedKey);\n url.pathname = path ? `/${path}` : \"/\";\n return url;\n }\n\n url.hostname = `${input.bucket}.${url.hostname}`;\n const path = joinPathSegments(basePath, encodedKey);\n url.pathname = path ? `/${path}` : \"/\";\n return url;\n};\n\nconst assertExpiresInSeconds = (value: number) => {\n if (!Number.isFinite(value) || value <= 0) {\n throw new Error(\"Expiration must be a positive number of seconds\");\n }\n if (value > MAX_PRESIGNED_EXPIRES_IN_SECONDS) {\n throw new Error(\"Expiration exceeds SigV4 maximum of 7 days\");\n }\n};\n\nconst resolveMetadataSize = (metadata?: Record<string, unknown> | null) => {\n if (!metadata) {\n return 0;\n }\n\n const serialized = JSON.stringify(metadata);\n return Buffer.byteLength(serialized, \"utf8\");\n};\n\nconst parseUploadId = (payload: string) => {\n const match = payload.match(/<UploadId>([^<]+)<\\/UploadId>/);\n if (!match) {\n return null;\n }\n\n return match[1];\n};\n\nconst escapeXml = (value: string) =>\n value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\");\n\nconst buildCompleteMultipartBody = (parts: { partNumber: number; etag: string }[]) => {\n const sorted = [...parts].sort((a, b) => a.partNumber - b.partNumber);\n const entries = sorted\n .map(\n (part) =>\n `<Part><PartNumber>${part.partNumber}</PartNumber><ETag>${escapeXml(\n part.etag,\n )}</ETag></Part>`,\n )\n .join(\"\");\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?><CompleteMultipartUpload>${entries}</CompleteMultipartUpload>`;\n};\n\nconst resolveMultipartPartSize = (input: {\n sizeBytes: bigint;\n desiredPartSizeBytes: number;\n minPartSizeBytes: number;\n maxPartSizeBytes: number;\n maxParts: number;\n}) => {\n let partSize = input.desiredPartSizeBytes;\n\n if (partSize < input.minPartSizeBytes) {\n partSize = input.minPartSizeBytes;\n }\n\n if (partSize > input.maxPartSizeBytes) {\n throw new Error(\"Multipart part size exceeds maximum allowed size\");\n }\n\n const sizeNumber = Number(input.sizeBytes);\n const minimumPartSizeForLimit = Math.ceil(sizeNumber / input.maxParts);\n\n if (minimumPartSizeForLimit > partSize) {\n partSize = minimumPartSizeForLimit;\n }\n\n if (partSize < input.minPartSizeBytes) {\n partSize = input.minPartSizeBytes;\n }\n\n if (partSize > input.maxPartSizeBytes) {\n throw new Error(\"Multipart part size exceeds maximum allowed size\");\n }\n\n const partCount = Math.ceil(sizeNumber / partSize);\n if (partCount > input.maxParts) {\n throw new Error(\"Multipart upload exceeds maximum number of parts\");\n }\n\n return partSize;\n};\n\nexport function createS3CompatibleStorageAdapter(\n options: S3CompatibleStorageAdapterOptions,\n): StorageAdapter {\n const storageKeyPrefix = normalizePrefix(options.storageKeyPrefix ?? \"\");\n const pathStyle = options.pathStyle ?? false;\n const maxStorageKeyLengthBytes =\n options.maxStorageKeyLengthBytes ?? DEFAULT_MAX_STORAGE_KEY_LENGTH_BYTES;\n const maxSingleUploadBytes = options.maxSingleUploadBytes ?? DEFAULT_MAX_SINGLE_UPLOAD_BYTES;\n const maxMultipartUploadBytes =\n options.maxMultipartUploadBytes ?? DEFAULT_MAX_MULTIPART_UPLOAD_BYTES;\n const minMultipartPartSizeBytes =\n options.minMultipartPartSizeBytes ?? DEFAULT_MIN_MULTIPART_PART_SIZE_BYTES;\n const maxMultipartPartSizeBytes =\n options.maxMultipartPartSizeBytes ?? DEFAULT_MAX_MULTIPART_PART_SIZE_BYTES;\n const maxMultipartParts = options.maxMultipartParts ?? DEFAULT_MAX_MULTIPART_PARTS;\n const uploadExpiresInSeconds =\n options.uploadExpiresInSeconds ?? DEFAULT_UPLOAD_EXPIRES_IN_SECONDS;\n const signedUrlExpiresInSeconds =\n options.signedUrlExpiresInSeconds ?? DEFAULT_SIGNED_URL_EXPIRES_IN_SECONDS;\n const directUploadThresholdBytes = options.directUploadThresholdBytes ?? maxSingleUploadBytes;\n const multipartThresholdBytes = options.multipartThresholdBytes ?? maxSingleUploadBytes;\n const multipartPartSizeBytes =\n options.multipartPartSizeBytes ?? DEFAULT_MULTIPART_PART_SIZE_BYTES;\n\n assertExpiresInSeconds(uploadExpiresInSeconds);\n assertExpiresInSeconds(signedUrlExpiresInSeconds);\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 buildUrl = (storageKey: string, queryParams: Record<string, string | undefined> = {}) => {\n const url = buildObjectUrl({\n endpoint: options.endpoint,\n bucket: options.bucket,\n storageKey,\n pathStyle,\n });\n\n for (const [key, value] of Object.entries(queryParams)) {\n if (value === undefined) {\n continue;\n }\n url.searchParams.set(key, value);\n }\n\n return url;\n };\n\n const validateMetadata = (metadata?: Record<string, unknown> | null) => {\n if (!metadata) {\n return;\n }\n\n if (options.maxMetadataBytes === undefined) {\n return;\n }\n\n if (resolveMetadataSize(metadata) > options.maxMetadataBytes) {\n throw new Error(\"Metadata exceeds maximum size\");\n }\n };\n\n return {\n name: \"s3\",\n capabilities: {\n directUpload: true,\n multipartUpload: true,\n signedDownload: true,\n proxyUpload: false,\n },\n limits: {\n maxSingleUploadBytes,\n maxMultipartUploadBytes,\n minMultipartPartSizeBytes,\n maxMultipartPartSizeBytes,\n maxMultipartParts,\n maxStorageKeyLengthBytes,\n maxMetadataBytes: options.maxMetadataBytes,\n },\n recommendations: {\n uploadExpiresInSeconds,\n signedUrlExpiresInSeconds,\n directUploadThresholdBytes,\n multipartThresholdBytes,\n multipartPartSizeBytes,\n },\n resolveStorageKey,\n initUpload: async ({ fileKey, fileKeyParts, sizeBytes, contentType, metadata, checksum }) => {\n validateMetadata(metadata);\n const storageKey = resolveStorageKey({ fileKey, fileKeyParts });\n\n const expiresAt = new Date(Date.now() + uploadExpiresInSeconds * 1000);\n const sizeNumber = Number(sizeBytes);\n\n if (Number.isNaN(sizeNumber) || sizeNumber < 0) {\n throw new Error(\"Upload size must be a non-negative number\");\n }\n\n const canMultipart = sizeNumber <= maxMultipartUploadBytes;\n const canSingle = sizeNumber <= maxSingleUploadBytes;\n\n if (!canMultipart) {\n throw new Error(\"Upload exceeds maximum multipart size\");\n }\n\n const prefersMultipart = sizeNumber >= multipartThresholdBytes;\n const canUseSingle = canSingle && sizeNumber <= directUploadThresholdBytes;\n\n if (prefersMultipart || !canUseSingle) {\n if (!canMultipart) {\n throw new Error(\"Upload exceeds maximum multipart size\");\n }\n\n const partSizeBytes = resolveMultipartPartSize({\n sizeBytes,\n desiredPartSizeBytes: multipartPartSizeBytes,\n minPartSizeBytes: minMultipartPartSizeBytes,\n maxPartSizeBytes: maxMultipartPartSizeBytes,\n maxParts: maxMultipartParts,\n });\n\n const createUrl = buildUrl(storageKey, { uploads: \"\" });\n const signed = await options.signer.sign({\n method: \"POST\",\n url: createUrl.toString(),\n headers: {\n \"Content-Type\": contentType,\n },\n });\n\n const response = await fetch(signed.url, {\n method: \"POST\",\n headers: signed.headers,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to create multipart upload (${response.status})`);\n }\n\n const payload = await response.text();\n const uploadId = parseUploadId(payload);\n if (!uploadId) {\n throw new Error(\"Failed to parse multipart upload id\");\n }\n\n return {\n strategy: \"direct-multipart\",\n storageKey,\n storageUploadId: uploadId,\n partSizeBytes,\n expiresAt,\n };\n }\n\n if (!canSingle) {\n throw new Error(\"Upload exceeds maximum single upload size\");\n }\n\n const uploadUrl = buildUrl(storageKey);\n const checksumHeaders = resolveChecksumHeaders(checksum);\n const signed = await options.signer.presign({\n method: \"PUT\",\n url: uploadUrl.toString(),\n headers: {\n \"Content-Type\": contentType,\n ...checksumHeaders,\n },\n expiresInSeconds: uploadExpiresInSeconds,\n });\n\n return {\n strategy: \"direct-single\",\n storageKey,\n expiresAt,\n uploadUrl: signed.url,\n uploadHeaders: signed.headers,\n };\n },\n getPartUploadUrls: async ({ storageKey, storageUploadId, partNumbers }) => {\n for (const partNumber of partNumbers) {\n if (partNumber < 1 || partNumber > maxMultipartParts) {\n throw new Error(\"INVALID_REQUEST\");\n }\n }\n\n const urls = await Promise.all(\n partNumbers.map(async (partNumber) => {\n const url = buildUrl(storageKey, {\n partNumber: String(partNumber),\n uploadId: storageUploadId,\n });\n const signed = await options.signer.presign({\n method: \"PUT\",\n url: url.toString(),\n expiresInSeconds: uploadExpiresInSeconds,\n });\n\n return {\n partNumber,\n url: signed.url,\n headers: signed.headers,\n };\n }),\n );\n\n return urls;\n },\n completeMultipartUpload: async ({ storageKey, storageUploadId, parts }) => {\n const url = buildUrl(storageKey, { uploadId: storageUploadId });\n const body = buildCompleteMultipartBody(parts);\n const signed = await options.signer.sign({\n method: \"POST\",\n url: url.toString(),\n headers: {\n \"Content-Type\": \"application/xml\",\n },\n body,\n });\n\n const response = await fetch(signed.url, {\n method: \"POST\",\n headers: signed.headers,\n body,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to complete multipart upload (${response.status})`);\n }\n\n const etag = response.headers.get(\"ETag\") ?? undefined;\n return { etag };\n },\n abortMultipartUpload: async ({ storageKey, storageUploadId }) => {\n const url = buildUrl(storageKey, { uploadId: storageUploadId });\n const signed = await options.signer.sign({\n method: \"DELETE\",\n url: url.toString(),\n });\n\n const response = await fetch(signed.url, {\n method: \"DELETE\",\n headers: signed.headers,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to abort multipart upload (${response.status})`);\n }\n },\n finalizeUpload: async ({ storageKey, expectedSizeBytes, checksum }) => {\n const url = buildUrl(storageKey);\n const signed = await options.signer.sign({\n method: \"HEAD\",\n url: url.toString(),\n });\n\n const response = await fetch(signed.url, {\n method: \"HEAD\",\n headers: signed.headers,\n });\n\n if (!response.ok) {\n throw new Error(\"STORAGE_ERROR\");\n }\n\n const sizeHeader = getHeaderValue(response.headers, \"content-length\");\n const sizeBytes = parseContentLength(sizeHeader);\n if (sizeBytes === null) {\n throw new Error(\"STORAGE_ERROR\");\n }\n if (sizeBytes !== expectedSizeBytes) {\n throw new Error(\"INVALID_CHECKSUM\");\n }\n\n const normalized = normalizeChecksum(checksum);\n if (normalized) {\n if (normalized.algo === \"md5\") {\n const etag = normalizeEtag(getHeaderValue(response.headers, \"etag\"));\n if (etag) {\n if (etag !== normalized.hex) {\n throw new Error(\"INVALID_CHECKSUM\");\n }\n } else {\n const signedGet = await options.signer.sign({\n method: \"GET\",\n url: buildUrl(storageKey).toString(),\n });\n const getResponse = await fetch(signedGet.url, {\n method: \"GET\",\n headers: signedGet.headers,\n });\n if (!getResponse.ok) {\n throw new Error(\"STORAGE_ERROR\");\n }\n const computed = await computeChecksumFromResponse(getResponse, \"md5\");\n if (computed !== normalized.hex) {\n throw new Error(\"INVALID_CHECKSUM\");\n }\n }\n } else {\n const checksumHeader = getHeaderValue(response.headers, \"x-amz-checksum-sha256\");\n if (checksumHeader) {\n const remote = parseBase64(checksumHeader, 32);\n if (!remote || remote.toString(\"base64\") !== normalized.base64) {\n throw new Error(\"INVALID_CHECKSUM\");\n }\n } else {\n const signedGet = await options.signer.sign({\n method: \"GET\",\n url: buildUrl(storageKey).toString(),\n });\n const getResponse = await fetch(signedGet.url, {\n method: \"GET\",\n headers: signedGet.headers,\n });\n if (!getResponse.ok) {\n throw new Error(\"STORAGE_ERROR\");\n }\n const computed = await computeChecksumFromResponse(getResponse, \"sha256\");\n if (computed !== normalized.hex) {\n throw new Error(\"INVALID_CHECKSUM\");\n }\n }\n }\n }\n\n const etag = getHeaderValue(response.headers, \"etag\");\n return { sizeBytes, etag: etag ?? undefined };\n },\n deleteObject: async ({ storageKey }) => {\n const url = buildUrl(storageKey);\n const signed = await options.signer.sign({\n method: \"DELETE\",\n url: url.toString(),\n });\n\n const response = await fetch(signed.url, {\n method: \"DELETE\",\n headers: signed.headers,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to delete object (${response.status})`);\n }\n },\n getDownloadUrl: async ({ storageKey, expiresInSeconds, contentDisposition, contentType }) => {\n assertExpiresInSeconds(expiresInSeconds);\n\n const url = buildUrl(storageKey, {\n \"response-content-disposition\": contentDisposition,\n \"response-content-type\": contentType,\n });\n\n const signed = await options.signer.presign({\n method: \"GET\",\n url: url.toString(),\n expiresInSeconds,\n });\n\n return {\n url: signed.url,\n headers: signed.headers,\n expiresAt: new Date(Date.now() + expiresInSeconds * 1000),\n };\n },\n };\n}\n"],"mappings":"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"}