UNPKG

@ayushmxxn/serenity-ui

Version:

A CLI tool for integrating Serenity UI components into your Next.js projects.

196 lines (168 loc) 5.46 kB
import inquirer from 'inquirer'; import fs from 'fs-jetpack'; import path from 'path'; import { fileURLToPath } from 'url'; import { execSync } from 'child_process'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const components = [ 'voice-testimonial', 'voice-testimonial-animate', 'star-rating-testimonial', 'username-testimonial', 'book-testimonial-3D', 'typewriter-testimonial', 'pricing-section-white', 'pricing-section-black', 'pricing-section-blue', 'sign-up-form', 'sign-up-form-v2', 'sign-in-form', 'forgot-password', 'email-form', 'otp-form', 'create-new-password-form', 'password-changed-form', 'image-carousel', 'video-carousel', 'tubelight-navbar', 'spotlightcard', 'swipecard', 'glowcard', 'dock', 'codeblock', 'image-gallery', 'shortcut-modal', 'steps', 'brandsection', 'star-rating', 'projectcard-black', 'projectcard-slate', 'projectcard-glass', 'newsletter', 'cookie', 'waitlist', 'techstack', 'toast', 'tooltip', 'flipcard3d', 'drawer', 'carousel360', 'filmroll', 'featuresection' ]; const toPascalCase = (str) => { return str .split('-') .map(word => word.charAt(0).toUpperCase() + word.slice(1)) .join(''); }; const extractDependencies = (filePath) => { const content = fs.read(filePath); const dependencies = []; const importRegex = /import\s+(?:.*?\s+from\s+)?['"](.*?)['"]/g; let match; while ((match = importRegex.exec(content)) !== null) { const importedModule = match[1]; if (importedModule.startsWith('react')) { continue; // Ignore react imports } const packageName = importedModule.startsWith('@') ? importedModule.split('/').slice(0, 2).join('/') : importedModule.split('/')[0]; dependencies.push(packageName); } return dependencies; }; const checkInstalledDependencies = (dependencies) => { const packageJsonPath = path.join(process.cwd(), 'package.json'); if (!fs.exists(packageJsonPath)) { console.error('package.json not found in the project directory.'); return dependencies; } const packageJson = fs.read(packageJsonPath, 'json'); const installedDependencies = new Set([ ...Object.keys(packageJson.dependencies || {}), ...Object.keys(packageJson.devDependencies || {}) ]); return dependencies.filter(dep => !installedDependencies.has(dep)); }; const installDependencies = (dependencies) => { if (dependencies.length > 0) { console.log('Installing missing dependencies...'); try { execSync(`npm install ${dependencies.join(' ')} --save`, { stdio: 'inherit' }); } catch (err) { console.error('Failed to install dependencies:', err.message); } } }; const add = async (component) => { if (!component) { const answer = await inquirer.prompt([ { type: 'checkbox', name: 'components', message: 'Which components would you like to add?', choices: components, }, ]); component = answer.components; } else { component = [component]; } const projectDir = process.cwd(); let destination; // Check for `app/components/ui` directory const appDir = path.join(projectDir, 'app', 'components', 'ui'); const srcAppDir = path.join(projectDir, 'src', 'app', 'components', 'ui'); const rootDir = path.join(projectDir, 'components', 'ui'); if (fs.exists(path.join(projectDir, 'app'))) { destination = appDir; } else if (fs.exists(path.join(projectDir, 'src'))) { destination = srcAppDir; } else { destination = rootDir; } // Ensure destination directory exists fs.dir(destination); const requiredDependencies = new Set(); for (const comp of component) { const pascalCaseName = toPascalCase(comp); const compPath = path.join(__dirname, `../components/${pascalCaseName}.tsx`); const destPath = path.join(destination, `${pascalCaseName}.tsx`); if (fs.exists(compPath)) { if (fs.exists(destPath)) { // Prompt user if file already exists in destination const { overwrite } = await inquirer.prompt([ { type: 'confirm', name: 'overwrite', message: `The component ${pascalCaseName} already exists. Do you want to overwrite it?`, default: false, }, ]); if (!overwrite) { console.log(`Skipped ${pascalCaseName}.`); continue; } } try { fs.copy(compPath, destPath, { overwrite: true }); console.log(`${pascalCaseName} component added successfully.`); } catch (err) { console.error(`Failed to copy ${pascalCaseName}: ${err.message}`); } // Extract required dependencies for this component const dependencies = extractDependencies(compPath); dependencies.forEach(dep => requiredDependencies.add(dep)); } else { console.error(`Component not found.`); } } // Check which dependencies need to be installed const dependenciesToInstall = checkInstalledDependencies(Array.from(requiredDependencies)); // Install missing dependencies installDependencies(dependenciesToInstall); }; export default add;