Files
Wanjohi 5353b9a1db fix(auth): reload the preview on every save, not just the first
bun --watch watches each imported file, and many editors save by
writing a new file and renaming it over the old one. The watch does not
follow the rename, so the first such save reloaded the preview and every
later one was silently ignored.

The preview now runs under a small supervisor that watches the source
directories and restarts the server, which sees a save however it was
made. It also stops the server when it is stopped itself, so the port
is not left held.
2026-10-02 05:48:10 +03:00

50 lines
1.6 KiB
TypeScript

/**
* Runs `preview.ts`, and runs it again whenever the sign-in UI's source changes.
*
* Not `bun --watch`, which watches each imported file. Many editors save by
* writing a new file and renaming it over the old one, and a watch on a file
* does not follow the rename: the first such save reloads, and every one after
* it is silently ignored. A watch on the directory sees every save, however it
* was made.
*/
import { watch } from 'node:fs';
import { join } from 'node:path';
const ROOT = join(import.meta.dir, '..', '..', '..');
const DIRS = [join(ROOT, 'packages/auth/src'), join(ROOT, 'apps/auth/src'), import.meta.dir];
const SERVER = join(import.meta.dir, 'preview.ts');
let child = start();
let timer: ReturnType<typeof setTimeout> | undefined;
function start() {
return Bun.spawn(['bun', SERVER], { stdio: ['inherit', 'inherit', 'inherit'] });
}
async function restart(file: string) {
child.kill();
// The port is free only once the old server has exited.
await child.exited;
console.log(`changed: ${file}`);
child = start();
}
for (const dir of DIRS) {
watch(dir, { recursive: true }, (_event, file) => {
if (!file || !/\.(ts|tsx)$/.test(file)) return;
// One save can be several events: a write, then a rename.
clearTimeout(timer);
timer = setTimeout(() => restart(file), 60);
});
}
// Ctrl-C reaches the whole process group, but a plain `kill` reaches only
// this process, and would leave the server holding the port.
for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP'] as const) {
process.on(signal, () => {
child.kill();
process.exit(0);
});
}