UNPKG

@pega/custom-dx-components

Version:

Utility for building custom UI components

322 lines (289 loc) 10.2 kB
import fs from 'fs'; import path from 'path'; import chalk from 'chalk'; 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, getFetchAgent, addDebugLog, getLibraryBased, getComponentsConfigs, getConfigDefaults, checkAccessTokenExpiration } 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')} Unable to 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', dispatcher: getFetchAgent(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}`); } }) .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', dispatcher: getFetchAgent(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); }) .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 ); if (!isLaunchpad) { await checkAccessTokenExpiration; } return new Promise((resolve, reject) => { try { fs.readFile(TOKEN_PATH, 'utf8', (err, data) => { if (err) { 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 => { // filter and only return non managed rules response.pxResults = response.pxResults.filter( component => component.pyManagedRule === false || component.pyManagedRule === undefined ); resolve(response); }) .catch(e => reject(e)); } } }); } catch (error) { console.log(`\n${chalk.bold.red(error)}`); 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}`)); } };