UNPKG

@pega/custom-dx-components

Version:

Utility for building custom UI components

209 lines (183 loc) 6 kB
import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; import { promisify } from 'util'; import { exec } from 'child_process'; import chalk from 'chalk'; import { execa } from 'execa'; import ncp from 'ncp'; 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 execPromise = promisify(exec); const copy = promisify(ncp); const writeGitignore = promisify(gitignore.writeFile); const writeFile = promisify(fs.writeFile); const createGitignore = async options => { const file = fs.createWriteStream(path.join(options.targetDirectory, '.gitignore'), { flags: 'a' }); return writeGitignore({ type: 'Node', file }); }; const createLicense = async options => { const targetPath = path.join(options.targetDirectory, 'LICENSE'); const licenseContent = 'Enter license text here'; return writeFile(targetPath, licenseContent, 'utf8'); }; const copyProjectTemplate = async options => { await copy(options.templateDirectory, options.targetDirectory, { clobber: false }); 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 }; const output = compileMustacheTemplate(packageJsonPath, options); fs.writeFileSync(packageJsonPath, output); fs.renameSync(packageJsonPath, packageJsonPath.replace('.mustache', '')); // rename template NPMRC to .npmrc, need to do this because npmjs won't publish an .npmrc file fs.renameSync(templateNPMRCPath, templateNPMRCPath.replace('templateNPMRC.txt', '.npmrc')); await createLicense(options); }; const initGit = async options => { const result = await execa('git', ['init'], { cwd: options.targetDirectory }); if (result.failed) { return Promise.reject(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(); await inquirer.prompt(questions).then(async answers => { projectName = answers.projectName; projectName = sanitize(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: () => execPromise('npm i --force --production=false', { cwd: options.targetDirectory }) }, */ { title: installDependenciesText, task: () => execPromise('npm i --force --dev', { cwd: options.targetDirectory }) }, /* { title: 'Installing tasks dependencies', task: () => execPromise('npm i --force --production=false', { cwd: options.componentDirectory }) }, { title: 'Installing tasks library dependencies', task: () => execPromise('npm i --force --production=false', { cwd: options.componentLibraryUtilsDirectory }) }, */ { title: 'Updating', task: () => execPromise('npm update --dev', { cwd: options.targetDirectory }) } /* { title: 'Installing quick run', task: () => execPromise('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', `${chalk.blueBright('npm run startStorybook')}`, `\n Start Storybook in development mode`, '\n\n', `${chalk.blueBright('npm run create')}`, '\n', `${chalk.blueBright('npm run list')}`, `\n Try out custom-component actions like create, list, publish, etc`, '\n\n', `${chalk.blueBright('npm run lint')}`, `\n Run eslint for component source files`, '\n' ); console.log( `We suggest that you begin by typing:`, '\n\n', `${chalk.blueBright('cd')} ${chalk.bold(projectName)}`, '\n', `${chalk.blueBright('npm run startStorybook')}`, '\n' ); return true; };