@visulima/storage 1.0.0-alpha.1 → 1.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +33 -14
  3. package/dist/adapter/nuxt/module.d.ts +39 -0
  4. package/dist/adapter/nuxt/module.js +93 -0
  5. package/dist/adapter/nuxt/package.json +20 -0
  6. package/dist/handler/base/base-handler-core.d.ts +91 -0
  7. package/dist/handler/base/base-handler-fetch.d.ts +76 -0
  8. package/dist/handler/base/base-handler-node.d.ts +137 -0
  9. package/dist/handler/http/fetch/index.d.ts +4 -0
  10. package/dist/handler/http/fetch/index.js +4 -0
  11. package/dist/handler/http/hono/index.d.ts +67 -0
  12. package/dist/handler/http/hono/index.js +65 -0
  13. package/dist/handler/http/nextjs/index.d.ts +61 -0
  14. package/dist/handler/http/nextjs/index.js +37 -0
  15. package/dist/handler/http/node/index.d.ts +4 -0
  16. package/dist/handler/http/node/index.js +4 -0
  17. package/dist/handler/http/solid-start/index.d.ts +60 -0
  18. package/dist/handler/http/solid-start/index.js +44 -0
  19. package/dist/handler/multipart/multipart-base.d.ts +84 -0
  20. package/dist/handler/multipart/multipart-fetch.d.ts +64 -0
  21. package/dist/handler/multipart/multipart.d.ts +49 -0
  22. package/dist/handler/rest/rest-base.d.ts +106 -0
  23. package/dist/handler/rest/rest-fetch.d.ts +88 -0
  24. package/dist/handler/rest/rest.d.ts +93 -0
  25. package/dist/handler/tus/tus-base.d.ts +152 -0
  26. package/dist/handler/tus/tus-fetch.d.ts +72 -0
  27. package/dist/handler/tus/tus.d.ts +78 -0
  28. package/dist/handler/types.d.ts +53 -0
  29. package/dist/handler/utils/request-parser.d.ts +72 -0
  30. package/dist/handler/utils/response-builder.d.ts +83 -0
  31. package/dist/handler/utils/storage-utils.d.ts +10 -0
  32. package/dist/handler/utils/stream-utils.d.ts +29 -0
  33. package/dist/handler/utils/upload-handlers.d.ts +76 -0
  34. package/dist/index.d.ts +17 -0
  35. package/dist/index.js +13 -0
  36. package/dist/metrics/index.d.ts +2 -0
  37. package/dist/metrics/no-op-metrics.d.ts +15 -0
  38. package/dist/metrics/opentelemetry-metrics.d.ts +55 -0
  39. package/dist/openapi/index.d.ts +5 -0
  40. package/dist/openapi/index.js +5 -0
  41. package/dist/openapi/rest.d.ts +7 -0
  42. package/dist/openapi/shared.d.ts +13 -0
  43. package/dist/openapi/transform.d.ts +3 -0
  44. package/dist/openapi/tus.d.ts +7 -0
  45. package/dist/openapi/xhr.d.ts +7 -0
  46. package/dist/packem_shared/AwsLightFile-tTneXZgG.js +11 -0
  47. package/dist/packem_shared/AwsLightMetaStorage-BWSOtVaN.js +4 -0
  48. package/dist/packem_shared/AwsLightStorage-Blv-GP4v.js +133 -0
  49. package/dist/packem_shared/AzureFile-CesgFzps.js +8 -0
  50. package/dist/packem_shared/AzureSMetaStorage-CFs-OYJT.js +88 -0
  51. package/dist/packem_shared/AzureStorage-B0v048hG.js +357 -0
  52. package/dist/packem_shared/BaseTransformer-C2gLib6v.js +82 -0
  53. package/dist/packem_shared/DiskStorage-BlltBst6.js +12 -0
  54. package/dist/packem_shared/DiskStorageWithChecksum-BJTmMklc.js +238 -0
  55. package/dist/packem_shared/ERRORS-D0apMqnc.js +97 -0
  56. package/dist/packem_shared/File-Bb3P23dr.js +69 -0
  57. package/dist/packem_shared/GCSConfig-vPP22kN6.js +11 -0
  58. package/dist/packem_shared/GCSFile-BIEunhAN.js +8 -0
  59. package/dist/packem_shared/GCSMetaStorage-BMFEdzJ7.js +7 -0
  60. package/dist/packem_shared/GCStorage-DnhiwaS9.js +406 -0
  61. package/dist/packem_shared/LocalMetaStorage-CZHhKkMd.js +7 -0
  62. package/dist/packem_shared/MediaTransformer-D6658DL1.js +1197 -0
  63. package/dist/packem_shared/MetaStorage-pECeFOad.js +46 -0
  64. package/dist/packem_shared/Metadata-DRLXeJ0F.js +89 -0
  65. package/dist/packem_shared/Multipart-CNFK_Okz.js +163 -0
  66. package/dist/packem_shared/Multipart-CtUL7BQw.js +128 -0
  67. package/dist/packem_shared/NetlifyBlobFile-CXzyjqrD.js +14 -0
  68. package/dist/packem_shared/NetlifyBlobMetaStorage-DxZ5aDvD.js +9 -0
  69. package/dist/packem_shared/NetlifyBlobStorage-CLPtjHqd.js +376 -0
  70. package/dist/packem_shared/NoOpMetrics-DhAk5rXc.js +10 -0
  71. package/dist/packem_shared/OpenTelemetryMetrics-BnxhqIaH.js +67 -0
  72. package/dist/packem_shared/Rest-CAOAEkOj.js +267 -0
  73. package/dist/packem_shared/Rest-DNuLwBrK.js +228 -0
  74. package/dist/packem_shared/S3File-DZiyk9Qt.js +11 -0
  75. package/dist/packem_shared/S3MetaStorage-Dz9aDabA.js +76 -0
  76. package/dist/packem_shared/S3Storage-DHmTk-hU.js +316 -0
  77. package/dist/packem_shared/TUS_RESUMABLE-GJzZ9R-f.js +434 -0
  78. package/dist/packem_shared/Tus-B8PmlMgR.js +200 -0
  79. package/dist/packem_shared/Tus-C4F1aYOl.js +195 -0
  80. package/dist/packem_shared/ValidationError-BfF1aE4h.js +26 -0
  81. package/dist/packem_shared/VercelBlobFile-BCg4aTEq.js +18 -0
  82. package/dist/packem_shared/VercelBlobMetaStorage-Bd9F-VFm.js +9 -0
  83. package/dist/packem_shared/VercelBlobStorage-DD9LMOS6.js +261 -0
  84. package/dist/packem_shared/_commonjsHelpers-B85MJLTf.js +5 -0
  85. package/dist/packem_shared/aws-light-meta-storage-DKJBgbR6.js +446 -0
  86. package/dist/packem_shared/backblaze-BlMnIcBC.js +20 -0
  87. package/dist/packem_shared/base-handler-core-BKuf4YLT.js +303 -0
  88. package/dist/packem_shared/base-handler-fetch-Cr0hLiqg.js +291 -0
  89. package/dist/packem_shared/base-handler-node-gk5aN9Cx.js +730 -0
  90. package/dist/packem_shared/cache-B88MXQ_2.js +18 -0
  91. package/dist/packem_shared/cloudflare-Bi1q8wXE.js +21 -0
  92. package/dist/packem_shared/defaultCloudStorageFileNameValidation-DUuacjWv.js +11 -0
  93. package/dist/packem_shared/digitalOcean-CWQRJM3L.js +21 -0
  94. package/dist/packem_shared/disk-storage-Bh2wy3YW.js +810 -0
  95. package/dist/packem_shared/gcs-meta-storage-0tgMNnPO.js +158 -0
  96. package/dist/packem_shared/has-content-CY66ehMK.js +3 -0
  97. package/dist/packem_shared/headers-DoS5nwM-.js +3220 -0
  98. package/dist/packem_shared/is-expired-CTThU1q5.js +8 -0
  99. package/dist/packem_shared/isRetryableError-Dycp7127.js +82 -0
  100. package/dist/packem_shared/isValidMediaType-BeDgiObq.js +35 -0
  101. package/dist/packem_shared/local-meta-storage-By-3SNBI.js +649 -0
  102. package/dist/packem_shared/minio-C2YBZQOw.js +22 -0
  103. package/dist/packem_shared/multipart-base-B3i67SSX.js +102 -0
  104. package/dist/packem_shared/part-match-BMNqHDYD.js +96 -0
  105. package/dist/packem_shared/path-CR6YkPXX-7R1-9CMk.js +161 -0
  106. package/dist/packem_shared/response-builder-BtnRiBUI.js +45 -0
  107. package/dist/packem_shared/rest-base-GRCcnan7.js +457 -0
  108. package/dist/packem_shared/restOpenApiSpec-CwcHHY2C.js +800 -0
  109. package/dist/packem_shared/s3-base-storage-C1DIHTYY.js +510 -0
  110. package/dist/packem_shared/sharedGet-Cpo7QUyu.js +1019 -0
  111. package/dist/packem_shared/storage-C6NSXb8h.js +1175 -0
  112. package/dist/packem_shared/tigris-Hac8TKnX.js +21 -0
  113. package/dist/packem_shared/transformOpenApiSpec-DWM5WtnN.js +975 -0
  114. package/dist/packem_shared/tusOpenApiSpec-6ohiToBy.js +740 -0
  115. package/dist/packem_shared/update-size-CCGm6i1J.js +8 -0
  116. package/dist/packem_shared/validator-BeX_lJet.js +78 -0
  117. package/dist/packem_shared/waitForStorage-Cscw85sx.js +18 -0
  118. package/dist/packem_shared/wasabi-DIyflHSd.js +21 -0
  119. package/dist/packem_shared/xhrOpenApiSpec-DS17brnx.js +264 -0
  120. package/dist/storage/aws/clients/backblaze.d.ts +12 -0
  121. package/dist/storage/aws/clients/cloudflare.d.ts +13 -0
  122. package/dist/storage/aws/clients/digital-ocean.d.ts +12 -0
  123. package/dist/storage/aws/clients/index.d.ts +6 -0
  124. package/dist/storage/aws/clients/index.js +6 -0
  125. package/dist/storage/aws/clients/minio.d.ts +13 -0
  126. package/dist/storage/aws/clients/tigris.d.ts +12 -0
  127. package/dist/storage/aws/clients/types.d.ts +95 -0
  128. package/dist/storage/aws/clients/wasabi.d.ts +12 -0
  129. package/dist/storage/aws/index.d.ts +4 -0
  130. package/dist/storage/aws/index.js +3 -0
  131. package/dist/storage/aws/s3-base-storage.d.ts +248 -0
  132. package/dist/storage/aws/s3-client-adapter.d.ts +110 -0
  133. package/dist/storage/aws/s3-file.d.ts +10 -0
  134. package/dist/storage/aws/s3-meta-storage.d.ts +15 -0
  135. package/dist/storage/aws/s3-storage.d.ts +70 -0
  136. package/dist/storage/aws/types.d.ts +119 -0
  137. package/dist/storage/aws-light/aws-light-api-adapter.d.ts +130 -0
  138. package/dist/storage/aws-light/aws-light-file.d.ts +10 -0
  139. package/dist/storage/aws-light/aws-light-meta-storage.d.ts +19 -0
  140. package/dist/storage/aws-light/aws-light-storage.d.ts +65 -0
  141. package/dist/storage/aws-light/index.d.ts +4 -0
  142. package/dist/storage/aws-light/index.js +3 -0
  143. package/dist/storage/aws-light/types.d.ts +37 -0
  144. package/dist/storage/azure/azure-file.d.ts +6 -0
  145. package/dist/storage/azure/azure-meta-storage.d.ts +15 -0
  146. package/dist/storage/azure/azure-storage.d.ts +69 -0
  147. package/dist/storage/azure/index.d.ts +4 -0
  148. package/dist/storage/azure/index.js +3 -0
  149. package/dist/storage/azure/types.d.ts +62 -0
  150. package/dist/storage/gcs/fetch-error.d.ts +11 -0
  151. package/dist/storage/gcs/gcs-config.d.ts +2 -0
  152. package/dist/storage/gcs/gcs-file.d.ts +6 -0
  153. package/dist/storage/gcs/gcs-meta-storage.d.ts +27 -0
  154. package/dist/storage/gcs/gcs-storage.d.ts +91 -0
  155. package/dist/storage/gcs/index.d.ts +5 -0
  156. package/dist/storage/gcs/index.js +4 -0
  157. package/dist/storage/gcs/types.d.ts +55 -0
  158. package/dist/storage/gcs/utils.d.ts +7 -0
  159. package/dist/storage/local/disk-storage-with-checksum.d.ts +15 -0
  160. package/dist/storage/local/disk-storage.d.ts +135 -0
  161. package/dist/storage/local/index.d.ts +4 -0
  162. package/dist/storage/local/index.js +3 -0
  163. package/dist/storage/local/local-meta-storage.d.ts +32 -0
  164. package/dist/storage/meta-storage.d.ts +30 -0
  165. package/dist/storage/netlify-blob/index.d.ts +4 -0
  166. package/dist/storage/netlify-blob/index.js +3 -0
  167. package/dist/storage/netlify-blob/netlify-blob-file.d.ts +12 -0
  168. package/dist/storage/netlify-blob/netlify-blob-meta-storage.d.ts +7 -0
  169. package/dist/storage/netlify-blob/netlify-blob-storage.d.ts +93 -0
  170. package/dist/storage/netlify-blob/types.d.ts +30 -0
  171. package/dist/storage/storage.d.ts +353 -0
  172. package/dist/storage/types.d.ts +221 -0
  173. package/dist/storage/utils/file/file.d.ts +25 -0
  174. package/dist/storage/utils/file/get-file-status.d.ts +9 -0
  175. package/dist/storage/utils/file/has-content.d.ts +9 -0
  176. package/dist/storage/utils/file/index.d.ts +10 -0
  177. package/dist/storage/utils/file/is-expired.d.ts +8 -0
  178. package/dist/storage/utils/file/metadata.d.ts +18 -0
  179. package/dist/storage/utils/file/part-match.d.ts +11 -0
  180. package/dist/storage/utils/file/types.d.ts +37 -0
  181. package/dist/storage/utils/file/update-metadata.d.ts +10 -0
  182. package/dist/storage/utils/file/update-size.d.ts +10 -0
  183. package/dist/storage/vercel-blob/index.d.ts +4 -0
  184. package/dist/storage/vercel-blob/index.js +3 -0
  185. package/dist/storage/vercel-blob/types.d.ts +32 -0
  186. package/dist/storage/vercel-blob/vercel-blob-file.d.ts +16 -0
  187. package/dist/storage/vercel-blob/vercel-blob-meta-storage.d.ts +7 -0
  188. package/dist/storage/vercel-blob/vercel-blob-storage.d.ts +76 -0
  189. package/dist/transformer/audio-transformer.d.ts +128 -0
  190. package/dist/transformer/audio-transformer.js +278 -0
  191. package/dist/transformer/base-transformer.d.ts +63 -0
  192. package/dist/transformer/image-transformer.d.ts +571 -0
  193. package/dist/transformer/image-transformer.js +1100 -0
  194. package/dist/transformer/index.d.ts +5 -0
  195. package/dist/transformer/index.js +4 -0
  196. package/dist/transformer/media-transformer.d.ts +332 -0
  197. package/dist/transformer/types.d.ts +652 -0
  198. package/dist/transformer/utils.d.ts +33 -0
  199. package/dist/transformer/validation-error.d.ts +23 -0
  200. package/dist/transformer/video-transformer.d.ts +145 -0
  201. package/dist/transformer/video-transformer.js +310 -0
  202. package/dist/utils/cache.d.ts +32 -0
  203. package/dist/utils/chunked-upload.d.ts +65 -0
  204. package/dist/utils/detect-file-type.d.ts +28 -0
  205. package/dist/utils/errors.d.ts +74 -0
  206. package/dist/utils/file-path-url-matcher.d.ts +18 -0
  207. package/dist/utils/headers.d.ts +111 -0
  208. package/dist/utils/http.d.ts +92 -0
  209. package/dist/utils/locker.d.ts +26 -0
  210. package/dist/utils/pipes/stream-checksum.d.ts +47 -0
  211. package/dist/utils/pipes/stream-length.d.ts +22 -0
  212. package/dist/utils/primitives/get-last-one.d.ts +3 -0
  213. package/dist/utils/primitives/is-record.d.ts +2 -0
  214. package/dist/utils/primitives/map-values.d.ts +9 -0
  215. package/dist/utils/primitives/pick.d.ts +2 -0
  216. package/dist/utils/primitives/to-milliseconds.d.ts +12 -0
  217. package/dist/utils/primitives/to-seconds.d.ts +12 -0
  218. package/dist/utils/range-checksum.d.ts +33 -0
  219. package/dist/utils/range-hasher.d.ts +46 -0
  220. package/dist/utils/retry.d.ts +64 -0
  221. package/dist/utils/types.d.ts +108 -0
  222. package/dist/utils/validation-error.d.ts +22 -0
  223. package/dist/utils/validator.d.ts +36 -0
  224. package/package.json +5 -5
@@ -0,0 +1,37 @@
1
+ import type { Readable } from "node:stream";
2
+ import type { Metadata } from "./metadata.d.ts";
3
+ export interface FileInit {
4
+ contentType?: string;
5
+ expiredAt?: Date | number | string;
6
+ metadata: Metadata;
7
+ originalName?: string;
8
+ size?: number | string;
9
+ storageClass?: string;
10
+ ttl?: number | string;
11
+ }
12
+ export interface FileReturn extends Omit<Required<FileInit>, "storageClass" | "ttl" | "expiredAt"> {
13
+ content: Buffer;
14
+ ETag?: string;
15
+ expiredAt?: Date | number | string;
16
+ id: string;
17
+ modifiedAt?: Date | number | string;
18
+ name: string;
19
+ storageClass?: string;
20
+ }
21
+ type UploadEventTypeValue = "completed" | "created" | "deleted" | "part" | "updated";
22
+ export type UploadEventType = UploadEventTypeValue;
23
+ export interface FileQuery {
24
+ id: string;
25
+ name?: string;
26
+ size?: number;
27
+ }
28
+ export interface Checksum {
29
+ checksum?: string;
30
+ checksumAlgorithm?: string;
31
+ }
32
+ export interface FilePart extends Checksum, FileQuery {
33
+ body: Readable;
34
+ contentLength?: number;
35
+ start: number;
36
+ }
37
+ export {};
@@ -0,0 +1,10 @@
1
+ import type File from "./file.d.ts";
2
+ /**
3
+ * Updates a file object with new metadata using deep merge.
4
+ * Also updates the originalName based on the merged metadata.
5
+ * @param file File object to update
6
+ * @param metadata Partial metadata to merge into the file
7
+ * @template T - File type extending base File class
8
+ */
9
+ declare const updateMetadata: <T extends File>(file: T, metadata: Partial<T>) => void;
10
+ export default updateMetadata;
@@ -0,0 +1,10 @@
1
+ import type File from "./file.d.ts";
2
+ /**
3
+ * Updates a file's size, but only if the new size is smaller than the current size.
4
+ * This prevents accidental size increases that could indicate data corruption.
5
+ * @param file File object to update
6
+ * @param size New size value
7
+ * @returns The updated file object
8
+ */
9
+ declare const updateSize: (file: File, size: number) => File;
10
+ export default updateSize;
@@ -0,0 +1,4 @@
1
+ export type { VercelBlobStorageOptions } from "./types.d.ts";
2
+ export { default as VercelBlobFile } from "./vercel-blob-file.d.ts";
3
+ export { default as VercelBlobMetaStorage } from "./vercel-blob-meta-storage.d.ts";
4
+ export { default as VercelBlobStorage } from "./vercel-blob-storage.d.ts";
@@ -0,0 +1,3 @@
1
+ export { default as VercelBlobFile } from '../../packem_shared/VercelBlobFile-BCg4aTEq.js';
2
+ export { default as VercelBlobMetaStorage } from '../../packem_shared/VercelBlobMetaStorage-Bd9F-VFm.js';
3
+ export { default as VercelBlobStorage } from '../../packem_shared/VercelBlobStorage-DD9LMOS6.js';
@@ -0,0 +1,32 @@
1
+ import type { LocalMetaStorageOptions } from "../local/local-meta-storage.d.ts";
2
+ import type { BaseStorageOptions } from "../types.d.ts";
3
+ import type VercelBlobFile from "./vercel-blob-file.d.ts";
4
+ export interface VercelBlobStorageOptions extends BaseStorageOptions<VercelBlobFile> {
5
+ /**
6
+ * Configure metafiles storage
7
+ * @example
8
+ * Using local metafiles
9
+ * ```ts
10
+ * const storage = new VercelBlobStorage({
11
+ * token: process.env.BLOB_READ_WRITE_TOKEN,
12
+ * metaStorageConfig: { directory: '/tmp/upload-metafiles' }
13
+ * })
14
+ * ```
15
+ */
16
+ metaStorageConfig?: LocalMetaStorageOptions;
17
+ /**
18
+ * Enable multipart uploads for large files
19
+ * Can be a boolean to always use multipart, or a number (in bytes) as threshold
20
+ * @default false
21
+ * @example
22
+ * // Always use multipart uploads
23
+ * multipart: true
24
+ * // Use multipart for files larger than 100MB
25
+ * multipart: 100 * 1024 * 1024
26
+ */
27
+ multipart?: boolean | number;
28
+ /**
29
+ * Vercel Blob read-write token
30
+ */
31
+ token?: string;
32
+ }
@@ -0,0 +1,16 @@
1
+ import { File } from "../utils/index.d.ts";
2
+ declare class VercelBlobFile extends File {
3
+ /**
4
+ * The blob's public URL
5
+ */
6
+ url?: string;
7
+ /**
8
+ * The blob's download URL (may be different from url for private blobs)
9
+ */
10
+ downloadUrl?: string;
11
+ /**
12
+ * The blob's pathname within the store
13
+ */
14
+ pathname?: string;
15
+ }
16
+ export default VercelBlobFile;
@@ -0,0 +1,7 @@
1
+ import type { LocalMetaStorageOptions } from "../local/local-meta-storage.d.ts";
2
+ import LocalMetaStorage from "../local/local-meta-storage.d.ts";
3
+ import type VercelBlobFile from "./vercel-blob-file.d.ts";
4
+ declare class VercelBlobMetaStorage extends LocalMetaStorage<VercelBlobFile> {
5
+ constructor(config?: LocalMetaStorageOptions);
6
+ }
7
+ export default VercelBlobMetaStorage;
@@ -0,0 +1,76 @@
1
+ import type MetaStorage from "../meta-storage.d.ts";
2
+ import { BaseStorage } from "../storage.d.ts";
3
+ import type { FileInit, FilePart, FileQuery, FileReturn } from "../utils/index.d.ts";
4
+ import type { VercelBlobStorageOptions } from "./types.d.ts";
5
+ import VercelBlobFile from "./vercel-blob-file.d.ts";
6
+ /**
7
+ * Vercel Blob storage based backend.
8
+ * @example
9
+ * ```ts
10
+ * const storage = new VercelBlobStorage({
11
+ * token: process.env.BLOB_READ_WRITE_TOKEN,
12
+ * metaStorageConfig: { directory: '/tmp/upload-metafiles' }
13
+ * });
14
+ * ```
15
+ * @remarks
16
+ * ## Supported Operations
17
+ * - ✅ create, write, delete, get, copy, move
18
+ * - ✅ Batch operations: deleteBatch, copyBatch, moveBatch (inherited from BaseStorage)
19
+ * - ✅ exists: Implemented (checks metadata and Vercel Blob)
20
+ * - ❌ getStream: Not implemented (use get() for file retrieval)
21
+ * - ❌ list: Not implemented (Vercel Blob API doesn't support listing)
22
+ * - ❌ update: Not implemented (Vercel Blob API doesn't support metadata updates)
23
+ * - ❌ getUrl: Not implemented (Vercel Blob URLs available via Vercel Blob API)
24
+ * - ❌ getUploadUrl: Not implemented (Vercel Blob upload URLs handled internally)
25
+ */
26
+ declare class VercelBlobStorage extends BaseStorage<VercelBlobFile, FileReturn> {
27
+ static readonly name: string;
28
+ checksumTypes: string[];
29
+ protected meta: MetaStorage<VercelBlobFile>;
30
+ private readonly token;
31
+ private readonly multipart;
32
+ constructor(config: VercelBlobStorageOptions);
33
+ create(config: FileInit): Promise<VercelBlobFile>;
34
+ write(part: FilePart | FileQuery | VercelBlobFile): Promise<VercelBlobFile>;
35
+ /**
36
+ * Deletes an upload and its metadata.
37
+ * @param query File query containing the file ID to delete.
38
+ * @param query.id File ID to delete.
39
+ * @returns Promise resolving to the deleted file object with status: "deleted".
40
+ * @throws {UploadError} If the file metadata cannot be found.
41
+ */
42
+ delete({ id }: FileQuery): Promise<VercelBlobFile>;
43
+ /**
44
+ * Checks if a file exists by verifying both metadata and the actual Vercel Blob.
45
+ * Returns true only if both the metadata and the blob exist.
46
+ * @param query File query containing the file ID to check.
47
+ * @returns Promise resolving to true if both metadata and blob exist, false otherwise.
48
+ */
49
+ exists({ id }: FileQuery): Promise<boolean>;
50
+ get({ id }: FileQuery): Promise<FileReturn>;
51
+ /**
52
+ * Copies an upload file to a new location.
53
+ * @param name Source file name/ID.
54
+ * @param destination Destination file name/ID.
55
+ * @returns Promise resolving to the copied file object.
56
+ * @throws {UploadError} If the source file cannot be found.
57
+ */
58
+ copy(name: string, destination: string): Promise<VercelBlobFile>;
59
+ /**
60
+ * Moves an upload file to a new location.
61
+ * @param name Source file name/ID.
62
+ * @param destination Destination file name/ID.
63
+ * @returns Promise resolving to the moved file object.
64
+ * @throws {UploadError} If the source file cannot be found.
65
+ */
66
+ move(name: string, destination: string): Promise<VercelBlobFile>;
67
+ list(limit?: number): Promise<VercelBlobFile[]>;
68
+ private internalOnComplete;
69
+ /**
70
+ * Determines if multipart upload should be used for the given file.
71
+ * @param file File object to check.
72
+ * @returns True if multipart upload should be used, false otherwise.
73
+ */
74
+ private shouldUseMultipart;
75
+ }
76
+ export default VercelBlobStorage;
@@ -0,0 +1,128 @@
1
+ import type { BaseStorage } from "../storage/storage.d.ts";
2
+ import type { File, FileReturn } from "../storage/utils/index.d.ts";
3
+ import BaseTransformer from "./base-transformer.d.ts";
4
+ import type { AudioChannelMixOptions, AudioResampleOptions, AudioTransformationStep, AudioTransformerConfig, AudioTransformOptions, AudioTransformResult } from "./types.d.ts";
5
+ /**
6
+ * Audio transformer that uses storage backends and Mediabunny to retrieve and transform audio files
7
+ *
8
+ * Supports audio transformations with query parameters for on-demand audio processing.
9
+ * @example
10
+ * ```ts
11
+ * const transformer = new AudioTransformer(storage, {
12
+ * maxAudioSize: 50 * 1024 * 1024, // 50MB
13
+ * cache: new Map()
14
+ * });
15
+ *
16
+ * // Programmatic usage - resample audio
17
+ * const result = await transformer.resample('audio-id', {
18
+ * sampleRate: 44100
19
+ * });
20
+ *
21
+ * // URL-based transformations
22
+ * // GET /files/audio-id?sampleRate=48000&codec=aac&bitrate=128000
23
+ * // GET /files/audio-id?numberOfChannels=1&format=mp3
24
+ * ```
25
+ *
26
+ * ## Supported Query Parameters
27
+ *
28
+ * - `sampleRate`: Sample rate in Hz (Number)
29
+ * - `numberOfChannels`: Number of channels (Number)
30
+ * - `codec`: Audio codec - aac/opus/mp3/vorbis/flac
31
+ * - `bitrate`: Audio bitrate in bits per second (Number)
32
+ * - `format`: Output format - mp3/wav/ogg/aac/flac
33
+ */
34
+ declare class AudioTransformer<TFile extends File = File, TFileReturn extends FileReturn = FileReturn> extends BaseTransformer<AudioTransformerConfig, AudioTransformResult<TFileReturn>, TFile, TFileReturn> {
35
+ /**
36
+ * Creates a new AudioTransformer instance.
37
+ * @param storage The storage backend for retrieving and storing audio files.
38
+ * @param config Configuration options for audio transformation including cache settings, codec defaults, and size limits.
39
+ */
40
+ constructor(storage: BaseStorage<TFile, TFileReturn>, config?: AudioTransformerConfig);
41
+ /**
42
+ * Resamples audio to different sample rate.
43
+ * @param fileId Unique identifier of the audio file to resample.
44
+ * @param options Resample options including target sample rate.
45
+ * @returns Promise resolving to transformed audio result.
46
+ */
47
+ resample(fileId: string, options: AudioResampleOptions): Promise<AudioTransformResult<TFileReturn>>;
48
+ /**
49
+ * Changes number of channels (up/downmixing).
50
+ * @param fileId Unique identifier of the audio file to process.
51
+ * @param options Channel mix options including target number of channels.
52
+ * @returns Promise resolving to transformed audio result.
53
+ */
54
+ mixChannels(fileId: string, options: AudioChannelMixOptions): Promise<AudioTransformResult<TFileReturn>>;
55
+ /**
56
+ * Converts audio format or codec.
57
+ * @param fileId Unique identifier of the audio file to convert.
58
+ * @param format Target audio format (e.g., "mp3", "wav", "ogg").
59
+ * @param options Additional transform options.
60
+ * @returns Promise resolving to transformed audio result.
61
+ */
62
+ convertFormat(fileId: string, format: string, options?: AudioTransformOptions): Promise<AudioTransformResult<TFileReturn>>;
63
+ /**
64
+ * Transcodes audio to different codec.
65
+ * @param fileId Unique identifier of the audio file to transcode.
66
+ * @param codec Target audio codec (e.g., "aac", "opus", "mp3").
67
+ * @param options Additional transform options.
68
+ * @returns Promise resolving to transformed audio result.
69
+ */
70
+ transcode(fileId: string, codec: AudioTransformOptions["codec"], options?: Omit<AudioTransformOptions, "codec">): Promise<AudioTransformResult<TFileReturn>>;
71
+ /**
72
+ * Applies a custom transformation pipeline to an audio file.
73
+ * @param fileId Unique identifier of the audio file to transform.
74
+ * @param steps Array of transformation steps to apply in sequence.
75
+ * @returns Promise resolving to transformed audio result.
76
+ */
77
+ transform(fileId: string, steps: AudioTransformationStep[]): Promise<AudioTransformResult<TFileReturn>>;
78
+ /**
79
+ * Apply multiple transformations in sequence using Mediabunny
80
+ */
81
+ private applyTransformations;
82
+ /**
83
+ * Convert transformation steps to Mediabunny audio options
84
+ * @param steps Array of audio transformation steps to convert
85
+ * @returns Mediabunny audio options object for conversion
86
+ * @private
87
+ */
88
+ private stepsToAudioOptions;
89
+ /**
90
+ * Determine output format based on transformation steps
91
+ * @param steps Array of audio transformation steps
92
+ * @returns Mediabunny output format instance (defaults to MP3)
93
+ * @private
94
+ */
95
+ private determineOutputFormat;
96
+ /**
97
+ * Convert format string to Mediabunny output format
98
+ * @param format Audio format string (aac, flac, mp3, ogg, wav)
99
+ * @returns Mediabunny output format instance
100
+ * @private
101
+ */
102
+ private formatStringToOutputFormat;
103
+ /**
104
+ * Validate that the file is a supported audio file
105
+ * @param file The file to validate
106
+ * @returns Promise that resolves if validation passes
107
+ * @throws Error if file size exceeds limits, wrong content type, unsupported format, or invalid audio
108
+ * @private
109
+ */
110
+ private validateAudio;
111
+ /**
112
+ * Create transformation result with metadata
113
+ * @param buffer The transformed audio buffer
114
+ * @param originalFile The original file information
115
+ * @returns Audio transformation result with metadata
116
+ * @private
117
+ */
118
+ private createTransformResult;
119
+ /**
120
+ * Generate cache key for transformation
121
+ * @param fileId The file identifier
122
+ * @param steps Array of transformation steps
123
+ * @returns Unique cache key string
124
+ * @private
125
+ */
126
+ private generateCacheKey;
127
+ }
128
+ export default AudioTransformer;
@@ -0,0 +1,278 @@
1
+ import { Input, BufferSource, ALL_FORMATS, Output, BufferTarget, Conversion, Mp3OutputFormat, WavOutputFormat, OggOutputFormat, FlacOutputFormat, AdtsOutputFormat } from 'mediabunny';
2
+ import BaseTransformer from '../packem_shared/BaseTransformer-C2gLib6v.js';
3
+ import { isValidMediaType, getFormatFromContentType } from '../packem_shared/isValidMediaType-BeDgiObq.js';
4
+
5
+ class AudioTransformer extends BaseTransformer {
6
+ /**
7
+ * Creates a new AudioTransformer instance.
8
+ * @param storage The storage backend for retrieving and storing audio files.
9
+ * @param config Configuration options for audio transformation including cache settings, codec defaults, and size limits.
10
+ */
11
+ constructor(storage, config = {}) {
12
+ const logger = config.logger || storage.logger;
13
+ const transformerConfig = {
14
+ cacheTtl: 3600,
15
+ // 1 hour
16
+ defaultBitrate: 128e3,
17
+ // 128 kbps
18
+ defaultCodec: "aac",
19
+ maxAudioSize: 100 * 1024 * 1024,
20
+ // 100MB
21
+ maxCacheSize: 100,
22
+ // Max 100 transformed audio files in cache
23
+ supportedFormats: ["mp3", "wav", "ogg", "aac", "flac", "m4a", "wma", "aiff"],
24
+ ...config
25
+ };
26
+ super(storage, transformerConfig, logger);
27
+ }
28
+ /**
29
+ * Resamples audio to different sample rate.
30
+ * @param fileId Unique identifier of the audio file to resample.
31
+ * @param options Resample options including target sample rate.
32
+ * @returns Promise resolving to transformed audio result.
33
+ */
34
+ async resample(fileId, options) {
35
+ return this.transform(fileId, [{ options, type: "resample" }]);
36
+ }
37
+ /**
38
+ * Changes number of channels (up/downmixing).
39
+ * @param fileId Unique identifier of the audio file to process.
40
+ * @param options Channel mix options including target number of channels.
41
+ * @returns Promise resolving to transformed audio result.
42
+ */
43
+ async mixChannels(fileId, options) {
44
+ return this.transform(fileId, [{ options, type: "channels" }]);
45
+ }
46
+ /**
47
+ * Converts audio format or codec.
48
+ * @param fileId Unique identifier of the audio file to convert.
49
+ * @param format Target audio format (e.g., "mp3", "wav", "ogg").
50
+ * @param options Additional transform options.
51
+ * @returns Promise resolving to transformed audio result.
52
+ */
53
+ async convertFormat(fileId, format, options = {}) {
54
+ return this.transform(fileId, [{ options: { ...options, format }, type: "format" }]);
55
+ }
56
+ /**
57
+ * Transcodes audio to different codec.
58
+ * @param fileId Unique identifier of the audio file to transcode.
59
+ * @param codec Target audio codec (e.g., "aac", "opus", "mp3").
60
+ * @param options Additional transform options.
61
+ * @returns Promise resolving to transformed audio result.
62
+ */
63
+ async transcode(fileId, codec, options = {}) {
64
+ return this.transform(fileId, [{ options: { ...options, codec }, type: "codec" }]);
65
+ }
66
+ /**
67
+ * Applies a custom transformation pipeline to an audio file.
68
+ * @param fileId Unique identifier of the audio file to transform.
69
+ * @param steps Array of transformation steps to apply in sequence.
70
+ * @returns Promise resolving to transformed audio result.
71
+ */
72
+ async transform(fileId, steps) {
73
+ const fileQuery = { id: fileId };
74
+ const cacheKey = this.generateCacheKey(fileId, steps);
75
+ if (this.cache) {
76
+ const cached = await Promise.resolve(this.cache.get(cacheKey));
77
+ if (cached) {
78
+ this.logger?.debug("Returning cached transformed audio for %s", fileId);
79
+ return cached;
80
+ }
81
+ }
82
+ const originalFile = await this.storage.get(fileQuery);
83
+ await this.validateAudio(originalFile);
84
+ const transformedBuffer = await this.applyTransformations(originalFile.content, steps);
85
+ const result = await this.createTransformResult(transformedBuffer, originalFile);
86
+ if (this.cache) {
87
+ this.cache.set(cacheKey, result);
88
+ }
89
+ return result;
90
+ }
91
+ /**
92
+ * Apply multiple transformations in sequence using Mediabunny
93
+ */
94
+ async applyTransformations(buffer, steps) {
95
+ const input = new Input({
96
+ formats: ALL_FORMATS,
97
+ source: new BufferSource(buffer)
98
+ });
99
+ const outputFormat = this.determineOutputFormat(steps);
100
+ const output = new Output({
101
+ format: outputFormat,
102
+ target: new BufferTarget()
103
+ });
104
+ const audioOptions = this.stepsToAudioOptions(steps);
105
+ const conversion = await Conversion.init({
106
+ audio: audioOptions,
107
+ input,
108
+ output
109
+ });
110
+ if (!conversion.isValid) {
111
+ const reasons = conversion.discardedTracks.map((track) => track.reason).join(", ");
112
+ throw new Error(`Audio transformation failed: ${reasons}`);
113
+ }
114
+ await conversion.execute();
115
+ return Buffer.from(output.target.buffer);
116
+ }
117
+ /**
118
+ * Convert transformation steps to Mediabunny audio options
119
+ * @param steps Array of audio transformation steps to convert
120
+ * @returns Mediabunny audio options object for conversion
121
+ * @private
122
+ */
123
+ // eslint-disable-next-line class-methods-use-this
124
+ stepsToAudioOptions(steps) {
125
+ const options = {};
126
+ for (const step of steps) {
127
+ switch (step.type) {
128
+ case "bitrate": {
129
+ const bitrateOptions = step.options;
130
+ if (bitrateOptions.bitrate) {
131
+ options.bitrate = bitrateOptions.bitrate;
132
+ }
133
+ break;
134
+ }
135
+ case "channels": {
136
+ const channelOptions = step.options;
137
+ if (channelOptions.numberOfChannels) {
138
+ options.numberOfChannels = channelOptions.numberOfChannels;
139
+ }
140
+ break;
141
+ }
142
+ case "codec": {
143
+ const codecOptions = step.options;
144
+ if (codecOptions.codec) {
145
+ options.codec = codecOptions.codec;
146
+ }
147
+ if (codecOptions.bitrate) {
148
+ options.bitrate = codecOptions.bitrate;
149
+ }
150
+ break;
151
+ }
152
+ case "resample": {
153
+ const resampleOptions = step.options;
154
+ if (resampleOptions.sampleRate) {
155
+ options.sampleRate = resampleOptions.sampleRate;
156
+ }
157
+ break;
158
+ }
159
+ }
160
+ }
161
+ return options;
162
+ }
163
+ /**
164
+ * Determine output format based on transformation steps
165
+ * @param steps Array of audio transformation steps
166
+ * @returns Mediabunny output format instance (defaults to MP3)
167
+ * @private
168
+ */
169
+ determineOutputFormat(steps) {
170
+ for (const step of steps) {
171
+ if (step.type === "format" && step.options.format) {
172
+ return this.formatStringToOutputFormat(step.options.format);
173
+ }
174
+ }
175
+ return new Mp3OutputFormat();
176
+ }
177
+ /**
178
+ * Convert format string to Mediabunny output format
179
+ * @param format Audio format string (aac, flac, mp3, ogg, wav)
180
+ * @returns Mediabunny output format instance
181
+ * @private
182
+ */
183
+ // eslint-disable-next-line class-methods-use-this
184
+ formatStringToOutputFormat(format) {
185
+ switch (format.toLowerCase()) {
186
+ case "aac": {
187
+ return new AdtsOutputFormat();
188
+ }
189
+ case "flac": {
190
+ return new FlacOutputFormat();
191
+ }
192
+ case "mp3": {
193
+ return new Mp3OutputFormat();
194
+ }
195
+ case "ogg": {
196
+ return new OggOutputFormat();
197
+ }
198
+ case "wav": {
199
+ return new WavOutputFormat();
200
+ }
201
+ default: {
202
+ return new Mp3OutputFormat();
203
+ }
204
+ }
205
+ }
206
+ /**
207
+ * Validate that the file is a supported audio file
208
+ * @param file The file to validate
209
+ * @returns Promise that resolves if validation passes
210
+ * @throws Error if file size exceeds limits, wrong content type, unsupported format, or invalid audio
211
+ * @private
212
+ */
213
+ async validateAudio(file) {
214
+ const fileSize = typeof file.size === "string" ? Number.parseInt(file.size, 10) : file.size;
215
+ if (this.config?.maxAudioSize && fileSize > this.config.maxAudioSize) {
216
+ throw new Error(`Audio size ${fileSize} exceeds maximum allowed size ${this.config.maxAudioSize}`);
217
+ }
218
+ if (!isValidMediaType(file.contentType, "audio")) {
219
+ throw new Error(`File is not audio: ${file.contentType}`);
220
+ }
221
+ const format = getFormatFromContentType(file.contentType);
222
+ if (this.config?.supportedFormats && format && !this.config.supportedFormats.includes(format)) {
223
+ throw new Error(`Unsupported audio format: ${format}`);
224
+ }
225
+ try {
226
+ const input = new Input({
227
+ formats: ALL_FORMATS,
228
+ source: new BufferSource(file.content)
229
+ });
230
+ const primaryTrack = await input.getPrimaryAudioTrack();
231
+ if (!primaryTrack) {
232
+ throw new Error("No audio track found");
233
+ }
234
+ } catch (error) {
235
+ throw new Error(`Invalid audio file: ${error}`);
236
+ }
237
+ }
238
+ /**
239
+ * Create transformation result with metadata
240
+ * @param buffer The transformed audio buffer
241
+ * @param originalFile The original file information
242
+ * @returns Audio transformation result with metadata
243
+ * @private
244
+ */
245
+ async createTransformResult(buffer, originalFile) {
246
+ const input = new Input({
247
+ formats: ALL_FORMATS,
248
+ source: new BufferSource(buffer)
249
+ });
250
+ const audioTrack = await input.getPrimaryAudioTrack();
251
+ const duration = await input.computeDuration();
252
+ return {
253
+ bitrate: this.config.defaultBitrate,
254
+ buffer,
255
+ duration,
256
+ format: "mp3",
257
+ // Default, would need to detect actual format
258
+ numberOfChannels: audioTrack?.numberOfChannels || 2,
259
+ originalFile,
260
+ sampleRate: audioTrack?.sampleRate || 44100,
261
+ size: buffer.length
262
+ };
263
+ }
264
+ /**
265
+ * Generate cache key for transformation
266
+ * @param fileId The file identifier
267
+ * @param steps Array of transformation steps
268
+ * @returns Unique cache key string
269
+ * @private
270
+ */
271
+ // eslint-disable-next-line class-methods-use-this
272
+ generateCacheKey(fileId, steps) {
273
+ const stepsKey = steps.map((step) => `${step.type}:${JSON.stringify(step.options)}`).join("|");
274
+ return `${fileId}:${stepsKey}`;
275
+ }
276
+ }
277
+
278
+ export { AudioTransformer as default };
@@ -0,0 +1,63 @@
1
+ import { Readable } from "node:stream";
2
+ import type { BaseStorage } from "../storage/storage.d.ts";
3
+ import type { File, FileReturn } from "../storage/utils/index.d.ts";
4
+ import type { Cache } from "../utils/cache.d.ts";
5
+ import type { BaseTransformerConfig } from "./types.d.ts";
6
+ /**
7
+ * Abstract base class for all media transformers.
8
+ *
9
+ * Provides a common interface and shared functionality for image, video, and audio transformers.
10
+ * All transformers must implement the abstract methods defined here.
11
+ */
12
+ declare abstract class BaseTransformer<Config extends BaseTransformerConfig, CacheValue extends object, TFile extends File = File, TFileReturn extends FileReturn = FileReturn> {
13
+ protected readonly storage: BaseStorage<TFile, TFileReturn>;
14
+ protected config: Config;
15
+ protected logger?: Console;
16
+ protected cache?: Cache<string, CacheValue>;
17
+ /**
18
+ * Creates a new BaseTransformer instance with common functionality.
19
+ * @param storage The storage backend for retrieving and storing files.
20
+ * @param config Configuration options for the transformer.
21
+ * @param logger Optional logger instance for logging operations.
22
+ * @protected
23
+ */
24
+ protected constructor(storage: BaseStorage<TFile, TFileReturn>, config: Config, logger?: Console);
25
+ /**
26
+ * Transforms a file with the given steps.
27
+ * @param fileId Unique identifier of the file to transform.
28
+ * @param steps Array of transformation steps to apply.
29
+ * @returns Promise resolving to transformation result.
30
+ */
31
+ abstract transform(fileId: string, steps: any[]): Promise<any>;
32
+ /**
33
+ * Streams transform of a file with the given steps (for large files).
34
+ * @param fileId Unique identifier of the file to transform.
35
+ * @param steps Array of transformation steps to apply.
36
+ * @returns Promise resolving to streaming result with headers, size, and stream.
37
+ */
38
+ transformStream?(fileId: string, steps: any[]): Promise<{
39
+ headers?: Record<string, string>;
40
+ size?: number;
41
+ stream: Readable;
42
+ }>;
43
+ /**
44
+ * Clears cache for a specific file or all files.
45
+ * @param fileId Optional file identifier to clear cache for specific file.
46
+ */
47
+ clearCache(fileId?: string): void;
48
+ /**
49
+ * Gets cache statistics.
50
+ * @returns Cache statistics including max size and current size.
51
+ */
52
+ getCacheStats(): {
53
+ maxSize: number;
54
+ size: number;
55
+ };
56
+ /**
57
+ * Gets content type from transformation result based on format.
58
+ * @param result Transformation result object containing format information.
59
+ * @returns Content type string (MIME type).
60
+ */
61
+ protected getContentTypeFromResult(result: any): string;
62
+ }
63
+ export default BaseTransformer;