@procedures/s3 0.0.0-stage → 0.2.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/CHANGELOG.md +25 -0
- package/LICENSE +21 -0
- package/README.md +886 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/module.d.ts +22 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +173 -0
- package/dist/module.js.map +1 -0
- package/dist/procedures/s3/delete.d.ts +26 -0
- package/dist/procedures/s3/delete.d.ts.map +1 -0
- package/dist/procedures/s3/delete.js +40 -0
- package/dist/procedures/s3/delete.js.map +1 -0
- package/dist/procedures/s3/download.d.ts +36 -0
- package/dist/procedures/s3/download.d.ts.map +1 -0
- package/dist/procedures/s3/download.js +143 -0
- package/dist/procedures/s3/download.js.map +1 -0
- package/dist/procedures/s3/index.d.ts +13 -0
- package/dist/procedures/s3/index.d.ts.map +1 -0
- package/dist/procedures/s3/index.js +13 -0
- package/dist/procedures/s3/index.js.map +1 -0
- package/dist/procedures/s3/list-all.d.ts +24 -0
- package/dist/procedures/s3/list-all.d.ts.map +1 -0
- package/dist/procedures/s3/list-all.js +57 -0
- package/dist/procedures/s3/list-all.js.map +1 -0
- package/dist/procedures/s3/list.d.ts +28 -0
- package/dist/procedures/s3/list.d.ts.map +1 -0
- package/dist/procedures/s3/list.js +56 -0
- package/dist/procedures/s3/list.js.map +1 -0
- package/dist/procedures/s3/multipart-abort.d.ts +21 -0
- package/dist/procedures/s3/multipart-abort.d.ts.map +1 -0
- package/dist/procedures/s3/multipart-abort.js +33 -0
- package/dist/procedures/s3/multipart-abort.js.map +1 -0
- package/dist/procedures/s3/multipart-complete.d.ts +26 -0
- package/dist/procedures/s3/multipart-complete.d.ts.map +1 -0
- package/dist/procedures/s3/multipart-complete.js +51 -0
- package/dist/procedures/s3/multipart-complete.js.map +1 -0
- package/dist/procedures/s3/multipart-init.d.ts +24 -0
- package/dist/procedures/s3/multipart-init.d.ts.map +1 -0
- package/dist/procedures/s3/multipart-init.js +42 -0
- package/dist/procedures/s3/multipart-init.js.map +1 -0
- package/dist/procedures/s3/multipart-upload.d.ts +24 -0
- package/dist/procedures/s3/multipart-upload.d.ts.map +1 -0
- package/dist/procedures/s3/multipart-upload.js +44 -0
- package/dist/procedures/s3/multipart-upload.js.map +1 -0
- package/dist/procedures/s3/upload.d.ts +30 -0
- package/dist/procedures/s3/upload.d.ts.map +1 -0
- package/dist/procedures/s3/upload.js +50 -0
- package/dist/procedures/s3/upload.js.map +1 -0
- package/dist/register.d.ts +7 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +9 -0
- package/dist/register.js.map +1 -0
- package/dist/s3-client.d.ts +38 -0
- package/dist/s3-client.d.ts.map +1 -0
- package/dist/s3-client.js +83 -0
- package/dist/s3-client.js.map +1 -0
- package/dist/types.d.ts +198 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +197 -0
- package/dist/types.js.map +1 -0
- package/package.json +80 -3
- package/src/index.ts +72 -0
- package/src/module.ts +234 -0
- package/src/procedures/s3/delete.ts +45 -0
- package/src/procedures/s3/download.ts +155 -0
- package/src/procedures/s3/index.ts +13 -0
- package/src/procedures/s3/list-all.ts +63 -0
- package/src/procedures/s3/list.ts +63 -0
- package/src/procedures/s3/multipart-abort.ts +40 -0
- package/src/procedures/s3/multipart-complete.ts +58 -0
- package/src/procedures/s3/multipart-init.ts +50 -0
- package/src/procedures/s3/multipart-upload.ts +53 -0
- package/src/procedures/s3/upload.ts +56 -0
- package/src/register.ts +11 -0
- package/src/s3-client.ts +94 -0
- package/src/types.ts +425 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-all.js","sourceRoot":"","sources":["../../../src/procedures/s3/list-all.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAGnC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAqB;IACnD,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,MAAM,cAAc,GAAa,EAAE,CAAC;IACpC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,IAAI,iBAAiB,GAAuB,SAAS,CAAC;IACtD,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,GAAG,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC;YACxB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,iBAAiB;SAClB,CAAC,CAAC;QACH,SAAS,IAAI,CAAC,CAAC;QAEf,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACzC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACzB,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;QAED,sEAAsE;QACtE,iBAAiB,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,CAAC;IAChF,CAAC,QAAQ,iBAAiB,EAAE;IAE5B,OAAO;QACL,QAAQ;QACR,cAAc;QACd,QAAQ,EAAE,QAAQ,CAAC,MAAM;QACzB,SAAS;KACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.list procedure
|
|
3
|
+
*
|
|
4
|
+
* List objects in S3 bucket.
|
|
5
|
+
*/
|
|
6
|
+
import type { S3ListInput, S3ListOutput } from "../../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* List objects in S3 bucket
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // List all objects with prefix
|
|
12
|
+
* const result = await client.call(["s3", "list"], {
|
|
13
|
+
* bucket: "my-bucket",
|
|
14
|
+
* prefix: "snapshots/",
|
|
15
|
+
* maxKeys: 100,
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // Hierarchical listing with delimiter
|
|
20
|
+
* const result = await client.call(["s3", "list"], {
|
|
21
|
+
* bucket: "my-bucket",
|
|
22
|
+
* prefix: "data/",
|
|
23
|
+
* delimiter: "/",
|
|
24
|
+
* });
|
|
25
|
+
* console.log(result.commonPrefixes); // ["data/2024/", "data/2025/"]
|
|
26
|
+
*/
|
|
27
|
+
export declare function s3List(input: S3ListInput): Promise<S3ListOutput>;
|
|
28
|
+
//# sourceMappingURL=list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/procedures/s3/list.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAgB,MAAM,gBAAgB,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAgCtE"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.list procedure
|
|
3
|
+
*
|
|
4
|
+
* List objects in S3 bucket.
|
|
5
|
+
*/
|
|
6
|
+
import { ListObjectsV2Command } from "@aws-sdk/client-s3";
|
|
7
|
+
import { getS3Client } from "../../s3-client.js";
|
|
8
|
+
/**
|
|
9
|
+
* List objects in S3 bucket
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // List all objects with prefix
|
|
13
|
+
* const result = await client.call(["s3", "list"], {
|
|
14
|
+
* bucket: "my-bucket",
|
|
15
|
+
* prefix: "snapshots/",
|
|
16
|
+
* maxKeys: 100,
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Hierarchical listing with delimiter
|
|
21
|
+
* const result = await client.call(["s3", "list"], {
|
|
22
|
+
* bucket: "my-bucket",
|
|
23
|
+
* prefix: "data/",
|
|
24
|
+
* delimiter: "/",
|
|
25
|
+
* });
|
|
26
|
+
* console.log(result.commonPrefixes); // ["data/2024/", "data/2025/"]
|
|
27
|
+
*/
|
|
28
|
+
export async function s3List(input) {
|
|
29
|
+
const client = getS3Client();
|
|
30
|
+
const command = new ListObjectsV2Command({
|
|
31
|
+
Bucket: input.bucket,
|
|
32
|
+
Prefix: input.prefix,
|
|
33
|
+
MaxKeys: input.maxKeys || 1000,
|
|
34
|
+
ContinuationToken: input.continuationToken,
|
|
35
|
+
Delimiter: input.delimiter,
|
|
36
|
+
});
|
|
37
|
+
const response = await client.send(command);
|
|
38
|
+
const contents = (response.Contents || []).map((obj) => ({
|
|
39
|
+
key: obj.Key || "",
|
|
40
|
+
size: obj.Size || 0,
|
|
41
|
+
lastModified: obj.LastModified?.toISOString() || "",
|
|
42
|
+
etag: obj.ETag?.replace(/"/g, "") || "",
|
|
43
|
+
storageClass: obj.StorageClass,
|
|
44
|
+
}));
|
|
45
|
+
const commonPrefixes = (response.CommonPrefixes || [])
|
|
46
|
+
.map((cp) => cp.Prefix || "")
|
|
47
|
+
.filter(Boolean);
|
|
48
|
+
return {
|
|
49
|
+
contents,
|
|
50
|
+
commonPrefixes,
|
|
51
|
+
isTruncated: response.IsTruncated || false,
|
|
52
|
+
nextContinuationToken: response.NextContinuationToken,
|
|
53
|
+
keyCount: response.KeyCount || contents.length,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/procedures/s3/list.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,KAAkB;IAC7C,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,MAAM,OAAO,GAAG,IAAI,oBAAoB,CAAC;QACvC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;QAC9B,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,SAAS,EAAE,KAAK,CAAC,SAAS;KAC3B,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5C,MAAM,QAAQ,GAAmB,CAAC,QAAQ,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACvE,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,EAAE;QAClB,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC;QACnB,YAAY,EAAE,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE;QACnD,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;QACvC,YAAY,EAAE,GAAG,CAAC,YAAY;KAC/B,CAAC,CAAC,CAAC;IAEJ,MAAM,cAAc,GAAG,CAAC,QAAQ,CAAC,cAAc,IAAI,EAAE,CAAC;SACnD,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC;SAC5B,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnB,OAAO;QACL,QAAQ;QACR,cAAc;QACd,WAAW,EAAE,QAAQ,CAAC,WAAW,IAAI,KAAK;QAC1C,qBAAqB,EAAE,QAAQ,CAAC,qBAAqB;QACrD,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM;KAC/C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.multipart.abort procedure
|
|
3
|
+
*
|
|
4
|
+
* Abort a multipart upload and clean up parts.
|
|
5
|
+
*/
|
|
6
|
+
import type { S3MultipartAbortInput, S3MultipartAbortOutput } from "../../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Abort multipart upload
|
|
9
|
+
*
|
|
10
|
+
* Use to cancel an in-progress multipart upload.
|
|
11
|
+
* This cleans up any parts that were already uploaded.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* await client.call(["s3", "multipart", "abort"], {
|
|
15
|
+
* bucket: "my-bucket",
|
|
16
|
+
* key: "large-file.tar.gz",
|
|
17
|
+
* uploadId: "abc123",
|
|
18
|
+
* });
|
|
19
|
+
*/
|
|
20
|
+
export declare function s3MultipartAbort(input: S3MultipartAbortInput): Promise<S3MultipartAbortOutput>;
|
|
21
|
+
//# sourceMappingURL=multipart-abort.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-abort.d.ts","sourceRoot":"","sources":["../../../src/procedures/s3/multipart-abort.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAEpF;;;;;;;;;;;;GAYG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,sBAAsB,CAAC,CAcjC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.multipart.abort procedure
|
|
3
|
+
*
|
|
4
|
+
* Abort a multipart upload and clean up parts.
|
|
5
|
+
*/
|
|
6
|
+
import { AbortMultipartUploadCommand } from "@aws-sdk/client-s3";
|
|
7
|
+
import { getS3Client } from "../../s3-client.js";
|
|
8
|
+
/**
|
|
9
|
+
* Abort multipart upload
|
|
10
|
+
*
|
|
11
|
+
* Use to cancel an in-progress multipart upload.
|
|
12
|
+
* This cleans up any parts that were already uploaded.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* await client.call(["s3", "multipart", "abort"], {
|
|
16
|
+
* bucket: "my-bucket",
|
|
17
|
+
* key: "large-file.tar.gz",
|
|
18
|
+
* uploadId: "abc123",
|
|
19
|
+
* });
|
|
20
|
+
*/
|
|
21
|
+
export async function s3MultipartAbort(input) {
|
|
22
|
+
const client = getS3Client();
|
|
23
|
+
const command = new AbortMultipartUploadCommand({
|
|
24
|
+
Bucket: input.bucket,
|
|
25
|
+
Key: input.key,
|
|
26
|
+
UploadId: input.uploadId,
|
|
27
|
+
});
|
|
28
|
+
await client.send(command);
|
|
29
|
+
return {
|
|
30
|
+
aborted: true,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=multipart-abort.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-abort.js","sourceRoot":"","sources":["../../../src/procedures/s3/multipart-abort.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAA4B;IAE5B,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,MAAM,OAAO,GAAG,IAAI,2BAA2B,CAAC;QAC9C,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC;IAEH,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE3B,OAAO;QACL,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.multipart.complete procedure
|
|
3
|
+
*
|
|
4
|
+
* Complete a multipart upload by assembling parts.
|
|
5
|
+
*/
|
|
6
|
+
import type { S3MultipartCompleteInput, S3MultipartCompleteOutput } from "../../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Complete multipart upload
|
|
9
|
+
*
|
|
10
|
+
* Call after all parts have been uploaded. Parts must be provided
|
|
11
|
+
* in order with their ETags from the upload responses.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const result = await client.call(["s3", "multipart", "complete"], {
|
|
15
|
+
* bucket: "my-bucket",
|
|
16
|
+
* key: "large-file.tar.gz",
|
|
17
|
+
* uploadId: "abc123",
|
|
18
|
+
* parts: [
|
|
19
|
+
* { partNumber: 1, etag: "etag1" },
|
|
20
|
+
* { partNumber: 2, etag: "etag2" },
|
|
21
|
+
* { partNumber: 3, etag: "etag3" },
|
|
22
|
+
* ],
|
|
23
|
+
* });
|
|
24
|
+
*/
|
|
25
|
+
export declare function s3MultipartComplete(input: S3MultipartCompleteInput): Promise<S3MultipartCompleteOutput>;
|
|
26
|
+
//# sourceMappingURL=multipart-complete.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-complete.d.ts","sourceRoot":"","sources":["../../../src/procedures/s3/multipart-complete.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAE1F;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,OAAO,CAAC,yBAAyB,CAAC,CA2BpC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.multipart.complete procedure
|
|
3
|
+
*
|
|
4
|
+
* Complete a multipart upload by assembling parts.
|
|
5
|
+
*/
|
|
6
|
+
import { CompleteMultipartUploadCommand } from "@aws-sdk/client-s3";
|
|
7
|
+
import { getS3Client } from "../../s3-client.js";
|
|
8
|
+
/**
|
|
9
|
+
* Complete multipart upload
|
|
10
|
+
*
|
|
11
|
+
* Call after all parts have been uploaded. Parts must be provided
|
|
12
|
+
* in order with their ETags from the upload responses.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const result = await client.call(["s3", "multipart", "complete"], {
|
|
16
|
+
* bucket: "my-bucket",
|
|
17
|
+
* key: "large-file.tar.gz",
|
|
18
|
+
* uploadId: "abc123",
|
|
19
|
+
* parts: [
|
|
20
|
+
* { partNumber: 1, etag: "etag1" },
|
|
21
|
+
* { partNumber: 2, etag: "etag2" },
|
|
22
|
+
* { partNumber: 3, etag: "etag3" },
|
|
23
|
+
* ],
|
|
24
|
+
* });
|
|
25
|
+
*/
|
|
26
|
+
export async function s3MultipartComplete(input) {
|
|
27
|
+
const client = getS3Client();
|
|
28
|
+
const command = new CompleteMultipartUploadCommand({
|
|
29
|
+
Bucket: input.bucket,
|
|
30
|
+
Key: input.key,
|
|
31
|
+
UploadId: input.uploadId,
|
|
32
|
+
MultipartUpload: {
|
|
33
|
+
// S3 refuses parts out of order. Parts that were uploaded in parallel can arrive in any
|
|
34
|
+
// order, so the procedure sorts them by number.
|
|
35
|
+
Parts: [...input.parts]
|
|
36
|
+
.sort((a, b) => a.partNumber - b.partNumber)
|
|
37
|
+
.map((part) => ({
|
|
38
|
+
ETag: `"${part.etag}"`,
|
|
39
|
+
PartNumber: part.partNumber,
|
|
40
|
+
})),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
const response = await client.send(command);
|
|
44
|
+
return {
|
|
45
|
+
location: response.Location || `s3://${input.bucket}/${input.key}`,
|
|
46
|
+
bucket: response.Bucket || input.bucket,
|
|
47
|
+
key: response.Key || input.key,
|
|
48
|
+
etag: response.ETag?.replace(/"/g, "") || "",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=multipart-complete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-complete.js","sourceRoot":"","sources":["../../../src/procedures/s3/multipart-complete.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAA+B;IAE/B,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,MAAM,OAAO,GAAG,IAAI,8BAA8B,CAAC;QACjD,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,eAAe,EAAE;YACf,wFAAwF;YACxF,gDAAgD;YAChD,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;iBACpB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC;iBAC3C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACd,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,GAAG;gBACtB,UAAU,EAAE,IAAI,CAAC,UAAU;aAC5B,CAAC,CAAC;SACN;KACF,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5C,OAAO;QACL,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAI,QAAQ,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE;QAClE,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM;QACvC,GAAG,EAAE,QAAQ,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG;QAC9B,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;KAC7C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.multipart.init procedure
|
|
3
|
+
*
|
|
4
|
+
* Initialize a multipart upload for large files.
|
|
5
|
+
*/
|
|
6
|
+
import type { S3MultipartInitInput, S3MultipartInitOutput } from "../../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Initialize multipart upload
|
|
9
|
+
*
|
|
10
|
+
* Use this for files larger than 5MB. Workflow:
|
|
11
|
+
* 1. s3.multipart.init - get uploadId
|
|
12
|
+
* 2. s3.multipart.upload - upload each part (5MB min, except last)
|
|
13
|
+
* 3. s3.multipart.complete - finalize with part ETags
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const init = await client.call(["s3", "multipart", "init"], {
|
|
17
|
+
* bucket: "my-bucket",
|
|
18
|
+
* key: "large-file.tar.gz",
|
|
19
|
+
* contentType: "application/gzip",
|
|
20
|
+
* });
|
|
21
|
+
* console.log(init.uploadId); // Use for subsequent part uploads
|
|
22
|
+
*/
|
|
23
|
+
export declare function s3MultipartInit(input: S3MultipartInitInput): Promise<S3MultipartInitOutput>;
|
|
24
|
+
//# sourceMappingURL=multipart-init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-init.d.ts","sourceRoot":"","sources":["../../../src/procedures/s3/multipart-init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAElF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,qBAAqB,CAAC,CAqBhC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.multipart.init procedure
|
|
3
|
+
*
|
|
4
|
+
* Initialize a multipart upload for large files.
|
|
5
|
+
*/
|
|
6
|
+
import { CreateMultipartUploadCommand } from "@aws-sdk/client-s3";
|
|
7
|
+
import { getS3Client } from "../../s3-client.js";
|
|
8
|
+
/**
|
|
9
|
+
* Initialize multipart upload
|
|
10
|
+
*
|
|
11
|
+
* Use this for files larger than 5MB. Workflow:
|
|
12
|
+
* 1. s3.multipart.init - get uploadId
|
|
13
|
+
* 2. s3.multipart.upload - upload each part (5MB min, except last)
|
|
14
|
+
* 3. s3.multipart.complete - finalize with part ETags
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const init = await client.call(["s3", "multipart", "init"], {
|
|
18
|
+
* bucket: "my-bucket",
|
|
19
|
+
* key: "large-file.tar.gz",
|
|
20
|
+
* contentType: "application/gzip",
|
|
21
|
+
* });
|
|
22
|
+
* console.log(init.uploadId); // Use for subsequent part uploads
|
|
23
|
+
*/
|
|
24
|
+
export async function s3MultipartInit(input) {
|
|
25
|
+
const client = getS3Client();
|
|
26
|
+
const command = new CreateMultipartUploadCommand({
|
|
27
|
+
Bucket: input.bucket,
|
|
28
|
+
Key: input.key,
|
|
29
|
+
ContentType: input.contentType,
|
|
30
|
+
Metadata: input.metadata,
|
|
31
|
+
});
|
|
32
|
+
const response = await client.send(command);
|
|
33
|
+
if (!response.UploadId) {
|
|
34
|
+
throw new Error("Failed to initialize multipart upload: no UploadId returned");
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
uploadId: response.UploadId,
|
|
38
|
+
bucket: input.bucket,
|
|
39
|
+
key: input.key,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=multipart-init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-init.js","sourceRoot":"","sources":["../../../src/procedures/s3/multipart-init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAA2B;IAE3B,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,MAAM,OAAO,GAAG,IAAI,4BAA4B,CAAC;QAC/C,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5C,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,EAAE,KAAK,CAAC,GAAG;KACf,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.multipart.upload procedure
|
|
3
|
+
*
|
|
4
|
+
* Upload a part in a multipart upload.
|
|
5
|
+
*/
|
|
6
|
+
import type { S3MultipartUploadInput, S3MultipartUploadOutput } from "../../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Upload a single part in multipart upload
|
|
9
|
+
*
|
|
10
|
+
* Parts must be at least 5MB (except the last part).
|
|
11
|
+
* Part numbers range from 1 to 10000.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const part1 = await client.call(["s3", "multipart", "upload"], {
|
|
15
|
+
* bucket: "my-bucket",
|
|
16
|
+
* key: "large-file.tar.gz",
|
|
17
|
+
* uploadId: "abc123",
|
|
18
|
+
* partNumber: 1,
|
|
19
|
+
* body: base64EncodedChunk1,
|
|
20
|
+
* });
|
|
21
|
+
* // Store part1.etag for complete call
|
|
22
|
+
*/
|
|
23
|
+
export declare function s3MultipartUpload(input: S3MultipartUploadInput): Promise<S3MultipartUploadOutput>;
|
|
24
|
+
//# sourceMappingURL=multipart-upload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-upload.d.ts","sourceRoot":"","sources":["../../../src/procedures/s3/multipart-upload.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAEtF;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,sBAAsB,GAC5B,OAAO,CAAC,uBAAuB,CAAC,CAwBlC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.multipart.upload procedure
|
|
3
|
+
*
|
|
4
|
+
* Upload a part in a multipart upload.
|
|
5
|
+
*/
|
|
6
|
+
import { UploadPartCommand } from "@aws-sdk/client-s3";
|
|
7
|
+
import { getS3Client } from "../../s3-client.js";
|
|
8
|
+
/**
|
|
9
|
+
* Upload a single part in multipart upload
|
|
10
|
+
*
|
|
11
|
+
* Parts must be at least 5MB (except the last part).
|
|
12
|
+
* Part numbers range from 1 to 10000.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* const part1 = await client.call(["s3", "multipart", "upload"], {
|
|
16
|
+
* bucket: "my-bucket",
|
|
17
|
+
* key: "large-file.tar.gz",
|
|
18
|
+
* uploadId: "abc123",
|
|
19
|
+
* partNumber: 1,
|
|
20
|
+
* body: base64EncodedChunk1,
|
|
21
|
+
* });
|
|
22
|
+
* // Store part1.etag for complete call
|
|
23
|
+
*/
|
|
24
|
+
export async function s3MultipartUpload(input) {
|
|
25
|
+
const client = getS3Client();
|
|
26
|
+
// Body is always base64 encoded for multipart
|
|
27
|
+
const body = Buffer.from(input.body, "base64");
|
|
28
|
+
const command = new UploadPartCommand({
|
|
29
|
+
Bucket: input.bucket,
|
|
30
|
+
Key: input.key,
|
|
31
|
+
UploadId: input.uploadId,
|
|
32
|
+
PartNumber: input.partNumber,
|
|
33
|
+
Body: body,
|
|
34
|
+
});
|
|
35
|
+
const response = await client.send(command);
|
|
36
|
+
if (!response.ETag) {
|
|
37
|
+
throw new Error(`Failed to upload part ${input.partNumber}: no ETag returned`);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
etag: response.ETag.replace(/"/g, ""),
|
|
41
|
+
partNumber: input.partNumber,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=multipart-upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multipart-upload.js","sourceRoot":"","sources":["../../../src/procedures/s3/multipart-upload.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAA6B;IAE7B,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,8CAA8C;IAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;QACpC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5C,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,CAAC,UAAU,oBAAoB,CAAC,CAAC;IACjF,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;QACrC,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.upload procedure
|
|
3
|
+
*
|
|
4
|
+
* Upload content to S3 bucket.
|
|
5
|
+
*/
|
|
6
|
+
import type { S3UploadInput, S3UploadOutput } from "../../types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Upload content to S3
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Upload text content
|
|
12
|
+
* await client.call(["s3", "upload"], {
|
|
13
|
+
* bucket: "my-bucket",
|
|
14
|
+
* key: "path/to/file.json",
|
|
15
|
+
* body: JSON.stringify({ data: "value" }),
|
|
16
|
+
* contentType: "application/json",
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // Upload base64 binary
|
|
21
|
+
* await client.call(["s3", "upload"], {
|
|
22
|
+
* bucket: "my-bucket",
|
|
23
|
+
* key: "path/to/image.png",
|
|
24
|
+
* body: base64EncodedData,
|
|
25
|
+
* base64: true,
|
|
26
|
+
* contentType: "image/png",
|
|
27
|
+
* });
|
|
28
|
+
*/
|
|
29
|
+
export declare function s3Upload(input: S3UploadInput): Promise<S3UploadOutput>;
|
|
30
|
+
//# sourceMappingURL=upload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../src/procedures/s3/upload.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAuB5E"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* s3.upload procedure
|
|
3
|
+
*
|
|
4
|
+
* Upload content to S3 bucket.
|
|
5
|
+
*/
|
|
6
|
+
import { PutObjectCommand } from "@aws-sdk/client-s3";
|
|
7
|
+
import { getS3Client } from "../../s3-client.js";
|
|
8
|
+
/**
|
|
9
|
+
* Upload content to S3
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Upload text content
|
|
13
|
+
* await client.call(["s3", "upload"], {
|
|
14
|
+
* bucket: "my-bucket",
|
|
15
|
+
* key: "path/to/file.json",
|
|
16
|
+
* body: JSON.stringify({ data: "value" }),
|
|
17
|
+
* contentType: "application/json",
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Upload base64 binary
|
|
22
|
+
* await client.call(["s3", "upload"], {
|
|
23
|
+
* bucket: "my-bucket",
|
|
24
|
+
* key: "path/to/image.png",
|
|
25
|
+
* body: base64EncodedData,
|
|
26
|
+
* base64: true,
|
|
27
|
+
* contentType: "image/png",
|
|
28
|
+
* });
|
|
29
|
+
*/
|
|
30
|
+
export async function s3Upload(input) {
|
|
31
|
+
const client = getS3Client();
|
|
32
|
+
// Convert body to Buffer if base64
|
|
33
|
+
const body = input.base64
|
|
34
|
+
? Buffer.from(input.body, "base64")
|
|
35
|
+
: input.body;
|
|
36
|
+
const command = new PutObjectCommand({
|
|
37
|
+
Bucket: input.bucket,
|
|
38
|
+
Key: input.key,
|
|
39
|
+
Body: body,
|
|
40
|
+
ContentType: input.contentType,
|
|
41
|
+
Metadata: input.metadata,
|
|
42
|
+
});
|
|
43
|
+
const response = await client.send(command);
|
|
44
|
+
return {
|
|
45
|
+
etag: response.ETag?.replace(/"/g, "") || "",
|
|
46
|
+
versionId: response.VersionId,
|
|
47
|
+
location: `s3://${input.bucket}/${input.key}`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../../src/procedures/s3/upload.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,KAAoB;IACjD,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,mCAAmC;IACnC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM;QACvB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC;QACnC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;IAEf,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC;QACnC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,IAAI,EAAE,IAAI;QACV,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE5C,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;QAC5C,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,QAAQ,EAAE,QAAQ,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,EAAE;KAC9C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Importing this file registers the procedures of @procedures/s3, and of the modules that it
|
|
3
|
+
* requires, in the global registry: `import "@procedures/s3/register"`. The package root and the
|
|
4
|
+
* `./module` entry register nothing (ARCHITECTURE-PROPOSALS-2026-10, P9).
|
|
5
|
+
*/
|
|
6
|
+
export * from "./module.js";
|
|
7
|
+
//# sourceMappingURL=register.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,cAAc,aAAa,CAAC"}
|
package/dist/register.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Importing this file registers the procedures of @procedures/s3, and of the modules that it
|
|
3
|
+
* requires, in the global registry: `import "@procedures/s3/register"`. The package root and the
|
|
4
|
+
* `./module` entry register nothing (ARCHITECTURE-PROPOSALS-2026-10, P9).
|
|
5
|
+
*/
|
|
6
|
+
import { registerS3Procedures } from "./module.js";
|
|
7
|
+
export * from "./module.js";
|
|
8
|
+
registerS3Procedures();
|
|
9
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,cAAc,aAAa,CAAC;AAE5B,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3 Client Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates an S3 client. Static credentials are read from environment variables
|
|
5
|
+
* when present; otherwise the AWS SDK's default credential provider chain
|
|
6
|
+
* (SSO, IAM roles/IMDS, shared config profiles, env, etc.) resolves them.
|
|
7
|
+
* NEVER hardcode credentials - always use environment variables or an IAM role.
|
|
8
|
+
*/
|
|
9
|
+
import { S3Client } from "@aws-sdk/client-s3";
|
|
10
|
+
import type { S3Config } from "./types.js";
|
|
11
|
+
/**
|
|
12
|
+
* Get S3 configuration from environment variables.
|
|
13
|
+
*
|
|
14
|
+
* Static credentials are optional: when `AWS_ACCESS_KEY_ID` /
|
|
15
|
+
* `AWS_SECRET_ACCESS_KEY` are absent, the returned config carries no
|
|
16
|
+
* credentials and the AWS SDK default provider chain is used instead.
|
|
17
|
+
* `AWS_SESSION_TOKEN` is included when present (STS/SSO temporary creds).
|
|
18
|
+
*/
|
|
19
|
+
export declare function getS3Config(): S3Config;
|
|
20
|
+
/**
|
|
21
|
+
* Create an S3 client.
|
|
22
|
+
*
|
|
23
|
+
* Explicit credentials are passed ONLY when both `AWS_ACCESS_KEY_ID` and
|
|
24
|
+
* `AWS_SECRET_ACCESS_KEY` are set (including `AWS_SESSION_TOKEN` when present).
|
|
25
|
+
* Otherwise `credentials` is omitted so the AWS SDK default credential
|
|
26
|
+
* provider chain resolves SSO / IAM-role / profile credentials.
|
|
27
|
+
*/
|
|
28
|
+
export declare function createS3Client(): S3Client;
|
|
29
|
+
/**
|
|
30
|
+
* Get singleton S3 client instance
|
|
31
|
+
* Creates client on first call, reuses on subsequent calls
|
|
32
|
+
*/
|
|
33
|
+
export declare function getS3Client(): S3Client;
|
|
34
|
+
/**
|
|
35
|
+
* Reset the singleton client (useful for testing or credential refresh)
|
|
36
|
+
*/
|
|
37
|
+
export declare function resetS3Client(): void;
|
|
38
|
+
//# sourceMappingURL=s3-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-client.d.ts","sourceRoot":"","sources":["../src/s3-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;;GAOG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CActC;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,IAAI,QAAQ,CAyBzC;AAKD;;;GAGG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAKtC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAKpC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3 Client Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates an S3 client. Static credentials are read from environment variables
|
|
5
|
+
* when present; otherwise the AWS SDK's default credential provider chain
|
|
6
|
+
* (SSO, IAM roles/IMDS, shared config profiles, env, etc.) resolves them.
|
|
7
|
+
* NEVER hardcode credentials - always use environment variables or an IAM role.
|
|
8
|
+
*/
|
|
9
|
+
import { S3Client } from "@aws-sdk/client-s3";
|
|
10
|
+
/**
|
|
11
|
+
* Get S3 configuration from environment variables.
|
|
12
|
+
*
|
|
13
|
+
* Static credentials are optional: when `AWS_ACCESS_KEY_ID` /
|
|
14
|
+
* `AWS_SECRET_ACCESS_KEY` are absent, the returned config carries no
|
|
15
|
+
* credentials and the AWS SDK default provider chain is used instead.
|
|
16
|
+
* `AWS_SESSION_TOKEN` is included when present (STS/SSO temporary creds).
|
|
17
|
+
*/
|
|
18
|
+
export function getS3Config() {
|
|
19
|
+
const accessKeyId = process.env["AWS_ACCESS_KEY_ID"];
|
|
20
|
+
const secretAccessKey = process.env["AWS_SECRET_ACCESS_KEY"];
|
|
21
|
+
const sessionToken = process.env["AWS_SESSION_TOKEN"];
|
|
22
|
+
const region = process.env["AWS_REGION"] || "us-east-1";
|
|
23
|
+
const endpoint = process.env["S3_ENDPOINT"];
|
|
24
|
+
return {
|
|
25
|
+
region,
|
|
26
|
+
endpoint,
|
|
27
|
+
accessKeyId,
|
|
28
|
+
secretAccessKey,
|
|
29
|
+
sessionToken,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create an S3 client.
|
|
34
|
+
*
|
|
35
|
+
* Explicit credentials are passed ONLY when both `AWS_ACCESS_KEY_ID` and
|
|
36
|
+
* `AWS_SECRET_ACCESS_KEY` are set (including `AWS_SESSION_TOKEN` when present).
|
|
37
|
+
* Otherwise `credentials` is omitted so the AWS SDK default credential
|
|
38
|
+
* provider chain resolves SSO / IAM-role / profile credentials.
|
|
39
|
+
*/
|
|
40
|
+
export function createS3Client() {
|
|
41
|
+
const config = getS3Config();
|
|
42
|
+
const clientConfig = {
|
|
43
|
+
region: config.region,
|
|
44
|
+
};
|
|
45
|
+
// Only supply static credentials when the env keys actually exist; otherwise
|
|
46
|
+
// let the SDK resolve credentials from its default chain (SSO/IMDS/profile).
|
|
47
|
+
if (config.accessKeyId && config.secretAccessKey) {
|
|
48
|
+
clientConfig.credentials = {
|
|
49
|
+
accessKeyId: config.accessKeyId,
|
|
50
|
+
secretAccessKey: config.secretAccessKey,
|
|
51
|
+
// Session token is required for STS/SSO temporary credentials.
|
|
52
|
+
...(config.sessionToken ? { sessionToken: config.sessionToken } : {}),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// Custom endpoint for MinIO, LocalStack, etc.
|
|
56
|
+
if (config.endpoint) {
|
|
57
|
+
clientConfig.endpoint = config.endpoint;
|
|
58
|
+
clientConfig.forcePathStyle = true; // Required for non-AWS S3
|
|
59
|
+
}
|
|
60
|
+
return new S3Client(clientConfig);
|
|
61
|
+
}
|
|
62
|
+
// Singleton client instance (lazy initialized)
|
|
63
|
+
let s3ClientInstance = null;
|
|
64
|
+
/**
|
|
65
|
+
* Get singleton S3 client instance
|
|
66
|
+
* Creates client on first call, reuses on subsequent calls
|
|
67
|
+
*/
|
|
68
|
+
export function getS3Client() {
|
|
69
|
+
if (!s3ClientInstance) {
|
|
70
|
+
s3ClientInstance = createS3Client();
|
|
71
|
+
}
|
|
72
|
+
return s3ClientInstance;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Reset the singleton client (useful for testing or credential refresh)
|
|
76
|
+
*/
|
|
77
|
+
export function resetS3Client() {
|
|
78
|
+
if (s3ClientInstance) {
|
|
79
|
+
s3ClientInstance.destroy();
|
|
80
|
+
s3ClientInstance = null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=s3-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-client.js","sourceRoot":"","sources":["../src/s3-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACrD,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,WAAW,CAAC;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAE5C,OAAO;QACL,MAAM;QACN,QAAQ;QACR,WAAW;QACX,eAAe;QACf,YAAY;KACb,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,MAAM,GAAG,WAAW,EAAE,CAAC;IAE7B,MAAM,YAAY,GAA8C;QAC9D,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC;IAEF,6EAA6E;IAC7E,6EAA6E;IAC7E,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;QACjD,YAAY,CAAC,WAAW,GAAG;YACzB,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,+DAA+D;YAC/D,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACtE,CAAC;IACJ,CAAC;IAED,8CAA8C;IAC9C,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,YAAY,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QACxC,YAAY,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC,0BAA0B;IAChE,CAAC;IAED,OAAO,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;AACpC,CAAC;AAED,+CAA+C;AAC/C,IAAI,gBAAgB,GAAoB,IAAI,CAAC;AAE7C;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,gBAAgB,GAAG,cAAc,EAAE,CAAC;IACtC,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,gBAAgB,EAAE,CAAC;QACrB,gBAAgB,CAAC,OAAO,EAAE,CAAC;QAC3B,gBAAgB,GAAG,IAAI,CAAC;IAC1B,CAAC;AACH,CAAC"}
|