initrajs
Version:
ā” InitraJS - JavaScript CLI Toolkit | Lightning-fast scaffolding for React, Next.js, Node.js with TypeScript | The future of JavaScript development | 10x faster than create-react-app | Ultimate developer productivity tool
132 lines (130 loc) ⢠5.86 kB
JavaScript
// src/commands/generate-page.ts
import fs from 'fs';
import path from 'path';
import chalk from 'chalk';
import { reactPageTemplate, nextPageTemplate, pageScssTemplate, pageTestTemplate } from '../templates/page-templates.js';
import { ensureDirectoryExists, toPascalCase } from '../utils/client-utils.js';
export function generatePage(name, options) {
try {
// Determine page type (default to React if neither specified)
const isNext = options.next;
const isReact = options.react || !isNext; // Default to React
// Determine file type (default to tsx if neither ts nor js is specified)
const isTypeScript = options.js ? false : true; // Default to TypeScript
const fileExtension = isTypeScript ? 'tsx' : 'jsx';
// Convert name to PascalCase
const pageName = toPascalCase(name.replace(/page$/i, '')); // Remove 'Page' suffix if present
// Template options
const templateOptions = {
name: pageName,
typescript: isTypeScript,
isNext,
isReact
};
if (isNext) {
generateNextPage(pageName, templateOptions, options, fileExtension);
}
else {
generateReactPage(pageName, templateOptions, options, fileExtension);
}
}
catch (error) {
console.error(chalk.red('ā Error generating page:'), error);
process.exit(1);
}
}
function generateReactPage(pageName, templateOptions, options, fileExtension) {
// Determine the output directory
const baseDir = options.path || 'src/pages';
const pageDir = path.join(process.cwd(), baseDir);
// Ensure directory exists
ensureDirectoryExists(pageDir);
// Generate page content
const pageContent = reactPageTemplate(templateOptions);
const pageFileName = `${pageName}Page.${fileExtension}`;
const pageFilePath = path.join(pageDir, pageFileName);
fs.writeFileSync(pageFilePath, pageContent);
console.log(chalk.green(`ā
React page created: ${pageFilePath}`));
// Generate additional files
generateAdditionalFiles(pageName, pageDir, options, templateOptions.typescript, false);
// Success message
console.log(chalk.cyan.bold(`\nš ${pageName}Page generated successfully!`));
console.log(chalk.yellow(`š Location: ${pageDir}`));
// Show import example
const relativePath = path.relative(process.cwd(), pageFilePath);
console.log(chalk.gray(`\nš” Import with: import ${pageName}Page from './${relativePath.replace(/\\/g, '/')}';`));
}
function generateNextPage(pageName, templateOptions, options, fileExtension) {
// Determine the output directory (Next.js app directory structure)
const baseDir = options.path || 'app';
const pageRoute = pageName.toLowerCase().replace(/page$/i, ''); // Convert to lowercase for route
const pageDir = path.join(process.cwd(), baseDir, pageRoute);
// Ensure directory exists
ensureDirectoryExists(pageDir);
// Generate page content
const pageContent = nextPageTemplate(templateOptions);
const pageFilePath = path.join(pageDir, `page.${fileExtension}`);
fs.writeFileSync(pageFilePath, pageContent);
console.log(chalk.green(`ā
Next.js page created: ${pageFilePath}`));
// Generate loading component
const loadingContent = `export default function Loading() {
return (
<div className="loading-container">
<div className="loading-spinner">
<div className="spinner"></div>
<p>Loading...</p>
</div>
</div>
);
}`;
const loadingFilePath = path.join(pageDir, `loading.${fileExtension}`);
fs.writeFileSync(loadingFilePath, loadingContent);
console.log(chalk.green(`ā
Loading component created: ${loadingFilePath}`));
// Generate error component
const errorContent = `'use client';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div className="error-container">
<h2>Something went wrong!</h2>
<p>{error.message}</p>
<button onClick={() => reset()}>Try again</button>
</div>
);
}`;
const errorFilePath = path.join(pageDir, `error.${fileExtension}`);
fs.writeFileSync(errorFilePath, errorContent);
console.log(chalk.green(`ā
Error component created: ${errorFilePath}`));
// Generate additional files
generateAdditionalFiles(pageName, pageDir, options, templateOptions.typescript, true);
// Success message
console.log(chalk.cyan.bold(`\nš ${pageName} Next.js page generated successfully!`));
console.log(chalk.yellow(`š Location: ${pageDir}`));
console.log(chalk.yellow(`š Route: /${pageRoute}`));
// Show usage example
console.log(chalk.gray(`\nš” Visit: http://localhost:3000/${pageRoute}`));
}
function generateAdditionalFiles(pageName, pageDir, options, isTypeScript, isNext) {
// Generate CSS file if requested
if (options.css) {
const cssContent = pageScssTemplate(pageName);
const cssFileName = isNext ? `${pageName.toLowerCase()}.scss` : `${pageName}Page.scss`;
const cssFilePath = path.join(pageDir, cssFileName);
fs.writeFileSync(cssFilePath, cssContent);
console.log(chalk.green(`ā
CSS file created: ${cssFilePath}`));
}
// Generate test file if requested
if (options.test) {
const testContent = pageTestTemplate(pageName, isTypeScript, isNext);
const testExtension = isTypeScript ? 'test.tsx' : 'test.jsx';
const testFileName = isNext ? `page.${testExtension}` : `${pageName}Page.${testExtension}`;
const testFilePath = path.join(pageDir, testFileName);
fs.writeFileSync(testFilePath, testContent);
console.log(chalk.green(`ā
Test file created: ${testFilePath}`));
}
}