apim-policy-utils
Version:
An XML file scripts maniputaling and debugging tool targeting to help working with Azure APIM Policy files in xml format.
190 lines • 7.77 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.combineScript = void 0;
const fs = __importStar(require("fs"));
const path_1 = __importDefault(require("path"));
const constants_1 = require("./constants");
async function combineScript(directoryPath, destinationPath) {
const filenames = await getFilenamesInDirectory(directoryPath);
// Compute the xml filename for storing the result
const dirArray = directoryPath.split('/');
const xmlFilename = `${dirArray[dirArray.length - 1]}.xml`;
// Read xmlContent from the generated xmlfile
let xmlFileContent = fs.readFileSync(`${directoryPath}/replaced.xml`, 'utf8');
// Get code outside of block-xxx.csx file and inline-xxx.csx file
filenames.forEach(filename => {
if ((filename.startsWith('inline') || filename.startsWith('block')) && filename.endsWith('.csx')) {
let codeSnippet = getCodeInMethod(`${directoryPath}/${filename}`, 'ExtractedScript');
codeSnippet = refineCode(filename, codeSnippet);
const xmlPlaceholder = filename.slice(0, -4);
xmlFileContent = replaceAll(xmlFileContent, xmlPlaceholder, codeSnippet);
}
// Write the combined XML to a file
if (!destinationPath) {
fs.writeFileSync(`${directoryPath}/${xmlFilename}`, xmlFileContent);
}
else {
updateFileInDirectory(destinationPath, xmlFilename, xmlFileContent)
.then(() => {
console.log('File update complete.');
})
.catch((error) => {
console.error('An error occurred while updating the file:', error);
});
}
});
}
exports.combineScript = combineScript;
function refineCode(file, codeSnippet) {
var _a;
if (codeSnippet === null) {
return '';
}
const inlinePrefix = "return ";
if (file.startsWith('inline')) {
codeSnippet = codeSnippet.trim();
if (codeSnippet.startsWith(inlinePrefix)) {
codeSnippet = codeSnippet.substring(inlinePrefix.length).trim(); // remove "return " prefix
return codeSnippet.slice(0, -1); // remove ";" suffix
}
}
if (file.startsWith('block')) {
const lines = codeSnippet.split('\n').map(line => line);
const nonEmptyLines = lines.filter(line => line !== '');
const indentation = (_a = nonEmptyLines[0].match(/^\s*/)) === null || _a === void 0 ? void 0 : _a[0];
const formattedContent = nonEmptyLines.map((line, index) => {
if (index === 0 || index === nonEmptyLines.length - 1) {
return line;
}
return `${indentation}${line}`;
}).join('\n');
return `${formattedContent}`;
}
return codeSnippet;
}
function getFilenamesInDirectory(directoryPath) {
return new Promise((resolve, reject) => {
fs.readdir(directoryPath, (err, files) => {
if (err) {
reject(err);
}
else {
const filenames = [];
files.forEach((file) => {
filenames.push(file);
});
resolve(filenames);
}
});
});
}
function getCodeInMethod(csxFilePath, methodName) {
try {
// Read the contents of the file at the given path
const fileContents = fs.readFileSync(csxFilePath, 'utf8');
// Find the starting index of the desired method
const startRegex = new RegExp(`(?<=\\b(?:public|private|internal)?\\s+(?:async\\s+)?(?:static\\s+)?(?:readonly\\s+)?(?:partial\\s+)?(?:unsafe\\s+)?(?:virtual\\s+)?(?:override\\s+)?\\w+\\s+${methodName}\\s*\\()`);
const startIndex = fileContents.search(startRegex);
if (startIndex === -1) {
console.error(`Method '${methodName}' not found in file at path '${csxFilePath}'`);
return null;
}
// Find the ending index of the desired method
let openBraces = 0;
let actualStartIndex = startIndex;
let endIndex = startIndex;
for (let i = startIndex; i < fileContents.length; i++) {
if (fileContents[i] === '{') {
openBraces++;
if (openBraces === 1) {
actualStartIndex = i;
}
}
else if (fileContents[i] === '}') {
openBraces--;
if (openBraces === 0) {
endIndex = i;
break;
}
}
}
// The code within the method
let codeInMethod = fileContents.slice(actualStartIndex, endIndex + 1);
codeInMethod = removeSurroundingChars(codeInMethod);
// Remove everything before the generated sepatators
codeInMethod = removeCodeAboveSeparator(codeInMethod);
codeInMethod = convertNamedValue(codeInMethod);
return codeInMethod;
}
catch (error) {
console.error(`Error reading file at path '${csxFilePath}': ${error.message}`);
return null;
}
}
function replaceAll(xml, toReplace, replacement) {
const regex = new RegExp(toReplace, 'g');
replacement = replacement ? replacement : '';
xml = xml.replace(regex, replacement);
return xml;
}
function removeSurroundingChars(str) {
if (str.startsWith('{') && str.endsWith('}')) {
str = str.slice(1, -1);
}
return str;
}
function removeCodeAboveSeparator(input) {
const separatorIndex = input.indexOf(constants_1.separator);
if (separatorIndex === -1) {
return "";
}
return input.substring(separatorIndex + constants_1.separator.length);
}
function convertNamedValue(input) {
const regex = /{nv_(\w+)}/g;
return input.replace(regex, (match, p1) => `{{${p1.replace(/_/g, "-")}}}`);
}
async function updateFileInDirectory(destinationPath, fileName, content) {
const files = fs.readdirSync(destinationPath);
if (files.includes(fileName)) {
const filePath = path_1.default.join(destinationPath, fileName);
fs.writeFileSync(filePath, content);
return;
}
for (const file of files) {
const filePath = path_1.default.join(destinationPath, file);
const isDirectory = fs.statSync(filePath).isDirectory();
if (isDirectory) {
await updateFileInDirectory(filePath, fileName, content);
}
}
const rootFilePath = path_1.default.join(destinationPath, fileName);
fs.writeFileSync(rootFilePath, content);
}
//# sourceMappingURL=scriptCombiner.js.map