// Dev server: shadow-cljs watch on the :app build, served by :dev-http on BOTH
// 5173 and 4173 (public/ + dist-dev/ merged roots — the relay's origin
// allowlist covers 4173/5173 only; shadow's default 8080 would be refused, and
// so would the mailbox mint). Two ports = two origins = two identities, which
// is what a two-tab convergence drill needs.
//
// Reads the SAME env vars ardz already exports and injects them as
// :closure-defines overrides, so `ardz dev chat` keeps working unchanged.
//
// THE WATCH WRITES TO dist-dev/assets, NEVER dist/ (the :output-dir override
// below). This replaces the game1 canon's known wart where 4173 served dist/
// while the watch overwrote dist/assets: dist/ is `ardz build`'s RELEASE tree
// — goog.DEBUG=false, the PRODUCTION relay multiaddr, a service worker — and
// serving it on a dev port handed one tab of a dev drill a production-network
// client (fresh page before the watch's first build, or a browser-cached
// assets/main.js afterwards). The two tabs then sat on different relays and
// never converged, with nothing in either console saying why. Separate trees
// make the mixture impossible. Smoke a release with a standalone static
// server over dist/, never through these ports.
import { spawnSync } from "node:child_process";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { readFileSync } from "node:fs";
const client = dirname(dirname(fileURLToPath(import.meta.url)));
const VERSION = JSON.parse(readFileSync(join(client, "version.json"), "utf8")).version;
// The npm rewrites shadow needs, and their gates (see the script's header).
// Its exit status is CHECKED: patch-npm is what keeps dev and release running
// the same npm sources, and rule 2 in particular is the only place the dev
// pipeline gets the `__esModule` fix that build.mjs applies to a release dist.
// Letting it fail and starting the watcher anyway is how a blank room screen
// reaches a developer with a green build log.
{
const r = spawnSync(process.execPath, [join(client, "scripts", "patch-npm.mjs")], { cwd: client, stdio: "inherit" });
if (r.status !== 0) process.exit(r.status ?? 1);
}
const defines = { "bursa.config/APP-VERSION": VERSION };
const env = {
VITE_APP_SALT: "bursa.config/VITE-APP-SALT",
VITE_STORAGE_NS: "bursa.config/VITE-STORAGE-NS",
VITE_RELAY_MULTIADDR: "bursa.config/VITE-RELAY-MULTIADDR",
VITE_TURN_CREDS_URL: "bursa.config/VITE-TURN-CREDS-URL",
VITE_DISCOVERY_TOPIC: "bursa.config/VITE-DISCOVERY-TOPIC",
VITE_MAILBOX_URL: "bursa.config/VITE-MAILBOX-URL",
VITE_MAILBOX_CREDS_URL: "bursa.config/VITE-MAILBOX-CREDS-URL",
VITE_ID_BRIDGE_URL: "bursa.config/VITE-ID-BRIDGE-URL",
};
for (const [k, define] of Object.entries(env)) {
if (process.env[k]) defines[define] = process.env[k];
}
const body = Object.entries(defines)
.map(([k, v]) => `${k} ${JSON.stringify(v)}`)
.join(" ");
const r = spawnSync(
join(client, "node_modules", ".bin", "shadow-cljs"),
[
"watch",
"app",
"--config-merge",
// :output-dir — the watch's own tree; see the header. dist/ stays the
// release build's alone.
`{:closure-defines {${body}} :output-dir "dist-dev/assets"}`,
],
{ cwd: client, stdio: "inherit" },
);
process.exit(r.status ?? 1);