@redocly/openapi-core
Version:
See https://github.com/Redocly/redocly-cli
120 lines • 4.62 kB
JavaScript
import { rootRedoclyConfigSchema } from '@redocly/config';
import { BaseResolver, resolveDocument, makeDocumentFromString } from './resolve.js';
import { normalizeVisitors } from './visitors.js';
import { walkDocument } from './walk.js';
import { initRules } from './config/rules.js';
import { normalizeTypes } from './types/index.js';
import { releaseAjvInstance } from './rules/ajv.js';
import { getTypes } from './oas-types.js';
import { detectSpec, getMajorSpecVersion } from './detect-spec.js';
import { createConfigTypes } from './types/redocly-yaml.js';
import { Struct } from './rules/common/struct.js';
import { NoUnresolvedRefs } from './rules/common/no-unresolved-refs.js';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore FIXME: remove this once we remove `theme` from the schema
delete rootRedoclyConfigSchema.properties.theme;
export async function lint(opts) {
const { ref, externalRefResolver = new BaseResolver(opts.config.resolve) } = opts;
const document = (await externalRefResolver.resolveDocument(null, ref, true));
opts.collectSpecData?.(document.parsed);
return lintDocument({
document,
...opts,
externalRefResolver,
});
}
export async function lintFromString(opts) {
const { source, absoluteRef, externalRefResolver = new BaseResolver(opts.config.resolve) } = opts;
const document = makeDocumentFromString(source, absoluteRef || '/');
return lintDocument({
document,
...opts,
externalRefResolver,
});
}
export async function lintDocument(opts) {
releaseAjvInstance(); // FIXME: preprocessors can modify nodes which are then cached to ajv-instance by absolute path
const { document, customTypes, externalRefResolver, config } = opts;
const specVersion = detectSpec(document.parsed);
const specMajorVersion = getMajorSpecVersion(specVersion);
const rules = config.getRulesForSpecVersion(specMajorVersion);
const types = normalizeTypes(config.extendTypes(customTypes ?? getTypes(specVersion), specVersion), config);
const ctx = {
problems: [],
specVersion,
config,
visitorsData: {},
};
const preprocessors = initRules(rules, config, 'preprocessors', specVersion);
const regularRules = initRules(rules, config, 'rules', specVersion);
let resolvedRefMap = await resolveDocument({
rootDocument: document,
rootType: types.Root,
externalRefResolver,
});
if (preprocessors.length > 0) {
// Make additional pass to resolve refs defined in preprocessors.
walkDocument({
document,
rootType: types.Root,
normalizedVisitors: normalizeVisitors(preprocessors, types),
resolvedRefMap,
ctx,
});
resolvedRefMap = await resolveDocument({
rootDocument: document,
rootType: types.Root,
externalRefResolver,
});
}
const normalizedVisitors = normalizeVisitors(regularRules, types);
walkDocument({
document,
rootType: types.Root,
normalizedVisitors,
resolvedRefMap,
ctx,
});
return ctx.problems.map((problem) => config.addProblemToIgnore(problem));
}
export async function lintConfig(opts) {
const { severity, externalRefResolver = new BaseResolver(), config } = opts;
if (!config.document) {
throw new Error('Config document is not set.');
}
const ctx = {
problems: [],
specVersion: 'oas3_0', // TODO: use config-specific version
config,
visitorsData: {},
};
const types = normalizeTypes(opts.externalConfigTypes || createConfigTypes(rootRedoclyConfigSchema, config));
const rules = [
{
severity: severity || 'error',
ruleId: 'configuration struct',
visitor: Struct({ severity: 'error' }),
},
{
severity: severity || 'error',
ruleId: 'configuration no-unresolved-refs',
visitor: NoUnresolvedRefs({ severity: 'error' }),
},
];
const normalizedVisitors = normalizeVisitors(rules, types);
const resolvedRefMap = config.resolvedRefMap ||
(await resolveDocument({
rootDocument: config.document,
rootType: types.ConfigRoot,
externalRefResolver,
}));
walkDocument({
document: config.document,
rootType: types.ConfigRoot,
normalizedVisitors,
resolvedRefMap,
ctx,
});
return ctx.problems;
}
//# sourceMappingURL=lint.js.map