Skip to content

Commit

Permalink
fix: more precise one-api-version-per-document (#7)
Browse files Browse the repository at this point in the history
Co-authored-by: Jakub Rożek <[email protected]>
  • Loading branch information
mnaumanali94 and P0lip authored Apr 4, 2023
1 parent bd613dc commit cbc1ac0
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 19 deletions.
27 changes: 27 additions & 0 deletions __tests__/one-api-version-per-document.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,31 @@ testRule("one-api-version-per-document", [
},
],
},

{
name: "valid: same versions",
document: {
openapi: "3.1.0",
info: { version: "1.0" },
"servers": [
{
"url": "https://stoplight.io/mocks/my-project/docs/12345",
"description": "Mock server Stoplight"
},
{
"url": "http://localhost:3000/v1",
"description": "Local"
},
{
"url": "https://api.dev.site.com/v1",
"description": "Development"
},
{
"url": "https://v1.site.com",
"description": "Production"
}
]
},
errors: [],
},
]);
58 changes: 39 additions & 19 deletions src/functions/onlyOneServerVersion.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,53 @@
import { createRulesetFunction } from '@stoplight/spectral-core';

const VERSION_REGEXP = /^(?:v|version)?([0-9]+)$/i;

function extractVersion(input: string) {
const value = VERSION_REGEXP.exec(input);
if (value !== null) {
return value[1];
}

return;
}

function isNonNullable<T>(value: T): value is NonNullable<T> {
return value !== null && value !== undefined;
}

/**
* @author Phil Sturgeon <https://github.com/philsturgeon>
*/
export default createRulesetFunction({
input: null,
options: {
type: ['null'],
export default createRulesetFunction<{ url: string }[], null>({
input: {
type: 'array',
items: {
type: 'object',
properties: {
url: {
type: 'string',
format: 'url',
}
},
required: ['url'],
}
},
}, (targetVal: Array<any>) => {

if (! Array.isArray(targetVal)) {
return [];
}
options: null,
}, (targetVal) => {

// Map through all the servers and see if they have versions, and if they do push them into a list
const versionsMatches = targetVal.reduce((result, { url }: any) => {
const matches = url.match(/([\\.|\\/|](v|version)?[0-9]{1,3}(?:\/)?)/i);
if (matches) {
result.push(matches[0]);
}
const versionsMatches = targetVal.reduce<string[]>((result, { url}) => {
const parsedUrl = new URL(url);
const versions = [
...parsedUrl.host.split('.'),
...parsedUrl.pathname.split('/'),
].map(extractVersion);

result.push(...versions.filter(isNonNullable));

return result;
}, []);

// No versions, thats easy.
if (versionsMatches === null || typeof versionsMatches === 'undefined') {
return [];
}

// If there are fewer than two versions mentioned there cannot be multiple versions
if (versionsMatches.length < 2) {
return [];
Expand Down

0 comments on commit cbc1ac0

Please sign in to comment.