Skip to content

Commit

Permalink
Add type synonym for plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
soenkehahn committed Nov 13, 2023
1 parent 23bef4b commit ebbecc6
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
56 changes: 55 additions & 1 deletion ts/project.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Check } from "./check.ts";
import { Executable } from "./executable.ts";
import { Project } from "./project.ts";
import { Plugin, Project } from "./project.ts";
import { describe, it } from "https://deno.land/[email protected]/testing/bdd.ts";
import * as garn from "./mod.ts";
import * as nix from "./nix.ts";
import { assertStdout, assertSuccess, runExecutable } from "./testUtils.ts";
import { Package } from "./mod.ts";

const assertTypeIsCheck = (_c: Check) => {};
const assertTypeIsExecutable = (_e: Executable) => {};
const assertTypeIsPackage = (_p: Package) => {};

const _testTypeCheckingOfAddCheck = (project: Project) => {
const p = project
Expand Down Expand Up @@ -133,4 +135,56 @@ describe("Project.add", () => {
assertSuccess(output);
assertStdout(output, "bar\n");
});

it("provides a nice type synonym for plugins that add a field", () => {
const plugin: Plugin<{}, { addedField: garn.Package }> = (p) => ({
...p,
addedField: garn.build``,
});
const project = garn
.mkProject(
{ description: "", defaultEnvironment: garn.emptyEnvironment },
{},
)
.addExecutable("foo", "")
.add(plugin);
assertTypeIsExecutable(project.foo);
assertTypeIsPackage(project.addedField);
});

it("provides a nice type synonym for plugins that add multiple fields", () => {
const plugin: Plugin<{}, { one: garn.Package; two: garn.Check }> = (p) => ({
...p,
one: garn.build``,
two: garn.check(""),
});
const project = garn
.mkProject(
{ description: "", defaultEnvironment: garn.emptyEnvironment },
{},
)
.addExecutable("foo", "")
.add(plugin);
assertTypeIsExecutable(project.foo);
assertTypeIsPackage(project.one);
assertTypeIsCheck(project.two);
});

it("provides a nice interface for plugins that depend on a non-standard field", () => {
const plugin: Plugin<{ dep: Package }, { addedField: Executable }> = (
p,
) => ({
...p,
addedField: garn.shell`${p.dep}/bin/whatever`,
});
const project = garn
.mkProject(
{ description: "", defaultEnvironment: garn.emptyEnvironment },
{ dep: garn.build`` },
)
.addExecutable("foo", "")
.add(plugin);
assertTypeIsExecutable(project.foo);
assertTypeIsExecutable(project.addedField);
});
});
4 changes: 4 additions & 0 deletions ts/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ type ProjectData = {
defaultExecutable?: Executable;
};

export type Plugin<Dependencies, Additions> = <T extends ProjectData>(
project: T & Dependencies,
) => T & Additions;

type ProjectHelpers = {
/**
* Returns a new Project with the provided devtools added to the default
Expand Down

0 comments on commit ebbecc6

Please sign in to comment.