Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e2747066ca | |||
| 0c3c9c6ad8 | |||
| b3d31b37b3 | |||
| 6f3814587f | |||
| 1c09bf43c2 | |||
| 6657af7ca0 | |||
| e3080467c9 | |||
| e84b62f4d6 | |||
| 06c668b587 | |||
| 56fa26acc8 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos",
|
||||
"sourceCommit": "7fd5e15105cef21d2b1c3da860c53c5033f66256",
|
||||
"sourceCommit": "1de28b236de076d239752b77553f833dfbdb5b43",
|
||||
"sourcePath": "quixos-instance/quixos-nix-helpers",
|
||||
"exportName": "quixos-nix-helpers",
|
||||
"mirrorRemote": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
|
||||
// Resolve build dependencies from the package's locked node_modules, not from
|
||||
// the helper's own Nix-store location. This program runs only during the build.
|
||||
const require = createRequire(path.join(process.cwd(), "package.json"));
|
||||
const { build } = require("esbuild");
|
||||
const options = JSON.parse(process.argv[2]);
|
||||
const platform = new Map([
|
||||
["react", "/__quixos/platform/react/v18.mjs"],
|
||||
["react/jsx-runtime", "/__quixos/platform/react-jsx-runtime/v18.mjs"],
|
||||
["react/jsx-dev-runtime", "/__quixos/platform/react-jsx-dev-runtime/v18.mjs"],
|
||||
["@quixos/web-studio-react-runtime", "/__quixos/platform/web-studio-react-runtime/v1.mjs"],
|
||||
]);
|
||||
await build({
|
||||
...options,
|
||||
plugins: [
|
||||
{
|
||||
name: "quixos-browser-source",
|
||||
setup(api) {
|
||||
api.onResolve({ filter: /\?browser-source$/ }, async ({ path: specifier, resolveDir }) => {
|
||||
if (!specifier.startsWith("./") && !specifier.startsWith("../"))
|
||||
throw new Error("Browser source imports must name a relative compiled module");
|
||||
const resolved = await api.resolve(specifier.slice(0, -"?browser-source".length), {
|
||||
resolveDir,
|
||||
kind: "import-statement",
|
||||
});
|
||||
if (resolved.errors.length) return { errors: resolved.errors };
|
||||
return { path: resolved.path, namespace: "browser-source" };
|
||||
});
|
||||
api.onLoad({ filter: /.*/, namespace: "browser-source" }, async ({ path: entry }) => {
|
||||
const browser = await build({
|
||||
entryPoints: [entry],
|
||||
bundle: true,
|
||||
write: false,
|
||||
outfile: "component.mjs",
|
||||
format: "esm",
|
||||
platform: "browser",
|
||||
target: "es2022",
|
||||
metafile: true,
|
||||
plugins: [
|
||||
{
|
||||
name: "quixos-platform",
|
||||
setup(browserApi) {
|
||||
browserApi.onResolve({ filter: /.*/ }, ({ path: name }) =>
|
||||
platform.has(name) ? { path: platform.get(name), external: true } : undefined,
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const js = browser.outputFiles.find((file) => file.path.endsWith(".mjs"));
|
||||
if (!js) throw new Error("Browser source build produced no JavaScript");
|
||||
const css = browser.outputFiles.find((file) => file.path.endsWith(".css"));
|
||||
if (css && Object.values(browser.metafile.outputs).some((output) => output.exports?.includes("styles")))
|
||||
throw new Error("Use either imported CSS or an explicit styles export, not both");
|
||||
if (browser.outputFiles.some((file) => !file.path.endsWith(".mjs") && !file.path.endsWith(".css")))
|
||||
throw new Error("Browser assets must be embedded, not emitted as unserved files");
|
||||
const source = js.text + (css ? `\nexport const styles = ${JSON.stringify(css.text)};\n` : "");
|
||||
return {
|
||||
contents: `export default ${JSON.stringify(source)};`,
|
||||
loader: "js",
|
||||
watchFiles: Object.keys(browser.metafile.inputs),
|
||||
};
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
+32
-9
@@ -1,17 +1,40 @@
|
||||
import fs from "node:fs";
|
||||
import crypto from "node:crypto";
|
||||
const [schemaPath, packageRevisionId, bindingOutput, generatorPath, output] = process.argv.slice(2);
|
||||
if (!schemaPath || !packageRevisionId || !bindingOutput || !generatorPath || !output) throw new Error("Missing candidate check receipt inputs");
|
||||
const canonical = (value) => Array.isArray(value) ? value.map(canonical) : value && typeof value === "object"
|
||||
? Object.fromEntries(Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, entry]) => [key, canonical(entry)])) : value;
|
||||
const hash = (value) => `sha256:${crypto.createHash("sha256").update(JSON.stringify(canonical(value))).digest("hex")}`;
|
||||
if (!schemaPath || !packageRevisionId || !bindingOutput || !generatorPath || !output)
|
||||
throw new Error("Missing candidate check receipt inputs");
|
||||
const canonical = (value) =>
|
||||
Array.isArray(value)
|
||||
? value.map(canonical)
|
||||
: value && typeof value === "object"
|
||||
? Object.fromEntries(
|
||||
Object.entries(value)
|
||||
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
||||
.map(([key, entry]) => [key, canonical(entry)]),
|
||||
)
|
||||
: value;
|
||||
const hash = (value) =>
|
||||
`sha256:${crypto
|
||||
.createHash("sha256")
|
||||
.update(JSON.stringify(canonical(value)))
|
||||
.digest("hex")}`;
|
||||
const schema = JSON.parse(fs.readFileSync(schemaPath, "utf8"));
|
||||
if (!schema.packages.some((entry) => entry.revisionId === packageRevisionId)) throw new Error("Checked binding schema lacks the package");
|
||||
if (!schema.packages.some((entry) => entry.revisionId === packageRevisionId))
|
||||
throw new Error("Checked binding schema lacks the package");
|
||||
const generated = fs.readFileSync(bindingOutput, "utf8");
|
||||
if (generated !== fs.readFileSync(".qx-checked-bindings", "utf8")) throw new Error("Build replaced candidate-generated bindings; its check is not evidence for this candidate");
|
||||
if (generated !== fs.readFileSync(".qx-checked-bindings", "utf8"))
|
||||
throw new Error("Build replaced candidate-generated bindings; its check is not evidence for this candidate");
|
||||
const receipt = {
|
||||
schemaVersion: 1, packageRevisionId, success: true, bindingSchema: schema,
|
||||
bindingSchemaDigest: hash(schema), generatedDigest: hash(generated),
|
||||
checkerDigest: hash({ generatorPath, compiler: JSON.parse(fs.readFileSync("node_modules/typescript/package.json", "utf8")), lock: fs.readFileSync("yarn.lock", "utf8") }),
|
||||
schemaVersion: 1,
|
||||
packageRevisionId,
|
||||
success: true,
|
||||
bindingSchema: schema,
|
||||
bindingSchemaDigest: hash(schema),
|
||||
generatedDigest: hash(generated),
|
||||
checkerDigest: hash({
|
||||
generatorPath,
|
||||
compiler: JSON.parse(fs.readFileSync("node_modules/typescript/package.json", "utf8")),
|
||||
lock: fs.readFileSync("yarn.lock", "utf8"),
|
||||
}),
|
||||
};
|
||||
fs.writeFileSync(output, `${JSON.stringify(receipt, null, 2)}\n`, { flag: "wx" });
|
||||
|
||||
+478
-388
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user