@atproto/bsky 0.0.10 → 0.0.12

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 (173) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/api/com/atproto/admin/util.d.ts +5 -0
  3. package/dist/config.d.ts +2 -0
  4. package/dist/context.d.ts +8 -0
  5. package/dist/db/index.js +51 -2
  6. package/dist/db/index.js.map +3 -3
  7. package/dist/db/migrations/20230929T192920807Z-record-cursor-indexes.d.ts +3 -0
  8. package/dist/db/migrations/index.d.ts +1 -0
  9. package/dist/did-cache.d.ts +2 -2
  10. package/dist/index.d.ts +2 -0
  11. package/dist/index.js +1818 -580
  12. package/dist/index.js.map +3 -3
  13. package/dist/lexicon/index.d.ts +16 -0
  14. package/dist/lexicon/lexicons.d.ts +330 -3
  15. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +1 -0
  16. package/dist/lexicon/types/com/atproto/admin/defs.d.ts +28 -0
  17. package/dist/lexicon/types/com/atproto/admin/getAccountInfo.d.ts +29 -0
  18. package/dist/lexicon/types/com/atproto/admin/getSubjectStatus.d.ts +39 -0
  19. package/dist/lexicon/types/com/atproto/admin/searchRepos.d.ts +0 -1
  20. package/dist/lexicon/types/com/atproto/admin/updateSubjectStatus.d.ts +46 -0
  21. package/dist/lexicon/types/com/atproto/server/confirmEmail.d.ts +27 -0
  22. package/dist/lexicon/types/com/atproto/server/createAccount.d.ts +2 -0
  23. package/dist/lexicon/types/com/atproto/server/createSession.d.ts +2 -0
  24. package/dist/lexicon/types/com/atproto/server/getSession.d.ts +1 -0
  25. package/dist/lexicon/types/com/atproto/server/refreshSession.d.ts +1 -0
  26. package/dist/lexicon/types/com/atproto/server/requestEmailConfirmation.d.ts +19 -0
  27. package/dist/lexicon/types/com/atproto/server/requestEmailUpdate.d.ts +30 -0
  28. package/dist/lexicon/types/com/atproto/server/reserveSigningKey.d.ts +30 -0
  29. package/dist/lexicon/types/com/atproto/server/updateEmail.d.ts +27 -0
  30. package/dist/lexicon/types/com/atproto/sync/listRepos.d.ts +1 -0
  31. package/dist/services/actor/index.d.ts +2 -2
  32. package/dist/services/actor/types.d.ts +1 -0
  33. package/dist/services/graph/index.d.ts +2 -0
  34. package/dist/services/moderation/index.d.ts +13 -3
  35. package/dist/services/util/search.d.ts +3 -3
  36. package/package.json +13 -14
  37. package/src/api/app/bsky/actor/searchActors.ts +36 -22
  38. package/src/api/app/bsky/actor/searchActorsTypeahead.ts +24 -17
  39. package/src/api/app/bsky/feed/getAuthorFeed.ts +2 -2
  40. package/src/api/app/bsky/feed/getPostThread.ts +2 -2
  41. package/src/api/app/bsky/graph/getSuggestedFollowsByActor.ts +1 -0
  42. package/src/api/app/bsky/notification/listNotifications.ts +33 -22
  43. package/src/api/com/atproto/admin/getModerationAction.ts +28 -2
  44. package/src/api/com/atproto/admin/getModerationReport.ts +27 -2
  45. package/src/api/com/atproto/admin/getRecord.ts +14 -2
  46. package/src/api/com/atproto/admin/getRepo.ts +13 -2
  47. package/src/api/com/atproto/admin/reverseModerationAction.ts +31 -5
  48. package/src/api/com/atproto/admin/searchRepos.ts +6 -12
  49. package/src/api/com/atproto/admin/takeModerationAction.ts +41 -7
  50. package/src/api/com/atproto/admin/util.ts +50 -0
  51. package/src/api/well-known.ts +8 -0
  52. package/src/auth.ts +12 -5
  53. package/src/auto-moderator/index.ts +1 -0
  54. package/src/config.ts +7 -0
  55. package/src/context.ts +30 -0
  56. package/src/db/migrations/20230929T192920807Z-record-cursor-indexes.ts +40 -0
  57. package/src/db/migrations/index.ts +1 -0
  58. package/src/did-cache.ts +29 -14
  59. package/src/feed-gen/with-friends.ts +2 -2
  60. package/src/index.ts +9 -1
  61. package/src/indexer/subscription.ts +1 -21
  62. package/src/lexicon/index.ts +96 -0
  63. package/src/lexicon/lexicons.ts +368 -4
  64. package/src/lexicon/types/app/bsky/actor/defs.ts +1 -0
  65. package/src/lexicon/types/com/atproto/admin/defs.ts +61 -0
  66. package/src/lexicon/types/com/atproto/admin/getAccountInfo.ts +41 -0
  67. package/src/lexicon/types/com/atproto/admin/getSubjectStatus.ts +54 -0
  68. package/src/lexicon/types/com/atproto/admin/searchRepos.ts +0 -1
  69. package/src/lexicon/types/com/atproto/admin/updateSubjectStatus.ts +61 -0
  70. package/src/lexicon/types/com/atproto/server/confirmEmail.ts +40 -0
  71. package/src/lexicon/types/com/atproto/server/createAccount.ts +2 -0
  72. package/src/lexicon/types/com/atproto/server/createSession.ts +2 -0
  73. package/src/lexicon/types/com/atproto/server/getSession.ts +1 -0
  74. package/src/lexicon/types/com/atproto/server/refreshSession.ts +1 -0
  75. package/src/lexicon/types/com/atproto/server/requestEmailConfirmation.ts +31 -0
  76. package/src/lexicon/types/com/atproto/server/requestEmailUpdate.ts +43 -0
  77. package/src/lexicon/types/com/atproto/server/reserveSigningKey.ts +44 -0
  78. package/src/lexicon/types/com/atproto/server/updateEmail.ts +41 -0
  79. package/src/lexicon/types/com/atproto/sync/listRepos.ts +1 -0
  80. package/src/logger.ts +8 -0
  81. package/src/services/actor/index.ts +16 -10
  82. package/src/services/actor/types.ts +1 -0
  83. package/src/services/actor/views.ts +26 -8
  84. package/src/services/graph/index.ts +26 -7
  85. package/src/services/indexing/index.ts +15 -17
  86. package/src/services/moderation/index.ts +94 -14
  87. package/src/services/moderation/views.ts +1 -0
  88. package/src/services/util/search.ts +24 -23
  89. package/tests/__snapshots__/feed-generation.test.ts.snap +12 -12
  90. package/tests/__snapshots__/indexing.test.ts.snap +4 -4
  91. package/tests/admin/__snapshots__/get-moderation-action.test.ts.snap +172 -0
  92. package/tests/admin/__snapshots__/get-moderation-actions.test.ts.snap +178 -0
  93. package/tests/admin/__snapshots__/get-moderation-report.test.ts.snap +177 -0
  94. package/tests/admin/__snapshots__/get-moderation-reports.test.ts.snap +307 -0
  95. package/tests/admin/__snapshots__/get-record.test.ts.snap +275 -0
  96. package/tests/admin/__snapshots__/get-repo.test.ts.snap +103 -0
  97. package/tests/admin/get-moderation-action.test.ts +100 -0
  98. package/tests/admin/get-moderation-actions.test.ts +164 -0
  99. package/tests/admin/get-moderation-report.test.ts +100 -0
  100. package/tests/admin/get-moderation-reports.test.ts +332 -0
  101. package/tests/admin/get-record.test.ts +115 -0
  102. package/tests/admin/get-repo.test.ts +101 -0
  103. package/tests/{moderation.test.ts → admin/moderation.test.ts} +107 -9
  104. package/tests/admin/repo-search.test.ts +124 -0
  105. package/tests/algos/hot-classic.test.ts +3 -5
  106. package/tests/algos/whats-hot.test.ts +3 -5
  107. package/tests/algos/with-friends.test.ts +2 -4
  108. package/tests/auth.test.ts +64 -0
  109. package/tests/auto-moderator/fuzzy-matcher.test.ts +2 -3
  110. package/tests/auto-moderator/labeler.test.ts +5 -7
  111. package/tests/auto-moderator/takedowns.test.ts +11 -12
  112. package/tests/blob-resolver.test.ts +1 -3
  113. package/tests/did-cache.test.ts +2 -5
  114. package/tests/feed-generation.test.ts +8 -6
  115. package/tests/handle-invalidation.test.ts +2 -3
  116. package/tests/image/server.test.ts +1 -4
  117. package/tests/image/sharp.test.ts +1 -1
  118. package/tests/indexing.test.ts +4 -4
  119. package/tests/notification-server.test.ts +2 -3
  120. package/tests/pipeline/backpressure.test.ts +2 -3
  121. package/tests/pipeline/reingest.test.ts +7 -4
  122. package/tests/pipeline/repartition.test.ts +2 -3
  123. package/tests/reprocessing.test.ts +2 -6
  124. package/tests/seeds/basic.ts +4 -4
  125. package/tests/seeds/follows.ts +1 -1
  126. package/tests/seeds/likes.ts +1 -1
  127. package/tests/seeds/reposts.ts +1 -1
  128. package/tests/seeds/users-bulk.ts +1 -1
  129. package/tests/seeds/users.ts +1 -1
  130. package/tests/server.test.ts +1 -3
  131. package/tests/subscription/repo.test.ts +2 -4
  132. package/tests/views/__snapshots__/author-feed.test.ts.snap +24 -24
  133. package/tests/views/__snapshots__/block-lists.test.ts.snap +42 -7
  134. package/tests/views/__snapshots__/blocks.test.ts.snap +2 -2
  135. package/tests/views/__snapshots__/list-feed.test.ts.snap +6 -6
  136. package/tests/views/__snapshots__/mute-lists.test.ts.snap +15 -4
  137. package/tests/views/__snapshots__/mutes.test.ts.snap +2 -2
  138. package/tests/views/__snapshots__/notifications.test.ts.snap +2 -2
  139. package/tests/views/__snapshots__/posts.test.ts.snap +8 -8
  140. package/tests/views/__snapshots__/thread.test.ts.snap +10 -10
  141. package/tests/views/__snapshots__/timeline.test.ts.snap +58 -58
  142. package/tests/views/actor-likes.test.ts +2 -3
  143. package/tests/views/actor-search.test.ts +5 -5
  144. package/tests/views/admin/repo-search.test.ts +2 -4
  145. package/tests/views/author-feed.test.ts +2 -4
  146. package/tests/views/block-lists.test.ts +34 -7
  147. package/tests/views/blocks.test.ts +6 -3
  148. package/tests/views/follows.test.ts +2 -4
  149. package/tests/views/likes.test.ts +2 -5
  150. package/tests/views/list-feed.test.ts +2 -4
  151. package/tests/views/mute-lists.test.ts +23 -5
  152. package/tests/views/mutes.test.ts +2 -5
  153. package/tests/views/notifications.test.ts +2 -4
  154. package/tests/views/posts.test.ts +2 -5
  155. package/tests/views/profile.test.ts +4 -5
  156. package/tests/views/reposts.test.ts +2 -4
  157. package/tests/views/suggested-follows.test.ts +2 -3
  158. package/tests/views/suggestions.test.ts +2 -4
  159. package/tests/views/thread.test.ts +2 -4
  160. package/tests/views/threadgating.test.ts +2 -3
  161. package/tests/views/timeline.test.ts +2 -4
  162. package/dist/env.d.ts +0 -1
  163. package/example.dev.env +0 -5
  164. package/src/env.ts +0 -9
  165. package/tests/seeds/client.ts +0 -466
  166. /package/tests/{__snapshots__ → admin/__snapshots__}/moderation.test.ts.snap +0 -0
  167. /package/tests/{image/fixtures → sample-img}/at.png +0 -0
  168. /package/tests/{image/fixtures → sample-img}/hd-key.jpg +0 -0
  169. /package/tests/{image/fixtures → sample-img}/key-alt.jpg +0 -0
  170. /package/tests/{image/fixtures → sample-img}/key-landscape-large.jpg +0 -0
  171. /package/tests/{image/fixtures → sample-img}/key-landscape-small.jpg +0 -0
  172. /package/tests/{image/fixtures → sample-img}/key-portrait-large.jpg +0 -0
  173. /package/tests/{image/fixtures → sample-img}/key-portrait-small.jpg +0 -0
@@ -0,0 +1,54 @@
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 } from '@atproto/xrpc-server'
10
+ import * as ComAtprotoAdminDefs from './defs'
11
+ import * as ComAtprotoRepoStrongRef from '../repo/strongRef'
12
+
13
+ export interface QueryParams {
14
+ did?: string
15
+ uri?: string
16
+ blob?: string
17
+ }
18
+
19
+ export type InputSchema = undefined
20
+
21
+ export interface OutputSchema {
22
+ subject:
23
+ | ComAtprotoAdminDefs.RepoRef
24
+ | ComAtprotoRepoStrongRef.Main
25
+ | ComAtprotoAdminDefs.RepoBlobRef
26
+ | { $type: string; [k: string]: unknown }
27
+ takedown?: ComAtprotoAdminDefs.StatusAttr
28
+ [k: string]: unknown
29
+ }
30
+
31
+ export type HandlerInput = undefined
32
+
33
+ export interface HandlerSuccess {
34
+ encoding: 'application/json'
35
+ body: OutputSchema
36
+ headers?: { [key: string]: string }
37
+ }
38
+
39
+ export interface HandlerError {
40
+ status: number
41
+ message?: string
42
+ }
43
+
44
+ export type HandlerOutput = HandlerError | HandlerSuccess
45
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
46
+ auth: HA
47
+ params: QueryParams
48
+ input: HandlerInput
49
+ req: express.Request
50
+ res: express.Response
51
+ }
52
+ export type Handler<HA extends HandlerAuth = never> = (
53
+ ctx: HandlerReqCtx<HA>,
54
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -13,7 +13,6 @@ export interface QueryParams {
13
13
  /** DEPRECATED: use 'q' instead */
14
14
  term?: string
15
15
  q?: string
16
- invitedBy?: string
17
16
  limit: number
18
17
  cursor?: string
19
18
  }
@@ -0,0 +1,61 @@
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 } from '@atproto/xrpc-server'
10
+ import * as ComAtprotoAdminDefs from './defs'
11
+ import * as ComAtprotoRepoStrongRef from '../repo/strongRef'
12
+
13
+ export interface QueryParams {}
14
+
15
+ export interface InputSchema {
16
+ subject:
17
+ | ComAtprotoAdminDefs.RepoRef
18
+ | ComAtprotoRepoStrongRef.Main
19
+ | ComAtprotoAdminDefs.RepoBlobRef
20
+ | { $type: string; [k: string]: unknown }
21
+ takedown?: ComAtprotoAdminDefs.StatusAttr
22
+ [k: string]: unknown
23
+ }
24
+
25
+ export interface OutputSchema {
26
+ subject:
27
+ | ComAtprotoAdminDefs.RepoRef
28
+ | ComAtprotoRepoStrongRef.Main
29
+ | ComAtprotoAdminDefs.RepoBlobRef
30
+ | { $type: string; [k: string]: unknown }
31
+ takedown?: ComAtprotoAdminDefs.StatusAttr
32
+ [k: string]: unknown
33
+ }
34
+
35
+ export interface HandlerInput {
36
+ encoding: 'application/json'
37
+ body: InputSchema
38
+ }
39
+
40
+ export interface HandlerSuccess {
41
+ encoding: 'application/json'
42
+ body: OutputSchema
43
+ headers?: { [key: string]: string }
44
+ }
45
+
46
+ export interface HandlerError {
47
+ status: number
48
+ message?: string
49
+ }
50
+
51
+ export type HandlerOutput = HandlerError | HandlerSuccess
52
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
53
+ auth: HA
54
+ params: QueryParams
55
+ input: HandlerInput
56
+ req: express.Request
57
+ res: express.Response
58
+ }
59
+ export type Handler<HA extends HandlerAuth = never> = (
60
+ ctx: HandlerReqCtx<HA>,
61
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -0,0 +1,40 @@
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 } from '@atproto/xrpc-server'
10
+
11
+ export interface QueryParams {}
12
+
13
+ export interface InputSchema {
14
+ email: string
15
+ token: string
16
+ [k: string]: unknown
17
+ }
18
+
19
+ export interface HandlerInput {
20
+ encoding: 'application/json'
21
+ body: InputSchema
22
+ }
23
+
24
+ export interface HandlerError {
25
+ status: number
26
+ message?: string
27
+ error?: 'AccountNotFound' | 'ExpiredToken' | 'InvalidToken' | 'InvalidEmail'
28
+ }
29
+
30
+ export type HandlerOutput = HandlerError | void
31
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
32
+ auth: HA
33
+ params: QueryParams
34
+ input: HandlerInput
35
+ req: express.Request
36
+ res: express.Response
37
+ }
38
+ export type Handler<HA extends HandlerAuth = never> = (
39
+ ctx: HandlerReqCtx<HA>,
40
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -17,6 +17,7 @@ export interface InputSchema {
17
17
  inviteCode?: string
18
18
  password: string
19
19
  recoveryKey?: string
20
+ plcOp?: Uint8Array
20
21
  [k: string]: unknown
21
22
  }
22
23
 
@@ -25,6 +26,7 @@ export interface OutputSchema {
25
26
  refreshJwt: string
26
27
  handle: string
27
28
  did: string
29
+ didDoc?: {}
28
30
  [k: string]: unknown
29
31
  }
30
32
 
@@ -22,7 +22,9 @@ export interface OutputSchema {
22
22
  refreshJwt: string
23
23
  handle: string
24
24
  did: string
25
+ didDoc?: {}
25
26
  email?: string
27
+ emailConfirmed?: boolean
26
28
  [k: string]: unknown
27
29
  }
28
30
 
@@ -16,6 +16,7 @@ export interface OutputSchema {
16
16
  handle: string
17
17
  did: string
18
18
  email?: string
19
+ emailConfirmed?: boolean
19
20
  [k: string]: unknown
20
21
  }
21
22
 
@@ -17,6 +17,7 @@ export interface OutputSchema {
17
17
  refreshJwt: string
18
18
  handle: string
19
19
  did: string
20
+ didDoc?: {}
20
21
  [k: string]: unknown
21
22
  }
22
23
 
@@ -0,0 +1,31 @@
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 } from '@atproto/xrpc-server'
10
+
11
+ export interface QueryParams {}
12
+
13
+ export type InputSchema = undefined
14
+ export type HandlerInput = undefined
15
+
16
+ export interface HandlerError {
17
+ status: number
18
+ message?: string
19
+ }
20
+
21
+ export type HandlerOutput = HandlerError | void
22
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
23
+ auth: HA
24
+ params: QueryParams
25
+ input: HandlerInput
26
+ req: express.Request
27
+ res: express.Response
28
+ }
29
+ export type Handler<HA extends HandlerAuth = never> = (
30
+ ctx: HandlerReqCtx<HA>,
31
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -0,0 +1,43 @@
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 } from '@atproto/xrpc-server'
10
+
11
+ export interface QueryParams {}
12
+
13
+ export type InputSchema = undefined
14
+
15
+ export interface OutputSchema {
16
+ tokenRequired: boolean
17
+ [k: string]: unknown
18
+ }
19
+
20
+ export type HandlerInput = undefined
21
+
22
+ export interface HandlerSuccess {
23
+ encoding: 'application/json'
24
+ body: OutputSchema
25
+ headers?: { [key: string]: string }
26
+ }
27
+
28
+ export interface HandlerError {
29
+ status: number
30
+ message?: string
31
+ }
32
+
33
+ export type HandlerOutput = HandlerError | HandlerSuccess
34
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
35
+ auth: HA
36
+ params: QueryParams
37
+ input: HandlerInput
38
+ req: express.Request
39
+ res: express.Response
40
+ }
41
+ export type Handler<HA extends HandlerAuth = never> = (
42
+ ctx: HandlerReqCtx<HA>,
43
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -0,0 +1,44 @@
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 } from '@atproto/xrpc-server'
10
+
11
+ export interface QueryParams {}
12
+
13
+ export type InputSchema = undefined
14
+
15
+ export interface OutputSchema {
16
+ /** Public signing key in the form of a did:key. */
17
+ signingKey: string
18
+ [k: string]: unknown
19
+ }
20
+
21
+ export type HandlerInput = undefined
22
+
23
+ export interface HandlerSuccess {
24
+ encoding: 'application/json'
25
+ body: OutputSchema
26
+ headers?: { [key: string]: string }
27
+ }
28
+
29
+ export interface HandlerError {
30
+ status: number
31
+ message?: string
32
+ }
33
+
34
+ export type HandlerOutput = HandlerError | HandlerSuccess
35
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
36
+ auth: HA
37
+ params: QueryParams
38
+ input: HandlerInput
39
+ req: express.Request
40
+ res: express.Response
41
+ }
42
+ export type Handler<HA extends HandlerAuth = never> = (
43
+ ctx: HandlerReqCtx<HA>,
44
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -0,0 +1,41 @@
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 } from '@atproto/xrpc-server'
10
+
11
+ export interface QueryParams {}
12
+
13
+ export interface InputSchema {
14
+ email: string
15
+ /** Requires a token from com.atproto.sever.requestEmailUpdate if the account's email has been confirmed. */
16
+ token?: string
17
+ [k: string]: unknown
18
+ }
19
+
20
+ export interface HandlerInput {
21
+ encoding: 'application/json'
22
+ body: InputSchema
23
+ }
24
+
25
+ export interface HandlerError {
26
+ status: number
27
+ message?: string
28
+ error?: 'ExpiredToken' | 'InvalidToken' | 'TokenRequired'
29
+ }
30
+
31
+ export type HandlerOutput = HandlerError | void
32
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
33
+ auth: HA
34
+ params: QueryParams
35
+ input: HandlerInput
36
+ req: express.Request
37
+ res: express.Response
38
+ }
39
+ export type Handler<HA extends HandlerAuth = never> = (
40
+ ctx: HandlerReqCtx<HA>,
41
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -49,6 +49,7 @@ export type Handler<HA extends HandlerAuth = never> = (
49
49
  export interface Repo {
50
50
  did: string
51
51
  head: string
52
+ rev: string
52
53
  [k: string]: unknown
53
54
  }
54
55
 
package/src/logger.ts CHANGED
@@ -12,4 +12,12 @@ export const httpLogger: ReturnType<typeof subsystemLogger> =
12
12
 
13
13
  export const loggerMiddleware = pinoHttp({
14
14
  logger: httpLogger,
15
+ serializers: {
16
+ err: (err) => {
17
+ return {
18
+ code: err?.code,
19
+ message: err?.message,
20
+ }
21
+ },
22
+ },
15
23
  })
@@ -66,7 +66,13 @@ export class ActorService {
66
66
  qb = qb.orWhere('actor.did', 'in', dids)
67
67
  }
68
68
  if (handles.length) {
69
- qb = qb.orWhere('actor.handle', 'in', handles)
69
+ qb = qb.orWhere(
70
+ 'actor.handle',
71
+ 'in',
72
+ handles.length === 1
73
+ ? [handles[0], handles[0]] // a silly (but worthwhile) optimization to avoid usage of actor_handle_tgrm_idx
74
+ : handles,
75
+ )
70
76
  }
71
77
  return qb
72
78
  })
@@ -83,15 +89,15 @@ export class ActorService {
83
89
  async getSearchResults({
84
90
  cursor,
85
91
  limit = 25,
86
- term = '',
92
+ query = '',
87
93
  includeSoftDeleted,
88
94
  }: {
89
95
  cursor?: string
90
96
  limit?: number
91
- term?: string
97
+ query?: string
92
98
  includeSoftDeleted?: boolean
93
99
  }) {
94
- const searchField = term.startsWith('did:') ? 'did' : 'handle'
100
+ const searchField = query.startsWith('did:') ? 'did' : 'handle'
95
101
  let paginatedBuilder
96
102
  const { ref } = this.db.db.dynamic
97
103
  const paginationOptions = {
@@ -101,10 +107,10 @@ export class ActorService {
101
107
  }
102
108
  let keyset
103
109
 
104
- if (term && searchField === 'handle') {
110
+ if (query && searchField === 'handle') {
105
111
  keyset = new SearchKeyset(sql``, sql``)
106
112
  paginatedBuilder = getUserSearchQuery(this.db, {
107
- term,
113
+ query,
108
114
  includeSoftDeleted,
109
115
  ...paginationOptions,
110
116
  }).select('distance')
@@ -114,10 +120,10 @@ export class ActorService {
114
120
  .select([sql<number>`0`.as('distance')])
115
121
  keyset = new ListKeyset(ref('indexedAt'), ref('did'))
116
122
 
117
- // When searchField === 'did', the term will always be a valid string because
118
- // searchField is set to 'did' after checking that the term is a valid did
119
- if (term && searchField === 'did') {
120
- paginatedBuilder = paginatedBuilder.where('actor.did', '=', term)
123
+ // When searchField === 'did', the query will always be a valid string because
124
+ // searchField is set to 'did' after checking that the query is a valid did
125
+ if (query && searchField === 'did') {
126
+ paginatedBuilder = paginatedBuilder.where('actor.did', '=', query)
121
127
  }
122
128
  paginatedBuilder = paginate(paginatedBuilder, {
123
129
  keyset,
@@ -16,6 +16,7 @@ export type ActorInfo = {
16
16
  mutedByList?: ListViewBasic
17
17
  blockedBy?: boolean
18
18
  blocking?: string
19
+ blockingByList?: ListViewBasic
19
20
  following?: string
20
21
  followedBy?: string
21
22
  }
@@ -137,10 +137,13 @@ export class ActorViews {
137
137
  ),
138
138
  ])
139
139
  const listUris = mapDefined(profiles, ({ did }) => {
140
- const list = viewer && bam.muteList([viewer, did])
141
- if (!list) return
142
- return list
143
- })
140
+ const muteList = viewer && bam.muteList([viewer, did])
141
+ const blockList = viewer && bam.blockList([viewer, did])
142
+ const lists: string[] = []
143
+ if (muteList) lists.push(muteList)
144
+ if (blockList) lists.push(blockList)
145
+ return lists
146
+ }).flat()
144
147
  const lists = await this.services.graph.getListViews(listUris, viewer)
145
148
  return { profilesDetailed: toMapByDid(profiles), labels, bam, lists }
146
149
  }
@@ -168,6 +171,11 @@ export class ActorViews {
168
171
  mutedByListUri && lists[mutedByListUri]
169
172
  ? this.services.graph.formatListViewBasic(lists[mutedByListUri])
170
173
  : undefined
174
+ const blockingByListUri = viewer && bam.blockList([viewer, did])
175
+ const blockingByList =
176
+ blockingByListUri && lists[blockingByListUri]
177
+ ? this.services.graph.formatListViewBasic(lists[blockingByListUri])
178
+ : undefined
171
179
  const actorLabels = labels[did] ?? []
172
180
  const selfLabels = getSelfLabels({
173
181
  uri: prof.profileUri,
@@ -194,6 +202,7 @@ export class ActorViews {
194
202
  mutedByList,
195
203
  blockedBy: !!bam.blockedBy([viewer, did]),
196
204
  blocking: bam.blocking([viewer, did]) ?? undefined,
205
+ blockingByList,
197
206
  following:
198
207
  prof?.viewerFollowing && !bam.block([viewer, did])
199
208
  ? prof.viewerFollowing
@@ -265,10 +274,13 @@ export class ActorViews {
265
274
  ),
266
275
  ])
267
276
  const listUris = mapDefined(profiles, ({ did }) => {
268
- const list = viewer && bam.muteList([viewer, did])
269
- if (!list) return
270
- return list
271
- })
277
+ const muteList = viewer && bam.muteList([viewer, did])
278
+ const blockList = viewer && bam.blockList([viewer, did])
279
+ const lists: string[] = []
280
+ if (muteList) lists.push(muteList)
281
+ if (blockList) lists.push(blockList)
282
+ return lists
283
+ }).flat()
272
284
  const lists = await this.services.graph.getListViews(listUris, viewer)
273
285
  return { profiles: toMapByDid(profiles), labels, bam, lists }
274
286
  }
@@ -298,6 +310,11 @@ export class ActorViews {
298
310
  mutedByListUri && lists[mutedByListUri]
299
311
  ? this.services.graph.formatListViewBasic(lists[mutedByListUri])
300
312
  : undefined
313
+ const blockingByListUri = viewer && bam.blockList([viewer, did])
314
+ const blockingByList =
315
+ blockingByListUri && lists[blockingByListUri]
316
+ ? this.services.graph.formatListViewBasic(lists[blockingByListUri])
317
+ : undefined
301
318
  const actorLabels = labels[did] ?? []
302
319
  const selfLabels = getSelfLabels({
303
320
  uri: prof.profileUri,
@@ -320,6 +337,7 @@ export class ActorViews {
320
337
  mutedByList,
321
338
  blockedBy: !!bam.blockedBy([viewer, did]),
322
339
  blocking: bam.blocking([viewer, did]) ?? undefined,
340
+ blockingByList,
323
341
  following:
324
342
  prof?.viewerFollowing && !bam.block([viewer, did])
325
343
  ? prof.viewerFollowing
@@ -267,28 +267,44 @@ export type RelationshipPair = [didA: string, didB: string]
267
267
  export class BlockAndMuteState {
268
268
  hasIdx = new Map<string, Set<string>>() // did -> did
269
269
  blockIdx = new Map<string, Map<string, string>>() // did -> did -> block uri
270
+ blockListIdx = new Map<string, Map<string, string>>() // did -> did -> list uri
270
271
  muteIdx = new Map<string, Set<string>>() // did -> did
271
272
  muteListIdx = new Map<string, Map<string, string>>() // did -> did -> list uri
272
273
  constructor(items: BlockAndMuteInfo[] = []) {
273
274
  items.forEach((item) => this.add(item))
274
275
  }
275
276
  add(item: BlockAndMuteInfo) {
276
- const blocking = item.blocking || item.blockingViaList // block or list uri
277
- if (blocking) {
277
+ if (item.source === item.target) {
278
+ return // we do not respect self-blocks or self-mutes
279
+ }
280
+ if (item.blocking) {
278
281
  const map = this.blockIdx.get(item.source) ?? new Map()
279
- map.set(item.target, blocking)
282
+ map.set(item.target, item.blocking)
280
283
  if (!this.blockIdx.has(item.source)) {
281
284
  this.blockIdx.set(item.source, map)
282
285
  }
283
286
  }
284
- const blockedBy = item.blockedBy || item.blockedByViaList // block or list uri
285
- if (blockedBy) {
287
+ if (item.blockingViaList) {
288
+ const map = this.blockListIdx.get(item.source) ?? new Map()
289
+ map.set(item.target, item.blockingViaList)
290
+ if (!this.blockListIdx.has(item.source)) {
291
+ this.blockListIdx.set(item.source, map)
292
+ }
293
+ }
294
+ if (item.blockedBy) {
286
295
  const map = this.blockIdx.get(item.target) ?? new Map()
287
- map.set(item.source, blockedBy)
296
+ map.set(item.source, item.blockedBy)
288
297
  if (!this.blockIdx.has(item.target)) {
289
298
  this.blockIdx.set(item.target, map)
290
299
  }
291
300
  }
301
+ if (item.blockedByViaList) {
302
+ const map = this.blockListIdx.get(item.target) ?? new Map()
303
+ map.set(item.source, item.blockedByViaList)
304
+ if (!this.blockListIdx.has(item.target)) {
305
+ this.blockListIdx.set(item.target, map)
306
+ }
307
+ }
292
308
  if (item.muting) {
293
309
  const set = this.muteIdx.get(item.source) ?? new Set()
294
310
  set.add(item.target)
@@ -314,7 +330,7 @@ export class BlockAndMuteState {
314
330
  }
315
331
  // block or list uri
316
332
  blocking(pair: RelationshipPair): string | null {
317
- return this.blockIdx.get(pair[0])?.get(pair[1]) ?? null
333
+ return this.blockIdx.get(pair[0])?.get(pair[1]) ?? this.blockList(pair)
318
334
  }
319
335
  // block or list uri
320
336
  blockedBy(pair: RelationshipPair): string | null {
@@ -324,6 +340,9 @@ export class BlockAndMuteState {
324
340
  return !!this.muteIdx.get(pair[0])?.has(pair[1]) || !!this.muteList(pair)
325
341
  }
326
342
  // list uri
343
+ blockList(pair: RelationshipPair): string | null {
344
+ return this.blockListIdx.get(pair[0])?.get(pair[1]) ?? null
345
+ }
327
346
  muteList(pair: RelationshipPair): string | null {
328
347
  return this.muteListIdx.get(pair[0])?.get(pair[1]) ?? null
329
348
  }
@@ -144,24 +144,22 @@ export class IndexingService {
144
144
  const handle: string | null =
145
145
  did === handleToDid ? atpData.handle.toLowerCase() : null
146
146
 
147
- if (actor && actor.handle !== handle) {
148
- const actorWithHandle =
149
- handle !== null
150
- ? await this.db.db
151
- .selectFrom('actor')
152
- .where('handle', '=', handle)
153
- .selectAll()
154
- .executeTakeFirst()
155
- : null
147
+ const actorWithHandle =
148
+ handle !== null
149
+ ? await this.db.db
150
+ .selectFrom('actor')
151
+ .where('handle', '=', handle)
152
+ .selectAll()
153
+ .executeTakeFirst()
154
+ : null
156
155
 
157
- // handle contention
158
- if (handle && actorWithHandle && did !== actorWithHandle.did) {
159
- await this.db.db
160
- .updateTable('actor')
161
- .where('actor.did', '=', actorWithHandle.did)
162
- .set({ handle: null })
163
- .execute()
164
- }
156
+ // handle contention
157
+ if (handle && actorWithHandle && did !== actorWithHandle.did) {
158
+ await this.db.db
159
+ .updateTable('actor')
160
+ .where('actor.did', '=', actorWithHandle.did)
161
+ .set({ handle: null })
162
+ .execute()
165
163
  }
166
164
 
167
165
  const actorInfo = { handle, indexedAt: timestamp }