UNPKG

@pega/custom-dx-components

Version:

Utility for building custom UI components

301 lines (265 loc) 10.1 kB
import fs from 'fs'; import path from 'path'; import chalk from 'chalk'; import fetch from 'node-fetch'; import { join } from 'path'; import { LIST_COMPONENT_SERVICE_REST_ENDPOINT, LP_LIST_COMPONENT_SERVICE_REST_ENDPOINT, TOKEN_PATH, COMPONENT_SCHEMA, TASKS_CONFIG_JSON_FILENAME, COMPONENTS_DIRECTORY_PATH, COMPONENTS_PATH } from '../../constants.js'; import { constructCompleteUrl, getComponents, getPegaServerConfig, getHttpsAgent, addDebugLog, getLibraryBased, getComponentsConfigs, getConfigDefaults } from '../../util.js'; export const SOURCE_OF_COMPONENT_TYPES = { SERVER: 'Server', LOCAL: 'Local' }; export const getListComponentsQuestions = async (options) => { addDebugLog("getListComponentsQuestions", "", ""); const defaultPegaServerConfig = await getPegaServerConfig(); return [ { name: 'sourceOfComponents', type: 'rawlist', message: 'List components from Server or Local ?', choices: Object.values(SOURCE_OF_COMPONENT_TYPES), default: defaultPegaServerConfig.sourceOfComponents, when() { return !options.params[3]; } } ]; }; export const getLaunchPadFilterQuestions = async () => { addDebugLog("getLaunchPadFilterQuestions", "", ""); const defaultPegaServerConfig = await getPegaServerConfig(); const currentDirectory = process.cwd(); const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME); let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' }); data = data && JSON.parse(data); if (!data[COMPONENTS_DIRECTORY_PATH]) { console.error( `${chalk.red.bold('ERROR')} Could not able find components directory path in config.json` ); process.exit(1); } const componentData = data[COMPONENTS_PATH]; let { library } = componentData; let { organization } = JSON.parse(fs.readFileSync(path.resolve('package.json'), 'utf8')); return [ { name: 'organization', message: 'Enter component organization (required)', default: organization, validate: value => { if (value) { return true; } return 'Please provide value for organization'; } }, { name: 'library', message: 'Enter library name (required)', default: library, validate: value => { if (value) { return true; } return 'Please provide value for library'; } } ]; } export const listLocalComponents = async (sourceOfComponents) => { addDebugLog("listLocalComponents", `sourceOfComponents: ${sourceOfComponents}`, ""); const isLibraryBased = getLibraryBased(); if (isLibraryBased) { const defConfig = getConfigDefaults(); const data = await getComponentsConfigs(); // get built on from first component if exists let builtOn = "(date unavailable)"; if (data[0] && data[0].buildDate) { builtOn = data[0].buildDate; } if (data.length === 0) { console.log(chalk.bold.redBright(`No custom components in ${sourceOfComponents}`)); process.exit(); } let libData = data.map((component) => ( {'Component': component.name, 'Label': component.label, 'Version': component.version, 'Type': component.type, 'Sub Type' : component.subtype})); console.log(chalk.bold.blueBright(`\nList of ${defConfig.library}:${defConfig.buildVersion} components.`)); console.table(libData, ['Component', 'Label', 'Version', 'Type', 'Sub Type']); } else { let localComponents = await getComponents(); localComponents = localComponents.map((name) => ({ 'Rule name': name })); if (localComponents.length > 0) { console.log(chalk.bold.blueBright(`List of custom components in ${sourceOfComponents}`)); console.table(localComponents, ['Rule name']); } else { console.log(chalk.bold.redBright(`No custom components in ${sourceOfComponents}`)); } } }; async function fetchComponentsFromInfinity(apiUrl, headers) { addDebugLog("fetchComponentsFromInfinity", `apiUrl: ${apiUrl}`, ""); const serverConfig = await getPegaServerConfig(); return new Promise((resolve, reject) => { let status = 500; fetch(apiUrl, { method: 'GET', agent: getHttpsAgent(serverConfig), headers }) .then((response) => { status = response.status; if (status === 401) { throw new Error('Error occurred in authentication. Please regenerate using authenticate'); } else if (status === 404){ throw new Error('404: Server resource not found'); } else if (status === 405){ throw new Error('405: Server method not allowed'); } else if (status === 408){ throw new Error('408: Server timed out'); } return response.json(); }) .then((resp) => { // const respData = JSON.parse(resp); if (status === 401) { throw new Error('Error occurred in authentication. Please regenerate using authenticate'); // console.log(accessTokenUri, refreshToken); /* TODO - Handle refresh_token */ } else if (status === 200) { resolve(resp); } else { throw new Error(`${resp.message}`); } }) // eslint-disable-next-line prefer-promise-reject-errors .catch((e) => reject(`${chalk.bold.red(e)}`)); }); } async function fetchComponentsFromLaunchpad(apiUrl, headers) { addDebugLog("fetchComponentsFromLaunchpad", `apiUrl: ${apiUrl}`, ""); const serverConfig = await getPegaServerConfig(); // constructing urls for all type of components const urls = COMPONENT_SCHEMA.type.map((type) => apiUrl.replace('{type}', type.value)); const statuses = []; return new Promise((resolve, reject) => { Promise.all( urls.map(async (url) => { return fetch(url, { method: 'GET', agent: getHttpsAgent(serverConfig), headers }); }) ) .then((responses) => { return Promise.all( responses.map((res) => { statuses.push(res.status); if (res.status === 401 || res.status === 503) { // Finding a 503 response is sometimes being returned from Launchpad in expired authentication scenario throw new Error('Authorization error. Please regenerate using authenticate'); } else if (res.ok) { return res.json(); } else { throw new Error(`Unexpected Error ${res.status} encountered. ${res.message}`); } }) ); }) .then((data) => { const components = data.map((res) => res.components).flat(); resolve(components); }) // eslint-disable-next-line prefer-promise-reject-errors .catch((e) => reject(`${chalk.bold.red(e)}`)); }); } export const getComponentsFromServer = async (library, organization) => { addDebugLog("getComponentsFromServer", `library: ${library}, organization: ${organization}`, ""); const defaultPegaServerConfig = await getPegaServerConfig(); const isLaunchpad = defaultPegaServerConfig.serverType === 'launchpad'; const url = constructCompleteUrl( defaultPegaServerConfig.server, isLaunchpad ? LP_LIST_COMPONENT_SERVICE_REST_ENDPOINT : LIST_COMPONENT_SERVICE_REST_ENDPOINT ); return new Promise((resolve, reject) => { try { fs.readFile(TOKEN_PATH, 'utf8', (err, data) => { if (err) { // eslint-disable-next-line prefer-promise-reject-errors reject(`\n${chalk.bold.red('Error occurred in authentication. Please regenerate using authenticate')}`); } if (data) { const { access_token: accessToken, token_type: tokenType } = JSON.parse(data); const headers = {}; if (isLaunchpad) { headers.cookie = `Pega-AAT=${accessToken}`; fetchComponentsFromLaunchpad(url, headers) .then((response) => { response = response.filter(component => (component.library === library || library === "*" ) && (component.organization === organization || organization === "*")); resolve(response); } ) .catch((e) => reject(e)); } else { headers.Authorization = `${tokenType} ${accessToken}`; fetchComponentsFromInfinity(url, headers) .then((response) => resolve(response)) .catch((e) => reject(e)); } } }); } catch (error) { console.log(`\n${chalk.bold.red(error)}`); // eslint-disable-next-line prefer-promise-reject-errors reject(`${chalk.bold.red(error)}`); } }); }; export const displayServerComponents = async (data) => { addDebugLog("displayServerComponents", "", ""); const defaultPegaServerConfig = await getPegaServerConfig(); const isLaunchpad = defaultPegaServerConfig.serverType === 'launchpad'; let list; if (isLaunchpad) { list = data; } else { try { if (typeof data === 'object') { list = data.pxResults; } else { list = JSON.parse(data).pxResults; } } catch (ex) { /* empty */ } } /** * TODO: Need to modify the components list mapping code to support Launchpad components */ const componentList = list?.map(({ label, pyRuleSet, pyRuleSetVersion, type }) => { if (isLaunchpad) { return { 'Component Name': label, Type: type }; } return { 'Rule name': label, 'Ruleset name': pyRuleSet, 'Ruleset version': pyRuleSetVersion }; }); if (componentList && componentList.length > 0) { console.log(chalk.bold.blueBright(`List of custom components in ${defaultPegaServerConfig.server}`)); if (isLaunchpad) { console.table(componentList, ['Component Name', 'Type']); } else { console.table(componentList, ['Rule name', 'Ruleset name', 'Ruleset version']); } } else { console.log(chalk.bold.redBright(`No custom components in ${defaultPegaServerConfig.server}`)); } };