[WIP] A (somewhat barebones) atproto app for creating custom sites without hosting!

server: minor backfill refactor

vielle.dev d1ad6c69 b6e105f8

verified
Changed files
+51 -602
lexicons
server
src
backfill
lexicons
types
com
atproto
-356
lexicons/com.atproto.sync.subscribeRepos.json
··· 1 - { 2 - "lexicon": 1, 3 - "id": "com.atproto.sync.subscribeRepos", 4 - "defs": { 5 - "info": { 6 - "type": "object", 7 - "required": [ 8 - "name" 9 - ], 10 - "properties": { 11 - "name": { 12 - "type": "string", 13 - "knownValues": [ 14 - "OutdatedCursor" 15 - ] 16 - }, 17 - "message": { 18 - "type": "string" 19 - } 20 - } 21 - }, 22 - "main": { 23 - "type": "subscription", 24 - "errors": [ 25 - { 26 - "name": "FutureCursor" 27 - }, 28 - { 29 - "name": "ConsumerTooSlow", 30 - "description": "If the consumer of the stream can not keep up with events, and a backlog gets too large, the server will drop the connection." 31 - } 32 - ], 33 - "message": { 34 - "schema": { 35 - "refs": [ 36 - "#commit", 37 - "#sync", 38 - "#identity", 39 - "#account", 40 - "#handle", 41 - "#migrate", 42 - "#tombstone", 43 - "#info" 44 - ], 45 - "type": "union" 46 - } 47 - }, 48 - "parameters": { 49 - "type": "params", 50 - "properties": { 51 - "cursor": { 52 - "type": "integer", 53 - "description": "The last known event seq number to backfill from." 54 - } 55 - } 56 - }, 57 - "description": "Repository event stream, aka Firehose endpoint. Outputs repo commits with diff data, and identity update events, for all repositories on the current server. See the atproto specifications for details around stream sequencing, repo versioning, CAR diff format, and more. Public and does not require auth; implemented by PDS and Relay." 58 - }, 59 - "sync": { 60 - "type": "object", 61 - "required": [ 62 - "seq", 63 - "did", 64 - "blocks", 65 - "rev", 66 - "time" 67 - ], 68 - "properties": { 69 - "did": { 70 - "type": "string", 71 - "format": "did", 72 - "description": "The account this repo event corresponds to. Must match that in the commit object." 73 - }, 74 - "rev": { 75 - "type": "string", 76 - "description": "The rev of the commit. This value must match that in the commit object." 77 - }, 78 - "seq": { 79 - "type": "integer", 80 - "description": "The stream sequence number of this message." 81 - }, 82 - "time": { 83 - "type": "string", 84 - "format": "datetime", 85 - "description": "Timestamp of when this message was originally broadcast." 86 - }, 87 - "blocks": { 88 - "type": "bytes", 89 - "maxLength": 10000, 90 - "description": "CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'." 91 - } 92 - }, 93 - "description": "Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository." 94 - }, 95 - "commit": { 96 - "type": "object", 97 - "nullable": [ 98 - "since" 99 - ], 100 - "required": [ 101 - "seq", 102 - "rebase", 103 - "tooBig", 104 - "repo", 105 - "commit", 106 - "rev", 107 - "since", 108 - "blocks", 109 - "ops", 110 - "blobs", 111 - "time" 112 - ], 113 - "properties": { 114 - "ops": { 115 - "type": "array", 116 - "items": { 117 - "ref": "#repoOp", 118 - "type": "ref", 119 - "description": "List of repo mutation operations in this commit (eg, records created, updated, or deleted)." 120 - }, 121 - "maxLength": 200 122 - }, 123 - "rev": { 124 - "type": "string", 125 - "format": "tid", 126 - "description": "The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event." 127 - }, 128 - "seq": { 129 - "type": "integer", 130 - "description": "The stream sequence number of this message." 131 - }, 132 - "repo": { 133 - "type": "string", 134 - "format": "did", 135 - "description": "The repo this event comes from. Note that all other message types name this field 'did'." 136 - }, 137 - "time": { 138 - "type": "string", 139 - "format": "datetime", 140 - "description": "Timestamp of when this message was originally broadcast." 141 - }, 142 - "blobs": { 143 - "type": "array", 144 - "items": { 145 - "type": "cid-link", 146 - "description": "DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit." 147 - } 148 - }, 149 - "since": { 150 - "type": "string", 151 - "format": "tid", 152 - "description": "The rev of the last emitted commit from this repo (if any)." 153 - }, 154 - "blocks": { 155 - "type": "bytes", 156 - "maxLength": 2000000, 157 - "description": "CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list." 158 - }, 159 - "commit": { 160 - "type": "cid-link", 161 - "description": "Repo commit object CID." 162 - }, 163 - "rebase": { 164 - "type": "boolean", 165 - "description": "DEPRECATED -- unused" 166 - }, 167 - "tooBig": { 168 - "type": "boolean", 169 - "description": "DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data." 170 - }, 171 - "prevData": { 172 - "type": "cid-link", 173 - "description": "The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose." 174 - } 175 - }, 176 - "description": "Represents an update of repository state. Note that empty commits are allowed, which include no repo data changes, but an update to rev and signature." 177 - }, 178 - "handle": { 179 - "type": "object", 180 - "required": [ 181 - "seq", 182 - "did", 183 - "handle", 184 - "time" 185 - ], 186 - "properties": { 187 - "did": { 188 - "type": "string", 189 - "format": "did" 190 - }, 191 - "seq": { 192 - "type": "integer" 193 - }, 194 - "time": { 195 - "type": "string", 196 - "format": "datetime" 197 - }, 198 - "handle": { 199 - "type": "string", 200 - "format": "handle" 201 - } 202 - }, 203 - "description": "DEPRECATED -- Use #identity event instead" 204 - }, 205 - "repoOp": { 206 - "type": "object", 207 - "nullable": [ 208 - "cid" 209 - ], 210 - "required": [ 211 - "action", 212 - "path", 213 - "cid" 214 - ], 215 - "properties": { 216 - "cid": { 217 - "type": "cid-link", 218 - "description": "For creates and updates, the new record CID. For deletions, null." 219 - }, 220 - "path": { 221 - "type": "string" 222 - }, 223 - "prev": { 224 - "type": "cid-link", 225 - "description": "For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined." 226 - }, 227 - "action": { 228 - "type": "string", 229 - "knownValues": [ 230 - "create", 231 - "update", 232 - "delete" 233 - ] 234 - } 235 - }, 236 - "description": "A repo operation, ie a mutation of a single record." 237 - }, 238 - "account": { 239 - "type": "object", 240 - "required": [ 241 - "seq", 242 - "did", 243 - "time", 244 - "active" 245 - ], 246 - "properties": { 247 - "did": { 248 - "type": "string", 249 - "format": "did" 250 - }, 251 - "seq": { 252 - "type": "integer" 253 - }, 254 - "time": { 255 - "type": "string", 256 - "format": "datetime" 257 - }, 258 - "active": { 259 - "type": "boolean", 260 - "description": "Indicates that the account has a repository which can be fetched from the host that emitted this event." 261 - }, 262 - "status": { 263 - "type": "string", 264 - "description": "If active=false, this optional field indicates a reason for why the account is not active.", 265 - "knownValues": [ 266 - "takendown", 267 - "suspended", 268 - "deleted", 269 - "deactivated", 270 - "desynchronized", 271 - "throttled" 272 - ] 273 - } 274 - }, 275 - "description": "Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active." 276 - }, 277 - "migrate": { 278 - "type": "object", 279 - "nullable": [ 280 - "migrateTo" 281 - ], 282 - "required": [ 283 - "seq", 284 - "did", 285 - "migrateTo", 286 - "time" 287 - ], 288 - "properties": { 289 - "did": { 290 - "type": "string", 291 - "format": "did" 292 - }, 293 - "seq": { 294 - "type": "integer" 295 - }, 296 - "time": { 297 - "type": "string", 298 - "format": "datetime" 299 - }, 300 - "migrateTo": { 301 - "type": "string" 302 - } 303 - }, 304 - "description": "DEPRECATED -- Use #account event instead" 305 - }, 306 - "identity": { 307 - "type": "object", 308 - "required": [ 309 - "seq", 310 - "did", 311 - "time" 312 - ], 313 - "properties": { 314 - "did": { 315 - "type": "string", 316 - "format": "did" 317 - }, 318 - "seq": { 319 - "type": "integer" 320 - }, 321 - "time": { 322 - "type": "string", 323 - "format": "datetime" 324 - }, 325 - "handle": { 326 - "type": "string", 327 - "format": "handle", 328 - "description": "The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details." 329 - } 330 - }, 331 - "description": "Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache." 332 - }, 333 - "tombstone": { 334 - "type": "object", 335 - "required": [ 336 - "seq", 337 - "did", 338 - "time" 339 - ], 340 - "properties": { 341 - "did": { 342 - "type": "string", 343 - "format": "did" 344 - }, 345 - "seq": { 346 - "type": "integer" 347 - }, 348 - "time": { 349 - "type": "string", 350 - "format": "datetime" 351 - } 352 - }, 353 - "description": "DEPRECATED -- Use #account event instead" 354 - } 355 - } 356 - }
+6 -21
server/src/backfill/index.ts
··· 2 2 import { routes } from "../db/schema.ts"; 3 3 import * as schema from "../db/schema.ts"; 4 4 import { db as db_type } from "../utils.ts"; 5 - import { Client, simpleFetchHandler } from "@atcute/client"; 6 5 import oldRecords from "./old-records.ts"; 7 6 import newRecords from "./new-records.ts"; 8 7 ··· 10 9 Deno.env.get("DB_FILE_NAME")! || 11 10 (() => { 12 11 throw "DB_FILE_NAME not set"; 13 - })(), 12 + })() 14 13 ); 15 14 16 - // we block access to the database till we've set up listeners etc 17 - // set an initial value for ts sake; this will set asap 18 - let res: (value: db_type) => void = (v) => console.log("failed to set", v); 19 - export default new Promise<db_type>((p_res) => { 20 - res = p_res; 21 - }); 22 - 23 - // clear old records 15 + // clear old records & blobs 24 16 // accounts could have deleted their sites or anything 25 17 // so we should just nuke them 18 + // blobs could be kept but would be a nightmare 26 19 await db.delete(routes); 20 + await Deno.remove("./blobs", { recursive: true }); 27 21 28 - const relay = new Client({ 29 - handler: simpleFetchHandler({ 30 - service: Deno.env.get("ATPROTO_RELAY") || 31 - (() => { 32 - throw "ATPROTO_RELAY not set"; 33 - })(), 34 - }), 35 - }); 36 - 37 - oldRecords(db, relay); 22 + oldRecords(db); 38 23 newRecords(db); 39 24 40 - res(db); 25 + export default db;
+26 -37
server/src/backfill/new-records.ts
··· 1 1 import { db, getPds, isDid, rkeyToUrl } from "../utils.ts"; 2 2 import { decodeFirst } from "@atcute/cbor"; 3 - import { 4 - ComAtprotoSyncSubscribeRepos, 5 - DevAtcitiesRoute, 6 - } from "../lexicons/index.ts"; 3 + import { DevAtcitiesRoute } from "../lexicons/index.ts"; 7 4 import { is } from "@atcute/lexicons"; 5 + import { ComAtprotoSyncSubscribeRepos } from "@atcute/atproto"; 8 6 import { Client, simpleFetchHandler } from "@atcute/client"; 9 7 import { routes } from "../db/schema.ts"; 10 8 import { and, eq } from "drizzle-orm"; 11 9 12 10 const ErrorEvent = Symbol("error event"); 13 - export default async function newRecords(db: db) { 11 + export default function newRecords(db: db) { 14 12 // https://pdsls.dev/at://did:plc:6msi3pj7krzih5qxqtryxlzw/com.atproto.lexicon.schema/com.atproto.sync.subscribeRepos 15 13 const ws = new WebSocket( 16 14 `${ ··· 27 25 ws.addEventListener("error", (ev) => { 28 26 throw ev; 29 27 }); 28 + ws.addEventListener("open", () => console.log("Listening for new events.")); 30 29 31 30 try { 32 31 ws.addEventListener("message", async (ev) => { ··· 43 42 throw ErrorEvent; 44 43 } 45 44 45 + // we only care about commits 46 + // identity events and similar are irrelevant 46 47 if (!is(ComAtprotoSyncSubscribeRepos.commitSchema, payload)) { 47 48 return; 48 49 } ··· 50 51 console.warn("Invalid did:", payload.repo); 51 52 return; 52 53 } 54 + const pds = await getPds(payload.repo); 55 + if (!pds) { 56 + return; 57 + } 53 58 54 - const pdsClient = (() => { 55 - let client: Client | undefined; 56 - return async () => { 57 - if (client) { 58 - return client; 59 - } 60 - if (!isDid(payload.repo)) { 61 - console.warn("Invalid did:", payload.repo); 62 - return; 63 - } 64 - 65 - const pds = await getPds(payload.repo); 66 - if (!pds) { 67 - return; 68 - } 69 - client = new Client({ 70 - handler: simpleFetchHandler({ 71 - service: pds, 72 - }), 73 - }); 74 - 75 - return client; 76 - }; 77 - })(); 59 + const client = new Client({ 60 + handler: simpleFetchHandler({ 61 + service: pds, 62 + }), 63 + }); 78 64 79 65 for (const op of payload.ops) { 80 66 const [collection, rkey] = op.path.split("/"); 67 + if (!collection || !rkey) { 68 + console.warn("Invalid path", op.path); 69 + continue; 70 + } 81 71 const path = rkeyToUrl(rkey); 82 72 if (!path) { 83 73 console.warn("rkey not valid!"); 84 74 continue; 85 75 } 86 76 if (collection !== "dev.atcities.route") continue; 77 + 87 78 switch (op.action) { 88 79 case "create": 89 80 case "update": { 90 - const client = await pdsClient(); 91 - if (!client) { 92 - console.warn("could not resolve pds for", payload.repo); 93 - return; 94 - } 81 + // hydrate data 95 82 const { data, ok } = await client.get( 96 83 "com.atproto.repo.getRecord", 97 84 { ··· 109 96 } 110 97 111 98 if (!is(DevAtcitiesRoute.mainSchema, data.value)) { 112 - console.warn("Invalid record"); 99 + console.warn( 100 + "Invalid record:", 101 + `at://${payload.repo}/dev.atcities.route.${rkey}` 102 + ); 113 103 continue; 114 104 } 115 105 116 106 if (data.value.page.$type !== "dev.atcities.route#blob") { 117 - console.warn("Unknown page type"); 118 107 continue; 119 108 } 120 109 110 + // if this page exists in db, get the id so it can be replaced 121 111 const id = ( 122 112 await db 123 113 .select({ ··· 198 188 if (e === ErrorEvent) newRecords(db); 199 189 else throw e; 200 190 } 201 - ws.addEventListener("open", () => console.log("subscribed!!")); 202 191 }
+19 -3
server/src/backfill/old-records.ts
··· 4 4 import { DevAtcitiesRoute } from "../lexicons/index.ts"; 5 5 import { routes } from "../db/schema.ts"; 6 6 7 - async function index(did: `did:${"web" | "plc"}:${string}`, db: db) { 7 + async function indexUser(did: `did:${"web" | "plc"}:${string}`, db: db) { 8 8 const pds = await getPds(did); 9 9 if (!pds) return console.error(did, "could not be resolved to a pds."); 10 10 const pdsClient = new Client({ 11 11 handler: simpleFetchHandler({ service: pds }), 12 12 }); 13 + 13 14 let cursor: string | undefined; 14 15 while (true) { 15 16 const { data, ok } = await pdsClient.get("com.atproto.repo.listRecords", { ··· 27 28 28 29 for (const record of data.records) { 29 30 if (is(DevAtcitiesRoute.mainSchema, record.value)) { 31 + // ignore non blob page values 32 + // this will be expanded in future 30 33 if (record.value.page.$type === "dev.atcities.route#blob") { 31 34 const url = rkeyToUrl(record.uri.split("/")[4]); 32 35 if (!url) continue; ··· 49 52 } 50 53 } 51 54 52 - export default async function (db: db, relay: Client) { 55 + export default async function (db: db) { 56 + const relay = new Client({ 57 + handler: simpleFetchHandler({ 58 + service: 59 + Deno.env.get("ATPROTO_RELAY") || 60 + (() => { 61 + throw "ATPROTO_RELAY not set"; 62 + })(), 63 + }), 64 + }); 65 + 53 66 let repos: `did:${string}:${string}`[] = []; 54 67 let cursor: string | undefined; 55 68 while (true) { ··· 72 85 if (!cursor) break; 73 86 } 74 87 88 + const pending: Promise<unknown>[] = []; 75 89 for (const i in repos) { 76 90 const did = repos[i]; 77 91 console.log(`indexing ${Number(i) + 1}/${repos.length} ${did}`); 78 - if (isDid(did)) index(did, db); 92 + if (isDid(did)) pending.push(indexUser(did, db)); 79 93 } 94 + await Promise.all(pending); 95 + console.log("Finished backfilling."); 80 96 }
-1
server/src/lexicons/index.ts
··· 1 - export * as ComAtprotoSyncSubscribeRepos from "./types/com/atproto/sync/subscribeRepos.ts"; 2 1 export * as DevAtcitiesRoute from "./types/dev/atcities/route.ts";
-184
server/src/lexicons/types/com/atproto/sync/subscribeRepos.ts
··· 1 - import type {} from "@atcute/lexicons"; 2 - import * as v from "@atcute/lexicons/validations"; 3 - import type {} from "@atcute/lexicons/ambient"; 4 - 5 - const _accountSchema = /*#__PURE__*/ v.object({ 6 - $type: /*#__PURE__*/ v.optional( 7 - /*#__PURE__*/ v.literal("com.atproto.sync.subscribeRepos#account"), 8 - ), 9 - active: /*#__PURE__*/ v.boolean(), 10 - did: /*#__PURE__*/ v.didString(), 11 - seq: /*#__PURE__*/ v.integer(), 12 - status: /*#__PURE__*/ v.optional( 13 - /*#__PURE__*/ v.string< 14 - | "deactivated" 15 - | "deleted" 16 - | "desynchronized" 17 - | "suspended" 18 - | "takendown" 19 - | "throttled" 20 - | (string & {}) 21 - >(), 22 - ), 23 - time: /*#__PURE__*/ v.datetimeString(), 24 - }); 25 - const _commitSchema = /*#__PURE__*/ v.object({ 26 - $type: /*#__PURE__*/ v.optional( 27 - /*#__PURE__*/ v.literal("com.atproto.sync.subscribeRepos#commit"), 28 - ), 29 - blobs: /*#__PURE__*/ v.array(/*#__PURE__*/ v.cidLink()), 30 - blocks: /*#__PURE__*/ v.constrain(/*#__PURE__*/ v.bytes(), [ 31 - /*#__PURE__*/ v.bytesSize(0, 2000000), 32 - ]), 33 - commit: /*#__PURE__*/ v.cidLink(), 34 - get ops() { 35 - return /*#__PURE__*/ v.constrain(/*#__PURE__*/ v.array(repoOpSchema), [ 36 - /*#__PURE__*/ v.arrayLength(0, 200), 37 - ]); 38 - }, 39 - prevData: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidLink()), 40 - rebase: /*#__PURE__*/ v.boolean(), 41 - repo: /*#__PURE__*/ v.didString(), 42 - rev: /*#__PURE__*/ v.tidString(), 43 - seq: /*#__PURE__*/ v.integer(), 44 - since: /*#__PURE__*/ v.nullable(/*#__PURE__*/ v.tidString()), 45 - time: /*#__PURE__*/ v.datetimeString(), 46 - tooBig: /*#__PURE__*/ v.boolean(), 47 - }); 48 - const _handleSchema = /*#__PURE__*/ v.object({ 49 - $type: /*#__PURE__*/ v.optional( 50 - /*#__PURE__*/ v.literal("com.atproto.sync.subscribeRepos#handle"), 51 - ), 52 - did: /*#__PURE__*/ v.didString(), 53 - handle: /*#__PURE__*/ v.handleString(), 54 - seq: /*#__PURE__*/ v.integer(), 55 - time: /*#__PURE__*/ v.datetimeString(), 56 - }); 57 - const _identitySchema = /*#__PURE__*/ v.object({ 58 - $type: /*#__PURE__*/ v.optional( 59 - /*#__PURE__*/ v.literal("com.atproto.sync.subscribeRepos#identity"), 60 - ), 61 - did: /*#__PURE__*/ v.didString(), 62 - handle: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.handleString()), 63 - seq: /*#__PURE__*/ v.integer(), 64 - time: /*#__PURE__*/ v.datetimeString(), 65 - }); 66 - const _infoSchema = /*#__PURE__*/ v.object({ 67 - $type: /*#__PURE__*/ v.optional( 68 - /*#__PURE__*/ v.literal("com.atproto.sync.subscribeRepos#info"), 69 - ), 70 - message: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), 71 - name: /*#__PURE__*/ v.string<"OutdatedCursor" | (string & {})>(), 72 - }); 73 - const _mainSchema = /*#__PURE__*/ v.subscription( 74 - "com.atproto.sync.subscribeRepos", 75 - { 76 - params: /*#__PURE__*/ v.object({ 77 - cursor: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.integer()), 78 - }), 79 - get message() { 80 - return /*#__PURE__*/ v.variant([ 81 - accountSchema, 82 - commitSchema, 83 - handleSchema, 84 - identitySchema, 85 - infoSchema, 86 - migrateSchema, 87 - syncSchema, 88 - tombstoneSchema, 89 - ]); 90 - }, 91 - }, 92 - ); 93 - const _migrateSchema = /*#__PURE__*/ v.object({ 94 - $type: /*#__PURE__*/ v.optional( 95 - /*#__PURE__*/ v.literal("com.atproto.sync.subscribeRepos#migrate"), 96 - ), 97 - did: /*#__PURE__*/ v.didString(), 98 - migrateTo: /*#__PURE__*/ v.nullable(/*#__PURE__*/ v.string()), 99 - seq: /*#__PURE__*/ v.integer(), 100 - time: /*#__PURE__*/ v.datetimeString(), 101 - }); 102 - const _repoOpSchema = /*#__PURE__*/ v.object({ 103 - $type: /*#__PURE__*/ v.optional( 104 - /*#__PURE__*/ v.literal("com.atproto.sync.subscribeRepos#repoOp"), 105 - ), 106 - action: /*#__PURE__*/ v.string< 107 - "create" | "delete" | "update" | (string & {}) 108 - >(), 109 - cid: /*#__PURE__*/ v.nullable(/*#__PURE__*/ v.cidLink()), 110 - path: /*#__PURE__*/ v.string(), 111 - prev: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.cidLink()), 112 - }); 113 - const _syncSchema = /*#__PURE__*/ v.object({ 114 - $type: /*#__PURE__*/ v.optional( 115 - /*#__PURE__*/ v.literal("com.atproto.sync.subscribeRepos#sync"), 116 - ), 117 - blocks: /*#__PURE__*/ v.constrain(/*#__PURE__*/ v.bytes(), [ 118 - /*#__PURE__*/ v.bytesSize(0, 10000), 119 - ]), 120 - did: /*#__PURE__*/ v.didString(), 121 - rev: /*#__PURE__*/ v.string(), 122 - seq: /*#__PURE__*/ v.integer(), 123 - time: /*#__PURE__*/ v.datetimeString(), 124 - }); 125 - const _tombstoneSchema = /*#__PURE__*/ v.object({ 126 - $type: /*#__PURE__*/ v.optional( 127 - /*#__PURE__*/ v.literal("com.atproto.sync.subscribeRepos#tombstone"), 128 - ), 129 - did: /*#__PURE__*/ v.didString(), 130 - seq: /*#__PURE__*/ v.integer(), 131 - time: /*#__PURE__*/ v.datetimeString(), 132 - }); 133 - 134 - type account$schematype = typeof _accountSchema; 135 - type commit$schematype = typeof _commitSchema; 136 - type handle$schematype = typeof _handleSchema; 137 - type identity$schematype = typeof _identitySchema; 138 - type info$schematype = typeof _infoSchema; 139 - type main$schematype = typeof _mainSchema; 140 - type migrate$schematype = typeof _migrateSchema; 141 - type repoOp$schematype = typeof _repoOpSchema; 142 - type sync$schematype = typeof _syncSchema; 143 - type tombstone$schematype = typeof _tombstoneSchema; 144 - 145 - export interface accountSchema extends account$schematype {} 146 - export interface commitSchema extends commit$schematype {} 147 - export interface handleSchema extends handle$schematype {} 148 - export interface identitySchema extends identity$schematype {} 149 - export interface infoSchema extends info$schematype {} 150 - export interface mainSchema extends main$schematype {} 151 - export interface migrateSchema extends migrate$schematype {} 152 - export interface repoOpSchema extends repoOp$schematype {} 153 - export interface syncSchema extends sync$schematype {} 154 - export interface tombstoneSchema extends tombstone$schematype {} 155 - 156 - export const accountSchema = _accountSchema as accountSchema; 157 - export const commitSchema = _commitSchema as commitSchema; 158 - export const handleSchema = _handleSchema as handleSchema; 159 - export const identitySchema = _identitySchema as identitySchema; 160 - export const infoSchema = _infoSchema as infoSchema; 161 - export const mainSchema = _mainSchema as mainSchema; 162 - export const migrateSchema = _migrateSchema as migrateSchema; 163 - export const repoOpSchema = _repoOpSchema as repoOpSchema; 164 - export const syncSchema = _syncSchema as syncSchema; 165 - export const tombstoneSchema = _tombstoneSchema as tombstoneSchema; 166 - 167 - export interface Account extends v.InferInput<typeof accountSchema> {} 168 - export interface Commit extends v.InferInput<typeof commitSchema> {} 169 - export interface Handle extends v.InferInput<typeof handleSchema> {} 170 - export interface Identity extends v.InferInput<typeof identitySchema> {} 171 - export interface Info extends v.InferInput<typeof infoSchema> {} 172 - export interface Migrate extends v.InferInput<typeof migrateSchema> {} 173 - export interface RepoOp extends v.InferInput<typeof repoOpSchema> {} 174 - export interface Sync extends v.InferInput<typeof syncSchema> {} 175 - export interface Tombstone extends v.InferInput<typeof tombstoneSchema> {} 176 - 177 - export interface $params extends v.InferInput<mainSchema["params"]> {} 178 - export type $message = v.InferInput<mainSchema["message"]>; 179 - 180 - declare module "@atcute/lexicons/ambient" { 181 - interface XRPCSubscriptions { 182 - "com.atproto.sync.subscribeRepos": mainSchema; 183 - } 184 - }