@visulima/storage 1.0.9 → 1.0.11

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 (174) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/adapter/nuxt/module.d.ts +9 -8
  3. package/dist/ai/ai-sdk/index.d.ts +52 -59
  4. package/dist/ai/claude/index.d.ts +105 -119
  5. package/dist/ai/openai/index.d.ts +87 -99
  6. package/dist/ai/tanstack/index.d.ts +54 -61
  7. package/dist/handler/http/fetch/index.d.ts +202 -201
  8. package/dist/handler/http/fetch/index.js +1 -1
  9. package/dist/handler/http/hono/index.d.ts +60 -59
  10. package/dist/handler/http/hono/index.js +1 -1
  11. package/dist/handler/http/nextjs/index.d.ts +55 -54
  12. package/dist/handler/http/nextjs/index.js +1 -1
  13. package/dist/handler/http/node/index.d.ts +234 -246
  14. package/dist/handler/http/node/index.js +1 -1
  15. package/dist/handler/http/solid-start/index.d.ts +55 -54
  16. package/dist/handler/http/solid-start/index.js +1 -1
  17. package/dist/index.d.ts +71 -70
  18. package/dist/index.js +1 -1
  19. package/dist/packem_shared/{AbstractBaseStorage-CiPEMcuo.js → AbstractBaseStorage-CLsYmMZg.js} +1 -1
  20. package/dist/packem_shared/AwsLightStorage-DGSPFUqr.js +1 -0
  21. package/dist/packem_shared/AzureStorage-DvKk_hhz.js +1 -0
  22. package/dist/packem_shared/BoxMetaStorage-CJsyeQ63.js +1 -0
  23. package/dist/packem_shared/{BoxStorage-DbGqBLux.js → BoxStorage-CmM95wi2.js} +1 -1
  24. package/dist/packem_shared/BunS3MetaStorage-CJsyeQ63.js +1 -0
  25. package/dist/packem_shared/{BunS3Storage-DNvimm9e.js → BunS3Storage-B_roVJ29.js} +1 -1
  26. package/dist/packem_shared/BunnyMetaStorage-CJsyeQ63.js +1 -0
  27. package/dist/packem_shared/{BunnyStorage-C7d0opLL.js → BunnyStorage-eZ1QDVaY.js} +1 -1
  28. package/dist/packem_shared/CloudinaryMetaStorage-Bv_YCZ0Q.js +1 -0
  29. package/dist/packem_shared/{CloudinaryStorage-Dc3XA2lP.js → CloudinaryStorage-CpH2f0Fv.js} +1 -1
  30. package/dist/packem_shared/DiskStorage-DzjjqCzo.js +1 -0
  31. package/dist/packem_shared/{DiskStorageWithChecksum-vFCubS6K.js → DiskStorageWithChecksum-MZkDEyts.js} +1 -1
  32. package/dist/packem_shared/DropboxMetaStorage-CJsyeQ63.js +1 -0
  33. package/dist/packem_shared/{DropboxStorage-CY9Ggu3m.js → DropboxStorage-BB9NoWK2.js} +1 -1
  34. package/dist/packem_shared/{Files-CpIcMjP0.js → Files-DyMJ9FPN.js} +1 -1
  35. package/dist/packem_shared/FirebaseMetaStorage-Bv_YCZ0Q.js +1 -0
  36. package/dist/packem_shared/{FirebaseStorage-D6O9CJXN.js → FirebaseStorage-BgbxzYNC.js} +1 -1
  37. package/dist/packem_shared/FtpMetaStorage-CJsyeQ63.js +1 -0
  38. package/dist/packem_shared/{FtpStorage-DbEjbq8z.js → FtpStorage-CNqXDz7P.js} +1 -1
  39. package/dist/packem_shared/{GCSMetaStorage-DT8K6zdm.js → GCSMetaStorage-gEhWlpfS.js} +1 -1
  40. package/dist/packem_shared/{GCStorage-6BHkFlEs.js → GCStorage-CRd5vjok.js} +1 -1
  41. package/dist/packem_shared/GoogleDriveMetaStorage-B0gLF7Io.js +1 -0
  42. package/dist/packem_shared/{GoogleDriveStorage-Bklsz7Bh.js → GoogleDriveStorage-Du7uBhSm.js} +1 -1
  43. package/dist/packem_shared/{LocalMetaStorage-BhicZnNl.js → LocalMetaStorage-CcGfFG39.js} +1 -1
  44. package/dist/packem_shared/{MemoryStorage-9gbWd09l.js → MemoryStorage-ChKyI6OY.js} +1 -1
  45. package/dist/packem_shared/{Multipart-D0ok6BBy.js → Multipart-C35TR2qL.js} +1 -1
  46. package/dist/packem_shared/{Multipart-CQjYqU--.js → Multipart-V64Bg5dt.js} +1 -1
  47. package/dist/packem_shared/NetlifyBlobMetaStorage-Bv_YCZ0Q.js +1 -0
  48. package/dist/packem_shared/NetlifyBlobStorage-CZsr_0DF.js +1 -0
  49. package/dist/packem_shared/OneDriveMetaStorage-B0gLF7Io.js +1 -0
  50. package/dist/packem_shared/{OneDriveStorage-CP6MvGAa.js → OneDriveStorage-B8qFgMq1.js} +1 -1
  51. package/dist/packem_shared/PocketBaseMetaStorage-Cm3v8g1-.js +1 -0
  52. package/dist/packem_shared/{PocketBaseStorage-2qhbI2PW.js → PocketBaseStorage-D2vMN-oY.js} +1 -1
  53. package/dist/packem_shared/{Rest-CI_BiZPv.js → Rest-B7g1sgkq.js} +1 -1
  54. package/dist/packem_shared/{Rest-DvfN4-kf.js → Rest-BrEMYgxZ.js} +1 -1
  55. package/dist/packem_shared/{S3Storage-YGeNk3Tt.js → S3Storage-CTe_BMDl.js} +1 -1
  56. package/dist/packem_shared/SftpMetaStorage-CJsyeQ63.js +1 -0
  57. package/dist/packem_shared/{SftpStorage-2Hz396Xr.js → SftpStorage-BKeAzuej.js} +1 -1
  58. package/dist/packem_shared/SharePointMetaStorage-CJsyeQ63.js +1 -0
  59. package/dist/packem_shared/{SharePointStorage-CrX2Pk6C.js → SharePointStorage-Dtnt5-wk.js} +1 -1
  60. package/dist/packem_shared/SupabaseMetaStorage-B0gLF7Io.js +1 -0
  61. package/dist/packem_shared/{SupabaseStorage-Dc_DBX29.js → SupabaseStorage-CmGQjqXf.js} +1 -1
  62. package/dist/packem_shared/{Tus-BlBZykIL.js → Tus-CJBgnJrn.js} +1 -1
  63. package/dist/packem_shared/{Tus-BBVt2ky3.js → Tus-D9c7KDnl.js} +1 -1
  64. package/dist/packem_shared/UploadThingMetaStorage-Bv_YCZ0Q.js +1 -0
  65. package/dist/packem_shared/{UploadThingStorage-BChykYSe.js → UploadThingStorage-DZ4zNvDH.js} +1 -1
  66. package/dist/packem_shared/VercelBlobMetaStorage-CJsyeQ63.js +1 -0
  67. package/dist/packem_shared/{VercelBlobStorage-CsRyPfw3.js → VercelBlobStorage-DDNEofR3.js} +1 -1
  68. package/dist/packem_shared/{approval.d-CMAYH9GF.d.ts → approval.d-C-d-t94D.d.ts} +6 -6
  69. package/dist/packem_shared/{base-handler-core-D-9Ku1h-.js → base-handler-core-BJP9jHCE.js} +1 -1
  70. package/dist/packem_shared/{base-handler-fetch-CfkNakv8.js → base-handler-fetch-yrYrukwL.js} +1 -1
  71. package/dist/packem_shared/base-handler-node-C8P9rkaH.js +1 -0
  72. package/dist/packem_shared/{createRetryWrapper-CxgiV_hH.js → createRetryWrapper-DgmeHPNF.js} +1 -1
  73. package/dist/packem_shared/disk-storage-DqnnFQAQ.js +1 -0
  74. package/dist/packem_shared/disk-storage-with-checksum.d-Dgwyza8a.d.ts +146 -0
  75. package/dist/packem_shared/{executors.d-BZP2rWo3.d.ts → executors.d-B9dIy3NT.d.ts} +3 -2
  76. package/dist/packem_shared/files.d-CmSZi3M0.d.ts +655 -0
  77. package/dist/packem_shared/gcs-meta-storage-C9F78Sqq.js +1 -0
  78. package/dist/packem_shared/local-meta-storage-BELb1YwO.js +11 -0
  79. package/dist/packem_shared/{local-meta-storage.d-D9PBfkn6.d.ts → local-meta-storage.d-cRTXr1kb.d.ts} +7 -7
  80. package/dist/packem_shared/media-transformer.d-C8tn4J2Z.d.ts +331 -0
  81. package/dist/packem_shared/{memory-storage.d-4EU1cMt1.d.ts → memory-storage.d-BNZvDG1b.d.ts} +32 -40
  82. package/dist/packem_shared/path-C-OWflAo-_mqb5p5d.js +1 -0
  83. package/dist/packem_shared/{rest-base-e0reNDE_.js → rest-base-BQ_dhWyV.js} +1 -1
  84. package/dist/packem_shared/s3-base-storage-CX94H-Za.js +1 -0
  85. package/dist/packem_shared/{s3-base-storage.d-BQgP5B-t.d.ts → s3-base-storage.d-ks99NSs-.d.ts} +64 -70
  86. package/dist/packem_shared/storage-DR7qdwBN.js +1 -0
  87. package/dist/packem_shared/storage.d-DwdJrArF.d.ts +1186 -0
  88. package/dist/packem_shared/tus-base.d-BKBoJVy0.d.ts +103 -0
  89. package/dist/packem_shared/types.d-B1_xZIhu.d.ts +104 -0
  90. package/dist/packem_shared/{types.d-CrUWY4On.d.ts → types.d-BEUv414z.d.ts} +134 -134
  91. package/dist/packem_shared/{types.d-CggTCgXr.d.ts → types.d-D7Zlz5RE.d.ts} +3 -3
  92. package/dist/storage/aws/clients/index.d.ts +388 -388
  93. package/dist/storage/aws/index.d.ts +110 -113
  94. package/dist/storage/aws/index.js +1 -1
  95. package/dist/storage/aws-light/index.d.ts +64 -67
  96. package/dist/storage/aws-light/index.js +1 -1
  97. package/dist/storage/azure/index.d.ts +134 -139
  98. package/dist/storage/azure/index.js +1 -1
  99. package/dist/storage/box/index.d.ts +89 -92
  100. package/dist/storage/box/index.js +1 -1
  101. package/dist/storage/bun-s3/index.d.ts +71 -76
  102. package/dist/storage/bun-s3/index.js +1 -1
  103. package/dist/storage/bunny/index.d.ts +52 -55
  104. package/dist/storage/bunny/index.js +1 -1
  105. package/dist/storage/cloudinary/index.d.ts +54 -59
  106. package/dist/storage/cloudinary/index.js +1 -1
  107. package/dist/storage/dropbox/index.d.ts +59 -62
  108. package/dist/storage/dropbox/index.js +1 -1
  109. package/dist/storage/firebase/index.d.ts +74 -79
  110. package/dist/storage/firebase/index.js +1 -1
  111. package/dist/storage/ftp/index.d.ts +38 -43
  112. package/dist/storage/ftp/index.js +1 -1
  113. package/dist/storage/gcs/index.d.ts +90 -95
  114. package/dist/storage/gcs/index.js +1 -1
  115. package/dist/storage/google-drive/index.d.ts +69 -72
  116. package/dist/storage/google-drive/index.js +1 -1
  117. package/dist/storage/local/index.d.ts +4 -3
  118. package/dist/storage/local/index.js +1 -1
  119. package/dist/storage/memory/index.d.ts +3 -2
  120. package/dist/storage/memory/index.js +1 -1
  121. package/dist/storage/netlify-blob/index.d.ts +86 -93
  122. package/dist/storage/netlify-blob/index.js +1 -1
  123. package/dist/storage/onedrive/index.d.ts +44 -53
  124. package/dist/storage/onedrive/index.js +1 -1
  125. package/dist/storage/pocketbase/index.d.ts +67 -72
  126. package/dist/storage/pocketbase/index.js +1 -1
  127. package/dist/storage/sftp/index.d.ts +40 -45
  128. package/dist/storage/sftp/index.js +1 -1
  129. package/dist/storage/sharepoint/index.d.ts +96 -95
  130. package/dist/storage/sharepoint/index.js +1 -1
  131. package/dist/storage/supabase/index.d.ts +50 -55
  132. package/dist/storage/supabase/index.js +1 -1
  133. package/dist/storage/uploadthing/index.d.ts +34 -37
  134. package/dist/storage/uploadthing/index.js +1 -1
  135. package/dist/storage/vercel-blob/index.d.ts +110 -115
  136. package/dist/storage/vercel-blob/index.js +1 -1
  137. package/dist/transformer/audio-transformer.d.ts +97 -96
  138. package/dist/transformer/image-transformer.d.ts +423 -422
  139. package/dist/transformer/index.d.ts +35 -34
  140. package/dist/transformer/video-transformer.d.ts +112 -111
  141. package/package.json +2 -2
  142. package/dist/packem_shared/AwsLightStorage-BK-WPL0h.js +0 -1
  143. package/dist/packem_shared/AzureStorage-1UvDIQZd.js +0 -1
  144. package/dist/packem_shared/BoxMetaStorage-BSn6Qfnf.js +0 -1
  145. package/dist/packem_shared/BunS3MetaStorage-BSn6Qfnf.js +0 -1
  146. package/dist/packem_shared/BunnyMetaStorage-BSn6Qfnf.js +0 -1
  147. package/dist/packem_shared/CloudinaryMetaStorage-DPVnmNe5.js +0 -1
  148. package/dist/packem_shared/DiskStorage-CI07TVNu.js +0 -1
  149. package/dist/packem_shared/DropboxMetaStorage-BSn6Qfnf.js +0 -1
  150. package/dist/packem_shared/FirebaseMetaStorage-DPVnmNe5.js +0 -1
  151. package/dist/packem_shared/FtpMetaStorage-BSn6Qfnf.js +0 -1
  152. package/dist/packem_shared/GoogleDriveMetaStorage-Cbwa1CHV.js +0 -1
  153. package/dist/packem_shared/NetlifyBlobMetaStorage-DPVnmNe5.js +0 -1
  154. package/dist/packem_shared/NetlifyBlobStorage-CkpCCoN1.js +0 -1
  155. package/dist/packem_shared/OneDriveMetaStorage-Cbwa1CHV.js +0 -1
  156. package/dist/packem_shared/PocketBaseMetaStorage-DOTLwVE7.js +0 -1
  157. package/dist/packem_shared/SftpMetaStorage-BSn6Qfnf.js +0 -1
  158. package/dist/packem_shared/SharePointMetaStorage-BSn6Qfnf.js +0 -1
  159. package/dist/packem_shared/SupabaseMetaStorage-Cbwa1CHV.js +0 -1
  160. package/dist/packem_shared/UploadThingMetaStorage-DPVnmNe5.js +0 -1
  161. package/dist/packem_shared/VercelBlobMetaStorage-BSn6Qfnf.js +0 -1
  162. package/dist/packem_shared/base-handler-node-BF1v1qDa.js +0 -1
  163. package/dist/packem_shared/disk-storage-CsQcYW3s.js +0 -1
  164. package/dist/packem_shared/disk-storage-with-checksum.d-B-VGEsfl.d.ts +0 -156
  165. package/dist/packem_shared/files.d-CH0iLBNC.d.ts +0 -655
  166. package/dist/packem_shared/gcs-meta-storage-B7BnctnV.js +0 -1
  167. package/dist/packem_shared/local-meta-storage-iuJnu90B.js +0 -11
  168. package/dist/packem_shared/media-transformer.d-Quf4ai47.d.ts +0 -331
  169. package/dist/packem_shared/path-0oTTdkvl-DvWvbDbh.js +0 -1
  170. package/dist/packem_shared/s3-base-storage-BoTyhuzO.js +0 -1
  171. package/dist/packem_shared/storage-0j5nCAUp.js +0 -1
  172. package/dist/packem_shared/storage.d-CEM1upWM.d.ts +0 -1176
  173. package/dist/packem_shared/tus-base.d-DLzKE54M.d.ts +0 -106
  174. package/dist/packem_shared/types.d-Bon9GVVe.d.ts +0 -104
@@ -1 +1 @@
1
- import{n as d}from"./headers-BAiAKekR.js";import{hasBody as _}from"type-is";import{b as h}from"./base-handler-core-D-9Ku1h-.js";import{ERRORS as E}from"./ERRORS-BIBxE2oR.js";import{b as g,a as C,c as S,d as X}from"./response-builder-CbSA8qPa.js";const M=(a,t={})=>{const e=h(a,"x-file-metadata",!0);if(!e)return t;try{return{...t,...JSON.parse(e)}}catch{return t}},v=a=>{if(!a)return;const t=2e3,e=a.length>t?a.slice(0,Math.max(0,t)):a,r=e.toLowerCase().indexOf("filename");if(r===-1)return;let s=r+8;for(;s<e.length&&(e[s]==="*"||e[s]===" "||e[s]===" ");)s++;if(s>=e.length||e[s]!=="=")return;for(s++;s<e.length&&(e[s]===" "||e[s]===" ");)s++;if(s>=e.length)return;let n=s,i;const o=e[s];return o==='"'||o==="'"?(n=s+1,i=e.indexOf(o,n),i===-1&&(i=e.indexOf(";",n),i===-1&&(i=e.length))):(i=e.indexOf(";",n),i===-1&&(i=e.length)),n>=i?void 0:e.substring(n,i).trim()||void 0},A=a=>{const t=h(a,"content-disposition",!0);return v(t)},L=a=>{const t=h(a,"x-chunked-upload",!0)==="true",e=h(a,"x-chunk-offset",!0),r=h(a,"x-total-size",!0),s={isChunkedUpload:t};if(e){const n=Number.parseInt(e,10);!Number.isNaN(n)&&n>=0&&(s.chunkOffset=n)}if(r){const n=Number.parseInt(r,10);!Number.isNaN(n)&&n>0&&(s.totalSize=n)}return s},P=(a,t=!1)=>{const e=h(a,"x-chunked-upload",!0)==="true";if(!(t&&e)){if(!_(a))throw d(400,"Request body is required");if(Number.parseInt(h(a,"content-length")||"0",10)===0&&!e)throw d(400,"Content-Length is required and must be greater than 0")}},B=(a,t=!1,e)=>{const r=h(a,"x-chunked-upload",!0)==="true",s=Number.parseInt(h(a,"content-length")||"0",10);if(!t&&!r&&s===0)throw d(400,"Content-Length is required and must be greater than 0");if(e!==void 0&&s>e)throw d(413,`File size exceeds maximum allowed size of ${e} bytes`);return s},W=(a,t,e="application/octet-stream")=>{const r=A(a),s=M(a),{isChunkedUpload:n,totalSize:i}=L(a),o=n&&i?i:t;return n&&i&&(s._chunkedUpload=!0,s._chunks=[],s._totalSize=i),{contentType:e,metadata:s,originalName:r,size:o}},x=(a,t)=>{if(a.length===0)return!1;const e=[...a].toSorted((n,i)=>n.offset-i.offset),r=e[0];if(r?.offset!==0)return!1;let s=r.length;for(let n=1;n<e.length;n+=1){const i=e[n];if(i){if(i.offset>s)return!1;s=Math.max(s,i.offset+i.length)}}return s>=t},T=(a,t,e,r)=>{if(Number.isNaN(a)||a<0)throw new Error("Chunk offset must be a valid non-negative number");if(t<=0)throw new Error("Chunk length must be greater than 0");if(t>r)throw new Error(`Chunk size exceeds maximum allowed size of ${r} bytes`);if(a+t>e)throw new Error(`Chunk exceeds file size. Offset: ${a}, Size: ${t}, Total: ${e}`)},D=(a,t)=>{const e=a.find(r=>r.offset===t.offset&&r.length===t.length);return e?t.checksum&&e.checksum!==t.checksum?a.map(r=>r.offset===t.offset?{...r,checksum:t.checksum}:r):a:[...a,t]},U=a=>(a.metadata||{})._chunkedUpload===!0,y=a=>{const t=a.metadata||{};if(t._chunkedUpload===!0&&typeof t._totalSize=="number")return t._totalSize};class j{async deleteSingle(t){const e=await this.storage.delete({id:t});if(e.status===void 0)throw d(404,"File not found");return{...e,headers:{},statusCode:204}}async handlePost(t,e,r,s,n){if(e&&t.size!==void 0){const l=typeof t.size=="number"?t.size:Number.parseInt(String(t.size),10);if(l>0&&l>this.storage.maxUploadSize)throw d(413,`File size exceeds maximum allowed size of ${this.storage.maxUploadSize} bytes`)}const i=await this.storage.create(t);if(e){const l=this.buildFileUrl(r,i);return g(i,{...C(i,l),"X-Chunked-Upload":"true","X-Upload-ID":i.id},201)}const o=await this.storage.write({body:s,contentLength:n,id:i.id,start:0}),c=this.buildFileUrl(r,o);return g(o,C(o,c),201)}async handlePut(t,e,r,s,n,i){let o,c=!1;try{await this.storage.getMeta(t),c=!0,i&&await this.storage.update({id:t},{metadata:i}),o=await this.storage.write({body:s,contentLength:n,id:t,start:0})}catch(f){const k=f;if(k.UploadErrorCode===E.FILE_NOT_FOUND||k.code==="ENOENT")try{const p=await this.storage.create(e);o=await this.storage.write({body:s,contentLength:n,id:p.id,start:0})}catch(p){throw p}else throw f}const l=this.buildFileUrl(r,o);return g(o,C(o,l),c?200:201)}async handlePatch(t,e,r,s,n,i){let o=await this.storage.getMeta(t);const c=o.metadata||{},l=U(o);if(l){const u=y(o);u&&o.size!==u&&(o={...o,size:u})}const f=typeof c._totalSize=="number"?c._totalSize:o.size||0;if(!l)throw d(400,"File is not a chunked upload. Use POST or PUT for full file uploads.");const k=100*1024*1024;try{T(e,r,f,k)}catch(u){throw u instanceof Error&&u.message.includes("exceeds maximum")?d(413,u.message):d(400,u instanceof Error?u.message:String(u))}if(o.status==="completed"){const u=this.buildFileUrl(n,o);return g(o,{...C(o,u),"X-Upload-Complete":"true"},200)}const p=await this.storage.withLock(`chunks:${t}`,async()=>{const u=(await this.storage.getMeta(t)).metadata??{},O=Array.isArray(u._chunks)?u._chunks:[],z=D(O,{checksum:s,length:r,offset:e});return await this.storage.update({id:t},{metadata:{...u,_chunks:z}}),z});let m=await this.storage.write({body:i,contentLength:r,id:t,start:e}),w=m.bytesWritten>=f;l&&(w=x(p,f),m.status==="completed"&&!w&&(await this.storage.update({id:t},{status:"part"}),m={...m,status:"part"}));const b=w&&m.bytesWritten!==f?{...m,bytesWritten:f}:m,N=this.buildFileUrl(n,b),F={...C(b,N),...S(b,w),"x-upload-offset":String(b.bytesWritten||0)};return g(b,F,w?200:202)}async handleHead(t){let e=await this.storage.getMeta(t);const r=U(e);if(r){const n=y(e);n&&e.size!==n&&(e={...e,size:n})}const s={...X(e)};if(r){const n=e.metadata||{},i=y(e)||e.size||0,o=Array.isArray(n._chunks)?n._chunks:[],c=x(o,i);Object.assign(s,S(e,c))}return g(e,s,200)}handleOptions(t,e){return{headers:{"Access-Control-Allow-Headers":"Authorization, Content-Type, Content-Length, Content-Disposition, X-File-Metadata, X-Chunked-Upload, X-Total-Size, X-Chunk-Offset, X-Chunk-Checksum","Access-Control-Allow-Methods":t.map(r=>r.toUpperCase()).join(", "),"Access-Control-Max-Age":86400,"X-Max-Upload-Size":String(e)},statusCode:204}}async deleteBatch(t){const e=await this.storage.deleteBatch(t);if(e.successfulCount===0&&e.failedCount>0){const r=e.failed.map(s=>s.id).join(", ");throw d(404,`Failed to delete files: ${r}`)}return{data:e.successful,headers:e.failedCount>0?{"X-Delete-Errors":JSON.stringify(e.failed),"X-Delete-Failed":String(e.failedCount),"X-Delete-Successful":String(e.successfulCount)}:{"X-Delete-Successful":String(e.successfulCount)},statusCode:e.successfulCount===t.length?204:207}}get storage(){throw new Error("storage must be implemented")}buildFileUrl(t,e){throw new Error("buildFileUrl must be implemented")}}export{j as X,B as a,A as b,L as c,W as e,v as p,P as v};
1
+ import{n as d}from"./headers-BAiAKekR.js";import{hasBody as _}from"type-is";import{b as h}from"./base-handler-core-BJP9jHCE.js";import{ERRORS as E}from"./ERRORS-BIBxE2oR.js";import{b as g,a as C,c as S,d as X}from"./response-builder-CbSA8qPa.js";const M=(a,t={})=>{const e=h(a,"x-file-metadata",!0);if(!e)return t;try{return{...t,...JSON.parse(e)}}catch{return t}},v=a=>{if(!a)return;const t=2e3,e=a.length>t?a.slice(0,Math.max(0,t)):a,r=e.toLowerCase().indexOf("filename");if(r===-1)return;let s=r+8;for(;s<e.length&&(e[s]==="*"||e[s]===" "||e[s]===" ");)s++;if(s>=e.length||e[s]!=="=")return;for(s++;s<e.length&&(e[s]===" "||e[s]===" ");)s++;if(s>=e.length)return;let n=s,i;const o=e[s];return o==='"'||o==="'"?(n=s+1,i=e.indexOf(o,n),i===-1&&(i=e.indexOf(";",n),i===-1&&(i=e.length))):(i=e.indexOf(";",n),i===-1&&(i=e.length)),n>=i?void 0:e.substring(n,i).trim()||void 0},A=a=>{const t=h(a,"content-disposition",!0);return v(t)},L=a=>{const t=h(a,"x-chunked-upload",!0)==="true",e=h(a,"x-chunk-offset",!0),r=h(a,"x-total-size",!0),s={isChunkedUpload:t};if(e){const n=Number.parseInt(e,10);!Number.isNaN(n)&&n>=0&&(s.chunkOffset=n)}if(r){const n=Number.parseInt(r,10);!Number.isNaN(n)&&n>0&&(s.totalSize=n)}return s},P=(a,t=!1)=>{const e=h(a,"x-chunked-upload",!0)==="true";if(!(t&&e)){if(!_(a))throw d(400,"Request body is required");if(Number.parseInt(h(a,"content-length")||"0",10)===0&&!e)throw d(400,"Content-Length is required and must be greater than 0")}},B=(a,t=!1,e)=>{const r=h(a,"x-chunked-upload",!0)==="true",s=Number.parseInt(h(a,"content-length")||"0",10);if(!t&&!r&&s===0)throw d(400,"Content-Length is required and must be greater than 0");if(e!==void 0&&s>e)throw d(413,`File size exceeds maximum allowed size of ${e} bytes`);return s},W=(a,t,e="application/octet-stream")=>{const r=A(a),s=M(a),{isChunkedUpload:n,totalSize:i}=L(a),o=n&&i?i:t;return n&&i&&(s._chunkedUpload=!0,s._chunks=[],s._totalSize=i),{contentType:e,metadata:s,originalName:r,size:o}},x=(a,t)=>{if(a.length===0)return!1;const e=[...a].toSorted((n,i)=>n.offset-i.offset),r=e[0];if(r?.offset!==0)return!1;let s=r.length;for(let n=1;n<e.length;n+=1){const i=e[n];if(i){if(i.offset>s)return!1;s=Math.max(s,i.offset+i.length)}}return s>=t},T=(a,t,e,r)=>{if(Number.isNaN(a)||a<0)throw new Error("Chunk offset must be a valid non-negative number");if(t<=0)throw new Error("Chunk length must be greater than 0");if(t>r)throw new Error(`Chunk size exceeds maximum allowed size of ${r} bytes`);if(a+t>e)throw new Error(`Chunk exceeds file size. Offset: ${a}, Size: ${t}, Total: ${e}`)},D=(a,t)=>{const e=a.find(r=>r.offset===t.offset&&r.length===t.length);return e?t.checksum&&e.checksum!==t.checksum?a.map(r=>r.offset===t.offset?{...r,checksum:t.checksum}:r):a:[...a,t]},U=a=>(a.metadata||{})._chunkedUpload===!0,y=a=>{const t=a.metadata||{};if(t._chunkedUpload===!0&&typeof t._totalSize=="number")return t._totalSize};class j{async deleteSingle(t){const e=await this.storage.delete({id:t});if(e.status===void 0)throw d(404,"File not found");return{...e,headers:{},statusCode:204}}async handlePost(t,e,r,s,n){if(e&&t.size!==void 0){const l=typeof t.size=="number"?t.size:Number.parseInt(String(t.size),10);if(l>0&&l>this.storage.maxUploadSize)throw d(413,`File size exceeds maximum allowed size of ${this.storage.maxUploadSize} bytes`)}const i=await this.storage.create(t);if(e){const l=this.buildFileUrl(r,i);return g(i,{...C(i,l),"X-Chunked-Upload":"true","X-Upload-ID":i.id},201)}const o=await this.storage.write({body:s,contentLength:n,id:i.id,start:0}),c=this.buildFileUrl(r,o);return g(o,C(o,c),201)}async handlePut(t,e,r,s,n,i){let o,c=!1;try{await this.storage.getMeta(t),c=!0,i&&await this.storage.update({id:t},{metadata:i}),o=await this.storage.write({body:s,contentLength:n,id:t,start:0})}catch(f){const k=f;if(k.UploadErrorCode===E.FILE_NOT_FOUND||k.code==="ENOENT")try{const p=await this.storage.create(e);o=await this.storage.write({body:s,contentLength:n,id:p.id,start:0})}catch(p){throw p}else throw f}const l=this.buildFileUrl(r,o);return g(o,C(o,l),c?200:201)}async handlePatch(t,e,r,s,n,i){let o=await this.storage.getMeta(t);const c=o.metadata||{},l=U(o);if(l){const u=y(o);u&&o.size!==u&&(o={...o,size:u})}const f=typeof c._totalSize=="number"?c._totalSize:o.size||0;if(!l)throw d(400,"File is not a chunked upload. Use POST or PUT for full file uploads.");const k=100*1024*1024;try{T(e,r,f,k)}catch(u){throw u instanceof Error&&u.message.includes("exceeds maximum")?d(413,u.message):d(400,u instanceof Error?u.message:String(u))}if(o.status==="completed"){const u=this.buildFileUrl(n,o);return g(o,{...C(o,u),"X-Upload-Complete":"true"},200)}const p=await this.storage.withLock(`chunks:${t}`,async()=>{const u=(await this.storage.getMeta(t)).metadata??{},O=Array.isArray(u._chunks)?u._chunks:[],z=D(O,{checksum:s,length:r,offset:e});return await this.storage.update({id:t},{metadata:{...u,_chunks:z}}),z});let m=await this.storage.write({body:i,contentLength:r,id:t,start:e}),w=m.bytesWritten>=f;l&&(w=x(p,f),m.status==="completed"&&!w&&(await this.storage.update({id:t},{status:"part"}),m={...m,status:"part"}));const b=w&&m.bytesWritten!==f?{...m,bytesWritten:f}:m,N=this.buildFileUrl(n,b),F={...C(b,N),...S(b,w),"x-upload-offset":String(b.bytesWritten||0)};return g(b,F,w?200:202)}async handleHead(t){let e=await this.storage.getMeta(t);const r=U(e);if(r){const n=y(e);n&&e.size!==n&&(e={...e,size:n})}const s={...X(e)};if(r){const n=e.metadata||{},i=y(e)||e.size||0,o=Array.isArray(n._chunks)?n._chunks:[],c=x(o,i);Object.assign(s,S(e,c))}return g(e,s,200)}handleOptions(t,e){return{headers:{"Access-Control-Allow-Headers":"Authorization, Content-Type, Content-Length, Content-Disposition, X-File-Metadata, X-Chunked-Upload, X-Total-Size, X-Chunk-Offset, X-Chunk-Checksum","Access-Control-Allow-Methods":t.map(r=>r.toUpperCase()).join(", "),"Access-Control-Max-Age":86400,"X-Max-Upload-Size":String(e)},statusCode:204}}async deleteBatch(t){const e=await this.storage.deleteBatch(t);if(e.successfulCount===0&&e.failedCount>0){const r=e.failed.map(s=>s.id).join(", ");throw d(404,`Failed to delete files: ${r}`)}return{data:e.successful,headers:e.failedCount>0?{"X-Delete-Errors":JSON.stringify(e.failed),"X-Delete-Failed":String(e.failedCount),"X-Delete-Successful":String(e.successfulCount)}:{"X-Delete-Successful":String(e.successfulCount)},statusCode:e.successfulCount===t.length?204:207}}get storage(){throw new Error("storage must be implemented")}buildFileUrl(t,e){throw new Error("buildFileUrl must be implemented")}}export{j as X,B as a,A as b,L as c,W as e,v as p,P as v};
@@ -0,0 +1 @@
1
+ import{Readable as w}from"node:stream";import{J as M,B as U,O as C,c as O}from"./storage-DR7qdwBN.js";import{d as T}from"./detect-file-type-BA7UBLKA.js";import{throwErrorCode as m,ERRORS as y}from"./ERRORS-BIBxE2oR.js";import{createRetryWrapper as A}from"./createRetryWrapper-DgmeHPNF.js";import{y as k}from"./local-meta-storage-BELb1YwO.js";import{t as x}from"./update-size-DuNuLyxj.js";import{i as I}from"./part-match-D-9dGX42.js";import{e as R}from"./has-content-50BsqrWw.js";import{t as S}from"./get-file-status-y3wTtDQs.js";const z=(u,t)=>{const i={};return Object.keys(u).forEach(e=>{i[e]=t(u[e])}),i},v=u=>u===Number(u)?u:(M(u)??0)/1e3,B=5*1024*1024,L=16*1024*1024,N=u=>{if(u)return`bytes=${Math.max(0,u.start)}-${u.end===void 0?"":u.end}`};class b extends U{checksumTypes=["md5","crc32","crc32c","sha1","sha256"];supportsRange=!0;supportsDelimiter=!0;bucket;meta;MAX_PARTS=1e4;partSize;retry;resolvedRetryConfig;constructor(t){if(super(t),this.bucket=t.bucket,this.partSize=typeof t.partSize=="string"?C(t.partSize):t.partSize||L,this.partSize<B)throw new Error("Minimum allowed partSize value is 5MB");const i={backoffMultiplier:2,initialDelay:1e3,maxDelay:3e4,maxRetries:3,retryableStatusCodes:[408,429,500,502,503,504],shouldRetry:a=>{const s=a;return s.statusCode&&[408,429,500,502,503,504].includes(s.statusCode)||s.retryable===!0?!0:void 0},...t.retryConfig};this.retry=A(i),this.resolvedRetryConfig=i;const{metaStorage:e,metaStorageConfig:r}=t;if(e)this.meta=e;else{const a={...t,...r,logger:this.logger};"directory"in a?(this.logger?.debug("Using local meta storage"),this.meta=new k(a)):this.meta=new k(a)}this.isReady=!1,this.accessCheck().then(()=>{this.isReady=!0}).catch(a=>{this.logger?.error("Storage access check failed: %O",a)})}getRetryConfig(){return this.resolvedRetryConfig}async create(t,i){return this.instrumentOperation("create",async()=>{const e={...t};if(t.ttl){const n=typeof t.ttl=="string"?O(t.ttl):t.ttl;n!==void 0&&(e.expiredAt=Date.now()+n)}const r=new(this.getFileClass())(e);r.name=this.namingFunction(r),await this.validate(r);try{const n=await this.getMeta(r.id);if(n.bytesWritten>=0)return n}catch{}const a=this.getS3Api();let s;try{s=await this.runOperation(i,n=>a.createMultipartUpload({ACL:this.getAcl(),Bucket:this.bucket,ContentType:r.contentType,Key:r.name,Metadata:z({originalName:r.originalName,...r.metadata},o=>encodeURI(String(o)))},{signal:n}))}catch{return m(y.FILE_ERROR,"s3 create upload error")}const{UploadId:c}=s||{};return c?(r.UploadId=c,r.bytesWritten=0,this.config.clientDirectUpload&&(r.partSize??=this.partSize),await this.saveMeta(r),r.status="created",await this.onCreate(r),this.config.clientDirectUpload?this.buildPresigned(r):r):m(y.FILE_ERROR,"s3 create upload error")})}async write(t,i){return this.instrumentOperation("write",async()=>{let e;if("contentType"in t&&"metadata"in t&&!("body"in t)&&!("start"in t)?e=t:(e=await this.getMeta(t.id),await this.checkIfExpired(e)),e.status==="completed")return e;if(typeof t.size=="number"&&t.size>0&&x(e,t.size),!I(t,e))return m(y.FILE_CONFLICT);if(this.config.clientDirectUpload)return this.buildPresigned(e);e.Parts??=await this.getParts(e),e.bytesWritten=e.Parts.map(a=>a.Size||0).reduce((a,s)=>a+s,0);const r=await this.lock(t.id);try{if(R(t)){if(this.isUnsupportedChecksum(t.checksumAlgorithm))return m(y.UNSUPPORTED_CHECKSUM_ALGORITHM);if(e.Parts.length===0&&(!e.contentType||e.contentType==="application/octet-stream"))try{const d=t.body instanceof w?t.body:w.fromWeb(t.body),{fileType:g,stream:f}=await T(d);g?.mime&&(e.contentType=g.mime),t.body=f}catch{}if(e.Parts.length>this.MAX_PARTS)throw new Error(`Exceeded ${this.MAX_PARTS} as part of the upload to ${this.bucket}.`);const a=e.Parts.length+1,s=this.getS3Api(),c=e.UploadId;if(!c)throw new Error("UploadId is required");const n=t.body,o=n instanceof Uint8Array,{ETag:l}=await this.runOperation(i,d=>s.uploadPart({Body:n,Bucket:this.bucket,ContentLength:t.contentLength||0,Key:e.name,PartNumber:a,UploadId:c,...t.checksumAlgorithm==="md5"?{ContentMD5:t.checksum}:{}},{signal:d}),{replayable:o}),p={ETag:l,PartNumber:a,Size:t.contentLength};e.Parts=[...e.Parts,p],e.bytesWritten+=t.contentLength||0}if(this.cache.set(e.id,e),e.status=S(e),e.status==="completed"){const[a]=await this.internalOnComplete(e);delete e.Parts,e.uri=a.Location,e.ETag=a.ETag}}finally{await this.unlock(t.id,r)}return e})}async delete({id:t},i){return this.instrumentOperation("delete",async()=>{const e=await this.getMeta(t);e.status="deleted",await this.abortMultipartUpload(e,i),await this.deleteMeta(e.id);const r={...e};return await this.onDelete(r),r})}async copy(t,i,e){return this.instrumentOperation("copy",async()=>{b.assertSafeId(t),b.assertSafeId(i);const r=await this.getMeta(t),a=`${this.bucket}/${t}`,s=this.bucket,c=i,n=this.getS3Api();return await this.runOperation(e,o=>n.copyObject({Bucket:s,CopySource:a,Key:c,...e?.storageClass&&{StorageClass:e.storageClass}},{signal:o})),{...r,id:c,name:c}})}async move(t,i,e){return this.instrumentOperation("move",async()=>{await this.copy(t,i,e);const r=this.getS3Api();return await this.runOperation(e,a=>r.deleteObject({Bucket:this.bucket,Key:t},{signal:a})),await this.getMeta(i)})}async list(t=1e3,i){return this.instrumentOperation("list",async()=>{const e=this.getS3Api(),r=Math.min(t,1e3);let a={Bucket:this.bucket,MaxKeys:r};const s=[];let c=!0;for(;c&&s.length<t;)try{const n=await this.runOperation(i,o=>e.listObjectsV2(a,{signal:o}));for(const{Key:o,LastModified:l}of n?.Contents||[]){if(s.length>=t)break;o!==void 0&&s.push({id:o,...l&&{createdAt:l}})}c=n.IsTruncated||!1,c&&n.NextContinuationToken&&s.length<t&&(a={...a,ContinuationToken:n.NextContinuationToken,MaxKeys:Math.min(r,t-s.length)})}catch(n){const o=this.normalizeError(n instanceof Error?n:new Error(String(n)));throw await this.onError(o),n}return s},{limit:t})}async listDirectory(t){return this.instrumentOperation("listDirectory",async()=>{const i=this.getS3Api(),e=t?.limit??1e3,r=Math.min(e,1e3);let a={Bucket:this.bucket,Delimiter:t?.delimiter,MaxKeys:r,...t?.prefix!==void 0&&{Prefix:t.prefix}};const s=[],c=new Set;let n=!0;for(;n&&s.length<e;)try{const o=await this.runOperation(t,l=>i.listObjectsV2(a,{signal:l}));for(const{Prefix:l}of o?.CommonPrefixes||[])l!==void 0&&c.add(l);for(const{Key:l,LastModified:p}of o?.Contents||[]){if(s.length>=e)break;l!==void 0&&s.push({id:l,...p&&{createdAt:p}})}n=o.IsTruncated||!1,n&&o.NextContinuationToken&&s.length<e&&(a={...a,ContinuationToken:o.NextContinuationToken,MaxKeys:Math.min(r,e-s.length)})}catch(o){const l=this.normalizeError(o instanceof Error?o:new Error(String(o)));throw await this.onError(l),o}return{files:s,prefixes:[...c]}},{limit:t?.limit??1e3})}async exists({id:t},i){return this.instrumentOperation("exists",async()=>{try{await this.getMeta(t);const e=this.getS3Api();return await this.runOperation(i,r=>e.headObject({Bucket:this.bucket,Key:t},{signal:r})),!0}catch{return!1}})}async get({id:t},i){return this.instrumentOperation("get",async()=>{const e=this.getS3Api(),r=N(i?.range),{Body:a,ContentLength:s,ContentType:c,ETag:n,Expires:o,LastModified:l,Metadata:p}=await this.runOperation(i,h=>e.getObject({Bucket:this.bucket,Key:t,...r!==void 0&&{Range:r}},{signal:h}));await this.checkIfExpired({expiredAt:o});const d=[];if(a)if(a instanceof w)for await(const h of a)d.push(h instanceof Uint8Array?h:new Uint8Array(h));else{const h=a.getReader();try{for(;;){const{done:P,value:E}=await h.read();if(P)break;d.push(E)}}finally{h.releaseLock()}}const{originalName:g,...f}=p||{};return{content:Buffer.concat(d),contentType:c,ETag:n,expiredAt:o,id:t,metadata:f,modifiedAt:l,name:t,originalName:g||t,size:Number(s)}})}async buildPresigned(t){const i=t;if(i.Parts?.length||(i.Parts=await this.getParts(t)),i.bytesWritten=i.Parts.map(e=>e.Size||0).reduce((e,r)=>e+r,0),t.status=S(i),i.partsUrls?.length||(i.partsUrls=await this.getPartsPresignedUrls(t)),t.status==="completed"){const[e]=await this.internalOnComplete(t);return delete i.Parts,i.uri=e.Location,t}return t}async getPartsPresignedUrls(t){t.partSize??=this.partSize;const i=t.UploadId;if(!i)throw new Error("UploadId is required for getting presigned URLs");const e=Math.trunc(t.size/this.partSize)+1,r=[],a=Math.trunc(v(this.config.expiration?.maxAge||"6hrs")),s=this.getS3Api();for(let c=0;c<e;c++)r.push(s.getPresignedUrl({Bucket:this.bucket,expiresIn:a,Key:t.name,PartNumber:c+1,UploadId:i}));return Promise.all(r)}async getParts(t){const i=this.getS3Api(),e=t.UploadId;if(!e)throw new Error("UploadId is required");const{Parts:r=[]}=await this.runOperation(void 0,a=>i.listParts({Bucket:this.bucket,Key:t.name,UploadId:e},{signal:a}));return r}completeMultipartUpload(t){const i=this.getS3Api(),e=t.UploadId;if(!e)throw new Error("UploadId is required");const r=t.Parts?.map(({ETag:a,PartNumber:s})=>{if(!a||!s)throw new Error("ETag and PartNumber are required");return{ETag:a,PartNumber:s}})||[];return this.runOperation(void 0,a=>i.completeMultipartUpload({Bucket:this.bucket,Key:t.name,Parts:r,UploadId:e},{signal:a}))}async abortMultipartUpload(t,i){if(t.status!=="completed")try{const e=this.getS3Api(),r=t.UploadId;if(!r)return;await this.runOperation(i,a=>e.abortMultipartUpload({Bucket:this.bucket,Key:t.name,UploadId:r},{signal:a}))}catch(e){this.logger?.error("abortMultipartUploadError: ",e);const r=this.normalizeError(e instanceof Error?e:new Error(String(e)));await this.onError(r)}}internalOnComplete=async t=>{const[i]=await Promise.all([this.completeMultipartUpload(t),this.deleteMeta(t.id)]);return[i,t]}}export{b as S,N as b};
@@ -1,16 +1,16 @@
1
1
  import { Readable } from 'node:stream';
2
- import { F as File, M as MetaStorage, c as createRetryWrapper, R as RetryConfig, d as FileInit, B as BaseStorage, O as OperationOptions, e as FilePart, f as FileQuery, g as FileReturn } from "./storage.d-CEM1upWM.js";
2
+ import { F as File, M as MetaStorage, c as createRetryWrapper, R as RetryConfig, d as FileInit, B as BaseStorage, O as OperationOptions, e as FilePart, f as FileQuery, g as FileReturn } from "./storage.d-DwdJrArF.js";
3
3
  /**
4
- * Part interface for multipart uploads.
5
- */
4
+ * Part interface for multipart uploads.
5
+ */
6
6
  interface Part {
7
7
  ETag?: string;
8
8
  PartNumber: number;
9
9
  Size?: number;
10
10
  }
11
11
  /**
12
- * Base file type for S3-compatible storage.
13
- */
12
+ * Base file type for S3-compatible storage.
13
+ */
14
14
  interface S3CompatibleFile extends File {
15
15
  Parts?: Part[];
16
16
  partSize?: number;
@@ -19,15 +19,15 @@ interface S3CompatibleFile extends File {
19
19
  uri?: string;
20
20
  }
21
21
  /**
22
- * Per-call options forwarded to the underlying AWS SDK send().
23
- */
22
+ * Per-call options forwarded to the underlying AWS SDK send().
23
+ */
24
24
  interface S3CallOptions {
25
25
  /** Forwarded to `client.send(command, { abortSignal })`. */
26
26
  signal?: AbortSignal;
27
27
  }
28
28
  /**
29
- * S3 API operations interface that must be implemented by concrete storage classes.
30
- */
29
+ * S3 API operations interface that must be implemented by concrete storage classes.
30
+ */
31
31
  interface S3ApiOperations {
32
32
  abortMultipartUpload: (params: {
33
33
  Bucket: string;
@@ -136,10 +136,10 @@ interface S3ApiOperations {
136
136
  }>;
137
137
  }
138
138
  /**
139
- * Base class for S3-compatible storage implementations.
140
- * Contains all shared business logic for S3 operations.
141
- * @template TFile The file type used by this storage backend.
142
- */
139
+ * Base class for S3-compatible storage implementations.
140
+ * Contains all shared business logic for S3 operations.
141
+ * @template TFile The file type used by this storage backend.
142
+ */
143
143
  declare abstract class S3BaseStorage<TFile extends S3CompatibleFile = S3CompatibleFile> extends BaseStorage<TFile> {
144
144
  override checksumTypes: string[];
145
145
  override readonly supportsRange: boolean;
@@ -147,27 +147,27 @@ declare abstract class S3BaseStorage<TFile extends S3CompatibleFile = S3Compatib
147
147
  protected bucket: string;
148
148
  protected meta: MetaStorage<TFile>;
149
149
  /**
150
- * S3 multipart upload does not allow more than 10000 parts.
151
- */
150
+ * S3 multipart upload does not allow more than 10000 parts.
151
+ */
152
152
  protected readonly MAX_PARTS = 1e4;
153
153
  protected readonly partSize: number;
154
154
  protected readonly retry: ReturnType<typeof createRetryWrapper>;
155
155
  protected readonly resolvedRetryConfig: RetryConfig;
156
156
  /**
157
- * Abstract method to get S3 API operations implementation.
158
- */
157
+ * Abstract method to get S3 API operations implementation.
158
+ */
159
159
  protected abstract getS3Api(): S3ApiOperations;
160
160
  /**
161
- * Abstract method to get the file class constructor.
162
- */
161
+ * Abstract method to get the file class constructor.
162
+ */
163
163
  protected abstract getFileClass(): new (config: FileInit) => TFile;
164
164
  /**
165
- * Abstract method to get ACL value.
166
- */
165
+ * Abstract method to get ACL value.
166
+ */
167
167
  protected abstract getAcl(): string | undefined;
168
168
  /**
169
- * Abstract method for access check.
170
- */
169
+ * Abstract method for access check.
170
+ */
171
171
  protected abstract accessCheck(maxWaitTime?: number): Promise<void>;
172
172
  constructor(config: {
173
173
  bucket: string;
@@ -184,39 +184,37 @@ declare abstract class S3BaseStorage<TFile extends S3CompatibleFile = S3Compatib
184
184
  });
185
185
  protected override getRetryConfig(): RetryConfig;
186
186
  /**
187
- * Creates a new S3 multipart upload.
188
- */
187
+ * Creates a new S3 multipart upload.
188
+ */
189
189
  create(config: FileInit, options?: OperationOptions): Promise<TFile>;
190
190
  /**
191
- * Writes data to an S3 multipart upload.
192
- */
191
+ * Writes data to an S3 multipart upload.
192
+ */
193
193
  write(part: FilePart | FileQuery | TFile, options?: OperationOptions): Promise<TFile>;
194
194
  /**
195
- * Deletes an upload and its metadata.
196
- */
197
- delete({
198
- id
199
- }: FileQuery, options?: OperationOptions): Promise<TFile>;
195
+ * Deletes an upload and its metadata.
196
+ */
197
+ delete({ id }: FileQuery, options?: OperationOptions): Promise<TFile>;
200
198
  /**
201
- * Copies an upload file to a new location.
202
- */
199
+ * Copies an upload file to a new location.
200
+ */
203
201
  copy(name: string, destination: string, options?: OperationOptions & {
204
202
  storageClass?: string;
205
203
  }): Promise<TFile>;
206
204
  /**
207
- * Moves an upload file to a new location.
208
- */
205
+ * Moves an upload file to a new location.
206
+ */
209
207
  move(name: string, destination: string, options?: OperationOptions): Promise<TFile>;
210
208
  /**
211
- * Lists files in the bucket.
212
- */
209
+ * Lists files in the bucket.
210
+ */
213
211
  override list(limit?: number, options?: OperationOptions): Promise<TFile[]>;
214
212
  /**
215
- * Directory-style listing via S3's native `Delimiter`/`Prefix` — the provider returns the direct
216
- * child objects plus the `CommonPrefixes` ("subdirectories") one delimiter level below `prefix`,
217
- * so the whole subtree never has to be fetched. Pages until exhausted or `limit` direct files
218
- * have been collected; common prefixes are accumulated (deduped) across pages.
219
- */
213
+ * Directory-style listing via S3's native `Delimiter`/`Prefix` — the provider returns the direct
214
+ * child objects plus the `CommonPrefixes` ("subdirectories") one delimiter level below `prefix`,
215
+ * so the whole subtree never has to be fetched. Pages until exhausted or `limit` direct files
216
+ * have been collected; common prefixes are accumulated (deduped) across pages.
217
+ */
220
218
  override listDirectory(options?: OperationOptions & {
221
219
  delimiter: string;
222
220
  limit?: number;
@@ -226,59 +224,55 @@ declare abstract class S3BaseStorage<TFile extends S3CompatibleFile = S3Compatib
226
224
  prefixes: string[];
227
225
  }>;
228
226
  /**
229
- * Checks if a file exists by verifying both metadata and the actual S3 object.
230
- * Returns true only if both the metadata and the S3 object exist.
231
- * @param query File query containing the file ID to check.
232
- * @returns Promise resolving to true if both metadata and S3 object exist, false otherwise.
233
- */
234
- override exists({
235
- id
236
- }: FileQuery, options?: OperationOptions): Promise<boolean>;
227
+ * Checks if a file exists by verifying both metadata and the actual S3 object.
228
+ * Returns true only if both the metadata and the S3 object exist.
229
+ * @param query File query containing the file ID to check.
230
+ * @returns Promise resolving to true if both metadata and S3 object exist, false otherwise.
231
+ */
232
+ override exists({ id }: FileQuery, options?: OperationOptions): Promise<boolean>;
237
233
  /**
238
- * Gets an uploaded file by ID.
239
- */
240
- get({
241
- id
242
- }: FileQuery, options?: OperationOptions & {
234
+ * Gets an uploaded file by ID.
235
+ */
236
+ get({ id }: FileQuery, options?: OperationOptions & {
243
237
  range?: {
244
238
  end?: number;
245
239
  start: number;
246
240
  };
247
241
  }): Promise<FileReturn>;
248
242
  /**
249
- * Gets file stream (abstract - must be implemented by subclasses due to stream differences).
250
- */
243
+ * Gets file stream (abstract - must be implemented by subclasses due to stream differences).
244
+ */
251
245
  abstract override getStream(query: FileQuery, options?: OperationOptions): Promise<{
252
246
  headers?: Record<string, string>;
253
247
  size?: number;
254
248
  stream: Readable;
255
249
  }>;
256
250
  /**
257
- * Builds presigned URLs for client uploads.
258
- */
251
+ * Builds presigned URLs for client uploads.
252
+ */
259
253
  protected buildPresigned(file: TFile): Promise<TFile>;
260
254
  /**
261
- * Gets presigned URLs for all parts.
262
- */
255
+ * Gets presigned URLs for all parts.
256
+ */
263
257
  protected getPartsPresignedUrls(file: TFile): Promise<string[]>;
264
258
  /**
265
- * Gets parts for a multipart upload.
266
- */
259
+ * Gets parts for a multipart upload.
260
+ */
267
261
  protected getParts(file: TFile): Promise<Part[]>;
268
262
  /**
269
- * Completes a multipart upload.
270
- */
263
+ * Completes a multipart upload.
264
+ */
271
265
  protected completeMultipartUpload(file: TFile): Promise<{
272
266
  ETag?: string;
273
267
  Location: string;
274
268
  }>;
275
269
  /**
276
- * Aborts a multipart upload.
277
- */
270
+ * Aborts a multipart upload.
271
+ */
278
272
  protected abortMultipartUpload(file: TFile, options?: OperationOptions): Promise<void>;
279
273
  /**
280
- * Internal onComplete handler.
281
- */
274
+ * Internal onComplete handler.
275
+ */
282
276
  protected internalOnComplete: (file: TFile) => Promise<[{
283
277
  ETag?: string;
284
278
  Location: string;
@@ -0,0 +1 @@
1
+ import{Readable as Y}from"node:stream";import{setInterval as G}from"node:timers";import{inspect as K}from"node:util";import{W as H,v as O}from"./path-C-OWflAo-_mqb5p5d.js";import q from"type-is";import J from"./NoOpMetrics-BLo6u4NY.js";import{N as Q}from"./cache-Cw3QjoVN.js";import{ErrorMap as $,throwErrorCode as b,ERRORS as v}from"./ERRORS-BIBxE2oR.js";import{randomUUID as X}from"node:crypto";import{LRUCache as ee}from"lru-cache";import{retry as te}from"./createRetryWrapper-DgmeHPNF.js";import{t as re}from"./is-expired-CBEk6XBi.js";const se=new RegExp("^(?<value>-?\\d+(?:[\\p{Zs}'’.,]\\d+)*)\\p{Zs}*(?<type>[a-z]+)?$","iu"),oe={iec:[{long:"Bytes",short:"B"},{long:"Kibibytes",short:"KiB"},{long:"Mebibytes",short:"MiB"},{long:"Gibibytes",short:"GiB"},{long:"Tebibytes",short:"TiB"},{long:"Pebibytes",short:"PiB"},{long:"Exbibytes",short:"EiB"},{long:"Zebibytes",short:"ZiB"},{long:"Yobibytes",short:"YiB"}],iec_octet:[{long:"Octets",short:"o"},{long:"Kibioctets",short:"Kio"},{long:"Mebioctets",short:"Mio"},{long:"Gibioctets",short:"Gio"},{long:"Tebioctets",short:"Tio"},{long:"Pebioctets",short:"Pio"},{long:"Exbioctets",short:"Eio"},{long:"Zebioctets",short:"Zio"},{long:"Yobioctets",short:"Yio"}],metric:[{long:"Bytes",short:"Bytes"},{long:"Kilobytes",short:"KB"},{long:"Megabytes",short:"MB"},{long:"Gigabytes",short:"GB"},{long:"Terabytes",short:"TB"},{long:"Petabytes",short:"PB"},{long:"Exabytes",short:"EB"},{long:"Zettabytes",short:"ZB"},{long:"Yottabytes",short:"YB"}],metric_octet:[{long:"Octets",short:"o"},{long:"Kilo-octets",short:"ko"},{long:"Mega-octets",short:"Mo"},{long:"Giga-octets",short:"Go"},{long:"Tera-octets",short:"To"},{long:"Peta-octets",short:"Po"},{long:"Exa-octets",short:"Eo"},{long:"Zetta-octets",short:"Zo"},{long:"Yotta-octets",short:"Yo"}]},ie=["metric","iec","metric_octet","iec_octet"],ne=1024,ae=t=>t==="iec"||t==="iec_octet",R=new Map,ce=t=>{let e=R.get(t);if(e===void 0){const r=new Intl.NumberFormat(t);e={decimalSeparator:r.format(1.1).replaceAll(new RegExp("\\p{Number}","gu"),""),thousandSeparator:r.format(11111).replaceAll(new RegExp("\\p{Number}","gu"),"")},R.set(t,e)}return e},le=(t,e)=>{const{decimalSeparator:r,thousandSeparator:s}=ce(e),o=t.replaceAll(/[\p{Zs}'’]/gu,"");return Number.parseFloat(o.replaceAll(new RegExp(`\\${s}`,"g"),"").replace(new RegExp(`\\${r}`),"."))},ue=t=>{switch(t){case 2:return 1024;case 10:return 1e3;default:throw new Error("Unsupported base.")}},ge=(t,e)=>{for(const r of[e,...ie.filter(s=>s!==e)]){const s=oe[r].findIndex(o=>o.short.toUpperCase()===t||o.long.toUpperCase()===t);if(s!==-1)return{level:s,system:r}}},U=(t,e)=>{const r={base:2,locale:"en-US",units:"metric",...e};if(typeof t!="string"||t.length===0)throw new TypeError("Value is not a string or is empty.");if(t.length>100)throw new TypeError("Value exceeds the maximum length of 100 characters.");const s=se.exec(t)?.groups;if(!s)return Number.NaN;const o=le(s.value,r.locale),i=ge((s.type??"Bytes").toUpperCase(),r.units);if(i===void 0)return Number.NaN;const n=ue(r.base),c=ae(i.system)?ne:n;return o*c**i.level},me=(t,e,r,s,o,i,n,c,l,a,u,m,g,p)=>{const d={d:s,h:o,m:i,mo:e,ms:c,s:n,w:r,y:t};return d.future=l,d.past=a,d.decimal=u,m!==void 0&&(d.unitMap=m),d.groupSeparator=g,d.placeholderSeparator=p,d},I={d:"d",day:"d",days:"d",h:"h",hour:"h",hours:"h",hr:"h",hrs:"h",m:"m",millisecond:"ms",milliseconds:"ms",min:"m",mins:"m",minute:"m",minutes:"m",mo:"mo",month:"mo",months:"mo",ms:"ms",s:"s",sec:"s",second:"s",seconds:"s",secs:"s",w:"w",week:"w",weeks:"w",y:"y",year:"y",years:"y",yr:"y",yrs:"y"},de=me(t=>`year${t===1?"":"s"}`,t=>`month${t===1?"":"s"}`,t=>`week${t===1?"":"s"}`,t=>`day${t===1?"":"s"}`,t=>`hour${t===1?"":"s"}`,t=>`minute${t===1?"":"s"}`,t=>`second${t===1?"":"s"}`,t=>`millisecond${t===1?"":"s"}`,"in %s","%s ago",".",I,",","_"),z=new WeakSet,he=t=>{if(z.has(t))return;const e=["y","mo","w","d","h","m","s","ms"];for(const s of e)if(!Object.hasOwn(t,s))throw new TypeError(`Missing required property: ${s}`);if(t.future!==void 0&&typeof t.future!="string")throw new TypeError("Properties future and past must be of type string");if(t.past!==void 0&&typeof t.past!="string")throw new TypeError("Properties future and past must be of type string");const r=["y","mo","w","d","h","m","s","ms"];for(const s of r)if(typeof t[s]!="string"&&typeof t[s]!="function")throw new TypeError(`Property ${s} must be of type string or function`);if(t.decimal&&typeof t.decimal!="string")throw new TypeError("Property decimal must be of type string");if(t.delimiter&&typeof t.delimiter!="string")throw new TypeError("Property delimiter must be of type string");if(t._digitReplacements&&!Array.isArray(t._digitReplacements))throw new TypeError("Property _digitReplacements must be an array");if(t._numberFirst&&typeof t._numberFirst!="boolean")throw new TypeError("Property _numberFirst must be of type boolean");if(t.unitMap&&typeof t.unitMap!="object")throw new TypeError("Property unitMap must be an object");if(t.unitMap&&Object.values(t.unitMap).some(s=>typeof s!="string"))throw new TypeError("All values in unitMap must be of type string");z.add(t)},w={d:864e5,h:36e5,m:6e4,mo:2629746e3,ms:1,s:1e3,w:6048e5,y:31556952e3},S=/[-/\\^$*+?.()|[\]{}]/g,P=new WeakMap,B=new WeakMap,pe=t=>{let e=B.get(t);if(e===void 0){const r=t.decimal??".",s=t.groupSeparator??",",o=t.placeholderSeparator??"_",i=r.replaceAll(S,String.raw`\$&`),n=s.replaceAll(S,String.raw`\$&`),c=o.replaceAll(S,String.raw`\$&`);e={decimalRewrite:r==="."?void 0:new RegExp(String.raw`(\d)${i}(\d)`,"g"),groupStrip:new RegExp(String.raw`(\d)[${c}${n}](\d)`,"g")},B.set(t,e)}return e},E=t=>String.raw`(?:(\d+(?:[.,]\d+)?)${t})?`,fe=new RegExp(`^P${E("Y")}${E("M")}${E("W")}${E("D")}(?:T${E("H")}${E("M")}${E("S")})?$`,"i"),ye=/^(?:\s*,)?\s*$/,A=new Map,we=64,be=t=>{const e=t===void 0?"":t.trim();if(e.length===0)return ye;let r=A.get(e);if(r===void 0){A.size>=we&&A.clear();const s=e.replaceAll(S,String.raw`\$&`);r=new RegExp(String.raw`^(?:\s*,)?\s*(?:${s}\s*)?$`,"i"),A.set(e,r)}return r},ve=/^(?:(\d+):)?(?:(\d+):)?(\d+)$/,Ee=/^[+-]?\d+(?:\.\d+)?$/,$e=/^[-+]/,xe=(t,e)=>{if(typeof t!="string"||t.length===0)return;const{conjunction:r,defaultUnit:s="ms",language:o=de}={};he(o);const{decimalRewrite:i,groupStrip:n}=pe(o),c=o.unitMap??I;let l=t.replaceAll(n,"$1$2");if(i!==void 0&&(l=l.replaceAll(i,"$1.$2")),Ee.test(l.trim())){const f=Number.parseFloat(l.trim());if(!Number.isNaN(f)){const h=c[s];if(h!==void 0)return f*w[h]}return}const a=fe.exec(t);if(a){const f=[[1,w.y],[2,w.mo],[3,w.w],[4,w.d],[5,w.h],[6,w.m],[7,w.s]];let h=0,y=!1;for(const[N,D]of f){const x=a[N];x!==void 0&&(y=!0,h+=Number.parseFloat(x.replace(",","."))*D)}if(y)return h}const u=ve.exec(t);if(u){let f=0,h=0;u[2]!==void 0?(f=Number.parseInt(u[1]??"0",10),h=Number.parseInt(u[2],10)):u[1]!==void 0&&(h=Number.parseInt(u[1],10));const y=Number.parseInt(u[3]??"0",10);return f*36e5+h*6e4+y*1e3}let m=P.get(c);if(m===void 0){const f=Object.keys(c).toSorted((h,y)=>y.length-h.length).map(h=>h.replaceAll(S,String.raw`\$&`)).join("|");m=new RegExp(String.raw`(-?\d*\.?\d+)\s*(${f})`,"gi"),P.set(c,m)}const g=be(r);let p=0,d,T=!1,_=-1,M=0;for(m.lastIndex=0;(d=m.exec(l))!==null;){const f=d[1],h=d[2];if(!f||!h)continue;const y=f.trim(),N=y.startsWith("-")?-1:1,D=y.replace($e,""),x=Number.parseFloat(D),k=c[h.toLowerCase()];if(k===void 0)continue;if(!T)_=d.index;else if(!g.test(l.slice(M,d.index)))return;T=!0,M=m.lastIndex;const Z=w[k];if(Number.isNaN(x))return;p+=N*x*Z}const j=l.slice(0,_).trim(),W=l.slice(M).trim();if(!(T&&(j.length>0||W.length>0))&&T)return p};class Se extends ee{constructor(e){super({ttl:3e4,ttlAutopurge:!0,...e})}lock(e){if(this.get(e)!==void 0)throw new Error(`${e} is locked`);const r=X();return this.set(e,r),r}unlock(e,r){return this.get(e)!==r?!1:this.delete(e)}}const C=t=>{if(t===Number(t))return t;if(!t)return;const e=xe(t);if(e!==void 0)return e};class Te extends Error{code;statusCode;body;headers;name="ValidationError";constructor(e,r,s,o){const i=typeof s=="string"?s:s?.message||"Validation error";super(i),this.code=e,this.statusCode=r,this.body=s,this.headers=o}}const Ae=t=>t&&t[0].toUpperCase()+t.slice(1),Ce=t=>{if(!Array.isArray(t))return t;const[e,r,s]=t;return{body:r,headers:s,statusCode:e}};class Me{constructor(e="ValidationError"){this.prefix=e}prefix;validators={};add(e){Object.entries(e).forEach(([r,s])=>{const o=`${this.prefix}${Ae(r)}`;if(this.validators[o]={...this.validators[o],...s},typeof this.validators[o].isValid!="function")throw new TypeError('Validation config "isValid" is missing, or it is not a function!')})}async verify(e){for(const[r,s]of Object.entries(this.validators))if(!await s.isValid(e)){const o=s.response||(r in $?$[r]:$.UnknownError),i=Ce(o),{body:n,headers:c,message:l,statusCode:a}=i;throw new Te(r,a,n||l,c)}}}const Ye=t=>t.name==="ValidationError",Ne=t=>{if(typeof t.name=="string")return t.name;if(typeof t.title=="string")return t.title;if(typeof t.originalName=="string")return t.originalName;if(typeof t.filename=="string")return t.filename},F=(t,e)=>{const r={...t};return Object.keys(e).forEach(s=>{const o=e[s];if(o!==null&&typeof o=="object"&&!Array.isArray(o)){const i=r[s],n=i&&typeof i=="object"&&!Array.isArray(i)?i:{};r[s]=F(n,o)}else r[s]=o}),r},De=(t,e)=>{const r=F(t,e);Object.assign(t,r),t.originalName=Ne(t.metadata)||t.originalName},Oe=/(secret|password|passwd|pwd|token|api[_-]?key|credential|authorization|sas|signature|sessiontoken|connectionstring)/i,L=t=>{const e={};for(const[r,s]of Object.entries(t))typeof s=="string"&&Oe.test(r)?e[r]="[REDACTED]":s&&typeof s=="object"&&!Array.isArray(s)&&s.constructor===Object?e[r]=L(s):e[r]=s;return e},_e={allowMIME:["*/*"],filename:({id:t})=>t,maxMetadataSize:"8MB",maxUploadSize:"5TB",onComplete:()=>{},onCreate:()=>{},onDelete:()=>{},onError:()=>{},onUpdate:()=>{},useRelativeLocation:!1,validation:{}},ke=t=>!t||t.length<3||t.length>255||O(t)?!1:!(t.toUpperCase().includes("../")||t.includes("\0")),Ge=t=>{if(!t||t.length<3||t.length>255||O(t))return!1;const e=t.toUpperCase();return!['"',"*",":","<",">","?","\\","|","../","\0"].some(r=>e.includes(r))};class V{onCreate;onUpdate;onComplete;onDelete;onError;isReady=!0;errorResponses={};cache;logger;metrics;genericConfig;maxMetadataSize;checksumTypes=[];supportsRange=!1;supportsMetadata=!0;supportsCacheControl=!1;supportsDelimiter=!1;reportsUploadProgress=!1;maxUploadSize;expiration;locker;namingFunction;validation=new Me;assetFolder=void 0;concurrency;autoPurgeTimer;constructor(e){const r={..._e,...e};this.onCreate=r.onCreate,this.onUpdate=r.onUpdate,this.onComplete=r.onComplete,this.onDelete=r.onDelete,this.onError=r.onError,this.namingFunction=r.filename,this.maxUploadSize=typeof r.maxUploadSize=="string"?U(r.maxUploadSize):r.maxUploadSize,this.maxMetadataSize=typeof r.maxMetadataSize=="string"?U(r.maxMetadataSize):r.maxMetadataSize,this.expiration=r.expiration,this.genericConfig=r,r.assetFolder!==void 0&&(this.assetFolder=H(r.assetFolder)),this.locker=new Se({max:1e3,ttl:3e4,ttlAutopurge:!0}),this.cache=r.cache??new Q,this.logger=r.logger,this.metrics=r.metrics??new J,this.logger?.debug(`${this.constructor.name} config: ${K(L({...e,logger:this.logger.constructor}))}`);const s=C(r.expiration?.purgeInterval);s&&this.startAutoPurge(s);const o={isValid(l){if(l.size===void 0)return!0;const a=l.size;if(a==null)return!1;const u=typeof a=="number"?a:Number(a);if(Number.isNaN(u)||u<0)return!1;const m=typeof this.value=="number"?this.value:Number(this.value);return!Number.isNaN(m)&&u<=m},response:$.RequestEntityTooLarge,value:this.maxUploadSize},i={isValid(l){return!!q.is(l.contentType,this.value)},response:$.UnsupportedMediaType,value:r.allowMIME},n=r.fileNameValidation??ke,c={isValid(l){return n(l.name)},response:$.InvalidFileName};this.validation.add({filename:c,mime:i,size:o}),this.validation.add({...r.validation})}get raw(){}async getReadUrl(e,r){return b(v.METHOD_NOT_ALLOWED,`${this.constructor.name} does not implement getReadUrl()`)}async getUploadUrl(e,r){return b(v.METHOD_NOT_ALLOWED,`${this.constructor.name} does not implement getUploadUrl()`)}get tusExtension(){const e=["creation","creation-with-upload","termination","checksum","creation-defer-length","concatenation"];return this.expiration&&e.push("expiration"),e}async validate(e){await this.validation.verify(e)}async exists(e,r){return this.instrumentOperation("exists",async()=>{try{return await this.getMeta(e.id,r),!0}catch{return!1}})}normalizeError(e){const r={code:e.name,message:e.message,name:e.name,statusCode:500};return{...r,message:`[${this.constructor.name}] ${r.message}`}}get config(){return this.genericConfig}async saveMeta(e){return V.assertSafeId(e.id),this.updateTimestamps(e),this.cache.set(e.id,e),this.meta.save(e.id,e)}static assertSafeId(e){(!e||typeof e!="string"||e.includes("\0")||e.includes("../")||e.includes("..\\")||e===".."||e.startsWith("../")||e.startsWith("..\\")||O(e)||/^[A-Z]:[/\\]/i.test(e))&&b(v.INVALID_FILE_NAME,`Invalid file id: "${e}"`)}async deleteMeta(e){return this.cache.delete(e),this.meta.delete(e)}async getMeta(e,r){try{const s=await this.meta.get(e);return this.cache.set(s.id,s),{...s}}catch(s){const o=this.normalizeError(s instanceof Error?s:new Error(String(s)));return await this.onError(o),b(v.FILE_NOT_FOUND)}}async checkIfExpired(e){return re(e)?(this.delete(e).catch(()=>{}),this.deleteMeta(e.id).catch(()=>{}),b(v.GONE)):e}async purge(e){return this.instrumentOperation("purge",async()=>{const r=C(e||this.expiration?.maxAge),s={items:[],maxAgeMs:r};if(r){const o=Date.now()-r,i=(await this.list()).filter(n=>Number(new Date(this.expiration?.rolling&&n.modifiedAt||n.createdAt))<o);for await(const{id:n,...c}of i)try{const l=await this.delete({id:n});s.items.push({...l,...c})}catch(l){this.logger?.warn(`Failed to delete file ${n} during purge: ${l instanceof Error?l.message:String(l)}`)}s.items.length>0&&(this.logger?.info(`Purge: removed ${s.items.length} uploads`),this.metrics.gauge("storage.operations.purge.items_count",s.items.length,{storage:this.constructor.name.toLowerCase().replace("storage","")}))}return s})}async getStream({id:e},r){return this.instrumentOperation("getStream",async()=>{const s=await this.get({id:e},r),o=Y.from(s.content);return{headers:{"Content-Length":String(s.size),"Content-Type":s.contentType,...s.ETag&&{ETag:s.ETag},...s.modifiedAt&&{"Last-Modified":s.modifiedAt.toString()}},size:typeof s.size=="number"?s.size:void 0,stream:o}})}async list(e=1e3,r){return this.instrumentOperation("list",async()=>{throw new Error("Not implemented")})}async listDirectory(e){return b(v.METHOD_NOT_ALLOWED,`${this.constructor.name} does not implement listDirectory()`)}async update({id:e},r){return this.instrumentOperation("update",async()=>{const s=await this.getMeta(e),o={...r};if("ttl"in o&&o.ttl!==void 0){const n=o.ttl,c=typeof n=="string"?C(n):n;c!==void 0&&(o.expiredAt=Date.now()+c),delete o.ttl}De(s,o),await this.saveMeta(s);const i={...s,status:"updated"};return await this.onUpdate(i),i})}async deleteBatch(e,r){const s=Date.now(),o=this.constructor.name.toLowerCase().replace("storage","");this.metrics.increment("storage.operations.batch.delete.count",1,{batch_size:e.length,storage:o});const i=[],n=[],c=e.map(async u=>{try{return{file:await this.delete({id:u},r),id:u,success:!0}}catch(m){const g=m instanceof Error?m.message:"Delete failed";return this.metrics.increment("storage.operations.delete.error.count",1,{error:g,storage:o}),{error:g,id:u,success:!1}}}),l=await Promise.allSettled(c);for(const u of l)u.status==="fulfilled"?u.value.success?i.push(u.value.file):n.push({error:u.value.error,id:u.value.id}):n.push({error:u.reason?.message||"Delete failed",id:""});const a=Date.now()-s;return this.metrics.timing("storage.operations.batch.delete.duration",a,{batch_size:e.length,storage:o}),this.metrics.gauge("storage.operations.batch.delete.success_count",i.length,{storage:o}),this.metrics.gauge("storage.operations.batch.delete.failed_count",n.length,{storage:o}),{failed:n,failedCount:n.length,successful:i,successfulCount:i.length}}async copyBatch(e){const r=Date.now(),s=this.constructor.name.toLowerCase().replace("storage","");this.metrics.increment("storage.operations.batch.copy.count",1,{batch_size:e.length,storage:s});const o=[],i=[],n=e.map(async({destination:a,options:u,source:m})=>{try{return{file:await this.copy(m,a,u),id:a,success:!0}}catch(g){const p=g instanceof Error?g.message:"Copy failed";return this.metrics.increment("storage.operations.copy.error.count",1,{error:p,storage:s}),{error:p,id:a,success:!1}}}),c=await Promise.allSettled(n);for(const a of c)a.status==="fulfilled"?a.value.success&&a.value.file?o.push(a.value.file):i.push({error:a.value.error||"Copy failed",id:a.value.id}):i.push({error:a.reason?.message||"Copy failed",id:""});const l=Date.now()-r;return this.metrics.timing("storage.operations.batch.copy.duration",l,{batch_size:e.length,storage:s}),this.metrics.gauge("storage.operations.batch.copy.success_count",o.length,{storage:s}),this.metrics.gauge("storage.operations.batch.copy.failed_count",i.length,{storage:s}),{failed:i,failedCount:i.length,successful:o,successfulCount:o.length}}async moveBatch(e){const r=Date.now(),s=this.constructor.name.toLowerCase().replace("storage","");this.metrics.increment("storage.operations.batch.move.count",1,{batch_size:e.length,storage:s});const o=[],i=[],n=e.map(async({destination:a,source:u})=>{try{return{file:await this.move(u,a),id:a,success:!0}}catch(m){const g=m instanceof Error?m.message:"Move failed";return this.metrics.increment("storage.operations.move.error.count",1,{error:g,storage:s}),{error:g,id:a,success:!1}}}),c=await Promise.allSettled(n);for(const a of c)a.status==="fulfilled"?a.value.success&&a.value.file?o.push(a.value.file):i.push({error:a.value.error||"Move failed",id:a.value.id}):i.push({error:a.reason?.message||"Move failed",id:a.reason?.id||""});const l=Date.now()-r;return this.metrics.timing("storage.operations.batch.move.duration",l,{batch_size:e.length,storage:s}),this.metrics.gauge("storage.operations.batch.move.success_count",o.length,{storage:s}),this.metrics.gauge("storage.operations.batch.move.failed_count",i.length,{storage:s}),{failed:i,failedCount:i.length,successful:o,successfulCount:o.length}}async lock(e){return this.locker.has(e)?b(v.FILE_LOCKED):this.config.concurrency&&typeof this.config.concurrency=="number"&&this.config.concurrency<=this.locker.size?b(v.STORAGE_BUSY):this.locker.lock(e)}async unlock(e,r){if(r===void 0){this.locker.delete(e);return}this.locker.unlock(e,r)}async withLock(e,r){const s=await this.lock(e);try{return await r()}finally{await this.unlock(e,s)}}isUnsupportedChecksum(e=""){return!!e&&!this.checksumTypes.includes(e)}startAutoPurge(e){if(e>=2147483647)throw new Error("“purgeInterval” must be less than 2147483647 ms");this.autoPurgeTimer=G(()=>{this.purge().catch(r=>this.logger?.error(r))},e),this.autoPurgeTimer.unref?.()}stopAutoPurge(){this.autoPurgeTimer&&(clearInterval(this.autoPurgeTimer),this.autoPurgeTimer=void 0)}async close(){this.stopAutoPurge()}updateTimestamps(e){e.createdAt??=new Date().toISOString();const r=C(this.expiration?.maxAge);return r&&!e.expiredAt&&(e.expiredAt=this.expiration?.rolling?Date.now()+r:+new Date(e.createdAt)+r),e}getRetryConfig(){}runOperation(e,r,s){let o;typeof e?.retries=="number"?o={maxRetries:e.retries}:e?.retries&&(o=e.retries);const i={...this.getRetryConfig(),...o};s?.replayable===!1&&(i.maxRetries=0);const n=[];this.genericConfig.defaultSignal&&n.push(this.genericConfig.defaultSignal),e?.signal&&n.push(e.signal);let c;n.length===1?[c]=n:n.length>1&&(c=AbortSignal.any(n));const l=typeof e?.timeout=="number"?e.timeout:this.genericConfig.defaultTimeout,a=typeof l=="number"&&l>0?l:void 0,u=i.shouldRetry;i.shouldRetry=g=>c?.aborted||g instanceof Error&&g.name==="AbortError"?!1:u?u(g):void 0;const m=g=>{if(g instanceof Error&&g.name==="AbortError")return g;const p=g instanceof Error&&g.message?g.message:"The operation was aborted",d=new Error(p,{cause:g});return d.name="AbortError",d};return te(async()=>{if(c?.aborted)throw m(c.reason);let g,p;if(a===void 0)p=c;else{const d=new AbortController;g=setTimeout(()=>{d.abort(new DOMException(`The operation timed out after ${a}ms`,"TimeoutError"))},a),p=c?AbortSignal.any([c,d.signal]):d.signal}try{return await r(p)}catch(d){throw p?.aborted?m(d):d}finally{g&&clearTimeout(g)}},i)}async instrumentOperation(e,r,s){const o=Date.now(),i={storage:this.constructor.name.toLowerCase().replace("storage",""),...s};try{this.metrics.increment(`storage.operations.${e}.count`,1,i);const n=await r(),c=Date.now()-o;return this.metrics.timing(`storage.operations.${e}.duration`,c,i),n&&typeof n=="object"&&"size"in n&&typeof n.size=="number"&&this.metrics.gauge("storage.files.size",n.size,{...i,operation:e}),n}catch(n){const c=Date.now()-o,l=n instanceof Error?n.message:"Unknown error";throw this.metrics.timing(`storage.operations.${e}.duration`,c,{...i,error:"true"}),this.metrics.increment(`storage.operations.${e}.error.count`,1,{...i,error:l}),n}}}export{V as B,xe as J,U as O,Ge as a,Te as b,C as c,ke as d,De as e,Ye as i};