@pega/custom-dx-components
Version:
Utility for building custom UI components
227 lines (195 loc) • 6.98 kB
JavaScript
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
import { promisify } from 'util';
import chalk from 'chalk';
import { execa } from 'execa';
import { Listr } from 'listr2';
import gitignore from 'gitignore';
import inquirer from 'inquirer';
import { compileMustacheTemplate, isPascalCase, convertIntoPascalCase, sanitize } from '../../util.js';
import { getInitProjectQuestions } from './helper.js';
const writeGitignore = promisify(gitignore.writeFile);
const copyProjectDir = async (src, dest) => {
if (typeof fs.cp === 'function') {
await fs.promises.cp(src, dest, { recursive: true, errorOnExist: false, force: false });
}
};
const createGitignore = async options => {
const file = fs.createWriteStream(path.join(options.targetDirectory, '.gitignore'), {
flags: 'a'
});
return writeGitignore({
type: 'Node',
file
});
};
const createLicense = async options => {
// Write LICENSE file directly
const targetPath = path.join(options.targetDirectory, 'LICENSE');
const licenseContent = 'Enter license text here';
await fs.promises.writeFile(targetPath, licenseContent, 'utf8');
};
const copyProjectTemplate = async options => {
// Use fast copy
await copyProjectDir(options.templateDirectory, options.targetDirectory);
const packageJsonPath = path.join(options.targetDirectory, 'package.json.mustache');
const templateNPMRCPath = path.join(options.targetDirectory, 'templateNPMRC.txt');
let { organization, projectName } = options;
projectName = sanitize(projectName).toLowerCase();
organization = sanitize(organization);
if (!isPascalCase(organization)) {
organization = convertIntoPascalCase(organization);
}
options = { ...options, organization, projectName };
// Compile and write package.json in one go
const output = compileMustacheTemplate(packageJsonPath, options);
await fs.promises.writeFile(packageJsonPath, output);
await fs.promises.rename(packageJsonPath, packageJsonPath.replace('.mustache', ''));
// Rename templateNPMRC.txt to .npmrc if exists
try {
await fs.promises.rename(templateNPMRCPath, templateNPMRCPath.replace('templateNPMRC.txt', '.npmrc'));
} catch (e) {
// ignore if not present
}
await createLicense(options);
};
const initGit = async options => {
// Use execa for async git init
const result = await execa('git', ['init'], {
cwd: options.targetDirectory
});
if (result.failed) {
throw new Error('Failed to initialize git');
}
};
export default async options => {
options.templateDirectory = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
'template'
);
let projectName = 'test';
const questions = getInitProjectQuestions();
const answers = await inquirer.prompt(questions);
projectName = sanitize(answers.projectName).toLowerCase();
options = { ...options, ...answers };
const projectDirectory = `./${projectName}`;
if (!fs.existsSync(projectDirectory)) {
fs.mkdirSync(projectDirectory);
} else {
console.log(chalk.bold.red(`A project with name ${projectName} already exists. Exiting...`));
process.exit();
}
const targetDirectory = options.targetDirectory || process.cwd();
options.targetDirectory = path.join(targetDirectory, projectName);
options.componentDirectory = path.join(
options.targetDirectory,
'node_modules/@pega/custom-dx-components'
);
options.componentLibraryUtilsDirectory = path.join(
options.targetDirectory,
'node_modules/@pega/constellation-dx-components-build-utils'
);
const installDependenciesText = `Installing dependencies. This will take a couple of minutes.`;
const tasks = new Listr(
[
{
title: `Creating a new custom component project in ${chalk.blue(options.targetDirectory)}`,
task: () => copyProjectTemplate(options)
},
{
title: 'Create gitignore',
task: () => createGitignore(options)
},
{
title: 'Initialize git',
task: () => initGit(options),
enabled: () => options.git
},
/*
{
title: installDependenciesText,
task: () =>
execa('npm', ['i', '--force', '--production=false'], { cwd: options.targetDirectory })
},
*/
{
title: installDependenciesText,
task: () =>
execa('npm', ['i', '--force', '--no-audit', '--no-fund', '--loglevel=error'], { cwd: options.targetDirectory })
},
/*
{
title: 'Installing tasks dependencies',
task: () => {
if (!fs.existsSync(options.componentDirectory)){
fs.mkdirSync(options.componentDirectory, { recursive: true });
};
execa('npm', ['i', '--force', '--no-audit', '--no-fund', '--loglevel=error'], { cwd: options.componentDirectory });
}
},
{
title: 'Installing tasks library dependencies',
task: () => {
if (!fs.existsSync(options.componentLibraryUtilsDirectory)){
fs.mkdirSync(options.componentLibraryUtilsDirectory, { recursive: true });
};
execa('npm', ['i', '--force', '--no-audit', '--no-fund', '--loglevel=error'], {
cwd: options.componentLibraryUtilsDirectory
});
}
},
*/
{
title: 'Updating',
task: () => execa('npm', ['update', '--dev', '--no-audit', '--no-fund', '--loglevel=error'], { cwd: options.targetDirectory })
}
/* {
title: 'Installing quick run',
task: () => execa('npm', ['i', '-g', 'npm-quick-run'], { cwd: options.targetDirectory })
} */
],
{
exitOnError: false
}
);
await tasks.run();
console.log('\n');
console.log(
`${chalk.green('Success!!')} Project created at ${chalk.blueBright(options.targetDirectory)}`
);
console.log(
'\n',
`Inside that directory, you can run several commands:`,
'\n\n',
`Get a list of commands\n`,
` ${chalk.blueBright('npm run help')}`,
'\n\n',
`Create or import a library first\n`,
` ${chalk.blueBright('npm run createLib')}\n`,
` ${chalk.blueBright('npm run importLibVersion')}`,
'\n\n',
`Try out custom-component actions like create, list, etc. \n`,
` ${chalk.blueBright('npm run create')}\n`,
` ${chalk.blueBright('npm run list')}`,
'\n\n',
`Start Storybook in development mode\n`,
` ${chalk.blueBright('npm run startStorybook')}`,
'\n\n',
`Validate components (schema, lint, test build of a library)\n`,
` ${chalk.blueBright('npm run validateAll')}`,
'\n\n',
`Publish component library\n`,
` ${chalk.blueBright('npm run publish')}`,
'\n'
);
console.log(
`We suggest that you begin by typing:`,
'\n\n',
`${chalk.blueBright('cd')} ${chalk.bold(projectName)}`,
'\n',
`${chalk.blueBright('npm run createLib')} or ${chalk.blueBright('npm run importLibVersion')}`,
'\n'
);
return true;
};