UNPKG

@redocly/cli

Version:

[@Redocly](https://redocly.com) CLI is your all-in-one API documentation utility. It builds, manages, improves, and quality-checks your API descriptions, all of which comes in handy for various phases of the API Lifecycle. Create your own rulesets to make

87 lines 3.92 kB
import { logger, lintDocument, pluralize, } from '@redocly/openapi-core'; import { exitWithError } from '../../../utils/error.js'; import { getTarget, resolveConfigForTarget } from '../targets-handler/targets-handler.js'; import { evaluatePluginsFromCode } from './plugin-evaluator.js'; export async function validateScorecard({ apiPath, document, externalRefResolver, scorecardConfig, configPath, pluginsCodeOrPlugins, targetLevel, metadata = {}, verbose = false, }) { const problems = []; const levelResults = new Map(); const targets = scorecardConfig.targets || []; if (targetLevel && !scorecardConfig.levels?.some((level) => level.name === targetLevel)) { exitWithError(`Target level "${targetLevel}" not found in the scorecard configuration levels.\n`); } const plugins = typeof pluginsCodeOrPlugins === 'string' ? await evaluatePluginsFromCode(pluginsCodeOrPlugins, verbose) : pluginsCodeOrPlugins; const pluginsList = Array.isArray(plugins) ? plugins : []; let levelConfigs = {}; let targetRules; if (targets.length > 0) { if (verbose) { logger.info(`Scorecard has ${targets.length} ${pluralize('target', targets.length)} defined. Resolving target configurations...\n`); } const matchedTarget = getTarget(targets, metadata); if (matchedTarget) { if (verbose) { logger.info(`Found matching target for metadata. Resolving configurations for target "${JSON.stringify(matchedTarget.where)}"...\n`); } targetRules = matchedTarget.rules; } else { if (verbose) { logger.info(`No matching target found for metadata. Proceeding with level configurations only.\n`); } } } levelConfigs = await resolveConfigForTarget(apiPath, targetRules, scorecardConfig.levels || [], pluginsList, configPath || ''); for (const level of scorecardConfig.levels || []) { if (verbose) { logger.info(`\nValidating level: "${level.name}"\n`); } if (verbose && plugins && plugins.length > 0) { logger.info(`Using ${plugins.length} ${pluralize('plugin', plugins.length)} for this level.\n`); } const config = levelConfigs[level.name]; if (verbose) { logger.info(`Linting document against level rules...\n`); } const levelProblems = await lintDocument({ document, externalRefResolver, config, }); const filteredProblems = levelProblems .filter(({ ignored }) => !ignored) .map((problem) => ({ ...problem, scorecardLevel: level.name, })); levelResults.set(level.name, filteredProblems); if (verbose) { logger.info(`Found ${filteredProblems.length} ${pluralize('problem', filteredProblems.length)} for level "${level.name}".\n`); } problems.push(...filteredProblems); } const achievedLevel = determineAchievedLevel(levelResults, scorecardConfig.levels || [], targetLevel); const targetLevelAchieved = targetLevel ? achievedLevel === targetLevel : true; return { problems, achievedLevel, targetLevelAchieved, }; } function determineAchievedLevel(levelResults, levels, targetLevel) { let lastPassedLevel = null; for (const level of levels) { const levelProblems = levelResults.get(level.name) || []; const hasErrors = levelProblems.some((p) => p.severity === 'error'); if (hasErrors) { return lastPassedLevel || 'Non Conformant'; } lastPassedLevel = level.name; if (targetLevel && level.name === targetLevel) { return level.name; } } return lastPassedLevel || 'Non Conformant'; } //# sourceMappingURL=validate-scorecard.js.map