> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS JavaScript and TypeScript SDK Guide

> Configure AWS SDK for JavaScript v3 to call a Cloud Adapter endpoint.

Use the normal AWS commands and response types, but construct the client with the Cloud Adapter endpoint. The example below uses AWS SDK for JavaScript v3 and S3.

## Choose how to set the endpoint

### Set it for the process

```bash theme={null}
export AWS_ENDPOINT_URL_S3="https://adapter.example.test"
```

AWS SDK for JavaScript v3 reads that service-specific setting when the client has no explicit `endpoint`:

```ts theme={null}
import { S3Client } from "@aws-sdk/client-s3";
import { fromIni } from "@aws-sdk/credential-providers";

const client = new S3Client({
  region: process.env.AWS_REGION ?? "us-east-1",
  credentials: fromIni({ profile: "adapter-test" }),
  forcePathStyle: true,
  maxAttempts: 3,
});
```

### Set it on one client

```bash theme={null}
export T9_CLOUD_ADAPTER_ENDPOINT="https://adapter.example.test"
```

```ts theme={null}
import { fromIni } from "@aws-sdk/credential-providers";
import {
  DeleteObjectCommand,
  GetObjectCommand,
  HeadObjectCommand,
  PutObjectCommand,
  S3Client,
} from "@aws-sdk/client-s3";

const client = new S3Client({
  endpoint: process.env.T9_CLOUD_ADAPTER_ENDPOINT,
  region: process.env.AWS_REGION ?? "us-east-1",
  credentials: fromIni({ profile: "adapter-test" }),
  forcePathStyle: true,
  maxAttempts: 3,
});
```

Keep this endpoint decision in dependency injection or a client factory. Do not make every call site know whether it is talking to AWS or Cloud Adapter.

The explicit `endpoint` wins when `AWS_ENDPOINT_URL_S3` is also set. Avoid setting both to different values.

For SDK v2, use the v2 client's `endpoint` and `s3ForcePathStyle` settings. Avoid silently selecting different endpoint behavior during a v2-to-v3 migration.

## Exercise create, read, compare, and delete

```ts theme={null}
const bucket = process.env.TEST_BUCKET!;
const key = `typescript/${Date.now()}-hello.txt`;
const expected = Buffer.from("hello through Cloud Adapter\n");

await client.send(new PutObjectCommand({
  Bucket: bucket,
  Key: key,
  Body: expected,
  ContentType: "text/plain",
}));
await client.send(new HeadObjectCommand({ Bucket: bucket, Key: key }));

const response = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
const actual = Buffer.from(await response.Body!.transformToByteArray());
if (!actual.equals(expected)) throw new Error("Object bytes changed in transit");

await client.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));
```

After the write, inspect the native target object. Confirm the target name, content type, metadata, and bytes.

## Log useful failures safely

AWS SDK v3 service exceptions include `$metadata`:

```ts theme={null}
try {
  await client.send(new HeadObjectCommand({ Bucket: bucket, Key: "missing-key" }));
} catch (error: any) {
  console.error({
    name: error.name,
    message: error.message,
    status: error.$metadata?.httpStatusCode,
    requestId: error.$metadata?.requestId,
    attempts: error.$metadata?.attempts,
  });
}
```

Do not log the complete request object, authorization headers, signed URLs, or response bodies. For a timeout after a mutation, inspect the target before retrying.

## Test what your application actually uses

The basic lifecycle does not certify paginators, multipart upload, conditional headers, presigned URLs, tags, version IDs, or retries. Add each feature to an integration test and compare it with the target-specific behavior on the [S3 service page](/cloud-adapter/service-catalog/aws/databases-storage/s3).

Use [Testing Your Adapters](/cloud-adapter/local-testing/testing-your-adapters) for repeatable tests and [Debugging Your Adapters](/cloud-adapter/debugging/overview) for translated errors.
