veR2

Quickstart: SDK

This page walks through the whole lifecycle of a versioned object. It assumes you've installed @ver2/sdk and @aws-sdk/client-s3 and have R2 credentials.

Create a client

import { createVer2 } from "@ver2/sdk";
import { S3ObjectStore } from "@ver2/sdk/s3";
 
const ver2 = createVer2({
  store: new S3ObjectStore({
    bucket: process.env.R2_BUCKET!,
    accountId: process.env.R2_ACCOUNT_ID,
    credentials: {
      accessKeyId: process.env.R2_ACCESS_KEY_ID!,
      secretAccessKey: process.env.R2_SECRET_ACCESS_KEY!,
    },
  }),
});

createVer2 takes more options (namespace, lease, a custom metadata store); see Configuration.

Write versions

const v1 = await ver2.put("docs/report.txt", "first draft", {
  headers: { contentType: "text/plain" },
});
const v2 = await ver2.put("docs/report.txt", new TextEncoder().encode("second draft"));

put accepts a Uint8Array or a string and returns { key, versionId, sha256, size, etag }. The object at docs/report.txt is now "second draft", exactly as if you had written it to R2 directly, and both versions are kept.

Read the history

const history = await ver2.versions.list("docs/report.txt");
for (const v of history) console.log(v.versionId, v.kind, v.source, v.createdAt, v.size);

History is newest first. Each record has:

FieldMeaning
versionIdA ULID identifying the version
kindput or delete
sourcever2 (written through veR2), external (a direct write to R2 that veR2 preserved) or restore
createdAtISO timestamp
size, sha256, headersFor put versions
restoredFromFor restores, the version that was restored

Restore an old version

await ver2.versions.restore("docs/report.txt", v1.versionId);

The object at the key goes back to "first draft". A restore doesn't rewrite history: it adds a new version with source: "restore" and restoredFrom set to v1.versionId.

Download any version

const { record, body } = await ver2.versions.download("docs/report.txt", v2.versionId);
const text = await new Response(body).text();

Leave out the version ID to get the current version. body is a ReadableStream, and veR2 checks its SHA-256 as it streams. If the bytes don't match what was recorded, the stream errors at the end with INTEGRITY_CHECK_FAILED, so don't trust the data until the stream has finished.

Delete

await ver2.delete("docs/report.txt");

The object at the key is removed and a delete marker is added to the history. Nothing else is lost: every earlier version can still be downloaded or restored. If nothing was there to delete, the result's versionId is null.

List versioned keys

const { keys, cursor } = await ver2.list("docs/", { limit: 100 });

This lists keys veR2 has a history for, including keys that are currently deleted. Pass cursor back in to get the next page.

Handle errors

Every error veR2 throws on purpose is a Ver2Error with a stable code:

import { Ver2Error } from "@ver2/sdk";
 
try {
  await ver2.versions.restore("docs/report.txt", "01JUNKNOWNVERSION0000000000");
} catch (e) {
  if (e instanceof Ver2Error && e.code === "VERSION_NOT_FOUND") {
    // show the user the list of versions instead
  } else {
    throw e;
  }
}

See Errors for every code and what to do about it.