Skip to content

chore: migrate package manager bun → pnpm + test runner bun:test → Vite+ (vp test)#450

Merged
paul-phan merged 3 commits into
mainfrom
chore/migrate-bun-to-pnpm-viteplus
May 18, 2026
Merged

chore: migrate package manager bun → pnpm + test runner bun:test → Vite+ (vp test)#450
paul-phan merged 3 commits into
mainfrom
chore/migrate-bun-to-pnpm-viteplus

Conversation

@paul-phan
Copy link
Copy Markdown
Member

Mirrors the staged migration shipped on the weaverse-builder repo (PRs #2360, #2361, #2362, #2363), squashed into one consolidated change since the SDK monorepo is much smaller (216 tests, 6 packages).

What changed

Package manager (Stage 1 equivalent)

  • packageManager: bun@1.3.11pnpm@11.1.2
  • bun.lock deleted, pnpm-lock.yaml generated
  • bunfig.toml deleted
  • New pnpm-workspace.yaml:
    • nodeLinker: hoisted — flat node_modules so transitive deps keep resolving without explicit declarations (matches bun's behaviour)
    • allowBuilds — explicit allow-list for postinstall scripts (esbuild, lefthook, biome, workerd, @parcel/watcher); pnpm 11 blocks them by default as supply-chain hardening
    • verifyDepsBeforeRun: false — prevents infinite recursion when turbo invokes nested pnpm run build calls
    • catalog: block aliases vite@voidzero-dev/vite-plus-core, vitest@voidzero-dev/vite-plus-test, plus vite-plus CLI
  • .npmrc: kept legacy-peer-deps=true, added verify-deps-before-run=false mirror for safety
  • Root package.json:
    • scripts: npm run Xpnpm run X
    • new test:run script (vp test --run --bail=1)
    • removed prepare script (caused recursive install loops under pnpm 11; this is a private monorepo so consumers don't need it)
    • added vite, vite-plus, vitest devDeps via catalog

Test runner (Stage 2 equivalent)

  • New root vite.config.ts with test: block (node env, forks pool, 30s timeout, include/exclude patterns relative to cwd so it works both from repo root and from each package via turbo)
  • Per-package test scripts: bun testvp test --run (hydrogen, i18n, react, schema, cli — cli's was echo 'No tests' even though it had a real test file)
  • All 12 test files ported from 'bun:test'from 'vitest':
    • spyOn / mock aliased locally (const spyOn = vi.spyOn, const mock = vi.fn) to keep diffs minimal
    • mock.module(name, factory)vi.mock(name, factory) (i18n/__tests__/client.test.ts) — works identically since vitest hoists vi.mock calls
    • mock.restore()vi.restoreAllMocks() (react data-connector)
  • 3 standalone validation scripts that use the .test.ts suffix but contain no describe/it blocks excluded by name (core/blah, schema/enhanced-features, schema/type-alignment) — these should probably be renamed in a follow-up

CI (.github/workflows/check.yml)

  • Replaced oven-sh/setup-bun + bun cache with pnpm/action-setup + Node's built-in pnpm cache, keyed on pnpm-lock.yaml
  • Added a test job running pnpm run test

Tooling

  • lefthook.yml: bun run biomepnpm exec biome
  • scripts/clean.sh: already handled both lockfiles; no change needed

Docs (AGENTS.md, CLAUDE.md, ARCHITECTURE.md)

  • Command tables rewritten for pnpm
  • Test patterns updated to import from vitest and use vi.* API

Verification

All passing locally on macOS arm64, Node 20, pnpm 11.1.2:

Check Result
pnpm install clean (184 packages)
pnpm run typecheck 4 packages green
pnpm run build 5 packages green
pnpm run test (turbo orchestrated) 6 packages, 13 files, 216 tests passing
pnpm run test:run (single vp invocation) same
pnpm run biome no issues

paul-phan added 3 commits May 18, 2026 15:58
…te+ (vp test)

Mirrors the staged migration shipped on the `weaverse-builder` repo
(PRs #2360, #2361, #2362, #2363), squashed into one consolidated change
since the SDK monorepo is much smaller (216 tests, 6 packages).

## What changed

### Package manager (Stage 1 equivalent)
- `packageManager`: bun@1.3.11 → pnpm@11.1.2
- `bun.lock` deleted, `pnpm-lock.yaml` generated
- `bunfig.toml` deleted
- New `pnpm-workspace.yaml`:
  - `nodeLinker: hoisted` — flat node_modules so transitive deps keep
    resolving without explicit declarations (matches bun's behaviour)
  - `allowBuilds` — explicit allow-list for postinstall scripts
    (esbuild, lefthook, biome, workerd, @parcel/watcher); pnpm 11
    blocks them by default as supply-chain hardening
  - `verifyDepsBeforeRun: false` — prevents infinite recursion when
    turbo invokes nested `pnpm run build` calls
  - `catalog:` block aliases `vite` → @voidzero-dev/vite-plus-core,
    `vitest` → @voidzero-dev/vite-plus-test, plus `vite-plus` CLI
- `.npmrc`: kept `legacy-peer-deps=true`, added
  `verify-deps-before-run=false` mirror for safety
- Root `package.json`:
  - scripts: `npm run X` → `pnpm run X`
  - new `test:run` script (`vp test --run --bail=1`)
  - removed `prepare` script (caused recursive install loops under
    pnpm 11; consumers don't need it since this is a private monorepo)
  - added `vite`, `vite-plus`, `vitest` devDeps via catalog

### Test runner (Stage 2 equivalent)
- New root `vite.config.ts` with `test:` block (node env, forks pool,
  30s timeout, include/exclude patterns relative to cwd so it works
  both from repo root and from each package via turbo)
- Per-package `test` scripts: `bun test` → `vp test --run`
  (hydrogen, i18n, react, schema, cli — cli's was `echo 'No tests'`
  even though it had a real test file)
- All 12 test files ported `from 'bun:test'` → `from 'vitest'`:
  - `spyOn` / `mock` aliased locally (`const spyOn = vi.spyOn`,
    `const mock = vi.fn`) to keep diffs minimal
  - `mock.module(name, factory)` → `vi.mock(name, factory)`
    (i18n/__tests__/client.test.ts) — works identically since
    vitest hoists `vi.mock` calls
  - `mock.restore()` → `vi.restoreAllMocks()` (react data-connector)
- 3 standalone validation scripts that use the `.test.ts` suffix but
  contain no `describe`/`it` blocks excluded by name
  (core/blah, schema/enhanced-features, schema/type-alignment)

### CI (.github/workflows/check.yml)
- Replaced `oven-sh/setup-bun` + bun cache with `pnpm/action-setup`
  + Node's built-in pnpm cache, keyed on pnpm-lock.yaml
- Added a `test` job running `pnpm run test`

### Tooling
- `lefthook.yml`: `bun run biome` → `pnpm exec biome`
- `scripts/clean.sh`: already handled both lockfiles; no change needed

### Docs (AGENTS.md, CLAUDE.md, ARCHITECTURE.md)
- Command tables rewritten for pnpm
- Test patterns updated to import from `vitest` and use `vi.*` API

## Verification

All passing locally on macOS arm64, Node 20, pnpm 11.1.2:
  pnpm install            → 184 packages, clean
  pnpm run typecheck      → 4 packages, clean
  pnpm run build          → 5 packages, clean
  pnpm run test           → 6 packages, 13 files, 216 tests passing
  pnpm run test:run       → same
  pnpm run biome          → no issues
- paths-ignore: skip docs/md/workflow-only PRs
- concurrency: cancel in-progress reviews when new commits land
- skip drafts (`if: !pr.draft`)
- widen permissions (pull-requests: write, issues: write, actions: read)
  so the action can actually post sticky comments + track progress
- enable use_sticky_comment + track_progress
- actions/checkout v4 → v6

Same config that's been running cleanly on `weaverse-builder`.
Fixes the silent 'directory mismatch' failure mode we hit on this
PR's first review run.
@paul-phan paul-phan merged commit 5bbe5da into main May 18, 2026
9 of 10 checks passed
@paul-phan paul-phan deleted the chore/migrate-bun-to-pnpm-viteplus branch May 18, 2026 09:53
paul-phan added a commit that referenced this pull request May 19, 2026
…452)

Fixes #451.

`WeaverseHydrogenRoot` previously resolved `weaverseData` by walking `useMatches()` and returning the deepest match's payload. Because `useMatches()` is tree-global, every `<WeaverseContent />` instance on the same page resolved to the same value — making it impossible for two instances (e.g. a layout-loaded page + a child-loaded page) to render different Weaverse pages on the same URL.

This restores the route-scoped primitive via `useLoaderData()` for the `weaverseData` lookup, while keeping the existing `useMatches()`-driven `createWeaverseDataContext` infrastructure untouched (it legitimately needs all matches to build the route-keyed data-connector context).

Resolution policy, implemented as a pure helper `pickWeaverseData()`:

1. **Explicit `data` prop** (new — escape hatch + supports the typed `Route.ComponentProps.loaderData` framework-mode pattern). Passing `null` explicitly suppresses rendering.
2. **Own route's loader data** via `useLoaderData()` — the route-scoped primitive that fixes the bug.
3. **Ancestor walk** through `useMatches()` — back-compat fallback for the index-without-loader pattern.

`hasWeaverseData` requires the value be defined (not just present), so `{ weaverseData: undefined }` does not short-circuit Tier 2.

Back-compat: unmodified themes with zero-prop `<WeaverseContent />` continue to work via Tier 2 — identical render output for the common single-instance case. Index leaves without loaders continue to fall back to ancestor `weaverseData` via Tier 3. Deferred (`Promise`) loaders pass through unchanged. `data?` prop is optional; existing call sites compile unchanged.

Pilot template audit: every `<WeaverseContent />` caller has its own loader; no layout-loaded `weaverseData` exists. No pilot changes required.

Tests: 21 new selector unit tests covering all three tiers, `weaverseData: undefined` at both Tier 2 and Tier 3, `null`-suppression, deferred loaders, and an explicit #451 regression assertion.

Also includes a `chore` commit replacing remaining `bun` references with `pnpm` in the `releasing-weaverse-sdks` skill (follow-up to #450).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant