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);