Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apidom/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions apidom/packages/apidom-ns-openapi-3-1/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@babel/runtime-corejs3": "=7.12.5",
"minim": "=0.23.8",
"ramda": "=0.27.0",
"ramda-adjunct": "=2.27.0",
"@types/ramda": "=0.27.6",
"apidom": "file:../apidom"
}
Expand Down
1 change: 1 addition & 0 deletions apidom/packages/apidom-ns-openapi-3-1/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export {
isPathItemElement,
isPathsElement,
isReferenceElement,
isReferenceElementExternal,
isRequestBodyElement,
isResponseElement,
isResponsesElement,
Expand Down
13 changes: 12 additions & 1 deletion apidom/packages/apidom-ns-openapi-3-1/src/predicates.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { allPass, either, is } from 'ramda';
import { allPass, either, is, startsWith } from 'ramda';
import { isNonEmptyString } from 'ramda-adjunct';
import { createPredicate } from 'apidom';

import CallbackElement from './elements/Callback';
Expand Down Expand Up @@ -180,6 +181,16 @@ export const isReferenceElement = createPredicate(
},
);

export const isReferenceElementExternal = (element: any): element is ReferenceElement => {
if (!isReferenceElement(element)) {
return false;
}

const value = element.$ref.toValue();

return isNonEmptyString(value) && !startsWith('#', value);
};

export const isRequestBodyElement = createPredicate(
({ hasBasicElementProps, isElementType, primitiveEq }) => {
const isElementTypeRequestBody = isElementType('requestBody');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
isReferenceLikeElement,
keyMap,
ReferenceElement,
isReferenceElementExternal,
} from 'apidom-ns-openapi-3-1';

import { Reference as IReference } from '../../../types';
Expand Down Expand Up @@ -68,6 +69,11 @@ const OpenApi3_1DereferenceVisitor = stampit({
},

async ReferenceElement(referenceElement: ReferenceElement) {
// ignore resolving external Reference Objects
if (!this.options.resolve.external && isReferenceElementExternal(referenceElement)) {
return false;
}

// @ts-ignore
const reference = await this.toReference(referenceElement.$ref.toValue());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
isReferenceLikeElement,
keyMap,
ReferenceElement,
isReferenceElementExternal,
} from 'apidom-ns-openapi-3-1';

import { Reference as IReference } from '../../../types';
Expand Down Expand Up @@ -78,13 +79,20 @@ const OpenApi3_1ResolveVisitor = stampit({
},

ReferenceElement(referenceElement: ReferenceElement) {
// ignore resolving external Reference Objects
if (!this.options.resolve.external && isReferenceElementExternal(referenceElement)) {
return false;
}

const uri = referenceElement.$ref.toValue();
const baseURI = this.toBaseURI(uri);

if (!has(baseURI, this.crawlingMap)) {
this.crawlingMap[baseURI] = this.toReference(uri);
}
this.crawledElements.push(referenceElement);

return undefined;
},

async crawlReferenceElement(referenceElement: ReferenceElement) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[
{
"openapi": "3.1.0",
"components": {
"parameters": {
"userId": {
"name": "userId",
"in": "query",
"description": "override",
"required": true
},
"indirection1": {
"name": "userId",
"in": "query",
"description": "ID of the user",
"required": true
},
"indirection2": {
"name": "userId",
"in": "query",
"description": "ID of the user",
"required": true
},
"userIdRef": {
"name": "userId",
"in": "query",
"description": "ID of the user",
"required": true
},
"externalRef": {
"$ref": "./ex.json#/externalParameter",
"description": "another ref"
}
}
}
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"externalParameter": {
"name": "externalParameter",
"in": "query",
"description": "this is parameter stored in external file",
"required": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"openapi": "3.1.0",
"components": {
"parameters": {
"userId": {
"$ref": "#/components/parameters/indirection1",
"description": "override"
},
"indirection1": {
"$ref": "#/components/parameters/indirection2",
"summary": "indirect summary"
},
"indirection2": {
"$ref": "#/components/parameters/userIdRef",
"summary": "indirect summary"
},
"userIdRef": {
"name": "userId",
"in": "query",
"description": "ID of the user",
"required": true
},
"externalRef": {
"$ref": "./ex.json#/externalParameter",
"description": "another ref"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,21 @@ describe('dereference', function () {
});
});

context('given Reference Objects with external resolution disabled', function () {
const fixturePath = path.join(rootFixturePath, 'ignore-external');

specify('should dereference', async function () {
const rootFilePath = path.join(fixturePath, 'root.json');
const actual = await dereference(rootFilePath, {
parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
resolve: { external: false },
});
const expected = loadJsonFile(path.join(fixturePath, 'dereferenced.json'));

assert.deepEqual(toValue(actual), expected);
});
});

context('given Reference Objects with direct circular internal reference', function () {
const fixturePath = path.join(rootFixturePath, 'direct-internal-circular');

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"externalParameter": {
"name": "externalParameter",
"in": "query",
"description": "this is parameter stored in external file",
"required": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"openapi": "3.1.0",
"components": {
"parameters": {
"userId": {
"$ref": "#/components/parameters/indirection1",
"description": "override"
},
"indirection1": {
"$ref": "#/components/parameters/indirection2",
"summary": "indirect summary"
},
"indirection2": {
"$ref": "#/components/parameters/userIdRef",
"summary": "indirect summary"
},
"userIdRef": {
"name": "userId",
"in": "query",
"description": "ID of the user",
"required": true
},
"externalRef": {
"$ref": "./ex.json#/externalParameter",
"description": "another ref"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,20 @@ describe('resolve', function () {
});
});

context('given Reference Objects with external resolution disable', function () {
const fixturePath = path.join(rootFixturePath, 'ignore-external');

specify('should resolve', async function () {
const rootFilePath = path.join(fixturePath, 'root.json');
const refSet = await resolve(rootFilePath, {
parse: { mediaType: 'application/vnd.oai.openapi+json;version=3.1.0' },
resolve: { external: false },
});

assert.strictEqual(refSet.size, 1);
});
});

context('given Reference Objects with direct circular internal reference', function () {
const fixturePath = path.join(rootFixturePath, 'direct-internal-circular');

Expand Down