The output tree's name has always been configurable (vite.doxa-maps-build-config.json "name"), but 61 tooling files ignored it and hardcoded 'doxa-maps' (181 literals), so a rename would have moved the build while the gates kept reading the old folder. - internal/_tree-name.mjs reads it once (validated as one URL-safe path segment; falls back to the historical name) and exports TREE_NAME / TREE_NAME_RE; `node internal/_tree-name.mjs` prints it for shell scripts. - A codemod rewrote 171 literals in internal/ to TREE_NAME; the regex literals, messages with backticks, atomic-public-swap.sh (fails loudly if the name cannot be read), build-lock.sh and vite.config.js (its duplicate readMfeName is gone) were done by hand. - The name is unchanged: old and new tooling produce all 1408 files under public/ byte for byte. Code lines still naming the tree in internal/ + vite.config.js: 2, both intended (the helper's fallback, the private-repo-name pattern in public-hygiene-check). This renames nothing visible; the eventual rename becomes a one-line config change.
50 lines
2.4 KiB
JavaScript
50 lines
2.4 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* clean.mjs — wipe + recreate the default output tree root before a build.
|
|
*
|
|
* The output folder name is configurable (vite.doxa-maps-build-config.json `name`, default
|
|
* "doxa-maps"), so this reads the same config instead of hardcoding the name —
|
|
* otherwise renaming the tree would leave a stale folder behind. Runs BEFORE the
|
|
* per-bundle vite builds (which emit into public/<name>/); generate-tree.mjs runs after.
|
|
*/
|
|
import { readFileSync, rmSync, mkdirSync } from 'node:fs'
|
|
import { dirname, resolve } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { TREE_NAME } from './_tree-name.mjs'
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
|
|
function config() {
|
|
try {
|
|
const cfg = JSON.parse(readFileSync(resolve(__dirname, '..', 'vite.doxa-maps-build-config.json'), 'utf8'))
|
|
const name = (typeof cfg?.name === 'string' && cfg.name.trim()) ? cfg.name.trim() : TREE_NAME
|
|
const paths = Array.isArray(cfg?.paths) ? cfg.paths.filter(p => typeof p === 'string' && p.trim()) : []
|
|
return { name, paths }
|
|
} catch { return { name: TREE_NAME, paths: [] } }
|
|
}
|
|
|
|
const { name, paths } = config()
|
|
|
|
// ⭐ BUG FIXED 2026-07-30 — CLEAN EVERY DESTINATION, NOT JUST app/.
|
|
// This used to reset ONLY app/<name>/, leaving each `paths` destination untouched.
|
|
// Result: a RECURSIVE SELF-NESTING pollution that grew with every build —
|
|
// public/doxa-maps/<bundle>/doxa-maps/<bundle>/doxa-maps/...
|
|
// because generate-tree copies app/<name>/ into <path>/<name>/, and on the next
|
|
// build the (never-cleaned) nested copies were still there to be copied again.
|
|
// It shipped 7 duplicate copies of the same 576 KB bundle into git before it was
|
|
// caught by a pre-push file-size audit.
|
|
// LESSON: a clean step must clear EVERY output destination the build writes to.
|
|
// Cleaning only the canonical outDir is a silent, compounding leak.
|
|
// The build writes into public/<name>/ directly (public/ is the committed served
|
|
// web-root). Only that ONE subfolder is cleaned — never public/ itself, which also
|
|
// holds the shell and the pre-generated posters that are committed source.
|
|
const roots = [
|
|
resolve(__dirname, '..', 'public', name),
|
|
...paths.map(p => resolve(__dirname, '..', p, name)),
|
|
]
|
|
|
|
for (const root of roots) {
|
|
rmSync(root, { recursive: true, force: true })
|
|
mkdirSync(root, { recursive: true })
|
|
console.log(`[clean] reset ${root}`)
|
|
}
|