JavaScript (AWS SDK v3)
Upload, list, download and delete Shelby objects with @aws-sdk/client-s3 in Node.js.
Prefer to run it? shelby-quickstart has this page as a script that checks every step and cleans up after itself.
Before you start
-
Node.js 22.18 or later, which runs TypeScript files directly
-
A project set up for ES modules, with the AWS SDK installed:
npm init -y npm pkg set type=module npm install @aws-sdk/client-s3 @aws-sdk/lib-storage
Copy your bucket name, and an access key ID and secret for that bucket, from the console. Export them so the commands below can use them:
export SHELBY_ACCESS_KEY_ID="<your access key ID, SHLB…>"
export SHELBY_SECRET_ACCESS_KEY="<your secret>"
export SHELBY_BUCKET="<your bucket name>"Create a client
import { S3Client } from "@aws-sdk/client-s3";
export const s3 = new S3Client({
endpoint: "https://s3.beta.shelby.xyz",
region: "default",
credentials: {
accessKeyId: process.env.SHELBY_ACCESS_KEY_ID!,
secretAccessKey: process.env.SHELBY_SECRET_ACCESS_KEY!,
},
forcePathStyle: true,
requestChecksumCalculation: "WHEN_REQUIRED",
responseChecksumValidation: "WHEN_REQUIRED",
});
export const Bucket = process.env.SHELBY_BUCKET!;requestChecksumCalculation is optional. It stops the SDK from computing CRC checksums
that Shelby accepts but doesn't verify.
responseChecksumValidation is needed for presigned download links. Without it, the SDK adds
x-amz-checksum-mode to them, which Shelby refuses with 501 NotImplemented. Shelby returns
no response checksums, so no check is lost.
Upload and read back
import {
GetObjectCommand,
ListObjectsV2Command,
PutObjectCommand,
} from "@aws-sdk/client-s3";
import { Bucket, s3 } from "./shelby-s3.ts";
const Key = "examples/hello.txt";
await s3.send(new PutObjectCommand({ Bucket, Key, Body: "Hello, Shelby\n" }));
const object = await s3.send(new GetObjectCommand({ Bucket, Key }));
console.log(await object.Body?.transformToString());
// A new object can take a few seconds to appear in listings.
const listing = await s3.send(
new ListObjectsV2Command({ Bucket, Prefix: "examples/" }),
);
for (const item of listing.Contents ?? []) console.log(item.Key, item.Size);Run it:
node quickstart.tsShare a download link
npm install @aws-sdk/s3-request-presignerimport { GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { Bucket, s3 } from "./shelby-s3.ts";
const url = await getSignedUrl(
s3,
new GetObjectCommand({ Bucket, Key: "examples/hello.txt" }),
{ expiresIn: 300 },
);
const response = await fetch(url); // sends no credentials
console.log(response.status, await response.text());node share.tsAnyone with url can download the object for the next 5 minutes, without credentials. Until
it expires, treat the link like a password. See
Presigned URLs.
Clean up
import { DeleteObjectCommand } from "@aws-sdk/client-s3";
import { Bucket, s3 } from "./shelby-s3.ts";
await s3.send(new DeleteObjectCommand({ Bucket, Key: "examples/hello.txt" }));node clean-up.tsUpload large files
Upload from @aws-sdk/lib-storage splits large bodies into parts, 5 MiB each by default.
Set partSize to at least 10 MiB, because smaller parts each count as 10 MiB of
storage, and large enough for your largest file to fit in Shelby's 3,000 parts:
import { createReadStream } from "node:fs";
import { Upload } from "@aws-sdk/lib-storage";
import { Bucket, s3 } from "./shelby-s3.ts";
await new Upload({
client: s3,
params: {
Bucket,
Key: "data/dataset.parquet",
Body: createReadStream("dataset.parquet"),
},
partSize: 64 * 1024 * 1024, // 64 MiB parts
}).done();What's different with the AWS SDK for JavaScript
- Run it on a server. Your secret must never reach a browser. To let a browser download an object, give it a presigned URL instead. Browsers can't upload, because Shelby has no presigned uploads.
CopyObjectCommandfails with501. Download and upload again.DeleteObjectsCommanddoesn't work yet. The SDK sends batch deletes in a form Shelby doesn't recognise, so nothing is deleted. Delete keys one at a time withDeleteObjectCommand. See Known compatibility issues.- Authentication failures surface as XML parse errors. Shelby returns a plain-text
401, which the SDK can't parse. See Troubleshooting.