UNPKG

@pega/custom-dx-components

Version:

Utility for building custom UI components

386 lines (299 loc) 10.8 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", "-"); };