lean-s3 0.7.1 → 0.7.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/index.d.ts +48 -4
- package/dist/index.js +69 -37
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ type DeleteObjectsError = {
|
|
|
57
57
|
message: string;
|
|
58
58
|
versionId: string;
|
|
59
59
|
};
|
|
60
|
-
interface S3FilePresignOptions {
|
|
60
|
+
interface S3FilePresignOptions extends OverridableS3ClientOptions {
|
|
61
61
|
contentHash?: Buffer;
|
|
62
62
|
/** Seconds. */
|
|
63
63
|
expiresIn?: number;
|
|
@@ -67,6 +67,27 @@ interface S3FilePresignOptions {
|
|
|
67
67
|
acl?: Acl;
|
|
68
68
|
/** `Content-Type` of the file. */
|
|
69
69
|
type?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Headers to set on the response of the S3 service.
|
|
72
|
+
*/
|
|
73
|
+
response?: {
|
|
74
|
+
/**
|
|
75
|
+
* Used to set the file name that browsers display when downloading the file.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```js
|
|
79
|
+
* client.presign("foo.jpg", {
|
|
80
|
+
* response: {
|
|
81
|
+
* contentDisposition: {
|
|
82
|
+
* type: "attachment",
|
|
83
|
+
* filename: "download.jpg",
|
|
84
|
+
* },
|
|
85
|
+
* },
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
contentDisposition?: ContentDisposition;
|
|
90
|
+
};
|
|
70
91
|
}
|
|
71
92
|
type ListObjectsOptions = {
|
|
72
93
|
bucket?: string;
|
|
@@ -311,9 +332,21 @@ declare class S3Client {
|
|
|
311
332
|
* expiresIn: 3600 // 1 hour
|
|
312
333
|
* });
|
|
313
334
|
* ```
|
|
335
|
+
*
|
|
336
|
+
* @example
|
|
337
|
+
* ```js
|
|
338
|
+
* client.presign("foo.jpg", {
|
|
339
|
+
* expiresIn: 3600 // 1 hour
|
|
340
|
+
* response: {
|
|
341
|
+
* contentDisposition: {
|
|
342
|
+
* type: "attachment",
|
|
343
|
+
* filename: "download.jpg",
|
|
344
|
+
* },
|
|
345
|
+
* },
|
|
346
|
+
* });
|
|
347
|
+
* ```
|
|
314
348
|
*/
|
|
315
|
-
presign(path: string,
|
|
316
|
-
storageClass, contentLength, type, acl, region: regionOverride, bucket: bucketOverride, endpoint: endpointOverride, }?: S3FilePresignOptions & OverridableS3ClientOptions): string;
|
|
349
|
+
presign(path: string, optio2ns?: S3FilePresignOptions): string;
|
|
317
350
|
createMultipartUpload(key: string, options?: CreateMultipartUploadOptions): Promise<CreateMultipartUploadResult>;
|
|
318
351
|
/**
|
|
319
352
|
* @remarks Uses [`ListMultipartUploads`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html).
|
|
@@ -538,5 +571,16 @@ type BucketInfo = {
|
|
|
538
571
|
dataRedundancy?: string;
|
|
539
572
|
type?: string;
|
|
540
573
|
};
|
|
574
|
+
/**
|
|
575
|
+
* Represents valid values for the [`Content-Disposition`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Disposition) header.
|
|
576
|
+
*/
|
|
577
|
+
type ContentDisposition = AttachmentContentDisposition | InlineContentDisposition;
|
|
578
|
+
type InlineContentDisposition = {
|
|
579
|
+
type: "inline";
|
|
580
|
+
};
|
|
581
|
+
type AttachmentContentDisposition = {
|
|
582
|
+
type: "attachment";
|
|
583
|
+
filename?: string;
|
|
584
|
+
};
|
|
541
585
|
|
|
542
|
-
export { type AbortMultipartUploadOptions, type Acl, type BucketCorsRule, type BucketCorsRules, type BucketCreationOptions, type BucketDeletionOptions, type BucketExistsOptions, type BucketInfo, type BucketLocationInfo, type ByteSource, type ChecksumAlgorithm, type ChecksumType, type CompleteMultipartUploadOptions, type CompleteMultipartUploadResult, type CreateFileInstanceOptions, type CreateMultipartUploadOptions, type CreateMultipartUploadResult, type DeleteBucketCorsOptions, type DeleteObjectsError, type DeleteObjectsOptions, type DeleteObjectsResult, type GetBucketCorsOptions, type GetBucketCorsResult, type HttpMethod, type ListMultipartUploadsOptions, type ListMultipartUploadsResult, type ListObjectsIteratingOptions, type ListObjectsOptions, type ListObjectsResult, type ListPartsOptions, type ListPartsResult, type MultipartUpload, type MultipartUploadPart, type OverridableS3ClientOptions, type PresignableHttpMethod, type PutBucketCorsOptions, S3BucketEntry, S3Client, type S3ClientOptions, S3Error, type S3ErrorOptions, S3File, type S3FileDeleteOptions, type S3FileExistsOptions, type S3FilePresignOptions, type S3FileWriteOptions, S3Stat, type S3StatOptions, type StorageClass, type UndiciBodyInit, type UploadPartOptions, type UploadPartResult };
|
|
586
|
+
export { type AbortMultipartUploadOptions, type Acl, type AttachmentContentDisposition, type BucketCorsRule, type BucketCorsRules, type BucketCreationOptions, type BucketDeletionOptions, type BucketExistsOptions, type BucketInfo, type BucketLocationInfo, type ByteSource, type ChecksumAlgorithm, type ChecksumType, type CompleteMultipartUploadOptions, type CompleteMultipartUploadResult, type ContentDisposition, type CreateFileInstanceOptions, type CreateMultipartUploadOptions, type CreateMultipartUploadResult, type DeleteBucketCorsOptions, type DeleteObjectsError, type DeleteObjectsOptions, type DeleteObjectsResult, type GetBucketCorsOptions, type GetBucketCorsResult, type HttpMethod, type InlineContentDisposition, type ListMultipartUploadsOptions, type ListMultipartUploadsResult, type ListObjectsIteratingOptions, type ListObjectsOptions, type ListObjectsResult, type ListPartsOptions, type ListPartsResult, type MultipartUpload, type MultipartUploadPart, type OverridableS3ClientOptions, type PresignableHttpMethod, type PutBucketCorsOptions, S3BucketEntry, S3Client, type S3ClientOptions, S3Error, type S3ErrorOptions, S3File, type S3FileDeleteOptions, type S3FileExistsOptions, type S3FilePresignOptions, type S3FileWriteOptions, S3Stat, type S3StatOptions, type StorageClass, type UndiciBodyInit, type UploadPartOptions, type UploadPartResult };
|
package/dist/index.js
CHANGED
|
@@ -202,7 +202,7 @@ function buildRequestUrl(endpoint, bucket, region, path) {
|
|
|
202
202
|
const result = new URL(endpointWithBucketAndRegion);
|
|
203
203
|
const pathPrefix = result.pathname.endsWith("/") ? result.pathname : `${result.pathname}/`;
|
|
204
204
|
const pathSuffix = replacedBucket ? normalizePath(path) : `${normalizedBucket}/${normalizePath(path)}`;
|
|
205
|
-
result.pathname = pathPrefix + pathSuffix.replaceAll(":", "%3A").replaceAll("+", "%2B").replaceAll("(", "%28").replaceAll(")", "%29").replaceAll(",", "%2C");
|
|
205
|
+
result.pathname = pathPrefix + pathSuffix.replaceAll(":", "%3A").replaceAll("+", "%2B").replaceAll("(", "%28").replaceAll(")", "%29").replaceAll(",", "%2C").replaceAll("'", "%27").replaceAll("*", "%2A");
|
|
206
206
|
return result;
|
|
207
207
|
}
|
|
208
208
|
function replaceDomainPlaceholders(endpoint, bucket, region) {
|
|
@@ -346,6 +346,32 @@ function ensureValidPath(path) {
|
|
|
346
346
|
return path;
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
+
// src/assertNever.ts
|
|
350
|
+
function assertNever(v) {
|
|
351
|
+
throw new TypeError(`Expected value not to have type ${typeof v}`);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// src/encode.ts
|
|
355
|
+
function getContentDispositionHeader(value) {
|
|
356
|
+
switch (value.type) {
|
|
357
|
+
case "inline":
|
|
358
|
+
return "inline";
|
|
359
|
+
case "attachment": {
|
|
360
|
+
const { filename } = value;
|
|
361
|
+
if (typeof filename === "undefined") {
|
|
362
|
+
return "attachment";
|
|
363
|
+
}
|
|
364
|
+
const encoded = encodeURIComponent(filename);
|
|
365
|
+
return `attachment;filename="${encoded}";filename*=UTF-8''${encoded}`;
|
|
366
|
+
}
|
|
367
|
+
default:
|
|
368
|
+
assertNever(value);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function encodeURIComponentExtended(value) {
|
|
372
|
+
return encodeURIComponent(value).replaceAll(":", "%3A").replaceAll("+", "%2B").replaceAll("(", "%28").replaceAll(")", "%29").replaceAll(",", "%2C").replaceAll("'", "%27").replaceAll("*", "%2A");
|
|
373
|
+
}
|
|
374
|
+
|
|
349
375
|
// src/S3Client.ts
|
|
350
376
|
var write = Symbol("write");
|
|
351
377
|
var stream = Symbol("stream");
|
|
@@ -471,50 +497,58 @@ var S3Client = class {
|
|
|
471
497
|
* expiresIn: 3600 // 1 hour
|
|
472
498
|
* });
|
|
473
499
|
* ```
|
|
500
|
+
*
|
|
501
|
+
* @example
|
|
502
|
+
* ```js
|
|
503
|
+
* client.presign("foo.jpg", {
|
|
504
|
+
* expiresIn: 3600 // 1 hour
|
|
505
|
+
* response: {
|
|
506
|
+
* contentDisposition: {
|
|
507
|
+
* type: "attachment",
|
|
508
|
+
* filename: "download.jpg",
|
|
509
|
+
* },
|
|
510
|
+
* },
|
|
511
|
+
* });
|
|
512
|
+
* ```
|
|
474
513
|
*/
|
|
475
|
-
presign(path, {
|
|
476
|
-
|
|
477
|
-
expiresIn = 3600,
|
|
478
|
-
// TODO: Maybe rename this to expiresInSeconds
|
|
479
|
-
storageClass,
|
|
480
|
-
contentLength,
|
|
481
|
-
type,
|
|
482
|
-
acl,
|
|
483
|
-
region: regionOverride,
|
|
484
|
-
bucket: bucketOverride,
|
|
485
|
-
endpoint: endpointOverride
|
|
486
|
-
} = {}) {
|
|
514
|
+
presign(path, optio2ns = {}) {
|
|
515
|
+
const contentLength = optio2ns.contentLength ?? void 0;
|
|
487
516
|
if (typeof contentLength === "number") {
|
|
488
517
|
if (contentLength < 0) {
|
|
489
518
|
throw new RangeError("`contentLength` must be >= 0.");
|
|
490
519
|
}
|
|
491
520
|
}
|
|
521
|
+
const method = optio2ns.method ?? "GET";
|
|
522
|
+
const contentType = optio2ns.type ?? void 0;
|
|
523
|
+
const region = optio2ns.region ?? this.#options.region;
|
|
524
|
+
const bucket = optio2ns.bucket ?? this.#options.bucket;
|
|
525
|
+
const endpoint = optio2ns.endpoint ?? this.#options.endpoint;
|
|
526
|
+
const responseOptions = optio2ns.response;
|
|
527
|
+
const contentDisposition = responseOptions?.contentDisposition;
|
|
528
|
+
const responseContentDisposition = contentDisposition ? getContentDispositionHeader(contentDisposition) : void 0;
|
|
529
|
+
const res = buildRequestUrl(endpoint, bucket, region, path);
|
|
492
530
|
const now2 = /* @__PURE__ */ new Date();
|
|
493
531
|
const date = getAmzDate(now2);
|
|
494
|
-
const options = this.#options;
|
|
495
|
-
const region = regionOverride ?? options.region;
|
|
496
|
-
const bucket = bucketOverride ?? options.bucket;
|
|
497
|
-
const endpoint = endpointOverride ?? options.endpoint;
|
|
498
|
-
const res = buildRequestUrl(endpoint, bucket, region, path);
|
|
499
532
|
const query = buildSearchParams(
|
|
500
|
-
`${options.accessKeyId}/${date.date}/${region}/s3/aws4_request`,
|
|
533
|
+
`${this.#options.accessKeyId}/${date.date}/${region}/s3/aws4_request`,
|
|
501
534
|
date,
|
|
502
|
-
expiresIn,
|
|
503
|
-
typeof contentLength === "number" || typeof
|
|
535
|
+
optio2ns.expiresIn ?? 3600,
|
|
536
|
+
typeof contentLength === "number" || typeof contentType === "string" ? typeof contentLength === "number" && typeof contentType === "string" ? "content-length;content-type;host" : typeof contentLength === "number" ? "content-length;host" : typeof contentType === "string" ? "content-type;host" : "" : "host",
|
|
504
537
|
unsignedPayload,
|
|
505
|
-
storageClass,
|
|
506
|
-
options.sessionToken,
|
|
507
|
-
acl
|
|
538
|
+
optio2ns.storageClass,
|
|
539
|
+
this.#options.sessionToken,
|
|
540
|
+
optio2ns.acl,
|
|
541
|
+
responseContentDisposition
|
|
508
542
|
);
|
|
509
|
-
const dataDigest = typeof contentLength === "number" || typeof
|
|
543
|
+
const dataDigest = typeof contentLength === "number" || typeof contentType === "string" ? createCanonicalDataDigest(
|
|
510
544
|
method,
|
|
511
545
|
res.pathname,
|
|
512
546
|
query,
|
|
513
|
-
typeof contentLength === "number" && typeof
|
|
547
|
+
typeof contentLength === "number" && typeof contentType === "string" ? {
|
|
514
548
|
"content-length": String(contentLength),
|
|
515
|
-
"content-type":
|
|
549
|
+
"content-type": contentType,
|
|
516
550
|
host: res.host
|
|
517
|
-
} : typeof contentLength === "number" ? { "content-length": String(contentLength), host: res.host } : typeof
|
|
551
|
+
} : typeof contentLength === "number" ? { "content-length": String(contentLength), host: res.host } : typeof contentType === "string" ? { "content-type": contentType, host: res.host } : {},
|
|
518
552
|
unsignedPayload
|
|
519
553
|
) : createCanonicalDataDigestHostOnly(
|
|
520
554
|
method,
|
|
@@ -525,8 +559,8 @@ var S3Client = class {
|
|
|
525
559
|
const signingKey = this.#keyCache.computeIfAbsent(
|
|
526
560
|
date,
|
|
527
561
|
region,
|
|
528
|
-
options.accessKeyId,
|
|
529
|
-
options.secretAccessKey
|
|
562
|
+
this.#options.accessKeyId,
|
|
563
|
+
this.#options.secretAccessKey
|
|
530
564
|
);
|
|
531
565
|
const signature = signCanonicalDataHash(
|
|
532
566
|
signingKey,
|
|
@@ -1409,7 +1443,7 @@ var S3Client = class {
|
|
|
1409
1443
|
});
|
|
1410
1444
|
}
|
|
1411
1445
|
};
|
|
1412
|
-
function buildSearchParams(amzCredential, date, expiresIn, headerList, contentHashStr, storageClass, sessionToken, acl) {
|
|
1446
|
+
function buildSearchParams(amzCredential, date, expiresIn, headerList, contentHashStr, storageClass, sessionToken, acl, responseContentDisposition) {
|
|
1413
1447
|
let res = "";
|
|
1414
1448
|
if (acl) {
|
|
1415
1449
|
res += `X-Amz-Acl=${encodeURIComponent(acl)}&`;
|
|
@@ -1418,7 +1452,7 @@ function buildSearchParams(amzCredential, date, expiresIn, headerList, contentHa
|
|
|
1418
1452
|
if (contentHashStr) {
|
|
1419
1453
|
res += `&X-Amz-Content-Sha256=${contentHashStr}`;
|
|
1420
1454
|
}
|
|
1421
|
-
res += `&X-Amz-Credential=${
|
|
1455
|
+
res += `&X-Amz-Credential=${encodeURIComponentExtended(amzCredential)}`;
|
|
1422
1456
|
res += `&X-Amz-Date=${date.dateTime}`;
|
|
1423
1457
|
res += `&X-Amz-Expires=${expiresIn}`;
|
|
1424
1458
|
if (sessionToken) {
|
|
@@ -1428,6 +1462,9 @@ function buildSearchParams(amzCredential, date, expiresIn, headerList, contentHa
|
|
|
1428
1462
|
if (storageClass) {
|
|
1429
1463
|
res += `&X-Amz-Storage-Class=${storageClass}`;
|
|
1430
1464
|
}
|
|
1465
|
+
if (responseContentDisposition) {
|
|
1466
|
+
res += `&response-content-disposition=${encodeURIComponentExtended(responseContentDisposition)}`;
|
|
1467
|
+
}
|
|
1431
1468
|
return res;
|
|
1432
1469
|
}
|
|
1433
1470
|
function ensureParsedXml(text) {
|
|
@@ -1447,11 +1484,6 @@ function ensureParsedXml(text) {
|
|
|
1447
1484
|
}
|
|
1448
1485
|
}
|
|
1449
1486
|
|
|
1450
|
-
// src/assertNever.ts
|
|
1451
|
-
function assertNever(v) {
|
|
1452
|
-
throw new TypeError(`Expected value not to have type ${typeof v}`);
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
1487
|
// src/S3File.ts
|
|
1456
1488
|
var S3File = class _S3File {
|
|
1457
1489
|
#client;
|