@atproto/sync 0.3.5 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @atproto/sync
2
2
 
3
+ ## 0.3.7
4
+
5
+ ### Patch Changes
6
+
7
+ - [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Update TypeScript build to rely on references to composite internal projects
8
+
9
+ - [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Bundle only necessary files in the NPM tarball, including the `CHANGELOG.md` and `README.md` files (if present).
10
+
11
+ - [#5099](https://github.com/bluesky-social/atproto/pull/5099) [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Build with `noImplicitAny` enabled
12
+
13
+ - Updated dependencies [[`28a0b58`](https://github.com/bluesky-social/atproto/commit/28a0b588147863eaef948cd2bb8fc0f19d08cda9), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07), [`b43ec31`](https://github.com/bluesky-social/atproto/commit/b43ec31f247f4461725b01226885f88bd430ca07)]:
14
+ - @atproto/syntax@0.6.4
15
+ - @atproto/identity@0.5.3
16
+ - @atproto/xrpc-server@0.11.6
17
+ - @atproto/lex@0.1.7
18
+ - @atproto/common@0.6.5
19
+ - @atproto/repo@0.10.3
20
+
21
+ ## 0.3.6
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies []:
26
+ - @atproto/lex@0.1.6
27
+ - @atproto/xrpc-server@0.11.5
28
+
3
29
  ## 0.3.5
4
30
 
5
31
  ### Patch Changes
@@ -26,7 +26,7 @@ export declare class Firehose {
26
26
  private destoryDefer;
27
27
  private matchCollection;
28
28
  constructor(opts: FirehoseOptions);
29
- start(): any;
29
+ start(): Promise<void>;
30
30
  private parseEvt;
31
31
  private processEvt;
32
32
  destroy(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/firehose/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/firehose/index.ts"],"names":[],"mappings":"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"}
@@ -87,7 +87,7 @@ export class Firehose {
87
87
  }
88
88
  }
89
89
  catch (err) {
90
- if (err && err['name'] === 'AbortError') {
90
+ if (err?.name === 'AbortError') {
91
91
  this.destoryDefer.resolve();
92
92
  return;
93
93
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/firehose/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ClientOptions } from 'ws'\nimport { Deferrable, createDeferrable, wait } from '@atproto/common'\nimport {\n DidDocument,\n IdResolver,\n parseToAtprotoDocument,\n} from '@atproto/identity'\nimport { Cid } from '@atproto/lex'\nimport {\n RepoVerificationError,\n cborToLexRecord,\n formatDataKey,\n parseDataKey,\n readCar,\n readCarWithRoot,\n verifyProofs,\n} from '@atproto/repo'\nimport { AtUri } from '@atproto/syntax'\nimport { Subscription } from '@atproto/xrpc-server'\nimport {\n AccountEvt,\n AccountStatus,\n CommitEvt,\n CommitMeta,\n Event,\n IdentityEvt,\n SyncEvt,\n} from '../events.js'\nimport { com } from '../lexicons/index.js'\nimport { EventRunner } from '../runner/index.js'\nimport { didAndSeqForEvt } from '../util.js'\n\nexport type FirehoseOptions = ClientOptions & {\n idResolver: IdResolver\n\n handleEvent: (evt: Event) => void | Promise<void>\n onError: (err: Error) => void\n getCursor?: () => number | undefined | Promise<number | undefined>\n\n runner?: EventRunner // should only set getCursor *or* runner\n\n service?: string\n subscriptionReconnectDelay?: number\n\n unauthenticatedCommits?: boolean\n unauthenticatedHandles?: boolean\n\n filterCollections?: string[]\n excludeIdentity?: boolean\n excludeAccount?: boolean\n excludeCommit?: boolean\n excludeSync?: boolean\n}\n\nexport class Firehose {\n private sub: Subscription<com.atproto.sync.subscribeRepos.$Message>\n private abortController: AbortController\n private destoryDefer: Deferrable\n private matchCollection: ((col: string) => boolean) | null = null\n\n constructor(public opts: FirehoseOptions) {\n this.destoryDefer = createDeferrable()\n this.abortController = new AbortController()\n if (this.opts.getCursor && this.opts.runner) {\n throw new Error('Must set only `getCursor` or `runner`')\n }\n if (opts.filterCollections) {\n const exact = new Set<string>()\n const prefixes: string[] = []\n\n for (const pattern of opts.filterCollections) {\n if (pattern.endsWith('.*')) {\n prefixes.push(pattern.slice(0, -2))\n } else {\n exact.add(pattern)\n }\n }\n this.matchCollection = (col: string): boolean => {\n if (exact.has(col)) return true\n for (const prefix of prefixes) {\n if (col.startsWith(prefix)) return true\n }\n return false\n }\n }\n this.sub = new Subscription({\n ...opts,\n service: opts.service ?? 'wss://bsky.network',\n method: com.atproto.sync.subscribeRepos.$lxm,\n signal: this.abortController.signal,\n getParams: async () => {\n let cursor: number | undefined\n if (this.opts.runner) {\n cursor = await this.opts.runner.getCursor()\n } else if (this.opts.getCursor) {\n cursor = await this.opts.getCursor()\n }\n return cursor === undefined ? undefined : { cursor }\n },\n validate: (value: unknown) => {\n const result = com.atproto.sync.subscribeRepos.$message.safeParse(value)\n if (result.success) {\n return result.value\n } else {\n this.opts.onError(new FirehoseValidationError(result.reason, value))\n }\n },\n })\n }\n\n async start() {\n try {\n for await (const evt of this.sub) {\n if (this.opts.runner) {\n const parsed = didAndSeqForEvt(evt)\n if (!parsed) {\n continue\n }\n this.opts.runner.trackEvent(parsed.did, parsed.seq, async () => {\n const parsed = await this.parseEvt(evt)\n for (const write of parsed) {\n try {\n await this.opts.handleEvent(write)\n } catch (err) {\n this.opts.onError(new FirehoseHandlerError(err, write))\n }\n }\n })\n } else {\n await this.processEvt(evt)\n }\n }\n } catch (err) {\n if (err && err['name'] === 'AbortError') {\n this.destoryDefer.resolve()\n return\n }\n this.opts.onError(new FirehoseSubscriptionError(err))\n await wait(this.opts.subscriptionReconnectDelay ?? 3000)\n return this.start()\n }\n }\n\n private async parseEvt(\n evt: com.atproto.sync.subscribeRepos.$Message,\n ): Promise<Event[]> {\n try {\n if (com.atproto.sync.subscribeRepos.commit.$isTypeOf(evt)) {\n if (this.opts.excludeCommit) return []\n\n return this.opts.unauthenticatedCommits\n ? await parseCommitUnauthenticated(evt, this.matchCollection)\n : await parseCommitAuthenticated(\n this.opts.idResolver,\n evt,\n this.matchCollection,\n )\n } else if (com.atproto.sync.subscribeRepos.account.$isTypeOf(evt)) {\n if (this.opts.excludeAccount) return []\n\n const parsed = parseAccount(evt)\n return parsed ? [parsed] : []\n } else if (com.atproto.sync.subscribeRepos.identity.$isTypeOf(evt)) {\n if (this.opts.excludeIdentity) return []\n\n const parsed = await parseIdentity(\n this.opts.idResolver,\n evt,\n this.opts.unauthenticatedHandles,\n )\n return parsed ? [parsed] : []\n } else if (com.atproto.sync.subscribeRepos.sync.$isTypeOf(evt)) {\n if (this.opts.excludeSync) return []\n\n const parsed = await parseSync(evt)\n return parsed ? [parsed] : []\n } else {\n return []\n }\n } catch (err) {\n this.opts.onError(new FirehoseParseError(err, evt))\n return []\n }\n }\n\n private async processEvt(evt: com.atproto.sync.subscribeRepos.$Message) {\n const parsed = await this.parseEvt(evt)\n for (const write of parsed) {\n try {\n await this.opts.handleEvent(write)\n } catch (err) {\n this.opts.onError(new FirehoseHandlerError(err, write))\n }\n }\n }\n\n async destroy(): Promise<void> {\n this.abortController.abort()\n await this.destoryDefer.complete\n }\n}\n\nexport const parseCommitAuthenticated = async (\n idResolver: IdResolver,\n evt: com.atproto.sync.subscribeRepos.Commit,\n matchCollection?: ((col: string) => boolean) | null,\n forceKeyRefresh = false,\n): Promise<CommitEvt[]> => {\n const did = evt.repo\n const ops = maybeFilterOps(evt.ops, matchCollection)\n if (ops.length === 0) {\n return []\n }\n const claims = ops.map((op) => {\n const { collection, rkey } = parseDataKey(op.path)\n return {\n collection,\n rkey,\n cid: op.action === 'delete' ? null : op.cid,\n }\n })\n const key = await idResolver.did.resolveAtprotoKey(did, forceKeyRefresh)\n const verifiedCids: Record<string, Cid | null> = {}\n try {\n const results = await verifyProofs(evt.blocks, claims, did, key)\n results.verified.forEach((op) => {\n const path = formatDataKey(op.collection, op.rkey)\n verifiedCids[path] = op.cid\n })\n } catch (err) {\n if (err instanceof RepoVerificationError && !forceKeyRefresh) {\n return parseCommitAuthenticated(idResolver, evt, matchCollection, true)\n }\n throw err\n }\n const verifiedOps: com.atproto.sync.subscribeRepos.RepoOp[] = ops.filter(\n (op) => {\n const verifiedCid = verifiedCids[op.path]\n if (op.action === 'delete') {\n return verifiedCid === null\n } else {\n return (\n op.cid != null && verifiedCid != null && verifiedCid.equals(op.cid)\n )\n }\n },\n )\n return formatCommitOps(evt, verifiedOps, {\n skipCidVerification: true, // already checked via verifyProofs()\n })\n}\n\nexport const parseCommitUnauthenticated = async (\n evt: com.atproto.sync.subscribeRepos.Commit,\n matchCollection?: ((col: string) => boolean) | null,\n): Promise<CommitEvt[]> => {\n const ops = maybeFilterOps(evt.ops, matchCollection)\n return formatCommitOps(evt, ops)\n}\n\nconst maybeFilterOps = (\n ops: com.atproto.sync.subscribeRepos.RepoOp[],\n matchCollection?: ((col: string) => boolean) | null,\n): com.atproto.sync.subscribeRepos.RepoOp[] => {\n if (!matchCollection) return ops\n return ops.filter((op) => {\n const { collection } = parseDataKey(op.path)\n return matchCollection(collection)\n })\n}\n\nconst formatCommitOps = async (\n evt: com.atproto.sync.subscribeRepos.Commit,\n ops: com.atproto.sync.subscribeRepos.RepoOp[],\n options?: { skipCidVerification: boolean },\n) => {\n const car = await readCar(evt.blocks, options)\n\n const evts: CommitEvt[] = []\n\n for (const op of ops) {\n const uri = AtUri.make(evt.repo, op.path)\n\n const meta: CommitMeta = {\n seq: evt.seq,\n time: evt.time,\n commit: evt.commit,\n blocks: car.blocks,\n rev: evt.rev,\n uri,\n did: uri.did,\n collection: uri.collection,\n rkey: uri.rkey,\n }\n\n if (op.action === 'create' || op.action === 'update') {\n if (!op.cid) continue\n const recordBytes = car.blocks.get(op.cid)\n if (!recordBytes) continue\n const record = cborToLexRecord(recordBytes)\n evts.push({\n ...meta,\n event: op.action as 'create' | 'update',\n cid: op.cid,\n record,\n })\n }\n\n if (op.action === 'delete') {\n evts.push({\n ...meta,\n event: 'delete',\n })\n }\n }\n\n return evts\n}\n\nexport const parseSync = async (\n evt: com.atproto.sync.subscribeRepos.Sync,\n): Promise<SyncEvt | null> => {\n const car = await readCarWithRoot(evt.blocks)\n\n return {\n event: 'sync',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n cid: car.root,\n rev: evt.rev,\n blocks: car.blocks,\n }\n}\n\nexport const parseIdentity = async (\n idResolver: IdResolver,\n evt: com.atproto.sync.subscribeRepos.Identity,\n unauthenticated = false,\n): Promise<IdentityEvt | null> => {\n const res = await idResolver.did.resolve(evt.did)\n const handle =\n res && !unauthenticated\n ? await verifyHandle(idResolver, evt.did, res)\n : undefined\n\n return {\n event: 'identity',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n handle,\n didDocument: res ?? undefined,\n }\n}\n\nconst verifyHandle = async (\n idResolver: IdResolver,\n did: string,\n didDoc: DidDocument,\n): Promise<string | undefined> => {\n const { handle } = parseToAtprotoDocument(didDoc)\n if (!handle) {\n return undefined\n }\n const res = await idResolver.handle.resolve(handle)\n return res === did ? handle : undefined\n}\n\nexport const parseAccount = (\n evt: com.atproto.sync.subscribeRepos.Account,\n): AccountEvt | undefined => {\n if (evt.status && !isValidStatus(evt.status)) return\n return {\n event: 'account',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n active: evt.active,\n status: evt.status as AccountStatus | undefined,\n }\n}\n\nconst isValidStatus = (str: string): str is AccountStatus => {\n return ['takendown', 'suspended', 'deleted', 'deactivated'].includes(str)\n}\n\nexport class FirehoseValidationError extends Error {\n constructor(\n err: unknown,\n public value: unknown,\n ) {\n super('error in firehose event lexicon validation', { cause: err })\n }\n}\n\nexport class FirehoseParseError extends Error {\n constructor(\n err: unknown,\n public event: com.atproto.sync.subscribeRepos.$Message,\n ) {\n super('error in parsing and authenticating firehose event', { cause: err })\n }\n}\n\nexport class FirehoseSubscriptionError extends Error {\n constructor(err: unknown) {\n super('error on firehose subscription', { cause: err })\n }\n}\n\nexport class FirehoseHandlerError extends Error {\n constructor(\n err: unknown,\n public event: Event,\n ) {\n super('error in firehose event handler', { cause: err })\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/firehose/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ClientOptions } from 'ws'\nimport { Deferrable, createDeferrable, wait } from '@atproto/common'\nimport {\n DidDocument,\n IdResolver,\n parseToAtprotoDocument,\n} from '@atproto/identity'\nimport { Cid } from '@atproto/lex'\nimport {\n RepoVerificationError,\n cborToLexRecord,\n formatDataKey,\n parseDataKey,\n readCar,\n readCarWithRoot,\n verifyProofs,\n} from '@atproto/repo'\nimport { AtUri } from '@atproto/syntax'\nimport { Subscription } from '@atproto/xrpc-server'\nimport {\n AccountEvt,\n AccountStatus,\n CommitEvt,\n CommitMeta,\n Event,\n IdentityEvt,\n SyncEvt,\n} from '../events.js'\nimport { com } from '../lexicons/index.js'\nimport { EventRunner } from '../runner/index.js'\nimport { didAndSeqForEvt } from '../util.js'\n\nexport type FirehoseOptions = ClientOptions & {\n idResolver: IdResolver\n\n handleEvent: (evt: Event) => void | Promise<void>\n onError: (err: Error) => void\n getCursor?: () => number | undefined | Promise<number | undefined>\n\n runner?: EventRunner // should only set getCursor *or* runner\n\n service?: string\n subscriptionReconnectDelay?: number\n\n unauthenticatedCommits?: boolean\n unauthenticatedHandles?: boolean\n\n filterCollections?: string[]\n excludeIdentity?: boolean\n excludeAccount?: boolean\n excludeCommit?: boolean\n excludeSync?: boolean\n}\n\nexport class Firehose {\n private sub: Subscription<com.atproto.sync.subscribeRepos.$Message>\n private abortController: AbortController\n private destoryDefer: Deferrable\n private matchCollection: ((col: string) => boolean) | null = null\n\n constructor(public opts: FirehoseOptions) {\n this.destoryDefer = createDeferrable()\n this.abortController = new AbortController()\n if (this.opts.getCursor && this.opts.runner) {\n throw new Error('Must set only `getCursor` or `runner`')\n }\n if (opts.filterCollections) {\n const exact = new Set<string>()\n const prefixes: string[] = []\n\n for (const pattern of opts.filterCollections) {\n if (pattern.endsWith('.*')) {\n prefixes.push(pattern.slice(0, -2))\n } else {\n exact.add(pattern)\n }\n }\n this.matchCollection = (col: string): boolean => {\n if (exact.has(col)) return true\n for (const prefix of prefixes) {\n if (col.startsWith(prefix)) return true\n }\n return false\n }\n }\n this.sub = new Subscription({\n ...opts,\n service: opts.service ?? 'wss://bsky.network',\n method: com.atproto.sync.subscribeRepos.$lxm,\n signal: this.abortController.signal,\n getParams: async () => {\n let cursor: number | undefined\n if (this.opts.runner) {\n cursor = await this.opts.runner.getCursor()\n } else if (this.opts.getCursor) {\n cursor = await this.opts.getCursor()\n }\n return cursor === undefined ? undefined : { cursor }\n },\n validate: (value: unknown) => {\n const result = com.atproto.sync.subscribeRepos.$message.safeParse(value)\n if (result.success) {\n return result.value\n } else {\n this.opts.onError(new FirehoseValidationError(result.reason, value))\n }\n },\n })\n }\n\n async start(): Promise<void> {\n try {\n for await (const evt of this.sub) {\n if (this.opts.runner) {\n const parsed = didAndSeqForEvt(evt)\n if (!parsed) {\n continue\n }\n this.opts.runner.trackEvent(parsed.did, parsed.seq, async () => {\n const parsed = await this.parseEvt(evt)\n for (const write of parsed) {\n try {\n await this.opts.handleEvent(write)\n } catch (err) {\n this.opts.onError(new FirehoseHandlerError(err, write))\n }\n }\n })\n } else {\n await this.processEvt(evt)\n }\n }\n } catch (err) {\n if ((err as any)?.name === 'AbortError') {\n this.destoryDefer.resolve()\n return\n }\n this.opts.onError(new FirehoseSubscriptionError(err))\n await wait(this.opts.subscriptionReconnectDelay ?? 3000)\n return this.start()\n }\n }\n\n private async parseEvt(\n evt: com.atproto.sync.subscribeRepos.$Message,\n ): Promise<Event[]> {\n try {\n if (com.atproto.sync.subscribeRepos.commit.$isTypeOf(evt)) {\n if (this.opts.excludeCommit) return []\n\n return this.opts.unauthenticatedCommits\n ? await parseCommitUnauthenticated(evt, this.matchCollection)\n : await parseCommitAuthenticated(\n this.opts.idResolver,\n evt,\n this.matchCollection,\n )\n } else if (com.atproto.sync.subscribeRepos.account.$isTypeOf(evt)) {\n if (this.opts.excludeAccount) return []\n\n const parsed = parseAccount(evt)\n return parsed ? [parsed] : []\n } else if (com.atproto.sync.subscribeRepos.identity.$isTypeOf(evt)) {\n if (this.opts.excludeIdentity) return []\n\n const parsed = await parseIdentity(\n this.opts.idResolver,\n evt,\n this.opts.unauthenticatedHandles,\n )\n return parsed ? [parsed] : []\n } else if (com.atproto.sync.subscribeRepos.sync.$isTypeOf(evt)) {\n if (this.opts.excludeSync) return []\n\n const parsed = await parseSync(evt)\n return parsed ? [parsed] : []\n } else {\n return []\n }\n } catch (err) {\n this.opts.onError(new FirehoseParseError(err, evt))\n return []\n }\n }\n\n private async processEvt(evt: com.atproto.sync.subscribeRepos.$Message) {\n const parsed = await this.parseEvt(evt)\n for (const write of parsed) {\n try {\n await this.opts.handleEvent(write)\n } catch (err) {\n this.opts.onError(new FirehoseHandlerError(err, write))\n }\n }\n }\n\n async destroy(): Promise<void> {\n this.abortController.abort()\n await this.destoryDefer.complete\n }\n}\n\nexport const parseCommitAuthenticated = async (\n idResolver: IdResolver,\n evt: com.atproto.sync.subscribeRepos.Commit,\n matchCollection?: ((col: string) => boolean) | null,\n forceKeyRefresh = false,\n): Promise<CommitEvt[]> => {\n const did = evt.repo\n const ops = maybeFilterOps(evt.ops, matchCollection)\n if (ops.length === 0) {\n return []\n }\n const claims = ops.map((op) => {\n const { collection, rkey } = parseDataKey(op.path)\n return {\n collection,\n rkey,\n cid: op.action === 'delete' ? null : op.cid,\n }\n })\n const key = await idResolver.did.resolveAtprotoKey(did, forceKeyRefresh)\n const verifiedCids: Record<string, Cid | null> = {}\n try {\n const results = await verifyProofs(evt.blocks, claims, did, key)\n results.verified.forEach((op) => {\n const path = formatDataKey(op.collection, op.rkey)\n verifiedCids[path] = op.cid\n })\n } catch (err) {\n if (err instanceof RepoVerificationError && !forceKeyRefresh) {\n return parseCommitAuthenticated(idResolver, evt, matchCollection, true)\n }\n throw err\n }\n const verifiedOps: com.atproto.sync.subscribeRepos.RepoOp[] = ops.filter(\n (op) => {\n const verifiedCid = verifiedCids[op.path]\n if (op.action === 'delete') {\n return verifiedCid === null\n } else {\n return (\n op.cid != null && verifiedCid != null && verifiedCid.equals(op.cid)\n )\n }\n },\n )\n return formatCommitOps(evt, verifiedOps, {\n skipCidVerification: true, // already checked via verifyProofs()\n })\n}\n\nexport const parseCommitUnauthenticated = async (\n evt: com.atproto.sync.subscribeRepos.Commit,\n matchCollection?: ((col: string) => boolean) | null,\n): Promise<CommitEvt[]> => {\n const ops = maybeFilterOps(evt.ops, matchCollection)\n return formatCommitOps(evt, ops)\n}\n\nconst maybeFilterOps = (\n ops: com.atproto.sync.subscribeRepos.RepoOp[],\n matchCollection?: ((col: string) => boolean) | null,\n): com.atproto.sync.subscribeRepos.RepoOp[] => {\n if (!matchCollection) return ops\n return ops.filter((op) => {\n const { collection } = parseDataKey(op.path)\n return matchCollection(collection)\n })\n}\n\nconst formatCommitOps = async (\n evt: com.atproto.sync.subscribeRepos.Commit,\n ops: com.atproto.sync.subscribeRepos.RepoOp[],\n options?: { skipCidVerification: boolean },\n) => {\n const car = await readCar(evt.blocks, options)\n\n const evts: CommitEvt[] = []\n\n for (const op of ops) {\n const uri = AtUri.make(evt.repo, op.path)\n\n const meta: CommitMeta = {\n seq: evt.seq,\n time: evt.time,\n commit: evt.commit,\n blocks: car.blocks,\n rev: evt.rev,\n uri,\n did: uri.did,\n collection: uri.collection,\n rkey: uri.rkey,\n }\n\n if (op.action === 'create' || op.action === 'update') {\n if (!op.cid) continue\n const recordBytes = car.blocks.get(op.cid)\n if (!recordBytes) continue\n const record = cborToLexRecord(recordBytes)\n evts.push({\n ...meta,\n event: op.action as 'create' | 'update',\n cid: op.cid,\n record,\n })\n }\n\n if (op.action === 'delete') {\n evts.push({\n ...meta,\n event: 'delete',\n })\n }\n }\n\n return evts\n}\n\nexport const parseSync = async (\n evt: com.atproto.sync.subscribeRepos.Sync,\n): Promise<SyncEvt | null> => {\n const car = await readCarWithRoot(evt.blocks)\n\n return {\n event: 'sync',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n cid: car.root,\n rev: evt.rev,\n blocks: car.blocks,\n }\n}\n\nexport const parseIdentity = async (\n idResolver: IdResolver,\n evt: com.atproto.sync.subscribeRepos.Identity,\n unauthenticated = false,\n): Promise<IdentityEvt | null> => {\n const res = await idResolver.did.resolve(evt.did)\n const handle =\n res && !unauthenticated\n ? await verifyHandle(idResolver, evt.did, res)\n : undefined\n\n return {\n event: 'identity',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n handle,\n didDocument: res ?? undefined,\n }\n}\n\nconst verifyHandle = async (\n idResolver: IdResolver,\n did: string,\n didDoc: DidDocument,\n): Promise<string | undefined> => {\n const { handle } = parseToAtprotoDocument(didDoc)\n if (!handle) {\n return undefined\n }\n const res = await idResolver.handle.resolve(handle)\n return res === did ? handle : undefined\n}\n\nexport const parseAccount = (\n evt: com.atproto.sync.subscribeRepos.Account,\n): AccountEvt | undefined => {\n if (evt.status && !isValidStatus(evt.status)) return\n return {\n event: 'account',\n seq: evt.seq,\n time: evt.time,\n did: evt.did,\n active: evt.active,\n status: evt.status as AccountStatus | undefined,\n }\n}\n\nconst isValidStatus = (str: string): str is AccountStatus => {\n return ['takendown', 'suspended', 'deleted', 'deactivated'].includes(str)\n}\n\nexport class FirehoseValidationError extends Error {\n constructor(\n err: unknown,\n public value: unknown,\n ) {\n super('error in firehose event lexicon validation', { cause: err })\n }\n}\n\nexport class FirehoseParseError extends Error {\n constructor(\n err: unknown,\n public event: com.atproto.sync.subscribeRepos.$Message,\n ) {\n super('error in parsing and authenticating firehose event', { cause: err })\n }\n}\n\nexport class FirehoseSubscriptionError extends Error {\n constructor(err: unknown) {\n super('error on firehose subscription', { cause: err })\n }\n}\n\nexport class FirehoseHandlerError extends Error {\n constructor(\n err: unknown,\n public event: Event,\n ) {\n super('error in firehose event handler', { cause: err })\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/sync",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "license": "MIT",
5
5
  "description": "atproto sync library",
6
6
  "keywords": [
@@ -15,33 +15,38 @@
15
15
  "url": "https://github.com/bluesky-social/atproto",
16
16
  "directory": "packages/sync"
17
17
  },
18
+ "files": [
19
+ "./dist",
20
+ "./README.md",
21
+ "./CHANGELOG.md"
22
+ ],
23
+ "type": "module",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "default": "./dist/index.js"
28
+ }
29
+ },
18
30
  "engines": {
19
31
  "node": ">=22"
20
32
  },
21
33
  "dependencies": {
22
34
  "p-queue": "^8.0.0",
23
35
  "ws": "^8.12.0",
24
- "@atproto/common": "^0.6.4",
25
- "@atproto/lex": "^0.1.5",
26
- "@atproto/syntax": "^0.6.3",
27
- "@atproto/repo": "^0.10.2",
28
- "@atproto/identity": "^0.5.2",
29
- "@atproto/xrpc-server": "^0.11.4"
36
+ "@atproto/common": "^0.6.5",
37
+ "@atproto/identity": "^0.5.3",
38
+ "@atproto/lex": "^0.1.7",
39
+ "@atproto/syntax": "^0.6.4",
40
+ "@atproto/xrpc-server": "^0.11.6",
41
+ "@atproto/repo": "^0.10.3"
30
42
  },
31
43
  "devDependencies": {
32
44
  "@types/ws": "^8.5.4",
33
45
  "jest": "^30.0.0"
34
46
  },
35
- "type": "module",
36
- "exports": {
37
- ".": {
38
- "types": "./dist/index.d.ts",
39
- "default": "./dist/index.js"
40
- }
41
- },
42
47
  "scripts": {
43
- "codegen": "lex build --clear --indexFile --lexicons ../../lexicons --include com.atproto.sync.subscribeRepos",
44
- "prebuild": "pnpm run codegen",
48
+ "codegen:lex": "lex build --clear --indexFile --lexicons ../../lexicons --include com.atproto.sync.subscribeRepos",
49
+ "prebuild": "pnpm run '/^(codegen:.+)$/'",
45
50
  "build": "tsgo --build tsconfig.build.json",
46
51
  "test": "NODE_OPTIONS=--experimental-vm-modules ../dev-infra/with-test-redis-and-db.sh jest"
47
52
  }
package/jest.config.cjs DELETED
@@ -1,22 +0,0 @@
1
- /** @type {import('jest').Config} */
2
- module.exports = {
3
- displayName: 'Sync',
4
- transform: {
5
- '^.+\\.(t|j)s$': [
6
- '@swc/jest',
7
- {
8
- jsc: {
9
- parser: { syntax: 'typescript', importAttributes: true },
10
- experimental: { keepImportAttributes: true },
11
- transform: {},
12
- },
13
- module: { type: 'es6' },
14
- },
15
- ],
16
- },
17
- extensionsToTreatAsEsm: ['.ts'],
18
- transformIgnorePatterns: [],
19
- testTimeout: 60000,
20
- setupFiles: ['<rootDir>/../../test.setup.ts'],
21
- moduleNameMapper: { '^(\\.\\.?\\/.+)\\.js$': ['$1.ts', '$1.js'] },
22
- }
package/src/events.ts DELETED
@@ -1,70 +0,0 @@
1
- import { DidDocument } from '@atproto/identity'
2
- import { Cid, LexMap } from '@atproto/lex'
3
- import { BlockMap } from '@atproto/repo'
4
- import { AtUri, DidString } from '@atproto/syntax'
5
-
6
- export type Event = CommitEvt | SyncEvt | IdentityEvt | AccountEvt
7
-
8
- export type CommitMeta = {
9
- seq: number
10
- time: string
11
- commit: Cid
12
- blocks: BlockMap
13
- rev: string
14
- uri: AtUri
15
- did: DidString
16
- collection: string
17
- rkey: string
18
- }
19
-
20
- export type CommitEvt = Create | Update | Delete
21
-
22
- export type Create = CommitMeta & {
23
- event: 'create'
24
- record: LexMap
25
- cid: Cid
26
- }
27
-
28
- export type Update = CommitMeta & {
29
- event: 'update'
30
- record: LexMap
31
- cid: Cid
32
- }
33
-
34
- export type Delete = CommitMeta & {
35
- event: 'delete'
36
- }
37
-
38
- export type SyncEvt = {
39
- seq: number
40
- time: string
41
- event: 'sync'
42
- did: DidString
43
- cid: Cid
44
- rev: string
45
- blocks: BlockMap
46
- }
47
-
48
- export type IdentityEvt = {
49
- seq: number
50
- time: string
51
- event: 'identity'
52
- did: DidString
53
- handle?: string
54
- didDocument?: DidDocument
55
- }
56
-
57
- export type AccountEvt = {
58
- seq: number
59
- time: string
60
- event: 'account'
61
- did: DidString
62
- active: boolean
63
- status?: AccountStatus
64
- }
65
-
66
- export type AccountStatus =
67
- | 'takendown'
68
- | 'suspended'
69
- | 'deleted'
70
- | 'deactivated'
@@ -1,419 +0,0 @@
1
- import type { ClientOptions } from 'ws'
2
- import { Deferrable, createDeferrable, wait } from '@atproto/common'
3
- import {
4
- DidDocument,
5
- IdResolver,
6
- parseToAtprotoDocument,
7
- } from '@atproto/identity'
8
- import { Cid } from '@atproto/lex'
9
- import {
10
- RepoVerificationError,
11
- cborToLexRecord,
12
- formatDataKey,
13
- parseDataKey,
14
- readCar,
15
- readCarWithRoot,
16
- verifyProofs,
17
- } from '@atproto/repo'
18
- import { AtUri } from '@atproto/syntax'
19
- import { Subscription } from '@atproto/xrpc-server'
20
- import {
21
- AccountEvt,
22
- AccountStatus,
23
- CommitEvt,
24
- CommitMeta,
25
- Event,
26
- IdentityEvt,
27
- SyncEvt,
28
- } from '../events.js'
29
- import { com } from '../lexicons/index.js'
30
- import { EventRunner } from '../runner/index.js'
31
- import { didAndSeqForEvt } from '../util.js'
32
-
33
- export type FirehoseOptions = ClientOptions & {
34
- idResolver: IdResolver
35
-
36
- handleEvent: (evt: Event) => void | Promise<void>
37
- onError: (err: Error) => void
38
- getCursor?: () => number | undefined | Promise<number | undefined>
39
-
40
- runner?: EventRunner // should only set getCursor *or* runner
41
-
42
- service?: string
43
- subscriptionReconnectDelay?: number
44
-
45
- unauthenticatedCommits?: boolean
46
- unauthenticatedHandles?: boolean
47
-
48
- filterCollections?: string[]
49
- excludeIdentity?: boolean
50
- excludeAccount?: boolean
51
- excludeCommit?: boolean
52
- excludeSync?: boolean
53
- }
54
-
55
- export class Firehose {
56
- private sub: Subscription<com.atproto.sync.subscribeRepos.$Message>
57
- private abortController: AbortController
58
- private destoryDefer: Deferrable
59
- private matchCollection: ((col: string) => boolean) | null = null
60
-
61
- constructor(public opts: FirehoseOptions) {
62
- this.destoryDefer = createDeferrable()
63
- this.abortController = new AbortController()
64
- if (this.opts.getCursor && this.opts.runner) {
65
- throw new Error('Must set only `getCursor` or `runner`')
66
- }
67
- if (opts.filterCollections) {
68
- const exact = new Set<string>()
69
- const prefixes: string[] = []
70
-
71
- for (const pattern of opts.filterCollections) {
72
- if (pattern.endsWith('.*')) {
73
- prefixes.push(pattern.slice(0, -2))
74
- } else {
75
- exact.add(pattern)
76
- }
77
- }
78
- this.matchCollection = (col: string): boolean => {
79
- if (exact.has(col)) return true
80
- for (const prefix of prefixes) {
81
- if (col.startsWith(prefix)) return true
82
- }
83
- return false
84
- }
85
- }
86
- this.sub = new Subscription({
87
- ...opts,
88
- service: opts.service ?? 'wss://bsky.network',
89
- method: com.atproto.sync.subscribeRepos.$lxm,
90
- signal: this.abortController.signal,
91
- getParams: async () => {
92
- let cursor: number | undefined
93
- if (this.opts.runner) {
94
- cursor = await this.opts.runner.getCursor()
95
- } else if (this.opts.getCursor) {
96
- cursor = await this.opts.getCursor()
97
- }
98
- return cursor === undefined ? undefined : { cursor }
99
- },
100
- validate: (value: unknown) => {
101
- const result = com.atproto.sync.subscribeRepos.$message.safeParse(value)
102
- if (result.success) {
103
- return result.value
104
- } else {
105
- this.opts.onError(new FirehoseValidationError(result.reason, value))
106
- }
107
- },
108
- })
109
- }
110
-
111
- async start() {
112
- try {
113
- for await (const evt of this.sub) {
114
- if (this.opts.runner) {
115
- const parsed = didAndSeqForEvt(evt)
116
- if (!parsed) {
117
- continue
118
- }
119
- this.opts.runner.trackEvent(parsed.did, parsed.seq, async () => {
120
- const parsed = await this.parseEvt(evt)
121
- for (const write of parsed) {
122
- try {
123
- await this.opts.handleEvent(write)
124
- } catch (err) {
125
- this.opts.onError(new FirehoseHandlerError(err, write))
126
- }
127
- }
128
- })
129
- } else {
130
- await this.processEvt(evt)
131
- }
132
- }
133
- } catch (err) {
134
- if (err && err['name'] === 'AbortError') {
135
- this.destoryDefer.resolve()
136
- return
137
- }
138
- this.opts.onError(new FirehoseSubscriptionError(err))
139
- await wait(this.opts.subscriptionReconnectDelay ?? 3000)
140
- return this.start()
141
- }
142
- }
143
-
144
- private async parseEvt(
145
- evt: com.atproto.sync.subscribeRepos.$Message,
146
- ): Promise<Event[]> {
147
- try {
148
- if (com.atproto.sync.subscribeRepos.commit.$isTypeOf(evt)) {
149
- if (this.opts.excludeCommit) return []
150
-
151
- return this.opts.unauthenticatedCommits
152
- ? await parseCommitUnauthenticated(evt, this.matchCollection)
153
- : await parseCommitAuthenticated(
154
- this.opts.idResolver,
155
- evt,
156
- this.matchCollection,
157
- )
158
- } else if (com.atproto.sync.subscribeRepos.account.$isTypeOf(evt)) {
159
- if (this.opts.excludeAccount) return []
160
-
161
- const parsed = parseAccount(evt)
162
- return parsed ? [parsed] : []
163
- } else if (com.atproto.sync.subscribeRepos.identity.$isTypeOf(evt)) {
164
- if (this.opts.excludeIdentity) return []
165
-
166
- const parsed = await parseIdentity(
167
- this.opts.idResolver,
168
- evt,
169
- this.opts.unauthenticatedHandles,
170
- )
171
- return parsed ? [parsed] : []
172
- } else if (com.atproto.sync.subscribeRepos.sync.$isTypeOf(evt)) {
173
- if (this.opts.excludeSync) return []
174
-
175
- const parsed = await parseSync(evt)
176
- return parsed ? [parsed] : []
177
- } else {
178
- return []
179
- }
180
- } catch (err) {
181
- this.opts.onError(new FirehoseParseError(err, evt))
182
- return []
183
- }
184
- }
185
-
186
- private async processEvt(evt: com.atproto.sync.subscribeRepos.$Message) {
187
- const parsed = await this.parseEvt(evt)
188
- for (const write of parsed) {
189
- try {
190
- await this.opts.handleEvent(write)
191
- } catch (err) {
192
- this.opts.onError(new FirehoseHandlerError(err, write))
193
- }
194
- }
195
- }
196
-
197
- async destroy(): Promise<void> {
198
- this.abortController.abort()
199
- await this.destoryDefer.complete
200
- }
201
- }
202
-
203
- export const parseCommitAuthenticated = async (
204
- idResolver: IdResolver,
205
- evt: com.atproto.sync.subscribeRepos.Commit,
206
- matchCollection?: ((col: string) => boolean) | null,
207
- forceKeyRefresh = false,
208
- ): Promise<CommitEvt[]> => {
209
- const did = evt.repo
210
- const ops = maybeFilterOps(evt.ops, matchCollection)
211
- if (ops.length === 0) {
212
- return []
213
- }
214
- const claims = ops.map((op) => {
215
- const { collection, rkey } = parseDataKey(op.path)
216
- return {
217
- collection,
218
- rkey,
219
- cid: op.action === 'delete' ? null : op.cid,
220
- }
221
- })
222
- const key = await idResolver.did.resolveAtprotoKey(did, forceKeyRefresh)
223
- const verifiedCids: Record<string, Cid | null> = {}
224
- try {
225
- const results = await verifyProofs(evt.blocks, claims, did, key)
226
- results.verified.forEach((op) => {
227
- const path = formatDataKey(op.collection, op.rkey)
228
- verifiedCids[path] = op.cid
229
- })
230
- } catch (err) {
231
- if (err instanceof RepoVerificationError && !forceKeyRefresh) {
232
- return parseCommitAuthenticated(idResolver, evt, matchCollection, true)
233
- }
234
- throw err
235
- }
236
- const verifiedOps: com.atproto.sync.subscribeRepos.RepoOp[] = ops.filter(
237
- (op) => {
238
- const verifiedCid = verifiedCids[op.path]
239
- if (op.action === 'delete') {
240
- return verifiedCid === null
241
- } else {
242
- return (
243
- op.cid != null && verifiedCid != null && verifiedCid.equals(op.cid)
244
- )
245
- }
246
- },
247
- )
248
- return formatCommitOps(evt, verifiedOps, {
249
- skipCidVerification: true, // already checked via verifyProofs()
250
- })
251
- }
252
-
253
- export const parseCommitUnauthenticated = async (
254
- evt: com.atproto.sync.subscribeRepos.Commit,
255
- matchCollection?: ((col: string) => boolean) | null,
256
- ): Promise<CommitEvt[]> => {
257
- const ops = maybeFilterOps(evt.ops, matchCollection)
258
- return formatCommitOps(evt, ops)
259
- }
260
-
261
- const maybeFilterOps = (
262
- ops: com.atproto.sync.subscribeRepos.RepoOp[],
263
- matchCollection?: ((col: string) => boolean) | null,
264
- ): com.atproto.sync.subscribeRepos.RepoOp[] => {
265
- if (!matchCollection) return ops
266
- return ops.filter((op) => {
267
- const { collection } = parseDataKey(op.path)
268
- return matchCollection(collection)
269
- })
270
- }
271
-
272
- const formatCommitOps = async (
273
- evt: com.atproto.sync.subscribeRepos.Commit,
274
- ops: com.atproto.sync.subscribeRepos.RepoOp[],
275
- options?: { skipCidVerification: boolean },
276
- ) => {
277
- const car = await readCar(evt.blocks, options)
278
-
279
- const evts: CommitEvt[] = []
280
-
281
- for (const op of ops) {
282
- const uri = AtUri.make(evt.repo, op.path)
283
-
284
- const meta: CommitMeta = {
285
- seq: evt.seq,
286
- time: evt.time,
287
- commit: evt.commit,
288
- blocks: car.blocks,
289
- rev: evt.rev,
290
- uri,
291
- did: uri.did,
292
- collection: uri.collection,
293
- rkey: uri.rkey,
294
- }
295
-
296
- if (op.action === 'create' || op.action === 'update') {
297
- if (!op.cid) continue
298
- const recordBytes = car.blocks.get(op.cid)
299
- if (!recordBytes) continue
300
- const record = cborToLexRecord(recordBytes)
301
- evts.push({
302
- ...meta,
303
- event: op.action as 'create' | 'update',
304
- cid: op.cid,
305
- record,
306
- })
307
- }
308
-
309
- if (op.action === 'delete') {
310
- evts.push({
311
- ...meta,
312
- event: 'delete',
313
- })
314
- }
315
- }
316
-
317
- return evts
318
- }
319
-
320
- export const parseSync = async (
321
- evt: com.atproto.sync.subscribeRepos.Sync,
322
- ): Promise<SyncEvt | null> => {
323
- const car = await readCarWithRoot(evt.blocks)
324
-
325
- return {
326
- event: 'sync',
327
- seq: evt.seq,
328
- time: evt.time,
329
- did: evt.did,
330
- cid: car.root,
331
- rev: evt.rev,
332
- blocks: car.blocks,
333
- }
334
- }
335
-
336
- export const parseIdentity = async (
337
- idResolver: IdResolver,
338
- evt: com.atproto.sync.subscribeRepos.Identity,
339
- unauthenticated = false,
340
- ): Promise<IdentityEvt | null> => {
341
- const res = await idResolver.did.resolve(evt.did)
342
- const handle =
343
- res && !unauthenticated
344
- ? await verifyHandle(idResolver, evt.did, res)
345
- : undefined
346
-
347
- return {
348
- event: 'identity',
349
- seq: evt.seq,
350
- time: evt.time,
351
- did: evt.did,
352
- handle,
353
- didDocument: res ?? undefined,
354
- }
355
- }
356
-
357
- const verifyHandle = async (
358
- idResolver: IdResolver,
359
- did: string,
360
- didDoc: DidDocument,
361
- ): Promise<string | undefined> => {
362
- const { handle } = parseToAtprotoDocument(didDoc)
363
- if (!handle) {
364
- return undefined
365
- }
366
- const res = await idResolver.handle.resolve(handle)
367
- return res === did ? handle : undefined
368
- }
369
-
370
- export const parseAccount = (
371
- evt: com.atproto.sync.subscribeRepos.Account,
372
- ): AccountEvt | undefined => {
373
- if (evt.status && !isValidStatus(evt.status)) return
374
- return {
375
- event: 'account',
376
- seq: evt.seq,
377
- time: evt.time,
378
- did: evt.did,
379
- active: evt.active,
380
- status: evt.status as AccountStatus | undefined,
381
- }
382
- }
383
-
384
- const isValidStatus = (str: string): str is AccountStatus => {
385
- return ['takendown', 'suspended', 'deleted', 'deactivated'].includes(str)
386
- }
387
-
388
- export class FirehoseValidationError extends Error {
389
- constructor(
390
- err: unknown,
391
- public value: unknown,
392
- ) {
393
- super('error in firehose event lexicon validation', { cause: err })
394
- }
395
- }
396
-
397
- export class FirehoseParseError extends Error {
398
- constructor(
399
- err: unknown,
400
- public event: com.atproto.sync.subscribeRepos.$Message,
401
- ) {
402
- super('error in parsing and authenticating firehose event', { cause: err })
403
- }
404
- }
405
-
406
- export class FirehoseSubscriptionError extends Error {
407
- constructor(err: unknown) {
408
- super('error on firehose subscription', { cause: err })
409
- }
410
- }
411
-
412
- export class FirehoseHandlerError extends Error {
413
- constructor(
414
- err: unknown,
415
- public event: Event,
416
- ) {
417
- super('error in firehose event handler', { cause: err })
418
- }
419
- }
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './runner/index.js'
2
- export * from './firehose/index.js'
3
- export * from './events.js'
@@ -1,44 +0,0 @@
1
- /**
2
- * Add items to a list, and mark those items as
3
- * completed. Upon item completion, get list of consecutive
4
- * items completed at the head of the list. Example:
5
- *
6
- * const consecutive = new ConsecutiveList<number>()
7
- * const item1 = consecutive.push(1)
8
- * const item2 = consecutive.push(2)
9
- * const item3 = consecutive.push(3)
10
- * item2.complete() // []
11
- * item1.complete() // [1, 2]
12
- * item3.complete() // [3]
13
- *
14
- */
15
- export class ConsecutiveList<T> {
16
- list: ConsecutiveItem<T>[] = []
17
-
18
- push(value: T) {
19
- const item = new ConsecutiveItem<T>(this, value)
20
- this.list.push(item)
21
- return item
22
- }
23
-
24
- complete(): T[] {
25
- let i = 0
26
- while (this.list[i]?.isComplete) {
27
- i += 1
28
- }
29
- return this.list.splice(0, i).map((item) => item.value)
30
- }
31
- }
32
-
33
- export class ConsecutiveItem<T> {
34
- isComplete = false
35
- constructor(
36
- private consecutive: ConsecutiveList<T>,
37
- public value: T,
38
- ) {}
39
-
40
- complete() {
41
- this.isComplete = true
42
- return this.consecutive.complete()
43
- }
44
- }
@@ -1,3 +0,0 @@
1
- export * from './consecutive-list.js'
2
- export * from './memory-runner.js'
3
- export * from './types.js'
@@ -1,79 +0,0 @@
1
- import PQueue from 'p-queue'
2
- import { ConsecutiveList } from './consecutive-list.js'
3
- import { EventRunner } from './types.js'
4
-
5
- export type MemoryRunnerOptions = {
6
- setCursor?: (cursor: number) => Promise<void>
7
- concurrency?: number
8
- startCursor?: number
9
- }
10
-
11
- type Queue = InstanceType<typeof PQueue>
12
-
13
- // A queue with arbitrarily many partitions, each processing work sequentially.
14
- // Partitions are created lazily and taken out of memory when they go idle.
15
- export class MemoryRunner implements EventRunner {
16
- private destroyed = false
17
- private readonly consecutive = new ConsecutiveList<number>()
18
- private readonly mainQueue: Queue
19
- private readonly partitions: Map<string, Queue> = new Map()
20
- private cursor: number | undefined
21
-
22
- constructor(public opts: MemoryRunnerOptions = {}) {
23
- this.mainQueue = new PQueue({ concurrency: opts.concurrency ?? Infinity })
24
- this.cursor = opts.startCursor
25
- }
26
-
27
- getCursor() {
28
- return this.cursor
29
- }
30
-
31
- /** @deprecated internal use only */
32
- get partitionCount() {
33
- return this.partitions.size
34
- }
35
-
36
- async addTask(partitionId: string, task: () => Promise<void>) {
37
- if (this.destroyed) return
38
- return this.mainQueue.add(() => {
39
- return this.getPartition(partitionId).add(task)
40
- })
41
- }
42
-
43
- private getPartition(partitionId: string) {
44
- let partition = this.partitions.get(partitionId)
45
- if (!partition) {
46
- partition = new PQueue({ concurrency: 1 })
47
- partition.once('idle', () => this.partitions.delete(partitionId))
48
- this.partitions.set(partitionId, partition)
49
- }
50
- return partition
51
- }
52
-
53
- async trackEvent(did: string, seq: number, handler: () => Promise<void>) {
54
- if (this.destroyed) return
55
- const item = this.consecutive.push(seq)
56
- await this.addTask(did, async () => {
57
- await handler()
58
- const latest = item.complete().at(-1)
59
- if (latest !== undefined) {
60
- this.cursor = latest
61
- if (this.opts.setCursor) {
62
- await this.opts.setCursor(this.cursor)
63
- }
64
- }
65
- })
66
- }
67
-
68
- async processAll() {
69
- const queue = this.mainQueue
70
- while (queue.size || queue.pending) await queue.onIdle()
71
- }
72
-
73
- async destroy() {
74
- this.destroyed = true
75
- this.mainQueue.clear()
76
- this.partitions.forEach((p) => p.clear())
77
- await this.processAll()
78
- }
79
- }
@@ -1,8 +0,0 @@
1
- export interface EventRunner {
2
- getCursor(): number | undefined | Promise<number | undefined>
3
- trackEvent(
4
- did: string,
5
- seq: number,
6
- handler: () => Promise<void>,
7
- ): Promise<void>
8
- }
package/src/util.ts DELETED
@@ -1,16 +0,0 @@
1
- import { com } from './lexicons/index.js'
2
-
3
- export const didAndSeqForEvt = (
4
- evt: com.atproto.sync.subscribeRepos.$Message,
5
- ): { did: string; seq: number } | undefined => {
6
- if (com.atproto.sync.subscribeRepos.commit.$isTypeOf(evt)) {
7
- return { seq: evt.seq, did: evt.repo }
8
- } else if (
9
- com.atproto.sync.subscribeRepos.account.$isTypeOf(evt) ||
10
- com.atproto.sync.subscribeRepos.identity.$isTypeOf(evt) ||
11
- com.atproto.sync.subscribeRepos.sync.$isTypeOf(evt)
12
- ) {
13
- return { seq: evt.seq, did: evt.did }
14
- }
15
- return undefined
16
- }
@@ -1,197 +0,0 @@
1
- import { createDeferrable, wait } from '@atproto/common'
2
- import {
3
- SeedClient,
4
- TestNetworkNoAppView,
5
- mockResolvers,
6
- } from '@atproto/dev-env'
7
- import { IdResolver } from '@atproto/identity'
8
- import { DidString } from '@atproto/syntax'
9
- import {
10
- Create,
11
- Event,
12
- Firehose,
13
- FirehoseOptions,
14
- MemoryRunner,
15
- } from '../src/index.js'
16
-
17
- describe('firehose', () => {
18
- let network: TestNetworkNoAppView
19
- let sc: SeedClient
20
- let idResolver: IdResolver
21
-
22
- beforeAll(async () => {
23
- network = await TestNetworkNoAppView.create({
24
- dbPostgresSchema: 'sync_firehose',
25
- })
26
- idResolver = new IdResolver({ plcUrl: network.plc.url })
27
- mockResolvers(idResolver, network.pds)
28
- sc = network.getSeedClient()
29
- })
30
-
31
- afterAll(async () => {
32
- await network?.close()
33
- })
34
-
35
- const createAndReadFirehose = async (
36
- count: number,
37
- opts: Partial<FirehoseOptions> = {},
38
- addRandomWait = false,
39
- ): Promise<Event[]> => {
40
- const defer = createDeferrable()
41
- const evts: Event[] = []
42
- const firehose = new Firehose({
43
- idResolver,
44
- service: network.pds.url.replace('http', 'ws'),
45
- handleEvent: async (evt) => {
46
- if (addRandomWait) {
47
- const time = Math.floor(Math.random()) * 20
48
- await wait(time)
49
- }
50
- evts.push(evt)
51
- if (evts.length >= count) {
52
- defer.resolve()
53
- }
54
- },
55
- onError: (err) => {
56
- defer.reject(err)
57
- },
58
- ...opts,
59
- })
60
- try {
61
- firehose.start()
62
- await defer.complete
63
- return evts
64
- } finally {
65
- await firehose.destroy()
66
- }
67
- }
68
-
69
- let alice: DidString
70
-
71
- it('reads events from firehose', async () => {
72
- const evtsPromise = createAndReadFirehose(6)
73
- await wait(10) // give the websocket just a second to spin up
74
- const aliceRes = await sc.createAccount('alice', {
75
- handle: 'alice.test',
76
- email: 'alice@test.com',
77
- password: 'alice-pass',
78
- })
79
- alice = aliceRes.did
80
- await sc.post(alice, 'one')
81
- await sc.post(alice, 'two')
82
- await sc.post(alice, 'three')
83
-
84
- const evts = await evtsPromise
85
- expect(evts.length).toBe(6)
86
- expect(evts.at(0)).toMatchObject({
87
- event: 'identity',
88
- did: alice,
89
- handle: aliceRes.handle,
90
- didDocument: {
91
- id: alice,
92
- },
93
- })
94
- expect(evts.at(1)).toMatchObject({
95
- event: 'account',
96
- did: alice,
97
- active: true,
98
- status: undefined,
99
- })
100
- expect(evts.at(2)).toMatchObject({
101
- event: 'sync',
102
- did: alice,
103
- })
104
- expect(evts.at(3)).toMatchObject({
105
- event: 'create',
106
- did: alice,
107
- collection: 'app.bsky.feed.post',
108
- record: {
109
- text: 'one',
110
- },
111
- })
112
- expect(evts.at(4)).toMatchObject({
113
- event: 'create',
114
- did: alice,
115
- collection: 'app.bsky.feed.post',
116
- record: {
117
- text: 'two',
118
- },
119
- })
120
- expect(evts.at(5)).toMatchObject({
121
- event: 'create',
122
- did: alice,
123
- collection: 'app.bsky.feed.post',
124
- record: {
125
- text: 'three',
126
- },
127
- })
128
- })
129
-
130
- it('does not naively pass through invalid handle evts', async () => {
131
- const evtsPromise = createAndReadFirehose(1)
132
- await wait(10) // give the websocket just a second to spin up
133
- await network.pds.ctx.sequencer.sequenceIdentity(alice, 'bad-handle.test')
134
- const evts = await evtsPromise
135
- expect(evts.at(0)).toMatchObject({ handle: 'alice.test' })
136
- })
137
-
138
- it('processes events through the sync queue', async () => {
139
- const currCursor = await network.pds.ctx.sequencer.curr()
140
- const runner = new MemoryRunner({
141
- startCursor: currCursor ?? undefined,
142
- })
143
- const evtsPromise = createAndReadFirehose(24, { runner }, true)
144
- const createAndPost = async (name: string) => {
145
- const user = await sc.createAccount('name', {
146
- handle: `${name}.test`,
147
- email: `${name}@example.com`,
148
- password: `${name}-pass`,
149
- })
150
- const did = user.did
151
- const post1 = await sc.post(did, 'one')
152
- const post2 = await sc.post(did, 'two')
153
- const post3 = await sc.post(did, 'three')
154
- return {
155
- did,
156
- post1: post1.ref.uriStr,
157
- post2: post2.ref.uriStr,
158
- post3: post3.ref.uriStr,
159
- }
160
- }
161
- const res = await Promise.all([
162
- createAndPost('user1'),
163
- createAndPost('user2'),
164
- createAndPost('user3'),
165
- createAndPost('user4'),
166
- ])
167
- const evts = await evtsPromise
168
- const user1Evts = evts.filter((e) => e.did === res[0].did)
169
- const user2Evts = evts.filter((e) => e.did === res[1].did)
170
- const user3Evts = evts.filter((e) => e.did === res[2].did)
171
- const user4Evts = evts.filter((e) => e.did === res[3].did)
172
- const EVT_ORDER = [
173
- 'identity',
174
- 'account',
175
- 'sync',
176
- 'create',
177
- 'create',
178
- 'create',
179
- ]
180
- expect(user1Evts.map((e) => e.event)).toEqual(EVT_ORDER)
181
- expect(user2Evts.map((e) => e.event)).toEqual(EVT_ORDER)
182
- expect(user3Evts.map((e) => e.event)).toEqual(EVT_ORDER)
183
- expect(user4Evts.map((e) => e.event)).toEqual(EVT_ORDER)
184
- expect(
185
- user1Evts.slice(3, 6).map((e) => (e as Create).uri.toString()),
186
- ).toEqual([res[0].post1, res[0].post2, res[0].post3])
187
- expect(
188
- user2Evts.slice(3, 6).map((e) => (e as Create).uri.toString()),
189
- ).toEqual([res[1].post1, res[1].post2, res[1].post3])
190
- expect(
191
- user3Evts.slice(3, 6).map((e) => (e as Create).uri.toString()),
192
- ).toEqual([res[2].post1, res[2].post2, res[2].post3])
193
- expect(
194
- user4Evts.slice(3, 6).map((e) => (e as Create).uri.toString()),
195
- ).toEqual([res[3].post1, res[3].post2, res[3].post3])
196
- })
197
- })
@@ -1,129 +0,0 @@
1
- import { wait } from '@atproto/common'
2
- import { ConsecutiveList, MemoryRunner } from '../src/index.js'
3
-
4
- describe('EventRunner utils', () => {
5
- describe('ConsecutiveList', () => {
6
- it('tracks consecutive complete items.', () => {
7
- const consecutive = new ConsecutiveList<number>()
8
- // add items
9
- const item1 = consecutive.push(1)
10
- const item2 = consecutive.push(2)
11
- const item3 = consecutive.push(3)
12
- expect(item1.isComplete).toEqual(false)
13
- expect(item2.isComplete).toEqual(false)
14
- expect(item3.isComplete).toEqual(false)
15
- // complete items out of order
16
- expect(consecutive.list.length).toBe(3)
17
- expect(item2.complete()).toEqual([])
18
- expect(item2.isComplete).toEqual(true)
19
- expect(consecutive.list.length).toBe(3)
20
- expect(item1.complete()).toEqual([1, 2])
21
- expect(item1.isComplete).toEqual(true)
22
- expect(consecutive.list.length).toBe(1)
23
- expect(item3.complete()).toEqual([3])
24
- expect(consecutive.list.length).toBe(0)
25
- expect(item3.isComplete).toEqual(true)
26
- })
27
- })
28
-
29
- describe('MemoryRunner', () => {
30
- it('performs work in parallel across partitions, serial within a partition.', async () => {
31
- const runner = new MemoryRunner({ concurrency: Infinity })
32
- const complete: {
33
- 1: number[]
34
- 2: number[]
35
- } = {
36
- 1: [],
37
- 2: [],
38
- }
39
- // partition 1 items start slow but get faster: slow should still complete first.
40
- runner.addTask('1', async () => {
41
- await wait(30)
42
- complete[1].push(1)
43
- })
44
- runner.addTask('1', async () => {
45
- await wait(20)
46
- complete[1].push(2)
47
- })
48
- runner.addTask('1', async () => {
49
- complete[1].push(3)
50
- })
51
- expect(runner.partitionCount).toEqual(1)
52
- // partition 2 items complete quickly except the last, which is slowest of all events.
53
- runner.addTask('2', async () => {
54
- await wait(1)
55
- complete[2].push(1)
56
- })
57
- runner.addTask('2', async () => {
58
- await wait(1)
59
- complete[2].push(2)
60
- })
61
- runner.addTask('2', async () => {
62
- complete[2].push(3)
63
- })
64
- runner.addTask('2', async () => {
65
- await wait(60)
66
- complete[2].push(4)
67
- })
68
- expect(runner.partitionCount).toEqual(2)
69
- await runner.processAll()
70
- expect(complete).toEqual({
71
- 1: [1, 2, 3],
72
- 2: [1, 2, 3, 4],
73
- })
74
- expect(runner.partitionCount).toEqual(0)
75
- })
76
-
77
- it('limits overall concurrency.', async () => {
78
- const runner = new MemoryRunner({ concurrency: 1 })
79
- const complete: number[] = []
80
- // if concurrency were not constrained, partition 1 would complete all items
81
- // before any items from partition 2. since it is constrained, the work is complete in the order added.
82
- runner.addTask('1', async () => {
83
- await wait(1)
84
- complete.push(11)
85
- })
86
- runner.addTask('2', async () => {
87
- await wait(10)
88
- complete.push(21)
89
- })
90
- runner.addTask('1', async () => {
91
- await wait(1)
92
- complete.push(12)
93
- })
94
- runner.addTask('2', async () => {
95
- await wait(10)
96
- complete.push(22)
97
- })
98
- // only partition 1 exists so far due to the concurrency
99
- expect(runner.partitionCount).toEqual(1)
100
- await runner.processAll()
101
- expect(complete).toEqual([11, 21, 12, 22])
102
- expect(runner.partitionCount).toEqual(0)
103
- })
104
-
105
- it('settles with many items.', async () => {
106
- const runner = new MemoryRunner({ concurrency: 100 })
107
- const complete: { partition: string; id: number }[] = []
108
- const partitions = new Set<string>()
109
- for (let i = 0; i < 500; ++i) {
110
- const partition = Math.floor(Math.random() * 16).toString(10)
111
- partitions.add(partition)
112
- runner.addTask(partition, async () => {
113
- await wait((i % 2) * 2)
114
- complete.push({ partition, id: i })
115
- })
116
- }
117
- expect(runner.partitionCount).toBeLessThanOrEqual(partitions.size)
118
- await runner.processAll()
119
- expect(complete.length).toEqual(500)
120
- for (const partition of partitions) {
121
- const ids = complete
122
- .filter((item) => item.partition === partition)
123
- .map((item) => item.id)
124
- expect(ids).toEqual([...ids].sort((a, b) => a - b))
125
- }
126
- expect(runner.partitionCount).toEqual(0)
127
- })
128
- })
129
- })
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../tsconfig/node.json",
3
- "compilerOptions": {
4
- "rootDir": "./src",
5
- "outDir": "./dist",
6
- },
7
- "include": ["./src"],
8
- }
@@ -1 +0,0 @@
1
- {"version":"7.0.0-dev.20260614.1","root":["./src/events.ts","./src/index.ts","./src/util.ts","./src/firehose/index.ts","./src/lexicons/com.ts","./src/lexicons/index.ts","./src/lexicons/com/atproto.ts","./src/lexicons/com/atproto/sync.ts","./src/lexicons/com/atproto/sync/subscribeRepos.defs.ts","./src/lexicons/com/atproto/sync/subscribeRepos.ts","./src/runner/consecutive-list.ts","./src/runner/index.ts","./src/runner/memory-runner.ts","./src/runner/types.ts"]}
package/tsconfig.json DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "include": [],
3
- "references": [
4
- { "path": "./tsconfig.build.json" },
5
- { "path": "./tsconfig.tests.json" },
6
- ],
7
- }
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "../../tsconfig/tests.json",
3
- "compilerOptions": {
4
- "rootDir": ".",
5
- "noUnusedLocals": false,
6
- },
7
- "include": ["./tests"],
8
- }