Files
quixos-nix-helpers/quixos-package-helpers.nix
T
Timothy J. Aveni 32652d5279 Implement workspace evolution, migrations, and runtime continuity
Enable evolution by default for source-backed workspaces. Add stable
conformance ownership, semantic-major review, candidate typechecking,
and durable fenced cutover with explicit migrations and forward recovery.

Independently supervise package runtimes so unchanged resource owners keep
their processes and connections across cutover. Add scoped invocation
authority, resource sessions, and typed callback rebinding.

Wire opaque object references through generated bindings and RPCs. Add
canonical relationship sets, keyed maps, and ordered lists with scoped
transactional mutations, revision checks, and inverse consistency. Support
planned cascade deletion, protection, tombstones, and lifecycle foundations.

Add journaled structural edits, package/function/migration scaffolding,
managed repository creation, and resumable bottom-up dependency pin
publication. Document lifetime boundaries, revision pinning, prototype
compatibility policy, commands, and deferred work.

Validate with 210 tests, user-systemd process/connection continuity,
generated-package TypeScript checks, and Nix host/protocol checks.
TTL handoff, physical reclamation, general multi-step migrations, and
root-systemd migration isolation acceptance remain deferred.
2026-09-10 18:29:25 -07:00

757 lines
26 KiB
Nix

let
mkSchemaSupport =
{
pkgs,
inputs,
system,
self ? null,
flakeRoot,
schemaDir,
schemaPrefix ? "packageSchema_",
schemaBuildCommand ? "yarn build",
schemaTypecheckCommand ? "yarn typecheck",
nodejs ? pkgs.nodejs_24,
git ? pkgs.git,
}:
let
schemaPackageJson = builtins.fromJSON (builtins.readFile "${schemaDir}/package.json");
schemaMainPath = schemaPackageJson.main or "dist/quixos-package-schema.js";
schemaMainPathDefault = "dist/quixos-package-schema.js";
schemaPackageName = schemaPackageJson.name or "schema";
selfSchemaName =
if pkgs.lib.hasInfix "/" schemaPackageName
then pkgs.lib.last (pkgs.lib.splitString "/" schemaPackageName)
else schemaPackageName;
flakeText =
builtins.replaceStrings
[ "\n" "\r" "\t" ]
[ " " " " " " ]
(builtins.readFile "${flakeRoot}/flake.nix");
getInputUrl = inputName:
let
pattern1 = ".*" + inputName + "[[:space:]]*\\.url[[:space:]]*=[[:space:]]*\"([^\"]+)\".*";
pattern2 = ".*" + inputName + "[[:space:]]*=[[:space:]]*\\{[^}]*url[[:space:]]*=[[:space:]]*\"([^\"]+)\".*";
match1 = builtins.match pattern1 flakeText;
match2 = if match1 != null then match1 else builtins.match pattern2 flakeText;
in if match2 == null then null else builtins.elemAt match2 0;
schemaBase =
(pkgs.callPackage "${schemaDir}/yarn-project.nix" {
inherit nodejs git;
})
{
# avoid pulling .git, etc.
src = pkgs.lib.cleanSource schemaDir;
};
schema = schemaBase.overrideAttrs (old: {
buildPhase = (old.buildPhase or "") + ''
runHook preBuild
${schemaBuildCommand}
runHook postBuild
'';
});
schemaCheck = schema.overrideAttrs (old: {
doCheck = true;
checkPhase = (old.checkPhase or "") + ''
runHook preCheck
${schemaTypecheckCommand}
runHook postCheck
'';
});
schemaInputs =
pkgs.lib.filterAttrs (name: _: pkgs.lib.hasPrefix schemaPrefix name) inputs;
decodeSchemaInputName = encodedName:
builtins.replaceStrings [ "__" ] [ "." ] encodedName;
schemaPackagesFromInputs =
pkgs.lib.mapAttrs'
(name: flake:
let
schemaName =
decodeSchemaInputName (pkgs.lib.removePrefix schemaPrefix name);
in
{
name = schemaName;
value = flake.packages.${system}.schema;
})
schemaInputs;
schemaPackages = schemaPackagesFromInputs // { "${selfSchemaName}" = schema; };
schemaMetaByName =
pkgs.lib.mapAttrs'
(name: flake:
let
schemaName =
decodeSchemaInputName (pkgs.lib.removePrefix schemaPrefix name);
sourceInfo = if flake ? sourceInfo then flake.sourceInfo else { };
sourceRev = sourceInfo.rev or null;
inputUrl = getInputUrl name;
urlBase =
if inputUrl == null
then null
else builtins.head (pkgs.lib.splitString "?" inputUrl);
isDisallowed =
inputUrl == null
|| pkgs.lib.hasPrefix "path:" inputUrl
|| pkgs.lib.hasPrefix "file:" inputUrl
|| pkgs.lib.hasPrefix "git+file:" inputUrl;
flakeRef =
if isDisallowed || sourceRev == null || urlBase == null
then null
else urlBase + "?rev=" + sourceRev;
meta =
{
name = "@quixos-package-schemas/${schemaName}";
type = sourceInfo.type or null;
url = inputUrl;
rev = sourceRev;
flakeRef = flakeRef;
};
in
if flakeRef == null
then throw "Schema input ${schemaName} must be a git flake with url+rev"
else {
name = schemaName;
value = meta;
})
schemaInputs;
schemaMetaJsonByName =
pkgs.lib.mapAttrs (_: meta: builtins.toJSON meta) schemaMetaByName;
schemaExtensionsBlock = pkgs.lib.concatStringsSep "\n" (
[
"packageExtensions:"
" \"quixos-package@*\":"
" dependencies:"
]
++ pkgs.lib.mapAttrsToList (
name: _: " \"@quixos-package-schemas/${name}\": \"portal:./quixos-package-schemas/${name}\""
) schemaPackages
);
schemaExtensionsBlockEscaped = pkgs.lib.escapeShellArg schemaExtensionsBlock;
schemaLinkCommands = pkgs.lib.concatStringsSep "\n" (
pkgs.lib.mapAttrsToList (name: drv: ''
schema_pkg="$(ls -d ${drv}/libexec/* 2>/dev/null | head -n1 || true)"
if [ -n "$schema_pkg" ]; then
ln -sfn "$schema_pkg" quixos-package-schemas/${name}
fi
'') schemaPackages
);
schemaInstallCommands = pkgs.lib.concatStringsSep "\n" (
pkgs.lib.mapAttrsToList (name: drv:
let
metaJson =
if pkgs.lib.hasAttr name schemaMetaJsonByName
then schemaMetaJsonByName.${name}
else null;
in
''
schema_pkg="$(ls -d ${drv}/libexec/* | head -n1)"
dest="quixos-package-schemas/${name}"
rm -rf "$dest"
cp -R --no-preserve=mode,ownership "$schema_pkg" "$dest"
chmod -R u+w "$dest"
''
+ (
if metaJson != null
then ''
schema_main="${schemaMainPathDefault}"
if [ -f "$dest/$schema_main" ]; then
block_tmp="$(mktemp -p "$dest")"
tmp_out="$(mktemp -p "$dest")"
cat > "$block_tmp" <<'EOF'
packageSchema.__quixos = ${metaJson};
EOF
chmod u+w "$dest/$schema_main"
if grep -q '^export default ' "$dest/$schema_main"; then
awk -v blockFile="$block_tmp" '
BEGIN {
while ((getline line < blockFile) > 0) {
block = block line "\n"
}
}
!inserted && /^export default / { printf "%s", block; inserted=1 }
{ print }
' "$dest/$schema_main" > "$tmp_out"
cat "$tmp_out" > "$dest/$schema_main"
elif grep -q '^//# sourceMappingURL=' "$dest/$schema_main"; then
awk -v blockFile="$block_tmp" '
BEGIN {
while ((getline line < blockFile) > 0) {
block = block line "\n"
}
}
/^\/\/# sourceMappingURL=/ { printf "%s", block; print; next }
{ print }
' "$dest/$schema_main" > "$tmp_out"
cat "$tmp_out" > "$dest/$schema_main"
else
printf '\n' >> "$dest/$schema_main"
cat "$block_tmp" >> "$dest/$schema_main"
fi
rm -f "$block_tmp" "$tmp_out"
fi
''
else ""
)
) schemaPackages
);
updateYarnrcScript = ''
quixos_package_schemas_update_yarnrc() {
local yarnrc=".yarnrc.yml"
local tmp="$(mktemp)"
local block_tmp="$(mktemp)"
printf '%s\n' ${schemaExtensionsBlockEscaped} > "$block_tmp"
awk -v blockFile="$block_tmp" '
BEGIN {
while ((getline line < blockFile) > 0) {
block = block line "\n"
}
}
/^# BEGIN packageExtensions/ {print; printf "%s", block; skip=1; next}
/^# END packageExtensions/ {skip=0; print; next}
!skip {print}
' "$yarnrc" > "$tmp"
mv "$tmp" "$yarnrc"
rm -f "$block_tmp"
}
'';
in
{
inherit
schema
schemaCheck
schemaPackages
schemaLinkCommands
schemaInstallCommands
updateYarnrcScript
schemaExtensionsBlockEscaped
selfSchemaName;
};
mkTsPackageServer =
{
srcDir,
serverBin ? "server",
nodejs ? null,
git ? null,
templatePreparePackages ? null,
buildCommand ? null,
typecheckCommand ? "yarn typecheck",
serverOverrides ? (old: { }),
}:
{
pkgs,
schemaSupport,
extraBuildInputs ? [ ],
extraNativeBuildInputs ? [ ],
extraRuntimePackages ? [ ],
}:
let
nodejs' = if nodejs != null then nodejs else pkgs.nodejs_24;
git' = if git != null then git else pkgs.git;
templatePreparePackages' =
if templatePreparePackages != null
then templatePreparePackages
else [
pkgs.findutils
git'
pkgs.gnused
nodejs'
pkgs.yarn-berry_4
];
packageJson = builtins.fromJSON (builtins.readFile "${srcDir}/package.json");
packageName = packageJson.name or "quixos-package";
base =
(pkgs.callPackage "${srcDir}/yarn-project.nix" {
nodejs = nodejs';
git = git';
})
{
# avoid pulling .git, etc.
src = pkgs.lib.cleanSource srcDir;
};
runtimeBinPath = pkgs.lib.makeBinPath extraRuntimePackages;
runtimeLibPath = pkgs.lib.makeLibraryPath extraRuntimePackages;
runtimeWrap =
if extraRuntimePackages == [ ]
then ""
else ''
wrapProgram "$out/bin/${serverBin}" \
--prefix PATH : ${runtimeBinPath} \
--prefix LD_LIBRARY_PATH : ${runtimeLibPath}
'';
server = base.overrideAttrs (old:
let
extraAttrs = serverOverrides old;
in
{
buildInputs = (old.buildInputs or [ ]) ++ extraBuildInputs;
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [
pkgs.python3
pkgs.gnumake
pkgs.gcc
pkgs.pkg-config
pkgs.makeWrapper
] ++ extraNativeBuildInputs;
# node-gyp will look at these
PYTHON = "${pkgs.python3}/bin/python3";
npm_config_python = "${pkgs.python3}/bin/python3";
preConfigure = (old.preConfigure or "") + ''
mkdir -p quixos-package-schemas
${schemaSupport.schemaLinkCommands}
'';
buildPhase =
(old.buildPhase or "")
+ (
if buildCommand != null
then ''
runHook preBuildQuixos
${buildCommand}
runHook postBuildQuixos
''
else ""
);
postFixup = (old.postFixup or "") + runtimeWrap;
postInstall = (old.postInstall or "") + ''
pkg_root="$out/libexec/${old.name}"
mkdir -p "$pkg_root/quixos-package-schemas"
(cd "$pkg_root" && ${schemaSupport.schemaInstallCommands})
'';
} // extraAttrs
);
check = server.overrideAttrs (old: {
doCheck = true;
checkPhase = (old.checkPhase or "") + ''
runHook preCheck
${typecheckCommand}
runHook postCheck
'';
});
prepareShell = pkgs.mkShell {
packages = templatePreparePackages';
};
in
{
inherit server check packageName serverBin;
devShells = {
"quixos-prepare" = prepareShell;
};
};
mkQuixosPackageFlake =
{
self ? null,
inputs,
nixpkgs,
flake-utils,
flakeRoot,
schemaDir,
schemaPrefix ? "packageSchema_",
serverBuilder,
packageName ? null,
extraBuildInputs ? (pkgs: [ ]),
extraNativeBuildInputs ? (pkgs: [ ]),
extraRuntimePackages ? (pkgs: [ ]),
extraDevShellPackages ? (pkgs: [ ]),
enableYarnrcHook ? true,
extraDevShellHook ? "",
appProgram ? null,
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs { inherit system; };
schemaSupport = mkSchemaSupport {
inherit pkgs inputs system schemaDir schemaPrefix self flakeRoot;
};
normalizeList = value:
if builtins.isFunction value
then value pkgs
else value;
serverResult = serverBuilder {
inherit pkgs schemaSupport;
extraBuildInputs = normalizeList extraBuildInputs;
extraNativeBuildInputs = normalizeList extraNativeBuildInputs;
extraRuntimePackages = normalizeList extraRuntimePackages;
};
combinedName = pkgs.lib.strings.sanitizeDerivationName (
if packageName != null
then packageName
else if serverResult ? packageName
then serverResult.packageName
else "quixos-package"
);
packageServer = serverResult.server;
packageServerCheck = if serverResult ? check then serverResult.check else null;
appProgramFinal =
if appProgram != null
then appProgram
else if serverResult ? appProgram
then serverResult.appProgram
else "${packageServer}/bin/${serverResult.serverBin or "server"}";
devShellHookBase =
if enableYarnrcHook
then ''
find_schema_root() {
dir="$PWD"
while [ "$dir" != "/" ]; do
if [ -f "$dir/src/.yarnrc.yml" ] && [ -d "$dir/schema" ]; then
printf "%s\n" "$dir"
return 0
fi
dir="$(dirname "$dir")"
done
return 1
}
${schemaSupport.updateYarnrcScript}
link_schemas() {
mkdir -p quixos-package-schemas
${schemaSupport.schemaLinkCommands}
}
base="$(find_schema_root || true)"
if [ -n "$base" ]; then
(cd "$base/src" && link_schemas && quixos_package_schemas_update_yarnrc)
if [ -d "$base/schema" ]; then
ln -sfn "$base/schema" "$base/src/quixos-package-schemas/${schemaSupport.selfSchemaName}"
fi
fi
''
else "";
devShellHook = devShellHookBase + extraDevShellHook;
devShellPackages = normalizeList extraDevShellPackages;
checks =
{ schema = schemaSupport.schemaCheck; }
// (if packageServerCheck != null then { default = packageServerCheck; } else { });
extraDevShells = if serverResult ? devShells then serverResult.devShells else { };
in
{
packages.default = pkgs.symlinkJoin {
name = combinedName;
paths = [ packageServer schemaSupport.schema ];
};
packages.server = packageServer;
packages.schema = schemaSupport.schema;
apps.default = {
type = "app";
program = appProgramFinal;
meta.description = "Quixos package server";
};
checks = checks;
devShells = extraDevShells // {
default = pkgs.mkShell {
inputsFrom = [ packageServer ] ++ builtins.attrValues schemaSupport.schemaPackages;
packages = devShellPackages;
shellHook = devShellHook;
};
};
}
);
mkCaminoSourcePackage =
{
pkgs,
src,
name ? "quixos-package-source",
}:
pkgs.stdenvNoCC.mkDerivation {
inherit name;
src = pkgs.lib.cleanSource src;
dontConfigure = true;
dontBuild = true;
installPhase = ''
runHook preInstall
cp -R . "$out"
runHook postInstall
'';
};
# Language-neutral, offline schema compilation. Snapshot directories must be
# fixed Nix inputs matching the resource lock's complete dependency closure.
mkQxBindingSchema = { pkgs, protocol, src, repository, commit, resources ? [ ] }:
let
snapshots = pkgs.writeText "qx-binding-snapshots.json" (builtins.toJSON { inherit resources; });
in pkgs.runCommand "qx-binding-schema.json" { } ''
${protocol}/bin/quixos-resource-compile \
--root ${src} --kind package \
--repository ${pkgs.lib.escapeShellArg repository} \
--commit ${pkgs.lib.escapeShellArg commit} \
--checkout-root "$TMPDIR/checkouts" \
--snapshot-map ${snapshots} --snapshot-only true --schema-out "$out" > /dev/null
'';
mkCaminoTsYarnNixifyFlake =
{
inputs,
nixpkgs,
flake-utils,
packageRoot,
packageName ? null,
sourceName ? "quixos-package-source",
promptName ? null,
nodejsAttr ? "nodejs_24",
buildCommand ? "yarn build",
buildEnv ? { },
# An exact, compiler-produced BindingSchema JSON artifact and a backend.
# Other language helpers can consume the same schema with their own generator/runtime.
bindings ? null,
# A dedicated entrypoint calling SDK serveMigration; never start the
# normal package server in the isolated migration execution boundary.
migrationEntrypoint ? null,
nativeBuildInputs ? [ ],
devShellPackages ? [ ],
devShellHook ? "",
bundle ? null,
installServer ? null,
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs { inherit system; };
lib = pkgs.lib;
nodejs = pkgs.${nodejsAttr};
callOption = value:
if builtins.isFunction value
then value { inherit inputs pkgs system; }
else value;
packageJson = builtins.fromJSON (builtins.readFile "${packageRoot}/package.json");
packageNameFinal = if packageName != null then packageName else packageJson.name or "quixos-package";
promptNameFinal =
if promptName != null
then promptName
else lib.strings.sanitizeDerivationName packageNameFinal;
sourcePackage = mkCaminoSourcePackage {
inherit pkgs;
src = packageRoot;
name = sourceName;
};
exportsFor = attrs:
lib.concatStringsSep "\n" (
lib.mapAttrsToList
(name: value: "export ${name}=${lib.escapeShellArg (toString value)}")
attrs
);
bindingConfig = if bindings == null then null else callOption bindings;
bindingSchema = if bindingConfig == null then null else bindingConfig.schema or (mkQxBindingSchema {
inherit pkgs;
protocol = bindingConfig.generator;
src = packageRoot;
inherit (bindingConfig) repository commit;
resources = bindingConfig.resources or [ ];
});
bindingOutput = if bindingConfig == null then "src/gen/qx.ts" else bindingConfig.output or "src/gen/qx.ts";
bindingOptions = if bindingConfig == null then null else
pkgs.writeText "qx-typescript-options.json" (builtins.toJSON (bindingConfig.options or { }));
bindingCommand = if bindingConfig == null then "" else ''
mkdir -p ${lib.escapeShellArg (dirOf bindingOutput)}
${bindingConfig.generator}/bin/quixos-codegen-ts \
${lib.escapeShellArg (toString bindingSchema)} \
${lib.escapeShellArg bindingConfig.packageRevisionId} \
${lib.escapeShellArg bindingOutput} ${bindingOptions}
'';
generateBindings = pkgs.writeShellApplication {
name = "qx-generate-bindings";
text = bindingCommand;
};
bundleConfig = if bundle == null then { } else bundle;
bundleOutfile = bundleConfig.outfile or "server.mjs";
bundlePlatform = bundleConfig.platform or "node";
bundleTarget = bundleConfig.target or "node24";
bundleFormat = bundleConfig.format or "esm";
bundleBanner = bundleConfig.banner or nodeRequireBanner;
bundleAliases = bundleConfig.aliases or {
"@automerge/automerge" = "./node_modules/@automerge/automerge/dist/mjs/entrypoints/fullfat_base64.js";
};
bundleAliasArgs = lib.concatStringsSep " " (
lib.mapAttrsToList
(from: to: "--alias:${from}=${lib.escapeShellArg to}")
bundleAliases
);
nodeRequireBanner = "import { createRequire } from 'module';const require = createRequire(import.meta.url);";
bundleCommand =
if bundle == null
then ""
else ''
esbuild ${lib.escapeShellArg bundleConfig.entry} \
--bundle \
--platform=${bundlePlatform} \
--target=${bundleTarget} \
--format=${bundleFormat} \
${bundleAliasArgs} \
${lib.optionalString (bundleConfig.preserveSymlinks or true) "--preserve-symlinks \\"}
--banner:js=${lib.escapeShellArg bundleBanner} \
--outfile=${lib.escapeShellArg bundleOutfile}
'';
installConfig = if installServer == null then { } else installServer;
serverBin = installConfig.binName or "server";
serverLibexecName =
installConfig.libexecName or (lib.strings.sanitizeDerivationName packageNameFinal);
serverFile = installConfig.serverFile or bundleOutfile;
descriptorPath = installConfig.descriptorPath or "descriptor.quixos-package.txtpb";
extraFiles = installConfig.extraFiles or [ ];
installExtraFile = file:
let
source = toString file.source;
target = file.target or (baseNameOf source);
mode = file.mode or "0644";
in ''
install -Dm${toString mode} ${lib.escapeShellArg source} "$out/libexec/${serverLibexecName}/${target}"
'';
installServerPhase =
if installServer == null
then null
else ''
runHook preInstall
install -Dm755 ${lib.escapeShellArg serverFile} "$out/libexec/${serverLibexecName}/${serverFile}"
${lib.concatMapStringsSep "\n" installExtraFile extraFiles}
mkdir -p "$out/bin"
cat > "$out/bin/${serverBin}" <<EOF
#!${pkgs.runtimeShell}
exec ${nodejs}/bin/node "$out/libexec/${serverLibexecName}/${serverFile}" "\$@"
EOF
chmod +x "$out/bin/${serverBin}"
${lib.optionalString (installConfig ? descriptorPath && descriptorPath != null) ''
cp ${lib.escapeShellArg descriptorPath} "$out/${descriptorPath}"
''}
${lib.optionalString (bindingConfig != null) ''
install -m 0444 quixos-check.json "$out/quixos-check.json"
''}
${lib.optionalString (migrationEntrypoint != null) ''
install -Dm444 migration.mjs "$out/libexec/${serverLibexecName}/migration.mjs"
cat > "$out/bin/migrate" <<EOF
#!${pkgs.runtimeShell}
exec ${nodejs}/bin/node --max-old-space-size=256 "$out/libexec/${serverLibexecName}/migration.mjs" "\$@"
EOF
chmod +x "$out/bin/migrate"
''}
runHook postInstall
'';
project = (pkgs.callPackage "${packageRoot}/yarn-project.nix" { inherit nodejs; }) {
src = packageRoot;
overrideAttrs = old: {
nativeBuildInputs =
(old.nativeBuildInputs or [ ])
++ lib.optional (bundle != null || migrationEntrypoint != null) pkgs.esbuild
++ callOption nativeBuildInputs;
buildPhase = ''
runHook preBuild
${exportsFor (callOption buildEnv)}
${bindingCommand}
${lib.optionalString (bindingConfig != null) "yarn exec tsc --noEmit"}
${lib.optionalString (bindingConfig != null) "cp ${lib.escapeShellArg bindingOutput} .qx-checked-bindings"}
${buildCommand}
${lib.optionalString (bindingConfig != null) ''
yarn exec tsc --noEmit
node ${./check-receipt.mjs} ${lib.escapeShellArg (toString bindingSchema)} \
${lib.escapeShellArg bindingConfig.packageRevisionId} ${lib.escapeShellArg bindingOutput} \
${lib.escapeShellArg (toString bindingConfig.generator)} quixos-check.json
''}
${bundleCommand}
${lib.optionalString (migrationEntrypoint != null) ''
esbuild ${lib.escapeShellArg migrationEntrypoint} --bundle --platform=node --target=node24 --format=esm \
${bundleAliasArgs} --preserve-symlinks --banner:js=${lib.escapeShellArg nodeRequireBanner} --outfile=migration.mjs
''}
runHook postBuild
'';
} // lib.optionalAttrs (installServerPhase != null) {
installPhase = installServerPhase;
};
};
devShellHookBase = ''
if [ -n "''${PS1-}" ]; then
if [ -n "''${QX_DEV_SHELL_PROMPT-}" ]; then
PS1="''${PS1#\[qx:''${QX_DEV_SHELL_PROMPT}\] }"
fi
export QX_DEV_SHELL_PROMPT=${lib.escapeShellArg promptNameFinal}
PS1="[qx:${promptNameFinal}] $PS1"
fi
'';
maybeServerOutputs =
if installServer == null
then { }
else {
packages.server = project;
apps.default = {
type = "app";
program = "${project}/bin/${serverBin}";
};
};
in
{
packages.default = project;
packages.source = sourcePackage;
devShells.default = pkgs.mkShell {
packages = [
nodejs
project.yarn-freestanding
] ++ lib.optional (bindingConfig != null) generateBindings ++ callOption devShellPackages;
# Explicit command keeps shell entry free of source mutations.
shellHook = devShellHookBase + callOption devShellHook;
};
} // maybeServerOutputs
);
in
{
inherit
mkQuixosPackageFlake
mkTsPackageServer
mkSchemaSupport
mkCaminoSourcePackage
mkQxBindingSchema
mkCaminoTsYarnNixifyFlake;
}