diff --git a/flake.nix b/flake.nix index d6695f8..c53d12c 100644 --- a/flake.nix +++ b/flake.nix @@ -108,6 +108,25 @@ EOF }; in { packages.default = quixos-protocol; + packages.inspector = (pkgs.callPackage ./yarn-project.nix { inherit nodejs; }) { + src = pkgs.lib.fileset.toSource { + root = ./.; + fileset = pkgs.lib.fileset.unions [ ./package.json ./yarn.lock ./.yarnrc.yml ./.yarn/plugins ./src ]; + }; + overrideAttrs = old: { + nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ pkgs.esbuild ]; + doCheck = false; + buildPhase = '' + esbuild src/capability-language/inspect-cli.ts --bundle --platform=node --target=node24 --format=esm --outfile=inspect.mjs + ''; + installPhase = '' + mkdir -p "$out/bin" "$out/lib" + cp inspect.mjs "$out/lib/inspect.mjs" + printf '#!${pkgs.runtimeShell}\nexec ${nodejs}/bin/node --max-old-space-size=128 %s/lib/inspect.mjs\n' "$out" > "$out/bin/quixos-qx-inspect" + chmod +x "$out/bin/quixos-qx-inspect" + ''; + }; + }; checks.default = quixos-protocol; devShells.default = pkgs.mkShell { packages = [ diff --git a/src/capability-language/inspect-cli.ts b/src/capability-language/inspect-cli.ts new file mode 100644 index 0000000..ffe9ded --- /dev/null +++ b/src/capability-language/inspect-cli.ts @@ -0,0 +1,21 @@ +#!/usr/bin/env node +// Data only: never load files, resolve repositories, or evaluate code. +import { parseQx } from "./source.js"; +import { parseQuixosLockDocument } from "../resource-lock/parser.js"; +let input = ""; +for await (const chunk of process.stdin) { + input += chunk; + if (Buffer.byteLength(input) > 6 * 1024 * 1024) throw new Error("Inspection input exceeds limit"); +} +const files: { path: string; source: string }[] = JSON.parse(input); +if (!Array.isArray(files) || files.length > 128) throw new Error("Too many source files"); +const result = files.map(({ path, source }) => { + if (typeof path !== "string" || typeof source !== "string" || source.length > 262144) + throw new Error("Invalid source input"); + if (path.endsWith(".qx")) { + const parsed = parseQx(source, path); + return { path, root: parsed.root, diagnostics: parsed.diagnostics }; + } + return { path, lock: parseQuixosLockDocument(source, path) }; +}); +process.stdout.write(JSON.stringify(result));