Make Camino examples and scaffolds complete Yarn and Nix packages

This commit is contained in:
Timothy J. Aveni
2026-09-22 14:42:54 -07:00
parent 0da022e216
commit f34ce87f55
8 changed files with 172 additions and 20 deletions
+38 -11
View File
@@ -1,3 +1,4 @@
import { installDependencies } from "./install-dependencies.mjs";
import fs from "node:fs/promises";
import path from "node:path";
import { createHash } from "node:crypto";
@@ -66,17 +67,43 @@ export async function buildComponents({ config, compiler, plan, pkg, output, rec
await writable(work);
const modules = path.join(work, "node_modules");
await fs.mkdir(path.join(modules, "@quixos"), { recursive: true });
if (config.nodeModules)
for (const item of await fs.readdir(config.nodeModules, { withFileTypes: true })) {
if (["@quixos", "react", "react-dom", "scheduler", "@types", "csstype"].includes(item.name))
throw Error("Application dependencies cannot substitute selected React/client types");
await fs.symlink(path.join(config.nodeModules, item.name), path.join(modules, item.name));
}
for (const item of await fs.readdir(path.join(settings.dependencies, "node_modules"))) {
await fs.symlink(path.join(settings.dependencies, "node_modules", item), path.join(modules, item));
await installDependencies({
destination: modules,
application: config.nodeModules,
defaults: [path.join(settings.dependencies, "node_modules")],
selected: { "@quixos/camino-react": settings.sdk },
reserved: [
"react",
"react-dom",
"scheduler",
"csstype",
"@types/react",
"@types/react-dom",
"@types/prop-types",
"@quixos/camino-react",
"@quixos/camino-replica-core",
"@quixos/camino-replica-client",
"@quixos/camino-replica-engine",
],
});
const packageFile = path.join(work, "package.json");
const packageMetadata = await fs.readFile(packageFile, "utf8").then(JSON.parse, (error) => {
if (error.code === "ENOENT") return {};
throw error;
});
await fs.writeFile(packageFile, JSON.stringify({ ...packageMetadata, type: "module" }));
// CommonJS dependencies may require React. An ESM bridge lets esbuild lower
// that require while retaining the one host-owned runtime instance.
const sharedAliases = [];
for (const [name, url] of Object.entries(imports)) {
const shim = path.join(work, "shared-" + digest(Buffer.from(name)).slice(0, 16) + ".mjs");
await fs.writeFile(
shim,
`export * from ${JSON.stringify(url)};` +
(name === "@quixos/camino-react" ? "" : `export {default} from ${JSON.stringify(url)};`),
);
sharedAliases.push("--alias:" + name + "=" + shim, "--external:" + url);
}
await fs.symlink(settings.sdk, path.join(modules, "@quixos/camino-react"));
await fs.writeFile(path.join(work, "package.json"), JSON.stringify({ type: "module" }));
const bindingPath = compiler.artifactPath(settings.bindingOutput),
bindings = compiler.generateComponentClientBindings(plan, pkg.revision),
assets = compiler.componentAssetDeclarations();
@@ -187,7 +214,7 @@ export async function buildComponents({ config, compiler, plan, pkg, output, rec
'--define:process.env.NODE_ENV="production"',
"--metafile=" + metadata,
"--outfile=" + path.join(output, directory, "module.mjs"),
...Object.entries(imports).flatMap(([name, url]) => ["--alias:" + name + "=" + url, "--external:" + url]),
...sharedAliases,
...["svg", "png", "jpg", "jpeg", "gif", "webp", "avif", "woff", "woff2", "ttf", "ico"].map(
(extension) => "--loader:." + extension + "=dataurl",
),