ut-tools
Version:
Build and Release management automation package.
240 lines • 11.1 kB
JavaScript
"use strict";
var _Ruleset_instances, _Ruleset_context, _Ruleset_getRules;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Ruleset = void 0;
const tslib_1 = require("tslib");
const path_1 = require("@stoplight/path");
const json_1 = require("@stoplight/json");
const minimatch_1 = require("./utils/minimatch");
const rule_1 = require("./rule");
const index_1 = require("./validation/index");
const rules_1 = require("./mergers/rules");
const __1 = require("..");
const rulesets_1 = require("./mergers/rulesets");
const formats_1 = require("./formats");
const guards_1 = require("./utils/guards");
const STACK_SYMBOL = Symbol('@stoplight/spectral/ruleset/#stack');
const EXPLICIT_SEVERITY = Symbol('@stoplight/spectral/ruleset/#explicit-severity');
const DEFAULT_RULESET_FILE = /^\.?spectral\.(ya?ml|json|m?js)$/;
let SEED = 1;
class Ruleset {
constructor(maybeDefinition, context) {
var _a;
this.maybeDefinition = maybeDefinition;
_Ruleset_instances.add(this);
this.id = SEED++;
this.formats = new formats_1.Formats();
_Ruleset_context.set(this, void 0);
let definition;
if ((0, json_1.isPlainObject)(maybeDefinition) && 'extends' in maybeDefinition) {
const { extends: _, ...def } = maybeDefinition;
(0, index_1.assertValidRuleset)({ extends: [], ...def }, 'js');
definition = maybeDefinition;
}
else {
(0, index_1.assertValidRuleset)(maybeDefinition, 'js');
definition = maybeDefinition;
}
this.definition = definition;
(0, tslib_1.__classPrivateFieldSet)(this, _Ruleset_context, {
severity: 'recommended',
...context,
}, "f");
let hasComplexAliases = false;
this.aliases =
definition.aliases === void 0
? null
: Object.fromEntries(Object.entries(definition.aliases).map(alias => {
const [name, value] = alias;
if ((0, guards_1.isSimpleAliasDefinition)(value)) {
return alias;
}
hasComplexAliases = true;
const targets = value.targets.map(target => ({
formats: new formats_1.Formats(target.formats),
given: target.given,
}));
return [name, { ...value, targets }];
}));
this.hasComplexAliases = hasComplexAliases;
const stack = (_a = context === null || context === void 0 ? void 0 : context[STACK_SYMBOL]) !== null && _a !== void 0 ? _a : new Map();
stack.set(this.definition, this);
this.extends =
'extends' in definition
? (Array.isArray(definition.extends) ? definition.extends : [definition.extends]).reduce((extensions, extension) => {
let actualExtension;
let severity = 'recommended';
const explicitSeverity = Array.isArray(extension);
if (explicitSeverity) {
[actualExtension, severity] = extension;
}
else {
actualExtension = extension;
}
const existingInstance = stack.get(actualExtension);
if (existingInstance !== void 0) {
return extensions;
}
extensions.push(new Ruleset(actualExtension, {
severity,
[STACK_SYMBOL]: stack,
[EXPLICIT_SEVERITY]: explicitSeverity,
}));
return extensions;
}, [])
: null;
if (stack.size === 1 && definition.overrides) {
this.overrides = definition.overrides;
}
else {
this.overrides = null;
}
stack.delete(this.definition);
if (Array.isArray(this.definition.formats)) {
for (const format of this.definition.formats) {
this.formats.add(format);
}
}
if (Array.isArray(this.extends)) {
for (const { formats } of this.extends) {
for (const format of formats) {
this.formats.add(format);
}
}
}
this.rules = (0, tslib_1.__classPrivateFieldGet)(this, _Ruleset_instances, "m", _Ruleset_getRules).call(this);
}
get source() {
var _a;
return (_a = (0, tslib_1.__classPrivateFieldGet)(this, _Ruleset_context, "f").source) !== null && _a !== void 0 ? _a : null;
}
fromSource(source) {
if (this.overrides === null) {
return this;
}
const { source: rulesetSource } = this;
if (source === null) {
throw new Error('Document must have some source assigned. If you use Spectral programmatically make sure to pass the source to Document');
}
if (rulesetSource === null) {
throw new Error('Ruleset must have some source assigned. If you use Spectral programmatically make sure to pass the source to Ruleset');
}
const relativeSource = (0, path_1.relative)((0, path_1.dirname)(rulesetSource), source);
const pointerOverrides = {};
const overrides = this.overrides.flatMap(({ files, ...ruleset }) => {
var _a, _b;
const filteredFiles = [];
for (const pattern of files) {
const actualPattern = (_a = (0, json_1.extractSourceFromRef)(pattern)) !== null && _a !== void 0 ? _a : pattern;
if (!(0, minimatch_1.minimatch)(relativeSource, actualPattern))
continue;
const pointer = (0, json_1.extractPointerFromRef)(pattern);
if (actualPattern === pattern) {
filteredFiles.push(pattern);
}
else if (!('rules' in ruleset) || pointer === null) {
throw new Error('Unknown error. The ruleset is presumably invalid.');
}
else {
for (const [ruleName, rule] of Object.entries(ruleset.rules)) {
if (typeof rule === 'object' || typeof rule === 'boolean') {
throw new Error('Unknown error. The ruleset is presumably invalid.');
}
const { definition: rulePointerOverrides } = ((_b = pointerOverrides[ruleName]) !== null && _b !== void 0 ? _b : (pointerOverrides[ruleName] = {
rulesetSource,
definition: new Map(),
}));
const severity = (0, __1.getDiagnosticSeverity)(rule);
let sourceRulePointerOverrides = rulePointerOverrides.get(actualPattern);
if (sourceRulePointerOverrides === void 0) {
sourceRulePointerOverrides = new Map();
rulePointerOverrides.set(actualPattern, sourceRulePointerOverrides);
}
sourceRulePointerOverrides.set(pointer, severity);
}
}
}
return filteredFiles.length === 0 ? [] : ruleset;
});
const { overrides: _, ...definition } = this.definition;
if (overrides.length === 0 && Object.keys(pointerOverrides).length === 0) {
return this;
}
const mergedOverrides = overrides.length === 0
? null
: overrides.length > 1
? overrides
.slice(1)
.reduce((left, right) => (0, rulesets_1.mergeRulesets)(left, right, true), overrides[0])
: overrides[0];
const ruleset = new Ruleset(mergedOverrides === null ? definition : (0, rulesets_1.mergeRulesets)(definition, mergedOverrides, false), {
severity: 'recommended',
source: rulesetSource,
});
for (const [ruleName, rulePointerOverrides] of Object.entries(pointerOverrides)) {
if (ruleName in ruleset.rules) {
ruleset.rules[ruleName].overrides = rulePointerOverrides;
}
}
return ruleset;
}
get parserOptions() {
return { ...__1.DEFAULT_PARSER_OPTIONS, ...this.definition.parserOptions };
}
static isDefaultRulesetFile(uri) {
return DEFAULT_RULESET_FILE.test(uri);
}
toJSON() {
return {
id: this.id,
extends: this.extends,
source: this.source,
aliases: this.aliases,
formats: this.formats.size === 0 ? null : this.formats,
rules: this.rules,
overrides: this.overrides,
parserOptions: this.parserOptions,
};
}
}
exports.Ruleset = Ruleset;
_Ruleset_context = new WeakMap(), _Ruleset_instances = new WeakSet(), _Ruleset_getRules = function _Ruleset_getRules() {
const rules = {};
if (this.extends !== null && this.extends.length > 0) {
for (const extendedRuleset of this.extends) {
if (extendedRuleset === this)
continue;
for (const rule of Object.values(extendedRuleset.rules)) {
rules[rule.name] = rule;
if ((0, tslib_1.__classPrivateFieldGet)(this, _Ruleset_context, "f")[STACK_SYMBOL] !== void 0 && (0, tslib_1.__classPrivateFieldGet)(this, _Ruleset_context, "f")[EXPLICIT_SEVERITY] === true) {
rule.enabled = rule_1.Rule.isEnabled(rule, (0, tslib_1.__classPrivateFieldGet)(this, _Ruleset_context, "f").severity);
}
}
}
}
if ('rules' in this.definition) {
for (const [name, definition] of Object.entries(this.definition.rules)) {
const rule = (0, rules_1.mergeRule)(rules[name], name, definition, this);
rules[name] = rule;
if (rule.owner === this) {
rule.enabled = rule_1.Rule.isEnabled(rule, (0, tslib_1.__classPrivateFieldGet)(this, _Ruleset_context, "f").severity);
}
if (rule.formats !== null) {
for (const format of rule.formats) {
this.formats.add(format);
}
}
else if (rule.owner !== this) {
rule.formats = rule.owner.definition.formats === void 0 ? null : new formats_1.Formats(rule.owner.definition.formats);
}
else if (this.definition.formats !== void 0) {
rule.formats = new formats_1.Formats(this.definition.formats);
}
if (this.definition.documentationUrl !== void 0 && rule.documentationUrl === null) {
rule.documentationUrl = `${this.definition.documentationUrl}#${name}`;
}
}
}
return rules;
};
//# sourceMappingURL=ruleset.js.map