UNPKG

create-kalp-boilerplate

Version:

A Kalp CLI tool to generate a React boilerplate

124 lines (110 loc) 3.66 kB
#!/usr/bin/env node import { Command } from 'commander'; import { exec } from 'child_process'; import { fileURLToPath } from 'url'; import fs from 'fs'; import ora from 'ora'; import path from 'path'; import util from 'util'; const execPromise = util.promisify(exec); // Promisify exec for async/await const program = new Command(); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); program .name('create-kalp-boilerplate') .version('1.0.0') .description('A Kalp CLI tool to generate React boilerplate') .argument('<app-name>', 'Name of your application') .option('--auth', 'Add authentication functionality') .option('--mfd-config', 'Add configuration for microfrontends') .action(async (appName, options) => { const spinner = ora(`Creating ${appName}...`).start(); const repoUrl = options.mfdConfig ? 'https://github.com/sachinp2e/react-microfrontend-boilerplate.git' : 'https://github.com/sachinp2e/react-boilerplate-ts.git'; const targetPath = path.resolve(process.cwd(), appName); try { await cloneRepo(repoUrl, appName, spinner); await postCloneSetup(targetPath, options); spinner.succeed(`App "${appName}" created successfully!`); console.log(`\nNavigate to your app:\n cd ${appName}`); console.log(`\nInstall dependencies:\n npm install`); } catch (error) { handleError(spinner, error); } }); program.parse(process.argv); /** * Clones a GitHub repository into the specified directory. */ async function cloneRepo(repoUrl, appName, spinner) { try { await execPromise(`git clone ${repoUrl} ${appName}`); } catch (error) { throw new Error( `Failed to clone the boilerplate: ${error.stderr || error.message}` ); } } /** * Handles post-clone setup like authentication and microfrontend config. */ async function postCloneSetup(targetPath, options) { if (options.auth) { addAuthFiles(targetPath); } } /** * Adds authentication files to the boilerplate. */ function addAuthFiles(targetPath) { const spinner = ora('Adding authentication functionality...').start(); const authFilePath = path.resolve( __dirname, '../templates/auth/apiClient.ts' ); const destPath = path.join( targetPath, 'src/services/api', 'axios-instance.ts' ); const authSlicePath = path.resolve( __dirname, '../templates/auth/redux/User/authSlice.ts' ); const authSliceDestPath = path.resolve( targetPath, 'src/store/slices', 'authSlice.ts' ); const authConfigPath = path.resolve(__dirname, '../templates/auth/config.ts'); const authConfigDestPath = path.resolve( targetPath, 'src/services/api', 'config.ts' ); const utilsPath = path.resolve(__dirname, '../templates/auth/utils.ts'); const utilsDestPath = path.resolve(targetPath, 'src', 'helpers', 'utils.ts'); try { fs.copyFileSync(authFilePath, destPath); fs.copyFileSync(authSlicePath, authSliceDestPath); fs.copyFileSync(authConfigPath, authConfigDestPath); const destDir = path.dirname(utilsDestPath); // Ensure the directory exists (create it if necessary) if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }); // Recursive creates nested directories if needed } // Copy the file fs.copyFileSync(utilsPath, utilsDestPath); spinner.succeed('Authentication functionality added successfully!'); } catch (error) { handleError(spinner, error); } } /** * Handles errors and logs them with the spinner. */ function handleError(spinner, error) { spinner.fail(error.message); process.exit(1); }