Compare commits
14 Commits
8b2a224698
...
exported
| Author | SHA1 | Date | |
|---|---|---|---|
| e2747066ca | |||
| 0c3c9c6ad8 | |||
| b3d31b37b3 | |||
| 6f3814587f | |||
| 1c09bf43c2 | |||
| 6657af7ca0 | |||
| e3080467c9 | |||
| e84b62f4d6 | |||
| 06c668b587 | |||
| 56fa26acc8 | |||
| cf7945abb6 | |||
| 74b6ff2ace | |||
| 5861e91298 | |||
| d109410617 |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos",
|
"sourceRepo": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos",
|
||||||
"sourceCommit": "e25eee6ce4f13702b2454a9354bc79a29eb2e4a1",
|
"sourceCommit": "1de28b236de076d239752b77553f833dfbdb5b43",
|
||||||
"sourcePath": "quixos-instance/quixos-nix-helpers",
|
"sourcePath": "quixos-instance/quixos-nix-helpers",
|
||||||
"exportName": "quixos-nix-helpers",
|
"exportName": "quixos-nix-helpers",
|
||||||
"mirrorRemote": "https://gitea-external.egads.tutti.syntaxblitz.net/quixos/quixos-nix-helpers.git"
|
"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 fs from "node:fs";
|
||||||
import crypto from "node:crypto";
|
import crypto from "node:crypto";
|
||||||
const [schemaPath, packageRevisionId, bindingOutput, generatorPath, output] = process.argv.slice(2);
|
const [schemaPath, packageRevisionId, bindingOutput, generatorPath, output] = process.argv.slice(2);
|
||||||
if (!schemaPath || !packageRevisionId || !bindingOutput || !generatorPath || !output) throw new Error("Missing candidate check receipt inputs");
|
if (!schemaPath || !packageRevisionId || !bindingOutput || !generatorPath || !output)
|
||||||
const canonical = (value) => Array.isArray(value) ? value.map(canonical) : value && typeof value === "object"
|
throw new Error("Missing candidate check receipt inputs");
|
||||||
? Object.fromEntries(Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, entry]) => [key, canonical(entry)])) : value;
|
const canonical = (value) =>
|
||||||
const hash = (value) => `sha256:${crypto.createHash("sha256").update(JSON.stringify(canonical(value))).digest("hex")}`;
|
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"));
|
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");
|
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 = {
|
const receipt = {
|
||||||
schemaVersion: 1, packageRevisionId, success: true, bindingSchema: schema,
|
schemaVersion: 1,
|
||||||
bindingSchemaDigest: hash(schema), generatedDigest: hash(generated),
|
packageRevisionId,
|
||||||
checkerDigest: hash({ generatorPath, compiler: JSON.parse(fs.readFileSync("node_modules/typescript/package.json", "utf8")), lock: fs.readFileSync("yarn.lock", "utf8") }),
|
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" });
|
fs.writeFileSync(output, `${JSON.stringify(receipt, null, 2)}\n`, { flag: "wx" });
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
# The caller has compiled this package and its exact recursive candidate graph.
|
|
||||||
# No credentials, mutable references, or workspace-wide unrelated schema enter
|
|
||||||
# the package derivation. Ordinary #server builds are not promotion evidence.
|
|
||||||
{ source, schema, generator, packageRevisionId, system ? builtins.currentSystem }:
|
|
||||||
let
|
|
||||||
package = builtins.getFlake ("path:" + source);
|
|
||||||
checked = package.quixosPackages.${system}.checkedServer or
|
|
||||||
(throw "Package ${packageRevisionId} lacks checkedServer. Upgrade its Nix helper and adopt generated implementation bindings before cutover.");
|
|
||||||
in checked {
|
|
||||||
inherit packageRevisionId;
|
|
||||||
schema = builtins.path { path = /. + schema; name = "candidate-package-bindings.json"; };
|
|
||||||
generator = builtins.storePath generator;
|
|
||||||
}
|
|
||||||
+224
-134
@@ -19,23 +19,25 @@ let
|
|||||||
schemaMainPathDefault = "dist/quixos-package-schema.js";
|
schemaMainPathDefault = "dist/quixos-package-schema.js";
|
||||||
schemaPackageName = schemaPackageJson.name or "schema";
|
schemaPackageName = schemaPackageJson.name or "schema";
|
||||||
selfSchemaName =
|
selfSchemaName =
|
||||||
if pkgs.lib.hasInfix "/" schemaPackageName
|
if pkgs.lib.hasInfix "/" schemaPackageName then
|
||||||
then pkgs.lib.last (pkgs.lib.splitString "/" schemaPackageName)
|
pkgs.lib.last (pkgs.lib.splitString "/" schemaPackageName)
|
||||||
else schemaPackageName;
|
else
|
||||||
|
schemaPackageName;
|
||||||
|
|
||||||
flakeText =
|
flakeText = builtins.replaceStrings [ "\n" "\r" "\t" ] [ " " " " " " ] (
|
||||||
builtins.replaceStrings
|
builtins.readFile "${flakeRoot}/flake.nix"
|
||||||
[ "\n" "\r" "\t" ]
|
);
|
||||||
[ " " " " " " ]
|
|
||||||
(builtins.readFile "${flakeRoot}/flake.nix");
|
|
||||||
|
|
||||||
getInputUrl = inputName:
|
getInputUrl =
|
||||||
|
inputName:
|
||||||
let
|
let
|
||||||
pattern1 = ".*" + inputName + "[[:space:]]*\\.url[[:space:]]*=[[:space:]]*\"([^\"]+)\".*";
|
pattern1 = ".*" + inputName + "[[:space:]]*\\.url[[:space:]]*=[[:space:]]*\"([^\"]+)\".*";
|
||||||
pattern2 = ".*" + inputName + "[[:space:]]*=[[:space:]]*\\{[^}]*url[[:space:]]*=[[:space:]]*\"([^\"]+)\".*";
|
pattern2 =
|
||||||
|
".*" + inputName + "[[:space:]]*=[[:space:]]*\\{[^}]*url[[:space:]]*=[[:space:]]*\"([^\"]+)\".*";
|
||||||
match1 = builtins.match pattern1 flakeText;
|
match1 = builtins.match pattern1 flakeText;
|
||||||
match2 = if match1 != null then match1 else builtins.match pattern2 flakeText;
|
match2 = if match1 != null then match1 else builtins.match pattern2 flakeText;
|
||||||
in if match2 == null then null else builtins.elemAt match2 0;
|
in
|
||||||
|
if match2 == null then null else builtins.elemAt match2 0;
|
||||||
|
|
||||||
schemaBase =
|
schemaBase =
|
||||||
(pkgs.callPackage "${schemaDir}/yarn-project.nix" {
|
(pkgs.callPackage "${schemaDir}/yarn-project.nix" {
|
||||||
@@ -65,51 +67,44 @@ let
|
|||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
|
|
||||||
schemaInputs =
|
schemaInputs = pkgs.lib.filterAttrs (name: _: pkgs.lib.hasPrefix schemaPrefix name) inputs;
|
||||||
pkgs.lib.filterAttrs (name: _: pkgs.lib.hasPrefix schemaPrefix name) inputs;
|
|
||||||
|
|
||||||
decodeSchemaInputName = encodedName:
|
decodeSchemaInputName = encodedName: builtins.replaceStrings [ "__" ] [ "." ] encodedName;
|
||||||
builtins.replaceStrings [ "__" ] [ "." ] encodedName;
|
|
||||||
|
|
||||||
schemaPackagesFromInputs =
|
schemaPackagesFromInputs = pkgs.lib.mapAttrs' (
|
||||||
pkgs.lib.mapAttrs'
|
name: flake:
|
||||||
(name: flake:
|
|
||||||
let
|
let
|
||||||
schemaName =
|
schemaName = decodeSchemaInputName (pkgs.lib.removePrefix schemaPrefix name);
|
||||||
decodeSchemaInputName (pkgs.lib.removePrefix schemaPrefix name);
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
name = schemaName;
|
name = schemaName;
|
||||||
value = flake.packages.${system}.schema;
|
value = flake.packages.${system}.schema;
|
||||||
})
|
}
|
||||||
schemaInputs;
|
) schemaInputs;
|
||||||
|
|
||||||
schemaPackages = schemaPackagesFromInputs // { "${selfSchemaName}" = schema; };
|
schemaPackages = schemaPackagesFromInputs // {
|
||||||
|
"${selfSchemaName}" = schema;
|
||||||
|
};
|
||||||
|
|
||||||
schemaMetaByName =
|
schemaMetaByName = pkgs.lib.mapAttrs' (
|
||||||
pkgs.lib.mapAttrs'
|
name: flake:
|
||||||
(name: flake:
|
|
||||||
let
|
let
|
||||||
schemaName =
|
schemaName = decodeSchemaInputName (pkgs.lib.removePrefix schemaPrefix name);
|
||||||
decodeSchemaInputName (pkgs.lib.removePrefix schemaPrefix name);
|
|
||||||
sourceInfo = if flake ? sourceInfo then flake.sourceInfo else { };
|
sourceInfo = if flake ? sourceInfo then flake.sourceInfo else { };
|
||||||
sourceRev = sourceInfo.rev or null;
|
sourceRev = sourceInfo.rev or null;
|
||||||
inputUrl = getInputUrl name;
|
inputUrl = getInputUrl name;
|
||||||
urlBase =
|
urlBase = if inputUrl == null then null else builtins.head (pkgs.lib.splitString "?" inputUrl);
|
||||||
if inputUrl == null
|
|
||||||
then null
|
|
||||||
else builtins.head (pkgs.lib.splitString "?" inputUrl);
|
|
||||||
isDisallowed =
|
isDisallowed =
|
||||||
inputUrl == null
|
inputUrl == null
|
||||||
|| pkgs.lib.hasPrefix "path:" inputUrl
|
|| pkgs.lib.hasPrefix "path:" inputUrl
|
||||||
|| pkgs.lib.hasPrefix "file:" inputUrl
|
|| pkgs.lib.hasPrefix "file:" inputUrl
|
||||||
|| pkgs.lib.hasPrefix "git+file:" inputUrl;
|
|| pkgs.lib.hasPrefix "git+file:" inputUrl;
|
||||||
flakeRef =
|
flakeRef =
|
||||||
if isDisallowed || sourceRev == null || urlBase == null
|
if isDisallowed || sourceRev == null || urlBase == null then
|
||||||
then null
|
null
|
||||||
else urlBase + "?rev=" + sourceRev;
|
else
|
||||||
meta =
|
urlBase + "?rev=" + sourceRev;
|
||||||
{
|
meta = {
|
||||||
name = "@quixos-package-schemas/${schemaName}";
|
name = "@quixos-package-schemas/${schemaName}";
|
||||||
type = sourceInfo.type or null;
|
type = sourceInfo.type or null;
|
||||||
url = inputUrl;
|
url = inputUrl;
|
||||||
@@ -117,16 +112,16 @@ let
|
|||||||
flakeRef = flakeRef;
|
flakeRef = flakeRef;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
if flakeRef == null
|
if flakeRef == null then
|
||||||
then throw "Schema input ${schemaName} must be a git flake with url+rev"
|
throw "Schema input ${schemaName} must be a git flake with url+rev"
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
name = schemaName;
|
name = schemaName;
|
||||||
value = meta;
|
value = meta;
|
||||||
})
|
}
|
||||||
schemaInputs;
|
) schemaInputs;
|
||||||
|
|
||||||
schemaMetaJsonByName =
|
schemaMetaJsonByName = pkgs.lib.mapAttrs (_: meta: builtins.toJSON meta) schemaMetaByName;
|
||||||
pkgs.lib.mapAttrs (_: meta: builtins.toJSON meta) schemaMetaByName;
|
|
||||||
|
|
||||||
schemaExtensionsBlock = pkgs.lib.concatStringsSep "\n" (
|
schemaExtensionsBlock = pkgs.lib.concatStringsSep "\n" (
|
||||||
[
|
[
|
||||||
@@ -151,12 +146,11 @@ let
|
|||||||
);
|
);
|
||||||
|
|
||||||
schemaInstallCommands = pkgs.lib.concatStringsSep "\n" (
|
schemaInstallCommands = pkgs.lib.concatStringsSep "\n" (
|
||||||
pkgs.lib.mapAttrsToList (name: drv:
|
pkgs.lib.mapAttrsToList (
|
||||||
|
name: drv:
|
||||||
let
|
let
|
||||||
metaJson =
|
metaJson =
|
||||||
if pkgs.lib.hasAttr name schemaMetaJsonByName
|
if pkgs.lib.hasAttr name schemaMetaJsonByName then schemaMetaJsonByName.${name} else null;
|
||||||
then schemaMetaJsonByName.${name}
|
|
||||||
else null;
|
|
||||||
in
|
in
|
||||||
''
|
''
|
||||||
schema_pkg="$(ls -d ${drv}/libexec/* | head -n1)"
|
schema_pkg="$(ls -d ${drv}/libexec/* | head -n1)"
|
||||||
@@ -166,8 +160,8 @@ let
|
|||||||
chmod -R u+w "$dest"
|
chmod -R u+w "$dest"
|
||||||
''
|
''
|
||||||
+ (
|
+ (
|
||||||
if metaJson != null
|
if metaJson != null then
|
||||||
then ''
|
''
|
||||||
schema_main="${schemaMainPathDefault}"
|
schema_main="${schemaMainPathDefault}"
|
||||||
if [ -f "$dest/$schema_main" ]; then
|
if [ -f "$dest/$schema_main" ]; then
|
||||||
block_tmp="$(mktemp -p "$dest")"
|
block_tmp="$(mktemp -p "$dest")"
|
||||||
@@ -205,7 +199,8 @@ EOF
|
|||||||
rm -f "$block_tmp" "$tmp_out"
|
rm -f "$block_tmp" "$tmp_out"
|
||||||
fi
|
fi
|
||||||
''
|
''
|
||||||
else ""
|
else
|
||||||
|
""
|
||||||
)
|
)
|
||||||
) schemaPackages
|
) schemaPackages
|
||||||
);
|
);
|
||||||
@@ -240,7 +235,8 @@ EOF
|
|||||||
schemaInstallCommands
|
schemaInstallCommands
|
||||||
updateYarnrcScript
|
updateYarnrcScript
|
||||||
schemaExtensionsBlockEscaped
|
schemaExtensionsBlockEscaped
|
||||||
selfSchemaName;
|
selfSchemaName
|
||||||
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
mkTsPackageServer =
|
mkTsPackageServer =
|
||||||
@@ -265,9 +261,10 @@ EOF
|
|||||||
nodejs' = if nodejs != null then nodejs else pkgs.nodejs_24;
|
nodejs' = if nodejs != null then nodejs else pkgs.nodejs_24;
|
||||||
git' = if git != null then git else pkgs.git;
|
git' = if git != null then git else pkgs.git;
|
||||||
templatePreparePackages' =
|
templatePreparePackages' =
|
||||||
if templatePreparePackages != null
|
if templatePreparePackages != null then
|
||||||
then templatePreparePackages
|
templatePreparePackages
|
||||||
else [
|
else
|
||||||
|
[
|
||||||
pkgs.findutils
|
pkgs.findutils
|
||||||
git'
|
git'
|
||||||
pkgs.gnused
|
pkgs.gnused
|
||||||
@@ -291,28 +288,33 @@ EOF
|
|||||||
runtimeBinPath = pkgs.lib.makeBinPath extraRuntimePackages;
|
runtimeBinPath = pkgs.lib.makeBinPath extraRuntimePackages;
|
||||||
runtimeLibPath = pkgs.lib.makeLibraryPath extraRuntimePackages;
|
runtimeLibPath = pkgs.lib.makeLibraryPath extraRuntimePackages;
|
||||||
runtimeWrap =
|
runtimeWrap =
|
||||||
if extraRuntimePackages == [ ]
|
if extraRuntimePackages == [ ] then
|
||||||
then ""
|
""
|
||||||
else ''
|
else
|
||||||
|
''
|
||||||
wrapProgram "$out/bin/${serverBin}" \
|
wrapProgram "$out/bin/${serverBin}" \
|
||||||
--prefix PATH : ${runtimeBinPath} \
|
--prefix PATH : ${runtimeBinPath} \
|
||||||
--prefix LD_LIBRARY_PATH : ${runtimeLibPath}
|
--prefix LD_LIBRARY_PATH : ${runtimeLibPath}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
server = base.overrideAttrs (old:
|
server = base.overrideAttrs (
|
||||||
|
old:
|
||||||
let
|
let
|
||||||
extraAttrs = serverOverrides old;
|
extraAttrs = serverOverrides old;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
buildInputs = (old.buildInputs or [ ]) ++ extraBuildInputs;
|
buildInputs = (old.buildInputs or [ ]) ++ extraBuildInputs;
|
||||||
|
|
||||||
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [
|
nativeBuildInputs =
|
||||||
|
(old.nativeBuildInputs or [ ])
|
||||||
|
++ [
|
||||||
pkgs.python3
|
pkgs.python3
|
||||||
pkgs.gnumake
|
pkgs.gnumake
|
||||||
pkgs.gcc
|
pkgs.gcc
|
||||||
pkgs.pkg-config
|
pkgs.pkg-config
|
||||||
pkgs.makeWrapper
|
pkgs.makeWrapper
|
||||||
] ++ extraNativeBuildInputs;
|
]
|
||||||
|
++ extraNativeBuildInputs;
|
||||||
|
|
||||||
# node-gyp will look at these
|
# node-gyp will look at these
|
||||||
PYTHON = "${pkgs.python3}/bin/python3";
|
PYTHON = "${pkgs.python3}/bin/python3";
|
||||||
@@ -326,13 +328,14 @@ EOF
|
|||||||
buildPhase =
|
buildPhase =
|
||||||
(old.buildPhase or "")
|
(old.buildPhase or "")
|
||||||
+ (
|
+ (
|
||||||
if buildCommand != null
|
if buildCommand != null then
|
||||||
then ''
|
''
|
||||||
runHook preBuildQuixos
|
runHook preBuildQuixos
|
||||||
${buildCommand}
|
${buildCommand}
|
||||||
runHook postBuildQuixos
|
runHook postBuildQuixos
|
||||||
''
|
''
|
||||||
else ""
|
else
|
||||||
|
""
|
||||||
);
|
);
|
||||||
|
|
||||||
postFixup = (old.postFixup or "") + runtimeWrap;
|
postFixup = (old.postFixup or "") + runtimeWrap;
|
||||||
@@ -342,7 +345,8 @@ EOF
|
|||||||
mkdir -p "$pkg_root/quixos-package-schemas"
|
mkdir -p "$pkg_root/quixos-package-schemas"
|
||||||
(cd "$pkg_root" && ${schemaSupport.schemaInstallCommands})
|
(cd "$pkg_root" && ${schemaSupport.schemaInstallCommands})
|
||||||
'';
|
'';
|
||||||
} // extraAttrs
|
}
|
||||||
|
// extraAttrs
|
||||||
);
|
);
|
||||||
|
|
||||||
check = server.overrideAttrs (old: {
|
check = server.overrideAttrs (old: {
|
||||||
@@ -360,7 +364,12 @@ EOF
|
|||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
inherit server check packageName serverBin;
|
inherit
|
||||||
|
server
|
||||||
|
check
|
||||||
|
packageName
|
||||||
|
serverBin
|
||||||
|
;
|
||||||
|
|
||||||
devShells = {
|
devShells = {
|
||||||
"quixos-prepare" = prepareShell;
|
"quixos-prepare" = prepareShell;
|
||||||
@@ -392,13 +401,18 @@ EOF
|
|||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
|
||||||
schemaSupport = mkSchemaSupport {
|
schemaSupport = mkSchemaSupport {
|
||||||
inherit pkgs inputs system schemaDir schemaPrefix self flakeRoot;
|
inherit
|
||||||
|
pkgs
|
||||||
|
inputs
|
||||||
|
system
|
||||||
|
schemaDir
|
||||||
|
schemaPrefix
|
||||||
|
self
|
||||||
|
flakeRoot
|
||||||
|
;
|
||||||
};
|
};
|
||||||
|
|
||||||
normalizeList = value:
|
normalizeList = value: if builtins.isFunction value then value pkgs else value;
|
||||||
if builtins.isFunction value
|
|
||||||
then value pkgs
|
|
||||||
else value;
|
|
||||||
|
|
||||||
serverResult = serverBuilder {
|
serverResult = serverBuilder {
|
||||||
inherit pkgs schemaSupport;
|
inherit pkgs schemaSupport;
|
||||||
@@ -408,26 +422,28 @@ EOF
|
|||||||
};
|
};
|
||||||
|
|
||||||
combinedName = pkgs.lib.strings.sanitizeDerivationName (
|
combinedName = pkgs.lib.strings.sanitizeDerivationName (
|
||||||
if packageName != null
|
if packageName != null then
|
||||||
then packageName
|
packageName
|
||||||
else if serverResult ? packageName
|
else if serverResult ? packageName then
|
||||||
then serverResult.packageName
|
serverResult.packageName
|
||||||
else "quixos-package"
|
else
|
||||||
|
"quixos-package"
|
||||||
);
|
);
|
||||||
|
|
||||||
packageServer = serverResult.server;
|
packageServer = serverResult.server;
|
||||||
packageServerCheck = if serverResult ? check then serverResult.check else null;
|
packageServerCheck = if serverResult ? check then serverResult.check else null;
|
||||||
|
|
||||||
appProgramFinal =
|
appProgramFinal =
|
||||||
if appProgram != null
|
if appProgram != null then
|
||||||
then appProgram
|
appProgram
|
||||||
else if serverResult ? appProgram
|
else if serverResult ? appProgram then
|
||||||
then serverResult.appProgram
|
serverResult.appProgram
|
||||||
else "${packageServer}/bin/${serverResult.serverBin or "server"}";
|
else
|
||||||
|
"${packageServer}/bin/${serverResult.serverBin or "server"}";
|
||||||
|
|
||||||
devShellHookBase =
|
devShellHookBase =
|
||||||
if enableYarnrcHook
|
if enableYarnrcHook then
|
||||||
then ''
|
''
|
||||||
find_schema_root() {
|
find_schema_root() {
|
||||||
dir="$PWD"
|
dir="$PWD"
|
||||||
while [ "$dir" != "/" ]; do
|
while [ "$dir" != "/" ]; do
|
||||||
@@ -455,21 +471,26 @@ EOF
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
''
|
''
|
||||||
else "";
|
else
|
||||||
|
"";
|
||||||
|
|
||||||
devShellHook = devShellHookBase + extraDevShellHook;
|
devShellHook = devShellHookBase + extraDevShellHook;
|
||||||
|
|
||||||
devShellPackages = normalizeList extraDevShellPackages;
|
devShellPackages = normalizeList extraDevShellPackages;
|
||||||
|
|
||||||
checks =
|
checks = {
|
||||||
{ schema = schemaSupport.schemaCheck; }
|
schema = schemaSupport.schemaCheck;
|
||||||
|
}
|
||||||
// (if packageServerCheck != null then { default = packageServerCheck; } else { });
|
// (if packageServerCheck != null then { default = packageServerCheck; } else { });
|
||||||
extraDevShells = if serverResult ? devShells then serverResult.devShells else { };
|
extraDevShells = if serverResult ? devShells then serverResult.devShells else { };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages.default = pkgs.symlinkJoin {
|
packages.default = pkgs.symlinkJoin {
|
||||||
name = combinedName;
|
name = combinedName;
|
||||||
paths = [ packageServer schemaSupport.schema ];
|
paths = [
|
||||||
|
packageServer
|
||||||
|
schemaSupport.schema
|
||||||
|
];
|
||||||
};
|
};
|
||||||
packages.server = packageServer;
|
packages.server = packageServer;
|
||||||
packages.schema = schemaSupport.schema;
|
packages.schema = schemaSupport.schema;
|
||||||
@@ -512,10 +533,19 @@ EOF
|
|||||||
|
|
||||||
# Language-neutral, offline schema compilation. Snapshot directories must be
|
# Language-neutral, offline schema compilation. Snapshot directories must be
|
||||||
# fixed Nix inputs matching the resource lock's complete dependency closure.
|
# fixed Nix inputs matching the resource lock's complete dependency closure.
|
||||||
mkQxBindingSchema = { pkgs, protocol, src, repository, commit, resources ? [ ] }:
|
mkQxBindingSchema =
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
protocol,
|
||||||
|
src,
|
||||||
|
repository,
|
||||||
|
commit,
|
||||||
|
resources ? [ ],
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
snapshots = pkgs.writeText "qx-binding-snapshots.json" (builtins.toJSON { inherit resources; });
|
snapshots = pkgs.writeText "qx-binding-snapshots.json" (builtins.toJSON { inherit resources; });
|
||||||
in pkgs.runCommand "qx-binding-schema.json" { } ''
|
in
|
||||||
|
pkgs.runCommand "qx-binding-schema.json" { } ''
|
||||||
${protocol}/bin/quixos-resource-compile \
|
${protocol}/bin/quixos-resource-compile \
|
||||||
--root ${src} --kind package \
|
--root ${src} --kind package \
|
||||||
--repository ${pkgs.lib.escapeShellArg repository} \
|
--repository ${pkgs.lib.escapeShellArg repository} \
|
||||||
@@ -539,7 +569,6 @@ EOF
|
|||||||
# An exact, compiler-produced BindingSchema JSON artifact and a backend.
|
# An exact, compiler-produced BindingSchema JSON artifact and a backend.
|
||||||
# Other language helpers can consume the same schema with their own generator/runtime.
|
# Other language helpers can consume the same schema with their own generator/runtime.
|
||||||
bindings ? null,
|
bindings ? null,
|
||||||
bindingOptions ? { },
|
|
||||||
# A dedicated entrypoint calling SDK serveMigration; never start the
|
# A dedicated entrypoint calling SDK serveMigration; never start the
|
||||||
# normal package server in the isolated migration execution boundary.
|
# normal package server in the isolated migration execution boundary.
|
||||||
migrationEntrypoint ? null,
|
migrationEntrypoint ? null,
|
||||||
@@ -552,23 +581,21 @@ EOF
|
|||||||
flake-utils.lib.eachDefaultSystem (
|
flake-utils.lib.eachDefaultSystem (
|
||||||
system:
|
system:
|
||||||
let
|
let
|
||||||
outputsFor = candidateBindings:
|
outputsFor =
|
||||||
|
candidateBindings:
|
||||||
let
|
let
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
lib = pkgs.lib;
|
lib = pkgs.lib;
|
||||||
nodejs = pkgs.${nodejsAttr};
|
nodejs = pkgs.${nodejsAttr};
|
||||||
|
|
||||||
callOption = value:
|
callOption =
|
||||||
if builtins.isFunction value
|
value: if builtins.isFunction value then value { inherit inputs pkgs system; } else value;
|
||||||
then value { inherit inputs pkgs system; }
|
|
||||||
else value;
|
|
||||||
|
|
||||||
packageJson = builtins.fromJSON (builtins.readFile "${packageRoot}/package.json");
|
packageJson = builtins.fromJSON (builtins.readFile "${packageRoot}/package.json");
|
||||||
packageNameFinal = if packageName != null then packageName else packageJson.name or "quixos-package";
|
packageNameFinal =
|
||||||
|
if packageName != null then packageName else packageJson.name or "quixos-package";
|
||||||
promptNameFinal =
|
promptNameFinal =
|
||||||
if promptName != null
|
if promptName != null then promptName else lib.strings.sanitizeDerivationName packageNameFinal;
|
||||||
then promptName
|
|
||||||
else lib.strings.sanitizeDerivationName packageNameFinal;
|
|
||||||
|
|
||||||
sourcePackage = mkCaminoSourcePackage {
|
sourcePackage = mkCaminoSourcePackage {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
@@ -576,31 +603,52 @@ EOF
|
|||||||
name = sourceName;
|
name = sourceName;
|
||||||
};
|
};
|
||||||
|
|
||||||
exportsFor = attrs:
|
exportsFor =
|
||||||
|
attrs:
|
||||||
lib.concatStringsSep "\n" (
|
lib.concatStringsSep "\n" (
|
||||||
lib.mapAttrsToList
|
lib.mapAttrsToList (name: value: "export ${name}=${lib.escapeShellArg (toString value)}") attrs
|
||||||
(name: value: "export ${name}=${lib.escapeShellArg (toString value)}")
|
|
||||||
attrs
|
|
||||||
);
|
);
|
||||||
|
|
||||||
bindingConfig = if candidateBindings != null then candidateBindings
|
bindingConfig =
|
||||||
else if bindings == null then null else callOption bindings;
|
if candidateBindings != null then
|
||||||
bindingSchema = if bindingConfig == null then null else bindingConfig.schema or (mkQxBindingSchema {
|
candidateBindings
|
||||||
|
else if bindings == null then
|
||||||
|
null
|
||||||
|
else
|
||||||
|
callOption bindings;
|
||||||
|
bindingSchema =
|
||||||
|
if bindingConfig == null then
|
||||||
|
null
|
||||||
|
else
|
||||||
|
bindingConfig.schema or (mkQxBindingSchema {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
protocol = bindingConfig.generator;
|
protocol = bindingConfig.generator;
|
||||||
src = packageRoot;
|
src = packageRoot;
|
||||||
inherit (bindingConfig) repository commit;
|
inherit (bindingConfig) repository commit;
|
||||||
resources = bindingConfig.resources or [ ];
|
resources = bindingConfig.resources or [ ];
|
||||||
});
|
});
|
||||||
bindingOutput = if bindingConfig == null then "src/gen/qx.ts" else bindingConfig.output or "src/gen/qx.ts";
|
bindingOutput =
|
||||||
bindingOptionsFile = if bindingConfig == null then null else
|
if bindingConfig == null then "src/gen/qx.ts" else bindingConfig.output or "src/gen/qx.ts";
|
||||||
pkgs.writeText "qx-typescript-options.json" (builtins.toJSON (bindingConfig.options or bindingOptions));
|
authoringCheck = builtins.fromJSON (builtins.readFile "${packageRoot}/quixos.check.json");
|
||||||
bindingCommand = if bindingConfig == null then "" else ''
|
bindingOptionsFile =
|
||||||
|
if bindingConfig == null then
|
||||||
|
null
|
||||||
|
else
|
||||||
|
pkgs.writeText "qx-typescript-options.json" (builtins.toJSON (authoringCheck.options or { }));
|
||||||
|
bindingCommand =
|
||||||
|
if bindingConfig == null then
|
||||||
|
""
|
||||||
|
else
|
||||||
|
''
|
||||||
mkdir -p ${lib.escapeShellArg (dirOf bindingOutput)}
|
mkdir -p ${lib.escapeShellArg (dirOf bindingOutput)}
|
||||||
${bindingConfig.generator}/bin/quixos-codegen-ts \
|
${bindingConfig.generator}/bin/quixos-codegen-ts \
|
||||||
${lib.escapeShellArg (toString bindingSchema)} \
|
${lib.escapeShellArg (toString bindingSchema)} \
|
||||||
${lib.escapeShellArg bindingConfig.packageRevisionId} \
|
${lib.escapeShellArg bindingConfig.packageRevisionId} \
|
||||||
${lib.escapeShellArg bindingOutput} ${bindingOptionsFile}
|
${lib.escapeShellArg bindingOutput} ${bindingOptionsFile}
|
||||||
|
${lib.optionalString (installServer != null && descriptorPath != null) ''
|
||||||
|
${bindingConfig.generator}/bin/quixos-qx package-descriptor ${lib.escapeShellArg (toString bindingSchema)} \
|
||||||
|
${lib.escapeShellArg bindingConfig.packageRevisionId} > ${lib.escapeShellArg descriptorPath}
|
||||||
|
''}
|
||||||
'';
|
'';
|
||||||
generateBindings = pkgs.writeShellApplication {
|
generateBindings = pkgs.writeShellApplication {
|
||||||
name = "qx-generate-bindings";
|
name = "qx-generate-bindings";
|
||||||
@@ -613,19 +661,38 @@ EOF
|
|||||||
bundleTarget = bundleConfig.target or "node24";
|
bundleTarget = bundleConfig.target or "node24";
|
||||||
bundleFormat = bundleConfig.format or "esm";
|
bundleFormat = bundleConfig.format or "esm";
|
||||||
bundleBanner = bundleConfig.banner or nodeRequireBanner;
|
bundleBanner = bundleConfig.banner or nodeRequireBanner;
|
||||||
bundleAliases = bundleConfig.aliases or {
|
bundleAliases =
|
||||||
"@automerge/automerge" = "./node_modules/@automerge/automerge/dist/mjs/entrypoints/fullfat_base64.js";
|
bundleConfig.aliases or {
|
||||||
|
"@automerge/automerge" =
|
||||||
|
"./node_modules/@automerge/automerge/dist/mjs/entrypoints/fullfat_base64.js";
|
||||||
};
|
};
|
||||||
bundleAliasArgs = lib.concatStringsSep " " (
|
bundleAliasArgs = lib.concatStringsSep " " (
|
||||||
lib.mapAttrsToList
|
lib.mapAttrsToList (from: to: "--alias:${from}=${lib.escapeShellArg to}") bundleAliases
|
||||||
(from: to: "--alias:${from}=${lib.escapeShellArg to}")
|
|
||||||
bundleAliases
|
|
||||||
);
|
);
|
||||||
nodeRequireBanner = "import { createRequire } from 'module';const require = createRequire(import.meta.url);";
|
nodeRequireBanner = "import { createRequire } from 'module';const require = createRequire(import.meta.url);";
|
||||||
bundleCommand =
|
bundleCommand =
|
||||||
if bundle == null
|
if bundle == null then
|
||||||
then ""
|
""
|
||||||
else ''
|
else if bundleConfig.browserSources or false then
|
||||||
|
''
|
||||||
|
${nodejs}/bin/node ${./browser-source.mjs} ${
|
||||||
|
lib.escapeShellArg (
|
||||||
|
builtins.toJSON {
|
||||||
|
entryPoints = [ bundleConfig.entry ];
|
||||||
|
bundle = true;
|
||||||
|
platform = bundlePlatform;
|
||||||
|
target = bundleTarget;
|
||||||
|
format = bundleFormat;
|
||||||
|
alias = bundleAliases;
|
||||||
|
preserveSymlinks = bundleConfig.preserveSymlinks or true;
|
||||||
|
banner.js = bundleBanner;
|
||||||
|
outfile = bundleOutfile;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
''
|
||||||
|
else
|
||||||
|
''
|
||||||
esbuild ${lib.escapeShellArg bundleConfig.entry} \
|
esbuild ${lib.escapeShellArg bundleConfig.entry} \
|
||||||
--bundle \
|
--bundle \
|
||||||
--platform=${bundlePlatform} \
|
--platform=${bundlePlatform} \
|
||||||
@@ -644,18 +711,21 @@ EOF
|
|||||||
serverFile = installConfig.serverFile or bundleOutfile;
|
serverFile = installConfig.serverFile or bundleOutfile;
|
||||||
descriptorPath = installConfig.descriptorPath or "descriptor.quixos-package.txtpb";
|
descriptorPath = installConfig.descriptorPath or "descriptor.quixos-package.txtpb";
|
||||||
extraFiles = installConfig.extraFiles or [ ];
|
extraFiles = installConfig.extraFiles or [ ];
|
||||||
installExtraFile = file:
|
installExtraFile =
|
||||||
|
file:
|
||||||
let
|
let
|
||||||
source = toString file.source;
|
source = toString file.source;
|
||||||
target = file.target or (baseNameOf source);
|
target = file.target or (baseNameOf source);
|
||||||
mode = file.mode or "0644";
|
mode = file.mode or "0644";
|
||||||
in ''
|
in
|
||||||
|
''
|
||||||
install -Dm${toString mode} ${lib.escapeShellArg source} "$out/libexec/${serverLibexecName}/${target}"
|
install -Dm${toString mode} ${lib.escapeShellArg source} "$out/libexec/${serverLibexecName}/${target}"
|
||||||
'';
|
'';
|
||||||
installServerPhase =
|
installServerPhase =
|
||||||
if installServer == null
|
if installServer == null then
|
||||||
then null
|
null
|
||||||
else ''
|
else
|
||||||
|
''
|
||||||
runHook preInstall
|
runHook preInstall
|
||||||
install -Dm755 ${lib.escapeShellArg serverFile} "$out/libexec/${serverLibexecName}/${serverFile}"
|
install -Dm755 ${lib.escapeShellArg serverFile} "$out/libexec/${serverLibexecName}/${serverFile}"
|
||||||
${lib.concatMapStringsSep "\n" installExtraFile extraFiles}
|
${lib.concatMapStringsSep "\n" installExtraFile extraFiles}
|
||||||
@@ -684,7 +754,9 @@ EOF
|
|||||||
|
|
||||||
project = (pkgs.callPackage "${packageRoot}/yarn-project.nix" { inherit nodejs; }) {
|
project = (pkgs.callPackage "${packageRoot}/yarn-project.nix" { inherit nodejs; }) {
|
||||||
src = packageRoot;
|
src = packageRoot;
|
||||||
overrideAttrs = old: {
|
overrideAttrs =
|
||||||
|
old:
|
||||||
|
{
|
||||||
nativeBuildInputs =
|
nativeBuildInputs =
|
||||||
(old.nativeBuildInputs or [ ])
|
(old.nativeBuildInputs or [ ])
|
||||||
++ lib.optional (bundle != null || migrationEntrypoint != null) pkgs.esbuild
|
++ lib.optional (bundle != null || migrationEntrypoint != null) pkgs.esbuild
|
||||||
@@ -693,8 +765,13 @@ EOF
|
|||||||
runHook preBuild
|
runHook preBuild
|
||||||
${exportsFor (callOption buildEnv)}
|
${exportsFor (callOption buildEnv)}
|
||||||
${bindingCommand}
|
${bindingCommand}
|
||||||
|
${lib.optionalString (
|
||||||
|
bindingConfig != null && bundle != null
|
||||||
|
) "${bindingConfig.generator}/bin/quixos-qx bundle-policy src"}
|
||||||
${lib.optionalString (bindingConfig != null) "yarn exec tsc --noEmit"}
|
${lib.optionalString (bindingConfig != null) "yarn exec tsc --noEmit"}
|
||||||
${lib.optionalString (bindingConfig != null) "cp ${lib.escapeShellArg bindingOutput} .qx-checked-bindings"}
|
${lib.optionalString (
|
||||||
|
bindingConfig != null
|
||||||
|
) "cp ${lib.escapeShellArg bindingOutput} .qx-checked-bindings"}
|
||||||
${buildCommand}
|
${buildCommand}
|
||||||
${lib.optionalString (bindingConfig != null) ''
|
${lib.optionalString (bindingConfig != null) ''
|
||||||
yarn exec tsc --noEmit
|
yarn exec tsc --noEmit
|
||||||
@@ -709,7 +786,8 @@ EOF
|
|||||||
''}
|
''}
|
||||||
runHook postBuild
|
runHook postBuild
|
||||||
'';
|
'';
|
||||||
} // lib.optionalAttrs (installServerPhase != null) {
|
}
|
||||||
|
// lib.optionalAttrs (installServerPhase != null) {
|
||||||
installPhase = installServerPhase;
|
installPhase = installServerPhase;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -725,9 +803,10 @@ EOF
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
maybeServerOutputs =
|
maybeServerOutputs =
|
||||||
if installServer == null
|
if installServer == null then
|
||||||
then { }
|
{ }
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
packages.server = project;
|
packages.server = project;
|
||||||
apps.default = {
|
apps.default = {
|
||||||
type = "app";
|
type = "app";
|
||||||
@@ -742,16 +821,26 @@ EOF
|
|||||||
packages = [
|
packages = [
|
||||||
nodejs
|
nodejs
|
||||||
project.yarn-freestanding
|
project.yarn-freestanding
|
||||||
] ++ lib.optional (bindingConfig != null) generateBindings ++ callOption devShellPackages;
|
]
|
||||||
|
++ lib.optional (bindingConfig != null) generateBindings
|
||||||
|
++ callOption devShellPackages;
|
||||||
# Explicit command keeps shell entry free of source mutations.
|
# Explicit command keeps shell entry free of source mutations.
|
||||||
shellHook = devShellHookBase + callOption devShellHook;
|
shellHook = devShellHookBase + callOption devShellHook;
|
||||||
};
|
};
|
||||||
} // maybeServerOutputs;
|
}
|
||||||
in (outputsFor null) // {
|
// maybeServerOutputs;
|
||||||
|
in
|
||||||
|
(outputsFor null)
|
||||||
|
// {
|
||||||
# The workspace supplies a compiler-produced schema for the exact
|
# The workspace supplies a compiler-produced schema for the exact
|
||||||
# candidate graph. Standalone builds may use checked-in authoring types,
|
# candidate graph. Standalone builds may use checked-in authoring types,
|
||||||
# but only this build path regenerates and witnesses candidate contracts.
|
# but only this build path regenerates and witnesses candidate contracts.
|
||||||
quixosPackages.checkedServer = { schema, generator, packageRevisionId }:
|
quixosPackages.checkedServer =
|
||||||
|
{
|
||||||
|
schema,
|
||||||
|
generator,
|
||||||
|
packageRevisionId,
|
||||||
|
}:
|
||||||
(outputsFor { inherit schema generator packageRevisionId; }).packages.server;
|
(outputsFor { inherit schema generator packageRevisionId; }).packages.server;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -763,5 +852,6 @@ in
|
|||||||
mkSchemaSupport
|
mkSchemaSupport
|
||||||
mkCaminoSourcePackage
|
mkCaminoSourcePackage
|
||||||
mkQxBindingSchema
|
mkQxBindingSchema
|
||||||
mkCaminoTsYarnNixifyFlake;
|
mkCaminoTsYarnNixifyFlake
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user