Expose node/edge prefixes publicly (#814)

Both the GitHub and Git plugins create a `_Prefix` object for nodes and
edges, which gives the respective prefixes for different node/edge
types. We named it `_Prefix` because we weren't sure if these should be
exported. In practice, these have proven quite useful to make generally
available, and despite the `_`-naming we expose the objects outside
their modules. This change renames `_Prefix` to `Prefix` to reflect the
reality that these are used as public consts.

Exporting them is safe as both objects are frozen.

Test plan: Simple rename, `yarn test` suffices.
This commit is contained in:
Dandelion Mané 2018-09-12 17:18:47 -07:00 committed by GitHub
parent 70fe677990
commit 335441e671
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 132 additions and 137 deletions

View File

@ -14,7 +14,7 @@ import {
defaultWeightsForAdapterSet, defaultWeightsForAdapterSet,
} from "./weights/weights"; } from "./weights/weights";
import RepositorySelect from "./RepositorySelect"; import RepositorySelect from "./RepositorySelect";
import {_Prefix as GithubPrefix} from "../../plugins/github/nodes"; import {Prefix as GithubPrefix} from "../../plugins/github/nodes";
import { import {
createStateTransitionMachine, createStateTransitionMachine,
type AppState, type AppState,

View File

@ -15,7 +15,7 @@ import RepositorySelect from "./RepositorySelect";
import {PagerankTable} from "./pagerankTable/Table"; import {PagerankTable} from "./pagerankTable/Table";
import {createApp, LoadingIndicator} from "./App"; import {createApp, LoadingIndicator} from "./App";
import {uninitializedState} from "./state"; import {uninitializedState} from "./state";
import {_Prefix as GithubPrefix} from "../../plugins/github/nodes"; import {Prefix as GithubPrefix} from "../../plugins/github/nodes";
require("../testUtil").configureEnzyme(); require("../testUtil").configureEnzyme();

View File

@ -4,8 +4,8 @@ import cloneDeep from "lodash.clonedeep";
import {createMinimalGraph} from "./createMinimalGraph"; import {createMinimalGraph} from "./createMinimalGraph";
import {GraphView} from "./graphView"; import {GraphView} from "./graphView";
import {_Prefix as NodePrefix} from "./nodes"; import {Prefix as NodePrefix} from "./nodes";
import {_Prefix as EdgePrefix} from "./edges"; import {Prefix as EdgePrefix} from "./edges";
import {NodeAddress, EdgeAddress} from "../../core/graph"; import {NodeAddress, EdgeAddress} from "../../core/graph";
const makeData = () => cloneDeep(require("./example/example-git")); const makeData = () => cloneDeep(require("./example/example-git"));

View File

@ -21,7 +21,7 @@ function gitEdgeAddress(...parts: string[]): RawAddress {
return EdgeAddress.append(GIT_PREFIX, ...parts); return EdgeAddress.append(GIT_PREFIX, ...parts);
} }
export const _Prefix = Object.freeze({ export const Prefix = Object.freeze({
base: GIT_PREFIX, base: GIT_PREFIX,
hasTree: gitEdgeAddress(HAS_TREE_TYPE), hasTree: gitEdgeAddress(HAS_TREE_TYPE),
hasParent: gitEdgeAddress(HAS_PARENT_TYPE), hasParent: gitEdgeAddress(HAS_PARENT_TYPE),
@ -211,29 +211,29 @@ export function toRaw(x: StructuredAddress): RawAddress {
switch (x.type) { switch (x.type) {
case HAS_TREE_TYPE: case HAS_TREE_TYPE:
return EdgeAddress.append( return EdgeAddress.append(
_Prefix.hasTree, Prefix.hasTree,
...lengthEncode(GitNode.toRaw(x.commit)) ...lengthEncode(GitNode.toRaw(x.commit))
); );
case HAS_PARENT_TYPE: case HAS_PARENT_TYPE:
return EdgeAddress.append( return EdgeAddress.append(
_Prefix.hasParent, Prefix.hasParent,
...lengthEncode(GitNode.toRaw(x.child)), ...lengthEncode(GitNode.toRaw(x.child)),
...lengthEncode(GitNode.toRaw(x.parent)) ...lengthEncode(GitNode.toRaw(x.parent))
); );
case INCLUDES_TYPE: case INCLUDES_TYPE:
return EdgeAddress.append( return EdgeAddress.append(
_Prefix.includes, Prefix.includes,
...lengthEncode(GitNode.toRaw(x.treeEntry)) ...lengthEncode(GitNode.toRaw(x.treeEntry))
); );
case BECOMES_TYPE: case BECOMES_TYPE:
return EdgeAddress.append( return EdgeAddress.append(
_Prefix.becomes, Prefix.becomes,
...lengthEncode(GitNode.toRaw(x.was)), ...lengthEncode(GitNode.toRaw(x.was)),
...lengthEncode(GitNode.toRaw(x.becomes)) ...lengthEncode(GitNode.toRaw(x.becomes))
); );
case HAS_CONTENTS_TYPE: case HAS_CONTENTS_TYPE:
return EdgeAddress.append( return EdgeAddress.append(
_Prefix.hasContents, Prefix.hasContents,
...lengthEncode(GitNode.toRaw(x.treeEntry)) ...lengthEncode(GitNode.toRaw(x.treeEntry))
); );
default: default:

View File

@ -25,7 +25,7 @@ export class GraphView {
node: GN.StructuredAddress, node: GN.StructuredAddress,
options: NeighborsOptions options: NeighborsOptions
): Iterator<T> { ): Iterator<T> {
if (!NodeAddress.hasPrefix(options.nodePrefix, GN._Prefix.base)) { if (!NodeAddress.hasPrefix(options.nodePrefix, GN.Prefix.base)) {
throw new Error(`_neighbors must filter to Git nodes`); throw new Error(`_neighbors must filter to Git nodes`);
} }
const rawNode: GN.RawAddress = GN.toRaw(node); const rawNode: GN.RawAddress = GN.toRaw(node);
@ -51,7 +51,7 @@ export class GraphView {
} }
*_commits(): Iterator<GN.CommitAddress> { *_commits(): Iterator<GN.CommitAddress> {
for (const node of this._graph.nodes({prefix: GN._Prefix.commit})) { for (const node of this._graph.nodes({prefix: GN.Prefix.commit})) {
const rawAddress: GN.RawAddress = ((node: NodeAddressT): any); const rawAddress: GN.RawAddress = ((node: NodeAddressT): any);
const commit: GN.CommitAddress = (GN.fromRaw(rawAddress): any); const commit: GN.CommitAddress = (GN.fromRaw(rawAddress): any);
this._maybeCheckInvariants(); this._maybeCheckInvariants();
@ -64,8 +64,8 @@ export class GraphView {
const result: GN.TreeAddress = Array.from( const result: GN.TreeAddress = Array.from(
this._neighbors(commit, { this._neighbors(commit, {
direction: Direction.OUT, direction: Direction.OUT,
nodePrefix: GN._Prefix.tree, nodePrefix: GN.Prefix.tree,
edgePrefix: GE._Prefix.hasTree, edgePrefix: GE.Prefix.hasTree,
}) })
)[0]; )[0];
this._maybeCheckInvariants(); this._maybeCheckInvariants();
@ -75,8 +75,8 @@ export class GraphView {
parents(commit: GN.CommitAddress): Iterator<GN.CommitAddress> { parents(commit: GN.CommitAddress): Iterator<GN.CommitAddress> {
const result: Iterator<GN.CommitAddress> = this._neighbors(commit, { const result: Iterator<GN.CommitAddress> = this._neighbors(commit, {
direction: Direction.OUT, direction: Direction.OUT,
nodePrefix: GN._Prefix.commit, nodePrefix: GN.Prefix.commit,
edgePrefix: GE._Prefix.hasParent, edgePrefix: GE.Prefix.hasParent,
}); });
this._maybeCheckInvariants(); this._maybeCheckInvariants();
return result; return result;
@ -85,8 +85,8 @@ export class GraphView {
entries(tree: GN.TreeAddress): Iterator<GN.TreeEntryAddress> { entries(tree: GN.TreeAddress): Iterator<GN.TreeEntryAddress> {
const result: Iterator<GN.TreeEntryAddress> = this._neighbors(tree, { const result: Iterator<GN.TreeEntryAddress> = this._neighbors(tree, {
direction: Direction.OUT, direction: Direction.OUT,
nodePrefix: GN._Prefix.treeEntry, nodePrefix: GN.Prefix.treeEntry,
edgePrefix: GE._Prefix.includes, edgePrefix: GE.Prefix.includes,
}); });
this._maybeCheckInvariants(); this._maybeCheckInvariants();
return result; return result;
@ -97,8 +97,8 @@ export class GraphView {
entry, entry,
{ {
direction: Direction.OUT, direction: Direction.OUT,
nodePrefix: GN._Prefix.base, // multiple kinds nodePrefix: GN.Prefix.base, // multiple kinds
edgePrefix: GE._Prefix.hasContents, edgePrefix: GE.Prefix.hasContents,
} }
); );
this._maybeCheckInvariants(); this._maybeCheckInvariants();
@ -108,8 +108,8 @@ export class GraphView {
evolvesTo(entry: GN.TreeEntryAddress): Iterator<GN.TreeEntryAddress> { evolvesTo(entry: GN.TreeEntryAddress): Iterator<GN.TreeEntryAddress> {
const result: Iterator<GN.TreeEntryAddress> = this._neighbors(entry, { const result: Iterator<GN.TreeEntryAddress> = this._neighbors(entry, {
direction: Direction.OUT, direction: Direction.OUT,
nodePrefix: GN._Prefix.treeEntry, nodePrefix: GN.Prefix.treeEntry,
edgePrefix: GE._Prefix.becomes, edgePrefix: GE.Prefix.becomes,
}); });
this._maybeCheckInvariants(); this._maybeCheckInvariants();
return result; return result;
@ -118,8 +118,8 @@ export class GraphView {
evolvesFrom(entry: GN.TreeEntryAddress): Iterator<GN.TreeEntryAddress> { evolvesFrom(entry: GN.TreeEntryAddress): Iterator<GN.TreeEntryAddress> {
const result: Iterator<GN.TreeEntryAddress> = this._neighbors(entry, { const result: Iterator<GN.TreeEntryAddress> = this._neighbors(entry, {
direction: Direction.IN, direction: Direction.IN,
nodePrefix: GN._Prefix.treeEntry, nodePrefix: GN.Prefix.treeEntry,
edgePrefix: GE._Prefix.becomes, edgePrefix: GE.Prefix.becomes,
}); });
this._maybeCheckInvariants(); this._maybeCheckInvariants();
return result; return result;
@ -135,7 +135,7 @@ export class GraphView {
checkInvariants() { checkInvariants() {
// All Git nodes and edges must have valid Git addresses. // All Git nodes and edges must have valid Git addresses.
for (const node of this._graph.nodes({prefix: GN._Prefix.base})) { for (const node of this._graph.nodes({prefix: GN.Prefix.base})) {
GN.fromRaw((((node: NodeAddressT): any): GN.RawAddress)); GN.fromRaw((((node: NodeAddressT): any): GN.RawAddress));
} }
// (Edges are checked down below.) // (Edges are checked down below.)
@ -150,35 +150,35 @@ export class GraphView {
|}; |};
const edgeInvariants = { const edgeInvariants = {
[GE.HAS_TREE_TYPE]: { [GE.HAS_TREE_TYPE]: {
prefix: GE._Prefix.hasTree, prefix: GE.Prefix.hasTree,
homs: [{srcPrefix: GN._Prefix.commit, dstPrefix: GN._Prefix.tree}], homs: [{srcPrefix: GN.Prefix.commit, dstPrefix: GN.Prefix.tree}],
}, },
[GE.HAS_PARENT_TYPE]: { [GE.HAS_PARENT_TYPE]: {
prefix: GE._Prefix.hasParent, prefix: GE.Prefix.hasParent,
homs: [{srcPrefix: GN._Prefix.commit, dstPrefix: GN._Prefix.commit}], homs: [{srcPrefix: GN.Prefix.commit, dstPrefix: GN.Prefix.commit}],
}, },
[GE.INCLUDES_TYPE]: { [GE.INCLUDES_TYPE]: {
prefix: GE._Prefix.includes, prefix: GE.Prefix.includes,
homs: [{srcPrefix: GN._Prefix.tree, dstPrefix: GN._Prefix.treeEntry}], homs: [{srcPrefix: GN.Prefix.tree, dstPrefix: GN.Prefix.treeEntry}],
}, },
[GE.BECOMES_TYPE]: { [GE.BECOMES_TYPE]: {
prefix: GE._Prefix.becomes, prefix: GE.Prefix.becomes,
homs: [ homs: [
{srcPrefix: GN._Prefix.treeEntry, dstPrefix: GN._Prefix.treeEntry}, {srcPrefix: GN.Prefix.treeEntry, dstPrefix: GN.Prefix.treeEntry},
], ],
}, },
[GE.HAS_CONTENTS_TYPE]: { [GE.HAS_CONTENTS_TYPE]: {
prefix: GE._Prefix.hasContents, prefix: GE.Prefix.hasContents,
homs: [ homs: [
{srcPrefix: GN._Prefix.treeEntry, dstPrefix: GN._Prefix.blob}, {srcPrefix: GN.Prefix.treeEntry, dstPrefix: GN.Prefix.blob},
{srcPrefix: GN._Prefix.treeEntry, dstPrefix: GN._Prefix.tree}, {srcPrefix: GN.Prefix.treeEntry, dstPrefix: GN.Prefix.tree},
{srcPrefix: GN._Prefix.treeEntry, dstPrefix: GN._Prefix.commit}, {srcPrefix: GN.Prefix.treeEntry, dstPrefix: GN.Prefix.commit},
], ],
}, },
}; };
for (const edge of this._graph.edges({ for (const edge of this._graph.edges({
addressPrefix: GE._Prefix.base, addressPrefix: GE.Prefix.base,
srcPrefix: NodeAddress.empty, srcPrefix: NodeAddress.empty,
dstPrefix: NodeAddress.empty, dstPrefix: NodeAddress.empty,
})) { })) {
@ -205,11 +205,11 @@ export class GraphView {
// Any HAS_TREE edge to a commit must be properly named. This // Any HAS_TREE edge to a commit must be properly named. This
// implies that a commit has at most one such edge. (Normal commits // implies that a commit has at most one such edge. (Normal commits
// should have trees, but submodule commits might not.) // should have trees, but submodule commits might not.)
for (const rawNode of this._graph.nodes({prefix: GN._Prefix.commit})) { for (const rawNode of this._graph.nodes({prefix: GN.Prefix.commit})) {
for (const neighbor of this._graph.neighbors(rawNode, { for (const neighbor of this._graph.neighbors(rawNode, {
direction: Direction.OUT, direction: Direction.OUT,
nodePrefix: NodeAddress.empty, nodePrefix: NodeAddress.empty,
edgePrefix: GE._Prefix.hasTree, edgePrefix: GE.Prefix.hasTree,
})) { })) {
const rawEdge = neighbor.edge; const rawEdge = neighbor.edge;
const edge: GE.HasTreeAddress = (GE.fromRaw( const edge: GE.HasTreeAddress = (GE.fromRaw(
@ -228,7 +228,7 @@ export class GraphView {
// All HAS_PARENT edges must map between between the correct commits. // All HAS_PARENT edges must map between between the correct commits.
for (const edge of this._graph.edges({ for (const edge of this._graph.edges({
addressPrefix: GE._Prefix.hasParent, addressPrefix: GE.Prefix.hasParent,
srcPrefix: NodeAddress.empty, srcPrefix: NodeAddress.empty,
dstPrefix: NodeAddress.empty, dstPrefix: NodeAddress.empty,
})) { })) {
@ -247,12 +247,12 @@ export class GraphView {
} }
// Each tree entry must have a unique and properly named INCLUDES edge. // Each tree entry must have a unique and properly named INCLUDES edge.
for (const rawNode of this._graph.nodes({prefix: GN._Prefix.treeEntry})) { for (const rawNode of this._graph.nodes({prefix: GN.Prefix.treeEntry})) {
const treeNeighbors = Array.from( const treeNeighbors = Array.from(
this._graph.neighbors(rawNode, { this._graph.neighbors(rawNode, {
direction: Direction.IN, direction: Direction.IN,
nodePrefix: NodeAddress.empty, nodePrefix: NodeAddress.empty,
edgePrefix: GE._Prefix.includes, edgePrefix: GE.Prefix.includes,
}) })
); );
if (treeNeighbors.length !== 1) { if (treeNeighbors.length !== 1) {
@ -278,7 +278,7 @@ export class GraphView {
// All BECOMES edges must map between between the correct tree entries. // All BECOMES edges must map between between the correct tree entries.
for (const edge of this._graph.edges({ for (const edge of this._graph.edges({
addressPrefix: GE._Prefix.becomes, addressPrefix: GE.Prefix.becomes,
srcPrefix: NodeAddress.empty, srcPrefix: NodeAddress.empty,
dstPrefix: NodeAddress.empty, dstPrefix: NodeAddress.empty,
})) { })) {
@ -298,7 +298,7 @@ export class GraphView {
// All HAS_CONTENTS edges must be properly named. // All HAS_CONTENTS edges must be properly named.
for (const edge of this._graph.edges({ for (const edge of this._graph.edges({
addressPrefix: GE._Prefix.hasContents, addressPrefix: GE.Prefix.hasContents,
srcPrefix: NodeAddress.empty, srcPrefix: NodeAddress.empty,
dstPrefix: NodeAddress.empty, dstPrefix: NodeAddress.empty,
})) { })) {

View File

@ -160,7 +160,7 @@ describe("plugins/git/graphView", () => {
const c1: GN.CommitAddress = {type: GN.COMMIT_TYPE, hash: "c1"}; const c1: GN.CommitAddress = {type: GN.COMMIT_TYPE, hash: "c1"};
const c2: GN.CommitAddress = {type: GN.COMMIT_TYPE, hash: "c2"}; const c2: GN.CommitAddress = {type: GN.COMMIT_TYPE, hash: "c2"};
const edge = { const edge = {
address: EdgeAddress.append(GE._Prefix.base, "wat"), address: EdgeAddress.append(GE.Prefix.base, "wat"),
src: GN.toRaw(c1), src: GN.toRaw(c1),
dst: GN.toRaw(c2), dst: GN.toRaw(c2),
}; };

View File

@ -15,17 +15,17 @@ export class StaticPluginAdapter implements IStaticPluginAdapter {
return "Git"; return "Git";
} }
nodePrefix() { nodePrefix() {
return N._Prefix.base; return N.Prefix.base;
} }
edgePrefix() { edgePrefix() {
return E._Prefix.base; return E.Prefix.base;
} }
nodeTypes() { nodeTypes() {
return [ return [
{ {
name: "Commit", name: "Commit",
pluralName: "Commits", pluralName: "Commits",
prefix: N._Prefix.commit, prefix: N.Prefix.commit,
defaultWeight: 2, defaultWeight: 2,
}, },
]; ];
@ -35,7 +35,7 @@ export class StaticPluginAdapter implements IStaticPluginAdapter {
{ {
forwardName: "has parent", forwardName: "has parent",
backwardName: "is parent of", backwardName: "is parent of",
prefix: E._Prefix.hasParent, prefix: E.Prefix.hasParent,
defaultForwardWeight: 1, defaultForwardWeight: 1,
defaultBackwardWeight: 1, defaultBackwardWeight: 1,
}, },

View File

@ -15,7 +15,7 @@ export const COMMIT_TYPE: "COMMIT" = "COMMIT";
export const TREE_TYPE: "TREE" = "TREE"; export const TREE_TYPE: "TREE" = "TREE";
export const TREE_ENTRY_TYPE: "TREE_ENTRY" = "TREE_ENTRY"; export const TREE_ENTRY_TYPE: "TREE_ENTRY" = "TREE_ENTRY";
export const _Prefix = Object.freeze({ export const Prefix = Object.freeze({
base: GIT_PREFIX, base: GIT_PREFIX,
blob: _gitAddress(BLOB_TYPE), blob: _gitAddress(BLOB_TYPE),
commit: _gitAddress(COMMIT_TYPE), commit: _gitAddress(COMMIT_TYPE),
@ -94,13 +94,13 @@ export function fromRaw(x: RawAddress): StructuredAddress {
export function toRaw(x: StructuredAddress): RawAddress { export function toRaw(x: StructuredAddress): RawAddress {
switch (x.type) { switch (x.type) {
case BLOB_TYPE: case BLOB_TYPE:
return NodeAddress.append(_Prefix.blob, x.hash); return NodeAddress.append(Prefix.blob, x.hash);
case COMMIT_TYPE: case COMMIT_TYPE:
return NodeAddress.append(_Prefix.commit, x.hash); return NodeAddress.append(Prefix.commit, x.hash);
case TREE_TYPE: case TREE_TYPE:
return NodeAddress.append(_Prefix.tree, x.hash); return NodeAddress.append(Prefix.tree, x.hash);
case TREE_ENTRY_TYPE: case TREE_ENTRY_TYPE:
return NodeAddress.append(_Prefix.treeEntry, x.treeHash, x.name); return NodeAddress.append(Prefix.treeEntry, x.treeHash, x.name);
default: default:
throw new Error(`Unexpected type ${(x.type: empty)}`); throw new Error(`Unexpected type ${(x.type: empty)}`);
} }

View File

@ -15,35 +15,35 @@ export class StaticPluginAdapter implements IStaticPluginAdapter {
return "Git"; return "Git";
} }
nodePrefix() { nodePrefix() {
return N._Prefix.base; return N.Prefix.base;
} }
edgePrefix() { edgePrefix() {
return E._Prefix.base; return E.Prefix.base;
} }
nodeTypes() { nodeTypes() {
return [ return [
{ {
name: "Blob", name: "Blob",
pluralName: "Blobs", pluralName: "Blobs",
prefix: N._Prefix.blob, prefix: N.Prefix.blob,
defaultWeight: 0.125, defaultWeight: 0.125,
}, },
{ {
name: "Commit", name: "Commit",
pluralName: "Commits", pluralName: "Commits",
prefix: N._Prefix.commit, prefix: N.Prefix.commit,
defaultWeight: 2, defaultWeight: 2,
}, },
{ {
name: "Tree", name: "Tree",
pluralName: "Trees", pluralName: "Trees",
prefix: N._Prefix.tree, prefix: N.Prefix.tree,
defaultWeight: 0.125, defaultWeight: 0.125,
}, },
{ {
name: "Tree entry", name: "Tree entry",
pluralName: "Tree entries", pluralName: "Tree entries",
prefix: N._Prefix.treeEntry, prefix: N.Prefix.treeEntry,
defaultWeight: 0.125, defaultWeight: 0.125,
}, },
]; ];
@ -55,35 +55,35 @@ export class StaticPluginAdapter implements IStaticPluginAdapter {
backwardName: "owned by", backwardName: "owned by",
defaultForwardWeight: 1, defaultForwardWeight: 1,
defaultBackwardWeight: 1, defaultBackwardWeight: 1,
prefix: E._Prefix.hasTree, prefix: E.Prefix.hasTree,
}, },
{ {
forwardName: "has parent", forwardName: "has parent",
backwardName: "is parent of", backwardName: "is parent of",
defaultForwardWeight: 1, defaultForwardWeight: 1,
defaultBackwardWeight: 1, defaultBackwardWeight: 1,
prefix: E._Prefix.hasParent, prefix: E.Prefix.hasParent,
}, },
{ {
forwardName: "includes", forwardName: "includes",
backwardName: "is included by", backwardName: "is included by",
defaultForwardWeight: 1, defaultForwardWeight: 1,
defaultBackwardWeight: 1, defaultBackwardWeight: 1,
prefix: E._Prefix.includes, prefix: E.Prefix.includes,
}, },
{ {
forwardName: "evolves to", forwardName: "evolves to",
backwardName: "evolves from", backwardName: "evolves from",
defaultForwardWeight: 1, defaultForwardWeight: 1,
defaultBackwardWeight: 1, defaultBackwardWeight: 1,
prefix: E._Prefix.becomes, prefix: E.Prefix.becomes,
}, },
{ {
forwardName: "has contents", forwardName: "has contents",
backwardName: "is contents of", backwardName: "is contents of",
defaultForwardWeight: 1, defaultForwardWeight: 1,
defaultBackwardWeight: 1, defaultBackwardWeight: 1,
prefix: E._Prefix.hasContents, prefix: E.Prefix.hasContents,
}, },
]; ];
} }

View File

@ -23,7 +23,7 @@ function githubEdgeAddress(...parts: string[]): RawAddress {
return EdgeAddress.append(GITHUB_PREFIX, ...parts); return EdgeAddress.append(GITHUB_PREFIX, ...parts);
} }
export const _Prefix = Object.freeze({ export const Prefix = Object.freeze({
base: GITHUB_PREFIX, base: GITHUB_PREFIX,
authors: githubEdgeAddress(AUTHORS_TYPE), authors: githubEdgeAddress(AUTHORS_TYPE),
mergedAs: githubEdgeAddress(MERGED_AS_TYPE), mergedAs: githubEdgeAddress(MERGED_AS_TYPE),
@ -225,29 +225,29 @@ export function toRaw(x: StructuredAddress): RawAddress {
switch (x.type) { switch (x.type) {
case AUTHORS_TYPE: case AUTHORS_TYPE:
return EdgeAddress.append( return EdgeAddress.append(
_Prefix.authors, Prefix.authors,
...lengthEncode(GithubNode.toRaw(x.author)), ...lengthEncode(GithubNode.toRaw(x.author)),
...lengthEncode(GithubNode.toRaw(x.content)) ...lengthEncode(GithubNode.toRaw(x.content))
); );
case MERGED_AS_TYPE: case MERGED_AS_TYPE:
return EdgeAddress.append( return EdgeAddress.append(
_Prefix.mergedAs, Prefix.mergedAs,
...lengthEncode(GithubNode.toRaw(x.pull)) ...lengthEncode(GithubNode.toRaw(x.pull))
); );
case HAS_PARENT_TYPE: case HAS_PARENT_TYPE:
return EdgeAddress.append( return EdgeAddress.append(
_Prefix.hasParent, Prefix.hasParent,
...lengthEncode(GithubNode.toRaw(x.child)) ...lengthEncode(GithubNode.toRaw(x.child))
); );
case REFERENCES_TYPE: case REFERENCES_TYPE:
return EdgeAddress.append( return EdgeAddress.append(
_Prefix.references, Prefix.references,
...lengthEncode(GithubNode.toRaw(x.referrer)), ...lengthEncode(GithubNode.toRaw(x.referrer)),
...lengthEncode(GithubNode.toRaw(x.referent)) ...lengthEncode(GithubNode.toRaw(x.referent))
); );
case MENTIONS_AUTHOR_TYPE: case MENTIONS_AUTHOR_TYPE:
return EdgeAddress.append( return EdgeAddress.append(
_Prefix.mentionsAuthor, Prefix.mentionsAuthor,
...lengthEncode(GithubNode.toRaw(x.reference.src)), ...lengthEncode(GithubNode.toRaw(x.reference.src)),
...lengthEncode(GithubNode.toRaw(x.reference.dst)), ...lengthEncode(GithubNode.toRaw(x.reference.dst)),
...lengthEncode(GithubNode.toRaw(x.reference.who)) ...lengthEncode(GithubNode.toRaw(x.reference.who))

View File

@ -6,7 +6,7 @@ import deepEqual from "lodash.isequal";
import * as GN from "./nodes"; import * as GN from "./nodes";
import * as GE from "./edges"; import * as GE from "./edges";
import {_Prefix as _GitPrefix} from "../git/nodes"; import {Prefix as _GitPrefix} from "../git/nodes";
import { import {
Graph, Graph,
@ -45,7 +45,7 @@ export class GraphView {
node: GN.StructuredAddress, node: GN.StructuredAddress,
options: NeighborsOptions options: NeighborsOptions
): Iterator<T> { ): Iterator<T> {
if (!NodeAddress.hasPrefix(options.nodePrefix, GN._Prefix.base)) { if (!NodeAddress.hasPrefix(options.nodePrefix, GN.Prefix.base)) {
throw new Error(`_neighbors must filter to GitHub nodes`); throw new Error(`_neighbors must filter to GitHub nodes`);
} }
const rawNode = GN.toRaw(node); const rawNode = GN.toRaw(node);
@ -62,38 +62,38 @@ export class GraphView {
): Iterator<T> { ): Iterator<T> {
const options = { const options = {
nodePrefix, nodePrefix,
edgePrefix: GE._Prefix.hasParent, edgePrefix: GE.Prefix.hasParent,
direction: Direction.IN, direction: Direction.IN,
}; };
return this._neighbors(node, options); return this._neighbors(node, options);
} }
repos(): Iterator<GN.RepoAddress> { repos(): Iterator<GN.RepoAddress> {
return this._nodes(GN._Prefix.repo); return this._nodes(GN.Prefix.repo);
} }
issues(repo: GN.RepoAddress): Iterator<GN.IssueAddress> { issues(repo: GN.RepoAddress): Iterator<GN.IssueAddress> {
return this._children(repo, GN._Prefix.issue); return this._children(repo, GN.Prefix.issue);
} }
pulls(repo: GN.RepoAddress): Iterator<GN.PullAddress> { pulls(repo: GN.RepoAddress): Iterator<GN.PullAddress> {
return this._children(repo, GN._Prefix.pull); return this._children(repo, GN.Prefix.pull);
} }
comments(commentable: GN.CommentableAddress): Iterator<GN.CommentAddress> { comments(commentable: GN.CommentableAddress): Iterator<GN.CommentAddress> {
return this._children(commentable, GN._Prefix.comment); return this._children(commentable, GN.Prefix.comment);
} }
reviews(pull: GN.PullAddress): Iterator<GN.ReviewAddress> { reviews(pull: GN.PullAddress): Iterator<GN.ReviewAddress> {
return this._children(pull, GN._Prefix.review); return this._children(pull, GN.Prefix.review);
} }
// TODO(@wchrgin) figure out how to overload this fn signature // TODO(@wchrgin) figure out how to overload this fn signature
parent(child: GN.ChildAddress): GN.ParentAddress { parent(child: GN.ChildAddress): GN.ParentAddress {
const options = { const options = {
direction: Direction.OUT, direction: Direction.OUT,
edgePrefix: GE._Prefix.hasParent, edgePrefix: GE.Prefix.hasParent,
nodePrefix: GN._Prefix.base, nodePrefix: GN.Prefix.base,
}; };
const parents: GN.ParentAddress[] = Array.from( const parents: GN.ParentAddress[] = Array.from(
this._neighbors(child, options) this._neighbors(child, options)
@ -109,8 +109,8 @@ export class GraphView {
authors(content: GN.AuthorableAddress): Iterator<GN.UserlikeAddress> { authors(content: GN.AuthorableAddress): Iterator<GN.UserlikeAddress> {
const options = { const options = {
direction: Direction.IN, direction: Direction.IN,
edgePrefix: GE._Prefix.authors, edgePrefix: GE.Prefix.authors,
nodePrefix: GN._Prefix.userlike, nodePrefix: GN.Prefix.userlike,
}; };
return this._neighbors(content, options); return this._neighbors(content, options);
} }
@ -144,7 +144,7 @@ export class GraphView {
[GN.REVIEW_TYPE]: (x) => x.pull, [GN.REVIEW_TYPE]: (x) => x.pull,
[GN.USERLIKE_TYPE]: null, [GN.USERLIKE_TYPE]: null,
}; };
for (const node of this._graph.nodes({prefix: GN._Prefix.base})) { for (const node of this._graph.nodes({prefix: GN.Prefix.base})) {
const structuredNode = GN.fromRaw((node: any)); const structuredNode = GN.fromRaw((node: any));
const type = structuredNode.type; const type = structuredNode.type;
const parentAccessor = nodeTypeToParentAccessor[type]; const parentAccessor = nodeTypeToParentAccessor[type];
@ -182,19 +182,19 @@ export class GraphView {
const edgeTypeToInvariants: {[type: string]: EdgeInvariant} = { const edgeTypeToInvariants: {[type: string]: EdgeInvariant} = {
[GE.HAS_PARENT_TYPE]: { [GE.HAS_PARENT_TYPE]: {
homs: [ homs: [
{srcPrefix: GN._Prefix.issue, dstPrefix: GN._Prefix.repo}, {srcPrefix: GN.Prefix.issue, dstPrefix: GN.Prefix.repo},
{srcPrefix: GN._Prefix.pull, dstPrefix: GN._Prefix.repo}, {srcPrefix: GN.Prefix.pull, dstPrefix: GN.Prefix.repo},
{srcPrefix: GN._Prefix.review, dstPrefix: GN._Prefix.pull}, {srcPrefix: GN.Prefix.review, dstPrefix: GN.Prefix.pull},
{srcPrefix: GN._Prefix.reviewComment, dstPrefix: GN._Prefix.review}, {srcPrefix: GN.Prefix.reviewComment, dstPrefix: GN.Prefix.review},
{srcPrefix: GN._Prefix.issueComment, dstPrefix: GN._Prefix.issue}, {srcPrefix: GN.Prefix.issueComment, dstPrefix: GN.Prefix.issue},
{srcPrefix: GN._Prefix.pullComment, dstPrefix: GN._Prefix.pull}, {srcPrefix: GN.Prefix.pullComment, dstPrefix: GN.Prefix.pull},
], ],
srcAccessor: (x) => GN.toRaw((x: any).child), srcAccessor: (x) => GN.toRaw((x: any).child),
}, },
[GE.MERGED_AS_TYPE]: { [GE.MERGED_AS_TYPE]: {
homs: [ homs: [
{ {
srcPrefix: GN._Prefix.pull, srcPrefix: GN.Prefix.pull,
dstPrefix: _GitPrefix.commit, dstPrefix: _GitPrefix.commit,
}, },
], ],
@ -203,18 +203,18 @@ export class GraphView {
[GE.REFERENCES_TYPE]: { [GE.REFERENCES_TYPE]: {
homs: homProduct( homs: homProduct(
[ [
GN._Prefix.issue, GN.Prefix.issue,
GN._Prefix.pull, GN.Prefix.pull,
GN._Prefix.review, GN.Prefix.review,
GN._Prefix.comment, GN.Prefix.comment,
], ],
[ [
GN._Prefix.repo, GN.Prefix.repo,
GN._Prefix.issue, GN.Prefix.issue,
GN._Prefix.pull, GN.Prefix.pull,
GN._Prefix.review, GN.Prefix.review,
GN._Prefix.comment, GN.Prefix.comment,
GN._Prefix.userlike, GN.Prefix.userlike,
] ]
), ),
srcAccessor: (x) => GN.toRaw((x: any).referrer), srcAccessor: (x) => GN.toRaw((x: any).referrer),
@ -222,21 +222,16 @@ export class GraphView {
}, },
[GE.AUTHORS_TYPE]: { [GE.AUTHORS_TYPE]: {
homs: homProduct( homs: homProduct(
[GN._Prefix.userlike], [GN.Prefix.userlike],
[ [GN.Prefix.issue, GN.Prefix.review, GN.Prefix.pull, GN.Prefix.comment]
GN._Prefix.issue,
GN._Prefix.review,
GN._Prefix.pull,
GN._Prefix.comment,
]
), ),
srcAccessor: (x) => GN.toRaw((x: any).author), srcAccessor: (x) => GN.toRaw((x: any).author),
dstAccessor: (x) => GN.toRaw((x: any).content), dstAccessor: (x) => GN.toRaw((x: any).content),
}, },
[GE.MENTIONS_AUTHOR_TYPE]: { [GE.MENTIONS_AUTHOR_TYPE]: {
homs: homProduct( homs: homProduct(
[GN._Prefix.issue, GN._Prefix.pull, GN._Prefix.comment], [GN.Prefix.issue, GN.Prefix.pull, GN.Prefix.comment],
[GN._Prefix.issue, GN._Prefix.pull, GN._Prefix.comment] [GN.Prefix.issue, GN.Prefix.pull, GN.Prefix.comment]
), ),
srcAccessor: (x) => GN.toRaw((x: any).reference.src), srcAccessor: (x) => GN.toRaw((x: any).reference.src),
dstAccessor: (x) => GN.toRaw((x: any).reference.dst), dstAccessor: (x) => GN.toRaw((x: any).reference.dst),
@ -244,7 +239,7 @@ export class GraphView {
}; };
for (const edge of this._graph.edges({ for (const edge of this._graph.edges({
addressPrefix: GE._Prefix.base, addressPrefix: GE.Prefix.base,
srcPrefix: NodeAddress.empty, srcPrefix: NodeAddress.empty,
dstPrefix: NodeAddress.empty, dstPrefix: NodeAddress.empty,
})) { })) {

View File

@ -315,7 +315,7 @@ describe("plugins/github/graphView", () => {
const otherParent = { const otherParent = {
src: GN.toRaw(issue), src: GN.toRaw(issue),
dst: GN.toRaw(otherRepo), dst: GN.toRaw(otherRepo),
address: EdgeAddress.append(GE._Prefix.hasParent, "foobar"), address: EdgeAddress.append(GE.Prefix.hasParent, "foobar"),
}; };
g.addEdge(otherParent); g.addEdge(otherParent);
expect(() => new GraphView(g)).toThrow("Parent invariant"); expect(() => new GraphView(g)).toThrow("Parent invariant");

View File

@ -18,7 +18,7 @@ export const USERLIKE_TYPE: "USERLIKE" = "USERLIKE";
export const USER_SUBTYPE: "USER" = "USER"; export const USER_SUBTYPE: "USER" = "USER";
export const BOT_SUBTYPE: "BOT" = "BOT"; export const BOT_SUBTYPE: "BOT" = "BOT";
export const _Prefix = Object.freeze({ export const Prefix = Object.freeze({
base: GITHUB_PREFIX, base: GITHUB_PREFIX,
repo: _githubAddress(REPO_TYPE), repo: _githubAddress(REPO_TYPE),
issue: _githubAddress(ISSUE_TYPE), issue: _githubAddress(ISSUE_TYPE),
@ -218,24 +218,24 @@ export function fromRaw(x: RawAddress): StructuredAddress {
export function toRaw(x: StructuredAddress): RawAddress { export function toRaw(x: StructuredAddress): RawAddress {
switch (x.type) { switch (x.type) {
case REPO_TYPE: case REPO_TYPE:
return NodeAddress.append(_Prefix.repo, x.owner, x.name); return NodeAddress.append(Prefix.repo, x.owner, x.name);
case ISSUE_TYPE: case ISSUE_TYPE:
return NodeAddress.append( return NodeAddress.append(
_Prefix.issue, Prefix.issue,
x.repo.owner, x.repo.owner,
x.repo.name, x.repo.name,
x.number x.number
); );
case PULL_TYPE: case PULL_TYPE:
return NodeAddress.append( return NodeAddress.append(
_Prefix.pull, Prefix.pull,
x.repo.owner, x.repo.owner,
x.repo.name, x.repo.name,
x.number x.number
); );
case REVIEW_TYPE: case REVIEW_TYPE:
return NodeAddress.append( return NodeAddress.append(
_Prefix.review, Prefix.review,
x.pull.repo.owner, x.pull.repo.owner,
x.pull.repo.name, x.pull.repo.name,
x.pull.number, x.pull.number,
@ -245,7 +245,7 @@ export function toRaw(x: StructuredAddress): RawAddress {
switch (x.parent.type) { switch (x.parent.type) {
case ISSUE_TYPE: case ISSUE_TYPE:
return NodeAddress.append( return NodeAddress.append(
_Prefix.issueComment, Prefix.issueComment,
x.parent.repo.owner, x.parent.repo.owner,
x.parent.repo.name, x.parent.repo.name,
x.parent.number, x.parent.number,
@ -253,7 +253,7 @@ export function toRaw(x: StructuredAddress): RawAddress {
); );
case PULL_TYPE: case PULL_TYPE:
return NodeAddress.append( return NodeAddress.append(
_Prefix.pullComment, Prefix.pullComment,
x.parent.repo.owner, x.parent.repo.owner,
x.parent.repo.name, x.parent.repo.name,
x.parent.number, x.parent.number,
@ -261,7 +261,7 @@ export function toRaw(x: StructuredAddress): RawAddress {
); );
case REVIEW_TYPE: case REVIEW_TYPE:
return NodeAddress.append( return NodeAddress.append(
_Prefix.reviewComment, Prefix.reviewComment,
x.parent.pull.repo.owner, x.parent.pull.repo.owner,
x.parent.pull.repo.name, x.parent.pull.repo.name,
x.parent.pull.number, x.parent.pull.number,
@ -274,9 +274,9 @@ export function toRaw(x: StructuredAddress): RawAddress {
case USERLIKE_TYPE: case USERLIKE_TYPE:
switch (x.subtype) { switch (x.subtype) {
case "BOT": case "BOT":
return NodeAddress.append(_Prefix.bot, x.login); return NodeAddress.append(Prefix.bot, x.login);
case "USER": case "USER":
return NodeAddress.append(_Prefix.user, x.login); return NodeAddress.append(Prefix.user, x.login);
default: default:
throw new Error((x.subtype: empty)); throw new Error((x.subtype: empty));
} }

View File

@ -19,53 +19,53 @@ export class StaticPluginAdapter implements IStaticPluginAdapter {
return "GitHub"; return "GitHub";
} }
nodePrefix() { nodePrefix() {
return N._Prefix.base; return N.Prefix.base;
} }
edgePrefix() { edgePrefix() {
return E._Prefix.base; return E.Prefix.base;
} }
nodeTypes() { nodeTypes() {
return [ return [
{ {
name: "Repository", name: "Repository",
pluralName: "Repositories", pluralName: "Repositories",
prefix: N._Prefix.repo, prefix: N.Prefix.repo,
defaultWeight: 4, defaultWeight: 4,
}, },
{ {
name: "Issue", name: "Issue",
pluralName: "Issues", pluralName: "Issues",
prefix: N._Prefix.issue, prefix: N.Prefix.issue,
defaultWeight: 2, defaultWeight: 2,
}, },
{ {
name: "Pull request", name: "Pull request",
pluralName: "Pull requests", pluralName: "Pull requests",
prefix: N._Prefix.pull, prefix: N.Prefix.pull,
defaultWeight: 4, defaultWeight: 4,
}, },
{ {
name: "Pull request review", name: "Pull request review",
pluralName: "Pull request reviews", pluralName: "Pull request reviews",
prefix: N._Prefix.review, prefix: N.Prefix.review,
defaultWeight: 1, defaultWeight: 1,
}, },
{ {
name: "Comment", name: "Comment",
pluralName: "Comments", pluralName: "Comments",
prefix: N._Prefix.comment, prefix: N.Prefix.comment,
defaultWeight: 1, defaultWeight: 1,
}, },
{ {
name: "User", name: "User",
pluralName: "Users", pluralName: "Users",
prefix: N._Prefix.user, prefix: N.Prefix.user,
defaultWeight: 1, defaultWeight: 1,
}, },
{ {
name: "Bot", name: "Bot",
pluralName: "Bots", pluralName: "Bots",
prefix: N._Prefix.bot, prefix: N.Prefix.bot,
defaultWeight: 0.25, defaultWeight: 0.25,
}, },
]; ];
@ -77,28 +77,28 @@ export class StaticPluginAdapter implements IStaticPluginAdapter {
backwardName: "is authored by", backwardName: "is authored by",
defaultForwardWeight: 1 / 2, defaultForwardWeight: 1 / 2,
defaultBackwardWeight: 1, defaultBackwardWeight: 1,
prefix: E._Prefix.authors, prefix: E.Prefix.authors,
}, },
{ {
forwardName: "has parent", forwardName: "has parent",
backwardName: "has child", backwardName: "has child",
defaultForwardWeight: 1, defaultForwardWeight: 1,
defaultBackwardWeight: 1 / 4, defaultBackwardWeight: 1 / 4,
prefix: E._Prefix.hasParent, prefix: E.Prefix.hasParent,
}, },
{ {
forwardName: "merges", forwardName: "merges",
backwardName: "is merged by", backwardName: "is merged by",
defaultForwardWeight: 1 / 2, defaultForwardWeight: 1 / 2,
defaultBackwardWeight: 1, defaultBackwardWeight: 1,
prefix: E._Prefix.mergedAs, prefix: E.Prefix.mergedAs,
}, },
{ {
forwardName: "references", forwardName: "references",
backwardName: "is referenced by", backwardName: "is referenced by",
defaultForwardWeight: 1, defaultForwardWeight: 1,
defaultBackwardWeight: 1 / 16, defaultBackwardWeight: 1 / 16,
prefix: E._Prefix.references, prefix: E.Prefix.references,
}, },
{ {
forwardName: "mentions author of", forwardName: "mentions author of",
@ -106,7 +106,7 @@ export class StaticPluginAdapter implements IStaticPluginAdapter {
defaultForwardWeight: 1, defaultForwardWeight: 1,
// TODO(#811): Probably change this to 0 // TODO(#811): Probably change this to 0
defaultBackwardWeight: 1 / 32, defaultBackwardWeight: 1 / 32,
prefix: E._Prefix.mentionsAuthor, prefix: E.Prefix.mentionsAuthor,
}, },
]; ];
} }