chub-dev 0.1.0 → 0.1.2-beta.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 (139) hide show
  1. package/README.md +55 -0
  2. package/bin/chub-mcp +2 -0
  3. package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
  4. package/dist/airtable/docs/database/python/DOC.md +1735 -0
  5. package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
  6. package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
  7. package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
  8. package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
  9. package/dist/asana/docs/tasks/DOC.md +1396 -0
  10. package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
  11. package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
  12. package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
  13. package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
  14. package/dist/auth0/docs/identity/python/DOC.md +1199 -0
  15. package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
  16. package/dist/aws/docs/s3/python/DOC.md +1807 -0
  17. package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
  18. package/dist/binance/docs/trading/python/DOC.md +1454 -0
  19. package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
  20. package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
  21. package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
  22. package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
  23. package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
  24. package/dist/clerk/docs/auth/python/DOC.md +274 -0
  25. package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
  26. package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
  27. package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
  28. package/dist/cohere/docs/llm/DOC.md +1335 -0
  29. package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
  30. package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
  31. package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
  32. package/dist/deepgram/docs/speech/python/DOC.md +685 -0
  33. package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
  34. package/dist/deepl/docs/translation/python/DOC.md +944 -0
  35. package/dist/deepseek/docs/llm/DOC.md +1220 -0
  36. package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
  37. package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
  38. package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
  39. package/dist/discord/docs/bot/python/DOC.md +1130 -0
  40. package/dist/elasticsearch/docs/search/DOC.md +1634 -0
  41. package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
  42. package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
  43. package/dist/firebase/docs/auth/DOC.md +1015 -0
  44. package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
  45. package/dist/gemini/docs/genai/python/DOC.md +555 -0
  46. package/dist/github/docs/octokit/DOC.md +1560 -0
  47. package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
  48. package/dist/google/docs/bigquery/python/DOC.md +1503 -0
  49. package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
  50. package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
  51. package/dist/huggingface/docs/transformers/DOC.md +948 -0
  52. package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
  53. package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
  54. package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
  55. package/dist/jira/docs/issues/python/DOC.md +1492 -0
  56. package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
  57. package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
  58. package/dist/landingai-ade/docs/api/DOC.md +620 -0
  59. package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
  60. package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
  61. package/dist/landingai-ade/skills/SKILL.md +489 -0
  62. package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
  63. package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
  64. package/dist/linear/docs/tracker/DOC.md +1554 -0
  65. package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
  66. package/dist/livekit/docs/realtime/python/DOC.md +163 -0
  67. package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
  68. package/dist/meilisearch/docs/search/DOC.md +1241 -0
  69. package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
  70. package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
  71. package/dist/mongodb/docs/atlas/DOC.md +2041 -0
  72. package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
  73. package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
  74. package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
  75. package/dist/okta/docs/identity/python/DOC.md +1401 -0
  76. package/dist/openai/docs/chat/javascript/DOC.md +407 -0
  77. package/dist/openai/docs/chat/python/DOC.md +568 -0
  78. package/dist/paypal/docs/checkout/DOC.md +278 -0
  79. package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
  80. package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
  81. package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
  82. package/dist/plaid/docs/banking/python/DOC.md +1203 -0
  83. package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
  84. package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
  85. package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
  86. package/dist/prisma/docs/orm/python/DOC.md +1317 -0
  87. package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
  88. package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
  89. package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
  90. package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
  91. package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
  92. package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
  93. package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
  94. package/dist/redis/docs/key-value/python/DOC.md +2054 -0
  95. package/dist/registry.json +2817 -0
  96. package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
  97. package/dist/resend/docs/email/DOC.md +1271 -0
  98. package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
  99. package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
  100. package/dist/search-index.json +1 -0
  101. package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
  102. package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
  103. package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
  104. package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
  105. package/dist/shopify/docs/storefront/DOC.md +457 -0
  106. package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
  107. package/dist/slack/docs/workspace/python/DOC.md +271 -0
  108. package/dist/square/docs/payments/javascript/DOC.md +1855 -0
  109. package/dist/square/docs/payments/python/DOC.md +1728 -0
  110. package/dist/stripe/docs/api/DOC.md +1727 -0
  111. package/dist/stripe/docs/payments/DOC.md +1726 -0
  112. package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
  113. package/dist/stytch/docs/auth/python/DOC.md +1962 -0
  114. package/dist/supabase/docs/client/DOC.md +1606 -0
  115. package/dist/twilio/docs/messaging/python/DOC.md +469 -0
  116. package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
  117. package/dist/vercel/docs/platform/DOC.md +1940 -0
  118. package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
  119. package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
  120. package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
  121. package/dist/zendesk/docs/support/python/DOC.md +2297 -0
  122. package/package.json +22 -6
  123. package/skills/get-api-docs/SKILL.md +84 -0
  124. package/src/commands/annotate.js +83 -0
  125. package/src/commands/build.js +12 -1
  126. package/src/commands/feedback.js +150 -0
  127. package/src/commands/get.js +83 -42
  128. package/src/commands/search.js +7 -0
  129. package/src/index.js +43 -17
  130. package/src/lib/analytics.js +90 -0
  131. package/src/lib/annotations.js +57 -0
  132. package/src/lib/bm25.js +170 -0
  133. package/src/lib/cache.js +69 -6
  134. package/src/lib/config.js +8 -3
  135. package/src/lib/identity.js +99 -0
  136. package/src/lib/registry.js +103 -20
  137. package/src/lib/telemetry.js +86 -0
  138. package/src/mcp/server.js +177 -0
  139. package/src/mcp/tools.js +251 -0
@@ -0,0 +1,1773 @@
1
+ ---
2
+ name: s3
3
+ description: "AWS S3 SDK for JavaScript (v3) - Complete guide for S3 operations in JavaScript/Node.js projects"
4
+ metadata:
5
+ languages: "javascript"
6
+ versions: "3.917.0"
7
+ updated-on: "2026-03-02"
8
+ source: maintainer
9
+ tags: "aws,s3,storage,cloud,bucket"
10
+ ---
11
+
12
+ # AWS S3 SDK for JavaScript (v3) - Complete Guide
13
+
14
+ ## Golden Rule
15
+
16
+ **ALWAYS use `@aws-sdk/client-s3` for AWS S3 operations in JavaScript/Node.js projects.**
17
+
18
+ ```bash
19
+ npm install @aws-sdk/client-s3
20
+ ```
21
+
22
+ **DO NOT use:**
23
+ - `aws-sdk` (v2) - End-of-support on September 8, 2025
24
+ - Any unofficial S3 libraries
25
+
26
+ The AWS SDK for JavaScript v3 (`@aws-sdk/client-s3`) is the official, maintained SDK. It uses a modular architecture that reduces bundle size and improves performance.
27
+
28
+ ---
29
+
30
+ ## Installation
31
+
32
+ ### Basic Installation
33
+
34
+ ```bash
35
+ npm install @aws-sdk/client-s3
36
+ ```
37
+
38
+ ### Additional Packages for Advanced Features
39
+
40
+ ```bash
41
+ # For presigned URLs
42
+ npm install @aws-sdk/s3-request-presigner
43
+
44
+ # For multipart uploads (large files)
45
+ npm install @aws-sdk/lib-storage
46
+
47
+ # For credential providers
48
+ npm install @aws-sdk/credential-providers
49
+ ```
50
+
51
+ ### Environment Variables
52
+
53
+ Create a `.env` file:
54
+
55
+ ```env
56
+ AWS_ACCESS_KEY_ID=your_access_key_id
57
+ AWS_SECRET_ACCESS_KEY=your_secret_access_key
58
+ AWS_REGION=us-east-1
59
+ AWS_S3_BUCKET=your-bucket-name
60
+ ```
61
+
62
+ Load environment variables in your code:
63
+
64
+ ```javascript
65
+ import dotenv from 'dotenv';
66
+ dotenv.config();
67
+
68
+ const REGION = process.env.AWS_REGION;
69
+ const BUCKET = process.env.AWS_S3_BUCKET;
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Initialization
75
+
76
+ ### Basic Client Setup
77
+
78
+ ```javascript
79
+ import { S3Client } from "@aws-sdk/client-s3";
80
+
81
+ // Default credentials from environment variables or AWS config files
82
+ const client = new S3Client({});
83
+ ```
84
+
85
+ ### Client with Region
86
+
87
+ ```javascript
88
+ import { S3Client } from "@aws-sdk/client-s3";
89
+
90
+ const client = new S3Client({
91
+ region: "us-east-1"
92
+ });
93
+ ```
94
+
95
+ ### Client with Explicit Credentials
96
+
97
+ ```javascript
98
+ import { S3Client } from "@aws-sdk/client-s3";
99
+
100
+ const client = new S3Client({
101
+ region: "us-east-1",
102
+ credentials: {
103
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
104
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
105
+ },
106
+ });
107
+ ```
108
+
109
+ ### Client with Cognito (Browser/Frontend)
110
+
111
+ ```javascript
112
+ import { S3Client } from "@aws-sdk/client-s3";
113
+ import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";
114
+
115
+ const client = new S3Client({
116
+ region: "us-east-1",
117
+ credentials: fromCognitoIdentityPool({
118
+ clientConfig: { region: "us-east-1" },
119
+ identityPoolId: "us-east-1:your-identity-pool-id",
120
+ }),
121
+ });
122
+ ```
123
+
124
+ ### Client with Custom Endpoint (LocalStack, MinIO)
125
+
126
+ ```javascript
127
+ import { S3Client } from "@aws-sdk/client-s3";
128
+
129
+ const client = new S3Client({
130
+ region: "us-east-1",
131
+ endpoint: "http://localhost:4566",
132
+ forcePathStyle: true,
133
+ credentials: {
134
+ accessKeyId: "test",
135
+ secretAccessKey: "test",
136
+ },
137
+ });
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Bucket Operations
143
+
144
+ ### List All Buckets
145
+
146
+ ```javascript
147
+ import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3";
148
+
149
+ const client = new S3Client({});
150
+
151
+ async function listBuckets() {
152
+ try {
153
+ const response = await client.send(new ListBucketsCommand({}));
154
+ console.log("Buckets:");
155
+ response.Buckets.forEach((bucket) => {
156
+ console.log(` • ${bucket.Name} (Created: ${bucket.CreationDate})`);
157
+ });
158
+ } catch (error) {
159
+ console.error("Error listing buckets:", error);
160
+ }
161
+ }
162
+ ```
163
+
164
+ ### Create Bucket
165
+
166
+ ```javascript
167
+ import {
168
+ S3Client,
169
+ CreateBucketCommand,
170
+ waitUntilBucketExists
171
+ } from "@aws-sdk/client-s3";
172
+
173
+ const client = new S3Client({ region: "us-east-1" });
174
+
175
+ async function createBucket(bucketName) {
176
+ try {
177
+ const response = await client.send(
178
+ new CreateBucketCommand({
179
+ Bucket: bucketName,
180
+ })
181
+ );
182
+
183
+ // Wait until bucket exists
184
+ await waitUntilBucketExists(
185
+ { client, maxWaitTime: 60 },
186
+ { Bucket: bucketName }
187
+ );
188
+
189
+ console.log(`Bucket created: ${response.Location}`);
190
+ } catch (error) {
191
+ console.error("Error creating bucket:", error);
192
+ }
193
+ }
194
+ ```
195
+
196
+ ### Create Bucket in Specific Region
197
+
198
+ ```javascript
199
+ import { S3Client, CreateBucketCommand } from "@aws-sdk/client-s3";
200
+
201
+ const client = new S3Client({ region: "us-west-2" });
202
+
203
+ async function createBucketInRegion(bucketName, region) {
204
+ try {
205
+ const params = {
206
+ Bucket: bucketName,
207
+ };
208
+
209
+ // us-east-1 doesn't require LocationConstraint
210
+ if (region !== "us-east-1") {
211
+ params.CreateBucketConfiguration = {
212
+ LocationConstraint: region,
213
+ };
214
+ }
215
+
216
+ await client.send(new CreateBucketCommand(params));
217
+ console.log(`Bucket created in ${region}`);
218
+ } catch (error) {
219
+ console.error("Error creating bucket:", error);
220
+ }
221
+ }
222
+ ```
223
+
224
+ ### Delete Bucket
225
+
226
+ ```javascript
227
+ import {
228
+ S3Client,
229
+ DeleteBucketCommand,
230
+ waitUntilBucketNotExists
231
+ } from "@aws-sdk/client-s3";
232
+
233
+ const client = new S3Client({});
234
+
235
+ async function deleteBucket(bucketName) {
236
+ try {
237
+ await client.send(new DeleteBucketCommand({ Bucket: bucketName }));
238
+
239
+ await waitUntilBucketNotExists(
240
+ { client, maxWaitTime: 60 },
241
+ { Bucket: bucketName }
242
+ );
243
+
244
+ console.log(`Bucket deleted: ${bucketName}`);
245
+ } catch (error) {
246
+ console.error("Error deleting bucket:", error);
247
+ }
248
+ }
249
+ ```
250
+
251
+ ### Check if Bucket Exists
252
+
253
+ ```javascript
254
+ import { S3Client, HeadBucketCommand } from "@aws-sdk/client-s3";
255
+
256
+ const client = new S3Client({});
257
+
258
+ async function bucketExists(bucketName) {
259
+ try {
260
+ await client.send(new HeadBucketCommand({ Bucket: bucketName }));
261
+ return true;
262
+ } catch (error) {
263
+ if (error.name === "NotFound") {
264
+ return false;
265
+ }
266
+ throw error;
267
+ }
268
+ }
269
+ ```
270
+
271
+ ---
272
+
273
+ ## Object Upload Operations
274
+
275
+ ### Upload File from Disk
276
+
277
+ ```javascript
278
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
279
+ import { readFile } from "node:fs/promises";
280
+
281
+ const client = new S3Client({});
282
+
283
+ async function uploadFile(bucketName, key, filePath) {
284
+ try {
285
+ const fileContent = await readFile(filePath);
286
+
287
+ const response = await client.send(
288
+ new PutObjectCommand({
289
+ Bucket: bucketName,
290
+ Key: key,
291
+ Body: fileContent,
292
+ })
293
+ );
294
+
295
+ console.log("Upload successful:", response.ETag);
296
+ } catch (error) {
297
+ console.error("Upload error:", error);
298
+ }
299
+ }
300
+ ```
301
+
302
+ ### Upload with Content Type
303
+
304
+ ```javascript
305
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
306
+ import { readFile } from "node:fs/promises";
307
+
308
+ const client = new S3Client({});
309
+
310
+ async function uploadWithContentType(bucketName, key, filePath, contentType) {
311
+ try {
312
+ const fileContent = await readFile(filePath);
313
+
314
+ await client.send(
315
+ new PutObjectCommand({
316
+ Bucket: bucketName,
317
+ Key: key,
318
+ Body: fileContent,
319
+ ContentType: contentType,
320
+ })
321
+ );
322
+
323
+ console.log(`Uploaded ${key} as ${contentType}`);
324
+ } catch (error) {
325
+ console.error("Upload error:", error);
326
+ }
327
+ }
328
+
329
+ // Usage
330
+ await uploadWithContentType(
331
+ "my-bucket",
332
+ "images/photo.jpg",
333
+ "./photo.jpg",
334
+ "image/jpeg"
335
+ );
336
+ ```
337
+
338
+ ### Upload String/Buffer
339
+
340
+ ```javascript
341
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
342
+
343
+ const client = new S3Client({});
344
+
345
+ async function uploadString(bucketName, key, content) {
346
+ try {
347
+ await client.send(
348
+ new PutObjectCommand({
349
+ Bucket: bucketName,
350
+ Key: key,
351
+ Body: content,
352
+ ContentType: "text/plain",
353
+ })
354
+ );
355
+
356
+ console.log(`Uploaded text to ${key}`);
357
+ } catch (error) {
358
+ console.error("Upload error:", error);
359
+ }
360
+ }
361
+
362
+ // Upload JSON
363
+ async function uploadJSON(bucketName, key, data) {
364
+ try {
365
+ await client.send(
366
+ new PutObjectCommand({
367
+ Bucket: bucketName,
368
+ Key: key,
369
+ Body: JSON.stringify(data),
370
+ ContentType: "application/json",
371
+ })
372
+ );
373
+
374
+ console.log(`Uploaded JSON to ${key}`);
375
+ } catch (error) {
376
+ console.error("Upload error:", error);
377
+ }
378
+ }
379
+ ```
380
+
381
+ ### Upload with Metadata
382
+
383
+ ```javascript
384
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
385
+
386
+ const client = new S3Client({});
387
+
388
+ async function uploadWithMetadata(bucketName, key, body) {
389
+ try {
390
+ await client.send(
391
+ new PutObjectCommand({
392
+ Bucket: bucketName,
393
+ Key: key,
394
+ Body: body,
395
+ Metadata: {
396
+ "uploaded-by": "user123",
397
+ "original-name": "document.pdf",
398
+ "category": "reports",
399
+ },
400
+ })
401
+ );
402
+
403
+ console.log("Uploaded with metadata");
404
+ } catch (error) {
405
+ console.error("Upload error:", error);
406
+ }
407
+ }
408
+ ```
409
+
410
+ ### Upload with Server-Side Encryption
411
+
412
+ ```javascript
413
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
414
+
415
+ const client = new S3Client({});
416
+
417
+ async function uploadEncrypted(bucketName, key, body) {
418
+ try {
419
+ await client.send(
420
+ new PutObjectCommand({
421
+ Bucket: bucketName,
422
+ Key: key,
423
+ Body: body,
424
+ ServerSideEncryption: "AES256",
425
+ })
426
+ );
427
+
428
+ console.log("Uploaded with encryption");
429
+ } catch (error) {
430
+ console.error("Upload error:", error);
431
+ }
432
+ }
433
+ ```
434
+
435
+ ### Batch Upload Multiple Files
436
+
437
+ ```javascript
438
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
439
+ import { readdirSync, readFileSync } from "node:fs";
440
+ import { join } from "node:path";
441
+
442
+ const client = new S3Client({});
443
+
444
+ async function uploadDirectory(bucketName, folderPath, s3Prefix = "") {
445
+ try {
446
+ const files = readdirSync(folderPath);
447
+
448
+ for (const file of files) {
449
+ const filePath = join(folderPath, file);
450
+ const fileContent = readFileSync(filePath);
451
+ const s3Key = s3Prefix ? `${s3Prefix}/${file}` : file;
452
+
453
+ await client.send(
454
+ new PutObjectCommand({
455
+ Bucket: bucketName,
456
+ Key: s3Key,
457
+ Body: fileContent,
458
+ })
459
+ );
460
+
461
+ console.log(`Uploaded: ${s3Key}`);
462
+ }
463
+
464
+ console.log(`Uploaded ${files.length} files`);
465
+ } catch (error) {
466
+ console.error("Batch upload error:", error);
467
+ }
468
+ }
469
+ ```
470
+
471
+ ---
472
+
473
+ ## Object Download Operations
474
+
475
+ ### Download File to Disk
476
+
477
+ ```javascript
478
+ import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
479
+ import { writeFile } from "node:fs/promises";
480
+
481
+ const client = new S3Client({});
482
+
483
+ async function downloadFile(bucketName, key, destinationPath) {
484
+ try {
485
+ const response = await client.send(
486
+ new GetObjectCommand({
487
+ Bucket: bucketName,
488
+ Key: key,
489
+ })
490
+ );
491
+
492
+ const fileContent = await response.Body.transformToByteArray();
493
+ await writeFile(destinationPath, fileContent);
494
+
495
+ console.log(`Downloaded to ${destinationPath}`);
496
+ } catch (error) {
497
+ console.error("Download error:", error);
498
+ }
499
+ }
500
+ ```
501
+
502
+ ### Download as String
503
+
504
+ ```javascript
505
+ import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
506
+
507
+ const client = new S3Client({});
508
+
509
+ async function downloadAsString(bucketName, key) {
510
+ try {
511
+ const response = await client.send(
512
+ new GetObjectCommand({
513
+ Bucket: bucketName,
514
+ Key: key,
515
+ })
516
+ );
517
+
518
+ const content = await response.Body.transformToString();
519
+ return content;
520
+ } catch (error) {
521
+ console.error("Download error:", error);
522
+ throw error;
523
+ }
524
+ }
525
+
526
+ // Download JSON
527
+ async function downloadJSON(bucketName, key) {
528
+ const content = await downloadAsString(bucketName, key);
529
+ return JSON.parse(content);
530
+ }
531
+ ```
532
+
533
+ ### Download with Error Handling
534
+
535
+ ```javascript
536
+ import {
537
+ S3Client,
538
+ GetObjectCommand,
539
+ NoSuchKey
540
+ } from "@aws-sdk/client-s3";
541
+
542
+ const client = new S3Client({});
543
+
544
+ async function downloadSafe(bucketName, key) {
545
+ try {
546
+ const response = await client.send(
547
+ new GetObjectCommand({
548
+ Bucket: bucketName,
549
+ Key: key,
550
+ })
551
+ );
552
+
553
+ return await response.Body.transformToString();
554
+ } catch (error) {
555
+ if (error instanceof NoSuchKey) {
556
+ console.error(`Key does not exist: ${key}`);
557
+ return null;
558
+ }
559
+ throw error;
560
+ }
561
+ }
562
+ ```
563
+
564
+ ### Download Byte Range
565
+
566
+ ```javascript
567
+ import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
568
+
569
+ const client = new S3Client({});
570
+
571
+ async function downloadRange(bucketName, key, start, end) {
572
+ try {
573
+ const response = await client.send(
574
+ new GetObjectCommand({
575
+ Bucket: bucketName,
576
+ Key: key,
577
+ Range: `bytes=${start}-${end}`,
578
+ })
579
+ );
580
+
581
+ return await response.Body.transformToByteArray();
582
+ } catch (error) {
583
+ console.error("Download error:", error);
584
+ }
585
+ }
586
+ ```
587
+
588
+ ### Get Object Metadata Only
589
+
590
+ ```javascript
591
+ import { S3Client, HeadObjectCommand } from "@aws-sdk/client-s3";
592
+
593
+ const client = new S3Client({});
594
+
595
+ async function getObjectMetadata(bucketName, key) {
596
+ try {
597
+ const response = await client.send(
598
+ new HeadObjectCommand({
599
+ Bucket: bucketName,
600
+ Key: key,
601
+ })
602
+ );
603
+
604
+ console.log("Metadata:", {
605
+ ContentType: response.ContentType,
606
+ ContentLength: response.ContentLength,
607
+ LastModified: response.LastModified,
608
+ ETag: response.ETag,
609
+ Metadata: response.Metadata,
610
+ });
611
+
612
+ return response;
613
+ } catch (error) {
614
+ console.error("Metadata error:", error);
615
+ }
616
+ }
617
+ ```
618
+
619
+ ---
620
+
621
+ ## List Objects
622
+
623
+ ### List All Objects (Paginated)
624
+
625
+ ```javascript
626
+ import { S3Client, paginateListObjectsV2 } from "@aws-sdk/client-s3";
627
+
628
+ const client = new S3Client({});
629
+
630
+ async function listAllObjects(bucketName) {
631
+ try {
632
+ const paginator = paginateListObjectsV2(
633
+ { client },
634
+ { Bucket: bucketName }
635
+ );
636
+
637
+ let totalObjects = 0;
638
+
639
+ for await (const page of paginator) {
640
+ if (page.Contents) {
641
+ page.Contents.forEach((obj) => {
642
+ console.log(` • ${obj.Key} (${obj.Size} bytes)`);
643
+ totalObjects++;
644
+ });
645
+ }
646
+ }
647
+
648
+ console.log(`\nTotal objects: ${totalObjects}`);
649
+ } catch (error) {
650
+ console.error("List error:", error);
651
+ }
652
+ }
653
+ ```
654
+
655
+ ### List Objects with Prefix
656
+
657
+ ```javascript
658
+ import { S3Client, paginateListObjectsV2 } from "@aws-sdk/client-s3";
659
+
660
+ const client = new S3Client({});
661
+
662
+ async function listObjectsWithPrefix(bucketName, prefix) {
663
+ try {
664
+ const paginator = paginateListObjectsV2(
665
+ { client },
666
+ {
667
+ Bucket: bucketName,
668
+ Prefix: prefix,
669
+ }
670
+ );
671
+
672
+ for await (const page of paginator) {
673
+ if (page.Contents) {
674
+ page.Contents.forEach((obj) => {
675
+ console.log(` • ${obj.Key}`);
676
+ });
677
+ }
678
+ }
679
+ } catch (error) {
680
+ console.error("List error:", error);
681
+ }
682
+ }
683
+ ```
684
+
685
+ ### List Objects with Custom Page Size
686
+
687
+ ```javascript
688
+ import { S3Client, paginateListObjectsV2 } from "@aws-sdk/client-s3";
689
+
690
+ const client = new S3Client({});
691
+
692
+ async function listObjectsPaged(bucketName, pageSize = 10) {
693
+ try {
694
+ const paginator = paginateListObjectsV2(
695
+ { client, pageSize },
696
+ { Bucket: bucketName }
697
+ );
698
+
699
+ let pageNumber = 1;
700
+
701
+ for await (const page of paginator) {
702
+ console.log(`\nPage ${pageNumber}:`);
703
+
704
+ if (page.Contents) {
705
+ page.Contents.forEach((obj) => {
706
+ console.log(` • ${obj.Key}`);
707
+ });
708
+ }
709
+
710
+ pageNumber++;
711
+ }
712
+ } catch (error) {
713
+ console.error("List error:", error);
714
+ }
715
+ }
716
+ ```
717
+
718
+ ### List Objects (Non-Paginated)
719
+
720
+ ```javascript
721
+ import { S3Client, ListObjectsV2Command } from "@aws-sdk/client-s3";
722
+
723
+ const client = new S3Client({});
724
+
725
+ async function listObjectsSimple(bucketName, maxKeys = 1000) {
726
+ try {
727
+ const response = await client.send(
728
+ new ListObjectsV2Command({
729
+ Bucket: bucketName,
730
+ MaxKeys: maxKeys,
731
+ })
732
+ );
733
+
734
+ if (response.Contents) {
735
+ response.Contents.forEach((obj) => {
736
+ console.log(` • ${obj.Key}`);
737
+ });
738
+ }
739
+
740
+ console.log(`Listed ${response.KeyCount} objects`);
741
+ console.log(`Truncated: ${response.IsTruncated}`);
742
+ } catch (error) {
743
+ console.error("List error:", error);
744
+ }
745
+ }
746
+ ```
747
+
748
+ ### List Objects in Folder Structure
749
+
750
+ ```javascript
751
+ import { S3Client, ListObjectsV2Command } from "@aws-sdk/client-s3";
752
+
753
+ const client = new S3Client({});
754
+
755
+ async function listFolder(bucketName, prefix) {
756
+ try {
757
+ const response = await client.send(
758
+ new ListObjectsV2Command({
759
+ Bucket: bucketName,
760
+ Prefix: prefix,
761
+ Delimiter: "/",
762
+ })
763
+ );
764
+
765
+ console.log("Folders:");
766
+ if (response.CommonPrefixes) {
767
+ response.CommonPrefixes.forEach((cp) => {
768
+ console.log(` 📁 ${cp.Prefix}`);
769
+ });
770
+ }
771
+
772
+ console.log("\nFiles:");
773
+ if (response.Contents) {
774
+ response.Contents.forEach((obj) => {
775
+ console.log(` 📄 ${obj.Key}`);
776
+ });
777
+ }
778
+ } catch (error) {
779
+ console.error("List error:", error);
780
+ }
781
+ }
782
+ ```
783
+
784
+ ---
785
+
786
+ ## Delete Operations
787
+
788
+ ### Delete Single Object
789
+
790
+ ```javascript
791
+ import {
792
+ S3Client,
793
+ DeleteObjectCommand,
794
+ waitUntilObjectNotExists
795
+ } from "@aws-sdk/client-s3";
796
+
797
+ const client = new S3Client({});
798
+
799
+ async function deleteObject(bucketName, key) {
800
+ try {
801
+ await client.send(
802
+ new DeleteObjectCommand({
803
+ Bucket: bucketName,
804
+ Key: key,
805
+ })
806
+ );
807
+
808
+ await waitUntilObjectNotExists(
809
+ { client, maxWaitTime: 60 },
810
+ { Bucket: bucketName, Key: key }
811
+ );
812
+
813
+ console.log(`Deleted: ${key}`);
814
+ } catch (error) {
815
+ console.error("Delete error:", error);
816
+ }
817
+ }
818
+ ```
819
+
820
+ ### Delete Multiple Objects (Batch)
821
+
822
+ ```javascript
823
+ import { S3Client, DeleteObjectsCommand } from "@aws-sdk/client-s3";
824
+
825
+ const client = new S3Client({});
826
+
827
+ async function deleteMultipleObjects(bucketName, keys) {
828
+ try {
829
+ const response = await client.send(
830
+ new DeleteObjectsCommand({
831
+ Bucket: bucketName,
832
+ Delete: {
833
+ Objects: keys.map((key) => ({ Key: key })),
834
+ },
835
+ })
836
+ );
837
+
838
+ if (response.Deleted) {
839
+ console.log(`Deleted ${response.Deleted.length} objects:`);
840
+ response.Deleted.forEach((obj) => {
841
+ console.log(` • ${obj.Key}`);
842
+ });
843
+ }
844
+
845
+ if (response.Errors) {
846
+ console.error("Errors:", response.Errors);
847
+ }
848
+ } catch (error) {
849
+ console.error("Batch delete error:", error);
850
+ }
851
+ }
852
+
853
+ // Usage
854
+ await deleteMultipleObjects("my-bucket", [
855
+ "file1.txt",
856
+ "file2.txt",
857
+ "folder/file3.txt",
858
+ ]);
859
+ ```
860
+
861
+ ### Delete All Objects with Prefix
862
+
863
+ ```javascript
864
+ import {
865
+ S3Client,
866
+ ListObjectsV2Command,
867
+ DeleteObjectsCommand
868
+ } from "@aws-sdk/client-s3";
869
+
870
+ const client = new S3Client({});
871
+
872
+ async function deleteObjectsWithPrefix(bucketName, prefix) {
873
+ try {
874
+ const listResponse = await client.send(
875
+ new ListObjectsV2Command({
876
+ Bucket: bucketName,
877
+ Prefix: prefix,
878
+ })
879
+ );
880
+
881
+ if (!listResponse.Contents || listResponse.Contents.length === 0) {
882
+ console.log("No objects to delete");
883
+ return;
884
+ }
885
+
886
+ const deleteResponse = await client.send(
887
+ new DeleteObjectsCommand({
888
+ Bucket: bucketName,
889
+ Delete: {
890
+ Objects: listResponse.Contents.map((obj) => ({ Key: obj.Key })),
891
+ },
892
+ })
893
+ );
894
+
895
+ console.log(`Deleted ${deleteResponse.Deleted.length} objects`);
896
+ } catch (error) {
897
+ console.error("Delete error:", error);
898
+ }
899
+ }
900
+ ```
901
+
902
+ ### Empty and Delete Bucket
903
+
904
+ ```javascript
905
+ import {
906
+ S3Client,
907
+ ListObjectsV2Command,
908
+ DeleteObjectsCommand,
909
+ DeleteBucketCommand
910
+ } from "@aws-sdk/client-s3";
911
+
912
+ const client = new S3Client({});
913
+
914
+ async function emptyAndDeleteBucket(bucketName) {
915
+ try {
916
+ // List all objects
917
+ const listResponse = await client.send(
918
+ new ListObjectsV2Command({ Bucket: bucketName })
919
+ );
920
+
921
+ // Delete all objects if any exist
922
+ if (listResponse.Contents && listResponse.Contents.length > 0) {
923
+ await client.send(
924
+ new DeleteObjectsCommand({
925
+ Bucket: bucketName,
926
+ Delete: {
927
+ Objects: listResponse.Contents.map((obj) => ({ Key: obj.Key })),
928
+ },
929
+ })
930
+ );
931
+
932
+ console.log(`Deleted ${listResponse.Contents.length} objects`);
933
+ }
934
+
935
+ // Delete the bucket
936
+ await client.send(new DeleteBucketCommand({ Bucket: bucketName }));
937
+ console.log(`Bucket deleted: ${bucketName}`);
938
+ } catch (error) {
939
+ console.error("Error:", error);
940
+ }
941
+ }
942
+ ```
943
+
944
+ ---
945
+
946
+ ## Copy and Move Operations
947
+
948
+ ### Copy Object
949
+
950
+ ```javascript
951
+ import { S3Client, CopyObjectCommand } from "@aws-sdk/client-s3";
952
+
953
+ const client = new S3Client({});
954
+
955
+ async function copyObject(sourceBucket, sourceKey, destBucket, destKey) {
956
+ try {
957
+ await client.send(
958
+ new CopyObjectCommand({
959
+ CopySource: `${sourceBucket}/${sourceKey}`,
960
+ Bucket: destBucket,
961
+ Key: destKey,
962
+ })
963
+ );
964
+
965
+ console.log(`Copied ${sourceKey} to ${destKey}`);
966
+ } catch (error) {
967
+ console.error("Copy error:", error);
968
+ }
969
+ }
970
+ ```
971
+
972
+ ### Move Object (Copy + Delete)
973
+
974
+ ```javascript
975
+ import {
976
+ S3Client,
977
+ CopyObjectCommand,
978
+ DeleteObjectCommand
979
+ } from "@aws-sdk/client-s3";
980
+
981
+ const client = new S3Client({});
982
+
983
+ async function moveObject(sourceBucket, sourceKey, destBucket, destKey) {
984
+ try {
985
+ // Copy
986
+ await client.send(
987
+ new CopyObjectCommand({
988
+ CopySource: `${sourceBucket}/${sourceKey}`,
989
+ Bucket: destBucket,
990
+ Key: destKey,
991
+ })
992
+ );
993
+
994
+ // Delete source
995
+ await client.send(
996
+ new DeleteObjectCommand({
997
+ Bucket: sourceBucket,
998
+ Key: sourceKey,
999
+ })
1000
+ );
1001
+
1002
+ console.log(`Moved ${sourceKey} to ${destKey}`);
1003
+ } catch (error) {
1004
+ console.error("Move error:", error);
1005
+ }
1006
+ }
1007
+ ```
1008
+
1009
+ ---
1010
+
1011
+ ## Presigned URLs
1012
+
1013
+ ### Install Required Package
1014
+
1015
+ ```bash
1016
+ npm install @aws-sdk/s3-request-presigner
1017
+ ```
1018
+
1019
+ ### Presigned URL for Download (GET)
1020
+
1021
+ ```javascript
1022
+ import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
1023
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
1024
+
1025
+ const client = new S3Client({ region: "us-east-1" });
1026
+
1027
+ async function createPresignedDownloadUrl(bucketName, key, expiresIn = 3600) {
1028
+ try {
1029
+ const command = new GetObjectCommand({
1030
+ Bucket: bucketName,
1031
+ Key: key,
1032
+ });
1033
+
1034
+ const url = await getSignedUrl(client, command, { expiresIn });
1035
+ return url;
1036
+ } catch (error) {
1037
+ console.error("Presigned URL error:", error);
1038
+ throw error;
1039
+ }
1040
+ }
1041
+
1042
+ // Usage
1043
+ const url = await createPresignedDownloadUrl("my-bucket", "file.pdf", 3600);
1044
+ console.log("Download URL:", url);
1045
+ ```
1046
+
1047
+ ### Presigned URL for Upload (PUT)
1048
+
1049
+ ```javascript
1050
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
1051
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
1052
+
1053
+ const client = new S3Client({ region: "us-east-1" });
1054
+
1055
+ async function createPresignedUploadUrl(bucketName, key, expiresIn = 3600) {
1056
+ try {
1057
+ const command = new PutObjectCommand({
1058
+ Bucket: bucketName,
1059
+ Key: key,
1060
+ });
1061
+
1062
+ const url = await getSignedUrl(client, command, { expiresIn });
1063
+ return url;
1064
+ } catch (error) {
1065
+ console.error("Presigned URL error:", error);
1066
+ throw error;
1067
+ }
1068
+ }
1069
+
1070
+ // Usage with fetch
1071
+ const uploadUrl = await createPresignedUploadUrl("my-bucket", "upload.txt");
1072
+
1073
+ // Client can now upload using PUT request
1074
+ await fetch(uploadUrl, {
1075
+ method: "PUT",
1076
+ body: fileContent,
1077
+ headers: {
1078
+ "Content-Type": "text/plain",
1079
+ },
1080
+ });
1081
+ ```
1082
+
1083
+ ### Presigned URL with Content Type
1084
+
1085
+ ```javascript
1086
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
1087
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
1088
+
1089
+ const client = new S3Client({ region: "us-east-1" });
1090
+
1091
+ async function createPresignedUploadUrlWithType(
1092
+ bucketName,
1093
+ key,
1094
+ contentType,
1095
+ expiresIn = 3600
1096
+ ) {
1097
+ try {
1098
+ const command = new PutObjectCommand({
1099
+ Bucket: bucketName,
1100
+ Key: key,
1101
+ ContentType: contentType,
1102
+ });
1103
+
1104
+ const url = await getSignedUrl(client, command, { expiresIn });
1105
+ return url;
1106
+ } catch (error) {
1107
+ console.error("Presigned URL error:", error);
1108
+ throw error;
1109
+ }
1110
+ }
1111
+ ```
1112
+
1113
+ ### Presigned URL with Metadata
1114
+
1115
+ ```javascript
1116
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
1117
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
1118
+
1119
+ const client = new S3Client({ region: "us-east-1" });
1120
+
1121
+ async function createPresignedUrlWithMetadata(bucketName, key) {
1122
+ try {
1123
+ const command = new PutObjectCommand({
1124
+ Bucket: bucketName,
1125
+ Key: key,
1126
+ Metadata: {
1127
+ "uploaded-by": "user123",
1128
+ "original-name": "document.pdf",
1129
+ },
1130
+ });
1131
+
1132
+ const url = await getSignedUrl(client, command, { expiresIn: 3600 });
1133
+ return url;
1134
+ } catch (error) {
1135
+ console.error("Presigned URL error:", error);
1136
+ throw error;
1137
+ }
1138
+ }
1139
+ ```
1140
+
1141
+ ### Complete Presigned Upload Example
1142
+
1143
+ ```javascript
1144
+ import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
1145
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
1146
+
1147
+ const client = new S3Client({ region: "us-east-1" });
1148
+
1149
+ // Server-side: Generate presigned URL
1150
+ async function generateUploadUrl(fileName, fileType) {
1151
+ const command = new PutObjectCommand({
1152
+ Bucket: "my-bucket",
1153
+ Key: `uploads/${fileName}`,
1154
+ ContentType: fileType,
1155
+ });
1156
+
1157
+ return await getSignedUrl(client, command, { expiresIn: 300 }); // 5 minutes
1158
+ }
1159
+
1160
+ // Client-side: Upload using presigned URL
1161
+ async function uploadUsingPresignedUrl(presignedUrl, file) {
1162
+ const response = await fetch(presignedUrl, {
1163
+ method: "PUT",
1164
+ body: file,
1165
+ headers: {
1166
+ "Content-Type": file.type,
1167
+ },
1168
+ });
1169
+
1170
+ if (response.ok) {
1171
+ console.log("Upload successful");
1172
+ } else {
1173
+ console.error("Upload failed:", response.statusText);
1174
+ }
1175
+ }
1176
+ ```
1177
+
1178
+ ---
1179
+
1180
+ ## Multipart Upload
1181
+
1182
+ ### Install Required Package
1183
+
1184
+ ```bash
1185
+ npm install @aws-sdk/lib-storage
1186
+ ```
1187
+
1188
+ ### Basic Multipart Upload
1189
+
1190
+ ```javascript
1191
+ import { S3Client } from "@aws-sdk/client-s3";
1192
+ import { Upload } from "@aws-sdk/lib-storage";
1193
+ import { createReadStream } from "node:fs";
1194
+
1195
+ const client = new S3Client({});
1196
+
1197
+ async function multipartUpload(bucketName, key, filePath) {
1198
+ try {
1199
+ const fileStream = createReadStream(filePath);
1200
+
1201
+ const upload = new Upload({
1202
+ client,
1203
+ params: {
1204
+ Bucket: bucketName,
1205
+ Key: key,
1206
+ Body: fileStream,
1207
+ },
1208
+ });
1209
+
1210
+ const result = await upload.done();
1211
+ console.log("Upload complete:", result.Location);
1212
+ } catch (error) {
1213
+ console.error("Multipart upload error:", error);
1214
+ }
1215
+ }
1216
+ ```
1217
+
1218
+ ### Multipart Upload with Progress Tracking
1219
+
1220
+ ```javascript
1221
+ import { S3Client } from "@aws-sdk/client-s3";
1222
+ import { Upload } from "@aws-sdk/lib-storage";
1223
+ import { createReadStream, statSync } from "node:fs";
1224
+
1225
+ const client = new S3Client({});
1226
+
1227
+ async function multipartUploadWithProgress(bucketName, key, filePath) {
1228
+ try {
1229
+ const fileStream = createReadStream(filePath);
1230
+ const fileSize = statSync(filePath).size;
1231
+
1232
+ const upload = new Upload({
1233
+ client,
1234
+ params: {
1235
+ Bucket: bucketName,
1236
+ Key: key,
1237
+ Body: fileStream,
1238
+ },
1239
+ });
1240
+
1241
+ upload.on("httpUploadProgress", (progress) => {
1242
+ const percentage = Math.round((progress.loaded / fileSize) * 100);
1243
+ console.log(`Upload progress: ${percentage}%`);
1244
+ });
1245
+
1246
+ const result = await upload.done();
1247
+ console.log("Upload complete:", result.Location);
1248
+ } catch (error) {
1249
+ console.error("Multipart upload error:", error);
1250
+ }
1251
+ }
1252
+ ```
1253
+
1254
+ ### Multipart Upload with Custom Configuration
1255
+
1256
+ ```javascript
1257
+ import { S3Client } from "@aws-sdk/client-s3";
1258
+ import { Upload } from "@aws-sdk/lib-storage";
1259
+ import { createReadStream } from "node:fs";
1260
+
1261
+ const client = new S3Client({});
1262
+
1263
+ async function multipartUploadConfigured(bucketName, key, filePath) {
1264
+ try {
1265
+ const fileStream = createReadStream(filePath);
1266
+
1267
+ const upload = new Upload({
1268
+ client,
1269
+ params: {
1270
+ Bucket: bucketName,
1271
+ Key: key,
1272
+ Body: fileStream,
1273
+ },
1274
+ queueSize: 4, // Number of concurrent uploads
1275
+ partSize: 1024 * 1024 * 5, // 5 MB parts (minimum is 5 MB)
1276
+ leavePartsOnError: false, // Clean up on error
1277
+ });
1278
+
1279
+ const result = await upload.done();
1280
+ console.log("Upload complete:", result.Location);
1281
+ } catch (error) {
1282
+ console.error("Multipart upload error:", error);
1283
+ }
1284
+ }
1285
+ ```
1286
+
1287
+ ### Multipart Upload with Tags and Metadata
1288
+
1289
+ ```javascript
1290
+ import { S3Client } from "@aws-sdk/client-s3";
1291
+ import { Upload } from "@aws-sdk/lib-storage";
1292
+ import { readFileSync } from "node:fs";
1293
+
1294
+ const client = new S3Client({});
1295
+
1296
+ async function multipartUploadWithTags(bucketName, key, filePath) {
1297
+ try {
1298
+ const fileContent = readFileSync(filePath);
1299
+
1300
+ const upload = new Upload({
1301
+ client,
1302
+ params: {
1303
+ Bucket: bucketName,
1304
+ Key: key,
1305
+ Body: fileContent,
1306
+ Metadata: {
1307
+ "uploaded-by": "system",
1308
+ "file-category": "large-files",
1309
+ },
1310
+ },
1311
+ tags: [
1312
+ { Key: "Environment", Value: "Production" },
1313
+ { Key: "Department", Value: "Engineering" },
1314
+ ],
1315
+ });
1316
+
1317
+ const result = await upload.done();
1318
+ console.log("Upload complete:", result.Location);
1319
+ } catch (error) {
1320
+ console.error("Multipart upload error:", error);
1321
+ }
1322
+ }
1323
+ ```
1324
+
1325
+ ### Abort Multipart Upload
1326
+
1327
+ ```javascript
1328
+ import { S3Client } from "@aws-sdk/client-s3";
1329
+ import { Upload } from "@aws-sdk/lib-storage";
1330
+ import { createReadStream } from "node:fs";
1331
+
1332
+ const client = new S3Client({});
1333
+
1334
+ async function abortableMultipartUpload(bucketName, key, filePath) {
1335
+ const fileStream = createReadStream(filePath);
1336
+
1337
+ const upload = new Upload({
1338
+ client,
1339
+ params: {
1340
+ Bucket: bucketName,
1341
+ Key: key,
1342
+ Body: fileStream,
1343
+ },
1344
+ });
1345
+
1346
+ // Abort after 5 seconds (example)
1347
+ setTimeout(() => {
1348
+ upload.abort();
1349
+ console.log("Upload aborted");
1350
+ }, 5000);
1351
+
1352
+ try {
1353
+ await upload.done();
1354
+ } catch (error) {
1355
+ if (error.name === "AbortError") {
1356
+ console.log("Upload was aborted");
1357
+ } else {
1358
+ console.error("Upload error:", error);
1359
+ }
1360
+ }
1361
+ }
1362
+ ```
1363
+
1364
+ ---
1365
+
1366
+ ## Streaming Operations
1367
+
1368
+ ### Stream Download
1369
+
1370
+ ```javascript
1371
+ import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
1372
+ import { pipeline } from "node:stream/promises";
1373
+ import { createWriteStream } from "node:fs";
1374
+
1375
+ const client = new S3Client({});
1376
+
1377
+ async function streamDownload(bucketName, key, destinationPath) {
1378
+ try {
1379
+ const response = await client.send(
1380
+ new GetObjectCommand({
1381
+ Bucket: bucketName,
1382
+ Key: key,
1383
+ })
1384
+ );
1385
+
1386
+ await pipeline(
1387
+ response.Body,
1388
+ createWriteStream(destinationPath)
1389
+ );
1390
+
1391
+ console.log(`Streamed download to ${destinationPath}`);
1392
+ } catch (error) {
1393
+ console.error("Stream download error:", error);
1394
+ }
1395
+ }
1396
+ ```
1397
+
1398
+ ### Stream Upload
1399
+
1400
+ ```javascript
1401
+ import { S3Client } from "@aws-sdk/client-s3";
1402
+ import { Upload } from "@aws-sdk/lib-storage";
1403
+ import { createReadStream } from "node:fs";
1404
+
1405
+ const client = new S3Client({});
1406
+
1407
+ async function streamUpload(bucketName, key, filePath) {
1408
+ try {
1409
+ const fileStream = createReadStream(filePath);
1410
+
1411
+ const upload = new Upload({
1412
+ client,
1413
+ params: {
1414
+ Bucket: bucketName,
1415
+ Key: key,
1416
+ Body: fileStream,
1417
+ },
1418
+ });
1419
+
1420
+ await upload.done();
1421
+ console.log("Stream upload complete");
1422
+ } catch (error) {
1423
+ console.error("Stream upload error:", error);
1424
+ }
1425
+ }
1426
+ ```
1427
+
1428
+ ---
1429
+
1430
+ ## Object Tagging
1431
+
1432
+ ### Put Object Tags
1433
+
1434
+ ```javascript
1435
+ import { S3Client, PutObjectTaggingCommand } from "@aws-sdk/client-s3";
1436
+
1437
+ const client = new S3Client({});
1438
+
1439
+ async function tagObject(bucketName, key, tags) {
1440
+ try {
1441
+ await client.send(
1442
+ new PutObjectTaggingCommand({
1443
+ Bucket: bucketName,
1444
+ Key: key,
1445
+ Tagging: {
1446
+ TagSet: tags.map(({ Key, Value }) => ({ Key, Value })),
1447
+ },
1448
+ })
1449
+ );
1450
+
1451
+ console.log(`Tagged ${key}`);
1452
+ } catch (error) {
1453
+ console.error("Tagging error:", error);
1454
+ }
1455
+ }
1456
+
1457
+ // Usage
1458
+ await tagObject("my-bucket", "file.txt", [
1459
+ { Key: "Environment", Value: "Production" },
1460
+ { Key: "Department", Value: "Engineering" },
1461
+ ]);
1462
+ ```
1463
+
1464
+ ### Get Object Tags
1465
+
1466
+ ```javascript
1467
+ import { S3Client, GetObjectTaggingCommand } from "@aws-sdk/client-s3";
1468
+
1469
+ const client = new S3Client({});
1470
+
1471
+ async function getObjectTags(bucketName, key) {
1472
+ try {
1473
+ const response = await client.send(
1474
+ new GetObjectTaggingCommand({
1475
+ Bucket: bucketName,
1476
+ Key: key,
1477
+ })
1478
+ );
1479
+
1480
+ console.log("Tags:");
1481
+ response.TagSet.forEach((tag) => {
1482
+ console.log(` ${tag.Key}: ${tag.Value}`);
1483
+ });
1484
+
1485
+ return response.TagSet;
1486
+ } catch (error) {
1487
+ console.error("Get tags error:", error);
1488
+ }
1489
+ }
1490
+ ```
1491
+
1492
+ ---
1493
+
1494
+ ## Bucket Configuration
1495
+
1496
+ ### Enable Versioning
1497
+
1498
+ ```javascript
1499
+ import { S3Client, PutBucketVersioningCommand } from "@aws-sdk/client-s3";
1500
+
1501
+ const client = new S3Client({});
1502
+
1503
+ async function enableVersioning(bucketName) {
1504
+ try {
1505
+ await client.send(
1506
+ new PutBucketVersioningCommand({
1507
+ Bucket: bucketName,
1508
+ VersioningConfiguration: {
1509
+ Status: "Enabled",
1510
+ },
1511
+ })
1512
+ );
1513
+
1514
+ console.log(`Versioning enabled for ${bucketName}`);
1515
+ } catch (error) {
1516
+ console.error("Versioning error:", error);
1517
+ }
1518
+ }
1519
+ ```
1520
+
1521
+ ### Set Bucket CORS
1522
+
1523
+ ```javascript
1524
+ import { S3Client, PutBucketCorsCommand } from "@aws-sdk/client-s3";
1525
+
1526
+ const client = new S3Client({});
1527
+
1528
+ async function setBucketCORS(bucketName) {
1529
+ try {
1530
+ await client.send(
1531
+ new PutBucketCorsCommand({
1532
+ Bucket: bucketName,
1533
+ CORSConfiguration: {
1534
+ CORSRules: [
1535
+ {
1536
+ AllowedHeaders: ["*"],
1537
+ AllowedMethods: ["GET", "PUT", "POST", "DELETE"],
1538
+ AllowedOrigins: ["*"],
1539
+ ExposeHeaders: ["ETag"],
1540
+ MaxAgeSeconds: 3000,
1541
+ },
1542
+ ],
1543
+ },
1544
+ })
1545
+ );
1546
+
1547
+ console.log("CORS configured");
1548
+ } catch (error) {
1549
+ console.error("CORS error:", error);
1550
+ }
1551
+ }
1552
+ ```
1553
+
1554
+ ### Get Bucket CORS
1555
+
1556
+ ```javascript
1557
+ import { S3Client, GetBucketCorsCommand } from "@aws-sdk/client-s3";
1558
+
1559
+ const client = new S3Client({});
1560
+
1561
+ async function getBucketCORS(bucketName) {
1562
+ try {
1563
+ const response = await client.send(
1564
+ new GetBucketCorsCommand({
1565
+ Bucket: bucketName,
1566
+ })
1567
+ );
1568
+
1569
+ console.log("CORS Rules:", JSON.stringify(response.CORSRules, null, 2));
1570
+ return response.CORSRules;
1571
+ } catch (error) {
1572
+ console.error("Get CORS error:", error);
1573
+ }
1574
+ }
1575
+ ```
1576
+
1577
+ ### Set Bucket Encryption
1578
+
1579
+ ```javascript
1580
+ import { S3Client, PutBucketEncryptionCommand } from "@aws-sdk/client-s3";
1581
+
1582
+ const client = new S3Client({});
1583
+
1584
+ async function setBucketEncryption(bucketName) {
1585
+ try {
1586
+ await client.send(
1587
+ new PutBucketEncryptionCommand({
1588
+ Bucket: bucketName,
1589
+ ServerSideEncryptionConfiguration: {
1590
+ Rules: [
1591
+ {
1592
+ ApplyServerSideEncryptionByDefault: {
1593
+ SSEAlgorithm: "AES256",
1594
+ },
1595
+ },
1596
+ ],
1597
+ },
1598
+ })
1599
+ );
1600
+
1601
+ console.log("Encryption enabled");
1602
+ } catch (error) {
1603
+ console.error("Encryption error:", error);
1604
+ }
1605
+ }
1606
+ ```
1607
+
1608
+ ---
1609
+
1610
+ ## Error Handling
1611
+
1612
+ ### Common Error Types
1613
+
1614
+ ```javascript
1615
+ import {
1616
+ S3Client,
1617
+ GetObjectCommand,
1618
+ NoSuchKey,
1619
+ NoSuchBucket,
1620
+ } from "@aws-sdk/client-s3";
1621
+
1622
+ const client = new S3Client({});
1623
+
1624
+ async function handleErrors(bucketName, key) {
1625
+ try {
1626
+ const response = await client.send(
1627
+ new GetObjectCommand({
1628
+ Bucket: bucketName,
1629
+ Key: key,
1630
+ })
1631
+ );
1632
+
1633
+ return await response.Body.transformToString();
1634
+ } catch (error) {
1635
+ if (error instanceof NoSuchKey) {
1636
+ console.error("Object not found");
1637
+ } else if (error instanceof NoSuchBucket) {
1638
+ console.error("Bucket not found");
1639
+ } else if (error.name === "AccessDenied") {
1640
+ console.error("Access denied");
1641
+ } else if (error.name === "InvalidAccessKeyId") {
1642
+ console.error("Invalid credentials");
1643
+ } else {
1644
+ console.error("Unknown error:", error);
1645
+ }
1646
+
1647
+ throw error;
1648
+ }
1649
+ }
1650
+ ```
1651
+
1652
+ ### Retry Logic
1653
+
1654
+ ```javascript
1655
+ import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
1656
+
1657
+ const client = new S3Client({
1658
+ maxAttempts: 3, // Built-in retry configuration
1659
+ });
1660
+
1661
+ async function downloadWithRetry(bucketName, key, maxRetries = 3) {
1662
+ let lastError;
1663
+
1664
+ for (let i = 0; i < maxRetries; i++) {
1665
+ try {
1666
+ const response = await client.send(
1667
+ new GetObjectCommand({
1668
+ Bucket: bucketName,
1669
+ Key: key,
1670
+ })
1671
+ );
1672
+
1673
+ return await response.Body.transformToString();
1674
+ } catch (error) {
1675
+ lastError = error;
1676
+ console.log(`Attempt ${i + 1} failed, retrying...`);
1677
+ await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));
1678
+ }
1679
+ }
1680
+
1681
+ throw lastError;
1682
+ }
1683
+ ```
1684
+
1685
+ ---
1686
+
1687
+ ## Complete Example: Full S3 Operations
1688
+
1689
+ ```javascript
1690
+ import {
1691
+ S3Client,
1692
+ CreateBucketCommand,
1693
+ PutObjectCommand,
1694
+ GetObjectCommand,
1695
+ ListObjectsV2Command,
1696
+ DeleteObjectCommand,
1697
+ DeleteBucketCommand,
1698
+ } from "@aws-sdk/client-s3";
1699
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
1700
+
1701
+ const client = new S3Client({ region: "us-east-1" });
1702
+ const bucketName = `my-test-bucket-${Date.now()}`;
1703
+
1704
+ async function completeS3Example() {
1705
+ try {
1706
+ // 1. Create bucket
1707
+ console.log("Creating bucket...");
1708
+ await client.send(new CreateBucketCommand({ Bucket: bucketName }));
1709
+
1710
+ // 2. Upload object
1711
+ console.log("Uploading object...");
1712
+ await client.send(
1713
+ new PutObjectCommand({
1714
+ Bucket: bucketName,
1715
+ Key: "test-file.txt",
1716
+ Body: "Hello, S3!",
1717
+ ContentType: "text/plain",
1718
+ })
1719
+ );
1720
+
1721
+ // 3. Generate presigned URL
1722
+ console.log("Generating presigned URL...");
1723
+ const url = await getSignedUrl(
1724
+ client,
1725
+ new GetObjectCommand({
1726
+ Bucket: bucketName,
1727
+ Key: "test-file.txt",
1728
+ }),
1729
+ { expiresIn: 3600 }
1730
+ );
1731
+ console.log("Presigned URL:", url);
1732
+
1733
+ // 4. Download object
1734
+ console.log("Downloading object...");
1735
+ const downloadResponse = await client.send(
1736
+ new GetObjectCommand({
1737
+ Bucket: bucketName,
1738
+ Key: "test-file.txt",
1739
+ })
1740
+ );
1741
+ const content = await downloadResponse.Body.transformToString();
1742
+ console.log("Content:", content);
1743
+
1744
+ // 5. List objects
1745
+ console.log("Listing objects...");
1746
+ const listResponse = await client.send(
1747
+ new ListObjectsV2Command({ Bucket: bucketName })
1748
+ );
1749
+ listResponse.Contents.forEach((obj) => {
1750
+ console.log(` • ${obj.Key}`);
1751
+ });
1752
+
1753
+ // 6. Delete object
1754
+ console.log("Deleting object...");
1755
+ await client.send(
1756
+ new DeleteObjectCommand({
1757
+ Bucket: bucketName,
1758
+ Key: "test-file.txt",
1759
+ })
1760
+ );
1761
+
1762
+ // 7. Delete bucket
1763
+ console.log("Deleting bucket...");
1764
+ await client.send(new DeleteBucketCommand({ Bucket: bucketName }));
1765
+
1766
+ console.log("Complete!");
1767
+ } catch (error) {
1768
+ console.error("Error:", error);
1769
+ }
1770
+ }
1771
+
1772
+ completeS3Example();
1773
+ ```