@turystack/config
v1.1.0
Published
The Turystack baseline: the biome, TypeScript and vitest decisions that do not depend on where the code runs.
Readme
@turystack/config
The Turystack baseline: the biome, TypeScript and vitest decisions that do not depend on where the code runs.
Installation
pnpm add -D @turystack/configPresets
{
"extends": ["@turystack/config/biome"]
}Available: @turystack/config/biome, @turystack/config/tsconfig,
@turystack/config/vitest
Where it sits
@turystack/config the root of a monorepo, and the floor under both
├── @turystack/backend-config APIs, handlers, domains, backend packages
└── @turystack/frontend-config web and mobile applicationsThe root of a monorepo is neither a backend nor a frontend, so it extends this
package directly. A backend package extends @turystack/backend-config, a
frontend one @turystack/frontend-config, and either may list this package
alongside its own:
{
"extends": ["@turystack/config/biome", "@turystack/backend-config/biome"]
}The order matters — later entries win — so the kind's configuration comes last.
What Biome does and does not do with extends
Three behaviours decide what can live here, and each was measured rather than read:
| Shape | What happens |
| --- | --- |
| extends: ["@turystack/config/biome"] | applies |
| extends: ["a", "b"] | both apply, b winning |
| a config reached through extends that itself extends another | ignored, silently |
The third is why @turystack/backend-config does not extend this package.
It cannot: Biome reads the nested extends, applies none of it, reports no
diagnostic and exits zero — the repository is then formatted with Biome's
defaults and nothing says so. So the two kind packages restate the blocks they
share with this one, and each ships scripts/check-baseline.mjs, which fails
their build when a shared block here and there stop matching.
config's own fixture asserts the limitation still holds. If that assertion
ever fails, Biome has started following the chain and the restating can be
replaced by extending.
What belongs here
A decision belongs in this package when it is true of any Turystack TypeScript: the formatter's shape, the strictness flags, the coverage floor, the order of the import groups every package shares.
A decision does not belong here when it names a path. Biome reads a path
inside a shared configuration relative to the folder that extends it, so a
plugins entry written here resolves against the consumer and finds nothing —
which is why the GritQL lists live in the two packages above and are repeated in
each generated project.
Two more shapes decide what a consumer can and cannot undo:
| Key | Through extends |
| --- | --- |
| files.includes, overrides | concatenated — what is written here is added to every consumer |
| assist › organizeImports › groups | replaced — a consumer that sets it ignores this one entirely |
| everything else | deep-merged, the consumer winning |
So files.includes here is the intersection of what the two packages above
already had, and never more: an entry added here appears in every project that
extends either of them.
The import groups name @repo as the scope a repository's own packages live
under. A repository generated by the Turystack CLI is scoped by its own name
instead — @acme/database — and writes its own groups for that reason, which
replaces this one entirely.
