109 lines
4.0 KiB
JavaScript
109 lines
4.0 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { writeFile } from "node:fs/promises";
|
|
import process from "node:process";
|
|
import { bindingSchema } from "../bindings/index.js";
|
|
import {
|
|
compileCapabilityResourceRepository,
|
|
type ResolvedCapabilityResource,
|
|
} from "./assembly.js";
|
|
import { createGitCapabilityResolver } from "./git-resolver.js";
|
|
|
|
const usage = `usage: quixos-resource-compile --root DIRECTORY --kind interface|package
|
|
--repository URL --commit GIT_REV --checkout-root DIRECTORY
|
|
[--snapshot-map PATH] [--snapshot-only true] [--graph-out PATH] [--schema-out PATH]
|
|
|
|
Resolves a standalone resource's recursive dependency-lock graph, validates
|
|
its interface.qx or package.qx manifest, and emits the checked resource as JSON.`;
|
|
|
|
const parseArgs = (args: string[]) => {
|
|
const values = new Map<string, string>();
|
|
for (let index = 0; index < args.length; index += 2) {
|
|
const key = args[index];
|
|
const value = args[index + 1];
|
|
if (!key?.startsWith("--") || !value) throw new Error(usage);
|
|
if (!["--root", "--kind", "--repository", "--commit", "--checkout-root", "--snapshot-map", "--snapshot-only", "--graph-out", "--schema-out"].includes(key) || values.has(key)) throw new Error(usage);
|
|
values.set(key, value);
|
|
}
|
|
const rootDirectory = values.get("--root");
|
|
const kind = values.get("--kind");
|
|
const repository = values.get("--repository");
|
|
const commit = values.get("--commit")?.toLowerCase();
|
|
const checkoutRoot = values.get("--checkout-root");
|
|
if (!rootDirectory || !repository || !commit || !checkoutRoot ||
|
|
(kind !== "interface" && kind !== "package")) {
|
|
throw new Error(usage);
|
|
}
|
|
if (!/^([0-9a-f]{40}|[0-9a-f]{64})$/.test(commit)) {
|
|
throw new Error("--commit must be a full Git object ID");
|
|
}
|
|
if (values.has("--snapshot-only") && values.get("--snapshot-only") !== "true") throw new Error("--snapshot-only accepts true");
|
|
return {
|
|
rootDirectory,
|
|
kind,
|
|
repository,
|
|
commit,
|
|
checkoutRoot,
|
|
snapshotMap: values.get("--snapshot-map"),
|
|
snapshotOnly: values.get("--snapshot-only") === "true",
|
|
graphOut: values.get("--graph-out"),
|
|
schemaOut: values.get("--schema-out"),
|
|
} as const;
|
|
};
|
|
|
|
const graphEntry = (node: ResolvedCapabilityResource) => ({
|
|
key: node.key,
|
|
kind: node.kind,
|
|
source: node.source,
|
|
directory: node.directory,
|
|
resourceId: node.resource.kind === "interface"
|
|
? node.resource.revision.interfaceId
|
|
: node.resource.revision.packageId,
|
|
revisionId: node.resource.revision.revisionId,
|
|
dependencies: [...node.dependencies.entries()].map(([binding, dependency]) => ({
|
|
binding,
|
|
resourceKey: dependency.key,
|
|
})),
|
|
});
|
|
|
|
const main = async () => {
|
|
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
process.stdout.write(`${usage}\n`);
|
|
return;
|
|
}
|
|
const options = parseArgs(process.argv.slice(2));
|
|
const resolveResource = await createGitCapabilityResolver({
|
|
checkoutRoot: options.checkoutRoot,
|
|
snapshotMap: options.snapshotMap,
|
|
snapshotOnly: options.snapshotOnly,
|
|
});
|
|
const compiled = await compileCapabilityResourceRepository({
|
|
rootDirectory: options.rootDirectory,
|
|
kind: options.kind,
|
|
source: {
|
|
resolver: "git",
|
|
repository: options.repository,
|
|
commit: options.commit,
|
|
},
|
|
resolveResource,
|
|
});
|
|
if (options.graphOut) {
|
|
await writeFile(options.graphOut, `${JSON.stringify({
|
|
formatVersion: 1,
|
|
quixos: compiled.lock.quixos,
|
|
root: graphEntry(compiled.resources.find((node) =>
|
|
node.source.repository === options.repository &&
|
|
node.source.commit === options.commit &&
|
|
node.kind === options.kind)!),
|
|
resources: compiled.resources.map(graphEntry),
|
|
}, null, 2)}\n`);
|
|
}
|
|
if (options.schemaOut) await writeFile(options.schemaOut, `${JSON.stringify(bindingSchema(compiled), null, 2)}\n`);
|
|
process.stdout.write(`${JSON.stringify(compiled.resource, null, 2)}\n`);
|
|
};
|
|
|
|
main().catch((error: unknown) => {
|
|
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
|
|
process.exitCode = 1;
|
|
});
|