@atproto/pds 0.5.34 → 0.5.35

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/actor-store/actor-store-reader.d.ts +3 -2
  3. package/dist/actor-store/actor-store-reader.d.ts.map +1 -1
  4. package/dist/actor-store/actor-store-reader.js +2 -2
  5. package/dist/actor-store/actor-store-reader.js.map +1 -1
  6. package/dist/actor-store/actor-store-transactor.d.ts +3 -2
  7. package/dist/actor-store/actor-store-transactor.d.ts.map +1 -1
  8. package/dist/actor-store/actor-store-transactor.js +1 -1
  9. package/dist/actor-store/actor-store-transactor.js.map +1 -1
  10. package/dist/actor-store/actor-store.d.ts +5 -4
  11. package/dist/actor-store/actor-store.d.ts.map +1 -1
  12. package/dist/actor-store/actor-store.js.map +1 -1
  13. package/dist/actor-store/record/reader.d.ts +5 -3
  14. package/dist/actor-store/record/reader.d.ts.map +1 -1
  15. package/dist/actor-store/record/reader.js +19 -8
  16. package/dist/actor-store/record/reader.js.map +1 -1
  17. package/dist/actor-store/record/transactor.d.ts +3 -1
  18. package/dist/actor-store/record/transactor.d.ts.map +1 -1
  19. package/dist/actor-store/record/transactor.js +3 -2
  20. package/dist/actor-store/record/transactor.js.map +1 -1
  21. package/dist/actor-store/repo/reader.d.ts +3 -1
  22. package/dist/actor-store/repo/reader.d.ts.map +1 -1
  23. package/dist/actor-store/repo/reader.js +3 -2
  24. package/dist/actor-store/repo/reader.js.map +1 -1
  25. package/dist/actor-store/repo/transactor.d.ts +3 -2
  26. package/dist/actor-store/repo/transactor.d.ts.map +1 -1
  27. package/dist/actor-store/repo/transactor.js +2 -2
  28. package/dist/actor-store/repo/transactor.js.map +1 -1
  29. package/dist/api/com/atproto/admin/getSubjectStatus.js +1 -1
  30. package/dist/api/com/atproto/admin/getSubjectStatus.js.map +1 -1
  31. package/dist/api/com/atproto/admin/updateSubjectStatus.js +1 -1
  32. package/dist/api/com/atproto/admin/updateSubjectStatus.js.map +1 -1
  33. package/dist/api/com/atproto/server/activateAccount.d.ts.map +1 -1
  34. package/dist/api/com/atproto/server/activateAccount.js +3 -1
  35. package/dist/api/com/atproto/server/activateAccount.js.map +1 -1
  36. package/dist/api/com/atproto/server/deactivateAccount.d.ts +1 -1
  37. package/dist/api/com/atproto/server/deactivateAccount.d.ts.map +1 -1
  38. package/dist/api/com/atproto/server/deactivateAccount.js +11 -5
  39. package/dist/api/com/atproto/server/deactivateAccount.js.map +1 -1
  40. package/dist/context.d.ts.map +1 -1
  41. package/dist/context.js +60 -24
  42. package/dist/context.js.map +1 -1
  43. package/dist/read-after-write/util.d.ts.map +1 -1
  44. package/dist/read-after-write/util.js.map +1 -1
  45. package/package.json +16 -17
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @atproto/pds
2
2
 
3
+ ## 0.5.35
4
+
5
+ ### Patch Changes
6
+
7
+ - [#5527](https://github.com/bluesky-social/atproto/pull/5527) [`7870a59`](https://github.com/bluesky-social/atproto/commit/7870a59c0b0aa5955ba3b663f9e095350f50e194) Thanks [@devinivy](https://github.com/devinivy)! - Speed up com.atproto.repo.listRecords pagination over large collections.
8
+
9
+ - [#5499](https://github.com/bluesky-social/atproto/pull/5499) [`210907c`](https://github.com/bluesky-social/atproto/commit/210907c801d281c6b83c92bf94c888b2dc3d531f) Thanks [@fatfingers23](https://github.com/fatfingers23)! - Resolve permission set lexicons hosted on the PDS itself from the local actor store instead of fetching them over the network. Re-export `LexResolverError` from `@atproto/oauth-provider`.
10
+
11
+ - [#5545](https://github.com/bluesky-social/atproto/pull/5545) [`2e583a4`](https://github.com/bluesky-social/atproto/commit/2e583a4ed26659923b2a1effd952fce937f0feeb) Thanks [@fatfingers23](https://github.com/fatfingers23)! - Allow OAuth sessions holding the `account:status?action=manage` permission to call `com.atproto.server.deactivateAccount`. Deactivating through OAuth also revokes every OAuth session, authorized client and app password, matching the account manager along with the fact that OAuth logins are not allowed via deactivated accounts. `com.atproto.server.activateAccount` still rejects OAuth credentials, now with a message pointing users to their account management page.
12
+
13
+ - [#5519](https://github.com/bluesky-social/atproto/pull/5519) [`88f32da`](https://github.com/bluesky-social/atproto/commit/88f32dac103908d1fff0461815afe57b72cb3338) Thanks [@rafaeleyng](https://github.com/rafaeleyng)! - Fix SSRF endpoint tests to seed updated DID documents without bypassing the behavior under test.
14
+
15
+ - [#5391](https://github.com/bluesky-social/atproto/pull/5391) [`30f8149`](https://github.com/bluesky-social/atproto/commit/30f8149e629f9afc3fe41cf66bd8482954d7c052) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Remove `dotenv` dependency
16
+ - Updated dependencies [[`80bcda7`](https://github.com/bluesky-social/atproto/commit/80bcda748b435ecfecc18158921f4a84de2b4247), [`7f6785b`](https://github.com/bluesky-social/atproto/commit/7f6785bd4c48438e621c9b96265a52f14d64ce3c), [`2480187`](https://github.com/bluesky-social/atproto/commit/2480187c9554ff161227480dd6c0bcaf5e7e3921), [`210907c`](https://github.com/bluesky-social/atproto/commit/210907c801d281c6b83c92bf94c888b2dc3d531f), [`80bcda7`](https://github.com/bluesky-social/atproto/commit/80bcda748b435ecfecc18158921f4a84de2b4247), [`210907c`](https://github.com/bluesky-social/atproto/commit/210907c801d281c6b83c92bf94c888b2dc3d531f), [`30f8149`](https://github.com/bluesky-social/atproto/commit/30f8149e629f9afc3fe41cf66bd8482954d7c052)]:
17
+ - @atproto/oauth-provider@0.22.9
18
+ - @atproto/xrpc-server@0.13.2
19
+ - @atproto/lex-document@0.1.12
20
+ - @atproto/identity@0.5.14
21
+ - @atproto-labs/xrpc-utils@0.1.23
22
+ - @atproto/lex@0.3.12
23
+
3
24
  ## 0.5.34
4
25
 
5
26
  ### Patch Changes
@@ -1,4 +1,5 @@
1
1
  import type { Keypair } from '@atproto/crypto';
2
+ import type { DidString } from '@atproto/lex';
2
3
  import type { ActorStoreResources } from './actor-store-resources.js';
3
4
  import { ActorStoreTransactor } from './actor-store-transactor.js';
4
5
  import type { ActorDb } from './db/index.js';
@@ -6,14 +7,14 @@ import { PreferenceReader } from './preference/reader.js';
6
7
  import { RecordReader } from './record/reader.js';
7
8
  import { RepoReader } from './repo/reader.js';
8
9
  export declare class ActorStoreReader {
9
- readonly did: string;
10
+ readonly did: DidString;
10
11
  protected readonly db: ActorDb;
11
12
  protected readonly resources: ActorStoreResources;
12
13
  readonly keypair: () => Promise<Keypair>;
13
14
  readonly repo: RepoReader;
14
15
  readonly record: RecordReader;
15
16
  readonly pref: PreferenceReader;
16
- constructor(did: string, db: ActorDb, resources: ActorStoreResources, keypair: () => Promise<Keypair>);
17
+ constructor(did: DidString, db: ActorDb, resources: ActorStoreResources, keypair: () => Promise<Keypair>);
17
18
  transact<T>(fn: (fn: ActorStoreTransactor) => T | PromiseLike<T>): Promise<T>;
18
19
  }
19
20
  //# sourceMappingURL=actor-store-reader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actor-store-reader.d.ts","sourceRoot":"","sources":["../../src/actor-store/actor-store-reader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,qBAAa,gBAAgB;aAMT,GAAG,EAAE,MAAM;IAC3B,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO;IAC9B,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB;aACjC,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC;IARjD,SAAgB,IAAI,EAAE,UAAU,CAAA;IAChC,SAAgB,MAAM,EAAE,YAAY,CAAA;IACpC,SAAgB,IAAI,EAAE,gBAAgB,CAAA;IAEtC,YACkB,GAAG,EAAE,MAAM,EACR,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,mBAAmB,EACjC,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAWhD;IAEK,QAAQ,CAAC,CAAC,EACd,EAAE,EAAE,CAAC,EAAE,EAAE,oBAAoB,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GACnD,OAAO,CAAC,CAAC,CAAC,CAWZ;CACF"}
1
+ {"version":3,"file":"actor-store-reader.d.ts","sourceRoot":"","sources":["../../src/actor-store/actor-store-reader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,qBAAa,gBAAgB;aAMT,GAAG,EAAE,SAAS;IAC9B,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO;IAC9B,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB;aACjC,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC;IARjD,SAAgB,IAAI,EAAE,UAAU,CAAA;IAChC,SAAgB,MAAM,EAAE,YAAY,CAAA;IACpC,SAAgB,IAAI,EAAE,gBAAgB,CAAA;IAEtC,YACkB,GAAG,EAAE,SAAS,EACX,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,mBAAmB,EACjC,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAWhD;IAEK,QAAQ,CAAC,CAAC,EACd,EAAE,EAAE,CAAC,EAAE,EAAE,oBAAoB,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GACnD,OAAO,CAAC,CAAC,CAAC,CAWZ;CACF"}
@@ -9,8 +9,8 @@ export class ActorStoreReader {
9
9
  this.resources = resources;
10
10
  this.keypair = keypair;
11
11
  const blobstore = resources.blobstore(did);
12
- this.repo = new RepoReader(db, blobstore);
13
- this.record = new RecordReader(db);
12
+ this.repo = new RepoReader(db, blobstore, did);
13
+ this.record = new RecordReader(db, did);
14
14
  this.pref = new PreferenceReader(db);
15
15
  // Invoke "keypair" once. Also avoids leaking "this" as keypair context.
16
16
  let keypairPromise;
@@ -1 +1 @@
1
- {"version":3,"file":"actor-store-reader.js","sourceRoot":"","sources":["../../src/actor-store/actor-store-reader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,MAAM,OAAO,gBAAgB;IAK3B,YACkB,GAAW,EACR,EAAW,EACX,SAA8B,EACjC,OAA+B;mBAH/B,GAAG;kBACA,EAAE;yBACF,SAAS;uBACZ,OAAO;QAEvB,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QAE1C,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;QACzC,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,CAAC,CAAA;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,gBAAgB,CAAC,EAAE,CAAC,CAAA;QAEpC,wEAAwE;QACxE,IAAI,cAAgC,CAAA;QACpC,IAAI,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC,cAAc,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;IAC3E,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,EAAoD;QAEpD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAA;QACpC,OAAO,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,EAAE;YACnC,MAAM,KAAK,GAAG,IAAI,oBAAoB,CACpC,IAAI,CAAC,GAAG,EACR,KAAK,EACL,OAAO,EACP,IAAI,CAAC,SAAS,CACf,CAAA;YACD,OAAO,EAAE,CAAC,KAAK,CAAC,CAAA;QAClB,CAAC,CAAC,CAAA;IACJ,CAAC;CACF","sourcesContent":["import type { Keypair } from '@atproto/crypto'\nimport type { ActorStoreResources } from './actor-store-resources.js'\nimport { ActorStoreTransactor } from './actor-store-transactor.js'\nimport type { ActorDb } from './db/index.js'\nimport { PreferenceReader } from './preference/reader.js'\nimport { RecordReader } from './record/reader.js'\nimport { RepoReader } from './repo/reader.js'\n\nexport class ActorStoreReader {\n public readonly repo: RepoReader\n public readonly record: RecordReader\n public readonly pref: PreferenceReader\n\n constructor(\n public readonly did: string,\n protected readonly db: ActorDb,\n protected readonly resources: ActorStoreResources,\n public readonly keypair: () => Promise<Keypair>,\n ) {\n const blobstore = resources.blobstore(did)\n\n this.repo = new RepoReader(db, blobstore)\n this.record = new RecordReader(db)\n this.pref = new PreferenceReader(db)\n\n // Invoke \"keypair\" once. Also avoids leaking \"this\" as keypair context.\n let keypairPromise: Promise<Keypair>\n this.keypair = () => (keypairPromise ??= Promise.resolve().then(keypair))\n }\n\n async transact<T>(\n fn: (fn: ActorStoreTransactor) => T | PromiseLike<T>,\n ): Promise<T> {\n const keypair = await this.keypair()\n return this.db.transaction((dbTxn) => {\n const store = new ActorStoreTransactor(\n this.did,\n dbTxn,\n keypair,\n this.resources,\n )\n return fn(store)\n })\n }\n}\n"]}
1
+ {"version":3,"file":"actor-store-reader.js","sourceRoot":"","sources":["../../src/actor-store/actor-store-reader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAElE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,MAAM,OAAO,gBAAgB;IAK3B,YACkB,GAAc,EACX,EAAW,EACX,SAA8B,EACjC,OAA+B;mBAH/B,GAAG;kBACA,EAAE;yBACF,SAAS;uBACZ,OAAO;QAEvB,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QAE1C,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,CAAA;QAC9C,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;QACvC,IAAI,CAAC,IAAI,GAAG,IAAI,gBAAgB,CAAC,EAAE,CAAC,CAAA;QAEpC,wEAAwE;QACxE,IAAI,cAAgC,CAAA;QACpC,IAAI,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC,cAAc,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;IAC3E,CAAC;IAED,KAAK,CAAC,QAAQ,CACZ,EAAoD;QAEpD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAA;QACpC,OAAO,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,EAAE;YACnC,MAAM,KAAK,GAAG,IAAI,oBAAoB,CACpC,IAAI,CAAC,GAAG,EACR,KAAK,EACL,OAAO,EACP,IAAI,CAAC,SAAS,CACf,CAAA;YACD,OAAO,EAAE,CAAC,KAAK,CAAC,CAAA;QAClB,CAAC,CAAC,CAAA;IACJ,CAAC;CACF","sourcesContent":["import type { Keypair } from '@atproto/crypto'\nimport type { DidString } from '@atproto/lex'\nimport type { ActorStoreResources } from './actor-store-resources.js'\nimport { ActorStoreTransactor } from './actor-store-transactor.js'\nimport type { ActorDb } from './db/index.js'\nimport { PreferenceReader } from './preference/reader.js'\nimport { RecordReader } from './record/reader.js'\nimport { RepoReader } from './repo/reader.js'\n\nexport class ActorStoreReader {\n public readonly repo: RepoReader\n public readonly record: RecordReader\n public readonly pref: PreferenceReader\n\n constructor(\n public readonly did: DidString,\n protected readonly db: ActorDb,\n protected readonly resources: ActorStoreResources,\n public readonly keypair: () => Promise<Keypair>,\n ) {\n const blobstore = resources.blobstore(did)\n\n this.repo = new RepoReader(db, blobstore, did)\n this.record = new RecordReader(db, did)\n this.pref = new PreferenceReader(db)\n\n // Invoke \"keypair\" once. Also avoids leaking \"this\" as keypair context.\n let keypairPromise: Promise<Keypair>\n this.keypair = () => (keypairPromise ??= Promise.resolve().then(keypair))\n }\n\n async transact<T>(\n fn: (fn: ActorStoreTransactor) => T | PromiseLike<T>,\n ): Promise<T> {\n const keypair = await this.keypair()\n return this.db.transaction((dbTxn) => {\n const store = new ActorStoreTransactor(\n this.did,\n dbTxn,\n keypair,\n this.resources,\n )\n return fn(store)\n })\n }\n}\n"]}
@@ -1,17 +1,18 @@
1
1
  import type { Keypair } from '@atproto/crypto';
2
+ import type { DidString } from '@atproto/lex';
2
3
  import type { ActorStoreResources } from './actor-store-resources.js';
3
4
  import type { ActorDb } from './db/index.js';
4
5
  import { PreferenceTransactor } from './preference/transactor.js';
5
6
  import { RecordTransactor } from './record/transactor.js';
6
7
  import { RepoTransactor } from './repo/transactor.js';
7
8
  export declare class ActorStoreTransactor {
8
- readonly did: string;
9
+ readonly did: DidString;
9
10
  protected readonly db: ActorDb;
10
11
  protected readonly keypair: Keypair;
11
12
  protected readonly resources: ActorStoreResources;
12
13
  readonly record: RecordTransactor;
13
14
  readonly repo: RepoTransactor;
14
15
  readonly pref: PreferenceTransactor;
15
- constructor(did: string, db: ActorDb, keypair: Keypair, resources: ActorStoreResources);
16
+ constructor(did: DidString, db: ActorDb, keypair: Keypair, resources: ActorStoreResources);
16
17
  }
17
18
  //# sourceMappingURL=actor-store-transactor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actor-store-transactor.d.ts","sourceRoot":"","sources":["../../src/actor-store/actor-store-transactor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,qBAAa,oBAAoB;aAMb,GAAG,EAAE,MAAM;IAC3B,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO;IAC9B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO;IACnC,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB;IARnD,SAAgB,MAAM,EAAE,gBAAgB,CAAA;IACxC,SAAgB,IAAI,EAAE,cAAc,CAAA;IACpC,SAAgB,IAAI,EAAE,oBAAoB,CAAA;IAE1C,YACkB,GAAG,EAAE,MAAM,EACR,EAAE,EAAE,OAAO,EACX,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,mBAAmB,EAalD;CACF"}
1
+ {"version":3,"file":"actor-store-transactor.d.ts","sourceRoot":"","sources":["../../src/actor-store/actor-store-transactor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,qBAAa,oBAAoB;aAMb,GAAG,EAAE,SAAS;IAC9B,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,OAAO;IAC9B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO;IACnC,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB;IARnD,SAAgB,MAAM,EAAE,gBAAgB,CAAA;IACxC,SAAgB,IAAI,EAAE,cAAc,CAAA;IACpC,SAAgB,IAAI,EAAE,oBAAoB,CAAA;IAE1C,YACkB,GAAG,EAAE,SAAS,EACX,EAAE,EAAE,OAAO,EACX,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,mBAAmB,EAalD;CACF"}
@@ -8,7 +8,7 @@ export class ActorStoreTransactor {
8
8
  this.keypair = keypair;
9
9
  this.resources = resources;
10
10
  const blobstore = resources.blobstore(did);
11
- this.record = new RecordTransactor(db, blobstore);
11
+ this.record = new RecordTransactor(db, did, blobstore);
12
12
  this.pref = new PreferenceTransactor(db);
13
13
  this.repo = new RepoTransactor(db, blobstore, did, keypair, resources.backgroundQueue);
14
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"actor-store-transactor.js","sourceRoot":"","sources":["../../src/actor-store/actor-store-transactor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,MAAM,OAAO,oBAAoB;IAK/B,YACkB,GAAW,EACR,EAAW,EACX,OAAgB,EAChB,SAA8B;mBAHjC,GAAG;kBACA,EAAE;uBACF,OAAO;yBACP,SAAS;QAE5B,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QAE1C,IAAI,CAAC,MAAM,GAAG,IAAI,gBAAgB,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;QACjD,IAAI,CAAC,IAAI,GAAG,IAAI,oBAAoB,CAAC,EAAE,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,IAAI,cAAc,CAC5B,EAAE,EACF,SAAS,EACT,GAAG,EACH,OAAO,EACP,SAAS,CAAC,eAAe,CAC1B,CAAA;IACH,CAAC;CACF","sourcesContent":["import type { Keypair } from '@atproto/crypto'\nimport type { ActorStoreResources } from './actor-store-resources.js'\nimport type { ActorDb } from './db/index.js'\nimport { PreferenceTransactor } from './preference/transactor.js'\nimport { RecordTransactor } from './record/transactor.js'\nimport { RepoTransactor } from './repo/transactor.js'\n\nexport class ActorStoreTransactor {\n public readonly record: RecordTransactor\n public readonly repo: RepoTransactor\n public readonly pref: PreferenceTransactor\n\n constructor(\n public readonly did: string,\n protected readonly db: ActorDb,\n protected readonly keypair: Keypair,\n protected readonly resources: ActorStoreResources,\n ) {\n const blobstore = resources.blobstore(did)\n\n this.record = new RecordTransactor(db, blobstore)\n this.pref = new PreferenceTransactor(db)\n this.repo = new RepoTransactor(\n db,\n blobstore,\n did,\n keypair,\n resources.backgroundQueue,\n )\n }\n}\n"]}
1
+ {"version":3,"file":"actor-store-transactor.js","sourceRoot":"","sources":["../../src/actor-store/actor-store-transactor.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,MAAM,OAAO,oBAAoB;IAK/B,YACkB,GAAc,EACX,EAAW,EACX,OAAgB,EAChB,SAA8B;mBAHjC,GAAG;kBACA,EAAE;uBACF,OAAO;yBACP,SAAS;QAE5B,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QAE1C,IAAI,CAAC,MAAM,GAAG,IAAI,gBAAgB,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAA;QACtD,IAAI,CAAC,IAAI,GAAG,IAAI,oBAAoB,CAAC,EAAE,CAAC,CAAA;QACxC,IAAI,CAAC,IAAI,GAAG,IAAI,cAAc,CAC5B,EAAE,EACF,SAAS,EACT,GAAG,EACH,OAAO,EACP,SAAS,CAAC,eAAe,CAC1B,CAAA;IACH,CAAC;CACF","sourcesContent":["import type { Keypair } from '@atproto/crypto'\nimport type { DidString } from '@atproto/lex'\nimport type { ActorStoreResources } from './actor-store-resources.js'\nimport type { ActorDb } from './db/index.js'\nimport { PreferenceTransactor } from './preference/transactor.js'\nimport { RecordTransactor } from './record/transactor.js'\nimport { RepoTransactor } from './repo/transactor.js'\n\nexport class ActorStoreTransactor {\n public readonly record: RecordTransactor\n public readonly repo: RepoTransactor\n public readonly pref: PreferenceTransactor\n\n constructor(\n public readonly did: DidString,\n protected readonly db: ActorDb,\n protected readonly keypair: Keypair,\n protected readonly resources: ActorStoreResources,\n ) {\n const blobstore = resources.blobstore(did)\n\n this.record = new RecordTransactor(db, did, blobstore)\n this.pref = new PreferenceTransactor(db)\n this.repo = new RepoTransactor(\n db,\n blobstore,\n did,\n keypair,\n resources.backgroundQueue,\n )\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import type { ExportableKeypair, Keypair } from '@atproto/crypto';
2
+ import type { DidString } from '@atproto/lex';
2
3
  import type { ActorStoreConfig } from '../config/index.js';
3
4
  import { ActorStoreReader } from './actor-store-reader.js';
4
5
  import type { ActorStoreResources } from './actor-store-resources.js';
@@ -18,11 +19,11 @@ export declare class ActorStore {
18
19
  exists(did: string): Promise<boolean>;
19
20
  keypair(did: string): Promise<Keypair>;
20
21
  openDb(did: string): Promise<ActorDb>;
21
- read<T>(did: string, fn: (fn: ActorStoreReader) => T | PromiseLike<T>): Promise<T>;
22
- transact<T>(did: string, fn: (fn: ActorStoreTransactor) => T | PromiseLike<T>): Promise<T>;
23
- writeNoTransaction<T>(did: string, fn: (fn: ActorStoreWriter) => T | PromiseLike<T>): Promise<T>;
22
+ read<T>(did: DidString, fn: (fn: ActorStoreReader) => T | PromiseLike<T>): Promise<T>;
23
+ transact<T>(did: DidString, fn: (fn: ActorStoreTransactor) => T | PromiseLike<T>): Promise<T>;
24
+ writeNoTransaction<T>(did: DidString, fn: (fn: ActorStoreWriter) => T | PromiseLike<T>): Promise<T>;
24
25
  create(did: string, keypair: ExportableKeypair): Promise<void>;
25
- destroy(did: string): Promise<void>;
26
+ destroy(did: DidString): Promise<void>;
26
27
  reserveKeypair(did?: string): Promise<string>;
27
28
  getReservedKeypair(signingKeyOrDid: string): Promise<ExportableKeypair | undefined>;
28
29
  clearReservedKeypair(keyDid: string, did?: string): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"actor-store.d.ts","sourceRoot":"","sources":["../../src/actor-store/actor-store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAEjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAI1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,eAAe,CAAA;AAEhE,qBAAa,UAAU;IAIZ,GAAG,EAAE,gBAAgB;IACrB,SAAS,EAAE,mBAAmB;IAJvC,cAAc,EAAE,MAAM,CAAA;IAEtB,YACS,GAAG,EAAE,gBAAgB,EACrB,SAAS,EAAE,mBAAmB,EAGtC;IAEK,WAAW,CAAC,GAAG,EAAE,MAAM;;;;OAM5B;IAEK,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG1C;IAEK,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAI3C;IAEK,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAoB1C;IAEK,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,gBAAgB,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,cAQ1E;IAEK,QAAQ,CAAC,CAAC,EACd,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,CAAC,EAAE,EAAE,oBAAoB,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,cAWrD;IAEK,kBAAkB,CAAC,CAAC,EACxB,GAAG,EAAE,MAAM,EACX,EAAE,EAAE,CAAC,EAAE,EAAE,gBAAgB,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,cASjD;IAEK,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,iBAmBnD;IAEK,OAAO,CAAC,GAAG,EAAE,MAAM,iBAexB;IAEK,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBlD;IAEK,kBAAkB,CACtB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAExC;IAEK,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,iBAKtD;IAEK,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,iBAI3C;IAEK,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAI/C;IAEK,UAAU,CAAC,GAAG,EAAE,MAAM,iBAI3B;CACF"}
1
+ {"version":3,"file":"actor-store.d.ts","sourceRoot":"","sources":["../../src/actor-store/actor-store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAI1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,KAAK,OAAO,EAAsB,MAAM,eAAe,CAAA;AAEhE,qBAAa,UAAU;IAIZ,GAAG,EAAE,gBAAgB;IACrB,SAAS,EAAE,mBAAmB;IAJvC,cAAc,EAAE,MAAM,CAAA;IAEtB,YACS,GAAG,EAAE,gBAAgB,EACrB,SAAS,EAAE,mBAAmB,EAGtC;IAEK,WAAW,CAAC,GAAG,EAAE,MAAM;;;;OAM5B;IAEK,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAG1C;IAEK,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAI3C;IAEK,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAoB1C;IAEK,IAAI,CAAC,CAAC,EACV,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,CAAC,EAAE,EAAE,gBAAgB,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,cASjD;IAEK,QAAQ,CAAC,CAAC,EACd,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,CAAC,EAAE,EAAE,oBAAoB,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,cAWrD;IAEK,kBAAkB,CAAC,CAAC,EACxB,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,CAAC,EAAE,EAAE,gBAAgB,KAAK,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,cASjD;IAEK,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,iBAmBnD;IAEK,OAAO,CAAC,GAAG,EAAE,SAAS,iBAe3B;IAEK,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBlD;IAEK,kBAAkB,CACtB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAExC;IAEK,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,iBAKtD;IAEK,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,iBAI3C;IAEK,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAI/C;IAEK,UAAU,CAAC,GAAG,EAAE,MAAM,iBAI3B;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"actor-store.js","sourceRoot":"","sources":["../../src/actor-store/actor-store.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport fs, { mkdir } from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileExists, readIfExists, rmIfExists } from '@atproto/common'\nimport * as crypto from '@atproto/crypto'\nimport type { ExportableKeypair, Keypair } from '@atproto/crypto'\nimport { InvalidRequestError } from '@atproto/xrpc-server'\nimport type { ActorStoreConfig } from '../config/index.js'\nimport { retrySqlite } from '../db/index.js'\nimport { DiskBlobStore } from '../disk-blobstore.js'\nimport { blobStoreLogger } from '../logger.js'\nimport { ActorStoreReader } from './actor-store-reader.js'\nimport type { ActorStoreResources } from './actor-store-resources.js'\nimport { ActorStoreTransactor } from './actor-store-transactor.js'\nimport { ActorStoreWriter } from './actor-store-writer.js'\nimport { type ActorDb, getDb, getMigrator } from './db/index.js'\n\nexport class ActorStore {\n reservedKeyDir: string\n\n constructor(\n public cfg: ActorStoreConfig,\n public resources: ActorStoreResources,\n ) {\n this.reservedKeyDir = path.join(cfg.directory, 'reserved_keys')\n }\n\n async getLocation(did: string) {\n const didHash = await crypto.sha256Hex(did)\n const directory = path.join(this.cfg.directory, didHash.slice(0, 2), did)\n const dbLocation = path.join(directory, `store.sqlite`)\n const keyLocation = path.join(directory, `key`)\n return { directory, dbLocation, keyLocation }\n }\n\n async exists(did: string): Promise<boolean> {\n const location = await this.getLocation(did)\n return await fileExists(location.dbLocation)\n }\n\n async keypair(did: string): Promise<Keypair> {\n const { keyLocation } = await this.getLocation(did)\n const privKey = await fs.readFile(keyLocation)\n return crypto.Secp256k1Keypair.import(privKey)\n }\n\n async openDb(did: string): Promise<ActorDb> {\n const { dbLocation } = await this.getLocation(did)\n const exists = await fileExists(dbLocation)\n if (!exists) {\n throw new InvalidRequestError('Repo not found', 'NotFound')\n }\n\n const db = getDb(dbLocation, this.cfg.disableWalAutoCheckpoint)\n\n // run a simple select with retry logic to ensure the db is ready (not in wal recovery mode)\n try {\n await retrySqlite(() =>\n db.db.selectFrom('repo_root').selectAll().execute(),\n )\n } catch (err) {\n db.close()\n throw err\n }\n\n return db\n }\n\n async read<T>(did: string, fn: (fn: ActorStoreReader) => T | PromiseLike<T>) {\n const db = await this.openDb(did)\n try {\n const getKeypair = () => this.keypair(did)\n return await fn(new ActorStoreReader(did, db, this.resources, getKeypair))\n } finally {\n db.close()\n }\n }\n\n async transact<T>(\n did: string,\n fn: (fn: ActorStoreTransactor) => T | PromiseLike<T>,\n ) {\n const keypair = await this.keypair(did)\n const db = await this.openDb(did)\n try {\n return await db.transaction((dbTxn) => {\n return fn(new ActorStoreTransactor(did, dbTxn, keypair, this.resources))\n })\n } finally {\n db.close()\n }\n }\n\n async writeNoTransaction<T>(\n did: string,\n fn: (fn: ActorStoreWriter) => T | PromiseLike<T>,\n ) {\n const keypair = await this.keypair(did)\n const db = await this.openDb(did)\n try {\n return await fn(new ActorStoreWriter(did, db, keypair, this.resources))\n } finally {\n db.close()\n }\n }\n\n async create(did: string, keypair: ExportableKeypair) {\n const { directory, dbLocation, keyLocation } = await this.getLocation(did)\n // ensure subdir exists\n await mkdir(directory, { recursive: true })\n const exists = await fileExists(dbLocation)\n if (exists) {\n throw new InvalidRequestError('Repo already exists', 'AlreadyExists')\n }\n const privKey = await keypair.export()\n await fs.writeFile(keyLocation, privKey)\n\n const db: ActorDb = getDb(dbLocation, this.cfg.disableWalAutoCheckpoint)\n try {\n await db.ensureWal()\n const migrator = getMigrator(db)\n await migrator.migrateToLatestOrThrow()\n } finally {\n db.close()\n }\n }\n\n async destroy(did: string) {\n const blobstore = this.resources.blobstore(did)\n if (blobstore instanceof DiskBlobStore) {\n await blobstore.deleteAll()\n } else {\n const cids = await this.read(did, async (store) =>\n store.repo.blob.getBlobCids(),\n )\n await blobstore.deleteMany(cids).catch((err) => {\n blobStoreLogger.error({ did, cids, err }, 'Failed to delete blobs')\n })\n }\n\n const { directory } = await this.getLocation(did)\n await rmIfExists(directory, true)\n }\n\n async reserveKeypair(did?: string): Promise<string> {\n let keyLoc: string | undefined\n if (did) {\n assertSafePathPart(did)\n keyLoc = path.join(this.reservedKeyDir, did)\n const maybeKey = await loadKey(keyLoc)\n if (maybeKey) {\n return maybeKey.did()\n }\n }\n const keypair = await crypto.Secp256k1Keypair.create({ exportable: true })\n const keyDid = keypair.did()\n keyLoc = keyLoc ?? path.join(this.reservedKeyDir, keyDid)\n await mkdir(this.reservedKeyDir, { recursive: true })\n await fs.writeFile(keyLoc, await keypair.export())\n return keyDid\n }\n\n async getReservedKeypair(\n signingKeyOrDid: string,\n ): Promise<ExportableKeypair | undefined> {\n return loadKey(path.join(this.reservedKeyDir, signingKeyOrDid))\n }\n\n async clearReservedKeypair(keyDid: string, did?: string) {\n await rmIfExists(path.join(this.reservedKeyDir, keyDid))\n if (did) {\n await rmIfExists(path.join(this.reservedKeyDir, did))\n }\n }\n\n async storePlcOp(did: string, op: Uint8Array) {\n const { directory } = await this.getLocation(did)\n const opLoc = path.join(directory, `did-op`)\n await fs.writeFile(opLoc, op)\n }\n\n async getPlcOp(did: string): Promise<Uint8Array> {\n const { directory } = await this.getLocation(did)\n const opLoc = path.join(directory, `did-op`)\n return await fs.readFile(opLoc)\n }\n\n async clearPlcOp(did: string) {\n const { directory } = await this.getLocation(did)\n const opLoc = path.join(directory, `did-op`)\n await rmIfExists(opLoc)\n }\n}\n\nconst loadKey = async (loc: string): Promise<ExportableKeypair | undefined> => {\n const privKey = await readIfExists(loc)\n if (!privKey) return undefined\n return crypto.Secp256k1Keypair.import(privKey, { exportable: true })\n}\n\nfunction assertSafePathPart(part: string) {\n const normalized = path.normalize(part)\n assert(\n part === normalized &&\n !part.startsWith('.') &&\n !part.includes('/') &&\n !part.includes('\\\\'),\n `unsafe path part: ${part}`,\n )\n}\n"]}
1
+ {"version":3,"file":"actor-store.js","sourceRoot":"","sources":["../../src/actor-store/actor-store.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from 'node:assert'\nimport fs, { mkdir } from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileExists, readIfExists, rmIfExists } from '@atproto/common'\nimport * as crypto from '@atproto/crypto'\nimport type { ExportableKeypair, Keypair } from '@atproto/crypto'\nimport type { DidString } from '@atproto/lex'\nimport { InvalidRequestError } from '@atproto/xrpc-server'\nimport type { ActorStoreConfig } from '../config/index.js'\nimport { retrySqlite } from '../db/index.js'\nimport { DiskBlobStore } from '../disk-blobstore.js'\nimport { blobStoreLogger } from '../logger.js'\nimport { ActorStoreReader } from './actor-store-reader.js'\nimport type { ActorStoreResources } from './actor-store-resources.js'\nimport { ActorStoreTransactor } from './actor-store-transactor.js'\nimport { ActorStoreWriter } from './actor-store-writer.js'\nimport { type ActorDb, getDb, getMigrator } from './db/index.js'\n\nexport class ActorStore {\n reservedKeyDir: string\n\n constructor(\n public cfg: ActorStoreConfig,\n public resources: ActorStoreResources,\n ) {\n this.reservedKeyDir = path.join(cfg.directory, 'reserved_keys')\n }\n\n async getLocation(did: string) {\n const didHash = await crypto.sha256Hex(did)\n const directory = path.join(this.cfg.directory, didHash.slice(0, 2), did)\n const dbLocation = path.join(directory, `store.sqlite`)\n const keyLocation = path.join(directory, `key`)\n return { directory, dbLocation, keyLocation }\n }\n\n async exists(did: string): Promise<boolean> {\n const location = await this.getLocation(did)\n return await fileExists(location.dbLocation)\n }\n\n async keypair(did: string): Promise<Keypair> {\n const { keyLocation } = await this.getLocation(did)\n const privKey = await fs.readFile(keyLocation)\n return crypto.Secp256k1Keypair.import(privKey)\n }\n\n async openDb(did: string): Promise<ActorDb> {\n const { dbLocation } = await this.getLocation(did)\n const exists = await fileExists(dbLocation)\n if (!exists) {\n throw new InvalidRequestError('Repo not found', 'NotFound')\n }\n\n const db = getDb(dbLocation, this.cfg.disableWalAutoCheckpoint)\n\n // run a simple select with retry logic to ensure the db is ready (not in wal recovery mode)\n try {\n await retrySqlite(() =>\n db.db.selectFrom('repo_root').selectAll().execute(),\n )\n } catch (err) {\n db.close()\n throw err\n }\n\n return db\n }\n\n async read<T>(\n did: DidString,\n fn: (fn: ActorStoreReader) => T | PromiseLike<T>,\n ) {\n const db = await this.openDb(did)\n try {\n const getKeypair = () => this.keypair(did)\n return await fn(new ActorStoreReader(did, db, this.resources, getKeypair))\n } finally {\n db.close()\n }\n }\n\n async transact<T>(\n did: DidString,\n fn: (fn: ActorStoreTransactor) => T | PromiseLike<T>,\n ) {\n const keypair = await this.keypair(did)\n const db = await this.openDb(did)\n try {\n return await db.transaction((dbTxn) => {\n return fn(new ActorStoreTransactor(did, dbTxn, keypair, this.resources))\n })\n } finally {\n db.close()\n }\n }\n\n async writeNoTransaction<T>(\n did: DidString,\n fn: (fn: ActorStoreWriter) => T | PromiseLike<T>,\n ) {\n const keypair = await this.keypair(did)\n const db = await this.openDb(did)\n try {\n return await fn(new ActorStoreWriter(did, db, keypair, this.resources))\n } finally {\n db.close()\n }\n }\n\n async create(did: string, keypair: ExportableKeypair) {\n const { directory, dbLocation, keyLocation } = await this.getLocation(did)\n // ensure subdir exists\n await mkdir(directory, { recursive: true })\n const exists = await fileExists(dbLocation)\n if (exists) {\n throw new InvalidRequestError('Repo already exists', 'AlreadyExists')\n }\n const privKey = await keypair.export()\n await fs.writeFile(keyLocation, privKey)\n\n const db: ActorDb = getDb(dbLocation, this.cfg.disableWalAutoCheckpoint)\n try {\n await db.ensureWal()\n const migrator = getMigrator(db)\n await migrator.migrateToLatestOrThrow()\n } finally {\n db.close()\n }\n }\n\n async destroy(did: DidString) {\n const blobstore = this.resources.blobstore(did)\n if (blobstore instanceof DiskBlobStore) {\n await blobstore.deleteAll()\n } else {\n const cids = await this.read(did, async (store) =>\n store.repo.blob.getBlobCids(),\n )\n await blobstore.deleteMany(cids).catch((err) => {\n blobStoreLogger.error({ did, cids, err }, 'Failed to delete blobs')\n })\n }\n\n const { directory } = await this.getLocation(did)\n await rmIfExists(directory, true)\n }\n\n async reserveKeypair(did?: string): Promise<string> {\n let keyLoc: string | undefined\n if (did) {\n assertSafePathPart(did)\n keyLoc = path.join(this.reservedKeyDir, did)\n const maybeKey = await loadKey(keyLoc)\n if (maybeKey) {\n return maybeKey.did()\n }\n }\n const keypair = await crypto.Secp256k1Keypair.create({ exportable: true })\n const keyDid = keypair.did()\n keyLoc = keyLoc ?? path.join(this.reservedKeyDir, keyDid)\n await mkdir(this.reservedKeyDir, { recursive: true })\n await fs.writeFile(keyLoc, await keypair.export())\n return keyDid\n }\n\n async getReservedKeypair(\n signingKeyOrDid: string,\n ): Promise<ExportableKeypair | undefined> {\n return loadKey(path.join(this.reservedKeyDir, signingKeyOrDid))\n }\n\n async clearReservedKeypair(keyDid: string, did?: string) {\n await rmIfExists(path.join(this.reservedKeyDir, keyDid))\n if (did) {\n await rmIfExists(path.join(this.reservedKeyDir, did))\n }\n }\n\n async storePlcOp(did: string, op: Uint8Array) {\n const { directory } = await this.getLocation(did)\n const opLoc = path.join(directory, `did-op`)\n await fs.writeFile(opLoc, op)\n }\n\n async getPlcOp(did: string): Promise<Uint8Array> {\n const { directory } = await this.getLocation(did)\n const opLoc = path.join(directory, `did-op`)\n return await fs.readFile(opLoc)\n }\n\n async clearPlcOp(did: string) {\n const { directory } = await this.getLocation(did)\n const opLoc = path.join(directory, `did-op`)\n await rmIfExists(opLoc)\n }\n}\n\nconst loadKey = async (loc: string): Promise<ExportableKeypair | undefined> => {\n const privKey = await readIfExists(loc)\n if (!privKey) return undefined\n return crypto.Secp256k1Keypair.import(privKey, { exportable: true })\n}\n\nfunction assertSafePathPart(part: string) {\n const normalized = path.normalize(part)\n assert(\n part === normalized &&\n !part.startsWith('.') &&\n !part.includes('/') &&\n !part.includes('\\\\'),\n `unsafe path part: ${part}`,\n )\n}\n"]}
@@ -1,6 +1,7 @@
1
+ import type { DidString, NsidString } from '@atproto/lex';
1
2
  import { type Cid, type LexMap } from '@atproto/lex-data';
2
3
  import { CidSet } from '@atproto/repo';
3
- import { AtUri, type AtUriString, type NsidString } from '@atproto/syntax';
4
+ import { AtUri, type AtUriString } from '@atproto/syntax';
4
5
  import { app, type com } from '../../lexicons/index.js';
5
6
  import type { LocalRecords } from '../../read-after-write/types.js';
6
7
  import type { ActorDb, Backlink } from '../db/index.js';
@@ -11,12 +12,13 @@ export type RecordDescript = {
11
12
  };
12
13
  export declare class RecordReader {
13
14
  db: ActorDb;
14
- constructor(db: ActorDb);
15
+ did: DidString;
16
+ constructor(db: ActorDb, did: DidString);
15
17
  recordCount(): Promise<number>;
16
18
  listAll(): Promise<RecordDescript[]>;
17
19
  listCollections(): Promise<NsidString[]>;
18
20
  listRecordsForCollection(opts: {
19
- collection: string;
21
+ collection: NsidString;
20
22
  limit: number;
21
23
  reverse: boolean;
22
24
  cursor?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../src/actor-store/record/reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,MAAM,EAAY,MAAM,mBAAmB,CAAA;AACnE,OAAO,EAAE,MAAM,EAAkC,MAAM,eAAe,CAAA;AACtE,OAAO,EACL,KAAK,EACL,KAAK,WAAW,EAEhB,KAAK,UAAU,EAGhB,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,GAAG,EAAE,KAAK,GAAG,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEvD,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,GAAG,CAAA;CACT,CAAA;AAED,qBAAa,YAAY;IACJ,EAAE,EAAE,OAAO;IAA9B,YAAmB,EAAE,EAAE,OAAO,EAAI;IAE5B,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAMnC;IAEK,OAAO,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAsBzC;IAEK,eAAe,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAQ7C;IAEK,wBAAwB,CAAC,IAAI,EAAE;QACnC,UAAU,EAAE,MAAM,CAAA;QAClB,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,OAAO,CAAA;QAChB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAC7B,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,WAAW,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CA4C9D;IAEK,SAAS,CACb,GAAG,EAAE,KAAK,GAAG,WAAW,EACxB,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,kBAAkB,UAAQ,GACzB,OAAO,CAAC;QACT,GAAG,EAAE,MAAM,CAAA;QACX,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,SAAS,EAAE,MAAM,CAAA;QACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAC3B,GAAG,IAAI,CAAC,CAsBR;IAEK,SAAS,CACb,GAAG,EAAE,KAAK,EACV,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,kBAAkB,UAAQ,GACzB,OAAO,CAAC,OAAO,CAAC,CAclB;IAEK,uBAAuB,CAC3B,GAAG,EAAE,KAAK,GACT,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,CAUnD;IAEK,mBAAmB,CAAC,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAOzD;IAEK,kBAAkB,CAAC,IAAI,EAAE;QAC7B,UAAU,EAAE,MAAM,CAAA;QAClB,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;KACf;;;;;;;;SAUA;IAKK,oBAAoB,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAgBvE;IAEK,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAiB1C;IAEK,gBAAgB,gDAYrB;IAEK,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAwD3D;CACF;AAKD,eAAO,MAAM,YAAY,QAAS,KAAK,UAAU,MAAM,KAAG,QAAQ,EA4CjE,CAAA"}
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../src/actor-store/record/reader.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,9 @@ import { AtUri, ensureValidAtUri, ensureValidDid, } from '@atproto/syntax';
4
4
  import { countAll, notSoftDeletedClause } from '../../db/util.js';
5
5
  import { app } from '../../lexicons/index.js';
6
6
  export class RecordReader {
7
- constructor(db) {
7
+ constructor(db, did) {
8
8
  this.db = db;
9
+ this.did = did;
9
10
  }
10
11
  async recordCount() {
11
12
  const res = await this.db.db
@@ -47,30 +48,35 @@ export class RecordReader {
47
48
  }
48
49
  async listRecordsForCollection(opts) {
49
50
  const { collection, limit, reverse, cursor, rkeyStart, rkeyEnd, includeSoftDeleted = false, } = opts;
51
+ const collectionUri = formatRecordUriKey(this.did, collection, '');
50
52
  const { ref } = this.db.db.dynamic;
51
53
  let builder = this.db.db
52
54
  .selectFrom('record')
53
55
  .innerJoin('repo_block', 'repo_block.cid', 'record.cid')
54
- .where('record.collection', '=', collection)
56
+ // @NOTE The URI primary key orders records by rkey within a collection;
57
+ // DEL sorts after every valid record-key character.
58
+ .where('record.uri', '>=', collectionUri)
59
+ .where('record.uri', '<', `${collectionUri}\x7f`)
55
60
  .$if(!includeSoftDeleted, (qb) => qb.where(notSoftDeletedClause(ref('record'))))
56
- .orderBy('record.rkey', reverse ? 'asc' : 'desc')
61
+ .orderBy('record.uri', reverse ? 'asc' : 'desc')
57
62
  .limit(limit)
58
63
  .selectAll();
59
- // prioritize cursor but fall back to soon-to-be-depcreated rkey start/end
64
+ // prioritize cursor but fall back to soon-to-be-deprecated rkey start/end
60
65
  if (cursor !== undefined) {
66
+ const cursorUri = formatRecordUriKey(this.did, collection, cursor);
61
67
  if (reverse) {
62
- builder = builder.where('record.rkey', '>', cursor);
68
+ builder = builder.where('record.uri', '>', cursorUri);
63
69
  }
64
70
  else {
65
- builder = builder.where('record.rkey', '<', cursor);
71
+ builder = builder.where('record.uri', '<', cursorUri);
66
72
  }
67
73
  }
68
74
  else {
69
75
  if (rkeyStart !== undefined) {
70
- builder = builder.where('record.rkey', '>', rkeyStart);
76
+ builder = builder.where('record.uri', '>', formatRecordUriKey(this.did, collection, rkeyStart));
71
77
  }
72
78
  if (rkeyEnd !== undefined) {
73
- builder = builder.where('record.rkey', '<', rkeyEnd);
79
+ builder = builder.where('record.uri', '<', formatRecordUriKey(this.did, collection, rkeyEnd));
74
80
  }
75
81
  }
76
82
  const res = await builder.execute();
@@ -243,6 +249,11 @@ export class RecordReader {
243
249
  return result;
244
250
  }
245
251
  }
252
+ function formatRecordUriKey(did, collection, rkey) {
253
+ // @NOTE This intentionally avoids atUri(): range bounds and opaque cursors
254
+ // are not necessarily valid AT URIs.
255
+ return `at://${did}/${collection}/${rkey}`;
256
+ }
246
257
  // @NOTE in the future this can be replaced with a more generic routine that pulls backlinks based on lex docs.
247
258
  // For now we just want to ensure we're tracking links from follows, blocks, likes, and reposts.
248
259
  export const getBacklinks = (uri, record) => {
@@ -1 +1 @@
1
- {"version":3,"file":"reader.js","sourceRoot":"","sources":["../../../src/actor-store/record/reader.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Cid, type LexMap, parseCid } from '@atproto/lex-data'\nimport { CidSet, cborToLexRecord, formatDataKey } from '@atproto/repo'\nimport {\n AtUri,\n type AtUriString,\n type DatetimeString,\n type NsidString,\n ensureValidAtUri,\n ensureValidDid,\n} from '@atproto/syntax'\nimport { countAll, notSoftDeletedClause } from '../../db/util.js'\nimport { app, type com } from '../../lexicons/index.js'\nimport type { LocalRecords } from '../../read-after-write/types.js'\nimport type { ActorDb, Backlink } from '../db/index.js'\n\nexport type RecordDescript = {\n uri: string\n path: string\n cid: Cid\n}\n\nexport class RecordReader {\n constructor(public db: ActorDb) {}\n\n async recordCount(): Promise<number> {\n const res = await this.db.db\n .selectFrom('record')\n .select(countAll.as('count'))\n .executeTakeFirst()\n return res?.count ?? 0\n }\n\n async listAll(): Promise<RecordDescript[]> {\n const records: RecordDescript[] = []\n let cursor: string | undefined = ''\n while (cursor !== undefined) {\n const res = await this.db.db\n .selectFrom('record')\n .select(['uri', 'cid'])\n .where('uri', '>', cursor)\n .orderBy('uri', 'asc')\n .limit(1000)\n .execute()\n for (const row of res) {\n const parsed = new AtUri(row.uri)\n records.push({\n uri: row.uri,\n path: formatDataKey(parsed.collection, parsed.rkey),\n cid: parseCid(row.cid),\n })\n }\n cursor = res.at(-1)?.uri\n }\n return records\n }\n\n async listCollections(): Promise<NsidString[]> {\n const collections = await this.db.db\n .selectFrom('record')\n .select('collection')\n .groupBy('collection')\n .execute()\n\n return collections.map((row) => row.collection as NsidString)\n }\n\n async listRecordsForCollection(opts: {\n collection: string\n limit: number\n reverse: boolean\n cursor?: string\n rkeyStart?: string\n rkeyEnd?: string\n includeSoftDeleted?: boolean\n }): Promise<{ uri: AtUriString; cid: string; value: LexMap }[]> {\n const {\n collection,\n limit,\n reverse,\n cursor,\n rkeyStart,\n rkeyEnd,\n includeSoftDeleted = false,\n } = opts\n\n const { ref } = this.db.db.dynamic\n let builder = this.db.db\n .selectFrom('record')\n .innerJoin('repo_block', 'repo_block.cid', 'record.cid')\n .where('record.collection', '=', collection)\n .$if(!includeSoftDeleted, (qb) =>\n qb.where(notSoftDeletedClause(ref('record'))),\n )\n .orderBy('record.rkey', reverse ? 'asc' : 'desc')\n .limit(limit)\n .selectAll()\n\n // prioritize cursor but fall back to soon-to-be-depcreated rkey start/end\n if (cursor !== undefined) {\n if (reverse) {\n builder = builder.where('record.rkey', '>', cursor)\n } else {\n builder = builder.where('record.rkey', '<', cursor)\n }\n } else {\n if (rkeyStart !== undefined) {\n builder = builder.where('record.rkey', '>', rkeyStart)\n }\n if (rkeyEnd !== undefined) {\n builder = builder.where('record.rkey', '<', rkeyEnd)\n }\n }\n const res = await builder.execute()\n return res.map((row) => ({\n uri: row.uri as AtUriString,\n cid: row.cid,\n value: cborToLexRecord(row.content),\n }))\n }\n\n async getRecord(\n uri: AtUri | AtUriString,\n cid: string | null,\n includeSoftDeleted = false,\n ): Promise<{\n uri: string\n cid: string\n value: LexMap\n indexedAt: string\n takedownRef: string | null\n } | null> {\n const { ref } = this.db.db.dynamic\n let builder = this.db.db\n .selectFrom('record')\n .innerJoin('repo_block', 'repo_block.cid', 'record.cid')\n .where('record.uri', '=', uri.toString())\n .selectAll()\n .$if(!includeSoftDeleted, (qb) =>\n qb.where(notSoftDeletedClause(ref('record'))),\n )\n if (cid) {\n builder = builder.where('record.cid', '=', cid)\n }\n const record = await builder.executeTakeFirst()\n if (!record) return null\n return {\n uri: record.uri,\n cid: record.cid,\n value: cborToLexRecord(record.content),\n indexedAt: record.indexedAt,\n takedownRef: record.takedownRef ? record.takedownRef.toString() : null,\n }\n }\n\n async hasRecord(\n uri: AtUri,\n cid: string | null,\n includeSoftDeleted = false,\n ): Promise<boolean> {\n const { ref } = this.db.db.dynamic\n let builder = this.db.db\n .selectFrom('record')\n .select('uri')\n .where('record.uri', '=', uri.toString())\n .$if(!includeSoftDeleted, (qb) =>\n qb.where(notSoftDeletedClause(ref('record'))),\n )\n if (cid) {\n builder = builder.where('record.cid', '=', cid)\n }\n const record = await builder.executeTakeFirst()\n return !!record\n }\n\n async getRecordTakedownStatus(\n uri: AtUri,\n ): Promise<com.atproto.admin.defs.StatusAttr | null> {\n const res = await this.db.db\n .selectFrom('record')\n .select('takedownRef')\n .where('uri', '=', uri.toString())\n .executeTakeFirst()\n if (!res) return null\n return res.takedownRef\n ? { applied: true, ref: res.takedownRef }\n : { applied: false }\n }\n\n async getCurrentRecordCid(uri: AtUri): Promise<Cid | null> {\n const res = await this.db.db\n .selectFrom('record')\n .select('cid')\n .where('uri', '=', uri.toString())\n .executeTakeFirst()\n return res ? parseCid(res.cid) : null\n }\n\n async getRecordBacklinks(opts: {\n collection: string\n path: string\n linkTo: string\n }) {\n const { collection, path, linkTo } = opts\n return await this.db.db\n .selectFrom('record')\n .innerJoin('backlink', 'backlink.uri', 'record.uri')\n .where('backlink.path', '=', path)\n .where('backlink.linkTo', '=', linkTo)\n .where('record.collection', '=', collection)\n .selectAll('record')\n .execute()\n }\n\n // @NOTE this logic is a placeholder until we allow users to specify these constraints themselves.\n // Ensures that we don't end-up with duplicate likes, reposts, and follows from race conditions.\n\n async getBacklinkConflicts(uri: AtUri, record: LexMap): Promise<AtUri[]> {\n const conflicts: AtUri[] = []\n\n for (const backlink of getBacklinks(uri, record)) {\n const backlinks = await this.getRecordBacklinks({\n collection: uri.collection,\n path: backlink.path,\n linkTo: backlink.linkTo,\n })\n\n for (const { rkey } of backlinks) {\n conflicts.push(AtUri.make(uri.hostname, uri.collection, rkey))\n }\n }\n\n return conflicts\n }\n\n async listExistingBlocks(): Promise<CidSet> {\n const cids = new CidSet()\n let cursor: string | undefined = ''\n while (cursor !== undefined) {\n const res = await this.db.db\n .selectFrom('repo_block')\n .select('cid')\n .where('cid', '>', cursor)\n .orderBy('cid', 'asc')\n .limit(1000)\n .execute()\n for (const row of res) {\n cids.add(parseCid(row.cid))\n }\n cursor = res.at(-1)?.cid\n }\n return cids\n }\n\n async getProfileRecord() {\n const row = await this.db.db\n .selectFrom('record')\n .leftJoin('repo_block', 'repo_block.cid', 'record.cid')\n .where('record.collection', '=', app.bsky.actor.profile.$type)\n .where('record.rkey', '=', 'self')\n .selectAll()\n .executeTakeFirst()\n\n if (!row?.content) return null\n\n return cborToLexRecord(row.content) as app.bsky.actor.profile.Main\n }\n\n async getRecordsSinceRev(rev: string): Promise<LocalRecords> {\n const result: LocalRecords = { count: 0, profile: null, posts: [] }\n\n const res = await this.db.db\n .selectFrom('record')\n .innerJoin('repo_block', 'repo_block.cid', 'record.cid')\n .select([\n 'repo_block.content',\n 'uri',\n 'repo_block.cid',\n 'record.indexedAt',\n ])\n .where('record.repoRev', '>', rev)\n .limit(10)\n .orderBy('record.repoRev', 'asc')\n .execute()\n\n // sanity check to ensure that the clock received is not before _all_ local records (for instance in case of account migration)\n if (res.length > 0) {\n const sanityCheckRes = await this.db.db\n .selectFrom('record')\n .selectAll()\n .where('record.repoRev', '<=', rev)\n .limit(1)\n .executeTakeFirst()\n\n if (!sanityCheckRes) {\n return result\n }\n }\n\n for (const cur of res) {\n result.count++\n\n const uri = new AtUri(cur.uri)\n if (\n uri.collection === app.bsky.actor.profile.$type &&\n uri.rkey === 'self'\n ) {\n result.profile = {\n uri,\n cid: parseCid(cur.cid),\n indexedAt: cur.indexedAt as DatetimeString,\n record: cborToLexRecord(cur.content) as app.bsky.actor.profile.Main,\n }\n } else if (uri.collection === app.bsky.feed.post.$type) {\n result.posts.push({\n uri,\n cid: parseCid(cur.cid),\n indexedAt: cur.indexedAt as DatetimeString,\n record: cborToLexRecord(cur.content) as app.bsky.feed.post.Main,\n })\n }\n }\n\n return result\n }\n}\n\n// @NOTE in the future this can be replaced with a more generic routine that pulls backlinks based on lex docs.\n// For now we just want to ensure we're tracking links from follows, blocks, likes, and reposts.\n\nexport const getBacklinks = (uri: AtUri, record: LexMap): Backlink[] => {\n if (\n record?.['$type'] === app.bsky.graph.follow.$type ||\n record?.['$type'] === app.bsky.graph.block.$type\n ) {\n const subject = record['subject']\n if (typeof subject !== 'string') {\n return []\n }\n try {\n ensureValidDid(subject)\n } catch {\n return []\n }\n return [\n {\n uri: uri.toString(),\n path: 'subject',\n linkTo: subject,\n },\n ]\n }\n if (\n record?.['$type'] === app.bsky.feed.like.$type ||\n record?.['$type'] === app.bsky.feed.repost.$type\n ) {\n const subject = record['subject']\n if (typeof subject?.['uri'] !== 'string') {\n return []\n }\n try {\n ensureValidAtUri(subject['uri'])\n } catch {\n return []\n }\n return [\n {\n uri: uri.toString(),\n path: 'subject.uri',\n linkTo: subject['uri'],\n },\n ]\n }\n return []\n}\n"]}
1
+ {"version":3,"file":"reader.js","sourceRoot":"","sources":["../../../src/actor-store/record/reader.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DidString, NsidString } from '@atproto/lex'\nimport { type Cid, type LexMap, parseCid } from '@atproto/lex-data'\nimport { CidSet, cborToLexRecord, formatDataKey } from '@atproto/repo'\nimport {\n AtUri,\n type AtUriString,\n type DatetimeString,\n ensureValidAtUri,\n ensureValidDid,\n} from '@atproto/syntax'\nimport { countAll, notSoftDeletedClause } from '../../db/util.js'\nimport { app, type com } from '../../lexicons/index.js'\nimport type { LocalRecords } from '../../read-after-write/types.js'\nimport type { ActorDb, Backlink } from '../db/index.js'\n\nexport type RecordDescript = {\n uri: string\n path: string\n cid: Cid\n}\n\nexport class RecordReader {\n constructor(\n public db: ActorDb,\n public did: DidString,\n ) {}\n\n async recordCount(): Promise<number> {\n const res = await this.db.db\n .selectFrom('record')\n .select(countAll.as('count'))\n .executeTakeFirst()\n return res?.count ?? 0\n }\n\n async listAll(): Promise<RecordDescript[]> {\n const records: RecordDescript[] = []\n let cursor: string | undefined = ''\n while (cursor !== undefined) {\n const res = await this.db.db\n .selectFrom('record')\n .select(['uri', 'cid'])\n .where('uri', '>', cursor)\n .orderBy('uri', 'asc')\n .limit(1000)\n .execute()\n for (const row of res) {\n const parsed = new AtUri(row.uri)\n records.push({\n uri: row.uri,\n path: formatDataKey(parsed.collection, parsed.rkey),\n cid: parseCid(row.cid),\n })\n }\n cursor = res.at(-1)?.uri\n }\n return records\n }\n\n async listCollections(): Promise<NsidString[]> {\n const collections = await this.db.db\n .selectFrom('record')\n .select('collection')\n .groupBy('collection')\n .execute()\n\n return collections.map((row) => row.collection as NsidString)\n }\n\n async listRecordsForCollection(opts: {\n collection: NsidString\n limit: number\n reverse: boolean\n cursor?: string\n rkeyStart?: string\n rkeyEnd?: string\n includeSoftDeleted?: boolean\n }): Promise<{ uri: AtUriString; cid: string; value: LexMap }[]> {\n const {\n collection,\n limit,\n reverse,\n cursor,\n rkeyStart,\n rkeyEnd,\n includeSoftDeleted = false,\n } = opts\n\n const collectionUri = formatRecordUriKey(this.did, collection, '')\n const { ref } = this.db.db.dynamic\n let builder = this.db.db\n .selectFrom('record')\n .innerJoin('repo_block', 'repo_block.cid', 'record.cid')\n // @NOTE The URI primary key orders records by rkey within a collection;\n // DEL sorts after every valid record-key character.\n .where('record.uri', '>=', collectionUri)\n .where('record.uri', '<', `${collectionUri}\\x7f`)\n .$if(!includeSoftDeleted, (qb) =>\n qb.where(notSoftDeletedClause(ref('record'))),\n )\n .orderBy('record.uri', reverse ? 'asc' : 'desc')\n .limit(limit)\n .selectAll()\n\n // prioritize cursor but fall back to soon-to-be-deprecated rkey start/end\n if (cursor !== undefined) {\n const cursorUri = formatRecordUriKey(this.did, collection, cursor)\n if (reverse) {\n builder = builder.where('record.uri', '>', cursorUri)\n } else {\n builder = builder.where('record.uri', '<', cursorUri)\n }\n } else {\n if (rkeyStart !== undefined) {\n builder = builder.where(\n 'record.uri',\n '>',\n formatRecordUriKey(this.did, collection, rkeyStart),\n )\n }\n if (rkeyEnd !== undefined) {\n builder = builder.where(\n 'record.uri',\n '<',\n formatRecordUriKey(this.did, collection, rkeyEnd),\n )\n }\n }\n const res = await builder.execute()\n return res.map((row) => ({\n uri: row.uri as AtUriString,\n cid: row.cid,\n value: cborToLexRecord(row.content),\n }))\n }\n\n async getRecord(\n uri: AtUri | AtUriString,\n cid: string | null,\n includeSoftDeleted = false,\n ): Promise<{\n uri: string\n cid: string\n value: LexMap\n indexedAt: string\n takedownRef: string | null\n } | null> {\n const { ref } = this.db.db.dynamic\n let builder = this.db.db\n .selectFrom('record')\n .innerJoin('repo_block', 'repo_block.cid', 'record.cid')\n .where('record.uri', '=', uri.toString())\n .selectAll()\n .$if(!includeSoftDeleted, (qb) =>\n qb.where(notSoftDeletedClause(ref('record'))),\n )\n if (cid) {\n builder = builder.where('record.cid', '=', cid)\n }\n const record = await builder.executeTakeFirst()\n if (!record) return null\n return {\n uri: record.uri,\n cid: record.cid,\n value: cborToLexRecord(record.content),\n indexedAt: record.indexedAt,\n takedownRef: record.takedownRef ? record.takedownRef.toString() : null,\n }\n }\n\n async hasRecord(\n uri: AtUri,\n cid: string | null,\n includeSoftDeleted = false,\n ): Promise<boolean> {\n const { ref } = this.db.db.dynamic\n let builder = this.db.db\n .selectFrom('record')\n .select('uri')\n .where('record.uri', '=', uri.toString())\n .$if(!includeSoftDeleted, (qb) =>\n qb.where(notSoftDeletedClause(ref('record'))),\n )\n if (cid) {\n builder = builder.where('record.cid', '=', cid)\n }\n const record = await builder.executeTakeFirst()\n return !!record\n }\n\n async getRecordTakedownStatus(\n uri: AtUri,\n ): Promise<com.atproto.admin.defs.StatusAttr | null> {\n const res = await this.db.db\n .selectFrom('record')\n .select('takedownRef')\n .where('uri', '=', uri.toString())\n .executeTakeFirst()\n if (!res) return null\n return res.takedownRef\n ? { applied: true, ref: res.takedownRef }\n : { applied: false }\n }\n\n async getCurrentRecordCid(uri: AtUri): Promise<Cid | null> {\n const res = await this.db.db\n .selectFrom('record')\n .select('cid')\n .where('uri', '=', uri.toString())\n .executeTakeFirst()\n return res ? parseCid(res.cid) : null\n }\n\n async getRecordBacklinks(opts: {\n collection: string\n path: string\n linkTo: string\n }) {\n const { collection, path, linkTo } = opts\n return await this.db.db\n .selectFrom('record')\n .innerJoin('backlink', 'backlink.uri', 'record.uri')\n .where('backlink.path', '=', path)\n .where('backlink.linkTo', '=', linkTo)\n .where('record.collection', '=', collection)\n .selectAll('record')\n .execute()\n }\n\n // @NOTE this logic is a placeholder until we allow users to specify these constraints themselves.\n // Ensures that we don't end-up with duplicate likes, reposts, and follows from race conditions.\n\n async getBacklinkConflicts(uri: AtUri, record: LexMap): Promise<AtUri[]> {\n const conflicts: AtUri[] = []\n\n for (const backlink of getBacklinks(uri, record)) {\n const backlinks = await this.getRecordBacklinks({\n collection: uri.collection,\n path: backlink.path,\n linkTo: backlink.linkTo,\n })\n\n for (const { rkey } of backlinks) {\n conflicts.push(AtUri.make(uri.hostname, uri.collection, rkey))\n }\n }\n\n return conflicts\n }\n\n async listExistingBlocks(): Promise<CidSet> {\n const cids = new CidSet()\n let cursor: string | undefined = ''\n while (cursor !== undefined) {\n const res = await this.db.db\n .selectFrom('repo_block')\n .select('cid')\n .where('cid', '>', cursor)\n .orderBy('cid', 'asc')\n .limit(1000)\n .execute()\n for (const row of res) {\n cids.add(parseCid(row.cid))\n }\n cursor = res.at(-1)?.cid\n }\n return cids\n }\n\n async getProfileRecord() {\n const row = await this.db.db\n .selectFrom('record')\n .leftJoin('repo_block', 'repo_block.cid', 'record.cid')\n .where('record.collection', '=', app.bsky.actor.profile.$type)\n .where('record.rkey', '=', 'self')\n .selectAll()\n .executeTakeFirst()\n\n if (!row?.content) return null\n\n return cborToLexRecord(row.content) as app.bsky.actor.profile.Main\n }\n\n async getRecordsSinceRev(rev: string): Promise<LocalRecords> {\n const result: LocalRecords = { count: 0, profile: null, posts: [] }\n\n const res = await this.db.db\n .selectFrom('record')\n .innerJoin('repo_block', 'repo_block.cid', 'record.cid')\n .select([\n 'repo_block.content',\n 'uri',\n 'repo_block.cid',\n 'record.indexedAt',\n ])\n .where('record.repoRev', '>', rev)\n .limit(10)\n .orderBy('record.repoRev', 'asc')\n .execute()\n\n // sanity check to ensure that the clock received is not before _all_ local records (for instance in case of account migration)\n if (res.length > 0) {\n const sanityCheckRes = await this.db.db\n .selectFrom('record')\n .selectAll()\n .where('record.repoRev', '<=', rev)\n .limit(1)\n .executeTakeFirst()\n\n if (!sanityCheckRes) {\n return result\n }\n }\n\n for (const cur of res) {\n result.count++\n\n const uri = new AtUri(cur.uri)\n if (\n uri.collection === app.bsky.actor.profile.$type &&\n uri.rkey === 'self'\n ) {\n result.profile = {\n uri,\n cid: parseCid(cur.cid),\n indexedAt: cur.indexedAt as DatetimeString,\n record: cborToLexRecord(cur.content) as app.bsky.actor.profile.Main,\n }\n } else if (uri.collection === app.bsky.feed.post.$type) {\n result.posts.push({\n uri,\n cid: parseCid(cur.cid),\n indexedAt: cur.indexedAt as DatetimeString,\n record: cborToLexRecord(cur.content) as app.bsky.feed.post.Main,\n })\n }\n }\n\n return result\n }\n}\n\nfunction formatRecordUriKey(\n did: DidString,\n collection: NsidString,\n rkey: string,\n): string {\n // @NOTE This intentionally avoids atUri(): range bounds and opaque cursors\n // are not necessarily valid AT URIs.\n return `at://${did}/${collection}/${rkey}`\n}\n\n// @NOTE in the future this can be replaced with a more generic routine that pulls backlinks based on lex docs.\n// For now we just want to ensure we're tracking links from follows, blocks, likes, and reposts.\n\nexport const getBacklinks = (uri: AtUri, record: LexMap): Backlink[] => {\n if (\n record?.['$type'] === app.bsky.graph.follow.$type ||\n record?.['$type'] === app.bsky.graph.block.$type\n ) {\n const subject = record['subject']\n if (typeof subject !== 'string') {\n return []\n }\n try {\n ensureValidDid(subject)\n } catch {\n return []\n }\n return [\n {\n uri: uri.toString(),\n path: 'subject',\n linkTo: subject,\n },\n ]\n }\n if (\n record?.['$type'] === app.bsky.feed.like.$type ||\n record?.['$type'] === app.bsky.feed.repost.$type\n ) {\n const subject = record['subject']\n if (typeof subject?.['uri'] !== 'string') {\n return []\n }\n try {\n ensureValidAtUri(subject['uri'])\n } catch {\n return []\n }\n return [\n {\n uri: uri.toString(),\n path: 'subject.uri',\n linkTo: subject['uri'],\n },\n ]\n }\n return []\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import type { DidString } from '@atproto/lex';
1
2
  import type { Cid, LexMap } from '@atproto/lex-data';
2
3
  import { type BlobStore, WriteOpAction } from '@atproto/repo';
3
4
  import type { AtUri } from '@atproto/syntax';
@@ -6,8 +7,9 @@ import type { ActorDb, Backlink } from '../db/index.js';
6
7
  import { RecordReader } from './reader.js';
7
8
  export declare class RecordTransactor extends RecordReader {
8
9
  db: ActorDb;
10
+ did: DidString;
9
11
  blobstore: BlobStore;
10
- constructor(db: ActorDb, blobstore: BlobStore);
12
+ constructor(db: ActorDb, did: DidString, blobstore: BlobStore);
11
13
  indexRecord(uri: AtUri, cid: Cid, record: LexMap | null, action: WriteOpAction.Create | WriteOpAction.Update | undefined, repoRev: string, timestamp?: string): Promise<void>;
12
14
  deleteRecord(uri: AtUri): Promise<void>;
13
15
  removeBacklinksByUri(uri: AtUri): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"transactor.d.ts","sourceRoot":"","sources":["../../../src/actor-store/record/transactor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,KAAK,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAA;AAElD,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAgB,MAAM,aAAa,CAAA;AAExD,qBAAa,gBAAiB,SAAQ,YAAY;IAEvC,EAAE,EAAE,OAAO;IACX,SAAS,EAAE,SAAS;IAF7B,YACS,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,SAAS,EAG5B;IAEK,WAAW,CACf,GAAG,EAAE,KAAK,EACV,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,MAAM,EAAE,aAAa,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,YAAuB,EAC1E,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,iBA4CnB;IAEK,YAAY,CAAC,GAAG,EAAE,KAAK,iBAW5B;IAEK,oBAAoB,CAAC,GAAG,EAAE,KAAK,iBAKpC;IAEK,YAAY,CAAC,SAAS,EAAE,QAAQ,EAAE,iBAOvC;IAEK,0BAA0B,CAC9B,GAAG,EAAE,KAAK,EACV,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,iBAU5C;CACF"}
1
+ {"version":3,"file":"transactor.d.ts","sourceRoot":"","sources":["../../../src/actor-store/record/transactor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,KAAK,SAAS,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,yBAAyB,CAAA;AAElD,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAgB,MAAM,aAAa,CAAA;AAExD,qBAAa,gBAAiB,SAAQ,YAAY;IAEvC,EAAE,EAAE,OAAO;IACX,GAAG,EAAE,SAAS;IACd,SAAS,EAAE,SAAS;IAH7B,YACS,EAAE,EAAE,OAAO,EACX,GAAG,EAAE,SAAS,EACd,SAAS,EAAE,SAAS,EAG5B;IAEK,WAAW,CACf,GAAG,EAAE,KAAK,EACV,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,MAAM,EAAE,aAAa,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,YAAuB,EAC1E,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,iBA4CnB;IAEK,YAAY,CAAC,GAAG,EAAE,KAAK,iBAW5B;IAEK,oBAAoB,CAAC,GAAG,EAAE,KAAK,iBAKpC;IAEK,YAAY,CAAC,SAAS,EAAE,QAAQ,EAAE,iBAOvC;IAEK,0BAA0B,CAC9B,GAAG,EAAE,KAAK,EACV,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,iBAU5C;CACF"}
@@ -2,9 +2,10 @@ import { WriteOpAction } from '@atproto/repo';
2
2
  import { dbLogger as log } from '../../logger.js';
3
3
  import { RecordReader, getBacklinks } from './reader.js';
4
4
  export class RecordTransactor extends RecordReader {
5
- constructor(db, blobstore) {
6
- super(db);
5
+ constructor(db, did, blobstore) {
6
+ super(db, did);
7
7
  this.db = db;
8
+ this.did = did;
8
9
  this.blobstore = blobstore;
9
10
  }
10
11
  async indexRecord(uri, cid, record, action = WriteOpAction.Create, repoRev, timestamp) {
@@ -1 +1 @@
1
- {"version":3,"file":"transactor.js","sourceRoot":"","sources":["../../../src/actor-store/record/transactor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Cid, LexMap } from '@atproto/lex-data'\nimport { type BlobStore, WriteOpAction } from '@atproto/repo'\nimport type { AtUri } from '@atproto/syntax'\nimport type { com } from '../../lexicons/index.js'\nimport { dbLogger as log } from '../../logger.js'\nimport type { ActorDb, Backlink } from '../db/index.js'\nimport { RecordReader, getBacklinks } from './reader.js'\n\nexport class RecordTransactor extends RecordReader {\n constructor(\n public db: ActorDb,\n public blobstore: BlobStore,\n ) {\n super(db)\n }\n\n async indexRecord(\n uri: AtUri,\n cid: Cid,\n record: LexMap | null,\n action: WriteOpAction.Create | WriteOpAction.Update = WriteOpAction.Create,\n repoRev: string,\n timestamp?: string,\n ) {\n log.debug({ uri }, 'indexing record')\n const row = {\n uri: uri.toString(),\n cid: cid.toString(),\n collection: uri.collection,\n rkey: uri.rkey,\n repoRev: repoRev,\n indexedAt: timestamp || new Date().toISOString(),\n }\n if (!uri.hostname.startsWith('did:')) {\n throw new Error('Expected indexed URI to contain DID')\n } else if (row.collection.length < 1) {\n throw new Error('Expected indexed URI to contain a collection')\n } else if (row.rkey.length < 1) {\n throw new Error('Expected indexed URI to contain a record key')\n }\n\n // Track current version of record\n await this.db.db\n .insertInto('record')\n .values(row)\n .onConflict((oc) =>\n oc.column('uri').doUpdateSet({\n cid: row.cid,\n repoRev: repoRev,\n indexedAt: row.indexedAt,\n }),\n )\n .execute()\n\n if (record !== null) {\n // Maintain backlinks\n const backlinks = getBacklinks(uri, record)\n if (action === WriteOpAction.Update) {\n // On update just recreate backlinks from scratch for the record, so we can clear out\n // the old ones. E.g. for weird cases like updating a follow to be for a different did.\n await this.removeBacklinksByUri(uri)\n }\n await this.addBacklinks(backlinks)\n }\n\n log.info({ uri }, 'indexed record')\n }\n\n async deleteRecord(uri: AtUri) {\n log.debug({ uri }, 'deleting indexed record')\n const deleteQuery = this.db.db\n .deleteFrom('record')\n .where('uri', '=', uri.toString())\n const backlinkQuery = this.db.db\n .deleteFrom('backlink')\n .where('uri', '=', uri.toString())\n await Promise.all([deleteQuery.execute(), backlinkQuery.execute()])\n\n log.info({ uri }, 'deleted indexed record')\n }\n\n async removeBacklinksByUri(uri: AtUri) {\n await this.db.db\n .deleteFrom('backlink')\n .where('uri', '=', uri.toString())\n .execute()\n }\n\n async addBacklinks(backlinks: Backlink[]) {\n if (backlinks.length === 0) return\n await this.db.db\n .insertInto('backlink')\n .values(backlinks)\n .onConflict((oc) => oc.doNothing())\n .execute()\n }\n\n async updateRecordTakedownStatus(\n uri: AtUri,\n takedown: com.atproto.admin.defs.StatusAttr,\n ) {\n const takedownRef = takedown.applied\n ? (takedown.ref ?? new Date().toISOString())\n : null\n await this.db.db\n .updateTable('record')\n .set({ takedownRef })\n .where('uri', '=', uri.toString())\n .executeTakeFirst()\n }\n}\n"]}
1
+ {"version":3,"file":"transactor.js","sourceRoot":"","sources":["../../../src/actor-store/record/transactor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DidString } from '@atproto/lex'\nimport type { Cid, LexMap } from '@atproto/lex-data'\nimport { type BlobStore, WriteOpAction } from '@atproto/repo'\nimport type { AtUri } from '@atproto/syntax'\nimport type { com } from '../../lexicons/index.js'\nimport { dbLogger as log } from '../../logger.js'\nimport type { ActorDb, Backlink } from '../db/index.js'\nimport { RecordReader, getBacklinks } from './reader.js'\n\nexport class RecordTransactor extends RecordReader {\n constructor(\n public db: ActorDb,\n public did: DidString,\n public blobstore: BlobStore,\n ) {\n super(db, did)\n }\n\n async indexRecord(\n uri: AtUri,\n cid: Cid,\n record: LexMap | null,\n action: WriteOpAction.Create | WriteOpAction.Update = WriteOpAction.Create,\n repoRev: string,\n timestamp?: string,\n ) {\n log.debug({ uri }, 'indexing record')\n const row = {\n uri: uri.toString(),\n cid: cid.toString(),\n collection: uri.collection,\n rkey: uri.rkey,\n repoRev: repoRev,\n indexedAt: timestamp || new Date().toISOString(),\n }\n if (!uri.hostname.startsWith('did:')) {\n throw new Error('Expected indexed URI to contain DID')\n } else if (row.collection.length < 1) {\n throw new Error('Expected indexed URI to contain a collection')\n } else if (row.rkey.length < 1) {\n throw new Error('Expected indexed URI to contain a record key')\n }\n\n // Track current version of record\n await this.db.db\n .insertInto('record')\n .values(row)\n .onConflict((oc) =>\n oc.column('uri').doUpdateSet({\n cid: row.cid,\n repoRev: repoRev,\n indexedAt: row.indexedAt,\n }),\n )\n .execute()\n\n if (record !== null) {\n // Maintain backlinks\n const backlinks = getBacklinks(uri, record)\n if (action === WriteOpAction.Update) {\n // On update just recreate backlinks from scratch for the record, so we can clear out\n // the old ones. E.g. for weird cases like updating a follow to be for a different did.\n await this.removeBacklinksByUri(uri)\n }\n await this.addBacklinks(backlinks)\n }\n\n log.info({ uri }, 'indexed record')\n }\n\n async deleteRecord(uri: AtUri) {\n log.debug({ uri }, 'deleting indexed record')\n const deleteQuery = this.db.db\n .deleteFrom('record')\n .where('uri', '=', uri.toString())\n const backlinkQuery = this.db.db\n .deleteFrom('backlink')\n .where('uri', '=', uri.toString())\n await Promise.all([deleteQuery.execute(), backlinkQuery.execute()])\n\n log.info({ uri }, 'deleted indexed record')\n }\n\n async removeBacklinksByUri(uri: AtUri) {\n await this.db.db\n .deleteFrom('backlink')\n .where('uri', '=', uri.toString())\n .execute()\n }\n\n async addBacklinks(backlinks: Backlink[]) {\n if (backlinks.length === 0) return\n await this.db.db\n .insertInto('backlink')\n .values(backlinks)\n .onConflict((oc) => oc.doNothing())\n .execute()\n }\n\n async updateRecordTakedownStatus(\n uri: AtUri,\n takedown: com.atproto.admin.defs.StatusAttr,\n ) {\n const takedownRef = takedown.applied\n ? (takedown.ref ?? new Date().toISOString())\n : null\n await this.db.db\n .updateTable('record')\n .set({ takedownRef })\n .where('uri', '=', uri.toString())\n .executeTakeFirst()\n }\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import type { DidString } from '@atproto/lex';
1
2
  import type { BlobStore } from '@atproto/repo';
2
3
  import type { SyncEvtData } from '../../repo/index.js';
3
4
  import { BlobReader } from '../blob/reader.js';
@@ -7,10 +8,11 @@ import { SqlRepoReader } from './sql-repo-reader.js';
7
8
  export declare class RepoReader {
8
9
  db: ActorDb;
9
10
  blobstore: BlobStore;
11
+ did: DidString;
10
12
  blob: BlobReader;
11
13
  record: RecordReader;
12
14
  storage: SqlRepoReader;
13
- constructor(db: ActorDb, blobstore: BlobStore);
15
+ constructor(db: ActorDb, blobstore: BlobStore, did: DidString);
14
16
  getSyncEventData(): Promise<SyncEvtData>;
15
17
  }
16
18
  //# sourceMappingURL=reader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../src/actor-store/repo/reader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEpD,qBAAa,UAAU;IAMZ,EAAE,EAAE,OAAO;IACX,SAAS,EAAE,SAAS;IAN7B,IAAI,EAAE,UAAU,CAAA;IAChB,MAAM,EAAE,YAAY,CAAA;IACpB,OAAO,EAAE,aAAa,CAAA;IAEtB,YACS,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,SAAS,EAK5B;IAEK,gBAAgB,IAAI,OAAO,CAAC,WAAW,CAAC,CAQ7C;CACF"}
1
+ {"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../../src/actor-store/repo/reader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEpD,qBAAa,UAAU;IAMZ,EAAE,EAAE,OAAO;IACX,SAAS,EAAE,SAAS;IACpB,GAAG,EAAE,SAAS;IAPvB,IAAI,EAAE,UAAU,CAAA;IAChB,MAAM,EAAE,YAAY,CAAA;IACpB,OAAO,EAAE,aAAa,CAAA;IAEtB,YACS,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,SAAS,EACpB,GAAG,EAAE,SAAS,EAKtB;IAEK,gBAAgB,IAAI,OAAO,CAAC,WAAW,CAAC,CAQ7C;CACF"}
@@ -2,11 +2,12 @@ import { BlobReader } from '../blob/reader.js';
2
2
  import { RecordReader } from '../record/reader.js';
3
3
  import { SqlRepoReader } from './sql-repo-reader.js';
4
4
  export class RepoReader {
5
- constructor(db, blobstore) {
5
+ constructor(db, blobstore, did) {
6
6
  this.db = db;
7
7
  this.blobstore = blobstore;
8
+ this.did = did;
8
9
  this.blob = new BlobReader(db, blobstore);
9
- this.record = new RecordReader(db);
10
+ this.record = new RecordReader(db, did);
10
11
  this.storage = new SqlRepoReader(db);
11
12
  }
12
13
  async getSyncEventData() {
@@ -1 +1 @@
1
- {"version":3,"file":"reader.js","sourceRoot":"","sources":["../../../src/actor-store/repo/reader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEpD,MAAM,OAAO,UAAU;IAKrB,YACS,EAAW,EACX,SAAoB;kBADpB,EAAE;yBACF,SAAS;QAEhB,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;QACzC,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,CAAC,CAAA;QAClC,IAAI,CAAC,OAAO,GAAG,IAAI,aAAa,CAAC,EAAE,CAAC,CAAA;IACtC,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAA;QACjD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;QAC3D,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,MAAM;SACP,CAAA;IACH,CAAC;CACF","sourcesContent":["import type { BlobStore } from '@atproto/repo'\nimport type { SyncEvtData } from '../../repo/index.js'\nimport { BlobReader } from '../blob/reader.js'\nimport type { ActorDb } from '../db/index.js'\nimport { RecordReader } from '../record/reader.js'\nimport { SqlRepoReader } from './sql-repo-reader.js'\n\nexport class RepoReader {\n blob: BlobReader\n record: RecordReader\n storage: SqlRepoReader\n\n constructor(\n public db: ActorDb,\n public blobstore: BlobStore,\n ) {\n this.blob = new BlobReader(db, blobstore)\n this.record = new RecordReader(db)\n this.storage = new SqlRepoReader(db)\n }\n\n async getSyncEventData(): Promise<SyncEvtData> {\n const root = await this.storage.getRootDetailed()\n const { blocks } = await this.storage.getBlocks([root.cid])\n return {\n cid: root.cid,\n rev: root.rev,\n blocks,\n }\n }\n}\n"]}
1
+ {"version":3,"file":"reader.js","sourceRoot":"","sources":["../../../src/actor-store/repo/reader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEpD,MAAM,OAAO,UAAU;IAKrB,YACS,EAAW,EACX,SAAoB,EACpB,GAAc;kBAFd,EAAE;yBACF,SAAS;mBACT,GAAG;QAEV,IAAI,CAAC,IAAI,GAAG,IAAI,UAAU,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;QACzC,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;QACvC,IAAI,CAAC,OAAO,GAAG,IAAI,aAAa,CAAC,EAAE,CAAC,CAAA;IACtC,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAA;QACjD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;QAC3D,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,MAAM;SACP,CAAA;IACH,CAAC;CACF","sourcesContent":["import type { DidString } from '@atproto/lex'\nimport type { BlobStore } from '@atproto/repo'\nimport type { SyncEvtData } from '../../repo/index.js'\nimport { BlobReader } from '../blob/reader.js'\nimport type { ActorDb } from '../db/index.js'\nimport { RecordReader } from '../record/reader.js'\nimport { SqlRepoReader } from './sql-repo-reader.js'\n\nexport class RepoReader {\n blob: BlobReader\n record: RecordReader\n storage: SqlRepoReader\n\n constructor(\n public db: ActorDb,\n public blobstore: BlobStore,\n public did: DidString,\n ) {\n this.blob = new BlobReader(db, blobstore)\n this.record = new RecordReader(db, did)\n this.storage = new SqlRepoReader(db)\n }\n\n async getSyncEventData(): Promise<SyncEvtData> {\n const root = await this.storage.getRootDetailed()\n const { blocks } = await this.storage.getBlocks([root.cid])\n return {\n cid: root.cid,\n rev: root.rev,\n blocks,\n }\n }\n}\n"]}