@visulima/storage 1.0.0-alpha.17 → 1.0.0-alpha.19
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.
- package/CHANGELOG.md +21 -0
- package/LICENSE.md +3 -0
- package/dist/adapter/nuxt/module.d.ts +3 -3
- package/dist/adapter/nuxt/module.js +1 -93
- package/dist/handler/http/fetch/index.d.ts +6 -6
- package/dist/handler/http/fetch/index.js +1 -4
- package/dist/handler/http/hono/index.d.ts +3 -3
- package/dist/handler/http/hono/index.js +1 -65
- package/dist/handler/http/nextjs/index.d.ts +4 -4
- package/dist/handler/http/nextjs/index.js +1 -37
- package/dist/handler/http/node/index.d.ts +6 -6
- package/dist/handler/http/node/index.js +1 -8
- package/dist/handler/http/solid-start/index.d.ts +4 -4
- package/dist/handler/http/solid-start/index.js +1 -44
- package/dist/index.js +1 -13
- package/dist/openapi/index.js +1 -5
- package/dist/packem_shared/AwsLightFile-BTLiRxXj.js +1 -0
- package/dist/packem_shared/AwsLightMetaStorage-DHz1nf_H.js +1 -0
- package/dist/packem_shared/AwsLightStorage-CA9cdfJ6.js +1 -0
- package/dist/packem_shared/AzureFile-BKHru1zB.js +1 -0
- package/dist/packem_shared/AzureSMetaStorage-BqA4jUDJ.js +1 -0
- package/dist/packem_shared/AzureStorage-BKUjCymW.js +1 -0
- package/dist/packem_shared/BaseTransformer-D68eLyz1.js +1 -0
- package/dist/packem_shared/DiskStorage-DNjpDMX9.js +1 -0
- package/dist/packem_shared/DiskStorageWithChecksum-Bb6JX_tC.js +1 -0
- package/dist/packem_shared/ERRORS-B9jkvKwx.js +1 -0
- package/dist/packem_shared/File-alcSNpLq.js +1 -0
- package/dist/packem_shared/GCSConfig-BQ0OpVhe.js +1 -0
- package/dist/packem_shared/GCSFile-CHjX_fJk.js +1 -0
- package/dist/packem_shared/GCSMetaStorage-CpxQ8wM9.js +1 -0
- package/dist/packem_shared/GCStorage-DAg1V55T.js +1 -0
- package/dist/packem_shared/LocalMetaStorage-BWuFvWn4.js +1 -0
- package/dist/packem_shared/MediaTransformer-2C8MJeAg.js +1 -0
- package/dist/packem_shared/MetaStorage-Y4m1dWgd.js +1 -0
- package/dist/packem_shared/Metadata-B6Ir0KO7.js +1 -0
- package/dist/packem_shared/Multipart-Bd9YFFn0.js +1 -0
- package/dist/packem_shared/Multipart-D5bcEvga.js +1 -0
- package/dist/packem_shared/NetlifyBlobFile-CpzkMKng.js +1 -0
- package/dist/packem_shared/NetlifyBlobMetaStorage-dD0oBLom.js +1 -0
- package/dist/packem_shared/NetlifyBlobStorage-ByTwCN-h.js +1 -0
- package/dist/packem_shared/NoOpMetrics-Dky06sf1.js +1 -0
- package/dist/packem_shared/OpenTelemetryMetrics-9uxQMSlg.js +1 -0
- package/dist/packem_shared/Rest-CYEBbtCD.js +1 -0
- package/dist/packem_shared/Rest-DoonVU7B.js +1 -0
- package/dist/packem_shared/S3File-Du6wP0Sz.js +1 -0
- package/dist/packem_shared/S3MetaStorage-vcriiosn.js +1 -0
- package/dist/packem_shared/S3Storage-Fx6-OSc-.js +1 -0
- package/dist/packem_shared/TUS_RESUMABLE-B7KtPVeC.js +1 -0
- package/dist/packem_shared/Tus-Bd_2Ki2G.js +1 -0
- package/dist/packem_shared/Tus-CUBCkuPE.js +1 -0
- package/dist/packem_shared/ValidationError-D8KKJiKA.js +1 -0
- package/dist/packem_shared/VercelBlobFile-CL9MjKcY.js +1 -0
- package/dist/packem_shared/VercelBlobMetaStorage-BsOTx-Su.js +1 -0
- package/dist/packem_shared/VercelBlobStorage-kNkk5Cn4.js +1 -0
- package/dist/packem_shared/_commonjsHelpers-D6W6KoPK.js +1 -0
- package/dist/packem_shared/aws-light-meta-storage-TPyQwLvk.js +4 -0
- package/dist/packem_shared/backblaze-DEflv87m.js +1 -0
- package/dist/packem_shared/base-handler-core-DaggCVsq.js +1 -0
- package/dist/packem_shared/base-handler-fetch-DnarP64X.js +1 -0
- package/dist/packem_shared/base-handler-node-BTes6sql.js +1 -0
- package/dist/packem_shared/cache-qV_5Umeq.js +1 -0
- package/dist/packem_shared/cloudflare-DLAeQvgD.js +1 -0
- package/dist/packem_shared/defaultCloudStorageFileNameValidation-yiM9GxHr.js +1 -0
- package/dist/packem_shared/digitalOcean-nhZUds87.js +1 -0
- package/dist/packem_shared/disk-storage-BvdK4bqF.js +5 -0
- package/dist/packem_shared/gcs-meta-storage-CvGkpzVE.js +1 -0
- package/dist/packem_shared/has-content-Bx2p8Okx.js +1 -0
- package/dist/packem_shared/headers-DC2MEOrK.js +27 -0
- package/dist/packem_shared/is-expired-1JuZjDtb.js +1 -0
- package/dist/packem_shared/isRetryableError-DQNSZiBc.js +1 -0
- package/dist/packem_shared/isValidMediaType-B-2UKjZx.js +1 -0
- package/dist/packem_shared/local-meta-storage-Bkwqi_gi.js +1 -0
- package/dist/packem_shared/{media-transformer.d-ChmjTvjc.d.ts → media-transformer.d-CY9CsEOe.d.ts} +1 -1
- package/dist/packem_shared/minio-BWwgGXeE.js +1 -0
- package/dist/packem_shared/multipart-base-C6OjBwMS.js +1 -0
- package/dist/packem_shared/part-match-DqD5U7An.js +1 -0
- package/dist/packem_shared/path-D7rMc9nq-B718mbm6.js +1 -0
- package/dist/packem_shared/response-builder-Wdo_fvcF.js +1 -0
- package/dist/packem_shared/rest-base-B2Dv7esY.js +1 -0
- package/dist/packem_shared/restOpenApiSpec-PaIVbESh.js +1 -0
- package/dist/packem_shared/s3-base-storage-xHZNtsGe.js +1 -0
- package/dist/packem_shared/sharedGet-Ce7WGAsc.js +1 -0
- package/dist/packem_shared/storage-m_Cxgiih.js +1 -0
- package/dist/packem_shared/tigris-DZoyrMNd.js +1 -0
- package/dist/packem_shared/transformOpenApiSpec-C0vEbDTO.js +1 -0
- package/dist/packem_shared/{tus-base.d-CpLzyd-S.d.ts → tus-base.d-DNZRXR9X.d.ts} +2 -2
- package/dist/packem_shared/tusOpenApiSpec-DF0-hlWV.js +1 -0
- package/dist/packem_shared/{types.d-DBjmJvIT.d.ts → types.d-BCN94sB_.d.ts} +1 -1
- package/dist/packem_shared/{types.d-DviSTLOg.d.ts → types.d-D4caL2Fp.d.ts} +1 -1
- package/dist/packem_shared/update-size-DANV7aa2.js +1 -0
- package/dist/packem_shared/validator-DK41xp8N.js +1 -0
- package/dist/packem_shared/waitForStorage-ChSBLhLc.js +1 -0
- package/dist/packem_shared/wasabi-Dmce4x9s.js +1 -0
- package/dist/packem_shared/xhrOpenApiSpec-nyoboz83.js +1 -0
- package/dist/storage/aws/clients/index.js +1 -6
- package/dist/storage/aws/index.js +1 -3
- package/dist/storage/aws-light/index.js +1 -3
- package/dist/storage/azure/index.js +1 -3
- package/dist/storage/gcs/index.js +1 -4
- package/dist/storage/local/index.js +1 -3
- package/dist/storage/netlify-blob/index.js +1 -3
- package/dist/storage/vercel-blob/index.js +1 -3
- package/dist/transformer/audio-transformer.d.ts +1 -1
- package/dist/transformer/audio-transformer.js +1 -278
- package/dist/transformer/image-transformer.d.ts +1 -1
- package/dist/transformer/image-transformer.js +1 -1100
- package/dist/transformer/index.d.ts +2 -2
- package/dist/transformer/index.js +1 -4
- package/dist/transformer/video-transformer.d.ts +1 -1
- package/dist/transformer/video-transformer.js +1 -310
- package/package.json +18 -18
- package/dist/packem_shared/AwsLightFile-C-Nd5rtl.js +0 -11
- package/dist/packem_shared/AwsLightMetaStorage-BIDb5EPg.js +0 -4
- package/dist/packem_shared/AwsLightStorage-CMuKw4bI.js +0 -133
- package/dist/packem_shared/AzureFile-C0kug4w4.js +0 -8
- package/dist/packem_shared/AzureSMetaStorage-BEbXX9Uk.js +0 -89
- package/dist/packem_shared/AzureStorage-98-LRZ1e.js +0 -359
- package/dist/packem_shared/BaseTransformer-9965D4pb.js +0 -83
- package/dist/packem_shared/DiskStorage-COMe_G42.js +0 -12
- package/dist/packem_shared/DiskStorageWithChecksum-BVaaZiyS.js +0 -249
- package/dist/packem_shared/ERRORS-D0apMqnc.js +0 -97
- package/dist/packem_shared/File-CPUhj3DI.js +0 -69
- package/dist/packem_shared/GCSConfig-vPP22kN6.js +0 -11
- package/dist/packem_shared/GCSFile-DaDiCKE2.js +0 -8
- package/dist/packem_shared/GCSMetaStorage-BygVH0Ee.js +0 -7
- package/dist/packem_shared/GCStorage-4hSx_bN1.js +0 -410
- package/dist/packem_shared/LocalMetaStorage-DvnZqf61.js +0 -7
- package/dist/packem_shared/MediaTransformer-BRRqYA0E.js +0 -1202
- package/dist/packem_shared/MetaStorage-pECeFOad.js +0 -46
- package/dist/packem_shared/Metadata-DRLXeJ0F.js +0 -89
- package/dist/packem_shared/Multipart-BzzvNxt4.js +0 -128
- package/dist/packem_shared/Multipart-DLtFLQ8s.js +0 -163
- package/dist/packem_shared/NetlifyBlobFile-CfyJtGWN.js +0 -14
- package/dist/packem_shared/NetlifyBlobMetaStorage-eJT6RFy9.js +0 -9
- package/dist/packem_shared/NetlifyBlobStorage-nPv7iIAG.js +0 -376
- package/dist/packem_shared/NoOpMetrics-DhAk5rXc.js +0 -10
- package/dist/packem_shared/OpenTelemetryMetrics-BnxhqIaH.js +0 -67
- package/dist/packem_shared/Rest-DEa7IA9R.js +0 -267
- package/dist/packem_shared/Rest-qhMbCn5a.js +0 -228
- package/dist/packem_shared/S3File-BXCuJaQZ.js +0 -11
- package/dist/packem_shared/S3MetaStorage-yT4CznlV.js +0 -77
- package/dist/packem_shared/S3Storage-wi5XT-yu.js +0 -317
- package/dist/packem_shared/TUS_RESUMABLE-Dtfsffnj.js +0 -434
- package/dist/packem_shared/Tus-Ck0Hdle5.js +0 -195
- package/dist/packem_shared/Tus-_0vCdHyB.js +0 -200
- package/dist/packem_shared/ValidationError-BfF1aE4h.js +0 -26
- package/dist/packem_shared/VercelBlobFile-DkFIIb9Q.js +0 -18
- package/dist/packem_shared/VercelBlobMetaStorage-DjFmi4vp.js +0 -9
- package/dist/packem_shared/VercelBlobStorage-CmMgiDgr.js +0 -261
- package/dist/packem_shared/_commonjsHelpers-BqLXS_qQ.js +0 -5
- package/dist/packem_shared/aws-light-meta-storage-BGZEiY3y.js +0 -447
- package/dist/packem_shared/backblaze-BlMnIcBC.js +0 -20
- package/dist/packem_shared/base-handler-core-lVB-D59L.js +0 -306
- package/dist/packem_shared/base-handler-fetch-CitgN-Aw.js +0 -291
- package/dist/packem_shared/base-handler-node-BiO2DF87.js +0 -731
- package/dist/packem_shared/cache-B88MXQ_2.js +0 -18
- package/dist/packem_shared/cloudflare-Bi1q8wXE.js +0 -21
- package/dist/packem_shared/defaultCloudStorageFileNameValidation-Brw40ZEP.js +0 -11
- package/dist/packem_shared/digitalOcean-CWQRJM3L.js +0 -21
- package/dist/packem_shared/disk-storage-D9RfoKjW.js +0 -832
- package/dist/packem_shared/gcs-meta-storage-8FovEDbW.js +0 -159
- package/dist/packem_shared/has-content-CY66ehMK.js +0 -3
- package/dist/packem_shared/headers-YLRp1dLo.js +0 -1318
- package/dist/packem_shared/is-expired-CTThU1q5.js +0 -8
- package/dist/packem_shared/isRetryableError-Dycp7127.js +0 -82
- package/dist/packem_shared/isValidMediaType-BeDgiObq.js +0 -35
- package/dist/packem_shared/local-meta-storage-D-pPc3FI.js +0 -658
- package/dist/packem_shared/minio-C2YBZQOw.js +0 -22
- package/dist/packem_shared/multipart-base-C994naBi.js +0 -102
- package/dist/packem_shared/part-match-Dt738Ddb.js +0 -96
- package/dist/packem_shared/path-aV9lMdcn-DMU5H1-h.js +0 -162
- package/dist/packem_shared/response-builder-BtnRiBUI.js +0 -45
- package/dist/packem_shared/rest-base-k1ory8uB.js +0 -457
- package/dist/packem_shared/restOpenApiSpec-BBJ_SiPE.js +0 -800
- package/dist/packem_shared/s3-base-storage-zUO8u8Cp.js +0 -510
- package/dist/packem_shared/sharedGet-CkSLSnMd.js +0 -1022
- package/dist/packem_shared/storage-5XW1E7XU.js +0 -1188
- package/dist/packem_shared/tigris-Hac8TKnX.js +0 -21
- package/dist/packem_shared/transformOpenApiSpec-BodFhFls.js +0 -975
- package/dist/packem_shared/tusOpenApiSpec-DzppyJTW.js +0 -740
- package/dist/packem_shared/update-size-CCGm6i1J.js +0 -8
- package/dist/packem_shared/validator-DuO17wFF.js +0 -79
- package/dist/packem_shared/waitForStorage-Cscw85sx.js +0 -18
- package/dist/packem_shared/wasabi-DIyflHSd.js +0 -21
- package/dist/packem_shared/xhrOpenApiSpec-CXz7BC5J.js +0 -264
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { type
|
|
2
|
-
export { M as MediaTransformer } from "../packem_shared/media-transformer.d-
|
|
1
|
+
export { type i as AudioChannelMixOptions, type h as AudioResampleOptions, type j as AudioTransformOptions, type g as AudioTransformResult, type k as AudioTransformationStep, type A as AudioTransformerConfig, B as BaseTransformer, type C as CropOptions, type m as ImageFormat, type I as ImageTransformerConfig, type U as MediaTransformQuery, type Q as MediaTransformResult, type W as MediaTransformationStep, type O as MediaTransformerConfig, type R as ResizeOptions, type l as RotateOptions, type n as TransformOptions, type T as TransformResult, type N as TransformationStep, type c as VideoCropOptions, type b as VideoResizeOptions, type d as VideoRotateOptions, type e as VideoTransformOptions, type a as VideoTransformResult, type f as VideoTransformationStep, type V as VideoTransformerConfig } from "../packem_shared/types.d-BCN94sB_.js";
|
|
2
|
+
export { M as MediaTransformer } from "../packem_shared/media-transformer.d-CY9CsEOe.js";
|
|
3
3
|
import { a as FileReturn } from "../packem_shared/storage.d-BOMUJD96.js";
|
|
4
4
|
import 'node:stream';
|
|
5
5
|
import 'node:crypto';
|
|
@@ -1,4 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { default as MediaTransformer } from '../packem_shared/MediaTransformer-BRRqYA0E.js';
|
|
3
|
-
export { getFormatFromContentType, isKnownContentType, isValidMediaType, validateMediaFile } from '../packem_shared/isValidMediaType-BeDgiObq.js';
|
|
4
|
-
export { default as ValidationError } from '../packem_shared/ValidationError-BfF1aE4h.js';
|
|
1
|
+
import{default as a}from"../packem_shared/BaseTransformer-D68eLyz1.js";import{default as t}from"../packem_shared/MediaTransformer-2C8MJeAg.js";import{getFormatFromContentType as d,isKnownContentType as f,isValidMediaType as n,validateMediaFile as m}from"../packem_shared/isValidMediaType-B-2UKjZx.js";import{default as l}from"../packem_shared/ValidationError-D8KKJiKA.js";export{a as BaseTransformer,t as MediaTransformer,l as ValidationError,d as getFormatFromContentType,f as isKnownContentType,n as isValidMediaType,m as validateMediaFile};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { F as File, a as FileReturn, B as BaseStorage } from "../packem_shared/storage.d-BOMUJD96.js";
|
|
2
|
-
import { V as VideoTransformerConfig,
|
|
2
|
+
import { V as VideoTransformerConfig, a as VideoTransformResult, b as VideoResizeOptions, c as VideoCropOptions, d as VideoRotateOptions, e as VideoTransformOptions, f as VideoTransformationStep, B as BaseTransformer } from "../packem_shared/types.d-BCN94sB_.js";
|
|
3
3
|
import 'node:stream';
|
|
4
4
|
import 'node:crypto';
|
|
5
5
|
import 'node:http';
|
|
@@ -1,310 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import BaseTransformer from '../packem_shared/BaseTransformer-9965D4pb.js';
|
|
3
|
-
import { isValidMediaType, getFormatFromContentType } from '../packem_shared/isValidMediaType-BeDgiObq.js';
|
|
4
|
-
|
|
5
|
-
class VideoTransformer extends BaseTransformer {
|
|
6
|
-
/**
|
|
7
|
-
* Creates a new VideoTransformer instance.
|
|
8
|
-
* @param storage The storage backend for retrieving and storing video files.
|
|
9
|
-
* @param config Configuration options for video 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: 2e6,
|
|
17
|
-
// 2 Mbps
|
|
18
|
-
defaultCodec: "avc",
|
|
19
|
-
// No cache provided - no caching
|
|
20
|
-
maxCacheSize: 50,
|
|
21
|
-
// Max 50 transformed videos in cache
|
|
22
|
-
maxVideoSize: 500 * 1024 * 1024,
|
|
23
|
-
// 500MB
|
|
24
|
-
supportedFormats: ["mp4", "webm", "mkv", "avi", "mov", "flv", "wmv"],
|
|
25
|
-
...config
|
|
26
|
-
};
|
|
27
|
-
super(storage, transformerConfig, logger);
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Resizes a video to specified dimensions with optional fit mode.
|
|
31
|
-
* @param fileId Unique identifier of the video file to resize.
|
|
32
|
-
* @param options Resize options including width, height, and fit mode.
|
|
33
|
-
* @returns Promise resolving to transformed video result.
|
|
34
|
-
*/
|
|
35
|
-
async resize(fileId, options) {
|
|
36
|
-
return this.transform(fileId, [{ options, type: "resize" }]);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Crops a video to the specified region.
|
|
40
|
-
* @param fileId Unique identifier of the video file to crop.
|
|
41
|
-
* @param options Crop options including region coordinates.
|
|
42
|
-
* @returns Promise resolving to transformed video result.
|
|
43
|
-
*/
|
|
44
|
-
async crop(fileId, options) {
|
|
45
|
-
return this.transform(fileId, [{ options, type: "crop" }]);
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Rotates a video by the specified angle.
|
|
49
|
-
* @param fileId Unique identifier of the video file to rotate.
|
|
50
|
-
* @param options Rotation configuration with angle in degrees and optional background color.
|
|
51
|
-
* @returns Promise resolving to transformed video result.
|
|
52
|
-
*/
|
|
53
|
-
async rotate(fileId, options) {
|
|
54
|
-
return this.transform(fileId, [{ options, type: "rotate" }]);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Converts video format or codec.
|
|
58
|
-
* @param fileId Unique identifier of the video file to convert.
|
|
59
|
-
* @param format Target video format (e.g., "mp4", "webm", "mkv").
|
|
60
|
-
* @param options Video transformation options including quality, bitrate, and codec settings.
|
|
61
|
-
* @returns Promise resolving to transformed video result with updated format metadata.
|
|
62
|
-
*/
|
|
63
|
-
async convertFormat(fileId, format, options = {}) {
|
|
64
|
-
return this.transform(fileId, [{ options: { ...options, format }, type: "format" }]);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Transcodes video to different codec.
|
|
68
|
-
* @param fileId Unique identifier of the video file to transcode.
|
|
69
|
-
* @param codec Target video codec (e.g., "avc", "hevc", "vp9").
|
|
70
|
-
* @param options Additional transform options.
|
|
71
|
-
* @returns Promise resolving to transformed video result.
|
|
72
|
-
*/
|
|
73
|
-
async transcode(fileId, codec, options = {}) {
|
|
74
|
-
return this.transform(fileId, [{ options: { ...options, codec }, type: "codec" }]);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Applies a custom transformation pipeline to a video.
|
|
78
|
-
* @param fileId Unique identifier of the video file to transform.
|
|
79
|
-
* @param steps Array of transformation steps to apply in sequence.
|
|
80
|
-
* @returns Promise resolving to transformed video result.
|
|
81
|
-
*/
|
|
82
|
-
async transform(fileId, steps) {
|
|
83
|
-
const fileQuery = { id: fileId };
|
|
84
|
-
const cacheKey = this.generateCacheKey(fileId, steps);
|
|
85
|
-
if (this.cache) {
|
|
86
|
-
const cached = await Promise.resolve(this.cache.get(cacheKey));
|
|
87
|
-
if (cached) {
|
|
88
|
-
this.logger?.debug("Returning cached transformed video for %s", fileId);
|
|
89
|
-
return cached;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
const originalFile = await this.storage.get(fileQuery);
|
|
93
|
-
await this.validateVideo(originalFile);
|
|
94
|
-
const transformedBuffer = await this.applyTransformations(originalFile.content, steps);
|
|
95
|
-
const result = await this.createTransformResult(transformedBuffer, originalFile);
|
|
96
|
-
if (this.cache) {
|
|
97
|
-
this.cache.set(cacheKey, result);
|
|
98
|
-
}
|
|
99
|
-
return result;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Applies multiple transformations in sequence using Mediabunny.
|
|
103
|
-
* @param buffer The original video buffer.
|
|
104
|
-
* @param steps Array of video transformation steps to apply.
|
|
105
|
-
* @returns Promise resolving to transformed video buffer.
|
|
106
|
-
* @private
|
|
107
|
-
*/
|
|
108
|
-
async applyTransformations(buffer, steps) {
|
|
109
|
-
const input = new Input({
|
|
110
|
-
formats: ALL_FORMATS,
|
|
111
|
-
source: new BufferSource(buffer)
|
|
112
|
-
});
|
|
113
|
-
const outputFormat = this.determineOutputFormat(steps);
|
|
114
|
-
const output = new Output({
|
|
115
|
-
format: outputFormat,
|
|
116
|
-
target: new BufferTarget()
|
|
117
|
-
});
|
|
118
|
-
const videoOptions = this.stepsToVideoOptions(steps);
|
|
119
|
-
const conversion = await Conversion.init({
|
|
120
|
-
input,
|
|
121
|
-
output,
|
|
122
|
-
video: videoOptions
|
|
123
|
-
});
|
|
124
|
-
if (!conversion.isValid) {
|
|
125
|
-
const reasons = conversion.discardedTracks.map((track) => track.reason).join(", ");
|
|
126
|
-
throw new Error(`Video transformation failed: ${reasons}`);
|
|
127
|
-
}
|
|
128
|
-
await conversion.execute();
|
|
129
|
-
return Buffer.from(output.target.buffer);
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Converts transformation steps to Mediabunny video options.
|
|
133
|
-
* @param steps Array of video transformation steps to convert.
|
|
134
|
-
* @returns Mediabunny video options object for conversion.
|
|
135
|
-
* @private
|
|
136
|
-
*/
|
|
137
|
-
// eslint-disable-next-line class-methods-use-this
|
|
138
|
-
stepsToVideoOptions(steps) {
|
|
139
|
-
const options = {};
|
|
140
|
-
for (const step of steps) {
|
|
141
|
-
switch (step.type) {
|
|
142
|
-
case "bitrate": {
|
|
143
|
-
const bitrateOptions = step.options;
|
|
144
|
-
if (bitrateOptions.bitrate) {
|
|
145
|
-
options.bitrate = bitrateOptions.bitrate;
|
|
146
|
-
}
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
case "codec": {
|
|
150
|
-
const codecOptions = step.options;
|
|
151
|
-
if (codecOptions.codec) {
|
|
152
|
-
options.codec = codecOptions.codec;
|
|
153
|
-
}
|
|
154
|
-
if (codecOptions.bitrate) {
|
|
155
|
-
options.bitrate = codecOptions.bitrate;
|
|
156
|
-
}
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
case "crop": {
|
|
160
|
-
const cropOptions = step.options;
|
|
161
|
-
options.crop = {
|
|
162
|
-
height: cropOptions.height,
|
|
163
|
-
left: cropOptions.left,
|
|
164
|
-
top: cropOptions.top,
|
|
165
|
-
width: cropOptions.width
|
|
166
|
-
};
|
|
167
|
-
break;
|
|
168
|
-
}
|
|
169
|
-
case "frameRate": {
|
|
170
|
-
const frameRateOptions = step.options;
|
|
171
|
-
if (frameRateOptions.frameRate) {
|
|
172
|
-
options.frameRate = frameRateOptions.frameRate;
|
|
173
|
-
}
|
|
174
|
-
break;
|
|
175
|
-
}
|
|
176
|
-
case "resize": {
|
|
177
|
-
const resizeOptions = step.options;
|
|
178
|
-
options.width = resizeOptions.width;
|
|
179
|
-
options.height = resizeOptions.height;
|
|
180
|
-
options.fit = resizeOptions.fit;
|
|
181
|
-
if (resizeOptions.position !== void 0) {
|
|
182
|
-
options.position = resizeOptions.position;
|
|
183
|
-
}
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
case "rotate": {
|
|
187
|
-
const rotateOptions = step.options;
|
|
188
|
-
options.rotate = rotateOptions.angle;
|
|
189
|
-
if (rotateOptions.background) {
|
|
190
|
-
options.background = rotateOptions.background;
|
|
191
|
-
}
|
|
192
|
-
break;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return options;
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Determines output format based on transformation steps.
|
|
200
|
-
* @param steps Array of video transformation steps.
|
|
201
|
-
* @returns Mediabunny output format instance (defaults to MP4).
|
|
202
|
-
* @private
|
|
203
|
-
*/
|
|
204
|
-
determineOutputFormat(steps) {
|
|
205
|
-
for (const step of steps) {
|
|
206
|
-
if (step.type === "format" && step.options.format) {
|
|
207
|
-
return this.formatStringToOutputFormat(step.options.format);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return new Mp4OutputFormat();
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* Converts format string to Mediabunny output format.
|
|
214
|
-
* @param format Video format string (mp4, webm, mkv, ogg).
|
|
215
|
-
* @returns Mediabunny output format instance.
|
|
216
|
-
* @private
|
|
217
|
-
*/
|
|
218
|
-
// eslint-disable-next-line class-methods-use-this
|
|
219
|
-
formatStringToOutputFormat(format) {
|
|
220
|
-
switch (format.toLowerCase()) {
|
|
221
|
-
case "mkv": {
|
|
222
|
-
return new MkvOutputFormat();
|
|
223
|
-
}
|
|
224
|
-
case "mp4": {
|
|
225
|
-
return new Mp4OutputFormat();
|
|
226
|
-
}
|
|
227
|
-
case "ogg": {
|
|
228
|
-
return new OggOutputFormat();
|
|
229
|
-
}
|
|
230
|
-
case "webm": {
|
|
231
|
-
return new WebMOutputFormat();
|
|
232
|
-
}
|
|
233
|
-
default: {
|
|
234
|
-
return new Mp4OutputFormat();
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Validates that the file is a supported video.
|
|
240
|
-
* @param file The file to validate.
|
|
241
|
-
* @returns Promise that resolves if validation passes.
|
|
242
|
-
* @throws Error if file size exceeds limits, wrong content type, unsupported format, or invalid video.
|
|
243
|
-
* @private
|
|
244
|
-
*/
|
|
245
|
-
async validateVideo(file) {
|
|
246
|
-
const fileSize = typeof file.size === "string" ? Number.parseInt(file.size, 10) : file.size;
|
|
247
|
-
if (this.config?.maxVideoSize && fileSize > this.config.maxVideoSize) {
|
|
248
|
-
throw new Error(`Video size ${fileSize} exceeds maximum allowed size ${this.config.maxVideoSize}`);
|
|
249
|
-
}
|
|
250
|
-
if (!isValidMediaType(file.contentType, "video")) {
|
|
251
|
-
throw new Error(`File is not a video: ${file.contentType}`);
|
|
252
|
-
}
|
|
253
|
-
const format = getFormatFromContentType(file.contentType);
|
|
254
|
-
if (this.config?.supportedFormats && format && !this.config.supportedFormats.includes(format)) {
|
|
255
|
-
throw new Error(`Unsupported video format: ${format}`);
|
|
256
|
-
}
|
|
257
|
-
try {
|
|
258
|
-
const input = new Input({
|
|
259
|
-
formats: ALL_FORMATS,
|
|
260
|
-
source: new BufferSource(file.content)
|
|
261
|
-
});
|
|
262
|
-
const primaryTrack = await input.getPrimaryVideoTrack();
|
|
263
|
-
if (!primaryTrack) {
|
|
264
|
-
throw new Error("No video track found");
|
|
265
|
-
}
|
|
266
|
-
} catch (error) {
|
|
267
|
-
throw new Error(`Invalid video file: ${error}`);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Creates transformation result with metadata.
|
|
272
|
-
* @param buffer The transformed video buffer.
|
|
273
|
-
* @param originalFile The original file information.
|
|
274
|
-
* @returns Video transformation result with metadata.
|
|
275
|
-
* @private
|
|
276
|
-
*/
|
|
277
|
-
async createTransformResult(buffer, originalFile) {
|
|
278
|
-
const input = new Input({
|
|
279
|
-
formats: ALL_FORMATS,
|
|
280
|
-
source: new BufferSource(buffer)
|
|
281
|
-
});
|
|
282
|
-
const videoTrack = await input.getPrimaryVideoTrack();
|
|
283
|
-
const duration = await input.computeDuration();
|
|
284
|
-
return {
|
|
285
|
-
bitrate: this.config.defaultBitrate,
|
|
286
|
-
buffer,
|
|
287
|
-
duration,
|
|
288
|
-
format: "mp4",
|
|
289
|
-
// Default, would need to detect actual format
|
|
290
|
-
height: videoTrack?.displayHeight || 0,
|
|
291
|
-
originalFile,
|
|
292
|
-
size: buffer.length,
|
|
293
|
-
width: videoTrack?.displayWidth || 0
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
/**
|
|
297
|
-
* Generates cache key for transformation.
|
|
298
|
-
* @param fileId The file identifier.
|
|
299
|
-
* @param steps Array of transformation steps.
|
|
300
|
-
* @returns Unique cache key string.
|
|
301
|
-
* @private
|
|
302
|
-
*/
|
|
303
|
-
// eslint-disable-next-line class-methods-use-this
|
|
304
|
-
generateCacheKey(fileId, steps) {
|
|
305
|
-
const stepsKey = steps.map((step) => `${step.type}:${JSON.stringify(step.options)}`).join("|");
|
|
306
|
-
return `${fileId}:${stepsKey}`;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
export { VideoTransformer as default };
|
|
1
|
+
var w=Object.defineProperty;var p=(n,t)=>w(n,"name",{value:t,configurable:!0});import{Input as f,BufferSource as m,ALL_FORMATS as u,Output as g,BufferTarget as l,Conversion as y,Mp4OutputFormat as d,WebMOutputFormat as b,OggOutputFormat as v,MkvOutputFormat as T}from"mediabunny";import F from"../packem_shared/BaseTransformer-D68eLyz1.js";import{isValidMediaType as k,getFormatFromContentType as O}from"../packem_shared/isValidMediaType-B-2UKjZx.js";var V=Object.defineProperty,z=p((n,t)=>V(n,"name",{value:t,configurable:!0}),"d");class C extends F{static{p(this,"b")}static{z(this,"VideoTransformer")}constructor(t,e={}){const r=e.logger||t.logger,o={cacheTtl:3600,defaultBitrate:2e6,defaultCodec:"avc",maxCacheSize:50,maxVideoSize:500*1024*1024,supportedFormats:["mp4","webm","mkv","avi","mov","flv","wmv"],...e};super(t,o,r)}async resize(t,e){return this.transform(t,[{options:e,type:"resize"}])}async crop(t,e){return this.transform(t,[{options:e,type:"crop"}])}async rotate(t,e){return this.transform(t,[{options:e,type:"rotate"}])}async convertFormat(t,e,r={}){return this.transform(t,[{options:{...r,format:e},type:"format"}])}async transcode(t,e,r={}){return this.transform(t,[{options:{...r,codec:e},type:"codec"}])}async transform(t,e){const r={id:t},o=this.generateCacheKey(t,e);if(this.cache){const s=await Promise.resolve(this.cache.get(o));if(s)return this.logger?.debug("Returning cached transformed video for %s",t),s}const a=await this.storage.get(r);await this.validateVideo(a);const c=await this.applyTransformations(a.content,e),i=await this.createTransformResult(c,a);return this.cache&&this.cache.set(o,i),i}async applyTransformations(t,e){const r=new f({formats:u,source:new m(t)}),o=this.determineOutputFormat(e),a=new g({format:o,target:new l}),c=this.stepsToVideoOptions(e),i=await y.init({input:r,output:a,video:c});if(!i.isValid){const s=i.discardedTracks.map(h=>h.reason).join(", ");throw new Error(`Video transformation failed: ${s}`)}return await i.execute(),Buffer.from(a.target.buffer)}stepsToVideoOptions(t){const e={};for(const r of t)switch(r.type){case"bitrate":{const o=r.options;o.bitrate&&(e.bitrate=o.bitrate);break}case"codec":{const o=r.options;o.codec&&(e.codec=o.codec),o.bitrate&&(e.bitrate=o.bitrate);break}case"crop":{const o=r.options;e.crop={height:o.height,left:o.left,top:o.top,width:o.width};break}case"frameRate":{const o=r.options;o.frameRate&&(e.frameRate=o.frameRate);break}case"resize":{const o=r.options;e.width=o.width,e.height=o.height,e.fit=o.fit,o.position!==void 0&&(e.position=o.position);break}case"rotate":{const o=r.options;e.rotate=o.angle,o.background&&(e.background=o.background);break}}return e}determineOutputFormat(t){for(const e of t)if(e.type==="format"&&e.options.format)return this.formatStringToOutputFormat(e.options.format);return new d}formatStringToOutputFormat(t){switch(t.toLowerCase()){case"mkv":return new T;case"mp4":return new d;case"ogg":return new v;case"webm":return new b;default:return new d}}async validateVideo(t){const e=typeof t.size=="string"?Number.parseInt(t.size,10):t.size;if(this.config?.maxVideoSize&&e>this.config.maxVideoSize)throw new Error(`Video size ${e} exceeds maximum allowed size ${this.config.maxVideoSize}`);if(!k(t.contentType,"video"))throw new Error(`File is not a video: ${t.contentType}`);const r=O(t.contentType);if(this.config?.supportedFormats&&r&&!this.config.supportedFormats.includes(r))throw new Error(`Unsupported video format: ${r}`);try{if(!await new f({formats:u,source:new m(t.content)}).getPrimaryVideoTrack())throw new Error("No video track found")}catch(o){throw new Error(`Invalid video file: ${o}`)}}async createTransformResult(t,e){const r=new f({formats:u,source:new m(t)}),o=await r.getPrimaryVideoTrack(),a=await r.computeDuration();return{bitrate:this.config.defaultBitrate,buffer:t,duration:a,format:"mp4",height:o?.displayHeight||0,originalFile:e,size:t.length,width:o?.displayWidth||0}}generateCacheKey(t,e){const r=e.map(o=>`${o.type}:${JSON.stringify(o.options)}`).join("|");return`${t}:${r}`}}export{C as default};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@visulima/storage",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.19",
|
|
4
4
|
"description": "Visulima upload - Store files in a web-accessible location via a simplified API. Can automatically scale and rotate images. Includes S3, Azure, GCS and local filesystem-based backends with the most convenient features of each.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"anolilab",
|
|
@@ -58,6 +58,11 @@
|
|
|
58
58
|
"visulima"
|
|
59
59
|
],
|
|
60
60
|
"homepage": "https://visulima.com/packages/uploads",
|
|
61
|
+
"license": "MIT",
|
|
62
|
+
"author": {
|
|
63
|
+
"name": "Daniel Bannert",
|
|
64
|
+
"email": "d.bannert@anolilab.de"
|
|
65
|
+
},
|
|
61
66
|
"repository": {
|
|
62
67
|
"type": "git",
|
|
63
68
|
"url": "https://github.com/visulima/visulima.git",
|
|
@@ -73,13 +78,14 @@
|
|
|
73
78
|
"url": "https://anolilab.com/support"
|
|
74
79
|
}
|
|
75
80
|
],
|
|
76
|
-
"
|
|
77
|
-
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
"files": [
|
|
82
|
+
"dist/**",
|
|
83
|
+
"README.md",
|
|
84
|
+
"CHANGELOG.md",
|
|
85
|
+
"LICENSE.md"
|
|
86
|
+
],
|
|
82
87
|
"type": "module",
|
|
88
|
+
"sideEffects": false,
|
|
83
89
|
"exports": {
|
|
84
90
|
".": {
|
|
85
91
|
"types": "./dist/index.d.ts",
|
|
@@ -179,12 +185,10 @@
|
|
|
179
185
|
},
|
|
180
186
|
"./package.json": "./package.json"
|
|
181
187
|
},
|
|
182
|
-
"
|
|
183
|
-
"
|
|
184
|
-
"
|
|
185
|
-
|
|
186
|
-
"LICENSE.md"
|
|
187
|
-
],
|
|
188
|
+
"publishConfig": {
|
|
189
|
+
"access": "public",
|
|
190
|
+
"provenance": true
|
|
191
|
+
},
|
|
188
192
|
"dependencies": {
|
|
189
193
|
"@remix-run/multipart-parser": "0.16.0",
|
|
190
194
|
"@sindresorhus/fnv1a": "3.1.0",
|
|
@@ -192,7 +196,7 @@
|
|
|
192
196
|
"file-type": "22.0.1",
|
|
193
197
|
"lru-cache": "11.3.5",
|
|
194
198
|
"mime": "^4.1.0",
|
|
195
|
-
"nanoid": "5.1.
|
|
199
|
+
"nanoid": "5.1.11",
|
|
196
200
|
"path-to-regexp": "8.4.2",
|
|
197
201
|
"type-is": "^2.0.1"
|
|
198
202
|
},
|
|
@@ -278,9 +282,5 @@
|
|
|
278
282
|
},
|
|
279
283
|
"engines": {
|
|
280
284
|
"node": "^22.14.0 || >=24.10.0"
|
|
281
|
-
},
|
|
282
|
-
"publishConfig": {
|
|
283
|
-
"access": "public",
|
|
284
|
-
"provenance": true
|
|
285
285
|
}
|
|
286
286
|
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { Readable } from 'node:stream';
|
|
2
|
-
import { S as S3BaseStorage } from './s3-base-storage-zUO8u8Cp.js';
|
|
3
|
-
import { a as AwsLightApiAdapter, A as AwsLightMetaStorage } from './aws-light-meta-storage-BGZEiY3y.js';
|
|
4
|
-
import AwsLightFile from './AwsLightFile-C-Nd5rtl.js';
|
|
5
|
-
|
|
6
|
-
class AwsLightStorage extends S3BaseStorage {
|
|
7
|
-
static name = "aws-light";
|
|
8
|
-
s3Api;
|
|
9
|
-
constructor(config) {
|
|
10
|
-
const { bucket = process.env.S3_BUCKET || process.env.AWS_S3_BUCKET, region } = config;
|
|
11
|
-
if (!bucket) {
|
|
12
|
-
throw new Error("S3 bucket is not defined");
|
|
13
|
-
}
|
|
14
|
-
if (!region) {
|
|
15
|
-
throw new Error("S3 region is not defined");
|
|
16
|
-
}
|
|
17
|
-
if (!config.accessKeyId) {
|
|
18
|
-
throw new Error("accessKeyId is required");
|
|
19
|
-
}
|
|
20
|
-
if (!config.secretAccessKey) {
|
|
21
|
-
throw new Error("secretAccessKey is required");
|
|
22
|
-
}
|
|
23
|
-
super({
|
|
24
|
-
bucket,
|
|
25
|
-
clientDirectUpload: config.clientDirectUpload,
|
|
26
|
-
expiration: config.expiration?.maxAge ? { maxAge: String(config.expiration.maxAge) } : void 0,
|
|
27
|
-
filename: config.filename,
|
|
28
|
-
logger: config.logger,
|
|
29
|
-
metaStorage: config.metaStorage,
|
|
30
|
-
metaStorageConfig: config.metaStorageConfig ? { ...config.metaStorageConfig, ...config } : { ...config },
|
|
31
|
-
partSize: config.partSize,
|
|
32
|
-
retryConfig: {
|
|
33
|
-
...config.retryConfig,
|
|
34
|
-
shouldRetry: (error) => {
|
|
35
|
-
const errorWithStatus = error;
|
|
36
|
-
if (errorWithStatus.statusCode && [408, 429, 500, 502, 503, 504].includes(errorWithStatus.statusCode)) {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
return errorWithStatus.retryable ?? false;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
this.s3Api = new AwsLightApiAdapter({
|
|
44
|
-
accessKeyId: config.accessKeyId,
|
|
45
|
-
bucket,
|
|
46
|
-
endpoint: config.endpoint,
|
|
47
|
-
region,
|
|
48
|
-
secretAccessKey: config.secretAccessKey,
|
|
49
|
-
service: config.service,
|
|
50
|
-
sessionToken: config.sessionToken
|
|
51
|
-
});
|
|
52
|
-
const { metaStorage, metaStorageConfig } = config;
|
|
53
|
-
if (!metaStorage) {
|
|
54
|
-
const metaConfig = { ...config, ...metaStorageConfig, logger: this.logger };
|
|
55
|
-
this.meta = new AwsLightMetaStorage(metaConfig);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Normalizes AWS S3 errors with S3-specific context.
|
|
60
|
-
*/
|
|
61
|
-
normalizeError(error) {
|
|
62
|
-
const awsError = error;
|
|
63
|
-
if (awsError.statusCode || awsError.code) {
|
|
64
|
-
return {
|
|
65
|
-
code: awsError.code || awsError.name,
|
|
66
|
-
message: awsError.message,
|
|
67
|
-
name: awsError.name,
|
|
68
|
-
statusCode: awsError.statusCode || 500
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
return super.normalizeError(error);
|
|
72
|
-
}
|
|
73
|
-
async update({ id }, metadata) {
|
|
74
|
-
if (this.config.clientDirectUpload) {
|
|
75
|
-
const file = await this.getMeta(id);
|
|
76
|
-
return this.buildPresigned({ ...file, ...metadata });
|
|
77
|
-
}
|
|
78
|
-
return super.update({ id }, metadata);
|
|
79
|
-
}
|
|
80
|
-
async getStream({ id }) {
|
|
81
|
-
return this.instrumentOperation("getStream", async () => {
|
|
82
|
-
const s3Api = this.getS3Api();
|
|
83
|
-
const { Body, ContentLength, ContentType, ETag, Expires, LastModified } = await this.retry(
|
|
84
|
-
() => s3Api.getObject({
|
|
85
|
-
Bucket: this.bucket,
|
|
86
|
-
Key: id
|
|
87
|
-
})
|
|
88
|
-
);
|
|
89
|
-
await this.checkIfExpired({ expiredAt: Expires });
|
|
90
|
-
const stream = Body instanceof ReadableStream ? Readable.fromWeb(Body) : Body;
|
|
91
|
-
const readableStream = new Readable({
|
|
92
|
-
read() {
|
|
93
|
-
stream.on("data", (chunk) => {
|
|
94
|
-
this.push(chunk);
|
|
95
|
-
});
|
|
96
|
-
stream.on("end", () => {
|
|
97
|
-
this.push(null);
|
|
98
|
-
});
|
|
99
|
-
stream.on("error", (error) => {
|
|
100
|
-
this.destroy(error);
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
return {
|
|
105
|
-
headers: {
|
|
106
|
-
"Content-Length": ContentLength?.toString() ?? "0",
|
|
107
|
-
"Content-Type": ContentType,
|
|
108
|
-
...ETag && { ETag },
|
|
109
|
-
...Expires && { "X-Upload-Expires": Expires.toString() },
|
|
110
|
-
...LastModified && { "Last-Modified": LastModified.toString() }
|
|
111
|
-
},
|
|
112
|
-
size: Number(ContentLength),
|
|
113
|
-
stream: readableStream
|
|
114
|
-
};
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
getS3Api() {
|
|
118
|
-
return this.s3Api;
|
|
119
|
-
}
|
|
120
|
-
// eslint-disable-next-line class-methods-use-this
|
|
121
|
-
getFileClass() {
|
|
122
|
-
return AwsLightFile;
|
|
123
|
-
}
|
|
124
|
-
// eslint-disable-next-line class-methods-use-this
|
|
125
|
-
getAcl() {
|
|
126
|
-
return void 0;
|
|
127
|
-
}
|
|
128
|
-
async accessCheck(_maxWaitTime = 30) {
|
|
129
|
-
await this.s3Api.checkBucketAccess({ Bucket: this.bucket });
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export { AwsLightStorage as default };
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { BlobServiceClient, StorageSharedKeyCredential } from '@azure/storage-blob';
|
|
2
|
-
import { throwErrorCode, ERRORS } from './ERRORS-D0apMqnc.js';
|
|
3
|
-
import MetaStorage from './MetaStorage-pECeFOad.js';
|
|
4
|
-
import { parseMetadata, stringifyMetadata } from './Metadata-DRLXeJ0F.js';
|
|
5
|
-
|
|
6
|
-
class AzureMetaStorage extends MetaStorage {
|
|
7
|
-
constructor(config) {
|
|
8
|
-
super(config);
|
|
9
|
-
this.config = config;
|
|
10
|
-
const { client, ...metaConfig } = config;
|
|
11
|
-
if (client === void 0) {
|
|
12
|
-
const connectionString = metaConfig.connectionString || process.env.AZURE_STORAGE_CONNECTION_STRING || void 0;
|
|
13
|
-
if (connectionString) {
|
|
14
|
-
this.client = BlobServiceClient.fromConnectionString(connectionString);
|
|
15
|
-
} else {
|
|
16
|
-
const accountKey = metaConfig.accountKey || process.env.AZURE_STORAGE_ACCOUNT_KEY || void 0;
|
|
17
|
-
const accountName = metaConfig.accountName || process.env.AZURE_STORAGE_ACCOUNT || void 0;
|
|
18
|
-
if (!metaConfig.accountKey) {
|
|
19
|
-
throw new Error("Missing required parameter: Azure blob storage account key.");
|
|
20
|
-
}
|
|
21
|
-
if (!metaConfig.accountName) {
|
|
22
|
-
throw new Error("Missing required parameter: Azure blob storage account name.");
|
|
23
|
-
}
|
|
24
|
-
const signedCredentials = new StorageSharedKeyCredential(accountName, accountKey);
|
|
25
|
-
this.client = new BlobServiceClient(config.endpoint ?? `https://${accountName}.blob.core.windows.net`, signedCredentials);
|
|
26
|
-
}
|
|
27
|
-
} else {
|
|
28
|
-
this.client = client;
|
|
29
|
-
}
|
|
30
|
-
const containerName = metaConfig.containerName || process.env.AZURE_STORAGE_CONTAINER || void 0;
|
|
31
|
-
if (!containerName) {
|
|
32
|
-
throw new Error("Missing required parameter: Azure container name.");
|
|
33
|
-
}
|
|
34
|
-
this.containerClient = this.client.getContainerClient(metaConfig.containerName);
|
|
35
|
-
}
|
|
36
|
-
config;
|
|
37
|
-
client;
|
|
38
|
-
containerClient;
|
|
39
|
-
async get(id) {
|
|
40
|
-
const appendBlobClient = this.containerClient.getAppendBlobClient(this.getMetaName(id));
|
|
41
|
-
let propertyData;
|
|
42
|
-
try {
|
|
43
|
-
propertyData = await appendBlobClient.getProperties();
|
|
44
|
-
} catch {
|
|
45
|
-
throw throwErrorCode(ERRORS.UNKNOWN_ERROR);
|
|
46
|
-
}
|
|
47
|
-
if (!propertyData.metadata) {
|
|
48
|
-
throw throwErrorCode(ERRORS.FILE_NOT_FOUND);
|
|
49
|
-
}
|
|
50
|
-
const file = propertyData.metadata;
|
|
51
|
-
if (file.metadata && typeof file.metadata === "string") {
|
|
52
|
-
file.metadata = parseMetadata(file.metadata);
|
|
53
|
-
}
|
|
54
|
-
return file;
|
|
55
|
-
}
|
|
56
|
-
async touch(id, file) {
|
|
57
|
-
return this.save(id, file);
|
|
58
|
-
}
|
|
59
|
-
async delete(id) {
|
|
60
|
-
const blobClient = this.containerClient.getBlockBlobClient(this.getMetaName(id));
|
|
61
|
-
await blobClient.deleteIfExists();
|
|
62
|
-
}
|
|
63
|
-
async save(id, file) {
|
|
64
|
-
const transformedMetadata = { ...file };
|
|
65
|
-
if (transformedMetadata.metadata) {
|
|
66
|
-
transformedMetadata.metadata = stringifyMetadata(file.metadata);
|
|
67
|
-
}
|
|
68
|
-
const appendBlobClient = this.containerClient.getAppendBlobClient(this.getMetaName(id));
|
|
69
|
-
await appendBlobClient.setMetadata(transformedMetadata, {});
|
|
70
|
-
return file;
|
|
71
|
-
}
|
|
72
|
-
async list() {
|
|
73
|
-
const blobs = [];
|
|
74
|
-
const iterator = this.containerClient.listBlobsFlat({
|
|
75
|
-
prefix: this.prefix
|
|
76
|
-
});
|
|
77
|
-
for await (const blob of iterator) {
|
|
78
|
-
blobs.push(blob);
|
|
79
|
-
}
|
|
80
|
-
return blobs.filter((blob) => blob.name.endsWith(this.suffix)).map((blob) => {
|
|
81
|
-
return {
|
|
82
|
-
createdAt: blob.properties.createdOn,
|
|
83
|
-
id: this.getIdFromMetaName(blob.name)
|
|
84
|
-
};
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export { AzureMetaStorage as default };
|