openapi-graph-core
Version:
A TS library to manage large API projects defined by OpenAPIv3 specification.
97 lines (96 loc) • 4.13 kB
JavaScript
;
/**
* The main goal is to find all openAPI specification given a path.
* Therefore, it will loop over all files and creating a structured object
* as a result
*
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.testables = exports.fetcher = void 0;
const fs_1 = require("fs");
const js_yaml_1 = require("js-yaml");
const openapi_graph_types_1 = require("openapi-graph-types");
const path_1 = require("path");
const _1 = require(".");
const COMMON_FOLDER_NAMES = ["node_modules", "target"];
const COMMON_FILES_NAMES = ["docker-compose"].flatMap(e => [`${e}.yml`, `${e}.yaml`]);
async function fetcher(input) {
if (typeof input === 'string') {
// If we are working with a path, then it means that we have to find all openAPI specifications
// Converts path to absolute
const resolvedPath = path_1.resolve(input);
const pathExists = fs_1.existsSync(resolvedPath);
if (!pathExists) {
throw new Error('The given path does not exist in your system');
}
else {
return await loadsSwaggerFiles(resolvedPath);
}
}
else if (([]).constructor === input.constructor) {
// If we are working with a path, then it means that we have to find all openAPI specifications
const resolvedPaths = input
.map(i => path_1.resolve(input))
.filter(resolvedPath => fs_1.existsSync(resolvedPath) || _1.log(`Ignoring ${resolvedPath} because the path is not reachable`, openapi_graph_types_1.LogLevel.WARN));
return getOpenApisContent(resolvedPaths);
}
else {
_1.log(`Invalid given input. It was expected a string or array of strings. Received ${input}`, openapi_graph_types_1.LogLevel.WARN);
return [];
}
}
exports.fetcher = fetcher;
/**
* Finds all the valid OpenApi specifications given a directory and returns a
* list of all the specification contents
*
* @param projectPath of the project where the specifications are suppose to be
* @returns a list of OpenAPIContent which has the path, openAPI version
* and the content for every specification found inside of the given path
*/
async function loadsSwaggerFiles(projectPath) {
const projectContent = await getFiles(path_1.resolve(projectPath));
_1.log(`Found (${projectContent.length}) ${projectContent}`);
if (projectContent === undefined || projectContent.length === 0) {
return [];
}
return await getOpenApisContent(projectContent);
}
async function getFiles(fromPath = './', paths = []) {
const entries = await fs_1.readdirSync(fromPath, { withFileTypes: true });
for (const entry of entries) {
// We don't check hidden files or folders
if (!/(^|\/)\.[^/.]/g.test(entry.name)) {
if (entry.isDirectory() &&
// Don't check common folder names
!COMMON_FOLDER_NAMES.includes(entry.name)) {
paths.push(...(await getFiles(`${fromPath}/${entry.name}/`)));
}
else if (entry.isFile() &&
// JSON are also valid, but they are more generic, so we don't look for them because it takes a lot of time
entry.name.match(/.*\.(yml|yaml)/gi) &&
// Don't check common file names
!COMMON_FILES_NAMES.includes(entry.name)) {
paths.push(path_1.resolve(`${fromPath}/${entry.name}`));
}
}
}
return paths;
}
/**
* reads the contents of all given paths. The files will be validated.
*
* @param paths of the .yaml|.yml files. The paths should exists.
* @returns the contents of the files as JSON with their path
*/
async function getOpenApisContent(paths) {
return (paths
.map(p => ({ path: p, content: js_yaml_1.load(fs_1.readFileSync(p, 'utf8')) || _1.log(`Couldn't load ${p}`, openapi_graph_types_1.LogLevel.WARN) }))
.filter(p => p.content?.openapi?.includes("3.0")));
}
// Just for testing reasons https://stackoverflow.com/a/54116079
exports.testables = {
loadsSwaggerFiles,
getFiles,
getOpenApisContent
};