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(); - } -}