UNPKG

@apistudio/apim-cli

Version:

CLI for API Management Products

113 lines (96 loc) 3.62 kB
/** * Copyright Super iPaaS Integration LLC, an IBM Company 2024 */ import JSZip from 'jszip'; import yaml from 'js-yaml'; import { TypeConvertor } from '../converter/type.converter.js'; import { YamlContent, SpecObject, AssetManagerInterface, TestMetadata } from '../models/interface.js'; import { LogWrapper } from '../service/log-wrapper.js'; export class AssetParser implements AssetManagerInterface { private readonly obj = new TypeConvertor(); async createAssetReferenceMap(buffer: Buffer): Promise<Map<string, boolean>> { const zip = new JSZip(); const refMap = new Map<string, boolean>(); const zipContent = await zip.loadAsync(buffer); for (const [fileName, file] of Object.entries(zipContent.files)) { if (fileName.endsWith('.yaml') || fileName.endsWith('.yml')) { const content = await file.async('string'); try { const yamlContents = yaml.loadAll(content) as YamlContent[]; for (const yamlContent of yamlContents) { if(yamlContent.kind.toLowerCase()==='test') { this.extractRefs(yamlContent, refMap); } this.updateMapWithMetadata(yamlContent, refMap); } } catch (err) { LogWrapper.logError('0013', `parsing YAML in file ${fileName}`, (err as Error).message); } } } return refMap; } updateMapWithMetadata(yamlContent: YamlContent, refMap: Map<string, boolean>): void { const metadata = yamlContent.metadata as TestMetadata; const keyParts = []; if (metadata.namespace) { keyParts.push(metadata.namespace); } if (metadata.name) { keyParts.push(metadata.name); } const version = this.obj.toString(metadata.version); keyParts.push(version); const key = keyParts.join(':'); refMap.set(key, true); LogWrapper.logDebug('0003', `Metadata key added to refMap: ${key}`); } async updateMapWithGatewayEndpoints(data: Buffer, refMap: Map<string, boolean>): Promise<void> { const zip = new JSZip(); const zipContent = await zip.loadAsync(data); for (const [fileName, file] of Object.entries(zipContent.files)) { if (fileName.includes('api-gatewayEndpoints.json')) { const content = await file.async('string'); const endpoints = JSON.parse(content); Object.keys(endpoints).forEach((key) => { refMap.set(key, true); LogWrapper.logInfo('0003', `Gateway endpoint added to refMap: ${key}`); }); } } } private extractRefs(yamlContent: YamlContent, refMap: Map<string, boolean>): void { const extractRef = (obj: SpecObject) => { for (const key in obj) { const value = obj[key]; if (key === '$ref' && typeof value === 'string') { const metadataWithUpdatedVersion=this.replaceVersionInString(value); if (!refMap.has(metadataWithUpdatedVersion)) { LogWrapper.logDebug('0003', `Reference found and added to refMap: ${value}`); refMap.set(metadataWithUpdatedVersion, false); } } else if (typeof value === 'object' && value !== null) { extractRef(value); } } }; const specOb=JSON.stringify(yamlContent.spec); extractRef(yaml.load(specOb) as SpecObject); } private replaceVersionInString(input: string): string { const parts = input.split(':'); const version=parts[parts.length-1]; const numberPattern = /^-?\d+(\.\d+)?$/; // Matches integers and decimals if (numberPattern.test(version)) { const numberVersion= parseFloat(version); if(!isNaN(numberVersion)){ parts[parts.length - 1]= this.obj.toString(numberVersion); return parts.join(':'); } }else{ parts[parts.length - 1]= this.obj.toString(version); return parts.join(':'); } return input; } }