code-to-design 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/canvas-dist/assets/index-DZ4iZlMc.js +40 -0
- package/canvas-dist/index.html +1 -1
- package/dist/{chunk-BHEMO5RW.js → chunk-HYFKUTC3.js} +509 -122
- package/dist/chunk-HYFKUTC3.js.map +1 -0
- package/dist/commands/scan.js +1 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/canvas-dist/assets/index-BRaZpda-.js +0 -40
- package/dist/chunk-BHEMO5RW.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/scan.ts","../../core/src/discovery/route-scanner.ts","../../core/src/analysis/code-analyzer.ts","../../core/src/analysis/auth-detector.ts","../../core/src/mock/types.ts","../../core/src/mock/llm-client.ts","../../core/src/mock/prompt-templates.ts","../../core/src/mock/mock-generator.ts","../../core/src/render/pre-renderer.ts","../../core/src/render/dev-server.ts","../../core/src/render/style-inliner.ts","../../core/src/render/interaction-capturer.ts","../src/server/canvas-server.ts","../src/server/api-routes.ts","../src/config.ts","../src/utils/progress.ts"],"sourcesContent":["import { join } from 'node:path';\nimport { rm, mkdir } from 'node:fs/promises';\nimport { existsSync, watch as fsWatch } from 'node:fs';\nimport {\n scanRoutes,\n analyzePage,\n generateMocks,\n preRenderPages,\n type RenderTask,\n type MockGeneratorOptions,\n} from '@code-to-design/core';\nimport { startCanvasServer } from '../server/canvas-server.js';\nimport { loadConfig, detectProject } from '../config.js';\nimport * as ui from '../utils/progress.js';\n\n/**\n * Main scan command — runs the full Code to Design pipeline.\n *\n * 1. Detect project type\n * 2. Discover routes\n * 3. Analyze code + generate mocks\n * 4. Pre-render pages\n * 5. Start canvas server\n */\nexport async function runScan(options: {\n projectRoot: string;\n skipRender?: boolean;\n open?: boolean;\n watch?: boolean;\n}): Promise<void> {\n const { projectRoot, skipRender = false, open = true, watch = false } = options;\n\n ui.banner();\n\n // Load config\n const config = await loadConfig(projectRoot);\n\n // Step 1: Detect project\n ui.header('Detecting project...');\n const project = await detectProject(projectRoot);\n\n if (!project.isSupported) {\n ui.error('Unsupported project type.');\n ui.log('Code to Design supports Next.js (App Router / Pages Router) and React Router (Vite) projects.');\n process.exit(1);\n }\n\n if (project.projectType !== 'react-router' && !project.appDir) {\n ui.error('No app/ or pages/ directory found.');\n process.exit(1);\n }\n\n ui.success(`Project: ${project.projectName} (${project.projectType})`);\n if (project.appDir) {\n ui.success(`App directory: ${project.appDir}`);\n }\n\n const c2dDir = join(projectRoot, '.c2d');\n\n // If --skip-render, just start the server with existing renders\n if (skipRender) {\n if (!existsSync(join(c2dDir, 'manifest.json'))) {\n ui.error('No previous renders found. Run without --skip-render first.');\n process.exit(1);\n }\n ui.log('Skipping render, using existing canvas data...');\n await startServer(c2dDir, config.port, open, projectRoot);\n return;\n }\n\n // Step 2: Discover routes\n ui.header('Discovering routes...');\n const scanDir = project.projectType === 'react-router' ? project.projectRoot : project.appDir!;\n const routerType = project.projectType === 'react-router' ? 'react-router' as const\n : project.projectType === 'nextjs-pages' ? 'pages-router' as const\n : 'app-router' as const;\n const routes = await scanRoutes({ appDir: scanDir, routerType });\n\n if (routes.length === 0) {\n ui.error('No routes found in app/ directory.');\n process.exit(1);\n }\n\n // Filter excluded routes\n const filteredRoutes = routes.filter(\n (r) => !config.excludeRoutes.some((pattern: string) => r.urlPath.includes(pattern)),\n );\n\n ui.success(`Found ${filteredRoutes.length} routes`);\n for (const r of filteredRoutes) {\n ui.log(` ${r.urlPath}${r.isDynamic ? ' [dynamic]' : ''}`);\n }\n\n // Step 3: Check API key\n if (!config.apiKey) {\n ui.warn('No API key configured. Mock generation will use fallback data.');\n ui.log('Set C2D_API_KEY env var or add apiKey to c2d.config.js');\n }\n\n // Step 4: Analyze and generate mocks\n ui.header('Analyzing code and generating mocks...');\n\n const renderTasks: RenderTask[] = [];\n let totalTokens = { input: 0, output: 0 };\n\n const mockOptions: MockGeneratorOptions = {\n apiKey: config.apiKey,\n };\n\n for (let i = 0; i < filteredRoutes.length; i++) {\n const route = filteredRoutes[i];\n ui.step(i + 1, filteredRoutes.length, `${route.urlPath}`);\n\n // Analyze page\n const analysis = await analyzePage(route, { projectRoot });\n\n // Generate mocks\n const { configs, tokenUsage } = await generateMocks(analysis, mockOptions);\n totalTokens.input += tokenUsage.input;\n totalTokens.output += tokenUsage.output;\n\n // Create render tasks\n for (const mockConfig of configs) {\n renderTasks.push({\n route,\n mockConfig,\n authConfig: analysis.authConfig,\n });\n }\n }\n\n if (totalTokens.input > 0) {\n ui.success(`Mock generation complete (${totalTokens.input} input tokens, ${totalTokens.output} output tokens)`);\n } else {\n ui.success('Using fallback mocks (no API key or no API dependencies)');\n }\n\n // Step 5: Pre-render\n ui.header(`Pre-rendering ${renderTasks.length} page states...`);\n\n // Clear previous renders but preserve comments\n if (existsSync(join(c2dDir, 'renders'))) {\n await rm(join(c2dDir, 'renders'), { recursive: true });\n }\n await mkdir(c2dDir, { recursive: true });\n\n const { results, manifest } = await preRenderPages(renderTasks, {\n projectRoot,\n outputDir: c2dDir,\n devServerUrl: config.devServerUrl,\n onProgress: (completed, total, result) => {\n const pct = Math.round((completed / total) * 100);\n const icon = result.success ? '✓' : '✗';\n const label = `${result.route.urlPath} [${result.stateName}]`;\n process.stdout.write(`\\r ${icon} ${completed}/${total} (${pct}%) ${label}${''.padEnd(20)}`);\n if (completed === total) process.stdout.write('\\n');\n },\n });\n\n const successCount = results.filter((r) => r.success).length;\n const failCount = results.filter((r) => !r.success).length;\n\n ui.success(`Rendered ${successCount}/${results.length} pages`);\n if (failCount > 0) {\n ui.warn(`${failCount} pages failed to render`);\n for (const r of results.filter((r) => !r.success)) {\n ui.error(` ${r.route.urlPath} [${r.stateName}]: ${r.error}`);\n }\n }\n\n // Step 6: Start canvas server\n if (watch) {\n // In watch mode, start the server without blocking so we can watch for changes\n const server = await startServerNonBlocking(c2dDir, config.port, open, projectRoot);\n const watchDir = project.projectType === 'react-router'\n ? join(projectRoot, 'src')\n : project.appDir!;\n watchAndRerender(projectRoot, watchDir, c2dDir, config, routerType);\n\n // Keep process alive until Ctrl+C\n await new Promise<void>((resolve) => {\n const shutdown = async () => {\n ui.log('\\nShutting down...');\n await server.close();\n resolve();\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n });\n } else {\n await startServer(c2dDir, config.port, open, projectRoot);\n }\n}\n\nasync function startServer(c2dDir: string, port: number, open: boolean, projectRoot?: string): Promise<void> {\n ui.header('Starting canvas server...');\n\n // Resolve canvas app directory: find canvas-dist relative to this package\n const canvasDir = await resolveCanvasDir(c2dDir);\n if (!canvasDir) {\n ui.warn('Canvas app not bundled. Using placeholder.');\n }\n\n const server = await startCanvasServer({\n port,\n canvasDir,\n c2dDir,\n projectRoot,\n });\n\n ui.success(`Canvas server running at ${server.url}`);\n ui.log('Share this URL with your team for collaborative review');\n ui.log('Press Ctrl+C to stop\\n');\n\n if (open) {\n try {\n const { exec } = await import('node:child_process');\n exec(`open ${server.url}`);\n } catch {\n // Can't open browser — not critical\n }\n }\n\n // Keep process alive until Ctrl+C\n await new Promise<void>((resolve) => {\n const shutdown = async () => {\n ui.log('\\nShutting down...');\n await server.close();\n resolve();\n };\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n });\n}\n\nasync function startServerNonBlocking(\n c2dDir: string,\n port: number,\n open: boolean,\n projectRoot?: string,\n): Promise<{ url: string; close: () => Promise<void> }> {\n ui.header('Starting canvas server...');\n\n const canvasDir = await resolveCanvasDir(c2dDir);\n if (!canvasDir) {\n ui.warn('Canvas app not bundled. Using placeholder.');\n }\n\n const server = await startCanvasServer({\n port,\n canvasDir: canvasDir!,\n c2dDir,\n projectRoot,\n });\n\n ui.success(`Canvas server running at ${server.url}`);\n ui.log('Share this URL with your team for collaborative review');\n ui.log('Watching for file changes...\\n');\n\n if (open) {\n try {\n const { exec } = await import('node:child_process');\n exec(`open ${server.url}`);\n } catch {\n // Can't open browser — not critical\n }\n }\n\n return server;\n}\n\n/**\n * Find the canvas-dist directory by walking up from the module's location\n * until we find a directory containing canvas-dist/.\n * Works in both npm-installed and monorepo-dev environments.\n */\nasync function resolveCanvasDir(c2dDir: string): Promise<string> {\n const { fileURLToPath } = await import('node:url');\n const { dirname } = await import('node:path');\n const __filename = fileURLToPath(import.meta.url);\n\n // Walk up from the current file's directory to find canvas-dist/\n let dir = dirname(__filename);\n for (let i = 0; i < 5; i++) {\n const candidate = join(dir, 'canvas-dist');\n if (existsSync(candidate) && existsSync(join(candidate, 'index.html'))) {\n return candidate;\n }\n dir = dirname(dir);\n }\n\n // Fallback: try monorepo dev location\n const monorepoDev = join(dirname(__filename), '..', '..', '..', '..', 'apps', 'canvas', 'dist');\n if (existsSync(monorepoDev) && existsSync(join(monorepoDev, 'index.html'))) {\n return monorepoDev;\n }\n\n // Last resort: write placeholder\n const placeholder = join(c2dDir, '_canvas');\n await mkdir(placeholder, { recursive: true });\n const { writeFile } = await import('node:fs/promises');\n await writeFile(join(placeholder, 'index.html'), `<!DOCTYPE html><html><body>\n <h1>Code to Design</h1>\n <p>Canvas app not built. Run: <code>cd apps/canvas && npx vite build</code></p>\n <p><a href=\"/api/manifest\">View Manifest</a></p>\n </body></html>`);\n return placeholder;\n}\n\n/** File extensions to watch for changes. */\nconst WATCH_EXTENSIONS = new Set(['.tsx', '.ts', '.jsx', '.js', '.css']);\n\n/** Directories and patterns to ignore during watch. */\nfunction shouldIgnoreFile(filename: string | null): boolean {\n if (!filename) return true;\n const ignored = ['node_modules', '.next', '.c2d', '.git'];\n if (ignored.some((dir) => filename.includes(dir))) return true;\n const ext = filename.slice(filename.lastIndexOf('.'));\n return !WATCH_EXTENSIONS.has(ext);\n}\n\nfunction watchAndRerender(\n projectRoot: string,\n appDir: string,\n c2dDir: string,\n config: Awaited<ReturnType<typeof loadConfig>>,\n routerType?: 'app-router' | 'pages-router' | 'react-router',\n): void {\n let debounceTimer: ReturnType<typeof setTimeout> | undefined;\n let isRendering = false;\n\n ui.log(`Watching ${appDir} for changes...`);\n\n fsWatch(appDir, { recursive: true }, (_event, filename) => {\n if (shouldIgnoreFile(filename as string | null)) return;\n\n clearTimeout(debounceTimer);\n debounceTimer = setTimeout(async () => {\n if (isRendering) return;\n isRendering = true;\n\n ui.log(`\\nFile changed: ${filename}. Re-rendering...`);\n\n try {\n // Re-discover routes\n const routes = await scanRoutes({ appDir, routerType });\n const filteredRoutes = routes.filter(\n (r) => !config.excludeRoutes.some((pattern: string) => r.urlPath.includes(pattern)),\n );\n\n // Re-analyze and generate mocks\n const renderTasks: RenderTask[] = [];\n const mockOptions: MockGeneratorOptions = { apiKey: config.apiKey };\n\n for (const route of filteredRoutes) {\n const analysis = await analyzePage(route, { projectRoot });\n const { configs } = await generateMocks(analysis, mockOptions);\n for (const mockConfig of configs) {\n renderTasks.push({\n route,\n mockConfig,\n authConfig: analysis.authConfig,\n });\n }\n }\n\n // Clear previous renders\n if (existsSync(join(c2dDir, 'renders'))) {\n await rm(join(c2dDir, 'renders'), { recursive: true });\n }\n await mkdir(c2dDir, { recursive: true });\n\n // Pre-render\n const { results } = await preRenderPages(renderTasks, {\n projectRoot,\n outputDir: c2dDir,\n devServerUrl: config.devServerUrl,\n });\n\n const successCount = results.filter((r) => r.success).length;\n ui.success(`Re-render complete. ${successCount} pages updated.`);\n } catch (err: any) {\n ui.error(`Re-render failed: ${err.message || err}`);\n } finally {\n isRendering = false;\n }\n }, 500);\n });\n}\n","import { readdir, readFile, stat } from 'node:fs/promises';\nimport { join, extname } from 'node:path';\nimport { RouteInfo, RouteParam, ScanOptions } from './types.js';\n\nconst PAGE_EXTENSIONS = new Set(['.js', '.jsx', '.ts', '.tsx']);\nconst PAGE_BASENAMES = new Set(['page']);\n\n/** Files that should be skipped in Pages Router (special Next.js files). */\nconst PAGES_ROUTER_SKIP = new Set(['_app', '_document', '_error']);\n\n/**\n * Check if a filename is an App Router page file (page.tsx, page.js, etc.)\n */\nfunction isPageFile(filename: string): boolean {\n const ext = extname(filename);\n const basename = filename.slice(0, -ext.length);\n return PAGE_EXTENSIONS.has(ext) && PAGE_BASENAMES.has(basename);\n}\n\n/**\n * Check if a filename is a valid Pages Router page file.\n * Skips files starting with `_` and non-page extensions.\n */\nfunction isPagesRouterFile(filename: string): boolean {\n const ext = extname(filename);\n if (!PAGE_EXTENSIONS.has(ext)) return false;\n const basename = filename.slice(0, -ext.length);\n if (basename.startsWith('_')) return false;\n return true;\n}\n\n/**\n * Check if a directory should be skipped entirely.\n */\nfunction shouldSkipDir(name: string): boolean {\n // Private folders\n if (name.startsWith('_')) return true;\n // Parallel route slots\n if (name.startsWith('@')) return true;\n // Intercepting routes\n if (name.startsWith('(.)') || name.startsWith('(..)')) return true;\n // Build artifacts and dependencies\n if (name === 'node_modules' || name === '.next') return true;\n return false;\n}\n\n/**\n * Check if a directory is a route group (parenthesized name like \"(auth)\").\n * Route groups are stripped from the URL but recursed into.\n */\nfunction isRouteGroup(name: string): boolean {\n return name.startsWith('(') && name.endsWith(')') && !name.startsWith('(.');\n}\n\n/**\n * Parse a dynamic route segment and extract parameter info.\n * Returns null if the segment is not dynamic.\n */\nfunction parseDynamicSegment(segment: string): RouteParam | null {\n // Optional catch-all: [[...param]]\n const optionalCatchAll = segment.match(/^\\[\\[\\.\\.\\.(.+)\\]\\]$/);\n if (optionalCatchAll) {\n return { name: optionalCatchAll[1], isCatchAll: true, isOptional: true };\n }\n\n // Required catch-all: [...param]\n const catchAll = segment.match(/^\\[\\.\\.\\.(.+)\\]$/);\n if (catchAll) {\n return { name: catchAll[1], isCatchAll: true, isOptional: false };\n }\n\n // Single dynamic: [param]\n const dynamic = segment.match(/^\\[(.+)\\]$/);\n if (dynamic) {\n return { name: dynamic[1], isCatchAll: false, isOptional: false };\n }\n\n return null;\n}\n\n/**\n * Convert a dynamic segment to a URL-friendly representation.\n */\nfunction segmentToUrlPart(segment: string): string {\n const param = parseDynamicSegment(segment);\n if (!param) return segment;\n\n if (param.isCatchAll && param.isOptional) return `:${param.name}*`;\n if (param.isCatchAll) return `:${param.name}+`;\n return `:${param.name}`;\n}\n\n/**\n * Recursively scan a directory for Next.js App Router page files.\n */\nasync function scanDir(\n dirPath: string,\n urlSegments: string[],\n params: RouteParam[],\n): Promise<RouteInfo[]> {\n const routes: RouteInfo[] = [];\n\n let entries: string[];\n try {\n entries = await readdir(dirPath);\n } catch {\n return routes;\n }\n\n for (const entry of entries) {\n const entryPath = join(dirPath, entry);\n const entryStat = await stat(entryPath).catch(() => null);\n if (!entryStat) continue;\n\n if (entryStat.isFile() && isPageFile(entry)) {\n const urlPath = '/' + urlSegments.join('/');\n routes.push({\n urlPath: urlPath || '/',\n filePath: entryPath,\n params: [...params],\n isDynamic: params.length > 0,\n });\n }\n\n if (entryStat.isDirectory()) {\n if (shouldSkipDir(entry)) continue;\n\n if (isRouteGroup(entry)) {\n // Route groups: recurse but don't add to URL\n const nested = await scanDir(entryPath, urlSegments, params);\n routes.push(...nested);\n } else {\n // Regular or dynamic segment\n const param = parseDynamicSegment(entry);\n const urlPart = segmentToUrlPart(entry);\n const newParams = param ? [...params, param] : params;\n const nested = await scanDir(entryPath, [...urlSegments, urlPart], newParams);\n routes.push(...nested);\n }\n }\n }\n\n return routes;\n}\n\n/**\n * Recursively scan a Pages Router `pages/` directory for page files.\n *\n * Pages Router conventions:\n * - Any .tsx/.ts/.jsx/.js file is a route (not just `page.*`)\n * - `index.tsx` maps to the directory root\n * - `_app`, `_document`, `_error` are skipped\n * - Files starting with `_` are skipped\n * - `api/` directory is skipped (API routes)\n */\nasync function scanPagesDir(\n dirPath: string,\n urlSegments: string[],\n params: RouteParam[],\n): Promise<RouteInfo[]> {\n const routes: RouteInfo[] = [];\n\n let entries: string[];\n try {\n entries = await readdir(dirPath);\n } catch {\n return routes;\n }\n\n for (const entry of entries) {\n const entryPath = join(dirPath, entry);\n const entryStat = await stat(entryPath).catch(() => null);\n if (!entryStat) continue;\n\n if (entryStat.isFile() && isPagesRouterFile(entry)) {\n const ext = extname(entry);\n const basename = entry.slice(0, -ext.length);\n\n // Convert filename to URL segment\n let fileUrlSegments: string[];\n let fileParams: RouteParam[];\n\n if (basename === 'index') {\n // index.tsx → use current directory path\n fileUrlSegments = urlSegments;\n fileParams = params;\n } else {\n const param = parseDynamicSegment(basename);\n const urlPart = segmentToUrlPart(basename);\n fileUrlSegments = [...urlSegments, urlPart];\n fileParams = param ? [...params, param] : params;\n }\n\n const urlPath = '/' + fileUrlSegments.join('/');\n routes.push({\n urlPath: urlPath || '/',\n filePath: entryPath,\n params: [...fileParams],\n isDynamic: fileParams.length > 0,\n });\n }\n\n if (entryStat.isDirectory()) {\n // Skip api/ directory and hidden/private directories\n if (entry === 'api') continue;\n if (entry.startsWith('_')) continue;\n if (entry === 'node_modules' || entry === '.next') continue;\n\n const param = parseDynamicSegment(entry);\n const urlPart = segmentToUrlPart(entry);\n const newParams = param ? [...params, param] : params;\n const nested = await scanPagesDir(entryPath, [...urlSegments, urlPart], newParams);\n routes.push(...nested);\n }\n }\n\n return routes;\n}\n\n/**\n * Parse a React Router `:param` dynamic segment into a RouteParam.\n */\nfunction parseReactRouterParam(segment: string): RouteParam | null {\n if (!segment.startsWith(':')) return null;\n return { name: segment.slice(1), isCatchAll: false, isOptional: false };\n}\n\n/**\n * Recursively find files under `dir` that have one of the given extensions.\n */\nasync function findFiles(dir: string, extensions: Set<string>): Promise<string[]> {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = await readdir(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const full = join(dir, entry);\n const s = await stat(full).catch(() => null);\n if (!s) continue;\n if (s.isDirectory()) {\n if (entry === 'node_modules' || entry === '.git' || entry === 'dist' || entry === 'build') continue;\n results.push(...(await findFiles(full, extensions)));\n } else if (extensions.has(extname(entry))) {\n results.push(full);\n }\n }\n return results;\n}\n\n/**\n * Check if a project at the given root uses react-router-dom.\n */\nasync function hasReactRouter(projectRoot: string): Promise<boolean> {\n try {\n const pkg = JSON.parse(await readFile(join(projectRoot, 'package.json'), 'utf-8'));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n return 'react-router-dom' in deps || 'react-router' in deps;\n } catch {\n return false;\n }\n}\n\n/**\n * Extract route paths from a source file that uses react-router-dom.\n *\n * This is a best-effort regex-based approach. It handles:\n * - JSX: `<Route path=\"/about\" ...`\n * - Object config: `{ path: \"/about\" ...` or `{ path: '/about' ...`\n * - createBrowserRouter / createRoutesFromElements patterns\n */\nfunction extractRoutePathsFromSource(source: string): string[] {\n const paths: string[] = [];\n const seen = new Set<string>();\n\n // Pattern 1: <Route path=\"...\" or <Route path='...'\n const jsxPattern = /<Route\\s[^>]*?path\\s*=\\s*[\"']([^\"']+)[\"']/g;\n let match: RegExpExecArray | null;\n while ((match = jsxPattern.exec(source)) !== null) {\n const p = match[1];\n if (p !== '*' && !seen.has(p)) {\n seen.add(p);\n paths.push(p);\n }\n }\n\n // Pattern 2: { path: \"...\" } or { path: '...' } in route config objects\n const objPattern = /path\\s*:\\s*[\"']([^\"']+)[\"']/g;\n while ((match = objPattern.exec(source)) !== null) {\n const p = match[1];\n if (p !== '*' && !seen.has(p)) {\n seen.add(p);\n paths.push(p);\n }\n }\n\n return paths;\n}\n\n/**\n * Scan a React Router project and extract route definitions from source code.\n *\n * This is inherently imprecise since React Router uses code-based routing.\n * The scanner finds files that import from `react-router-dom` and contain\n * route definitions, then extracts paths using regex.\n */\nasync function scanReactRouter(projectRoot: string): Promise<RouteInfo[]> {\n const routes: RouteInfo[] = [];\n const seen = new Set<string>();\n\n // Find candidate source files under src/ (or project root if no src/)\n const srcDir = join(projectRoot, 'src');\n const scanRoot = await stat(srcDir).then(() => srcDir).catch(() => projectRoot);\n const files = await findFiles(scanRoot, PAGE_EXTENSIONS);\n\n for (const filePath of files) {\n let source: string;\n try {\n source = await readFile(filePath, 'utf-8');\n } catch {\n continue;\n }\n\n // Only process files that import from react-router-dom / react-router\n if (\n !source.includes('react-router-dom') &&\n !source.includes('react-router')\n ) {\n continue;\n }\n\n // Check for Route or createBrowserRouter usage\n if (\n !source.includes('Route') &&\n !source.includes('createBrowserRouter') &&\n !source.includes('createRoutesFromElements') &&\n !source.match(/path\\s*:\\s*[\"']/)\n ) {\n continue;\n }\n\n const extractedPaths = extractRoutePathsFromSource(source);\n\n for (const routePath of extractedPaths) {\n if (seen.has(routePath)) continue;\n seen.add(routePath);\n\n // Parse dynamic segments (:param)\n const segments = routePath.split('/').filter(Boolean);\n const params: RouteParam[] = [];\n for (const seg of segments) {\n const param = parseReactRouterParam(seg);\n if (param) params.push(param);\n }\n\n // Normalize path — ensure leading slash\n const urlPath = routePath.startsWith('/') ? routePath : '/' + routePath;\n\n routes.push({\n urlPath,\n filePath,\n params,\n isDynamic: params.length > 0,\n });\n }\n }\n\n return routes;\n}\n\n/**\n * Scan a project directory and extract all renderable routes.\n *\n * Supports Next.js App Router, Pages Router, and React Router (Vite):\n * - App Router: page.{js,jsx,ts,tsx} files, route groups, parallel routes, etc.\n * - Pages Router: any .tsx/.ts/.jsx/.js file (except _app, _document, _error, api/)\n * - React Router: regex-based extraction from source files importing react-router-dom\n *\n * For Next.js, `appDir` should point to the `app/` or `pages/` directory.\n * For React Router, `appDir` should point to the project root.\n * The scanner auto-detects which router convention to use based on `routerType`\n * (default 'auto' detects from directory name and project structure).\n */\nexport async function scanRoutes(options: ScanOptions): Promise<RouteInfo[]> {\n const { appDir, routerType = 'auto' } = options;\n\n // React Router: explicit or auto-detected\n if (routerType === 'react-router') {\n const routes = await scanReactRouter(appDir);\n routes.sort((a, b) => a.urlPath.localeCompare(b.urlPath));\n return routes;\n }\n\n if (routerType === 'auto') {\n // Check if this looks like a React Router project (has package.json with react-router-dom)\n const isReactRouter = await hasReactRouter(appDir);\n if (isReactRouter) {\n const routes = await scanReactRouter(appDir);\n routes.sort((a, b) => a.urlPath.localeCompare(b.urlPath));\n return routes;\n }\n }\n\n const dirStat = await stat(appDir).catch(() => null);\n if (!dirStat || !dirStat.isDirectory()) {\n throw new Error(`App directory not found: ${appDir}`);\n }\n\n // Detect if this is a Pages Router directory\n const dirName = appDir.replace(/\\/$/, '').split('/').pop();\n const isPagesRouter = routerType === 'pages-router' || (routerType === 'auto' && dirName === 'pages');\n\n const routes = isPagesRouter\n ? await scanPagesDir(appDir, [], [])\n : await scanDir(appDir, [], []);\n\n // Sort routes for consistent output\n routes.sort((a, b) => a.urlPath.localeCompare(b.urlPath));\n\n return routes;\n}\n","import { readFile } from 'node:fs/promises';\nimport { join, dirname, resolve, extname } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type { RouteInfo } from '../discovery/types.js';\nimport type { PageAnalysis, AnalyzeOptions } from './types.js';\nimport { detectAuth } from './auth-detector.js';\n\nconst DEFAULT_MAX_TOKENS = 8000;\nconst CHARS_PER_TOKEN = 4; // rough approximation\n\n/**\n * Extract import paths from TypeScript/JavaScript source code.\n * Uses regex — does not handle barrel exports or re-exports.\n */\nfunction extractImportPaths(source: string): string[] {\n const paths: string[] = [];\n // Match: import ... from '...' and import '...'\n const regex = /import\\s+(?:[\\s\\S]*?\\s+from\\s+)?['\"]([^'\"]+)['\"]/g;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(source)) !== null) {\n paths.push(match[1]);\n }\n return paths;\n}\n\n/**\n * Resolve tsconfig path aliases (e.g., @/lib/api → /absolute/path/lib/api).\n * Returns an absolute path when aliases contain absolute base paths.\n */\nfunction resolvePathAlias(\n importPath: string,\n aliases: Record<string, string>,\n): string | null {\n for (const [pattern, replacement] of Object.entries(aliases)) {\n const prefix = pattern.replace(/\\*$/, '');\n if (importPath.startsWith(prefix)) {\n const rest = importPath.slice(prefix.length);\n return replacement.replace(/\\*$/, '') + rest;\n }\n }\n return null;\n}\n\n/**\n * Read tsconfig.json and extract path aliases.\n */\nasync function readPathAliases(projectRoot: string): Promise<Record<string, string>> {\n const aliases: Record<string, string> = {};\n\n for (const filename of ['tsconfig.json', 'jsconfig.json']) {\n const configPath = join(projectRoot, filename);\n if (!existsSync(configPath)) continue;\n\n try {\n const content = await readFile(configPath, 'utf-8');\n // Strip JSON5-style comments while preserving // inside strings.\n // Match strings first (to skip them), then line & block comments.\n const stripped = content.replace(\n /\"(?:[^\"\\\\]|\\\\.)*\"|\\/\\/.*$|\\/\\*[\\s\\S]*?\\*\\//gm,\n (match) => (match.startsWith('\"') ? match : ''),\n );\n const config = JSON.parse(stripped);\n const paths = config.compilerOptions?.paths;\n const baseUrl = config.compilerOptions?.baseUrl || '.';\n const resolvedBaseUrl = resolve(projectRoot, baseUrl);\n\n if (paths) {\n for (const [key, values] of Object.entries(paths)) {\n const targets = values as string[];\n if (targets.length > 0) {\n // Store as absolute path for reliable resolution\n aliases[key] = join(resolvedBaseUrl, targets[0]);\n }\n }\n }\n } catch {\n // Can't parse tsconfig — skip aliases\n }\n }\n\n return aliases;\n}\n\n/**\n * Try to resolve an import path to an actual file.\n */\nfunction resolveImportToFile(importPath: string, fromDir: string): string | null {\n // Try exact path first, then with extensions\n const extensions = ['.ts', '.tsx', '.js', '.jsx'];\n const candidates: string[] = [];\n\n const resolved = resolve(fromDir, importPath);\n\n // Try exact\n candidates.push(resolved);\n // Try with extensions\n for (const ext of extensions) {\n candidates.push(resolved + ext);\n }\n // Try as directory with index\n for (const ext of extensions) {\n candidates.push(join(resolved, `index${ext}`));\n }\n\n for (const candidate of candidates) {\n if (existsSync(candidate)) return candidate;\n }\n return null;\n}\n\n/**\n * Trace imports from a source file, up to maxDepth levels deep.\n * Returns a map of filePath → source content.\n */\nasync function traceImports(\n filePath: string,\n projectRoot: string,\n aliases: Record<string, string>,\n maxDepth: number,\n visited: Set<string> = new Set(),\n): Promise<Map<string, string>> {\n const results = new Map<string, string>();\n\n if (visited.has(filePath) || maxDepth < 0) return results;\n visited.add(filePath);\n\n let source: string;\n try {\n source = await readFile(filePath, 'utf-8');\n } catch {\n return results;\n }\n\n results.set(filePath, source);\n\n const importPaths = extractImportPaths(source);\n const fileDir = dirname(filePath);\n\n for (const importPath of importPaths) {\n // Skip node_modules imports\n if (!importPath.startsWith('.') && !importPath.startsWith('@/') && !importPath.startsWith('~/')) {\n // Check if it's a path alias\n const aliasResolved = resolvePathAlias(importPath, aliases);\n if (!aliasResolved) continue;\n\n const resolved = resolveImportToFile(aliasResolved, projectRoot);\n if (resolved && !visited.has(resolved)) {\n const nested = await traceImports(resolved, projectRoot, aliases, maxDepth - 1, visited);\n for (const [path, content] of nested) {\n results.set(path, content);\n }\n }\n } else if (importPath.startsWith('.')) {\n // Relative import\n const resolved = resolveImportToFile(importPath, fileDir);\n if (resolved && !visited.has(resolved)) {\n const nested = await traceImports(resolved, projectRoot, aliases, maxDepth - 1, visited);\n for (const [path, content] of nested) {\n results.set(path, content);\n }\n }\n } else {\n // Path alias (e.g., @/lib/api-client)\n const aliasResolved = resolvePathAlias(importPath, aliases);\n if (aliasResolved) {\n const resolved = resolveImportToFile(aliasResolved, projectRoot);\n if (resolved && !visited.has(resolved)) {\n const nested = await traceImports(resolved, projectRoot, aliases, maxDepth - 1, visited);\n for (const [path, content] of nested) {\n results.set(path, content);\n }\n }\n }\n }\n }\n\n return results;\n}\n\n/**\n * Estimate token count from a string (rough: ~4 chars per token).\n */\nfunction estimateTokens(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n}\n\n/**\n * Check if source code contains API call patterns.\n */\nfunction hasApiCalls(source: string): boolean {\n return /\\bfetch\\s*\\(/.test(source)\n || /\\baxios\\b/.test(source)\n || /\\buseQuery\\b/.test(source)\n || /\\buseMutation\\b/.test(source)\n || /\\bapiRequest\\b/.test(source)\n || /\\bgetServerSideProps\\b/.test(source)\n || /\\bgetStaticProps\\b/.test(source)\n || /API_BASE_URL/.test(source)\n || /['\"]\\/api\\//.test(source)\n // Detect imports from api/client modules (common naming patterns)\n || /from\\s+['\"].*api[-_]?client.*['\"]/.test(source)\n || /from\\s+['\"].*\\/api['\"]/.test(source)\n || /from\\s+['\"].*\\/services\\//.test(source);\n}\n\n/**\n * Analyze a single page: read its source, trace imports, detect auth,\n * and produce a context string suitable for LLM mock generation.\n */\nexport async function analyzePage(\n route: RouteInfo,\n options: AnalyzeOptions,\n): Promise<PageAnalysis> {\n const { projectRoot, maxTokensPerPage = DEFAULT_MAX_TOKENS } = options;\n const maxChars = maxTokensPerPage * CHARS_PER_TOKEN;\n\n const aliases = await readPathAliases(projectRoot);\n\n // Trace imports from the page file, up to 2 levels deep\n const tracedFiles = await traceImports(route.filePath, projectRoot, aliases, 2);\n\n const resolvedImports = [...tracedFiles.keys()].filter(p => p !== route.filePath);\n const allSources = [...tracedFiles.values()];\n\n // Build the source context with file headers\n let sourceContext = '';\n for (const [filePath, content] of tracedFiles) {\n const relativePath = filePath.startsWith(projectRoot)\n ? filePath.slice(projectRoot.length + 1)\n : filePath;\n const section = `\\n// === ${relativePath} ===\\n${content}\\n`;\n\n if (sourceContext.length + section.length > maxChars) {\n // Truncation: include just the page file and skip the rest\n break;\n }\n sourceContext += section;\n }\n\n // Detect auth patterns\n const authConfig = await detectAuth(projectRoot, allSources);\n\n // Check for API dependencies — check both the truncated context and all traced sources\n const combinedSource = allSources.join('\\n');\n const hasApi = hasApiCalls(sourceContext) || hasApiCalls(combinedSource);\n\n // Collect unresolved imports\n const allImportPaths = allSources.flatMap(extractImportPaths);\n const resolvedSet = new Set(resolvedImports.map(p => p));\n const unresolvedImports = allImportPaths\n .filter(p => p.startsWith('.') || p.startsWith('@/') || p.startsWith('~/'))\n .filter(p => {\n // Check if this import was resolved to any file\n const aliasResolved = resolvePathAlias(p, aliases);\n const checkPath = aliasResolved\n ? resolveImportToFile(aliasResolved, projectRoot)\n : resolveImportToFile(p, dirname(route.filePath));\n return !checkPath;\n });\n\n return {\n route,\n sourceContext,\n resolvedImports,\n unresolvedImports: [...new Set(unresolvedImports)],\n authConfig,\n hasApiDependencies: hasApi,\n estimatedTokens: estimateTokens(sourceContext),\n };\n}\n\n/**\n * Analyze all discovered routes in a project.\n */\nexport async function analyzeRoutes(\n routes: RouteInfo[],\n options: AnalyzeOptions,\n): Promise<PageAnalysis[]> {\n const results: PageAnalysis[] = [];\n for (const route of routes) {\n const analysis = await analyzePage(route, options);\n results.push(analysis);\n }\n return results;\n}\n","import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type { AuthConfig } from './types.js';\n\nconst MIDDLEWARE_FILES = ['middleware.ts', 'middleware.js', 'middleware.tsx', 'middleware.jsx'];\n\n/**\n * Extract cookie names from middleware source code.\n * Looks for patterns like: request.cookies.get('access_token')\n */\nfunction extractCookieNames(source: string): string[] {\n const cookies: string[] = [];\n const regex = /cookies\\.get\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(source)) !== null) {\n cookies.push(match[1]);\n }\n return [...new Set(cookies)];\n}\n\n/**\n * Extract API base URL from environment configuration.\n * Looks for NEXT_PUBLIC_API_URL or similar patterns.\n */\nfunction extractApiBaseUrl(source: string): string | null {\n const regex = /process\\.env\\.(\\w*API_URL\\w*)\\s*\\|\\|\\s*['\"]([^'\"]+)['\"]/;\n const match = source.match(regex);\n if (match) return match[2];\n\n const simpleRegex = /['\"]https?:\\/\\/[^'\"]+\\/api['\"]/;\n const simpleMatch = source.match(simpleRegex);\n if (simpleMatch) return simpleMatch[0].replace(/['\"]/g, '');\n\n return null;\n}\n\n/**\n * Extract auth check endpoint from source code.\n * Looks for patterns like: fetch(`${base}/auth/me`)\n */\nfunction extractAuthCheckEndpoint(source: string): string | null {\n const patterns = [\n /[`'\"](\\/auth\\/me)[`'\"]/,\n /[`'\"](\\/api\\/auth\\/me)[`'\"]/,\n /[`'\"](\\/auth\\/session)[`'\"]/,\n /[`'\"](\\/api\\/auth\\/session)[`'\"]/,\n /[`'\"](\\/auth\\/user)[`'\"]/,\n /[`'\"](\\/api\\/user\\/me)[`'\"]/,\n ];\n\n for (const pattern of patterns) {\n const match = source.match(pattern);\n if (match) return match[1];\n }\n\n return null;\n}\n\n/**\n * Detect authentication patterns in the target project.\n *\n * Scans for:\n * 1. middleware.ts/js with cookie checks\n * 2. Auth context providers with auth-check endpoints\n * 3. API base URL configuration\n */\nexport async function detectAuth(projectRoot: string, allSources: string[]): Promise<AuthConfig> {\n const config: AuthConfig = {\n hasAuth: false,\n cookieNames: [],\n authCheckEndpoint: null,\n apiBaseUrl: null,\n };\n\n // 1. Check for middleware\n for (const filename of MIDDLEWARE_FILES) {\n const middlewarePath = join(projectRoot, filename);\n if (existsSync(middlewarePath)) {\n try {\n const source = await readFile(middlewarePath, 'utf-8');\n const cookies = extractCookieNames(source);\n if (cookies.length > 0) {\n config.hasAuth = true;\n config.cookieNames.push(...cookies);\n }\n } catch {\n // Middleware exists but can't be read — skip\n }\n }\n }\n\n // 2. Scan all collected sources for auth patterns\n const combinedSource = allSources.join('\\n');\n\n const authEndpoint = extractAuthCheckEndpoint(combinedSource);\n if (authEndpoint) {\n config.hasAuth = true;\n config.authCheckEndpoint = authEndpoint;\n }\n\n // Look for auth context patterns\n if (/useAuth|AuthProvider|AuthContext|SessionProvider/i.test(combinedSource)) {\n config.hasAuth = true;\n }\n\n // 3. Extract API base URL\n config.apiBaseUrl = extractApiBaseUrl(combinedSource);\n\n return config;\n}\n","/**\n * A single mock response for an API endpoint.\n */\nexport interface MockResponse {\n /** HTTP status code */\n status: number;\n /** Response body as JSON-serializable data */\n body: unknown;\n /** Optional delay in milliseconds before responding */\n delay?: number;\n}\n\n/**\n * A complete mock configuration for rendering a page in a specific state.\n */\nexport interface MockConfig {\n /** State variant name (e.g., \"success\", \"error\", \"empty\", \"loading\") */\n stateName: string;\n /** Map of URL patterns to mock responses */\n apiMocks: Record<string, MockResponse>;\n /** Mock user data for auth, if auth is required */\n authMock: {\n /** Cookies to inject (e.g., { access_token: \"mock_token\" }) */\n cookies: Record<string, string>;\n /** Auth check endpoint mock response */\n authCheckResponse: MockResponse | null;\n } | null;\n /** Sample route parameters for dynamic routes */\n routeParams?: Record<string, string>;\n}\n\n/**\n * State variants to generate for each page.\n */\nexport type StateVariant = 'success' | 'empty' | 'error' | 'loading';\n\nexport const ALL_STATE_VARIANTS: StateVariant[] = ['success', 'empty', 'error', 'loading'];\n\n/**\n * Options for mock generation.\n */\nexport interface MockGeneratorOptions {\n /** Anthropic API key */\n apiKey: string;\n /** Model to use (default: claude-sonnet-4-20250514) */\n model?: string;\n /** State variants to generate (default: all) */\n variants?: StateVariant[];\n}\n","import Anthropic from '@anthropic-ai/sdk';\n\nexport interface LlmResponse {\n content: string;\n inputTokens: number;\n outputTokens: number;\n}\n\n/**\n * Simple LLM client wrapper for Anthropic Claude API.\n */\nexport class LlmClient {\n private client: Anthropic;\n private model: string;\n\n constructor(apiKey: string, model: string = 'claude-sonnet-4-20250514') {\n this.client = new Anthropic({ apiKey });\n this.model = model;\n }\n\n async generate(systemPrompt: string, userPrompt: string): Promise<LlmResponse> {\n const response = await this.client.messages.create({\n model: this.model,\n max_tokens: 4096,\n system: systemPrompt,\n messages: [{ role: 'user', content: userPrompt }],\n });\n\n const textBlock = response.content.find(block => block.type === 'text');\n const content = textBlock ? textBlock.text : '';\n\n return {\n content,\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n };\n }\n}\n","import type { PageAnalysis } from '../analysis/types.js';\n\nexport const SYSTEM_PROMPT = `You are a mock data generator for a UI pre-rendering tool called VibeCanvas.\nYour job is to analyze a Next.js page's source code and generate realistic mock API responses that will make the page render correctly.\n\nRules:\n1. Output ONLY valid JSON — no markdown, no code fences, no explanation.\n2. Mock data must match the TypeScript interfaces found in the source code.\n3. Generate contextually appropriate data (e.g., real company names for a finance app, realistic usernames for a social app).\n4. For each API endpoint, generate mock responses for these state variants:\n - \"success\": realistic data with multiple items\n - \"empty\": empty collections, zero counts\n - \"error\": API returns HTTP 500 with error message\n - \"loading\": same as success but with a 3000ms delay\n5. Include auth mock data if the page requires authentication.\n6. For dynamic route parameters, generate a realistic sample value.`;\n\n/**\n * Build the user prompt for mock generation from a PageAnalysis.\n */\nexport function buildUserPrompt(analysis: PageAnalysis): string {\n const parts: string[] = [];\n\n parts.push(`## Page Route: ${analysis.route.urlPath}`);\n parts.push(`## Page File: ${analysis.route.filePath}`);\n\n if (analysis.route.isDynamic) {\n parts.push(`## Dynamic Parameters: ${analysis.route.params.map(p => p.name).join(', ')}`);\n }\n\n parts.push('## Source Code Context');\n parts.push(analysis.sourceContext);\n\n if (analysis.authConfig.hasAuth) {\n parts.push('## Auth Configuration');\n parts.push(`- Requires authentication: yes`);\n if (analysis.authConfig.cookieNames.length > 0) {\n parts.push(`- Auth cookies: ${analysis.authConfig.cookieNames.join(', ')}`);\n }\n if (analysis.authConfig.authCheckEndpoint) {\n parts.push(`- Auth check endpoint: ${analysis.authConfig.authCheckEndpoint}`);\n }\n if (analysis.authConfig.apiBaseUrl) {\n parts.push(`- API base URL: ${analysis.authConfig.apiBaseUrl}`);\n }\n }\n\n parts.push(`\n## Required Output Format\n\nReturn a JSON object with this exact structure:\n{\n \"routeParams\": { \"paramName\": \"sampleValue\" }, // only if dynamic route\n \"apiEndpoints\": [\n {\n \"urlPattern\": \"/api/endpoint\", // the URL path pattern to intercept\n \"method\": \"GET\", // HTTP method\n \"states\": {\n \"success\": { \"status\": 200, \"body\": { ... } },\n \"empty\": { \"status\": 200, \"body\": { ... } },\n \"error\": { \"status\": 500, \"body\": { \"detail\": \"Internal server error\" } },\n \"loading\": { \"status\": 200, \"body\": { ... }, \"delay\": 3000 }\n }\n }\n ],\n \"authMock\": { // only if auth is required\n \"cookies\": { \"cookie_name\": \"mock_value\" },\n \"authCheckEndpoint\": \"/auth/me\",\n \"authCheckResponse\": { \"status\": 200, \"body\": { ... } }\n }\n}\n\nGenerate ONLY the JSON. No explanation, no markdown fences.`);\n\n return parts.join('\\n\\n');\n}\n","import type { PageAnalysis } from '../analysis/types.js';\nimport type { MockConfig, MockResponse, StateVariant, MockGeneratorOptions } from './types.js';\nimport { ALL_STATE_VARIANTS } from './types.js';\nimport { LlmClient } from './llm-client.js';\nimport { SYSTEM_PROMPT, buildUserPrompt } from './prompt-templates.js';\n\ninterface LlmMockOutput {\n routeParams?: Record<string, string>;\n apiEndpoints?: Array<{\n urlPattern: string;\n method: string;\n states: Record<string, { status: number; body: unknown; delay?: number }>;\n }>;\n authMock?: {\n cookies: Record<string, string>;\n authCheckEndpoint: string;\n authCheckResponse: { status: number; body: unknown };\n };\n}\n\n/**\n * Parse the LLM response as JSON, handling common formatting issues.\n */\nfunction parseLlmJson(content: string): LlmMockOutput | null {\n // Strip markdown code fences if present\n let cleaned = content.trim();\n if (cleaned.startsWith('```')) {\n cleaned = cleaned.replace(/^```(?:json)?\\n?/, '').replace(/\\n?```$/, '');\n }\n\n try {\n return JSON.parse(cleaned);\n } catch {\n // Try to find JSON object in the response\n const jsonMatch = cleaned.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch) {\n try {\n return JSON.parse(jsonMatch[0]);\n } catch {\n return null;\n }\n }\n return null;\n }\n}\n\n/**\n * Convert LLM output into MockConfig[] (one per state variant).\n */\nfunction convertToMockConfigs(\n output: LlmMockOutput,\n analysis: PageAnalysis,\n variants: StateVariant[],\n): MockConfig[] {\n const configs: MockConfig[] = [];\n\n for (const variant of variants) {\n const apiMocks: Record<string, MockResponse> = {};\n\n if (output.apiEndpoints) {\n for (const endpoint of output.apiEndpoints) {\n const stateData = endpoint.states[variant];\n if (stateData) {\n const key = `${endpoint.method} ${endpoint.urlPattern}`;\n apiMocks[key] = {\n status: stateData.status,\n body: stateData.body,\n delay: stateData.delay,\n };\n }\n }\n }\n\n let authMock: MockConfig['authMock'] = null;\n if (analysis.authConfig.hasAuth && output.authMock) {\n authMock = {\n cookies: output.authMock.cookies,\n authCheckResponse: {\n status: output.authMock.authCheckResponse.status,\n body: output.authMock.authCheckResponse.body,\n },\n };\n }\n\n configs.push({\n stateName: variant,\n apiMocks,\n authMock,\n routeParams: output.routeParams,\n });\n }\n\n return configs;\n}\n\n/**\n * Generate a fallback MockConfig when LLM fails or page has no API deps.\n */\nfunction generateFallbackConfigs(\n analysis: PageAnalysis,\n variants: StateVariant[],\n): MockConfig[] {\n return variants.map(variant => ({\n stateName: variant,\n apiMocks: {},\n authMock: analysis.authConfig.hasAuth\n ? {\n cookies: Object.fromEntries(\n analysis.authConfig.cookieNames.map(name => [name, 'mock_token_c2d']),\n ),\n authCheckResponse: variant === 'error'\n ? { status: 401, body: { detail: 'Unauthorized' } }\n : { status: 200, body: { id: 'mock_user', email: 'demo@c2d.dev', name: 'Demo User' } },\n }\n : null,\n routeParams: analysis.route.isDynamic\n ? Object.fromEntries(analysis.route.params.map(p => [p.name, 'sample-1']))\n : undefined,\n }));\n}\n\n/**\n * Generate mock data for a single page using an LLM.\n *\n * Returns one MockConfig per requested state variant.\n * Falls back to empty mocks if:\n * - The page has no API dependencies\n * - LLM returns invalid data\n * - LLM call fails\n */\nexport async function generateMocks(\n analysis: PageAnalysis,\n options: MockGeneratorOptions,\n): Promise<{ configs: MockConfig[]; tokenUsage: { input: number; output: number } }> {\n const variants = options.variants ?? ALL_STATE_VARIANTS;\n\n // If no API dependencies, just return fallback configs (no LLM call needed)\n if (!analysis.hasApiDependencies) {\n return {\n configs: generateFallbackConfigs(analysis, variants),\n tokenUsage: { input: 0, output: 0 },\n };\n }\n\n const client = new LlmClient(options.apiKey, options.model);\n const userPrompt = buildUserPrompt(analysis);\n\n try {\n const response = await client.generate(SYSTEM_PROMPT, userPrompt);\n const parsed = parseLlmJson(response.content);\n\n if (!parsed) {\n console.warn(`[c2d] Failed to parse LLM response for ${analysis.route.urlPath}, using fallback`);\n return {\n configs: generateFallbackConfigs(analysis, variants),\n tokenUsage: { input: response.inputTokens, output: response.outputTokens },\n };\n }\n\n const configs = convertToMockConfigs(parsed, analysis, variants);\n\n return {\n configs,\n tokenUsage: { input: response.inputTokens, output: response.outputTokens },\n };\n } catch (error) {\n console.warn(`[c2d] LLM call failed for ${analysis.route.urlPath}: ${error}`);\n return {\n configs: generateFallbackConfigs(analysis, variants),\n tokenUsage: { input: 0, output: 0 },\n };\n }\n}\n\n/**\n * Generate mocks for all analyzed pages.\n */\nexport async function generateAllMocks(\n analyses: PageAnalysis[],\n options: MockGeneratorOptions,\n): Promise<{\n results: Map<string, MockConfig[]>;\n totalTokens: { input: number; output: number };\n}> {\n const results = new Map<string, MockConfig[]>();\n const totalTokens = { input: 0, output: 0 };\n\n for (const analysis of analyses) {\n const { configs, tokenUsage } = await generateMocks(analysis, options);\n results.set(analysis.route.urlPath, configs);\n totalTokens.input += tokenUsage.input;\n totalTokens.output += tokenUsage.output;\n }\n\n return { results, totalTokens };\n}\n","import { chromium, type Browser, type BrowserContext, type Page } from 'playwright';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { MockConfig, MockResponse } from '../mock/types.js';\nimport type { AuthConfig } from '../analysis/types.js';\nimport type { RouteInfo } from '../discovery/types.js';\nimport type {\n RenderResult,\n RenderTask,\n RenderManifest,\n ManifestRoute,\n PreRenderOptions,\n ViewportConfig,\n} from './types.js';\nimport { startDevServer, type DevServerHandle } from './dev-server.js';\nimport { inlineStylesAndCleanup } from './style-inliner.js';\nimport { captureInteractions, type InteractionResult } from './interaction-capturer.js';\n\nconst DEFAULT_CONCURRENCY = 3;\nconst DEFAULT_PAGE_TIMEOUT = 15000;\nconst DEFAULT_SETTLE_TIME = 1500;\nconst DEFAULT_VIEWPORT = { width: 1440, height: 900 };\n\n/**\n * Build the actual URL path for a route, substituting dynamic params.\n */\nfunction buildUrlPath(route: RouteInfo, mockConfig: MockConfig): string {\n let path = route.urlPath;\n if (route.isDynamic && mockConfig.routeParams) {\n for (const param of route.params) {\n const value = mockConfig.routeParams[param.name] || 'sample-1';\n path = path.replace(`:${param.name}`, value);\n // Also handle catch-all notation\n path = path.replace(`:${param.name}+`, value);\n path = path.replace(`:${param.name}*`, value);\n }\n }\n return path;\n}\n\n/**\n * Slugify a URL path for use as a directory name.\n * \"/\" → \"index\", \"/dashboard\" → \"dashboard\", \"/editor/:id\" → \"editor-_id\"\n */\nfunction slugifyRoute(urlPath: string): string {\n if (urlPath === '/') return 'index';\n return urlPath\n .replace(/^\\//, '')\n .replace(/\\//g, '-')\n .replace(/:/g, '_')\n .replace(/[^a-zA-Z0-9_-]/g, '_');\n}\n\n/**\n * Set up Playwright route interception for a page with the given mock config.\n */\nasync function setupMockInterception(\n page: Page,\n devServerUrl: string,\n mockConfig: MockConfig,\n authConfig: AuthConfig,\n): Promise<void> {\n // 1. Inject auth cookies if needed\n if (mockConfig.authMock) {\n const cookies = Object.entries(mockConfig.authMock.cookies).map(([name, value]) => ({\n name,\n value,\n domain: new URL(devServerUrl).hostname,\n path: '/',\n }));\n await page.context().addCookies(cookies);\n } else if (authConfig.hasAuth && authConfig.cookieNames.length > 0) {\n // Fallback: inject dummy cookies for detected auth\n const cookies = authConfig.cookieNames.map(name => ({\n name,\n value: 'c2d_mock_token',\n domain: new URL(devServerUrl).hostname,\n path: '/',\n }));\n await page.context().addCookies(cookies);\n }\n\n // 2. Build auth mock response for interception\n const authMockBody = mockConfig.authMock?.authCheckResponse\n ? JSON.stringify(mockConfig.authMock.authCheckResponse.body)\n : JSON.stringify({ id: 'mock_user', email: 'demo@c2d.dev', name: 'Demo User', email_verified: true, avatar_url: null, created_at: '2026-01-01T00:00:00Z' });\n\n // Common auth check URL patterns to always intercept\n const AUTH_PATTERNS = ['/auth/me', '/auth/session', '/api/auth/me', '/api/user/me', '/api/auth/session'];\n\n // 3. Intercept API calls\n await page.route('**/*', async (route) => {\n const request = route.request();\n const url = request.url();\n const method = request.method();\n\n // Always intercept auth check endpoints (common patterns + detected endpoint)\n const isAuthCheck = AUTH_PATTERNS.some(p => url.includes(p))\n || (authConfig.authCheckEndpoint && url.includes(authConfig.authCheckEndpoint));\n\n if (isAuthCheck) {\n const status = mockConfig.authMock?.authCheckResponse?.status ?? 200;\n return route.fulfill({\n status,\n contentType: 'application/json',\n body: authMockBody,\n });\n }\n\n // Check API mocks from AI-generated config\n for (const [pattern, mock] of Object.entries(mockConfig.apiMocks)) {\n // Pattern format: \"GET /api/reports\" or \"DELETE /api/reports/{id}\"\n const [mockMethod, ...pathParts] = pattern.split(' ');\n let mockPath = pathParts.join(' ');\n // Convert {param} placeholders to match any value\n mockPath = mockPath.replace(/\\{[^}]+\\}/g, '[^/]+');\n // Also handle * wildcards\n mockPath = mockPath.replace(/\\*/g, '[^/]+');\n\n const pathRegex = new RegExp(mockPath.replace(/\\//g, '\\\\/'));\n if (method === mockMethod && pathRegex.test(url)) {\n if (mock.delay) await new Promise(r => setTimeout(r, mock.delay));\n return route.fulfill({\n status: mock.status,\n contentType: 'application/json',\n body: JSON.stringify(mock.body),\n });\n }\n }\n\n // Pass through all other requests\n return route.continue();\n });\n}\n\n/**\n * Render a single page in a specific state and capture HTML + screenshot.\n */\nasync function renderPage(\n context: BrowserContext,\n devServerUrl: string,\n task: RenderTask,\n outputDir: string,\n options: { pageTimeout: number; settleTime: number; captureInteractionStates?: boolean; maxInteractions?: number },\n viewport?: ViewportConfig,\n): Promise<RenderResult> {\n const { route, mockConfig, authConfig } = task;\n const routeSlug = slugifyRoute(route.urlPath);\n const stateDir = join(outputDir, 'renders', routeSlug);\n await mkdir(stateDir, { recursive: true });\n\n // Include viewport name in file paths to avoid collisions when rendering multiple viewports\n const filePrefix = viewport ? `${mockConfig.stateName}_${viewport.name}` : mockConfig.stateName;\n const htmlRelPath = join('renders', routeSlug, `${filePrefix}.html`);\n const pngRelPath = join('renders', routeSlug, `${filePrefix}.png`);\n const htmlAbsPath = join(outputDir, htmlRelPath);\n const pngAbsPath = join(outputDir, pngRelPath);\n\n const page = await context.newPage();\n\n // Override viewport size for this page if a specific viewport was requested\n if (viewport) {\n await page.setViewportSize({ width: viewport.width, height: viewport.height });\n }\n\n try {\n await setupMockInterception(page, devServerUrl, mockConfig, authConfig);\n\n const urlPath = buildUrlPath(route, mockConfig);\n const fullUrl = `${devServerUrl}${urlPath}`;\n\n await page.goto(fullUrl, {\n waitUntil: 'networkidle',\n timeout: options.pageTimeout,\n });\n\n // Extra settle time for React hydration\n await page.waitForTimeout(options.settleTime);\n\n // Inline all external stylesheets so HTML is self-contained\n await inlineStylesAndCleanup(page);\n\n // Capture HTML\n const html = await page.content();\n await writeFile(htmlAbsPath, html, 'utf-8');\n\n // Capture screenshot\n await page.screenshot({ path: pngAbsPath, fullPage: true });\n\n // Capture interaction variants (only for success/empty states, not error/loading)\n const interactionStates = ['success', 'empty'];\n const shouldCapture = options.captureInteractionStates !== false\n && interactionStates.includes(mockConfig.stateName);\n\n let interactions: Array<{ description: string; htmlPath: string }> | undefined;\n\n if (shouldCapture) {\n // Reload before interaction capture to get a clean page with scripts intact\n await page.goto(fullUrl, { waitUntil: 'networkidle', timeout: options.pageTimeout });\n await page.waitForTimeout(options.settleTime);\n\n const interactionResults = await captureInteractions(\n page,\n fullUrl,\n route,\n mockConfig.stateName,\n outputDir,\n { maxInteractions: options.maxInteractions, settleTime: 500 },\n );\n\n const successful = interactionResults.filter(r => r.success);\n if (successful.length > 0) {\n interactions = successful.map(r => ({\n description: r.elementDescription,\n htmlPath: r.htmlPath,\n }));\n }\n }\n\n return {\n route,\n stateName: mockConfig.stateName,\n htmlPath: htmlRelPath,\n screenshotPath: pngRelPath,\n success: true,\n viewportName: viewport?.name,\n interactions,\n };\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : String(err);\n\n // Write an error placeholder HTML\n const errorHtml = `<!DOCTYPE html><html><body style=\"display:flex;align-items:center;justify-content:center;height:100vh;font-family:sans-serif;color:#666;\">\n <div style=\"text-align:center\"><h2>Render Failed</h2><p>${route.urlPath} [${mockConfig.stateName}]</p><pre style=\"color:#c00\">${errorMsg}</pre></div>\n </body></html>`;\n await writeFile(htmlAbsPath, errorHtml, 'utf-8').catch(() => {});\n\n return {\n route,\n stateName: mockConfig.stateName,\n htmlPath: htmlRelPath,\n screenshotPath: pngRelPath,\n success: false,\n error: errorMsg,\n viewportName: viewport?.name,\n };\n } finally {\n await page.close();\n }\n}\n\n/**\n * Process render tasks with limited concurrency.\n */\nasync function processWithConcurrency<T>(\n items: T[],\n concurrency: number,\n fn: (item: T) => Promise<RenderResult>,\n onProgress?: (completed: number, total: number, result: RenderResult) => void,\n): Promise<RenderResult[]> {\n const results: RenderResult[] = [];\n const queue = [...items];\n const total = items.length;\n let completed = 0;\n\n async function worker() {\n while (queue.length > 0) {\n const item = queue.shift()!;\n const result = await fn(item);\n results.push(result);\n completed++;\n onProgress?.(completed, total, result);\n }\n }\n\n const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());\n await Promise.all(workers);\n\n return results;\n}\n\n/**\n * Build the render manifest from results.\n */\nfunction buildManifest(\n results: RenderResult[],\n projectName: string,\n viewports?: ViewportConfig[],\n): RenderManifest {\n const routeMap = new Map<string, ManifestRoute>();\n\n // Build a lookup for viewport widths by name\n const viewportWidthMap = new Map<string, number>();\n if (viewports) {\n for (const vp of viewports) {\n viewportWidthMap.set(vp.name, vp.width);\n }\n }\n\n for (const result of results) {\n const key = result.route.urlPath;\n if (!routeMap.has(key)) {\n routeMap.set(key, {\n urlPath: result.route.urlPath,\n filePath: result.route.filePath,\n states: [],\n });\n }\n routeMap.get(key)!.states.push({\n name: result.viewportName\n ? `${result.stateName} (${result.viewportName})`\n : result.stateName,\n htmlPath: result.htmlPath,\n screenshotPath: result.screenshotPath,\n status: result.success ? 'ok' : 'error',\n error: result.error,\n viewport: result.viewportName,\n viewportWidth: result.viewportName\n ? viewportWidthMap.get(result.viewportName)\n : undefined,\n interactions: result.interactions,\n });\n }\n\n return {\n generatedAt: new Date().toISOString(),\n projectName,\n routes: [...routeMap.values()].sort((a, b) => a.urlPath.localeCompare(b.urlPath)),\n };\n}\n\n/**\n * Pre-render all pages with their mock configurations.\n *\n * This is the main entry point for the rendering pipeline:\n * 1. Start dev server (or use provided URL)\n * 2. Launch Playwright browser\n * 3. For each (route, state) pair: intercept APIs, navigate, capture\n * 4. Write manifest.json\n * 5. Clean up\n */\nexport async function preRenderPages(\n tasks: RenderTask[],\n options: PreRenderOptions,\n): Promise<{ results: RenderResult[]; manifest: RenderManifest }> {\n const {\n projectRoot,\n outputDir = join(projectRoot, '.c2d'),\n concurrency = DEFAULT_CONCURRENCY,\n pageTimeout = DEFAULT_PAGE_TIMEOUT,\n settleTime = DEFAULT_SETTLE_TIME,\n viewportWidth = DEFAULT_VIEWPORT.width,\n viewportHeight = DEFAULT_VIEWPORT.height,\n captureInteractions: captureInteractionStates = true,\n maxInteractions,\n } = options;\n\n // Resolve viewports: if explicit viewports array is provided use it,\n // otherwise fall back to the single viewport from viewportWidth/Height\n // (which themselves default to 1440x900).\n const viewports: ViewportConfig[] | undefined = options.viewports;\n const useMultiViewport = viewports && viewports.length > 0;\n\n // Create output directory\n await mkdir(outputDir, { recursive: true });\n\n // Start dev server\n let devServer: DevServerHandle | null = null;\n try {\n devServer = await startDevServer(projectRoot, {\n port: options.devServerPort,\n devServerUrl: options.devServerUrl,\n });\n\n // Launch browser\n const browser = await chromium.launch({ headless: true });\n const context = await browser.newContext({\n viewport: { width: viewportWidth, height: viewportHeight },\n });\n\n try {\n let results: RenderResult[];\n\n if (useMultiViewport) {\n // Expand tasks: each original task is rendered at each viewport\n const expandedItems: Array<{ task: RenderTask; viewport: ViewportConfig }> = [];\n for (const task of tasks) {\n for (const vp of viewports) {\n expandedItems.push({ task, viewport: vp });\n }\n }\n\n results = await processWithConcurrency(\n expandedItems,\n concurrency,\n ({ task, viewport: vp }) =>\n renderPage(context, devServer!.url, task, outputDir, { pageTimeout, settleTime, captureInteractionStates, maxInteractions }, vp),\n options.onProgress,\n );\n } else {\n // Single viewport — backward-compatible path (no viewportName in results)\n results = await processWithConcurrency(\n tasks,\n concurrency,\n (task) => renderPage(context, devServer!.url, task, outputDir, { pageTimeout, settleTime, captureInteractionStates, maxInteractions }),\n options.onProgress,\n );\n }\n\n // Read project name from package.json\n let projectName = 'unknown';\n try {\n const pkg = await import(join(projectRoot, 'package.json'), { with: { type: 'json' } });\n projectName = pkg.default?.name || 'unknown';\n } catch {\n // Can't read package.json — use fallback\n }\n\n // Build and write manifest\n const manifest = buildManifest(\n results,\n projectName,\n useMultiViewport ? viewports : undefined,\n );\n await writeFile(\n join(outputDir, 'manifest.json'),\n JSON.stringify(manifest, null, 2),\n 'utf-8',\n );\n\n return { results, manifest };\n } finally {\n await context.close();\n await browser.close();\n }\n } finally {\n if (devServer) {\n await devServer.stop();\n }\n }\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createServer } from 'node:net';\n\n/**\n * Find a free port on the system.\n */\nexport async function findFreePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = createServer();\n server.listen(0, () => {\n const address = server.address();\n if (address && typeof address === 'object') {\n const port = address.port;\n server.close(() => resolve(port));\n } else {\n server.close(() => reject(new Error('Could not find free port')));\n }\n });\n server.on('error', reject);\n });\n}\n\n/**\n * Wait for a URL to become reachable.\n */\nasync function waitForUrl(url: string, timeoutMs: number = 30000): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n const response = await fetch(url, { signal: AbortSignal.timeout(2000) });\n // Any response (even redirects) means the server is up\n if (response.status > 0) return;\n } catch {\n // Server not ready yet\n }\n await new Promise(r => setTimeout(r, 500));\n }\n throw new Error(`Dev server did not become ready at ${url} within ${timeoutMs}ms`);\n}\n\n/**\n * Detect the dev command for a project.\n */\nfunction detectDevCommand(projectRoot: string): { cmd: string; args: string[] } {\n if (existsSync(join(projectRoot, 'next.config.ts')) ||\n existsSync(join(projectRoot, 'next.config.js')) ||\n existsSync(join(projectRoot, 'next.config.mjs'))) {\n return { cmd: 'npx', args: ['next', 'dev'] };\n }\n // Fallback to npm run dev\n return { cmd: 'npm', args: ['run', 'dev'] };\n}\n\nexport interface DevServerHandle {\n url: string;\n port: number;\n process: ChildProcess | null;\n stop: () => Promise<void>;\n}\n\n/**\n * Start a dev server for the target project.\n *\n * If devServerUrl is provided, uses that instead of starting a new server.\n */\nexport async function startDevServer(\n projectRoot: string,\n options?: { port?: number; devServerUrl?: string },\n): Promise<DevServerHandle> {\n // If a URL is provided, use it directly (user has server running)\n if (options?.devServerUrl) {\n await waitForUrl(options.devServerUrl, 10000);\n return {\n url: options.devServerUrl,\n port: 0,\n process: null,\n stop: async () => {},\n };\n }\n\n const port = options?.port ?? await findFreePort();\n const { cmd, args } = detectDevCommand(projectRoot);\n const fullArgs = [...args, '--port', String(port)];\n\n const child = spawn(cmd, fullArgs, {\n cwd: projectRoot,\n stdio: ['ignore', 'pipe', 'pipe'],\n env: { ...process.env, PORT: String(port) },\n });\n\n const url = `http://localhost:${port}`;\n\n // Collect stderr for error reporting\n let stderr = '';\n child.stderr?.on('data', (data: Buffer) => {\n stderr += data.toString();\n });\n\n // Handle early exit\n const exitPromise = new Promise<never>((_, reject) => {\n child.on('exit', (code) => {\n if (code !== null && code !== 0) {\n reject(new Error(`Dev server exited with code ${code}.\\n${stderr.slice(-500)}`));\n }\n });\n });\n\n // Wait for server to be ready or fail\n try {\n await Promise.race([\n waitForUrl(url, 60000),\n exitPromise,\n ]);\n } catch (err) {\n child.kill('SIGTERM');\n throw err;\n }\n\n return {\n url,\n port,\n process: child,\n stop: async () => {\n if (child.exitCode === null) {\n child.kill('SIGTERM');\n await new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n child.kill('SIGKILL');\n resolve();\n }, 5000);\n child.on('exit', () => {\n clearTimeout(timer);\n resolve();\n });\n });\n }\n },\n };\n}\n","import type { Page } from 'playwright';\n\n/**\n * Inline all external stylesheets into <style> tags and remove <script> tags.\n *\n * This makes the captured HTML self-contained so it can be displayed\n * outside the dev server context. Shared by both the main render pipeline\n * and the interaction capturer.\n */\nexport async function inlineStylesAndCleanup(page: Page): Promise<void> {\n await page.evaluate(`(() => {\n const links = document.querySelectorAll('link[rel=\"stylesheet\"]');\n links.forEach(link => {\n try {\n const href = link.getAttribute('href');\n if (!href) return;\n for (const sheet of document.styleSheets) {\n if (sheet.href && sheet.href.includes(href.replace(/^\\\\//, ''))) {\n const rules = Array.from(sheet.cssRules).map(r => r.cssText).join('\\\\n');\n const style = document.createElement('style');\n style.textContent = rules;\n link.parentNode.replaceChild(style, link);\n break;\n }\n }\n } catch (e) {}\n });\n document.querySelectorAll('script').forEach(s => s.remove());\n })()`);\n}\n","import type { Page } from 'playwright';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { RouteInfo } from '../discovery/types.js';\nimport { inlineStylesAndCleanup } from './style-inliner.js';\n\n/**\n * Result of capturing a single interaction variant.\n */\nexport interface InteractionResult {\n /** Human-readable description, e.g. \"Tab: Settings\", \"Button: Open Modal\" */\n elementDescription: string;\n /** Relative path to captured HTML file */\n htmlPath: string;\n /** Whether the interaction capture succeeded */\n success: boolean;\n /** Error message if capture failed */\n error?: string;\n}\n\n/**\n * Serializable info about a clickable element found on the page.\n */\ninterface ClickableElement {\n /** CSS selector path to re-find the element */\n selector: string;\n /** Human-readable description */\n description: string;\n}\n\n/**\n * Slugify a URL path for use as a directory name.\n */\nfunction slugifyRoute(urlPath: string): string {\n if (urlPath === '/') return 'index';\n return urlPath\n .replace(/^\\//, '')\n .replace(/\\//g, '-')\n .replace(/:/g, '_')\n .replace(/[^a-zA-Z0-9_-]/g, '_');\n}\n\n/**\n * Find clickable interactive elements on the current page.\n *\n * Looks for tabs, buttons, and anchor-like elements, excluding\n * already-active, disabled, submit, and external link elements.\n * Uses a string-based evaluate to avoid DOM type issues in Node context.\n */\nasync function findClickableElements(\n page: Page,\n maxElements: number,\n): Promise<ClickableElement[]> {\n return page.evaluate(`((max) => {\n const selectors = [\n '[role=\"tab\"]:not([aria-selected=\"true\"]):not([aria-disabled=\"true\"])',\n '[role=\"button\"]:not([aria-disabled=\"true\"]):not([disabled])',\n 'button:not([disabled]):not([type=\"submit\"])',\n '[data-tab]:not(.active):not(.selected)',\n '.tab:not(.active):not(.selected)',\n 'a[href=\"#\"]:not(.active)',\n 'a[href^=\"#\"]:not([href=\"#\"]):not(.active)',\n ];\n\n const seen = new Set();\n const results = [];\n\n for (const sel of selectors) {\n if (results.length >= max) break;\n const elements = document.querySelectorAll(sel);\n\n for (const el of elements) {\n if (results.length >= max) break;\n if (seen.has(el)) continue;\n seen.add(el);\n\n const rect = el.getBoundingClientRect();\n if (rect.width === 0 || rect.height === 0) continue;\n const style = window.getComputedStyle(el);\n if (style.display === 'none' || style.visibility === 'hidden') continue;\n\n if (el.tagName === 'A') {\n const href = el.getAttribute('href') || '';\n if (href.startsWith('http') || href.startsWith('//')) continue;\n }\n\n if (el.tagName === 'BUTTON' && el.type === 'submit') continue;\n\n const text = (el.textContent || '').trim().slice(0, 50);\n const ariaLabel = el.getAttribute('aria-label');\n const role = el.getAttribute('role');\n const tag = el.tagName.toLowerCase();\n\n let desc = '';\n if (role === 'tab') desc = 'Tab: ' + (ariaLabel || text || 'unnamed');\n else if (role === 'button') desc = 'Button: ' + (ariaLabel || text || 'unnamed');\n else if (tag === 'button') desc = 'Button: ' + (ariaLabel || text || 'unnamed');\n else desc = 'Clickable: ' + (ariaLabel || text || 'unnamed');\n\n let uniqueSelector = '';\n const id = el.getAttribute('id');\n if (id) {\n uniqueSelector = '#' + CSS.escape(id);\n } else {\n const dataTestId = el.getAttribute('data-testid');\n if (dataTestId) {\n uniqueSelector = '[data-testid=\"' + CSS.escape(dataTestId) + '\"]';\n } else {\n const allMatching = document.querySelectorAll(sel);\n const idx = Array.from(allMatching).indexOf(el);\n uniqueSelector = '__INDEX__' + sel + '__' + idx;\n }\n }\n\n results.push({ selector: uniqueSelector, description: desc });\n }\n }\n\n return results;\n })(${maxElements})`) as Promise<ClickableElement[]>;\n}\n\n/**\n * Capture interaction variants by clicking interactive elements on a rendered page.\n *\n * This function expects the page to already be rendered and navigated to the target URL.\n * It finds clickable elements, clicks each one, captures the resulting HTML,\n * then reloads the page to reset state before the next interaction.\n *\n * @param page - Already rendered Playwright page\n * @param pageUrl - The full URL to reload between interactions\n * @param route - Route info for file naming\n * @param stateName - State variant name (e.g. \"success\")\n * @param outputDir - Base output directory\n * @param options - Configuration options\n * @returns Array of interaction results\n */\nexport async function captureInteractions(\n page: Page,\n pageUrl: string,\n route: RouteInfo,\n stateName: string,\n outputDir: string,\n options?: { maxInteractions?: number; settleTime?: number },\n): Promise<InteractionResult[]> {\n const maxInteractions = options?.maxInteractions ?? 5;\n const settleTime = options?.settleTime ?? 500;\n const routeSlug = slugifyRoute(route.urlPath);\n const stateDir = join(outputDir, 'renders', routeSlug);\n await mkdir(stateDir, { recursive: true });\n\n // Find clickable elements\n const clickables = await findClickableElements(page, maxInteractions);\n if (clickables.length === 0) return [];\n\n const results: InteractionResult[] = [];\n\n for (let i = 0; i < clickables.length; i++) {\n const clickable = clickables[i];\n const htmlRelPath = join('renders', routeSlug, `${stateName}_interaction_${i}.html`);\n const htmlAbsPath = join(outputDir, htmlRelPath);\n\n try {\n // Re-find and click the element\n let clicked = false;\n\n if (clickable.selector.startsWith('__INDEX__')) {\n // Parse the fallback selector format: __INDEX__{selector}__{index}\n const parts = clickable.selector.slice('__INDEX__'.length);\n const lastUnderscoreIdx = parts.lastIndexOf('__');\n const sel = parts.slice(0, lastUnderscoreIdx);\n const idx = parseInt(parts.slice(lastUnderscoreIdx + 2), 10);\n\n const elements = await page.$$(sel);\n if (elements[idx]) {\n await elements[idx].click();\n clicked = true;\n }\n } else {\n const element = await page.$(clickable.selector);\n if (element) {\n await element.click();\n clicked = true;\n }\n }\n\n if (!clicked) {\n results.push({\n elementDescription: clickable.description,\n htmlPath: htmlRelPath,\n success: false,\n error: 'Element not found on re-query',\n });\n continue;\n }\n\n // Wait for state change\n await page.waitForTimeout(settleTime);\n\n // Inline styles and clean up (same as main render pipeline)\n await inlineStylesAndCleanup(page);\n\n // Capture HTML\n const html = await page.content();\n await writeFile(htmlAbsPath, html, 'utf-8');\n\n results.push({\n elementDescription: clickable.description,\n htmlPath: htmlRelPath,\n success: true,\n });\n } catch (err) {\n results.push({\n elementDescription: clickable.description,\n htmlPath: htmlRelPath,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n\n // Reset page state for next interaction by reloading\n try {\n await page.goto(pageUrl, { waitUntil: 'networkidle', timeout: 10000 });\n await page.waitForTimeout(settleTime);\n } catch {\n // If reload fails, remaining interactions will likely fail too\n break;\n }\n }\n\n return results;\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from 'node:http';\nimport { join } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport sirv from 'sirv';\nimport { handleApiRequest } from './api-routes.js';\n\n/**\n * Options for starting the canvas server.\n */\nexport interface CanvasServerOptions {\n /** Port to listen on (default: 4800) */\n port: number;\n /** Path to the built canvas app directory */\n canvasDir: string;\n /** Path to the .c2d/ output directory */\n c2dDir: string;\n /** Path to the target project root (for serving public/ assets) */\n projectRoot?: string;\n}\n\nconst MAX_PORT_ATTEMPTS = 10;\n\n/**\n * Try to listen on a port. Returns a promise that resolves on success\n * or rejects with the error.\n */\nfunction tryListen(\n requestHandler: (req: IncomingMessage, res: ServerResponse) => void,\n port: number,\n): Promise<{ url: string; port: number; close: () => Promise<void> }> {\n return new Promise((resolve, reject) => {\n const server = createServer(requestHandler);\n server.once('error', reject);\n server.listen(port, () => {\n const actualPort = (server.address() as { port: number }).port;\n resolve({\n url: `http://localhost:${actualPort}`,\n port: actualPort,\n close: () =>\n new Promise<void>((resolveClose, rejectClose) => {\n server.close((err) => {\n if (err) rejectClose(err);\n else resolveClose();\n });\n }),\n });\n });\n });\n}\n\n/**\n * Start the canvas server that serves:\n * 1. API endpoints under /api/\n * 2. Pre-rendered files from .c2d/renders/ under /renders/\n * 3. Canvas app static assets (SPA fallback) for everything else\n *\n * If the default port is in use, tries up to 10 consecutive ports.\n */\nexport async function startCanvasServer(options: CanvasServerOptions): Promise<{\n url: string;\n port: number;\n close: () => Promise<void>;\n}> {\n const { port = 4800, canvasDir, c2dDir, projectRoot } = options;\n\n // Static file handlers\n const canvasHandler = sirv(canvasDir, { single: true, dev: true });\n const rendersDir = join(c2dDir, 'renders');\n const rendersHandler = sirv(rendersDir, { dev: true });\n\n // Serve target project's public/ folder for static assets (images, fonts, etc.)\n const publicDir = projectRoot ? join(projectRoot, 'public') : null;\n const publicHandler = publicDir && existsSync(publicDir)\n ? sirv(publicDir, { dev: true })\n : null;\n\n // Request handler\n const requestHandler = async (req: IncomingMessage, res: ServerResponse) => {\n const url = req.url ?? '/';\n const method = req.method ?? 'GET';\n\n // CORS headers on all responses\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n // Handle CORS preflight\n if (method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // API routes\n if (url.startsWith('/api/')) {\n try {\n const handled = await handleApiRequest(req, res, c2dDir);\n if (!handled) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Not found' }));\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Internal server error';\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: message }));\n }\n return;\n }\n\n // Renders (pre-rendered HTML/screenshots)\n if (url.startsWith('/renders/')) {\n req.url = url.slice('/renders'.length) || '/';\n rendersHandler(req, res, () => {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Render not found' }));\n });\n return;\n }\n\n // Try project's public/ folder (images, fonts, icons, etc.)\n if (publicHandler) {\n publicHandler(req, res, () => {\n // Not found in public/ — fall through to canvas SPA\n canvasHandler(req, res, () => {\n res.writeHead(404);\n res.end('Not found');\n });\n });\n return;\n }\n\n // Canvas app (SPA with fallback to index.html)\n canvasHandler(req, res, () => {\n res.writeHead(404);\n res.end('Not found');\n });\n };\n\n // Try ports starting from the configured port\n for (let attempt = 0; attempt < MAX_PORT_ATTEMPTS; attempt++) {\n const tryPort = port + attempt;\n try {\n return await tryListen(requestHandler, tryPort);\n } catch (err: any) {\n if (err.code === 'EADDRINUSE' && attempt < MAX_PORT_ATTEMPTS - 1) {\n continue;\n }\n throw err;\n }\n }\n\n throw new Error(`Could not find an available port (tried ${port}-${port + MAX_PORT_ATTEMPTS - 1})`);\n}\n","import { readFile, writeFile, mkdir } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\n\n/**\n * A single pen stroke on the drawing canvas.\n */\nexport interface DrawingStroke {\n points: { x: number; y: number }[];\n color: string;\n width: number;\n}\n\n/**\n * A comment pinned to a canvas coordinate.\n */\nexport interface Comment {\n id: string;\n x: number;\n y: number;\n text: string;\n author: string;\n timestamp: string;\n}\n\n/**\n * Handle API requests under the /api/ prefix.\n *\n * Returns true if the request was handled, false otherwise.\n */\nexport async function handleApiRequest(\n req: IncomingMessage,\n res: ServerResponse,\n c2dDir: string,\n): Promise<boolean> {\n const url = req.url ?? '/';\n const method = req.method ?? 'GET';\n\n if (url === '/api/manifest' && method === 'GET') {\n await handleGetManifest(res, c2dDir);\n return true;\n }\n\n if (url === '/api/comments' && method === 'GET') {\n await handleGetComments(res, c2dDir);\n return true;\n }\n\n if (url === '/api/comments' && method === 'POST') {\n await handlePostComment(req, res, c2dDir);\n return true;\n }\n\n const deleteMatch = url.match(/^\\/api\\/comments\\/(.+)$/);\n if (deleteMatch && method === 'DELETE') {\n await handleDeleteComment(res, c2dDir, deleteMatch[1]);\n return true;\n }\n\n if (url === '/api/drawings' && method === 'GET') {\n await handleGetDrawings(res, c2dDir);\n return true;\n }\n\n if (url === '/api/drawings' && method === 'POST') {\n await handlePostDrawings(req, res, c2dDir);\n return true;\n }\n\n return false;\n}\n\n// --- Handlers ---\n\nasync function handleGetManifest(\n res: ServerResponse,\n c2dDir: string,\n): Promise<void> {\n const manifestPath = join(c2dDir, 'manifest.json');\n if (!existsSync(manifestPath)) {\n sendJson(res, 404, { error: 'manifest.json not found' });\n return;\n }\n const data = await readFile(manifestPath, 'utf-8');\n sendRawJson(res, 200, data);\n}\n\nasync function handleGetComments(\n res: ServerResponse,\n c2dDir: string,\n): Promise<void> {\n const comments = await loadComments(c2dDir);\n sendJson(res, 200, comments);\n}\n\nasync function handlePostComment(\n req: IncomingMessage,\n res: ServerResponse,\n c2dDir: string,\n): Promise<void> {\n const body = await readRequestBody(req);\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n sendJson(res, 400, { error: 'Invalid JSON body' });\n return;\n }\n\n if (!isValidCommentInput(parsed)) {\n sendJson(res, 400, { error: 'Missing required fields: x, y, text, author' });\n return;\n }\n\n const comment: Comment = {\n id: randomUUID(),\n x: parsed.x,\n y: parsed.y,\n text: parsed.text,\n author: parsed.author,\n timestamp: new Date().toISOString(),\n };\n\n const comments = await loadComments(c2dDir);\n comments.push(comment);\n await saveComments(c2dDir, comments);\n sendJson(res, 201, comment);\n}\n\nasync function handleDeleteComment(\n res: ServerResponse,\n c2dDir: string,\n id: string,\n): Promise<void> {\n const comments = await loadComments(c2dDir);\n const index = comments.findIndex(c => c.id === id);\n if (index === -1) {\n sendJson(res, 404, { error: 'Comment not found' });\n return;\n }\n comments.splice(index, 1);\n await saveComments(c2dDir, comments);\n sendJson(res, 200, { ok: true });\n}\n\n// --- Drawing Handlers ---\n\nasync function handleGetDrawings(\n res: ServerResponse,\n c2dDir: string,\n): Promise<void> {\n const drawings = await loadDrawings(c2dDir);\n sendJson(res, 200, drawings);\n}\n\nasync function handlePostDrawings(\n req: IncomingMessage,\n res: ServerResponse,\n c2dDir: string,\n): Promise<void> {\n const body = await readRequestBody(req);\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n sendJson(res, 400, { error: 'Invalid JSON body' });\n return;\n }\n\n if (!Array.isArray(parsed)) {\n sendJson(res, 400, { error: 'Body must be an array of strokes' });\n return;\n }\n\n await saveDrawings(c2dDir, parsed as DrawingStroke[]);\n sendJson(res, 200, { ok: true });\n}\n\nasync function loadDrawings(c2dDir: string): Promise<DrawingStroke[]> {\n const drawingsPath = join(c2dDir, 'drawings.json');\n if (!existsSync(drawingsPath)) {\n return [];\n }\n const data = await readFile(drawingsPath, 'utf-8');\n try {\n const parsed = JSON.parse(data);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nasync function saveDrawings(c2dDir: string, drawings: DrawingStroke[]): Promise<void> {\n const drawingsPath = join(c2dDir, 'drawings.json');\n const dir = dirname(drawingsPath);\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true });\n }\n await writeFile(drawingsPath, JSON.stringify(drawings, null, 2), 'utf-8');\n}\n\n// --- Helpers ---\n\nfunction isValidCommentInput(\n value: unknown,\n): value is { x: number; y: number; text: string; author: string } {\n if (typeof value !== 'object' || value === null) return false;\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.x === 'number' &&\n typeof obj.y === 'number' &&\n typeof obj.text === 'string' &&\n typeof obj.author === 'string'\n );\n}\n\nasync function loadComments(c2dDir: string): Promise<Comment[]> {\n const commentsPath = join(c2dDir, 'comments.json');\n if (!existsSync(commentsPath)) {\n return [];\n }\n const data = await readFile(commentsPath, 'utf-8');\n try {\n const parsed = JSON.parse(data);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nasync function saveComments(c2dDir: string, comments: Comment[]): Promise<void> {\n const commentsPath = join(c2dDir, 'comments.json');\n const dir = dirname(commentsPath);\n if (!existsSync(dir)) {\n await mkdir(dir, { recursive: true });\n }\n await writeFile(commentsPath, JSON.stringify(comments, null, 2), 'utf-8');\n}\n\nfunction readRequestBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n req.on('error', reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, data: unknown): void {\n const body = JSON.stringify(data);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Access-Control-Allow-Origin': '*',\n });\n res.end(body);\n}\n\nfunction sendRawJson(res: ServerResponse, status: number, jsonString: string): void {\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Access-Control-Allow-Origin': '*',\n });\n res.end(jsonString);\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\n\nexport interface VibeCanvasConfig {\n apiKey: string;\n port: number;\n excludeRoutes: string[];\n devServerUrl?: string;\n devServerCommand?: string;\n}\n\nconst DEFAULT_PORT = 4800;\n\n/**\n * Load configuration from environment variables and optional config file.\n */\nexport async function loadConfig(projectRoot: string): Promise<VibeCanvasConfig> {\n let fileConfig: Partial<VibeCanvasConfig> = {};\n\n // Try to load c2d.config.js\n const configPath = join(projectRoot, 'c2d.config.js');\n if (existsSync(configPath)) {\n try {\n const mod = await import(configPath);\n fileConfig = mod.default || mod;\n } catch {\n // Config file exists but can't be loaded — use defaults\n }\n }\n\n const apiKey = process.env.C2D_API_KEY || fileConfig.apiKey || '';\n\n return {\n apiKey,\n port: fileConfig.port || Number(process.env.C2D_PORT) || DEFAULT_PORT,\n excludeRoutes: fileConfig.excludeRoutes || [],\n devServerUrl: fileConfig.devServerUrl || process.env.C2D_DEV_SERVER_URL,\n devServerCommand: fileConfig.devServerCommand,\n };\n}\n\nexport interface DetectedProject {\n isSupported: boolean;\n projectType: 'nextjs-app' | 'nextjs-pages' | 'react-router' | 'unknown';\n appDir: string | null;\n projectRoot: string;\n projectName: string;\n}\n\n/**\n * Detect the project type and routing convention.\n *\n * Supports Next.js (App Router & Pages Router) and React Router (Vite).\n */\nexport async function detectProject(projectRoot: string): Promise<DetectedProject> {\n let projectName = 'unknown';\n try {\n const pkg = JSON.parse(await readFile(join(projectRoot, 'package.json'), 'utf-8'));\n projectName = pkg.name || 'unknown';\n } catch {\n // No package.json\n }\n\n // Check for Next.js first\n const hasNextConfig =\n existsSync(join(projectRoot, 'next.config.ts')) ||\n existsSync(join(projectRoot, 'next.config.js')) ||\n existsSync(join(projectRoot, 'next.config.mjs'));\n\n if (hasNextConfig) {\n // Check App Router first, then Pages Router as fallback\n // Priority: app/ → src/app/ → pages/ → src/pages/\n let appDir = join(projectRoot, 'app');\n let hasAppDir = existsSync(appDir);\n if (!hasAppDir) {\n appDir = join(projectRoot, 'src', 'app');\n hasAppDir = existsSync(appDir);\n }\n\n if (hasAppDir) {\n return { isSupported: true, projectType: 'nextjs-app', appDir, projectRoot, projectName };\n }\n\n appDir = join(projectRoot, 'pages');\n hasAppDir = existsSync(appDir);\n if (!hasAppDir) {\n appDir = join(projectRoot, 'src', 'pages');\n hasAppDir = existsSync(appDir);\n }\n\n if (hasAppDir) {\n return { isSupported: true, projectType: 'nextjs-pages', appDir, projectRoot, projectName };\n }\n\n // Has next config but no recognized directory\n return { isSupported: false, projectType: 'unknown', appDir: null, projectRoot, projectName };\n }\n\n // Check for React Router (commonly used with Vite)\n try {\n const pkg = JSON.parse(await readFile(join(projectRoot, 'package.json'), 'utf-8'));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if ('react-router-dom' in deps || 'react-router' in deps) {\n return { isSupported: true, projectType: 'react-router', appDir: null, projectRoot, projectName };\n }\n } catch {\n // No package.json or can't parse\n }\n\n return { isSupported: false, projectType: 'unknown', appDir: null, projectRoot, projectName };\n}\n\n/**\n * Detect if the current directory is a Next.js App Router project.\n * @deprecated Use `detectProject` instead, which also supports React Router.\n */\nexport async function detectNextJsProject(projectRoot: string): Promise<{\n isNextJs: boolean;\n appDir: string | null;\n projectName: string;\n}> {\n const result = await detectProject(projectRoot);\n return {\n isNextJs: result.projectType === 'nextjs-app' || result.projectType === 'nextjs-pages',\n appDir: result.appDir,\n projectName: result.projectName,\n };\n}\n","/**\n * Simple console progress utilities for the CLI.\n */\n\nconst COLORS = {\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n dim: '\\x1b[2m',\n green: '\\x1b[32m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n red: '\\x1b[31m',\n cyan: '\\x1b[36m',\n};\n\nexport function log(message: string): void {\n console.log(`${COLORS.dim}[c2d]${COLORS.reset} ${message}`);\n}\n\nexport function success(message: string): void {\n console.log(`${COLORS.green} ✓${COLORS.reset} ${message}`);\n}\n\nexport function warn(message: string): void {\n console.log(`${COLORS.yellow} ⚠${COLORS.reset} ${message}`);\n}\n\nexport function error(message: string): void {\n console.error(`${COLORS.red} ✗${COLORS.reset} ${message}`);\n}\n\nexport function header(message: string): void {\n console.log(`\\n${COLORS.bold}${COLORS.cyan}${message}${COLORS.reset}`);\n}\n\nexport function step(current: number, total: number, message: string): void {\n console.log(`${COLORS.dim} [${current}/${total}]${COLORS.reset} ${message}`);\n}\n\nexport function banner(): void {\n console.log(`\n${COLORS.bold}${COLORS.cyan} Code to Design${COLORS.reset} ${COLORS.dim}v0.1.0${COLORS.reset}\n${COLORS.dim} AI-powered UI review canvas${COLORS.reset}\n`);\n}\n"],"mappings":"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","names":["join","mkdir","existsSync","routes","readFile","join","existsSync","readFile","join","join","existsSync","readFile","error","mkdir","writeFile","join","existsSync","join","resolve","join","join","slugifyRoute","join","mkdir","writeFile","createServer","join","existsSync","readFile","writeFile","mkdir","existsSync","join","dirname","resolve","resolve","createServer","join","existsSync","existsSync","readFile","join","join","existsSync","scanDir","mkdir","r","resolve","dirname","writeFile"]}
|
package/dist/commands/scan.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ interface CanvasServerOptions {
|
|
|
12
12
|
canvasDir: string;
|
|
13
13
|
/** Path to the .c2d/ output directory */
|
|
14
14
|
c2dDir: string;
|
|
15
|
+
/** Path to the target project root (for serving public/ assets) */
|
|
16
|
+
projectRoot?: string;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* Start the canvas server that serves:
|
|
@@ -50,8 +52,22 @@ interface VibeCanvasConfig {
|
|
|
50
52
|
* Load configuration from environment variables and optional config file.
|
|
51
53
|
*/
|
|
52
54
|
declare function loadConfig(projectRoot: string): Promise<VibeCanvasConfig>;
|
|
55
|
+
interface DetectedProject {
|
|
56
|
+
isSupported: boolean;
|
|
57
|
+
projectType: 'nextjs-app' | 'nextjs-pages' | 'react-router' | 'unknown';
|
|
58
|
+
appDir: string | null;
|
|
59
|
+
projectRoot: string;
|
|
60
|
+
projectName: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Detect the project type and routing convention.
|
|
64
|
+
*
|
|
65
|
+
* Supports Next.js (App Router & Pages Router) and React Router (Vite).
|
|
66
|
+
*/
|
|
67
|
+
declare function detectProject(projectRoot: string): Promise<DetectedProject>;
|
|
53
68
|
/**
|
|
54
69
|
* Detect if the current directory is a Next.js App Router project.
|
|
70
|
+
* @deprecated Use `detectProject` instead, which also supports React Router.
|
|
55
71
|
*/
|
|
56
72
|
declare function detectNextJsProject(projectRoot: string): Promise<{
|
|
57
73
|
isNextJs: boolean;
|
|
@@ -59,4 +75,4 @@ declare function detectNextJsProject(projectRoot: string): Promise<{
|
|
|
59
75
|
projectName: string;
|
|
60
76
|
}>;
|
|
61
77
|
|
|
62
|
-
export { type CanvasServerOptions, type Comment, detectNextJsProject, loadConfig, startCanvasServer, version };
|
|
78
|
+
export { type CanvasServerOptions, type Comment, type DetectedProject, detectNextJsProject, detectProject, loadConfig, startCanvasServer, version };
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectNextJsProject,
|
|
3
|
+
detectProject,
|
|
3
4
|
loadConfig,
|
|
4
5
|
runScan,
|
|
5
6
|
startCanvasServer
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HYFKUTC3.js";
|
|
7
8
|
|
|
8
9
|
// src/version.ts
|
|
9
10
|
var version = "0.1.0";
|
|
10
11
|
export {
|
|
11
12
|
detectNextJsProject,
|
|
13
|
+
detectProject,
|
|
12
14
|
loadConfig,
|
|
13
15
|
runScan,
|
|
14
16
|
startCanvasServer,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const version = '0.1.0';\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const version = '0.1.0';\n"],"mappings":";;;;;;;;;AAAO,IAAM,UAAU;","names":[]}
|