Skip to content

canvasxyz/atsync

Repository files navigation

atsync

AT Protocol utilities.

Installation

npm install atsync

Usage

import { AtObject } from "atsync"

const app = await AtObject.initialize(["app.bsky.feed.post"], null)

app.listen("wss://bsky.network")

app.close()

Listen to a relay

app.listen("wss://bsky.network", {
  onConnect: () => console.log("Connected to firehose"),
  onDisconnect: () => console.log("Disconnected from firehose"),
  onError: (error) => console.error("Firehose error:", error)
})

Backfill from a relay (limited to ~12h of history)

const cursor = "123456789"
await app.backfill("wss://bsky.network", cursor, {
  onConnect: () => console.log("Started backfill"),
  onDisconnect: () => console.log("Backfill complete")
})

Backfill from PDSes

const users = ["alice.bsky.social", "bob.bsky.social", "did:plc:example"]
await app.backfillUsers(users)

Initialization

Simple Collections

// Track multiple collections
const app = await AtObject.initialize([
  "com.whtwnd.blog.entry",
  "app.bsky.feed.post"
], null)

Named Tables

// Rename tables for collections
const app = await AtObject.initialize([
  { $type: "com.whtwnd.blog.entry", table: "entries" },
  { $type: "app.bsky.feed.post", table: "posts" }
], null)

Filters

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)

Custom Handlers

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)

Database Setup

// 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)

Database Querying

// 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")

About

ATProto sync utilities

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published