@darrylblake/create-component
Version:
A very opinionated command-line utility to generate scaffolding for a minimal TypeScript React component with optional unit test, Storybook demo, and module SCSS file.
137 lines (112 loc) • 4.55 kB
JavaScript
#!/usr/bin/env node
import { Command } from "commander";
import fs from "fs-extra";
import path from "path";
import { fileURLToPath } from "url";
import handlebars from "handlebars";
import inquirer from "inquirer";
const program = new Command();
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const templatesPath = path.join(__dirname, "..", "templates");
program
.version("0.0.1")
.argument("<componentName>", "name of the component")
.argument("[componentPath]", "optional path for the component")
.action((componentName, componentPath) => {
promptForActions(componentName, componentPath || process.cwd());
});
program.parse(process.argv);
async function promptForActions(componentName, componentPath) {
const answers = await inquirer.prompt([
{
message: "Create a unit test for this component?",
name: "createTest",
type: "confirm",
default: true,
},
{
message: "Create a Storybook demo for this component?",
name: "createStory",
type: "confirm",
default: true,
},
{
message: "Create a module.scss file for this component?",
suffix: " (this will also include a style import in the component file)",
name: "createScssModule",
type: "confirm",
default: false,
},
]);
await generateIndex(componentName, componentPath);
await generateComponent(
componentName,
componentPath,
answers.createScssModule
);
if (answers.createTest) {
await generateUnitTest(componentName, componentPath);
}
if (answers.createStory) {
await generateStorybook(componentName, componentPath);
}
if (answers.createScssModule) {
await generateScssModule(componentName, componentPath);
}
}
// Utils to generate files
const generateIndex = async (componentName, componentPath) => {
const componentDir = path.join(componentPath, componentName);
const indexFile = path.join(componentDir, "index.ts");
const componentTemplatePath = path.join(templatesPath, "index.hbs");
const templateContent = await fs.readFile(componentTemplatePath, "utf-8");
const template = handlebars.compile(templateContent);
const componentContent = template({ componentName });
await fs.ensureDir(componentDir);
await fs.writeFile(indexFile, componentContent);
};
const generateComponent = async (
componentName,
componentPath,
createScssModule
) => {
const componentDir = path.join(componentPath, componentName);
const componentFile = path.join(componentDir, `${componentName}.tsx`);
const componentTemplatePath = path.join(templatesPath, "react-component.hbs");
const templateContent = await fs.readFile(componentTemplatePath, "utf-8");
const template = handlebars.compile(templateContent);
const componentContent = template({ componentName, createScssModule });
await fs.ensureDir(componentDir);
await fs.writeFile(componentFile, componentContent);
};
const generateUnitTest = async (componentName, componentPath) => {
const componentDir = path.join(componentPath, componentName);
const testFile = path.join(componentDir, `${componentName}.test.tsx`);
const testTemplatePath = path.join(
templatesPath,
"react-component-unit-test.hbs"
);
const templateContent = await fs.readFile(testTemplatePath, "utf-8");
const template = handlebars.compile(templateContent);
const testContent = template({ componentName });
await fs.writeFile(testFile, testContent);
};
const generateStorybook = async (componentName, componentPath) => {
const componentDir = path.join(componentPath, componentName);
const storybookFile = path.join(componentDir, `${componentName}.stories.tsx`);
const storybookTemplatePath = path.join(templatesPath, "react-storybook.hbs");
const templateContent = await fs.readFile(storybookTemplatePath, "utf-8");
const template = handlebars.compile(templateContent);
const storyContent = template({ componentName });
await fs.writeFile(storybookFile, storyContent);
};
const generateScssModule = async (componentName, componentPath) => {
const componentDir = path.join(componentPath, componentName);
const styleFile = path.join(componentDir, `${componentName}.module.scss`);
const styleTemplatePath = path.join(templatesPath, "scss-module.hbs");
const templateContent = await fs.readFile(styleTemplatePath, "utf-8");
const template = handlebars.compile(templateContent);
const styleContent = template({ componentName });
await fs.writeFile(styleFile, styleContent);
};