UNPKG

@stoplight/spectral

Version:

A flexible object linter with out of the box support for OpenAPI v2 and v3.

113 lines 4.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const json_1 = require("@stoplight/json"); const json_ref_resolver_1 = require("@stoplight/json-ref-resolver"); const types_1 = require("@stoplight/types"); const yaml_1 = require("@stoplight/yaml"); const lodash_1 = require("lodash"); const functions_1 = require("./functions"); const runner_1 = require("./runner"); tslib_1.__exportStar(require("./types"), exports); class Spectral { constructor(opts) { this._rules = {}; this._functions = functions_1.functions; this.resolver = opts && opts.resolver ? opts.resolver : new json_ref_resolver_1.Resolver(); } run(target) { return tslib_1.__awaiter(this, void 0, void 0, function* () { let results = []; let parsedResult; if (!exports.isParsedResult(target)) { parsedResult = { parsed: yaml_1.parseWithPointers(typeof target === 'string' ? target : json_1.safeStringify(target, undefined, 2)), getLocationForJsonPath: yaml_1.getLocationForJsonPath, }; results = results.concat(formatParserDiagnostics(parsedResult.parsed, parsedResult.source)); } else { parsedResult = target; } const { result: resolvedTarget, errors } = yield this.resolver.resolve(parsedResult.parsed.data); return [ ...results, ...formatResolverErrors(errors, parsedResult), ...runner_1.runRules(parsedResult, this.rules, this.functions, { resolvedTarget }), ]; }); } get functions() { return this._functions; } addFunctions(functions) { Object.assign(this._functions, lodash_1.merge({}, functions)); } get rules() { const rules = {}; for (const name in this._rules) { if (!this._rules.hasOwnProperty(name)) continue; const rule = this._rules[name]; rules[name] = Object.assign({ name }, rule); } return rules; } addRules(rules) { Object.assign(this._rules, lodash_1.merge({}, rules)); } mergeRules(rules) { for (const ruleName in lodash_1.merge({}, rules)) { if (!rules.hasOwnProperty(ruleName)) continue; const rule = rules[ruleName]; if (rule) { this._rules[ruleName] = lodash_1.merge(this._rules[ruleName], rule); } } } applyRuleDeclarations(declarations) { for (const ruleName in declarations) { if (!declarations.hasOwnProperty(ruleName)) continue; const declaration = declarations[ruleName]; const rule = this.rules[ruleName]; if (rule) { if (typeof declaration === 'boolean') { this._rules[ruleName].enabled = declaration; } } } } } exports.Spectral = Spectral; exports.isParsedResult = (obj) => { if (!obj || typeof obj !== 'object') return false; if (!obj.parsed || typeof obj.parsed !== 'object') return false; if (!obj.getLocationForJsonPath || typeof obj.getLocationForJsonPath !== 'function') return false; return true; }; function formatParserDiagnostics(parsed, source) { return parsed.diagnostics.map(diagnostic => (Object.assign({}, diagnostic, { path: [], source }))); } const prettyPrintResolverError = (message) => message.replace(/^Error\s*:\s*/, ''); const formatResolverErrors = (resolveErrors, result) => { return lodash_1.uniqBy(resolveErrors, 'message').reduce((errors, error) => { const path = [...error.path, '$ref']; const location = result.getLocationForJsonPath(result.parsed, path); if (location) { errors.push({ code: 'invalid-ref', path, message: prettyPrintResolverError(error.message), severity: types_1.DiagnosticSeverity.Error, range: location.range, }); } return errors; }, []); }; //# sourceMappingURL=spectral.js.map