@procedures/s3 0.0.0-stage → 0.1.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.
Files changed (80) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +886 -2
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/index.d.ts +18 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +21 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/module.d.ts +16 -0
  10. package/dist/module.d.ts.map +1 -0
  11. package/dist/module.js +151 -0
  12. package/dist/module.js.map +1 -0
  13. package/dist/procedures/s3/delete.d.ts +26 -0
  14. package/dist/procedures/s3/delete.d.ts.map +1 -0
  15. package/dist/procedures/s3/delete.js +40 -0
  16. package/dist/procedures/s3/delete.js.map +1 -0
  17. package/dist/procedures/s3/download.d.ts +36 -0
  18. package/dist/procedures/s3/download.d.ts.map +1 -0
  19. package/dist/procedures/s3/download.js +143 -0
  20. package/dist/procedures/s3/download.js.map +1 -0
  21. package/dist/procedures/s3/index.d.ts +13 -0
  22. package/dist/procedures/s3/index.d.ts.map +1 -0
  23. package/dist/procedures/s3/index.js +13 -0
  24. package/dist/procedures/s3/index.js.map +1 -0
  25. package/dist/procedures/s3/list-all.d.ts +24 -0
  26. package/dist/procedures/s3/list-all.d.ts.map +1 -0
  27. package/dist/procedures/s3/list-all.js +57 -0
  28. package/dist/procedures/s3/list-all.js.map +1 -0
  29. package/dist/procedures/s3/list.d.ts +28 -0
  30. package/dist/procedures/s3/list.d.ts.map +1 -0
  31. package/dist/procedures/s3/list.js +56 -0
  32. package/dist/procedures/s3/list.js.map +1 -0
  33. package/dist/procedures/s3/multipart-abort.d.ts +21 -0
  34. package/dist/procedures/s3/multipart-abort.d.ts.map +1 -0
  35. package/dist/procedures/s3/multipart-abort.js +33 -0
  36. package/dist/procedures/s3/multipart-abort.js.map +1 -0
  37. package/dist/procedures/s3/multipart-complete.d.ts +26 -0
  38. package/dist/procedures/s3/multipart-complete.d.ts.map +1 -0
  39. package/dist/procedures/s3/multipart-complete.js +51 -0
  40. package/dist/procedures/s3/multipart-complete.js.map +1 -0
  41. package/dist/procedures/s3/multipart-init.d.ts +24 -0
  42. package/dist/procedures/s3/multipart-init.d.ts.map +1 -0
  43. package/dist/procedures/s3/multipart-init.js +42 -0
  44. package/dist/procedures/s3/multipart-init.js.map +1 -0
  45. package/dist/procedures/s3/multipart-upload.d.ts +24 -0
  46. package/dist/procedures/s3/multipart-upload.d.ts.map +1 -0
  47. package/dist/procedures/s3/multipart-upload.js +44 -0
  48. package/dist/procedures/s3/multipart-upload.js.map +1 -0
  49. package/dist/procedures/s3/upload.d.ts +30 -0
  50. package/dist/procedures/s3/upload.d.ts.map +1 -0
  51. package/dist/procedures/s3/upload.js +50 -0
  52. package/dist/procedures/s3/upload.js.map +1 -0
  53. package/dist/register.d.ts +8 -0
  54. package/dist/register.d.ts.map +1 -0
  55. package/dist/register.js +14 -0
  56. package/dist/register.js.map +1 -0
  57. package/dist/s3-client.d.ts +38 -0
  58. package/dist/s3-client.d.ts.map +1 -0
  59. package/dist/s3-client.js +83 -0
  60. package/dist/s3-client.js.map +1 -0
  61. package/dist/types.d.ts +198 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/dist/types.js +197 -0
  64. package/dist/types.js.map +1 -0
  65. package/package.json +77 -3
  66. package/src/index.ts +73 -0
  67. package/src/module.ts +211 -0
  68. package/src/procedures/s3/delete.ts +45 -0
  69. package/src/procedures/s3/download.ts +155 -0
  70. package/src/procedures/s3/index.ts +13 -0
  71. package/src/procedures/s3/list-all.ts +63 -0
  72. package/src/procedures/s3/list.ts +63 -0
  73. package/src/procedures/s3/multipart-abort.ts +40 -0
  74. package/src/procedures/s3/multipart-complete.ts +58 -0
  75. package/src/procedures/s3/multipart-init.ts +50 -0
  76. package/src/procedures/s3/multipart-upload.ts +53 -0
  77. package/src/procedures/s3/upload.ts +56 -0
  78. package/src/register.ts +17 -0
  79. package/src/s3-client.ts +94 -0
  80. package/src/types.ts +425 -0
@@ -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,8 @@
1
+ /**
2
+ * Importing this file registers the procedures of @procedures/s3 in the global registry
3
+ * (DECISIONS-2026-10, "Every package root registers its procedures"). The procedures as data
4
+ * are in `module.ts`, which registers nothing: a host with its own registry uses that one.
5
+ */
6
+ export * from "./module.js";
7
+ export declare function registerS3Procedures(): void;
8
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,cAAc,aAAa,CAAC;AAE5B,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Importing this file registers the procedures of @procedures/s3 in the global registry
3
+ * (DECISIONS-2026-10, "Every package root registers its procedures"). The procedures as data
4
+ * are in `module.ts`, which registers nothing: a host with its own registry uses that one.
5
+ */
6
+ import { registerProcedures } from "@procedures/client";
7
+ import { s3Module } from "./module.js";
8
+ export * from "./module.js";
9
+ export function registerS3Procedures() {
10
+ registerProcedures(s3Module.procedures);
11
+ }
12
+ // Auto-register when this module is loaded
13
+ registerS3Procedures();
14
+ //# 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,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,cAAc,aAAa,CAAC;AAE5B,MAAM,UAAU,oBAAoB;IAClC,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC1C,CAAC;AAED,2CAA2C;AAC3C,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"}