Define Reaction edges (#845)

This adds support to `github/edges` for creating edges representing
GitHub reactions. These edges are not actually added to the graph.

Test plan: Unit tests
This commit is contained in:
Dandelion Mané 2018-09-17 13:35:47 -07:00 committed by GitHub
parent e9279bee90
commit 33d14b9d1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 198 additions and 1 deletions

View File

@ -155,6 +155,127 @@ Object {
}
`;
exports[`plugins/github/edges createEdge works for "reactsHeart" 1`] = `
Object {
"addressParts": Array [
"sourcecred",
"github",
"REACTS",
"HEART",
"5",
"sourcecred",
"github",
"USERLIKE",
"USER",
"decentralion",
"6",
"sourcecred",
"github",
"PULL",
"sourcecred",
"example-github",
"5",
],
"dstParts": Array [
"sourcecred",
"github",
"PULL",
"sourcecred",
"example-github",
"5",
],
"srcParts": Array [
"sourcecred",
"github",
"USERLIKE",
"USER",
"decentralion",
],
}
`;
exports[`plugins/github/edges createEdge works for "reactsHooray" 1`] = `
Object {
"addressParts": Array [
"sourcecred",
"github",
"REACTS",
"HOORAY",
"5",
"sourcecred",
"github",
"USERLIKE",
"USER",
"decentralion",
"8",
"sourcecred",
"github",
"COMMENT",
"ISSUE",
"sourcecred",
"example-github",
"2",
"373768703",
],
"dstParts": Array [
"sourcecred",
"github",
"COMMENT",
"ISSUE",
"sourcecred",
"example-github",
"2",
"373768703",
],
"srcParts": Array [
"sourcecred",
"github",
"USERLIKE",
"USER",
"decentralion",
],
}
`;
exports[`plugins/github/edges createEdge works for "reactsThumbsUp" 1`] = `
Object {
"addressParts": Array [
"sourcecred",
"github",
"REACTS",
"THUMBS_UP",
"5",
"sourcecred",
"github",
"USERLIKE",
"USER",
"decentralion",
"6",
"sourcecred",
"github",
"ISSUE",
"sourcecred",
"example-github",
"2",
],
"dstParts": Array [
"sourcecred",
"github",
"ISSUE",
"sourcecred",
"example-github",
"2",
],
"srcParts": Array [
"sourcecred",
"github",
"USERLIKE",
"USER",
"decentralion",
],
}
`;
exports[`plugins/github/edges createEdge works for "references" 1`] = `
Object {
"addressParts": Array [

View File

@ -9,6 +9,8 @@ import {
import * as GithubNode from "./nodes";
import * as GitNode from "../git/nodes";
import type {MentionsAuthorReference} from "./heuristics/mentionsAuthorReference";
// TODO(@decentralion): Opportunity to reduce bundle size (tree shaking?)
import {Reactions, type ReactionContent} from "./graphql";
export opaque type RawAddress: EdgeAddressT = EdgeAddressT;
@ -17,6 +19,7 @@ export const MERGED_AS_TYPE = "MERGED_AS";
export const HAS_PARENT_TYPE = "HAS_PARENT";
export const REFERENCES_TYPE = "REFERENCES";
export const MENTIONS_AUTHOR_TYPE = "MENTIONS_AUTHOR";
export const REACTS_TYPE = "REACTS";
const GITHUB_PREFIX = EdgeAddress.fromParts(["sourcecred", "github"]);
function githubEdgeAddress(...parts: string[]): RawAddress {
@ -30,6 +33,10 @@ export const Prefix = Object.freeze({
references: githubEdgeAddress(REFERENCES_TYPE),
hasParent: githubEdgeAddress(HAS_PARENT_TYPE),
mentionsAuthor: githubEdgeAddress(MENTIONS_AUTHOR_TYPE),
reacts: githubEdgeAddress(REACTS_TYPE),
reactsThumbsUp: githubEdgeAddress(REACTS_TYPE, Reactions.THUMBS_UP),
reactsHeart: githubEdgeAddress(REACTS_TYPE, Reactions.HEART),
reactsHooray: githubEdgeAddress(REACTS_TYPE, Reactions.HOORAY),
});
export type AuthorsAddress = {|
@ -54,13 +61,20 @@ export type MentionsAuthorAddress = {|
+type: typeof MENTIONS_AUTHOR_TYPE,
+reference: MentionsAuthorReference,
|};
export type ReactsAddress = {|
+type: typeof REACTS_TYPE,
+reactionType: ReactionContent,
+user: GithubNode.UserlikeAddress,
+reactable: GithubNode.ReactableAddress,
|};
export type StructuredAddress =
| AuthorsAddress
| MergedAsAddress
| HasParentAddress
| ReferencesAddress
| MentionsAuthorAddress;
| MentionsAuthorAddress
| ReactsAddress;
export const createEdge = Object.freeze({
authors: (
@ -100,6 +114,20 @@ export const createEdge = Object.freeze({
src: GithubNode.toRaw(reference.src),
dst: GithubNode.toRaw(reference.dst),
}),
reacts: (
reactionType: ReactionContent,
user: GithubNode.UserlikeAddress,
reactable: GithubNode.ReactableAddress
): Edge => ({
address: toRaw({
type: REACTS_TYPE,
user,
reactionType,
reactable,
}),
src: GithubNode.toRaw(user),
dst: GithubNode.toRaw(reactable),
}),
});
function lengthEncode(x: GithubNode.RawAddress): $ReadOnlyArray<string> {
@ -213,6 +241,25 @@ export function fromRaw(x: RawAddress): StructuredAddress {
const reference = {src, dst, who};
return {type: MENTIONS_AUTHOR_TYPE, reference};
}
case REACTS_TYPE: {
const [rawReactionType, ...rest2] = rest;
const reactionType = Reactions[rawReactionType];
if (reactionType == null) {
throw fail();
}
const parts = multiLengthDecode(rest2, fail);
if (parts.length !== 2) {
throw fail();
}
const [userParts, reactableParts] = parts;
const user: GithubNode.UserlikeAddress = (GithubNode.fromRaw(
(NodeAddress.fromParts(userParts): any)
): any);
const reactable: GithubNode.ReactableAddress = (GithubNode.fromRaw(
(NodeAddress.fromParts(reactableParts): any)
): any);
return {type: REACTS_TYPE, reactionType, user, reactable};
}
default:
throw fail();
}
@ -249,6 +296,13 @@ export function toRaw(x: StructuredAddress): RawAddress {
...lengthEncode(GithubNode.toRaw(x.reference.dst)),
...lengthEncode(GithubNode.toRaw(x.reference.who))
);
case REACTS_TYPE:
return EdgeAddress.append(
Prefix.reacts,
x.reactionType,
...lengthEncode(GithubNode.toRaw(x.user)),
...lengthEncode(GithubNode.toRaw(x.reactable))
);
default:
throw new Error((x.type: empty));
}

View File

@ -5,6 +5,7 @@ import {createEdge, fromRaw, toRaw} from "./edges";
import * as GE from "./edges";
import * as GN from "./nodes";
import {COMMIT_TYPE} from "../git/nodes";
import {Reactions} from "./graphql";
describe("plugins/github/edges", () => {
const nodeExamples = {
@ -63,6 +64,24 @@ describe("plugins/github/edges", () => {
dst: nodeExamples.issue(),
who: nodeExamples.user(),
}),
reactsHeart: () =>
createEdge.reacts(
Reactions.HEART,
nodeExamples.user(),
nodeExamples.pull()
),
reactsThumbsUp: () =>
createEdge.reacts(
Reactions.THUMBS_UP,
nodeExamples.user(),
nodeExamples.issue()
),
reactsHooray: () =>
createEdge.reacts(
Reactions.HOORAY,
nodeExamples.user(),
nodeExamples.issueComment()
),
};
describe("createEdge", () => {

View File

@ -120,6 +120,9 @@ export type ParentAddress =
| PullAddress
| ReviewAddress;
// GitHub allows you to react to these types
export type ReactableAddress = IssueAddress | PullAddress | CommentAddress;
// Each of these types may have Comments as children
export type CommentableAddress = IssueAddress | PullAddress | ReviewAddress;