Skip to content

Commit

Permalink
feat: push importmap
Browse files Browse the repository at this point in the history
  • Loading branch information
danewalters committed Jun 15, 2024
1 parent 37c4288 commit ad509a1
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 2 deletions.
24 changes: 24 additions & 0 deletions src/jcli/config/project-json-patch-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { apply_patch as applyPatch } from "jsonpatch";
import {
Project,
ProjectCapability,
ProjectImports,
ProjectPluginInstance,
ProjectScopes,
} from "@/jet/project.ts";

import {
Expand Down Expand Up @@ -369,6 +371,22 @@ function updatePatch<T>(
}
}

function buildImportsPatch(
_op: DiffPatchOp,
value: unknown,
patch: ProjectPatch,
): void {
patch.imports = value as ProjectImports | undefined;
}

function buildScopesPatch(
_op: DiffPatchOp,
value: unknown,
patch: ProjectPatch,
): void {
patch.scopes = value as ProjectScopes | undefined;
}

export const builder = new BuilderNode().children([
new BuilderNode().on(equal("name")).do(buildNamePatch),
new BuilderNode().on(equal("title")).do(buildTitlePatch),
Expand All @@ -390,4 +408,10 @@ export const builder = new BuilderNode().children([
).do(buildInstancePatch),
]),
]),
new BuilderNode({ alwaysRun: true }).on(equal("imports")).do(
buildImportsPatch,
),
new BuilderNode({ alwaysRun: true }).on(equal("scopes")).do(
buildScopesPatch,
),
]);
13 changes: 12 additions & 1 deletion src/jcli/config/project-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {
Project,
ProjectCapability,
ProjectCapabilityPayload,
ProjectImports,
ProjectPluginInstance,
ProjectScopes,
} from "@/jet/project.ts";

import {
Expand All @@ -30,6 +32,8 @@ export class ProjectDotJSON {
readonly title: string;
#capabilities: Array<ProjectCapability>;
#instances: Array<ProjectPluginInstance>;
#imports: ProjectImports | undefined;
#scopes: ProjectScopes | undefined;

static fromJSON(data: string) {
return new ProjectDotJSON(JSON.parse(data));
Expand All @@ -40,6 +44,8 @@ export class ProjectDotJSON {
this.title = project.title;
this.#capabilities = project.capabilities;
this.#instances = project.instances;
this.#imports = project.imports;
this.#scopes = project.scopes;
}

toJSON() {
Expand All @@ -49,6 +55,8 @@ export class ProjectDotJSON {
title: this.title,
capabilities: this.#capabilities,
instances: this.#instances,
imports: this.#imports,
scopes: this.#scopes,
};
}

Expand All @@ -74,7 +82,8 @@ function buildPatch(

export function isPatchEmpty(patch: ProjectPatch): boolean {
return !("title" in patch) && !("name" in patch) &&
patch.capabilities.length === 0 && patch.instances.length === 0;
patch.capabilities.length === 0 && patch.instances.length === 0 &&
!("imports" in patch) && !("scopes" in patch);
}

export interface ProjectCapabilityCreatePatch {
Expand Down Expand Up @@ -131,4 +140,6 @@ export interface ProjectPatch {
title?: string;
capabilities: Array<ProjectCapabilityPatch>;
instances: Array<ProjectPluginInstancePatch>;
imports?: ProjectImports;
scopes?: ProjectScopes;
}
10 changes: 10 additions & 0 deletions src/jet/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,20 @@ export interface ProjectPluginInstance {
capabilityNames: Array<string>;
}

export interface ProjectImports {
[key: string]: string;
}

export interface ProjectScopes {
[scopeName: string]: Record<string, string>;
}

export interface Project {
id: string;
name: string;
title: string;
capabilities: Array<ProjectCapability>;
instances: Array<ProjectPluginInstance>;
imports?: ProjectImports;
scopes?: ProjectScopes;
}
46 changes: 45 additions & 1 deletion test/jcli/config/project-json-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import {
it,
} from "@test/mod.ts";

import { ProjectCapability, ProjectPluginInstance } from "@/jet/project.ts";
import {
ProjectCapability,
ProjectImports,
ProjectPluginInstance,
ProjectScopes,
} from "@/jet/project.ts";

import { ProjectDotJSON } from "@/jcli/config/project-json.ts";

Expand All @@ -19,13 +24,17 @@ describe("ProjectDotJSON", () => {
title?: string;
capabilities?: Array<ProjectCapability>;
instances?: Array<ProjectPluginInstance>;
imports?: ProjectImports;
scopes?: ProjectScopes;
} = {}) => {
return new ProjectDotJSON({
id,
name: args.name ?? "name",
title: args.title ?? "title",
capabilities: args.capabilities ?? [],
instances: args.instances ?? [],
imports: args.imports,
scopes: args.scopes,
});
};

Expand Down Expand Up @@ -264,5 +273,40 @@ describe("ProjectDotJSON", () => {
});
});
});

it("diff imports", () => {
const initialImports = undefined;
const updatedImports = { "lib": "v2" };
const updatedImportsTwo = undefined;
const one = build({ imports: initialImports });
const another = build({ imports: updatedImports });
const diff = one.diff(another);

assertObjectMatch(diff!, {
imports: updatedImports,
});

const anotherTwo = build({ imports: updatedImportsTwo });
const diffTwo = one.diff(anotherTwo);
assertEquals(diffTwo.imports, undefined);
});

it.only("diff scopes", () => {
const initialScopes = undefined;
const updatedScopes = { "std": { "foo": "foo" } };
const updatedScopesTwo = undefined;

const one = build({ scopes: initialScopes });
const another = build({ scopes: updatedScopes });
const diff = one.diff(another);

assertObjectMatch(diff!, {
scopes: updatedScopes,
});

const anotherTwo = build({ scopes: updatedScopesTwo });
const diffTwo = one.diff(anotherTwo);
assertEquals(diffTwo.scopes, undefined);
});
});
});
115 changes: 115 additions & 0 deletions test/subcommands/push/action/push-configuration_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ describe("configuration", () => {
capabilityNames: ["capability1"],
},
],
imports: {
"#functions": "./",
},
scopes: {
"https://deno.land/x/example/": {
"@std/foo": "./patched/mod.ts",
},
},
};

beforeEach(async () => {
Expand Down Expand Up @@ -91,7 +99,60 @@ describe("configuration", () => {
capabilityNames: ["capability1"],
},
],
imports: { "#functions": "./" },
scopes: {
"https://deno.land/x/example/": { "@std/foo": "./patched/mod.ts" },
},
});
});

it("updates db", async () => {
const db = await api.db.connect(PROJECT_DB_PATH);
const entries = db.queryEntries<{ data: string }>(
"SELECT data FROM configuration",
);

assertEquals(entries.length, 1);

const config = JSON.parse(entries[0].data);

assertObjectMatch(config, newConfiguration);

db.close();
});
});

describe("does not push importmap", () => {
const newConfiguration = {
name: "name",
title: "title",
capabilities: [],
instances: [],
};

beforeEach(async () => {
await api.fs.writeTextFile(
"project.json",
JSON.stringify(newConfiguration),
);

await action(options);
});

it("pushes to jet", () => {
const patches = api.jet.getConfigurationPatches(projectId);

assertNotEquals(patches, undefined);
assertEquals(patches!.length, 1);

assertObjectMatch(patches![0], {
name: "name",
title: "title",
capabilities: [],
instances: [],
});
assertEquals(patches![0].imports, undefined);
assertEquals(patches![0].scopes, undefined);
});

it("updates db", async () => {
Expand All @@ -105,6 +166,8 @@ describe("configuration", () => {
const config = JSON.parse(entries[0].data);

assertObjectMatch(config, newConfiguration);
assertEquals(config.imports, undefined);
assertEquals(config.scopes, undefined);

db.close();
});
Expand Down Expand Up @@ -163,4 +226,56 @@ describe("configuration", () => {
db.close();
});
});

describe("fails importmap", () => {
const invalidConfiguration = {
name: "name",
title: "title",
capabilities: [],
instances: [],
imports: {
"#functions": 1,
},
scopes: {
"https://deno.land/x/example/": {
"@std/foo": "./patched/mod.ts",
},
},
};

beforeEach(async () => {
await api.fs.writeTextFile(
"project.json",
JSON.stringify(invalidConfiguration),
);
});

it("rejects invalid configuration", async () => {
await assertRejects(async () => {
await action(options);
}, "Invalid configuration");

const patches = api.jet.getConfigurationPatches(projectId);

assertEquals(patches!.length, 0);

const db = await api.db.connect(PROJECT_DB_PATH);
const entries = db.queryEntries<{ data: string }>(
"SELECT data FROM configuration",
);

const config = JSON.parse(entries[0].data);

assertObjectMatch(config, {
name: "my_proj",
title: "my_proj",
capabilities: [],
instances: [],
});
assertEquals(config.imports, undefined);
assertEquals(config.scopes, undefined);

db.close();
});
});
});

0 comments on commit ad509a1

Please sign in to comment.