UNPKG

@pega/custom-dx-components

Version:

Utility for building custom UI components

341 lines (280 loc) 10.7 kB
import fs from 'fs'; import { promisify } from 'util'; import { join } from 'path'; import inquirer from 'inquirer'; import ncp from 'ncp'; import chalk from 'chalk'; import { sanitize, checkPathAccess, showVersion, getDirectoryFiles, addDebugLog, checkLibraryAndArchives, getConfigDefaults, getComponents, getUseInputConfig, getInputConfigForCommand, convertYNToBoolean } from '../../util.js'; import { TASKS_CONFIG_JSON_FILENAME } from '../../constants.js'; import { getFilePathQuestions, getFileNameQuestions, updateSavedFilePath } from './helper.js'; import buildComponent from '../build-comp/index.js'; import inquirerFuzzyPath from '@pega/inquirer-fuzzy-path'; export const DXCB_CONFIG_INTERNAL_JSON_FILENAME = 'src/dxcb.config.json'; const currentDirectory = process.cwd(); const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME); import { convertIntoPascalCase, getComponentDirectoryPath } from '../../util.js'; const copy = promisify(ncp); let gFilePath = ''; export const updateConfig = async ( { oldComponentKey, newComponentKey, library, version, targetDirectory, newLabel = '', organization }, options, onlyCompanion = false ) => { addDebugLog('updateConfig', `oldComponentKey: ${oldComponentKey}, newComponentKey: ${newComponentKey}`, ''); let configData = fs.readFileSync(join(targetDirectory, '/config.json'), { encoding: 'utf8' }); configData = configData && JSON.parse(configData); configData.name = newComponentKey; if (configData.componentKey) configData.componentKey = newComponentKey; configData.library = library; configData.version = version; configData.organization = organization; if (newLabel != '') { configData.label = newLabel; configData.description = newLabel; } // stringify "4", makes the json string look like JSON in the file, formatted instead of a single line fs.writeFileSync(join(targetDirectory, '/config.json'), JSON.stringify(configData, null, 4), { encoding: 'utf8' }); }; export const updateFile = async (fileName, oldComponentKeyPC, newComponentKeyPC, targetDirectory) => { addDebugLog( 'updateFile', `fileName: ${fileName}, oldComponentKeyPC: ${oldComponentKeyPC}, newComponentKeyPC: ${newComponentKeyPC}, targetDirectory: ${targetDirectory}`, '' ); let fileData = fs.readFileSync(join(targetDirectory, '/', fileName), { encoding: 'utf8' }); if (fileData.indexOf(oldComponentKeyPC) >= 0) { fileData = fileData.replaceAll(oldComponentKeyPC, newComponentKeyPC); fs.writeFileSync(join(targetDirectory, '/', fileName), fileData, { encoding: 'utf8' }); } }; // rename the component export const renameComponent = async (componentKey, orgLib, version, newName = '', newLabel = '', organization, options) => { addDebugLog('renameComponent', `orgLib: ${orgLib}, componentKey: ${componentKey}`, ''); const componentName = newName != '' ? newName : componentKey.split('_')[2]; const newComponentKey = `${orgLib}_${componentName}`; const library = orgLib.split('_')[1]; const oldComponentKey = componentKey; const newComponentKeyPC = convertIntoPascalCase(newComponentKey); const oldComponentKeyPC = convertIntoPascalCase(oldComponentKey); const currentDirectory = await getComponentDirectoryPath(componentKey); const targetDirectory = await getComponentDirectoryPath(newComponentKey); // custom component try { fs.renameSync(currentDirectory, targetDirectory); } catch (err) { console.log(err); } const targetFileList = await getDirectoryFiles(targetDirectory); for (var fileIndex in targetFileList) { const fileName = targetFileList[fileIndex]; if (fileName === 'config.json') { await updateConfig( { oldComponentKey, newComponentKey, componentName, library, version, targetDirectory, newLabel, organization }, options ); } else { await updateFile(fileName, oldComponentKeyPC, newComponentKeyPC, targetDirectory); } } // for return newComponentKey; }; export const importComp = async (filePath, fileName, askValidate) => { addDebugLog('importComp', `filePath: ${filePath}, fileName: ${fileName}`, ''); const currentDirectory = process.cwd(); // const compDirectory = join(currentDirectory, "src", "components"); const copyFilePath = join(filePath, fileName); const configDef = getConfigDefaults(); const copyDir = await getComponentDirectoryPath(fileName); let configData; let newName = ''; let newLabel = ''; if (fs.existsSync(copyDir)) { configData = fs.readFileSync(join(copyDir, '/config.json'), { encoding: 'utf8' }); configData = configData && JSON.parse(configData); const compName = configData.componentKey.split('_')[2]; const potentialCompKey = `${configDef.currentOrgLib}_${compName}`; const currentCompList = await getComponents(); if (currentCompList && currentCompList.includes(potentialCompKey)) { console.log(`\nComponent ${chalk.yellow(`${potentialCompKey}`)} already exists.`); const proceedAnswers = await inquirer.prompt([ { name: 'proceedAs', type: 'rawlist', message: `Proceed as ?`, default: 'No import', choices: ['No import', 'Overwrite', 'New name'] }, { name: 'componentName', message: 'Enter component name (required)', when(answers) { return answers.proceedAs === 'New name'; }, validate: value => { /* value should not be empty It should not have spaces It should not start with a number Only case-insensitive alphanumeric values are allowed */ if (value && !/^\d/.test(value) && value === sanitize(value)) { return true; } return 'Only alphanumeric values are allowed, starting with alphabets, no spaces.'; } }, { name: 'componentLabel', message: 'Enter component label for display (required)', when(answers) { return answers.proceedAs === 'New name'; }, validate: value => { if (value) { return true; } return 'Please provide value for label'; } } ]); switch (proceedAnswers.proceedAs) { case 'No import': // removed copied // fs.rmSync(copyDir, { recursive: true, force: true, maxRetries: 2 }); process.exit(); break; case 'Overwrite': // remove existing const existingComp = await getComponentDirectoryPath(potentialCompKey); fs.rmSync(existingComp, { recursive: true, force: true, maxRetries: 2 }); break; case 'New name': newName = proceedAnswers.componentName; newLabel = proceedAnswers.componentLabel; break; } } } if (fs.existsSync(copyFilePath)) { fs.cpSync(copyFilePath, copyDir, { recursive: true, force: true }); configData = fs.readFileSync(join(copyDir, '/config.json'), { encoding: 'utf8' }); configData = configData && JSON.parse(configData); const newCompKey = await renameComponent( configData.componentKey, configDef.currentOrgLib, configDef.buildVersion, newName, newLabel, configDef.organization, null ); console.log(`\n${chalk.green(`${fileName}`)} has been imported as ${chalk.green(`${newCompKey}`)}\n`); if (askValidate) { const validateAnswers = await inquirer.prompt([ { name: 'doValidate', type: 'confirm', message: `Validate ${chalk.yellow(`${newCompKey}`)}`, default: true } ]); if (validateAnswers.doValidate) { const args = ['', '', '', `${newCompKey}`]; let myOptions = {}; myOptions['params'] = args; await buildComponent(myOptions); } } } }; export const getFolderList = async filePath => { addDebugLog('getFolderList', `filePath: ${filePath}`, ''); if (fs.existsSync(filePath)) { return fs .readdirSync(filePath, { withFileTypes: true }) .filter(dirent => dirent.isDirectory() && !dirent.name.startsWith('.')) .map(dirent => dirent.name); } else { console.log(chalk.red.bold(`File path: ${filePath} does not exist or no permissions.`)); process.exit(1); } }; export const hasConfig = dir => { const configPath = join(gFilePath, dir, 'config.json'); if (fs.existsSync(configPath)) { return true; } return false; }; export const getComponentList = async filePath => { addDebugLog('getComponentList', `filePath: ${filePath}`, ''); let compList = await getFolderList(filePath); gFilePath = filePath; if (compList.length > 0) { return compList.filter(hasConfig); } return compList; }; export default async options => { await showVersion(); await checkLibraryAndArchives(); await checkPathAccess(pegaConfigJsonPath); const useInputConfig = getUseInputConfig(); addDebugLog('importComponent', '', '+'); if (options.params.length >= 5) { const filePath = options.params[3]; const fileName = options.params[4]; let askValidate = true; if (options.params.length >= 6) { if (options.params[5] === 'noAskValidate') { askValidate = false; } } await importComp(filePath, fileName, askValidate); } else { let filePath; let fileName; if (useInputConfig) { const inputConfig = await getInputConfigForCommand('importComponent'); filePath = inputConfig.fileLocation; fileName = inputConfig.fileName; await importComp(filePath, fileName, false); } else { inquirer.registerPrompt('fuzzypath', inquirerFuzzyPath); const filePathQuestions = await getFilePathQuestions(); const filePathAnswers = await inquirer.prompt(filePathQuestions); const { filePath } = filePathAnswers; const compFileList = await getComponentList(filePath); if (!compFileList || compFileList.length === 0) { console.log(chalk.red.bold(`No component files exist at path: ${filePath}`)); process.exit(); } await updateSavedFilePath(filePath); const fileNameQuestions = await getFileNameQuestions(compFileList); const fileNameAnswers = await inquirer.prompt(fileNameQuestions); const { fileName } = fileNameAnswers; await importComp(filePath, fileName, true); } } addDebugLog('importComponent', 'END', '-'); };