From 629d609792828be10b53072c50e09a98050b8e76 Mon Sep 17 00:00:00 2001 From: maulanasdqn Date: Tue, 31 Mar 2026 16:29:00 +0700 Subject: [PATCH] chore: remove tools/ai-migrations generated by nx migrate Co-Authored-By: Claude Opus 4.6 --- tools/ai-migrations/MIGRATE_NEXT_16.md | 845 ------------------------ tools/ai-migrations/MIGRATE_VITEST_4.md | 725 -------------------- 2 files changed, 1570 deletions(-) delete mode 100644 tools/ai-migrations/MIGRATE_NEXT_16.md delete mode 100644 tools/ai-migrations/MIGRATE_VITEST_4.md diff --git a/tools/ai-migrations/MIGRATE_NEXT_16.md b/tools/ai-migrations/MIGRATE_NEXT_16.md deleted file mode 100644 index c1d2c79..0000000 --- a/tools/ai-migrations/MIGRATE_NEXT_16.md +++ /dev/null @@ -1,845 +0,0 @@ -# Next.js 16 Migration Instructions for LLM - -## Overview - -These instructions guide you through migrating an Nx workspace containing Next.js projects from Next.js 15 to Next.js 16. Work systematically through each breaking change category. - -## Pre-Migration Checklist - -1. **Identify all Next.js projects**: - - ```bash - nx show projects --with-target build | xargs -I {} nx show project {} --json | jq -r 'select(.targets.build.executor | contains("next")) | .name' - ``` - - Or search for Next.js configuration files: - - ```bash - find . -name "next.config.*" -not -path "*/node_modules/*" - ``` - -2. **Update packages**: - - ```bash - npm install next@latest react@latest react-dom@latest - npm install -D @types/react @types/react-dom # if using TypeScript - ``` - -3. **Verify minimum requirements**: - - Node.js 20.9+ (Node.js 18 is no longer supported) - - TypeScript 5.1.0+ - - Browser support: Chrome 111+, Edge 111+, Firefox 111+, Safari 16.4+ - -## Migration Steps by Category - -### 1. Async Request APIs (Major Breaking Change) - -This is the most impactful change in Next.js 16. All dynamic request APIs are now asynchronous. - -**Search Patterns**: - -- `cookies()` usage in server components -- `headers()` usage in server components -- `draftMode()` usage -- `params` in page, layout, route handlers, and metadata files -- `searchParams` in page components - -#### 1.1 Page Components with params - -**Changes Required**: - -```tsx -// BEFORE (Next.js 15) -export default function Page({ params }) { - const { slug } = params; - return

{slug}

; -} - -// AFTER (Next.js 16) -export default async function Page(props) { - const { slug } = await props.params; - return

{slug}

; -} -``` - -**Action Items**: - -- [ ] Make all page components that use `params` async -- [ ] Add `await` before accessing `props.params` -- [ ] Update TypeScript types if applicable - -#### 1.2 Page Components with searchParams - -**Changes Required**: - -```tsx -// BEFORE (Next.js 15) -export default function Page({ searchParams }) { - const query = searchParams.q; - return ; -} - -// AFTER (Next.js 16) -export default async function Page(props) { - const searchParams = await props.searchParams; - const query = searchParams.q; - return ; -} -``` - -**Action Items**: - -- [ ] Make all page components that use `searchParams` async -- [ ] Add `await` before accessing `props.searchParams` - -#### 1.3 Layout Components with params - -**Changes Required**: - -```tsx -// BEFORE (Next.js 15) -export default function Layout({ children, params }) { - const { locale } = params; - return
{children}
; -} - -// AFTER (Next.js 16) -export default async function Layout(props) { - const { locale } = await props.params; - return
{props.children}
; -} -``` - -#### 1.4 Route Handlers - -**Changes Required**: - -```tsx -// BEFORE (Next.js 15) -export async function GET(request, { params }) { - const { id } = params; - return Response.json({ id }); -} - -// AFTER (Next.js 16) -export async function GET(request, props) { - const { id } = await props.params; - return Response.json({ id }); -} -``` - -#### 1.5 cookies() and headers() - -**Changes Required**: - -```tsx -// BEFORE (Next.js 15) -import { cookies, headers } from 'next/headers'; - -export default function Page() { - const cookieStore = cookies(); - const headersList = headers(); - const theme = cookieStore.get('theme'); - const userAgent = headersList.get('user-agent'); - return
...
; -} - -// AFTER (Next.js 16) -import { cookies, headers } from 'next/headers'; - -export default async function Page() { - const cookieStore = await cookies(); - const headersList = await headers(); - const theme = cookieStore.get('theme'); - const userAgent = headersList.get('user-agent'); - return
...
; -} -``` - -#### 1.6 draftMode() - -**Changes Required**: - -```tsx -// BEFORE (Next.js 15) -import { draftMode } from 'next/headers'; - -export default function Page() { - const { isEnabled } = draftMode(); - return
{isEnabled ? 'Draft' : 'Published'}
; -} - -// AFTER (Next.js 16) -import { draftMode } from 'next/headers'; - -export default async function Page() { - const { isEnabled } = await draftMode(); - return
{isEnabled ? 'Draft' : 'Published'}
; -} -``` - -#### 1.7 generateMetadata with params - -**Changes Required**: - -```tsx -// BEFORE (Next.js 15) -export async function generateMetadata({ params }) { - const { slug } = params; - return { title: slug }; -} - -// AFTER (Next.js 16) -export async function generateMetadata(props) { - const { slug } = await props.params; - return { title: slug }; -} -``` - -#### 1.8 Automated Migration - -Run the Next.js codemod for automated migration: - -```bash -npx @next/codemod@canary upgrade latest -``` - -Generate type helpers for safer migrations (Next.js 15.5+): - -```bash -npx next typegen -``` - -This generates `PageProps`, `LayoutProps`, and `RouteContext` helpers. - -### 2. Image Generation Functions - -**Search Pattern**: `generateImageMetadata`, `default function Image` in opengraph-image or twitter-image files - -**Changes Required**: - -```tsx -// BEFORE (Next.js 15) -export function generateImageMetadata({ params }) { - const { slug } = params; - return [{ id: '1' }]; -} - -export default function Image({ params, id }) { - const slug = params.slug; - return new ImageResponse(/* ... */); -} - -// AFTER (Next.js 16) -export async function generateImageMetadata({ params }) { - const { slug } = await params; - return [{ id: '1' }]; -} - -export default async function Image({ params, id }) { - const { slug } = await params; - const imageId = await id; - return new ImageResponse(/* ... */); -} -``` - -**Action Items**: - -- [ ] Make `generateImageMetadata` functions async -- [ ] Make Image components async -- [ ] Add `await` for both `params` and `id` access - -### 3. Sitemap Generation - -**Search Pattern**: `sitemap` functions with `id` parameter - -**Changes Required**: - -```tsx -// BEFORE (Next.js 15) -export default async function sitemap({ id }) { - const start = id * 50000; - // ... -} - -// AFTER (Next.js 16) -export default async function sitemap({ id }) { - const resolvedId = await id; - const start = resolvedId * 50000; - // ... -} -``` - -### 4. Turbopack Configuration - -Turbopack is now the default bundler for development. - -**Search Pattern**: `--turbo` or `--turbopack` flags in package.json scripts, `turbopack` in next.config - -#### 4.1 Remove Explicit Turbopack Flags - -```json -// BEFORE (Next.js 15) -{ - "scripts": { - "dev": "next dev --turbo" - } -} - -// AFTER (Next.js 16) - Turbopack is default -{ - "scripts": { - "dev": "next dev" - } -} -``` - -#### 4.2 Opt Out to Webpack (if needed) - -```json -{ - "scripts": { - "build": "next build --webpack" - } -} -``` - -#### 4.3 Move Turbopack Config Out of Experimental - -```ts -// BEFORE (Next.js 15) -const nextConfig = { - experimental: { - turbopack: { - /* options */ - }, - }, -}; - -// AFTER (Next.js 16) -const nextConfig = { - turbopack: { - /* options */ - }, -}; -``` - -#### 4.4 Update Sass Imports (Turbopack Specific) - -```scss -/* BEFORE */ -@import '~bootstrap/dist/css/bootstrap.min.css'; - -/* AFTER - Remove tilde prefix */ -@import 'bootstrap/dist/css/bootstrap.min.css'; -``` - -**Action Items**: - -- [ ] Remove `--turbo` and `--turbopack` flags from scripts -- [ ] Move `turbopack` config from `experimental` to root level -- [ ] Remove tilde (`~`) prefix from Sass imports -- [ ] Add `--webpack` flag if Webpack is required - -### 5. Middleware to Proxy Rename - -**Search Pattern**: `middleware.ts` or `middleware.js` files - -**Changes Required**: - -```bash -# Rename the file -mv middleware.ts proxy.ts -``` - -```ts -// BEFORE (middleware.ts) -export function middleware(request) { - // ... -} - -// AFTER (proxy.ts) -export function proxy(request) { - // ... -} -``` - -**Config Updates**: - -```js -// BEFORE -{ - skipMiddlewareUrlNormalize: true; -} - -// AFTER -{ - skipProxyUrlNormalize: true; -} -``` - -**Important**: The Edge runtime is no longer supported in `proxy`. It now uses Node.js runtime. - -**Action Items**: - -- [ ] Rename `middleware.ts/js` to `proxy.ts/js` -- [ ] Rename exported function from `middleware` to `proxy` -- [ ] Update config option names -- [ ] Remove Edge runtime usage from proxy files - -### 6. Parallel Routes default.js Requirement - -**Search Pattern**: Directories starting with `@` in the app folder (parallel route slots) - -All parallel route slots now require an explicit `default.js` file. - -**Changes Required**: - -```tsx -// Create app/@modal/default.tsx for each parallel route slot -import { notFound } from 'next/navigation'; - -export default function Default() { - notFound(); // or return null -} -``` - -**Action Items**: - -- [ ] Find all parallel route slots (`app/@*/`) -- [ ] Create `default.tsx` in each slot that doesn't have one - -### 7. Image Optimization Changes - -#### 7.1 Local Images with Query Strings - -```tsx -// Now requires explicit configuration -Photo -``` - -```js -// next.config.js -module.exports = { - images: { - localPatterns: [ - { - pathname: '/assets/**', - search: '?v=1', - }, - ], - }, -}; -``` - -#### 7.2 Default Value Changes - -Add these to `next.config.js` if you need the old defaults: - -```js -module.exports = { - images: { - // minimumCacheTTL changed from 60 to 14400 seconds - minimumCacheTTL: 60, - - // Value 16 removed from default imageSizes - imageSizes: [16, 32, 48, 64, 96, 128, 256, 384], - - // qualities now defaults to [75] only - qualities: [50, 75, 100], - - // Local IP now blocked by default - dangerouslyAllowLocalIP: true, // only for private networks - - // Maximum redirects changed from unlimited to 3 - maximumRedirects: 5, - }, -}; -``` - -#### 7.3 Deprecated images.domains - -```js -// BEFORE - Remove this -module.exports = { - images: { - domains: ['example.com'], - }, -}; - -// AFTER - Use remotePatterns instead -module.exports = { - images: { - remotePatterns: [ - { - protocol: 'https', - hostname: 'example.com', - }, - ], - }, -}; -``` - -**Action Items**: - -- [ ] Add `localPatterns` for images with query strings -- [ ] Migrate `images.domains` to `images.remotePatterns` -- [ ] Review and update default values if needed - -### 8. Caching API Updates - -#### 8.1 Remove unstable\_ Prefix - -```ts -// BEFORE (Next.js 15) -import { - unstable_cacheLife as cacheLife, - unstable_cacheTag as cacheTag, -} from 'next/cache'; - -// AFTER (Next.js 16) -import { cacheLife, cacheTag } from 'next/cache'; -``` - -#### 8.2 New Cache Functions - -**revalidateTag with cacheLife profile**: - -```ts -'use server'; -import { revalidateTag } from 'next/cache'; - -export async function updateArticle(articleId: string) { - revalidateTag(`article-${articleId}`, 'max'); -} -``` - -**updateTag (new)**: - -```ts -'use server'; -import { updateTag } from 'next/cache'; - -export async function updateUserProfile(userId: string, profile: Profile) { - await db.users.update(userId, profile); - updateTag(`user-${userId}`); -} -``` - -**refresh (new)**: - -```ts -'use server'; -import { refresh } from 'next/cache'; - -export async function markNotificationAsRead(notificationId: string) { - await db.notifications.markAsRead(notificationId); - refresh(); -} -``` - -**Action Items**: - -- [ ] Remove `unstable_` prefix from `cacheLife` and `cacheTag` imports -- [ ] Consider using new `updateTag` and `refresh` functions - -### 9. React Compiler Support - -React Compiler is now stable and supported: - -```ts -// next.config.ts -const nextConfig = { - reactCompiler: true, -}; - -export default nextConfig; -``` - -Install the plugin: - -```bash -npm install -D babel-plugin-react-compiler -``` - -**Note**: Expect higher compile times with React Compiler enabled. - -### 10. Scroll Behavior Override - -Next.js no longer overrides `scroll-behavior: smooth` during navigation. - -To restore previous behavior: - -```tsx -// app/layout.tsx -export default function RootLayout({ children }) { - return ( - - {children} - - ); -} -``` - -### 11. ESLint Migration - -The `next lint` command has been removed. Migrate to ESLint CLI directly. - -```bash -# Run migration codemod -npx @next/codemod@canary next-lint-to-eslint-cli . -``` - -Remove from `next.config.js`: - -```js -// Remove this -{ - eslint: { - } -} -``` - -**Action Items**: - -- [ ] Run the ESLint migration codemod -- [ ] Remove `eslint` config from `next.config.js` -- [ ] Update CI scripts to use `eslint` directly instead of `next lint` - -### 12. Feature Removals - -#### 12.1 AMP Support Removed - -- All AMP APIs have been deleted -- Remove `useAmp` hook usage -- Remove `amp` config option -- Delete AMP-specific pages - -#### 12.2 Runtime Configuration Removed - -```js -// BEFORE - Remove these -module.exports = { - serverRuntimeConfig: { dbUrl: process.env.DATABASE_URL }, - publicRuntimeConfig: { apiUrl: '/api' }, -}; -``` - -**Migration for server-side config**: - -```tsx -// Use environment variables directly -async function fetchData() { - const dbUrl = process.env.DATABASE_URL; - return await db.query(dbUrl, 'SELECT * FROM users'); -} -``` - -**Migration for client-side config**: - -```bash -# .env.local -NEXT_PUBLIC_API_URL="/api" -``` - -```tsx -'use client'; -export default function Component() { - const apiUrl = process.env.NEXT_PUBLIC_API_URL; - // ... -} -``` - -#### 12.3 devIndicators Options Removed - -Remove these from `next.config.js`: - -- `appIsrStatus` -- `buildActivity` -- `buildActivityPosition` - -#### 12.4 experimental.dynamicIO Renamed - -```js -// BEFORE -{ - experimental: { - dynamicIO: true; - } -} - -// AFTER -{ - cacheComponents: true; -} -``` - -#### 12.5 unstable_rootParams Removed - -This API is removed. Await alternative API in a future minor release. - -**Action Items**: - -- [ ] Remove all AMP-related code -- [ ] Migrate runtime configuration to environment variables -- [ ] Remove deprecated devIndicators options -- [ ] Rename `dynamicIO` to `cacheComponents` - -### 13. Development Changes - -#### 13.1 Concurrent dev and build - -Development now outputs to `.next/dev` (separate from build). - -**Update Turbopack tracing command**: - -```bash -npx next internal trace .next/dev/trace-turbopack -``` - -## Post-Migration Validation - -### 1. Run Build Per Project - -```bash -# Build each Next.js project individually -nx run PROJECT_NAME:build -``` - -### 2. Run Development Server - -```bash -# Start dev server to verify Turbopack works -nx run PROJECT_NAME:serve -``` - -### 3. Run All Affected Builds - -```bash -# Build all affected projects -nx affected -t build -``` - -### 4. Run Full Validation - -```bash -# Run full CI validation -nx prepush -``` - -### 5. Review Migration Checklist - -- [ ] All async request APIs updated -- [ ] All page/layout components using params are async -- [ ] Turbopack configuration updated -- [ ] Middleware renamed to proxy -- [ ] Parallel routes have default.js files -- [ ] Image configuration updated -- [ ] Cache imports updated (removed unstable\_ prefix) -- [ ] AMP code removed -- [ ] Runtime config migrated to env vars -- [ ] ESLint configuration migrated -- [ ] All projects build successfully -- [ ] Development servers start correctly - -## Common Issues and Solutions - -### Issue: "cookies() expects to be called in a synchronous context" - -**Solution**: Make the function async and await `cookies()` - -### Issue: "params should be awaited before accessing properties" - -**Solution**: Add `await` before accessing `props.params` - -### Issue: Build fails with Turbopack - -**Solution**: Add `--webpack` flag to build script, then gradually address Turbopack compatibility - -### Issue: Middleware not working after rename - -**Solution**: Ensure both file and function are renamed from `middleware` to `proxy` - -### Issue: Parallel route not rendering - -**Solution**: Add `default.tsx` file to the parallel route slot - -### Issue: Images with query strings not loading - -**Solution**: Add `localPatterns` configuration for those images - -### Issue: TypeScript errors with params types - -**Solution**: Run `npx next typegen` to generate type helpers, then use `PageProps`, `LayoutProps` types - -## Files to Review - -Create a checklist of all files that need review: - -```bash -# Find all pages with potential params usage -find . -path "*/app/*" -name "page.tsx" -o -name "page.ts" | xargs grep -l "params\|searchParams" - -# Find all layouts -find . -path "*/app/*" -name "layout.tsx" -o -name "layout.ts" - -# Find all route handlers -find . -path "*/app/*" -name "route.ts" -o -name "route.tsx" - -# Find middleware files -find . -name "middleware.ts" -o -name "middleware.js" - -# Find files using cookies/headers -rg "from 'next/headers'" --type ts --type tsx - -# Find next.config files -find . -name "next.config.*" -not -path "*/node_modules/*" - -# Find parallel routes -find . -path "*/app/@*" -type d -``` - -## Migration Strategy for Large Workspaces - -1. **Migrate in phases**: Start with a small project, validate, then expand -2. **Use the codemod**: Run `npx @next/codemod@canary upgrade latest` for automated fixes -3. **Generate types**: Run `npx next typegen` for type-safe migrations -4. **Run tests frequently**: After each configuration change, run affected tests -5. **Document issues**: Keep track of project-specific issues and solutions - -## Useful Commands During Migration - -```bash -# Find all Next.js projects -nx show projects --with-target build - -# Build specific project -nx build PROJECT_NAME - -# Serve specific project -nx serve PROJECT_NAME - -# Build all affected -nx affected -t build - -# View project details -nx show project PROJECT_NAME --web - -# Clear Nx cache if needed -nx reset -``` - ---- - -## Notes for LLM Execution - -When executing this migration: - -1. **Work systematically**: Complete one category before moving to the next -2. **Test after each change**: Don't batch all changes without validation -3. **Keep user informed**: Report progress through each section -4. **Handle errors promptly**: If builds fail, fix immediately before proceeding -5. **Use the codemod first**: Let `@next/codemod` handle repetitive async/await changes -6. **Prioritize breaking changes**: Focus on async APIs first as they're most impactful -7. **Create meaningful commits**: Group related changes together with clear messages -8. **Use TodoWrite tool**: Track migration progress for visibility diff --git a/tools/ai-migrations/MIGRATE_VITEST_4.md b/tools/ai-migrations/MIGRATE_VITEST_4.md deleted file mode 100644 index 3cd49fa..0000000 --- a/tools/ai-migrations/MIGRATE_VITEST_4.md +++ /dev/null @@ -1,725 +0,0 @@ -# Vitest 4.0 Migration Instructions for LLM - -## Overview - -These instructions guide you through migrating an Nx workspace containing multiple Vitest projects from Vitest 3.x to Vitest 4.0. Work systematically through each breaking change category. - -## Pre-Migration Checklist - -1. **Identify all Vitest projects**: - - ```bash - nx show projects --with-target test - ``` - -2. **Locate all Vitest configuration files**: - - Search for `vitest.config.{ts,js,mjs}` - - Search for `vitest.workspace.{ts,js,mjs}` - - Check `project.json` files for inline Vitest configuration - -3. **Identify affected code**: - - Test files: `**/*.{spec,test}.{ts,js,tsx,jsx}` - - Mock usage: Files using `vi.fn()`, `vi.spyOn()`, `vi.mock()` - - Coverage configuration references - -## Migration Steps by Category - -### 1. Configuration File Updates - -#### 1.1 Coverage Configuration - -**Search Pattern**: `coverage` in all `vitest.config.*` files and `project.json` test target options - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -export default defineConfig({ - test: { - coverage: { - all: true, - extensions: ['.ts', '.tsx'], - ignoreEmptyLines: false, - experimentalAstAwareRemapping: true, - }, - }, -}); - -// ✅ AFTER (Vitest 4.0) -export default defineConfig({ - test: { - coverage: { - // Explicitly define files to include in coverage - include: ['src/**/*.{ts,tsx}'], - // Remove: all, extensions, ignoreEmptyLines, experimentalAstAwareRemapping - }, - }, -}); -``` - -**Action Items**: - -- [ ] Remove `coverage.all` option -- [ ] Remove `coverage.extensions` option -- [ ] Remove `coverage.ignoreEmptyLines` option -- [ ] Remove `coverage.experimentalAstAwareRemapping` option -- [ ] Add explicit `coverage.include` patterns based on project structure -- [ ] Update any documentation referencing these options - -#### 1.2 Pool Options Restructuring - -**Search Pattern**: `poolOptions`, `maxThreads`, `maxForks`, `singleThread`, `singleFork` in all Vitest config files - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -export default defineConfig({ - test: { - maxThreads: 4, - maxForks: 2, - singleThread: false, - poolOptions: { - threads: { - useAtomics: true, - }, - vmThreads: { - memoryLimit: '512MB', - }, - }, - }, -}); - -// ✅ AFTER (Vitest 4.0) -export default defineConfig({ - test: { - maxWorkers: 4, // Consolidates maxThreads and maxForks - isolate: true, // Replaces singleThread: false - // Remove: poolOptions, threads.useAtomics - vmMemoryLimit: '512MB', // Moved to top-level - }, -}); -``` - -**Action Items**: - -- [ ] Replace `maxThreads` and `maxForks` with single `maxWorkers` option -- [ ] Replace `singleThread: true` or `singleFork: true` with `maxWorkers: 1, isolate: false` -- [ ] Move all `poolOptions.*` nested options to top-level (e.g., `poolOptions.vmThreads.memoryLimit` → `vmMemoryLimit`) -- [ ] Remove `threads.useAtomics` option -- [ ] Update CI environment variables: `VITEST_MAX_THREADS` and `VITEST_MAX_FORKS` → `VITEST_MAX_WORKERS` - -#### 1.3 Workspace to Projects Rename - -**Search Pattern**: `workspace` property in Vitest config files - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -export default defineConfig({ - test: { - workspace: ['apps/*', 'libs/*'], - }, -}); - -// ✅ AFTER (Vitest 4.0) -export default defineConfig({ - test: { - projects: ['apps/*', 'libs/*'], - }, -}); -``` - -**Action Items**: - -- [ ] Rename `workspace` property to `projects` in all config files -- [ ] Remove external workspace file references (must be inline in config) -- [ ] Update `poolMatchGlobs` to use `projects` pattern matching instead -- [ ] Update `environmentMatchGlobs` to use `projects` pattern matching instead - -#### 1.4 Browser Configuration - -**Search Pattern**: `browser.provider`, `browser.testerScripts`, imports from `@vitest/browser` - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -export default defineConfig({ - test: { - browser: { - enabled: true, - provider: 'playwright', // String value - testerScripts: ['./setup.js'], - }, - }, -}); - -// Import changes -import { page } from '@vitest/browser'; - -// ✅ AFTER (Vitest 4.0) -export default defineConfig({ - test: { - browser: { - enabled: true, - provider: { name: 'playwright' }, // Object value - testerHtmlPath: './test-setup.html', // Renamed from testerScripts - }, - }, -}); - -// Import changes -import { page } from 'vitest/browser'; -``` - -**Action Items**: - -- [ ] Convert `browser.provider` string values to object format: `{ name: 'provider-name' }` -- [ ] Replace `browser.testerScripts` with `browser.testerHtmlPath` -- [ ] Update all imports from `@vitest/browser` to `vitest/browser` -- [ ] Remove `@vitest/browser` from dependencies if no longer needed - -#### 1.5 Deprecated Configuration Options - -**Search Pattern**: `deps.external`, `deps.inline`, `deps.fallbackCJS` in config files - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -export default defineConfig({ - test: { - deps: { - external: ['some-package'], - inline: ['inline-package'], - fallbackCJS: true, - }, - }, -}); - -// ✅ AFTER (Vitest 4.0) -export default defineConfig({ - test: { - server: { - deps: { - external: ['some-package'], - inline: ['inline-package'], - fallbackCJS: true, - }, - }, - }, -}); -``` - -**Action Items**: - -- [ ] Move `deps.*` options under `server.deps` namespace -- [ ] Remove `poolMatchGlobs` (use `projects` with conditions instead) -- [ ] Remove `environmentMatchGlobs` (use `projects` with conditions instead) - -### 2. Test Code Updates - -#### 2.1 Mock Function Name Changes - -**Search Pattern**: `.getMockName()` calls in test files - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -const mockFn = vi.fn(); -expect(mockFn.getMockName()).toBe('spy'); // Old default - -// ✅ AFTER (Vitest 4.0) -const mockFn = vi.fn(); -expect(mockFn.getMockName()).toBe('vi.fn()'); // New default - -// If you need custom names, set them explicitly -const namedMock = vi.fn().mockName('myCustomName'); -expect(namedMock.getMockName()).toBe('myCustomName'); -``` - -**Action Items**: - -- [ ] Update test assertions checking default mock names from `'spy'` to `'vi.fn()'` -- [ ] Add explicit `.mockName()` calls where specific names are required - -#### 2.2 Mock Invocation Call Order - -**Search Pattern**: `.mock.invocationCallOrder` in test files - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -const mockFn = vi.fn(); -mockFn(); -expect(mockFn.mock.invocationCallOrder[0]).toBe(0); // Started at 0 - -// ✅ AFTER (Vitest 4.0) -const mockFn = vi.fn(); -mockFn(); -expect(mockFn.mock.invocationCallOrder[0]).toBe(1); // Now starts at 1 (Jest-compatible) -``` - -**Action Items**: - -- [ ] Update assertions on `invocationCallOrder` to account for 1-based indexing -- [ ] Search for off-by-one errors in call order comparisons - -#### 2.3 Constructor Spies and Mocks - -**Search Pattern**: `vi.spyOn` on constructors, `vi.fn()` used as constructors - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) - Arrow function constructors might have worked -const MockConstructor = vi.fn(() => ({ value: 42 })); -new MockConstructor(); // May have worked in v3 - -// ✅ AFTER (Vitest 4.0) - Must use function or class -const MockConstructor = vi.fn(function () { - return { value: 42 }; -}); -new MockConstructor(); // Correctly supports 'new' - -// Or use class syntax -class MockClass { - value = 42; -} -const MockConstructor = vi.fn(MockClass); -``` - -**Action Items**: - -- [ ] Convert arrow function mocks used as constructors to `function` keyword or `class` syntax -- [ ] Test all constructor spies to ensure `new` keyword works correctly -- [ ] Update any mocks that expect constructor behavior - -#### 2.4 RestoreAllMocks Behavior - -**Search Pattern**: `vi.restoreAllMocks()` in test files - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -vi.mock('./module', () => ({ fn: vi.fn() })); -vi.restoreAllMocks(); // Would restore automocks - -// ✅ AFTER (Vitest 4.0) -vi.mock('./module', () => ({ fn: vi.fn() })); -vi.restoreAllMocks(); // Only restores manual spies, NOT automocks - -// To reset automocks, use: -vi.unmock('./module'); -// or -vi.resetModules(); -``` - -**Action Items**: - -- [ ] Review all `vi.restoreAllMocks()` usage -- [ ] Add explicit `vi.unmock()` or `vi.resetModules()` calls for automocked modules -- [ ] Ensure test isolation is maintained after this change - -#### 2.5 SpyOn Return Value Changes - -**Search Pattern**: `vi.spyOn()` on already mocked functions - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -const mock = vi.fn(); -const spy = vi.spyOn({ method: mock }, 'method'); -// spy !== mock (created new spy) - -// ✅ AFTER (Vitest 4.0) -const mock = vi.fn(); -const spy = vi.spyOn({ method: mock }, 'method'); -// spy === mock (returns same instance) -``` - -**Action Items**: - -- [ ] Review code that creates spies on existing mocks -- [ ] Remove redundant spy creation if same instance is returned -- [ ] Update assertions that check spy identity - -#### 2.6 Automock Behavior Changes - -**Search Pattern**: `vi.mock()` with factory functions, `.mockRestore()` on automocks - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -vi.mock('./utils', () => ({ - get value() { - return 42; - }, // Would call getter -})); - -import { value } from './utils'; -console.log(value); // Would execute getter logic - -// Restore might have worked -const spy = vi.spyOn(obj, 'method'); -spy.mockRestore(); // Might work on automocks - -// ✅ AFTER (Vitest 4.0) -vi.mock('./utils', () => ({ - get value() { - return 42; - }, -})); - -import { value } from './utils'; -console.log(value); // Returns undefined (doesn't call getter) - -// Explicitly return value if needed -vi.mock('./utils', () => ({ - value: 42, // Not a getter -})); - -// mockRestore no longer works on automocks -const spy = vi.spyOn(obj, 'method'); -spy.mockRestore(); // Throws error if method is automocked - -// Use unmock instead -vi.unmock('./module'); -``` - -**Action Items**: - -- [ ] Convert automocked getters to plain property values where needed -- [ ] Remove `.mockRestore()` calls on automocked methods -- [ ] Use `vi.unmock()` to clear automocks instead -- [ ] Test instance method isolation (they now share state with prototype) - -#### 2.7 Settled Results Immediate Population - -**Search Pattern**: `.mock.settledResults` in test files - -**Changes Required**: - -```typescript -// ✅ AFTER (Vitest 4.0) -const asyncMock = vi.fn(async () => 'result'); -const promise = asyncMock(); - -// settledResults is immediately populated with 'incomplete' status -expect(asyncMock.mock.settledResults[0]).toEqual({ - type: 'incomplete', - value: undefined, -}); - -// After promise resolves -await promise; -expect(asyncMock.mock.settledResults[0]).toEqual({ - type: 'fulfilled', - value: 'result', -}); -``` - -**Action Items**: - -- [ ] Update tests that check `settledResults` before promise resolution -- [ ] Handle `'incomplete'` status in assertions -- [ ] Ensure tests properly await promises before checking settled results - -### 3. Reporter and CLI Changes - -#### 3.1 Reporter API Changes - -**Search Pattern**: Custom reporters, `onCollected`, `onTaskUpdate`, `onFinished` - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -export default { - onCollected(files) { - // Handle collected files - }, - onTaskUpdate(task) { - // Handle task update - }, - onFinished(files) { - // Handle completion - }, -}; - -// ✅ AFTER (Vitest 4.0) -// Use new reporter API - consult Vitest 4 docs for replacement methods -``` - -**Action Items**: - -- [ ] Review custom reporters for removed API usage -- [ ] Consult Vitest 4 documentation for new reporter API -- [ ] Update or rewrite custom reporters to use new APIs - -#### 3.2 Built-in Reporter Changes - -**Search Pattern**: `reporters: ['basic']`, `reporters: ['verbose']` - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -export default defineConfig({ - test: { - reporters: ['basic'], - }, -}); - -// ✅ AFTER (Vitest 4.0) -export default defineConfig({ - test: { - reporters: [['default', { summary: false }]], // Equivalent to 'basic' - }, -}); - -// For verbose (tree output) -reporters: ['tree']; // Use 'tree' for hierarchical output -``` - -**Action Items**: - -- [ ] Replace `'basic'` reporter with `['default', { summary: false }]` -- [ ] Replace `'verbose'` reporter with `'tree'` for hierarchical output -- [ ] Update CI configuration if reporters are specified there - -### 4. Snapshot Changes - -#### 4.1 Custom Elements Shadow Root - -**Search Pattern**: Snapshot tests involving custom elements or Web Components - -**Changes Required**: - -```typescript -// ✅ AFTER (Vitest 4.0) -// Shadow root contents now printed by default in snapshots - -// If you want old behavior (don't print shadow root): -export default defineConfig({ - test: { - printShadowRoot: false, - }, -}); -``` - -**Action Items**: - -- [ ] Review snapshot tests for custom elements -- [ ] Update snapshots if shadow root contents are now included -- [ ] Add `printShadowRoot: false` if old behavior is required - -### 5. Environment Variable Updates - -**Search Pattern**: CI/CD configuration files, `.env` files, documentation - -**Changes Required**: - -```bash -# ❌ BEFORE (Vitest 3.x) -VITEST_MAX_THREADS=4 -VITEST_MAX_FORKS=2 -VITE_NODE_DEPS_MODULE_DIRECTORIES=/custom/path - -# ✅ AFTER (Vitest 4.0) -VITEST_MAX_WORKERS=4 -VITEST_MODULE_DIRECTORIES=/custom/path -``` - -**Action Items**: - -- [ ] Update CI/CD pipeline environment variables -- [ ] Update `.env` files -- [ ] Update documentation referencing old environment variables -- [ ] Search for `VITEST_MAX_THREADS`, `VITEST_MAX_FORKS`, `VITE_NODE_DEPS_MODULE_DIRECTORIES` - -### 6. Advanced: Module Runner Changes - -**Search Pattern**: `vitest/execute`, `__vitest_executor`, `vite-node` - -**Changes Required**: - -```typescript -// ❌ BEFORE (Vitest 3.x) -import { execute } from 'vitest/execute'; -// Access to __vitest_executor - -// ✅ AFTER (Vitest 4.0) -// Use Vite's Module Runner API instead -// Consult Vite Module Runner documentation -``` - -**Action Items**: - -- [ ] If using `vitest/execute`, migrate to Vite Module Runner -- [ ] Remove dependencies on `__vitest_executor` -- [ ] Update custom pool implementations (complete rewrite needed) - -### 7. Type Definition Updates - -**Search Pattern**: TypeScript imports from `vitest`, type errors after upgrade - -**Changes Required**: - -```typescript -// All deprecated type exports removed -// If you get TypeScript errors about missing types: -// - Check if you're using deprecated type names -// - Update to current type names from Vitest 4 API -// - Remove explicit @types/node if it was only needed due to Vitest bug -``` - -**Action Items**: - -- [ ] Run TypeScript compilation on all test files -- [ ] Fix any type errors related to removed Vitest type definitions -- [ ] Review `@types/node` usage (may no longer be accidentally included) - -## Post-Migration Validation - -### 1. Run Tests Per Project - -```bash -# Test each project individually -nx run-many -t test -p PROJECT_NAME -``` - -### 2. Run All Tests - -```bash -# Run tests across all affected projects -nx affected -t test -``` - -### 3. Check Coverage - -```bash -# Verify coverage generation works with new config -nx affected -t test --coverage -``` - -### 4. Validate CI Pipeline - -```bash -# Run full CI validation -nx prepush -``` - -### 5. Review Migration Checklist - -- [ ] All configuration files updated -- [ ] All test files pass -- [ ] Coverage reports generate correctly -- [ ] CI/CD pipeline runs successfully -- [ ] Environment variables updated -- [ ] Documentation updated -- [ ] No deprecated API warnings in console - -## Common Issues and Solutions - -### Issue: Coverage includes too many files - -**Solution**: Add explicit `coverage.include` patterns to match your source files - -### Issue: Tests fail with "arrow function constructors not supported" - -**Solution**: Convert arrow functions used as constructors to `function` keyword or `class` syntax - -### Issue: Automocks not resetting between tests - -**Solution**: Use `vi.unmock()` or `vi.resetModules()` instead of `vi.restoreAllMocks()` - -### Issue: Mock call order assertions failing - -**Solution**: Update to 1-based indexing for `invocationCallOrder` - -### Issue: Browser tests failing after upgrade - -**Solution**: Check browser provider is object format and imports use `vitest/browser` - -### Issue: TypeScript errors in test files - -**Solution**: Update to new type definitions and remove usage of deprecated types - -## Files to Review - -Create a checklist of all files that need review: - -```bash -# Configuration files -find . -name "vitest.config.*" -o -name "vitest.workspace.*" -find . -name "project.json" -exec grep -l "vitest" {} \; - -# Test files -find . -name "*.spec.*" -o -name "*.test.*" - -# Files with mock usage -rg "vi\.(fn|spyOn|mock|restoreAllMocks)" --type ts --type tsx --type js - -# Files with coverage config -rg "coverage\.(all|extensions|ignoreEmptyLines)" --type ts --type js - -# CI configuration -find . -name ".github/workflows/*.yml" -o -name ".gitlab-ci.yml" -o -name "azure-pipelines.yml" -``` - -## Migration Strategy for Large Workspaces - -1. **Migrate in phases**: Start with a small project, validate, then expand -2. **Use feature branches**: Create separate branches for different migration aspects -3. **Run tests frequently**: After each configuration change, run affected tests -4. **Document issues**: Keep track of project-specific issues and solutions -5. **Automate where possible**: Create codemods for repetitive changes - -## Useful Commands During Migration - -```bash -# Find all vitest configurations -nx show projects --with-target test - -# Test specific project after changes -nx test PROJECT_NAME - -# Test all affected -nx affected -t test - -# View project details -nx show project PROJECT_NAME --web - -# Clear Nx cache if needed -nx reset -``` - -## Guard Rails - -DO NOT - -- Force tests to pass by removing test logic and replacing it with `expect(true).toBe(true)` -- Remove assertions -- Add additional mocks that force tests to pass - ---- - -## Notes for LLM Execution - -When executing this migration: - -1. **Work systematically**: Complete one category before moving to the next -2. **Test after each change**: Don't batch all changes without validation -3. **Keep user informed**: Report progress through each section -4. **Handle errors promptly**: If tests fail, fix immediately before proceeding -5. **Update documentation**: Note any workspace-specific patterns or issues -6. **Create meaningful commits**: Group related changes together with clear messages -7. **Use TodoWrite tool**: Track migration progress for visibility