mirror of
https://github.com/LukeHagar/redocly-cli.git
synced 2025-12-11 04:21:21 +00:00
chore: Setup and run Prettier (#797)
This commit is contained in:
@@ -5,7 +5,14 @@ import * as path from 'path';
|
||||
import { performance } from 'perf_hooks';
|
||||
const isEqual = require('lodash.isequal');
|
||||
|
||||
import { printExecutionTime, pathToFilename, readYaml, writeYaml, exitWithError, escapeLanguageName } from '../../utils';
|
||||
import {
|
||||
printExecutionTime,
|
||||
pathToFilename,
|
||||
readYaml,
|
||||
writeYaml,
|
||||
exitWithError,
|
||||
escapeLanguageName,
|
||||
} from '../../utils';
|
||||
import { isString, isObject, isEmptyObject } from '../../js-utils';
|
||||
import {
|
||||
Definition,
|
||||
@@ -23,14 +30,10 @@ import {
|
||||
componentsPath,
|
||||
OPENAPI3_METHOD_NAMES,
|
||||
OPENAPI3_COMPONENT_NAMES,
|
||||
Referenced
|
||||
Referenced,
|
||||
} from './types';
|
||||
|
||||
export async function handleSplit (argv: {
|
||||
entrypoint: string;
|
||||
outDir: string
|
||||
separator: string
|
||||
}) {
|
||||
export async function handleSplit(argv: { entrypoint: string; outDir: string; separator: string }) {
|
||||
const startedAt = performance.now();
|
||||
const { entrypoint, outDir, separator } = argv;
|
||||
validateDefinitionFileName(entrypoint!);
|
||||
@@ -38,27 +41,45 @@ export async function handleSplit (argv: {
|
||||
splitDefinition(openapi, outDir, separator);
|
||||
process.stderr.write(
|
||||
`🪓 Document: ${blue(entrypoint!)} ${green('is successfully split')}
|
||||
and all related files are saved to the directory: ${blue(outDir)} \n`,
|
||||
and all related files are saved to the directory: ${blue(outDir)} \n`
|
||||
);
|
||||
printExecutionTime('split', startedAt, entrypoint!);
|
||||
}
|
||||
|
||||
function splitDefinition(openapi: Oas3Definition | Oas3_1Definition, openapiDir: string, pathSeparator: string) {
|
||||
function splitDefinition(
|
||||
openapi: Oas3Definition | Oas3_1Definition,
|
||||
openapiDir: string,
|
||||
pathSeparator: string
|
||||
) {
|
||||
fs.mkdirSync(openapiDir, { recursive: true });
|
||||
|
||||
const componentsFiles: ComponentsFiles = {};
|
||||
iterateComponents(openapi, openapiDir, componentsFiles);
|
||||
iteratePathItems(openapi.paths, openapiDir, path.join(openapiDir, 'paths'), componentsFiles, pathSeparator);
|
||||
const webhooks = (openapi as Oas3_1Definition).webhooks || (openapi as Oas3Definition)['x-webhooks'];
|
||||
iteratePathItems(
|
||||
openapi.paths,
|
||||
openapiDir,
|
||||
path.join(openapiDir, 'paths'),
|
||||
componentsFiles,
|
||||
pathSeparator
|
||||
);
|
||||
const webhooks =
|
||||
(openapi as Oas3_1Definition).webhooks || (openapi as Oas3Definition)['x-webhooks'];
|
||||
// use webhook_ prefix for code samples to prevent potential name-clashes with paths samples
|
||||
iteratePathItems(webhooks, openapiDir, path.join(openapiDir, 'webhooks'), componentsFiles, pathSeparator, 'webhook_');
|
||||
iteratePathItems(
|
||||
webhooks,
|
||||
openapiDir,
|
||||
path.join(openapiDir, 'webhooks'),
|
||||
componentsFiles,
|
||||
pathSeparator,
|
||||
'webhook_'
|
||||
);
|
||||
|
||||
replace$Refs(openapi, openapiDir, componentsFiles);
|
||||
writeYaml(openapi, path.join(openapiDir, 'openapi.yaml'));
|
||||
}
|
||||
|
||||
function isStartsWithComponents(node: string) {
|
||||
return node.startsWith(componentsPath)
|
||||
return node.startsWith(componentsPath);
|
||||
}
|
||||
|
||||
function isNotYaml(filename: string) {
|
||||
@@ -77,7 +98,10 @@ function validateDefinitionFileName(fileName: string) {
|
||||
if (!fs.existsSync(fileName)) exitWithError(`File ${blue(fileName)} does not exist \n`);
|
||||
const file = loadFile(fileName);
|
||||
if ((file as Oas2Definition).swagger) exitWithError('OpenAPI 2 is not supported by this command');
|
||||
if (!(file as Oas3Definition | Oas3_1Definition).openapi) exitWithError('File does not conform to the OpenAPI Specification. OpenAPI version is not specified');
|
||||
if (!(file as Oas3Definition | Oas3_1Definition).openapi)
|
||||
exitWithError(
|
||||
'File does not conform to the OpenAPI Specification. OpenAPI version is not specified'
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -90,8 +114,8 @@ function langToExt(lang: string) {
|
||||
bash: '.sh',
|
||||
javascript: '.js',
|
||||
js: '.js',
|
||||
python: '.py'
|
||||
}
|
||||
python: '.py',
|
||||
};
|
||||
return langObj[lang];
|
||||
}
|
||||
|
||||
@@ -111,7 +135,7 @@ function traverseDirectoryDeep(directory: string, callback: any, componentsFiles
|
||||
function traverseDirectoryDeepCallback(
|
||||
filename: string,
|
||||
directory: string,
|
||||
componentsFiles: object,
|
||||
componentsFiles: object
|
||||
) {
|
||||
if (isNotYaml(filename)) return;
|
||||
const pathData = readYaml(filename);
|
||||
@@ -127,11 +151,7 @@ function crawl(object: any, visitor: any) {
|
||||
}
|
||||
}
|
||||
|
||||
function replace$Refs(
|
||||
obj: any,
|
||||
relativeFrom: string,
|
||||
componentFiles = {} as ComponentsFiles
|
||||
) {
|
||||
function replace$Refs(obj: any, relativeFrom: string, componentFiles = {} as ComponentsFiles) {
|
||||
crawl(obj, (node: any) => {
|
||||
if (node.$ref && isString(node.$ref) && isStartsWithComponents(node.$ref)) {
|
||||
replace(node, '$ref');
|
||||
@@ -156,7 +176,9 @@ function replace$Refs(
|
||||
const filesGroupName = componentFiles[groupName];
|
||||
if (!filesGroupName || !filesGroupName[name!]) return;
|
||||
let filename = path.relative(relativeFrom, filesGroupName[name!].filename);
|
||||
if (!filename.startsWith('.')) { filename = '.' + path.sep + filename; }
|
||||
if (!filename.startsWith('.')) {
|
||||
filename = '.' + path.sep + filename;
|
||||
}
|
||||
node[key] = filename;
|
||||
}
|
||||
}
|
||||
@@ -182,30 +204,40 @@ function implicitlyReferenceDiscriminator(
|
||||
const discriminatorEnum = discriminatorPropSchema && discriminatorPropSchema.enum;
|
||||
const mapping = (obj.discriminator.mapping = obj.discriminator.mapping || {});
|
||||
for (const name of Object.keys(implicitMapping)) {
|
||||
if (discriminatorEnum && !discriminatorEnum.includes(name)) { continue; }
|
||||
if (discriminatorEnum && !discriminatorEnum.includes(name)) {
|
||||
continue;
|
||||
}
|
||||
if (mapping[name] && mapping[name] !== implicitMapping[name]) {
|
||||
process.stderr.write(yellow(
|
||||
`warning: explicit mapping overlaps with local mapping entry ${red(name)} at ${blue(filename)}. Please check it.`
|
||||
));
|
||||
process.stderr.write(
|
||||
yellow(
|
||||
`warning: explicit mapping overlaps with local mapping entry ${red(name)} at ${blue(
|
||||
filename
|
||||
)}. Please check it.`
|
||||
)
|
||||
);
|
||||
}
|
||||
mapping[name] = implicitMapping[name];
|
||||
}
|
||||
}
|
||||
|
||||
function isNotSecurityComponentType(componentType: string) {
|
||||
return componentType !== OPENAPI3_COMPONENT.SecuritySchemes
|
||||
return componentType !== OPENAPI3_COMPONENT.SecuritySchemes;
|
||||
}
|
||||
|
||||
function findComponentTypes(components: any) {
|
||||
return OPENAPI3_COMPONENT_NAMES
|
||||
.filter(item => isNotSecurityComponentType(item) && Object.keys(components).includes(item))
|
||||
return OPENAPI3_COMPONENT_NAMES.filter(
|
||||
(item) => isNotSecurityComponentType(item) && Object.keys(components).includes(item)
|
||||
);
|
||||
}
|
||||
|
||||
function doesFileDiffer(filename: string, componentData: any) {
|
||||
return fs.existsSync(filename) && !isEqual(readYaml(filename), componentData);
|
||||
}
|
||||
|
||||
function removeEmptyComponents(openapi: Oas3Definition | Oas3_1Definition, componentType: Oas3ComponentName) {
|
||||
function removeEmptyComponents(
|
||||
openapi: Oas3Definition | Oas3_1Definition,
|
||||
componentType: Oas3ComponentName
|
||||
) {
|
||||
if (openapi.components && isEmptyObject(openapi.components[componentType])) {
|
||||
delete openapi.components[componentType];
|
||||
}
|
||||
@@ -237,19 +269,21 @@ function gatherComponentsFiles(
|
||||
) {
|
||||
let inherits = [];
|
||||
if (componentType === OPENAPI3_COMPONENT.Schemas) {
|
||||
inherits = ((components?.[componentType]?.[componentName] as Oas3Schema)?.allOf || []).map((s: any) => s.$ref).filter(Boolean);
|
||||
inherits = ((components?.[componentType]?.[componentName] as Oas3Schema)?.allOf || [])
|
||||
.map((s: any) => s.$ref)
|
||||
.filter(Boolean);
|
||||
}
|
||||
componentsFiles[componentType] = componentsFiles[componentType] || {};
|
||||
componentsFiles[componentType][componentName] = { inherits, filename };
|
||||
}
|
||||
|
||||
function iteratePathItems(
|
||||
pathItems: Record<string, Referenced<Oas3PathItem>> | undefined,
|
||||
pathItems: Record<string, Referenced<Oas3PathItem>> | undefined,
|
||||
openapiDir: string,
|
||||
outDir: string,
|
||||
componentsFiles: object,
|
||||
pathSeparator: string,
|
||||
codeSamplesPathPrefix: string = '',
|
||||
codeSamplesPathPrefix: string = ''
|
||||
) {
|
||||
if (!pathItems) return;
|
||||
fs.mkdirSync(outDir, { recursive: true });
|
||||
@@ -259,7 +293,7 @@ function iteratePathItems(
|
||||
const pathData = pathItems[pathName] as Oas3PathItem;
|
||||
|
||||
if (isRef(pathData)) continue;
|
||||
|
||||
|
||||
for (const method of OPENAPI3_METHOD_NAMES) {
|
||||
const methodData = pathData[method];
|
||||
const methodDataXCode = methodData?.['x-code-samples'] || methodData?.['x-codeSamples'];
|
||||
@@ -273,20 +307,20 @@ function iteratePathItems(
|
||||
'code_samples',
|
||||
escapeLanguageName(sample.lang),
|
||||
codeSamplesPathPrefix + pathToFilename(pathName, pathSeparator),
|
||||
method + langToExt(sample.lang),
|
||||
method + langToExt(sample.lang)
|
||||
);
|
||||
|
||||
fs.mkdirSync(path.dirname(sampleFileName), { recursive: true });
|
||||
fs.writeFileSync(sampleFileName, sample.source);
|
||||
// @ts-ignore
|
||||
sample.source = {
|
||||
$ref: slash(path.relative(outDir, sampleFileName))
|
||||
$ref: slash(path.relative(outDir, sampleFileName)),
|
||||
};
|
||||
}
|
||||
}
|
||||
writeYaml(pathData, pathFile);
|
||||
pathItems[pathName] = {
|
||||
$ref: slash(path.relative(openapiDir, pathFile))
|
||||
$ref: slash(path.relative(openapiDir, pathFile)),
|
||||
};
|
||||
|
||||
traverseDirectoryDeep(outDir, traverseDirectoryDeepCallback, componentsFiles);
|
||||
@@ -329,9 +363,13 @@ function iterateComponents(
|
||||
);
|
||||
|
||||
if (doesFileDiffer(filename, componentData)) {
|
||||
process.stderr.write(yellow(
|
||||
`warning: conflict for ${componentName} - file already exists with different content: ${blue(filename)} ... Skip.\n`
|
||||
));
|
||||
process.stderr.write(
|
||||
yellow(
|
||||
`warning: conflict for ${componentName} - file already exists with different content: ${blue(
|
||||
filename
|
||||
)} ... Skip.\n`
|
||||
)
|
||||
);
|
||||
} else {
|
||||
writeYaml(componentData, filename);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user