Skip to content

Commit

Permalink
added rules for channel-server v3
Browse files Browse the repository at this point in the history
  • Loading branch information
ibishal committed Jul 2, 2024
1 parent f7feb39 commit 1bcd063
Show file tree
Hide file tree
Showing 3 changed files with 278 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/ruleset/v3/functions/channelServer3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { createRulesetFunction } from '@stoplight/spectral-core';
import type { IFunctionResult } from '@stoplight/spectral-core';

export const channelServers3 = createRulesetFunction<
{ servers?: Record<string, unknown>; channels?: Record<string, { servers?: Array<{ $ref: string }> }> },
null
>(
{
input: {
type: 'object',
properties: {
servers: {
type: 'object',
},
channels: {
type: 'object',
additionalProperties: {
type: 'object',
properties: {
servers: {
type: 'array',
items: {
type: 'object',
required: ['$ref'],
properties: {
$ref: { type: 'string' },
},
},
},
},
},
},
},
},
options: null,
},
(targetVal) => {
console.log('channelServers function called with:', JSON.stringify(targetVal, null, 2));
const results: IFunctionResult[] = [];
if (!targetVal.channels) return results;

Object.entries(targetVal.channels ?? {}).forEach(([channelAddress, channel]) => {
if (!channel.servers) return;

channel.servers.forEach((serverRef, index) => {
if (!serverRef.$ref.startsWith('#/servers/')) {
results.push({
message: 'Channel server must reference a server defined in the root "servers" object.',
path: ['channels', channelAddress, 'servers', index, '$ref'],
});
}
});
});
console.log('channelServers function returning results:', results);
return results;
},
);
11 changes: 11 additions & 0 deletions src/ruleset/v3/ruleset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { AsyncAPIFormats } from '../formats';
import { operationMessagesUnambiguity } from './functions/operationMessagesUnambiguity';
import { channelServers3 } from './functions/channelServers3';
import { pattern } from '@stoplight/spectral-functions';

export const v3CoreRuleset = {
Expand Down Expand Up @@ -56,6 +57,16 @@ export const v3CoreRuleset = {
match: '#\\/servers\\/', // If doesn't match, rule fails.
},
},
},
'asyncapi3-channel-servers': {
description: 'Channel servers must be defined in the root "servers" object.',
message: '{{error}}',
severity: 'error',
recommended: true,
given: '$',
then: {
function: channelServers3,
},
}
},
};
210 changes: 210 additions & 0 deletions test/ruleset/rules/v3/asyncapi3-channel-server.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { testRule, DiagnosticSeverity } from '../../tester';

testRule('asyncapi3-channel-servers', [
{
name: 'valid case',
document: {
asyncapi: '3.0.0',
servers: {
development: {},
production: {},
},
channels: {
channel: {
servers: [{ $ref: '#/servers/development' }],
},
},
},
errors: [],
},

{
name: 'valid case - multiple servers',
document: {
asyncapi: '3.0.0',
servers: {
development: {},
production: {},
staging: {},
},
channels: {
channel: {
servers: [
{ $ref: '#/servers/development' },
{ $ref: '#/servers/production' },
],
},
},
},
errors: [],
},

{
name: 'valid case - without defined servers',
document: {
asyncapi: '3.0.0',
servers: {
development: {},
production: {},
},
channels: {
channel: {},
},
},
errors: [],
},

{
name: 'valid case - without defined servers in the root',
document: {
asyncapi: '3.0.0',
channels: {
channel: {},
},
},
errors: [],
},

{
name: 'valid case - without defined channels in the root',
document: {
asyncapi: '3.0.0',
servers: {
development: {},
production: {},
},
},
errors: [],
},

{
name: 'valid case - with empty array',
document: {
asyncapi: '3.0.0',
servers: {
development: {},
production: {},
},
channels: {
channel: {
servers: [],
},
},
},
errors: [],
},

{
name: 'invalid case - incorrect $ref',
document: {
asyncapi: '3.0.0',
servers: {
development: {},
production: {},
},
channels: {
channel: {
servers: [{ $ref: '#/components/servers/another-server' }],
},
},
},
errors: [
{
message: 'Channel server must reference a server defined in the root "servers" object.',
path: ['channels', 'channel', 'servers', '0', '$ref'],
severity: DiagnosticSeverity.Error,
},
],
},

{
name: 'invalid case - one server is correct, another one is incorrect',
document: {
asyncapi: '3.0.0',
servers: {
development: {},
production: {},
},
channels: {
channel: {
servers: [
{ $ref: '#/servers/production' },
{ $ref: '#/components/servers/another-server' },
],
},
},
},
errors: [
{
message: 'Channel server must reference a server defined in the root "servers" object.',
path: ['channels', 'channel', 'servers', '1', '$ref'],
severity: DiagnosticSeverity.Error,
},
],
},

{
name: 'invalid case - without defined servers',
document: {
asyncapi: '3.0.0',
channels: {
channel: {
servers: [{ $ref: '#/servers/production' }],
},
},
},
errors: [
{
message: 'Channel server must reference a server defined in the root "servers" object.',
path: ['channels', 'channel', 'servers', '0', '$ref'],
severity: DiagnosticSeverity.Error,
},
],
},

{
name: 'invalid case - incorrect $ref format',
document: {
asyncapi: '3.0.0',
servers: {
development: {},
production: {},
},
channels: {
channel: {
servers: [{ $ref: 'production' }],
},
},
},
errors: [
{
message: 'Channel server must reference a server defined in the root "servers" object.',
path: ['channels', 'channel', 'servers', '0', '$ref'],
severity: DiagnosticSeverity.Error,
},
],
},

{
name: 'invalid case - servers is not an array',
document: {
asyncapi: '3.0.0',
servers: {
development: {},
production: {},
},
channels: {
channel: {
servers: { $ref: '#/servers/production' },
},
},
},
errors: [
{
message: 'Channel servers must be an array of references to servers.',
path: ['channels', 'channel', 'servers'],
severity: DiagnosticSeverity.Error,
},
],
},
]);

0 comments on commit 1bcd063

Please sign in to comment.