agentsclimarketplace

Infra platform aws sdk

Skill agents-inc/skills/src/skills/infra-platform-aws-sdk

AWS SDK v3 for TypeScript — modular clients, command pattern, S3, DynamoDB, SQS, Lambda, SNS, Secrets ManagerFrom its SKILL.md

Install
npx -y skills add agents-inc/skills --skill infra-platform-aws-sdk

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 20 stars20 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

16.0 KB, ~3.8k tokens by cl100k_base, as published. Nobody here has run it

AWS SDK v3 Patterns

Quick Guide: AWS SDK v3 for JavaScript/TypeScript uses modular packages (@aws-sdk/client-*) with a command pattern: create a client, instantiate a command, call client.send(command). Import only the services you need for tree-shaking. Use DynamoDBDocumentClient for native JS types. Use getSignedUrl from @aws-sdk/s3-request-presigner for presigned URLs. Handle errors with instanceof specific exception classes. Use built-in paginators (paginate*) with for await...of.


<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST use AWS SDK v3 modular packages (@aws-sdk/client-*) — NEVER the monolithic aws-sdk v2 package)

(You MUST use the command pattern: client.send(new XxxCommand({...})) — NEVER call methods directly on the client)

(You MUST use DynamoDBDocumentClient from @aws-sdk/lib-dynamodb for DynamoDB — it auto-marshalls native JS types)

(You MUST handle errors with instanceof specific exception classes — NEVER catch generic Error and check .code)

(You MUST use built-in paginators (paginate* functions) for paginated APIs — NEVER manually track continuation tokens)

</critical_requirements>


Examples

  • Core Patterns — Client setup, S3 operations, DynamoDB basics, credential providers, error handling, pagination
  • Messaging — SQS send/receive/delete, SNS publish, FIFO queues, dead-letter patterns
  • Advanced — Lambda invocation, Secrets Manager, presigned URLs, middleware, streaming
  • Quick Reference — Package cheat sheet, import patterns, error handling decision tree, credential provider chain

Auto-detection: AWS SDK, @aws-sdk/client, S3Client, DynamoDBClient, DynamoDBDocumentClient, SQSClient, LambdaClient, SNSClient, SecretsManagerClient, PutObjectCommand, GetObjectCommand, GetCommand, PutCommand, QueryCommand, SendMessageCommand, InvokeCommand, GetSecretValueCommand, getSignedUrl, s3-request-presigner, credential-providers, fromEnv, fromIni, paginateListObjectsV2, aws-sdk-client-mock

When to use:

  • Interacting with any AWS service from TypeScript/JavaScript
  • S3 file operations (upload, download, presigned URLs, listings)
  • DynamoDB CRUD operations and queries
  • SQS message sending, receiving, and queue management
  • Lambda function invocation from other services
  • SNS topic publishing and notifications
  • Secrets Manager secret retrieval
  • Custom middleware for request/response modification

When NOT to use:

  • Infrastructure provisioning (use an IaC tool)
  • AWS console-only operations with no SDK equivalent
  • Simple CLI-only tasks better served by the AWS CLI directly

Key patterns covered:

  • Modular client setup with typed configuration
  • Command pattern (client.send(new Command({...})))
  • S3: upload, download, delete, list, presigned URLs, streaming
  • DynamoDB: DynamoDBDocumentClient with Get, Put, Query, Update, Delete
  • SQS: send, receive, delete messages, long polling, FIFO
  • SNS: publish to topics, message attributes
  • Lambda: synchronous and asynchronous invocation
  • Secrets Manager: secret retrieval with caching
  • Credential provider chain and explicit providers
  • Error handling with instanceof exception classes and $metadata
  • Pagination with async iterators
  • Middleware stack customization
  • Retry configuration

<philosophy>

Philosophy

AWS SDK v3 is a ground-up rewrite of the v2 SDK for modern JavaScript/TypeScript. The core design principles:

  1. Modular packages — Each service is a separate npm package (@aws-sdk/client-s3, @aws-sdk/client-dynamodb). Import only what you use. This reduces bundle size by up to 90% compared to the monolithic v2 aws-sdk package.

  2. Command pattern — Every API call is a Command object sent through a Client. This enables middleware, type safety, and testability. The client handles serialization, signing, retries, and deserialization.

  3. First-class TypeScript — Every command input and output is fully typed. Use the types to avoid runtime errors.

  4. Middleware stack — Customize request/response handling at various stages (serialize, build, finalize, deserialize) without monkey-patching.

  5. Built-in pagination — Paginator functions return async iterators, eliminating manual token tracking.

When to use AWS SDK v3:

  • Any server-side or serverless TypeScript/JavaScript that interacts with AWS services
  • Frontend applications that need direct AWS access (with appropriate auth)
  • Lambda functions (SDK v3 is included in Node.js 18+ Lambda runtimes)

When NOT to use:

  • Infrastructure provisioning and management (use an IaC tool)
  • One-off tasks better served by the AWS CLI
  • Languages other than JavaScript/TypeScript
</philosophy>
<patterns>

Core Patterns

Pattern 1: Client Setup and Command Pattern

Every AWS service follows the same pattern: import the client and command, create a client instance, send the command.

import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

const s3 = new S3Client({ region: "us-east-1" });
await s3.send(
  new PutObjectCommand({
    Bucket: "my-bucket",
    Key: "data.json",
    Body: JSON.stringify({ hello: "world" }),
    ContentType: "application/json",
  }),
);

Why good: modular import keeps bundle small, command pattern enables middleware and type safety, region is explicit

Create clients once and reuse them — they manage connection pooling internally. In Lambda, create clients outside the handler for connection reuse across invocations.

See examples/core.md for client reuse patterns and configuration options.


Pattern 2: S3 Operations

S3 is the most commonly used service. Key operations: PutObject, GetObject, DeleteObject, ListObjectsV2, and presigned URLs via @aws-sdk/s3-request-presigner.

import { GetObjectCommand, NoSuchKey } from "@aws-sdk/client-s3";

const response = await s3.send(
  new GetObjectCommand({
    Bucket: "my-bucket",
    Key: "data.json",
  }),
);
const body = await response.Body?.transformToString();

For presigned URLs, use the separate @aws-sdk/s3-request-presigner package:

import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const PRESIGN_EXPIRY_SECONDS = 3_600;
const url = await getSignedUrl(
  s3,
  new GetObjectCommand({
    Bucket: "my-bucket",
    Key: "file.pdf",
  }),
  { expiresIn: PRESIGN_EXPIRY_SECONDS },
);

See examples/core.md for upload, download, delete, list, and streaming patterns.


Pattern 3: DynamoDB with Document Client

Use DynamoDBDocumentClient from @aws-sdk/lib-dynamodb — it automatically marshalls/unmarshalls between native JS types and DynamoDB's AttributeValue format.

import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import {
  DynamoDBDocumentClient,
  GetCommand,
  PutCommand,
} from "@aws-sdk/lib-dynamodb";

const ddbDocClient = DynamoDBDocumentClient.from(new DynamoDBClient({}));

const { Item } = await ddbDocClient.send(
  new GetCommand({
    TableName: "users",
    Key: { userId: "abc-123" },
  }),
);

Why good: no manual marshall()/unmarshall() calls, native JS objects in and out, full type safety

Gotcha: Import commands from @aws-sdk/lib-dynamodb (not @aws-sdk/client-dynamodb) when using the document client — the lib-dynamodb commands accept native JS types.

See examples/core.md for Put, Query, Update, Delete, and batch operations.


Pattern 4: Error Handling

AWS SDK v3 errors extend service-specific base classes (e.g., S3ServiceException). Use instanceof for typed error handling.

import {
  GetObjectCommand,
  NoSuchKey,
  S3ServiceException,
} from "@aws-sdk/client-s3";

try {
  await s3.send(new GetObjectCommand({ Bucket: "b", Key: "k" }));
} catch (error) {
  if (error instanceof NoSuchKey) {
    // Typed: error.name === "NoSuchKey", error.$metadata.httpStatusCode === 404
    return null;
  }
  if (error instanceof S3ServiceException) {
    // Any S3 service error — check error.$metadata.httpStatusCode
    throw error;
  }
  throw error; // Non-AWS error (network, etc.)
}

Why good: instanceof gives TypeScript type narrowing, exception classes are exported from the client package, $metadata provides HTTP status and request ID for debugging

See examples/core.md for the full error handling decision tree and retry patterns.


Pattern 5: Pagination with Async Iterators

Use built-in paginator functions for any paginated API. They return async iterators that handle continuation tokens automatically.

import { paginateListObjectsV2 } from "@aws-sdk/client-s3";

for await (const page of paginateListObjectsV2(
  { client: s3 },
  { Bucket: "my-bucket" },
)) {
  // page.Contents is an array of objects for this page
}

Why good: no manual token tracking, clean for await...of loop, handles all edge cases (empty pages, token format)

See examples/core.md for full S3 list, DynamoDB pagination, and good/bad comparison with manual token tracking.


Pattern 6: SQS Messaging

SQS uses SendMessageCommand, ReceiveMessageCommand, and DeleteMessageCommand. Always delete messages after processing.

import { SQSClient, SendMessageCommand } from "@aws-sdk/client-sqs";

const sqs = new SQSClient({});
await sqs.send(
  new SendMessageCommand({
    QueueUrl: QUEUE_URL,
    MessageBody: JSON.stringify({ orderId: "order-123" }),
  }),
);

See examples/messaging.md for receive/delete, long polling, FIFO queues, and dead-letter patterns.


Pattern 7: SNS Publishing

SNS publishes messages to topics. Subscribers receive messages on their configured endpoints.

import { SNSClient, PublishCommand } from "@aws-sdk/client-sns";

const sns = new SNSClient({});
await sns.send(
  new PublishCommand({
    TopicArn: TOPIC_ARN,
    Message: JSON.stringify({ event: "order.created", orderId: "order-123" }),
    MessageAttributes: {
      eventType: { DataType: "String", StringValue: "order.created" },
    },
  }),
);

See examples/messaging.md for topic management and message filtering.


Pattern 8: Lambda Invocation and Secrets Manager

Invoke Lambda functions synchronously or asynchronously. Retrieve secrets from Secrets Manager with caching.

import { LambdaClient, InvokeCommand } from "@aws-sdk/client-lambda";

const lambda = new LambdaClient({});
const response = await lambda.send(
  new InvokeCommand({
    FunctionName: "process-order",
    InvocationType: "RequestResponse", // synchronous
    Payload: JSON.stringify({ orderId: "order-123" }),
  }),
);
const result = JSON.parse(new TextDecoder().decode(response.Payload));

See examples/advanced.md for async invocation, Secrets Manager retrieval, and caching patterns.

</patterns>

<decision_framework>

Decision Framework

Choosing the Right DynamoDB Client

Are you working with DynamoDB?
  |
  +-- Need native JS objects (recommended) --> DynamoDBDocumentClient from @aws-sdk/lib-dynamodb
  |     +-- Import Get/Put/Query/Update/Delete Commands from @aws-sdk/lib-dynamodb
  |
  +-- Need raw AttributeValue format --> DynamoDBClient from @aws-sdk/client-dynamodb
        +-- Import commands from @aws-sdk/client-dynamodb
        +-- Manually marshall/unmarshall with @aws-sdk/util-dynamodb

Choosing Between Synchronous and Async Lambda Invocation

Do you need the Lambda response immediately?
  |
  +-- YES --> InvocationType: "RequestResponse" (synchronous, waits for result)
  |
  +-- NO  --> InvocationType: "Event" (async, returns immediately, 3 retries)

Credential Provider Selection

Where is this code running?
  |
  +-- Lambda / ECS / EC2 --> Default chain (auto-detects IAM role) — no config needed
  |
  +-- Local development --> fromIni() (reads ~/.aws/credentials) or fromEnv()
  |
  +-- CI/CD pipeline --> fromEnv() with AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY
  |
  +-- Cross-account access --> fromTemporaryCredentials() with STS AssumeRole

</decision_framework>


<red_flags>

RED FLAGS

High Priority Issues:

  • Using the monolithic aws-sdk v2 package — it ships the entire SDK (~70 MB). Use modular @aws-sdk/client-* packages.
  • Calling methods directly on the client (v2 style: s3.getObject()) — use the command pattern: s3.send(new GetObjectCommand({...})).
  • Using raw DynamoDBClient commands with manual marshall()/unmarshall() — use DynamoDBDocumentClient from @aws-sdk/lib-dynamodb.
  • Catching errors with .code string comparison (v2 style) — use instanceof with typed exception classes.
  • Manually tracking pagination tokens in a while loop — use built-in paginate* functions with for await...of.
  • Hardcoding AWS credentials in source code — use the credential provider chain or environment variables.

Medium Priority Issues:

  • Creating a new client instance per request — create clients once and reuse them (they manage connection pooling).
  • Not setting a region explicitly — defaults vary by environment and cause confusing errors.
  • Mixing @aws-sdk/client-dynamodb and @aws-sdk/lib-dynamodb command imports — pick one approach per codebase.
  • Missing ContentType on S3 PutObject — S3 defaults to application/octet-stream, breaking browser downloads.
  • Not buffering the S3 GetObject response body — response.Body is a stream; call .transformToString() or .transformToByteArray().

Gotchas and Edge Cases:

  • GetObject response body is a ReadableStream (not a string) — you must consume it with .transformToString(), .transformToByteArray(), or pipe it to a writable stream.
  • DynamoDBDocumentClient commands come from @aws-sdk/lib-dynamodb, NOT @aws-sdk/client-dynamodb — importing from the wrong package gives you raw AttributeValue types.
  • Presigned URLs require the separate @aws-sdk/s3-request-presigner package — it is NOT included in @aws-sdk/client-s3.
  • InvokeCommand returns Payload as a Uint8Array — decode with new TextDecoder().decode(response.Payload) before JSON.parse.
  • SDK v3 version mismatches across client packages cause TypeScript errors — pin all @aws-sdk/* packages to the same version range.
  • In Lambda, the SDK is bundled in the runtime but may be outdated — bundle your own version for latest features.
  • SQS ReceiveMessageCommand may return Messages: undefined (not empty array) when no messages are available — always use response.Messages ?? [].
  • Presigned URL expiry is capped at 7 days, but temporary credentials may expire sooner — the URL stops working when the signing credentials expire.

</red_flags>


<critical_reminders>

CRITICAL REMINDERS

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST use AWS SDK v3 modular packages (@aws-sdk/client-*) — NEVER the monolithic aws-sdk v2 package)

(You MUST use the command pattern: client.send(new XxxCommand({...})) — NEVER call methods directly on the client)

(You MUST use DynamoDBDocumentClient from @aws-sdk/lib-dynamodb for DynamoDB — it auto-marshalls native JS types)

(You MUST handle errors with instanceof specific exception classes — NEVER catch generic Error and check .code)

(You MUST use built-in paginators (paginate* functions) for paginated APIs — NEVER manually track continuation tokens)

Failure to follow these rules will cause bloated bundles (v2), lost type safety (direct calls), marshalling bugs (raw DynamoDB), and fragile error handling (string comparison).

</critical_reminders>

What ships with it: 5 files

30.5 KB alongside SKILL.md

examples/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.