Skip to content

Ship shared vitest/tsconfig presets — start's examples carry ~262 lines of identical config copies #2

Open

Description

@btravers

Found while auditing btravstack/start (2026-08-13).

Measured across start's 11 example workspaces: ~262 lines of config files are byte-identical copies —

  • src/vitest.d.ts (import type {} from "@unthrown/vitest";): 11 identical copies
  • vitest.config.ts (the 9-line node/include/setupFiles/coverage block): 9 identical copies
  • tsconfig.test-d.json (6 lines): 9 identical copies
  • tsconfig.json: one 9-line "library" variant × 6, one 13-line "app" variant × 4
  • the same 3-script block (test / test:types / typecheck) in 9 of 11 package.json files

This repo already ships @btravstack/tsconfig; the same move covers the rest. Every btravstack monorepo with more than a couple of workspaces pays this copy tax, and drift between copies is silent (start's two divergent vitest.config.ts are legitimate, but nothing distinguishes a deliberate divergence from a stale copy).

Acceptance

  • A shared vitest preset (defineConfig-mergeable or an extendable base) covering environment, include, setupFiles: ["@unthrown/vitest"] and the coverage defaults, so a workspace's vitest.config.ts states only its deltas.
  • A published tsconfig.test-d.json base, and the library/app tsconfig variants if they are not already expressible from @btravstack/tsconfig.
  • start's examples adopt them and delete the copies.

Activity

  1. btravers commented on Sep 3, 2026

    @btravers
    ContributorAuthor

    Criterion 2 is shipped — @btravstack/tsconfig/test-d.json (#12, released in 0.4.0) and adopted across all nineteen of start's workspaces in btravstack/btravstack#258. Criterion 3 is done for that half: the copies are deleted.

    Leaving this open for criterion 1, the vitest preset, because measuring it argues against a published package and that is your call rather than mine.

    What the numbers look like now

    The issue's premise was "~262 lines of byte-identical copies" in start, and that "every btravstack monorepo with more than a couple of workspaces pays this copy tax". Measured across all four repos today, 52 vitest.config.ts files:

    repo configs byte-distinct
    start 24 5 of the 10 in examples/
    unthrown 15 12
    temporal-contract 5 5
    amqp-contract 8 7

    Two findings cut against a published preset:

    1. start already solved it locally, and recorded a decision about the remainder. vitest.shared.ts sits at the root and five example workspaces re-export it as a one-liner. Its own comment says why the rest are not extended:

    A workspace that needs more (coverage thresholds, globalSetup, a cache dir) writes its own config instead of extending this one — divergence should be visible in the workspace, not hidden in an override.

    2. The "common core" is not common across repos. setupFiles appears in 0 of unthrown's 15 configs — it is the library, so there is nothing to register. environment: "node" in 0 of temporal-contract's 5. include: ["src/**/*.spec.ts"] in 4 of amqp-contract's 8. A preset that three of four repos must override on its headline defaults is not a preset; it is a fourth thing to keep in sync.

    Recommendation

    Replicate the repo-local vitest.shared.ts pattern where a repo actually has near-identical configs, and do not publish @btravstack/vitest. That also avoids minting a new npm package, which has now cost two blocked releases waiting on Trusted Publisher setup (@unthrown/saga, @btravstack/tsconfig).

    If you would rather have the published preset anyway — for consistency across repos rather than for line count — say so and I will build it; the shape would be a defineConfig-mergeable base so a workspace states only its deltas, which does not conflict with the "divergence should be visible" rule since the deltas stay in the workspace file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions