Files

138 lines
5.9 KiB
TypeScript

import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { capabilityId, type WorkspaceRevision } from "../../src/capability-model/index.js";
import {
compileCapabilityResourceSource,
compileCapabilitySource,
type CapabilityImportEnvironment,
} from "../../src/capability-language/index.js";
import type { InterfaceRevision, PackageRevision } from "../../src/capability-model/index.js";
export const fixtureId = {
workspace: capabilityId.workspace("workspace:todo"),
workspaceRevision: capabilityId.workspaceRevision("workspace:todo@1"),
project: capabilityId.atom("atom:project"),
person: capabilityId.atom("atom:person"),
namedV1: capabilityId.interfaceRevision("interface:named@1"),
ownedV1: capabilityId.interfaceRevision("interface:owned@1"),
summaryV1: capabilityId.interfaceRevision("interface:summary@1"),
namedGet: capabilityId.operation("operation:named:name:get"),
namedSet: capabilityId.operation("operation:named:name:set"),
ownerResolve: capabilityId.operation("operation:owned:owner:resolve"),
summaryGet: capabilityId.operation("operation:summary:summary:get"),
projectTitle: capabilityId.slot("slot:project:title"),
personName: capabilityId.slot("slot:person:name"),
projectOwner: capabilityId.edgeType("edge:project:owner"),
projectOwnerProjection: capabilityId.edgeProjection("projection:project-owner:owner"),
projectNamedConformance: {
atomId: capabilityId.atom("atom:project"),
interfaceRevisionId: capabilityId.interfaceRevision("interface:named@1"),
},
personNamedConformance: {
atomId: capabilityId.atom("atom:person"),
interfaceRevisionId: capabilityId.interfaceRevision("interface:named@1"),
},
projectOwnedConformance: {
atomId: capabilityId.atom("atom:project"),
interfaceRevisionId: capabilityId.interfaceRevision("interface:owned@1"),
},
projectSummaryConformance: {
atomId: capabilityId.atom("atom:project"),
interfaceRevisionId: capabilityId.interfaceRevision("interface:summary@1"),
},
todoRuntimeV1: capabilityId.packageRevision("package:todo-runtime@1"),
summaryGetExport: capabilityId.packageExport("export:todo-runtime:summary-get"),
createPersonExport: capabilityId.packageExport("export:todo-runtime:create-person"),
titlePort: capabilityId.dependencyPort("port:summary:title"),
namedPort: capabilityId.dependencyPort("port:summary:named"),
personPort: capabilityId.dependencyPort("port:summary:person"),
} as const;
export const capabilityFixturePath = resolve(process.cwd(), "test/fixtures/todo.capabilities.qx");
export const capabilityFixtureSource = readFileSync(capabilityFixturePath, "utf8");
const resourceSource = (name: string) => readFileSync(resolve(process.cwd(), "test/fixtures", name), "utf8");
export const capabilityResourceSources = {
named: resourceSource("named.interface.qx"),
owned: resourceSource("owned.interface.qx"),
summary: resourceSource("summary.interface.qx"),
todo: resourceSource("todo.package.qx"),
} as const;
const source = (repository: string, commit: string) => ({ repository, commit });
const interfaceRevision = (
resource: { kind: "interface"; revision: InterfaceRevision } | { kind: "package"; revision: PackageRevision },
) => {
if (resource.kind !== "interface") throw new Error("Expected interface fixture");
return resource.revision;
};
const packageRevision = (
resource: { kind: "interface"; revision: InterfaceRevision } | { kind: "package"; revision: PackageRevision },
) => {
if (resource.kind !== "package") throw new Error("Expected package fixture");
return resource.revision;
};
export const compileCapabilityFixture = (
overrides: Partial<{
workspace: string;
named: string;
owned: string;
summary: string;
todo: string;
}> = {},
) => {
const named = compileCapabilityResourceSource(overrides.named ?? capabilityResourceSources.named, {
source: source("https://repos.quixos.org/quixos-todo/interface-named.git", "2".repeat(40)),
fileName: "named.interface.qx",
});
if (!named.ok) return named;
const namedRevision = interfaceRevision(named.resource);
const namedEnvironment: CapabilityImportEnvironment = {
interfaces: new Map([["Named", namedRevision]]),
interfaceClosure: [namedRevision],
};
const owned = compileCapabilityResourceSource(overrides.owned ?? capabilityResourceSources.owned, {
source: source("https://repos.quixos.org/quixos-todo/interface-owned.git", "3".repeat(40)),
fileName: "owned.interface.qx",
environment: namedEnvironment,
});
if (!owned.ok) return owned;
const ownedRevision = interfaceRevision(owned.resource);
const summary = compileCapabilityResourceSource(overrides.summary ?? capabilityResourceSources.summary, {
source: source("https://repos.quixos.org/quixos-todo/interface-summary.git", "4".repeat(40)),
fileName: "summary.interface.qx",
});
if (!summary.ok) return summary;
const summaryRevision = interfaceRevision(summary.resource);
const todo = compileCapabilityResourceSource(overrides.todo ?? capabilityResourceSources.todo, {
source: source("https://repos.quixos.org/quixos-todo/package-todo-runtime.git", "5".repeat(40)),
fileName: "todo.package.qx",
environment: namedEnvironment,
});
if (!todo.ok) return todo;
const todoRevision = packageRevision(todo.resource);
return compileCapabilitySource(overrides.workspace ?? capabilityFixtureSource, capabilityFixturePath, {
interfaces: new Map([
["Named", namedRevision],
["Owned", ownedRevision],
["Summary", summaryRevision],
]),
packages: new Map([["TodoRuntime", todoRevision]]),
interfaceClosure: [namedRevision, ownedRevision, summaryRevision],
packageClosure: [todoRevision],
});
};
export const makeValidCapabilityWorkspace = (): WorkspaceRevision => {
const result = compileCapabilityFixture();
if (!result.ok) {
throw new Error(result.diagnostics.map((entry) => `${entry.phase}/${entry.code}: ${entry.message}`).join("\n"));
}
return structuredClone(result.workspace);
};