diff --git a/README.md b/README.md index 58ba78c..20afbeb 100644 --- a/README.md +++ b/README.md @@ -218,7 +218,9 @@ development workflow, and the Makefile targets are thin shims that call them. We provide: - `script/bootstrap` — install all dependencies (pinned node via nvm if needed, - yarn via corepack, `yarn install --frozen-lockfile`) + yarn via corepack, `yarn install --frozen-lockfile`), then fail, naming the + package, if node cannot find a package listed in `dependencies` or + `devDependencies` of `package.json` - `script/setup` — make a fresh clone ready for development: bootstrap plus the git pre-commit hook - `script/projectname` — print the project name (used for the Docker image tag) diff --git a/TODO.md b/TODO.md index 225c833..a3db404 100644 --- a/TODO.md +++ b/TODO.md @@ -45,6 +45,15 @@ but the review is broader than any of them. # Completed Steps +- 2026-10-06: `script/bootstrap` no longer reports success while node cannot + find a package listed in `dependencies` or `devDependencies` of `package.json` + ([#263](https://git.eeqj.de/sneak/AutistMask/issues/263)). After the install + it asks node for each one's `package.json`, and fails naming the missing + package and the fix. yarn skips the install whenever + `node_modules/.yarn-integrity` matches `yarn.lock`, so a package deleted from + `node_modules` stayed deleted while bootstrap said it was complete. The + fresh-clone failure the issue reports did not reproduce. + - 2026-10-06: A token symbol or name read off a contract is no longer stored cut between the two halves of an emoji ([#458](https://git.eeqj.de/sneak/AutistMask/issues/458)). `lookupTokenInfo()` diff --git a/script/bootstrap b/script/bootstrap index 4df1d8c..a0a19ef 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -127,6 +127,40 @@ install_js_deps() { fi } +# run_node: run node from the repo root, through nvm when node is not on PATH; +# the script comes on stdin +run_node() { + if missing node && [ -s "$HOME/.nvm/nvm.sh" ]; then + nvm_sh "nvm use $NODE_VERSION >/dev/null && cd \"$ROOT\" && node" + else + node + fi +} + +# yarn install exits 0 without touching node_modules once +# node_modules/.yarn-integrity matches yarn.lock, so a package deleted from +# node_modules stays deleted. Fail unless node finds every package listed in +# dependencies and devDependencies of package.json, by its package.json. When a +# package's exports does not list that file, node throws +# ERR_PACKAGE_PATH_NOT_EXPORTED, which it can only do once it has found the +# package, so that error counts as found. +check_js_deps() { + run_node <<'EOF' +const { dependencies, devDependencies } = require("./package.json"); +for (const name of Object.keys({ ...dependencies, ...devDependencies })) { + try { + require.resolve(name + "/package.json"); + } catch (e) { + if (e.code !== "ERR_PACKAGE_PATH_NOT_EXPORTED") { + console.error(`bootstrap: node cannot find ${name} after yarn install`); + console.error(" fix: rm -rf node_modules && make bootstrap"); + process.exit(1); + } + } +} +EOF +} + main() { cd "$ROOT" @@ -136,6 +170,7 @@ main() { ensure_node ensure_yarn install_js_deps + check_js_deps echo "bootstrap complete" }