@redocly/cli
Version:
[@Redocly](https://redocly.com) CLI is your all-in-one OpenAPI utility. It builds, manages, improves, and quality-checks your OpenAPI descriptions, all of which comes in handy for various phases of the API Lifecycle. Create your own rulesets to make API g
101 lines • 4.15 kB
JavaScript
import { blue, gray } from 'colorette';
import { performance } from 'perf_hooks';
import { formatProblems, getTotals, lint, lintConfig, pluralize, ConfigValidationError, logger, } from '@redocly/openapi-core';
import { checkIfRulesetExist, formatPath, getExecutionTime, getFallbackApisOrExit, handleError, printConfigLintTotals, printLintTotals, printUnusedWarnings, } from '../utils/miscellaneous.js';
import { AbortFlowError, exitWithError } from '../utils/error.js';
import { getCommandNameFromArgs } from '../utils/get-command-name-from-args.js';
export async function handleLint({ argv, config, version, collectSpecData, }) {
const apis = await getFallbackApisOrExit(argv.apis, config);
if (!apis.length) {
exitWithError('No APIs were provided.');
}
if (argv['generate-ignore-file']) {
config.ignore = {}; // clear ignore
}
const totals = { errors: 0, warnings: 0, ignored: 0 };
let totalIgnored = 0;
// TODO: use shared externalRef resolver, blocked by preprocessors now as they can mutate documents
for (const { path, alias } of apis) {
try {
const startedAt = performance.now();
const aliasConfig = config.forAlias(alias);
checkIfRulesetExist(aliasConfig.rules);
aliasConfig.skipRules(argv['skip-rule']);
aliasConfig.skipPreprocessors(argv['skip-preprocessor']);
if (typeof config.document?.parsed === 'undefined') {
logger.info(`No configurations were provided -- using built in ${blue('recommended')} configuration by default.\n\n`);
}
if (alias === undefined) {
logger.info(gray(`validating ${formatPath(path)}...\n`));
}
else {
logger.info(gray(`validating ${formatPath(path)} using lint rules for api '${alias}'...\n`));
}
const results = await lint({
ref: path,
config: aliasConfig,
collectSpecData,
});
const fileTotals = getTotals(results);
totals.errors += fileTotals.errors;
totals.warnings += fileTotals.warnings;
totals.ignored += fileTotals.ignored;
if (argv['generate-ignore-file']) {
for (const m of results) {
config.addIgnore(m);
totalIgnored++;
}
}
else {
formatProblems(results, {
format: argv.format,
maxProblems: argv['max-problems'],
totals: fileTotals,
version,
});
}
const elapsed = getExecutionTime(startedAt);
logger.info(gray(`${formatPath(path)}: validated in ${elapsed}\n\n`));
}
catch (e) {
handleError(e, path);
}
}
if (argv['generate-ignore-file']) {
config.saveIgnore();
logger.info(`Generated ignore file with ${totalIgnored} ${pluralize('problem', totalIgnored)}.\n\n`);
}
else {
printLintTotals(totals, apis.length);
}
printUnusedWarnings(config);
if (!(totals.errors === 0 || argv['generate-ignore-file'])) {
throw new AbortFlowError('Lint failed.');
}
}
export async function handleLintConfig(argv, version, config) {
if (argv['lint-config'] === 'off' || config.document === undefined) {
return;
}
if (argv.format === 'json') {
// we can't print config lint results as it will break json output
return;
}
const command = argv ? getCommandNameFromArgs(argv) : undefined;
const problems = await lintConfig({
config,
severity: argv['lint-config'] || 'warn',
});
const fileTotals = getTotals(problems);
formatProblems(problems, {
format: argv.format,
maxProblems: argv['max-problems'],
totals: fileTotals,
version,
});
printConfigLintTotals(fileTotals, command);
if (fileTotals.errors > 0) {
throw new ConfigValidationError();
}
}
//# sourceMappingURL=lint.js.map