@apistudio/apim-cli
Version:
CLI for API Management Products
61 lines (60 loc) • 3.78 kB
JavaScript
import { checkForNullOrUndefined } from "../common/data-helper.js";
import path from "node:path";
import fs from "node:fs";
import { showError, showInfo, showWarning } from "../common/message-helper.js";
const bundleApiDependency = (asset, searchResult, cachedUnProcessedAsset, rootDirPath, project, zipFile) => {
const sourceProjectName = cachedUnProcessedAsset.sourceProject;
if (!sourceProjectName) {
showError(`Source project not found for API dependency ${cachedUnProcessedAsset.ref}`);
return;
}
// Pass the timestamp as the unique value that gets appended to project name
const timeStamp = Date.now();
// Add API with project folder structure
const apiRelativePath = addApiDependencyAsset(searchResult, zipFile, project, // target project name
sourceProjectName, rootDirPath, timeStamp);
showInfo(`API added: ${project}/${apiRelativePath}`);
// Also add the API specification
resolveAndAddApiSpec(asset, zipFile, apiRelativePath, project, // target project name
sourceProjectName, rootDirPath, timeStamp);
};
const addApiDependencyAsset = (file, zip, targetProjectName, sourceProjectName, rootDirPath, timeStamp) => {
// Calculate relative path from target project root
const targetProjectPath = path.join(rootDirPath, targetProjectName);
const relativePath = path.relative(targetProjectPath, path.join(file.parentPath, file.name));
// Add to zip with project folder structure nested inside source project
// Result: sourceProject/targetProject/api-assets/api.yml
const zipPath = path.join(sourceProjectName, `${targetProjectName}_${timeStamp}`, relativePath);
zip.addLocalFile(path.join(file.parentPath, file.name), path.dirname(zipPath));
return relativePath;
};
const resolveAndAddApiSpec = (asset, zip, apiFileRelativePath, targetProjectName, sourceProjectName, rootDirPath, timeStamp) => {
const apiAsset = asset;
const spec = checkForNullOrUndefined(apiAsset.spec, `Spec is not defined for the asset with kind 'API' and name '${apiAsset.metadata?.name}'`);
const apiSpec = checkForNullOrUndefined(spec["api-spec"], `Attribute 'api-spec' is not defined
for kind 'API' and name '${apiAsset.metadata?.name}'`);
const apiSpecPath = checkForNullOrUndefined(apiSpec.$path, `API Definition Path is not found for ${asset}`);
// Get the directory where the API file is located
const apiFileDir = path.dirname(apiFileRelativePath);
// Resolve api spec path relative to project folder by default
let resolvedSpecPath = apiSpecPath;
if (apiSpecPath.startsWith('../') || apiSpecPath.startsWith('./')) {
// Resolve relative path from API file's directory
// Example: apiFileDir = "api-assets", apiSpecPath = "../specs/petstore.yaml"
// Result: "specs/petstore.yaml"
const specPathFromProjectRoot = path.join(apiFileDir, apiSpecPath);
resolvedSpecPath = path.normalize(specPathFromProjectRoot);
}
// Build absolute file system path for reading the spec
const absoluteSpecPath = path.join(rootDirPath, targetProjectName, resolvedSpecPath);
if (!fs.existsSync(absoluteSpecPath)) {
showWarning(`API spec not found: ${absoluteSpecPath} for API ${apiAsset.metadata?.namespace}:${apiAsset.metadata?.name}:${apiAsset.metadata.version}`);
return;
}
// Build zip path using the relative spec path from API
// apiSpecPath is already relative (e.g., "specs/petstore.yaml")
const zipSpecPath = path.join(sourceProjectName, `${targetProjectName}_${timeStamp}`, resolvedSpecPath);
zip.addLocalFile(absoluteSpecPath, path.dirname(zipSpecPath));
showInfo(`Spec added: ${zipSpecPath}`);
};
export { bundleApiDependency, addApiDependencyAsset, resolveAndAddApiSpec };