Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
status: accepted, partly superseded by ADR-0055 (pnpm installs and runs the scripts, Vite+ runs the tasks instead of Turborepo, and type-aware lint runs on Vite+'s bundled tsgolint instead of tsrslint; tsrs still typechecks)
status: accepted, partly superseded by ADR-0055 (pnpm installs and runs the scripts, Vite+ runs the tasks instead of Turborepo, and tsrs's own linter replaces tsrslint as the type-aware lint backend, through a pnpm override instead of `scripts/link-tsrslint.sh`; tsrs still typechecks)
---

# Bun installs and runs scripts, tsrs typechecks, and Vitest stays on Node
Expand Down
11 changes: 6 additions & 5 deletions docs/adr/0055-vite-plus-and-pnpm.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@ status: accepted

# pnpm installs, and Vite+ checks, lints, formats and runs the tasks

The repo installs with pnpm again, and its toolchain is Vite+ (`vite-plus`): `vp check` formats, lints and runs the type-aware lint once at the root, `vp run` runs every package's tasks and caches them, and `vp staged` with `.vite-hooks/` replaces lint-staged and Husky. This replaces [ADR-0028](0028-bun-for-installs-and-scripts-and-tsrs-for-typecheck.md)'s Bun, Turborepo and tsrslint; each package's typecheck stays `effect-tsgo tsrs`, for the Effect diagnostics that `vp check`'s type-check does not run.
The repo installs with pnpm again, and its toolchain is Vite+ (`vite-plus`): `vp check` formats, lints and runs the type-aware lint (on tsrs's linter) once at the root, `vp run` runs every package's tasks and caches them, and `vp staged` with `.vite-hooks/` replaces lint-staged and Husky. This replaces [ADR-0028](0028-bun-for-installs-and-scripts-and-tsrs-for-typecheck.md)'s Bun and Turborepo, and `scripts/link-tsrslint.sh`, which made tsrslint oxlint's type-aware backend; each package's typecheck stays `effect-tsgo tsrs`, for the Effect diagnostics that `vp check`'s type-check does not run.

- **pnpm** (`packageManager`, `mise.toml`): `pnpm-workspace.yaml` holds the workspace, the patched dependencies, the packages allowed to run install scripts (`allowBuilds`: the pnpm list from before ADR-0028, with `core-js-pure` still blocked and `just-bash`'s optional compressors now blocked too, as ADR-0028 found they serve only its Node command line; `typescript`, which Bun had to trust for the effect-tsgo patch, needs no entry under pnpm) and the exemptions from pnpm's default minimum release age of a day. Workspace dependencies stay plain `"*"` for npm's production install of the root (`pi install git:…`), so `linkWorkspacePackages` links them. `dedupePeers` tells peer variants apart by their peers' versions alone: without it the server had two `@cloudflare/computer`s, and `infra` two `alchemy`s (one per `ws`, which an override now holds at one version), and their typechecks failed.
- **One config** (`vite.config.ts` at the root): the lint rules, the anti-slop plugins and every package's own rules (as `lint.overrides` by path; Vite+ reads no nested lint or format config), the format settings and the staged-file rules. `vp check` runs at the root, not per package: it lints the whole repo in one process.
- **Tasks** (`packages/config/src/tasks.ts`, passed to `run.tasks` by each package's `vite.config.ts`): `typecheck` and `test`. Vite Task records the files each task reads and replays a task none of whose inputs changed, so a change to a package's source reruns its dependents' tasks without Turborepo's `transit` node or `apps/web/turbo.json`'s hand-listed inputs. A cached task runs in a clean environment, so `test` names the variables that change what a test checks (`CI`, the live tests' and benchmarks' switches, `UPDATE_SNAPSHOT`) and passes the rest through untracked. `test` is `vitest run`, not `vp test`: Vite Task runs a `vp test` inside the `vp` that started it, with that copy's Vitest, and a `vp` that is not the project's (mise's `npm:vite-plus`) gives the workerd projects a second Vitest, which `@cloudflare/vitest-plugin`'s worker cannot reach.
- **Versions**: `vite-plus` 1.4.0, the last release that bundles Vitest 5.0.5; 1.5 and 1.6 bundle 5.1, under which the workerd tests fail (docs/development/dependencies.md). Overrides make every `vite` Vite+'s core and every `vitest` 5.0.5. Vite+ 1.4.0 bundles oxlint 1.89, oxfmt 0.74 and tsgolint 7.0.2004, older than the 1.91, 0.76 and tsrslint they replace; oxfmt 0.74 wraps three signatures differently, reformatted with the switch.
- **Versions**: `vite-plus` 1.4.0, the last release that bundles Vitest 5.0.5; 1.5 and 1.6 bundle 5.1, under which the workerd tests fail (docs/development/dependencies.md). Overrides make every `vite` Vite+'s core and every `vitest` 5.0.5. Vite+ 1.4.0 bundles oxlint 1.89 and oxfmt 0.74, older than the 1.91 and 0.76 they replace (tsrs's linter, which speaks tsgolint 7.0.2005's protocol, runs under 1.89); oxfmt 0.74 wraps three signatures differently, reformatted with the switch.
- **CI** sets up with `voidzero-dev/setup-vp`, which installs the Vite+ of the root `package.json` (so its `vp` runs the project's copy), Node and pnpm, and caches pnpm's store. Each check part restores and saves its Vite Task cache (`node_modules/.vite/task-cache`) under a rolling key and clears it past 1 GiB, since Vite Task never evicts.

Measured on an 8-core Apple Silicon laptop (2026-11-12), warm caches:

- **Lint**: `vp lint` over the whole repo, type-aware with type-check, 16 s wall, 48 s of CPU, 3.6 GB peak memory (ADR-0028's tsrslint, one package after another: 18–24 s, 19 s, 0.47 GB).
- **Lint**: `vp lint` over the whole repo, type-aware with type-check, on tsrs 0.24's linter: 7–8 s wall, 15 s of CPU, 0.9–1.0 GB peak memory (two runs); on tsrslint 0.1.6: 9–10 s, 13–14 s, 1.5–2.1 GB; on Vite+'s own tsgolint 7.0.2004: 16 s, 48 s, 3.6 GB (ADR-0028's tsrslint, one package after another: 18–24 s, 19 s, 0.47 GB).
- **Typecheck**: `vp run -r typecheck`, 7–11 s uncached; 0.9 s when every task replays.
- **Tests**: `vp run -r test`, 4 min uncached; 1 min when only the tasks that modify their own inputs (`@cloudpid/mcp`'s import-rule test plants files) and `@cloudpid/sandbox-image`'s, which is uncached, run again.
- **Install** with a warm store and no `node_modules`, `prepare` included: 5.1 s wall, 1.1 s of user CPU (ADR-0028: Bun 0.85 s, pnpm 2.4 s, before `prepare`'s `vp config`).

## Consequences

- The type-aware lint is tsgolint again, not tsrslint: Vite+ sets `OXLINT_TSGOLINT_PATH` to its own `oxlint-tsgolint` and ignores `node_modules/.bin/tsgolint`. It takes more memory than tsrslint in one process, but runs once rather than per package. `scripts/link-tsrslint.sh` and `@maschwenk/tsrslint` are gone.
- The type-aware lint runs on tsrs's own linter (`tsrs-lint`, `tsrs --lint`, since tsrs 0.21: tsgolint's headless protocol and its 61 type-aware rules), which replaces tsrslint, its predecessor outside tsrs. Vite+ sets `OXLINT_TSGOLINT_PATH` to the `bin/tsgolint` of its own `oxlint-tsgolint` and ignores `node_modules/.bin`, so `scripts/link-tsrslint.sh` is gone, and a pnpm override makes `oxlint-tsgolint` the repo's `tools/tsrs-lint-shim`, whose `bin/tsgolint.js` loads the root `tsrs` package's `tsrs-lint`. It rests on where Vite+ looks for its backend (docs/development/dependencies.md says what to check on an upgrade). The shim has no `package.json`, or `effect-tsgo patch` finds it as Vite+'s `oxlint-tsgolint` and fails `prepare` looking for tsgolint's platform binary. The `tsrs` package is the linter only: `effect-tsgo tsrs` typechecks with the Effect-patched tsrs that `@effect/tsgo` ships. It goes once `effect-tsgo --tsrs-lint vp lint` (`@effect/tsgo` 0.68 and later: Vite+'s lint on the Effect-patched tsrs, with the Effect rules, and no shim) can run, which needs oxlint 1.91 or later, so a Vite+ past 1.4.0 (`Versions`). The shim does not run on Windows, where Vite+ looks for `tsgolint.exe` or `tsgolint.cmd` in `.bin`, not the `.js` the shim is; tsrs itself ships for macOS, Linux (glibc and musl) and Windows.
- Run the project's own `vp`: `pnpm exec vp`, the root scripts, or the standalone global CLI from vite.plus, which hands a command to the project's copy. mise's `npm:vite-plus` is a second copy of the whole toolchain.
- Turborepo's CI pruning is gone; the Vite Task cache is experimental in CI (Vite+'s docs say so) and is bounded by size instead.
- On macOS, Vite Task runs a cached task's system coreutils as uutils' to record what it reads. The tests that probe the host for GNU coreutils check `--version` for `(GNU coreutils)`, and `@cloudpid/sandbox-image`'s `test` is uncached, since its memory-guard tests fail under uutils. Linux is unaffected.
Expand All @@ -34,4 +34,5 @@ Measured on an 8-core Apple Silicon laptop (2026-11-12), warm caches:
- **Keeping Bun with Vite+.** Vite+ supports Bun, but the owner chose pnpm; Bun's install speed was most of ADR-0028's case for it, and pnpm's global virtual store is available where it matters, on the Container.
- **Keeping Turborepo with Vite+'s lint and format.** Turborepo's `transit` node and hand-listed inputs were what Vite Task's file tracking does by itself, and one task runner is one less tool.
- **Vite+ 1.6 with Vitest 5.1.** The workerd tests fail under Vitest 5.1 (dependencies.md); 1.4.0 holds Vitest at 5.0.5 until that is fixed.
- **tsrslint behind `vp lint`** (an override of `oxlint-tsgolint` with a package that runs tsrslint). Possible, but a shim around a shim; one lint over the repo already costs about what the per-package tsrslint runs did.
- **Vite+'s own tsgolint**, with nothing to keep in step with Vite+. One lint over the repo on it took 16 s and 3.6 GB against tsrs's 7–8 s and 1.0 GB at most, and needs no shim, but ADR-0028 chose a linter on tsrs for that cost, and the shim is one file.
- **tsrslint** (`@maschwenk/tsrslint`) behind the same shim. It worked (9–10 s, 2.1 GB at most), but tsrs now ships the same port itself, and its author means to fold tsrslint into it.
Loading
Loading