@atproto/bsky 0.0.199 → 0.0.201

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 (170) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/api/app/bsky/ageassurance/begin.d.ts.map +1 -1
  3. package/dist/api/app/bsky/ageassurance/begin.js +1 -2
  4. package/dist/api/app/bsky/ageassurance/begin.js.map +1 -1
  5. package/dist/api/app/bsky/contact/dismissMatch.d.ts +4 -0
  6. package/dist/api/app/bsky/contact/dismissMatch.d.ts.map +1 -0
  7. package/dist/api/app/bsky/contact/dismissMatch.js +23 -0
  8. package/dist/api/app/bsky/contact/dismissMatch.js.map +1 -0
  9. package/dist/api/app/bsky/contact/getMatches.d.ts +4 -0
  10. package/dist/api/app/bsky/contact/getMatches.d.ts.map +1 -0
  11. package/dist/api/app/bsky/contact/getMatches.js +59 -0
  12. package/dist/api/app/bsky/contact/getMatches.js.map +1 -0
  13. package/dist/api/app/bsky/contact/getSyncStatus.d.ts +4 -0
  14. package/dist/api/app/bsky/contact/getSyncStatus.d.ts.map +1 -0
  15. package/dist/api/app/bsky/contact/getSyncStatus.js +32 -0
  16. package/dist/api/app/bsky/contact/getSyncStatus.js.map +1 -0
  17. package/dist/api/app/bsky/contact/importContacts.d.ts +4 -0
  18. package/dist/api/app/bsky/contact/importContacts.d.ts.map +1 -0
  19. package/dist/api/app/bsky/contact/importContacts.js +62 -0
  20. package/dist/api/app/bsky/contact/importContacts.js.map +1 -0
  21. package/dist/api/app/bsky/contact/removeData.d.ts +4 -0
  22. package/dist/api/app/bsky/contact/removeData.d.ts.map +1 -0
  23. package/dist/api/app/bsky/contact/removeData.js +22 -0
  24. package/dist/api/app/bsky/contact/removeData.js.map +1 -0
  25. package/dist/api/app/bsky/contact/sendNotification.d.ts +4 -0
  26. package/dist/api/app/bsky/contact/sendNotification.d.ts.map +1 -0
  27. package/dist/api/app/bsky/contact/sendNotification.js +30 -0
  28. package/dist/api/app/bsky/contact/sendNotification.js.map +1 -0
  29. package/dist/api/app/bsky/contact/startPhoneVerification.d.ts +4 -0
  30. package/dist/api/app/bsky/contact/startPhoneVerification.d.ts.map +1 -0
  31. package/dist/api/app/bsky/contact/startPhoneVerification.js +23 -0
  32. package/dist/api/app/bsky/contact/startPhoneVerification.js.map +1 -0
  33. package/dist/api/app/bsky/contact/util.d.ts +6 -0
  34. package/dist/api/app/bsky/contact/util.d.ts.map +1 -0
  35. package/dist/api/app/bsky/contact/util.js +10 -0
  36. package/dist/api/app/bsky/contact/util.js.map +1 -0
  37. package/dist/api/app/bsky/contact/verifyPhone.d.ts +4 -0
  38. package/dist/api/app/bsky/contact/verifyPhone.d.ts.map +1 -0
  39. package/dist/api/app/bsky/contact/verifyPhone.js +26 -0
  40. package/dist/api/app/bsky/contact/verifyPhone.js.map +1 -0
  41. package/dist/api/app/bsky/graph/getRelationships.d.ts.map +1 -1
  42. package/dist/api/app/bsky/graph/getRelationships.js +4 -0
  43. package/dist/api/app/bsky/graph/getRelationships.js.map +1 -1
  44. package/dist/api/index.d.ts.map +1 -1
  45. package/dist/api/index.js +14 -0
  46. package/dist/api/index.js.map +1 -1
  47. package/dist/config.d.ts +8 -0
  48. package/dist/config.d.ts.map +1 -1
  49. package/dist/config.js +21 -0
  50. package/dist/config.js.map +1 -1
  51. package/dist/context.d.ts +3 -0
  52. package/dist/context.d.ts.map +1 -1
  53. package/dist/context.js +3 -0
  54. package/dist/context.js.map +1 -1
  55. package/dist/hydration/actor.js +1 -1
  56. package/dist/hydration/actor.js.map +1 -1
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +12 -0
  59. package/dist/index.js.map +1 -1
  60. package/dist/lexicon/index.d.ts +21 -0
  61. package/dist/lexicon/index.d.ts.map +1 -1
  62. package/dist/lexicon/index.js +52 -1
  63. package/dist/lexicon/index.js.map +1 -1
  64. package/dist/lexicon/lexicons.d.ts +908 -102
  65. package/dist/lexicon/lexicons.d.ts.map +1 -1
  66. package/dist/lexicon/lexicons.js +427 -0
  67. package/dist/lexicon/lexicons.js.map +1 -1
  68. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +13 -1
  69. package/dist/lexicon/types/app/bsky/actor/defs.d.ts.map +1 -1
  70. package/dist/lexicon/types/app/bsky/actor/defs.js +9 -0
  71. package/dist/lexicon/types/app/bsky/actor/defs.js.map +1 -1
  72. package/dist/lexicon/types/app/bsky/contact/defs.d.ts +34 -0
  73. package/dist/lexicon/types/app/bsky/contact/defs.d.ts.map +1 -0
  74. package/dist/lexicon/types/app/bsky/contact/defs.js +34 -0
  75. package/dist/lexicon/types/app/bsky/contact/defs.js.map +1 -0
  76. package/dist/lexicon/types/app/bsky/contact/dismissMatch.d.ts +25 -0
  77. package/dist/lexicon/types/app/bsky/contact/dismissMatch.d.ts.map +1 -0
  78. package/dist/lexicon/types/app/bsky/contact/dismissMatch.js +7 -0
  79. package/dist/lexicon/types/app/bsky/contact/dismissMatch.js.map +1 -0
  80. package/dist/lexicon/types/app/bsky/contact/getMatches.d.ts +25 -0
  81. package/dist/lexicon/types/app/bsky/contact/getMatches.d.ts.map +1 -0
  82. package/dist/lexicon/types/app/bsky/contact/getMatches.js +7 -0
  83. package/dist/lexicon/types/app/bsky/contact/getMatches.js.map +1 -0
  84. package/dist/lexicon/types/app/bsky/contact/getSyncStatus.d.ts +21 -0
  85. package/dist/lexicon/types/app/bsky/contact/getSyncStatus.d.ts.map +1 -0
  86. package/dist/lexicon/types/app/bsky/contact/getSyncStatus.js +7 -0
  87. package/dist/lexicon/types/app/bsky/contact/getSyncStatus.js.map +1 -0
  88. package/dist/lexicon/types/app/bsky/contact/importContacts.d.ts +30 -0
  89. package/dist/lexicon/types/app/bsky/contact/importContacts.d.ts.map +1 -0
  90. package/dist/lexicon/types/app/bsky/contact/importContacts.js +7 -0
  91. package/dist/lexicon/types/app/bsky/contact/importContacts.js.map +1 -0
  92. package/dist/lexicon/types/app/bsky/contact/removeData.d.ts +23 -0
  93. package/dist/lexicon/types/app/bsky/contact/removeData.d.ts.map +1 -0
  94. package/dist/lexicon/types/app/bsky/contact/removeData.js +7 -0
  95. package/dist/lexicon/types/app/bsky/contact/removeData.js.map +1 -0
  96. package/dist/lexicon/types/app/bsky/contact/sendNotification.d.ts +26 -0
  97. package/dist/lexicon/types/app/bsky/contact/sendNotification.d.ts.map +1 -0
  98. package/dist/lexicon/types/app/bsky/contact/sendNotification.js +7 -0
  99. package/dist/lexicon/types/app/bsky/contact/sendNotification.js.map +1 -0
  100. package/dist/lexicon/types/app/bsky/contact/startPhoneVerification.d.ts +25 -0
  101. package/dist/lexicon/types/app/bsky/contact/startPhoneVerification.d.ts.map +1 -0
  102. package/dist/lexicon/types/app/bsky/contact/startPhoneVerification.js +7 -0
  103. package/dist/lexicon/types/app/bsky/contact/startPhoneVerification.js.map +1 -0
  104. package/dist/lexicon/types/app/bsky/contact/verifyPhone.d.ts +29 -0
  105. package/dist/lexicon/types/app/bsky/contact/verifyPhone.d.ts.map +1 -0
  106. package/dist/lexicon/types/app/bsky/contact/verifyPhone.js +7 -0
  107. package/dist/lexicon/types/app/bsky/contact/verifyPhone.js.map +1 -0
  108. package/dist/lexicon/types/app/bsky/graph/defs.d.ts +8 -0
  109. package/dist/lexicon/types/app/bsky/graph/defs.d.ts.map +1 -1
  110. package/dist/lexicon/types/app/bsky/graph/defs.js.map +1 -1
  111. package/dist/proto/bsky_pb.d.ts +0 -4
  112. package/dist/proto/bsky_pb.d.ts.map +1 -1
  113. package/dist/proto/bsky_pb.js +0 -10
  114. package/dist/proto/bsky_pb.js.map +1 -1
  115. package/dist/proto/rolodex_connect.d.ts +83 -0
  116. package/dist/proto/rolodex_connect.d.ts.map +1 -0
  117. package/dist/proto/rolodex_connect.js +90 -0
  118. package/dist/proto/rolodex_connect.js.map +1 -0
  119. package/dist/proto/rolodex_pb.d.ts +363 -0
  120. package/dist/proto/rolodex_pb.d.ts.map +1 -0
  121. package/dist/proto/rolodex_pb.js +1032 -0
  122. package/dist/proto/rolodex_pb.js.map +1 -0
  123. package/dist/rolodex.d.ts +9 -0
  124. package/dist/rolodex.d.ts.map +1 -0
  125. package/dist/rolodex.js +25 -0
  126. package/dist/rolodex.js.map +1 -0
  127. package/dist/stash.d.ts +2 -1
  128. package/dist/stash.d.ts.map +1 -1
  129. package/dist/stash.js +2 -1
  130. package/dist/stash.js.map +1 -1
  131. package/package.json +11 -11
  132. package/proto/rolodex.proto +116 -0
  133. package/src/api/app/bsky/ageassurance/begin.ts +1 -4
  134. package/src/api/app/bsky/contact/dismissMatch.ts +24 -0
  135. package/src/api/app/bsky/contact/getMatches.ts +111 -0
  136. package/src/api/app/bsky/contact/getSyncStatus.ts +35 -0
  137. package/src/api/app/bsky/contact/importContacts.ts +118 -0
  138. package/src/api/app/bsky/contact/removeData.ts +23 -0
  139. package/src/api/app/bsky/contact/sendNotification.ts +32 -0
  140. package/src/api/app/bsky/contact/startPhoneVerification.ts +24 -0
  141. package/src/api/app/bsky/contact/util.ts +13 -0
  142. package/src/api/app/bsky/contact/verifyPhone.ts +27 -0
  143. package/src/api/app/bsky/graph/getRelationships.ts +4 -0
  144. package/src/api/index.ts +14 -0
  145. package/src/config.ts +27 -0
  146. package/src/context.ts +6 -0
  147. package/src/hydration/actor.ts +1 -1
  148. package/src/index.ts +13 -0
  149. package/src/lexicon/index.ts +114 -0
  150. package/src/lexicon/lexicons.ts +454 -0
  151. package/src/lexicon/types/app/bsky/actor/defs.ts +22 -0
  152. package/src/lexicon/types/app/bsky/contact/defs.ts +71 -0
  153. package/src/lexicon/types/app/bsky/contact/dismissMatch.ts +43 -0
  154. package/src/lexicon/types/app/bsky/contact/getMatches.ts +43 -0
  155. package/src/lexicon/types/app/bsky/contact/getSyncStatus.ts +39 -0
  156. package/src/lexicon/types/app/bsky/contact/importContacts.ts +49 -0
  157. package/src/lexicon/types/app/bsky/contact/removeData.ts +40 -0
  158. package/src/lexicon/types/app/bsky/contact/sendNotification.ts +44 -0
  159. package/src/lexicon/types/app/bsky/contact/startPhoneVerification.ts +43 -0
  160. package/src/lexicon/types/app/bsky/contact/verifyPhone.ts +48 -0
  161. package/src/lexicon/types/app/bsky/graph/defs.ts +8 -0
  162. package/src/proto/bsky_pb.ts +0 -6
  163. package/src/proto/rolodex_connect.ts +89 -0
  164. package/src/proto/rolodex_pb.ts +746 -0
  165. package/src/rolodex.ts +42 -0
  166. package/src/stash.ts +5 -2
  167. package/tests/views/__snapshots__/profile.test.ts.snap +103 -0
  168. package/tests/views/age-assurance-v2.test.ts +8 -1
  169. package/tests/views/profile.test.ts +39 -0
  170. package/tsconfig.build.tsbuildinfo +1 -1
@@ -0,0 +1,118 @@
1
+ import { mapDefined } from '@atproto/common'
2
+ import { AppContext } from '../../../../context'
3
+ import {
4
+ HydrateCtx,
5
+ HydrationState,
6
+ Hydrator,
7
+ } from '../../../../hydration/hydrator'
8
+ import { Server } from '../../../../lexicon'
9
+ import { MatchAndContactIndex } from '../../../../lexicon/types/app/bsky/contact/defs'
10
+ import { InputSchema } from '../../../../lexicon/types/app/bsky/contact/importContacts'
11
+ import {
12
+ HydrationFnInput,
13
+ SkeletonFnInput,
14
+ createPipeline,
15
+ noRules,
16
+ } from '../../../../pipeline'
17
+ import { ImportContactsMatch } from '../../../../proto/rolodex_pb'
18
+ import { RolodexClient } from '../../../../rolodex'
19
+ import { Views } from '../../../../views'
20
+ import { assertRolodexOrThrowUnimplemented } from './util'
21
+
22
+ export default function (server: Server, ctx: AppContext) {
23
+ const importContacts = createPipeline(
24
+ skeleton,
25
+ hydration,
26
+ noRules, //
27
+ presentation,
28
+ )
29
+ server.app.bsky.contact.importContacts({
30
+ auth: ctx.authVerifier.standard,
31
+ handler: async ({ input, auth, req }) => {
32
+ assertRolodexOrThrowUnimplemented(ctx)
33
+
34
+ const viewer = auth.credentials.iss
35
+ const labelers = ctx.reqLabelers(req)
36
+ const hydrateCtx = await ctx.hydrator.createContext({
37
+ labelers,
38
+ viewer,
39
+ })
40
+
41
+ const result = await importContacts(
42
+ { ...input.body, hydrateCtx: hydrateCtx.copy({ viewer }) },
43
+ ctx,
44
+ )
45
+
46
+ return {
47
+ encoding: 'application/json',
48
+ body: result,
49
+ }
50
+ },
51
+ })
52
+ }
53
+
54
+ const skeleton = async (
55
+ input: SkeletonFnInput<Context, Params>,
56
+ ): Promise<SkeletonState> => {
57
+ const { params, ctx } = input
58
+ const actor = params.hydrateCtx.viewer
59
+ // TODO: Error handling.
60
+ const { matches } = await ctx.rolodexClient.importContacts({
61
+ actor: params.hydrateCtx.viewer,
62
+ contacts: params.contacts,
63
+ token: params.token,
64
+ })
65
+ return {
66
+ actor,
67
+ matches,
68
+ }
69
+ }
70
+
71
+ const hydration = async (
72
+ input: HydrationFnInput<Context, Params, SkeletonState>,
73
+ ) => {
74
+ const { ctx, params, skeleton } = input
75
+ const { matches } = skeleton
76
+ const subjects = matches.map((m) => m.subject)
77
+ return ctx.hydrator.hydrateProfiles(subjects, params.hydrateCtx)
78
+ }
79
+
80
+ const presentation = (input: {
81
+ ctx: Context
82
+ params: Params
83
+ skeleton: SkeletonState
84
+ hydration: HydrationState
85
+ }) => {
86
+ const { ctx, skeleton, hydration } = input
87
+ const matchesAndContactIndexes = mapDefined(
88
+ skeleton.matches,
89
+ ({ subject, inputIndex }): MatchAndContactIndex | undefined => {
90
+ const profile = ctx.views.profile(subject, hydration)
91
+
92
+ if (!profile) {
93
+ return undefined
94
+ }
95
+
96
+ return {
97
+ contactIndex: inputIndex,
98
+ match: profile,
99
+ }
100
+ },
101
+ )
102
+ return { matchesAndContactIndexes }
103
+ }
104
+
105
+ type Context = {
106
+ hydrator: Hydrator
107
+ rolodexClient: RolodexClient
108
+ views: Views
109
+ }
110
+
111
+ type Params = InputSchema & {
112
+ hydrateCtx: HydrateCtx & { viewer: string }
113
+ }
114
+
115
+ type SkeletonState = {
116
+ actor: string
117
+ matches: ImportContactsMatch[]
118
+ }
@@ -0,0 +1,23 @@
1
+ import { AppContext } from '../../../../context'
2
+ import { Server } from '../../../../lexicon'
3
+ import { assertRolodexOrThrowUnimplemented } from './util'
4
+
5
+ export default function (server: Server, ctx: AppContext) {
6
+ server.app.bsky.contact.removeData({
7
+ auth: ctx.authVerifier.standard,
8
+ handler: async ({ auth }) => {
9
+ assertRolodexOrThrowUnimplemented(ctx)
10
+
11
+ const actor = auth.credentials.iss
12
+ // TODO: Error handling.
13
+ await ctx.rolodexClient.removeData({
14
+ actor,
15
+ })
16
+
17
+ return {
18
+ encoding: 'application/json',
19
+ body: {},
20
+ }
21
+ },
22
+ })
23
+ }
@@ -0,0 +1,32 @@
1
+ import { TID } from '@atproto/common'
2
+ import { AppContext } from '../../../../context'
3
+ import { Server } from '../../../../lexicon'
4
+ import { Namespaces } from '../../../../stash'
5
+ import { assertRolodexOrThrowUnimplemented } from './util'
6
+
7
+ export default function (server: Server, ctx: AppContext) {
8
+ server.app.bsky.contact.sendNotification({
9
+ auth: ctx.authVerifier.role,
10
+ handler: async ({ input }) => {
11
+ // Assert rolodex even though we don't call it, it is a proxy to whether the app is configured with contact import support.
12
+ assertRolodexOrThrowUnimplemented(ctx)
13
+
14
+ const { from, to } = input.body
15
+
16
+ await ctx.stashClient.create({
17
+ actorDid: from,
18
+ namespace: Namespaces.AppBskyContactDefsNotification,
19
+ payload: {
20
+ from,
21
+ to,
22
+ },
23
+ key: TID.nextStr(),
24
+ })
25
+
26
+ return {
27
+ encoding: 'application/json',
28
+ body: {},
29
+ }
30
+ },
31
+ })
32
+ }
@@ -0,0 +1,24 @@
1
+ import { AppContext } from '../../../../context'
2
+ import { Server } from '../../../../lexicon'
3
+ import { assertRolodexOrThrowUnimplemented } from './util'
4
+
5
+ export default function (server: Server, ctx: AppContext) {
6
+ server.app.bsky.contact.startPhoneVerification({
7
+ auth: ctx.authVerifier.standard,
8
+ handler: async ({ auth, input }) => {
9
+ assertRolodexOrThrowUnimplemented(ctx)
10
+
11
+ const actor = auth.credentials.iss
12
+ // TODO: Error handling.
13
+ await ctx.rolodexClient.startPhoneVerification({
14
+ actor,
15
+ phone: input.body.phone,
16
+ })
17
+
18
+ return {
19
+ encoding: 'application/json',
20
+ body: {},
21
+ }
22
+ },
23
+ })
24
+ }
@@ -0,0 +1,13 @@
1
+ import { MethodNotImplementedError } from '@atproto/xrpc-server'
2
+ import { AppContext } from '../../../..'
3
+ import { RolodexClient } from '../../../../rolodex'
4
+
5
+ export function assertRolodexOrThrowUnimplemented(
6
+ ctx: AppContext,
7
+ ): asserts ctx is AppContext & { rolodexClient: RolodexClient } {
8
+ if (!ctx.rolodexClient) {
9
+ throw new MethodNotImplementedError(
10
+ 'This service is not configured to support contact imports.',
11
+ )
12
+ }
13
+ }
@@ -0,0 +1,27 @@
1
+ import { AppContext } from '../../../../context'
2
+ import { Server } from '../../../../lexicon'
3
+ import { assertRolodexOrThrowUnimplemented } from './util'
4
+
5
+ export default function (server: Server, ctx: AppContext) {
6
+ server.app.bsky.contact.verifyPhone({
7
+ auth: ctx.authVerifier.standard,
8
+ handler: async ({ auth, input }) => {
9
+ assertRolodexOrThrowUnimplemented(ctx)
10
+
11
+ const actor = auth.credentials.iss
12
+ // TODO: Error handling.
13
+ const res = await ctx.rolodexClient.verifyPhone({
14
+ actor,
15
+ verificationCode: input.body.code,
16
+ phone: input.body.phone,
17
+ })
18
+
19
+ return {
20
+ encoding: 'application/json',
21
+ body: {
22
+ token: res.token,
23
+ },
24
+ }
25
+ },
26
+ })
27
+ }
@@ -26,6 +26,10 @@ export default function (server: Server, ctx: AppContext) {
26
26
  did,
27
27
  following: subject.following,
28
28
  followedBy: subject.followedBy,
29
+ blocking: subject.blocking,
30
+ blockedBy: subject.blockedBy,
31
+ blockingByList: subject.blockingByList,
32
+ blockedByList: subject.blockedByList,
29
33
  }
30
34
  : {
31
35
  $type: 'app.bsky.graph.defs#notFoundActor',
package/src/api/index.ts CHANGED
@@ -11,6 +11,13 @@ import aaGetState from './app/bsky/ageassurance/getState'
11
11
  import createBookmark from './app/bsky/bookmark/createBookmark'
12
12
  import deleteBookmark from './app/bsky/bookmark/deleteBookmark'
13
13
  import getBookmarks from './app/bsky/bookmark/getBookmarks'
14
+ import dismissMatch from './app/bsky/contact/dismissMatch'
15
+ import getMatches from './app/bsky/contact/getMatches'
16
+ import getSyncStatus from './app/bsky/contact/getSyncStatus'
17
+ import importContacts from './app/bsky/contact/importContacts'
18
+ import removeData from './app/bsky/contact/removeData'
19
+ import startPhoneVerification from './app/bsky/contact/startPhoneVerification'
20
+ import verifyPhone from './app/bsky/contact/verifyPhone'
14
21
  import getActorFeeds from './app/bsky/feed/getActorFeeds'
15
22
  import getActorLikes from './app/bsky/feed/getActorLikes'
16
23
  import getAuthorFeed from './app/bsky/feed/getAuthorFeed'
@@ -94,6 +101,13 @@ export default function (server: Server, ctx: AppContext) {
94
101
  createBookmark(server, ctx)
95
102
  deleteBookmark(server, ctx)
96
103
  getBookmarks(server, ctx)
104
+ dismissMatch(server, ctx)
105
+ getMatches(server, ctx)
106
+ getSyncStatus(server, ctx)
107
+ importContacts(server, ctx)
108
+ removeData(server, ctx)
109
+ startPhoneVerification(server, ctx)
110
+ verifyPhone(server, ctx)
97
111
  getActorFeeds(server, ctx)
98
112
  getSuggestedFeeds(server, ctx)
99
113
  getAuthorFeed(server, ctx)
package/src/config.ts CHANGED
@@ -55,6 +55,10 @@ export interface ServerConfigValues {
55
55
  courierApiKey?: string
56
56
  courierHttpVersion?: '1.1' | '2'
57
57
  courierIgnoreBadTls?: boolean
58
+ rolodexUrl?: string
59
+ rolodexApiKey?: string
60
+ rolodexHttpVersion?: '1.1' | '2'
61
+ rolodexIgnoreBadTls?: boolean
58
62
  searchUrl?: string
59
63
  searchTagsHide: Set<string>
60
64
  suggestionsUrl?: string
@@ -186,6 +190,12 @@ export class ServerConfig {
186
190
  const courierIgnoreBadTls =
187
191
  process.env.BSKY_COURIER_IGNORE_BAD_TLS === 'true'
188
192
  assert(courierHttpVersion === '1.1' || courierHttpVersion === '2')
193
+ const rolodexUrl = process.env.BSKY_ROLODEX_URL || undefined
194
+ const rolodexApiKey = process.env.BSKY_ROLODEX_API_KEY || undefined
195
+ const rolodexHttpVersion = process.env.BSKY_ROLODEX_HTTP_VERSION || '2'
196
+ const rolodexIgnoreBadTls =
197
+ process.env.BSKY_ROLODEX_IGNORE_BAD_TLS === 'true'
198
+ assert(rolodexHttpVersion === '1.1' || rolodexHttpVersion === '2')
189
199
  const blobRateLimitBypassKey =
190
200
  process.env.BSKY_BLOB_RATE_LIMIT_BYPASS_KEY || undefined
191
201
  // single domain would be e.g. "mypds.com", subdomains are supported with a leading dot e.g. ".mypds.com"
@@ -347,6 +357,10 @@ export class ServerConfig {
347
357
  courierApiKey,
348
358
  courierHttpVersion,
349
359
  courierIgnoreBadTls,
360
+ rolodexUrl,
361
+ rolodexApiKey,
362
+ rolodexHttpVersion,
363
+ rolodexIgnoreBadTls,
350
364
  blobRateLimitBypassKey,
351
365
  blobRateLimitBypassHostname,
352
366
  adminPasswords,
@@ -470,6 +484,19 @@ export class ServerConfig {
470
484
  return this.cfg.courierIgnoreBadTls
471
485
  }
472
486
 
487
+ get rolodexUrl() {
488
+ return this.cfg.rolodexUrl
489
+ }
490
+ get rolodexApiKey() {
491
+ return this.cfg.rolodexApiKey
492
+ }
493
+ get rolodexHttpVersion() {
494
+ return this.cfg.rolodexHttpVersion
495
+ }
496
+ get rolodexIgnoreBadTls() {
497
+ return this.cfg.rolodexIgnoreBadTls
498
+ }
499
+
473
500
  get searchUrl() {
474
501
  return this.cfg.searchUrl
475
502
  }
package/src/context.ts CHANGED
@@ -14,6 +14,7 @@ import { FeatureGates } from './feature-gates'
14
14
  import { Hydrator } from './hydration/hydrator'
15
15
  import { KwsClient } from './kws'
16
16
  import { httpLogger as log } from './logger'
17
+ import { RolodexClient } from './rolodex'
17
18
  import { StashClient } from './stash'
18
19
  import {
19
20
  ParsedLabelers,
@@ -39,6 +40,7 @@ export class AppContext {
39
40
  bsyncClient: BsyncClient
40
41
  stashClient: StashClient
41
42
  courierClient: CourierClient | undefined
43
+ rolodexClient: RolodexClient | undefined
42
44
  authVerifier: AuthVerifier
43
45
  featureGates: FeatureGates
44
46
  blobDispatcher: Dispatcher
@@ -106,6 +108,10 @@ export class AppContext {
106
108
  return this.opts.courierClient
107
109
  }
108
110
 
111
+ get rolodexClient(): RolodexClient | undefined {
112
+ return this.opts.rolodexClient
113
+ }
114
+
109
115
  get authVerifier(): AuthVerifier {
110
116
  return this.opts.authVerifier
111
117
  }
@@ -179,7 +179,7 @@ export class ActorHydrator {
179
179
  return acc.set(did, null)
180
180
  }
181
181
 
182
- const profile = actor.profile
182
+ const profile = actor.profile?.record
183
183
  ? parseRecord<ProfileRecord>(actor.profile, includeTakedowns)
184
184
  : undefined
185
185
 
package/src/index.ts CHANGED
@@ -30,6 +30,7 @@ import { ImageUriBuilder } from './image/uri'
30
30
  import { createKwsClient } from './kws'
31
31
  import { createServer } from './lexicon'
32
32
  import { loggerMiddleware } from './logger'
33
+ import { authWithApiKey as rolodexAuth, createRolodexClient } from './rolodex'
33
34
  import { createStashClient } from './stash'
34
35
  import { Views } from './views'
35
36
  import { VideoUriBuilder } from './views/util'
@@ -156,6 +157,17 @@ export class BskyAppView {
156
157
  })
157
158
  : undefined
158
159
 
160
+ const rolodexClient = config.rolodexUrl
161
+ ? createRolodexClient({
162
+ baseUrl: config.rolodexUrl,
163
+ httpVersion: config.rolodexHttpVersion ?? '2',
164
+ nodeOptions: { rejectUnauthorized: !config.rolodexIgnoreBadTls },
165
+ interceptors: config.rolodexApiKey
166
+ ? [rolodexAuth(config.rolodexApiKey)]
167
+ : [],
168
+ })
169
+ : undefined
170
+
159
171
  const kwsClient = config.kws ? createKwsClient(config.kws) : undefined
160
172
 
161
173
  const entrywayJwtPublicKey = config.entrywayJwtPublicKeyHex
@@ -191,6 +203,7 @@ export class BskyAppView {
191
203
  bsyncClient,
192
204
  stashClient,
193
205
  courierClient,
206
+ rolodexClient,
194
207
  authVerifier,
195
208
  featureGates,
196
209
  blobDispatcher,
@@ -23,6 +23,14 @@ import * as AppBskyAgeassuranceGetState from './types/app/bsky/ageassurance/getS
23
23
  import * as AppBskyBookmarkCreateBookmark from './types/app/bsky/bookmark/createBookmark.js'
24
24
  import * as AppBskyBookmarkDeleteBookmark from './types/app/bsky/bookmark/deleteBookmark.js'
25
25
  import * as AppBskyBookmarkGetBookmarks from './types/app/bsky/bookmark/getBookmarks.js'
26
+ import * as AppBskyContactDismissMatch from './types/app/bsky/contact/dismissMatch.js'
27
+ import * as AppBskyContactGetMatches from './types/app/bsky/contact/getMatches.js'
28
+ import * as AppBskyContactGetSyncStatus from './types/app/bsky/contact/getSyncStatus.js'
29
+ import * as AppBskyContactImportContacts from './types/app/bsky/contact/importContacts.js'
30
+ import * as AppBskyContactRemoveData from './types/app/bsky/contact/removeData.js'
31
+ import * as AppBskyContactSendNotification from './types/app/bsky/contact/sendNotification.js'
32
+ import * as AppBskyContactStartPhoneVerification from './types/app/bsky/contact/startPhoneVerification.js'
33
+ import * as AppBskyContactVerifyPhone from './types/app/bsky/contact/verifyPhone.js'
26
34
  import * as AppBskyFeedDescribeFeedGenerator from './types/app/bsky/feed/describeFeedGenerator.js'
27
35
  import * as AppBskyFeedGetActorFeeds from './types/app/bsky/feed/getActorFeeds.js'
28
36
  import * as AppBskyFeedGetActorLikes from './types/app/bsky/feed/getActorLikes.js'
@@ -276,6 +284,7 @@ export class AppBskyNS {
276
284
  actor: AppBskyActorNS
277
285
  ageassurance: AppBskyAgeassuranceNS
278
286
  bookmark: AppBskyBookmarkNS
287
+ contact: AppBskyContactNS
279
288
  embed: AppBskyEmbedNS
280
289
  feed: AppBskyFeedNS
281
290
  graph: AppBskyGraphNS
@@ -290,6 +299,7 @@ export class AppBskyNS {
290
299
  this.actor = new AppBskyActorNS(server)
291
300
  this.ageassurance = new AppBskyAgeassuranceNS(server)
292
301
  this.bookmark = new AppBskyBookmarkNS(server)
302
+ this.contact = new AppBskyContactNS(server)
293
303
  this.embed = new AppBskyEmbedNS(server)
294
304
  this.feed = new AppBskyFeedNS(server)
295
305
  this.graph = new AppBskyGraphNS(server)
@@ -481,6 +491,110 @@ export class AppBskyBookmarkNS {
481
491
  }
482
492
  }
483
493
 
494
+ export class AppBskyContactNS {
495
+ _server: Server
496
+
497
+ constructor(server: Server) {
498
+ this._server = server
499
+ }
500
+
501
+ dismissMatch<A extends Auth = void>(
502
+ cfg: MethodConfigOrHandler<
503
+ A,
504
+ AppBskyContactDismissMatch.QueryParams,
505
+ AppBskyContactDismissMatch.HandlerInput,
506
+ AppBskyContactDismissMatch.HandlerOutput
507
+ >,
508
+ ) {
509
+ const nsid = 'app.bsky.contact.dismissMatch' // @ts-ignore
510
+ return this._server.xrpc.method(nsid, cfg)
511
+ }
512
+
513
+ getMatches<A extends Auth = void>(
514
+ cfg: MethodConfigOrHandler<
515
+ A,
516
+ AppBskyContactGetMatches.QueryParams,
517
+ AppBskyContactGetMatches.HandlerInput,
518
+ AppBskyContactGetMatches.HandlerOutput
519
+ >,
520
+ ) {
521
+ const nsid = 'app.bsky.contact.getMatches' // @ts-ignore
522
+ return this._server.xrpc.method(nsid, cfg)
523
+ }
524
+
525
+ getSyncStatus<A extends Auth = void>(
526
+ cfg: MethodConfigOrHandler<
527
+ A,
528
+ AppBskyContactGetSyncStatus.QueryParams,
529
+ AppBskyContactGetSyncStatus.HandlerInput,
530
+ AppBskyContactGetSyncStatus.HandlerOutput
531
+ >,
532
+ ) {
533
+ const nsid = 'app.bsky.contact.getSyncStatus' // @ts-ignore
534
+ return this._server.xrpc.method(nsid, cfg)
535
+ }
536
+
537
+ importContacts<A extends Auth = void>(
538
+ cfg: MethodConfigOrHandler<
539
+ A,
540
+ AppBskyContactImportContacts.QueryParams,
541
+ AppBskyContactImportContacts.HandlerInput,
542
+ AppBskyContactImportContacts.HandlerOutput
543
+ >,
544
+ ) {
545
+ const nsid = 'app.bsky.contact.importContacts' // @ts-ignore
546
+ return this._server.xrpc.method(nsid, cfg)
547
+ }
548
+
549
+ removeData<A extends Auth = void>(
550
+ cfg: MethodConfigOrHandler<
551
+ A,
552
+ AppBskyContactRemoveData.QueryParams,
553
+ AppBskyContactRemoveData.HandlerInput,
554
+ AppBskyContactRemoveData.HandlerOutput
555
+ >,
556
+ ) {
557
+ const nsid = 'app.bsky.contact.removeData' // @ts-ignore
558
+ return this._server.xrpc.method(nsid, cfg)
559
+ }
560
+
561
+ sendNotification<A extends Auth = void>(
562
+ cfg: MethodConfigOrHandler<
563
+ A,
564
+ AppBskyContactSendNotification.QueryParams,
565
+ AppBskyContactSendNotification.HandlerInput,
566
+ AppBskyContactSendNotification.HandlerOutput
567
+ >,
568
+ ) {
569
+ const nsid = 'app.bsky.contact.sendNotification' // @ts-ignore
570
+ return this._server.xrpc.method(nsid, cfg)
571
+ }
572
+
573
+ startPhoneVerification<A extends Auth = void>(
574
+ cfg: MethodConfigOrHandler<
575
+ A,
576
+ AppBskyContactStartPhoneVerification.QueryParams,
577
+ AppBskyContactStartPhoneVerification.HandlerInput,
578
+ AppBskyContactStartPhoneVerification.HandlerOutput
579
+ >,
580
+ ) {
581
+ const nsid = 'app.bsky.contact.startPhoneVerification' // @ts-ignore
582
+ return this._server.xrpc.method(nsid, cfg)
583
+ }
584
+
585
+ verifyPhone<A extends Auth = void>(
586
+ cfg: MethodConfigOrHandler<
587
+ A,
588
+ AppBskyContactVerifyPhone.QueryParams,
589
+ AppBskyContactVerifyPhone.HandlerInput,
590
+ AppBskyContactVerifyPhone.HandlerOutput
591
+ >,
592
+ ) {
593
+ const nsid = 'app.bsky.contact.verifyPhone' // @ts-ignore
594
+ return this._server.xrpc.method(nsid, cfg)
595
+ }
596
+ }
597
+
484
598
  export class AppBskyEmbedNS {
485
599
  _server: Server
486
600