UNPKG

create-ignite

Version:

🚀 Universal CLI to scaffold modern web projects - React, Vue, Next.js, Express, and more with zero configuration

267 lines (231 loc) • 6.58 kB
/** * Dependency installation logic */ import { execa } from "execa"; import chalk from "chalk"; import { FRAMEWORKS, CSS_FRAMEWORKS, STATE_MANAGEMENT, DEPENDENCY_VERSIONS, PACKAGE_MANAGERS, } from "./constants.js"; import { ErrorHandler } from "./errorHandler.js"; /** * Install dependencies based on configuration * @param {Object} config - Project configuration * @param {Object} spinner - Ora spinner instance */ export async function installDependencies(config, spinner) { const { framework, language, cssFramework, stateManagement, installRouter, installIcons, installAxios, installESLint, installPrettier, packageManager, } = config; try { // Install base dependencies first spinner.text = chalk.cyan("Installing base dependencies..."); await installBaseDependencies(packageManager, spinner); // Collect additional dependencies const dependencies = []; const devDependencies = []; // Framework-specific dependencies addFrameworkDependencies(framework, dependencies); // CSS framework dependencies addCSSFrameworkDependencies(cssFramework, framework, dependencies, devDependencies); // State management addStateManagementDependencies(stateManagement, dependencies); // Router if (installRouter) { addRouterDependencies(framework, dependencies); } // Icons if (installIcons) { dependencies.push("react-icons"); } // Axios if (installAxios) { dependencies.push("axios"); } // TypeScript if (language === "ts") { addTypeScriptDependencies(framework, devDependencies); } // ESLint if (installESLint) { addESLintDependencies(framework, devDependencies); } // Prettier if (installPrettier) { devDependencies.push("prettier"); } // Backend-specific if (framework === FRAMEWORKS.EXPRESS || framework === FRAMEWORKS.FASTIFY) { addBackendDependencies(framework, language, dependencies, devDependencies); } // Install production dependencies if (dependencies.length > 0) { spinner.text = chalk.cyan(`Installing dependencies: ${dependencies.join(", ")}`); await installPackages(packageManager, dependencies, false); } // Install dev dependencies if (devDependencies.length > 0) { spinner.text = chalk.cyan(`Installing dev dependencies...`); await installPackages(packageManager, devDependencies, true); } spinner.text = chalk.green("Dependencies installed"); } catch (error) { throw ErrorHandler.createError( `Failed to install dependencies: ${error.message}`, "INSTALL_FAILED" ); } } /** * Install base dependencies */ async function installBaseDependencies(packageManager, spinner) { const cmd = packageManager === PACKAGE_MANAGERS.NPM ? "npm" : packageManager; await execa(cmd, ["install"], { stdio: "inherit" }); } /** * Install packages */ async function installPackages(packageManager, packages, isDev = false) { if (packages.length === 0) return; const cmd = packageManager === PACKAGE_MANAGERS.NPM ? "npm" : packageManager; const args = packageManager === PACKAGE_MANAGERS.NPM ? ["install"] : ["add"]; if (isDev) { args.push(packageManager === PACKAGE_MANAGERS.NPM ? "--save-dev" : "-D"); } args.push(...packages); await ErrorHandler.retry( async () => await execa(cmd, args, { stdio: "inherit" }), 3, 2000 ); } /** * Add framework-specific dependencies */ function addFrameworkDependencies(framework, dependencies) { switch (framework) { case FRAMEWORKS.REACT: // Vite already includes React break; case FRAMEWORKS.VUE: // Vite already includes Vue break; case FRAMEWORKS.NEXTJS: // Next.js includes React break; case FRAMEWORKS.NUXT: // Nuxt includes Vue break; case FRAMEWORKS.EXPRESS: dependencies.push("express"); break; case FRAMEWORKS.FASTIFY: dependencies.push("fastify"); break; } } /** * Add CSS framework dependencies */ function addCSSFrameworkDependencies(cssFramework, framework, dependencies, devDependencies) { switch (cssFramework) { case CSS_FRAMEWORKS.TAILWIND: devDependencies.push("tailwindcss", "@tailwindcss/vite"); break; case CSS_FRAMEWORKS.BOOTSTRAP: dependencies.push("bootstrap"); break; case CSS_FRAMEWORKS.MATERIAL_UI: if (framework === FRAMEWORKS.REACT || framework === FRAMEWORKS.NEXTJS) { dependencies.push("@mui/material", "@emotion/react", "@emotion/styled"); } break; case CSS_FRAMEWORKS.CHAKRA_UI: if (framework === FRAMEWORKS.REACT || framework === FRAMEWORKS.NEXTJS) { dependencies.push("@chakra-ui/react", "@emotion/react", "@emotion/styled"); } break; } } /** * Add state management dependencies */ function addStateManagementDependencies(stateManagement, dependencies) { switch (stateManagement) { case STATE_MANAGEMENT.REDUX: dependencies.push("@reduxjs/toolkit", "react-redux"); break; case STATE_MANAGEMENT.ZUSTAND: dependencies.push("zustand"); break; case STATE_MANAGEMENT.PINIA: dependencies.push("pinia"); break; case STATE_MANAGEMENT.VUEX: dependencies.push("vuex"); break; case STATE_MANAGEMENT.MOBX: dependencies.push("mobx", "mobx-react-lite"); break; } } /** * Add router dependencies */ function addRouterDependencies(framework, dependencies) { switch (framework) { case FRAMEWORKS.REACT: dependencies.push("react-router-dom"); break; case FRAMEWORKS.VUE: dependencies.push("vue-router"); break; // Next.js and Nuxt have built-in routing } } /** * Add TypeScript dependencies */ function addTypeScriptDependencies(framework, devDependencies) { devDependencies.push("typescript"); if (framework === FRAMEWORKS.REACT) { devDependencies.push("@types/react", "@types/react-dom"); } else if (framework === FRAMEWORKS.EXPRESS) { devDependencies.push("@types/node", "@types/express", "tsx"); } else if (framework === FRAMEWORKS.FASTIFY) { devDependencies.push("@types/node", "tsx"); } } /** * Add ESLint dependencies */ function addESLintDependencies(framework, devDependencies) { devDependencies.push("eslint"); if (framework === FRAMEWORKS.REACT || framework === FRAMEWORKS.NEXTJS) { devDependencies.push("eslint-plugin-react", "eslint-plugin-react-hooks"); } else if (framework === FRAMEWORKS.VUE || framework === FRAMEWORKS.NUXT) { devDependencies.push("eslint-plugin-vue"); } } /** * Add backend-specific dependencies */ function addBackendDependencies(framework, language, dependencies, devDependencies) { dependencies.push("cors", "dotenv"); if (language === "js") { devDependencies.push("nodemon"); } }