fix(docs): cap vite below 7 (rolldown-vite) and pin mermaid transitives #161

Merged
julien merged 1 commits from fix/docs-site-cap-vite-below-rolldown into main 2026-05-15 23:57:58 +02:00
Owner

Summary

pnpm docs:dev failed after #159's transitive-vuln fix landed. Two distinct symptoms in the same log :

  1. VitePress refused to bootVitePress v1 is not compatible with rolldown-vite. Use VitePress v2 instead. The override added in #159 (vite@<6.4.2 → >=6.4.2) had no upper bound; pnpm resolved vitepress's vite ^5.0.0 constraint up to vite 7.3.2, which uses the new rolldown bundler. VitePress 1.x explicitly rejects rolldown-vite.

  2. Resolution-warning flood — Even on a fallback port, the console showed Failed to resolve dependency: dayjs / debug / @braintree/sanitize-url / cytoscape / cytoscape-cose-bilkent from optimizeDeps.include. The vitepress-plugin-mermaid wrapper injects those into the optimizer's include list, but under pnpm's strict isolation they aren't reachable from the workspace root (transitives of mermaid, never hoisted).

What lands

1. Vite override is now an unconditional >=6.4.2 <7 range

package.json:

- "vite@<6.4.2": ">=6.4.2",
+ "vite": ">=6.4.2 <7",

The selector form (vite@<6.4.2) was a no-op once vite had resolved into 7.x — the override only activates when the resolved version is in the vulnerable range. Vite 7 is ≥ 6.4.2, so the override stayed dormant and rolldown-vite slipped through.

The unconditional form forces a downgrade across every consumer (vitepress, @nx/vite, @analogjs/vite-plugin-angular, Vitest, etc.). All six top-level projects still lint, test, and build under vite 6.4.2.

Trade-off acknowledged: we're now pinning the whole workspace to vite 6.x to keep VitePress 1.x happy. The day VitePress 2 ships a 1.0 (currently in beta), we revisit and let vite advance again. Tracked as a soft follow-up.

2. optimizeDeps.include simplified to ['mermaid']

docs/.vitepress/config.mts:

- include: ['mermaid', 'dayjs', 'debug', '@braintree/sanitize-url'],
+ include: ['mermaid'],

Vite 6's dep optimizer walks Mermaid's transitives automatically once Mermaid itself is in include. The explicit child list from #157 was carried forward in the rolldown attempt and tripped on vite's stricter resolver — collapsing it now both removes the noise and matches what the plugin's docs recommend for vite 6.

3. Mermaid transitives pinned as top-level devDeps

package.json:

+ "@braintree/sanitize-url": "^7.1.2",
+ "cytoscape": "^3.33.3",
+ "cytoscape-cose-bilkent": "^4.1.0",
+ "dayjs": "^1.11.20",
+ "debug": "^4.4.3",

These are already in node_modules (pulled in by mermaid). Declaring them at the workspace root makes them reachable from optimizeDeps.include under pnpm's strict isolation, which silences the five "Failed to resolve dependency" warnings the plugin's wrapper produced.

Cost: five extra devDep lines in package.json whose only purpose is to make the optimizer happy. Acceptable — they don't influence the resolved tree, just the resolver's reachability rules.

Notes for the reviewer

  • Why not bump VitePress 1 → 2? VitePress 2 is still beta. Per CLAUDE.md §"Project rules": pre-1.0 dependencies and one-maintainer projects are rejected unless an ADR justifies the exception. ADR-0022 already records VitePress 1.6.4 as the chosen baseline; switching to a beta on the very first follow-up PR would burn the rationale.
  • Why an unconditional vite range, not a tighter selector? The selector form (vite@vulnerable-range → patched-range) is the standard pattern when the parent dep's own range includes a patched version — pnpm picks it naturally and the override never fires. Here vite's 5.x branch was never patched (5.4.21 stayed vulnerable; vite team moved on to 6.x), so we need to force the downgrade from 7.x to 6.x regardless of the previous resolution. An unconditional override is the cleanest expression of that intent.
  • Why not extract the mermaid-transitive pins into the ADR-0022 trail? They're plumbing for the plugin wrapper, not an architectural decision worth recording. If the plugin ships a fix that removes the include list, these can be removed without consequence. Pinning them is reversible.

Test plan

  • pnpm install clean; lockfile changes reflect vite 6.4.2 across all consumers.
  • pnpm audit --audit-level=moderateNo known vulnerabilities found.
  • pnpm docs:dev — server boots cleanly on :5173, no warnings, home + ADR-0009 page return 200.
  • pnpm docs:build — clean build in ~9 s (back to Rollup-based timings; the rolldown 3.87 s we saw briefly was the incompatible path).
  • pnpm exec nx run-many -t lint test --projects=portal-shell,portal-admin,portal-bff,shared-ui,shared-state,feature-auth — 12/12 tasks green under the vite 6 downgrade.
  • pnpm exec nx build portal-shell — clean Angular production build; no Vite 6 incompatibility surfaced.
  • Manual smoke (visual)pnpm docs:dev, open http://localhost:5173, navigate to /decisions/0009-… and /architecture, confirm Mermaid diagrams render inline (this is the actual UX the user opened the issue on). Dark mode toggle still flips diagrams.

Follow-ups (optional)

  • When VitePress 2 reaches 1.0 (vue/vitepress > releases), revisit this override and let vite resume its mainline cadence.
  • If the next Renovate cycle proposes a cytoscape / dayjs / debug major bump that VitePress 1.x can't keep up with, the pins above act as the safety net — Renovate will open a PR rather than silently break the dev server.
## Summary `pnpm docs:dev` failed after #159's transitive-vuln fix landed. Two distinct symptoms in the same log : 1. **VitePress refused to boot** — `VitePress v1 is not compatible with rolldown-vite. Use VitePress v2 instead.` The override added in #159 (`vite@<6.4.2 → >=6.4.2`) had no upper bound; pnpm resolved vitepress's `vite ^5.0.0` constraint up to **vite 7.3.2**, which uses the new rolldown bundler. VitePress 1.x explicitly rejects rolldown-vite. 2. **Resolution-warning flood** — Even on a fallback port, the console showed `Failed to resolve dependency: dayjs / debug / @braintree/sanitize-url / cytoscape / cytoscape-cose-bilkent` from `optimizeDeps.include`. The vitepress-plugin-mermaid wrapper injects those into the optimizer's include list, but under pnpm's strict isolation they aren't reachable from the workspace root (transitives of mermaid, never hoisted). ## What lands ### 1. Vite override is now an **unconditional** `>=6.4.2 <7` range [`package.json`](package.json): ```diff - "vite@<6.4.2": ">=6.4.2", + "vite": ">=6.4.2 <7", ``` The selector form (`vite@<6.4.2`) was a no-op once vite had resolved into 7.x — the override only activates when the resolved version is _in_ the vulnerable range. Vite 7 is ≥ 6.4.2, so the override stayed dormant and rolldown-vite slipped through. The unconditional form forces a downgrade across every consumer (vitepress, `@nx/vite`, `@analogjs/vite-plugin-angular`, Vitest, etc.). All six top-level projects still lint, test, and build under vite 6.4.2. **Trade-off acknowledged**: we're now pinning the whole workspace to vite 6.x to keep VitePress 1.x happy. The day VitePress 2 ships a 1.0 (currently in beta), we revisit and let vite advance again. Tracked as a soft follow-up. ### 2. `optimizeDeps.include` simplified to `['mermaid']` [`docs/.vitepress/config.mts`](docs/.vitepress/config.mts): ```diff - include: ['mermaid', 'dayjs', 'debug', '@braintree/sanitize-url'], + include: ['mermaid'], ``` Vite 6's dep optimizer walks Mermaid's transitives automatically once Mermaid itself is in `include`. The explicit child list from #157 was carried forward in the rolldown attempt and tripped on vite's stricter resolver — collapsing it now both removes the noise and matches what the plugin's docs recommend for vite 6. ### 3. Mermaid transitives pinned as top-level devDeps [`package.json`](package.json): ```diff + "@braintree/sanitize-url": "^7.1.2", + "cytoscape": "^3.33.3", + "cytoscape-cose-bilkent": "^4.1.0", + "dayjs": "^1.11.20", + "debug": "^4.4.3", ``` These are already in `node_modules` (pulled in by mermaid). Declaring them at the workspace root makes them reachable from `optimizeDeps.include` under pnpm's strict isolation, which silences the five "Failed to resolve dependency" warnings the plugin's wrapper produced. Cost: five extra devDep lines in `package.json` whose only purpose is to make the optimizer happy. Acceptable — they don't influence the resolved tree, just the resolver's reachability rules. ## Notes for the reviewer - **Why not bump VitePress 1 → 2?** VitePress 2 is still beta. Per [CLAUDE.md](CLAUDE.md) §"Project rules": pre-1.0 dependencies and one-maintainer projects are rejected unless an ADR justifies the exception. ADR-0022 already records VitePress 1.6.4 as the chosen baseline; switching to a beta on the very first follow-up PR would burn the rationale. - **Why an unconditional vite range, not a tighter selector?** The selector form (`vite@vulnerable-range → patched-range`) is the standard pattern when the parent dep's own range *includes* a patched version — pnpm picks it naturally and the override never fires. Here vite's 5.x branch was never patched (5.4.21 stayed vulnerable; vite team moved on to 6.x), so we need to force the downgrade from 7.x to 6.x regardless of the previous resolution. An unconditional override is the cleanest expression of that intent. - **Why not extract the mermaid-transitive pins into the ADR-0022 trail?** They're plumbing for the plugin wrapper, not an architectural decision worth recording. If the plugin ships a fix that removes the include list, these can be removed without consequence. Pinning them is reversible. ## Test plan - [x] `pnpm install` clean; lockfile changes reflect vite 6.4.2 across all consumers. - [x] `pnpm audit --audit-level=moderate` — **No known vulnerabilities found**. - [x] `pnpm docs:dev` — server boots cleanly on `:5173`, no warnings, home + ADR-0009 page return 200. - [x] `pnpm docs:build` — clean build in ~9 s (back to Rollup-based timings; the rolldown 3.87 s we saw briefly was the incompatible path). - [x] `pnpm exec nx run-many -t lint test --projects=portal-shell,portal-admin,portal-bff,shared-ui,shared-state,feature-auth` — 12/12 tasks green under the vite 6 downgrade. - [x] `pnpm exec nx build portal-shell` — clean Angular production build; no Vite 6 incompatibility surfaced. - [ ] **Manual smoke (visual)** — `pnpm docs:dev`, open `http://localhost:5173`, navigate to `/decisions/0009-…` and `/architecture`, confirm Mermaid diagrams render inline (this is the actual UX the user opened the issue on). Dark mode toggle still flips diagrams. ## Follow-ups (optional) - When VitePress 2 reaches 1.0 (`vue/vitepress > releases`), revisit this override and let vite resume its mainline cadence. - If the next Renovate cycle proposes a `cytoscape` / `dayjs` / `debug` major bump that VitePress 1.x can't keep up with, the pins above act as the safety net — Renovate will open a PR rather than silently break the dev server.
julien added 1 commit 2026-05-15 23:54:37 +02:00
fix(docs): cap vite below 7 (rolldown-vite) and pin mermaid transitives
CI / scan (pull_request) Successful in 2m58s
CI / commits (pull_request) Successful in 2m58s
CI / check (pull_request) Successful in 4m56s
CI / a11y (pull_request) Successful in 2m17s
Docs site / build (pull_request) Successful in 2m7s
CI / perf (pull_request) Successful in 5m54s
003dc35f71
`pnpm docs:dev` failed with two distinct symptoms after #159 forced
vite past its vulnerable 5.x line:

1. VitePress refused to boot with `VitePress v1 is not compatible
   with rolldown-vite. Use VitePress v2 instead.` The previous
   override `vite@<6.4.2 → >=6.4.2` had no upper bound; pnpm
   resolved vitepress's `vite ^5.0.0` constraint up to vite 7.3.2,
   which uses the new rolldown bundler and is explicitly rejected
   by VitePress 1.x.

2. Even when the server eventually booted on a different port, the
   console was flooded with `Failed to resolve dependency: dayjs,
   debug, @braintree/sanitize-url, cytoscape, cytoscape-cose-bilkent`
   — the vitepress-plugin-mermaid wrapper injects those into
   `optimizeDeps.include` but they aren't reachable from the
   workspace root under pnpm's strict isolation (transitives of
   mermaid, never hoisted).

Three changes:

* `pnpm.overrides.vite` is now an **unconditional** `>=6.4.2 <7`
  range (not the previous `<6.4.2 → >=6.4.2` selector). The
  selector form was a no-op once vite had already resolved into
  7.x; the unconditional form forces a downgrade to 6.4.2 across
  every consumer (vitepress, @nx/vite, @analogjs, Vitest). All
  six top-level projects still lint, test, and build.

* `optimizeDeps.include` simplified to `['mermaid']`. Vite 6's
  dep optimizer walks Mermaid's transitives automatically once
  Mermaid itself is included, so the explicit list of children
  the previous fix carried (#157) becomes redundant.

* `dayjs`, `debug`, `@braintree/sanitize-url`, `cytoscape`,
  `cytoscape-cose-bilkent` are pinned as **top-level devDeps**.
  The vitepress-plugin-mermaid wrapper expects them at the
  workspace root; under pnpm's strict isolation a transitive of
  mermaid isn't reachable from a `optimizeDeps.include` lookup
  unless the workspace declares it. Pinning silences the
  resolution warnings without changing the resolved tree (these
  packages were already present via mermaid).

Verification: `pnpm docs:dev` boots clean on :5173, home + ADR
pages return 200, no warnings. `pnpm docs:build` succeeds in ~9 s.
`pnpm audit --audit-level=moderate` reports zero vulnerabilities.
`pnpm exec nx run-many -t lint test build` for the 6 main projects
all pass.
julien merged commit 2dbf2d8ce4 into main 2026-05-15 23:57:58 +02:00
julien deleted branch fix/docs-site-cap-vite-below-rolldown 2026-05-15 23:58:01 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: julien/apf_portal#161