UNPKG

node-ts-scaffold

Version:

CLI tool to scaffold TypeScript projects with ESLint and Prettier

154 lines (136 loc) 5.67 kB
#!/usr/bin/env node // src/index.ts - Main CLI entry point import fs from 'fs/promises'; import path from 'path'; import { fileURLToPath } from 'url'; import { exec } from 'child_process'; import prompts from 'prompts'; import chalk from 'chalk'; import ora from 'ora'; import { createPackageJson, createTsConfig, createEslintConfig, createPrettierConfig, createGitignore, createSrcIndex, createTestFile, createVitestConfig } from './template.js' // Get current directory const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); async function executeCommand(command: string, cwd: string): Promise<void> { return new Promise((resolve, reject) => { exec(command, { cwd }, (error, stdout, stderr) => { if (error) { console.error(chalk.red(`Error: ${error.message}`)); reject(error); return; } if (stderr) { console.error(chalk.yellow(`Warning: ${stderr}`)); } resolve(); }); }); } async function ensureDirectoryExists(dirPath: string): Promise<void> { try { await fs.mkdir(dirPath, { recursive: true }); } catch (error) { console.error(chalk.red(`Failed to create directory: ${dirPath}`)); throw error; } } async function createFile(filePath: string, content: string): Promise<void> { try { await fs.writeFile(filePath, content); } catch (error) { console.error(chalk.red(`Failed to write file: ${filePath}`)); throw error; } } async function scaffold(): Promise<void> { try { // Get project details const response = await prompts([ { type: 'text', name: 'projectName', message: 'What is the name of your project?', initial: 'my-typescript-project' }, { type: 'text', name: 'description', message: 'Enter a brief description:', initial: 'A TypeScript project' }, { type: 'text', name: 'author', message: 'Enter author name:', initial: '' }, { type: 'confirm', name: 'installDeps', message: 'Install dependencies after scaffolding?', initial: true } ]); if (!response.projectName) { console.error(chalk.red('Project name is required.')); process.exit(1); } const { projectName, description, author, installDeps } = response; const projectPath = path.join(process.cwd(), projectName); // Check if directory already exists try { await fs.access(projectPath); console.error(chalk.red(`Directory ${projectName} already exists.`)); process.exit(1); } catch (error) { // Directory doesn't exist, which is what we want } // Create project directory const spinner = ora('Creating project scaffold...').start(); await ensureDirectoryExists(projectPath); await ensureDirectoryExists(path.join(projectPath, 'src')); await ensureDirectoryExists(path.join(projectPath, 'test')); await ensureDirectoryExists(path.join(projectPath, 'build')); // Create config files await createFile( path.join(projectPath, 'package.json'), createPackageJson({ name: projectName, description, author }) ); await createFile(path.join(projectPath, 'tsconfig.json'), createTsConfig()); await createFile(path.join(projectPath, 'eslint.config.js'), createEslintConfig()); await createFile(path.join(projectPath, '.prettierrc'), createPrettierConfig()); await createFile(path.join(projectPath, '.gitignore'), createGitignore()); await createFile(path.join(projectPath, 'vitest.config.ts'), createVitestConfig()); // Create source files await createFile(path.join(projectPath, 'src', 'index.ts'), createSrcIndex()); await createFile(path.join(projectPath, 'test', 'index.test.ts'), createTestFile()); spinner.succeed(chalk.green(`Project scaffold created at ${projectName}/`)); // Install dependencies if requested if (installDeps) { spinner.text = 'Installing dependencies...'; spinner.start(); try { await executeCommand('npm install', projectPath); spinner.succeed(chalk.green('Dependencies installed successfully!')); } catch (error) { spinner.fail(chalk.red('Failed to install dependencies.')); console.error(chalk.red('You can install them manually by running `npm install` in the project directory.')); } } // Final instructions console.log(chalk.cyan('\nSetup complete! 🎉')); console.log(chalk.white(`\nNext steps:`)); console.log(chalk.white(` 1. cd ${projectName}`)); if (!installDeps) { console.log(chalk.white(` 2. npm install`)); } console.log(chalk.white(` 3. npm run dev # To start development`)); console.log(chalk.white(` 4. npm test # To run tests`)); console.log(chalk.white(` 5. npm run build # To build the project`)); } catch (error) { console.error(chalk.red('Failed to scaffold project:'), error); process.exit(1); } } // Run the scaffolding process scaffold();