Files
airship/scripts/clean.mjs
T
Nayan ff818c1145 build: replace the rm -rf clean scripts with a cross-platform runner
Every workspace `clean` was `rm -rf`, and pnpm runs lifecycle scripts through
the platform shell — on Windows that is cmd.exe, which has no `rm`. The root
`clean` fans out to all eleven packages through turbo, so `pnpm clean` failed
eleven times over.

A shared script rather than a `rimraf` dependency: it needs no install to work,
nothing to keep pinned against the release-age gate in pnpm-workspace.yaml, and
no argument that has to survive two different shells' quoting rules. Node
accepts forward slashes on Windows, so `node ../../scripts/clean.mjs dist
.turbo` is the same string in every package.

It deletes recursively and by force, so it refuses any target that is not
strictly inside the calling package — a typo in a package.json should not be
able to reach the workspace root.
2026-08-11 23:11:04 +05:30

44 lines
1.7 KiB
JavaScript

// Removes build output for the package that invokes it.
//
// Why this exists: every workspace `clean` script used to be `rm -rf dist
// .turbo`, and `rm` does not exist on Windows. pnpm runs lifecycle scripts
// through the platform shell, so on Windows that is cmd.exe and all eleven of
// them died with "'rm' is not recognized". `turbo run clean` fans out to every
// package, so `pnpm clean` failed eleven times over.
//
// A shared script rather than a `rimraf` dependency: this needs no install to
// work, nothing to keep pinned against the release-age gate in
// pnpm-workspace.yaml, and no argument that has to survive two different
// shells' quoting rules. Node resolves forward slashes on Windows, so
// `node ../../scripts/clean.mjs dist .turbo` is literally the same string
// everywhere.
//
// Usage, from a package directory: node ../../scripts/clean.mjs <path>...
import { rmSync } from "node:fs";
import { isAbsolute, relative, resolve, sep } from "node:path";
const targets = process.argv.slice(2);
if (targets.length === 0) {
process.stderr.write("clean: nothing to remove (pass one or more paths)\n");
process.exit(1);
}
const cwd = process.cwd();
for (const target of targets) {
// This deletes recursively and by force, so it refuses anything that is not
// strictly inside the calling package. A typo in a package.json should not be
// able to reach the workspace root.
const abs = resolve(cwd, target);
const rel = relative(cwd, abs);
if (isAbsolute(target) || rel === "" || rel.startsWith(`..${sep}`)) {
process.stderr.write(
`clean: refusing to remove "${target}" — it escapes ${cwd}\n`
);
process.exit(1);
}
rmSync(abs, { force: true, recursive: true });
}