@pelatform/storage 1.0.2 → 1.0.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.
- package/dist/{chunk-ZTZZCC52.js → chunk-NNFNVWIN.js} +18 -8
- package/dist/{chunk-KJMGBTTL.js → chunk-VZDXZ6EA.js} +35 -23
- package/dist/cloudinary.d.ts +1 -1
- package/dist/cloudinary.js +10 -6
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/s3.d.ts +1 -1
- package/dist/s3.js +23 -20
- package/dist/{storage-interface-BKeDAlGP.d.ts → storage-interface-CoYx1E3B.d.ts} +7 -7
- package/package.json +16 -4
|
@@ -31,11 +31,15 @@ function getRequiredEnvVar(key) {
|
|
|
31
31
|
}
|
|
32
32
|
function getBooleanEnvVar(key, defaultValue = false) {
|
|
33
33
|
const value = getEnvVar(key);
|
|
34
|
-
if (!value)
|
|
34
|
+
if (!value) {
|
|
35
|
+
return defaultValue;
|
|
36
|
+
}
|
|
35
37
|
return value.toLowerCase() === "true" || value === "1";
|
|
36
38
|
}
|
|
37
39
|
function loadS3Config() {
|
|
38
|
-
const provider = getRequiredEnvVar(
|
|
40
|
+
const provider = getRequiredEnvVar(
|
|
41
|
+
ENV_VARS.PELATFORM_S3_PROVIDER
|
|
42
|
+
);
|
|
39
43
|
const validProviders = [
|
|
40
44
|
"aws",
|
|
41
45
|
"cloudflare-r2",
|
|
@@ -75,15 +79,15 @@ function loadStorageConfig() {
|
|
|
75
79
|
if (provider) {
|
|
76
80
|
if (provider === "cloudinary") {
|
|
77
81
|
return loadCloudinaryConfig();
|
|
78
|
-
} else {
|
|
79
|
-
return loadS3Config();
|
|
80
82
|
}
|
|
83
|
+
return loadS3Config();
|
|
81
84
|
}
|
|
82
85
|
const hasCloudinaryVars = getEnvVar(ENV_VARS.PELATFORM_CLOUDINARY_CLOUD_NAME) && getEnvVar(ENV_VARS.PELATFORM_CLOUDINARY_API_KEY) && getEnvVar(ENV_VARS.PELATFORM_CLOUDINARY_API_SECRET);
|
|
83
86
|
const hasS3Vars = getEnvVar(ENV_VARS.PELATFORM_S3_BUCKET) && getEnvVar(ENV_VARS.PELATFORM_S3_ACCESS_KEY_ID) && getEnvVar(ENV_VARS.PELATFORM_S3_SECRET_ACCESS_KEY);
|
|
84
87
|
if (hasCloudinaryVars) {
|
|
85
88
|
return loadCloudinaryConfig();
|
|
86
|
-
}
|
|
89
|
+
}
|
|
90
|
+
if (hasS3Vars) {
|
|
87
91
|
const config = loadS3Config();
|
|
88
92
|
if (!config.provider) {
|
|
89
93
|
config.provider = "aws";
|
|
@@ -107,11 +111,17 @@ function isStorageConfigured() {
|
|
|
107
111
|
}
|
|
108
112
|
function getStorageProvider() {
|
|
109
113
|
const provider = getEnvVar(ENV_VARS.PELATFORM_S3_PROVIDER);
|
|
110
|
-
if (provider)
|
|
114
|
+
if (provider) {
|
|
115
|
+
return provider;
|
|
116
|
+
}
|
|
111
117
|
const hasCloudinaryVars = getEnvVar(ENV_VARS.PELATFORM_CLOUDINARY_CLOUD_NAME);
|
|
112
118
|
const hasS3Vars = getEnvVar(ENV_VARS.PELATFORM_S3_BUCKET);
|
|
113
|
-
if (hasCloudinaryVars)
|
|
114
|
-
|
|
119
|
+
if (hasCloudinaryVars) {
|
|
120
|
+
return "cloudinary";
|
|
121
|
+
}
|
|
122
|
+
if (hasS3Vars) {
|
|
123
|
+
return "aws";
|
|
124
|
+
}
|
|
115
125
|
return void 0;
|
|
116
126
|
}
|
|
117
127
|
function validateS3EnvVars() {
|
|
@@ -26,13 +26,13 @@ function validateFileType(fileName, allowedTypes) {
|
|
|
26
26
|
const extension = fileName.split(".").pop()?.toLowerCase();
|
|
27
27
|
const isValidMime = allowedTypes.some((type) => {
|
|
28
28
|
if (type.includes("*")) {
|
|
29
|
-
const baseType = type.split("/")[0];
|
|
29
|
+
const baseType = type.split("/")[0] ?? "";
|
|
30
30
|
return mimeType.startsWith(baseType);
|
|
31
31
|
}
|
|
32
32
|
return mimeType === type;
|
|
33
33
|
});
|
|
34
34
|
const isValidExtension = extension && allowedTypes.includes(`.${extension}`);
|
|
35
|
-
if (!isValidMime
|
|
35
|
+
if (!(isValidMime || isValidExtension)) {
|
|
36
36
|
return {
|
|
37
37
|
valid: false,
|
|
38
38
|
error: `File type not allowed. Allowed types: ${allowedTypes.join(", ")}`
|
|
@@ -41,11 +41,13 @@ function validateFileType(fileName, allowedTypes) {
|
|
|
41
41
|
return { valid: true };
|
|
42
42
|
}
|
|
43
43
|
function formatFileSize(bytes) {
|
|
44
|
-
if (bytes === 0)
|
|
44
|
+
if (bytes === 0) {
|
|
45
|
+
return "0 Bytes";
|
|
46
|
+
}
|
|
45
47
|
const k = 1024;
|
|
46
48
|
const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
|
|
47
49
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
48
|
-
return `${parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;
|
|
50
|
+
return `${Number.parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;
|
|
49
51
|
}
|
|
50
52
|
function sanitizeFileName(fileName) {
|
|
51
53
|
return fileName.replace(/[^a-zA-Z0-9.-]/g, "_").replace(/_{2,}/g, "_").replace(/^_|_$/g, "").toLowerCase();
|
|
@@ -68,11 +70,10 @@ function parseS3Url(url) {
|
|
|
68
70
|
bucket: pathParts2[0],
|
|
69
71
|
key: pathParts2.slice(1).join("/")
|
|
70
72
|
};
|
|
71
|
-
} else {
|
|
72
|
-
const bucket = urlObj.hostname.split(".")[0];
|
|
73
|
-
const key = urlObj.pathname.substring(1);
|
|
74
|
-
return { bucket, key };
|
|
75
73
|
}
|
|
74
|
+
const bucket = urlObj.hostname.split(".")[0];
|
|
75
|
+
const key = urlObj.pathname.substring(1);
|
|
76
|
+
return { bucket, key };
|
|
76
77
|
}
|
|
77
78
|
const pathParts = urlObj.pathname.split("/").filter(Boolean);
|
|
78
79
|
return {
|
|
@@ -138,19 +139,18 @@ function extractS3Info(url) {
|
|
|
138
139
|
if (urlObj.hostname.includes("amazonaws.com")) {
|
|
139
140
|
if (urlObj.hostname.startsWith("s3")) {
|
|
140
141
|
const pathParts2 = urlObj.pathname.split("/").filter(Boolean);
|
|
141
|
-
const
|
|
142
|
+
const region2 = urlObj.hostname.split(".")[1];
|
|
142
143
|
return {
|
|
143
144
|
bucket: pathParts2[0],
|
|
144
145
|
key: pathParts2.slice(1).join("/"),
|
|
145
|
-
region
|
|
146
|
+
region: region2
|
|
146
147
|
};
|
|
147
|
-
} else {
|
|
148
|
-
const hostParts = urlObj.hostname.split(".");
|
|
149
|
-
const bucket = hostParts[0];
|
|
150
|
-
const region = hostParts[2];
|
|
151
|
-
const key = urlObj.pathname.substring(1);
|
|
152
|
-
return { bucket, key, region };
|
|
153
148
|
}
|
|
149
|
+
const hostParts = urlObj.hostname.split(".");
|
|
150
|
+
const bucket = hostParts[0];
|
|
151
|
+
const region = hostParts[2];
|
|
152
|
+
const key = urlObj.pathname.substring(1);
|
|
153
|
+
return { bucket, key, region };
|
|
154
154
|
}
|
|
155
155
|
const pathParts = urlObj.pathname.split("/").filter(Boolean);
|
|
156
156
|
return {
|
|
@@ -273,7 +273,7 @@ function getFileName(key) {
|
|
|
273
273
|
return lastSlashIndex === -1 ? normalizedKey : normalizedKey.substring(lastSlashIndex + 1);
|
|
274
274
|
}
|
|
275
275
|
function base64ToBuffer(base64) {
|
|
276
|
-
const cleanBase64 = base64.includes(",") ? base64.split(",")[1] : base64;
|
|
276
|
+
const cleanBase64 = base64.includes(",") ? base64.split(",")[1] ?? "" : base64;
|
|
277
277
|
return Buffer.from(cleanBase64, "base64");
|
|
278
278
|
}
|
|
279
279
|
function bufferToBase64(buffer, includeDataUrl = false, mimeType) {
|
|
@@ -301,7 +301,9 @@ function validateBatchFiles(files, options) {
|
|
|
301
301
|
return files.map((file) => ({
|
|
302
302
|
valid: false,
|
|
303
303
|
fileName: file.name,
|
|
304
|
-
errors: [
|
|
304
|
+
errors: [
|
|
305
|
+
`Maximum ${options.maxFiles} files allowed, but ${files.length} files provided`
|
|
306
|
+
]
|
|
305
307
|
}));
|
|
306
308
|
}
|
|
307
309
|
for (const file of files) {
|
|
@@ -347,25 +349,35 @@ function detectFileTypeFromContent(buffer) {
|
|
|
347
349
|
return "image/webp";
|
|
348
350
|
}
|
|
349
351
|
if (header[0] === 80 && header[1] === 75 && (header[2] === 3 || header[2] === 5)) {
|
|
350
|
-
const zipContent = buffer.toString(
|
|
351
|
-
|
|
352
|
+
const zipContent = buffer.toString(
|
|
353
|
+
"utf8",
|
|
354
|
+
0,
|
|
355
|
+
Math.min(buffer.length, 1e3)
|
|
356
|
+
);
|
|
357
|
+
if (zipContent.includes("word/")) {
|
|
352
358
|
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
|
353
|
-
|
|
359
|
+
}
|
|
360
|
+
if (zipContent.includes("xl/")) {
|
|
354
361
|
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
355
|
-
|
|
362
|
+
}
|
|
363
|
+
if (zipContent.includes("ppt/")) {
|
|
356
364
|
return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
|
365
|
+
}
|
|
357
366
|
return "application/zip";
|
|
358
367
|
}
|
|
359
368
|
if (header.subarray(4, 8).toString() === "ftyp") {
|
|
360
369
|
return "video/mp4";
|
|
361
370
|
}
|
|
362
|
-
if (header[0] === 255 && (header[1] & 224) === 224 || header.subarray(0, 3).toString() === "ID3") {
|
|
371
|
+
if (header[0] !== void 0 && header[1] !== void 0 && header[0] === 255 && (header[1] & 224) === 224 || header.subarray(0, 3).toString() === "ID3") {
|
|
363
372
|
return "audio/mpeg";
|
|
364
373
|
}
|
|
365
374
|
let isText = true;
|
|
366
375
|
const sampleSize = Math.min(buffer.length, 512);
|
|
367
376
|
for (let i = 0; i < sampleSize; i++) {
|
|
368
377
|
const byte = buffer[i];
|
|
378
|
+
if (byte === void 0) {
|
|
379
|
+
continue;
|
|
380
|
+
}
|
|
369
381
|
if (byte === 0 || byte < 32 && byte !== 9 && byte !== 10 && byte !== 13) {
|
|
370
382
|
isText = false;
|
|
371
383
|
break;
|
package/dist/cloudinary.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as StorageInterface, C as CloudinaryConfig, U as UploadOptions, a as UploadResult, D as DownloadOptions, b as DownloadResult, c as DeleteOptions, d as DeleteResult, B as BatchDeleteOptions, e as BatchDeleteResult, L as ListOptions, f as ListResult, E as ExistsResult, g as CopyOptions, h as CopyResult, M as MoveOptions, i as MoveResult, j as DuplicateOptions, k as DuplicateResult, P as PresignedUrlOptions, l as PresignedUrlResult, m as CreateFolderOptions, n as CreateFolderResult, o as DeleteFolderOptions, p as DeleteFolderResult, q as ListFoldersOptions, r as ListFoldersResult, F as FolderExistsResult, R as RenameFolderOptions, s as RenameFolderResult, t as CopyFolderOptions, u as CopyFolderResult } from './storage-interface-
|
|
1
|
+
import { S as StorageInterface, C as CloudinaryConfig, U as UploadOptions, a as UploadResult, D as DownloadOptions, b as DownloadResult, c as DeleteOptions, d as DeleteResult, B as BatchDeleteOptions, e as BatchDeleteResult, L as ListOptions, f as ListResult, E as ExistsResult, g as CopyOptions, h as CopyResult, M as MoveOptions, i as MoveResult, j as DuplicateOptions, k as DuplicateResult, P as PresignedUrlOptions, l as PresignedUrlResult, m as CreateFolderOptions, n as CreateFolderResult, o as DeleteFolderOptions, p as DeleteFolderResult, q as ListFoldersOptions, r as ListFoldersResult, F as FolderExistsResult, R as RenameFolderOptions, s as RenameFolderResult, t as CopyFolderOptions, u as CopyFolderResult } from './storage-interface-CoYx1E3B.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Cloudinary storage service implementation
|
package/dist/cloudinary.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadCloudinaryConfig
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NNFNVWIN.js";
|
|
4
4
|
|
|
5
5
|
// src/providers/cloudinary.ts
|
|
6
6
|
import { v2 as cloudinary } from "cloudinary";
|
|
@@ -30,11 +30,13 @@ var CloudinaryProvider = class {
|
|
|
30
30
|
} else if (options.contentType?.startsWith("video/")) {
|
|
31
31
|
resourceType = "video";
|
|
32
32
|
}
|
|
33
|
-
const keyParts = options.key.split("/");
|
|
33
|
+
const keyParts = options.key.split("/").filter(Boolean);
|
|
34
34
|
let folder = "";
|
|
35
35
|
let publicId = options.key;
|
|
36
36
|
if (keyParts.length > 1) {
|
|
37
37
|
folder = keyParts.slice(0, -1).join("/");
|
|
38
|
+
}
|
|
39
|
+
if (keyParts.length > 0) {
|
|
38
40
|
publicId = keyParts[keyParts.length - 1];
|
|
39
41
|
}
|
|
40
42
|
const uploadOptions = {
|
|
@@ -294,10 +296,12 @@ var CloudinaryProvider = class {
|
|
|
294
296
|
async listFolders(_options) {
|
|
295
297
|
try {
|
|
296
298
|
const result = await cloudinary.api.root_folders();
|
|
297
|
-
const folders = (result.folders || []).map(
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
299
|
+
const folders = (result.folders || []).map(
|
|
300
|
+
(folder) => ({
|
|
301
|
+
name: folder.name,
|
|
302
|
+
path: folder.path
|
|
303
|
+
})
|
|
304
|
+
);
|
|
301
305
|
return {
|
|
302
306
|
success: true,
|
|
303
307
|
folders,
|
package/dist/helpers.d.ts
CHANGED
|
@@ -420,7 +420,7 @@ declare function validateBucketName(bucketName: string): {
|
|
|
420
420
|
* // Returns: 'attachment; filename="filename.txt"'
|
|
421
421
|
* ```
|
|
422
422
|
*/
|
|
423
|
-
declare function getContentDisposition(fileName: string, disposition?:
|
|
423
|
+
declare function getContentDisposition(fileName: string, disposition?: "inline" | "attachment"): string;
|
|
424
424
|
/**
|
|
425
425
|
* Check if file is an image based on MIME type
|
|
426
426
|
* @param fileName File name or path
|
|
@@ -659,7 +659,7 @@ declare function bufferToBase64(buffer: Buffer, includeDataUrl?: boolean, mimeTy
|
|
|
659
659
|
* }
|
|
660
660
|
* ```
|
|
661
661
|
*/
|
|
662
|
-
declare function generateFileHash(content: Buffer | string, algorithm?:
|
|
662
|
+
declare function generateFileHash(content: Buffer | string, algorithm?: "md5" | "sha1" | "sha256"): Promise<string>;
|
|
663
663
|
/**
|
|
664
664
|
* Generate multiple unique keys at once for batch operations
|
|
665
665
|
* @param fileNames Array of file names
|
package/dist/helpers.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { v as S3Config, C as CloudinaryConfig, w as StorageConfig } from './storage-interface-
|
|
2
|
-
export { B as BatchDeleteOptions, e as BatchDeleteResult, t as CopyFolderOptions, u as CopyFolderResult, g as CopyOptions, h as CopyResult, m as CreateFolderOptions, n as CreateFolderResult, o as DeleteFolderOptions, p as DeleteFolderResult, c as DeleteOptions, d as DeleteResult, D as DownloadOptions, b as DownloadResult, j as DuplicateOptions, k as DuplicateResult, E as ExistsResult, z as FileInfo, F as FolderExistsResult, A as FolderInfo, q as ListFoldersOptions, r as ListFoldersResult, L as ListOptions, f as ListResult, M as MoveOptions, i as MoveResult, P as PresignedUrlOptions, l as PresignedUrlResult, R as RenameFolderOptions, s as RenameFolderResult, x as S3ProviderType, S as StorageInterface, y as StorageProvider, U as UploadOptions, a as UploadResult } from './storage-interface-
|
|
1
|
+
import { v as S3Config, C as CloudinaryConfig, w as StorageConfig } from './storage-interface-CoYx1E3B.js';
|
|
2
|
+
export { B as BatchDeleteOptions, e as BatchDeleteResult, t as CopyFolderOptions, u as CopyFolderResult, g as CopyOptions, h as CopyResult, m as CreateFolderOptions, n as CreateFolderResult, o as DeleteFolderOptions, p as DeleteFolderResult, c as DeleteOptions, d as DeleteResult, D as DownloadOptions, b as DownloadResult, j as DuplicateOptions, k as DuplicateResult, E as ExistsResult, z as FileInfo, F as FolderExistsResult, A as FolderInfo, q as ListFoldersOptions, r as ListFoldersResult, L as ListOptions, f as ListResult, M as MoveOptions, i as MoveResult, P as PresignedUrlOptions, l as PresignedUrlResult, R as RenameFolderOptions, s as RenameFolderResult, x as S3ProviderType, S as StorageInterface, y as StorageProvider, U as UploadOptions, a as UploadResult } from './storage-interface-CoYx1E3B.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Storage configuration from environment variables
|
package/dist/index.js
CHANGED
package/dist/s3.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as StorageInterface, v as S3Config, U as UploadOptions, a as UploadResult, D as DownloadOptions, b as DownloadResult, c as DeleteOptions, d as DeleteResult, B as BatchDeleteOptions, e as BatchDeleteResult, L as ListOptions, f as ListResult, E as ExistsResult, g as CopyOptions, h as CopyResult, M as MoveOptions, i as MoveResult, j as DuplicateOptions, k as DuplicateResult, P as PresignedUrlOptions, l as PresignedUrlResult, m as CreateFolderOptions, n as CreateFolderResult, o as DeleteFolderOptions, p as DeleteFolderResult, q as ListFoldersOptions, r as ListFoldersResult, F as FolderExistsResult, R as RenameFolderOptions, s as RenameFolderResult, t as CopyFolderOptions, u as CopyFolderResult } from './storage-interface-
|
|
1
|
+
import { S as StorageInterface, v as S3Config, U as UploadOptions, a as UploadResult, D as DownloadOptions, b as DownloadResult, c as DeleteOptions, d as DeleteResult, B as BatchDeleteOptions, e as BatchDeleteResult, L as ListOptions, f as ListResult, E as ExistsResult, g as CopyOptions, h as CopyResult, M as MoveOptions, i as MoveResult, j as DuplicateOptions, k as DuplicateResult, P as PresignedUrlOptions, l as PresignedUrlResult, m as CreateFolderOptions, n as CreateFolderResult, o as DeleteFolderOptions, p as DeleteFolderResult, q as ListFoldersOptions, r as ListFoldersResult, F as FolderExistsResult, R as RenameFolderOptions, s as RenameFolderResult, t as CopyFolderOptions, u as CopyFolderResult } from './storage-interface-CoYx1E3B.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* S3 storage service implementation
|
package/dist/s3.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildPublicUrl,
|
|
3
3
|
getMimeType
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-VZDXZ6EA.js";
|
|
5
5
|
import {
|
|
6
6
|
loadS3Config
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NNFNVWIN.js";
|
|
8
8
|
|
|
9
9
|
// src/providers/s3.ts
|
|
10
10
|
import { S3Client } from "@aws-sdk/client-s3";
|
|
@@ -74,7 +74,9 @@ var FileOperations = class {
|
|
|
74
74
|
const reader = result.Body.transformToWebStream().getReader();
|
|
75
75
|
while (true) {
|
|
76
76
|
const { done, value } = await reader.read();
|
|
77
|
-
if (done)
|
|
77
|
+
if (done) {
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
78
80
|
chunks.push(value);
|
|
79
81
|
}
|
|
80
82
|
const data = Buffer.concat(chunks);
|
|
@@ -124,7 +126,9 @@ var FileOperations = class {
|
|
|
124
126
|
}
|
|
125
127
|
});
|
|
126
128
|
const result = await this.client.send(command);
|
|
127
|
-
const deleted = result.Deleted?.map((obj) => obj.Key).filter(
|
|
129
|
+
const deleted = result.Deleted?.map((obj) => obj.Key).filter(
|
|
130
|
+
Boolean
|
|
131
|
+
);
|
|
128
132
|
const errors = result.Errors?.map((err) => ({
|
|
129
133
|
key: err.Key || "",
|
|
130
134
|
error: err.Message || "Unknown error"
|
|
@@ -349,33 +353,32 @@ var FolderOperations = class {
|
|
|
349
353
|
deletedFiles: []
|
|
350
354
|
};
|
|
351
355
|
}
|
|
352
|
-
const
|
|
356
|
+
const deleteCommand2 = new DeleteObjectsCommand2({
|
|
353
357
|
Bucket: this.config.bucket,
|
|
354
358
|
Delete: {
|
|
355
359
|
Objects: listResult.Contents.map((obj) => ({ Key: obj.Key })),
|
|
356
360
|
Quiet: false
|
|
357
361
|
}
|
|
358
362
|
});
|
|
359
|
-
const deleteResult = await this.client.send(
|
|
363
|
+
const deleteResult = await this.client.send(deleteCommand2);
|
|
360
364
|
const deletedFiles = deleteResult.Deleted?.map((obj) => obj.Key).filter(Boolean) || [];
|
|
361
365
|
return {
|
|
362
366
|
success: true,
|
|
363
367
|
deletedFiles
|
|
364
368
|
};
|
|
365
|
-
} else {
|
|
366
|
-
const deleteCommand = new DeleteObjectsCommand2({
|
|
367
|
-
Bucket: this.config.bucket,
|
|
368
|
-
Delete: {
|
|
369
|
-
Objects: [{ Key: folderPath }],
|
|
370
|
-
Quiet: false
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
await this.client.send(deleteCommand);
|
|
374
|
-
return {
|
|
375
|
-
success: true,
|
|
376
|
-
deletedFiles: [folderPath]
|
|
377
|
-
};
|
|
378
369
|
}
|
|
370
|
+
const deleteCommand = new DeleteObjectsCommand2({
|
|
371
|
+
Bucket: this.config.bucket,
|
|
372
|
+
Delete: {
|
|
373
|
+
Objects: [{ Key: folderPath }],
|
|
374
|
+
Quiet: false
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
await this.client.send(deleteCommand);
|
|
378
|
+
return {
|
|
379
|
+
success: true,
|
|
380
|
+
deletedFiles: [folderPath]
|
|
381
|
+
};
|
|
379
382
|
} catch (error) {
|
|
380
383
|
return {
|
|
381
384
|
success: false,
|
|
@@ -559,7 +562,7 @@ var S3Provider = class {
|
|
|
559
562
|
secretAccessKey: config.secretAccessKey
|
|
560
563
|
},
|
|
561
564
|
endpoint: config.endpoint,
|
|
562
|
-
forcePathStyle: config.forcePathStyle
|
|
565
|
+
forcePathStyle: config.forcePathStyle
|
|
563
566
|
});
|
|
564
567
|
this.fileOps = new FileOperations(this.client, this.config);
|
|
565
568
|
this.folderOps = new FolderOperations(this.client, this.config);
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
* S3-compatible provider types
|
|
7
7
|
* @public
|
|
8
8
|
*/
|
|
9
|
-
type S3ProviderType =
|
|
9
|
+
type S3ProviderType = "aws" | "cloudflare-r2" | "minio" | "digitalocean" | "supabase" | "custom";
|
|
10
10
|
/**
|
|
11
11
|
* All supported storage provider types
|
|
12
12
|
* @public
|
|
13
13
|
*/
|
|
14
|
-
type StorageProvider = S3ProviderType |
|
|
14
|
+
type StorageProvider = S3ProviderType | "cloudinary";
|
|
15
15
|
/**
|
|
16
16
|
* Union type for all storage configurations
|
|
17
17
|
* @public
|
|
@@ -45,7 +45,7 @@ interface S3Config {
|
|
|
45
45
|
*/
|
|
46
46
|
interface CloudinaryConfig {
|
|
47
47
|
/** Provider type (always 'cloudinary') */
|
|
48
|
-
provider:
|
|
48
|
+
provider: "cloudinary";
|
|
49
49
|
/** Cloudinary cloud name */
|
|
50
50
|
cloudName: string;
|
|
51
51
|
/** Cloudinary API key */
|
|
@@ -104,7 +104,7 @@ interface UploadOptions {
|
|
|
104
104
|
metadata?: Record<string, string>;
|
|
105
105
|
cacheControl?: string;
|
|
106
106
|
contentDisposition?: string;
|
|
107
|
-
acl?:
|
|
107
|
+
acl?: "private" | "public-read" | "public-read-write";
|
|
108
108
|
expires?: Date;
|
|
109
109
|
}
|
|
110
110
|
interface UploadResult {
|
|
@@ -153,7 +153,7 @@ interface CopyOptions {
|
|
|
153
153
|
sourceKey: string;
|
|
154
154
|
destinationKey: string;
|
|
155
155
|
metadata?: Record<string, string>;
|
|
156
|
-
metadataDirective?:
|
|
156
|
+
metadataDirective?: "COPY" | "REPLACE";
|
|
157
157
|
}
|
|
158
158
|
interface CopyResult {
|
|
159
159
|
success: boolean;
|
|
@@ -164,7 +164,7 @@ interface MoveOptions {
|
|
|
164
164
|
sourceKey: string;
|
|
165
165
|
destinationKey: string;
|
|
166
166
|
metadata?: Record<string, string>;
|
|
167
|
-
metadataDirective?:
|
|
167
|
+
metadataDirective?: "COPY" | "REPLACE";
|
|
168
168
|
}
|
|
169
169
|
interface MoveResult {
|
|
170
170
|
success: boolean;
|
|
@@ -194,7 +194,7 @@ interface ListResult {
|
|
|
194
194
|
}
|
|
195
195
|
interface PresignedUrlOptions {
|
|
196
196
|
key: string;
|
|
197
|
-
operation:
|
|
197
|
+
operation: "get" | "put";
|
|
198
198
|
expiresIn?: number;
|
|
199
199
|
contentType?: string;
|
|
200
200
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pelatform/storage",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Storage utilities for SaaS applications.",
|
|
5
|
-
"author": "Pelatform
|
|
5
|
+
"author": "Pelatform",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "./dist/index.js",
|
|
@@ -33,6 +33,11 @@
|
|
|
33
33
|
"build": "tsup",
|
|
34
34
|
"types:check": "tsc --noEmit"
|
|
35
35
|
},
|
|
36
|
+
"repository": "github:devpelatform/toolkits",
|
|
37
|
+
"homepage": "https://github.com/devpelatform/toolkits",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/devpelatform/toolkits/issues"
|
|
40
|
+
},
|
|
36
41
|
"files": [
|
|
37
42
|
"dist"
|
|
38
43
|
],
|
|
@@ -49,8 +54,9 @@
|
|
|
49
54
|
"mime-types": "^3.0.2"
|
|
50
55
|
},
|
|
51
56
|
"devDependencies": {
|
|
52
|
-
"@aws-sdk/client-s3": "^3.
|
|
53
|
-
"@aws-sdk/s3-request-presigner": "^3.
|
|
57
|
+
"@aws-sdk/client-s3": "^3.943.0",
|
|
58
|
+
"@aws-sdk/s3-request-presigner": "^3.943.0",
|
|
59
|
+
"@pelatform/tsconfig": "0.1.0",
|
|
54
60
|
"@types/mime-types": "^3.0.1",
|
|
55
61
|
"@types/node": "^24.10.1",
|
|
56
62
|
"cloudinary": "^2.8.0",
|
|
@@ -74,6 +80,12 @@
|
|
|
74
80
|
}
|
|
75
81
|
},
|
|
76
82
|
"publishConfig": {
|
|
83
|
+
"registry": "https://registry.npmjs.org/",
|
|
77
84
|
"access": "public"
|
|
85
|
+
},
|
|
86
|
+
"lint-staged": {
|
|
87
|
+
"*.{js,jsx,ts,tsx,cjs,mjs,cts,mts}": "biome check --write --no-errors-on-unmatched",
|
|
88
|
+
"*.{md,yml,yaml}": "prettier --write",
|
|
89
|
+
"*.{json,jsonc,html}": "biome format --write --no-errors-on-unmatched"
|
|
78
90
|
}
|
|
79
91
|
}
|