my-costom
Version:
Advanced project template generator CLI with interactive selection and custom Hello World templates
270 lines (225 loc) ⢠6.97 kB
JavaScript
#!/usr/bin/env node
const { execSync } = require('child_process');
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// Enhanced template list with more options
const templates = {
'1': {
name: 'Next.js',
cmd: 'npx create-next-app@latest',
description: 'Full-stack React framework with SSR/SSG'
},
'2': {
name: 'React + Vite',
cmd: 'npm create vite@latest',
description: 'Fast React development with Vite'
},
'3': {
name: 'React Router',
cmd: 'npx create-react-app',
description: 'React SPA with routing capabilities',
postInstall: 'npm install react-router-dom'
},
'4': {
name: 'Astro',
cmd: 'npm create astro@latest',
description: 'Static site generator with islands architecture'
},
'5': {
name: 'Remix',
cmd: 'npx create-remix@latest',
description: 'Full-stack web framework focused on web standards'
}
};
console.log('š Enhanced Project Generator\n');
console.log('Available templates:');
Object.entries(templates).forEach(([key, template]) => {
console.log(`${key}. ${template.name}`);
console.log(` ${template.description}`);
console.log('');
});
rl.question('Select a template (1-5): ', (choice) => {
if (!templates[choice]) {
console.log('ā Invalid choice! Please select 1-5.');
process.exit(1);
}
const selectedTemplate = templates[choice];
rl.question('Project name: ', (name) => {
if (!name.trim()) {
console.log('ā Project name is required!');
process.exit(1);
}
// Validate project name (basic validation)
if (!/^[a-zA-Z0-9-_]+$/.test(name)) {
console.log('ā Project name should only contain letters, numbers, hyphens, and underscores.');
process.exit(1);
}
console.log(`\nš§ Creating ${selectedTemplate.name} project: ${name}`);
console.log(`š ${selectedTemplate.description}\n`);
try {
// Create the project
execSync(`${selectedTemplate.cmd} ${name}`, { stdio: 'inherit' });
// Handle post-installation steps
if (selectedTemplate.postInstall) {
console.log(`\nš¦ Installing additional dependencies...`);
process.chdir(name);
execSync(selectedTemplate.postInstall, { stdio: 'inherit' });
// For React Router, create a basic routing setup
if (selectedTemplate.name === 'React Router') {
createReactRouterSetup();
}
}
console.log(`\nā
Project ${name} created successfully!`);
console.log(`\nš Next steps:`);
console.log(` cd ${name}`);
if (!selectedTemplate.postInstall) {
console.log(` npm install`);
}
console.log(` npm run dev` + (selectedTemplate.name === 'React Router' ? ' (or npm start)' : ''));
// Template-specific instructions
if (selectedTemplate.name === 'React Router') {
console.log(`\nš React Router features added:`);
console.log(` ⢠Basic routing setup in src/App.js`);
console.log(` ⢠Example pages: Home, About, Contact`);
console.log(` ⢠Navigation component`);
}
} catch (error) {
console.error('ā Failed to create project:', error.message);
process.exit(1);
}
rl.close();
});
});
// Function to create React Router setup
function createReactRouterSetup() {
const fs = require('fs');
const path = require('path');
// Create App.js with routing
const appContent = `import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Navigation from './components/Navigation';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
import './App.css';
function App() {
return (
<Router>
<div className="App">
<Navigation />
<main className="main-content">
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</main>
</div>
</Router>
);
}
export default App;`;
// Create directories
if (!fs.existsSync('src/components')) fs.mkdirSync('src/components', { recursive: true });
if (!fs.existsSync('src/pages')) fs.mkdirSync('src/pages', { recursive: true });
// Write App.js
fs.writeFileSync('src/App.js', appContent);
// Create Navigation component
const navContent = `import React from 'react';
import { Link } from 'react-router-dom';
import './Navigation.css';
function Navigation() {
return (
<nav className="navigation">
<div className="nav-container">
<Link to="/" className="nav-logo">My App</Link>
<div className="nav-links">
<Link to="/" className="nav-link">Home</Link>
<Link to="/about" className="nav-link">About</Link>
<Link to="/contact" className="nav-link">Contact</Link>
</div>
</div>
</nav>
);
}
export default Navigation;`;
fs.writeFileSync('src/components/Navigation.js', navContent);
// Create page components
const homeContent = `import React from 'react';
function Home() {
return (
<div className="page">
<h1>Welcome Home</h1>
<p>This is the home page of your React Router application.</p>
</div>
);
}
export default Home;`;
const aboutContent = `import React from 'react';
function About() {
return (
<div className="page">
<h1>About Us</h1>
<p>Learn more about our company and mission.</p>
</div>
);
}
export default About;`;
const contactContent = `import React from 'react';
function Contact() {
return (
<div className="page">
<h1>Contact Us</h1>
<p>Get in touch with our team.</p>
</div>
);
}
export default Contact;`;
fs.writeFileSync('src/pages/Home.js', homeContent);
fs.writeFileSync('src/pages/About.js', aboutContent);
fs.writeFileSync('src/pages/Contact.js', contactContent);
// Create basic CSS for navigation
const navCss = `.navigation {
background-color: #282c34;
padding: 1rem 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 2rem;
}
.nav-logo {
color: #61dafb;
font-size: 1.5rem;
font-weight: bold;
text-decoration: none;
}
.nav-links {
display: flex;
gap: 2rem;
}
.nav-link {
color: white;
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 4px;
transition: background-color 0.3s;
}
.nav-link:hover {
background-color: rgba(97, 218, 251, 0.1);
}
.page {
padding: 2rem;
max-width: 1200px;
margin: 0 auto;
}`;
fs.writeFileSync('src/components/Navigation.css', navCss);
console.log('š React Router setup files created successfully!');
}