a collection of lightweight TypeScript packages for AT Protocol, the protocol powering Bluesky
atproto bluesky typescript npm
README.md

@atcute/repo#

read AT Protocol repository exports.

npm install @atcute/repo

AT Protocol stores user data in repositories - Merkle tree structures containing records organized by collection. this package reads repository CAR exports (from com.atproto.sync.getRepo or account exports) and iterates over the records.

usage#

streaming usage#

import { fromStream } from '@atcute/repo';

const stream = new ReadableStream({
	/* ... */
});

await using repo = fromStream(stream);

for await (const entry of repo) {
	entry;
	// ^? RepoEntry { collection: 'app.bsky.feed.post', rkey: '3lprcc55bb222', ... }
}

repo.missingBlocks;
//   ^? []

streaming usage (for runtimes without await using yet)#

const repo = fromStream(stream);

try {
	for await (const entry of repo) {
		entry;
		// ^? RepoEntry
	}
} finally {
	await repo.dispose();
}

sync usage#

const buffer = Uint8Array.from([
	/* ... */
]);

const repo = fromUint8Array(buffer);

for (const entry of repo) {
	entry;
	// ^? RepoEntry { collection: 'app.bsky.feed.post', rkey: '3lprcc55bb222', ... }
}

repo.missingBlocks;
//   ^? []

verifying records#

verify a record's inclusion in a repository with optional signature verification:

import { verifyRecord } from '@atcute/repo';

const { cid, record } = await verifyRecord({
	collection: 'app.bsky.feed.post',
	rkey: '3lprcc55bb222',
	carBytes: carBytes,
	// optional: verify commit signature
	publicKey: key,
	// optional: verify DID matches
	did: 'did:plc:...',
});

transform streams#

for piping repository data through a transform:

import { repoEntryTransform } from '@atcute/repo';

const { readable, writable } = repoEntryTransform();

// pipe CAR data in, get RepoEntry objects out
response.body.pipeTo(writable);

for await (const entry of readable) {
	console.log(entry.collection, entry.rkey);
}