Implement the GitHub plugin adapter (#461)
Summary: This enables grabbing the GitHub relational view from disk and converting it to a graph on the client. Paired with @decentralion. Test Plan: For testing, information about the GitHub graph is printed when you click the “Load data” button in the UI. Do so. wchargin-branch: github-plugin-adapter
This commit is contained in:
parent
95c206b346
commit
4767dce749
|
@ -4,6 +4,7 @@ import React from "react";
|
|||
import {StyleSheet, css} from "aphrodite/no-important";
|
||||
|
||||
import LocalStore from "./LocalStore";
|
||||
import {createPluginAdapter as createGithubAdapter} from "../../plugins/github/pluginAdapter";
|
||||
|
||||
type Props = {};
|
||||
type State = {
|
||||
|
@ -81,7 +82,12 @@ export default class App extends React.Component<Props, State> {
|
|||
console.error(`Invalid repository name: ${JSON.stringify(repoName)}`);
|
||||
return;
|
||||
}
|
||||
console.log(`Would load data for: ${repoOwner}/${repoName}.`);
|
||||
createGithubAdapter(repoOwner, repoName).then((githubAdapter) => {
|
||||
const graph = githubAdapter.graph();
|
||||
const nodeCount = Array.from(graph.nodes()).length;
|
||||
const edgeCount = Array.from(graph.edges()).length;
|
||||
console.log(`Loaded graph: ${nodeCount} nodes, ${edgeCount} edges.`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// @flow
|
||||
|
||||
import type {Graph, NodeAddressT} from "../core/graph";
|
||||
|
||||
export interface Renderer {
|
||||
nodeDescription(NodeAddressT): string;
|
||||
}
|
||||
|
||||
export interface PluginAdapter {
|
||||
graph(): Graph;
|
||||
renderer(): Renderer;
|
||||
nodePrefix(): NodeAddressT;
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// @flow
|
||||
import type {
|
||||
PluginAdapter as IPluginAdapter,
|
||||
Renderer as IRenderer,
|
||||
} from "../../app/pluginAdapter";
|
||||
import {type Graph, NodeAddress} from "../../core/graph";
|
||||
import {createGraph} from "./createGraph";
|
||||
import * as N from "./nodes";
|
||||
import {RelationalView} from "./relationalView";
|
||||
import {description} from "./render";
|
||||
|
||||
export async function createPluginAdapter(
|
||||
repoOwner: string,
|
||||
repoName: string
|
||||
): Promise<IPluginAdapter> {
|
||||
const url = `/api/v1/data/data/${repoOwner}/${repoName}/github/view.json`;
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
return Promise.reject(response);
|
||||
}
|
||||
const json = await response.json();
|
||||
const view = RelationalView.fromJSON(json);
|
||||
const graph = createGraph(view);
|
||||
return new PluginAdapter(view, graph);
|
||||
}
|
||||
|
||||
class PluginAdapter implements IPluginAdapter {
|
||||
+_view: RelationalView;
|
||||
+_graph: Graph;
|
||||
constructor(view: RelationalView, graph: Graph) {
|
||||
this._view = view;
|
||||
this._graph = graph;
|
||||
}
|
||||
graph() {
|
||||
return this._graph;
|
||||
}
|
||||
renderer() {
|
||||
return new Renderer(this._view);
|
||||
}
|
||||
nodePrefix() {
|
||||
return N._Prefix.base;
|
||||
}
|
||||
}
|
||||
|
||||
class Renderer implements IRenderer {
|
||||
+_view: RelationalView;
|
||||
constructor(view) {
|
||||
this._view = view;
|
||||
}
|
||||
nodeDescription(node) {
|
||||
// This cast is unsound, and might throw at runtime, but won't have
|
||||
// silent failures or cause problems down the road.
|
||||
const address = N.fromRaw((node: any));
|
||||
const entity = this._view.entity(address);
|
||||
if (entity == null) {
|
||||
throw new Error(`unknown entity: ${NodeAddress.toString(node)}`);
|
||||
}
|
||||
return description(entity);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue