@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,45 +1,46 @@
1
- export { type d as AudioChannelMixOptions, type c as AudioResampleOptions, type e as AudioTransformOptions, type b as AudioTransformResult, type f as AudioTransformationStep, type A as AudioTransformerConfig, B as BaseTransformer, type C as CropOptions, type h as ImageFormat, type I as ImageTransformerConfig, type U as MediaTransformQuery, type a as MediaTransformResult, type W as MediaTransformationStep, type M as MediaTransformerConfig, type R as ResizeOptions, type g as RotateOptions, type i as TransformOptions, type T as TransformResult, type z as TransformationStep, type K as VideoCropOptions, type H as VideoResizeOptions, type N as VideoRotateOptions, type O as VideoTransformOptions, type F as VideoTransformResult, type Q as VideoTransformationStep, type V as VideoTransformerConfig } from "../packem_shared/types.d-CrUWY4On.js";
2
- export { M as MediaTransformer } from "../packem_shared/media-transformer.d-Quf4ai47.js";
3
- import { g as FileReturn } from "../packem_shared/storage.d-CEM1upWM.js";
1
+ export { type d as AudioChannelMixOptions, type c as AudioResampleOptions, type e as AudioTransformOptions, type b as AudioTransformResult, type f as AudioTransformationStep, type A as AudioTransformerConfig, B as BaseTransformer, type C as CropOptions, type h as ImageFormat, type I as ImageTransformerConfig, type U as MediaTransformQuery, type a as MediaTransformResult, type W as MediaTransformationStep, type M as MediaTransformerConfig, type R as ResizeOptions, type g as RotateOptions, type i as TransformOptions, type T as TransformResult, type z as TransformationStep, type K as VideoCropOptions, type H as VideoResizeOptions, type N as VideoRotateOptions, type O as VideoTransformOptions, type F as VideoTransformResult, type Q as VideoTransformationStep, type V as VideoTransformerConfig } from "../packem_shared/types.d-BEUv414z.js";
2
+ export { M as MediaTransformer } from "../packem_shared/media-transformer.d-C8tn4J2Z.js";
3
+ import { g as FileReturn } from "../packem_shared/storage.d-DwdJrArF.js";
4
4
  import 'node:stream';
5
+ import 'node:timers';
5
6
  import 'node:crypto';
6
7
  import 'node:http';
7
8
  import 'lru-cache';
8
9
  /**
9
- * Check if a content type is valid for a specific media type.
10
- * @param contentType MIME content type string to validate
11
- * @param expectedType Expected media type ('image', 'video', or 'audio')
12
- * @returns True if the content type is valid for the expected media type
13
- */
10
+ * Check if a content type is valid for a specific media type.
11
+ * @param contentType MIME content type string to validate
12
+ * @param expectedType Expected media type ('image', 'video', or 'audio')
13
+ * @returns True if the content type is valid for the expected media type
14
+ */
14
15
  declare const isValidMediaType: (contentType: string | undefined, expectedType: "image" | "video" | "audio") => boolean;
15
16
  /**
16
- * Get format (extension) from content type using mime package.
17
- * @param contentType MIME content type string to extract format from
18
- * @returns Format string or undefined if not found
19
- */
17
+ * Get format (extension) from content type using mime package.
18
+ * @param contentType MIME content type string to extract format from
19
+ * @returns Format string or undefined if not found
20
+ */
20
21
  declare const getFormatFromContentType: (contentType: string | undefined) => string | undefined;
21
22
  /**
22
- * Validate a media file for a specific type with size and format checks.
23
- * @param file File to validate
24
- * @param expectedType Expected media type ('image', 'video', or 'audio')
25
- * @param config Validation configuration with optional maxSize and supportedFormats
26
- * @param config.maxSize Maximum allowed file size in bytes
27
- * @param config.supportedFormats Array of supported file formats
28
- * @throws Error if validation fails (size exceeded, wrong type, or unsupported format)
29
- */
23
+ * Validate a media file for a specific type with size and format checks.
24
+ * @param file File to validate
25
+ * @param expectedType Expected media type ('image', 'video', or 'audio')
26
+ * @param config Validation configuration with optional maxSize and supportedFormats
27
+ * @param config.maxSize Maximum allowed file size in bytes
28
+ * @param config.supportedFormats Array of supported file formats
29
+ * @throws Error if validation fails (size exceeded, wrong type, or unsupported format)
30
+ */
30
31
  declare const validateMediaFile: (file: FileReturn, expectedType: "image" | "video" | "audio", config?: {
31
32
  maxSize?: number;
32
33
  supportedFormats?: string[];
33
34
  }) => void;
34
35
  /**
35
- * Validate that a content type is known and supported by the mime package.
36
- * @param contentType MIME content type string to check
37
- * @returns True if the content type is known and has a registered extension
38
- */
36
+ * Validate that a content type is known and supported by the mime package.
37
+ * @param contentType MIME content type string to check
38
+ * @returns True if the content type is known and has a registered extension
39
+ */
39
40
  declare const isKnownContentType: (contentType: string | undefined) => boolean;
40
41
  /**
41
- * Custom error class for validation failures
42
- */
42
+ * Custom error class for validation failures
43
+ */
43
44
  declare class ValidationError extends Error {
44
45
  readonly code: string;
45
46
  readonly details: {
@@ -49,14 +50,14 @@ declare class ValidationError extends Error {
49
50
  validParams: string[];
50
51
  };
51
52
  /**
52
- * Creates a new ValidationError instance with detailed error information.
53
- * @param message Human-readable error message describing the validation failure
54
- * @param code Machine-readable error code for programmatic error handling
55
- * @param mediaType The media type where validation failed ('image', 'video', or 'audio')
56
- * @param invalidParameters Array of parameter names that were invalid
57
- * @param validParameters Array of valid parameter names or values
58
- * @param suggestions Optional array of suggested corrections or valid values
59
- */
53
+ * Creates a new ValidationError instance with detailed error information.
54
+ * @param message Human-readable error message describing the validation failure
55
+ * @param code Machine-readable error code for programmatic error handling
56
+ * @param mediaType The media type where validation failed ('image', 'video', or 'audio')
57
+ * @param invalidParameters Array of parameter names that were invalid
58
+ * @param validParameters Array of valid parameter names or values
59
+ * @param suggestions Optional array of suggested corrections or valid values
60
+ */
60
61
  constructor(message: string, code: string, mediaType: string, invalidParameters: string[], validParameters: string[], suggestions?: string[]);
61
62
  }
62
63
  export { ValidationError, getFormatFromContentType, isKnownContentType, isValidMediaType, validateMediaFile };
@@ -1,147 +1,148 @@
1
- import { F as File, g as FileReturn, B as BaseStorage } from "../packem_shared/storage.d-CEM1upWM.js";
2
- import { V as VideoTransformerConfig, F as VideoTransformResult, H as VideoResizeOptions, K as VideoCropOptions, N as VideoRotateOptions, O as VideoTransformOptions, Q as VideoTransformationStep, B as BaseTransformer } from "../packem_shared/types.d-CrUWY4On.js";
1
+ import { F as File, g as FileReturn, B as BaseStorage } from "../packem_shared/storage.d-DwdJrArF.js";
2
+ import { V as VideoTransformerConfig, F as VideoTransformResult, H as VideoResizeOptions, K as VideoCropOptions, N as VideoRotateOptions, O as VideoTransformOptions, Q as VideoTransformationStep, B as BaseTransformer } from "../packem_shared/types.d-BEUv414z.js";
3
3
  import 'node:stream';
4
+ import 'node:timers';
4
5
  import 'node:crypto';
5
6
  import 'node:http';
6
7
  import 'lru-cache';
7
8
  /**
8
- * Video transformer that uses storage backends and Mediabunny library to retrieve and transform videos.
9
- * @template TFile The file type used by this transformer.
10
- * @template TFileReturn The return type for file retrieval operations.
11
- *
12
- * Supports video transformations with query parameters for on-demand video processing.
13
- * @example
14
- * ```ts
15
- * const transformer = new VideoTransformer(storage, {
16
- * maxVideoSize: 100 * 1024 * 1024, // 100MB
17
- * cache: new Map()
18
- * });
19
- *
20
- * // Programmatic usage - resize a video
21
- * const result = await transformer.resize('video-id', {
22
- * width: 1920,
23
- * height: 1080,
24
- * fit: 'contain'
25
- * });
26
- *
27
- * // URL-based transformations
28
- * // GET /files/video-id?width=1280&height=720&fit=cover&bitrate=2000000
29
- * // GET /files/video-id?codec=vp9&bitrate=1000000
30
- * ```
31
- *
32
- * ## Supported Query Parameters
33
- *
34
- * - `width`: Width in pixels (Number)
35
- * - `height`: Height in pixels (Number)
36
- * - `fit`: Resize fit mode - cover/contain/fill/inside/outside
37
- * - `codec`: Video codec - avc/hevc/vp8/vp9/av1
38
- * - `bitrate`: Video bitrate in bits per second (Number)
39
- * - `frameRate`: Frame rate in Hz (Number)
40
- * - `format`: Output format - mp4/webm/mkv/ogg
41
- */
9
+ * Video transformer that uses storage backends and Mediabunny library to retrieve and transform videos.
10
+ * @template TFile The file type used by this transformer.
11
+ * @template TFileReturn The return type for file retrieval operations.
12
+ *
13
+ * Supports video transformations with query parameters for on-demand video processing.
14
+ * @example
15
+ * ```ts
16
+ * const transformer = new VideoTransformer(storage, {
17
+ * maxVideoSize: 100 * 1024 * 1024, // 100MB
18
+ * cache: new Map()
19
+ * });
20
+ *
21
+ * // Programmatic usage - resize a video
22
+ * const result = await transformer.resize('video-id', {
23
+ * width: 1920,
24
+ * height: 1080,
25
+ * fit: 'contain'
26
+ * });
27
+ *
28
+ * // URL-based transformations
29
+ * // GET /files/video-id?width=1280&height=720&fit=cover&bitrate=2000000
30
+ * // GET /files/video-id?codec=vp9&bitrate=1000000
31
+ * ```
32
+ *
33
+ * ## Supported Query Parameters
34
+ *
35
+ * - `width`: Width in pixels (Number)
36
+ * - `height`: Height in pixels (Number)
37
+ * - `fit`: Resize fit mode - cover/contain/fill/inside/outside
38
+ * - `codec`: Video codec - avc/hevc/vp8/vp9/av1
39
+ * - `bitrate`: Video bitrate in bits per second (Number)
40
+ * - `frameRate`: Frame rate in Hz (Number)
41
+ * - `format`: Output format - mp4/webm/mkv/ogg
42
+ */
42
43
  declare class VideoTransformer<TFile extends File = File, TFileReturn extends FileReturn = FileReturn> extends BaseTransformer<VideoTransformerConfig, VideoTransformResult<TFileReturn>, TFile, TFileReturn> {
43
44
  /**
44
- * Creates a new VideoTransformer instance.
45
- * @param storage The storage backend for retrieving and storing video files.
46
- * @param config Configuration options for video transformation including cache settings, codec defaults, and size limits.
47
- */
45
+ * Creates a new VideoTransformer instance.
46
+ * @param storage The storage backend for retrieving and storing video files.
47
+ * @param config Configuration options for video transformation including cache settings, codec defaults, and size limits.
48
+ */
48
49
  constructor(storage: BaseStorage<TFile, TFileReturn>, config?: VideoTransformerConfig);
49
50
  /**
50
- * Resizes a video to specified dimensions with optional fit mode.
51
- * @param fileId Unique identifier of the video file to resize.
52
- * @param options Resize options including width, height, and fit mode.
53
- * @returns Promise resolving to transformed video result.
54
- */
51
+ * Resizes a video to specified dimensions with optional fit mode.
52
+ * @param fileId Unique identifier of the video file to resize.
53
+ * @param options Resize options including width, height, and fit mode.
54
+ * @returns Promise resolving to transformed video result.
55
+ */
55
56
  resize(fileId: string, options: VideoResizeOptions): Promise<VideoTransformResult<TFileReturn>>;
56
57
  /**
57
- * Crops a video to the specified region.
58
- * @param fileId Unique identifier of the video file to crop.
59
- * @param options Crop options including region coordinates.
60
- * @returns Promise resolving to transformed video result.
61
- */
58
+ * Crops a video to the specified region.
59
+ * @param fileId Unique identifier of the video file to crop.
60
+ * @param options Crop options including region coordinates.
61
+ * @returns Promise resolving to transformed video result.
62
+ */
62
63
  crop(fileId: string, options: VideoCropOptions): Promise<VideoTransformResult<TFileReturn>>;
63
64
  /**
64
- * Rotates a video by the specified angle.
65
- * @param fileId Unique identifier of the video file to rotate.
66
- * @param options Rotation configuration with angle in degrees and optional background color.
67
- * @returns Promise resolving to transformed video result.
68
- */
65
+ * Rotates a video by the specified angle.
66
+ * @param fileId Unique identifier of the video file to rotate.
67
+ * @param options Rotation configuration with angle in degrees and optional background color.
68
+ * @returns Promise resolving to transformed video result.
69
+ */
69
70
  rotate(fileId: string, options: VideoRotateOptions): Promise<VideoTransformResult<TFileReturn>>;
70
71
  /**
71
- * Converts video format or codec.
72
- * @param fileId Unique identifier of the video file to convert.
73
- * @param format Target video format (e.g., "mp4", "webm", "mkv").
74
- * @param options Video transformation options including quality, bitrate, and codec settings.
75
- * @returns Promise resolving to transformed video result with updated format metadata.
76
- */
72
+ * Converts video format or codec.
73
+ * @param fileId Unique identifier of the video file to convert.
74
+ * @param format Target video format (e.g., "mp4", "webm", "mkv").
75
+ * @param options Video transformation options including quality, bitrate, and codec settings.
76
+ * @returns Promise resolving to transformed video result with updated format metadata.
77
+ */
77
78
  convertFormat(fileId: string, format: string, options?: VideoTransformOptions): Promise<VideoTransformResult<TFileReturn>>;
78
79
  /**
79
- * Transcodes video to different codec.
80
- * @param fileId Unique identifier of the video file to transcode.
81
- * @param codec Target video codec (e.g., "avc", "hevc", "vp9").
82
- * @param options Additional transform options.
83
- * @returns Promise resolving to transformed video result.
84
- */
80
+ * Transcodes video to different codec.
81
+ * @param fileId Unique identifier of the video file to transcode.
82
+ * @param codec Target video codec (e.g., "avc", "hevc", "vp9").
83
+ * @param options Additional transform options.
84
+ * @returns Promise resolving to transformed video result.
85
+ */
85
86
  transcode(fileId: string, codec: VideoTransformOptions["codec"], options?: Omit<VideoTransformOptions, "codec">): Promise<VideoTransformResult<TFileReturn>>;
86
87
  /**
87
- * Applies a custom transformation pipeline to a video.
88
- * @param fileId Unique identifier of the video file to transform.
89
- * @param steps Array of transformation steps to apply in sequence.
90
- * @returns Promise resolving to transformed video result.
91
- */
88
+ * Applies a custom transformation pipeline to a video.
89
+ * @param fileId Unique identifier of the video file to transform.
90
+ * @param steps Array of transformation steps to apply in sequence.
91
+ * @returns Promise resolving to transformed video result.
92
+ */
92
93
  transform(fileId: string, steps: VideoTransformationStep[]): Promise<VideoTransformResult<TFileReturn>>;
93
94
  /**
94
- * Applies multiple transformations in sequence using Mediabunny.
95
- * @param buffer The original video buffer.
96
- * @param steps Array of video transformation steps to apply.
97
- * @returns Promise resolving to transformed video buffer.
98
- * @private
99
- */
95
+ * Applies multiple transformations in sequence using Mediabunny.
96
+ * @param buffer The original video buffer.
97
+ * @param steps Array of video transformation steps to apply.
98
+ * @returns Promise resolving to transformed video buffer.
99
+ * @private
100
+ */
100
101
  private applyTransformations;
101
102
  /**
102
- * Converts transformation steps to Mediabunny video options.
103
- * @param steps Array of video transformation steps to convert.
104
- * @returns Mediabunny video options object for conversion.
105
- * @private
106
- */
103
+ * Converts transformation steps to Mediabunny video options.
104
+ * @param steps Array of video transformation steps to convert.
105
+ * @returns Mediabunny video options object for conversion.
106
+ * @private
107
+ */
107
108
  private stepsToVideoOptions;
108
109
  /**
109
- * Determines output format based on transformation steps.
110
- * @param steps Array of video transformation steps.
111
- * @returns Mediabunny output format instance (defaults to MP4).
112
- * @private
113
- */
110
+ * Determines output format based on transformation steps.
111
+ * @param steps Array of video transformation steps.
112
+ * @returns Mediabunny output format instance (defaults to MP4).
113
+ * @private
114
+ */
114
115
  private determineOutputFormat;
115
116
  /**
116
- * Converts format string to Mediabunny output format.
117
- * @param format Video format string (mp4, webm, mkv, ogg).
118
- * @returns Mediabunny output format instance.
119
- * @private
120
- */
117
+ * Converts format string to Mediabunny output format.
118
+ * @param format Video format string (mp4, webm, mkv, ogg).
119
+ * @returns Mediabunny output format instance.
120
+ * @private
121
+ */
121
122
  private formatStringToOutputFormat;
122
123
  /**
123
- * Validates that the file is a supported video.
124
- * @param file The file to validate.
125
- * @returns Promise that resolves if validation passes.
126
- * @throws Error if file size exceeds limits, wrong content type, unsupported format, or invalid video.
127
- * @private
128
- */
124
+ * Validates that the file is a supported video.
125
+ * @param file The file to validate.
126
+ * @returns Promise that resolves if validation passes.
127
+ * @throws Error if file size exceeds limits, wrong content type, unsupported format, or invalid video.
128
+ * @private
129
+ */
129
130
  private validateVideo;
130
131
  /**
131
- * Creates transformation result with metadata.
132
- * @param buffer The transformed video buffer.
133
- * @param originalFile The original file information.
134
- * @returns Video transformation result with metadata.
135
- * @private
136
- */
132
+ * Creates transformation result with metadata.
133
+ * @param buffer The transformed video buffer.
134
+ * @param originalFile The original file information.
135
+ * @returns Video transformation result with metadata.
136
+ * @private
137
+ */
137
138
  private createTransformResult;
138
139
  /**
139
- * Generates cache key for transformation.
140
- * @param fileId The file identifier.
141
- * @param steps Array of transformation steps.
142
- * @returns Unique cache key string.
143
- * @private
144
- */
140
+ * Generates cache key for transformation.
141
+ * @param fileId The file identifier.
142
+ * @param steps Array of transformation steps.
143
+ * @returns Unique cache key string.
144
+ * @private
145
+ */
145
146
  private generateCacheKey;
146
147
  }
147
148
  export { VideoTransformer as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visulima/storage",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "Server-side file-storage abstraction - store files in a web-accessible location via a simplified API. Includes S3, Azure, GCS, local filesystem and 20+ other backends with TUS/multipart/REST upload handlers and the most convenient features of each.",
5
5
  "keywords": [
6
6
  "anolilab",
@@ -271,7 +271,7 @@
271
271
  "dependencies": {
272
272
  "@remix-run/multipart-parser": "0.16.3",
273
273
  "@sindresorhus/fnv1a": "3.1.0",
274
- "@visulima/pagination": "5.0.0",
274
+ "@visulima/pagination": "6.0.0",
275
275
  "file-type": "22.0.1",
276
276
  "lru-cache": "11.5.1",
277
277
  "mime": "^4.1.0",
@@ -1 +0,0 @@
1
- import{Readable as u}from"node:stream";import{S as m}from"./s3-base-storage-BoTyhuzO.js";import{b as h,p as l}from"./aws-light-meta-storage-DGrn72VJ.js";import f from"./AwsLightFile-CpZrubaV.js";class b extends m{static name="aws-light";s3Api;constructor(e){const{bucket:t=process.env.S3_BUCKET||process.env.AWS_S3_BUCKET,region:r}=e;if(!t)throw new Error("S3 bucket is not defined");if(!r)throw new Error("S3 region is not defined");if(!e.accessKeyId)throw new Error("accessKeyId is required");if(!e.secretAccessKey)throw new Error("secretAccessKey is required");super({bucket:t,clientDirectUpload:e.clientDirectUpload,expiration:e.expiration?.maxAge?{maxAge:String(e.expiration.maxAge)}:void 0,filename:e.filename,logger:e.logger,metaStorage:e.metaStorage,metaStorageConfig:e.metaStorageConfig?{...e.metaStorageConfig,...e}:{...e},partSize:e.partSize,retryConfig:{...e.retryConfig,shouldRetry:n=>{const s=n;return s.statusCode&&[408,429,500,502,503,504].includes(s.statusCode)?!0:s.retryable??!1}}}),this.s3Api=new h({accessKeyId:e.accessKeyId,bucket:t,endpoint:e.endpoint,region:r,secretAccessKey:e.secretAccessKey,service:e.service,sessionToken:e.sessionToken});const{metaStorage:i,metaStorageConfig:a}=e;if(!i){const n={...e,...a,logger:this.logger};this.meta=new l(n)}}normalizeError(e){const t=e;return t.statusCode||t.code?{code:t.code||t.name,message:t.message,name:t.name,statusCode:t.statusCode||500}:super.normalizeError(e)}async update({id:e},t){if(this.config.clientDirectUpload){const r=await this.getMeta(e);return this.buildPresigned({...r,...t})}return super.update({id:e},t)}async getStream({id:e},t){return this.instrumentOperation("getStream",async()=>{const r=this.getS3Api(),{Body:i,ContentLength:a,ContentType:n,ETag:s,Expires:c,LastModified:g}=await this.runOperation(t,o=>r.getObject({Bucket:this.bucket,Key:e},{signal:o}));await this.checkIfExpired({expiredAt:c});const d=i instanceof ReadableStream?u.fromWeb(i):i,p=new u({read(){d.on("data",o=>{this.push(o)}),d.on("end",()=>{this.push(null)}),d.on("error",o=>{this.destroy(o)})}});return{headers:{"Content-Length":a?.toString()??"0","Content-Type":n,...s&&{ETag:s},...c&&{"X-Upload-Expires":c.toString()},...g&&{"Last-Modified":g.toString()}},size:Number(a),stream:p}})}get raw(){return this.s3Api.aws}getS3Api(){return this.s3Api}getFileClass(){return f}getAcl(){}async accessCheck(e=30){await this.s3Api.checkBucketAccess({Bucket:this.bucket})}}export{b as default};
@@ -1 +0,0 @@
1
- import{W as f}from"./path-0oTTdkvl-DvWvbDbh.js";import{d as b}from"./detect-file-type-BA7UBLKA.js";import{throwErrorCode as u,ERRORS as h}from"./ERRORS-BIBxE2oR.js";import{B as C,c as w}from"./storage-0j5nCAUp.js";import{y as T}from"./local-meta-storage-iuJnu90B.js";import{a as O,c as S,b as m,d as y}from"./azure-meta-storage-ClbEsfI4.js";import k from"./AzureFile-DFSaVe25.js";import{i as E}from"./part-match-D-9dGX42.js";import{e as B}from"./has-content-50BsqrWw.js";import{t as F}from"./get-file-status-y3wTtDQs.js";class z extends C{static name="azure";checksumTypes=["md5"];get raw(){return this.client}meta;client;containerClient;root;resolvedRetryConfig;signer;sasToken;anonymous;constructor(t){if(super(t),!t.containerName)throw new Error("Missing required parameter: Azure container name.");const{anonymous:r,client:e,sasToken:n,signer:s}=O(t);this.client=e,this.signer=s,this.sasToken=n,this.anonymous=r,this.containerClient=this.client.getContainerClient(t.containerName),this.root=t.root?f(t.root).replace(/^\//,""):"";const o={backoffMultiplier:2,initialDelay:1e3,maxDelay:3e4,maxRetries:3,retryableStatusCodes:[408,429,500,502,503,504],shouldRetry:i=>{const a=i;if(a.statusCode&&[408,429,500,502,503,504].includes(a.statusCode))return!0;if(i instanceof Error){const l=a.code;if(l==="ECONNRESET"||l==="ETIMEDOUT"||l==="ENOTFOUND"||l==="ECONNREFUSED")return!0}return!1},...t.retryConfig};if(this.resolvedRetryConfig=o,t.metaStorage)this.meta=t.metaStorage;else{let i={...t,...t.metaStorageConfig,logger:this.logger};if("directory"in i)this.logger?.debug("Using local meta storage"),this.meta=new T(i);else{const a=t.metaStorageConfig;a&&["accountKey","accountName","connectionString","credential","endpoint","sasToken"].some(l=>l in a)||(i={...i,client:this.client}),this.meta=new S(i)}}this.isReady=!1,this.accessCheck().then(()=>{this.isReady=!0}).catch(i=>{this.logger?.error("Storage access check failed: %O",i)})}getRetryConfig(){return this.resolvedRetryConfig}async create(t,r){return this.instrumentOperation("create",async()=>{const e={...t};if(t.ttl){const a=typeof t.ttl=="string"?w(t.ttl):t.ttl;a!==void 0&&(e.expiredAt=Date.now()+a)}const n=new k(e);n.name=this.namingFunction(n),await this.validate(n);try{const a=await this.getMeta(n.id);if(a.bytesWritten>=0)return a}catch{}const s=this.containerClient.getBlockBlobClient(this.getFullPath(n.name)),o={};for(const[a,l]of Object.entries(n.metadata||{}))o[a]=JSON.stringify(l);const i=await this.runOperation(r,a=>s.uploadData(Buffer.from(""),{abortSignal:a,blobHTTPHeaders:{blobContentType:n.contentType},metadata:{name:n.name,originalName:n.originalName,...o}}));return i.requestId===void 0?u(h.FILE_ERROR,"azure create upload error"):(n.requestId=i.requestId,n.uri=i._response.headers.get("location"),n.bytesWritten=0,await this.saveMeta(n),n.status="created",await this.onCreate(n),n)})}async delete({id:t},r){return this.instrumentOperation("delete",async()=>{const e=await this.getMeta(t);e.status="deleted",await this.runOperation(r,s=>this.containerClient.getBlockBlobClient(this.getFullPath(e.name)).deleteIfExists({abortSignal:s})),await this.deleteMeta(e.id);const n={...e};return await this.onDelete(n),n})}async deleteBatch(t,r){if(t.length===0)return{failed:[],failedCount:0,successful:[],successfulCount:0};const e=256;try{const n=this.client.getBlobBatchClient(),s=[],o=[];for(let i=0;i<t.length;i+=e){const a=t.slice(i,i+e),l=a.map(c=>this.containerClient.getBlockBlobClient(this.getFullPath(c))),d=await this.runOperation(r,c=>n.deleteBlobs(l,{abortSignal:c}));for(const[c,p]of d.subResponses.entries()){const g=a[c];p.status===202||p.status===404?s.push({id:g,name:g,status:"deleted"}):o.push({error:p.errorCode??`HTTP ${p.status}`,id:g})}}return await Promise.all(s.map(async i=>{try{await this.deleteMeta(i.id),await this.onDelete(i)}catch{}})),{failed:o,failedCount:o.length,successful:s,successfulCount:s.length}}catch(n){return this.logger?.warn(`Azure Blob Batch delete unavailable, falling back to per-key delete: ${n instanceof Error?n.message:String(n)}`),super.deleteBatch(t,r)}}async move(t,r,e){return this.instrumentOperation("move",async()=>{const n=await this.copy(t,r,e),s=this.getFullPath(t);return await this.runOperation(e,o=>this.containerClient.getBlockBlobClient(s).deleteIfExists({abortSignal:o})),n})}async write(t,r){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(!E(t,e))return u(h.FILE_CONFLICT);const n=await this.lock(t.id);try{if(B(t)){if((e.bytesWritten===0||Number.isNaN(e.bytesWritten))&&(!e.contentType||e.contentType==="application/octet-stream"))try{const{fileType:a,stream:l}=await b(t.body);a?.mime&&(e.contentType=a.mime),t.body=l}catch{}const s=this.containerClient.getBlockBlobClient(this.getFullPath(e.name)),o=new AbortController;t.body.on("error",()=>{o.abort()});const i=await this.runOperation(r,a=>{const l=a?AbortSignal.any([o.signal,a]):o.signal;return s.uploadStream(t.body,void 0,void 0,{abortSignal:l,blobHTTPHeaders:{blobContentType:e.contentType??"application/octet-stream"},metadata:e.metadata})},{replayable:!1});if(i.requestId===void 0)return u(h.FILE_ERROR,"azure write upload error");e.requestId=i.requestId,e.bytesWritten+=t.contentLength||0,e.status=F(e),e.status==="completed"&&(e.uri=i._response.headers.get("location"),await this.deleteMeta(e.id))}}finally{await this.unlock(t.id,n)}return e})}async get({id:t},r){return this.instrumentOperation("get",async()=>{const e=this.containerClient.getBlockBlobClient(this.getFullPath(t));if(!await this.runOperation(r,c=>e.exists({abortSignal:c})))try{return await this.getMeta(t),u(h.GONE)}catch{return u(h.FILE_NOT_FOUND)}const n=await this.runOperation(r,c=>e.getProperties({abortSignal:c})),{contentLength:s,contentType:o,etag:i,expiresOn:a,lastModified:l,metadata:d}=n;return{content:await this.runOperation(r,c=>e.downloadToBuffer(0,void 0,{abortSignal:c})),contentType:o,ETag:i,expiredAt:a,id:t,metadata:d||{},modifiedAt:l,name:d?.name||t,originalName:d?.originalName||"",size:s}})}async exists({id:t},r){return this.instrumentOperation("exists",async()=>{try{await this.getMeta(t);const e=this.containerClient.getBlockBlobClient(this.getFullPath(t));return await this.runOperation(r,n=>e.exists({abortSignal:n}))}catch{return!1}})}async copy(t,r,e){return this.instrumentOperation("copy",async()=>{const n=this.containerClient.getBlockBlobClient(this.getFullPath(t));if(!await this.runOperation(e,a=>n.exists({abortSignal:a})))try{return await this.getMeta(t),u(h.GONE)}catch{return u(h.FILE_NOT_FOUND)}const s=this.containerClient.getBlockBlobClient(this.getFullPath(r));let o=n.url;this.signer?.kind==="userDelegation"?o=await m(this.containerClient.getBlobClient(this.getFullPath(t)),this.signer,{expiresIn:300,permissions:"r"}):this.sasToken&&(o=y(n.url,this.sasToken));const i=await this.runOperation(e,a=>s.beginCopyFromURL(o,{abortSignal:a}));return await this.runOperation(e,()=>i.pollUntilDone()),{...await this.getMeta(t),id:r,name:r}})}async list(t=1e3,r){return this.instrumentOperation("list",async()=>{const e=[];let n=!0,s;for(;n&&e.length<t;)try{const o=Math.min(t-e.length,1e3),i=(await this.runOperation(r,a=>this.containerClient.listBlobsFlat({abortSignal:a,includeMetadata:!0,prefix:this.root}).byPage({continuationToken:s,maxPageSize:o}).next())).value;if(i!==void 0&&"segment"in i){for(const a of i.segment.blobItems)if(!a.deleted&&(e.push({createdAt:a.properties.createdOn,id:a.name,modifiedAt:a.properties.lastModified}),e.length>=t))break}n=i?.continuationToken!==void 0,n&&(s=i.continuationToken)}catch(o){const i=this.normalizeError(o instanceof Error?o:new Error(String(o)));throw await this.onError(i),o}return e},{limit:t})}async getReadUrl(t,r){const e=this.containerClient.getBlobClient(this.getFullPath(t));return this.signer?m(e,this.signer,{expiresIn:r?.expiresIn??3600,permissions:"r",...r?.responseContentDisposition&&{contentDisposition:r.responseContentDisposition},...r?.responseContentType&&{contentType:r.responseContentType}}):r?.responseContentDisposition!==void 0||r?.responseContentType!==void 0?u(h.BAD_REQUEST,"azure: `responseContentDisposition`/`responseContentType` require a freshly minted SAS (construct with a shared key or Microsoft Entra credential). A pre-issued `sasToken` or anonymous public-container URL has no signature in which to bind the override, so it cannot be enforced."):this.sasToken?y(e.url,this.sasToken):this.anonymous?e.url:u(h.METHOD_NOT_ALLOWED,"azure: cannot produce a read URL without a shared key, Microsoft Entra credential, or SAS token. Construct the adapter with accountKey + accountName, a connectionString containing an account key, a credential + accountName, or a sasToken.")}async getUploadUrl(t,r){if(r?.contentType!==void 0||r?.contentLength!==void 0)return u(h.BAD_REQUEST,"azure: `contentType`/`contentLength` are not supported for upload URLs. An Azure SAS does not bind the request Content-Type into the signature and cannot enforce a size limit; validate both at your application gateway/proxy before issuing the SAS, or omit them and accept the unbounded PUT.");const e=this.containerClient.getBlobClient(this.getFullPath(t));return this.signer?m(e,this.signer,{expiresIn:r?.expiresIn??3600,permissions:"cw"}):this.sasToken?y(e.url,this.sasToken):u(h.METHOD_NOT_ALLOWED,"azure: cannot produce an upload URL without a shared key, Microsoft Entra credential, or SAS token. Anonymous (public-container) access is read-only.")}getFullPath(t){return this.assetFolder!==void 0?`${this.assetFolder}/${t}`:t}async accessCheck(){await this.runOperation(void 0,t=>this.containerClient.getProperties({abortSignal:t}))}}export{z as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(e){super(e)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(e){super(e)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(e){super(e)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as s}from"./local-meta-storage-iuJnu90B.js";class o extends s{constructor(r){super(r)}}export{o as default};
@@ -1 +0,0 @@
1
- import"node:fs";import"node:fs/promises";import"node:stream";import"./local-meta-storage-iuJnu90B.js";import"./path-0oTTdkvl-DvWvbDbh.js";import"./index-nZWCQrSe.js";import"./detect-file-type-BA7UBLKA.js";import"./ERRORS-BIBxE2oR.js";import{F as c}from"./disk-storage-CsQcYW3s.js";import"./storage-0j5nCAUp.js";import"./File-W8aOo15X.js";import"./get-file-status-y3wTtDQs.js";import"./update-size-DuNuLyxj.js";import"./part-match-D-9dGX42.js";import"./has-content-50BsqrWw.js";export{c as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(e){super(e)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as s}from"./local-meta-storage-iuJnu90B.js";class o extends s{constructor(r){super(r)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(e){super(e)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(t){super(t)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as s}from"./local-meta-storage-iuJnu90B.js";class o extends s{constructor(r){super(r)}}export{o as default};
@@ -1 +0,0 @@
1
- import{getStore as u}from"@netlify/blobs";import{a as p}from"./detect-file-type-BA7UBLKA.js";import{B as y,c as h,e as d}from"./storage-0j5nCAUp.js";import{y as w}from"./local-meta-storage-iuJnu90B.js";import f from"./NetlifyBlobFile-DoFhkzaH.js";import{t as m}from"./get-file-status-y3wTtDQs.js";import{t as g}from"./update-size-DuNuLyxj.js";import{i as b}from"./part-match-D-9dGX42.js";import{e as O}from"./has-content-50BsqrWw.js";class C extends y{static name="netlify-blob";checksumTypes=["md5"];get raw(){return this.store}meta;storeName;siteID;token;store;resolvedRetryConfig;constructor(e){super(e),this.storeName=e.storeName||"default",this.siteID=e.siteID||process.env.NETLIFY_SITE_ID,this.token=e.token||process.env.NETLIFY_TOKEN,this.store=u({name:this.storeName,...this.siteID&&{siteID:this.siteID},...this.token&&{token:this.token}});const n={backoffMultiplier:2,initialDelay:1e3,maxDelay:3e4,maxRetries:3,retryableStatusCodes:[408,429,500,502,503,504],shouldRetry:r=>{if(r instanceof Error){const i=r.code;if(i==="ECONNRESET"||i==="ETIMEDOUT"||i==="ENOTFOUND"||i==="ECONNREFUSED")return!0}const s=r;return!!(s.status&&[408,429,500,502,503,504].includes(s.status))},...e.retryConfig};this.resolvedRetryConfig=n;const{metaStorage:t,metaStorageConfig:a}=e;this.meta=t||new w(a),this.isReady=!0}getRetryConfig(){return this.resolvedRetryConfig}async create(e,n){return this.instrumentOperation("create",async()=>{const t={...e};if(e.ttl){const r=typeof e.ttl=="string"?h(e.ttl):e.ttl;t.expiredAt=r===void 0?void 0:Date.now()+r}const a=new f(t);a.name=this.namingFunction(a),await this.validate(a);try{const r=await this.getMeta(a.id);if(r.bytesWritten>=0)return r}catch{}return a.bytesWritten=0,a.status=m(a),await this.saveMeta(a),await this.onCreate(a),a})}async write(e,n){return this.instrumentOperation("write",async()=>{let t;if("contentType"in e&&"metadata"in e&&!("body"in e)&&!("start"in e)?t=e:(t=await this.getMeta(e.id),await this.checkIfExpired(t)),t.status==="completed")return t;if(e.size!==void 0&&g(t,e.size),!b(e,t))throw new Error("File part does not match");const a=await this.lock(e.id);try{if(O(e)){if(this.isUnsupportedChecksum(e.checksumAlgorithm))throw new Error("Unsupported checksum algorithm");const r=[],s=e.body;for await(const o of s)r.push(Buffer.from(o));const i=Buffer.concat(r);if((t.bytesWritten===0||Number.isNaN(t.bytesWritten))&&(!t.contentType||t.contentType==="application/octet-stream"))try{const o=await p(i);o?.mime&&(t.contentType=o.mime)}catch{}await this.runOperation(n,()=>this.store.set(t.name,i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength),{metadata:{...t.metadata,contentType:t.contentType}})),t.pathname=t.name,t.url=this.getBlobUrl(t.name),t.bytesWritten=i.length}return t.status=m(t),t.status==="completed"&&await this.internalOnComplete(t),await this.saveMeta(t),t}finally{await this.unlock(e.id,a)}})}async delete({id:e},n){return this.instrumentOperation("delete",async()=>{const t=await this.getMeta(e);if(!t.pathname)throw new Error(`File ${e} does not have a valid pathname`);t.status="deleted";try{await this.runOperation(n,()=>this.store.delete(t.pathname))}catch(r){this.logger?.error("Failed to delete blob from Netlify Blob:",r);const s=this.normalizeError(r instanceof Error?r:new Error(String(r)));await this.onError(s)}await this.deleteMeta(t.id);const a={...t};return await this.onDelete(a),a})}async exists({id:e},n){return this.instrumentOperation("exists",async()=>{try{const t=await this.getMeta(e);return!t.pathname||t.pathname.length<=0?!1:await this.runOperation(n,()=>this.store.get(t.pathname,{type:"blob"}))!=null}catch{return!1}})}async get({id:e},n){return this.instrumentOperation("get",async()=>{const t=await this.checkIfExpired(await this.getMeta(e));if(!t.pathname||t.pathname.length<=0)throw new Error("File pathname not found");const a=await this.runOperation(n,()=>this.store.get(t.pathname,{type:"blob"}));if(!a)throw new Error("File not found in Netlify Blob");let r;if(typeof a=="string")r=Buffer.from(a,"utf8").buffer;else if(a&&typeof a=="object"&&"arrayBuffer"in a&&typeof a.arrayBuffer=="function")r=await this.runOperation(n,()=>a.arrayBuffer());else throw new Error("Invalid blob type returned from Netlify Blob");const s=Buffer.from(r);let i=null;try{i=await this.store.getMetadata?.(t.pathname)??null}catch{}return{content:s,contentType:i?.contentType||t.contentType,ETag:t.ETag,expiredAt:t.expiredAt,id:e,metadata:{...t.metadata,...i?.metadata},modifiedAt:t.modifiedAt,name:t.name,originalName:t.originalName,size:t.size||s.length}})}async copy(e,n,t){return this.instrumentOperation("copy",async()=>{const a=await this.getMeta(e);if(!a.pathname)throw new Error("Source file pathname not found");const r=await this.runOperation(t,()=>this.store.get(a.pathname,{type:"blob"}));if(!r)throw new Error("Source file not found in Netlify Blob");let s=null;try{const l=this.store;l.getMetadata&&a.pathname&&(s=await l.getMetadata(a.pathname))}catch{}let i;if(typeof r=="string")i=Buffer.from(r,"utf8").buffer;else if(r&&typeof r=="object"&&"arrayBuffer"in r){const l=r;i=await this.runOperation(t,()=>l.arrayBuffer())}else throw new Error("Invalid blob type returned from Netlify Blob");const o=Buffer.from(i);await this.runOperation(t,()=>this.store.set(n,o.buffer.slice(o.byteOffset,o.byteOffset+o.byteLength),{metadata:s||{contentType:a.contentType,...a.metadata}}));const c={...a,id:n,name:n,pathname:n,url:this.getBlobUrl(n)};return await this.saveMeta(c),c})}async move(e,n,t){return this.instrumentOperation("move",async()=>{const a=await this.copy(e,n,t);return await this.delete({id:e},t),a})}async update({id:e},n,t){return this.instrumentOperation("update",async()=>{const a=await this.getMeta(e),r={...n};if("ttl"in r&&r.ttl!==void 0){const i=r.ttl,o=typeof i=="string"?h(i):i;o!==void 0&&(r.expiredAt=Date.now()+o),delete r.ttl}d(a,r),await this.saveMeta(a);const s={...a,status:"updated"};return await this.onUpdate(s),s})}async list(e=1e3,n){return this.instrumentOperation("list",async()=>{const t=await this.runOperation(n,()=>this.store.list()),a=[];for await(const r of t.blobs){let s=null;try{s=await this.store.getMetadata?.(r.key)??null}catch{}const i=new f({contentType:s?.contentType||"application/octet-stream",metadata:s?.metadata||{},originalName:r.key}),o=r;if(i.createdAt=o.createdAt?.toISOString(),i.id=r.key,i.modifiedAt=o.updatedAt?.toISOString(),i.name=r.key,i.pathname=r.key,i.size=o.size,i.url=this.getBlobUrl(r.key),a.push(i),a.length>=e)break}return a},{limit:e})}internalOnComplete=e=>this.deleteMeta(e.id);getBlobUrl(e){return`/api/blobs/${this.storeName}/${e}`}}export{C as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(t){super(t)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class e extends r{constructor(o){super(o)}}export{e as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(e){super(e)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(e){super(e)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(t){super(t)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as s}from"./local-meta-storage-iuJnu90B.js";class o extends s{constructor(r){super(r)}}export{o as default};
@@ -1 +0,0 @@
1
- import{y as r}from"./local-meta-storage-iuJnu90B.js";class o extends r{constructor(e){super(e)}}export{o as default};
@@ -1 +0,0 @@
1
- import{paginate as H}from"@visulima/pagination";import{H as b,h as N,n as f}from"./headers-BAiAKekR.js";import T from"mime";import{ERRORS as g,isUploadError as L}from"./ERRORS-BIBxE2oR.js";import{match as z}from"path-to-regexp";import{d as O,c as M,s as S,e as w,u as R}from"./base-handler-core-D-9Ku1h-.js";import{i as j}from"./storage-0j5nCAUp.js";import{waitForStorage as k}from"./waitForStorage-ByQmG4xF.js";import{PassThrough as $}from"node:stream";import{e as v}from"./response-builder-CbSA8qPa.js";const P=z(["/:uuid","/*path/:uuid.:ext/:metadata","/*path/:uuid/:metadata","/*path/:uuid.:ext","/*path/:uuid"],{decode:decodeURIComponent}),F=c=>{const e=P(c);if(!e)return;const{params:t}=e;if(!t.uuid)return;const s={uuid:t.uuid};return t.metadata!==void 0&&(s.metadata=t.metadata),t.path!==void 0&&(s.path=t.path),t.ext!==void 0&&(s.ext=t.ext),{params:s,path:e.path}},D=(c,e,t)=>{let s=0,r=0;const o=t-e+1;return new $({highWaterMark:Math.min(64*1024,o),transform(n,d,a){const h=n.length,i=s,p=i+h-1;if(s+=h,p<e){a();return}if(i>t){this.end(),a();return}const u=Math.max(0,e-i),y=Math.min(h,t-i+1);if(u<y){const C=n.subarray(u,y);r+=C.length,this.push(C)||c.pause()}r>=o&&(this.end(),c.destroy()),a()}})},_=(c,e,t)=>{let s=!1;const r=()=>{s||(s=!0,c.destroy())};e.on("drain",()=>{c.resume()}),e.on("close",r),e.on("finish",r),e.on("error",r),c.on("end",()=>{e.end()}),c.on("error",async o=>{s||(await t(e,o),r())}),c.on("data",o=>{e.write(o)||c.pause()}),typeof e.listeners=="function"&&e.listeners("close")?.length===0&&e.on("close",r)},I=(c,e,t)=>{const{headers:s,statusCode:r}=c;e(t,{headers:s,statusCode:r})},X=(c,e,t,s,r,o,n)=>{e.body=c?.data===void 0?c:c.data;const{headers:d,statusCode:a}=c,h=c;if(h.stream)if(typeof s=="function")s();else{const i=n(e.headers.range,h.size||0);o(t,h.stream,{headers:d,range:i||void 0,size:h.size,statusCode:a})}else{let i="";c.content!==void 0?i=c.content:typeof c=="object"&&"data"in c&&(i=c.data),typeof s=="function"?s():r(t,{body:i,headers:d,statusCode:a})}},q=async(c,e,t,s,r,o,n)=>{const{headers:d,statusCode:a,...h}=c;if(typeof s=="function")e._body=!0,e.body=h,s();else{const i=c,p=i.headers?{...i.headers}:{};i.headers===void 0&&(i.headers={}),i.statusCode===void 0&&(i.statusCode=200);try{const u=r.onComplete(h,i,e);u instanceof Promise&&await u}catch(u){throw o?.error&&o.error("[onComplete error]: %O",u),u}Object.keys(i.headers||{}).length===0&&Object.keys(p).length>0?i.headers=p:i.headers&&Object.keys(p).length>0&&(i.headers={...p,...i.headers}),n(e,t,i)}},G=(c,e,t,s)=>{const{headers:r,statusCode:o,...n}=c,d=r||{},a=d["X-Chunked-Upload"]==="true"||d["x-chunked-upload"]==="true";let h;const i={...v(d),...r?v(r):{},...n.hash===void 0?{}:{[`X-Range-${n.hash?.algorithm.toUpperCase()}`]:String(n.hash?.value)}};a&&(h=JSON.stringify(n),!i["Content-Type"]&&!i["content-type"]&&(i["Content-Type"]="application/json; charset=utf-8")),e.method==="HEAD"&&(h=""),s(t,{body:h,headers:i,statusCode:o||200})},W=async(c,e,t,s,r,o,n)=>{const d=c instanceof Error?c:new Error(String(c)),a={...O(d,["name",...Object.getOwnPropertyNames(d)]),request:O(e,["headers","method","url"])};s("error")>0&&t("error",a),r?.error&&r.error("[error]: %O",a),await o(n,d)},m="Content-Type";class x extends M{static methods=["delete","get","head","options","patch","post","put"];registeredHandlers=new Map;constructor(e){super(e),this.compose()}get handlers(){return this.registeredHandlers}handle=async(e,t)=>this.upload(e,t);upload=async(e,t,s)=>{e.on("error",o=>this.logger?.error("[request error]: %O",o)),this.logger?.debug("[request]: %s %s",e.method,e.url);const r=this.registeredHandlers.get(e.method);if(!r){await this.sendError(t,{UploadErrorCode:g.METHOD_NOT_ALLOWED});return}try{await k(this.storage)}catch{await this.sendError(t,{UploadErrorCode:g.STORAGE_ERROR});return}try{const o=await r.call(this,e,t);if(["HEAD","OPTIONS"].includes(e.method))I(o,this.send.bind(this),t);else if(e.method==="GET"){const n=o;n&&X(n,e,t,s,this.send.bind(this),this.sendStream.bind(this),this.parseRangeHeader.bind(this))}else{const{headers:n,statusCode:d,...a}=o;this.logger?.debug("[%s]: %s: %d/%d",a.status,a.name,a.bytesWritten,a.size),a.status!==void 0&&this.listenerCount(a.status)>0&&this.emit(a.status,{...a,request:O(e,["headers","method","url"])}),a.status==="completed"?await q(o,e,t,s,this.storage,this.logger,(h,i,p)=>{this.finish(h,i,p)}):G(o,e,t,(h,i)=>{this.send(h,{body:i.body,headers:i.headers,statusCode:i.statusCode})})}}catch(o){await W(o,e,this.emit.bind(this),this.listenerCount.bind(this),this.logger,this.sendError.bind(this),t)}};send(e,{body:t="",headers:s={},statusCode:r=200}){let o;const n={...s};if(typeof t=="string"){if(o=t,n[m]===void 0)n[m]=b.createContentType({mediaType:"text/plain"});else{const d=Array.isArray(n[m])?n[m].join(", "):String(n[m]);n[m]=b.ensureCharset(d)}n["Content-Length"]===void 0&&(n["Content-Length"]=Buffer.byteLength(t))}else t instanceof Buffer?o=t:(o=JSON.stringify(t),n[m]||(n[m]=b.createContentType({charset:"utf8",mediaType:"application/json"})));S(e,n),e.statusCode=r,e.end(o)}async sendError(e,t){let s;L(t)?s=this.internalErrorResponses[t.UploadErrorCode]:!j(t)&&!N.isHttpError(t)?s=this.storage.normalizeError(t):s={...t,code:t.code||t.name,headers:t.headers||{},message:t.message,name:t.name,statusCode:t.statusCode||500},await this.storage.onError(s);let r;s.body?typeof s.body=="object"&&s.body!==null?r={body:s.body,headers:s.headers,statusCode:s.statusCode}:r={body:{error:{code:s.code||s.name||"Error",message:s.body||s.message||"Unknown error",name:s.name||"Error"}},headers:s.headers,statusCode:s.statusCode||500}:r={body:{error:{code:s.code||s.name||"Error",message:s.message||"Unknown error",name:s.name||"Error"}},headers:s.headers,statusCode:s.statusCode||500},this.send(e,r)}sendStream(e,t,{headers:s={},range:r,size:o,statusCode:n=200}){S(e,s),e.statusCode=n;let d=t;r&&o?(e.statusCode=206,e.setHeader("Content-Range",`bytes ${r.start}-${r.end}/${o}`),e.setHeader("Content-Length",r.end-r.start+1),e.setHeader("Accept-Ranges","bytes"),d=D(t,r.start,r.end)):(o&&e.setHeader("Content-Length",o),e.setHeader("Accept-Ranges","bytes")),_(d,e,(a,h)=>this.sendError(a,h))}finish(e,t,s){const r="id"in s&&"headers"in s&&!("body"in s);let o,n,d;if(r){const a=s,h=a.headers||{},i=a.statusCode||200,{headers:p,statusCode:u,...y}=a;o=y,n={...h},d=i}else{const a=s;o=a.body,n=a.headers||{},d=a.statusCode||200}if(o&&typeof o=="object"&&o.content!==void 0){const{content:a,contentType:h}=o;o=a,n={...n,"Content-Type":h}}this.send(t,{body:o||s,headers:n,statusCode:d})}buildFileUrl(e,t){return this.buildFileUrlFromString(e.originalUrl||e.url,t,e.headers)}negotiateContentType(e,t){return super.negotiateContentTypeFromHeader(e.headers.accept,t)}async options(e,t){return{headers:{"Access-Control-Allow-Methods":(this.constructor.methods||x.methods).map(s=>s.toUpperCase()).join(", ")},statusCode:204}}async get(e,t){const s=F(w(e));if(s?.params.uuid){const{ext:r,metadata:o,uuid:n}=s.params,d=r?n.replace(new RegExp(String.raw`\.${r}$`),""):n;if(o==="metadata"&&w(e).endsWith("/metadata"))try{const a=await this.storage.getMeta(d);return{...a,content:JSON.stringify(a),headers:{"Content-Type":b.createContentType({charset:"utf8",mediaType:"application/json"}),...a.expiredAt===void 0?{}:{"X-Upload-Expires":a.expiredAt.toString()},...a.modifiedAt===void 0?{}:{"Last-Modified":a.modifiedAt.toString()}},statusCode:200}}catch(a){const h=a;throw h.UploadErrorCode===g.FILE_NOT_FOUND||h.UploadErrorCode===g.GONE?f(404,"File metadata not found"):a}if(!R.test(d))return this.list(e,t);try{const a=new URL(e.url||"","http://localhost"),h=Object.fromEntries(a.searchParams.entries());if(Object.keys(h).length>0&&this.mediaTransformer&&this.mediaTransformer)try{const l=await this.mediaTransformer.handle(d,h);return{content:l.buffer,headers:{"Content-Length":String(l.size),"Content-Type":`${l.mediaType}/${l.format}`,"X-Media-Type":l.mediaType,"X-Original-Format":l.originalFile?.contentType?.split("/")[1]||"","X-Transformed-Format":l.format,...l.originalFile?.expiredAt===void 0?{}:{"X-Upload-Expires":l.originalFile.expiredAt.toString()},...l.originalFile?.modifiedAt===void 0?{}:{"Last-Modified":l.originalFile.modifiedAt.toString()},...l.originalFile?.ETag===void 0?{}:{ETag:l.originalFile.ETag}},statusCode:200}}catch(l){if(l.name==="ValidationError")throw f(400,l.message);this.logger?.warn(`Media transformation failed: ${l.message}`)}const i=await this.storage.getMeta(d);if((e.headers.range||i.size&&i.size>1024*1024)&&this.storage.getStream)try{const l=await this.storage.getStream({id:d});let E=l.headers?.["Content-Type"]||i.contentType;return E.includes("image")&&typeof r=="string"&&(E=T.getType(r)||E),{headers:{...l.headers,"Accept-Ranges":"bytes","Content-Type":E},size:l.size,statusCode:200,stream:l.stream,...i,contentType:E}}catch(l){this.logger?.warn(`Streaming failed, falling back to buffer: ${l}`)}const p=await this.storage.get({id:d});let{contentType:u}=p;u.includes("image")&&typeof r=="string"&&(u=T.getType(r)||u);const{ETag:y,expiredAt:C,modifiedAt:U,size:A}=p;return{headers:{"Accept-Ranges":"bytes","Content-Length":String(A),"Content-Type":u,...C===void 0?{}:{"X-Upload-Expires":C.toString()},...U===void 0?{}:{"Last-Modified":U.toString()},...y===void 0?{}:{ETag:y}},statusCode:200,...p,contentType:u}}catch(a){const h=a;throw h.UploadErrorCode===g.FILE_NOT_FOUND||h.UploadErrorCode===g.GONE?f(404,"File not found"):a}}return this.list(e,t)}async list(e,t){const s=new URL(e.url||"","http://localhost"),r=s.searchParams.get("limit"),o=s.searchParams.get("page"),n=await this.storage.list(Number(r||1e3));return n.length===0?{data:[],headers:{},statusCode:200}:o!==void 0&&r!==void 0?{data:H(Number(o),Number(r),n.length,n),headers:{},statusCode:200}:{data:n,headers:{},statusCode:200}}async download(e,t){const s=F(w(e));if(!s?.params.uuid||!R.test(s.params.uuid))throw f(404,"File not found");const{ext:r,uuid:o}=s.params;try{const n=await this.storage.getMeta(o);if(!this.storage.getStream){await this.sendError(t,f(501,"Streaming download not supported"));return}const d=await this.storage.getStream({id:o});let a=d.headers?.["Content-Type"]||n.contentType;a.includes("image")&&typeof r=="string"&&(a=T.getType(r)||a);const h=this.parseRangeHeader(e.headers.range,d.size||0),i={...d.headers,"Accept-Ranges":"bytes","Content-Disposition":b.createContentDisposition({filename:n.originalName||o,type:"attachment"}),"Content-Type":a};this.sendStream(t,d.stream,{headers:i,range:h||void 0,size:d.size,statusCode:h?206:200})}catch(n){const d=n;if(d.UploadErrorCode===g.FILE_NOT_FOUND||d.UploadErrorCode===g.GONE){await this.sendError(t,f(404,"File not found"));return}await this.sendError(t,n)}}checkForUndefinedIdOrPath(e){if(e instanceof Error&&["Id is undefined","Invalid request URL","Path is undefined"].includes(e.message))throw f(404,"File not found")}}export{x as T};
@@ -1 +0,0 @@
1
- import{createReadStream as _,createWriteStream as C}from"node:fs";import{truncate as P,stat as F,open as L,copyFile as A}from"node:fs/promises";import{PassThrough as W,Transform as x,pipeline as U}from"node:stream";import{y as D,d as I,z as B,l as M,V,x as Q,f as H}from"./local-meta-storage-iuJnu90B.js";import{A as G,m as K}from"./path-0oTTdkvl-DvWvbDbh.js";import{F as X}from"./index-nZWCQrSe.js";import{d as Y}from"./detect-file-type-BA7UBLKA.js";import{throwErrorCode as g,ERRORS as h,isUploadError as q}from"./ERRORS-BIBxE2oR.js";import{createHash as j}from"node:crypto";import{B as J,a as Z,c as $}from"./storage-0j5nCAUp.js";import tt from"./File-W8aOo15X.js";import{t as k}from"./get-file-status-y3wTtDQs.js";import{t as et}from"./update-size-DuNuLyxj.js";import{i as rt}from"./part-match-D-9dGX42.js";import{e as it}from"./has-content-50BsqrWw.js";class st extends x{constructor(t,e,r="base64"){super(),this.checksum=t,this.algorithm=e,this.encoding=r,this.hash=j(e)}checksum;algorithm;encoding;length=0;digest="";hash;get calculatedDigest(){return this.digest}_transform(t,e,r){this.push(t),this.hash.update(t),this.length+=t.length,r()}_flush(t){this.digest=this.hash.digest(this.encoding),this.checksum&&this.checksum!==this.digest?t(new Error("Checksum mismatch")):t()}}const at=(S,t,e="base64")=>t?new st(S,t,e):new W;class nt extends x{constructor(t=Number.POSITIVE_INFINITY){super(),this.limit=t}limit;length=0;_transform(t,e,r){const a=this.length+t.length;this.limit>=a?(this.push(t),this.length=a,r()):r(new Error("Stream length limit exceeded"))}}class w extends J{static name="disk";checksumTypes=["md5","sha1"];supportsRange=!0;get raw(){return{directory:this.directory}}directory;meta;constructor(t){const e={...t,fileNameValidation:t.fileNameValidation??Z};if(super(e),this.directory=e.directory,e.metaStorage)this.meta=e.metaStorage;else{const r={...e,...e.metaStorageConfig,logger:this.logger};this.meta=new D(r)}this.isReady=!1,this.accessCheck().then(()=>{this.isReady=!0}).catch(r=>{this.logger?.error("Storage access check failed: %O",r)})}normalizeError(t){return super.normalizeError(t)}async create(t){return this.instrumentOperation("create",async()=>{const e={...t};if(t.ttl){const i=typeof t.ttl=="string"?$(t.ttl):t.ttl;i!==void 0&&(e.expiredAt=Date.now()+i)}e.size!==void 0&&Number(e.size)<0&&g(h.REQUEST_ENTITY_TOO_LARGE,"Request entity too large");const r=new tt(e);try{const i=await this.getMeta(r.id);if(i.status==="completed")return i}catch{}r.name=this.namingFunction(r),(r.size===void 0||Number.isNaN(r.size))&&(r.size===void 0||(r.size=this.maxUploadSize)),await this.validate(r);const a=this.getFilePath(r.name);try{await I(a),r.bytesWritten=0}catch(i){const s=this.normalizeError(i instanceof Error?i:new Error(String(i)));await this.onError(s),g(h.FILE_ERROR,s.message)}return r.status=k(r),await this.saveMeta(r),await this.onCreate(r),r})}async write(t){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(t.size!==void 0&&et(e,t.size),!rt(t,e))return g(h.FILE_CONFLICT);const r=this.getFilePath(e.name),a=await this.lock(r);try{const i=t.start||0;if(await I(r),e.bytesWritten===0&&(e.bytesWritten=i),it(t)){if(this.isUnsupportedChecksum(t.checksumAlgorithm))return g(h.UNSUPPORTED_CHECKSUM_ALGORITHM);if((t.start===0||t.start===void 0)&&(e.bytesWritten===0||Number.isNaN(e.bytesWritten))&&(!e.contentType||e.contentType==="application/octet-stream"))try{const{fileType:u,stream:d}=await Y(t.body);u?.mime&&(e.contentType=u.mime),t.body=d}catch{}const s=t.signal,o={...e,...t,body:t.body};s&&(o.signal=s);const[n,m]=await this.lazyWrite(o);if(m)return await P(r,e.bytesWritten),g(m);const l=i+(t.contentLength||0);e.bytesWritten=Math.max(e.bytesWritten||0,l),e.bytesWritten=Math.max(e.bytesWritten||0,n),e.status=k(e),await this.saveMeta(e)}else await I(r),e.bytesWritten=0;return e}catch(i){if(q(i))throw i;const s=this.normalizeError(i instanceof Error?i:new Error(String(i)));return await this.onError(s),g(h.FILE_ERROR,(typeof s.message=="string"?s.message:String(i))||String(i))}finally{await this.unlock(r,a)}})}async get({id:t},e){return this.instrumentOperation("get",async()=>{const r=await this.checkIfExpired(await this.meta.get(t)),{bytesWritten:a,contentType:i,expiredAt:s,metadata:o,modifiedAt:n,name:m,originalName:l,size:u}=r,d=this.getFilePath(m),E=e?.range,b=async c=>{const y=c;if(y.code==="ENOENT"||y.code==="EPERM"){const p=this.normalizeError(c instanceof Error?c:new Error(y.message||String(c)));return await this.onError(p),g(h.FILE_NOT_FOUND,(typeof p.message=="string"?p.message:String(c))||String(c))}const f=this.normalizeError(c instanceof Error?c:new Error(String(c)));throw await this.onError(f),c};if(E){let c;try{c=await F(d)}catch(R){return b(R)}const y=c.size,f=Math.max(0,E.start),p=E.end===void 0?y-1:Math.min(y-1,E.end);if(f>p||f>=y)return g(h.BAD_REQUEST,`Invalid range ${f}-${E.end??""}`);const N=p-f+1,z=Buffer.allocUnsafe(N);let O;try{O=await L(d,"r"),await O.read(z,0,N,f)}catch(R){return b(R)}finally{await O?.close()}const v=`W/"${y.toString(16)}-${Math.trunc(c.mtimeMs).toString(16)}-${f}-${p}"`;return{content:z,contentType:i,ETag:v,expiredAt:s,id:t,metadata:o,modifiedAt:n,name:m,originalName:l,size:N}}let T;try{T=await B(d,{buffer:!0})}catch(c){return b(c)}return{content:T,contentType:i,ETag:X(T),expiredAt:s,id:t,metadata:o,modifiedAt:n,name:m,originalName:l,size:u||a}})}async exists({id:t}){return this.instrumentOperation("exists",async()=>{try{const e=await this.getMeta(t),r=this.getFilePath(e.name);return await F(r),!0}catch{return!1}})}async getStream({id:t}){return this.instrumentOperation("getStream",async()=>{try{const e=await this.checkIfExpired(await this.meta.get(t)),{bytesWritten:r,contentType:a,expiredAt:i,modifiedAt:s,name:o,size:n}=e,m=_(this.getFilePath(o));return{headers:{"Content-Length":String(n||r),"Content-Type":a,...i&&{"X-Upload-Expires":i.toString()},...s&&{"Last-Modified":s.toString()}},size:n||r,stream:m}}catch(e){const r=this.normalizeError(e instanceof Error?e:new Error(String(e)));throw await this.onError(r),g(h.FILE_NOT_FOUND,(typeof r.message=="string"?r.message:String(e))||String(e))}})}async delete({id:t}){return this.instrumentOperation("delete",async()=>{const e=await this.getMeta(t);await M(this.getFilePath(e.name)),await this.deleteMeta(t);const r={...e,status:"deleted"};return await this.onDelete(r),r})}async copy(t,e){return this.instrumentOperation("copy",async()=>{w.assertSafeId(t),w.assertSafeId(e);const r=await this.getMeta(t);return await A(this.getFilePath(r.name),this.getFilePath(e)),{...r,name:e}})}async move(t,e){return this.instrumentOperation("move",async()=>{w.assertSafeId(t),w.assertSafeId(e);const r=await this.getMeta(t),a=this.getFilePath(r.name),i=this.getFilePath(e);try{await V(a,i)}catch(s){if(s?.code==="EXDEV")await A(a,i),await M(a);else{const o=this.normalizeError(s instanceof Error?s:new Error(String(s)));throw await this.onError(o),s}}return{...r,id:r.id,name:e}})}async list(){return this.instrumentOperation("list",async()=>{const t={followSymlinks:!1,includeDirs:!1,includeFiles:!0,skip:["*.META$"]},e=[],{directory:r}=this,a=s=>s.replaceAll("\\","/"),i=a(r);for await(const s of Q(r,t)){const{suffix:o}=this.meta,{path:n}=s;if(!n.includes(o)){const{birthtime:m,ctime:l,mtime:u}=await F(n),d=a(n),E=d.startsWith(i)?d.slice(i.length):d;e.push({createdAt:m||l,id:E,modifiedAt:u})}}return e})}getFilePath(t){return w.assertSafeId(t),G(t)&&g(h.INVALID_FILE_NAME,`Invalid file id: "${t}"`),K(this.directory,t)}lazyWrite(t){return new Promise((e,r)=>{const a=C(this.getFilePath(t.name),{flags:"r+",start:t.start}),i=new nt(t.contentLength||t.size-t.start),s=at(t.checksum,t.checksumAlgorithm),o=!t.checksum,{signal:n}=t,m=()=>{a.close(),i.destroy(),s.destroy()},l=d=>{m(),e([Number.NaN,d])};if(i.on("error",()=>{l(h.FILE_CONFLICT)}),s.on("error",()=>{l(h.CHECKSUM_MISMATCH)}),t.body.on("aborted",()=>{l(o?void 0:h.REQUEST_ABORTED)}),t.body.on("error",d=>{m(),r(d)}),n?.aborted){l(o?void 0:h.REQUEST_ABORTED);return}let u;n&&(u=()=>{m(),a.destroy(),i.destroy(),s.destroy(),t.body.destroy(),e([Number.NaN,o?void 0:h.REQUEST_ABORTED])},n.addEventListener("abort",u,{once:!0})),U(t.body,i,s,a,d=>{if(n&&u&&n.removeEventListener("abort",u),d){if(m(),n?.aborted){e([Number.NaN,o?void 0:h.REQUEST_ABORTED]);return}e([Number.NaN,h.FILE_ERROR]);return}e([t.start+a.bytesWritten])})})}async accessCheck(){await H(this.directory)}}export{w as F,nt as n,at as s};