@atproto/pds 0.4.27 → 0.4.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/account-manager/helpers/account.d.ts +7 -0
  3. package/dist/account-manager/helpers/account.d.ts.map +1 -1
  4. package/dist/account-manager/helpers/account.js +9 -1
  5. package/dist/account-manager/helpers/account.js.map +1 -1
  6. package/dist/account-manager/index.d.ts +3 -1
  7. package/dist/account-manager/index.d.ts.map +1 -1
  8. package/dist/account-manager/index.js +22 -6
  9. package/dist/account-manager/index.js.map +1 -1
  10. package/dist/api/com/atproto/admin/deleteAccount.d.ts.map +1 -1
  11. package/dist/api/com/atproto/admin/deleteAccount.js +4 -2
  12. package/dist/api/com/atproto/admin/deleteAccount.js.map +1 -1
  13. package/dist/api/com/atproto/admin/updateAccountHandle.js +1 -1
  14. package/dist/api/com/atproto/admin/updateAccountHandle.js.map +1 -1
  15. package/dist/api/com/atproto/admin/updateSubjectStatus.d.ts.map +1 -1
  16. package/dist/api/com/atproto/admin/updateSubjectStatus.js +2 -0
  17. package/dist/api/com/atproto/admin/updateSubjectStatus.js.map +1 -1
  18. package/dist/api/com/atproto/identity/submitPlcOperation.d.ts.map +1 -1
  19. package/dist/api/com/atproto/identity/submitPlcOperation.js.map +1 -1
  20. package/dist/api/com/atproto/identity/updateHandle.js +1 -1
  21. package/dist/api/com/atproto/identity/updateHandle.js.map +1 -1
  22. package/dist/api/com/atproto/repo/describeRepo.d.ts.map +1 -1
  23. package/dist/api/com/atproto/repo/describeRepo.js +2 -4
  24. package/dist/api/com/atproto/repo/describeRepo.js.map +1 -1
  25. package/dist/api/com/atproto/server/activateAccount.d.ts.map +1 -1
  26. package/dist/api/com/atproto/server/activateAccount.js +2 -1
  27. package/dist/api/com/atproto/server/activateAccount.js.map +1 -1
  28. package/dist/api/com/atproto/server/createAccount.d.ts.map +1 -1
  29. package/dist/api/com/atproto/server/createAccount.js +4 -2
  30. package/dist/api/com/atproto/server/createAccount.js.map +1 -1
  31. package/dist/api/com/atproto/server/deactivateAccount.d.ts.map +1 -1
  32. package/dist/api/com/atproto/server/deactivateAccount.js +2 -0
  33. package/dist/api/com/atproto/server/deactivateAccount.js.map +1 -1
  34. package/dist/api/com/atproto/server/deleteAccount.d.ts.map +1 -1
  35. package/dist/api/com/atproto/server/deleteAccount.js +4 -3
  36. package/dist/api/com/atproto/server/deleteAccount.js.map +1 -1
  37. package/dist/api/com/atproto/server/util.d.ts +1 -0
  38. package/dist/api/com/atproto/server/util.d.ts.map +1 -1
  39. package/dist/api/com/atproto/server/util.js +9 -6
  40. package/dist/api/com/atproto/server/util.js.map +1 -1
  41. package/dist/api/com/atproto/sync/deprecated/getCheckout.d.ts.map +1 -1
  42. package/dist/api/com/atproto/sync/deprecated/getCheckout.js +2 -8
  43. package/dist/api/com/atproto/sync/deprecated/getCheckout.js.map +1 -1
  44. package/dist/api/com/atproto/sync/deprecated/getHead.d.ts.map +1 -1
  45. package/dist/api/com/atproto/sync/deprecated/getHead.js +2 -7
  46. package/dist/api/com/atproto/sync/deprecated/getHead.js.map +1 -1
  47. package/dist/api/com/atproto/sync/getBlob.d.ts.map +1 -1
  48. package/dist/api/com/atproto/sync/getBlob.js +3 -6
  49. package/dist/api/com/atproto/sync/getBlob.js.map +1 -1
  50. package/dist/api/com/atproto/sync/getBlocks.d.ts.map +1 -1
  51. package/dist/api/com/atproto/sync/getBlocks.js +2 -7
  52. package/dist/api/com/atproto/sync/getBlocks.js.map +1 -1
  53. package/dist/api/com/atproto/sync/getLatestCommit.d.ts.map +1 -1
  54. package/dist/api/com/atproto/sync/getLatestCommit.js +2 -7
  55. package/dist/api/com/atproto/sync/getLatestCommit.js.map +1 -1
  56. package/dist/api/com/atproto/sync/getRecord.d.ts.map +1 -1
  57. package/dist/api/com/atproto/sync/getRecord.js +2 -7
  58. package/dist/api/com/atproto/sync/getRecord.js.map +1 -1
  59. package/dist/api/com/atproto/sync/getRepo.d.ts.map +1 -1
  60. package/dist/api/com/atproto/sync/getRepo.js +2 -7
  61. package/dist/api/com/atproto/sync/getRepo.js.map +1 -1
  62. package/dist/api/com/atproto/sync/getRepoStatus.d.ts +4 -0
  63. package/dist/api/com/atproto/sync/getRepoStatus.d.ts.map +1 -0
  64. package/dist/api/com/atproto/sync/getRepoStatus.js +28 -0
  65. package/dist/api/com/atproto/sync/getRepoStatus.js.map +1 -0
  66. package/dist/api/com/atproto/sync/index.d.ts.map +1 -1
  67. package/dist/api/com/atproto/sync/index.js +2 -0
  68. package/dist/api/com/atproto/sync/index.js.map +1 -1
  69. package/dist/api/com/atproto/sync/listBlobs.d.ts.map +1 -1
  70. package/dist/api/com/atproto/sync/listBlobs.js +2 -8
  71. package/dist/api/com/atproto/sync/listBlobs.js.map +1 -1
  72. package/dist/api/com/atproto/sync/listRepos.d.ts.map +1 -1
  73. package/dist/api/com/atproto/sync/listRepos.js +13 -8
  74. package/dist/api/com/atproto/sync/listRepos.js.map +1 -1
  75. package/dist/api/com/atproto/sync/subscribeRepos.d.ts.map +1 -1
  76. package/dist/api/com/atproto/sync/subscribeRepos.js +8 -0
  77. package/dist/api/com/atproto/sync/subscribeRepos.js.map +1 -1
  78. package/dist/api/com/atproto/sync/util.d.ts +11 -0
  79. package/dist/api/com/atproto/sync/util.d.ts.map +1 -0
  80. package/dist/api/com/atproto/sync/util.js +41 -0
  81. package/dist/api/com/atproto/sync/util.js.map +1 -0
  82. package/dist/index.d.ts +1 -0
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +4 -2
  85. package/dist/index.js.map +1 -1
  86. package/dist/lexicon/index.d.ts +2 -0
  87. package/dist/lexicon/index.d.ts.map +1 -1
  88. package/dist/lexicon/index.js +4 -0
  89. package/dist/lexicon/index.js.map +1 -1
  90. package/dist/lexicon/lexicons.d.ts +105 -0
  91. package/dist/lexicon/lexicons.d.ts.map +1 -1
  92. package/dist/lexicon/lexicons.js +185 -4
  93. package/dist/lexicon/lexicons.js.map +1 -1
  94. package/dist/lexicon/types/chat/bsky/convo/defs.d.ts +1 -1
  95. package/dist/lexicon/types/com/atproto/sync/getBlob.d.ts +1 -0
  96. package/dist/lexicon/types/com/atproto/sync/getBlob.d.ts.map +1 -1
  97. package/dist/lexicon/types/com/atproto/sync/getBlocks.d.ts +1 -0
  98. package/dist/lexicon/types/com/atproto/sync/getBlocks.d.ts.map +1 -1
  99. package/dist/lexicon/types/com/atproto/sync/getLatestCommit.d.ts +1 -1
  100. package/dist/lexicon/types/com/atproto/sync/getLatestCommit.d.ts.map +1 -1
  101. package/dist/lexicon/types/com/atproto/sync/getRecord.d.ts +1 -0
  102. package/dist/lexicon/types/com/atproto/sync/getRecord.d.ts.map +1 -1
  103. package/dist/lexicon/types/com/atproto/sync/getRepo.d.ts +1 -0
  104. package/dist/lexicon/types/com/atproto/sync/getRepo.d.ts.map +1 -1
  105. package/dist/lexicon/types/com/atproto/sync/getRepoStatus.d.ts +42 -0
  106. package/dist/lexicon/types/com/atproto/sync/getRepoStatus.d.ts.map +1 -0
  107. package/dist/lexicon/types/com/atproto/sync/getRepoStatus.js +3 -0
  108. package/dist/lexicon/types/com/atproto/sync/getRepoStatus.js.map +1 -0
  109. package/dist/lexicon/types/com/atproto/sync/listBlobs.d.ts +1 -0
  110. package/dist/lexicon/types/com/atproto/sync/listBlobs.d.ts.map +1 -1
  111. package/dist/lexicon/types/com/atproto/sync/listRepos.d.ts +3 -0
  112. package/dist/lexicon/types/com/atproto/sync/listRepos.d.ts.map +1 -1
  113. package/dist/lexicon/types/com/atproto/sync/listRepos.js.map +1 -1
  114. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.d.ts +19 -4
  115. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.d.ts.map +1 -1
  116. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.js +11 -1
  117. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.js.map +1 -1
  118. package/dist/scripts/index.d.ts +4 -0
  119. package/dist/scripts/index.d.ts.map +1 -0
  120. package/dist/scripts/index.js +8 -0
  121. package/dist/scripts/index.js.map +1 -0
  122. package/dist/scripts/rebuild-repo.d.ts +3 -0
  123. package/dist/scripts/rebuild-repo.d.ts.map +1 -0
  124. package/dist/scripts/rebuild-repo.js +121 -0
  125. package/dist/scripts/rebuild-repo.js.map +1 -0
  126. package/dist/sequencer/db/schema.d.ts +1 -1
  127. package/dist/sequencer/db/schema.d.ts.map +1 -1
  128. package/dist/sequencer/events.d.ts +27 -2
  129. package/dist/sequencer/events.d.ts.map +1 -1
  130. package/dist/sequencer/events.js +35 -2
  131. package/dist/sequencer/events.js.map +1 -1
  132. package/dist/sequencer/sequencer.d.ts +8 -6
  133. package/dist/sequencer/sequencer.d.ts.map +1 -1
  134. package/dist/sequencer/sequencer.js +22 -9
  135. package/dist/sequencer/sequencer.js.map +1 -1
  136. package/package.json +4 -4
  137. package/src/account-manager/helpers/account.ts +8 -0
  138. package/src/account-manager/index.ts +19 -6
  139. package/src/api/com/atproto/admin/deleteAccount.ts +7 -2
  140. package/src/api/com/atproto/admin/updateAccountHandle.ts +1 -1
  141. package/src/api/com/atproto/admin/updateSubjectStatus.ts +2 -0
  142. package/src/api/com/atproto/identity/submitPlcOperation.ts +1 -0
  143. package/src/api/com/atproto/identity/updateHandle.ts +1 -1
  144. package/src/api/com/atproto/repo/describeRepo.ts +2 -4
  145. package/src/api/com/atproto/server/activateAccount.ts +2 -1
  146. package/src/api/com/atproto/server/createAccount.ts +6 -3
  147. package/src/api/com/atproto/server/deactivateAccount.ts +2 -0
  148. package/src/api/com/atproto/server/deleteAccount.ts +7 -3
  149. package/src/api/com/atproto/server/util.ts +12 -5
  150. package/src/api/com/atproto/sync/deprecated/getCheckout.ts +6 -8
  151. package/src/api/com/atproto/sync/deprecated/getHead.ts +7 -10
  152. package/src/api/com/atproto/sync/getBlob.ts +8 -6
  153. package/src/api/com/atproto/sync/getBlocks.ts +6 -7
  154. package/src/api/com/atproto/sync/getLatestCommit.ts +7 -10
  155. package/src/api/com/atproto/sync/getRecord.ts +7 -7
  156. package/src/api/com/atproto/sync/getRepo.ts +6 -7
  157. package/src/api/com/atproto/sync/getRepoStatus.ts +31 -0
  158. package/src/api/com/atproto/sync/index.ts +2 -0
  159. package/src/api/com/atproto/sync/listBlobs.ts +6 -8
  160. package/src/api/com/atproto/sync/listRepos.ts +13 -8
  161. package/src/api/com/atproto/sync/subscribeRepos.ts +7 -0
  162. package/src/api/com/atproto/sync/util.ts +59 -0
  163. package/src/index.ts +3 -2
  164. package/src/lexicon/index.ts +12 -0
  165. package/src/lexicon/lexicons.ts +193 -7
  166. package/src/lexicon/types/chat/bsky/convo/defs.ts +1 -1
  167. package/src/lexicon/types/com/atproto/sync/getBlob.ts +6 -0
  168. package/src/lexicon/types/com/atproto/sync/getBlocks.ts +6 -0
  169. package/src/lexicon/types/com/atproto/sync/getLatestCommit.ts +1 -1
  170. package/src/lexicon/types/com/atproto/sync/getRecord.ts +6 -0
  171. package/src/lexicon/types/com/atproto/sync/getRepo.ts +1 -0
  172. package/src/lexicon/types/com/atproto/sync/getRepoStatus.ts +52 -0
  173. package/src/lexicon/types/com/atproto/sync/listBlobs.ts +1 -0
  174. package/src/lexicon/types/com/atproto/sync/listRepos.ts +3 -0
  175. package/src/lexicon/types/com/atproto/sync/subscribeRepos.ts +30 -3
  176. package/src/scripts/index.ts +5 -0
  177. package/src/scripts/rebuild-repo.ts +143 -0
  178. package/src/sequencer/db/schema.ts +1 -0
  179. package/src/sequencer/events.ts +47 -0
  180. package/src/sequencer/sequencer.ts +35 -14
  181. package/tests/account-deactivation.test.ts +36 -10
  182. package/tests/account-deletion.test.ts +10 -2
  183. package/tests/moderation.test.ts +2 -2
  184. package/tests/proxied/notif.test.ts +1 -0
  185. package/tests/sequencer.test.ts +2 -2
  186. package/tests/sync/list.test.ts +1 -0
  187. package/tests/sync/subscribe-repos.test.ts +224 -40
  188. package/tests/sync/sync.test.ts +48 -4
@@ -1,22 +1,19 @@
1
1
  import { InvalidRequestError } from '@atproto/xrpc-server'
2
2
  import { Server } from '../../../../lexicon'
3
3
  import AppContext from '../../../../context'
4
+ import { assertRepoAvailability } from './util'
4
5
 
5
6
  export default function (server: Server, ctx: AppContext) {
6
7
  server.com.atproto.sync.getLatestCommit({
7
8
  auth: ctx.authVerifier.optionalAccessOrAdminToken,
8
9
  handler: async ({ params, auth }) => {
9
10
  const { did } = params
10
- // takedown check for anyone other than an admin or the user
11
- if (!ctx.authVerifier.isUserOrAdmin(auth, did)) {
12
- const available = await ctx.accountManager.isRepoAvailable(did)
13
- if (!available) {
14
- throw new InvalidRequestError(
15
- `Could not find root for DID: ${did}`,
16
- 'RepoNotFound',
17
- )
18
- }
19
- }
11
+ await assertRepoAvailability(
12
+ ctx,
13
+ did,
14
+ ctx.authVerifier.isUserOrAdmin(auth, did),
15
+ )
16
+
20
17
  const root = await ctx.actorStore.read(did, (store) =>
21
18
  store.repo.storage.getRootDetailed(),
22
19
  )
@@ -6,19 +6,19 @@ import { Server } from '../../../../lexicon'
6
6
  import AppContext from '../../../../context'
7
7
  import { byteIterableToStream } from '@atproto/common'
8
8
  import { SqlRepoReader } from '../../../../actor-store/repo/sql-repo-reader'
9
+ import { assertRepoAvailability } from './util'
9
10
 
10
11
  export default function (server: Server, ctx: AppContext) {
11
12
  server.com.atproto.sync.getRecord({
12
13
  auth: ctx.authVerifier.optionalAccessOrAdminToken,
13
14
  handler: async ({ params, auth }) => {
14
15
  const { did, collection, rkey } = params
15
- // takedown check for anyone other than an admin or the user
16
- if (!ctx.authVerifier.isUserOrAdmin(auth, did)) {
17
- const available = await ctx.accountManager.isRepoAvailable(did)
18
- if (!available) {
19
- throw new InvalidRequestError(`Could not find repo for DID: ${did}`)
20
- }
21
- }
16
+ await assertRepoAvailability(
17
+ ctx,
18
+ did,
19
+ ctx.authVerifier.isUserOrAdmin(auth, did),
20
+ )
21
+
22
22
  // must open up the db outside of store interface so that we can close the file handle after finished streaming
23
23
  const actorDb = await ctx.actorStore.openDb(did)
24
24
 
@@ -6,19 +6,18 @@ import {
6
6
  RepoRootNotFoundError,
7
7
  SqlRepoReader,
8
8
  } from '../../../../actor-store/repo/sql-repo-reader'
9
+ import { assertRepoAvailability } from './util'
9
10
 
10
11
  export default function (server: Server, ctx: AppContext) {
11
12
  server.com.atproto.sync.getRepo({
12
13
  auth: ctx.authVerifier.optionalAccessOrAdminToken,
13
14
  handler: async ({ params, auth }) => {
14
15
  const { did, since } = params
15
- // takedown check for anyone other than an admin or the user
16
- if (!ctx.authVerifier.isUserOrAdmin(auth, did)) {
17
- const available = await ctx.accountManager.isRepoAvailable(did)
18
- if (!available) {
19
- throw new InvalidRequestError(`Could not find repo for DID: ${did}`)
20
- }
21
- }
16
+ await assertRepoAvailability(
17
+ ctx,
18
+ did,
19
+ ctx.authVerifier.isUserOrAdmin(auth, did),
20
+ )
22
21
 
23
22
  const carStream = await getCarStream(ctx, did, since)
24
23
 
@@ -0,0 +1,31 @@
1
+ import { Server } from '../../../../lexicon'
2
+ import AppContext from '../../../../context'
3
+ import { assertRepoAvailability, formatAccountStatus } from './util'
4
+
5
+ export default function (server: Server, ctx: AppContext) {
6
+ server.com.atproto.sync.getRepoStatus({
7
+ handler: async ({ params }) => {
8
+ const { did } = params
9
+ const account = await assertRepoAvailability(ctx, did, true)
10
+ const { active, status } = formatAccountStatus(account)
11
+
12
+ let rev: string | undefined = undefined
13
+ if (active) {
14
+ const root = await ctx.actorStore.read(did, (store) =>
15
+ store.repo.storage.getRootDetailed(),
16
+ )
17
+ rev = root.rev
18
+ }
19
+
20
+ return {
21
+ encoding: 'application/json',
22
+ body: {
23
+ did,
24
+ active,
25
+ status,
26
+ rev,
27
+ },
28
+ }
29
+ },
30
+ })
31
+ }
@@ -3,6 +3,7 @@ import AppContext from '../../../../context'
3
3
  import getBlob from './getBlob'
4
4
  import getBlocks from './getBlocks'
5
5
  import getLatestCommit from './getLatestCommit'
6
+ import getRepoStatus from './getRepoStatus'
6
7
  import getRecord from './getRecord'
7
8
  import getRepo from './getRepo'
8
9
  import subscribeRepos from './subscribeRepos'
@@ -15,6 +16,7 @@ export default function (server: Server, ctx: AppContext) {
15
16
  getBlob(server, ctx)
16
17
  getBlocks(server, ctx)
17
18
  getLatestCommit(server, ctx)
19
+ getRepoStatus(server, ctx)
18
20
  getRecord(server, ctx)
19
21
  getRepo(server, ctx)
20
22
  subscribeRepos(server, ctx)
@@ -1,19 +1,17 @@
1
- import { InvalidRequestError } from '@atproto/xrpc-server'
2
1
  import { Server } from '../../../../lexicon'
3
2
  import AppContext from '../../../../context'
3
+ import { assertRepoAvailability } from './util'
4
4
 
5
5
  export default function (server: Server, ctx: AppContext) {
6
6
  server.com.atproto.sync.listBlobs({
7
7
  auth: ctx.authVerifier.optionalAccessOrAdminToken,
8
8
  handler: async ({ params, auth }) => {
9
9
  const { did, since, limit, cursor } = params
10
- // takedown check for anyone other than an admin or the user
11
- if (!ctx.authVerifier.isUserOrAdmin(auth, did)) {
12
- const available = await ctx.accountManager.isRepoAvailable(did)
13
- if (!available) {
14
- throw new InvalidRequestError(`Could not find root for DID: ${did}`)
15
- }
16
- }
10
+ await assertRepoAvailability(
11
+ ctx,
12
+ did,
13
+ ctx.authVerifier.isUserOrAdmin(auth, did),
14
+ )
17
15
 
18
16
  const blobCids = await ctx.actorStore.read(did, (store) =>
19
17
  store.repo.blob.listBlobs({ since, limit, cursor }),
@@ -2,7 +2,7 @@ import { InvalidRequestError } from '@atproto/xrpc-server'
2
2
  import { Server } from '../../../../lexicon'
3
3
  import AppContext from '../../../../context'
4
4
  import { Cursor, GenericKeyset, paginate } from '../../../../db/pagination'
5
- import { notSoftDeletedClause } from '../../../../db/util'
5
+ import { formatAccountStatus } from './util'
6
6
 
7
7
  export default function (server: Server, ctx: AppContext) {
8
8
  server.com.atproto.sync.listRepos(async ({ params }) => {
@@ -12,13 +12,13 @@ export default function (server: Server, ctx: AppContext) {
12
12
  let builder = db.db
13
13
  .selectFrom('actor')
14
14
  .innerJoin('repo_root', 'repo_root.did', 'actor.did')
15
- .where(notSoftDeletedClause(ref('actor')))
16
- .where('actor.deactivatedAt', 'is', null)
17
15
  .select([
18
16
  'actor.did as did',
19
17
  'repo_root.cid as head',
20
18
  'repo_root.rev as rev',
21
19
  'actor.createdAt as createdAt',
20
+ 'actor.deactivatedAt as deactivatedAt',
21
+ 'actor.takedownRef as takedownRef',
22
22
  ])
23
23
  const keyset = new TimeDidKeyset(ref('actor.createdAt'), ref('actor.did'))
24
24
  builder = paginate(builder, {
@@ -29,11 +29,16 @@ export default function (server: Server, ctx: AppContext) {
29
29
  tryIndex: true,
30
30
  })
31
31
  const res = await builder.execute()
32
- const repos = res.map((row) => ({
33
- did: row.did,
34
- head: row.head,
35
- rev: row.rev ?? '',
36
- }))
32
+ const repos = res.map((row) => {
33
+ const { active, status } = formatAccountStatus(row)
34
+ return {
35
+ did: row.did,
36
+ head: row.head,
37
+ rev: row.rev ?? '',
38
+ active,
39
+ status,
40
+ }
41
+ })
37
42
  return {
38
43
  encoding: 'application/json',
39
44
  body: {
@@ -59,6 +59,13 @@ export default function (server: Server, ctx: AppContext) {
59
59
  time: evt.time,
60
60
  ...evt.evt,
61
61
  }
62
+ } else if (evt.type === 'account') {
63
+ yield {
64
+ $type: '#account',
65
+ seq: evt.seq,
66
+ time: evt.time,
67
+ ...evt.evt,
68
+ }
62
69
  } else if (evt.type === 'tombstone') {
63
70
  yield {
64
71
  $type: '#tombstone',
@@ -0,0 +1,59 @@
1
+ import { InvalidRequestError } from '@atproto/xrpc-server'
2
+ import {
3
+ AccountStatus,
4
+ ActorAccount,
5
+ } from '../../../../account-manager/helpers/account'
6
+ import AppContext from '../../../../context'
7
+
8
+ export const assertRepoAvailability = async (
9
+ ctx: AppContext,
10
+ did: string,
11
+ isAdminOrSelf: boolean,
12
+ ): Promise<ActorAccount> => {
13
+ const account = await ctx.accountManager.getAccount(did, {
14
+ includeDeactivated: true,
15
+ includeTakenDown: true,
16
+ })
17
+ if (!account) {
18
+ throw new InvalidRequestError(
19
+ `Could not find repo for DID: ${did}`,
20
+ 'RepoNotFound',
21
+ )
22
+ }
23
+ if (isAdminOrSelf) {
24
+ return account
25
+ }
26
+ if (account.takedownRef) {
27
+ throw new InvalidRequestError(
28
+ `Repo has been takendown: ${did}`,
29
+ 'RepoTakendown',
30
+ )
31
+ }
32
+ if (account.deactivatedAt) {
33
+ throw new InvalidRequestError(
34
+ `Repo has been deactivated: ${did}`,
35
+ 'RepoDeactivated',
36
+ )
37
+ }
38
+ return account
39
+ }
40
+
41
+ export const formatAccountStatus = (account: {
42
+ takedownRef: string | null
43
+ deactivatedAt: string | null
44
+ }): {
45
+ active: boolean
46
+ status?: AccountStatus
47
+ } => {
48
+ let status: AccountStatus | undefined = undefined
49
+ if (account.takedownRef) {
50
+ status = AccountStatus.Takendown
51
+ } else if (account.deactivatedAt) {
52
+ status = AccountStatus.Deactivated
53
+ }
54
+ const active = !status
55
+ return {
56
+ active,
57
+ status,
58
+ }
59
+ }
package/src/index.ts CHANGED
@@ -9,7 +9,7 @@ import cors from 'cors'
9
9
  import http from 'http'
10
10
  import events from 'events'
11
11
  import { Options as XrpcServerOptions } from '@atproto/xrpc-server'
12
- import { DAY, HOUR, MINUTE } from '@atproto/common'
12
+ import { DAY, HOUR, MINUTE, SECOND } from '@atproto/common'
13
13
  import API from './api'
14
14
  import * as basicRoutes from './basic-routes'
15
15
  import * as wellKnown from './well-known'
@@ -33,6 +33,7 @@ export { createServer as createLexiconServer } from './lexicon'
33
33
  export * as sequencer from './sequencer'
34
34
  export { type PreparedWrite } from './repo'
35
35
  export * as repoPrepare from './repo/prepare'
36
+ export { scripts } from './scripts'
36
37
 
37
38
  export class PDS {
38
39
  public ctx: AppContext
@@ -54,7 +55,7 @@ export class PDS {
54
55
  ): Promise<PDS> {
55
56
  const app = express()
56
57
  app.set('trust proxy', true)
57
- app.use(cors())
58
+ app.use(cors({ maxAge: DAY / SECOND }))
58
59
  app.use(loggerMiddleware)
59
60
  app.use(compression())
60
61
 
@@ -73,6 +73,7 @@ import * as ComAtprotoSyncGetHead from './types/com/atproto/sync/getHead'
73
73
  import * as ComAtprotoSyncGetLatestCommit from './types/com/atproto/sync/getLatestCommit'
74
74
  import * as ComAtprotoSyncGetRecord from './types/com/atproto/sync/getRecord'
75
75
  import * as ComAtprotoSyncGetRepo from './types/com/atproto/sync/getRepo'
76
+ import * as ComAtprotoSyncGetRepoStatus from './types/com/atproto/sync/getRepoStatus'
76
77
  import * as ComAtprotoSyncListBlobs from './types/com/atproto/sync/listBlobs'
77
78
  import * as ComAtprotoSyncListRepos from './types/com/atproto/sync/listRepos'
78
79
  import * as ComAtprotoSyncNotifyOfUpdate from './types/com/atproto/sync/notifyOfUpdate'
@@ -1009,6 +1010,17 @@ export class ComAtprotoSyncNS {
1009
1010
  return this._server.xrpc.method(nsid, cfg)
1010
1011
  }
1011
1012
 
1013
+ getRepoStatus<AV extends AuthVerifier>(
1014
+ cfg: ConfigOf<
1015
+ AV,
1016
+ ComAtprotoSyncGetRepoStatus.Handler<ExtractAuth<AV>>,
1017
+ ComAtprotoSyncGetRepoStatus.HandlerReqCtx<ExtractAuth<AV>>
1018
+ >,
1019
+ ) {
1020
+ const nsid = 'com.atproto.sync.getRepoStatus' // @ts-ignore
1021
+ return this._server.xrpc.method(nsid, cfg)
1022
+ }
1023
+
1012
1024
  listBlobs<AV extends AuthVerifier>(
1013
1025
  cfg: ConfigOf<
1014
1026
  AV,
@@ -2912,6 +2912,23 @@ export const schemaDict = {
2912
2912
  output: {
2913
2913
  encoding: '*/*',
2914
2914
  },
2915
+ errors: [
2916
+ {
2917
+ name: 'BlobNotFound',
2918
+ },
2919
+ {
2920
+ name: 'RepoNotFound',
2921
+ },
2922
+ {
2923
+ name: 'RepoTakendown',
2924
+ },
2925
+ {
2926
+ name: 'RepoSuspended',
2927
+ },
2928
+ {
2929
+ name: 'RepoDeactivated',
2930
+ },
2931
+ ],
2915
2932
  },
2916
2933
  },
2917
2934
  },
@@ -2944,6 +2961,23 @@ export const schemaDict = {
2944
2961
  output: {
2945
2962
  encoding: 'application/vnd.ipld.car',
2946
2963
  },
2964
+ errors: [
2965
+ {
2966
+ name: 'BlockNotFound',
2967
+ },
2968
+ {
2969
+ name: 'RepoNotFound',
2970
+ },
2971
+ {
2972
+ name: 'RepoTakendown',
2973
+ },
2974
+ {
2975
+ name: 'RepoSuspended',
2976
+ },
2977
+ {
2978
+ name: 'RepoDeactivated',
2979
+ },
2980
+ ],
2947
2981
  },
2948
2982
  },
2949
2983
  },
@@ -3050,6 +3084,15 @@ export const schemaDict = {
3050
3084
  {
3051
3085
  name: 'RepoNotFound',
3052
3086
  },
3087
+ {
3088
+ name: 'RepoTakendown',
3089
+ },
3090
+ {
3091
+ name: 'RepoSuspended',
3092
+ },
3093
+ {
3094
+ name: 'RepoDeactivated',
3095
+ },
3053
3096
  ],
3054
3097
  },
3055
3098
  },
@@ -3090,6 +3133,23 @@ export const schemaDict = {
3090
3133
  output: {
3091
3134
  encoding: 'application/vnd.ipld.car',
3092
3135
  },
3136
+ errors: [
3137
+ {
3138
+ name: 'RecordNotFound',
3139
+ },
3140
+ {
3141
+ name: 'RepoNotFound',
3142
+ },
3143
+ {
3144
+ name: 'RepoTakendown',
3145
+ },
3146
+ {
3147
+ name: 'RepoSuspended',
3148
+ },
3149
+ {
3150
+ name: 'RepoDeactivated',
3151
+ },
3152
+ ],
3093
3153
  },
3094
3154
  },
3095
3155
  },
@@ -3120,6 +3180,74 @@ export const schemaDict = {
3120
3180
  output: {
3121
3181
  encoding: 'application/vnd.ipld.car',
3122
3182
  },
3183
+ errors: [
3184
+ {
3185
+ name: 'RepoNotFound',
3186
+ },
3187
+ {
3188
+ name: 'RepoTakendown',
3189
+ },
3190
+ {
3191
+ name: 'RepoSuspended',
3192
+ },
3193
+ {
3194
+ name: 'RepoDeactivated',
3195
+ },
3196
+ ],
3197
+ },
3198
+ },
3199
+ },
3200
+ ComAtprotoSyncGetRepoStatus: {
3201
+ lexicon: 1,
3202
+ id: 'com.atproto.sync.getRepoStatus',
3203
+ defs: {
3204
+ main: {
3205
+ type: 'query',
3206
+ description:
3207
+ 'Get the hosting status for a repository, on this server. Expected to be implemented by PDS and Relay.',
3208
+ parameters: {
3209
+ type: 'params',
3210
+ required: ['did'],
3211
+ properties: {
3212
+ did: {
3213
+ type: 'string',
3214
+ format: 'did',
3215
+ description: 'The DID of the repo.',
3216
+ },
3217
+ },
3218
+ },
3219
+ output: {
3220
+ encoding: 'application/json',
3221
+ schema: {
3222
+ type: 'object',
3223
+ required: ['did', 'active'],
3224
+ properties: {
3225
+ did: {
3226
+ type: 'string',
3227
+ format: 'did',
3228
+ },
3229
+ active: {
3230
+ type: 'boolean',
3231
+ },
3232
+ status: {
3233
+ type: 'string',
3234
+ description:
3235
+ 'If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.',
3236
+ knownValues: ['takendown', 'suspended', 'deactivated'],
3237
+ },
3238
+ rev: {
3239
+ type: 'string',
3240
+ description:
3241
+ 'Optional field, the current rev of the repo, if active=true',
3242
+ },
3243
+ },
3244
+ },
3245
+ },
3246
+ errors: [
3247
+ {
3248
+ name: 'RepoNotFound',
3249
+ },
3250
+ ],
3123
3251
  },
3124
3252
  },
3125
3253
  },
@@ -3174,6 +3302,20 @@ export const schemaDict = {
3174
3302
  },
3175
3303
  },
3176
3304
  },
3305
+ errors: [
3306
+ {
3307
+ name: 'RepoNotFound',
3308
+ },
3309
+ {
3310
+ name: 'RepoTakendown',
3311
+ },
3312
+ {
3313
+ name: 'RepoSuspended',
3314
+ },
3315
+ {
3316
+ name: 'RepoDeactivated',
3317
+ },
3318
+ ],
3177
3319
  },
3178
3320
  },
3179
3321
  },
@@ -3235,6 +3377,15 @@ export const schemaDict = {
3235
3377
  rev: {
3236
3378
  type: 'string',
3237
3379
  },
3380
+ active: {
3381
+ type: 'boolean',
3382
+ },
3383
+ status: {
3384
+ type: 'string',
3385
+ description:
3386
+ 'If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.',
3387
+ knownValues: ['takendown', 'suspended', 'deactivated'],
3388
+ },
3238
3389
  },
3239
3390
  },
3240
3391
  },
@@ -3312,6 +3463,7 @@ export const schemaDict = {
3312
3463
  refs: [
3313
3464
  'lex:com.atproto.sync.subscribeRepos#commit',
3314
3465
  'lex:com.atproto.sync.subscribeRepos#identity',
3466
+ 'lex:com.atproto.sync.subscribeRepos#account',
3315
3467
  'lex:com.atproto.sync.subscribeRepos#handle',
3316
3468
  'lex:com.atproto.sync.subscribeRepos#migrate',
3317
3469
  'lex:com.atproto.sync.subscribeRepos#tombstone',
@@ -3435,12 +3587,47 @@ export const schemaDict = {
3435
3587
  type: 'string',
3436
3588
  format: 'datetime',
3437
3589
  },
3590
+ handle: {
3591
+ type: 'string',
3592
+ format: 'handle',
3593
+ description:
3594
+ "The current handle for the account, or 'handle.invalid' if validation fails. This field is optional, might have been validated or passed-through from an upstream source. Semantics and behaviors for PDS vs Relay may evolve in the future; see atproto specs for more details.",
3595
+ },
3438
3596
  },
3439
3597
  },
3440
- handle: {
3598
+ account: {
3441
3599
  type: 'object',
3442
3600
  description:
3443
- "Represents an update of the account's handle, or transition to/from invalid state. NOTE: Will be deprecated in favor of #identity.",
3601
+ "Represents a change to an account's status on a host (eg, PDS or Relay). The semantics of this event are that the status is at the host which emitted the event, not necessarily that at the currently active PDS. Eg, a Relay takedown would emit a takedown with active=false, even if the PDS is still active.",
3602
+ required: ['seq', 'did', 'time', 'active'],
3603
+ properties: {
3604
+ seq: {
3605
+ type: 'integer',
3606
+ },
3607
+ did: {
3608
+ type: 'string',
3609
+ format: 'did',
3610
+ },
3611
+ time: {
3612
+ type: 'string',
3613
+ format: 'datetime',
3614
+ },
3615
+ active: {
3616
+ type: 'boolean',
3617
+ description:
3618
+ 'Indicates that the account has a repository which can be fetched from the host that emitted this event.',
3619
+ },
3620
+ status: {
3621
+ type: 'string',
3622
+ description:
3623
+ 'If active=false, this optional field indicates a reason for why the account is not active.',
3624
+ knownValues: ['takendown', 'suspended', 'deleted', 'deactivated'],
3625
+ },
3626
+ },
3627
+ },
3628
+ handle: {
3629
+ type: 'object',
3630
+ description: 'DEPRECATED -- Use #identity event instead',
3444
3631
  required: ['seq', 'did', 'handle', 'time'],
3445
3632
  properties: {
3446
3633
  seq: {
@@ -3462,8 +3649,7 @@ export const schemaDict = {
3462
3649
  },
3463
3650
  migrate: {
3464
3651
  type: 'object',
3465
- description:
3466
- 'Represents an account moving from one PDS instance to another. NOTE: not implemented; account migration uses #identity instead',
3652
+ description: 'DEPRECATED -- Use #account event instead',
3467
3653
  required: ['seq', 'did', 'migrateTo', 'time'],
3468
3654
  nullable: ['migrateTo'],
3469
3655
  properties: {
@@ -3485,8 +3671,7 @@ export const schemaDict = {
3485
3671
  },
3486
3672
  tombstone: {
3487
3673
  type: 'object',
3488
- description:
3489
- 'Indicates that an account has been deleted. NOTE: may be deprecated in favor of #identity or a future #account event',
3674
+ description: 'DEPRECATED -- Use #account event instead',
3490
3675
  required: ['seq', 'did', 'time'],
3491
3676
  properties: {
3492
3677
  seq: {
@@ -8379,7 +8564,7 @@ export const schemaDict = {
8379
8564
  },
8380
8565
  embed: {
8381
8566
  type: 'union',
8382
- refs: ['lex:app.bsky.embed.record'],
8567
+ refs: ['lex:app.bsky.embed.record#view'],
8383
8568
  },
8384
8569
  sender: {
8385
8570
  type: 'ref',
@@ -10624,6 +10809,7 @@ export const ids = {
10624
10809
  ComAtprotoSyncGetLatestCommit: 'com.atproto.sync.getLatestCommit',
10625
10810
  ComAtprotoSyncGetRecord: 'com.atproto.sync.getRecord',
10626
10811
  ComAtprotoSyncGetRepo: 'com.atproto.sync.getRepo',
10812
+ ComAtprotoSyncGetRepoStatus: 'com.atproto.sync.getRepoStatus',
10627
10813
  ComAtprotoSyncListBlobs: 'com.atproto.sync.listBlobs',
10628
10814
  ComAtprotoSyncListRepos: 'com.atproto.sync.listRepos',
10629
10815
  ComAtprotoSyncNotifyOfUpdate: 'com.atproto.sync.notifyOfUpdate',
@@ -54,7 +54,7 @@ export interface MessageView {
54
54
  text: string
55
55
  /** Annotations of text (mentions, URLs, hashtags, etc) */
56
56
  facets?: AppBskyRichtextFacet.Main[]
57
- embed?: AppBskyEmbedRecord.Main | { $type: string; [k: string]: unknown }
57
+ embed?: AppBskyEmbedRecord.View | { $type: string; [k: string]: unknown }
58
58
  sender: MessageViewSender
59
59
  sentAt: string
60
60
  [k: string]: unknown
@@ -28,6 +28,12 @@ export interface HandlerSuccess {
28
28
  export interface HandlerError {
29
29
  status: number
30
30
  message?: string
31
+ error?:
32
+ | 'BlobNotFound'
33
+ | 'RepoNotFound'
34
+ | 'RepoTakendown'
35
+ | 'RepoSuspended'
36
+ | 'RepoDeactivated'
31
37
  }
32
38
 
33
39
  export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
@@ -27,6 +27,12 @@ export interface HandlerSuccess {
27
27
  export interface HandlerError {
28
28
  status: number
29
29
  message?: string
30
+ error?:
31
+ | 'BlockNotFound'
32
+ | 'RepoNotFound'
33
+ | 'RepoTakendown'
34
+ | 'RepoSuspended'
35
+ | 'RepoDeactivated'
30
36
  }
31
37
 
32
38
  export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
@@ -32,7 +32,7 @@ export interface HandlerSuccess {
32
32
  export interface HandlerError {
33
33
  status: number
34
34
  message?: string
35
- error?: 'RepoNotFound'
35
+ error?: 'RepoNotFound' | 'RepoTakendown' | 'RepoSuspended' | 'RepoDeactivated'
36
36
  }
37
37
 
38
38
  export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough