UNPKG

vite-custom-setup

Version:

A CLI tool to set up Vite with Tailwind CSS and Framer Motion for React projects.

225 lines (201 loc) 6.16 kB
#!/usr/bin/env node import fs from "fs"; import { execSync } from "child_process"; import inquirer from "inquirer"; // Function to execute shell commands with error handling const runCommand = (command) => { try { execSync(command, { stdio: "inherit" }); return true; } catch (error) { console.error(`\x1b[31mFailed to execute command: ${command}\x1b[0m`); return false; } }; // Create Tailwind CSS configuration const setupTailwind = () => { console.log("\x1b[34mSetting up Tailwind CSS...\x1b[0m"); if ( !runCommand("npm install -D tailwindcss postcss autoprefixer") || !runCommand("npx tailwindcss init -p") ) { console.error("\x1b[31mFailed to set up Tailwind CSS.\x1b[0m"); process.exit(1); } // Update Tailwind configuration file try { const tailwindConfig = ` module.exports = { content: ["./src/**/*.{js,jsx,ts,tsx}"], theme: { extend: {}, }, plugins: [], }; `; fs.writeFileSync("./tailwind.config.js", tailwindConfig); // Add Tailwind directives to CSS const cssContent = ` @tailwind base; @tailwind components; @tailwind utilities; `; fs.writeFileSync("./src/index.css", cssContent); console.log("\x1b[32m✓ Tailwind CSS setup complete.\x1b[0m"); } catch (error) { console.error("\x1b[31mFailed to configure Tailwind CSS.\x1b[0m", error); process.exit(1); } }; // Create example component const createExampleComponent = ( installTailwind, installFramer, installReactIcons, installLucideReact, installAxios ) => { const exampleContent = ` import React from 'react'${ installFramer ? "\nimport { motion } from 'framer-motion'" : "" }${installReactIcons ? "\nimport { FaReact } from 'react-icons/fa'" : ""}${ installLucideReact ? "\nimport { LucideIcon } from 'lucide-react'" : "" }${installAxios ? "\nimport axios from 'axios'" : ""} export default function Example() { ${ installAxios ? "\n React.useEffect(() => { axios.get('https://api.example.com').then(console.log); }, []);" : "" } return ( ${installFramer ? "<motion.div" : "<div"} ${ installFramer ? ` initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.5 }}` : "" } className="min-h-screen flex items-center justify-center bg-gray-100" > <div className="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4"> ${installReactIcons ? "<FaReact size={32} color='blue' />" : ""} ${ installLucideReact ? "<LucideIcon size={32} />" : "" } <div className="text-xl font-medium text-black">Your setup is complete!</div> </div> ${installFramer ? "</motion.div>" : "</div>"} )}`; try { fs.writeFileSync("./src/components/Example.jsx", exampleContent); console.log("\x1b[32m✓ Example component created.\x1b[0m"); } catch (error) { console.error("\x1b[31m✗ Failed to create example component.\x1b[0m"); } }; // Update main App.jsx const updateMainApp = () => { const appContent = ` import Example from './components/Example' function App() { return ( <div> <Example /> </div> ) } export default App`; try { fs.writeFileSync("./src/App.jsx", appContent); console.log("\x1b[32m✓ App.jsx updated.\x1b[0m"); } catch (error) { console.error("\x1b[31m✗ Failed to update App.jsx.\x1b[0m"); } }; // Main setup function const setupProject = async () => { console.log( "\x1b[34m\nVite Custom Setup - React + Tailwind + Framer Motion + Icons + Axios\x1b[0m\n" ); const answers = await inquirer.prompt([ { type: "input", name: "projectName", message: "Enter your project name:", default: "my-vite-app", validate: (input) => { if (/^([A-Za-z\-_\d])+$/.test(input)) return true; return "Project name may only include letters, numbers, underscores and hashes."; }, }, { type: "confirm", name: "installTailwind", message: "Would you like to install Tailwind CSS?", default: true, }, { type: "confirm", name: "installFramer", message: "Would you like to install Framer Motion?", default: true, }, { type: "confirm", name: "installReactIcons", message: "Would you like to install React Icons?", default: true, }, { type: "confirm", name: "installLucideReact", message: "Would you like to install Lucide React?", default: true, }, { type: "confirm", name: "installAxios", message: "Would you like to install Axios?", default: true, }, ]); const { projectName, installTailwind, installFramer, installReactIcons, installLucideReact, installAxios, } = answers; console.log("\n\x1b[34mCreating Vite project...\x1b[0m"); if (!runCommand(`npm create vite@latest ${projectName} -- --template react`)) process.exit(1); process.chdir(projectName); if (!runCommand("npm install")) process.exit(1); if (installTailwind) setupTailwind(); if (installFramer) runCommand("npm install framer-motion"); if (installReactIcons) runCommand("npm install react-icons"); if (installLucideReact) runCommand("npm install lucide-react"); if (installAxios) runCommand("npm install axios"); createExampleComponent( installTailwind, installFramer, installReactIcons, installLucideReact, installAxios ); updateMainApp(); console.log("\n\x1b[32m✨ Setup complete!\x1b[0m"); console.log( `\n\x1b[34mNext steps:\x1b[0m\n cd ${projectName}\n npm run dev\n` ); }; process.on("uncaughtException", (err) => { console.error("\x1b[31mAn error occurred:\x1b[0m", err); process.exit(1); }); setupProject().catch((error) => { console.error("\x1b[31mSetup failed:\x1b[0m", error); process.exit(1); });