@atproto/pds 0.4.60 → 0.4.61

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 (93) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/account-manager/helpers/account.d.ts +1 -0
  3. package/dist/account-manager/helpers/account.d.ts.map +1 -1
  4. package/dist/account-manager/helpers/account.js +15 -1
  5. package/dist/account-manager/helpers/account.js.map +1 -1
  6. package/dist/account-manager/helpers/invite.d.ts +1 -1
  7. package/dist/account-manager/helpers/invite.d.ts.map +1 -1
  8. package/dist/account-manager/helpers/invite.js +20 -9
  9. package/dist/account-manager/helpers/invite.js.map +1 -1
  10. package/dist/account-manager/index.d.ts +2 -0
  11. package/dist/account-manager/index.d.ts.map +1 -1
  12. package/dist/account-manager/index.js +8 -1
  13. package/dist/account-manager/index.js.map +1 -1
  14. package/dist/api/com/atproto/admin/getAccountInfo.d.ts.map +1 -1
  15. package/dist/api/com/atproto/admin/getAccountInfo.js +6 -14
  16. package/dist/api/com/atproto/admin/getAccountInfo.js.map +1 -1
  17. package/dist/api/com/atproto/admin/getAccountInfos.d.ts +4 -0
  18. package/dist/api/com/atproto/admin/getAccountInfos.d.ts.map +1 -0
  19. package/dist/api/com/atproto/admin/getAccountInfos.js +32 -0
  20. package/dist/api/com/atproto/admin/getAccountInfos.js.map +1 -0
  21. package/dist/api/com/atproto/admin/index.d.ts.map +1 -1
  22. package/dist/api/com/atproto/admin/index.js +2 -0
  23. package/dist/api/com/atproto/admin/index.js.map +1 -1
  24. package/dist/api/com/atproto/admin/util.d.ts +17 -0
  25. package/dist/api/com/atproto/admin/util.d.ts.map +1 -1
  26. package/dist/api/com/atproto/admin/util.js +27 -1
  27. package/dist/api/com/atproto/admin/util.js.map +1 -1
  28. package/dist/api/com/atproto/repo/getRecord.d.ts.map +1 -1
  29. package/dist/api/com/atproto/repo/getRecord.js +1 -1
  30. package/dist/api/com/atproto/repo/getRecord.js.map +1 -1
  31. package/dist/config/config.d.ts +8 -0
  32. package/dist/config/config.d.ts.map +1 -1
  33. package/dist/config/config.js +1 -0
  34. package/dist/config/config.js.map +1 -1
  35. package/dist/config/env.d.ts +1 -0
  36. package/dist/config/env.d.ts.map +1 -1
  37. package/dist/config/env.js +1 -0
  38. package/dist/config/env.js.map +1 -1
  39. package/dist/lexicon/index.d.ts +4 -0
  40. package/dist/lexicon/index.d.ts.map +1 -1
  41. package/dist/lexicon/index.js +8 -0
  42. package/dist/lexicon/index.js.map +1 -1
  43. package/dist/lexicon/lexicons.d.ts +85 -0
  44. package/dist/lexicon/lexicons.d.ts.map +1 -1
  45. package/dist/lexicon/lexicons.js +93 -0
  46. package/dist/lexicon/lexicons.js.map +1 -1
  47. package/dist/lexicon/types/com/atproto/repo/getRecord.d.ts +1 -0
  48. package/dist/lexicon/types/com/atproto/repo/getRecord.d.ts.map +1 -1
  49. package/dist/lexicon/types/tools/ozone/moderation/getRecords.d.ts +39 -0
  50. package/dist/lexicon/types/tools/ozone/moderation/getRecords.d.ts.map +1 -0
  51. package/dist/lexicon/types/tools/ozone/moderation/getRecords.js +3 -0
  52. package/dist/lexicon/types/tools/ozone/moderation/getRecords.js.map +1 -0
  53. package/dist/lexicon/types/tools/ozone/moderation/getRepos.d.ts +39 -0
  54. package/dist/lexicon/types/tools/ozone/moderation/getRepos.d.ts.map +1 -0
  55. package/dist/lexicon/types/tools/ozone/moderation/getRepos.js +3 -0
  56. package/dist/lexicon/types/tools/ozone/moderation/getRepos.js.map +1 -0
  57. package/dist/mailer/templates/confirm-email.js +1 -1
  58. package/dist/mailer/templates/confirm-email.js.map +1 -1
  59. package/dist/mailer/templates/delete-account.js +1 -1
  60. package/dist/mailer/templates/delete-account.js.map +1 -1
  61. package/dist/mailer/templates/plc-operation.js +1 -1
  62. package/dist/mailer/templates/plc-operation.js.map +1 -1
  63. package/dist/mailer/templates/reset-password.js +1 -1
  64. package/dist/mailer/templates/reset-password.js.map +1 -1
  65. package/dist/mailer/templates/update-email.js +1 -1
  66. package/dist/mailer/templates/update-email.js.map +1 -1
  67. package/dist/pipethrough.d.ts +1 -1
  68. package/dist/pipethrough.d.ts.map +1 -1
  69. package/dist/pipethrough.js +105 -73
  70. package/dist/pipethrough.js.map +1 -1
  71. package/package.json +11 -11
  72. package/src/account-manager/helpers/account.ts +22 -0
  73. package/src/account-manager/helpers/invite.ts +19 -9
  74. package/src/account-manager/index.ts +13 -1
  75. package/src/api/com/atproto/admin/getAccountInfo.ts +6 -13
  76. package/src/api/com/atproto/admin/getAccountInfos.ts +33 -0
  77. package/src/api/com/atproto/admin/index.ts +2 -0
  78. package/src/api/com/atproto/admin/util.ts +38 -0
  79. package/src/api/com/atproto/repo/getRecord.ts +4 -1
  80. package/src/config/config.ts +10 -0
  81. package/src/config/env.ts +2 -0
  82. package/src/lexicon/index.ts +24 -0
  83. package/src/lexicon/lexicons.ts +93 -0
  84. package/src/lexicon/types/com/atproto/repo/getRecord.ts +1 -0
  85. package/src/lexicon/types/tools/ozone/moderation/getRecords.ts +50 -0
  86. package/src/lexicon/types/tools/ozone/moderation/getRepos.ts +50 -0
  87. package/src/mailer/templates/confirm-email.hbs +1 -1
  88. package/src/mailer/templates/delete-account.hbs +1 -1
  89. package/src/mailer/templates/plc-operation.hbs +1 -1
  90. package/src/mailer/templates/reset-password.hbs +1 -1
  91. package/src/mailer/templates/update-email.hbs +1 -1
  92. package/src/pipethrough.ts +131 -92
  93. package/tests/proxied/read-after-write.test.ts +77 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/pds",
3
- "version": "0.4.60",
3
+ "version": "0.4.61",
4
4
  "license": "MIT",
5
5
  "description": "Reference implementation of atproto Personal Data Server (PDS)",
6
6
  "keywords": [
@@ -44,18 +44,18 @@
44
44
  "uint8arrays": "3.0.0",
45
45
  "undici": "^6.19.8",
46
46
  "zod": "^3.23.8",
47
- "@atproto/api": "^0.13.8",
48
- "@atproto/aws": "^0.2.6",
49
- "@atproto/common": "^0.4.3",
47
+ "@atproto-labs/fetch-node": "0.1.1",
48
+ "@atproto/api": "^0.13.9",
49
+ "@atproto/aws": "^0.2.7",
50
+ "@atproto/common": "^0.4.4",
50
51
  "@atproto/crypto": "^0.4.1",
51
52
  "@atproto/identity": "^0.4.2",
52
- "@atproto-labs/fetch-node": "0.1.1",
53
53
  "@atproto/lexicon": "^0.4.2",
54
- "@atproto/oauth-provider": "^0.2.2",
55
- "@atproto/repo": "^0.5.2",
54
+ "@atproto/oauth-provider": "^0.2.3",
55
+ "@atproto/repo": "^0.5.3",
56
+ "@atproto/syntax": "^0.3.0",
56
57
  "@atproto/xrpc": "^0.6.3",
57
- "@atproto/xrpc-server": "^0.7.0",
58
- "@atproto/syntax": "^0.3.0"
58
+ "@atproto/xrpc-server": "^0.7.1"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@atproto/pds-entryway": "npm:@atproto/pds@0.3.0-entryway.3",
@@ -73,8 +73,8 @@
73
73
  "jest": "^28.1.2",
74
74
  "ts-node": "^10.8.2",
75
75
  "ws": "^8.12.0",
76
- "@atproto/api": "^0.13.8",
77
- "@atproto/bsky": "^0.0.84",
76
+ "@atproto/api": "^0.13.9",
77
+ "@atproto/bsky": "^0.0.85",
78
78
  "@atproto/lex-cli": "^0.5.1"
79
79
  },
80
80
  "scripts": {
@@ -64,6 +64,28 @@ export const getAccount = async (
64
64
  return found || null
65
65
  }
66
66
 
67
+ export const getAccounts = async (
68
+ db: AccountDb,
69
+ dids: string[],
70
+ flags?: AvailabilityFlags,
71
+ ): Promise<Map<string, ActorAccount>> => {
72
+ const results = new Map<string, ActorAccount>()
73
+
74
+ if (!dids.length) {
75
+ return results
76
+ }
77
+
78
+ const accounts = await selectAccountQB(db, flags)
79
+ .where('actor.did', 'in', dids)
80
+ .execute()
81
+
82
+ accounts.forEach((account) => {
83
+ results.set(account.did, account)
84
+ })
85
+
86
+ return results
87
+ }
88
+
67
89
  export const getAccountByEmail = async (
68
90
  db: AccountDb,
69
91
  email: string,
@@ -139,20 +139,30 @@ export const selectInviteCodesQb = (db: AccountDb) => {
139
139
  return db.db.selectFrom(builder.as('codes')).selectAll()
140
140
  }
141
141
 
142
- export const getAccountInviteCodes = async (
142
+ export const getAccountsInviteCodes = async (
143
143
  db: AccountDb,
144
- did: string,
145
- ): Promise<CodeDetail[]> => {
144
+ dids: string[],
145
+ ): Promise<Map<string, CodeDetail[]>> => {
146
+ const results = new Map<string, CodeDetail[]>()
147
+ // We don't want to pass an empty array to kysely and let's avoid running a query entirely if there is nothing to match for
148
+ if (!dids.length) return results
146
149
  const res = await selectInviteCodesQb(db)
147
- .where('forAccount', '=', did)
150
+ .where('forAccount', 'in', dids)
148
151
  .execute()
149
152
  const codes = res.map((row) => row.code)
150
153
  const uses = await getInviteCodesUses(db, codes)
151
- return res.map((row) => ({
152
- ...row,
153
- uses: uses[row.code] ?? [],
154
- disabled: row.disabled === 1,
155
- }))
154
+ res.forEach((row) => {
155
+ const existing = results.get(row.forAccount) ?? []
156
+ results.set(row.forAccount, [
157
+ ...existing,
158
+ {
159
+ ...row,
160
+ uses: uses[row.code] ?? [],
161
+ disabled: row.disabled === 1,
162
+ },
163
+ ])
164
+ })
165
+ return results
156
166
  }
157
167
 
158
168
  export const getInviteCodesUses = async (
@@ -78,6 +78,13 @@ export class AccountManager
78
78
  return account.getAccount(this.db, handleOrDid, flags)
79
79
  }
80
80
 
81
+ async getAccounts(
82
+ dids: string[],
83
+ flags?: account.AvailabilityFlags,
84
+ ): Promise<Map<string, ActorAccount>> {
85
+ return account.getAccounts(this.db, dids, flags)
86
+ }
87
+
81
88
  async getAccountByEmail(
82
89
  email: string,
83
90
  flags?: account.AvailabilityFlags,
@@ -397,7 +404,12 @@ export class AccountManager
397
404
  }
398
405
 
399
406
  async getAccountInvitesCodes(did: string) {
400
- return invite.getAccountInviteCodes(this.db, did)
407
+ const inviteCodes = await invite.getAccountsInviteCodes(this.db, [did])
408
+ return inviteCodes.get(did) ?? []
409
+ }
410
+
411
+ async getAccountsInvitesCodes(dids: string[]) {
412
+ return invite.getAccountsInviteCodes(this.db, dids)
401
413
  }
402
414
 
403
415
  async getInvitedByForAccounts(dids: string[]) {
@@ -2,6 +2,7 @@ import { Server } from '../../../../lexicon'
2
2
  import AppContext from '../../../../context'
3
3
  import { InvalidRequestError } from '@atproto/xrpc-server'
4
4
  import { INVALID_HANDLE } from '@atproto/syntax'
5
+ import { formatAccountInfo } from './util'
5
6
 
6
7
  export default function (server: Server, ctx: AppContext) {
7
8
  server.com.atproto.admin.getAccountInfo({
@@ -21,19 +22,11 @@ export default function (server: Server, ctx: AppContext) {
21
22
  const managesOwnInvites = !ctx.cfg.entryway
22
23
  return {
23
24
  encoding: 'application/json',
24
- body: {
25
- did: account.did,
26
- handle: account.handle ?? INVALID_HANDLE,
27
- email: account.email ?? undefined,
28
- indexedAt: account.createdAt,
29
- emailConfirmedAt: account.emailConfirmedAt ?? undefined,
30
- invitedBy: managesOwnInvites ? invitedBy[params.did] : undefined,
31
- invites: managesOwnInvites ? invites : undefined,
32
- invitesDisabled: managesOwnInvites
33
- ? account.invitesDisabled === 1
34
- : undefined,
35
- deactivatedAt: account.deactivatedAt ?? undefined,
36
- },
25
+ body: formatAccountInfo(account, {
26
+ managesOwnInvites,
27
+ invitedBy,
28
+ invites,
29
+ }),
37
30
  }
38
31
  },
39
32
  })
@@ -0,0 +1,33 @@
1
+ import { Server } from '../../../../lexicon'
2
+ import AppContext from '../../../../context'
3
+ import { formatAccountInfo } from './util'
4
+
5
+ export default function (server: Server, ctx: AppContext) {
6
+ server.com.atproto.admin.getAccountInfos({
7
+ auth: ctx.authVerifier.moderator,
8
+ handler: async ({ params }) => {
9
+ const [accounts, invites, invitedBy] = await Promise.all([
10
+ ctx.accountManager.getAccounts(params.dids, {
11
+ includeDeactivated: true,
12
+ includeTakenDown: true,
13
+ }),
14
+ ctx.accountManager.getAccountsInvitesCodes(params.dids),
15
+ ctx.accountManager.getInvitedByForAccounts(params.dids),
16
+ ])
17
+
18
+ const managesOwnInvites = !ctx.cfg.entryway
19
+ const infos = Array.from(accounts.values()).map((account) => {
20
+ return formatAccountInfo(account, {
21
+ managesOwnInvites,
22
+ invitedBy,
23
+ invites,
24
+ })
25
+ })
26
+
27
+ return {
28
+ encoding: 'application/json',
29
+ body: { infos },
30
+ }
31
+ },
32
+ })
33
+ }
@@ -12,11 +12,13 @@ import updateAccountEmail from './updateAccountEmail'
12
12
  import updateAccountPassword from './updateAccountPassword'
13
13
  import sendEmail from './sendEmail'
14
14
  import deleteAccount from './deleteAccount'
15
+ import getAccountInfos from './getAccountInfos'
15
16
 
16
17
  export default function (server: Server, ctx: AppContext) {
17
18
  updateSubjectStatus(server, ctx)
18
19
  getSubjectStatus(server, ctx)
19
20
  getAccountInfo(server, ctx)
21
+ getAccountInfos(server, ctx)
20
22
  enableAccountInvites(server, ctx)
21
23
  disableAccountInvites(server, ctx)
22
24
  disableInviteCodes(server, ctx)
@@ -1,4 +1,7 @@
1
1
  import express from 'express'
2
+ import { ActorAccount } from '../../../../account-manager/helpers/account'
3
+ import { INVALID_HANDLE } from '@atproto/syntax'
4
+ import { CodeDetail } from '../../../../account-manager/helpers/invite'
2
5
 
3
6
  // Output designed to passed as second arg to AtpAgent methods.
4
7
  // The encoding field here is a quirk of the AtpAgent.
@@ -22,3 +25,38 @@ export function authPassthru(req: express.Request, withEncoding?: boolean) {
22
25
  }
23
26
  }
24
27
  }
28
+
29
+ export function formatAccountInfo(
30
+ account: ActorAccount,
31
+ {
32
+ managesOwnInvites,
33
+ invitedBy,
34
+ invites,
35
+ }: {
36
+ managesOwnInvites: boolean
37
+ invites: Map<string, CodeDetail[]> | CodeDetail[]
38
+ invitedBy: Record<string, CodeDetail>
39
+ },
40
+ ) {
41
+ let invitesResults: CodeDetail[] | undefined
42
+ if (managesOwnInvites) {
43
+ if (Array.isArray(invites)) {
44
+ invitesResults = invites
45
+ } else {
46
+ invitesResults = invites.get(account.did) || []
47
+ }
48
+ }
49
+ return {
50
+ did: account.did,
51
+ handle: account.handle ?? INVALID_HANDLE,
52
+ email: account.email ?? undefined,
53
+ indexedAt: account.createdAt,
54
+ emailConfirmedAt: account.emailConfirmedAt ?? undefined,
55
+ invitedBy: managesOwnInvites ? invitedBy[account.did] : undefined,
56
+ invites: invitesResults,
57
+ invitesDisabled: managesOwnInvites
58
+ ? account.invitesDisabled === 1
59
+ : undefined,
60
+ deactivatedAt: account.deactivatedAt ?? undefined,
61
+ }
62
+ }
@@ -16,7 +16,10 @@ export default function (server: Server, ctx: AppContext) {
16
16
  store.record.getRecord(uri, cid ?? null),
17
17
  )
18
18
  if (!record || record.takedownRef !== null) {
19
- throw new InvalidRequestError(`Could not locate record: ${uri}`)
19
+ throw new InvalidRequestError(
20
+ `Could not locate record: ${uri}`,
21
+ 'RecordNotFound',
22
+ )
20
23
  }
21
24
  return {
22
25
  encoding: 'application/json',
@@ -246,6 +246,7 @@ export const envToCfg = (env: ServerEnvironment): ServerConfig => {
246
246
  headersTimeout: env.proxyHeadersTimeout ?? 10e3,
247
247
  bodyTimeout: env.proxyBodyTimeout ?? 30e3,
248
248
  maxResponseSize: env.proxyMaxResponseSize ?? 10 * 1024 * 1024, // 10mb
249
+ preferCompressed: env.proxyPreferCompressed ?? false,
249
250
  }
250
251
 
251
252
  const oauthCfg: ServerConfig['oauth'] = entrywayCfg
@@ -413,6 +414,15 @@ export type ProxyConfig = {
413
414
  headersTimeout: number
414
415
  bodyTimeout: number
415
416
  maxResponseSize: number
417
+
418
+ /**
419
+ * When proxying requests that might get intercepted (for read-after-write) we
420
+ * negotiate the encoding based on the client's preferences. We will however
421
+ * use or own weights in order to be able to better control if the PDS will
422
+ * need to perform content decoding. This settings allows to prefer compressed
423
+ * content over uncompressed one.
424
+ */
425
+ preferCompressed: boolean
416
426
  }
417
427
 
418
428
  export type OAuthConfig = {
package/src/config/env.ts CHANGED
@@ -128,6 +128,7 @@ export const readEnv = (): ServerEnvironment => {
128
128
  proxyHeadersTimeout: envInt('PDS_PROXY_HEADERS_TIMEOUT'),
129
129
  proxyBodyTimeout: envInt('PDS_PROXY_BODY_TIMEOUT'),
130
130
  proxyMaxResponseSize: envInt('PDS_PROXY_MAX_RESPONSE_SIZE'),
131
+ proxyPreferCompressed: envBool('PDS_PROXY_PREFER_COMPRESSED'),
131
132
  }
132
133
  }
133
134
 
@@ -253,4 +254,5 @@ export type ServerEnvironment = {
253
254
  proxyHeadersTimeout?: number
254
255
  proxyBodyTimeout?: number
255
256
  proxyMaxResponseSize?: number
257
+ proxyPreferCompressed?: boolean
256
258
  }
@@ -166,7 +166,9 @@ import * as ToolsOzoneCommunicationUpdateTemplate from './types/tools/ozone/comm
166
166
  import * as ToolsOzoneModerationEmitEvent from './types/tools/ozone/moderation/emitEvent'
167
167
  import * as ToolsOzoneModerationGetEvent from './types/tools/ozone/moderation/getEvent'
168
168
  import * as ToolsOzoneModerationGetRecord from './types/tools/ozone/moderation/getRecord'
169
+ import * as ToolsOzoneModerationGetRecords from './types/tools/ozone/moderation/getRecords'
169
170
  import * as ToolsOzoneModerationGetRepo from './types/tools/ozone/moderation/getRepo'
171
+ import * as ToolsOzoneModerationGetRepos from './types/tools/ozone/moderation/getRepos'
170
172
  import * as ToolsOzoneModerationQueryEvents from './types/tools/ozone/moderation/queryEvents'
171
173
  import * as ToolsOzoneModerationQueryStatuses from './types/tools/ozone/moderation/queryStatuses'
172
174
  import * as ToolsOzoneModerationSearchRepos from './types/tools/ozone/moderation/searchRepos'
@@ -2262,6 +2264,17 @@ export class ToolsOzoneModerationNS {
2262
2264
  return this._server.xrpc.method(nsid, cfg)
2263
2265
  }
2264
2266
 
2267
+ getRecords<AV extends AuthVerifier>(
2268
+ cfg: ConfigOf<
2269
+ AV,
2270
+ ToolsOzoneModerationGetRecords.Handler<ExtractAuth<AV>>,
2271
+ ToolsOzoneModerationGetRecords.HandlerReqCtx<ExtractAuth<AV>>
2272
+ >,
2273
+ ) {
2274
+ const nsid = 'tools.ozone.moderation.getRecords' // @ts-ignore
2275
+ return this._server.xrpc.method(nsid, cfg)
2276
+ }
2277
+
2265
2278
  getRepo<AV extends AuthVerifier>(
2266
2279
  cfg: ConfigOf<
2267
2280
  AV,
@@ -2273,6 +2286,17 @@ export class ToolsOzoneModerationNS {
2273
2286
  return this._server.xrpc.method(nsid, cfg)
2274
2287
  }
2275
2288
 
2289
+ getRepos<AV extends AuthVerifier>(
2290
+ cfg: ConfigOf<
2291
+ AV,
2292
+ ToolsOzoneModerationGetRepos.Handler<ExtractAuth<AV>>,
2293
+ ToolsOzoneModerationGetRepos.HandlerReqCtx<ExtractAuth<AV>>
2294
+ >,
2295
+ ) {
2296
+ const nsid = 'tools.ozone.moderation.getRepos' // @ts-ignore
2297
+ return this._server.xrpc.method(nsid, cfg)
2298
+ }
2299
+
2276
2300
  queryEvents<AV extends AuthVerifier>(
2277
2301
  cfg: ConfigOf<
2278
2302
  AV,
@@ -1686,6 +1686,11 @@ export const schemaDict = {
1686
1686
  },
1687
1687
  },
1688
1688
  },
1689
+ errors: [
1690
+ {
1691
+ name: 'RecordNotFound',
1692
+ },
1693
+ ],
1689
1694
  },
1690
1695
  },
1691
1696
  },
@@ -11643,6 +11648,49 @@ export const schemaDict = {
11643
11648
  },
11644
11649
  },
11645
11650
  },
11651
+ ToolsOzoneModerationGetRecords: {
11652
+ lexicon: 1,
11653
+ id: 'tools.ozone.moderation.getRecords',
11654
+ defs: {
11655
+ main: {
11656
+ type: 'query',
11657
+ description: 'Get details about some records.',
11658
+ parameters: {
11659
+ type: 'params',
11660
+ required: ['uris'],
11661
+ properties: {
11662
+ uris: {
11663
+ type: 'array',
11664
+ maxLength: 100,
11665
+ items: {
11666
+ type: 'string',
11667
+ format: 'at-uri',
11668
+ },
11669
+ },
11670
+ },
11671
+ },
11672
+ output: {
11673
+ encoding: 'application/json',
11674
+ schema: {
11675
+ type: 'object',
11676
+ required: ['records'],
11677
+ properties: {
11678
+ records: {
11679
+ type: 'array',
11680
+ items: {
11681
+ type: 'union',
11682
+ refs: [
11683
+ 'lex:tools.ozone.moderation.defs#recordViewDetail',
11684
+ 'lex:tools.ozone.moderation.defs#recordViewNotFound',
11685
+ ],
11686
+ },
11687
+ },
11688
+ },
11689
+ },
11690
+ },
11691
+ },
11692
+ },
11693
+ },
11646
11694
  ToolsOzoneModerationGetRepo: {
11647
11695
  lexicon: 1,
11648
11696
  id: 'tools.ozone.moderation.getRepo',
@@ -11675,6 +11723,49 @@ export const schemaDict = {
11675
11723
  },
11676
11724
  },
11677
11725
  },
11726
+ ToolsOzoneModerationGetRepos: {
11727
+ lexicon: 1,
11728
+ id: 'tools.ozone.moderation.getRepos',
11729
+ defs: {
11730
+ main: {
11731
+ type: 'query',
11732
+ description: 'Get details about some repositories.',
11733
+ parameters: {
11734
+ type: 'params',
11735
+ required: ['dids'],
11736
+ properties: {
11737
+ dids: {
11738
+ type: 'array',
11739
+ maxLength: 100,
11740
+ items: {
11741
+ type: 'string',
11742
+ format: 'did',
11743
+ },
11744
+ },
11745
+ },
11746
+ },
11747
+ output: {
11748
+ encoding: 'application/json',
11749
+ schema: {
11750
+ type: 'object',
11751
+ required: ['repos'],
11752
+ properties: {
11753
+ repos: {
11754
+ type: 'array',
11755
+ items: {
11756
+ type: 'union',
11757
+ refs: [
11758
+ 'lex:tools.ozone.moderation.defs#repoViewDetail',
11759
+ 'lex:tools.ozone.moderation.defs#repoViewNotFound',
11760
+ ],
11761
+ },
11762
+ },
11763
+ },
11764
+ },
11765
+ },
11766
+ },
11767
+ },
11768
+ },
11678
11769
  ToolsOzoneModerationQueryEvents: {
11679
11770
  lexicon: 1,
11680
11771
  id: 'tools.ozone.moderation.queryEvents',
@@ -12491,7 +12582,9 @@ export const ids = {
12491
12582
  ToolsOzoneModerationEmitEvent: 'tools.ozone.moderation.emitEvent',
12492
12583
  ToolsOzoneModerationGetEvent: 'tools.ozone.moderation.getEvent',
12493
12584
  ToolsOzoneModerationGetRecord: 'tools.ozone.moderation.getRecord',
12585
+ ToolsOzoneModerationGetRecords: 'tools.ozone.moderation.getRecords',
12494
12586
  ToolsOzoneModerationGetRepo: 'tools.ozone.moderation.getRepo',
12587
+ ToolsOzoneModerationGetRepos: 'tools.ozone.moderation.getRepos',
12495
12588
  ToolsOzoneModerationQueryEvents: 'tools.ozone.moderation.queryEvents',
12496
12589
  ToolsOzoneModerationQueryStatuses: 'tools.ozone.moderation.queryStatuses',
12497
12590
  ToolsOzoneModerationSearchRepos: 'tools.ozone.moderation.searchRepos',
@@ -39,6 +39,7 @@ export interface HandlerSuccess {
39
39
  export interface HandlerError {
40
40
  status: number
41
41
  message?: string
42
+ error?: 'RecordNotFound'
42
43
  }
43
44
 
44
45
  export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
@@ -0,0 +1,50 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import express from 'express'
5
+ import { ValidationResult, BlobRef } from '@atproto/lexicon'
6
+ import { lexicons } from '../../../../lexicons'
7
+ import { isObj, hasProp } from '../../../../util'
8
+ import { CID } from 'multiformats/cid'
9
+ import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
10
+ import * as ToolsOzoneModerationDefs from './defs'
11
+
12
+ export interface QueryParams {
13
+ uris: string[]
14
+ }
15
+
16
+ export type InputSchema = undefined
17
+
18
+ export interface OutputSchema {
19
+ records: (
20
+ | ToolsOzoneModerationDefs.RecordViewDetail
21
+ | ToolsOzoneModerationDefs.RecordViewNotFound
22
+ | { $type: string; [k: string]: unknown }
23
+ )[]
24
+ [k: string]: unknown
25
+ }
26
+
27
+ export type HandlerInput = undefined
28
+
29
+ export interface HandlerSuccess {
30
+ encoding: 'application/json'
31
+ body: OutputSchema
32
+ headers?: { [key: string]: string }
33
+ }
34
+
35
+ export interface HandlerError {
36
+ status: number
37
+ message?: string
38
+ }
39
+
40
+ export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
41
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
42
+ auth: HA
43
+ params: QueryParams
44
+ input: HandlerInput
45
+ req: express.Request
46
+ res: express.Response
47
+ }
48
+ export type Handler<HA extends HandlerAuth = never> = (
49
+ ctx: HandlerReqCtx<HA>,
50
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -0,0 +1,50 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import express from 'express'
5
+ import { ValidationResult, BlobRef } from '@atproto/lexicon'
6
+ import { lexicons } from '../../../../lexicons'
7
+ import { isObj, hasProp } from '../../../../util'
8
+ import { CID } from 'multiformats/cid'
9
+ import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
10
+ import * as ToolsOzoneModerationDefs from './defs'
11
+
12
+ export interface QueryParams {
13
+ dids: string[]
14
+ }
15
+
16
+ export type InputSchema = undefined
17
+
18
+ export interface OutputSchema {
19
+ repos: (
20
+ | ToolsOzoneModerationDefs.RepoViewDetail
21
+ | ToolsOzoneModerationDefs.RepoViewNotFound
22
+ | { $type: string; [k: string]: unknown }
23
+ )[]
24
+ [k: string]: unknown
25
+ }
26
+
27
+ export type HandlerInput = undefined
28
+
29
+ export interface HandlerSuccess {
30
+ encoding: 'application/json'
31
+ body: OutputSchema
32
+ headers?: { [key: string]: string }
33
+ }
34
+
35
+ export interface HandlerError {
36
+ status: number
37
+ message?: string
38
+ }
39
+
40
+ export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
41
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
42
+ auth: HA
43
+ params: QueryParams
44
+ input: HandlerInput
45
+ req: express.Request
46
+ res: express.Response
47
+ }
48
+ export type Handler<HA extends HandlerAuth = never> = (
49
+ ctx: HandlerReqCtx<HA>,
50
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -68,7 +68,7 @@
68
68
  style="font-size:16px;line-height:1.4;margin:0px 0px;letter-spacing:0.25px;color:hsl(211, 24%, 34.2%);font-family:-apple-system, BlinkMacSystemFont, &#x27;Roboto&#x27;, &#x27;Oxygen&#x27;, &#x27;Ubuntu&#x27;, &#x27;Cantarell&#x27;, &#x27;Fira Sans&#x27;, &#x27;Droid Sans&#x27;, &#x27;Helvetica Neue&#x27;, sans-serif;padding-top:12px;padding-bottom:12px;padding-right:32px"
69
69
  >To confirm this email for your account, please enter the
70
70
  code below in the app.</p><code
71
- style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:lowercase"
71
+ style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:uppercase"
72
72
  >{{token}}</code>
73
73
  <p
74
74
  style="font-size:14px;line-height:1.4;margin:0px 0px;letter-spacing:0.25px;color:hsl(211, 20%, 53%);font-family:-apple-system, BlinkMacSystemFont, &#x27;Roboto&#x27;, &#x27;Oxygen&#x27;, &#x27;Ubuntu&#x27;, &#x27;Cantarell&#x27;, &#x27;Fira Sans&#x27;, &#x27;Droid Sans&#x27;, &#x27;Helvetica Neue&#x27;, sans-serif;padding-top:12px"
@@ -71,7 +71,7 @@
71
71
  account,</span>
72
72
  <!-- -->please enter the code below in the app along with
73
73
  your password.</p><code
74
- style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:lowercase"
74
+ style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:uppercase"
75
75
  >{{token}}</code>
76
76
  <p
77
77
  style="font-size:14px;line-height:1.4;margin:0px 0px;letter-spacing:0.25px;color:hsl(211, 20%, 53%);font-family:-apple-system, BlinkMacSystemFont, &#x27;Roboto&#x27;, &#x27;Oxygen&#x27;, &#x27;Ubuntu&#x27;, &#x27;Cantarell&#x27;, &#x27;Fira Sans&#x27;, &#x27;Droid Sans&#x27;, &#x27;Helvetica Neue&#x27;, sans-serif;padding-top:12px;padding-right:32px"
@@ -68,7 +68,7 @@
68
68
  style="font-size:16px;line-height:1.4;margin:0px 0px;letter-spacing:0.25px;color:hsl(211, 24%, 34.2%);font-family:-apple-system, BlinkMacSystemFont, &#x27;Roboto&#x27;, &#x27;Oxygen&#x27;, &#x27;Ubuntu&#x27;, &#x27;Cantarell&#x27;, &#x27;Fira Sans&#x27;, &#x27;Droid Sans&#x27;, &#x27;Helvetica Neue&#x27;, sans-serif;padding-top:12px;padding-bottom:12px"
69
69
  >We received a request to update your PLC identity. Your
70
70
  confirmation code is:</p><code
71
- style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:lowercase"
71
+ style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:uppercase"
72
72
  >{{token}}</code>
73
73
  <p
74
74
  style="font-size:14px;line-height:1.4;margin:0px 0px;letter-spacing:0.25px;color:hsl(211, 20%, 53%);font-family:-apple-system, BlinkMacSystemFont, &#x27;Roboto&#x27;, &#x27;Oxygen&#x27;, &#x27;Ubuntu&#x27;, &#x27;Cantarell&#x27;, &#x27;Fira Sans&#x27;, &#x27;Droid Sans&#x27;, &#x27;Helvetica Neue&#x27;, sans-serif;padding-top:12px"
@@ -70,7 +70,7 @@
70
70
  <span
71
71
  style="color:hsl(211, 99%, 53%)"
72
72
  >@<!-- -->{{handle}}<!-- -->.</span></p><code
73
- style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:lowercase"
73
+ style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:uppercase"
74
74
  >{{token}}</code>
75
75
  <p
76
76
  style="font-size:14px;line-height:1.4;margin:0px 0px;letter-spacing:0.25px;color:hsl(211, 20%, 53%);font-family:-apple-system, BlinkMacSystemFont, &#x27;Roboto&#x27;, &#x27;Oxygen&#x27;, &#x27;Ubuntu&#x27;, &#x27;Cantarell&#x27;, &#x27;Fira Sans&#x27;, &#x27;Droid Sans&#x27;, &#x27;Helvetica Neue&#x27;, sans-serif;padding-top:12px"
@@ -69,7 +69,7 @@
69
69
  style="font-size:16px;line-height:1.4;margin:0px 0px;letter-spacing:0.25px;color:hsl(211, 24%, 34.2%);font-family:-apple-system, BlinkMacSystemFont, &#x27;Roboto&#x27;, &#x27;Oxygen&#x27;, &#x27;Ubuntu&#x27;, &#x27;Cantarell&#x27;, &#x27;Fira Sans&#x27;, &#x27;Droid Sans&#x27;, &#x27;Helvetica Neue&#x27;, sans-serif;padding-top:12px;padding-bottom:12px;padding-right:32px"
70
70
  >To update the email for your account, enter the code below
71
71
  in the app along with your new email.</p><code
72
- style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:lowercase"
72
+ style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:uppercase"
73
73
  >{{token}}</code>
74
74
  <p
75
75
  style="font-size:14px;line-height:1.4;margin:0px 0px;letter-spacing:0.25px;color:hsl(211, 20%, 53%);font-family:-apple-system, BlinkMacSystemFont, &#x27;Roboto&#x27;, &#x27;Oxygen&#x27;, &#x27;Ubuntu&#x27;, &#x27;Cantarell&#x27;, &#x27;Fira Sans&#x27;, &#x27;Droid Sans&#x27;, &#x27;Helvetica Neue&#x27;, sans-serif;padding-top:12px"