create-new-react-component
Version:
an utility to create a new react component with a single command
163 lines (148 loc) • 5.08 kB
JavaScript
const commander = require("commander");
const inquirer = require("inquirer");
const fs = require("fs");
const path = require("path");
const validateComponentName = require("./ValidateComponentName");
const program = new commander.Command();
program
.name("create-new-react-component")
.usage("[options]")
.version("1.5.0")
.description(
"Create a new React component with an optional CSS file. " +
"The component will be created in a new directory with the same name as the component."
)
.action(async () => {
try {
const answers = await inquirer.prompt([
{
type: 'input',
name: 'componentName',
message: 'What is the name of your component?',
validate: (input) => {
const validation = validateComponentName(input);
if (!validation.isValid) {
return validation.error;
}
// Check if component directory already exists
const componentDir = path.join(process.cwd(), input.trim());
if (fs.existsSync(componentDir)) {
return `Component directory "${input.trim()}" already exists in the current directory`;
}
return true;
}
},
{
type: 'list',
name: 'componentType',
message: 'What type of component would you like to create?',
choices: [
{ name: 'Functional Component', value: 'functional' },
{ name: 'Arrow Function Component', value: 'arrow' },
{ name: 'Class Component', value: 'class' },
{ name: 'Memoized Component (React.memo)', value: 'memoized' },
{ name: 'ForwardRef Component (React.forwardRef)', value: 'forwardRef' }
],
default: 'functional'
},
{
type: 'list',
name: 'lang',
message: 'What language would you like to use?',
choices: ['js', 'ts'],
default: 'js'
},
{
type: 'list',
name: 'style',
message: 'What styling solution would you like to use?',
choices: [
{ name: 'CSS', value: 'css' },
{ name: 'SCSS', value: 'scss' },
{ name: 'None', value: null }
],
default: 'css'
},
{
type: 'confirm',
name: 'withProps',
message: 'Would you like to include props in your component?',
default: false
},
{
type: 'confirm',
name: 'withImportReact',
message: 'Would you like to include React import statement?',
default: false
}
]);
createComponent(answers.componentName, {
componentType: answers.componentType,
lang: answers.lang,
style: answers.style,
withProps: answers.withProps,
withImportReact: answers.withImportReact
});
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}
});
function createComponent(componentName, options) {
if (!componentName) {
console.error("Error: <componentName> is required.");
process.exit(1); // Exit the process with an error code
}
const validation = validateComponentName(componentName);
if (!validation.isValid) {
console.error(`Error: ${validation.error}`);
process.exit(1);
}
const componentDir = path.join(process.cwd(), componentName);
const indexFilePath = path.join(componentDir, `index.${options.lang}`);
const componentFilePath = path.join(
componentDir,
`${componentName}.${options.lang === "ts" ? "tsx" : "jsx"}`
);
const stylesFilePath = path.join(
componentDir,
`${componentName}.module${options.style ? `.${options.style}` : ''}`
);
const indexFileContent = `export { default } from './${componentName}';`;
const ComponentFileContent = require("./ComponentFileContent");
const componentFileContent = new ComponentFileContent(
componentName,
options.style ? `.${options.style}` : null,
options.lang,
options.withProps,
options.withImportReact,
options.componentType
);
const componentFileContentContent =
componentFileContent.generateComponentContent();
const stylesFileContent = `/* Add your component styles here */
.${componentName} {
}
`;
if (fs.existsSync(componentDir)) {
console.error(`Component ${componentName} already exists`);
return;
}
try {
fs.mkdirSync(componentDir);
fs.writeFileSync(indexFilePath, indexFileContent);
fs.writeFileSync(componentFilePath, componentFileContentContent);
if (options.style) {
fs.writeFileSync(stylesFilePath, stylesFileContent);
}
console.log(
`Component ${componentName} created successfully as ${options.componentType} component${
options.style ? " with styles" : ""
} (${options.lang})`
);
} catch (err) {
console.error(`Error creating component ${componentName}:`, err);
}
}
program.parse(process.argv);