chore(build): give the shared build config one home each - #60
Merged
Conversation
Three pieces of per-package plumbing that had been copy-pasted nine times, with no mechanism keeping the copies in step. SWC config. Sixteen of the eighteen `.swcrc` / `.swcrc-cjs` files were byte-for- byte the same settings; `nestize` held the only real difference (legacy decorators). The shared pair now lives at the repo root and is reached with `--config-file`, which is the mechanism the CJS build already used. A package that needs its own keeps it, and `swc-build.ts` prefers a local file when one exists — so the exception lives next to the package it belongs to rather than in a list somewhere else. Note for anyone tempted by the tidier spelling: SWC has no `extends` in `.swcrc`. It rejects the key outright and enumerates the fields it does accept. `--config-file` is the supported route. SWC flags. The invocation was repeated verbatim in nine manifests, including `--out-file-extension mjs --strip-leading-paths -s --ignore "**/*.d.ts"`, where one package quietly losing a flag would produce a subtly different published artifact. It now lives once in `scripts/build/swc-build.ts`, beside the `fix-esm-extensions` and `prepare-package` scripts that were already shared. Verified byte-identical output before and after, per package and per format. Jest config. Only the resolution/compilation block and the coverage block were genuinely common — and the four-line comment explaining `collectCoverageFrom` had nine homes, so nine chances to stop being true. Those are now `baseProject` / `coverage` / `conventions` in `scripts/jest/base-config.js`. Everything else stays where it is, because it is load-bearing and specific: `maxWorkers: 1` wherever suites share a process-global sequelize/model registry, `forceExit` where ioredis holds handles past the last suite, the `TEMPORALIZE_INTEGRATION` gate on a suite that downloads a Temporal server, and nestize's decorator transform. An earlier pass at this collapsed all nine to one call and broke four suites; the base is deliberately partial as a result. Dependency versions. 27 toolchain packages move to a pnpm catalog, so `@swc/core`, `jest`, `tsx` and `typescript` are pinned once instead of nine times. There was no drift — it was maintained by hand, which is the reason to make it structural. devDependencies only, and that boundary is load-bearing: `prepare-package.ts` strips devDependencies from the published manifest but does not resolve `catalog:`, so a catalog reference in `dependencies` or `peerDependencies` would be published verbatim and break installs. Anything that is also a runtime or peer dependency is excluded for that reason — and the peer ranges are deliberately wider than the dev pin beside them (`graphql` `^17.0.0` against `17.0.2`, `sequelize` `^6.35.1` against `^6.37.7`), which a single shared version would silently narrow. No behaviour change. Verified: full build across all nine packages, artifacts compared (decorators present in both formats, ESM specifiers rewritten, CJS still CJS), `pnpm install --frozen-lockfile` resolves, and coverage denominators are unmoved — a broken `collectCoverageFrom` reports less rather than failing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019fGumVzMfMXDZ5vS7PJGDW
Azerothian
force-pushed
the
chore/build-plumbing
branch
from
September 1, 2026 00:03
5da8368 to
bacf165
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Group 2 of the condense/dedupe/optimise pass. Pure plumbing — no behaviour change, no source touched.
Three pieces of per-package config that had been copy-pasted nine times with nothing keeping the copies in step.
SWC config: 18 files → 2 + one override
16 of the 18
.swcrc/.swcrc-cjsfiles were the same settings byte-for-byte;nestizeheld the only real difference (legacy decorators). The shared pair moves to the repo root, reached via--config-file— the mechanism the CJS build already used.swc-build.tsprefers a local.swcrcwhen one exists, so the exception lives next to the package it belongs to rather than in a list elsewhere.SWC flags: 9 copies → 1
This was repeated verbatim in nine manifests:
One package quietly losing a flag would produce a subtly different published artifact. Now in
scripts/build/swc-build.ts, besidefix-esm-extensionsandprepare-package, which were already shared.Jest config: 203 lines → 32 + a partial base
Only the resolution/compilation block and the coverage block were genuinely common — and the four-line
collectCoverageFromcomment had nine homes, so nine chances to stop being true.The base is deliberately partial. An earlier pass collapsed all nine configs to one call and broke four suites. These stay per-package because they are load-bearing:
maxWorkers: 1forceExitTEMPORALIZE_INTEGRATIONgateDependency versions: pnpm catalog
27 toolchain packages pinned once instead of nine times. There was no drift — it was maintained by hand, which is precisely the reason to make it structural.
devDependencies only, and that boundary matters.
prepare-package.tsstrips devDependencies from the published manifest but does not resolvecatalog:— so a catalog reference independenciesorpeerDependencieswould publish verbatim and break installs. Anything that is also a runtime or peer dep is excluded, and the peer ranges are deliberately wider than the dev pin beside them (graphql^17.0.0vs17.0.2,sequelize^6.35.1vs^6.37.7) — a single shared version would silently narrow them.Verification
pnpm buildacross all 9 packages, artifacts compared before/after: decorators present in both ESM and CJS output, ESM specifiers rewritten, CJS still CJSpnpm install --frozen-lockfileresolvescollectCoverageFromreports less, it does not fail, so this was checked explicitlypnpm typecheckandpnpm lintcleanStacked on top of #59 conceptually but independent — this branch is off
mainand touches no source files.🤖 Generated with Claude Code
https://claude.ai/code/session_019fGumVzMfMXDZ5vS7PJGDW