UNPKG

@ayushmxxn/serenity-ui

Version:

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

174 lines (147 loc) 4.89 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", "book-testimonial-3D", "typewriter-testimonial", "image-carousel", "video-carousel", "tubelight-navbar", "spotlightcard", "swipecard", "glowcard", "dock", "image-gallery", "shortcut-modal", "brandsection", "toast", "flipcard3d", "carousel360", ]; 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;