Skip to content

Commit

Permalink
feat(Stations): Create the necessary scaffolding for a station comple…
Browse files Browse the repository at this point in the history
…ment plugin aspect.


This is necessary so assets can be included with stations,
including station logos and card icons. It opens the possibility
of folks creating custom station sets in the future, but we won't
build any APIs or UIs for that right now.

Closes #87

* Add automated tests for the Station Complement plugin aspect

* Fix test
  • Loading branch information
alexanderson1993 authored Nov 17, 2021
1 parent 8b5b58a commit 3b02377
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 9 deletions.
7 changes: 2 additions & 5 deletions server/src/classes/Card.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import uniqid from "@thorium/uniqid";
type CardConfig = unknown;
export class Card {
id: string;

name: string;

component: string;

config: CardConfig;
config?: CardConfig;

icon: string | null;
icon?: string | null;

constructor(params: Partial<Card>) {
this.id = params.id || uniqid("crd-");
this.name = params.name || "Card";
this.component = params.component || "Card";
this.config = params.config;
Expand Down
59 changes: 59 additions & 0 deletions server/src/classes/Plugins/StationComplement.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import StationComplementPlugin from "./StationComplement";
import Plugin from "./index";
import {ServerDataModel} from "../ServerDataModel";
import {promises as fs} from "fs";
import path from "path";
const testYaml = `apiVersion: "stations/v1"
kind: "stations"
name: "Test Station"
hasShipMap: false
stations:
- name: Pilot
description: A single player position that controls all aspects of the ship.
logo: Pilot.svg
cards:
- name: Pilot
component: Pilot
`;
describe("StationComplementPlugin", () => {
afterAll(async () => {
await fs.rm("./plugins", {recursive: true});
});
it("should instantiate correctly", async () => {
const plugin = new Plugin({}, {plugins: []} as unknown as ServerDataModel);
const stationComplement = new StationComplementPlugin({}, plugin);
expect(stationComplement).toBeInstanceOf(StationComplementPlugin);
expect(stationComplement.name).toBe("New Station Complement");
expect(stationComplement.stationCount).toBe(0);
});
it("should load test yaml", async () => {
const plugin = new Plugin({name: "Test Plugin"}, {
plugins: [],
} as unknown as ServerDataModel);
await plugin.writeFile(true);
await fs.mkdir(
path.resolve(
path.join(".", plugin.path, "../stationComplements/Test Station")
),
{recursive: true}
);
await fs.writeFile(
path.resolve(
path.join(
".",
plugin.path,
"../stationComplements/Test Station/manifest.yml"
)
),
testYaml
);
const stationComplement = new StationComplementPlugin(
{name: "Test Station"},
plugin
);
expect(stationComplement.name).toBe("Test Station");
expect(stationComplement.stationCount).toBe(1);
expect(stationComplement.stations[0].name).toBe("Pilot");
expect(stationComplement.assets["Pilot-logo"]).toBeTruthy();
});
});
45 changes: 45 additions & 0 deletions server/src/classes/Plugins/StationComplement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {generateIncrementedName} from "server/src/utils/generateIncrementedName";
import BasePlugin from ".";
import Station from "../Station";
import {Aspect} from "./Aspect";

export default class StationComplementPlugin extends Aspect {
apiVersion = "stations/v1" as const;
kind = "stationComplements" as const;
name!: string;
hasShipMap!: boolean;
stations!: Station[];
get stationCount() {
return this.stations.length;
}
assets!: Record<string, string>;
constructor(params: Partial<StationComplementPlugin>, plugin: BasePlugin) {
const name = generateIncrementedName(
params.name || "New Station Complement",
plugin.aspects.stationComplements.map(station => station.name)
);
super({name, ...params}, {kind: "stationComplements"}, plugin);

this.stations = this.stations || params.stations || [];
this.hasShipMap = this.hasShipMap || params.hasShipMap || false;
this.assets = this.assets || params.assets || {};

this.assets = this.stations.reduce((assets, station) => {
const cardIcons = station.cards.reduce(
(icons: Record<string, string>, card) => {
if (card.icon) {
icons[`${station.name}-${card.name}-icon`] = card.icon;
}
return icons;
},
{}
);

return {
...assets,
[`${station.name}-logo`]: station.logo,
...cardIcons,
};
}, {});
}
}
9 changes: 9 additions & 0 deletions server/src/classes/Plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {thoriumPath} from "server/src/utils/appPaths";
import fs from "fs/promises";
import {FSDataStore} from "@thorium/db-fs";
import path from "path";
import StationComplementPlugin from "./StationComplement";
import {loadFolderYaml} from "server/src/utils/loadFolderYaml";

export function pluginPublish(plugin: BasePlugin) {
Expand All @@ -19,6 +20,7 @@ export function pluginPublish(plugin: BasePlugin) {

interface Aspects {
ships: ShipPlugin[];
stationComplements: StationComplementPlugin[];
}
// Storing the server here so it doesn't get
// serialized with the plugin.
Expand Down Expand Up @@ -77,13 +79,20 @@ export default class BasePlugin extends FSDataStore {
if (!aspects) {
aspects = {
ships: [],
stationComplements: [],
};
pluginAspects.set(this, aspects);
}
return aspects;
}
async loadAspects() {
this.aspects.ships = await BasePlugin.loadAspect(this, "ships", ShipPlugin);

this.aspects.stationComplements = await BasePlugin.loadAspect(
this,
"stationComplements",
StationComplementPlugin
);
}
toJSON() {
const {_coverImage, ...data} = this;
Expand Down
8 changes: 4 additions & 4 deletions server/src/classes/Station.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,27 @@ import uuid from "@thorium/uniqid";
import {Card} from "./Card";

export default class Station {
id: string;
apiVersion = "stations/v1" as const;
kind = "stations" as const;

name: string;

description: string;

logo: string;

layout: string;
theme: string;

tags: string[];

cards: Card[];

constructor(params: Partial<Station>) {
this.id = params.id || uuid("sta-");
this.name = params.name || "Station";
this.description = params.description || "";
this.tags = params.tags || [];
this.logo = params.logo || "";
this.layout = params.layout || "Default";
this.theme = params.theme || "Default";
this.cards = [];
params.cards?.forEach(c => this.cards.push(new Card(c)));
}
Expand Down
2 changes: 2 additions & 0 deletions server/src/components/stationComplement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export class StationComplementComponent extends Component {

name: string = "Station Complement";

hasShipMap: boolean = false;

stations: Station[] = [];

init(params: Partial<StationComplementComponent>) {
Expand Down

0 comments on commit 3b02377

Please sign in to comment.