@atproto/bsky 0.0.18 → 0.0.19

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.
@@ -5,7 +5,7 @@ export interface QueryParams {
5
5
  actor: string;
6
6
  limit: number;
7
7
  cursor?: string;
8
- filter: 'posts_with_replies' | 'posts_no_replies' | 'posts_with_media' | (string & {});
8
+ filter: 'posts_with_replies' | 'posts_no_replies' | 'posts_with_media' | 'posts_and_author_threads' | (string & {});
9
9
  }
10
10
  export declare type InputSchema = undefined;
11
11
  export interface OutputSchema {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/bsky",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "license": "MIT",
5
5
  "description": "Reference implementation of app.bsky App View (Bluesky API)",
6
6
  "keywords": [
@@ -35,13 +35,13 @@
35
35
  "sharp": "^0.32.6",
36
36
  "typed-emitter": "^2.1.0",
37
37
  "uint8arrays": "3.0.0",
38
- "@atproto/api": "^0.7.1",
38
+ "@atproto/api": "^0.7.2",
39
39
  "@atproto/common": "^0.3.3",
40
40
  "@atproto/crypto": "^0.3.0",
41
41
  "@atproto/syntax": "^0.1.5",
42
+ "@atproto/identity": "^0.3.2",
42
43
  "@atproto/lexicon": "^0.3.1",
43
44
  "@atproto/repo": "^0.3.6",
44
- "@atproto/identity": "^0.3.2",
45
45
  "@atproto/xrpc-server": "^0.4.2"
46
46
  },
47
47
  "devDependencies": {
@@ -52,10 +52,10 @@
52
52
  "@types/pg": "^8.6.6",
53
53
  "@types/qs": "^6.9.7",
54
54
  "axios": "^0.27.2",
55
- "@atproto/api": "^0.7.1",
56
- "@atproto/dev-env": "^0.2.18",
55
+ "@atproto/api": "^0.7.2",
56
+ "@atproto/dev-env": "^0.2.19",
57
57
  "@atproto/lex-cli": "^0.2.5",
58
- "@atproto/pds": "^0.3.6",
58
+ "@atproto/pds": "^0.3.7",
59
59
  "@atproto/xrpc": "^0.4.1"
60
60
  },
61
61
  "scripts": {
@@ -102,6 +102,13 @@ export const skeleton = async (
102
102
  feedItemsQb = feedItemsQb.where((qb) =>
103
103
  qb.where('post.replyParent', 'is', null).orWhere('type', '=', 'repost'),
104
104
  )
105
+ } else if (filter === 'posts_and_author_threads') {
106
+ feedItemsQb = feedItemsQb.where((qb) =>
107
+ qb
108
+ .where('type', '=', 'repost')
109
+ .orWhere('post.replyParent', 'is', null)
110
+ .orWhere('post.replyRoot', 'like', `at://${actorDid}/%`),
111
+ )
105
112
  }
106
113
 
107
114
  const keyset = new FeedKeyset(ref('feed_item.sortAt'), ref('feed_item.cid'))
@@ -5572,6 +5572,7 @@ export const schemaDict = {
5572
5572
  'posts_with_replies',
5573
5573
  'posts_no_replies',
5574
5574
  'posts_with_media',
5575
+ 'posts_and_author_threads',
5575
5576
  ],
5576
5577
  default: 'posts_with_replies',
5577
5578
  },
@@ -17,6 +17,7 @@ export interface QueryParams {
17
17
  | 'posts_with_replies'
18
18
  | 'posts_no_replies'
19
19
  | 'posts_with_media'
20
+ | 'posts_and_author_threads'
20
21
  | (string & {})
21
22
  }
22
23
 
@@ -0,0 +1,95 @@
1
+ import { SeedClient } from '@atproto/dev-env'
2
+ import basicSeed from './basic'
3
+
4
+ export default async (sc: SeedClient) => {
5
+ await basicSeed(sc)
6
+ await sc.createAccount('eve', {
7
+ email: 'eve@test.com',
8
+ handle: 'eve.test',
9
+ password: 'eve-pass',
10
+ })
11
+ await sc.createAccount('fred', {
12
+ email: 'fred@test.com',
13
+ handle: 'fred.test',
14
+ password: 'fred-pass',
15
+ })
16
+
17
+ const alice = sc.dids.alice
18
+ const eve = sc.dids.eve
19
+ const fred = sc.dids.fred
20
+
21
+ /*
22
+ * Self thread
23
+ */
24
+ await sc.post(eve, evePosts[0])
25
+ await sc.reply(
26
+ eve,
27
+ sc.posts[eve][0].ref,
28
+ sc.posts[eve][0].ref,
29
+ eveOwnThreadReplies[0],
30
+ )
31
+ await sc.reply(
32
+ eve,
33
+ sc.posts[eve][0].ref,
34
+ sc.replies[eve][0].ref,
35
+ eveOwnThreadReplies[1],
36
+ )
37
+ await sc.reply(
38
+ eve,
39
+ sc.posts[eve][0].ref,
40
+ sc.replies[eve][1].ref,
41
+ eveOwnThreadReplies[2],
42
+ )
43
+
44
+ /**
45
+ * Two replies to Alice
46
+ */
47
+ await sc.reply(
48
+ eve,
49
+ sc.posts[alice][1].ref,
50
+ sc.posts[alice][1].ref,
51
+ eveAliceReplies[0],
52
+ )
53
+ await sc.reply(
54
+ eve,
55
+ sc.posts[alice][1].ref,
56
+ sc.replies[eve][3].ref,
57
+ eveAliceReplies[1],
58
+ )
59
+
60
+ /**
61
+ * Two replies to Fred, who replied to Eve's root post. This creates a
62
+ * "detached" thread, where one Fred post breaks the continuity.
63
+ */
64
+ await sc.post(eve, evePosts[1])
65
+ await sc.reply(
66
+ fred,
67
+ sc.posts[eve][1].ref,
68
+ sc.posts[eve][1].ref,
69
+ fredReplies[0],
70
+ )
71
+ await sc.reply(
72
+ eve,
73
+ sc.posts[eve][1].ref,
74
+ sc.replies[fred][0].ref,
75
+ eveFredReplies[0],
76
+ )
77
+ await sc.reply(
78
+ eve,
79
+ sc.posts[eve][1].ref,
80
+ sc.replies[eve][4].ref,
81
+ eveFredReplies[1],
82
+ )
83
+
84
+ return sc
85
+ }
86
+
87
+ const evePosts = ['eve own thread', 'eve detached thread']
88
+ const eveOwnThreadReplies = [
89
+ 'eve own reply 1',
90
+ 'eve own reply 2',
91
+ 'eve own reply 3',
92
+ ]
93
+ const eveAliceReplies = ['eve reply to alice 1', 'eve reply to alice 2']
94
+ const eveFredReplies = ['eve reply to fred 1', 'eve reply to fred 2']
95
+ const fredReplies = ['fred reply to eve 1']
@@ -178,7 +178,7 @@ Array [
178
178
  "createdAt": "1970-01-01T00:00:00.000000Z",
179
179
  "text": "again",
180
180
  },
181
- "replyCount": 2,
181
+ "replyCount": 3,
182
182
  "repostCount": 1,
183
183
  "uri": "record(2)",
184
184
  "viewer": Object {},
@@ -395,7 +395,7 @@ Array [
395
395
  "createdAt": "1970-01-01T00:00:00.000000Z",
396
396
  "text": "again",
397
397
  },
398
- "replyCount": 2,
398
+ "replyCount": 3,
399
399
  "repostCount": 1,
400
400
  "uri": "record(2)",
401
401
  "viewer": Object {},
@@ -590,7 +590,7 @@ Array [
590
590
  "createdAt": "1970-01-01T00:00:00.000000Z",
591
591
  "text": "again",
592
592
  },
593
- "replyCount": 2,
593
+ "replyCount": 3,
594
594
  "repostCount": 1,
595
595
  "uri": "record(1)",
596
596
  "viewer": Object {
@@ -638,7 +638,7 @@ Array [
638
638
  "createdAt": "1970-01-01T00:00:00.000000Z",
639
639
  "text": "again",
640
640
  },
641
- "replyCount": 2,
641
+ "replyCount": 3,
642
642
  "repostCount": 1,
643
643
  "uri": "record(1)",
644
644
  "viewer": Object {
@@ -961,7 +961,7 @@ Array [
961
961
  "createdAt": "1970-01-01T00:00:00.000000Z",
962
962
  "text": "again",
963
963
  },
964
- "replyCount": 2,
964
+ "replyCount": 3,
965
965
  "repostCount": 1,
966
966
  "uri": "record(6)",
967
967
  "viewer": Object {
@@ -1009,7 +1009,7 @@ Array [
1009
1009
  "createdAt": "1970-01-01T00:00:00.000000Z",
1010
1010
  "text": "again",
1011
1011
  },
1012
- "replyCount": 2,
1012
+ "replyCount": 3,
1013
1013
  "repostCount": 1,
1014
1014
  "uri": "record(6)",
1015
1015
  "viewer": Object {
@@ -1326,7 +1326,7 @@ Array [
1326
1326
  "createdAt": "1970-01-01T00:00:00.000000Z",
1327
1327
  "text": "again",
1328
1328
  },
1329
- "replyCount": 2,
1329
+ "replyCount": 3,
1330
1330
  "repostCount": 1,
1331
1331
  "uri": "record(3)",
1332
1332
  "viewer": Object {
@@ -1376,7 +1376,7 @@ Array [
1376
1376
  "createdAt": "1970-01-01T00:00:00.000000Z",
1377
1377
  "text": "again",
1378
1378
  },
1379
- "replyCount": 2,
1379
+ "replyCount": 3,
1380
1380
  "repostCount": 1,
1381
1381
  "uri": "record(3)",
1382
1382
  "viewer": Object {
@@ -1765,7 +1765,7 @@ Array [
1765
1765
  "createdAt": "1970-01-01T00:00:00.000000Z",
1766
1766
  "text": "again",
1767
1767
  },
1768
- "replyCount": 2,
1768
+ "replyCount": 3,
1769
1769
  "repostCount": 1,
1770
1770
  "uri": "record(4)",
1771
1771
  "viewer": Object {
@@ -1987,7 +1987,7 @@ Array [
1987
1987
  "createdAt": "1970-01-01T00:00:00.000000Z",
1988
1988
  "text": "again",
1989
1989
  },
1990
- "replyCount": 2,
1990
+ "replyCount": 3,
1991
1991
  "repostCount": 1,
1992
1992
  "uri": "record(4)",
1993
1993
  "viewer": Object {
@@ -1,7 +1,7 @@
1
1
  import AtpAgent from '@atproto/api'
2
2
  import { TestNetwork, SeedClient } from '@atproto/dev-env'
3
3
  import { forSnapshot, paginateAll, stripViewerFromPost } from '../_util'
4
- import basicSeed from '../seeds/basic'
4
+ import authorFeedSeed from '../seeds/author-feed'
5
5
  import { isRecord } from '../../src/lexicon/types/app/bsky/feed/post'
6
6
  import { isView as isEmbedRecordWithMedia } from '../../src/lexicon/types/app/bsky/embed/recordWithMedia'
7
7
  import { isView as isImageEmbed } from '../../src/lexicon/types/app/bsky/embed/images'
@@ -16,6 +16,7 @@ describe('pds author feed views', () => {
16
16
  let bob: string
17
17
  let carol: string
18
18
  let dan: string
19
+ let eve: string
19
20
 
20
21
  beforeAll(async () => {
21
22
  network = await TestNetwork.create({
@@ -23,12 +24,13 @@ describe('pds author feed views', () => {
23
24
  })
24
25
  agent = network.bsky.getClient()
25
26
  sc = network.getSeedClient()
26
- await basicSeed(sc)
27
+ await authorFeedSeed(sc)
27
28
  await network.processAll()
28
29
  alice = sc.dids.alice
29
30
  bob = sc.dids.bob
30
31
  carol = sc.dids.carol
31
32
  dan = sc.dids.dan
33
+ eve = sc.dids.eve
32
34
  })
33
35
 
34
36
  afterAll(async () => {
@@ -305,4 +307,20 @@ describe('pds author feed views', () => {
305
307
  }),
306
308
  ).toBeTruthy()
307
309
  })
310
+
311
+ it('posts_and_author_threads includes self-replies', async () => {
312
+ const { data: eveFeed } = await agent.api.app.bsky.feed.getAuthorFeed({
313
+ actor: eve,
314
+ filter: 'posts_and_author_threads',
315
+ })
316
+
317
+ expect(eveFeed.feed.length).toEqual(7)
318
+ expect(
319
+ eveFeed.feed.some(({ post }) => {
320
+ return (
321
+ isRecord(post.record) && post.record.reply && post.author.did === eve
322
+ )
323
+ }),
324
+ ).toBeTruthy()
325
+ })
308
326
  })