From e557a057d89af59b3fd664bf00550195020e203e Mon Sep 17 00:00:00 2001 From: "Timothy J. Aveni" Date: Tue, 15 Sep 2026 17:32:53 -0700 Subject: [PATCH] Mark first-party generated files with .gen; preserve third-party conventions --- .yarnrc.yml | 1 + README.md | 2 +- flake.nix | 4 ++-- src/bindings/cli.ts | 2 +- src/capability-language/scaffold-recipes.ts | 16 ++++++++-------- src/capability-language/tool-cli.ts | 5 +++-- test/scaffold-recipes.test.ts | 7 +++++-- yarn-project.nix => yarn-project.gen.nix | 0 8 files changed, 21 insertions(+), 16 deletions(-) rename yarn-project.nix => yarn-project.gen.nix (100%) diff --git a/.yarnrc.yml b/.yarnrc.yml index de9b346..42b6936 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -1,3 +1,4 @@ +nixExprPath: yarn-project.gen.nix enableScripts: true generateDefaultNix: false diff --git a/README.md b/README.md index c71eedc..0cef1ea 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ fragment, so fragments do not become independent repositories or identities. Executable package metadata remains protobuf text format: ```sh -quixos-descriptor-check path/to/descriptor.quixos-package.txtpb +quixos-descriptor-check path/to/descriptor.quixos-package.gen.txtpb ``` Descriptors identify exact package revisions and exported runtime symbols. diff --git a/flake.nix b/flake.nix index 7a86d3d..f990f98 100644 --- a/flake.nix +++ b/flake.nix @@ -18,7 +18,7 @@ let pkgs = import nixpkgs { inherit system; }; nodejs = pkgs.nodejs_24; - quixos-protocol = (pkgs.callPackage ./yarn-project.nix { inherit nodejs; }) { + quixos-protocol = (pkgs.callPackage ./yarn-project.gen.nix { inherit nodejs; }) { src = pkgs.lib.cleanSource ./.; overrideAttrs = old: { nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ @@ -127,7 +127,7 @@ in { packages.default = quixos-protocol; - packages.inspector = (pkgs.callPackage ./yarn-project.nix { inherit nodejs; }) { + packages.inspector = (pkgs.callPackage ./yarn-project.gen.nix { inherit nodejs; }) { src = pkgs.lib.fileset.toSource { root = ./.; fileset = pkgs.lib.fileset.unions [ diff --git a/src/bindings/cli.ts b/src/bindings/cli.ts index df81397..86ccab9 100644 --- a/src/bindings/cli.ts +++ b/src/bindings/cli.ts @@ -12,7 +12,7 @@ const main = async () => { const generated = generateTypeScriptBindings(JSON.parse(await readFile(schema, "utf8")), revision, config); await writeFile(output, generated); if (config.messages?.["org.quixos.web-studio.ReactProps"]) { - await writeFile(path.join(path.dirname(output), "web-studio-react-runtime.d.ts"), reactPlatformTypes); + await writeFile(path.join(path.dirname(output), "web-studio-react-runtime.gen.d.ts"), reactPlatformTypes); } }; main().catch((error: unknown) => { diff --git a/src/capability-language/scaffold-recipes.ts b/src/capability-language/scaffold-recipes.ts index 7a3dd20..71bea7b 100644 --- a/src/capability-language/scaffold-recipes.ts +++ b/src/capability-language/scaffold-recipes.ts @@ -146,13 +146,13 @@ export const scaffoldRecipe = async ( ); create( "src/impl/sourceGet.ts", - `import componentSource from "../component.js?browser-source";\nimport type {Implementation} from "../gen/qx.js";\nexport const handler: Implementation["sourceGet"] = () => componentSource;\n`, + `import componentSource from "../component.js?browser-source";\nimport type {Implementation} from "../gen/qx.gen.js";\nexport const handler: Implementation["sourceGet"] = () => componentSource;\n`, ); create( "src/browser-assets.d.ts", `declare module "*?browser-source" { const source: string; export default source; }\ndeclare module "*.css" {}\n`, ); - create("src/gen/web-studio-react-runtime.d.ts", reactPlatformTypes); + create("src/gen/web-studio-react-runtime.gen.d.ts", reactPlatformTypes); } create(".gitignore", "node_modules/\ndist/\n.quixos/\nresult\n.yarn/install-state.gz\n"); create( @@ -177,7 +177,7 @@ export const scaffoldRecipe = async ( "quixos.check.json", json({ backend: "typescript", - bindingOutput: "src/gen/qx.ts", + bindingOutput: "src/gen/qx.gen.ts", ...(react ? { options: { @@ -204,7 +204,7 @@ export const scaffoldRecipe = async ( inherit inputs nixpkgs flake-utils; packageRoot = ./.; bundle = { entry = ${JSON.stringify(react ? "src/server.ts" : "dist/server.js")}; ${react ? "browserSources = true;" : ""} }; migrationEntrypoint = "dist/migrate.js"; - installServer = { libexecName = ${JSON.stringify(name.toLowerCase())}; descriptorPath = "descriptor.quixos-package.txtpb"; }; + installServer = { libexecName = ${JSON.stringify(name.toLowerCase())}; descriptorPath = "descriptor.quixos-package.gen.txtpb"; }; }; }\n`, ); @@ -282,7 +282,7 @@ export const scaffoldRecipe = async ( const implementation = command === "migration" ? `import type {MigrationContext} from "@quixos/camino-package-runtime";\nexport const handler = async (_context: MigrationContext): Promise => { throw new Error(${JSON.stringify(`Implement migration ${name}`)}); };\n` - : `import type {Implementation} from "../gen/qx.js";\nexport const handler: Implementation[${JSON.stringify(name)}] = ${derived ? '{kind: "derived", get: ' : ""}async (_context) => { throw new Error(${JSON.stringify(`Implement ${name}`)}); }${derived ? "}" : ""};\n`; + : `import type {Implementation} from "../gen/qx.gen.js";\nexport const handler: Implementation[${JSON.stringify(name)}] = ${derived ? '{kind: "derived", get: ' : ""}async (_context) => { throw new Error(${JSON.stringify(`Implement ${name}`)}); }${derived ? "}" : ""};\n`; create(file, implementation); packageModel.exports.push({ name, id: spec.id, file, ...(command === "migration" ? { migration: true } : {}) }); if (command === "migration") { @@ -333,7 +333,7 @@ export const scaffoldRecipe = async ( } else { create( "src/server.ts", - `import {servePackageRuntime} from "@quixos/camino-package-runtime";\nimport {createRuntime} from "./gen/qx.js";\n` + + `import {servePackageRuntime} from "@quixos/camino-package-runtime";\nimport {createRuntime} from "./gen/qx.gen.js";\n` + packageModel.exports .filter((entry) => !entry.migration) .map( @@ -364,7 +364,7 @@ export const scaffoldRecipe = async ( ); } generated( - "descriptor.quixos-package.txtpb", + "descriptor.quixos-package.gen.txtpb", `# Generated by qx-scaffold-v1\npackage_id: ${JSON.stringify(packageModel.id)}\npackage_revision_id: ${JSON.stringify(packageModel.revision)}\nruntime_protocol_version: "quixos-capabilities-v1"\n` + packageModel.exports .map( @@ -403,7 +403,7 @@ export const scaffoldRecipe = async ( } // A composed React recipe supplies its own modules and complete server. if (reactRecipe(spec)) { - for (const file of ["src/component.tsx", "src/impl/sourceGet.ts", "descriptor.quixos-package.txtpb"]) + for (const file of ["src/component.tsx", "src/impl/sourceGet.ts", "descriptor.quixos-package.gen.txtpb"]) if (!(file in spec.initialFiles)) { const index = files.findIndex((entry) => entry.file === prefix + file); if (index >= 0) files.splice(index, 1); diff --git a/src/capability-language/tool-cli.ts b/src/capability-language/tool-cli.ts index feae14a..b2c8329 100644 --- a/src/capability-language/tool-cli.ts +++ b/src/capability-language/tool-cli.ts @@ -437,6 +437,7 @@ const main = async () => { for (const [executable, args] of [ ["corepack", ["yarn", "plugin", "import", toolchain.nixifyPluginUrl]], ["corepack", ["yarn", "config", "set", "generateDefaultNix", "false"]], + ["corepack", ["yarn", "config", "set", "nixExprPath", "yarn-project.gen.nix"]], ["corepack", ["yarn", "config", "set", "individualNixPackaging", "true"]], ["corepack", ["yarn", "install"]], ] as const) { @@ -447,10 +448,10 @@ const main = async () => { ); } try { - await readFile(path.join(cwd, "yarn-project.nix")); + await readFile(path.join(cwd, "yarn-project.gen.nix")); } catch { throw new Error( - "Nixify did not generate yarn-project.nix. It skips repositories under the OS temporary directory; use an ordinary workspace checkout and retry installation.", + "Nixify did not generate yarn-project.gen.nix. It skips repositories under the OS temporary directory; use an ordinary workspace checkout and retry installation.", ); } await snapshotCommit(cwd); diff --git a/test/scaffold-recipes.test.ts b/test/scaffold-recipes.test.ts index f933301..56d02d6 100644 --- a/test/scaffold-recipes.test.ts +++ b/test/scaffold-recipes.test.ts @@ -28,7 +28,10 @@ test("React preset applies its browser build script and shared-platform imports" await applyStructure(await planStructure(root, request)); assert.match(await fs.readFile(path.join(root, "src/impl/sourceGet.ts"), "utf8"), /component.js\?browser-source/); assert.match(await fs.readFile(path.join(root, "flake.nix"), "utf8"), /browserSources = true/); - assert.equal(await fs.readFile(path.join(root, "src/gen/web-studio-react-runtime.d.ts"), "utf8"), reactPlatformTypes); + assert.equal( + await fs.readFile(path.join(root, "src/gen/web-studio-react-runtime.gen.d.ts"), "utf8"), + reactPlatformTypes, + ); assert.match(await fs.readFile(path.join(root, "src/browser-assets.d.ts"), "utf8"), /declare module "\*\.css"/); assert.equal( JSON.parse(await fs.readFile(path.join(root, "quixos.check.json"), "utf8")).options.messages[ @@ -62,7 +65,7 @@ test("imperative scaffolds preserve authored wiring; migration sealing is explic await apply("function", { ...base, name: "play", id: "export:play" }); const filename = path.join(root, base.directory, "src/impl/play.ts"); const edited = - 'import type {Implementation} from "../gen/qx.js";\nexport const handler: Implementation["play"] = async () => null;\n'; + 'import type {Implementation} from "../gen/qx.gen.js";\nexport const handler: Implementation["play"] = async () => null;\n'; await fs.writeFile(filename, edited); const old = { version: 1 }, next = { version: 2 }, diff --git a/yarn-project.nix b/yarn-project.gen.nix similarity index 100% rename from yarn-project.nix rename to yarn-project.gen.nix