@pega/constellation-dx-components-build-utils
Version:
This tool uses a 'v3' approach to group components in a library, create a component map, employ webpack, and load the library like Pega-generated components, constellation app-static.
333 lines (312 loc) • 8.56 kB
JavaScript
const path = require('path');
const https = require('https');
const chalk = require('chalk');
const fs = require('fs');
const arg = require('arg');
const semver = require('semver');
const archive = require('archiver');
const CONSTANTS = require('./constant');
/*
wrapper for importing which might have a chance of error
catch error incase of modulepath not found.
*/
exports.getRequiredFunction = (modulePath) => {
try {
return require(modulePath);
} catch (err) {
console.log(
chalk.red(
`getRequiredFunction(): The file: ${modulePath} could not be loaded`
)
);
return false;
}
};
/*
returns the build foldername which should be libname/libversion
the same folder structure is supported by component publish in v2
uses package.json to get the packagename and version and appends
*/
exports.getBuildFolderName = (libraryName, libraryVersion) => {
let packageDetails = {};
if(libraryName && libraryVersion){
packageDetails = {"name" : libraryName, "version" : libraryVersion };
} else{
packageDetails = this.getRequiredFunction(
path.join(CONSTANTS.CURRENT_WORKING_DIR, 'package.json')
);
}
const buildFolderFullPath = path.join(
packageDetails.name,
packageDetails.version
);
const buildFolderName = packageDetails.name;
return {
buildFolderFullPath,
buildFolderName,
packageVersion: packageDetails.version,
};
};
exports.getAppstaticEnd = (appStaticSVCUrl) => {
const appStaticURL = this.getAppStaticServerUrl(appStaticSVCUrl)
? this.getAppStaticServerUrl(appStaticSVCUrl)
: '{APP_URL}';
return appStaticURL && appStaticURL.endsWith('/')
? appStaticURL + CONSTANTS.ENDPOINTURL
: appStaticURL + '/' + CONSTANTS.ENDPOINTURL;
};
/**/
exports.getHttpsAgent = () => {
const agentOptions = { rejectUnauthorized: false };
return new https.Agent(agentOptions);
};
/**
*
* @param {none}
* @returns headers
*/
exports.getHeaders = (tokenParams) => {
const bs2Token = this.getB2SToken(tokenParams);
if (bs2Token === '') {
console.log(
chalk.red('B2STOKEN, Auth token is empty.. please fix and try again')
);
return false;
}
const token = bs2Token.startsWith('Bearer ')
? bs2Token.substring(7)
: bs2Token;
return {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
};
};
/*
Before zipping remove any previous versions of library i.e package.version should be the only folder
*/
exports.cleanUpBuildFolder = (
parentFolder,
buildFolderName,
packageVersion
) => {
try {
const removedVersions = fs
.readdirSync(path.join(parentFolder, buildFolderName))
.filter((version) => version === packageVersion)
.map((version) => {
const versionPath = path.join(parentFolder, buildFolderName, version);
if (fs.statSync(versionPath).isDirectory()) {
fs.rmSync(versionPath, { recursive: true });
return buildFolderName + '/' + version;
}
})
.filter(Boolean); // Filter out undefined values
console.log(
chalk.yellow(
`Removed following output version : ${removedVersions.join(', ')}`
)
);
} catch (ex) {
// console.log(ex);
}
};
/*
String Utils
*/
exports.formatEndPointURL = (...params) => {
// Remove any trailing slashes from the first parameter
let result = params[0] && params[0].replace(/\/+$/, '');
// Loop through the remaining parameters starting from the second one
for (let i = 1; i < params.length; i++) {
// Check if the parameter is empty before appending
if (params[i]) {
// Append a slash and the current parameter
result += '/' + params[i].replace(/^\/+/, ''); // Remove any leading slashes
}
}
return result;
};
/*
Questions utils for inquirer prompts
*/
exports.getQuestionsListDynamically = (name, message, list) => {
return [
{
name,
message,
type: 'list',
choices: list,
},
];
};
/*
Return Org ID for source map
*/
exports.getPayloadFromTkn = (tkn, keyToPayload) => {
let valueToPayload = '';
if (tkn && keyToPayload) {
const base64Url = tkn.split('.')[1];
if (base64Url) {
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(
Buffer.from(base64, 'base64')
.toString()
.split('')
.map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
})
.join('')
);
try {
valueToPayload = JSON.parse(jsonPayload)[keyToPayload];
} catch (ex) {
console.error(`tkn parse failed : ${jsonPayload}`);
return '';
}
}
}
return valueToPayload;
};
exports.getVersionFromListOutput = (listOutput, packageNamePattern) => {
const regex = new RegExp(`${packageNamePattern}[^\\s]+@[^\\s]+`, 'g');
const matches = listOutput.match(regex);
const versions = {};
if (matches) {
matches.forEach((match) => {
const lastIndex = match.lastIndexOf('@');
const packageName = match.substring(0, lastIndex);
const version = match.substring(lastIndex + 1);
versions[packageName] = version;
});
}
return versions;
};
exports.compareObjects = (smallObj, bigObj) => {
const mismatches = {};
for (const key in smallObj) {
if (bigObj.hasOwnProperty(key)) {
if (
!(
semver.major(smallObj[key]) === semver.major(bigObj[key]) &&
semver.minor(smallObj[key]) === semver.minor(bigObj[key])
)
) {
mismatches[key] = {
'Your library Package.json version': smallObj[key],
'Package version used in targeted Constellation runtime portal':
bigObj[key],
};
}
}
}
return mismatches;
};
exports.getB2SToken = (tokenParams) => {
if(tokenParams){
return tokenParams;
}
const args = arg(
{
'--token-path': String,
},
{
argv: process.argv.slice(2),
}
);
if (args['--token-path']) {
try {
const tokenPath = path.join(path.resolve(), args['--token-path']);
const OauthData = fs.readFileSync(tokenPath, 'utf8');
if (OauthData) {
const { C11NB2S: C11NB2S } = JSON.parse(OauthData);
return C11NB2S;
}
} catch (ex) {
console.log(
'Fallback to predefined token path; unable to read from specified --token-path argument : ',
args['--token-path']
);
}
}
if (CONSTANTS.TOKEN_PATH) {
try {
const OauthData = fs.readFileSync(
path.join(CONSTANTS.CURRENT_WORKING_DIR, CONSTANTS.TOKEN_PATH),
'utf8'
);
if (OauthData) {
const { C11NB2S: C11NB2S } = JSON.parse(OauthData);
return C11NB2S;
}
} catch (ex) {
console.log(
'Fallback to constant value B2STOKEN; unable to read token from default path.'
);
}
}
return CONSTANTS.B2STOKEN;
};
exports.getAppStaticServerUrl = (appStaticSVCUrl) => {
if(appStaticSVCUrl){
return appStaticSVCUrl;
}
const args = arg(
{
'--token-path': String,
},
{
argv: process.argv.slice(2),
}
);
if (args['--token-path']) {
try {
const tokenPath = path.join(path.resolve(), args['--token-path']);
const OauthData = fs.readFileSync(tokenPath, 'utf8');
if (OauthData) {
const { appStaticContentServer: appStaticContentServer } =
JSON.parse(OauthData);
return appStaticContentServer;
}
} catch (ex) {
console.log(
'Fallback to constant value APPSTATICURL; unable to read from specified --token-path argument : ',
args['--token-path']
);
}
}
return CONSTANTS.APPSTATICURL;
};
/*
zip content after building from build-library
@param: folderName
*/
exports.zipContent = async (folderName, srcToZip) => {
const promise = new Promise((resolve, reject) => {
try {
const op = fs.createWriteStream(`${folderName}.zip`);
const arch = archive('zip', {
zlib: { level: 9 },
});
op.on('close', () => {
resolve({
status: 'success',
});
});
arch.on('error', (err) => {
throw err;
});
arch.pipe(op);
arch.directory(srcToZip);
arch.finalize();
} catch (error) {
console.log(
chalk.red(`helper(): error while zipping content:: ${error}`)
);
reject({
status: 'failure',
error,
});
}
});
return promise;
};