lean-s3 0.8.15 → 0.9.0
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.mts +25 -2
- package/dist/index.mjs +76 -3
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -98,7 +98,10 @@ type DeleteObjectsError = {
|
|
|
98
98
|
};
|
|
99
99
|
interface S3FilePresignOptions extends OverridableS3ClientOptions {
|
|
100
100
|
contentHash?: Buffer;
|
|
101
|
-
/**
|
|
101
|
+
/**
|
|
102
|
+
* In seconds.
|
|
103
|
+
* @default 3600 (1 hour)
|
|
104
|
+
*/
|
|
102
105
|
expiresIn?: number;
|
|
103
106
|
method?: PresignableHttpMethod;
|
|
104
107
|
contentLength?: number;
|
|
@@ -128,6 +131,25 @@ interface S3FilePresignOptions extends OverridableS3ClientOptions {
|
|
|
128
131
|
contentDisposition?: ContentDisposition;
|
|
129
132
|
};
|
|
130
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Ref: https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-HTTPPOSTConstructPolicy.html#sigv4-ConditionMatching
|
|
136
|
+
*/
|
|
137
|
+
type ConditionMatchType = "starts-with" | "eq" | "content-length-range";
|
|
138
|
+
type PostPolicyCondition = [string, string] | [ConditionMatchType, string | number, string | number];
|
|
139
|
+
interface PresignPostOptions extends OverridableS3ClientOptions {
|
|
140
|
+
key: string;
|
|
141
|
+
/**
|
|
142
|
+
* In seconds.
|
|
143
|
+
* @default 3600 (1 hour)
|
|
144
|
+
*/
|
|
145
|
+
expiresIn?: number;
|
|
146
|
+
fields?: Record<string, string>;
|
|
147
|
+
conditions?: PostPolicyCondition[];
|
|
148
|
+
}
|
|
149
|
+
type PresignPostResult = {
|
|
150
|
+
url: string;
|
|
151
|
+
fields: Record<string, string>;
|
|
152
|
+
};
|
|
131
153
|
type CopyObjectOptions = {
|
|
132
154
|
/** Set this to override the {@link S3ClientOptions#bucket} that was passed on creation of the {@link S3Client}. */
|
|
133
155
|
sourceBucket?: string;
|
|
@@ -387,7 +409,7 @@ declare class S3Client {
|
|
|
387
409
|
/**
|
|
388
410
|
* Create a new instance of an S3 bucket so that credentials can be managed from a single instance instead of being passed to every method.
|
|
389
411
|
*
|
|
390
|
-
* @param
|
|
412
|
+
* @param options The default options to use for the S3 client.
|
|
391
413
|
*/
|
|
392
414
|
constructor(options: S3ClientOptions);
|
|
393
415
|
/** @internal */
|
|
@@ -452,6 +474,7 @@ declare class S3Client {
|
|
|
452
474
|
* ```
|
|
453
475
|
*/
|
|
454
476
|
presign(path: string, options?: S3FilePresignOptions): string;
|
|
477
|
+
presignPost(options: PresignPostOptions): PresignPostResult;
|
|
455
478
|
/**
|
|
456
479
|
* Copies an object from a source to a destination.
|
|
457
480
|
* @remarks Uses [`CopyObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html).
|
package/dist/index.mjs
CHANGED
|
@@ -84,8 +84,11 @@ var S3BucketEntry = class S3BucketEntry {
|
|
|
84
84
|
function deriveSigningKey(date, region, secretAccessKey) {
|
|
85
85
|
return createHmac("sha256", createHmac("sha256", createHmac("sha256", createHmac("sha256", `AWS4${secretAccessKey}`).update(date).digest()).update(region).digest()).update("s3").digest()).update("aws4_request").digest();
|
|
86
86
|
}
|
|
87
|
-
function
|
|
88
|
-
return createHmac("sha256",
|
|
87
|
+
function signEncodedPolicy(signingKey, encodedPolicy) {
|
|
88
|
+
return createHmac("sha256", signingKey).update(encodedPolicy).digest("hex");
|
|
89
|
+
}
|
|
90
|
+
function signCanonicalDataHash(signingKey, canonicalDataHash, date, region) {
|
|
91
|
+
return createHmac("sha256", signingKey).update(`AWS4-HMAC-SHA256\n${date.dateTime}\n${date.date}/${region}/s3/aws4_request\n${canonicalDataHash}`).digest("hex");
|
|
89
92
|
}
|
|
90
93
|
const unsignedPayload = "UNSIGNED-PAYLOAD";
|
|
91
94
|
/**
|
|
@@ -346,7 +349,7 @@ var S3Client = class {
|
|
|
346
349
|
/**
|
|
347
350
|
* Create a new instance of an S3 bucket so that credentials can be managed from a single instance instead of being passed to every method.
|
|
348
351
|
*
|
|
349
|
-
* @param
|
|
352
|
+
* @param options The default options to use for the S3 client.
|
|
350
353
|
*/
|
|
351
354
|
constructor(options) {
|
|
352
355
|
if (!options) throw new Error("`options` is required.");
|
|
@@ -457,6 +460,76 @@ var S3Client = class {
|
|
|
457
460
|
res.search = `${query}&X-Amz-Signature=${signCanonicalDataHash(signingKey, dataDigest, date, region)}`;
|
|
458
461
|
return res.toString();
|
|
459
462
|
}
|
|
463
|
+
presignPost(options) {
|
|
464
|
+
const now$1 = /* @__PURE__ */ new Date();
|
|
465
|
+
const date = getAmzDate(now$1);
|
|
466
|
+
const key = options.key;
|
|
467
|
+
const region = ensureValidRegion(options.region ?? this.#options.region);
|
|
468
|
+
const bucket = ensureValidBucketName(options.bucket ?? this.#options.bucket);
|
|
469
|
+
const endpoint = ensureValidEndpoint(options.endpoint ?? this.#options.endpoint);
|
|
470
|
+
const expiresIn = options.expiresIn ?? 3600;
|
|
471
|
+
const credential = `${this.#options.accessKeyId}/${date.date}/${region}/s3/aws4_request`;
|
|
472
|
+
const fields = {
|
|
473
|
+
...options.fields,
|
|
474
|
+
bucket,
|
|
475
|
+
"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
|
|
476
|
+
"X-Amz-Credential": credential,
|
|
477
|
+
"X-Amz-Date": date.dateTime,
|
|
478
|
+
...this.#options.sessionToken ? { "X-Amz-Security-Token": this.#options.sessionToken } : void 0
|
|
479
|
+
};
|
|
480
|
+
const policy = {
|
|
481
|
+
expiration: new Date(now$1.getTime() + expiresIn * 1e3).toISOString().replace(/\.\d{3}Z$/, "Z"),
|
|
482
|
+
conditions: [
|
|
483
|
+
[
|
|
484
|
+
"eq",
|
|
485
|
+
"$bucket",
|
|
486
|
+
bucket
|
|
487
|
+
],
|
|
488
|
+
key.endsWith("{{filename}}") ? [
|
|
489
|
+
"starts-with",
|
|
490
|
+
"$key",
|
|
491
|
+
key.substring(0, key.lastIndexOf("{{filename}}"))
|
|
492
|
+
] : [
|
|
493
|
+
"eq",
|
|
494
|
+
"$key",
|
|
495
|
+
key
|
|
496
|
+
],
|
|
497
|
+
...options.conditions ? options.conditions : [],
|
|
498
|
+
[
|
|
499
|
+
"eq",
|
|
500
|
+
"$x-amz-algorithm",
|
|
501
|
+
"AWS4-HMAC-SHA256"
|
|
502
|
+
],
|
|
503
|
+
[
|
|
504
|
+
"eq",
|
|
505
|
+
"$x-amz-credential",
|
|
506
|
+
credential
|
|
507
|
+
],
|
|
508
|
+
[
|
|
509
|
+
"eq",
|
|
510
|
+
"$x-amz-date",
|
|
511
|
+
date.dateTime
|
|
512
|
+
]
|
|
513
|
+
]
|
|
514
|
+
};
|
|
515
|
+
if (this.#options.sessionToken) policy.conditions.push([
|
|
516
|
+
"eq",
|
|
517
|
+
"$x-amz-security-token",
|
|
518
|
+
this.#options.sessionToken
|
|
519
|
+
]);
|
|
520
|
+
const policyJson = JSON.stringify(policy);
|
|
521
|
+
const encodedPolicy = Buffer.from(policyJson).toString("base64");
|
|
522
|
+
const signingKey = this.#keyCache.computeIfAbsent(date, region, this.#options.accessKeyId, this.#options.secretAccessKey);
|
|
523
|
+
return {
|
|
524
|
+
url: buildRequestUrl(endpoint, bucket, region, "").toString(),
|
|
525
|
+
fields: {
|
|
526
|
+
...fields,
|
|
527
|
+
key,
|
|
528
|
+
Policy: encodedPolicy,
|
|
529
|
+
"X-Amz-Signature": signEncodedPolicy(signingKey, encodedPolicy)
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
}
|
|
460
533
|
/**
|
|
461
534
|
* Copies an object from a source to a destination.
|
|
462
535
|
* @remarks Uses [`CopyObject`](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html).
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "lean-s3",
|
|
3
3
|
"author": "Niklas Mollenhauer",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.9.0",
|
|
6
6
|
"description": "A server-side S3 API for the regular user.",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"s3",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@testcontainers/minio": "^11.8.1",
|
|
53
53
|
"@testcontainers/s3mock": "^11.8.1",
|
|
54
54
|
"@types/node": "^24.10.1",
|
|
55
|
-
"@typescript/native-preview": "^7.0.0-dev.
|
|
55
|
+
"@typescript/native-preview": "^7.0.0-dev.20251118.1",
|
|
56
56
|
"expect": "^30.2.0",
|
|
57
57
|
"lefthook": "^2.0.4",
|
|
58
58
|
"testcontainers": "^11.8.1",
|