From 7a88d32cb27de825d6170ab0bf9e1c9f3fc48ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dandelion=20Man=C3=A9?= Date: Sun, 14 Jul 2019 20:08:11 +0100 Subject: [PATCH] Remove the ExplorerAdapter from the legacy app Prior to #1136, we needed an `ExplorerAdapter` abstraction to get node description data to the frontend. Now that it's included in the graph, we can throw away this abstraction, which is a big step towards plugin simplification (work towards #1120). Since it only affects a deprecated/legacy part of the code base, I didn't put much effort into making the result super clean. I also removed a few tests that became inconvenient. Test plan: Verified that the legacy frontend still works. There's one tiny regression, which is that the link color in the legacy frontend no longer matches the rest of the UI, but that's actually consistent with the timeline frontend, so no biggie. `yarn test` passes. --- src/explorer/legacy/App.js | 19 +- src/explorer/legacy/App.test.js | 13 +- .../legacy/adapters/explorerAdapter.js | 18 -- .../legacy/adapters/explorerAdapterSet.js | 134 -------------- .../adapters/explorerAdapterSet.test.js | 166 ------------------ .../legacy/pagerankTable/Aggregation.js | 10 +- .../legacy/pagerankTable/Aggregation.test.js | 15 +- .../legacy/pagerankTable/Connection.js | 27 +-- .../legacy/pagerankTable/Connection.test.js | 21 +-- src/explorer/legacy/pagerankTable/Node.js | 4 +- .../legacy/pagerankTable/Node.test.js | 11 +- src/explorer/legacy/pagerankTable/Table.js | 48 +++-- .../legacy/pagerankTable/Table.test.js | 5 +- src/explorer/legacy/pagerankTable/shared.js | 40 +++-- .../legacy/pagerankTable/sharedTestUtils.js | 11 +- src/explorer/legacy/state.js | 71 +++----- src/explorer/legacy/state.test.js | 72 ++------ src/homepage/homepageExplorer.js | 14 +- src/plugins/demo/explorerAdapter.js | 50 ------ src/plugins/git/explorerAdapter.js | 77 -------- src/plugins/github/explorerAdapter.js | 62 ------- 21 files changed, 145 insertions(+), 743 deletions(-) delete mode 100644 src/explorer/legacy/adapters/explorerAdapter.js delete mode 100644 src/explorer/legacy/adapters/explorerAdapterSet.js delete mode 100644 src/explorer/legacy/adapters/explorerAdapterSet.test.js delete mode 100644 src/plugins/demo/explorerAdapter.js delete mode 100644 src/plugins/git/explorerAdapter.js delete mode 100644 src/plugins/github/explorerAdapter.js diff --git a/src/explorer/legacy/App.js b/src/explorer/legacy/App.js index d03198c..e43b5c7 100644 --- a/src/explorer/legacy/App.js +++ b/src/explorer/legacy/App.js @@ -9,6 +9,7 @@ import BrowserLocalStore from "../../webutil/browserLocalStore"; import Link from "../../webutil/Link"; import type {RepoId} from "../../core/repoId"; import {type NodeAddressT} from "../../core/graph"; +import {declaration as githubDeclaration} from "../../plugins/github/declaration"; import {PagerankTable} from "./pagerankTable/Table"; import {WeightConfig} from "../weights/WeightConfig"; @@ -21,7 +22,6 @@ import { type StateTransitionMachineInterface, initialState, } from "./state"; -import {StaticExplorerAdapterSet} from "./adapters/explorerAdapterSet"; import {userNodeType} from "../../plugins/github/declaration"; const credOverviewUrl = @@ -31,7 +31,6 @@ const feedbackUrl = export class AppPage extends React.Component<{| +assets: Assets, - +adapters: StaticExplorerAdapterSet, +repoId: RepoId, |}> { static _LOCAL_STORE = new CheckedLocalStore( @@ -47,7 +46,6 @@ export class AppPage extends React.Component<{| ); @@ -57,7 +55,6 @@ export class AppPage extends React.Component<{| type Props = {| +assets: Assets, +localStore: LocalStore, - +adapters: StaticExplorerAdapterSet, +repoId: RepoId, |}; type State = {| @@ -90,9 +87,7 @@ export function createApp( const {appState} = this.state; const weightConfig = ( a.declaration())} + declarations={[githubDeclaration]} nodeTypeWeights={this.state.weights.nodeTypeWeights} edgeTypeWeights={this.state.weights.edgeTypeWeights} onNodeWeightChange={(prefix, weight) => { @@ -119,15 +114,15 @@ export function createApp( ); let pagerankTable; if (appState.type === "PAGERANK_EVALUATED") { - const adapters = appState.graphWithAdapters.adapters; const pnd = appState.pagerankNodeDecomposition; pagerankTable = ( this.setState(({weights}) => { weights.nodeManualWeights.set(addr, weight); @@ -164,9 +159,11 @@ export function createApp( onClick={() => this.stateTransitionMachine.loadGraphAndRunPagerank( this.props.assets, - this.props.adapters, this.state.weights, - this.props.adapters.combinedTypes(), + { + nodeTypes: githubDeclaration.nodeTypes.slice(), + edgeTypes: githubDeclaration.edgeTypes.slice(), + }, GithubPrefix.user ) } diff --git a/src/explorer/legacy/App.test.js b/src/explorer/legacy/App.test.js index 074096a..26b2b99 100644 --- a/src/explorer/legacy/App.test.js +++ b/src/explorer/legacy/App.test.js @@ -7,10 +7,6 @@ import {Graph} from "../../core/graph"; import {makeRepoId} from "../../core/repoId"; import {Assets} from "../../webutil/assets"; import testLocalStore from "../../webutil/testLocalStore"; -import { - DynamicExplorerAdapterSet, - StaticExplorerAdapterSet, -} from "./adapters/explorerAdapterSet"; import {PagerankTable} from "./pagerankTable/Table"; import {createApp, LoadingIndicator, ProjectDetail} from "./App"; @@ -37,7 +33,6 @@ describe("explorer/legacy/App", () => { const el = shallow( @@ -56,10 +51,6 @@ describe("explorer/legacy/App", () => { }; } - const emptyAdapters = new DynamicExplorerAdapterSet( - new StaticExplorerAdapterSet([]), - [] - ); const exampleStates = { readyToLoadGraph: (loadingState) => { return () => ({ @@ -73,7 +64,7 @@ describe("explorer/legacy/App", () => { type: "READY_TO_RUN_PAGERANK", repoId: makeRepoId("foo", "bar"), loading: loadingState, - graphWithAdapters: {graph: new Graph(), adapters: emptyAdapters}, + graph: new Graph(), }); }, pagerankEvaluated: (loadingState) => { @@ -81,7 +72,7 @@ describe("explorer/legacy/App", () => { type: "PAGERANK_EVALUATED", repoId: makeRepoId("foo", "bar"), loading: loadingState, - graphWithAdapters: {graph: new Graph(), adapters: emptyAdapters}, + graph: new Graph(), pagerankNodeDecomposition: new Map(), }); }, diff --git a/src/explorer/legacy/adapters/explorerAdapter.js b/src/explorer/legacy/adapters/explorerAdapter.js deleted file mode 100644 index 70dbdb9..0000000 --- a/src/explorer/legacy/adapters/explorerAdapter.js +++ /dev/null @@ -1,18 +0,0 @@ -// @flow - -import {type Node as ReactNode} from "react"; -import {Graph, type NodeAddressT} from "../../../core/graph"; -import type {Assets} from "../../../webutil/assets"; -import type {RepoId} from "../../../core/repoId"; -import type {PluginDeclaration} from "../../../analysis/pluginDeclaration"; - -export interface StaticExplorerAdapter { - declaration(): PluginDeclaration; - load(assets: Assets, repoId: RepoId): Promise; -} - -export interface DynamicExplorerAdapter { - graph(): Graph; - nodeDescription(NodeAddressT): ReactNode; - static(): StaticExplorerAdapter; -} diff --git a/src/explorer/legacy/adapters/explorerAdapterSet.js b/src/explorer/legacy/adapters/explorerAdapterSet.js deleted file mode 100644 index 6f60fe9..0000000 --- a/src/explorer/legacy/adapters/explorerAdapterSet.js +++ /dev/null @@ -1,134 +0,0 @@ -// @flow -/** - * This module is deprecated; logic for aggregating over different plugins, - * and matching adapters for a particular or edge, should live at the - * core plugin level, not at the level of particular adapters. Otherwise, - * we will find ourselves re-implementing the same logic repetitiously for - * every new adapter. - * - * If considering adding new dependencies on this file or adding new features, - * please consider simply re-writing it to live in the analysis module and - * be paramterized over the adapter choice. - */ - -import {Graph, type NodeAddressT, type EdgeAddressT} from "../../../core/graph"; -import {NodeTrie, EdgeTrie} from "../../../core/trie"; -import type {NodeAndEdgeTypes} from "../../../analysis/types"; -import {combineTypes} from "../../../analysis/pluginDeclaration"; -import type {Assets} from "../../../webutil/assets"; -import type {RepoId} from "../../../core/repoId"; - -import type { - StaticExplorerAdapter, - DynamicExplorerAdapter, -} from "./explorerAdapter"; -import type {EdgeType, NodeType} from "../../../analysis/types"; - -export class StaticExplorerAdapterSet { - _adapters: $ReadOnlyArray; - _adapterNodeTrie: NodeTrie; - _adapterEdgeTrie: EdgeTrie; - _typeNodeTrie: NodeTrie; - _typeEdgeTrie: EdgeTrie; - - constructor(adapters: $ReadOnlyArray): void { - this._adapters = adapters; - this._adapterNodeTrie = new NodeTrie(); - this._adapterEdgeTrie = new EdgeTrie(); - this._typeNodeTrie = new NodeTrie(); - this._typeEdgeTrie = new EdgeTrie(); - const usedPluginNames = new Set(); - this._adapters.forEach((a) => { - const name = a.declaration().name; - if (usedPluginNames.has(name)) { - throw new Error(`Multiple plugins with name "${name}"`); - } - usedPluginNames.add(name); - this._adapterNodeTrie.add(a.declaration().nodePrefix, a); - this._adapterEdgeTrie.add(a.declaration().edgePrefix, a); - }); - this.nodeTypes().forEach((t) => this._typeNodeTrie.add(t.prefix, t)); - this.edgeTypes().forEach((t) => this._typeEdgeTrie.add(t.prefix, t)); - } - - adapters(): $ReadOnlyArray { - return this._adapters; - } - - combinedTypes(): NodeAndEdgeTypes { - return combineTypes(this._adapters.map((x) => x.declaration())); - } - - // TODO(@decentralion): Remove the next two methods - // (Although really I want to remove this whole class.) - nodeTypes(): NodeType[] { - return [].concat(...this._adapters.map((x) => x.declaration().nodeTypes)); - } - - edgeTypes(): EdgeType[] { - return [].concat(...this._adapters.map((x) => x.declaration().edgeTypes)); - } - - adapterMatchingNode(x: NodeAddressT): ?StaticExplorerAdapter { - return this._adapterNodeTrie.getLast(x); - } - - adapterMatchingEdge(x: EdgeAddressT): ?StaticExplorerAdapter { - return this._adapterEdgeTrie.getLast(x); - } - - typeMatchingNode(x: NodeAddressT): ?NodeType { - return this._typeNodeTrie.getLast(x); - } - - typeMatchingEdge(x: EdgeAddressT): ?EdgeType { - return this._typeEdgeTrie.getLast(x); - } - - load(assets: Assets, repoId: RepoId): Promise { - return Promise.all(this._adapters.map((a) => a.load(assets, repoId))).then( - (adapters) => new DynamicExplorerAdapterSet(this, adapters) - ); - } -} - -export class DynamicExplorerAdapterSet { - _adapters: $ReadOnlyArray; - _staticExplorerAdapterSet: StaticExplorerAdapterSet; - _adapterNodeTrie: NodeTrie; - _adapterEdgeTrie: EdgeTrie; - - constructor( - staticExplorerAdapterSet: StaticExplorerAdapterSet, - adapters: $ReadOnlyArray - ): void { - this._staticExplorerAdapterSet = staticExplorerAdapterSet; - this._adapters = adapters; - this._adapterNodeTrie = new NodeTrie(); - this._adapterEdgeTrie = new EdgeTrie(); - this._adapters.forEach((a) => { - this._adapterNodeTrie.add(a.static().declaration().nodePrefix, a); - this._adapterEdgeTrie.add(a.static().declaration().edgePrefix, a); - }); - } - - adapterMatchingNode(x: NodeAddressT): ?DynamicExplorerAdapter { - return this._adapterNodeTrie.getLast(x); - } - - adapterMatchingEdge(x: EdgeAddressT): ?DynamicExplorerAdapter { - return this._adapterEdgeTrie.getLast(x); - } - - adapters(): $ReadOnlyArray { - return this._adapters; - } - - graph(): Graph { - return Graph.merge(this._adapters.map((x) => x.graph())); - } - - static() { - return this._staticExplorerAdapterSet; - } -} diff --git a/src/explorer/legacy/adapters/explorerAdapterSet.test.js b/src/explorer/legacy/adapters/explorerAdapterSet.test.js deleted file mode 100644 index fb0d281..0000000 --- a/src/explorer/legacy/adapters/explorerAdapterSet.test.js +++ /dev/null @@ -1,166 +0,0 @@ -// @flow - -import {NodeAddress, EdgeAddress, Graph} from "../../../core/graph"; -import {FactorioStaticAdapter} from "../../../plugins/demo/explorerAdapter"; -import {StaticExplorerAdapterSet} from "./explorerAdapterSet"; -import {Assets} from "../../../webutil/assets"; -import {makeRepoId} from "../../../core/repoId"; -import * as NullUtil from "../../../util/null"; - -describe("explorer/legacy/adapters/explorerAdapterSet", () => { - describe("StaticExplorerAdapterSet", () => { - function example() { - const x = new FactorioStaticAdapter(); - const sas = new StaticExplorerAdapterSet([x]); - return {x, sas}; - } - it("errors if two plugins have the same name", () => { - const x = new FactorioStaticAdapter(); - const shouldError = () => new StaticExplorerAdapterSet([x, x]); - expect(shouldError).toThrowError("Multiple plugins with name"); - }); - it("includes the manually provided plugin adapters", () => { - const {x, sas} = example(); - expect(sas.adapters()[0].declaration().name).toBe(x.declaration().name); - }); - it("aggregates NodeTypes across plugins", () => { - const {sas} = example(); - const nodeTypes = sas.nodeTypes(); - const expectedNumNodeTypes = new FactorioStaticAdapter().declaration() - .nodeTypes.length; - expect(nodeTypes).toHaveLength(expectedNumNodeTypes); - }); - it("aggregates EdgeTypes across plugins", () => { - const {sas} = example(); - const edgeTypes = sas.edgeTypes(); - const expectedNumEdgeTypes = new FactorioStaticAdapter().declaration() - .edgeTypes.length; - expect(edgeTypes).toHaveLength(expectedNumEdgeTypes); - }); - it("finds adapter matching a node", () => { - const {x, sas} = example(); - let matching = sas.adapterMatchingNode( - NodeAddress.fromParts(["factorio", "inserter"]) - ); - matching = NullUtil.get(matching); - expect(matching.declaration().name).toBe(x.declaration().name); - }); - it("finds adapter matching an edge", () => { - const {x, sas} = example(); - let matching = sas.adapterMatchingEdge( - EdgeAddress.fromParts(["factorio", "assembles"]) - ); - matching = NullUtil.get(matching); - expect(matching.declaration().name).toBe(x.declaration().name); - }); - it("finds no adapter for unregistered node", () => { - const {sas} = example(); - const adapter = sas.adapterMatchingNode(NodeAddress.fromParts(["weird"])); - expect(adapter).toBe(undefined); - }); - it("finds no adapter for unregistered edge", () => { - const {sas} = example(); - const adapter = sas.adapterMatchingEdge(EdgeAddress.fromParts(["weird"])); - expect(adapter).toBe(undefined); - }); - it("finds type matching a node", () => { - const {sas} = example(); - const type = NullUtil.get( - sas.typeMatchingNode( - NodeAddress.fromParts(["factorio", "inserter", "1", "foo"]) - ) - ); - expect(type.name).toBe("inserter"); - }); - it("finds type matching an edge", () => { - const {sas} = example(); - const type = NullUtil.get( - sas.typeMatchingEdge( - EdgeAddress.fromParts(["factorio", "assembles", "other", "1", "foo"]) - ) - ); - expect(type.forwardName).toBe("assembles"); - }); - it("finds no type for unregistered node", () => { - const {sas} = example(); - const type = sas.typeMatchingNode( - NodeAddress.fromParts(["wombat", "1", "foo"]) - ); - expect(type).toBe(undefined); - }); - it("finds no type for unregistered edge", () => { - const {sas} = example(); - const type = sas.typeMatchingEdge( - EdgeAddress.fromParts(["wombat", "1", "foo"]) - ); - expect(type).toBe(undefined); - }); - it("loads a dynamicExplorerAdapterSet", async () => { - const {x, sas} = example(); - const loadingMock = jest.fn().mockResolvedValue(); - x.loadingMock = loadingMock; - expect(x.loadingMock).toHaveBeenCalledTimes(0); - const assets = new Assets("/my/gateway/"); - const repoId = makeRepoId("foo", "bar"); - const das = await sas.load(assets, repoId); - expect(loadingMock).toHaveBeenCalledTimes(1); - expect(loadingMock.mock.calls[0]).toHaveLength(2); - expect(loadingMock.mock.calls[0][0]).toBe(assets); - expect(loadingMock.mock.calls[0][1]).toBe(repoId); - expect(das).toEqual(expect.anything()); - }); - }); - - describe("DynamicExplorerAdapterSet", () => { - async function example() { - const x = new FactorioStaticAdapter(); - const sas = new StaticExplorerAdapterSet([x]); - const das = await sas.load( - new Assets("/my/gateway/"), - makeRepoId("foo", "bar") - ); - return {x, sas, das}; - } - it("allows retrieval of the original StaticExplorerAdapterSet", async () => { - const {sas, das} = await example(); - expect(das.static()).toBe(sas); - }); - it("allows accessing the dynamic adapters", async () => { - const {sas, das} = await example(); - expect(das.adapters().map((a) => a.static().declaration().name)).toEqual( - sas.adapters().map((a) => a.declaration().name) - ); - }); - it("allows retrieval of the aggregated graph", async () => { - const {das} = await example(); - const expectedGraph = Graph.merge(das.adapters().map((x) => x.graph())); - expect(das.graph().equals(expectedGraph)).toBe(true); - }); - it("finds adapter matching a node", async () => { - const {x, das} = await example(); - let matching = das.adapterMatchingNode( - NodeAddress.fromParts(["factorio", "inserter"]) - ); - matching = NullUtil.get(matching); - expect(matching.static().declaration().name).toBe(x.declaration().name); - }); - it("finds adapter matching an edge", async () => { - const {x, das} = await example(); - let matching = das.adapterMatchingEdge( - EdgeAddress.fromParts(["factorio", "assembles"]) - ); - matching = NullUtil.get(matching); - expect(matching.static().declaration().name).toBe(x.declaration().name); - }); - it("finds no adapter for unregistered node", async () => { - const {das} = await example(); - const adapter = das.adapterMatchingNode(NodeAddress.fromParts(["weird"])); - expect(adapter).toBe(undefined); - }); - it("finds no adapter for unregistered edge", async () => { - const {das} = await example(); - const adapter = das.adapterMatchingEdge(EdgeAddress.fromParts(["weird"])); - expect(adapter).toBe(undefined); - }); - }); -}); diff --git a/src/explorer/legacy/pagerankTable/Aggregation.js b/src/explorer/legacy/pagerankTable/Aggregation.js index a12341c..e90372d 100644 --- a/src/explorer/legacy/pagerankTable/Aggregation.js +++ b/src/explorer/legacy/pagerankTable/Aggregation.js @@ -20,13 +20,11 @@ type AggregationRowListProps = {| export class AggregationRowList extends React.PureComponent { render() { const {depth, node, sharedProps} = this.props; - const {pnd, adapters} = sharedProps; + const {pnd, declarations} = sharedProps; + const nodeTypes = [].concat(...declarations.map((x) => x.nodeTypes)); + const edgeTypes = [].concat(...declarations.map((x) => x.edgeTypes)); const {scoredConnections} = NullUtil.get(pnd.get(node)); - const aggregations = aggregateFlat( - scoredConnections, - adapters.static().nodeTypes(), - adapters.static().edgeTypes() - ); + const aggregations = aggregateFlat(scoredConnections, nodeTypes, edgeTypes); return ( {aggregations.map((agg) => ( diff --git a/src/explorer/legacy/pagerankTable/Aggregation.test.js b/src/explorer/legacy/pagerankTable/Aggregation.test.js index fe54006..f2a8891 100644 --- a/src/explorer/legacy/pagerankTable/Aggregation.test.js +++ b/src/explorer/legacy/pagerankTable/Aggregation.test.js @@ -6,6 +6,7 @@ import {shallow} from "enzyme"; import * as NullUtil from "../../../util/null"; import {NodeAddress, EdgeAddress} from "../../../core/graph"; import type {EdgeType, NodeType} from "../../../analysis/types"; +import {combineTypes} from "../../../analysis/pluginDeclaration"; import { AggregationRowList, AggregationRow, @@ -23,14 +24,15 @@ require("../../../webutil/testUtil").configureEnzyme(); describe("explorer/legacy/pagerankTable/Aggregation", () => { describe("AggregationRowList", () => { it("instantiates AggregationRows for each aggregation", async () => { - const {adapters, pnd, sharedProps} = await example(); + const {pnd, sharedProps} = await example(); const node = factorioNodes.inserter1.address; const depth = 20; const connections = NullUtil.get(pnd.get(node)).scoredConnections; + const types = combineTypes(sharedProps.declarations); const aggregations = aggregateFlat( connections, - adapters.static().nodeTypes(), - adapters.static().edgeTypes() + types.nodeTypes, + types.edgeTypes ); const el = shallow( { describe("AggregationRow", () => { async function setup() { - const {pnd, adapters, sharedProps} = await example(); + const {pnd, sharedProps} = await example(); const target = factorioNodes.inserter1.address; const {scoredConnections} = NullUtil.get(pnd.get(target)); + const types = combineTypes(sharedProps.declarations); const aggregations = aggregateFlat( scoredConnections, - adapters.static().nodeTypes(), - adapters.static().edgeTypes() + types.nodeTypes, + types.edgeTypes ); const aggregation = aggregations[0]; const depth = 23; diff --git a/src/explorer/legacy/pagerankTable/Connection.js b/src/explorer/legacy/pagerankTable/Connection.js index c2c8ed3..7c6505c 100644 --- a/src/explorer/legacy/pagerankTable/Connection.js +++ b/src/explorer/legacy/pagerankTable/Connection.js @@ -3,14 +3,14 @@ import React from "react"; import * as NullUtil from "../../../util/null"; -import type {NodeAddressT} from "../../../core/graph"; +import {type PluginDeclaration} from "../../../analysis/pluginDeclaration"; +import {type NodeAddressT, Graph} from "../../../core/graph"; import type {Connection} from "../../../core/attribution/graphToMarkovChain"; import type {ScoredConnection} from "../../../analysis/pagerankNodeDecomposition"; -import {DynamicExplorerAdapterSet} from "../adapters/explorerAdapterSet"; import {TableRow} from "./TableRow"; import {NodeRow} from "./Node"; -import {edgeVerb, nodeDescription, type SharedProps, Badge} from "./shared"; +import {nodeDescription, edgeVerb, type SharedProps, Badge} from "./shared"; type ConnectionRowListProps = {| +depth: number, @@ -54,13 +54,17 @@ export class ConnectionRow extends React.PureComponent { depth, scoredConnection: {connection, source, connectionScore}, } = this.props; - const {pnd, adapters} = sharedProps; + const {pnd, declarations, graph} = sharedProps; const {score: targetScore} = NullUtil.get(pnd.get(target)); const connectionProportion = connectionScore / targetScore; const connectionPercent = (connectionProportion * 100).toFixed(2) + "%"; const connectionView = ( - + ); return ( { export class ConnectionView extends React.PureComponent<{| +connection: Connection, - +adapters: DynamicExplorerAdapterSet, + +declarations: $ReadOnlyArray, + +graph: Graph, |}> { render() { - const {connection, adapters} = this.props; + const {connection, declarations, graph} = this.props; const {adjacency} = connection; switch (adjacency.type) { case "SYNTHETIC_LOOP": @@ -96,18 +101,18 @@ export class ConnectionView extends React.PureComponent<{| return ( - {edgeVerb(adjacency.edge.address, "BACKWARD", adapters)} + {edgeVerb(adjacency.edge.address, "BACKWARD", declarations)} {" "} - {nodeDescription(adjacency.edge.src, adapters)} + {nodeDescription(adjacency.edge.src, graph)} ); case "OUT_EDGE": return ( - {edgeVerb(adjacency.edge.address, "FORWARD", adapters)} + {edgeVerb(adjacency.edge.address, "FORWARD", declarations)} {" "} - {nodeDescription(adjacency.edge.dst, adapters)} + {nodeDescription(adjacency.edge.dst, graph)} ); default: diff --git a/src/explorer/legacy/pagerankTable/Connection.test.js b/src/explorer/legacy/pagerankTable/Connection.test.js index 147a3b7..15a202d 100644 --- a/src/explorer/legacy/pagerankTable/Connection.test.js +++ b/src/explorer/legacy/pagerankTable/Connection.test.js @@ -108,13 +108,11 @@ describe("explorer/legacy/pagerankTable/Connection", () => { expect(row.props().multiuseColumn).toBe(expectedPercent); }); it("with a ConnectionView as description", async () => { - const {row, sharedProps, scoredConnection} = await setup(); - const {adapters} = sharedProps; + const {row, scoredConnection} = await setup(); const description = row.props().description; const cv = shallow(description).instance(); expect(cv).toBeInstanceOf(ConnectionView); expect(cv.props.connection).toEqual(scoredConnection.connection); - expect(cv.props.adapters).toEqual(adapters); }); describe("with a NodeRow as children", () => { function getChildren(row) { @@ -146,7 +144,7 @@ describe("explorer/legacy/pagerankTable/Connection", () => { }); describe("ConnectionView", () => { async function setup() { - const {pnd, adapters} = await example(); + const {pnd, sharedProps} = await example(); const {scoredConnections} = NullUtil.get( pnd.get(factorioNodes.machine1.address) ); @@ -162,11 +160,14 @@ describe("explorer/legacy/pagerankTable/Connection", () => { const syntheticConnection = connectionByType("SYNTHETIC_LOOP"); function cvForConnection(connection: Connection) { return shallow( - + ); } return { - adapters, connections, pnd, cvForConnection, @@ -195,22 +196,14 @@ describe("explorer/legacy/pagerankTable/Connection", () => { const view = cvForConnection(inConnection); const outerSpan = view.find("span").first(); const badge = outerSpan.find("Badge"); - const description = outerSpan.children().find("span"); expect(badge.children().text()).toEqual("is transported by"); - expect(description.text()).toEqual( - '[factorio]: NodeAddress["factorio","inserter","1"]' - ); }); it("for outward connections, renders a `Badge` and description", async () => { const {cvForConnection, outConnection} = await setup(); const view = cvForConnection(outConnection); const outerSpan = view.find("span").first(); const badge = outerSpan.find("Badge"); - const description = outerSpan.children().find("span"); expect(badge.children().text()).toEqual("assembles"); - expect(description.text()).toEqual( - '[factorio]: NodeAddress["factorio","inserter","2"]' - ); }); it("for synthetic connections, renders only a `Badge`", async () => { const {cvForConnection, syntheticConnection} = await setup(); diff --git a/src/explorer/legacy/pagerankTable/Node.js b/src/explorer/legacy/pagerankTable/Node.js index b8119e5..c5a0179 100644 --- a/src/explorer/legacy/pagerankTable/Node.js +++ b/src/explorer/legacy/pagerankTable/Node.js @@ -55,7 +55,7 @@ export type NodeRowProps = {| export class NodeRow extends React.PureComponent { render() { const {depth, node, sharedProps, showPadding} = this.props; - const {pnd, adapters, onManualWeightsChange, manualWeights} = sharedProps; + const {pnd, graph, onManualWeightsChange, manualWeights} = sharedProps; const {score} = NullUtil.get(pnd.get(node)); const weight = NullUtil.orElse(manualWeights.get(node), 1); const slider = ( @@ -74,7 +74,7 @@ export class NodeRow extends React.PureComponent { /> ); - const description = {nodeDescription(node, adapters)}; + const description = {nodeDescription(node, graph)}; return ( { return sortBy(nodes, (node) => -NullUtil.get(pnd.get(node)).score); } async function setup(maxEntriesPerList: number = 123) { - const {adapters, pnd, sharedProps: changeEntries} = await example(); + const {pnd, sharedProps: changeEntries} = await example(); const sharedProps = {...changeEntries, maxEntriesPerList}; const nodes = Array.from(pnd.keys()); expect(nodes).not.toHaveLength(0); const component = ; const element = shallow(component); - return {element, adapters, sharedProps, nodes}; + return {element, sharedProps, nodes}; } it("creates `NodeRow`s with the right props", async () => { const {element, nodes, sharedProps} = await setup(); @@ -164,12 +163,6 @@ describe("explorer/legacy/pagerankTable/Node", () => { expect(span.text()).toEqual("4×"); }); }); - it("with the node description", async () => { - const {row, sharedProps, node} = await setup(); - const {adapters} = sharedProps; - const description = shallow(row.props().description); - expect(description.text()).toEqual(nodeDescription(node, adapters)); - }); describe("with a AggregationRowList as children", () => { function getChildren(row) { const children = row.props().children; diff --git a/src/explorer/legacy/pagerankTable/Table.js b/src/explorer/legacy/pagerankTable/Table.js index c16b353..4f4e900 100644 --- a/src/explorer/legacy/pagerankTable/Table.js +++ b/src/explorer/legacy/pagerankTable/Table.js @@ -5,16 +5,16 @@ import sortBy from "lodash.sortby"; import {WeightConfig} from "../../weights/WeightConfig"; import {WeightsFileManager} from "../../weights/WeightsFileManager"; -import {NodeAddress, type NodeAddressT} from "../../../core/graph"; +import {Graph, NodeAddress, type NodeAddressT} from "../../../core/graph"; import type {PagerankNodeDecomposition} from "../../../analysis/pagerankNodeDecomposition"; -import {DynamicExplorerAdapterSet} from "../adapters/explorerAdapterSet"; -import type {DynamicExplorerAdapter} from "../adapters/explorerAdapter"; import {NodeRowList} from "./Node"; import {type NodeType} from "../../../analysis/types"; +import {type PluginDeclaration} from "../../../analysis/pluginDeclaration"; type PagerankTableProps = {| +pnd: PagerankNodeDecomposition, - +adapters: DynamicExplorerAdapterSet, + +declarations: $ReadOnlyArray, + +graph: Graph, +maxEntriesPerList: number, +defaultNodeType: ?NodeType, +manualWeights: Map, @@ -75,29 +75,26 @@ export class PagerankTable extends React.PureComponent< } renderFilterSelect() { - const {pnd, adapters} = this.props; - if (pnd == null || adapters == null) { + const {pnd, declarations} = this.props; + if (pnd == null || declarations == null) { throw new Error("Impossible."); } - function optionGroup(adapter: DynamicExplorerAdapter) { + function optionGroup(declaration: PluginDeclaration) { const header = ( ); - const entries = adapter - .static() - .declaration() - .nodeTypes.map((type) => ( - - )); + const entries = declaration.nodeTypes.map((type) => ( + + )); return [header, ...entries]; } return ( @@ -110,10 +107,9 @@ export class PagerankTable extends React.PureComponent< } > - {sortBy( - adapters.adapters(), - (a: DynamicExplorerAdapter) => a.static().declaration().name - ).map(optionGroup)} + {sortBy(declarations, (d: PluginDeclaration) => d.name).map( + optionGroup + )} ); @@ -122,20 +118,22 @@ export class PagerankTable extends React.PureComponent< renderTable() { const { pnd, - adapters, + declarations, maxEntriesPerList, manualWeights, onManualWeightsChange, + graph, } = this.props; - if (pnd == null || adapters == null || maxEntriesPerList == null) { + if (pnd == null || declarations == null || maxEntriesPerList == null) { throw new Error("Impossible."); } const sharedProps = { pnd, - adapters, + declarations, maxEntriesPerList, manualWeights, onManualWeightsChange, + graph, }; return ( { async function setup(defaultNodeType?: NodeType) { const { pnd, - adapters, sharedProps, manualWeights, onManualWeightsChange, @@ -31,7 +30,8 @@ describe("explorer/legacy/pagerankTable/Table", () => { weightConfig={weightConfig} weightFileManager={weightFileManager} pnd={pnd} - adapters={adapters} + graph={sharedProps.graph} + declarations={sharedProps.declarations} maxEntriesPerList={maxEntriesPerList} manualWeights={manualWeights} onManualWeightsChange={onManualWeightsChange} @@ -39,7 +39,6 @@ describe("explorer/legacy/pagerankTable/Table", () => { ); return { pnd, - adapters, element, maxEntriesPerList, weightConfig, diff --git a/src/explorer/legacy/pagerankTable/shared.js b/src/explorer/legacy/pagerankTable/shared.js index bfda9d0..0ca50ce 100644 --- a/src/explorer/legacy/pagerankTable/shared.js +++ b/src/explorer/legacy/pagerankTable/shared.js @@ -1,45 +1,51 @@ // @flow import React, {type Node as ReactNode} from "react"; +import Markdown from "react-markdown"; import { + Graph, type EdgeAddressT, type NodeAddressT, - NodeAddress, + EdgeAddress, } from "../../../core/graph"; - -import {DynamicExplorerAdapterSet} from "../adapters/explorerAdapterSet"; +import {type PluginDeclaration} from "../../../analysis/pluginDeclaration"; import type {PagerankNodeDecomposition} from "../../../analysis/pagerankNodeDecomposition"; export function nodeDescription( address: NodeAddressT, - adapters: DynamicExplorerAdapterSet + graph: Graph ): ReactNode { - const adapter = adapters.adapterMatchingNode(address); - if (adapter == null) { - return NodeAddress.toString(address); - } - try { - return adapter.nodeDescription(address); - } catch (e) { - const result = NodeAddress.toString(address); - console.error(`Error getting description for ${result}: ${e.message}`); - return result; + const node = graph.node(address); + if (node == null) { + throw new Error(`No node for ${address}`); } + return ; } export function edgeVerb( address: EdgeAddressT, direction: "FORWARD" | "BACKWARD", - adapters: DynamicExplorerAdapterSet + declarations: $ReadOnlyArray ): string { - const edgeType = adapters.static().typeMatchingEdge(address); + function getType() { + for (const {edgeTypes} of declarations) { + for (const edgeType of edgeTypes) { + if (EdgeAddress.hasPrefix(address, edgeType.prefix)) { + return edgeType; + } + } + } + throw Error(`No matching type for ${address}`); + } + const edgeType = getType(); return direction === "FORWARD" ? edgeType.forwardName : edgeType.backwardName; } export type SharedProps = {| +pnd: PagerankNodeDecomposition, - +adapters: DynamicExplorerAdapterSet, + +graph: Graph, + +declarations: $ReadOnlyArray, +maxEntriesPerList: number, +manualWeights: Map, +onManualWeightsChange: (NodeAddressT, number) => void, diff --git a/src/explorer/legacy/pagerankTable/sharedTestUtils.js b/src/explorer/legacy/pagerankTable/sharedTestUtils.js index ccbfa0d..287e6a6 100644 --- a/src/explorer/legacy/pagerankTable/sharedTestUtils.js +++ b/src/explorer/legacy/pagerankTable/sharedTestUtils.js @@ -4,14 +4,15 @@ import React from "react"; import {type NodeAddressT} from "../../../core/graph"; import {pagerank} from "../../../analysis/pagerank"; -import {dynamicExplorerAdapterSet} from "../../../plugins/demo/explorerAdapter"; +import {graph as demoGraph} from "../../../plugins/demo/graph"; +import {declaration as demoDeclaration} from "../../../plugins/demo/declaration"; import type {SharedProps} from "./shared"; export const COLUMNS = () => ["Description", "", "Cred"]; export async function example() { - const adapters = await dynamicExplorerAdapterSet(); - const graph = adapters.graph(); + const graph = demoGraph(); + const declarations = [demoDeclaration]; const pnd = await pagerank(graph, (_unused_Edge) => ({ forwards: 1, backwards: 1, @@ -23,7 +24,8 @@ export async function example() { const weightFileManager: any =
; const sharedProps: SharedProps = { - adapters, + graph, + declarations, pnd, maxEntriesPerList, manualWeights, @@ -31,7 +33,6 @@ export async function example() { }; return { - adapters, pnd, maxEntriesPerList, sharedProps, diff --git a/src/explorer/legacy/state.js b/src/explorer/legacy/state.js index c99e1a7..04894a2 100644 --- a/src/explorer/legacy/state.js +++ b/src/explorer/legacy/state.js @@ -7,16 +7,13 @@ import type {Assets} from "../../webutil/assets"; import type {RepoId} from "../../core/repoId"; import {type EdgeEvaluator} from "../../analysis/pagerank"; import type {NodeAndEdgeTypes} from "../../analysis/types"; +import {defaultLoader} from "../TimelineApp"; import { type PagerankNodeDecomposition, type PagerankOptions, pagerank, } from "../../analysis/pagerank"; -import { - StaticExplorerAdapterSet, - DynamicExplorerAdapterSet, -} from "./adapters/explorerAdapterSet"; import type {Weights} from "../../analysis/weights"; import {weightsToEdgeEvaluator} from "../../analysis/weightsToEdgeEvaluator"; @@ -42,12 +39,12 @@ export type ReadyToLoadGraph = {| export type ReadyToRunPagerank = {| +type: "READY_TO_RUN_PAGERANK", +repoId: RepoId, - +graphWithAdapters: GraphWithAdapters, + +graph: Graph, +loading: LoadingState, |}; export type PagerankEvaluated = {| +type: "PAGERANK_EVALUATED", - +graphWithAdapters: GraphWithAdapters, + +graph: Graph, +repoId: RepoId, +pagerankNodeDecomposition: PagerankNodeDecomposition, +loading: LoadingState, @@ -61,38 +58,28 @@ export function createStateTransitionMachine( getState: () => AppState, setState: (AppState) => void ): StateTransitionMachine { - return new StateTransitionMachine( - getState, - setState, - loadGraphWithAdapters, - pagerank - ); + return new StateTransitionMachine(getState, setState, doLoadGraph, pagerank); } // Exported for testing purposes. export interface StateTransitionMachineInterface { - +loadGraph: (Assets, StaticExplorerAdapterSet) => Promise; + +loadGraph: (Assets) => Promise; +runPagerank: (Weights, NodeAndEdgeTypes, NodeAddressT) => Promise; +loadGraphAndRunPagerank: ( Assets, - StaticExplorerAdapterSet, Weights, NodeAndEdgeTypes, NodeAddressT ) => Promise; } /* In production, instantiate via createStateTransitionMachine; the constructor - * implementation allows specification of the loadGraphWithAdapters and + * implementation allows specification of the loadGraph and * pagerank functions for DI/testing purposes. **/ export class StateTransitionMachine implements StateTransitionMachineInterface { getState: () => AppState; setState: (AppState) => void; - loadGraphWithAdapters: ( - assets: Assets, - adapters: StaticExplorerAdapterSet, - repoId: RepoId - ) => Promise; + doLoadGraph: (assets: Assets, repoId: RepoId) => Promise; pagerank: ( Graph, EdgeEvaluator, @@ -102,11 +89,7 @@ export class StateTransitionMachine implements StateTransitionMachineInterface { constructor( getState: () => AppState, setState: (AppState) => void, - loadGraphWithAdapters: ( - assets: Assets, - adapters: StaticExplorerAdapterSet, - repoId: RepoId - ) => Promise, + doLoadGraph: (assets: Assets, repoId: RepoId) => Promise, pagerank: ( Graph, EdgeEvaluator, @@ -115,15 +98,12 @@ export class StateTransitionMachine implements StateTransitionMachineInterface { ) { this.getState = getState; this.setState = setState; - this.loadGraphWithAdapters = loadGraphWithAdapters; + this.doLoadGraph = doLoadGraph; this.pagerank = pagerank; } /** Loads the graph, reports whether it was successful */ - async loadGraph( - assets: Assets, - adapters: StaticExplorerAdapterSet - ): Promise { + async loadGraph(assets: Assets): Promise { const state = this.getState(); if (state.type !== "READY_TO_LOAD_GRAPH") { throw new Error("Tried to loadGraph in incorrect state"); @@ -134,14 +114,10 @@ export class StateTransitionMachine implements StateTransitionMachineInterface { let newState: ?AppState; let success = true; try { - const graphWithAdapters = await this.loadGraphWithAdapters( - assets, - adapters, - repoId - ); + const graph = await this.doLoadGraph(assets, repoId); newState = { type: "READY_TO_RUN_PAGERANK", - graphWithAdapters, + graph, repoId, loading: "NOT_LOADING", }; @@ -175,7 +151,7 @@ export class StateTransitionMachine implements StateTransitionMachineInterface { ? {...state, loading: "LOADING"} : {...state, loading: "LOADING"}; this.setState(loadingState); - const graph = state.graphWithAdapters.graph; + const graph = state.graph; let newState: ?AppState; try { const pagerankNodeDecomposition = await this.pagerank( @@ -189,7 +165,7 @@ export class StateTransitionMachine implements StateTransitionMachineInterface { newState = { type: "PAGERANK_EVALUATED", pagerankNodeDecomposition, - graphWithAdapters: state.graphWithAdapters, + graph: state.graph, repoId: state.repoId, loading: "NOT_LOADING", }; @@ -208,7 +184,6 @@ export class StateTransitionMachine implements StateTransitionMachineInterface { async loadGraphAndRunPagerank( assets: Assets, - adapters: StaticExplorerAdapterSet, weights: Weights, types: NodeAndEdgeTypes, totalScoreNodePrefix: NodeAddressT @@ -217,7 +192,7 @@ export class StateTransitionMachine implements StateTransitionMachineInterface { const type = state.type; switch (type) { case "READY_TO_LOAD_GRAPH": - const loadedGraph = await this.loadGraph(assets, adapters); + const loadedGraph = await this.loadGraph(assets); if (loadedGraph) { await this.runPagerank(weights, types, totalScoreNodePrefix); } @@ -232,15 +207,13 @@ export class StateTransitionMachine implements StateTransitionMachineInterface { } } -export type GraphWithAdapters = {| - +graph: Graph, - +adapters: DynamicExplorerAdapterSet, -|}; -export async function loadGraphWithAdapters( +export async function doLoadGraph( assets: Assets, - adapters: StaticExplorerAdapterSet, repoId: RepoId -): Promise { - const dynamicAdapters = await adapters.load(assets, repoId); - return {graph: dynamicAdapters.graph(), adapters: dynamicAdapters}; +): Promise { + const loadResult = await defaultLoader(assets, repoId); + if (loadResult.type !== "SUCCESS") { + throw new Error(loadResult); + } + return loadResult.timelineCred.graph(); } diff --git a/src/explorer/legacy/state.test.js b/src/explorer/legacy/state.test.js index 1421cf6..6840015 100644 --- a/src/explorer/legacy/state.test.js +++ b/src/explorer/legacy/state.test.js @@ -1,20 +1,12 @@ // @flow -import { - StateTransitionMachine, - type AppState, - type GraphWithAdapters, -} from "./state"; +import {StateTransitionMachine, type AppState} from "./state"; import {Graph, NodeAddress} from "../../core/graph"; import {Assets} from "../../webutil/assets"; import {makeRepoId, type RepoId} from "../../core/repoId"; import {type EdgeEvaluator} from "../../analysis/pagerank"; import {defaultWeights} from "../../analysis/weights"; -import { - StaticExplorerAdapterSet, - DynamicExplorerAdapterSet, -} from "./adapters/explorerAdapterSet"; import type { PagerankNodeDecomposition, PagerankOptions, @@ -28,8 +20,8 @@ describe("explorer/legacy/state", () => { stateContainer.appState = appState; }; const loadGraphMock: JestMockFn< - [Assets, StaticExplorerAdapterSet, RepoId], - Promise + [Assets, RepoId], + Promise > = jest.fn(); const pagerankMock: JestMockFn< @@ -56,27 +48,18 @@ describe("explorer/legacy/state", () => { type: "READY_TO_RUN_PAGERANK", repoId: makeRepoId("foo", "bar"), loading: "NOT_LOADING", - graphWithAdapters: graphWithAdapters(), + graph: new Graph(), }; } function pagerankEvaluated(): AppState { return { type: "PAGERANK_EVALUATED", repoId: makeRepoId("foo", "bar"), - graphWithAdapters: graphWithAdapters(), + graph: new Graph(), pagerankNodeDecomposition: pagerankNodeDecomposition(), loading: "NOT_LOADING", }; } - function graphWithAdapters(): GraphWithAdapters { - return { - graph: new Graph(), - adapters: new DynamicExplorerAdapterSet( - new StaticExplorerAdapterSet([]), - [] - ), - }; - } function pagerankNodeDecomposition() { return new Map(); } @@ -92,45 +75,34 @@ describe("explorer/legacy/state", () => { const badStates = [readyToRunPagerank(), pagerankEvaluated()]; for (const b of badStates) { const {stm} = example(b); - await expect( - stm.loadGraph( - new Assets("/my/gateway/"), - new StaticExplorerAdapterSet([]) - ) - ).rejects.toThrow("incorrect state"); + await expect(stm.loadGraph(new Assets("/my/gateway/"))).rejects.toThrow( + "incorrect state" + ); } }); - it("passes along the adapters and repoId", () => { + it("passes along the repoId", () => { const {stm, loadGraphMock} = example(readyToLoadGraph()); expect(loadGraphMock).toHaveBeenCalledTimes(0); const assets = new Assets("/my/gateway/"); - const adapters = new StaticExplorerAdapterSet([]); - stm.loadGraph(assets, adapters); + stm.loadGraph(assets); expect(loadGraphMock).toHaveBeenCalledTimes(1); expect(loadGraphMock).toHaveBeenCalledWith( assets, - adapters, makeRepoId("foo", "bar") ); }); it("immediately sets loading status", () => { const {getState, stm} = example(readyToLoadGraph()); expect(loading(getState())).toBe("NOT_LOADING"); - stm.loadGraph( - new Assets("/my/gateway/"), - new StaticExplorerAdapterSet([]) - ); + stm.loadGraph(new Assets("/my/gateway/")); expect(loading(getState())).toBe("LOADING"); expect(getState().type).toBe("READY_TO_LOAD_GRAPH"); }); it("transitions to READY_TO_RUN_PAGERANK on success", async () => { const {getState, stm, loadGraphMock} = example(readyToLoadGraph()); - const gwa = graphWithAdapters(); - loadGraphMock.mockReturnValue(Promise.resolve(gwa)); - const succeeded = await stm.loadGraph( - new Assets("/my/gateway/"), - new StaticExplorerAdapterSet([]) - ); + const graph = new Graph(); + loadGraphMock.mockReturnValue(Promise.resolve(graph)); + const succeeded = await stm.loadGraph(new Assets("/my/gateway/")); expect(succeeded).toBe(true); const state = getState(); expect(loading(state)).toBe("NOT_LOADING"); @@ -138,7 +110,7 @@ describe("explorer/legacy/state", () => { if (state.type !== "READY_TO_RUN_PAGERANK") { throw new Error("Impossible"); } - expect(state.graphWithAdapters).toBe(gwa); + expect(state.graph).toBe(graph); }); it("sets loading state FAILED on reject", async () => { const {getState, stm, loadGraphMock} = example(readyToLoadGraph()); @@ -146,10 +118,7 @@ describe("explorer/legacy/state", () => { // $ExpectFlowError console.error = jest.fn(); loadGraphMock.mockReturnValue(Promise.reject(error)); - const succeeded = await stm.loadGraph( - new Assets("/my/gateway/"), - new StaticExplorerAdapterSet([]) - ); + const succeeded = await stm.loadGraph(new Assets("/my/gateway/")); expect(succeeded).toBe(false); const state = getState(); expect(loading(state)).toBe("FAILED"); @@ -225,13 +194,12 @@ describe("explorer/legacy/state", () => { (stm: any).runPagerank = jest.fn(); stm.loadGraph.mockResolvedValue(true); const assets = new Assets("/gateway/"); - const adapters = new StaticExplorerAdapterSet([]); const prefix = NodeAddress.fromParts(["bar"]); const types = defaultTypes(); const wt = defaultWeights(); - await stm.loadGraphAndRunPagerank(assets, adapters, wt, types, prefix); + await stm.loadGraphAndRunPagerank(assets, wt, types, prefix); expect(stm.loadGraph).toHaveBeenCalledTimes(1); - expect(stm.loadGraph).toHaveBeenCalledWith(assets, adapters); + expect(stm.loadGraph).toHaveBeenCalledWith(assets); expect(stm.runPagerank).toHaveBeenCalledTimes(1); expect(stm.runPagerank).toHaveBeenCalledWith(wt, types, prefix); }); @@ -241,11 +209,9 @@ describe("explorer/legacy/state", () => { (stm: any).runPagerank = jest.fn(); stm.loadGraph.mockResolvedValue(false); const assets = new Assets("/gateway/"); - const adapters = new StaticExplorerAdapterSet([]); const prefix = NodeAddress.fromParts(["bar"]); await stm.loadGraphAndRunPagerank( assets, - adapters, defaultWeights(), defaultTypes(), prefix @@ -262,7 +228,6 @@ describe("explorer/legacy/state", () => { const types = defaultTypes(); await stm.loadGraphAndRunPagerank( new Assets("/gateway/"), - new StaticExplorerAdapterSet([]), wt, types, prefix @@ -280,7 +245,6 @@ describe("explorer/legacy/state", () => { const types = defaultTypes(); await stm.loadGraphAndRunPagerank( new Assets("/gateway/"), - new StaticExplorerAdapterSet([]), wt, types, prefix diff --git a/src/homepage/homepageExplorer.js b/src/homepage/homepageExplorer.js index 7fdcf0b..93de438 100644 --- a/src/homepage/homepageExplorer.js +++ b/src/homepage/homepageExplorer.js @@ -3,26 +3,14 @@ import React from "react"; import type {Assets} from "../webutil/assets"; -import {StaticExplorerAdapterSet} from "../explorer/legacy/adapters/explorerAdapterSet"; -import {StaticExplorerAdapter as GithubAdapter} from "../plugins/github/explorerAdapter"; import {AppPage} from "../explorer/legacy/App"; import type {RepoId} from "../core/repoId"; -function homepageStaticAdapters(): StaticExplorerAdapterSet { - return new StaticExplorerAdapterSet([new GithubAdapter()]); -} - export default class HomepageExplorer extends React.Component<{| +assets: Assets, +repoId: RepoId, |}> { render() { - return ( - - ); + return ; } } diff --git a/src/plugins/demo/explorerAdapter.js b/src/plugins/demo/explorerAdapter.js deleted file mode 100644 index 08d5489..0000000 --- a/src/plugins/demo/explorerAdapter.js +++ /dev/null @@ -1,50 +0,0 @@ -// @flow - -import type {PluginDeclaration} from "../../analysis/pluginDeclaration"; -import {declaration} from "./declaration"; -import type { - StaticExplorerAdapter, - DynamicExplorerAdapter, -} from "../../explorer/legacy/adapters/explorerAdapter"; -import {StaticExplorerAdapterSet} from "../../explorer/legacy/adapters/explorerAdapterSet"; -import {Assets} from "../../webutil/assets"; -import {type RepoId, makeRepoId} from "../../core/repoId"; -import {NodeAddress, type NodeAddressT} from "../../core/graph"; -import {graph} from "./graph"; - -export class FactorioStaticAdapter implements StaticExplorerAdapter { - loadingMock: (assets: Assets, repoId: RepoId) => Promise; - declaration(): PluginDeclaration { - return declaration; - } - async load(assets: Assets, repoId: RepoId) { - const result: FactorioDynamicAdapter = new FactorioDynamicAdapter(); - if (this.loadingMock) { - return this.loadingMock(assets, repoId).then(() => result); - } - return Promise.resolve(result); - } -} - -export class FactorioDynamicAdapter implements DynamicExplorerAdapter { - graph() { - return graph(); - } - nodeDescription(x: NodeAddressT) { - return `[factorio]: ${NodeAddress.toString(x)}`; - } - static(): FactorioStaticAdapter { - return new FactorioStaticAdapter(); - } -} - -export function staticExplorerAdapterSet() { - return new StaticExplorerAdapterSet([new FactorioStaticAdapter()]); -} - -export async function dynamicExplorerAdapterSet() { - return await staticExplorerAdapterSet().load( - new Assets("/gateway/"), - makeRepoId("foo", "bar") - ); -} diff --git a/src/plugins/git/explorerAdapter.js b/src/plugins/git/explorerAdapter.js deleted file mode 100644 index 472c5c8..0000000 --- a/src/plugins/git/explorerAdapter.js +++ /dev/null @@ -1,77 +0,0 @@ -// @flow -import type { - StaticExplorerAdapter as IStaticExplorerAdapter, - DynamicExplorerAdapter as IDynamicExplorerAdapter, -} from "../../explorer/legacy/adapters/explorerAdapter"; -import {Graph} from "../../core/graph"; -import * as N from "./nodes"; -import {description} from "./render"; -import type {Assets} from "../../webutil/assets"; -import type {RepoId} from "../../core/repoId"; -import type {Repository} from "./types"; -import type {GitGateway} from "./gitGateway"; -import type {PluginDeclaration} from "../../analysis/pluginDeclaration"; -import {declaration} from "./declaration"; - -export class StaticExplorerAdapter implements IStaticExplorerAdapter { - _gitGateway: GitGateway; - - constructor(gg: GitGateway): void { - this._gitGateway = gg; - } - declaration(): PluginDeclaration { - return declaration; - } - async load(assets: Assets, repoId: RepoId): Promise { - const baseUrl = `/api/v1/data/data/${repoId.owner}/${repoId.name}/git/`; - async function loadGraph() { - const url = assets.resolve(baseUrl + "graph.json"); - const response = await fetch(url); - if (!response.ok) { - return Promise.reject(response); - } - const json = await response.json(); - return Graph.fromJSON(json); - } - async function loadRepository(): Promise { - const url = assets.resolve(baseUrl + "repository.json"); - const response = await fetch(url); - if (!response.ok) { - return Promise.reject(response); - } - return await response.json(); - } - const [graph, repository] = await Promise.all([ - loadGraph(), - loadRepository(), - ]); - return new DynamicExplorerAdapter(this._gitGateway, graph, repository); - } -} - -class DynamicExplorerAdapter implements IDynamicExplorerAdapter { - +_graph: Graph; - +_repository: Repository; - +_gitGateway: GitGateway; - constructor( - gitGateway: GitGateway, - graph: Graph, - repository: Repository - ): void { - this._graph = graph; - this._repository = repository; - this._gitGateway = gitGateway; - } - graph() { - return this._graph; - } - 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)); - return description(address, this._repository, this._gitGateway); - } - static() { - return new StaticExplorerAdapter(this._gitGateway); - } -} diff --git a/src/plugins/github/explorerAdapter.js b/src/plugins/github/explorerAdapter.js deleted file mode 100644 index bfff7ca..0000000 --- a/src/plugins/github/explorerAdapter.js +++ /dev/null @@ -1,62 +0,0 @@ -// @flow -import pako from "pako"; - -import type { - StaticExplorerAdapter as IStaticExplorerAdapter, - DynamicExplorerAdapter as IDynamicExplorerAdapter, -} from "../../explorer/legacy/adapters/explorerAdapter"; -import {type Graph, NodeAddress} from "../../core/graph"; -import {createGraph} from "./createGraph"; -import * as N from "./nodes"; -import {RelationalView} from "./relationalView"; -import {description} from "./render"; -import type {Assets} from "../../webutil/assets"; -import type {RepoId} from "../../core/repoId"; -import type {PluginDeclaration} from "../../analysis/pluginDeclaration"; -import {declaration} from "./declaration"; - -export class StaticExplorerAdapter implements IStaticExplorerAdapter { - declaration(): PluginDeclaration { - return declaration; - } - async load(assets: Assets, repoId: RepoId): Promise { - const url = assets.resolve( - `/api/v1/data/data/${repoId.owner}/${repoId.name}/github/view.json.gz` - ); - const response = await fetch(url); - if (!response.ok) { - return Promise.reject(response); - } - const arrayBuffer = await response.arrayBuffer(); - const blob = new Uint8Array(arrayBuffer); - const json = JSON.parse(pako.ungzip(blob, {to: "string"})); - const view = RelationalView.fromJSON(json); - const graph = createGraph(view); - return new DynamicExplorerAdapter(view, graph); - } -} - -class DynamicExplorerAdapter implements IDynamicExplorerAdapter { - +_view: RelationalView; - +_graph: Graph; - constructor(view: RelationalView, graph: Graph): void { - this._view = view; - this._graph = graph; - } - 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); - } - graph() { - return this._graph; - } - static() { - return new StaticExplorerAdapter(); - } -}