AT Protocol utilities.
npm install atsync
import { AtObject } from "atsync"
const app = await AtObject.initialize(["app.bsky.feed.post"], null)
app.listen("wss://bsky.network")
app.close()
app.listen("wss://bsky.network", {
onConnect: () => console.log("Connected to firehose"),
onDisconnect: () => console.log("Disconnected from firehose"),
onError: (error) => console.error("Firehose error:", error)
})
const cursor = "123456789"
await app.backfill("wss://bsky.network", cursor, {
onConnect: () => console.log("Started backfill"),
onDisconnect: () => console.log("Backfill complete")
})
const users = ["alice.bsky.social", "bob.bsky.social", "did:plc:example"]
await app.backfillUsers(users)
// Track multiple collections
const app = await AtObject.initialize([
"com.whtwnd.blog.entry",
"app.bsky.feed.post"
], null)
// Rename tables for collections
const app = await AtObject.initialize([
{ $type: "com.whtwnd.blog.entry", table: "entries" },
{ $type: "app.bsky.feed.post", table: "posts" }
], null)
const app = await AtObject.initialize({
entries: "com.whtwnd.blog.entry",
comments: {
nsid: "app.bsky.feed.post",
filter: (creator: string, rkey: string, post: Post) => {
// Only index posts that are replies
return post.reply && post.reply.parent && post.reply.root
}
}
}, null)
const app = await AtObject.initialize({
posts: {
nsid: "app.bsky.feed.post",
handler: async (creator: string, rkey: string, post: Post | null, db) => {
if (post === null) {
// Handle deletion
await db.delete("posts", rkey)
} else {
// Custom processing
if (post.text.includes("canvas")) {
await db.set("posts", { rkey, record: post })
}
}
}
}
}, null)
// sqlite
const app = await AtObject.initialize(collections, "./data.db")
// postgres
const app2 = await AtObject.initialize(collections, "postgres://user:pass@localhost/db")
// in-memory sqlite
const app3 = await AtObject.initialize(collections, null)
// Query all records from a table
const posts = await app.db.query("posts")
// Get specific record
const post = await app.db.get("posts", "specific-rkey")
// Delete record
await app.db.delete("posts", "rkey-to-delete")