import { defineConfig } from 'vitest/config' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' import path from 'node:path' import fs from 'node:fs' const monacoEditorPath = path.resolve( __dirname, '../node_modules/.pnpm/monaco-editor@0.55.1/node_modules/monaco-editor', ); const workspaceRoot = path.resolve(__dirname, '..', '..'); const commonPlatRoot = path.join(workspaceRoot, 'learning_ai_common_plat'); function commonPlatSourceEntry(pkg: string): string | null { const sourceEntry = path.join(commonPlatRoot, 'packages', pkg, 'src', 'index.ts'); return fs.existsSync(sourceEntry) ? sourceEntry : null; } // Resolve a @bytelyst/* package: prefer web/node_modules, fall back to vendor/ function bytelystAlias(pkg: string): string { const sourceEntry = commonPlatSourceEntry(pkg); if (sourceEntry) return sourceEntry; const nmPath = path.resolve(__dirname, 'node_modules/@bytelyst', pkg); const vendorPath = path.resolve(__dirname, '../vendor/bytelyst', pkg); if (fs.existsSync(nmPath)) return nmPath; if (fs.existsSync(vendorPath)) return vendorPath; return nmPath; // let Vite surface the missing-module error } // https://vite.dev/config/ export default defineConfig({ plugins: [ react(), tailwindcss(), ], // Shared files (../shared/*.ts) live outside web/ so Vite resolves their imports // from the repo root where @bytelyst/* are not installed. Redirect all @bytelyst/* // imports first to web/node_modules, then fall back to the monorepo vendor/ dir. resolve: { // Deduplicate React so the vendored react-auth dist resolves the same react instance dedupe: ['react', 'react-dom', 'react/jsx-runtime', 'react-router-dom'], alias: [ // Vendor packages that live only in vendor/ (not in web/node_modules/) { find: '@bytelyst/api-client', replacement: bytelystAlias('api-client') }, { find: '@bytelyst/design-tokens', replacement: path.join(commonPlatRoot, 'packages', 'design-tokens') }, { find: '@bytelyst/errors', replacement: bytelystAlias('errors') }, { find: '@bytelyst/kill-switch-client', replacement: bytelystAlias('kill-switch-client') }, { find: '@bytelyst/react-auth', replacement: bytelystAlias('react-auth') }, { find: '@bytelyst/telemetry-client', replacement: bytelystAlias('telemetry-client') }, { find: '@bytelyst/ui', replacement: bytelystAlias('ui') }, // Monaco is an explicit web dependency, but this workspace often runs // against pnpm's root store without a web/node_modules symlink when the // private mobile registry is unavailable. Keep local worker imports // resolvable for Vite in that partially installed state. { find: /^monaco-editor$/, replacement: monacoEditorPath }, { find: /^monaco-editor\/(.+)/, replacement: `${monacoEditorPath}/$1` }, // General catch-all: every other @bytelyst/* → web/node_modules { find: /^@bytelyst\/(.+)/, replacement: path.resolve(__dirname, 'node_modules/@bytelyst/$1'), }, ], }, test: { environment: 'jsdom', setupFiles: ['./src/test/setup.ts'], include: ['src/**/*.test.ts', 'src/**/*.test.tsx', 'src/**/*.dom.test.tsx'], }, build: { chunkSizeWarningLimit: 5000, rollupOptions: { output: { manualChunks(id) { if (id.includes('monaco-editor') || id.includes('@monaco-editor')) { return 'monaco-vendor'; } if (id.includes('/node_modules/lucide-react/')) { return 'ui-vendor'; } if (id.includes('/node_modules/')) { return 'vendor'; } return undefined; }, }, }, }, })