Generate typed QX bindings and add source editing tools

This commit is contained in:
Timothy J. Aveni
2026-09-08 14:27:24 -07:00
parent 7177130c03
commit 7e4fb60155
+45 -1
View File
@@ -510,6 +510,20 @@ EOF
''; '';
}; };
# 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 = mkCaminoTsYarnNixifyFlake =
{ {
inputs, inputs,
@@ -522,6 +536,9 @@ EOF
nodejsAttr ? "nodejs_24", nodejsAttr ? "nodejs_24",
buildCommand ? "yarn build", buildCommand ? "yarn build",
buildEnv ? { }, 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,
nativeBuildInputs ? [ ], nativeBuildInputs ? [ ],
devShellPackages ? [ ], devShellPackages ? [ ],
devShellHook ? "", devShellHook ? "",
@@ -560,6 +577,29 @@ EOF
attrs 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; bundleConfig = if bundle == null then { } else bundle;
bundleOutfile = bundleConfig.outfile or "server.mjs"; bundleOutfile = bundleConfig.outfile or "server.mjs";
bundlePlatform = bundleConfig.platform or "node"; bundlePlatform = bundleConfig.platform or "node";
@@ -634,6 +674,8 @@ EOF
buildPhase = '' buildPhase = ''
runHook preBuild runHook preBuild
${exportsFor (callOption buildEnv)} ${exportsFor (callOption buildEnv)}
${bindingCommand}
${lib.optionalString (bindingConfig != null) "yarn exec tsc --noEmit"}
${buildCommand} ${buildCommand}
${bundleCommand} ${bundleCommand}
runHook postBuild runHook postBuild
@@ -671,7 +713,8 @@ EOF
packages = [ packages = [
nodejs nodejs
project.yarn-freestanding project.yarn-freestanding
] ++ callOption devShellPackages; ] ++ lib.optional (bindingConfig != null) generateBindings ++ callOption devShellPackages;
# Explicit command keeps shell entry free of source mutations.
shellHook = devShellHookBase + callOption devShellHook; shellHook = devShellHookBase + callOption devShellHook;
}; };
} // maybeServerOutputs } // maybeServerOutputs
@@ -683,5 +726,6 @@ in
mkTsPackageServer mkTsPackageServer
mkSchemaSupport mkSchemaSupport
mkCaminoSourcePackage mkCaminoSourcePackage
mkQxBindingSchema
mkCaminoTsYarnNixifyFlake; mkCaminoTsYarnNixifyFlake;
} }