@atproto/bsky 0.0.176 → 0.0.178
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 +19 -0
- package/dist/api/app/bsky/graph/getList.js +1 -6
- package/dist/api/app/bsky/graph/getList.js.map +1 -1
- package/dist/api/app/bsky/graph/getLists.d.ts.map +1 -1
- package/dist/api/app/bsky/graph/getLists.js +16 -4
- package/dist/api/app/bsky/graph/getLists.js.map +1 -1
- package/dist/api/app/bsky/graph/getListsWithMembership.d.ts +4 -0
- package/dist/api/app/bsky/graph/getListsWithMembership.d.ts.map +1 -0
- package/dist/api/app/bsky/graph/getListsWithMembership.js +88 -0
- package/dist/api/app/bsky/graph/getListsWithMembership.js.map +1 -0
- package/dist/api/app/bsky/graph/getStarterPacksWithMembership.d.ts +4 -0
- package/dist/api/app/bsky/graph/getStarterPacksWithMembership.d.ts.map +1 -0
- package/dist/api/app/bsky/graph/getStarterPacksWithMembership.js +72 -0
- package/dist/api/app/bsky/graph/getStarterPacksWithMembership.js.map +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +4 -0
- package/dist/api/index.js.map +1 -1
- package/dist/hydration/graph.d.ts +4 -0
- package/dist/hydration/graph.d.ts.map +1 -1
- package/dist/hydration/graph.js.map +1 -1
- package/dist/hydration/hydrator.d.ts +3 -1
- package/dist/hydration/hydrator.d.ts.map +1 -1
- package/dist/hydration/hydrator.js +27 -0
- package/dist/hydration/hydrator.js.map +1 -1
- package/dist/lexicon/index.d.ts +234 -230
- package/dist/lexicon/index.d.ts.map +1 -1
- package/dist/lexicon/index.js +682 -674
- package/dist/lexicon/index.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +17073 -16785
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +9126 -8980
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/graph/getLists.d.ts +2 -0
- package/dist/lexicon/types/app/bsky/graph/getLists.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/graph/getListsWithMembership.d.ts +40 -0
- package/dist/lexicon/types/app/bsky/graph/getListsWithMembership.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/getListsWithMembership.js +16 -0
- package/dist/lexicon/types/app/bsky/graph/getListsWithMembership.js.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPacksWithMembership.d.ts +38 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPacksWithMembership.d.ts.map +1 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPacksWithMembership.js +16 -0
- package/dist/lexicon/types/app/bsky/graph/getStarterPacksWithMembership.js.map +1 -0
- package/dist/views/index.d.ts +2 -1
- package/dist/views/index.d.ts.map +1 -1
- package/dist/views/index.js +6 -0
- package/dist/views/index.js.map +1 -1
- package/package.json +11 -11
- package/src/api/app/bsky/graph/getList.ts +3 -5
- package/src/api/app/bsky/graph/getLists.ts +18 -5
- package/src/api/app/bsky/graph/getListsWithMembership.ts +139 -0
- package/src/api/app/bsky/graph/getStarterPacksWithMembership.ts +135 -0
- package/src/api/index.ts +4 -0
- package/src/hydration/graph.ts +8 -0
- package/src/hydration/hydrator.ts +43 -0
- package/src/lexicon/index.ts +1247 -1221
- package/src/lexicon/lexicons.ts +9494 -9341
- package/src/lexicon/types/app/bsky/graph/getLists.ts +2 -0
- package/src/lexicon/types/app/bsky/graph/getListsWithMembership.ts +63 -0
- package/src/lexicon/types/app/bsky/graph/getStarterPacksWithMembership.ts +65 -0
- package/src/views/index.ts +11 -0
- package/tests/views/__snapshots__/lists.test.ts.snap +160 -8
- package/tests/views/lists.test.ts +270 -36
- package/tests/views/starter-packs.test.ts +132 -3
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { mapDefined } from '@atproto/common'
|
|
2
|
+
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
3
|
+
import { AppContext } from '../../../../context'
|
|
4
|
+
import { HydrateCtx, Hydrator } from '../../../../hydration/hydrator'
|
|
5
|
+
import { Server } from '../../../../lexicon'
|
|
6
|
+
import {
|
|
7
|
+
CURATELIST,
|
|
8
|
+
MODLIST,
|
|
9
|
+
} from '../../../../lexicon/types/app/bsky/graph/defs'
|
|
10
|
+
import { QueryParams } from '../../../../lexicon/types/app/bsky/graph/getListsWithMembership'
|
|
11
|
+
import {
|
|
12
|
+
HydrationFnInput,
|
|
13
|
+
PresentationFnInput,
|
|
14
|
+
RulesFnInput,
|
|
15
|
+
SkeletonFnInput,
|
|
16
|
+
createPipeline,
|
|
17
|
+
} from '../../../../pipeline'
|
|
18
|
+
import { Views } from '../../../../views'
|
|
19
|
+
import { clearlyBadCursor, resHeaders } from '../../../util'
|
|
20
|
+
|
|
21
|
+
export default function (server: Server, ctx: AppContext) {
|
|
22
|
+
const getListsWithMembership = createPipeline(
|
|
23
|
+
skeleton,
|
|
24
|
+
hydration,
|
|
25
|
+
filterPurposes,
|
|
26
|
+
presentation,
|
|
27
|
+
)
|
|
28
|
+
server.app.bsky.graph.getListsWithMembership({
|
|
29
|
+
auth: ctx.authVerifier.standard,
|
|
30
|
+
handler: async ({ params, auth, req }) => {
|
|
31
|
+
const viewer = auth.credentials.iss
|
|
32
|
+
const labelers = ctx.reqLabelers(req)
|
|
33
|
+
const hydrateCtx = await ctx.hydrator.createContext({
|
|
34
|
+
labelers,
|
|
35
|
+
viewer,
|
|
36
|
+
})
|
|
37
|
+
const result = await getListsWithMembership(
|
|
38
|
+
{ ...params, hydrateCtx: hydrateCtx.copy({ viewer }) },
|
|
39
|
+
ctx,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
encoding: 'application/json',
|
|
44
|
+
body: result,
|
|
45
|
+
headers: resHeaders({ labelers: hydrateCtx.labelers }),
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const skeleton = async (
|
|
52
|
+
input: SkeletonFnInput<Context, Params>,
|
|
53
|
+
): Promise<SkeletonState> => {
|
|
54
|
+
const { ctx, params } = input
|
|
55
|
+
const [actorDid] = await ctx.hydrator.actor.getDids([params.actor])
|
|
56
|
+
if (!actorDid) throw new InvalidRequestError('Profile not found')
|
|
57
|
+
|
|
58
|
+
if (clearlyBadCursor(params.cursor)) {
|
|
59
|
+
return { actorDid, listUris: [] }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const { listUris, cursor } = await ctx.hydrator.dataplane.getActorLists({
|
|
63
|
+
actorDid: params.hydrateCtx.viewer,
|
|
64
|
+
cursor: params.cursor,
|
|
65
|
+
limit: params.limit,
|
|
66
|
+
})
|
|
67
|
+
return { actorDid, listUris, cursor: cursor || undefined }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const hydration = async (
|
|
71
|
+
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
72
|
+
) => {
|
|
73
|
+
const { ctx, params, skeleton } = input
|
|
74
|
+
const { actorDid, listUris } = skeleton
|
|
75
|
+
return ctx.hydrator.hydrateListsMembership(
|
|
76
|
+
listUris,
|
|
77
|
+
actorDid,
|
|
78
|
+
params.hydrateCtx,
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const filterPurposes = (
|
|
83
|
+
input: RulesFnInput<Context, Params, SkeletonState>,
|
|
84
|
+
) => {
|
|
85
|
+
const { skeleton, hydration, params } = input
|
|
86
|
+
const purposes = params.purposes || ['modlist', 'curatelist']
|
|
87
|
+
|
|
88
|
+
const acceptedPurposes = new Set()
|
|
89
|
+
if (purposes.includes('modlist')) acceptedPurposes.add(MODLIST)
|
|
90
|
+
if (purposes.includes(MODLIST)) acceptedPurposes.add(MODLIST)
|
|
91
|
+
if (purposes.includes('curatelist')) acceptedPurposes.add(CURATELIST)
|
|
92
|
+
if (purposes.includes(CURATELIST)) acceptedPurposes.add(CURATELIST)
|
|
93
|
+
|
|
94
|
+
// @NOTE: While we don't support filtering on the dataplane, this might result in empty pages.
|
|
95
|
+
// Despite the empty pages, the pagination still can enumerate all items for the specified filters.
|
|
96
|
+
skeleton.listUris = skeleton.listUris.filter((uri) => {
|
|
97
|
+
const list = hydration.lists?.get(uri)
|
|
98
|
+
return acceptedPurposes.has(list?.record.purpose)
|
|
99
|
+
})
|
|
100
|
+
return skeleton
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const presentation = (
|
|
104
|
+
input: PresentationFnInput<Context, Params, SkeletonState>,
|
|
105
|
+
) => {
|
|
106
|
+
const { ctx, skeleton, hydration } = input
|
|
107
|
+
const { actorDid, listUris, cursor } = skeleton
|
|
108
|
+
const listsWithMembership = mapDefined(listUris, (uri) => {
|
|
109
|
+
const list = ctx.views.list(uri, hydration)
|
|
110
|
+
if (!list) return
|
|
111
|
+
|
|
112
|
+
const listItemUri = hydration.listMemberships
|
|
113
|
+
?.get(uri)
|
|
114
|
+
?.get(actorDid)?.actorListItemUri
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
list,
|
|
118
|
+
listItem: listItemUri
|
|
119
|
+
? ctx.views.listItemView(listItemUri, actorDid, hydration)
|
|
120
|
+
: undefined,
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
return { listsWithMembership, cursor }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
type Context = {
|
|
127
|
+
hydrator: Hydrator
|
|
128
|
+
views: Views
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
type Params = QueryParams & {
|
|
132
|
+
hydrateCtx: HydrateCtx & { viewer: string }
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
type SkeletonState = {
|
|
136
|
+
actorDid: string
|
|
137
|
+
listUris: string[]
|
|
138
|
+
cursor?: string
|
|
139
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { mapDefined } from '@atproto/common'
|
|
2
|
+
import { InvalidRequestError } from '@atproto/xrpc-server'
|
|
3
|
+
import { AppContext } from '../../../../context'
|
|
4
|
+
import {
|
|
5
|
+
HydrateCtx,
|
|
6
|
+
Hydrator,
|
|
7
|
+
mergeManyStates,
|
|
8
|
+
} from '../../../../hydration/hydrator'
|
|
9
|
+
import { Server } from '../../../../lexicon'
|
|
10
|
+
import {
|
|
11
|
+
OutputSchema,
|
|
12
|
+
QueryParams,
|
|
13
|
+
} from '../../../../lexicon/types/app/bsky/graph/getStarterPacksWithMembership'
|
|
14
|
+
import {
|
|
15
|
+
HydrationFnInput,
|
|
16
|
+
PresentationFnInput,
|
|
17
|
+
SkeletonFnInput,
|
|
18
|
+
createPipeline,
|
|
19
|
+
noRules,
|
|
20
|
+
} from '../../../../pipeline'
|
|
21
|
+
import { Views } from '../../../../views'
|
|
22
|
+
import { clearlyBadCursor, resHeaders } from '../../../util'
|
|
23
|
+
|
|
24
|
+
export default function (server: Server, ctx: AppContext) {
|
|
25
|
+
const getStarterPacksWithMembership = createPipeline(
|
|
26
|
+
skeleton,
|
|
27
|
+
hydration,
|
|
28
|
+
noRules,
|
|
29
|
+
presentation,
|
|
30
|
+
)
|
|
31
|
+
server.app.bsky.graph.getStarterPacksWithMembership({
|
|
32
|
+
auth: ctx.authVerifier.standard,
|
|
33
|
+
handler: async ({ params, auth, req }) => {
|
|
34
|
+
const viewer = auth.credentials.iss
|
|
35
|
+
const labelers = ctx.reqLabelers(req)
|
|
36
|
+
const hydrateCtx = await ctx.hydrator.createContext({
|
|
37
|
+
labelers,
|
|
38
|
+
viewer,
|
|
39
|
+
})
|
|
40
|
+
const result = await getStarterPacksWithMembership(
|
|
41
|
+
{ ...params, hydrateCtx: hydrateCtx.copy({ viewer }) },
|
|
42
|
+
ctx,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
encoding: 'application/json',
|
|
47
|
+
body: result,
|
|
48
|
+
headers: resHeaders({ labelers: hydrateCtx.labelers }),
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const skeleton = async (
|
|
55
|
+
input: SkeletonFnInput<Context, Params>,
|
|
56
|
+
): Promise<SkeletonState> => {
|
|
57
|
+
const { ctx, params } = input
|
|
58
|
+
const [actorDid] = await ctx.hydrator.actor.getDids([params.actor])
|
|
59
|
+
if (!actorDid) throw new InvalidRequestError('Profile not found')
|
|
60
|
+
|
|
61
|
+
if (clearlyBadCursor(params.cursor)) {
|
|
62
|
+
return { actorDid, starterPackUris: [] }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { uris: starterPackUris, cursor } =
|
|
66
|
+
await ctx.hydrator.dataplane.getActorStarterPacks({
|
|
67
|
+
actorDid: params.hydrateCtx.viewer,
|
|
68
|
+
cursor: params.cursor,
|
|
69
|
+
limit: params.limit,
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
return { actorDid, starterPackUris, cursor: cursor || undefined }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const hydration = async (
|
|
76
|
+
input: HydrationFnInput<Context, Params, SkeletonState>,
|
|
77
|
+
) => {
|
|
78
|
+
const { ctx, params, skeleton } = input
|
|
79
|
+
const { actorDid, starterPackUris } = skeleton
|
|
80
|
+
const spHydrationState = await ctx.hydrator.hydrateStarterPacks(
|
|
81
|
+
starterPackUris,
|
|
82
|
+
params.hydrateCtx,
|
|
83
|
+
)
|
|
84
|
+
const listUris = mapDefined(
|
|
85
|
+
starterPackUris,
|
|
86
|
+
(uri) => spHydrationState.starterPacks?.get(uri)?.record.list,
|
|
87
|
+
)
|
|
88
|
+
const listMembershipHydrationState =
|
|
89
|
+
await ctx.hydrator.hydrateListsMembership(
|
|
90
|
+
listUris,
|
|
91
|
+
actorDid,
|
|
92
|
+
params.hydrateCtx,
|
|
93
|
+
)
|
|
94
|
+
return mergeManyStates(spHydrationState, listMembershipHydrationState)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const presentation = (
|
|
98
|
+
input: PresentationFnInput<Context, Params, SkeletonState>,
|
|
99
|
+
): OutputSchema => {
|
|
100
|
+
const { ctx, skeleton, hydration } = input
|
|
101
|
+
const { actorDid, starterPackUris, cursor } = skeleton
|
|
102
|
+
|
|
103
|
+
const starterPacksWithMembership = mapDefined(starterPackUris, (spUri) => {
|
|
104
|
+
const listUri = hydration.starterPacks?.get(spUri)?.record.list
|
|
105
|
+
const starterPack = ctx.views.starterPack(spUri, hydration)
|
|
106
|
+
if (!listUri || !starterPack) return
|
|
107
|
+
|
|
108
|
+
const listItemUri = hydration.listMemberships
|
|
109
|
+
?.get(listUri)
|
|
110
|
+
?.get(actorDid)?.actorListItemUri
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
starterPack,
|
|
114
|
+
listItem: listItemUri
|
|
115
|
+
? ctx.views.listItemView(listItemUri, actorDid, hydration)
|
|
116
|
+
: undefined,
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
return { starterPacksWithMembership, cursor }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
type Context = {
|
|
123
|
+
hydrator: Hydrator
|
|
124
|
+
views: Views
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
type Params = QueryParams & {
|
|
128
|
+
hydrateCtx: HydrateCtx & { viewer: string }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
type SkeletonState = {
|
|
132
|
+
actorDid: string
|
|
133
|
+
starterPackUris: string[]
|
|
134
|
+
cursor?: string
|
|
135
|
+
}
|
package/src/api/index.ts
CHANGED
|
@@ -29,10 +29,12 @@ import getList from './app/bsky/graph/getList'
|
|
|
29
29
|
import getListBlocks from './app/bsky/graph/getListBlocks'
|
|
30
30
|
import getListMutes from './app/bsky/graph/getListMutes'
|
|
31
31
|
import getLists from './app/bsky/graph/getLists'
|
|
32
|
+
import getListsWithMembership from './app/bsky/graph/getListsWithMembership'
|
|
32
33
|
import getMutes from './app/bsky/graph/getMutes'
|
|
33
34
|
import getRelationships from './app/bsky/graph/getRelationships'
|
|
34
35
|
import getStarterPack from './app/bsky/graph/getStarterPack'
|
|
35
36
|
import getStarterPacks from './app/bsky/graph/getStarterPacks'
|
|
37
|
+
import getStarterPacksWithMembership from './app/bsky/graph/getStarterPacksWithMembership'
|
|
36
38
|
import getSuggestedFollowsByActor from './app/bsky/graph/getSuggestedFollowsByActor'
|
|
37
39
|
import muteActor from './app/bsky/graph/muteActor'
|
|
38
40
|
import muteActorList from './app/bsky/graph/muteActorList'
|
|
@@ -108,11 +110,13 @@ export default function (server: Server, ctx: AppContext) {
|
|
|
108
110
|
getFollows(server, ctx)
|
|
109
111
|
getList(server, ctx)
|
|
110
112
|
getLists(server, ctx)
|
|
113
|
+
getListsWithMembership(server, ctx)
|
|
111
114
|
getListMutes(server, ctx)
|
|
112
115
|
getMutes(server, ctx)
|
|
113
116
|
getRelationships(server, ctx)
|
|
114
117
|
getStarterPack(server, ctx)
|
|
115
118
|
getStarterPacks(server, ctx)
|
|
119
|
+
getStarterPacksWithMembership(server, ctx)
|
|
116
120
|
searchStarterPacks(server, ctx)
|
|
117
121
|
muteActor(server, ctx)
|
|
118
122
|
unmuteActor(server, ctx)
|
package/src/hydration/graph.ts
CHANGED
|
@@ -22,6 +22,14 @@ export type ListViewerState = {
|
|
|
22
22
|
|
|
23
23
|
export type ListViewerStates = HydrationMap<ListViewerState>
|
|
24
24
|
|
|
25
|
+
export type ListMembershipState = {
|
|
26
|
+
actorListItemUri?: string
|
|
27
|
+
}
|
|
28
|
+
// list uri => actor did => state
|
|
29
|
+
export type ListMembershipStates = HydrationMap<
|
|
30
|
+
HydrationMap<ListMembershipState>
|
|
31
|
+
>
|
|
32
|
+
|
|
25
33
|
export type Follow = RecordInfo<FollowRecord>
|
|
26
34
|
export type Follows = HydrationMap<Follow>
|
|
27
35
|
|
|
@@ -43,6 +43,8 @@ import {
|
|
|
43
43
|
GraphHydrator,
|
|
44
44
|
ListAggs,
|
|
45
45
|
ListItems,
|
|
46
|
+
ListMembershipState,
|
|
47
|
+
ListMembershipStates,
|
|
46
48
|
ListViewerStates,
|
|
47
49
|
Lists,
|
|
48
50
|
RelationshipPair,
|
|
@@ -109,6 +111,7 @@ export type HydrationState = {
|
|
|
109
111
|
postgates?: Postgates
|
|
110
112
|
lists?: Lists
|
|
111
113
|
listAggs?: ListAggs
|
|
114
|
+
listMemberships?: ListMembershipStates
|
|
112
115
|
listViewers?: ListViewerStates
|
|
113
116
|
listItems?: ListItems
|
|
114
117
|
likes?: Likes
|
|
@@ -363,6 +366,45 @@ export class Hydrator {
|
|
|
363
366
|
return mergeStates(profileState, { listItems, ctx })
|
|
364
367
|
}
|
|
365
368
|
|
|
369
|
+
async hydrateListsMembership(
|
|
370
|
+
uris: string[],
|
|
371
|
+
did: string,
|
|
372
|
+
ctx: HydrateCtx,
|
|
373
|
+
): Promise<HydrationState> {
|
|
374
|
+
const [
|
|
375
|
+
actorsHydrationState,
|
|
376
|
+
listsHydrationState,
|
|
377
|
+
{ listitemUris: listItemUris },
|
|
378
|
+
] = await Promise.all([
|
|
379
|
+
this.hydrateProfiles([did], ctx),
|
|
380
|
+
this.hydrateLists(uris, ctx),
|
|
381
|
+
this.dataplane.getListMembership({
|
|
382
|
+
actorDid: did,
|
|
383
|
+
listUris: uris,
|
|
384
|
+
}),
|
|
385
|
+
])
|
|
386
|
+
|
|
387
|
+
// mapping uri -> did -> { actorListItemUri }
|
|
388
|
+
const listMemberships = new HydrationMap(
|
|
389
|
+
uris.map((uri, i) => {
|
|
390
|
+
const listItemUri = listItemUris[i]
|
|
391
|
+
return [
|
|
392
|
+
uri,
|
|
393
|
+
new HydrationMap<ListMembershipState>([
|
|
394
|
+
listItemUri
|
|
395
|
+
? [did, { actorListItemUri: listItemUri }]
|
|
396
|
+
: [did, null],
|
|
397
|
+
]),
|
|
398
|
+
]
|
|
399
|
+
}),
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
return mergeManyStates(actorsHydrationState, listsHydrationState, {
|
|
403
|
+
listMemberships,
|
|
404
|
+
ctx,
|
|
405
|
+
})
|
|
406
|
+
}
|
|
407
|
+
|
|
366
408
|
// app.bsky.feed.defs#postView
|
|
367
409
|
// - post
|
|
368
410
|
// - profile
|
|
@@ -1356,6 +1398,7 @@ export const mergeStates = (
|
|
|
1356
1398
|
postgates: mergeMaps(stateA.postgates, stateB.postgates),
|
|
1357
1399
|
lists: mergeMaps(stateA.lists, stateB.lists),
|
|
1358
1400
|
listAggs: mergeMaps(stateA.listAggs, stateB.listAggs),
|
|
1401
|
+
listMemberships: mergeMaps(stateA.listMemberships, stateB.listMemberships),
|
|
1359
1402
|
listViewers: mergeMaps(stateA.listViewers, stateB.listViewers),
|
|
1360
1403
|
listItems: mergeMaps(stateA.listItems, stateB.listItems),
|
|
1361
1404
|
likes: mergeMaps(stateA.likes, stateB.likes),
|