mirror of
https://github.com/status-im/sourcecred.git
synced 2025-01-11 13:14:28 +00:00
Add the demo plugin (#965)
* Add the demo plugin This ports the ad-hoc demo adapter defined in `src/app/adapters/demoAdapters.js` into its own demo plugin. This has the benefit that the demo plugin can now be depended on outside the app module, e.g. for the analysis module as well. Correspondingly, I've added a demo analysis adapter. Test plan: `yarn test`. Note that no unit tests were added, as the demo plugin is trivial. * Delete `src/app/adapters/demoAdapters.js` Now that we have an explicit demo plugin at `src/plugins/demo/`, we can remove the legacy declaration of that plugin within the `app` module. This commit deletes the old version, and re-writes all references to point to the standalone plugin. Test plan: `yarn test`
This commit is contained in:
parent
6b789d61d6
commit
86a5b532f8
@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import {NodeAddress, EdgeAddress, Graph} from "../../core/graph";
|
||||
import {FactorioStaticAdapter} from "./demoAdapters";
|
||||
import {FactorioStaticAdapter} from "../../plugins/demo/appAdapter";
|
||||
import {StaticAdapterSet} from "./adapterSet";
|
||||
import {
|
||||
FallbackStaticAdapter,
|
||||
@ -103,8 +103,7 @@ describe("app/adapters/adapterSet", () => {
|
||||
});
|
||||
it("loads a dynamicAdapterSet", async () => {
|
||||
const {x, sas} = example();
|
||||
x.loadingMock = jest.fn();
|
||||
x.loadingMock.mockResolvedValue();
|
||||
x.loadingMock = jest.fn().mockResolvedValue();
|
||||
expect(x.loadingMock).toHaveBeenCalledTimes(0);
|
||||
const assets = new Assets("/my/gateway/");
|
||||
const repoId = makeRepoId("foo", "bar");
|
||||
|
@ -1,126 +0,0 @@
|
||||
// @flow
|
||||
|
||||
import {Assets} from "../assets";
|
||||
import {
|
||||
Graph,
|
||||
NodeAddress,
|
||||
type NodeAddressT,
|
||||
EdgeAddress,
|
||||
} from "../../core/graph";
|
||||
import type {StaticAppAdapter, DynamicAppAdapter} from "./appAdapter";
|
||||
import type {EdgeType, NodeType} from "../../analysis/types";
|
||||
import type {PluginDeclaration} from "../../analysis/pluginDeclaration";
|
||||
|
||||
import {StaticAdapterSet} from "./adapterSet";
|
||||
import {makeRepoId, type RepoId} from "../../core/repoId";
|
||||
|
||||
export const inserterNodeType: NodeType = Object.freeze({
|
||||
name: "inserter",
|
||||
pluralName: "inserters",
|
||||
prefix: NodeAddress.fromParts(["factorio", "inserter"]),
|
||||
defaultWeight: 1,
|
||||
});
|
||||
|
||||
export const machineNodeType: NodeType = Object.freeze({
|
||||
name: "machine",
|
||||
pluralName: "machines",
|
||||
prefix: NodeAddress.fromParts(["factorio", "machine"]),
|
||||
defaultWeight: 2,
|
||||
});
|
||||
|
||||
export const assemblesEdgeType: EdgeType = Object.freeze({
|
||||
forwardName: "assembles",
|
||||
defaultForwardWeight: 2,
|
||||
backwardName: "is assembled by",
|
||||
defaultBackwardWeight: 2 ** -2,
|
||||
prefix: EdgeAddress.fromParts(["factorio", "assembles"]),
|
||||
});
|
||||
|
||||
export const transportsEdgeType: EdgeType = Object.freeze({
|
||||
forwardName: "transports",
|
||||
defaultForwardWeight: 1,
|
||||
backwardName: "is transported by",
|
||||
defaultBackwardWeight: 2 ** -1,
|
||||
prefix: EdgeAddress.fromParts(["factorio", "transports"]),
|
||||
});
|
||||
|
||||
export const declaration: PluginDeclaration = Object.freeze({
|
||||
name: "Factorio demo adapter",
|
||||
nodePrefix: NodeAddress.fromParts(["factorio"]),
|
||||
nodeTypes: [inserterNodeType, machineNodeType],
|
||||
edgePrefix: EdgeAddress.fromParts(["factorio"]),
|
||||
edgeTypes: [assemblesEdgeType, transportsEdgeType],
|
||||
});
|
||||
|
||||
export class FactorioStaticAdapter implements StaticAppAdapter {
|
||||
loadingMock: Function;
|
||||
declaration() {
|
||||
return declaration;
|
||||
}
|
||||
async load(assets: Assets, repoId: RepoId): Promise<DynamicAppAdapter> {
|
||||
if (this.loadingMock) {
|
||||
return this.loadingMock(assets, repoId).then(
|
||||
() => new FactorioDynamicAdapter()
|
||||
);
|
||||
}
|
||||
return Promise.resolve(new FactorioDynamicAdapter());
|
||||
}
|
||||
}
|
||||
|
||||
export const factorioNodes = Object.freeze({
|
||||
inserter1: NodeAddress.fromParts(["factorio", "inserter", "1"]),
|
||||
machine1: NodeAddress.fromParts(["factorio", "machine", "1"]),
|
||||
inserter2: NodeAddress.fromParts(["factorio", "inserter", "2"]),
|
||||
machine2: NodeAddress.fromParts(["factorio", "machine", "2"]),
|
||||
});
|
||||
|
||||
export const factorioEdges = Object.freeze({
|
||||
transports1: Object.freeze({
|
||||
src: factorioNodes.inserter1,
|
||||
dst: factorioNodes.machine1,
|
||||
address: EdgeAddress.fromParts(["factorio", "transports", "1"]),
|
||||
}),
|
||||
assembles1: Object.freeze({
|
||||
src: factorioNodes.machine1,
|
||||
dst: factorioNodes.inserter2,
|
||||
address: EdgeAddress.fromParts(["factorio", "assembles", "1"]),
|
||||
}),
|
||||
transports2: Object.freeze({
|
||||
src: factorioNodes.inserter2,
|
||||
dst: factorioNodes.machine2,
|
||||
address: EdgeAddress.fromParts(["factorio", "assembles", "2"]),
|
||||
}),
|
||||
});
|
||||
export function factorioGraph() {
|
||||
return new Graph()
|
||||
.addNode(factorioNodes.inserter1)
|
||||
.addNode(factorioNodes.inserter2)
|
||||
.addNode(factorioNodes.machine1)
|
||||
.addNode(factorioNodes.machine2)
|
||||
.addEdge(factorioEdges.transports1)
|
||||
.addEdge(factorioEdges.transports2)
|
||||
.addEdge(factorioEdges.assembles1);
|
||||
}
|
||||
|
||||
export class FactorioDynamicAdapter implements DynamicAppAdapter {
|
||||
graph() {
|
||||
return factorioGraph();
|
||||
}
|
||||
nodeDescription(x: NodeAddressT) {
|
||||
return NodeAddress.toString(x);
|
||||
}
|
||||
static() {
|
||||
return new FactorioStaticAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
export function staticAdapterSet() {
|
||||
return new StaticAdapterSet([new FactorioStaticAdapter()]);
|
||||
}
|
||||
|
||||
export async function dynamicAdapterSet() {
|
||||
return await staticAdapterSet().load(
|
||||
new Assets("/gateway/"),
|
||||
makeRepoId("foo", "bar")
|
||||
);
|
||||
}
|
@ -8,7 +8,7 @@ import {makeRepoId} from "../../core/repoId";
|
||||
import {Assets} from "../assets";
|
||||
import testLocalStore from "../testLocalStore";
|
||||
import {DynamicAdapterSet, StaticAdapterSet} from "../adapters/adapterSet";
|
||||
import {FactorioStaticAdapter} from "../adapters/demoAdapters";
|
||||
import {FactorioStaticAdapter} from "../../plugins/demo/appAdapter";
|
||||
import {defaultWeightsForAdapter} from "./weights/weights";
|
||||
|
||||
import RepositorySelect from "./RepositorySelect";
|
||||
|
@ -16,7 +16,7 @@ import {Badge} from "./shared";
|
||||
import {example} from "./sharedTestUtils";
|
||||
import {aggregateFlat, type FlatAggregation} from "./aggregate";
|
||||
import {TableRow} from "./TableRow";
|
||||
import {factorioNodes} from "../../adapters/demoAdapters";
|
||||
import {nodes as factorioNodes} from "../../../plugins/demo/graph";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
|
||||
|
@ -9,7 +9,7 @@ import {ConnectionRowList, ConnectionRow, ConnectionView} from "./Connection";
|
||||
import {example} from "./sharedTestUtils";
|
||||
import {TableRow} from "./TableRow";
|
||||
import {NodeRow} from "./Node";
|
||||
import {factorioNodes} from "../../adapters/demoAdapters";
|
||||
import {nodes as factorioNodes} from "../../../plugins/demo/graph";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
|
||||
@ -196,7 +196,7 @@ describe("app/credExplorer/pagerankTable/Connection", () => {
|
||||
const description = outerSpan.children().find("span");
|
||||
expect(badge.children().text()).toEqual("is transported by");
|
||||
expect(description.text()).toEqual(
|
||||
'NodeAddress["factorio","inserter","1"]'
|
||||
'[factorio]: NodeAddress["factorio","inserter","1"]'
|
||||
);
|
||||
});
|
||||
it("for outward connections, renders a `Badge` and description", async () => {
|
||||
@ -207,7 +207,7 @@ describe("app/credExplorer/pagerankTable/Connection", () => {
|
||||
const description = outerSpan.children().find("span");
|
||||
expect(badge.children().text()).toEqual("assembles");
|
||||
expect(description.text()).toEqual(
|
||||
'NodeAddress["factorio","inserter","2"]'
|
||||
'[factorio]: NodeAddress["factorio","inserter","2"]'
|
||||
);
|
||||
});
|
||||
it("for synthetic connections, renders only a `Badge`", async () => {
|
||||
|
@ -12,7 +12,7 @@ import type {NodeAddressT} from "../../../core/graph";
|
||||
import {nodeDescription} from "./shared";
|
||||
import {example} from "./sharedTestUtils";
|
||||
import {NodeRowList, NodeRow, type NodeRowProps} from "./Node";
|
||||
import {factorioNodes} from "../../adapters/demoAdapters";
|
||||
import {nodes as factorioNodes} from "../../../plugins/demo/graph";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
|
||||
|
@ -10,7 +10,7 @@ import {example, COLUMNS} from "./sharedTestUtils";
|
||||
import {NodeRowList} from "./Node";
|
||||
import {WeightConfig} from "../weights/WeightConfig";
|
||||
import {defaultWeightsForAdapter} from "../weights/weights";
|
||||
import {FactorioStaticAdapter} from "../../adapters/demoAdapters";
|
||||
import {FactorioStaticAdapter} from "../../../plugins/demo/appAdapter";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
describe("app/credExplorer/pagerankTable/Table", () => {
|
||||
|
@ -1,8 +1,8 @@
|
||||
// @flow
|
||||
|
||||
import {dynamicAdapterSet} from "../../adapters/demoAdapters";
|
||||
import {pagerank} from "../../../analysis/pagerank";
|
||||
import {defaultWeightsForAdapterSet} from "../weights/weights";
|
||||
import {dynamicAdapterSet} from "../../../plugins/demo/appAdapter";
|
||||
|
||||
export const COLUMNS = () => ["Description", "", "Cred"];
|
||||
|
||||
|
@ -20,7 +20,7 @@ import type {
|
||||
PagerankNodeDecomposition,
|
||||
PagerankOptions,
|
||||
} from "../../analysis/pagerank";
|
||||
import {staticAdapterSet} from "../adapters/demoAdapters";
|
||||
import {staticAdapterSet} from "../../plugins/demo/appAdapter";
|
||||
|
||||
describe("app/credExplorer/state", () => {
|
||||
function example(startingState: AppState) {
|
||||
|
@ -5,7 +5,7 @@ import {shallow} from "enzyme";
|
||||
|
||||
import {WeightSlider} from "./WeightSlider";
|
||||
import {EdgeTypeConfig, EdgeWeightSlider} from "./EdgeTypeConfig";
|
||||
import {assemblesEdgeType} from "../../adapters/demoAdapters";
|
||||
import {assemblesEdgeType} from "../../../plugins/demo/declaration";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
|
||||
|
@ -5,7 +5,7 @@ import {shallow} from "enzyme";
|
||||
|
||||
import {WeightSlider} from "./WeightSlider";
|
||||
import {NodeTypeConfig} from "./NodeTypeConfig";
|
||||
import {inserterNodeType} from "../../adapters/demoAdapters";
|
||||
import {inserterNodeType} from "../../../plugins/demo/declaration";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
|
||||
|
@ -4,10 +4,10 @@ import React from "react";
|
||||
import {shallow} from "enzyme";
|
||||
import {PluginWeightConfig} from "./PluginWeightConfig";
|
||||
import {
|
||||
FactorioStaticAdapter,
|
||||
inserterNodeType,
|
||||
assemblesEdgeType,
|
||||
} from "../../adapters/demoAdapters";
|
||||
} from "../../../plugins/demo/declaration";
|
||||
import {FactorioStaticAdapter} from "../../../plugins/demo/appAdapter";
|
||||
import {
|
||||
fallbackNodeType,
|
||||
fallbackEdgeType,
|
||||
|
@ -4,10 +4,10 @@ import React from "react";
|
||||
import {shallow} from "enzyme";
|
||||
import {PluginWeightConfig} from "./PluginWeightConfig";
|
||||
import {
|
||||
staticAdapterSet,
|
||||
inserterNodeType,
|
||||
FactorioStaticAdapter,
|
||||
} from "../../adapters/demoAdapters";
|
||||
staticAdapterSet,
|
||||
} from "../../../plugins/demo/appAdapter";
|
||||
import {inserterNodeType} from "../../../plugins/demo/declaration";
|
||||
import {FALLBACK_NAME} from "../../adapters/fallbackAdapter";
|
||||
import {defaultWeightsForAdapterSet, defaultWeightsForAdapter} from "./weights";
|
||||
import {WeightConfig} from "./WeightConfig";
|
||||
|
@ -12,9 +12,11 @@ import {
|
||||
machineNodeType,
|
||||
assemblesEdgeType,
|
||||
transportsEdgeType,
|
||||
} from "../../../plugins/demo/declaration";
|
||||
import {
|
||||
FactorioStaticAdapter,
|
||||
staticAdapterSet,
|
||||
} from "../../adapters/demoAdapters";
|
||||
} from "../../../plugins/demo/appAdapter";
|
||||
|
||||
describe("app/credExplorer/weights/weights", () => {
|
||||
describe("defaultWeightedNodeType", () => {
|
||||
|
@ -9,8 +9,8 @@ import {
|
||||
inserterNodeType,
|
||||
machineNodeType,
|
||||
assemblesEdgeType,
|
||||
factorioEdges,
|
||||
} from "../../adapters/demoAdapters";
|
||||
} from "../../../plugins/demo/declaration";
|
||||
import {edges as factorioEdges} from "../../../plugins/demo/graph";
|
||||
import {weightsToEdgeEvaluator} from "./weightsToEdgeEvaluator";
|
||||
|
||||
describe("app/credExplorer/weights/weightsToEdgeEvaluator", () => {
|
||||
|
14
src/plugins/demo/README.md
Normal file
14
src/plugins/demo/README.md
Normal file
@ -0,0 +1,14 @@
|
||||
# The Demo Plugin
|
||||
|
||||
This plugin exists for testing convenience. It's nice sometimes to have a super
|
||||
lightweight plugin, with a few basic node types, basic (and mockable) adapters,
|
||||
and a simple graph.
|
||||
|
||||
Note: This plugin is **not** intended to be a model for what a canonical plugin
|
||||
would look like. It only exists to test code that depends on having some plugin
|
||||
available.
|
||||
|
||||
The plugin is loosely based on the wonderful video game [Factorio], which the
|
||||
SourceCred developers heartily recommend.
|
||||
|
||||
[Factorio]: https://www.factorio.com/
|
23
src/plugins/demo/analysisAdapter.js
Normal file
23
src/plugins/demo/analysisAdapter.js
Normal file
@ -0,0 +1,23 @@
|
||||
// @flow
|
||||
|
||||
import {Graph} from "../../core/graph";
|
||||
import type {RepoId} from "../../core/repoId";
|
||||
import type {PluginDeclaration} from "../../analysis/pluginDeclaration";
|
||||
import type {IAnalysisAdapter} from "../../analysis/analysisAdapter";
|
||||
|
||||
import {declaration} from "./declaration";
|
||||
import {graph} from "./graph";
|
||||
|
||||
export class AnalysisAdapter implements IAnalysisAdapter {
|
||||
loadingMock: (sourcecredDirectory: string, repoId: RepoId) => Promise<mixed>;
|
||||
declaration(): PluginDeclaration {
|
||||
return declaration;
|
||||
}
|
||||
|
||||
load(sourcecredDirectory: string, repoId: RepoId): Promise<Graph> {
|
||||
if (this.loadingMock) {
|
||||
return this.loadingMock(sourcecredDirectory, repoId).then(() => graph());
|
||||
}
|
||||
return Promise.resolve(graph());
|
||||
}
|
||||
}
|
50
src/plugins/demo/appAdapter.js
Normal file
50
src/plugins/demo/appAdapter.js
Normal file
@ -0,0 +1,50 @@
|
||||
// @flow
|
||||
|
||||
import type {PluginDeclaration} from "../../analysis/pluginDeclaration";
|
||||
import {declaration} from "./declaration";
|
||||
import type {
|
||||
StaticAppAdapter,
|
||||
DynamicAppAdapter,
|
||||
} from "../../app/adapters/appAdapter";
|
||||
import {StaticAdapterSet} from "../../app/adapters/adapterSet";
|
||||
import {Assets} from "../../app/assets";
|
||||
import {type RepoId, makeRepoId} from "../../core/repoId";
|
||||
import {NodeAddress, type NodeAddressT} from "../../core/graph";
|
||||
import {graph} from "./graph";
|
||||
|
||||
export class FactorioStaticAdapter implements StaticAppAdapter {
|
||||
loadingMock: (assets: Assets, repoId: RepoId) => Promise<mixed>;
|
||||
declaration(): PluginDeclaration {
|
||||
return declaration;
|
||||
}
|
||||
async load(assets: Assets, repoId: RepoId): Promise<FactorioDynamicAdapter> {
|
||||
const result: FactorioDynamicAdapter = new FactorioDynamicAdapter();
|
||||
if (this.loadingMock) {
|
||||
return this.loadingMock(assets, repoId).then(() => result);
|
||||
}
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
}
|
||||
|
||||
export class FactorioDynamicAdapter implements DynamicAppAdapter {
|
||||
graph() {
|
||||
return graph();
|
||||
}
|
||||
nodeDescription(x: NodeAddressT) {
|
||||
return `[factorio]: ${NodeAddress.toString(x)}`;
|
||||
}
|
||||
static() {
|
||||
return new FactorioStaticAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
export function staticAdapterSet() {
|
||||
return new StaticAdapterSet([new FactorioStaticAdapter()]);
|
||||
}
|
||||
|
||||
export async function dynamicAdapterSet() {
|
||||
return await staticAdapterSet().load(
|
||||
new Assets("/gateway/"),
|
||||
makeRepoId("foo", "bar")
|
||||
);
|
||||
}
|
45
src/plugins/demo/declaration.js
Normal file
45
src/plugins/demo/declaration.js
Normal file
@ -0,0 +1,45 @@
|
||||
// @flow
|
||||
|
||||
import {NodeAddress, EdgeAddress} from "../../core/graph";
|
||||
|
||||
import type {PluginDeclaration} from "../../analysis/pluginDeclaration";
|
||||
|
||||
import type {EdgeType, NodeType} from "../../analysis/types";
|
||||
|
||||
export const inserterNodeType: NodeType = Object.freeze({
|
||||
name: "inserter",
|
||||
pluralName: "inserters",
|
||||
prefix: NodeAddress.fromParts(["factorio", "inserter"]),
|
||||
defaultWeight: 1,
|
||||
});
|
||||
|
||||
export const machineNodeType: NodeType = Object.freeze({
|
||||
name: "machine",
|
||||
pluralName: "machines",
|
||||
prefix: NodeAddress.fromParts(["factorio", "machine"]),
|
||||
defaultWeight: 2,
|
||||
});
|
||||
|
||||
export const assemblesEdgeType: EdgeType = Object.freeze({
|
||||
forwardName: "assembles",
|
||||
defaultForwardWeight: 2,
|
||||
backwardName: "is assembled by",
|
||||
defaultBackwardWeight: 2 ** -2,
|
||||
prefix: EdgeAddress.fromParts(["factorio", "assembles"]),
|
||||
});
|
||||
|
||||
export const transportsEdgeType: EdgeType = Object.freeze({
|
||||
forwardName: "transports",
|
||||
defaultForwardWeight: 1,
|
||||
backwardName: "is transported by",
|
||||
defaultBackwardWeight: 2 ** -1,
|
||||
prefix: EdgeAddress.fromParts(["factorio", "transports"]),
|
||||
});
|
||||
|
||||
export const declaration: PluginDeclaration = Object.freeze({
|
||||
name: "Factorio demo adapter",
|
||||
nodePrefix: NodeAddress.fromParts(["factorio"]),
|
||||
nodeTypes: Object.freeze([inserterNodeType, machineNodeType]),
|
||||
edgePrefix: EdgeAddress.fromParts(["factorio"]),
|
||||
edgeTypes: Object.freeze([assemblesEdgeType, transportsEdgeType]),
|
||||
});
|
39
src/plugins/demo/graph.js
Normal file
39
src/plugins/demo/graph.js
Normal file
@ -0,0 +1,39 @@
|
||||
// @flow
|
||||
|
||||
import {Graph, NodeAddress, EdgeAddress} from "../../core/graph";
|
||||
|
||||
export const nodes = Object.freeze({
|
||||
inserter1: NodeAddress.fromParts(["factorio", "inserter", "1"]),
|
||||
machine1: NodeAddress.fromParts(["factorio", "machine", "1"]),
|
||||
inserter2: NodeAddress.fromParts(["factorio", "inserter", "2"]),
|
||||
machine2: NodeAddress.fromParts(["factorio", "machine", "2"]),
|
||||
});
|
||||
|
||||
export const edges = Object.freeze({
|
||||
transports1: Object.freeze({
|
||||
src: nodes.inserter1,
|
||||
dst: nodes.machine1,
|
||||
address: EdgeAddress.fromParts(["factorio", "transports", "1"]),
|
||||
}),
|
||||
assembles1: Object.freeze({
|
||||
src: nodes.machine1,
|
||||
dst: nodes.inserter2,
|
||||
address: EdgeAddress.fromParts(["factorio", "assembles", "1"]),
|
||||
}),
|
||||
transports2: Object.freeze({
|
||||
src: nodes.inserter2,
|
||||
dst: nodes.machine2,
|
||||
address: EdgeAddress.fromParts(["factorio", "assembles", "2"]),
|
||||
}),
|
||||
});
|
||||
|
||||
export function graph() {
|
||||
return new Graph()
|
||||
.addNode(nodes.inserter1)
|
||||
.addNode(nodes.inserter2)
|
||||
.addNode(nodes.machine1)
|
||||
.addNode(nodes.machine2)
|
||||
.addEdge(edges.transports1)
|
||||
.addEdge(edges.transports2)
|
||||
.addEdge(edges.assembles1);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user