Skip to content

Commit c319089

Browse files
authored
JavaScript (v3): S3 - Standardize S3 examples as per the audit. 🧵 1/2 (#6932)
1 parent 4c5489e commit c319089

File tree

55 files changed

+2026
-601
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2026
-601
lines changed

‎javascriptv3/example_code/cross-services/photo-asset-manager/tests/detect-labels-handler.unit.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ describe("detect-labels handler", () => {
1313
{
1414
s3: {
1515
bucket: {
16-
name: "my-bucket",
16+
name: "amzn-s3-demo-bucket",
1717
},
1818
object: {
1919
key: "my_image.jpeg",

‎javascriptv3/example_code/libs/tests/util-string.unit.test.js

+6
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ describe("util-string", () => {
1616
const u2 = getUniqueName(value);
1717
expect(u1).not.toEqual(u2);
1818
});
19+
20+
it("should return undefined if a falsy value is passed in", () => {
21+
expect(getUniqueName()).toBeUndefined();
22+
expect(getUniqueName("")).toBeUndefined();
23+
expect(getUniqueName(0)).toBeUndefined();
24+
});
1925
});
2026

2127
describe("postfix", () => {
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
3+
import { fileURLToPath } from "url";
34

45
export const getEnv = (/** @type {string} */ key) => process.env[key];
56
export const setEnv = (/** @type {string} */ key, value) => {
67
process.env[key] = value;
78
};
9+
10+
/**
11+
* Check if the running file was run directly.
12+
* @param {string | URL} fileUrl
13+
*/
14+
export const isMain = (fileUrl) => process.argv[1] === fileURLToPath(fileUrl);

‎javascriptv3/example_code/libs/utils/util-string.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import { v4 as uuidv4 } from "uuid";
55
/**
66
* @param {string} name
77
*/
8-
export const getUniqueName = (name) => `${uuidv4()}-${name.toLowerCase()}`;
8+
export const getUniqueName = (name) => {
9+
if (!name) {
10+
return;
11+
}
12+
13+
return `${name.toLowerCase()}-${uuidv4()}`;
14+
};
915

1016
/**
1117
* @param {int} length

‎javascriptv3/example_code/s3/README.md

+17-17
Original file line numberDiff line numberDiff line change
@@ -45,28 +45,28 @@ Code examples that show you how to perform the essential operations within a ser
4545

4646
Code excerpts that show you how to call individual service functions.
4747

48-
- [CopyObject](actions/copy-object.js#L6)
49-
- [CreateBucket](actions/create-bucket.js#L6)
48+
- [CopyObject](actions/copy-object.js#L4)
49+
- [CreateBucket](actions/create-bucket.js#L4)
5050
- [DeleteBucket](actions/delete-bucket.js#L6)
51-
- [DeleteBucketPolicy](actions/delete-bucket-policy.js#L6)
52-
- [DeleteBucketWebsite](actions/delete-bucket-website.js#L6)
53-
- [DeleteObject](actions/delete-object.js#L6)
54-
- [DeleteObjects](actions/delete-objects.js#L6)
55-
- [GetBucketAcl](actions/get-bucket-acl.js#L6)
56-
- [GetBucketCors](actions/get-bucket-cors.js#L6)
57-
- [GetBucketPolicy](actions/get-bucket-policy.js#L6)
58-
- [GetBucketWebsite](actions/get-bucket-website.js#L6)
59-
- [GetObject](actions/get-object.js#L6)
51+
- [DeleteBucketPolicy](actions/delete-bucket-policy.js#L4)
52+
- [DeleteBucketWebsite](actions/delete-bucket-website.js#L4)
53+
- [DeleteObject](actions/delete-object.js#L4)
54+
- [DeleteObjects](actions/delete-objects.js#L4)
55+
- [GetBucketAcl](actions/get-bucket-acl.js#L4)
56+
- [GetBucketCors](actions/get-bucket-cors.js#L4)
57+
- [GetBucketPolicy](actions/get-bucket-policy.js#L4)
58+
- [GetBucketWebsite](actions/get-bucket-website.js#L4)
59+
- [GetObject](actions/get-object.js#L4)
6060
- [GetObjectLegalHold](actions/get-object-legal-hold.js)
6161
- [GetObjectLockConfiguration](actions/get-object-lock-configuration.js)
6262
- [GetObjectRetention](actions/get-object-retention.js)
6363
- [ListBuckets](actions/list-buckets.js#L6)
64-
- [ListObjectsV2](actions/list-objects.js#L6)
65-
- [PutBucketAcl](actions/put-bucket-acl.js#L6)
66-
- [PutBucketCors](actions/put-bucket-cors.js#L6)
67-
- [PutBucketPolicy](actions/put-bucket-policy.js#L6)
68-
- [PutBucketWebsite](actions/put-bucket-website.js#L6)
69-
- [PutObject](actions/put-object.js#L6)
64+
- [ListObjectsV2](actions/list-objects.js#L4)
65+
- [PutBucketAcl](actions/put-bucket-acl.js#L4)
66+
- [PutBucketCors](actions/put-bucket-cors.js#L4)
67+
- [PutBucketPolicy](actions/put-bucket-policy.js#L4)
68+
- [PutBucketWebsite](actions/put-bucket-website.js#L4)
69+
- [PutObject](actions/put-object.js#L4)
7070
- [PutObjectLegalHold](actions/put-object-legal-hold.js)
7171
- [PutObjectLockConfiguration](actions/put-object-lock-configuration.js)
7272
- [PutObjectRetention](actions/put-object-retention.js)
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,81 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { fileURLToPath } from "url";
5-
64
// snippet-start:[s3.JavaScript.buckets.copyObjectV3]
7-
import { S3Client, CopyObjectCommand } from "@aws-sdk/client-s3";
8-
9-
const client = new S3Client({});
5+
import {
6+
S3Client,
7+
CopyObjectCommand,
8+
ObjectNotInActiveTierError,
9+
waitUntilObjectExists,
10+
} from "@aws-sdk/client-s3";
1011

1112
/**
12-
* Copy an Amazon S3 object from one bucket to another.
13+
* Copy an S3 object from one bucket to another.
14+
*
15+
* @param {{
16+
* sourceBucket: string,
17+
* sourceKey: string,
18+
* destinationBucket: string,
19+
* destinationKey: string }} config
1320
*/
14-
export const main = async () => {
15-
const command = new CopyObjectCommand({
16-
CopySource: "SOURCE_BUCKET/SOURCE_OBJECT_KEY",
17-
Bucket: "DESTINATION_BUCKET",
18-
Key: "NEW_OBJECT_KEY",
19-
});
21+
export const main = async ({
22+
sourceBucket,
23+
sourceKey,
24+
destinationBucket,
25+
destinationKey,
26+
}) => {
27+
const client = new S3Client({});
2028

2129
try {
22-
const response = await client.send(command);
23-
console.log(response);
24-
} catch (err) {
25-
console.error(err);
30+
await client.send(
31+
new CopyObjectCommand({
32+
CopySource: `${sourceBucket}/${sourceKey}`,
33+
Bucket: destinationBucket,
34+
Key: destinationKey,
35+
}),
36+
);
37+
await waitUntilObjectExists(
38+
{ client },
39+
{ Bucket: destinationBucket, Key: destinationKey },
40+
);
41+
console.log(
42+
`Successfully copied ${sourceBucket}/${sourceKey} to ${destinationBucket}/${destinationKey}`,
43+
);
44+
} catch (caught) {
45+
if (caught instanceof ObjectNotInActiveTierError) {
46+
console.error(
47+
`Could not copy ${sourceKey} from ${sourceBucket}. Object is not in the active tier.`,
48+
);
49+
} else {
50+
throw caught;
51+
}
2652
}
2753
};
2854
// snippet-end:[s3.JavaScript.buckets.copyObjectV3]
2955

30-
// Invoke main function if this file was run directly.
56+
// Call function if run directly
57+
import { fileURLToPath } from "url";
58+
import { parseArgs } from "util";
59+
3160
if (process.argv[1] === fileURLToPath(import.meta.url)) {
32-
main();
61+
const options = {
62+
sourceBucket: {
63+
type: "string",
64+
default: "source-bucket",
65+
},
66+
sourceKey: {
67+
type: "string",
68+
default: "todo.txt",
69+
},
70+
destinationBucket: {
71+
type: "string",
72+
default: "destination-bucket",
73+
},
74+
destinationKey: {
75+
type: "string",
76+
default: "todo.txt",
77+
},
78+
};
79+
const { values } = parseArgs({ options });
80+
main(values);
3381
}
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,64 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { fileURLToPath } from "url";
5-
64
// snippet-start:[s3.JavaScript.buckets.createBucketV3]
7-
import { CreateBucketCommand, S3Client } from "@aws-sdk/client-s3";
8-
9-
const client = new S3Client({});
5+
import {
6+
BucketAlreadyExists,
7+
BucketAlreadyOwnedByYou,
8+
CreateBucketCommand,
9+
S3Client,
10+
waitUntilBucketExists,
11+
} from "@aws-sdk/client-s3";
1012

11-
export const main = async () => {
12-
const command = new CreateBucketCommand({
13-
// The name of the bucket. Bucket names are unique and have several other constraints.
14-
// See https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html
15-
Bucket: "bucket-name",
16-
});
13+
/**
14+
* Create an Amazon S3 bucket.
15+
* @param {{ bucketName: string }} config
16+
*/
17+
export const main = async ({ bucketName }) => {
18+
const client = new S3Client({});
1719

1820
try {
19-
const { Location } = await client.send(command);
21+
const { Location } = await client.send(
22+
new CreateBucketCommand({
23+
// The name of the bucket. Bucket names are unique and have several other constraints.
24+
// See https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html
25+
Bucket: bucketName,
26+
}),
27+
);
28+
await waitUntilBucketExists({ client }, { Bucket: bucketName });
2029
console.log(`Bucket created with location ${Location}`);
21-
} catch (err) {
22-
console.error(err);
30+
} catch (caught) {
31+
if (caught instanceof BucketAlreadyExists) {
32+
console.error(
33+
`The bucket "${bucketName}" already exists in another AWS account. Bucket names must be globally unique.`,
34+
);
35+
}
36+
// WARNING: If you try to create a bucket in the North Virginia region,
37+
// and you already own a bucket in that region with the same name, this
38+
// error will not be thrown. Instead, the call will return successfully
39+
// and the ACL on that bucket will be reset.
40+
else if (caught instanceof BucketAlreadyOwnedByYou) {
41+
console.error(
42+
`The bucket "${bucketName}" already exists in this AWS account.`,
43+
);
44+
} else {
45+
throw caught;
46+
}
2347
}
2448
};
2549
// snippet-end:[s3.JavaScript.buckets.createBucketV3]
2650

27-
// Invoke main function if this file was run directly.
51+
// Call function if run directly
52+
import { fileURLToPath } from "url";
53+
import { parseArgs } from "util";
54+
2855
if (process.argv[1] === fileURLToPath(import.meta.url)) {
29-
main();
56+
const options = {
57+
bucketName: {
58+
type: "string",
59+
default: "bucket-name",
60+
},
61+
};
62+
const { values } = parseArgs({ options });
63+
main(values);
3064
}
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,57 @@
11
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { fileURLToPath } from "url";
5-
64
// snippet-start:[s3.JavaScript.policy.deleteBucketPolicyV3]
7-
import { DeleteBucketPolicyCommand, S3Client } from "@aws-sdk/client-s3";
8-
9-
const client = new S3Client({});
5+
import {
6+
DeleteBucketPolicyCommand,
7+
S3Client,
8+
S3ServiceException,
9+
} from "@aws-sdk/client-s3";
1010

11-
// This will remove the policy from the bucket.
12-
export const main = async () => {
13-
const command = new DeleteBucketPolicyCommand({
14-
Bucket: "test-bucket",
15-
});
11+
/**
12+
* Remove the policy from an Amazon S3 bucket.
13+
* @param {{ bucketName: string }}
14+
*/
15+
export const main = async ({ bucketName }) => {
16+
const client = new S3Client({});
1617

1718
try {
18-
const response = await client.send(command);
19-
console.log(response);
20-
} catch (err) {
21-
console.error(err);
19+
await client.send(
20+
new DeleteBucketPolicyCommand({
21+
Bucket: bucketName,
22+
}),
23+
);
24+
console.log(`Bucket policy deleted from "${bucketName}".`);
25+
} catch (caught) {
26+
if (
27+
caught instanceof S3ServiceException &&
28+
caught.name === "NoSuchBucket"
29+
) {
30+
console.error(
31+
`Error from S3 while deleting policy from ${bucketName}. The bucket doesn't exist.`,
32+
);
33+
} else if (caught instanceof S3ServiceException) {
34+
console.error(
35+
`Error from S3 while deleting policy from ${bucketName}. ${caught.name}: ${caught.message}`,
36+
);
37+
} else {
38+
throw caught;
39+
}
2240
}
2341
};
2442
// snippet-end:[s3.JavaScript.policy.deleteBucketPolicyV3]
2543

26-
// Invoke main function if this file was run directly.
44+
// Call function if run directly
45+
import { fileURLToPath } from "url";
46+
import { parseArgs } from "util";
47+
2748
if (process.argv[1] === fileURLToPath(import.meta.url)) {
28-
main();
49+
const options = {
50+
bucketName: {
51+
type: "string",
52+
default: "amzn-s3-demo-bucket",
53+
},
54+
};
55+
const { values } = parseArgs({ options });
56+
main(values);
2957
}

0 commit comments

Comments
 (0)