Created
September 12, 2017 17:07
-
-
Save brianlovin/5572d1b729363d1c1eda9655602690d4 to your computer and use it in GitHub Desktop.
Resolving downstream info
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
On Spectrum we store permissions within communities in a table called `usersCommunities`. | |
This table returns records that look like: | |
{ | |
id: ID | |
userId: ID | |
communityId: ID | |
isMember: Boolean | |
isModerator: Boolean | |
isOwner: Boolean | |
reputation: Int | |
} | |
There are times on Spectrum where I'm viewing different contexts and would like to fetch these permissions for | |
every user being rendered on the client. | |
For example, when viewing a thread - | |
(https://spectrum.chat/thread/d7b90e8a-7de7-4266-8e4a-0b7c58725f5b) | |
we want to render badges next to each username to show if they are a moderator in that community, and also show a | |
small count for each user's reputation within the community where that thread was posted. | |
Let's take a look at how we get thread messages info: | |
*/ | |
// schema | |
type Thread { | |
... | |
messageConnection(first: Int, after: String): ThreadMessagesConnection! | |
} | |
type ThreadMessagesConnection { | |
pageInfo: PageInfo! | |
edges: [ThreadMessageEdge!] | |
} | |
type ThreadMessageEdge { | |
cursor: String! | |
node: Message! | |
} | |
type Message { | |
... | |
sender: User! | |
} | |
/* | |
So you can see that when we query for a thread's messages, we return a cursor-paginated | |
list and use the `sender` field to resolve a User. | |
The problem is that by the time the sender hits the User resolver, we've now lost the original query variable | |
containing the thread id: | |
*/ | |
query getThreadMessages($id: ID!, $after: String) { | |
thread(id: $id) { | |
id | |
...threadMessages | |
} | |
} | |
fragment threadMessages on Thread { | |
messageConnection(after: $after) { | |
pageInfo { | |
hasNextPage | |
hasPreviousPage | |
} | |
edges { | |
node { | |
...messageInfo | |
} | |
} | |
} | |
} | |
fragment messageInfo on Message { | |
... | |
sender { | |
...userInfo | |
contextPermissions { | |
reputation | |
isOwner | |
isModerator | |
} | |
} | |
/* | |
In order to get that `contextPermissions` field, I need to know a few things in the resolver: | |
1. The threadId that is being viewed | |
2. The communityId where that thread was posted | |
Unfortunately I don't know how to get that context so far downstream in the resolver flow. | |
But I realized I could use the fourth `info` argument to possibly hack around this. Here's my solution: | |
*/ | |
contextPermissions: (user, _, __, info) => { | |
const queryName = info.operation.name.value; | |
const handleCheck = async () => { | |
switch (queryName) { | |
case 'getThreadMessages': { | |
const threadId = info.variableValues.id; | |
const { communityId } = await getThread(threadId); | |
const { | |
reputation, | |
isModerator, | |
isOwner, | |
} = await getUserPermissionsInCommunity(communityId, user.id); | |
return { | |
reputation, | |
isModerator, | |
isOwner, | |
}; | |
} | |
} | |
}; | |
return handleCheck(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment