From 72c4c077133b27bf6f4d80fe739ae2a1936354fc Mon Sep 17 00:00:00 2001 From: Roman Hotsiy Date: Mon, 25 Nov 2024 20:10:04 +0800 Subject: [PATCH] fix: resolve problem with severity change for configurable rules (#1811) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: resolve problem with severity change for configurable rules * chore: update snapshots * Update .changeset/fuzzy-crews-boil.md * Update .changeset/fuzzy-crews-boil.md * chore: review comments --------- Co-authored-by: Jacek Łękawa <164185257+JLekawa@users.noreply.github.com> --- .changeset/fuzzy-crews-boil.md | 6 ++ .../config-resolvers.test.ts.snap | 10 ++- .../core/src/config/__tests__/utils.test.ts | 21 +++++ packages/core/src/config/utils.ts | 85 ++++++++++--------- packages/core/src/utils.ts | 25 +++++- 5 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 .changeset/fuzzy-crews-boil.md diff --git a/.changeset/fuzzy-crews-boil.md b/.changeset/fuzzy-crews-boil.md new file mode 100644 index 0000000000..f73c1287be --- /dev/null +++ b/.changeset/fuzzy-crews-boil.md @@ -0,0 +1,6 @@ +--- +"@redocly/openapi-core": patch +"@redocly/cli": patch +--- + +Resolved an issue where overrides for the severity of configurable rules were ignored. diff --git a/packages/core/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap b/packages/core/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap index d28851a81c..049cd5a681 100644 --- a/packages/core/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +++ b/packages/core/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap @@ -63,7 +63,10 @@ exports[`resolveConfig should ignore minimal from the root and read local file 1 "component-name-unique": "off", "no-empty-servers": "error", "no-example-value-and-externalValue": "error", - "no-invalid-media-type-examples": "error", + "no-invalid-media-type-examples": { + "allowAdditionalProperties": false, + "severity": "error", + }, "no-server-example.com": "warn", "no-server-trailing-slash": "error", "no-server-variables-empty-enum": "error", @@ -208,7 +211,10 @@ exports[`resolveStyleguideConfig should resolve extends with local file config w "component-name-unique": "off", "no-empty-servers": "error", "no-example-value-and-externalValue": "error", - "no-invalid-media-type-examples": "warn", + "no-invalid-media-type-examples": { + "allowAdditionalProperties": false, + "severity": "warn", + }, "no-server-example.com": "warn", "no-server-trailing-slash": "error", "no-server-variables-empty-enum": "error", diff --git a/packages/core/src/config/__tests__/utils.test.ts b/packages/core/src/config/__tests__/utils.test.ts index cd5c6b1d1c..b775d82025 100644 --- a/packages/core/src/config/__tests__/utils.test.ts +++ b/packages/core/src/config/__tests__/utils.test.ts @@ -202,3 +202,24 @@ describe('transformConfig', () => { }); }); }); + +describe('mergeExtends', () => { + it('should work with empty extends', () => { + expect(utils.mergeExtends([]).rules).toEqual({}); + }); + + it('should work with configurable rules changing severity', () => { + expect( + utils.mergeExtends([ + { + rules: { 'rule/abc': { severity: 'error', subject: 'Operation' } }, + }, + { + rules: { 'rule/abc': 'warn' }, + }, + ]).rules + ).toEqual({ + 'rule/abc': { severity: 'warn', subject: 'Operation' }, + }); + }); +}); diff --git a/packages/core/src/config/utils.ts b/packages/core/src/config/utils.ts index 92904d4e29..13a64833ac 100644 --- a/packages/core/src/config/utils.ts +++ b/packages/core/src/config/utils.ts @@ -1,5 +1,6 @@ import { - assignExisting, + assignOnlyExistingConfig, + assignConfig, isDefined, isTruthy, showErrorForDeprecatedField, @@ -198,47 +199,47 @@ export function mergeExtends(rulesConfList: ResolvedStyleguideConfig[]) { ); } - Object.assign(result.rules, rulesConf.rules); - Object.assign(result.oas2Rules, rulesConf.oas2Rules); - assignExisting(result.oas2Rules, rulesConf.rules || {}); - Object.assign(result.oas3_0Rules, rulesConf.oas3_0Rules); - assignExisting(result.oas3_0Rules, rulesConf.rules || {}); - Object.assign(result.oas3_1Rules, rulesConf.oas3_1Rules); - assignExisting(result.oas3_1Rules, rulesConf.rules || {}); - Object.assign(result.async2Rules, rulesConf.async2Rules); - assignExisting(result.async2Rules, rulesConf.rules || {}); - Object.assign(result.async3Rules, rulesConf.async3Rules); - assignExisting(result.async3Rules, rulesConf.rules || {}); - Object.assign(result.arazzoRules, rulesConf.arazzoRules); - assignExisting(result.arazzoRules, rulesConf.rules || {}); - - Object.assign(result.preprocessors, rulesConf.preprocessors); - Object.assign(result.oas2Preprocessors, rulesConf.oas2Preprocessors); - assignExisting(result.oas2Preprocessors, rulesConf.preprocessors || {}); - Object.assign(result.oas3_0Preprocessors, rulesConf.oas3_0Preprocessors); - assignExisting(result.oas3_0Preprocessors, rulesConf.preprocessors || {}); - Object.assign(result.oas3_1Preprocessors, rulesConf.oas3_1Preprocessors); - assignExisting(result.oas3_1Preprocessors, rulesConf.preprocessors || {}); - Object.assign(result.async2Preprocessors, rulesConf.async2Preprocessors); - assignExisting(result.async2Preprocessors, rulesConf.preprocessors || {}); - Object.assign(result.async3Preprocessors, rulesConf.async3Preprocessors); - assignExisting(result.async3Preprocessors, rulesConf.preprocessors || {}); - Object.assign(result.arazzoPreprocessors, rulesConf.arazzoPreprocessors); - assignExisting(result.arazzoPreprocessors, rulesConf.preprocessors || {}); - - Object.assign(result.decorators, rulesConf.decorators); - Object.assign(result.oas2Decorators, rulesConf.oas2Decorators); - assignExisting(result.oas2Decorators, rulesConf.decorators || {}); - Object.assign(result.oas3_0Decorators, rulesConf.oas3_0Decorators); - assignExisting(result.oas3_0Decorators, rulesConf.decorators || {}); - Object.assign(result.oas3_1Decorators, rulesConf.oas3_1Decorators); - assignExisting(result.oas3_1Decorators, rulesConf.decorators || {}); - Object.assign(result.async2Decorators, rulesConf.async2Decorators); - assignExisting(result.async2Decorators, rulesConf.decorators || {}); - Object.assign(result.async3Decorators, rulesConf.async3Decorators); - assignExisting(result.async3Decorators, rulesConf.decorators || {}); - Object.assign(result.arazzoDecorators, rulesConf.arazzoDecorators); - assignExisting(result.arazzoDecorators, rulesConf.decorators || {}); + assignConfig(result.rules, rulesConf.rules); + assignConfig(result.oas2Rules, rulesConf.oas2Rules); + assignOnlyExistingConfig(result.oas2Rules, rulesConf.rules); + assignConfig(result.oas3_0Rules, rulesConf.oas3_0Rules); + assignOnlyExistingConfig(result.oas3_0Rules, rulesConf.rules); + assignConfig(result.oas3_1Rules, rulesConf.oas3_1Rules); + assignOnlyExistingConfig(result.oas3_1Rules, rulesConf.rules); + assignConfig(result.async2Rules, rulesConf.async2Rules); + assignOnlyExistingConfig(result.async2Rules, rulesConf.rules); + assignConfig(result.async3Rules, rulesConf.async3Rules); + assignOnlyExistingConfig(result.async3Rules, rulesConf.rules); + assignConfig(result.arazzoRules, rulesConf.arazzoRules); + assignOnlyExistingConfig(result.arazzoRules, rulesConf.rules); + + assignConfig(result.preprocessors, rulesConf.preprocessors); + assignConfig(result.oas2Preprocessors, rulesConf.oas2Preprocessors); + assignOnlyExistingConfig(result.oas2Preprocessors, rulesConf.preprocessors); + assignConfig(result.oas3_0Preprocessors, rulesConf.oas3_0Preprocessors); + assignOnlyExistingConfig(result.oas3_0Preprocessors, rulesConf.preprocessors); + assignConfig(result.oas3_1Preprocessors, rulesConf.oas3_1Preprocessors); + assignOnlyExistingConfig(result.oas3_1Preprocessors, rulesConf.preprocessors); + assignConfig(result.async2Preprocessors, rulesConf.async2Preprocessors); + assignOnlyExistingConfig(result.async2Preprocessors, rulesConf.preprocessors); + assignConfig(result.async3Preprocessors, rulesConf.async3Preprocessors); + assignOnlyExistingConfig(result.async3Preprocessors, rulesConf.preprocessors); + assignConfig(result.arazzoPreprocessors, rulesConf.arazzoPreprocessors); + assignOnlyExistingConfig(result.arazzoPreprocessors, rulesConf.preprocessors); + + assignConfig(result.decorators, rulesConf.decorators); + assignConfig(result.oas2Decorators, rulesConf.oas2Decorators); + assignOnlyExistingConfig(result.oas2Decorators, rulesConf.decorators); + assignConfig(result.oas3_0Decorators, rulesConf.oas3_0Decorators); + assignOnlyExistingConfig(result.oas3_0Decorators, rulesConf.decorators); + assignConfig(result.oas3_1Decorators, rulesConf.oas3_1Decorators); + assignOnlyExistingConfig(result.oas3_1Decorators, rulesConf.decorators); + assignConfig(result.async2Decorators, rulesConf.async2Decorators); + assignOnlyExistingConfig(result.async2Decorators, rulesConf.decorators); + assignConfig(result.async3Decorators, rulesConf.async3Decorators); + assignOnlyExistingConfig(result.async3Decorators, rulesConf.decorators); + assignConfig(result.arazzoDecorators, rulesConf.arazzoDecorators); + assignOnlyExistingConfig(result.arazzoDecorators, rulesConf.decorators); result.plugins!.push(...(rulesConf.plugins || [])); result.pluginPaths!.push(...(rulesConf.pluginPaths || [])); diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index 994319dded..bce689d998 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -196,9 +196,30 @@ export function isNotString(value: string | T): value is T { return !isString(value); } -export function assignExisting(target: Record, obj: Record) { +export const assignConfig = ( + target: Record, + obj?: Record +) => { + if (!obj) return; for (const k of Object.keys(obj)) { - if (target.hasOwnProperty(k)) { + if (isPlainObject(target[k]) && typeof obj[k] === 'string') { + target[k].severity = obj[k]; + } else { + target[k] = obj[k]; + } + } +}; + +export function assignOnlyExistingConfig( + target: Record, + obj?: Record +) { + if (!obj) return; + for (const k of Object.keys(obj)) { + if (!target.hasOwnProperty(k)) continue; + if (isPlainObject(target[k]) && typeof obj[k] === 'string') { + target[k].severity = obj[k]; + } else { target[k] = obj[k]; } }