@atproto/bsky 0.0.155 → 0.0.157

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 (144) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/api/app/bsky/{unspecced/getPostThreadHiddenV2.d.ts → notification/getPreferences.d.ts} +1 -1
  3. package/dist/api/app/bsky/notification/getPreferences.d.ts.map +1 -0
  4. package/dist/api/app/bsky/notification/getPreferences.js +39 -0
  5. package/dist/api/app/bsky/notification/getPreferences.js.map +1 -0
  6. package/dist/api/app/bsky/notification/putPreferencesV2.d.ts +4 -0
  7. package/dist/api/app/bsky/notification/putPreferencesV2.d.ts.map +1 -0
  8. package/dist/api/app/bsky/notification/putPreferencesV2.js +47 -0
  9. package/dist/api/app/bsky/notification/putPreferencesV2.js.map +1 -0
  10. package/dist/api/app/bsky/notification/util.d.ts +9 -0
  11. package/dist/api/app/bsky/notification/util.d.ts.map +1 -0
  12. package/dist/api/app/bsky/notification/util.js +84 -0
  13. package/dist/api/app/bsky/notification/util.js.map +1 -0
  14. package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.d.ts +4 -0
  15. package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.d.ts.map +1 -0
  16. package/dist/api/app/bsky/unspecced/{getPostThreadHiddenV2.js → getPostThreadOtherV2.js} +5 -5
  17. package/dist/api/app/bsky/unspecced/getPostThreadOtherV2.js.map +1 -0
  18. package/dist/api/app/bsky/unspecced/getPostThreadV2.js +2 -2
  19. package/dist/api/app/bsky/unspecced/getPostThreadV2.js.map +1 -1
  20. package/dist/api/index.d.ts.map +1 -1
  21. package/dist/api/index.js +6 -2
  22. package/dist/api/index.js.map +1 -1
  23. package/dist/context.d.ts +3 -0
  24. package/dist/context.d.ts.map +1 -1
  25. package/dist/context.js +3 -0
  26. package/dist/context.js.map +1 -1
  27. package/dist/data-plane/bsync/index.d.ts.map +1 -1
  28. package/dist/data-plane/bsync/index.js +84 -0
  29. package/dist/data-plane/bsync/index.js.map +1 -1
  30. package/dist/data-plane/server/db/database-schema.d.ts +2 -1
  31. package/dist/data-plane/server/db/database-schema.d.ts.map +1 -1
  32. package/dist/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.d.ts +4 -0
  33. package/dist/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.d.ts.map +1 -0
  34. package/dist/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.js +24 -0
  35. package/dist/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.js.map +1 -0
  36. package/dist/data-plane/server/db/migrations/index.d.ts +1 -0
  37. package/dist/data-plane/server/db/migrations/index.d.ts.map +1 -1
  38. package/dist/data-plane/server/db/migrations/index.js +2 -1
  39. package/dist/data-plane/server/db/migrations/index.js.map +1 -1
  40. package/dist/data-plane/server/db/tables/private-data.d.ts +13 -0
  41. package/dist/data-plane/server/db/tables/private-data.d.ts.map +1 -0
  42. package/dist/data-plane/server/db/tables/private-data.js +5 -0
  43. package/dist/data-plane/server/db/tables/private-data.js.map +1 -0
  44. package/dist/data-plane/server/routes/index.d.ts.map +1 -1
  45. package/dist/data-plane/server/routes/index.js +2 -0
  46. package/dist/data-plane/server/routes/index.js.map +1 -1
  47. package/dist/data-plane/server/routes/private-data.d.ts +9 -0
  48. package/dist/data-plane/server/routes/private-data.d.ts.map +1 -0
  49. package/dist/data-plane/server/routes/private-data.js +63 -0
  50. package/dist/data-plane/server/routes/private-data.js.map +1 -0
  51. package/dist/data-plane/server/util.d.ts +6 -6
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +3 -0
  54. package/dist/index.js.map +1 -1
  55. package/dist/lexicon/index.d.ts +8 -4
  56. package/dist/lexicon/index.d.ts.map +1 -1
  57. package/dist/lexicon/index.js +14 -6
  58. package/dist/lexicon/index.js.map +1 -1
  59. package/dist/lexicon/lexicons.d.ts +518 -100
  60. package/dist/lexicon/lexicons.d.ts.map +1 -1
  61. package/dist/lexicon/lexicons.js +277 -52
  62. package/dist/lexicon/lexicons.js.map +1 -1
  63. package/dist/lexicon/types/app/bsky/notification/defs.d.ts +40 -0
  64. package/dist/lexicon/types/app/bsky/notification/defs.d.ts.map +1 -1
  65. package/dist/lexicon/types/app/bsky/notification/defs.js +36 -0
  66. package/dist/lexicon/types/app/bsky/notification/defs.js.map +1 -1
  67. package/dist/lexicon/types/app/bsky/notification/getPreferences.d.ts +35 -0
  68. package/dist/lexicon/types/app/bsky/notification/getPreferences.d.ts.map +1 -0
  69. package/dist/lexicon/types/app/bsky/notification/getPreferences.js +7 -0
  70. package/dist/lexicon/types/app/bsky/notification/getPreferences.js.map +1 -0
  71. package/dist/lexicon/types/app/bsky/notification/putPreferencesV2.d.ts +52 -0
  72. package/dist/lexicon/types/app/bsky/notification/putPreferencesV2.d.ts.map +1 -0
  73. package/dist/lexicon/types/app/bsky/notification/putPreferencesV2.js +7 -0
  74. package/dist/lexicon/types/app/bsky/notification/putPreferencesV2.js.map +1 -0
  75. package/dist/lexicon/types/app/bsky/unspecced/{getPostThreadHiddenV2.d.ts → getPostThreadOtherV2.d.ts} +7 -7
  76. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadOtherV2.d.ts.map +1 -0
  77. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadOtherV2.js +16 -0
  78. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadOtherV2.js.map +1 -0
  79. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.d.ts +2 -2
  80. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadV2.d.ts.map +1 -1
  81. package/dist/proto/bsky_connect.d.ts +10 -1
  82. package/dist/proto/bsky_connect.d.ts.map +1 -1
  83. package/dist/proto/bsky_connect.js +9 -0
  84. package/dist/proto/bsky_connect.js.map +1 -1
  85. package/dist/proto/bsky_pb.d.ts +234 -0
  86. package/dist/proto/bsky_pb.d.ts.map +1 -1
  87. package/dist/proto/bsky_pb.js +693 -5
  88. package/dist/proto/bsky_pb.js.map +1 -1
  89. package/dist/proto/bsync_pb.d.ts +10 -10
  90. package/dist/proto/bsync_pb.d.ts.map +1 -1
  91. package/dist/proto/bsync_pb.js +15 -15
  92. package/dist/proto/bsync_pb.js.map +1 -1
  93. package/dist/stash.d.ts +26 -0
  94. package/dist/stash.d.ts.map +1 -0
  95. package/dist/stash.js +56 -0
  96. package/dist/stash.js.map +1 -0
  97. package/dist/views/index.d.ts +8 -8
  98. package/dist/views/index.d.ts.map +1 -1
  99. package/dist/views/index.js +32 -32
  100. package/dist/views/index.js.map +1 -1
  101. package/dist/views/threads-v2.d.ts +11 -11
  102. package/dist/views/threads-v2.d.ts.map +1 -1
  103. package/dist/views/threads-v2.js.map +1 -1
  104. package/package.json +4 -4
  105. package/proto/bsky.proto +61 -0
  106. package/src/api/app/bsky/notification/getPreferences.ts +50 -0
  107. package/src/api/app/bsky/notification/putPreferencesV2.ts +62 -0
  108. package/src/api/app/bsky/notification/util.ts +123 -0
  109. package/src/api/app/bsky/unspecced/{getPostThreadHiddenV2.ts → getPostThreadOtherV2.ts} +5 -5
  110. package/src/api/app/bsky/unspecced/getPostThreadV2.ts +2 -2
  111. package/src/api/index.ts +6 -2
  112. package/src/context.ts +6 -0
  113. package/src/data-plane/bsync/index.ts +109 -1
  114. package/src/data-plane/server/db/database-schema.ts +3 -1
  115. package/src/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.ts +22 -0
  116. package/src/data-plane/server/db/migrations/index.ts +1 -0
  117. package/src/data-plane/server/db/tables/private-data.ts +13 -0
  118. package/src/data-plane/server/routes/index.ts +2 -0
  119. package/src/data-plane/server/routes/private-data.ts +90 -0
  120. package/src/index.ts +4 -0
  121. package/src/lexicon/index.ts +38 -14
  122. package/src/lexicon/lexicons.ts +281 -54
  123. package/src/lexicon/types/app/bsky/notification/defs.ts +76 -0
  124. package/src/lexicon/types/app/bsky/notification/getPreferences.ts +52 -0
  125. package/src/lexicon/types/app/bsky/notification/putPreferencesV2.ts +69 -0
  126. package/src/lexicon/types/app/bsky/unspecced/{getPostThreadHiddenV2.ts → getPostThreadOtherV2.ts} +10 -10
  127. package/src/lexicon/types/app/bsky/unspecced/getPostThreadV2.ts +2 -2
  128. package/src/proto/bsky_connect.ts +11 -0
  129. package/src/proto/bsky_pb.ts +669 -0
  130. package/src/proto/bsync_pb.ts +15 -15
  131. package/src/stash.ts +75 -0
  132. package/src/views/index.ts +46 -46
  133. package/src/views/threads-v2.ts +23 -23
  134. package/tests/stash.test.ts +156 -0
  135. package/tests/views/__snapshots__/thread-v2.test.ts.snap +7 -7
  136. package/tests/views/notifications.test.ts +221 -0
  137. package/tests/views/thread-v2.test.ts +93 -93
  138. package/tsconfig.build.tsbuildinfo +1 -1
  139. package/tsconfig.tests.tsbuildinfo +1 -1
  140. package/dist/api/app/bsky/unspecced/getPostThreadHiddenV2.d.ts.map +0 -1
  141. package/dist/api/app/bsky/unspecced/getPostThreadHiddenV2.js.map +0 -1
  142. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.d.ts.map +0 -1
  143. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.js +0 -16
  144. package/dist/lexicon/types/app/bsky/unspecced/getPostThreadHiddenV2.js.map +0 -1
@@ -0,0 +1,156 @@
1
+ import { TestNetwork } from '@atproto/dev-env'
2
+ import { ProfileAssociatedChat } from '../dist/lexicon/types/app/bsky/actor/defs'
3
+ import { StashClient } from '../dist/stash'
4
+
5
+ type Database = TestNetwork['bsky']['db']
6
+
7
+ describe('private data', () => {
8
+ let network: TestNetwork
9
+ let stashClient: StashClient
10
+ let db: Database
11
+
12
+ const actorDid = 'did:plc:example'
13
+ // This lexicon has nothing special other than being simple, convenient to use in a test.
14
+ const namespace = 'app.bsky.actor.defs#profileAssociatedChat'
15
+ const key = 'self'
16
+
17
+ const validPayload0: ProfileAssociatedChat = { allowIncoming: 'all' }
18
+ const validPayload1: ProfileAssociatedChat = { allowIncoming: 'following' }
19
+ const invalidPayload: ProfileAssociatedChat = {
20
+ invalid: 'all',
21
+ } as unknown as ProfileAssociatedChat
22
+
23
+ beforeAll(async () => {
24
+ network = await TestNetwork.create({
25
+ dbPostgresSchema: 'bsky_private_data',
26
+ })
27
+ db = network.bsky.db
28
+ stashClient = network.bsky.ctx.stashClient
29
+ })
30
+
31
+ afterEach(async () => {
32
+ await clearPrivateData(db)
33
+ })
34
+
35
+ afterAll(async () => {
36
+ await network.close()
37
+ })
38
+
39
+ describe('create', () => {
40
+ it('creates entry', async () => {
41
+ await stashClient.create({
42
+ actorDid,
43
+ namespace,
44
+ key,
45
+ payload: validPayload0,
46
+ })
47
+ await network.processAll()
48
+
49
+ const dbResult = await db.db
50
+ .selectFrom('private_data')
51
+ .selectAll()
52
+ .where('actorDid', '=', actorDid)
53
+ .where('namespace', '=', namespace)
54
+ .where('key', '=', key)
55
+ .executeTakeFirstOrThrow()
56
+ expect(dbResult).toStrictEqual({
57
+ actorDid,
58
+ namespace,
59
+ key,
60
+ payload: JSON.stringify({ $type: namespace, ...validPayload0 }),
61
+ indexedAt: expect.any(String),
62
+ updatedAt: expect.any(String),
63
+ })
64
+ })
65
+
66
+ it('validates lexicon', async () => {
67
+ expect(() =>
68
+ stashClient.create({
69
+ actorDid,
70
+ namespace,
71
+ key,
72
+ payload: invalidPayload,
73
+ }),
74
+ ).toThrow('Object must have the property "allowIncoming"')
75
+ })
76
+ })
77
+
78
+ describe('update', () => {
79
+ it('updates entry', async () => {
80
+ await stashClient.create({
81
+ actorDid,
82
+ namespace,
83
+ key,
84
+ payload: validPayload0,
85
+ })
86
+ await network.processAll()
87
+
88
+ await stashClient.update({
89
+ actorDid,
90
+ namespace,
91
+ key,
92
+ payload: validPayload1,
93
+ })
94
+ await network.processAll()
95
+
96
+ const dbResult = await db.db
97
+ .selectFrom('private_data')
98
+ .selectAll()
99
+ .where('actorDid', '=', actorDid)
100
+ .where('namespace', '=', namespace)
101
+ .where('key', '=', key)
102
+ .executeTakeFirstOrThrow()
103
+ expect(dbResult).toStrictEqual({
104
+ actorDid,
105
+ namespace,
106
+ key,
107
+ payload: JSON.stringify({ $type: namespace, ...validPayload1 }),
108
+ indexedAt: expect.any(String),
109
+ updatedAt: expect.any(String),
110
+ })
111
+ })
112
+
113
+ it('validates lexicon', async () => {
114
+ expect(() =>
115
+ stashClient.update({
116
+ actorDid,
117
+ namespace,
118
+ key,
119
+ payload: invalidPayload,
120
+ }),
121
+ ).toThrow('Object must have the property "allowIncoming"')
122
+ })
123
+ })
124
+
125
+ describe('delete', () => {
126
+ it('deletes entry', async () => {
127
+ await stashClient.create({
128
+ actorDid,
129
+ namespace,
130
+ key,
131
+ payload: validPayload0,
132
+ })
133
+ await network.processAll()
134
+
135
+ await stashClient.delete({
136
+ actorDid,
137
+ namespace,
138
+ key,
139
+ })
140
+ await network.processAll()
141
+
142
+ const dbResult = await db.db
143
+ .selectFrom('private_data')
144
+ .selectAll()
145
+ .where('actorDid', '=', actorDid)
146
+ .where('namespace', '=', namespace)
147
+ .where('key', '=', key)
148
+ .executeTakeFirst()
149
+ expect(dbResult).toBe(undefined)
150
+ })
151
+ })
152
+ })
153
+
154
+ const clearPrivateData = async (db: Database) => {
155
+ await db.db.deleteFrom('private_data').execute()
156
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  exports[`appview thread views v2 simple thread returns thread anchored on 1 1`] = `
4
4
  Object {
5
- "hasHiddenReplies": false,
5
+ "hasOtherReplies": false,
6
6
  "thread": Array [
7
7
  Object {
8
8
  "depth": -1,
@@ -100,7 +100,7 @@ Object {
100
100
 
101
101
  exports[`appview thread views v2 simple thread returns thread anchored on 2 1`] = `
102
102
  Object {
103
- "hasHiddenReplies": false,
103
+ "hasOtherReplies": false,
104
104
  "thread": Array [
105
105
  Object {
106
106
  "depth": -1,
@@ -248,7 +248,7 @@ Object {
248
248
 
249
249
  exports[`appview thread views v2 simple thread returns thread anchored on 2.0 1`] = `
250
250
  Object {
251
- "hasHiddenReplies": false,
251
+ "hasOtherReplies": false,
252
252
  "thread": Array [
253
253
  Object {
254
254
  "depth": -2,
@@ -396,7 +396,7 @@ Object {
396
396
 
397
397
  exports[`appview thread views v2 simple thread returns thread anchored on 3 1`] = `
398
398
  Object {
399
- "hasHiddenReplies": false,
399
+ "hasOtherReplies": false,
400
400
  "thread": Array [
401
401
  Object {
402
402
  "depth": -1,
@@ -494,7 +494,7 @@ Object {
494
494
 
495
495
  exports[`appview thread views v2 simple thread returns thread anchored on r 0 1`] = `
496
496
  Object {
497
- "hasHiddenReplies": false,
497
+ "hasOtherReplies": false,
498
498
  "thread": Array [
499
499
  Object {
500
500
  "depth": -1,
@@ -642,7 +642,7 @@ Object {
642
642
 
643
643
  exports[`appview thread views v2 simple thread returns thread anchored on r 0.0 1`] = `
644
644
  Object {
645
- "hasHiddenReplies": false,
645
+ "hasOtherReplies": false,
646
646
  "thread": Array [
647
647
  Object {
648
648
  "depth": -2,
@@ -790,7 +790,7 @@ Object {
790
790
 
791
791
  exports[`appview thread views v2 simple thread returns thread anchored on root 1`] = `
792
792
  Object {
793
- "hasHiddenReplies": false,
793
+ "hasOtherReplies": false,
794
794
  "thread": Array [
795
795
  Object {
796
796
  "depth": 0,
@@ -2,11 +2,22 @@ import { AtpAgent } from '@atproto/api'
2
2
  import { SeedClient, TestNetwork, basicSeed } from '@atproto/dev-env'
3
3
  import { delayCursor } from '../../src/api/app/bsky/notification/listNotifications'
4
4
  import { ids } from '../../src/lexicon/lexicons'
5
+ import {
6
+ ChatPreference,
7
+ FilterablePreference,
8
+ Preference,
9
+ Preferences,
10
+ } from '../../src/lexicon/types/app/bsky/notification/defs'
5
11
  import { Notification } from '../../src/lexicon/types/app/bsky/notification/listNotifications'
12
+ import { InputSchema } from '../../src/lexicon/types/app/bsky/notification/putPreferencesV2'
6
13
  import { forSnapshot, paginateAll } from '../_util'
7
14
 
15
+ type Database = TestNetwork['bsky']['db']
16
+
8
17
  describe('notification views', () => {
9
18
  let network: TestNetwork
19
+ let db: Database
20
+
10
21
  let agent: AtpAgent
11
22
  let sc: SeedClient
12
23
 
@@ -19,6 +30,7 @@ describe('notification views', () => {
19
30
  network = await TestNetwork.create({
20
31
  dbPostgresSchema: 'bsky_views_notifications',
21
32
  })
33
+ db = network.bsky.db
22
34
  agent = network.bsky.getClient()
23
35
  sc = network.getSeedClient()
24
36
  await basicSeed(sc)
@@ -905,4 +917,213 @@ describe('notification views', () => {
905
917
  })
906
918
  })
907
919
  })
920
+
921
+ describe('preferences v2', () => {
922
+ beforeEach(async () => {
923
+ await clearPrivateData(db)
924
+ })
925
+
926
+ // Defaults
927
+ const fp: FilterablePreference = {
928
+ filter: 'all',
929
+ list: true,
930
+ push: true,
931
+ }
932
+ const p: Preference = {
933
+ list: true,
934
+ push: true,
935
+ }
936
+ const cp: ChatPreference = {
937
+ filter: 'all',
938
+ push: true,
939
+ }
940
+
941
+ it('gets preferences filling up with the defaults', async () => {
942
+ const actorDid = sc.dids.carol
943
+
944
+ const getAndAssert = async (
945
+ expectedApi: Preferences,
946
+ expectedDb: Preferences | undefined,
947
+ ) => {
948
+ const { data } = await agent.app.bsky.notification.getPreferences(
949
+ {},
950
+ {
951
+ headers: await network.serviceHeaders(
952
+ actorDid,
953
+ ids.AppBskyNotificationGetPreferences,
954
+ ),
955
+ },
956
+ )
957
+ expect(data.preferences).toStrictEqual(expectedApi)
958
+
959
+ const dbResult = await db.db
960
+ .selectFrom('private_data')
961
+ .selectAll()
962
+ .where('actorDid', '=', actorDid)
963
+ .where('namespace', '=', 'app.bsky.notification.defs#preferences')
964
+ .where('key', '=', 'self')
965
+ .executeTakeFirst()
966
+ if (dbResult === undefined) {
967
+ expect(dbResult).toBe(expectedDb)
968
+ } else {
969
+ expect(dbResult).toStrictEqual({
970
+ actorDid: actorDid,
971
+ namespace: 'app.bsky.notification.defs#preferences',
972
+ key: 'self',
973
+ indexedAt: expect.any(String),
974
+ payload: expect.anything(), // Better to compare payload parsed.
975
+ updatedAt: expect.any(String),
976
+ })
977
+ expect(JSON.parse(dbResult.payload)).toStrictEqual({
978
+ $type: 'app.bsky.notification.defs#preferences',
979
+ ...expectedDb,
980
+ })
981
+ }
982
+ }
983
+
984
+ const expectedApi0: Preferences = {
985
+ chat: cp,
986
+ follow: fp,
987
+ like: fp,
988
+ likeViaRepost: fp,
989
+ mention: fp,
990
+ quote: fp,
991
+ reply: fp,
992
+ repost: fp,
993
+ repostViaRepost: fp,
994
+ starterpackJoined: p,
995
+ subscribedPost: p,
996
+ unverified: p,
997
+ verified: p,
998
+ }
999
+ // The user has no preferences set yet, so nothing stored.
1000
+ const expectedDb0 = undefined
1001
+ await getAndAssert(expectedApi0, expectedDb0)
1002
+
1003
+ await agent.app.bsky.notification.putPreferencesV2(
1004
+ { verified: { list: false, push: false } },
1005
+ {
1006
+ encoding: 'application/json',
1007
+ headers: await network.serviceHeaders(
1008
+ actorDid,
1009
+ ids.AppBskyNotificationPutPreferencesV2,
1010
+ ),
1011
+ },
1012
+ )
1013
+ await network.processAll()
1014
+
1015
+ const expectedApi1: Preferences = {
1016
+ chat: cp,
1017
+ follow: fp,
1018
+ like: fp,
1019
+ likeViaRepost: fp,
1020
+ mention: fp,
1021
+ quote: fp,
1022
+ reply: fp,
1023
+ repost: fp,
1024
+ repostViaRepost: fp,
1025
+ starterpackJoined: p,
1026
+ subscribedPost: p,
1027
+ unverified: p,
1028
+ verified: { list: false, push: false },
1029
+ }
1030
+ // Stored all the defaults.
1031
+ const expectedDb1 = expectedApi1
1032
+ await getAndAssert(expectedApi1, expectedDb1)
1033
+ })
1034
+
1035
+ it('stores the preferences setting the defaults', async () => {
1036
+ const actorDid = sc.dids.carol
1037
+
1038
+ const putAndAssert = async (
1039
+ input: InputSchema,
1040
+ expected: Preferences,
1041
+ ) => {
1042
+ const { data } = await agent.app.bsky.notification.putPreferencesV2(
1043
+ input,
1044
+ {
1045
+ encoding: 'application/json',
1046
+ headers: await network.serviceHeaders(
1047
+ actorDid,
1048
+ ids.AppBskyNotificationPutPreferencesV2,
1049
+ ),
1050
+ },
1051
+ )
1052
+ await network.processAll()
1053
+ expect(data.preferences).toStrictEqual(expected)
1054
+
1055
+ const dbResult = await db.db
1056
+ .selectFrom('private_data')
1057
+ .selectAll()
1058
+ .where('actorDid', '=', actorDid)
1059
+ .where('namespace', '=', 'app.bsky.notification.defs#preferences')
1060
+ .where('key', '=', 'self')
1061
+ .executeTakeFirstOrThrow()
1062
+ expect(dbResult).toStrictEqual({
1063
+ actorDid: actorDid,
1064
+ namespace: 'app.bsky.notification.defs#preferences',
1065
+ key: 'self',
1066
+ indexedAt: expect.any(String),
1067
+ payload: expect.anything(), // Better to compare payload parsed.
1068
+ updatedAt: expect.any(String),
1069
+ })
1070
+ expect(JSON.parse(dbResult.payload)).toStrictEqual({
1071
+ $type: 'app.bsky.notification.defs#preferences',
1072
+ ...expected,
1073
+ })
1074
+ }
1075
+
1076
+ const input0 = {
1077
+ chat: {
1078
+ push: false,
1079
+ filter: 'accepted',
1080
+ },
1081
+ }
1082
+ const expected0: Preferences = {
1083
+ chat: input0.chat,
1084
+ follow: fp,
1085
+ like: fp,
1086
+ likeViaRepost: fp,
1087
+ mention: fp,
1088
+ quote: fp,
1089
+ reply: fp,
1090
+ repost: fp,
1091
+ repostViaRepost: fp,
1092
+ starterpackJoined: p,
1093
+ subscribedPost: p,
1094
+ unverified: p,
1095
+ verified: p,
1096
+ }
1097
+ await putAndAssert(input0, expected0)
1098
+
1099
+ const input1 = {
1100
+ mention: {
1101
+ list: false,
1102
+ push: false,
1103
+ filter: 'follows',
1104
+ },
1105
+ }
1106
+ const expected1: Preferences = {
1107
+ // Kept from the previous call.
1108
+ chat: input0.chat,
1109
+ follow: fp,
1110
+ like: fp,
1111
+ likeViaRepost: fp,
1112
+ mention: input1.mention,
1113
+ quote: fp,
1114
+ reply: fp,
1115
+ repost: fp,
1116
+ repostViaRepost: fp,
1117
+ starterpackJoined: p,
1118
+ subscribedPost: p,
1119
+ unverified: p,
1120
+ verified: p,
1121
+ }
1122
+ await putAndAssert(input1, expected1)
1123
+ })
1124
+ })
908
1125
  })
1126
+
1127
+ const clearPrivateData = async (db: Database) => {
1128
+ await db.db.deleteFrom('private_data').execute()
1129
+ }