From 111d157ea0db7f14e7ff60192de969f88e1b2fd9 Mon Sep 17 00:00:00 2001 From: Varshitha Besthavemula Date: Sat, 27 Dec 2025 16:33:41 +0530 Subject: [PATCH 1/3] feat: create rule 'asyncapi3-server-variables' for v3 core ruleset --- .../{v2 => }/functions/serverVariables.ts | 2 +- packages/parser/src/ruleset/v2/ruleset.ts | 2 +- packages/parser/src/ruleset/v3/ruleset.ts | 15 ++ .../v3/asyncapi3-server-variables.spec.ts | 154 ++++++++++++++++++ 4 files changed, 171 insertions(+), 2 deletions(-) rename packages/parser/src/ruleset/{v2 => }/functions/serverVariables.ts (98%) create mode 100644 packages/parser/test/ruleset/rules/v3/asyncapi3-server-variables.spec.ts diff --git a/packages/parser/src/ruleset/v2/functions/serverVariables.ts b/packages/parser/src/ruleset/functions/serverVariables.ts similarity index 98% rename from packages/parser/src/ruleset/v2/functions/serverVariables.ts rename to packages/parser/src/ruleset/functions/serverVariables.ts index 921c0ed1d..8380e4757 100644 --- a/packages/parser/src/ruleset/v2/functions/serverVariables.ts +++ b/packages/parser/src/ruleset/functions/serverVariables.ts @@ -1,6 +1,6 @@ import { createRulesetFunction } from '@stoplight/spectral-core'; -import { getMissingProps, getRedundantProps, parseUrlVariables } from '../../utils'; +import { getMissingProps, getRedundantProps, parseUrlVariables } from '../utils'; import type { IFunctionResult } from '@stoplight/spectral-core'; diff --git a/packages/parser/src/ruleset/v2/ruleset.ts b/packages/parser/src/ruleset/v2/ruleset.ts index b03a7549f..fec6a882f 100644 --- a/packages/parser/src/ruleset/v2/ruleset.ts +++ b/packages/parser/src/ruleset/v2/ruleset.ts @@ -12,7 +12,7 @@ import { messageIdUniqueness } from './functions/messageIdUniqueness'; import { operationIdUniqueness } from './functions/operationIdUniqueness'; import { schemaValidation } from './functions/schemaValidation'; import { security } from './functions/security'; -import { serverVariables } from './functions/serverVariables'; +import { serverVariables } from '../functions/serverVariables'; import { unusedSecuritySchemes } from './functions/unusedSecuritySchemes'; import { uniquenessTags } from '../functions/uniquenessTags'; import { asyncApi2SchemaParserRule } from '../../schema-parser/spectral-rule-v2'; diff --git a/packages/parser/src/ruleset/v3/ruleset.ts b/packages/parser/src/ruleset/v3/ruleset.ts index efc719483..397ffed84 100644 --- a/packages/parser/src/ruleset/v3/ruleset.ts +++ b/packages/parser/src/ruleset/v3/ruleset.ts @@ -5,11 +5,26 @@ import { AsyncAPIFormats } from '../formats'; import { operationMessagesUnambiguity } from './functions/operationMessagesUnambiguity'; import { pattern } from '@stoplight/spectral-functions'; import { channelServers } from '../functions/channelServers'; +import { serverVariables } from '../functions/serverVariables'; export const v3CoreRuleset = { description: 'Core AsyncAPI 3.x.x ruleset.', formats: AsyncAPIFormats.filterByMajorVersions(['3']).formats(), rules: { + /** + * Server Object rules + */ + 'asyncapi3-server-variables': { + description: 'Server variables must be defined and there must be no redundant variables.', + message: '{{error}}', + severity: 'error', + recommended: true, + given: ['$.servers.*', '$.components.servers.*'], + then: { + function: serverVariables, + }, + }, + /** * Operation Object rules */ diff --git a/packages/parser/test/ruleset/rules/v3/asyncapi3-server-variables.spec.ts b/packages/parser/test/ruleset/rules/v3/asyncapi3-server-variables.spec.ts new file mode 100644 index 000000000..61d45d2b7 --- /dev/null +++ b/packages/parser/test/ruleset/rules/v3/asyncapi3-server-variables.spec.ts @@ -0,0 +1,154 @@ +import { testRule, DiagnosticSeverity } from '../../tester'; + +testRule('asyncapi3-server-variables', [ + { + name: 'valid case', + document: { + asyncapi: '3.0.0', + servers: { + production: { + url: '{sub}.stoplight.io', + protocol: 'https', + variables: { + sub: {}, + }, + }, + }, + }, + errors: [], + }, + + { + name: 'server has not defined definition for one of the url variables', + document: { + asyncapi: '3.0.0', + servers: { + production: { + url: '{sub}.{anotherParam}.stoplight.io', + protocol: 'https', + variables: { + sub: {}, + }, + }, + }, + }, + errors: [ + { + message: 'Not all server\'s variables are described with "variables" object. Missed: anotherParam.', + path: ['servers', 'production', 'variables'], + severity: DiagnosticSeverity.Error, + }, + ], + }, + + { + name: 'server has not defined definition for two of the url variables', + document: { + asyncapi: '3.0.0', + servers: { + production: { + url: '{sub}.{anotherParam1}.{anotherParam2}.stoplight.io', + protocol: 'https', + variables: { + sub: {}, + }, + }, + }, + }, + errors: [ + { + message: + 'Not all server\'s variables are described with "variables" object. Missed: anotherParam1, anotherParam2.', + path: ['servers', 'production', 'variables'], + severity: DiagnosticSeverity.Error, + }, + ], + }, + + { + name: 'server has not defined definition for one of the url variables (in the components.servers)', + document: { + asyncapi: '3.0.0', + components: { + servers: { + production: { + url: '{sub}.{anotherParam}.stoplight.io', + protocol: 'https', + variables: { + sub: {}, + }, + }, + }, + }, + }, + errors: [ + { + message: 'Not all server\'s variables are described with "variables" object. Missed: anotherParam.', + path: ['components', 'servers', 'production', 'variables'], + severity: DiagnosticSeverity.Error, + }, + ], + }, + + { + name: 'server has redundant url variables', + document: { + asyncapi: '3.0.0', + servers: { + production: { + url: '{sub}.stoplight.io', + protocol: 'https', + variables: { + sub: {}, + anotherParam1: {}, + anotherParam2: {}, + }, + }, + }, + }, + errors: [ + { + message: 'Server\'s "variables" object has redundant defined "anotherParam1" url variable.', + path: ['servers', 'production', 'variables', 'anotherParam1'], + severity: DiagnosticSeverity.Error, + }, + { + message: 'Server\'s "variables" object has redundant defined "anotherParam2" url variable.', + path: ['servers', 'production', 'variables', 'anotherParam2'], + severity: DiagnosticSeverity.Error, + }, + ], + }, + + { + name: 'server has redundant url variables (in the components.servers)', + document: { + asyncapi: '3.0.0', + components: { + servers: { + production: { + url: '{sub}.stoplight.io', + protocol: 'https', + variables: { + sub: {}, + anotherParam1: {}, + anotherParam2: {}, + }, + }, + }, + }, + }, + errors: [ + { + message: 'Server\'s "variables" object has redundant defined "anotherParam1" url variable.', + path: ['components', 'servers', 'production', 'variables', 'anotherParam1'], + severity: DiagnosticSeverity.Error, + }, + { + message: 'Server\'s "variables" object has redundant defined "anotherParam2" url variable.', + path: ['components', 'servers', 'production', 'variables', 'anotherParam2'], + severity: DiagnosticSeverity.Error, + }, + ], + }, +]); From 1a28aa72122e9da2c86b1108d9e01dd36712bcfc Mon Sep 17 00:00:00 2001 From: Varshitha Besthavemula Date: Mon, 12 Jan 2026 19:17:30 +0530 Subject: [PATCH 2/3] add SonarQube rule suppression --- packages/parser/src/ruleset/v3/ruleset.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/parser/src/ruleset/v3/ruleset.ts b/packages/parser/src/ruleset/v3/ruleset.ts index 397ffed84..fca88c709 100644 --- a/packages/parser/src/ruleset/v3/ruleset.ts +++ b/packages/parser/src/ruleset/v3/ruleset.ts @@ -20,7 +20,7 @@ export const v3CoreRuleset = { severity: 'error', recommended: true, given: ['$.servers.*', '$.components.servers.*'], - then: { + then: { //NOSONAR function: serverVariables, }, }, From 5fb995b93d84627a475b3e82e262e27c6e621b20 Mon Sep 17 00:00:00 2001 From: Varshitha Besthavemula Date: Mon, 12 Jan 2026 22:50:33 +0530 Subject: [PATCH 3/3] add changeset --- .changeset/ten-rooms-fly.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/ten-rooms-fly.md diff --git a/.changeset/ten-rooms-fly.md b/.changeset/ten-rooms-fly.md new file mode 100644 index 000000000..bc03e6279 --- /dev/null +++ b/.changeset/ten-rooms-fly.md @@ -0,0 +1,5 @@ +--- +"@asyncapi/parser": minor +--- + +feat: create the rule `asyncapi3-server-variables' for v3 core ruleset