138 lines
5.9 KiB
TypeScript
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);
|
|
};
|