UNPKG

@nuggetwise/cli

Version:

Magic Nuggetwise CLI for Cursor IDE integration

195 lines (161 loc) 5.43 kB
import { exec } from 'child_process'; import { promisify } from 'util'; import fs from 'fs-extra'; import path from 'path'; import { BuildResult, PreviewResult } from '../types/index.js'; const execAsync = promisify(exec); export class PreviewManager { private workspace: string; private buildTool: 'next' | 'vite' | 'esbuild'; constructor(workspace: string, buildTool: 'next' | 'vite' | 'esbuild' = 'next') { this.workspace = workspace; this.buildTool = buildTool; } async buildProject(): Promise<BuildResult> { const startTime = Date.now(); try { console.log(`Building project with ${this.buildTool}...`); let buildCommand: string; let outputDir: string; switch (this.buildTool) { case 'next': buildCommand = 'npm run build'; outputDir = '.next'; break; case 'vite': buildCommand = 'npm run build'; outputDir = 'dist'; break; case 'esbuild': buildCommand = 'npx esbuild src/**/*.{ts,tsx} --bundle --outdir=dist --format=esm --target=es2020'; outputDir = 'dist'; break; default: throw new Error(`Unsupported build tool: ${this.buildTool}`); } const { stdout, stderr } = await execAsync(buildCommand, { cwd: this.workspace, timeout: 60000 // 60 second timeout }); const buildTime = Date.now() - startTime; if (stderr && !stderr.includes('warning')) { return { success: false, error: stderr, buildTime }; } // Verify build output exists const outputPath = path.join(this.workspace, outputDir); if (!await fs.pathExists(outputPath)) { return { success: false, error: `Build output not found at ${outputDir}`, buildTime }; } return { success: true, output: stdout, buildTime }; } catch (error: any) { const buildTime = Date.now() - startTime; return { success: false, error: error.message || 'Build failed', buildTime }; } } async deployPreview(): Promise<PreviewResult> { try { console.log('Deploying preview to Vercel...'); // Check if Vercel CLI is available try { await execAsync('vercel --version'); } catch (error) { throw new Error('Vercel CLI not found. Please install with: npm i -g vercel'); } // Deploy to Vercel const { stdout, stderr } = await execAsync('vercel deploy --prebuilt --prod false --yes', { cwd: this.workspace, timeout: 120000 // 2 minute timeout }); if (stderr && !stderr.includes('warning')) { return { success: false, error: stderr }; } // Extract deployment URL from output const urlMatch = stdout.match(/https:\/\/[^\s]+/); const deploymentIdMatch = stdout.match(/Deployment ID: ([^\s]+)/); if (!urlMatch) { return { success: false, error: 'Could not extract deployment URL from Vercel output' }; } return { success: true, url: urlMatch[0], deploymentId: deploymentIdMatch?.[1] }; } catch (error: any) { return { success: false, error: error.message || 'Deployment failed' }; } } async buildAndDeploy(): Promise<PreviewResult> { // First build the project const buildResult = await this.buildProject(); if (!buildResult.success) { return { success: false, error: `Build failed: ${buildResult.error}` }; } console.log(`Build completed in ${buildResult.buildTime}ms`); // Then deploy the preview return await this.deployPreview(); } async detectBuildTool(): Promise<'next' | 'vite' | 'esbuild'> { // Check for Next.js if (await fs.pathExists(path.join(this.workspace, 'next.config.js')) || await fs.pathExists(path.join(this.workspace, 'next.config.ts'))) { return 'next'; } // Check for Vite if (await fs.pathExists(path.join(this.workspace, 'vite.config.js')) || await fs.pathExists(path.join(this.workspace, 'vite.config.ts'))) { return 'vite'; } // Check package.json for build scripts const packageJsonPath = path.join(this.workspace, 'package.json'); if (await fs.pathExists(packageJsonPath)) { const packageJson = await fs.readJson(packageJsonPath); const scripts = packageJson.scripts || {}; if (scripts.build && scripts.build.includes('next')) { return 'next'; } if (scripts.build && scripts.build.includes('vite')) { return 'vite'; } } // Default to esbuild return 'esbuild'; } async setupBuildEnvironment(): Promise<void> { // Install dependencies if node_modules doesn't exist const nodeModulesPath = path.join(this.workspace, 'node_modules'); if (!await fs.pathExists(nodeModulesPath)) { console.log('Installing dependencies...'); await execAsync('npm install', { cwd: this.workspace }); } // Update build tool detection this.buildTool = await this.detectBuildTool(); } }