@apistudio/apim-cli
Version:
CLI for API Management Products
169 lines (151 loc) • 5.26 kB
text/typescript
import {
checkFileExtension,
constructErrorResponse,
DeployValidationException,
isRelativePath,
isValidAsset,
SpecObject,
YamlContent,
ZipProcessor,
} from '../index.js';
import { BuildProjectAssets } from '../build-project-assets.js';
import yaml from 'js-yaml';
import path from 'path';
import JSZip from 'jszip';
import { LogWrapper } from '../service/log-wrapper.js';
import { AppConstants } from '../constants/app.constants.js';
export const processBuild = async (fileBuffer: Buffer) => {
LogWrapper.logInfo('0003', 'Starting build process.');
const obj = new ZipProcessor(fileBuffer);
LogWrapper.logInfo('0003', 'Processing zip file.');
const result = await obj.processZip();
if (!result) {
LogWrapper.logError('0003', 'Build process failed.');
throw new Error(JSON.stringify(constructErrorResponse()));
}
LogWrapper.logInfo('0003', 'Build process succeeded.');
const { buildZip: gatewayZip } = result;
LogWrapper.logInfo('0003', 'Generating zip buffer from gatewayZip.');
const zipBuffer = await gatewayZip.generateAsync({ type: 'nodebuffer' });
LogWrapper.logInfo('0003', 'Zip buffer generation successful.');
return { zipBuffer };
};
export const processGatewayJson = async (fileBuffer: Buffer) => {
LogWrapper.logInfo('0003', 'Starting extraction of gateway JSON.');
const obj = new ZipProcessor(fileBuffer);
return obj.extractGatewaysJson(fileBuffer);
};
export const normalizeZipPaths = async (zip: JSZip) => {
LogWrapper.logDebug('0003', 'Starting path normalization in zip file.');
const normalizedZip = new JSZip();
await Promise.all(
Object.values(zip.files).map(async (file) => {
const normalizedPath = path.normalize(file.name);
if (file.dir) {
normalizedZip.folder(normalizedPath);
LogWrapper.logDebug('0301', 'directory', `${normalizedPath}`);
} else {
const fileData = await file.async('nodebuffer');
normalizedZip.file(normalizedPath, fileData);
LogWrapper.logDebug('0301', 'file', `${normalizedPath}`);
}
})
);
LogWrapper.logDebug('0003', 'Path normalization completed.');
return normalizedZip;
};
export const updateRelativePath = async (
asset: YamlContent,
basePath: string
): Promise<YamlContent> => {
const extract = (obj: SpecObject) => {
for (const key in obj) {
const value = obj[key];
if (key === AppConstants.pathVariable && typeof value === 'string') {
if(isRelativePath(value))
{
const baseDir = path.dirname(basePath);
const resolvedPath = path.join(baseDir, value);
const normalizedPath = path.normalize(resolvedPath).replace(/\\+/g, '/');
obj[key] = normalizedPath.slice(normalizedPath.indexOf('/')+1);
}
}
else if (typeof value === 'object' && value !== null)
{
extract(value);
}
}
};
if (asset.spec)
{
extract(asset.spec as unknown as SpecObject);
}
return asset;
};
export const updatePathValueInContent = async (
content: string,
basePath: string
)=> {
const parsedObjs = yaml.loadAll(content) as YamlContent[];
const updatedObjs = await Promise.all(
parsedObjs.map(async (obj) => {
if (isValidAsset(obj))
{
return await updateRelativePath(obj, basePath);
}
return obj;
})
);
return updatedObjs.map(obj => yaml.dump(obj)) .join('---\n');
};
export const resolveRelativePaths = async (zipBuffer: Buffer) => {
LogWrapper.logDebug('0003', 'Starting path normalization in zip file.');
const zip = await JSZip.loadAsync(zipBuffer);
const resolvedZip = new JSZip();
await Promise.all(
Object.values(zip.files).map(async (file) => {
if (file.dir) {
resolvedZip.folder(file.name);
LogWrapper.logDebug('0301', 'directory', file.name);
} else
{
const nameArray = file.name.split(path.sep);
const name = nameArray[nameArray.length - 1];
if (checkFileExtension(name)) {
const content = await file.async('string');
const updatedContent = await updatePathValueInContent(
content,
file.name
);
resolvedZip.file(file.name,updatedContent);
} else {
const fileData = await file.async('nodebuffer');
resolvedZip.file(file.name, fileData);
}
}
})
);
LogWrapper.logDebug('0003', 'Path normalization completed.');
return resolvedZip;
};
export const processProjectBuild = async (fileBuffer: Buffer) =>
{
LogWrapper.logInfo('0003', 'Starting project build processing.');
const zip = await JSZip.loadAsync(fileBuffer);
LogWrapper.logDebug('0003', 'Loading and normalizing zip paths.');
const normalizedZip = await normalizeZipPaths(zip);
const normalizedBuffer = await normalizedZip.generateAsync({ type: 'nodebuffer' });
const resolvedZip = await resolveRelativePaths(normalizedBuffer);
LogWrapper.logDebug('0003', 'Normalized zip buffer generated.');
const obj = new BuildProjectAssets();
LogWrapper.logInfo('0003', 'Processing normalized project zip.');
const result = await obj.processProjectZip(await resolvedZip.generateAsync({
type: 'nodebuffer',
}));
if (!result) {
LogWrapper.logError('0003', 'Project build processing failed.');
throw new DeployValidationException('Asset Validation Failed For Deloyment');
}
LogWrapper.logInfo('0003', 'Project build processing succeeded.');
return result.generateAsync({ type: 'nodebuffer' });
};