UNPKG

@apistudio/apim-cli

Version:

CLI for API Management Products

169 lines (151 loc) 5.26 kB
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' }); };