@pega/custom-dx-components
Version:
Utility for building custom UI components
1,446 lines (1,201 loc) • 93.8 kB
JavaScript
import fs from 'fs';
import path from 'path';
import { join } from 'path';
import { promisify } from 'util';
import crypto from 'node:crypto';
import { createRequire } from 'module';
import { jwtDecode } from 'jwt-decode';
import archiver from 'archiver';
import { unarchive } from 'unarchive';
import ora from 'ora';
import undici from 'undici';
import chalk from 'chalk';
import mustache from 'mustache';
import pascalCase from 'pascalcase';
// import checkGit from 'check-git';
import * as currentPath from './currentPath.cjs';
import {
COMPONENTS_DIRECTORY_PATH,
COMPONENTS_CONFIG_FILE_NAME,
TASKS_CONFIG_JSON_FILENAME,
INPUT_CONFIG_JSON_FILENAME,
PACKAGE_JSON_FILENAME,
PACKAGE_LOCK_JSON_FILENAME,
TOKEN_PATH,
OOTB_COMPONENT_SERVICE_REST_ENDPOINT,
DELETE_COMPONENT_SERVICE_REST_ENDPOINT,
LP_DELETE_COMPONENT_SERVICE_REST_ENDPOINT,
DELETE_COMPONENT_LIBRARY_SERVICE_REST_ENDPOINT,
OOTB_COMPONENTS,
USE_PROMOTED_WEB_PACK,
BOOTSTRAP_CONFIG,
LIBRARY_BASED,
LIBRARY_BASED_CL,
USE_INPUT_CONFIG,
SHARED_DIRECTORY,
COMPONENT_SCHEMA,
ARCHIVES_PATH,
BIN_ARCHIVES_PATH,
TEMP_PATH,
JEST_TESTS_FUNCTIONAL_PATH,
IMPORT_RELATIVE_PATH,
EXPORT_RELATIVE_PATH,
MAX_RFT_CHARS
} from './constants.js';
const access = promisify(fs.access);
let showDebug = false;
let debugLevel = 1;
let haveDependencyDifference = false;
let addAboutData = true;
// updated upon start
let defaultConfigs = {
serverType: '',
isLibraryBased: false,
isLibraryBasedCL: false,
devBuild: true,
devServerPort: '',
library: '',
organization: '',
currentOrgLib: '',
version: '',
buildVersion: '',
displayLibVersion: '',
showDebug: false,
importRelativePath: '',
exportRelativePath: '',
useInputConfig: false
};
let pegaConfig = null;
let pegaData = null;
let sPegaData;
let sPegaServerConfig;
export const modAddAboutData = addInAboutData => {
// used by jest to not put in to match assets without aboutData
addAboutData = addInAboutData;
};
export const addDebugLog = (sFunctionName, sLogData, sIncDec) => {
let sLog;
if (showDebug) {
if (sIncDec === '-') {
debugLevel--;
}
sLog = `>> log ${debugLevel} `;
for (let i = 0; i < debugLevel; i++) {
sLog = sLog.concat('-');
}
sLog = sLog.concat(sFunctionName).concat(': ').concat(sLogData);
console.log(`${chalk.hex('#A0522D')(sLog)}`);
if (sIncDec === '+') {
debugLevel++;
}
}
};
export const setUpDefaults = async () => {
// defaults, start up function will set these up
// so that won't have to continuously hit files to get data
// thus saving time.
let retrievedConfigData = {
serverType: '',
isLibraryBased: false,
isLibraryBasedCL: false,
devBuild: true,
devServerPort: '',
library: '',
organization: '',
currentOrgLib: '',
version: '',
buildVersion: '',
displayLibVersion: '',
showDebug: false,
importRelativePath: '',
exportRelativePath: '',
useInputConfig: false
};
// retrievedConfigData
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
try {
// force to throw error and not console log
await checkPathAccess(pegaConfigJsonPath, {}, true);
let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
data = JSON.parse(data);
if (data[IMPORT_RELATIVE_PATH]) {
retrievedConfigData.importRelativePath = data[IMPORT_RELATIVE_PATH];
}
if (data[EXPORT_RELATIVE_PATH]) {
retrievedConfigData.exportRelativePath = data[EXPORT_RELATIVE_PATH];
}
if (data[USE_INPUT_CONFIG]) {
retrievedConfigData.useInputConfig = data[USE_INPUT_CONFIG];
}
if (data[LIBRARY_BASED]) {
retrievedConfigData.isLibraryBased = data[LIBRARY_BASED];
}
retrievedConfigData.library = data.component.library;
retrievedConfigData.version = data.component.version;
if (data[LIBRARY_BASED_CL]) {
retrievedConfigData.isLibraryBasedCL = data[LIBRARY_BASED_CL];
// if this is true, then force library based to true, so it doesn't have to be set
if (retrievedConfigData.isLibraryBasedCL) {
retrievedConfigData.isLibraryBased = retrievedConfigData.isLibraryBasedCL;
}
}
const { organization } = JSON.parse(fs.readFileSync(path.resolve('package.json'), 'utf8'));
retrievedConfigData.organization = organization;
if (data['showDebug']) {
retrievedConfigData.showDebug = data.showDebug;
showDebug = data.showDebug;
}
retrievedConfigData.serverType = data['server-config'].serverType;
retrievedConfigData.devBuild = data['server-config'].devBuild;
// override devBuild for libraryBasedCL, always false.
if (retrievedConfigData.isLibraryBasedCL) {
retrievedConfigData.devBuild = false;
}
retrievedConfigData.devServerPort = data['server-config'].devServerPort;
retrievedConfigData.buildVersion = retrievedConfigData.devBuild ? `${retrievedConfigData.version}-dev` : retrievedConfigData.version;
retrievedConfigData.currentOrgLib = `${retrievedConfigData.organization}_${retrievedConfigData.library}`;
retrievedConfigData.displayLibVersion = `${retrievedConfigData.currentOrgLib}/${retrievedConfigData.buildVersion}`;
} catch (ex) {
// when can't find it, always be false, assume no library based.
// This is IMPORTANT for init (npx install)
return false;
}
return JSON.parse(JSON.stringify(retrievedConfigData));
};
export const convertYNToBoolean = inputYN => {
switch (inputYN) {
case 'Y':
case 'y':
case 'Yes':
case 'YES':
case 't':
case 'true':
case 'True':
case 'TRUE':
return true;
}
return false;
};
export const getInputConfigForCommand = async commandName => {
// retrievedConfigData
const currentDirectory = process.cwd();
const inputConfigJsonPath = join(currentDirectory, INPUT_CONFIG_JSON_FILENAME);
const isLibraryBased = getLibraryBased();
try {
// force to throw error and not console log
await checkPathAccess(inputConfigJsonPath, {}, true);
let data = fs.readFileSync(inputConfigJsonPath, { encoding: 'utf8' });
data = JSON.parse(data);
if (isLibraryBased) {
const libraryCommands = data['libraryMode'];
if (libraryCommands[commandName]) {
return libraryCommands[commandName];
}
} else {
const standardCommands = data['standard'];
if (standardCommands[commandName]) {
return standardCommands[commandName];
}
}
} catch (ex) {
// when can't find it, always be false, assume no library based.
// This is IMPORTANT for init (npx install)
return {};
}
return {};
};
// initialize
// await setUpDefaults();
export const checkPathAccess = async (path, options = {}, throwError = false) => {
const { errorMessage } = options;
try {
await access(path, fs.constants.R_OK);
} catch (err) {
if (throwError) {
if (showDebug) addDebugLog('checkPathAccess', 'path: '.concat(path), '+');
if (showDebug) addDebugLog('checkPathAccess', 'Error: '.concat(err), '');
if (showDebug) addDebugLog('checkPathAccess', 'END', '-');
throw new Error(err);
} else {
if (showDebug) addDebugLog('checkPathAccess', 'path: '.concat(path), '+');
const message = errorMessage || `${chalk.red.bold('ERROR')} Unable to access path - ${path}`;
console.error(message);
if (showDebug) addDebugLog('checkPathAccess', 'END', '-');
process.exit(1);
}
}
};
export const getUseWebPackPromotion = async () => {
if (showDebug) addDebugLog('getUseWebPackPromotion', '', '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
try {
// force to throw error and not console log
await checkPathAccess(pegaConfigJsonPath, {}, true);
} catch (ex) {
// when can't find it, always be false, assume no webpack override.
// This is IMPORTANT for init (npx install)
return false;
}
let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
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);
}
if (data[USE_PROMOTED_WEB_PACK] == null) {
// value doesn't exist in task config, so add it with default of false
data[USE_PROMOTED_WEB_PACK] = false;
await updateUseWebPackPromotion(false);
}
return data[USE_PROMOTED_WEB_PACK];
};
export const updateUseWebPackPromotion = async (useValue = false) => {
if (showDebug) addDebugLog('updateUseWebPackPromotion', '', '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
await checkPathAccess(pegaConfigJsonPath);
let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
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);
}
data['usePromotedWebPack'] = useValue;
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(data, null, 4), { encoding: 'utf8', flag: 'w' });
};
export const getAboutData = async (currentOrgLib, buildVersion, dateStamp) => {
if (showDebug) addDebugLog('getAboutData', `currentOrgLib: ${currentOrgLib}, buildVersion: ${buildVersion}, dateStamp: ${dateStamp}`, '');
const tokenAndStaticServer = await getC11NB2STokenAndStaticServer();
if (tokenAndStaticServer.C11NB2S === undefined) {
// console.log(chalk.yellowBright("Need to authenticate, missing services token.\nLibrary requires authentication to acquire a token to build."));
return `${currentOrgLib} ${buildVersion}, ${dateStamp}`;
}
const jwt = jwtDecode(tokenAndStaticServer.C11NB2S);
let infinityVersion = jwt.infinity_version;
infinityVersion = infinityVersion.replace('8.', '');
return `${currentOrgLib} ${buildVersion}, ${dateStamp}, ${infinityVersion}`;
};
export const applyPegaData = async configJson => {
if (showDebug) addDebugLog('applyPegaData', '', '');
const tokenAndStaticServer = await getC11NB2STokenAndStaticServer();
const currentDirectory = process.cwd();
// const currentPackagePath = join(currentDirectory, PACKAGE_JSON_FILENAME);
const currentPackageLockPath = join(currentDirectory, PACKAGE_LOCK_JSON_FILENAME);
// let currentPackageData;
let currentPackageLockData;
try {
currentPackageLockData = fs.readFileSync(currentPackageLockPath);
} catch (ex) {
console.log(chalk.red(`\nUnable to retrieve current package-lock.json.`));
process.exit(1);
}
// const cData = JSON.parse(currentPackageData);
// const cosmosVersion = cData.dependencies["@pega/cosmos-react-core"];
const cData = JSON.parse(currentPackageLockData);
const cosmosReact = cData.packages['node_modules/@pega/cosmos-react-core'];
const cosmosVersion = cosmosReact.version;
let infinityVersion = '';
if (tokenAndStaticServer.C11NB2S === undefined) {
} else {
const jwt = jwtDecode(tokenAndStaticServer.C11NB2S);
infinityVersion = jwt.infinity_version;
// don't remove "8." from infinity version so can do a comparison
}
// apply info to config.json
configJson.infinityVersion = infinityVersion;
configJson.packageCosmosVersion = cosmosVersion;
};
export const checkJWTExpiration = async () => {
const tokenAndStaticServer = await getC11NB2STokenAndStaticServer();
const isLibraryBased = getLibraryBased();
const isLibraryBasedCL = getLibraryBasedCL();
if (!isLibraryBasedCL && isLibraryBased) {
if (tokenAndStaticServer.C11NB2S === undefined) {
console.log(
chalk.redBright('Need to authenticate, missing services token.\nBuilding a library requires authentication to acquire a token to build.')
);
process.exit(1);
}
}
const jwt = jwtDecode(tokenAndStaticServer.C11NB2S);
const { exp, customer_org } = jwt;
if (exp < (new Date().getTime() + 1) / 1000) {
console.log(chalk.redBright('JWT token has expired, please reauthenticate.'));
process.exit(1);
}
// only check if older isLibraryBased
if (!isLibraryBasedCL && isLibraryBased) {
// check that there is customer_org
if (!customer_org || customer_org === '') {
console.log(chalk.red(`PegaInfinity server DSS setting ${chalk.redBright.bold(`C11nCCv2CustomerOrg`)} is NOT set.`));
console.log(chalk.red('Please update DSS setting, save and then reauthenticate.'));
process.exit(1);
}
}
};
export const checkAccessTokenExpiration = async () => {
const tokenAndStaticServer = await getC11NB2STokenAndStaticServer();
if (tokenAndStaticServer.access_token === undefined) {
console.log(chalk.redBright('Need to authenticate, missing token.\n'));
process.exit(1);
}
const jwt = jwtDecode(tokenAndStaticServer.access_token);
const { exp, customer_org, sub, app_name, app_version, operator_access } = jwt;
if (exp < (new Date().getTime() + 1) / 1000) {
console.log(chalk.redBright('Authentication token has expired, please reauthenticate.'));
process.exit(1);
}
};
export const getApplicationAndVersionFromToken = async () => {
const tokenAndStaticServer = await getC11NB2STokenAndStaticServer();
if (tokenAndStaticServer.access_token === undefined) {
// console.log(chalk.redBright("Need to authenticate, missing token.\n"));
// process.exit(1);
const app_name = '**';
const app_version = '**';
const sub = '**';
const operator_access = '**';
return { app_name, app_version, sub, operator_access };
}
const jwt = jwtDecode(tokenAndStaticServer.access_token);
const { app_name, app_version, sub, operator_access } = jwt;
return { app_name, app_version, sub, operator_access };
};
export const getLibraryBased = () => {
if (showDebug) addDebugLog('getLibraryBased', '', '');
return defaultConfigs.isLibraryBased;
};
export const getLibraryBasedCL = () => {
if (showDebug) addDebugLog('getLibraryBasedCL', '', '');
return defaultConfigs.isLibraryBasedCL;
};
export const getUseInputConfig = () => {
if (showDebug) addDebugLog('getUseInputConfig', '', '');
return defaultConfigs.useInputConfig;
};
export const setLibraryBased = async isLibraryBased => {
if (showDebug) addDebugLog('setLibraryBased', '', '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
try {
// force to throw error and not console log
await checkPathAccess(pegaConfigJsonPath, {}, true);
} catch (ex) {
// when can't find it, always be false, assume no library based.
// This is IMPORTANT for init (npx install)
return false;
}
let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
data = JSON.parse(data);
if (data[LIBRARY_BASED] != undefined) {
data[LIBRARY_BASED] = isLibraryBased;
// update file
// stringify "4", makes the json string look like JSON in the file, formatted instead of a single line
try {
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(data, null, 4), { encoding: 'utf8', flag: 'w' });
} catch (err) {
console.error(err);
}
// await forceDefaultsUpdate();
defaultConfigs.isLibraryBased = isLibraryBased;
// reset
pegaData = null;
pegaConfig = null;
}
};
export const setLibraryBasedCL = async isLibraryBasedCL => {
if (showDebug) addDebugLog('setLibraryBased', '', '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
try {
// force to throw error and not console log
await checkPathAccess(pegaConfigJsonPath, {}, true);
} catch (ex) {
// when can't find it, always be false, assume no library based.
// This is IMPORTANT for init (npx install)
return false;
}
let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
data = JSON.parse(data);
if (data[LIBRARY_BASED_CL] != undefined) {
data[LIBRARY_BASED_CL] = isLibraryBasedCL;
// if not undefined, force this as well
if (data[LIBRARY_BASED] != undefined) {
data[LIBRARY_BASED] = isLibraryBasedCL;
}
// update file
// stringify "4", makes the json string look like JSON in the file, formatted instead of a single line
try {
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(data, null, 4), { encoding: 'utf8', flag: 'w' });
} catch (err) {
console.error(err);
}
// await forceDefaultsUpdate();
defaultConfigs.isLibraryBasedCL = isLibraryBasedCL;
// force libraryBased if isLibraryBasedCL is true
defaultConfigs.isLibraryBased = isLibraryBasedCL;
// reset
pegaData = null;
pegaConfig = null;
}
};
export const getShowDebug = () => {
return defaultConfigs.showDebug;
};
export const deleteLocalComponent = async componentKey => {
if (showDebug) addDebugLog('deleteLocalComponent', `componentKey: ${componentKey}`, '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
await checkPathAccess(pegaConfigJsonPath);
let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
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 directory = join(currentDirectory, data[COMPONENTS_DIRECTORY_PATH], componentKey);
try {
fs.rmSync(directory, { recursive: true });
console.log(`${chalk.red.bold(componentKey)} is deleted from Local`);
} catch (err) {
console.log('no file');
throw new Error(`No such file ${componentKey}`);
}
};
export const getFetchAgent = serverConfig => {
const nodeUseEnvProxy = process.env.node_use_env_proxy || process.env.NODE_USE_ENV_PROXY;
const agentOptions = { rejectUnauthorized: false };
if (serverConfig.legacyTLS) {
agentOptions.secureOptions = crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT;
}
if (nodeUseEnvProxy === '1') {
return new undici.EnvHttpProxyAgent({
proxyTls: agentOptions,
requestTls: agentOptions
});
}
return new undici.Agent({ connect: agentOptions });
};
export const deleteServerComponent = async componentKey => {
if (showDebug) addDebugLog('deleteServerComponent', `componentKey: ${componentKey}`, '');
const serverConfig = await getPegaServerConfig();
const { server, user, password } = serverConfig;
const url = constructCompleteUrl(server, DELETE_COMPONENT_SERVICE_REST_ENDPOINT);
const [componentName, rulesetName, rulesetVersion] = componentKey.split('~|~');
const deleteUrl = `${url}/${componentName}/rulesetname/${rulesetName}/rulesetversion/${rulesetVersion}`;
try {
const OauthData = fs.readFileSync(TOKEN_PATH, 'utf8');
if (OauthData) {
const { access_token: accessToken, token_type: tokenType, refresh_token: refreshToken } = JSON.parse(OauthData);
fetch(deleteUrl, {
method: 'DELETE',
dispatcher: getFetchAgent(serverConfig),
headers: {
Authorization: `${tokenType} ${accessToken}`
}
})
.then(response => response.text())
.then(resp => {
let respData;
try {
respData = JSON.parse(resp);
} catch (e) {
console.log(chalk.bold.redBright(`Failure : ${resp}`));
process.exit(1);
}
if (respData.status == 200) {
console.log(chalk.bold.green(`Success : ${respData.message}`));
} else {
throw new Error(`${respData.message}`);
}
})
.catch(e => Promise.reject(`${chalk.bold.red(e)}`));
}
} catch (error) {
console.log(`\n${chalk.bold.red(error)}`);
}
};
export const copyFileToShared = async (fileName, fileContents) => {
if (showDebug) addDebugLog('copyFileToShared', `fileName: ${fileName}`, '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
await checkPathAccess(pegaConfigJsonPath);
let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
data = JSON.parse(data);
if (!data[COMPONENTS_DIRECTORY_PATH]) {
console.error(`${chalk.red.bold('ERROR')} Could not find components directory path in config.json`);
process.exit(1);
}
const directory = join(currentDirectory, data[COMPONENTS_DIRECTORY_PATH]);
const sharedDirectory = join(directory, SHARED_DIRECTORY);
// if shared doesn't exist, create it
if (!fs.existsSync(sharedDirectory)) {
fs.mkdirSync(sharedDirectory, { recursive: true });
}
const filePath = join(sharedDirectory, fileName);
if (!fs.existsSync(filePath)) {
fs.writeFileSync(filePath, fileContents);
}
};
export const getComponents = async (overrideDirectory = null) => {
if (showDebug) addDebugLog('getComponents', '', '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
await checkPathAccess(pegaConfigJsonPath);
let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
data = JSON.parse(data);
if (!data[COMPONENTS_DIRECTORY_PATH]) {
console.error(`${chalk.red.bold('ERROR')} Could not find components directory path in config.json`);
process.exit(1);
}
const directory = overrideDirectory || join(currentDirectory, data[COMPONENTS_DIRECTORY_PATH]);
return fs
.readdirSync(directory, { withFileTypes: true })
.filter(dirent => dirent.isDirectory() && dirent.name !== SHARED_DIRECTORY)
.map(dirent => dirent.name);
};
export const getTopLevelConfigFiles = async directory => {
if (showDebug) addDebugLog('getTopLevelConfigFiles', `directory: ${directory}`, '');
if (fs.existsSync(directory)) {
return fs
.readdirSync(directory, { withFileTypes: true })
.filter(dirent => !dirent.isDirectory())
.map(dirent => dirent.name);
} else {
return [];
}
};
export const removeTopLevelConfigFiles = async directory => {
if (showDebug) addDebugLog('removeTopLevelConfigFiles', `directory: ${directory}`, '');
const configFiles = await getTopLevelConfigFiles(directory);
if (configFiles && configFiles.length > 0) {
for (const configF of configFiles) {
// don't remove these files, otherwise, remove it
if (
configF !== 'package-lock.json' &&
configF !== 'package.json' &&
configF !== 'tasks.config.json' &&
configF !== '.gitignore' &&
configF !== '.npmrc' &&
configF !== '.prettierignore'
) {
fs.rmSync(join(directory, configF), { recursive: true, force: true, maxRetries: 2 });
}
}
}
};
export const restoreTopLevelConfigFiles = async directory => {
if (showDebug) addDebugLog('restoreTopLevelConfigFiles', `directory: ${directory}`, '');
const currentDirectory = process.cwd();
const tempDirectory = join(currentDirectory, TEMP_PATH);
const configFiles = await getTopLevelConfigFiles(tempDirectory);
// we force to get the tasks.config.json and store it locally
// when we call updateComponentTaskConfig we will use this stored version to bring back server-config (except ruleset/version)
// and component objects
await getPegaConfig(true);
if (configFiles && configFiles.length > 0) {
for (const configF of configFiles) {
// don't want to restore package, package-lock or an archive file
if (configF !== 'package-lock.json' && configF !== 'package.json' && configF.indexOf('.zip') < 0) {
fs.copyFileSync(join(tempDirectory, configF), join(directory, configF));
}
}
}
};
export const getTemplateConfigFiles = async () => {
if (showDebug) addDebugLog('getTemplateConfigFiles', ``, '');
const currentDirectory = process.cwd();
const initDir = join(currentDirectory, 'node_modules', '@pega', 'custom-dx-components', 'src', 'tasks', 'init');
const templateDir = join(initDir, 'template');
if (fs.existsSync(templateDir)) {
return fs
.readdirSync(templateDir, { withFileTypes: true })
.filter(dirent => !dirent.isDirectory())
.map(dirent => dirent.name);
} else {
return [];
}
};
export const restoreTopLevelConfigFilesFromTemplate = async (clearDep = true) => {
if (showDebug) addDebugLog('restoreTopLevelConfigFilesFromTemplate', ``, '');
// we can't loose devDep that is part of install, so go get the template mustache and push
// those in, replacing any changes there, but allowing additional, an keeping it updated
// so won't loose new function if an old archive
const currentDirectory = process.cwd();
const initDir = join(currentDirectory, 'node_modules', '@pega', 'custom-dx-components', 'src', 'tasks', 'init');
const templateDir = join(initDir, 'template');
const packageTemplateJsonPath = path.join(templateDir, 'package.json.mustache');
const currentPackagePath = join(currentDirectory, PACKAGE_JSON_FILENAME);
let currentPackageData;
// reset
haveDependencyDifference = false;
try {
currentPackageData = fs.readFileSync(currentPackagePath);
} catch (ex) {
console.log($chalk.red(`\nUnable to retrieve current package.json.`));
process.exit(1);
}
let cData = JSON.parse(currentPackageData);
let retrievedTemplateData;
try {
retrievedTemplateData = fs.readFileSync(packageTemplateJsonPath);
} catch (ex) {
console.log($chalk.red(`\nUnable to retrieve package.json.mustache from code.`));
process.exit(1);
}
// copy template dependencies and devDependencies
const tData = JSON.parse(retrievedTemplateData);
// check to see if any dependency changes
const sDep = JSON.stringify(tData.dependencies);
const sDevDep = JSON.stringify(tData.devDependencies);
const sCurDep = JSON.stringify(cData.dependencies);
const sCurDevDep = JSON.stringify(cData.devDependencies);
// any changes, update haveDependencyDifference variable
if (sDep != sCurDep) {
haveDependencyDifference = true;
} else if (sDevDep != sCurDevDep) {
haveDependencyDifference = true;
}
await removeTopLevelConfigFiles(currentDirectory);
// clear out
if (clearDep) {
cData.dependencies = {};
cData.devDependencies = {};
}
const tDep = tData.dependencies;
for (const [key, value] of Object.entries(tDep)) {
cData.dependencies[key] = value;
}
const tDevDep = tData.devDependencies;
for (const [key, value] of Object.entries(tDevDep)) {
cData.devDependencies[key] = value;
}
// update current package json file
fs.writeFileSync(currentPackagePath, JSON.stringify(cData, null, 4), { encoding: 'utf8', flag: 'w' });
// restore from template
const templateFiles = await getTemplateConfigFiles();
if (templateFiles && templateFiles.length > 0) {
for (const tFile of templateFiles) {
if (tFile !== 'package.json.mustache' && tFile !== 'templateNPMRC.txt' && tFile !== 'tasks.config.json') {
fs.copyFileSync(join(templateDir, tFile), join(currentDirectory, tFile));
}
}
}
};
export const getSubComponents = async (directory, type) => {
if (showDebug) addDebugLog('getDirectoryFiles', `directory: ${directory}, type: ${type}`, '');
const subDirectory = join(directory, type);
return fs
.readdirSync(subDirectory, { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name);
};
export const getDirectoryFiles = async directory => {
if (showDebug) addDebugLog('getDirectoryFiles', `directory: ${directory}`, '');
return fs
.readdirSync(directory, { withFileTypes: true })
.filter(dirent => !dirent.isDirectory())
.map(dirent => dirent.name);
};
export const getComponentsObj = async () => {
if (showDebug) addDebugLog('getComponentsObj', '', '+');
const compList = [];
// const componentList = await getDirectoryFiles(directory);
const componentList = await getComponents();
if (componentList.length > 0) {
compList.push(
...componentList.map(name => {
const container = {};
container.name = name;
container.value = name;
if (showDebug) addDebugLog('getComponentsObj', `container: ${JSON.stringify(container)}`, '');
return container;
})
);
}
if (showDebug) addDebugLog('getComponentsObj', 'END', '-');
return compList;
};
export const getPegaConfig = async (force = false) => {
if (showDebug) {
addDebugLog('getPegaConfig', '', '+');
}
if (!pegaData || force) {
if (showDebug) {
addDebugLog('getPegaConfig', 'retrieveData', '');
}
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
await checkPathAccess(pegaConfigJsonPath);
sPegaData = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
pegaData = JSON.parse(sPegaData);
}
if (showDebug) {
addDebugLog('getPegaConfig', `pegaData: ${sPegaData}`, '');
}
if (showDebug) {
addDebugLog('getPegaConfig', 'END', '-');
}
return pegaData;
};
export const getPegaServerConfig = async (force = false) => {
if (showDebug) addDebugLog('getPegaServerConfig', '', '+');
if (!pegaConfig || force) {
pegaConfig = await getPegaConfig(force);
if (getServerType() === 'launchpad') {
// need to append isolation id for now
let OAuthData;
try {
OAuthData = fs.readFileSync(TOKEN_PATH, 'utf8');
} catch (ex) {
return {};
}
if (OAuthData) {
const oOAuthData = JSON.parse(OAuthData);
if (oOAuthData['isolation-ids']) {
const isolationId = oOAuthData['isolation-ids'].write;
pegaConfig['server-config'].isolationId = isolationId[0];
}
}
}
sPegaServerConfig = JSON.stringify(pegaConfig['server-config']);
}
if (showDebug) addDebugLog('getPegaServerConfig', `server config:${sPegaServerConfig}`, '');
if (showDebug) addDebugLog('getPegaServerConfig', 'END', '-');
return pegaConfig['server-config'];
};
// contains all the config, task config, etc. created upon start
export const getConfigDefaults = () => {
if (showDebug) addDebugLog('getConfigDefaults', `defaults: ${JSON.stringify(defaultConfigs)}`, '');
return defaultConfigs;
};
export const forceDefaultsUpdate = async () => {
defaultConfigs = await setUpDefaults();
};
export const updateServerConfigRuleSetAndVersion = async (rulesetName, rulesetVersion) => {
if (showDebug) addDebugLog('updateServerConfigRuleSetAndVersion', `rulesetName: ${rulesetName}, rulesetVersion: ${rulesetVersion}`, '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
let configData = await getPegaConfig(true);
let serverConfig = configData['server-config'];
serverConfig.rulesetName = rulesetName;
serverConfig.rulesetVersion = rulesetVersion;
// update file
// stringify "4", makes the json string look like JSON in the file, formatted instead of a single line
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(configData, null, 4), { encoding: 'utf8', flag: 'w' });
};
export const updateServerConfigArchiveRuleSetAndVersion = async (rulesetName, rulesetVersion) => {
if (showDebug) addDebugLog('updateServerConfigArchiveRuleSetAndVersion', `rulesetName: ${rulesetName}, rulesetVersion: ${rulesetVersion}`, '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
let configData = await getPegaConfig(true);
let serverConfig = configData['server-config'];
serverConfig.archiveRulesetName = rulesetName;
serverConfig.archiveRulesetVersion = rulesetVersion;
// update file
// stringify "4", makes the json string look like JSON in the file, formatted instead of a single line
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(configData, null, 4), { encoding: 'utf8', flag: 'w' });
};
export const updateComponentDefaultLibrary = async library => {
if (showDebug) addDebugLog('updateComponentDefaultLibrary', `library: ${library}`, '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
await checkPathAccess(pegaConfigJsonPath);
let config = await getPegaConfig(true);
let componentsDefault = config.component;
componentsDefault.library = library;
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(config, null, 4), { encoding: 'utf8', flag: 'w' });
};
export const updateComponentDefaultVersion = async version => {
if (showDebug) addDebugLog('updateComponentDefaultVersion', `version: ${version}`, '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
await checkPathAccess(pegaConfigJsonPath);
let config = await getPegaConfig(true);
let componentsDefault = config.component;
componentsDefault.version = version;
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(config, null, 4), { encoding: 'utf8', flag: 'w' });
};
export const getConfigDevBuild = async () => {
if (showDebug) addDebugLog('getConfigDevBuild', '', '');
// const serverConfig = await getPegaServerConfig();
if (getLibraryBasedCL()) {
return false;
}
// return serverConfig.devBuild;
return defaultConfigs.devBuild;
};
export const setConfigDevBuild = async devBuild => {
if (showDebug) addDebugLog('setConfigDevBuild', `devBuild: ${devBuild}`, '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
let configData = await getPegaConfig(true);
let serverConfig = configData['server-config'];
serverConfig.devBuild = devBuild;
// update file
// stringify "4", makes the json string look like JSON in the file, formatted instead of a single line
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(configData, null, 4), { encoding: 'utf8', flag: 'w' });
};
export const getConfigDevServerPort = async () => {
if (showDebug) addDebugLog('getConfigDevServerPort', '', '');
// const serverConfig = await getPegaServerConfig();
return defaultConfigs.devServerPort;
};
export const setConfigImportRelativePath = async importRelativePath => {
if (showDebug) addDebugLog('setConfigImportRelativePath', `importRelativePath: ${importRelativePath}`, '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
let configData = await getPegaConfig(true);
configData[IMPORT_RELATIVE_PATH] = importRelativePath;
// update file
// stringify "4", makes the json string look like JSON in the file, formatted instead of a single line
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(configData, null, 4), { encoding: 'utf8', flag: 'w' });
};
export const setConfigExportRelativePath = async exportRelativePath => {
if (showDebug) addDebugLog('setConfigExportRelativePath', `exportRelativePath: ${exportRelativePath}`, '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
let configData = await getPegaConfig(true);
configData[EXPORT_RELATIVE_PATH] = exportRelativePath;
// update file
// stringify "4", makes the json string look like JSON in the file, formatted instead of a single line
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(configData, null, 4), { encoding: 'utf8', flag: 'w' });
};
export const updateDefaultOrganization = async organization => {
if (showDebug) addDebugLog('updateDefaultOrganization', `organization: ${organization}`, '');
let packageData = JSON.parse(fs.readFileSync(path.resolve('package.json'), 'utf-8'));
packageData.organization = organization;
fs.writeFileSync(path.resolve('package.json'), JSON.stringify(packageData, null, 4), { encoding: 'utf8', flag: 'w' });
};
export const updateConfigVersion = async (componentKey, buildVersion, currentOrgLib) => {
if (showDebug)
addDebugLog('updateConfigVersion', `componentKey: ${componentKey}, buildVersion: ${buildVersion}, currentOrgLib: ${currentOrgLib}`, '');
const componentDirectory = await getComponentDirectoryPath(componentKey);
const configFileName = 'config.json';
const configFile = path.join(componentDirectory, configFileName);
let configData;
try {
configData = fs.readFileSync(path.resolve(configFile), 'utf8');
} catch (err) {
// for now, if now file just end
console.log(`${chalk.bold.yellow(`Config file not available for: ${componentKey}`)}`);
return;
}
const currentDate = new Date(Date.now());
const dateStamp = currentDate.toDateString();
const aboutData = await getAboutData(currentOrgLib, buildVersion, dateStamp);
let data;
try {
data = JSON.parse(configData);
// find "About" and create or update
const properties = data.properties;
if (properties) {
let foundProp = null;
// check to see if PegaAboutData exists. If customer decides to put
// data under PegaAboutData, we won't change the order
// otherwise, will put at bottom
for (let i in properties) {
if (properties[i].name && properties[i].name === 'PegaAboutData') {
foundProp = properties[i];
break;
}
}
if (addAboutData) {
if (foundProp) {
foundProp.label = aboutData;
} else {
// don't have "About"
const aboutLabelJSON = {
format: 'LABEL',
label: 'About',
name: 'PegaAboutLabel',
variant: 'h3'
};
const aboutDataJSON = {
format: 'LABEL',
label: aboutData,
name: 'PegaAboutData',
variant: 'primary'
};
properties.push(aboutLabelJSON);
properties.push(aboutDataJSON);
}
}
}
} catch (er) {
throw new Error(`Invalid schema json in config.json: ${er}`);
}
data.version = buildVersion;
if (addAboutData) {
data.buildDate = currentDate;
await applyPegaData(data);
}
// write back file
fs.writeFileSync(configFile, JSON.stringify(data, null, 4), { encoding: 'utf8', flag: 'w' });
};
export const getServerType = () => {
if (showDebug) addDebugLog('getServerType', '', '+');
// const defaultPegaServerConfig = await getPegaServerConfig();
// if (showDebug) addDebugLog("getServerType", "serverType:" + defaultPegaServerConfig.serverType, "");
if (showDebug) addDebugLog('getServerType', 'END', '-');
// return defaultPegaServerConfig.serverType;
return defaultConfigs.serverType;
};
export const setServerType = async serverType => {
if (showDebug) addDebugLog('setServerType', `serverType: ${serverType}`, '');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
let configData = await getPegaConfig(true);
let serverConfig = configData['server-config'];
serverConfig.serverType = serverType;
// update file
// stringify "4", makes the json string look like JSON in the file, formatted instead of a single line
fs.writeFileSync(pegaConfigJsonPath, JSON.stringify(configData, null, 4), { encoding: 'utf8', flag: 'w' });
// reset
pegaData = null;
pegaConfig = null;
await forceDefaultsUpdate();
};
export const getSrcDirectoryPath = async () => {
const currentDirectory = process.cwd();
return join(currentDirectory, 'src');
};
export const getComponentDirectoryPath = async (componentKey, overrideDir = null) => {
if (showDebug) addDebugLog('getComponentDirectoryPath', '', '+');
const currentDirectory = process.cwd();
const pegaConfigJsonPath = join(currentDirectory, TASKS_CONFIG_JSON_FILENAME);
await checkPathAccess(pegaConfigJsonPath);
let data = fs.readFileSync(pegaConfigJsonPath, { encoding: 'utf8' });
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);
}
if (showDebug) addDebugLog('getComponentDirectoryPath', `path: ${join(currentDirectory, data[COMPONENTS_DIRECTORY_PATH], componentKey)}`, '');
if (showDebug) addDebugLog('getComponentDirectoryPath', 'END', '-');
return overrideDir ? join(overrideDir, componentKey) : join(currentDirectory, data[COMPONENTS_DIRECTORY_PATH], componentKey);
};
export const compileMustacheTemplate = (file, data) => {
if (showDebug) addDebugLog('compileMustacheTemplate', `file: ${file}`, '');
const content = fs.readFileSync(file, 'utf8');
return mustache.render(content, data);
};
export const isPascalCase = string => {
return string === pascalCase(string);
};
export const convertIntoPascalCase = string => {
return pascalCase(string);
};
export const constructCompleteUrl = (baseServer, endPoint) => {
if (showDebug)
addDebugLog('constructCompleteUrl', `url: ${baseServer.endsWith('/')}` ? `${baseServer}${endPoint}` : `${baseServer}/${endPoint}`, '');
return baseServer.endsWith('/') ? `${baseServer}${endPoint}` : `${baseServer}/${endPoint}`;
};
export const sanitize = str => {
/* Allow only numbers and case insensitive alphabets */
str = str.replace(/[^a-zA-Z0-9 ]/g, '');
/* spaces will be replaced by - */
str = str.replace(/\s+/g, '-');
return str;
};
export const validateSemver = str => {
/* basic semver version validation - 0.0.1-dev */
const regex = /^[0-9]\d*\.\d+\.\d+(?:-[a-zA-Z0-9]+)?$/g;
return regex.test(str);
};
export const validateRulesetVersion = str => {
/* Ruleset version range - 01-99 */
if (str.indexOf('00') !== -1) {
return false;
}
/* basic ruleset version validation - 01-01-01 */
const regex = /^\d\d-\d\d-\d\d$/g;
return regex.test(str);
};
export const standardizeStr = (str, length) => {
return str.padEnd(length);
};
export const showVersion = async () => {
// get package version, so can display at start
// const require = createRequire(import.meta.url);
const require = createRequire(currentPath.default);
const serverType = getServerType();
const sLibMode = getLibraryBased() ? '(library mode)' : serverType === 'launchpad' ? '(LaunchPad)' : '';
const pData = require('@pega/custom-dx-components/package.json');
const serverConfig = await getPegaServerConfig();
console.log(chalk.green(`DX Component Builder${sLibMode} v${pData.version}`));
showDebug = getShowDebug();
if (getLibraryBased() && serverType === 'launchpad') {
console.log(`\nLaunchpad commands only supported for ${chalk.bold.green('non library mode')} components.\n`);
process.exit();
}
// do a check of node version, it should be 24 or greater
const arNodeVersion = process.versions.node.split('.');
const nodeMajorVersion = parseInt(arNodeVersion[0]);
const nodeMinorVersion = parseInt(arNodeVersion[1]);
const nodePatchVersion = parseInt(arNodeVersion[2]);
if (nodeMajorVersion < 24) {
console.log(chalk.redBright(`DX Component Builder - requires node v24.4.1 or greater, current version: ${process.version}`));
process.exit(1);
} else if (nodeMajorVersion == 24 && nodeMinorVersion < 4) {
console.log(chalk.redBright(`DX Component Builder - requires node v24.4.1 or greater, current version: ${process.version}`));
process.exit(1);
} else if (nodeMajorVersion == 24 && nodeMinorVersion == 4 && nodePatchVersion < 1) {
console.log(chalk.redBright(`DX Component Builder - requires node v24.4.1 or greater, current version: ${process.version}`));
process.exit(1);
}
await checkForBranch(serverConfig.rulesetName);
};
export const checkForBranch = async rulesetName => {
if (getServerType() === 'infinity') {
if (rulesetName === '') {
const serverConfig = await getPegaServerConfig();
rulesetName = serverConfig.rulesetName;
}
if (rulesetName.toLowerCase().indexOf('_branch') >= 0) {
console.log(chalk.redBright(`Ruleset ${chalk.bold(`${rulesetName}`)} is a branch ruleset.\nPublishing to branch rulesets are not supported.`));
process.exit(1);
}
}
};
export const getOOTBComponents = async () => {
if (showDebug) addDebugLog('getOOTBComponents', '', '');
return new Promise(resolve => {
fs.readFile(OOTB_COMPONENTS, 'utf-8', async (error, ootbComponentsData) => {
if (error) {
try {
const serverConfig = await getPegaServerConfig();
const { server } = serverConfig;
const url = constructCompleteUrl(server, OOTB_COMPONENT_SERVICE_REST_ENDPOINT);
const OauthData = fs.readFileSync(TOKEN_PATH, 'utf8');
if (OauthData) {
const { access_token: accessToken, token_type: tokenType } = JSON.parse(OauthData);
fetch(url, {
method: 'GET',
dispatcher: getFetchAgent(serverConfig),
headers: {
Authorization: `${tokenType} ${accessToken}`
}
})
.then(response => response.text())
.then(data => {
if (data.charAt() === '[') {
data = data.slice(1, -1);
data = data.replace(/\s/g, '');
fs.writeFile(OOTB_COMPONENTS, data, err => {
if (err) {
console.error(err);
}
resolve(data.split(','));
});
} else {
data = JSON.parse(data);
if (data && data.errors) {
const errMessages = data.errors;
errMessages.forEach(msgArr => {
throw new Error(`Failed with error - ${JSON.stringify(msgArr.message)}`);
});
}
}
})
.catch(e => Promise.reject(`${chalk.bold.red(e)}`));
}
} catch (e) {
throw new Error('Error occurred in validation', e);
}
} else {
resolve(ootbComponentsData.split(','));
}
});
});
};
export const deleteInfinityServerComponent = async componentKey => {
if (showDebug) addDebugLog('deleteInfinityServerComponent', `componentKey: ${componentKey}`, '');
const serverConfig = await getPegaServerConfig();
const { server } = serverConfig;
const url = constructCompleteUrl(server, DELETE_COMPONENT_SERVICE_REST_ENDPOINT);
const [componentName, rulesetName, rulesetVersion] = componentKey.split('~|~');
const deleteUrl = `${url}/${componentName}/rulesetname/${rulesetName}/rulesetversion/${rulesetVersion}`;
try {
const OauthData = fs.readFileSync(TOKEN_PATH, 'utf8');
let status = 500;
if (OauthData) {
const { access_token: accessToken, token_type: tokenType } = JSON.parse(OauthData);
const response = await fetch(deleteUrl, {
method: 'DELETE',
dispatcher: getFetchAgent(serverConfig),
headers: {
Authorization: `${tokenType} ${accessToken}`
}
});
status = response.status;
if (!response.ok) {
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 === 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');
} else if (response.status === 403) {
throw new Error('Error forbidden: User does not have privileges to Publish.');
}
}
try {
const respData = await response.json();
console.log(chalk.bold.green(`Success : ${respData.message}`));
if (status === 500) {
status = 999;
throw new Error(respData.message);
}
} catch (err) {
if (status === 500) {
throw new Error(`Error occurred in authentication. Please regenerate using authenticate`);
} else if (status === 999) {
throw new Error(err);
}
}
}
} catch (error) {
throw new Error(error);
}
};
export const deleteInfinityServerComponentLibrary = async (libraryName, rulesetName, rulesetVersion) => {
if (showDebug)
addDebugLog(
'deleteInfinityServerComponentLibrary',
`componentKey: ${componentKey}, rulesetName: ${rulesetName}, rulesetVersion: ${rulesetVersion}`,
''
);
const serverConfig = await getPegaServerConfig();
const { server } = serverConfig;
const url = constructCompleteUrl(server, DELETE_COMPONENT_LIBRARY_SERVICE_REST_ENDPOINT);
const deleteUrl = `${url}/${libraryName}/rulesetname/${rulesetName}/rulesetversion/${rulesetVersion}`;
try {
const OauthData = fs.readFileSync(TOKEN_PATH, 'utf8');
let status = 500;
if (OauthData) {
const { access_token: accessToken, token_type: tokenType } = JSON.parse(OauthData);
let spinner;
console.log();
spinner = ora(chalk.green.bold('Deleting component library...')).start();
const response = await fetch(deleteUrl, {
method: 'DELETE',
dispatcher: getFetchAgent(serverConfig),
headers: {
Authorization: `${tokenType} ${accessToken}`
}
});
spinner.stop();
console.log();
status = response.status;
if (!response.ok) {
if (status === 401) {
throw new Error('Error occurred in authentication. Please regenerate using authenticate');
// console.log(accessTokenUri, refreshToken);
/* TODO - Handle re