@atproto/bsky 0.0.248 → 0.0.250

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 (62) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/api/age-assurance/const.d.ts.map +1 -1
  3. package/dist/api/age-assurance/const.js +19 -0
  4. package/dist/api/age-assurance/const.js.map +1 -1
  5. package/dist/api/age-assurance/kws/age-verified.d.ts +20 -0
  6. package/dist/api/age-assurance/kws/age-verified.d.ts.map +1 -1
  7. package/dist/api/age-assurance/kws/age-verified.js +6 -0
  8. package/dist/api/age-assurance/kws/age-verified.js.map +1 -1
  9. package/dist/api/app/bsky/graph/muteActor.d.ts.map +1 -1
  10. package/dist/api/app/bsky/graph/muteActor.js +3 -0
  11. package/dist/api/app/bsky/graph/muteActor.js.map +1 -1
  12. package/dist/api/kws/types.d.ts +33 -0
  13. package/dist/api/kws/types.d.ts.map +1 -1
  14. package/dist/api/kws/types.js +3 -0
  15. package/dist/api/kws/types.js.map +1 -1
  16. package/dist/data-plane/index.d.ts +0 -1
  17. package/dist/data-plane/index.d.ts.map +1 -1
  18. package/dist/data-plane/index.js +0 -1
  19. package/dist/data-plane/index.js.map +1 -1
  20. package/dist/data-plane/server/bsync-subscription.d.ts +47 -0
  21. package/dist/data-plane/server/bsync-subscription.d.ts.map +1 -0
  22. package/dist/data-plane/server/bsync-subscription.js +461 -0
  23. package/dist/data-plane/server/bsync-subscription.js.map +1 -0
  24. package/dist/data-plane/server/index.d.ts +1 -0
  25. package/dist/data-plane/server/index.d.ts.map +1 -1
  26. package/dist/data-plane/server/index.js +1 -0
  27. package/dist/data-plane/server/index.js.map +1 -1
  28. package/dist/lexicons/app/bsky/ageassurance/defs.defs.d.ts +4 -0
  29. package/dist/lexicons/app/bsky/ageassurance/defs.defs.d.ts.map +1 -1
  30. package/dist/lexicons/app/bsky/ageassurance/defs.defs.js +3 -0
  31. package/dist/lexicons/app/bsky/ageassurance/defs.defs.js.map +1 -1
  32. package/dist/lexicons/chat/bsky/convo/defs.defs.js +1 -1
  33. package/dist/lexicons/chat/bsky/convo/defs.defs.js.map +1 -1
  34. package/dist/lexicons/chat/bsky/group/editGroup.defs.d.ts +4 -4
  35. package/dist/lexicons/chat/bsky/group/editGroup.defs.js +2 -2
  36. package/dist/lexicons/chat/bsky/group/editGroup.defs.js.map +1 -1
  37. package/dist/lexicons/chat/bsky/moderation/defs.defs.js +1 -1
  38. package/dist/lexicons/chat/bsky/moderation/defs.defs.js.map +1 -1
  39. package/package.json +16 -16
  40. package/src/api/age-assurance/const.ts +19 -0
  41. package/src/api/age-assurance/kws/age-verified.test.ts +98 -0
  42. package/src/api/age-assurance/kws/age-verified.ts +6 -0
  43. package/src/api/app/bsky/graph/muteActor.ts +3 -0
  44. package/src/api/kws/types.ts +11 -0
  45. package/src/api/kws/util.test.ts +50 -0
  46. package/src/data-plane/index.ts +0 -1
  47. package/src/data-plane/{bsync/index.ts → server/bsync-subscription.ts} +245 -121
  48. package/src/data-plane/server/index.ts +1 -0
  49. package/tests/data-plane/thread-mutes.test.ts +2 -0
  50. package/tests/stash.test.ts +6 -1
  51. package/tests/views/age-assurance-v2.test.ts +3 -0
  52. package/tests/views/age-assurance.test.ts +8 -0
  53. package/tests/views/bookmarks.test.ts +19 -0
  54. package/tests/views/drafts.test.ts +25 -2
  55. package/tests/views/mute-lists.test.ts +2 -0
  56. package/tests/views/mutes.test.ts +1 -0
  57. package/tests/views/notifications.test.ts +16 -0
  58. package/tsconfig.build.tsbuildinfo +1 -1
  59. package/dist/data-plane/bsync/index.d.ts +0 -11
  60. package/dist/data-plane/bsync/index.d.ts.map +0 -1
  61. package/dist/data-plane/bsync/index.js +0 -376
  62. package/dist/data-plane/bsync/index.js.map +0 -1
@@ -56,6 +56,9 @@ describe('appview bookmarks views', () => {
56
56
 
57
57
  afterEach(async () => {
58
58
  vi.resetAllMocks()
59
+ // Drain pending bsync ops before clearing, so a stale op can't land after
60
+ // the reset.
61
+ await network.processAll()
59
62
  await clearPrivateData(db)
60
63
  await clearBookmarks(db)
61
64
  })
@@ -114,6 +117,7 @@ describe('appview bookmarks views', () => {
114
117
 
115
118
  await create(bob, sc.posts[bob][0].ref)
116
119
  await create(bob, sc.posts[carol][0].ref)
120
+ await network.processAll()
117
121
 
118
122
  const { data: dataAlice } = await get(alice)
119
123
  expect(dataAlice.bookmarks).toHaveLength(3)
@@ -126,10 +130,12 @@ describe('appview bookmarks views', () => {
126
130
  const uri = sc.posts[alice][0].ref
127
131
 
128
132
  await create(alice, uri)
133
+ await network.processAll()
129
134
  const { data: data0 } = await get(alice)
130
135
  expect(data0.bookmarks).toHaveLength(1)
131
136
 
132
137
  await create(alice, uri)
138
+ await network.processAll()
133
139
  const { data: data1 } = await get(alice)
134
140
  expect(data1.bookmarks).toHaveLength(1)
135
141
  })
@@ -147,12 +153,14 @@ describe('appview bookmarks views', () => {
147
153
  await create(alice, sc.posts[alice][0].ref)
148
154
  await create(alice, sc.posts[bob][0].ref)
149
155
  await create(alice, sc.posts[carol][0].ref)
156
+ await network.processAll()
150
157
 
151
158
  const { data: dataBefore } = await get(alice)
152
159
  expect(dataBefore.bookmarks).toHaveLength(3)
153
160
 
154
161
  await del(alice, sc.posts[alice][0].ref)
155
162
  await del(alice, sc.posts[carol][0].ref)
163
+ await network.processAll()
156
164
 
157
165
  const { data: dataAfter } = await get(alice)
158
166
  expect(dataAfter.bookmarks).toHaveLength(1)
@@ -161,12 +169,17 @@ describe('appview bookmarks views', () => {
161
169
  it('is idempotent', async () => {
162
170
  const uri = sc.posts[alice][0].ref
163
171
  await create(alice, uri)
172
+ // deleteBookmark resolves the bookmark's key from indexed state, so the
173
+ // create must be indexed before the delete is issued.
174
+ await network.processAll()
164
175
 
165
176
  await del(alice, uri)
177
+ await network.processAll()
166
178
  const { data: data0 } = await get(alice)
167
179
  expect(data0.bookmarks).toHaveLength(0)
168
180
 
169
181
  await del(alice, uri)
182
+ await network.processAll()
170
183
  const { data: data1 } = await get(alice)
171
184
  expect(data1.bookmarks).toHaveLength(0)
172
185
  })
@@ -192,12 +205,14 @@ describe('appview bookmarks views', () => {
192
205
  expect(postBefore.viewer?.bookmarked).toBe(false)
193
206
 
194
207
  await create(alice, ref)
208
+ await network.processAll()
195
209
  const postAfterCreate = await getPost(alice, ref)
196
210
  expect(postAfterCreate.viewer?.bookmarked).toBe(true)
197
211
  const postAfterCreateForBob = await getPost(bob, ref)
198
212
  expect(postAfterCreateForBob.viewer?.bookmarked).toBe(false)
199
213
 
200
214
  await del(alice, ref)
215
+ await network.processAll()
201
216
  const postAfterDel = await getPost(alice, ref)
202
217
  expect(postAfterDel.viewer?.bookmarked).toBe(false)
203
218
  })
@@ -210,16 +225,19 @@ describe('appview bookmarks views', () => {
210
225
 
211
226
  await create(alice, uri)
212
227
  await create(carol, uri)
228
+ await network.processAll()
213
229
  const postAfterCreate = await getPost(alice, uri)
214
230
  expect(postAfterCreate.bookmarkCount).toBe(2)
215
231
  const postAfterCreateForBob = await getPost(bob, uri)
216
232
  expect(postAfterCreateForBob.bookmarkCount).toBe(2)
217
233
 
218
234
  await del(alice, uri)
235
+ await network.processAll()
219
236
  const postAfterAliceDel = await getPost(alice, uri)
220
237
  expect(postAfterAliceDel.bookmarkCount).toBe(1)
221
238
 
222
239
  await del(carol, uri)
240
+ await network.processAll()
223
241
  const postAfterCarolDel = await getPost(carol, uri)
224
242
  expect(postAfterCarolDel.bookmarkCount).toBe(0)
225
243
  })
@@ -232,6 +250,7 @@ describe('appview bookmarks views', () => {
232
250
  await create(alice, sc.posts[carol][0].ref)
233
251
  await create(alice, sc.posts[dan][0].ref)
234
252
  await create(alice, sc.posts[dan][1].ref)
253
+ await network.processAll()
235
254
 
236
255
  const results = (out: AppBskyBookmarkGetBookmarks.OutputSchema[]) =>
237
256
  out.flatMap((res) => res.bookmarks)
@@ -48,8 +48,13 @@ describe('appview drafts views', () => {
48
48
  })
49
49
 
50
50
  beforeEach(async () => network.processAll())
51
- afterEach(async () => vi.resetAllMocks())
52
- afterEach(async () => clearDrafts(network.bsky.db))
51
+ afterEach(async () => {
52
+ vi.resetAllMocks()
53
+ // Drain in-flight bsync operations before resetting state directly,
54
+ // otherwise a late-applied op can resurrect state after the reset.
55
+ await network.processAll()
56
+ await clearDrafts(network.bsky.db)
57
+ })
53
58
  afterAll(async () => network?.close())
54
59
 
55
60
  const makeDraft = (): AppBskyDraftDefs.Draft => ({
@@ -113,6 +118,7 @@ describe('appview drafts views', () => {
113
118
 
114
119
  await create(bob, makeDraft())
115
120
  await create(bob, makeDraft())
121
+ await network.processAll()
116
122
 
117
123
  const { data: dataAlice } = await get(alice)
118
124
  expect(dataAlice.drafts).toHaveLength(3)
@@ -131,6 +137,7 @@ describe('appview drafts views', () => {
131
137
  }
132
138
 
133
139
  await create(alice, draft)
140
+ await network.processAll()
134
141
  const { data } = await get(alice)
135
142
  expect(data.drafts).toHaveLength(1)
136
143
  expect(data.drafts[0].draft.posts).toHaveLength(3)
@@ -159,6 +166,7 @@ describe('appview drafts views', () => {
159
166
  }
160
167
 
161
168
  await create(alice, draft1)
169
+ await network.processAll()
162
170
  const { data: data0 } = await get(alice)
163
171
  expect(data0.drafts).toHaveLength(1)
164
172
  expect(data0.drafts[0].draft.posts[0].text).toBe('First version')
@@ -170,6 +178,7 @@ describe('appview drafts views', () => {
170
178
  }
171
179
 
172
180
  await update(alice, draft2)
181
+ await network.processAll()
173
182
  const { data: data1 } = await get(alice)
174
183
  expect(data1.drafts).toHaveLength(1)
175
184
  expect(data1.drafts[0].draft.posts[0].text).toBe('Updated version')
@@ -182,6 +191,7 @@ describe('appview drafts views', () => {
182
191
  }
183
192
 
184
193
  await update(alice, nonExistingDraft)
194
+ await network.processAll()
185
195
  const { data } = await get(alice)
186
196
  expect(data.drafts).toHaveLength(0)
187
197
  })
@@ -192,6 +202,7 @@ describe('appview drafts views', () => {
192
202
  await create(alice, makeDraft())
193
203
  await create(alice, makeDraft())
194
204
  await create(alice, makeDraft())
205
+ await network.processAll()
195
206
 
196
207
  const { data: dataBefore } = await get(alice)
197
208
  expect(dataBefore.drafts).toHaveLength(3)
@@ -202,6 +213,7 @@ describe('appview drafts views', () => {
202
213
 
203
214
  await del(alice, draft1Id)
204
215
  await del(alice, draft3Id)
216
+ await network.processAll()
205
217
 
206
218
  const { data: dataAfter } = await get(alice)
207
219
  expect(dataAfter.drafts).toHaveLength(1)
@@ -210,16 +222,19 @@ describe('appview drafts views', () => {
210
222
 
211
223
  it('is idempotent', async () => {
212
224
  await create(alice, makeDraft())
225
+ await network.processAll()
213
226
 
214
227
  const { data: data0 } = await get(alice)
215
228
  expect(data0.drafts).toHaveLength(1)
216
229
  const draftId = data0.drafts[0].id
217
230
 
218
231
  await del(alice, draftId)
232
+ await network.processAll()
219
233
  const { data: data1 } = await get(alice)
220
234
  expect(data1.drafts).toHaveLength(0)
221
235
 
222
236
  await del(alice, draftId)
237
+ await network.processAll()
223
238
  const { data: data2 } = await get(alice)
224
239
  expect(data2.drafts).toHaveLength(0)
225
240
  })
@@ -235,6 +250,7 @@ describe('appview drafts views', () => {
235
250
  await create(alice, makeDraft())
236
251
  await create(alice, makeDraft())
237
252
  await create(bob, makeDraft())
253
+ await network.processAll()
238
254
 
239
255
  const { data: dataAlice } = await get(alice)
240
256
  expect(dataAlice.drafts).toHaveLength(2)
@@ -246,6 +262,7 @@ describe('appview drafts views', () => {
246
262
  it('includes timestamps', async () => {
247
263
  const beforeCreate = new Date()
248
264
  await create(alice, makeDraft())
265
+ await network.processAll()
249
266
  const afterCreate = new Date()
250
267
 
251
268
  const { data } = await get(alice)
@@ -264,6 +281,7 @@ describe('appview drafts views', () => {
264
281
  for (let i = 0; i < 7; i++) {
265
282
  await create(alice, makeDraft())
266
283
  }
284
+ await network.processAll()
267
285
 
268
286
  const results = (out: AppBskyDraftGetDrafts.OutputSchema[]) =>
269
287
  out.flatMap((res) => res.drafts)
@@ -319,6 +337,7 @@ describe('appview drafts views', () => {
319
337
 
320
338
  it('round-trips a draft with embedGallery', async () => {
321
339
  await create(alice, galleryDraft(3))
340
+ await network.processAll()
322
341
  const { data } = await get(alice)
323
342
  expect(data.drafts).toHaveLength(1)
324
343
 
@@ -335,6 +354,7 @@ describe('appview drafts views', () => {
335
354
 
336
355
  it('updates a draft to add a gallery', async () => {
337
356
  await create(alice, { posts: [{ text: 'text only' }] })
357
+ await network.processAll()
338
358
  const { data: before } = await get(alice)
339
359
  expect(before.drafts).toHaveLength(1)
340
360
  expect(before.drafts[0].draft.posts[0].embedGallery).toBeUndefined()
@@ -344,6 +364,7 @@ describe('appview drafts views', () => {
344
364
  id: draftId,
345
365
  draft: galleryDraft(2),
346
366
  })
367
+ await network.processAll()
347
368
 
348
369
  const { data: after } = await get(alice)
349
370
  expect(after.drafts).toHaveLength(1)
@@ -353,6 +374,7 @@ describe('appview drafts views', () => {
353
374
 
354
375
  it('updates a draft to change gallery items', async () => {
355
376
  await create(alice, galleryDraft(2))
377
+ await network.processAll()
356
378
  const { data: before } = await get(alice)
357
379
  expect(before.drafts[0].draft.posts[0].embedGallery?.items).toHaveLength(
358
380
  2,
@@ -363,6 +385,7 @@ describe('appview drafts views', () => {
363
385
  id: draftId,
364
386
  draft: galleryDraft(5),
365
387
  })
388
+ await network.processAll()
366
389
 
367
390
  const { data: after } = await get(alice)
368
391
  const post = after.drafts[0].draft.posts[0]
@@ -334,6 +334,7 @@ describe('bsky views with mutes from mute lists', () => {
334
334
  ),
335
335
  },
336
336
  )
337
+ await network.processAll()
337
338
 
338
339
  const res = await agent.api.app.bsky.graph.getListMutes(
339
340
  {},
@@ -392,6 +393,7 @@ describe('bsky views with mutes from mute lists', () => {
392
393
  ),
393
394
  },
394
395
  )
396
+ await network.processAll()
395
397
 
396
398
  const res = await agent.api.app.bsky.graph.getListMutes(
397
399
  {},
@@ -275,6 +275,7 @@ describe('mute views', () => {
275
275
  encoding: 'application/json',
276
276
  },
277
277
  )
278
+ await network.processAll()
278
279
 
279
280
  const { data: final } = await agent.api.app.bsky.graph.getMutes(
280
281
  {},
@@ -1036,6 +1036,9 @@ describe('notification views', () => {
1036
1036
 
1037
1037
  describe('preferences v2', () => {
1038
1038
  beforeEach(async () => {
1039
+ // Drain pending bsync ops before clearing, so a stale op can't land
1040
+ // after the reset.
1041
+ await network.processAll()
1039
1042
  await clearPrivateData(db)
1040
1043
  })
1041
1044
 
@@ -1354,6 +1357,9 @@ describe('notification views', () => {
1354
1357
  })
1355
1358
 
1356
1359
  beforeEach(async () => {
1360
+ // Drain pending bsync ops before clearing, so a stale op can't land
1361
+ // after the reset.
1362
+ await network.processAll()
1357
1363
  await clearActivitySubscription(db)
1358
1364
  })
1359
1365
 
@@ -1383,6 +1389,7 @@ describe('notification views', () => {
1383
1389
  subject: subjectDid,
1384
1390
  activitySubscription: val,
1385
1391
  })
1392
+ await network.processAll()
1386
1393
 
1387
1394
  const { data: listData } = await list(actorDid)
1388
1395
  expect(listData).toEqual({
@@ -1413,6 +1420,7 @@ describe('notification views', () => {
1413
1420
  subject: subjectDid,
1414
1421
  activitySubscription: valUpdate,
1415
1422
  })
1423
+ await network.processAll()
1416
1424
 
1417
1425
  const { data: listData } = await list(actorDid)
1418
1426
  expect(listData).toEqual({
@@ -1435,10 +1443,12 @@ describe('notification views', () => {
1435
1443
  const valDelete = { post: false, reply: false }
1436
1444
 
1437
1445
  await put(actorDid, subjectDid, valCreate)
1446
+ await network.processAll()
1438
1447
  const { data: list0 } = await list(actorDid)
1439
1448
  expect(list0.subscriptions).toHaveLength(1)
1440
1449
 
1441
1450
  await put(actorDid, subjectDid, valDelete)
1451
+ await network.processAll()
1442
1452
  const { data: list1 } = await list(actorDid)
1443
1453
  expect(list1.subscriptions).toHaveLength(0)
1444
1454
  })
@@ -1454,6 +1464,7 @@ describe('notification views', () => {
1454
1464
  await put(actorDid, eve, val)
1455
1465
  await put(actorDid, fred, val)
1456
1466
  await put(actorDid, blocked, val) // blocked is removed from the list.
1467
+ await network.processAll()
1457
1468
 
1458
1469
  const results = (
1459
1470
  results: AppBskyNotificationListActivitySubscriptions.OutputSchema[],
@@ -1507,24 +1518,29 @@ describe('notification views', () => {
1507
1518
 
1508
1519
  // 'none' declaration.
1509
1520
  await put(viewer, bob, val)
1521
+ await network.processAll()
1510
1522
  await expect(viewerActivitySub(viewer, bob)).resolves.toBeUndefined()
1511
1523
 
1512
1524
  // 'mutuals' declaration and both follow.
1513
1525
  await put(viewer, carol, val)
1526
+ await network.processAll()
1514
1527
  await expect(viewerActivitySub(viewer, carol)).resolves.toStrictEqual(
1515
1528
  val,
1516
1529
  )
1517
1530
 
1518
1531
  // 'mutuals' declaration but only actor follows.
1519
1532
  await put(viewer, dan, val)
1533
+ await network.processAll()
1520
1534
  await expect(viewerActivitySub(viewer, dan)).resolves.toBeUndefined()
1521
1535
 
1522
1536
  // 'mutuals' declaration but only subject follows.
1523
1537
  await put(viewer, eve, val)
1538
+ await network.processAll()
1524
1539
  await expect(viewerActivitySub(viewer, eve)).resolves.toBeUndefined()
1525
1540
 
1526
1541
  // 'followers' declaration and viewer follows.
1527
1542
  await put(viewer, fred, val)
1543
+ await network.processAll()
1528
1544
  await expect(viewerActivitySub(viewer, carol)).resolves.toStrictEqual(
1529
1545
  val,
1530
1546
  )