argon-cli
Version:
Argon CLI provide tools for creating components and running build scripts
204 lines (195 loc) • 8.55 kB
JavaScript
const inquirer = require('inquirer');
const argv = require('yargs').argv;
const configFile = argv.config || 'argon.config';
const fs = require('fs-extra');
const chalk = require('chalk');
const path = require('path');
let config = null;
let globalConfig = null;
const NAME_VALIDATION_REGEX = /^\d|[^A-Za-z0-9_]/;
const globalConfigFilePath = `${process.cwd()}/${configFile}`;
try {
globalConfig = require(globalConfigFilePath);
config = globalConfig.createComponent;
} catch (e) {
console.log(chalk.red(chalk.bold('An error occurred while loading configuration')));
return;
}
const layouts = config.layouts || `${process.cwd()}/source/templates/layouts`;
if (typeof layouts !== 'string') {
console.log(chalk.red(chalk.bold(`Missing configuration "layouts". Please update your config file's "createComponent" configuration to include "layouts" path.`)));
return;
}
// Resolve Layout File name
let layoutFileName = '';
try {
if (fs.lstatSync(layouts).isDirectory()) {
// Get list of layouts
const layoutFiles = fs.readdirSync(layouts).sort();
layoutFileName = layoutFiles[0];
} else {
layoutFileName = path.basename(layouts);
}
} catch (e) {
console.log(chalk.red(chalk.bold(`The layouts are undefined OR "layouts" path specified seems to be incorrect.`)));
return;
}
let targetModule = 'component';
if (argv.atom) {
targetFolder = 'atoms';
targetModule = 'atom'
} else if (argv.molecule) {
targetFolder = 'molecules';
targetModule = 'molecule'
}
const questions = [
{
message: `Enter ${targetModule} name\nRules: \n1. Name should start with capital or small case\n2. Name should not start with a number\n3. Name can contain an underscore\n:`,
name: "cName",
type: 'text'
}
];
// Resolve webpack configuration
if (
globalConfig.webpack
&& targetModule === 'component'
) {
const webpackConfig = globalConfig.webpack;
if (webpackConfig.cacheGroups) {
const bundles = Object.keys(webpackConfig.cacheGroups).filter(bundle => webpackConfig.cacheGroups[bundle].testMultiple);
questions.push({
type: 'list',
message: `Select a bundle where you wish to place your JavaScript file\nOR\nSelect "new" to create new bundle`,
choices: ['[new]', ...bundles],
default: '[new]',
name: 'bundle'
});
}
}
function createNewBundle(bundle) {
return new Promise((resolve, reject) => {
if (bundle === '[new]') {
inquirer.prompt([{
message: 'Enter a bundle name',
name: 'bundleName',
type: 'text'
}]).then(({ bundleName: name }) => {
if (typeof name !== 'string') {
name = '';
}
name = name.trim();
if (
name
&& !NAME_VALIDATION_REGEX.test(name)
&& !globalConfig.webpack.cacheGroups[name]) {
Object.assign(globalConfig.webpack.cacheGroups, {
[name]: {
testMultiple: true,
name,
enforce: true,
chunks: 'all'
}
});
Object.assign(globalConfig.webpack.componentGroups, {
[name]: []
});
} else {
console.log(chalk.blue('Invalid name or bundle already exists!'));
}
resolve(name);
}).catch(reject);
} else {
resolve(bundle);
}
});
}
function createComponent(name, bundle) {
createNewBundle(bundle).then((bundleName) => {
// Create folder structure
const currentConfig = argv.atom
? 'atomsFolder'
: argv.molecule
? 'moleculesFolder'
: 'componentsFolder';
const compRelativePath = `${config[currentConfig]}/${name.toLowerCase()}`;
const componentPath = `${process.cwd()}/${compRelativePath}`;
fs.mkdirsSync(componentPath);
// Create files
fs.writeFileSync(`${componentPath}/_${name}.scss`, '');
const templateFileName = name.toLowerCase();
const jsFileName = `${name.charAt(0).toUpperCase()}${name.substring(1)}`;
try {
const isAtomOrMolecule = (argv.atom || argv.molecule);
const slyComponentTemplate = fs.readFileSync(`${__dirname}/templates/slyComponentTemplate.txt`, 'utf8').toString();
const slyTemplate = fs.readFileSync(`${__dirname}/templates/slyTemplate.txt`, 'utf8').toString();
const jsTemplate = fs.readFileSync(`${__dirname}/templates/jsClassTemplate.txt`, 'utf8').toString();
const jsTestTemplate = fs.readFileSync(`${__dirname}/templates/jsTestFileTemplate.txt`, 'utf8').toString();
const uxPreviewTemplate = fs.readFileSync(`${__dirname}/templates/uxPreviewTemplate.txt`, 'utf8').toString();
fs.writeFileSync(`${componentPath}/${templateFileName}-template.html`, (isAtomOrMolecule ? slyTemplate : slyComponentTemplate).replace('#templateFileName#', templateFileName).replace('#className#', jsFileName));
if (!isAtomOrMolecule) {
const instanceName = `${name.charAt(0).toLowerCase()}${name.substring(1)}`;
fs.writeFileSync(`${componentPath}/${jsFileName}.js`, jsTemplate.replace(/#component#/g, jsFileName));
fs.writeFileSync(`${componentPath}/${jsFileName}.spec.js`, jsTestTemplate.replace(/#component#/g, jsFileName).replace(/#instance#/g, instanceName));
fs.writeFileSync(`${componentPath}/ux-model.json`, '{}');
const previewHtml = uxPreviewTemplate.replace(/#name#/g, templateFileName).replace(/#layoutFileName#/, layoutFileName);
fs.writeFileSync(`${componentPath}/${templateFileName}.hbs`, previewHtml);
}
console.log(chalk.green(chalk.bold(`${targetModule} ${name} has been created!`)));
} catch (e) {
console.log(chalk.red(chalk.bold('Unable to read template file(s)!')));
}
// Add bundle
if (
bundleName
&& !globalConfig.webpack.componentGroups[bundleName].includes(`${compRelativePath}/`)
) {
globalConfig.webpack.componentGroups[bundleName].push(`${compRelativePath}/`);
// Write configuration back
fs.writeFileSync(globalConfigFilePath, JSON.stringify(globalConfig, null, 2));
}
}).catch(() => {
console.log(chalk.red(chalk.bold('Something went wrong while resolving the bundle!')));
});
}
inquirer.prompt(questions)
.then((data) => {
if (
data.cName
&& !NAME_VALIDATION_REGEX.test(data.cName)
) {
const inputComponentName = `${data.cName.charAt(0).toLowerCase()}${data.cName.substring(1)}`;
// Check if component already exists
try {
let folder = config.componentsFolder;
let moduleName = 'Component';
if (argv.atom) {
folder = config.atomsFolder;
moduleName = 'Atom';
} else if (argv.molecule) {
folder = config.moleculesFolder;
moduleName = 'Molecule';
}
if (!fs.existsSync(folder)) {
fs.mkdirsSync(folder);
}
const componentList = fs.readdirSync(`${process.cwd()}/${folder}`);
if (componentList.includes(inputComponentName.toLowerCase())) {
console.log(chalk.red(chalk.bold(`${moduleName} with name ${inputComponentName} already exists!`)));
} else {
const params = [inputComponentName];
if (moduleName === 'Component') {
params.push(data.bundle);
}
createComponent(...params);
}
} catch (e) {
console.log(chalk.red(chalk.bold('Something went wrong!')));
}
} else {
console.log(chalk.red(chalk.bold('You need to provide a valid component name')));
}
})
.catch(() => {
console.log(chalk.red(chalk.bold('Something went wrong!')));
});