UNPKG

@apistudio/apim-cli

Version:

CLI for API Management Products

179 lines (164 loc) 5.01 kB
import path from "path"; import fs from "fs"; import { BaseAsset } from "../../model/assets-model.js"; import { isValidAsset } from "./asset-helper.js"; import { readMultiYaml } from "../common/yaml-helper.js"; import { readFile, isYamlFile, isDirectory, isDirOrFileExists, getSubDirectory, normalizePath, } from "../common/fs-helper.js"; import { showWarning, showError } from "../common/message-helper.js"; import { DIRECTORY_DOESNT_EXIST, ERROR_IN_SEARCH_OF_ASSET, NO_ENTRIES_FOUND_FOR_KIND, NO_ASSET_METADATA, IS_FOUND_IN, INVALID_DIRECTORY, } from "../../constants/message-constants.js"; import { COMMA } from "../../constants/app-constants.js"; import { equalsIgnoreCase } from "../common/data-helper.js"; const searchAssetByKind = async ( kindToSearch: string, rootDirPath: string, projectNames: string ): Promise<Record<string, string>> => { const projectAssetMetadata: Record<string, string[]> = {}; try { const projects = projectNames.split(COMMA); for (const project of projects) { const projectDirPath = getSubDirectory(rootDirPath, project); if (!isDirOrFileExists(projectDirPath) || !isDirectory(projectDirPath)) { showWarning(`${DIRECTORY_DOESNT_EXIST} ${projectDirPath}`); continue; } const matchingEntries = searchAssetByKindInDirectory( kindToSearch, projectDirPath ); if (matchingEntries.length > 0) { for (const entry of matchingEntries) { const filePath = path.join(entry.parentPath, entry.name); extractKindMetadata( filePath, project, kindToSearch, projectAssetMetadata ); } } else { showWarning( `${NO_ENTRIES_FOUND_FOR_KIND} - '${kindToSearch}' ${IS_FOUND_IN} '${projectDirPath}'` ); } } return formatMetadataResult(projectAssetMetadata); } catch (error) { showError( `${ERROR_IN_SEARCH_OF_ASSET} ${kindToSearch}: ${(error as Error).message}` ); throw error; } }; const searchAssetByKindInDirectory = ( kindToSearch: string, projectDirPath: string ): fs.Dirent[] => { if (!isDirOrFileExists(projectDirPath) || !isDirectory(projectDirPath)) { throw new Error(`${INVALID_DIRECTORY} ${projectDirPath}`); } try { const entries: fs.Dirent[] = fs.readdirSync(projectDirPath, { withFileTypes: true, recursive: true, }); return entries.filter((entry) => { if (entry.isDirectory()) { return false; } if (!isYamlFile(entry.name)) { return false; } const assets = readMultiYaml<BaseAsset>( normalizePath(`${entry.parentPath}/${entry.name}`), readFile(entry.parentPath, entry.name) ); return containsMatchingKind(assets, kindToSearch); }); } catch (error) { showError( `${ERROR_IN_SEARCH_OF_ASSET} ${kindToSearch}: ${(error as Error).message}` ); throw error; } }; const containsMatchingKind = ( assets: BaseAsset[], kindToSearch: string ): boolean => { for (const asset of assets) { if (isValidAsset(asset) && equalsIgnoreCase(kindToSearch, asset.kind)) { return true; } } return false; }; const extractKindMetadata = ( filePath: string, project: string, kindToSearch: string, projectAssetMetadata: Record<string, string[]> ): boolean => { try { const fileContent = readFile( path.dirname(filePath), path.basename(filePath) ); const yamlContents = readMultiYaml<BaseAsset>(filePath, fileContent); const assetMetadata: string[] = []; yamlContents.forEach((yamlContent) => { if (isValidAsset(yamlContent)) { const kind = yamlContent.kind ? yamlContent.kind.toLowerCase() : ""; if (kind === kindToSearch.toLowerCase()) { const metadata = getMetadata(yamlContent); assetMetadata.push(metadata); } } }); if (assetMetadata.length > 0) { if (!projectAssetMetadata[project]) { projectAssetMetadata[project] = []; } projectAssetMetadata[project].push(...assetMetadata); } return assetMetadata.length > 0; } catch (error) { showError( `${error instanceof Error ? error.message : "Unknown error"}` ); return false; } }; const formatMetadataResult = ( projectAssetMetadata: Record<string, string[]> ): Record<string, string> => { if (Object.keys(projectAssetMetadata).length === 0) { showError(NO_ASSET_METADATA); } const result: Record<string, string> = {}; for (const [project, metadataArray] of Object.entries(projectAssetMetadata)) { result[project] = metadataArray.join(COMMA); } return result; }; const getMetadata = (asset: BaseAsset): string => { const namespace = asset.metadata?.namespace || ""; const name = asset.metadata?.name || ""; const version = asset.metadata?.version || ""; return `${namespace}:${name}:${version}`; }; export { searchAssetByKind };