@atproto/pds 0.4.32 → 0.4.34

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/actor-store/preference/reader.d.ts +2 -1
  3. package/dist/actor-store/preference/reader.d.ts.map +1 -1
  4. package/dist/actor-store/preference/reader.js +3 -1
  5. package/dist/actor-store/preference/reader.js.map +1 -1
  6. package/dist/actor-store/preference/transactor.d.ts +2 -1
  7. package/dist/actor-store/preference/transactor.d.ts.map +1 -1
  8. package/dist/actor-store/preference/transactor.js +7 -1
  9. package/dist/actor-store/preference/transactor.js.map +1 -1
  10. package/dist/actor-store/preference/util.d.ts +3 -0
  11. package/dist/actor-store/preference/util.d.ts.map +1 -0
  12. package/dist/actor-store/preference/util.js +12 -0
  13. package/dist/actor-store/preference/util.js.map +1 -0
  14. package/dist/api/app/bsky/actor/getPreferences.d.ts.map +1 -1
  15. package/dist/api/app/bsky/actor/getPreferences.js +1 -6
  16. package/dist/api/app/bsky/actor/getPreferences.js.map +1 -1
  17. package/dist/api/app/bsky/actor/putPreferences.d.ts.map +1 -1
  18. package/dist/api/app/bsky/actor/putPreferences.js +1 -1
  19. package/dist/api/app/bsky/actor/putPreferences.js.map +1 -1
  20. package/dist/lexicon/index.d.ts +6 -0
  21. package/dist/lexicon/index.d.ts.map +1 -1
  22. package/dist/lexicon/index.js +12 -0
  23. package/dist/lexicon/index.js.map +1 -1
  24. package/dist/lexicon/lexicons.d.ts +127 -0
  25. package/dist/lexicon/lexicons.d.ts.map +1 -1
  26. package/dist/lexicon/lexicons.js +127 -0
  27. package/dist/lexicon/lexicons.js.map +1 -1
  28. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +9 -0
  29. package/dist/lexicon/types/app/bsky/actor/defs.d.ts.map +1 -1
  30. package/dist/lexicon/types/app/bsky/actor/defs.js +11 -1
  31. package/dist/lexicon/types/app/bsky/actor/defs.js.map +1 -1
  32. package/dist/lexicon/types/app/bsky/feed/defs.d.ts +1 -0
  33. package/dist/lexicon/types/app/bsky/feed/defs.d.ts.map +1 -1
  34. package/dist/lexicon/types/app/bsky/feed/defs.js.map +1 -1
  35. package/dist/lexicon/types/app/bsky/graph/getKnownFollowers.d.ts +40 -0
  36. package/dist/lexicon/types/app/bsky/graph/getKnownFollowers.d.ts.map +1 -0
  37. package/dist/lexicon/types/app/bsky/graph/getKnownFollowers.js +3 -0
  38. package/dist/lexicon/types/app/bsky/graph/getKnownFollowers.js.map +1 -0
  39. package/dist/lexicon/types/app/bsky/graph/muteThread.d.ts +29 -0
  40. package/dist/lexicon/types/app/bsky/graph/muteThread.d.ts.map +1 -0
  41. package/dist/lexicon/types/app/bsky/graph/muteThread.js +3 -0
  42. package/dist/lexicon/types/app/bsky/graph/muteThread.js.map +1 -0
  43. package/dist/lexicon/types/app/bsky/graph/unmuteThread.d.ts +29 -0
  44. package/dist/lexicon/types/app/bsky/graph/unmuteThread.d.ts.map +1 -0
  45. package/dist/lexicon/types/app/bsky/graph/unmuteThread.js +3 -0
  46. package/dist/lexicon/types/app/bsky/graph/unmuteThread.js.map +1 -0
  47. package/package.json +4 -4
  48. package/src/actor-store/preference/reader.ts +7 -1
  49. package/src/actor-store/preference/transactor.ts +10 -0
  50. package/src/actor-store/preference/util.ts +8 -0
  51. package/src/api/app/bsky/actor/getPreferences.ts +2 -9
  52. package/src/api/app/bsky/actor/putPreferences.ts +5 -1
  53. package/src/lexicon/index.ts +36 -0
  54. package/src/lexicon/lexicons.ts +129 -0
  55. package/src/lexicon/types/app/bsky/actor/defs.ts +20 -0
  56. package/src/lexicon/types/app/bsky/feed/defs.ts +1 -0
  57. package/src/lexicon/types/app/bsky/graph/getKnownFollowers.ts +50 -0
  58. package/src/lexicon/types/app/bsky/graph/muteThread.ts +38 -0
  59. package/src/lexicon/types/app/bsky/graph/unmuteThread.ts +38 -0
  60. package/tests/handle-validation.test.ts +1 -1
  61. package/tests/preferences.test.ts +67 -1
  62. package/tests/proxied/__snapshots__/feedgen.test.ts.snap +4 -1
  63. package/tests/proxied/__snapshots__/views.test.ts.snap +193 -42
@@ -4107,6 +4107,29 @@ export const schemaDict = {
4107
4107
  type: 'string',
4108
4108
  format: 'at-uri',
4109
4109
  },
4110
+ knownFollowers: {
4111
+ type: 'ref',
4112
+ ref: 'lex:app.bsky.actor.defs#knownFollowers',
4113
+ },
4114
+ },
4115
+ },
4116
+ knownFollowers: {
4117
+ type: 'object',
4118
+ description: "The subject's followers whom you also follow",
4119
+ required: ['count', 'followers'],
4120
+ properties: {
4121
+ count: {
4122
+ type: 'integer',
4123
+ },
4124
+ followers: {
4125
+ type: 'array',
4126
+ minLength: 0,
4127
+ maxLength: 5,
4128
+ items: {
4129
+ type: 'ref',
4130
+ ref: 'lex:app.bsky.actor.defs#profileViewBasic',
4131
+ },
4132
+ },
4110
4133
  },
4111
4134
  },
4112
4135
  preferences: {
@@ -5079,6 +5102,9 @@ export const schemaDict = {
5079
5102
  type: 'string',
5080
5103
  format: 'at-uri',
5081
5104
  },
5105
+ threadMuted: {
5106
+ type: 'boolean',
5107
+ },
5082
5108
  replyDisabled: {
5083
5109
  type: 'boolean',
5084
5110
  },
@@ -7101,6 +7127,59 @@ export const schemaDict = {
7101
7127
  },
7102
7128
  },
7103
7129
  },
7130
+ AppBskyGraphGetKnownFollowers: {
7131
+ lexicon: 1,
7132
+ id: 'app.bsky.graph.getKnownFollowers',
7133
+ defs: {
7134
+ main: {
7135
+ type: 'query',
7136
+ description:
7137
+ 'Enumerates accounts which follow a specified account (actor) and are followed by the viewer.',
7138
+ parameters: {
7139
+ type: 'params',
7140
+ required: ['actor'],
7141
+ properties: {
7142
+ actor: {
7143
+ type: 'string',
7144
+ format: 'at-identifier',
7145
+ },
7146
+ limit: {
7147
+ type: 'integer',
7148
+ minimum: 1,
7149
+ maximum: 100,
7150
+ default: 50,
7151
+ },
7152
+ cursor: {
7153
+ type: 'string',
7154
+ },
7155
+ },
7156
+ },
7157
+ output: {
7158
+ encoding: 'application/json',
7159
+ schema: {
7160
+ type: 'object',
7161
+ required: ['subject', 'followers'],
7162
+ properties: {
7163
+ subject: {
7164
+ type: 'ref',
7165
+ ref: 'lex:app.bsky.actor.defs#profileView',
7166
+ },
7167
+ cursor: {
7168
+ type: 'string',
7169
+ },
7170
+ followers: {
7171
+ type: 'array',
7172
+ items: {
7173
+ type: 'ref',
7174
+ ref: 'lex:app.bsky.actor.defs#profileView',
7175
+ },
7176
+ },
7177
+ },
7178
+ },
7179
+ },
7180
+ },
7181
+ },
7182
+ },
7104
7183
  AppBskyGraphGetList: {
7105
7184
  lexicon: 1,
7106
7185
  id: 'app.bsky.graph.getList',
@@ -7599,6 +7678,30 @@ export const schemaDict = {
7599
7678
  },
7600
7679
  },
7601
7680
  },
7681
+ AppBskyGraphMuteThread: {
7682
+ lexicon: 1,
7683
+ id: 'app.bsky.graph.muteThread',
7684
+ defs: {
7685
+ main: {
7686
+ type: 'procedure',
7687
+ description:
7688
+ 'Mutes a thread preventing notifications from the thread and any of its children. Mutes are private in Bluesky. Requires auth.',
7689
+ input: {
7690
+ encoding: 'application/json',
7691
+ schema: {
7692
+ type: 'object',
7693
+ required: ['root'],
7694
+ properties: {
7695
+ root: {
7696
+ type: 'string',
7697
+ format: 'at-uri',
7698
+ },
7699
+ },
7700
+ },
7701
+ },
7702
+ },
7703
+ },
7704
+ },
7602
7705
  AppBskyGraphUnmuteActor: {
7603
7706
  lexicon: 1,
7604
7707
  id: 'app.bsky.graph.unmuteActor',
@@ -7645,6 +7748,29 @@ export const schemaDict = {
7645
7748
  },
7646
7749
  },
7647
7750
  },
7751
+ AppBskyGraphUnmuteThread: {
7752
+ lexicon: 1,
7753
+ id: 'app.bsky.graph.unmuteThread',
7754
+ defs: {
7755
+ main: {
7756
+ type: 'procedure',
7757
+ description: 'Unmutes the specified thread. Requires auth.',
7758
+ input: {
7759
+ encoding: 'application/json',
7760
+ schema: {
7761
+ type: 'object',
7762
+ required: ['root'],
7763
+ properties: {
7764
+ root: {
7765
+ type: 'string',
7766
+ format: 'at-uri',
7767
+ },
7768
+ },
7769
+ },
7770
+ },
7771
+ },
7772
+ },
7773
+ },
7648
7774
  AppBskyLabelerDefs: {
7649
7775
  lexicon: 1,
7650
7776
  id: 'app.bsky.labeler.defs',
@@ -11015,6 +11141,7 @@ export const ids = {
11015
11141
  AppBskyGraphGetBlocks: 'app.bsky.graph.getBlocks',
11016
11142
  AppBskyGraphGetFollowers: 'app.bsky.graph.getFollowers',
11017
11143
  AppBskyGraphGetFollows: 'app.bsky.graph.getFollows',
11144
+ AppBskyGraphGetKnownFollowers: 'app.bsky.graph.getKnownFollowers',
11018
11145
  AppBskyGraphGetList: 'app.bsky.graph.getList',
11019
11146
  AppBskyGraphGetListBlocks: 'app.bsky.graph.getListBlocks',
11020
11147
  AppBskyGraphGetListMutes: 'app.bsky.graph.getListMutes',
@@ -11028,8 +11155,10 @@ export const ids = {
11028
11155
  AppBskyGraphListitem: 'app.bsky.graph.listitem',
11029
11156
  AppBskyGraphMuteActor: 'app.bsky.graph.muteActor',
11030
11157
  AppBskyGraphMuteActorList: 'app.bsky.graph.muteActorList',
11158
+ AppBskyGraphMuteThread: 'app.bsky.graph.muteThread',
11031
11159
  AppBskyGraphUnmuteActor: 'app.bsky.graph.unmuteActor',
11032
11160
  AppBskyGraphUnmuteActorList: 'app.bsky.graph.unmuteActorList',
11161
+ AppBskyGraphUnmuteThread: 'app.bsky.graph.unmuteThread',
11033
11162
  AppBskyLabelerDefs: 'app.bsky.labeler.defs',
11034
11163
  AppBskyLabelerGetServices: 'app.bsky.labeler.getServices',
11035
11164
  AppBskyLabelerService: 'app.bsky.labeler.service',
@@ -133,6 +133,7 @@ export interface ViewerState {
133
133
  blockingByList?: AppBskyGraphDefs.ListViewBasic
134
134
  following?: string
135
135
  followedBy?: string
136
+ knownFollowers?: KnownFollowers
136
137
  [k: string]: unknown
137
138
  }
138
139
 
@@ -148,6 +149,25 @@ export function validateViewerState(v: unknown): ValidationResult {
148
149
  return lexicons.validate('app.bsky.actor.defs#viewerState', v)
149
150
  }
150
151
 
152
+ /** The subject's followers whom you also follow */
153
+ export interface KnownFollowers {
154
+ count: number
155
+ followers: ProfileViewBasic[]
156
+ [k: string]: unknown
157
+ }
158
+
159
+ export function isKnownFollowers(v: unknown): v is KnownFollowers {
160
+ return (
161
+ isObj(v) &&
162
+ hasProp(v, '$type') &&
163
+ v.$type === 'app.bsky.actor.defs#knownFollowers'
164
+ )
165
+ }
166
+
167
+ export function validateKnownFollowers(v: unknown): ValidationResult {
168
+ return lexicons.validate('app.bsky.actor.defs#knownFollowers', v)
169
+ }
170
+
151
171
  export type Preferences = (
152
172
  | AdultContentPref
153
173
  | ContentLabelPref
@@ -49,6 +49,7 @@ export function validatePostView(v: unknown): ValidationResult {
49
49
  export interface ViewerState {
50
50
  repost?: string
51
51
  like?: string
52
+ threadMuted?: boolean
52
53
  replyDisabled?: boolean
53
54
  [k: string]: unknown
54
55
  }
@@ -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 AppBskyActorDefs from '../actor/defs'
11
+
12
+ export interface QueryParams {
13
+ actor: string
14
+ limit: number
15
+ cursor?: string
16
+ }
17
+
18
+ export type InputSchema = undefined
19
+
20
+ export interface OutputSchema {
21
+ subject: AppBskyActorDefs.ProfileView
22
+ cursor?: string
23
+ followers: AppBskyActorDefs.ProfileView[]
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,38 @@
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
+
11
+ export interface QueryParams {}
12
+
13
+ export interface InputSchema {
14
+ root: string
15
+ [k: string]: unknown
16
+ }
17
+
18
+ export interface HandlerInput {
19
+ encoding: 'application/json'
20
+ body: InputSchema
21
+ }
22
+
23
+ export interface HandlerError {
24
+ status: number
25
+ message?: string
26
+ }
27
+
28
+ export type HandlerOutput = HandlerError | void
29
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
30
+ auth: HA
31
+ params: QueryParams
32
+ input: HandlerInput
33
+ req: express.Request
34
+ res: express.Response
35
+ }
36
+ export type Handler<HA extends HandlerAuth = never> = (
37
+ ctx: HandlerReqCtx<HA>,
38
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -0,0 +1,38 @@
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
+
11
+ export interface QueryParams {}
12
+
13
+ export interface InputSchema {
14
+ root: string
15
+ [k: string]: unknown
16
+ }
17
+
18
+ export interface HandlerInput {
19
+ encoding: 'application/json'
20
+ body: InputSchema
21
+ }
22
+
23
+ export interface HandlerError {
24
+ status: number
25
+ message?: string
26
+ }
27
+
28
+ export type HandlerOutput = HandlerError | void
29
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
30
+ auth: HA
31
+ params: QueryParams
32
+ input: HandlerInput
33
+ req: express.Request
34
+ res: express.Response
35
+ }
36
+ export type Handler<HA extends HandlerAuth = never> = (
37
+ ctx: HandlerReqCtx<HA>,
38
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -34,7 +34,7 @@ describe('handle validation', () => {
34
34
  const expectThrow = (handle: string, err: string) => {
35
35
  expect(() => ensureHandleServiceConstraints(handle, domains)).toThrow(err)
36
36
  }
37
- const expectNotThrow = (handle: string, memo: string) => {
37
+ const expectNotThrow = (handle: string, _memo: string) => {
38
38
  expect(() =>
39
39
  ensureHandleServiceConstraints(handle, domains),
40
40
  ).not.toThrow()
@@ -1,11 +1,13 @@
1
1
  import { TestNetworkNoAppView, SeedClient } from '@atproto/dev-env'
2
2
  import AtpAgent from '@atproto/api'
3
3
  import usersSeed from './seeds/users'
4
+ import { AuthScope } from '../dist/auth-verifier'
4
5
 
5
6
  describe('user preferences', () => {
6
7
  let network: TestNetworkNoAppView
7
8
  let agent: AtpAgent
8
9
  let sc: SeedClient
10
+ let appPassHeaders: { authorization: string }
9
11
 
10
12
  beforeAll(async () => {
11
13
  network = await TestNetworkNoAppView.create({
@@ -14,6 +16,16 @@ describe('user preferences', () => {
14
16
  agent = network.pds.getClient()
15
17
  sc = network.getSeedClient()
16
18
  await usersSeed(sc)
19
+ const appPass = await network.pds.ctx.accountManager.createAppPassword(
20
+ sc.dids.alice,
21
+ 'test app pass',
22
+ false,
23
+ )
24
+ const res = await agent.com.atproto.server.createSession({
25
+ identifier: sc.dids.alice,
26
+ password: appPass.password,
27
+ })
28
+ appPassHeaders = { authorization: `Bearer ${res.data.accessJwt}` }
17
29
  })
18
30
 
19
31
  afterAll(async () => {
@@ -46,6 +58,7 @@ describe('user preferences', () => {
46
58
  store.pref.putPreferences(
47
59
  [{ $type: 'com.atproto.server.defs#unknown' }],
48
60
  'com.atproto',
61
+ AuthScope.Access,
49
62
  ),
50
63
  )
51
64
  const { data } = await agent.api.app.bsky.actor.getPreferences(
@@ -96,7 +109,7 @@ describe('user preferences', () => {
96
109
  // Ensure other prefs were not clobbered
97
110
  const otherPrefs = await network.pds.ctx.actorStore.read(
98
111
  sc.dids.alice,
99
- (store) => store.pref.getPreferences('com.atproto'),
112
+ (store) => store.pref.getPreferences('com.atproto', AuthScope.Access),
100
113
  )
101
114
  expect(otherPrefs).toEqual([{ $type: 'com.atproto.server.defs#unknown' }])
102
115
  })
@@ -178,4 +191,57 @@ describe('user preferences', () => {
178
191
  'Input/preferences/1 must be an object which includes the "$type" property',
179
192
  )
180
193
  })
194
+
195
+ it('does not read permissioned preferences with an app password', async () => {
196
+ await agent.api.app.bsky.actor.putPreferences(
197
+ {
198
+ preferences: [
199
+ {
200
+ $type: 'app.bsky.actor.defs#personalDetailsPref',
201
+ birthDate: new Date().toISOString(),
202
+ },
203
+ ],
204
+ },
205
+ { headers: sc.getHeaders(sc.dids.alice), encoding: 'application/json' },
206
+ )
207
+ const res = await agent.api.app.bsky.actor.getPreferences(
208
+ {},
209
+ { headers: appPassHeaders },
210
+ )
211
+ expect(res.data.preferences).toEqual([])
212
+ })
213
+
214
+ it('does not write permissioned preferences with an app password', async () => {
215
+ const tryPut = agent.api.app.bsky.actor.putPreferences(
216
+ {
217
+ preferences: [
218
+ {
219
+ $type: 'app.bsky.actor.defs#personalDetailsPref',
220
+ birthDate: new Date().toISOString(),
221
+ },
222
+ ],
223
+ },
224
+ { headers: appPassHeaders, encoding: 'application/json' },
225
+ )
226
+ await expect(tryPut).rejects.toThrow(
227
+ /Do not have authorization to set preferences/,
228
+ )
229
+ })
230
+
231
+ it('does not remove permissioned preferences with an app password', async () => {
232
+ await agent.api.app.bsky.actor.putPreferences(
233
+ {
234
+ preferences: [],
235
+ },
236
+ { headers: appPassHeaders, encoding: 'application/json' },
237
+ )
238
+ const res = await agent.api.app.bsky.actor.getPreferences(
239
+ {},
240
+ { headers: sc.getHeaders(sc.dids.alice) },
241
+ )
242
+ const scopedPref = res.data.preferences.find(
243
+ (pref) => pref.$type === 'app.bsky.actor.defs#personalDetailsPref',
244
+ )
245
+ expect(scopedPref).toBeDefined()
246
+ })
181
247
  })
@@ -59,7 +59,9 @@ Object {
59
59
  "replyCount": 0,
60
60
  "repostCount": 0,
61
61
  "uri": "record(0)",
62
- "viewer": Object {},
62
+ "viewer": Object {
63
+ "threadMuted": false,
64
+ },
63
65
  },
64
66
  },
65
67
  Object {
@@ -178,6 +180,7 @@ Object {
178
180
  "uri": "record(2)",
179
181
  "viewer": Object {
180
182
  "like": "record(8)",
183
+ "threadMuted": false,
181
184
  },
182
185
  },
183
186
  },