seveibar/nema17-rp2040-stepper-controller
A tscircuit package created by seveibar.
- Version
- 0.3.1
- License
- unset
- Stars
- 0
scripts/dev.ts
import { mkdir } from "node:fs/promises";
import { join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { patchPreviewRenderer } from "./patch-preview-renderer";
const projectDir = resolve(import.meta.dir, "..");
const outputDir = join(projectDir, ".tscircuit/preview-runtime");
const args = process.argv.slice(2);
const sourceFlag = args.indexOf("--source");
const sourceMode = sourceFlag !== -1 || args.some(arg => /\.[jt]sx?$/.test(arg));
if (sourceFlag !== -1) args.splice(sourceFlag, 1);
if (!args.some(arg => /(?:\.[jt]sx?|circuit\.json)$/.test(arg))) {
args.unshift(sourceMode ? "index.circuit.tsx" : "dist/index/circuit.json");
}
const inputPath = args.find(arg => /(?:\.[jt]sx?|circuit\.json)$/.test(arg))!;
// Serve the built JSON by default: it contains the checked, saved PCB routing
// and needs no browser evaluator or autorouting. Patch a local copy of runframe;
// never alter the installed dependency or the board's circuit JSON.
let standalone = patchPreviewRenderer(await Bun.file(
fileURLToPath(import.meta.resolve("@tscircuit/runframe/standalone")),
).text());
if (sourceMode) {
// Source evaluation requires a separately supplied worker built against the
// pinned core. A package override cannot change the core embedded in a worker.
const workerPath = join(outputDir, "worker.js");
const manifestFile = Bun.file(join(outputDir, "manifest.json"));
if (!(await manifestFile.exists()) || !(await Bun.file(workerPath).exists())) {
throw new Error("Source preview needs a matching worker.js and manifest.json in .tscircuit/preview-runtime. Use bun run dev to view the validated build; rebuild it with bunx tsci build index.circuit.tsx.");
}
const manifest = await manifestFile.json();
const projectPackage = await Bun.file(join(projectDir, "package.json")).json();
if (manifest.coreVersion !== projectPackage.overrides["@tscircuit/core"]) {
throw new Error("Rebuild the preview worker after changing the pinned core version.");
}
const injectionPoint = '"<--INJECT_TSCIRCUIT_EVAL_WEB_WORKER_BLOB_URL-->"';
if (standalone.split(injectionPoint).length !== 2) {
throw new Error("Runframe worker injection point changed; review the preview adapter.");
}
const workerBase64 = Buffer.from(await Bun.file(workerPath).arrayBuffer()).toString("base64");
const prefix = `const motorPreviewWorkerUrl=URL.createObjectURL(new Blob([new TextDecoder().decode(Uint8Array.from(atob(${JSON.stringify(workerBase64)}), c => c.charCodeAt(0)))],{type:"application/javascript"}));\n`;
standalone = prefix + standalone.replace(injectionPoint, "motorPreviewWorkerUrl");
console.log(`Preview evaluator: core ${manifest.coreVersion}, checks ${manifest.checksVersion}`);
} else if (!(await Bun.file(resolve(projectDir, inputPath)).exists())) {
throw new Error(`Preview input not found: ${inputPath}. Run bunx tsci build index.circuit.tsx first.`);
}
await mkdir(outputDir, { recursive: true });
const standalonePath = join(outputDir, "standalone.min.js");
await Bun.write(standalonePath, standalone);
console.log(`Preview: ${inputPath} (multilayer trace rendering fixed locally)`);
const child = Bun.spawn([
process.execPath, join(projectDir, "node_modules/.bin/tsci"), "dev", ...args,
], {
cwd: projectDir,
env: { ...process.env, RUNFRAME_STANDALONE_FILE_PATH: standalonePath },
stdin: "inherit", stdout: "inherit", stderr: "inherit",
});
process.on("SIGINT", () => child.kill("SIGINT"));
process.on("SIGTERM", () => child.kill("SIGTERM"));
process.exit(await child.exited);