@atproto/bsky 0.0.64 → 0.0.65
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.
- package/CHANGELOG.md +10 -0
- package/dist/api/app/bsky/actor/searchActors.js +1 -1
- package/dist/api/app/bsky/actor/searchActors.js.map +1 -1
- package/dist/api/app/bsky/feed/getPostThread.js +1 -10
- package/dist/api/app/bsky/feed/getPostThread.js.map +1 -1
- package/dist/api/app/bsky/feed/searchPosts.js +1 -1
- package/dist/api/app/bsky/feed/searchPosts.js.map +1 -1
- package/dist/api/app/bsky/graph/getActorStarterPacks.d.ts +4 -0
- package/dist/api/app/bsky/graph/getActorStarterPacks.d.ts.map +1 -0
- package/dist/api/app/bsky/graph/getActorStarterPacks.js +58 -0
- package/dist/api/app/bsky/graph/getActorStarterPacks.js.map +1 -0
- package/dist/api/app/bsky/graph/getStarterPack.d.ts +4 -0
- package/dist/api/app/bsky/graph/getStarterPack.d.ts.map +1 -0
- package/dist/api/app/bsky/graph/getStarterPack.js +45 -0
- package/dist/api/app/bsky/graph/getStarterPack.js.map +1 -0
- package/dist/api/app/bsky/graph/getStarterPacks.d.ts +4 -0
- package/dist/api/app/bsky/graph/getStarterPacks.d.ts.map +1 -0
- package/dist/api/app/bsky/graph/getStarterPacks.js +40 -0
- package/dist/api/app/bsky/graph/getStarterPacks.js.map +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +6 -0
- package/dist/api/index.js.map +1 -1
- package/dist/data-plane/server/db/database-schema.d.ts +2 -1
- package/dist/data-plane/server/db/database-schema.d.ts.map +1 -1
- package/dist/data-plane/server/db/migrations/20240606T222548219Z-starter-packs.d.ts +4 -0
- package/dist/data-plane/server/db/migrations/20240606T222548219Z-starter-packs.d.ts.map +1 -0
- package/dist/data-plane/server/db/migrations/20240606T222548219Z-starter-packs.js +47 -0
- package/dist/data-plane/server/db/migrations/20240606T222548219Z-starter-packs.js.map +1 -0
- package/dist/data-plane/server/db/migrations/index.d.ts +1 -0
- package/dist/data-plane/server/db/migrations/index.d.ts.map +1 -1
- package/dist/data-plane/server/db/migrations/index.js +2 -1
- package/dist/data-plane/server/db/migrations/index.js.map +1 -1
- package/dist/data-plane/server/db/tables/profile.d.ts +2 -0
- package/dist/data-plane/server/db/tables/profile.d.ts.map +1 -1
- package/dist/data-plane/server/db/tables/starter-pack.d.ts +14 -0
- package/dist/data-plane/server/db/tables/starter-pack.d.ts.map +1 -0
- package/dist/data-plane/server/db/tables/starter-pack.js +5 -0
- package/dist/data-plane/server/db/tables/starter-pack.js.map +1 -0
- package/dist/data-plane/server/indexing/index.d.ts +2 -0
- package/dist/data-plane/server/indexing/index.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/index.js +2 -0
- package/dist/data-plane/server/indexing/index.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/profile.d.ts.map +1 -1
- package/dist/data-plane/server/indexing/plugins/profile.js +18 -2
- package/dist/data-plane/server/indexing/plugins/profile.js.map +1 -1
- package/dist/data-plane/server/indexing/plugins/starter-pack.d.ts +11 -0
- package/dist/data-plane/server/indexing/plugins/starter-pack.d.ts.map +1 -0
- package/dist/data-plane/server/indexing/plugins/starter-pack.js +78 -0
- package/dist/data-plane/server/indexing/plugins/starter-pack.js.map +1 -0
- package/dist/data-plane/server/routes/index.d.ts.map +1 -1
- package/dist/data-plane/server/routes/index.js +2 -0
- package/dist/data-plane/server/routes/index.js.map +1 -1
- package/dist/data-plane/server/routes/interactions.d.ts.map +1 -1
- package/dist/data-plane/server/routes/interactions.js +57 -1
- package/dist/data-plane/server/routes/interactions.js.map +1 -1
- package/dist/data-plane/server/routes/profile.d.ts.map +1 -1
- package/dist/data-plane/server/routes/profile.js +1 -0
- package/dist/data-plane/server/routes/profile.js.map +1 -1
- package/dist/data-plane/server/routes/records.d.ts.map +1 -1
- package/dist/data-plane/server/routes/records.js +1 -0
- package/dist/data-plane/server/routes/records.js.map +1 -1
- package/dist/data-plane/server/routes/starter-packs.d.ts +6 -0
- package/dist/data-plane/server/routes/starter-packs.d.ts.map +1 -0
- package/dist/data-plane/server/routes/starter-packs.js +25 -0
- package/dist/data-plane/server/routes/starter-packs.js.map +1 -0
- package/dist/data-plane/server/util.d.ts +6 -6
- package/dist/hydration/actor.d.ts +2 -0
- package/dist/hydration/actor.d.ts.map +1 -1
- package/dist/hydration/actor.js +2 -0
- package/dist/hydration/actor.js.map +1 -1
- package/dist/hydration/feed.d.ts +1 -5
- package/dist/hydration/feed.d.ts.map +1 -1
- package/dist/hydration/feed.js +0 -1
- package/dist/hydration/feed.js.map +1 -1
- package/dist/hydration/graph.d.ts +17 -1
- package/dist/hydration/graph.d.ts.map +1 -1
- package/dist/hydration/graph.js +30 -1
- package/dist/hydration/graph.js.map +1 -1
- package/dist/hydration/hydrator.d.ts +9 -3
- package/dist/hydration/hydrator.d.ts.map +1 -1
- package/dist/hydration/hydrator.js +114 -5
- package/dist/hydration/hydrator.js.map +1 -1
- package/dist/hydration/util.d.ts +4 -0
- package/dist/hydration/util.d.ts.map +1 -1
- package/dist/hydration/util.js.map +1 -1
- package/dist/lexicon/index.d.ts +7 -0
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +13 -0
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +332 -0
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +335 -1
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/actor/defs.d.ts +5 -0
- package/dist/lexicon/types/app/bsky/actor/defs.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/actor/defs.js.map +1 -1
- package/dist/lexicon/types/app/bsky/actor/profile.d.ts +3 -0
- package/dist/lexicon/types/app/bsky/actor/profile.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/actor/profile.js.map +1 -1
- package/dist/lexicon/types/app/bsky/graph/defs.d.ts +36 -1
- package/dist/lexicon/types/app/bsky/graph/defs.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/graph/defs.js +23 -1
- package/dist/lexicon/types/app/bsky/graph/defs.js.map +1 -1
- package/dist/lexicon/types/app/bsky/graph/getActorStarterPacks.d.ts +39 -0
- package/dist/lexicon/types/app/bsky/graph/getActorStarterPacks.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/getActorStarterPacks.js +3 -0
- package/dist/lexicon/types/app/bsky/graph/getActorStarterPacks.js.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPack.d.ts +37 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPack.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPack.js +3 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPack.js.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPacks.d.ts +36 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPacks.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPacks.js +3 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPacks.js.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/starterpack.d.ts +25 -0
- package/dist/lexicon/types/app/bsky/graph/starterpack.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/starterpack.js +27 -0
- package/dist/lexicon/types/app/bsky/graph/starterpack.js.map +1 -0
- package/dist/lexicon/types/app/bsky/notification/listNotifications.d.ts +2 -2
- package/dist/lexicon/types/app/bsky/notification/listNotifications.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/notification/listNotifications.js.map +1 -1
- package/dist/proto/bsky_connect.d.ts +39 -1
- package/dist/proto/bsky_connect.d.ts.map +1 -1
- package/dist/proto/bsky_connect.js +38 -0
- package/dist/proto/bsky_connect.js.map +1 -1
- package/dist/proto/bsky_pb.d.ts +160 -0
- package/dist/proto/bsky_pb.d.ts.map +1 -1
- package/dist/proto/bsky_pb.js +508 -4
- package/dist/proto/bsky_pb.js.map +1 -1
- package/dist/views/index.d.ts +3 -1
- package/dist/views/index.d.ts.map +1 -1
- package/dist/views/index.js +64 -0
- package/dist/views/index.js.map +1 -1
- package/package.json +5 -5
- package/proto/bsky.proto +47 -0
- package/src/api/app/bsky/actor/searchActors.ts +1 -1
- package/src/api/app/bsky/feed/getPostThread.ts +1 -9
- package/src/api/app/bsky/feed/searchPosts.ts +1 -1
- package/src/api/app/bsky/graph/getActorStarterPacks.ts +99 -0
- package/src/api/app/bsky/graph/getStarterPack.ts +80 -0
- package/src/api/app/bsky/graph/getStarterPacks.ts +81 -0
- package/src/api/index.ts +6 -0
- package/src/data-plane/server/db/database-schema.ts +2 -0
- package/src/data-plane/server/db/migrations/20240606T222548219Z-starter-packs.ts +45 -0
- package/src/data-plane/server/db/migrations/index.ts +1 -0
- package/src/data-plane/server/db/tables/profile.ts +2 -0
- package/src/data-plane/server/db/tables/starter-pack.ts +16 -0
- package/src/data-plane/server/indexing/index.ts +3 -0
- package/src/data-plane/server/indexing/plugins/profile.ts +16 -2
- package/src/data-plane/server/indexing/plugins/starter-pack.ts +76 -0
- package/src/data-plane/server/routes/index.ts +2 -0
- package/src/data-plane/server/routes/interactions.ts +56 -2
- package/src/data-plane/server/routes/profile.ts +1 -0
- package/src/data-plane/server/routes/records.ts +1 -0
- package/src/data-plane/server/routes/starter-packs.ts +32 -0
- package/src/hydration/actor.ts +5 -0
- package/src/hydration/feed.ts +1 -2
- package/src/hydration/graph.ts +55 -2
- package/src/hydration/hydrator.ts +143 -6
- package/src/hydration/util.ts +2 -0
- package/src/lexicon/index.ts +37 -0
- package/src/lexicon/lexicons.ts +337 -1
- package/src/lexicon/types/app/bsky/actor/defs.ts +5 -0
- package/src/lexicon/types/app/bsky/actor/profile.ts +3 -0
- package/src/lexicon/types/app/bsky/graph/defs.ts +58 -0
- package/src/lexicon/types/app/bsky/graph/getActorStarterPacks.ts +49 -0
- package/src/lexicon/types/app/bsky/graph/getStarterPack.ts +47 -0
- package/src/lexicon/types/app/bsky/graph/getStarterPacks.ts +46 -0
- package/src/lexicon/types/app/bsky/graph/starterpack.ts +50 -0
- package/src/lexicon/types/app/bsky/notification/listNotifications.ts +2 -1
- package/src/proto/bsky_connect.ts +46 -0
- package/src/proto/bsky_pb.ts +512 -0
- package/src/views/index.ts +71 -1
- package/tests/__snapshots__/feed-generation.test.ts.snap +28 -0
- package/tests/data-plane/__snapshots__/indexing.test.ts.snap +9 -0
- package/tests/views/__snapshots__/author-feed.test.ts.snap +29 -0
- package/tests/views/__snapshots__/block-lists.test.ts.snap +16 -0
- package/tests/views/__snapshots__/blocks.test.ts.snap +4 -0
- package/tests/views/__snapshots__/follows.test.ts.snap +34 -0
- package/tests/views/__snapshots__/labeler-service.test.ts.snap +4 -0
- package/tests/views/__snapshots__/likes.test.ts.snap +1 -0
- package/tests/views/__snapshots__/list-feed.test.ts.snap +12 -0
- package/tests/views/__snapshots__/mute-lists.test.ts.snap +20 -0
- package/tests/views/__snapshots__/mutes.test.ts.snap +8 -0
- package/tests/views/__snapshots__/notifications.test.ts.snap +10 -0
- package/tests/views/__snapshots__/posts.test.ts.snap +6 -0
- package/tests/views/__snapshots__/profile.test.ts.snap +18 -0
- package/tests/views/__snapshots__/reposts.test.ts.snap +1 -0
- package/tests/views/__snapshots__/starter-packs.test.ts.snap +482 -0
- package/tests/views/__snapshots__/thread.test.ts.snap +22 -0
- package/tests/views/__snapshots__/threadgating.test.ts.snap +2 -0
- package/tests/views/__snapshots__/timeline.test.ts.snap +81 -0
- package/tests/views/starter-packs.test.ts +121 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { dedupeStrs, mapDefined } from '@atproto/common'
|
|
2
|
+
import { Server } from '../../../../lexicon'
|
|
3
|
+
import { QueryParams } from '../../../../lexicon/types/app/bsky/graph/getStarterPacks'
|
|
4
|
+
import AppContext from '../../../../context'
|
|
5
|
+
import { resHeaders } from '../../../util'
|
|
6
|
+
import { createPipeline, noRules } from '../../../../pipeline'
|
|
7
|
+
import {
|
|
8
|
+
HydrateCtx,
|
|
9
|
+
HydrationState,
|
|
10
|
+
Hydrator,
|
|
11
|
+
} from '../../../../hydration/hydrator'
|
|
12
|
+
import { Views } from '../../../../views'
|
|
13
|
+
|
|
14
|
+
export default function (server: Server, ctx: AppContext) {
|
|
15
|
+
const getStarterPacks = createPipeline(
|
|
16
|
+
skeleton,
|
|
17
|
+
hydration,
|
|
18
|
+
noRules,
|
|
19
|
+
presentation,
|
|
20
|
+
)
|
|
21
|
+
server.app.bsky.graph.getStarterPacks({
|
|
22
|
+
auth: ctx.authVerifier.standardOptional,
|
|
23
|
+
handler: async ({ auth, params, req }) => {
|
|
24
|
+
const { viewer, includeTakedowns } = ctx.authVerifier.parseCreds(auth)
|
|
25
|
+
const labelers = ctx.reqLabelers(req)
|
|
26
|
+
const hydrateCtx = await ctx.hydrator.createContext({
|
|
27
|
+
viewer,
|
|
28
|
+
labelers,
|
|
29
|
+
includeTakedowns,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const result = await getStarterPacks({ ...params, hydrateCtx }, ctx)
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
encoding: 'application/json',
|
|
36
|
+
body: result,
|
|
37
|
+
headers: resHeaders({ labelers: hydrateCtx.labelers }),
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const skeleton = async (inputs: { params: Params }) => {
|
|
44
|
+
return { uris: inputs.params.uris }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const hydration = async (input: {
|
|
48
|
+
ctx: Context
|
|
49
|
+
params: Params
|
|
50
|
+
skeleton: SkeletonState
|
|
51
|
+
}) => {
|
|
52
|
+
const { ctx, params, skeleton } = input
|
|
53
|
+
return ctx.hydrator.hydrateStarterPacksBasic(
|
|
54
|
+
dedupeStrs(skeleton.uris),
|
|
55
|
+
params.hydrateCtx,
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const presentation = (input: {
|
|
60
|
+
ctx: Context
|
|
61
|
+
params: Params
|
|
62
|
+
skeleton: SkeletonState
|
|
63
|
+
hydration: HydrationState
|
|
64
|
+
}) => {
|
|
65
|
+
const { ctx, skeleton, hydration } = input
|
|
66
|
+
const starterPacks = mapDefined(skeleton.uris, (did) =>
|
|
67
|
+
ctx.views.starterPackBasic(did, hydration),
|
|
68
|
+
)
|
|
69
|
+
return { starterPacks }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
type Context = {
|
|
73
|
+
hydrator: Hydrator
|
|
74
|
+
views: Views
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
type Params = QueryParams & {
|
|
78
|
+
hydrateCtx: HydrateCtx
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
type SkeletonState = { uris: string[] }
|
package/src/api/index.ts
CHANGED
|
@@ -16,6 +16,7 @@ import getActorLikes from './app/bsky/feed/getActorLikes'
|
|
|
16
16
|
import getProfile from './app/bsky/actor/getProfile'
|
|
17
17
|
import getProfiles from './app/bsky/actor/getProfiles'
|
|
18
18
|
import getRepostedBy from './app/bsky/feed/getRepostedBy'
|
|
19
|
+
import getActorStarterPacks from './app/bsky/graph/getActorStarterPacks'
|
|
19
20
|
import getBlocks from './app/bsky/graph/getBlocks'
|
|
20
21
|
import getListBlocks from './app/bsky/graph/getListBlocks'
|
|
21
22
|
import getFollowers from './app/bsky/graph/getFollowers'
|
|
@@ -26,6 +27,8 @@ import getLists from './app/bsky/graph/getLists'
|
|
|
26
27
|
import getListMutes from './app/bsky/graph/getListMutes'
|
|
27
28
|
import getMutes from './app/bsky/graph/getMutes'
|
|
28
29
|
import getRelationships from './app/bsky/graph/getRelationships'
|
|
30
|
+
import getStarterPack from './app/bsky/graph/getStarterPack'
|
|
31
|
+
import getStarterPacks from './app/bsky/graph/getStarterPacks'
|
|
29
32
|
import muteActor from './app/bsky/graph/muteActor'
|
|
30
33
|
import unmuteActor from './app/bsky/graph/unmuteActor'
|
|
31
34
|
import muteActorList from './app/bsky/graph/muteActorList'
|
|
@@ -75,6 +78,7 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
75
78
|
getProfile(server, ctx)
|
|
76
79
|
getProfiles(server, ctx)
|
|
77
80
|
getRepostedBy(server, ctx)
|
|
81
|
+
getActorStarterPacks(server, ctx)
|
|
78
82
|
getBlocks(server, ctx)
|
|
79
83
|
getListBlocks(server, ctx)
|
|
80
84
|
getFollowers(server, ctx)
|
|
@@ -85,6 +89,8 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
85
89
|
getListMutes(server, ctx)
|
|
86
90
|
getMutes(server, ctx)
|
|
87
91
|
getRelationships(server, ctx)
|
|
92
|
+
getStarterPack(server, ctx)
|
|
93
|
+
getStarterPacks(server, ctx)
|
|
88
94
|
muteActor(server, ctx)
|
|
89
95
|
unmuteActor(server, ctx)
|
|
90
96
|
muteActorList(server, ctx)
|
|
@@ -34,6 +34,7 @@ import * as suggestedFeed from './tables/suggested-feed'
|
|
|
34
34
|
import * as taggedSuggestion from './tables/tagged-suggestion'
|
|
35
35
|
import * as blobTakedown from './tables/blob-takedown'
|
|
36
36
|
import * as labeler from './tables/labeler'
|
|
37
|
+
import * as starterPack from './tables/starter-pack'
|
|
37
38
|
|
|
38
39
|
export type DatabaseSchemaType = duplicateRecord.PartialDB &
|
|
39
40
|
profile.PartialDB &
|
|
@@ -69,6 +70,7 @@ export type DatabaseSchemaType = duplicateRecord.PartialDB &
|
|
|
69
70
|
suggestedFeed.PartialDB &
|
|
70
71
|
blobTakedown.PartialDB &
|
|
71
72
|
labeler.PartialDB &
|
|
73
|
+
starterPack.PartialDB &
|
|
72
74
|
taggedSuggestion.PartialDB
|
|
73
75
|
|
|
74
76
|
export type DatabaseSchema = Kysely<DatabaseSchemaType>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Kysely, sql } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
4
|
+
await db.schema
|
|
5
|
+
.createTable('starter_pack')
|
|
6
|
+
.addColumn('uri', 'varchar', (col) => col.primaryKey())
|
|
7
|
+
.addColumn('cid', 'varchar', (col) => col.notNull())
|
|
8
|
+
.addColumn('creator', 'varchar', (col) => col.notNull())
|
|
9
|
+
.addColumn('createdAt', 'varchar', (col) => col.notNull())
|
|
10
|
+
.addColumn('indexedAt', 'varchar', (col) => col.notNull())
|
|
11
|
+
.addColumn('sortAt', 'varchar', (col) =>
|
|
12
|
+
col
|
|
13
|
+
.generatedAlwaysAs(sql`least("createdAt", "indexedAt")`)
|
|
14
|
+
.stored()
|
|
15
|
+
.notNull(),
|
|
16
|
+
)
|
|
17
|
+
.execute()
|
|
18
|
+
await db.schema
|
|
19
|
+
.createIndex('starter_pack_creator_order_by_idx')
|
|
20
|
+
.on('starter_pack')
|
|
21
|
+
.columns(['creator', 'sortAt', 'cid'])
|
|
22
|
+
.execute()
|
|
23
|
+
await db.schema
|
|
24
|
+
.alterTable('profile')
|
|
25
|
+
.addColumn('joinedViaStarterPackUri', 'varchar')
|
|
26
|
+
.execute()
|
|
27
|
+
await db.schema
|
|
28
|
+
.alterTable('profile')
|
|
29
|
+
.addColumn('createdAt', 'varchar', (col) => col.notNull())
|
|
30
|
+
.execute()
|
|
31
|
+
await db.schema
|
|
32
|
+
.createIndex('profile_starter_pack_joined_idx')
|
|
33
|
+
.on('profile')
|
|
34
|
+
.columns(['joinedViaStarterPackUri', 'createdAt'])
|
|
35
|
+
.execute()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
39
|
+
await db.schema.dropTable('starter_pack').execute()
|
|
40
|
+
await db.schema
|
|
41
|
+
.alterTable('profile')
|
|
42
|
+
.dropColumn('joinedViaStarterPackUri')
|
|
43
|
+
.execute()
|
|
44
|
+
await db.schema.alterTable('profile').dropColumn('createdAt').execute()
|
|
45
|
+
}
|
|
@@ -36,3 +36,4 @@ export * as _20240124T023719200Z from './20240124T023719200Z-tagged-suggestions'
|
|
|
36
36
|
export * as _20240226T225725627Z from './20240226T225725627Z-labelers'
|
|
37
37
|
export * as _20240530T170337073Z from './20240530T170337073Z-account-deactivation'
|
|
38
38
|
export * as _20240606T171229898Z from './20240606T171229898Z-thread-mutes'
|
|
39
|
+
export * as _20240606T222548219Z from './20240606T222548219Z-starter-packs'
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { GeneratedAlways } from 'kysely'
|
|
2
|
+
|
|
3
|
+
export const tableName = 'starter_pack'
|
|
4
|
+
|
|
5
|
+
export interface StarterPack {
|
|
6
|
+
uri: string
|
|
7
|
+
cid: string
|
|
8
|
+
creator: string
|
|
9
|
+
createdAt: string
|
|
10
|
+
indexedAt: string
|
|
11
|
+
sortAt: GeneratedAlways<string>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type PartialDB = {
|
|
15
|
+
[tableName]: StarterPack
|
|
16
|
+
}
|
|
@@ -26,6 +26,7 @@ import * as ListItem from './plugins/list-item'
|
|
|
26
26
|
import * as ListBlock from './plugins/list-block'
|
|
27
27
|
import * as Block from './plugins/block'
|
|
28
28
|
import * as FeedGenerator from './plugins/feed-generator'
|
|
29
|
+
import * as StarterPack from './plugins/starter-pack'
|
|
29
30
|
import * as Labeler from './plugins/labeler'
|
|
30
31
|
import * as ChatDeclaration from './plugins/chat-declaration'
|
|
31
32
|
import RecordProcessor from './processor'
|
|
@@ -46,6 +47,7 @@ export class IndexingService {
|
|
|
46
47
|
listBlock: ListBlock.PluginType
|
|
47
48
|
block: Block.PluginType
|
|
48
49
|
feedGenerator: FeedGenerator.PluginType
|
|
50
|
+
starterPack: StarterPack.PluginType
|
|
49
51
|
labeler: Labeler.PluginType
|
|
50
52
|
chatDeclaration: ChatDeclaration.PluginType
|
|
51
53
|
}
|
|
@@ -67,6 +69,7 @@ export class IndexingService {
|
|
|
67
69
|
listBlock: ListBlock.makePlugin(this.db, this.background),
|
|
68
70
|
block: Block.makePlugin(this.db, this.background),
|
|
69
71
|
feedGenerator: FeedGenerator.makePlugin(this.db, this.background),
|
|
72
|
+
starterPack: StarterPack.makePlugin(this.db, this.background),
|
|
70
73
|
labeler: Labeler.makePlugin(this.db, this.background),
|
|
71
74
|
chatDeclaration: ChatDeclaration.makePlugin(this.db, this.background),
|
|
72
75
|
}
|
|
@@ -28,6 +28,8 @@ const insertFn = async (
|
|
|
28
28
|
description: obj.description,
|
|
29
29
|
avatarCid: obj.avatar?.ref.toString(),
|
|
30
30
|
bannerCid: obj.banner?.ref.toString(),
|
|
31
|
+
joinedViaStarterPackUri: obj.joinedViaStarterPack?.uri,
|
|
32
|
+
createdAt: obj.createdAt ?? new Date().toISOString(),
|
|
31
33
|
indexedAt: timestamp,
|
|
32
34
|
})
|
|
33
35
|
.onConflict((oc) => oc.doNothing())
|
|
@@ -40,8 +42,20 @@ const findDuplicate = async (): Promise<AtUri | null> => {
|
|
|
40
42
|
return null
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
const notifsForInsert = () => {
|
|
44
|
-
return []
|
|
45
|
+
const notifsForInsert = (obj: IndexedProfile) => {
|
|
46
|
+
if (!obj.joinedViaStarterPackUri) return []
|
|
47
|
+
const starterPackUri = new AtUri(obj.joinedViaStarterPackUri)
|
|
48
|
+
return [
|
|
49
|
+
{
|
|
50
|
+
did: starterPackUri.host,
|
|
51
|
+
author: obj.creator,
|
|
52
|
+
recordUri: obj.uri,
|
|
53
|
+
recordCid: obj.cid,
|
|
54
|
+
reason: 'starterpack-joined' as const,
|
|
55
|
+
reasonSubject: obj.joinedViaStarterPackUri,
|
|
56
|
+
sortAt: obj.indexedAt,
|
|
57
|
+
},
|
|
58
|
+
]
|
|
45
59
|
}
|
|
46
60
|
|
|
47
61
|
const deleteFn = async (
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Selectable } from 'kysely'
|
|
2
|
+
import { AtUri, normalizeDatetimeAlways } from '@atproto/syntax'
|
|
3
|
+
import { CID } from 'multiformats/cid'
|
|
4
|
+
import * as StarterPack from '../../../../lexicon/types/app/bsky/graph/starterpack'
|
|
5
|
+
import * as lex from '../../../../lexicon/lexicons'
|
|
6
|
+
import { Database } from '../../db'
|
|
7
|
+
import { DatabaseSchema, DatabaseSchemaType } from '../../db/database-schema'
|
|
8
|
+
import RecordProcessor from '../processor'
|
|
9
|
+
import { BackgroundQueue } from '../../background'
|
|
10
|
+
|
|
11
|
+
const lexId = lex.ids.AppBskyGraphStarterpack
|
|
12
|
+
type IndexedStarterPack = Selectable<DatabaseSchemaType['starter_pack']>
|
|
13
|
+
|
|
14
|
+
const insertFn = async (
|
|
15
|
+
db: DatabaseSchema,
|
|
16
|
+
uri: AtUri,
|
|
17
|
+
cid: CID,
|
|
18
|
+
obj: StarterPack.Record,
|
|
19
|
+
timestamp: string,
|
|
20
|
+
): Promise<IndexedStarterPack | null> => {
|
|
21
|
+
const inserted = await db
|
|
22
|
+
.insertInto('starter_pack')
|
|
23
|
+
.values({
|
|
24
|
+
uri: uri.toString(),
|
|
25
|
+
cid: cid.toString(),
|
|
26
|
+
creator: uri.host,
|
|
27
|
+
createdAt: normalizeDatetimeAlways(obj.createdAt),
|
|
28
|
+
indexedAt: timestamp,
|
|
29
|
+
})
|
|
30
|
+
.onConflict((oc) => oc.doNothing())
|
|
31
|
+
.returningAll()
|
|
32
|
+
.executeTakeFirst()
|
|
33
|
+
return inserted || null
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const findDuplicate = async (): Promise<AtUri | null> => {
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const notifsForInsert = () => {
|
|
41
|
+
return []
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const deleteFn = async (
|
|
45
|
+
db: DatabaseSchema,
|
|
46
|
+
uri: AtUri,
|
|
47
|
+
): Promise<IndexedStarterPack | null> => {
|
|
48
|
+
const deleted = await db
|
|
49
|
+
.deleteFrom('starter_pack')
|
|
50
|
+
.where('uri', '=', uri.toString())
|
|
51
|
+
.returningAll()
|
|
52
|
+
.executeTakeFirst()
|
|
53
|
+
return deleted || null
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const notifsForDelete = () => {
|
|
57
|
+
return { notifs: [], toDelete: [] }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type PluginType = RecordProcessor<StarterPack.Record, IndexedStarterPack>
|
|
61
|
+
|
|
62
|
+
export const makePlugin = (
|
|
63
|
+
db: Database,
|
|
64
|
+
background: BackgroundQueue,
|
|
65
|
+
): PluginType => {
|
|
66
|
+
return new RecordProcessor(db, background, {
|
|
67
|
+
lexId,
|
|
68
|
+
insertFn,
|
|
69
|
+
findDuplicate,
|
|
70
|
+
deleteFn,
|
|
71
|
+
notifsForInsert,
|
|
72
|
+
notifsForDelete,
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default makePlugin
|
|
@@ -22,6 +22,7 @@ import search from './search'
|
|
|
22
22
|
import suggestions from './suggestions'
|
|
23
23
|
import sync from './sync'
|
|
24
24
|
import threads from './threads'
|
|
25
|
+
import starterPacks from './starter-packs'
|
|
25
26
|
import { Database } from '../db'
|
|
26
27
|
|
|
27
28
|
export default (db: Database, idResolver: IdResolver) =>
|
|
@@ -48,6 +49,7 @@ export default (db: Database, idResolver: IdResolver) =>
|
|
|
48
49
|
...suggestions(db),
|
|
49
50
|
...sync(db),
|
|
50
51
|
...threads(db),
|
|
52
|
+
...starterPacks(db),
|
|
51
53
|
|
|
52
54
|
async ping() {
|
|
53
55
|
return {}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { keyBy } from '@atproto/common'
|
|
1
|
+
import { DAY, keyBy } from '@atproto/common'
|
|
2
2
|
import { ServiceImpl } from '@connectrpc/connect'
|
|
3
3
|
import { Service } from '../../../proto/bsky_connect'
|
|
4
4
|
import { Database } from '../db'
|
|
@@ -24,7 +24,7 @@ export default (db: Database): Partial<ServiceImpl<typeof Service>> => ({
|
|
|
24
24
|
},
|
|
25
25
|
async getCountsForUsers(req) {
|
|
26
26
|
if (req.dids.length === 0) {
|
|
27
|
-
return {
|
|
27
|
+
return {}
|
|
28
28
|
}
|
|
29
29
|
const { ref } = db.db.dynamic
|
|
30
30
|
const res = await db.db
|
|
@@ -42,6 +42,11 @@ export default (db: Database): Partial<ServiceImpl<typeof Service>> => ({
|
|
|
42
42
|
.whereRef('creator', '=', ref('profile_agg.did'))
|
|
43
43
|
.select(countAll.as('val'))
|
|
44
44
|
.as('listsCount'),
|
|
45
|
+
db.db
|
|
46
|
+
.selectFrom('starter_pack')
|
|
47
|
+
.whereRef('creator', '=', ref('profile_agg.did'))
|
|
48
|
+
.select(countAll.as('val'))
|
|
49
|
+
.as('starterPacksCount'),
|
|
45
50
|
])
|
|
46
51
|
.execute()
|
|
47
52
|
const byDid = keyBy(res, 'did')
|
|
@@ -51,6 +56,55 @@ export default (db: Database): Partial<ServiceImpl<typeof Service>> => ({
|
|
|
51
56
|
posts: req.dids.map((uri) => byDid[uri]?.postsCount ?? 0),
|
|
52
57
|
lists: req.dids.map((uri) => byDid[uri]?.listsCount ?? 0),
|
|
53
58
|
feeds: req.dids.map((uri) => byDid[uri]?.feedGensCount ?? 0),
|
|
59
|
+
starterPacks: req.dids.map((uri) => byDid[uri]?.starterPacksCount ?? 0),
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
async getStarterPackCounts(req) {
|
|
63
|
+
const weekAgo = new Date(Date.now() - 7 * DAY)
|
|
64
|
+
const uris = req.refs.map((ref) => ref.uri)
|
|
65
|
+
if (uris.length === 0) {
|
|
66
|
+
return { joinedAllTime: [], joinedWeek: [] }
|
|
67
|
+
}
|
|
68
|
+
const countsAllTime = await db.db
|
|
69
|
+
.selectFrom('profile')
|
|
70
|
+
.where('joinedViaStarterPackUri', 'in', uris)
|
|
71
|
+
.select(['joinedViaStarterPackUri as uri', countAll.as('count')])
|
|
72
|
+
.groupBy('joinedViaStarterPackUri')
|
|
73
|
+
.execute()
|
|
74
|
+
const countsWeek = await db.db
|
|
75
|
+
.selectFrom('profile')
|
|
76
|
+
.where('joinedViaStarterPackUri', 'in', uris)
|
|
77
|
+
.where('createdAt', '>', weekAgo.toISOString())
|
|
78
|
+
.select(['joinedViaStarterPackUri as uri', countAll.as('count')])
|
|
79
|
+
.groupBy('joinedViaStarterPackUri')
|
|
80
|
+
.execute()
|
|
81
|
+
const countsWeekByUri = countsWeek.reduce((cur, item) => {
|
|
82
|
+
if (!item.uri) return cur
|
|
83
|
+
return cur.set(item.uri, item.count)
|
|
84
|
+
}, new Map<string, number>())
|
|
85
|
+
const countsAllTimeByUri = countsAllTime.reduce((cur, item) => {
|
|
86
|
+
if (!item.uri) return cur
|
|
87
|
+
return cur.set(item.uri, item.count)
|
|
88
|
+
}, new Map<string, number>())
|
|
89
|
+
return {
|
|
90
|
+
joinedWeek: uris.map((uri) => countsWeekByUri.get(uri) ?? 0),
|
|
91
|
+
joinedAllTime: uris.map((uri) => countsAllTimeByUri.get(uri) ?? 0),
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
async getListCounts(req) {
|
|
95
|
+
const uris = req.refs.map((ref) => ref.uri)
|
|
96
|
+
if (uris.length === 0) {
|
|
97
|
+
return { listItems: [] }
|
|
98
|
+
}
|
|
99
|
+
const countsListItems = await db.db
|
|
100
|
+
.selectFrom('list_item')
|
|
101
|
+
.where('listUri', 'in', uris)
|
|
102
|
+
.select(['listUri as uri', countAll.as('count')])
|
|
103
|
+
.groupBy('listUri')
|
|
104
|
+
.execute()
|
|
105
|
+
const countsByUri = keyBy(countsListItems, 'uri')
|
|
106
|
+
return {
|
|
107
|
+
listItems: uris.map((uri) => countsByUri[uri]?.count ?? 0),
|
|
54
108
|
}
|
|
55
109
|
},
|
|
56
110
|
})
|
|
@@ -54,6 +54,7 @@ export default (db: Database): Partial<ServiceImpl<typeof Service>> => ({
|
|
|
54
54
|
? chatDeclaration['allowIncoming']
|
|
55
55
|
: undefined,
|
|
56
56
|
upstreamStatus: row?.upstreamStatus ?? '',
|
|
57
|
+
createdAt: profiles.records[i].createdAt, // @NOTE profile creation date not trusted in production
|
|
57
58
|
}
|
|
58
59
|
})
|
|
59
60
|
return { actors }
|
|
@@ -22,6 +22,7 @@ export default (db: Database): Partial<ServiceImpl<typeof Service>> => ({
|
|
|
22
22
|
getThreadGateRecords: getRecords(db, ids.AppBskyFeedThreadgate),
|
|
23
23
|
getLabelerRecords: getRecords(db, ids.AppBskyLabelerService),
|
|
24
24
|
getActorChatDeclarationRecords: getRecords(db, ids.ChatBskyActorDeclaration),
|
|
25
|
+
getStarterPackRecords: getRecords(db, ids.AppBskyGraphStarterpack),
|
|
25
26
|
})
|
|
26
27
|
|
|
27
28
|
export const getRecords =
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ServiceImpl } from '@connectrpc/connect'
|
|
2
|
+
import { Service } from '../../../proto/bsky_connect'
|
|
3
|
+
import { Database } from '../db'
|
|
4
|
+
import { TimeCidKeyset, paginate } from '../db/pagination'
|
|
5
|
+
|
|
6
|
+
export default (db: Database): Partial<ServiceImpl<typeof Service>> => ({
|
|
7
|
+
async getActorStarterPacks(req) {
|
|
8
|
+
const { actorDid, limit, cursor } = req
|
|
9
|
+
|
|
10
|
+
const { ref } = db.db.dynamic
|
|
11
|
+
let builder = db.db
|
|
12
|
+
.selectFrom('starter_pack')
|
|
13
|
+
.selectAll()
|
|
14
|
+
.where('creator', '=', actorDid)
|
|
15
|
+
|
|
16
|
+
const keyset = new TimeCidKeyset(
|
|
17
|
+
ref('starter_pack.sortAt'),
|
|
18
|
+
ref('starter_pack.cid'),
|
|
19
|
+
)
|
|
20
|
+
builder = paginate(builder, {
|
|
21
|
+
limit,
|
|
22
|
+
cursor,
|
|
23
|
+
keyset,
|
|
24
|
+
})
|
|
25
|
+
const starterPacks = await builder.execute()
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
uris: starterPacks.map((sp) => sp.uri),
|
|
29
|
+
cursor: keyset.packFromResult(starterPacks),
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
})
|
package/src/hydration/actor.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Timestamp } from '@bufbuild/protobuf'
|
|
1
2
|
import { DataPlaneClient } from '../data-plane/client'
|
|
2
3
|
import { Record as ProfileRecord } from '../lexicon/types/app/bsky/actor/profile'
|
|
3
4
|
import { Record as ChatDeclarationRecord } from '../lexicon/types/chat/bsky/actor/declaration'
|
|
@@ -21,6 +22,7 @@ export type Actor = {
|
|
|
21
22
|
isLabeler: boolean
|
|
22
23
|
allowIncomingChatsFrom?: string
|
|
23
24
|
upstreamStatus?: string
|
|
25
|
+
createdAt?: Date
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
export type Actors = HydrationMap<Actor>
|
|
@@ -54,6 +56,7 @@ export type ProfileAgg = {
|
|
|
54
56
|
posts: number
|
|
55
57
|
lists: number
|
|
56
58
|
feeds: number
|
|
59
|
+
starterPacks: number
|
|
57
60
|
}
|
|
58
61
|
|
|
59
62
|
export type ProfileAggs = HydrationMap<ProfileAgg>
|
|
@@ -127,6 +130,7 @@ export class ActorHydrator {
|
|
|
127
130
|
isLabeler: actor.labeler ?? false,
|
|
128
131
|
allowIncomingChatsFrom: actor.allowIncomingChatsFrom || undefined,
|
|
129
132
|
upstreamStatus: actor.upstreamStatus || undefined,
|
|
133
|
+
createdAt: actor.createdAt?.toDate(),
|
|
130
134
|
})
|
|
131
135
|
}, new HydrationMap<Actor>())
|
|
132
136
|
}
|
|
@@ -211,6 +215,7 @@ export class ActorHydrator {
|
|
|
211
215
|
posts: counts.posts[i] ?? 0,
|
|
212
216
|
lists: counts.lists[i] ?? 0,
|
|
213
217
|
feeds: counts.feeds[i] ?? 0,
|
|
218
|
+
starterPacks: counts.starterPacks[i] ?? 0,
|
|
214
219
|
})
|
|
215
220
|
}, new HydrationMap<ProfileAgg>())
|
|
216
221
|
}
|
package/src/hydration/feed.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { Record as FeedGenRecord } from '../lexicon/types/app/bsky/feed/generato
|
|
|
6
6
|
import { Record as ThreadgateRecord } from '../lexicon/types/app/bsky/feed/threadgate'
|
|
7
7
|
import {
|
|
8
8
|
HydrationMap,
|
|
9
|
+
ItemRef,
|
|
9
10
|
RecordInfo,
|
|
10
11
|
parseRecord,
|
|
11
12
|
parseString,
|
|
@@ -58,7 +59,6 @@ export type FeedGenViewerStates = HydrationMap<FeedGenViewerState>
|
|
|
58
59
|
export type Threadgate = RecordInfo<ThreadgateRecord>
|
|
59
60
|
export type Threadgates = HydrationMap<Threadgate>
|
|
60
61
|
|
|
61
|
-
export type ItemRef = { uri: string; cid?: string }
|
|
62
62
|
export type ThreadRef = ItemRef & { threadRoot: string }
|
|
63
63
|
|
|
64
64
|
// @NOTE the feed item types in the protos for author feeds and timelines
|
|
@@ -203,7 +203,6 @@ export class FeedHydrator {
|
|
|
203
203
|
}, new HydrationMap<Threadgate>())
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
-
// @TODO may not be supported yet by data plane
|
|
207
206
|
async getLikes(uris: string[], includeTakedowns = false): Promise<Likes> {
|
|
208
207
|
if (!uris.length) return new HydrationMap<Like>()
|
|
209
208
|
const res = await this.dataplane.getLikeRecords({ uris })
|
package/src/hydration/graph.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Record as FollowRecord } from '../lexicon/types/app/bsky/graph/follow'
|
|
2
2
|
import { Record as BlockRecord } from '../lexicon/types/app/bsky/graph/block'
|
|
3
|
+
import { Record as StarterPackRecord } from '../lexicon/types/app/bsky/graph/starterpack'
|
|
3
4
|
import { Record as ListRecord } from '../lexicon/types/app/bsky/graph/list'
|
|
4
5
|
import { Record as ListItemRecord } from '../lexicon/types/app/bsky/graph/listitem'
|
|
5
6
|
import { DataPlaneClient } from '../data-plane/client'
|
|
6
|
-
import { HydrationMap, RecordInfo, parseRecord } from './util'
|
|
7
|
+
import { HydrationMap, ItemRef, RecordInfo, parseRecord } from './util'
|
|
7
8
|
import { FollowInfo } from '../proto/bsky_pb'
|
|
8
9
|
|
|
9
10
|
export type List = RecordInfo<ListRecord>
|
|
@@ -25,6 +26,23 @@ export type Follows = HydrationMap<Follow>
|
|
|
25
26
|
|
|
26
27
|
export type Block = RecordInfo<BlockRecord>
|
|
27
28
|
|
|
29
|
+
export type StarterPack = RecordInfo<StarterPackRecord>
|
|
30
|
+
export type StarterPacks = HydrationMap<StarterPack>
|
|
31
|
+
|
|
32
|
+
export type StarterPackAgg = {
|
|
33
|
+
joinedWeek: number
|
|
34
|
+
joinedAllTime: number
|
|
35
|
+
listItemSampleUris?: string[] // gets set during starter pack hydration (not for basic view)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type StarterPackAggs = HydrationMap<StarterPackAgg>
|
|
39
|
+
|
|
40
|
+
export type ListAgg = {
|
|
41
|
+
listItems: number
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type ListAggs = HydrationMap<ListAgg>
|
|
45
|
+
|
|
28
46
|
export type RelationshipPair = [didA: string, didB: string]
|
|
29
47
|
|
|
30
48
|
const dedupePairs = (pairs: RelationshipPair[]): RelationshipPair[] => {
|
|
@@ -84,7 +102,6 @@ export class GraphHydrator {
|
|
|
84
102
|
}, new HydrationMap<List>())
|
|
85
103
|
}
|
|
86
104
|
|
|
87
|
-
// @TODO may not be supported yet by data plane
|
|
88
105
|
async getListItems(
|
|
89
106
|
uris: string[],
|
|
90
107
|
includeTakedowns = false,
|
|
@@ -195,4 +212,40 @@ export class GraphHydrator {
|
|
|
195
212
|
})
|
|
196
213
|
return { followers: res.followers, cursor: res.cursor }
|
|
197
214
|
}
|
|
215
|
+
|
|
216
|
+
async getStarterPacks(
|
|
217
|
+
uris: string[],
|
|
218
|
+
includeTakedowns = false,
|
|
219
|
+
): Promise<StarterPacks> {
|
|
220
|
+
if (!uris.length) return new HydrationMap<StarterPack>()
|
|
221
|
+
const res = await this.dataplane.getStarterPackRecords({ uris })
|
|
222
|
+
return uris.reduce((acc, uri, i) => {
|
|
223
|
+
const record = parseRecord<StarterPackRecord>(
|
|
224
|
+
res.records[i],
|
|
225
|
+
includeTakedowns,
|
|
226
|
+
)
|
|
227
|
+
return acc.set(uri, record ?? null)
|
|
228
|
+
}, new HydrationMap<StarterPack>())
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async getStarterPackAggregates(refs: ItemRef[]) {
|
|
232
|
+
if (!refs.length) return new HydrationMap<StarterPackAgg>()
|
|
233
|
+
const counts = await this.dataplane.getStarterPackCounts({ refs })
|
|
234
|
+
return refs.reduce((acc, { uri }, i) => {
|
|
235
|
+
return acc.set(uri, {
|
|
236
|
+
joinedWeek: counts.joinedWeek[i] ?? 0,
|
|
237
|
+
joinedAllTime: counts.joinedAllTime[i] ?? 0,
|
|
238
|
+
})
|
|
239
|
+
}, new HydrationMap<StarterPackAgg>())
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async getListAggregates(refs: ItemRef[]) {
|
|
243
|
+
if (!refs.length) return new HydrationMap<ListAgg>()
|
|
244
|
+
const counts = await this.dataplane.getListCounts({ refs })
|
|
245
|
+
return refs.reduce((acc, { uri }, i) => {
|
|
246
|
+
return acc.set(uri, {
|
|
247
|
+
listItems: counts.listItems[i] ?? 0,
|
|
248
|
+
})
|
|
249
|
+
}, new HydrationMap<ListAgg>())
|
|
250
|
+
}
|
|
198
251
|
}
|