@fluxmedia/s3 1.0.2 → 2.0.1
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/index.cjs +62 -10
- package/dist/index.js +62 -10
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -113,7 +113,9 @@ var S3Provider = class {
|
|
|
113
113
|
secretAccessKey: this.config.secretAccessKey
|
|
114
114
|
},
|
|
115
115
|
...this.config.endpoint && { endpoint: this.config.endpoint },
|
|
116
|
-
...this.config.forcePathStyle !== void 0 && {
|
|
116
|
+
...this.config.forcePathStyle !== void 0 && {
|
|
117
|
+
forcePathStyle: this.config.forcePathStyle
|
|
118
|
+
}
|
|
117
119
|
});
|
|
118
120
|
this.client = client;
|
|
119
121
|
return client;
|
|
@@ -123,7 +125,12 @@ var S3Provider = class {
|
|
|
123
125
|
const Upload = await getUploadClass();
|
|
124
126
|
try {
|
|
125
127
|
const key = this.generateKey(options);
|
|
126
|
-
const
|
|
128
|
+
const isStream = this.isStreamInput(file);
|
|
129
|
+
const { contentType, extension } = isStream ? {
|
|
130
|
+
contentType: options?.contentType ?? "application/octet-stream",
|
|
131
|
+
extension: options?.contentType ? this.extensionFromMime(options.contentType) : ""
|
|
132
|
+
} : await this.getContentType(file);
|
|
133
|
+
const hasRetryConfig = !!options?.metadata?._retry;
|
|
127
134
|
const upload = new Upload({
|
|
128
135
|
client,
|
|
129
136
|
params: {
|
|
@@ -141,20 +148,29 @@ var S3Provider = class {
|
|
|
141
148
|
// Upload 4 parts in parallel
|
|
142
149
|
partSize: 5 * 1024 * 1024,
|
|
143
150
|
// 5MB per part (S3 minimum)
|
|
144
|
-
leavePartsOnError:
|
|
145
|
-
//
|
|
151
|
+
leavePartsOnError: hasRetryConfig,
|
|
152
|
+
// Keep parts for resume when retry is configured
|
|
153
|
+
...options?.signal && { abortController: new AbortController() }
|
|
146
154
|
});
|
|
147
|
-
if (options?.onProgress) {
|
|
155
|
+
if (options?.onProgress || options?.onByteProgress) {
|
|
148
156
|
upload.on("httpUploadProgress", (progress) => {
|
|
149
|
-
if (
|
|
157
|
+
if (options?.onByteProgress) {
|
|
158
|
+
options.onByteProgress(progress.loaded ?? 0, progress.total);
|
|
159
|
+
}
|
|
160
|
+
if (options?.onProgress && progress.total) {
|
|
150
161
|
const percentComplete = progress.loaded / progress.total * 100;
|
|
151
162
|
options.onProgress(percentComplete);
|
|
152
163
|
}
|
|
153
164
|
});
|
|
154
165
|
}
|
|
155
166
|
await upload.done();
|
|
156
|
-
const size = file instanceof Buffer ? file.byteLength : file.size;
|
|
157
|
-
return this.createResult(
|
|
167
|
+
const size = file instanceof Buffer ? file.byteLength : typeof File !== "undefined" && file instanceof File ? file.size : 0;
|
|
168
|
+
return this.createResult(
|
|
169
|
+
key,
|
|
170
|
+
size,
|
|
171
|
+
extension,
|
|
172
|
+
options?.metadata
|
|
173
|
+
);
|
|
158
174
|
} catch (error) {
|
|
159
175
|
throw this.mapS3Error(error, core.MediaErrorCode.UPLOAD_FAILED);
|
|
160
176
|
}
|
|
@@ -291,13 +307,49 @@ var S3Provider = class {
|
|
|
291
307
|
async getContentType(file) {
|
|
292
308
|
if (file instanceof Buffer) {
|
|
293
309
|
const detected = await core.getFileType(file);
|
|
294
|
-
return {
|
|
310
|
+
return {
|
|
311
|
+
contentType: detected?.mime ?? "application/octet-stream",
|
|
312
|
+
extension: detected?.ext ?? ""
|
|
313
|
+
};
|
|
295
314
|
}
|
|
296
|
-
return {
|
|
315
|
+
return {
|
|
316
|
+
contentType: file.type || "application/octet-stream",
|
|
317
|
+
extension: file.name.split(".").pop() || ""
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Check whether the given input is a stream (Node.js Readable or Web ReadableStream).
|
|
322
|
+
*/
|
|
323
|
+
isStreamInput(file) {
|
|
324
|
+
if (file instanceof Buffer) return false;
|
|
325
|
+
if (typeof File !== "undefined" && file instanceof File) return false;
|
|
326
|
+
return typeof file.pipe === "function" || typeof file.getReader === "function";
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Derive a file extension from a MIME type string.
|
|
330
|
+
*/
|
|
331
|
+
extensionFromMime(mime) {
|
|
332
|
+
const map = {
|
|
333
|
+
"image/jpeg": "jpg",
|
|
334
|
+
"image/png": "png",
|
|
335
|
+
"image/gif": "gif",
|
|
336
|
+
"image/webp": "webp",
|
|
337
|
+
"image/avif": "avif",
|
|
338
|
+
"image/svg+xml": "svg",
|
|
339
|
+
"video/mp4": "mp4",
|
|
340
|
+
"video/webm": "webm",
|
|
341
|
+
"video/quicktime": "mov",
|
|
342
|
+
"audio/mpeg": "mp3",
|
|
343
|
+
"audio/wav": "wav",
|
|
344
|
+
"application/pdf": "pdf",
|
|
345
|
+
"application/octet-stream": ""
|
|
346
|
+
};
|
|
347
|
+
return map[mime] ?? mime.split("/").pop() ?? "";
|
|
297
348
|
}
|
|
298
349
|
createResult(key, size, extension, metadata) {
|
|
299
350
|
return {
|
|
300
351
|
id: key,
|
|
352
|
+
storageKey: key,
|
|
301
353
|
url: this.getUrl(key),
|
|
302
354
|
publicUrl: this.getUrl(key),
|
|
303
355
|
size,
|
package/dist/index.js
CHANGED
|
@@ -111,7 +111,9 @@ var S3Provider = class {
|
|
|
111
111
|
secretAccessKey: this.config.secretAccessKey
|
|
112
112
|
},
|
|
113
113
|
...this.config.endpoint && { endpoint: this.config.endpoint },
|
|
114
|
-
...this.config.forcePathStyle !== void 0 && {
|
|
114
|
+
...this.config.forcePathStyle !== void 0 && {
|
|
115
|
+
forcePathStyle: this.config.forcePathStyle
|
|
116
|
+
}
|
|
115
117
|
});
|
|
116
118
|
this.client = client;
|
|
117
119
|
return client;
|
|
@@ -121,7 +123,12 @@ var S3Provider = class {
|
|
|
121
123
|
const Upload = await getUploadClass();
|
|
122
124
|
try {
|
|
123
125
|
const key = this.generateKey(options);
|
|
124
|
-
const
|
|
126
|
+
const isStream = this.isStreamInput(file);
|
|
127
|
+
const { contentType, extension } = isStream ? {
|
|
128
|
+
contentType: options?.contentType ?? "application/octet-stream",
|
|
129
|
+
extension: options?.contentType ? this.extensionFromMime(options.contentType) : ""
|
|
130
|
+
} : await this.getContentType(file);
|
|
131
|
+
const hasRetryConfig = !!options?.metadata?._retry;
|
|
125
132
|
const upload = new Upload({
|
|
126
133
|
client,
|
|
127
134
|
params: {
|
|
@@ -139,20 +146,29 @@ var S3Provider = class {
|
|
|
139
146
|
// Upload 4 parts in parallel
|
|
140
147
|
partSize: 5 * 1024 * 1024,
|
|
141
148
|
// 5MB per part (S3 minimum)
|
|
142
|
-
leavePartsOnError:
|
|
143
|
-
//
|
|
149
|
+
leavePartsOnError: hasRetryConfig,
|
|
150
|
+
// Keep parts for resume when retry is configured
|
|
151
|
+
...options?.signal && { abortController: new AbortController() }
|
|
144
152
|
});
|
|
145
|
-
if (options?.onProgress) {
|
|
153
|
+
if (options?.onProgress || options?.onByteProgress) {
|
|
146
154
|
upload.on("httpUploadProgress", (progress) => {
|
|
147
|
-
if (
|
|
155
|
+
if (options?.onByteProgress) {
|
|
156
|
+
options.onByteProgress(progress.loaded ?? 0, progress.total);
|
|
157
|
+
}
|
|
158
|
+
if (options?.onProgress && progress.total) {
|
|
148
159
|
const percentComplete = progress.loaded / progress.total * 100;
|
|
149
160
|
options.onProgress(percentComplete);
|
|
150
161
|
}
|
|
151
162
|
});
|
|
152
163
|
}
|
|
153
164
|
await upload.done();
|
|
154
|
-
const size = file instanceof Buffer ? file.byteLength : file.size;
|
|
155
|
-
return this.createResult(
|
|
165
|
+
const size = file instanceof Buffer ? file.byteLength : typeof File !== "undefined" && file instanceof File ? file.size : 0;
|
|
166
|
+
return this.createResult(
|
|
167
|
+
key,
|
|
168
|
+
size,
|
|
169
|
+
extension,
|
|
170
|
+
options?.metadata
|
|
171
|
+
);
|
|
156
172
|
} catch (error) {
|
|
157
173
|
throw this.mapS3Error(error, MediaErrorCode.UPLOAD_FAILED);
|
|
158
174
|
}
|
|
@@ -289,13 +305,49 @@ var S3Provider = class {
|
|
|
289
305
|
async getContentType(file) {
|
|
290
306
|
if (file instanceof Buffer) {
|
|
291
307
|
const detected = await getFileType(file);
|
|
292
|
-
return {
|
|
308
|
+
return {
|
|
309
|
+
contentType: detected?.mime ?? "application/octet-stream",
|
|
310
|
+
extension: detected?.ext ?? ""
|
|
311
|
+
};
|
|
293
312
|
}
|
|
294
|
-
return {
|
|
313
|
+
return {
|
|
314
|
+
contentType: file.type || "application/octet-stream",
|
|
315
|
+
extension: file.name.split(".").pop() || ""
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Check whether the given input is a stream (Node.js Readable or Web ReadableStream).
|
|
320
|
+
*/
|
|
321
|
+
isStreamInput(file) {
|
|
322
|
+
if (file instanceof Buffer) return false;
|
|
323
|
+
if (typeof File !== "undefined" && file instanceof File) return false;
|
|
324
|
+
return typeof file.pipe === "function" || typeof file.getReader === "function";
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Derive a file extension from a MIME type string.
|
|
328
|
+
*/
|
|
329
|
+
extensionFromMime(mime) {
|
|
330
|
+
const map = {
|
|
331
|
+
"image/jpeg": "jpg",
|
|
332
|
+
"image/png": "png",
|
|
333
|
+
"image/gif": "gif",
|
|
334
|
+
"image/webp": "webp",
|
|
335
|
+
"image/avif": "avif",
|
|
336
|
+
"image/svg+xml": "svg",
|
|
337
|
+
"video/mp4": "mp4",
|
|
338
|
+
"video/webm": "webm",
|
|
339
|
+
"video/quicktime": "mov",
|
|
340
|
+
"audio/mpeg": "mp3",
|
|
341
|
+
"audio/wav": "wav",
|
|
342
|
+
"application/pdf": "pdf",
|
|
343
|
+
"application/octet-stream": ""
|
|
344
|
+
};
|
|
345
|
+
return map[mime] ?? mime.split("/").pop() ?? "";
|
|
295
346
|
}
|
|
296
347
|
createResult(key, size, extension, metadata) {
|
|
297
348
|
return {
|
|
298
349
|
id: key,
|
|
350
|
+
storageKey: key,
|
|
299
351
|
url: this.getUrl(key),
|
|
300
352
|
publicUrl: this.getUrl(key),
|
|
301
353
|
size,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluxmedia/s3",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "AWS S3 provider for FluxMedia - unified media upload library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fluxmedia",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"!dist/**/*.map"
|
|
42
42
|
],
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@fluxmedia/core": "
|
|
44
|
+
"@fluxmedia/core": "2.0.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@aws-sdk/client-s3": "^3.980.0",
|