@apistudio/apim-cli
Version:
CLI for API Management Products
113 lines (96 loc) • 3.62 kB
text/typescript
/**
* 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;
}
}