From b29f9244166436638be5c5ebfd0b78c4b7f89b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 11 Sep 2026 20:04:33 +0000 Subject: [PATCH] :wrench: Clean dist before each build tsc does not prune orphaned emit output, so dropping declarationMap left stale *.d.ts.map files in dist/ until a manual clean. A prebuild hook now empties dist/ first, keeping the build reproducible. It deliberately leaves coverage/ alone, since the manual `clean` resets both. --- README.md | 1 + cspell.json | 1 + package.json | 1 + 3 files changed, 3 insertions(+) diff --git a/README.md b/README.md index 0326550..3bdec4f 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ Each tool's configuration trade-off is recorded in [Tooling decisions](#tooling- The choice and configuration of each tool above is the result of deliberate trade-offs, not defaults. The non-obvious ones: - **`tsconfig.json` extends `@tsconfig/strictest` + `@tsconfig/node26`**; `tsconfig.build.json` extends it to add the emit-only options (`declaration`, `sourceMap`, `inlineSources`, `outDir`, `target: es2024`, `rewriteRelativeImportExtensions: true`) and to exclude test files. `inlineSources` embeds the original TypeScript in `dist/*.js.map`, so debuggers can map into `src/` without it being shipped; `declarationMap` is intentionally off because a `.d.ts.map` cannot embed source and would dangle. This separation lets the editor and CI type-check from one config while the build emits from the other. +- **`npm run build` first runs a `prebuild` hook that empties `dist/`.** `tsc` does not prune orphaned emit output — dropping `declarationMap`, for example, left stale `*.d.ts.map` files behind — so the build must start from an empty `dist/` to be reproducible. `prebuild` removes only `dist`; the manual `clean` still resets `dist` + `coverage`, so a local coverage report survives a build. - **Source imports use `.ts` extensions** so `node --strip-types` resolves them at test time. `rewriteRelativeImportExtensions: true` in `tsconfig.build.json` rewrites them to `.js` in the emitted JavaScript; the emitted `.d.ts` keep the `.ts` specifier, which TypeScript >= 5.0 resolves (see [Requirements](#requirements)), so no post-processing step is needed. - **Type-aware oxlint is enabled declaratively** via `options.typeAware: true` in `.oxlintrc.json` (powered by `oxlint-tsgolint`). The script commands stay clean — no CLI flag — and type-aware mode is a property of the config, not the invocation. - **Source-level `oxlint-disable` directives** are used for known type-aware false positives (see `src/pattern.ts`, `src/match.ts`, `src/index.test.ts`). The disable lives next to the code it silences, not in `.oxlintrc.json`, so the trade-off is visible to anyone reading the source. diff --git a/cspell.json b/cspell.json index 0af72ba..58d50e3 100644 --- a/cspell.json +++ b/cspell.json @@ -28,6 +28,7 @@ "runwisp", "glab", "postversion", + "prebuild", "Zilla", "kacl", "bestikk", diff --git a/package.json b/package.json index 317b12e..ee3234f 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ }, "scripts": { "build": "tsc -p tsconfig.build.json", + "prebuild": "rm -rf dist", "check": "npm run check:tsc && npm run check:oxlint && npm run check:oxfmt && npm run check:cspell", "check:cspell": "cspell lint ${LEFTHOOK_FILES:-.}", "check:oxfmt": "oxfmt --check ${LEFTHOOK_FILES:-.}",