From 9d005dbb8d283465d77cc23377783b39549dadeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Gorej?= Date: Thu, 7 Mar 2024 12:31:44 +0100 Subject: [PATCH] feat(reference): add support for skipping internal references in OpenAPI 3.1.0 dereference strategy (#3906) Refs #3451 --- .../strategies/openapi-3-1/visitor.ts | 60 ++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts b/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts index 52b4837e20..742b146f84 100644 --- a/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts +++ b/packages/apidom-reference/src/dereference/strategies/openapi-3-1/visitor.ts @@ -154,9 +154,16 @@ const OpenApi3_1DereferenceVisitor = stampit({ } const retrievalURI = this.toBaseURI(toValue(referencingElement.$ref)); + const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI; + const isExternalReference = !isInternalReference; + // ignore resolving internal Reference Objects + if (!this.options.resolve.internal && isInternalReference) { + // skip traversing this reference element and all it's child elements + return false; + } // ignore resolving external Reference Objects - if (!this.options.resolve.external && url.stripHash(this.reference.uri) !== retrievalURI) { + if (!this.options.resolve.external && isExternalReference) { // skip traversing this reference element and all it's child elements return false; } @@ -303,9 +310,16 @@ const OpenApi3_1DereferenceVisitor = stampit({ } const retrievalURI = this.toBaseURI(toValue(referencingElement.$ref)); + const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI; + const isExternalReference = !isInternalReference; // ignore resolving external Path Item Objects - if (!this.options.resolve.external && url.stripHash(this.reference.uri) !== retrievalURI) { + if (!this.options.resolve.internal && isInternalReference) { + // skip traversing this Path Item element but traverse all it's child elements + return undefined; + } + // ignore resolving external Path Item Objects + if (!this.options.resolve.external && isExternalReference) { // skip traversing this Path Item element but traverse all it's child elements return undefined; } @@ -436,9 +450,16 @@ const OpenApi3_1DereferenceVisitor = stampit({ // possibly non-semantic referenced element const jsonPointer = uriToPointer(toValue(linkElement.operationRef)); const retrievalURI = this.toBaseURI(toValue(linkElement.operationRef)); + const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI; + const isExternalReference = !isInternalReference; + // ignore resolving internal Operation Object reference + if (!this.options.resolve.internal && isInternalReference) { + // skip traversing this Link element but traverse all it's child elements + return undefined; + } // ignore resolving external Operation Object reference - if (!this.options.resolve.external && url.stripHash(this.reference.uri) !== retrievalURI) { + if (!this.options.resolve.external && isExternalReference) { // skip traversing this Link element but traverse all it's child elements return undefined; } @@ -515,9 +536,16 @@ const OpenApi3_1DereferenceVisitor = stampit({ } const retrievalURI = this.toBaseURI(toValue(exampleElement.externalValue)); + const isInternalReference = url.stripHash(this.reference.uri) === retrievalURI; + const isExternalReference = !isInternalReference; + // ignore resolving internal Example Objects + if (!this.options.resolve.internal && isInternalReference) { + // skip traversing this Example element but traverse all it's child elements + return undefined; + } // ignore resolving external Example Objects - if (!this.options.resolve.external && url.stripHash(this.reference.uri) !== retrievalURI) { + if (!this.options.resolve.external && isExternalReference) { // skip traversing this Example element but traverse all it's child elements return undefined; } @@ -562,7 +590,8 @@ const OpenApi3_1DereferenceVisitor = stampit({ const file = File({ uri: $refBaseURIStrippedHash }); const isUnknownURI = none((r: IResolver) => r.canRead(file), this.options.resolve.resolvers); const isURL = !isUnknownURI; - const isExternalURL = (uri: string) => url.stripHash(this.reference.uri) !== uri; + const isInternalReference = (uri: string) => url.stripHash(this.reference.uri) === uri; + const isExternalReference = (uri: string) => !isInternalReference(uri); this.indirections.push(referencingElement); @@ -582,8 +611,13 @@ const OpenApi3_1DereferenceVisitor = stampit({ // we're assuming here that we're dealing with JSON Pointer here retrievalURI = this.toBaseURI(toValue($refBaseURI)); + // ignore resolving internal Schema Objects + if (!this.options.resolve.internal && isInternalReference(retrievalURI)) { + // skip traversing this schema element but traverse all it's child elements + return undefined; + } // ignore resolving external Schema Objects - if (!this.options.resolve.external && isExternalURL(retrievalURI)) { + if (!this.options.resolve.external && isExternalReference(retrievalURI)) { // skip traversing this schema element but traverse all it's child elements return undefined; } @@ -605,8 +639,13 @@ const OpenApi3_1DereferenceVisitor = stampit({ // we're dealing with JSON Schema $anchor here retrievalURI = this.toBaseURI(toValue($refBaseURI)); + // ignore resolving internal Schema Objects + if (!this.options.resolve.internal && isInternalReference(retrievalURI)) { + // skip traversing this schema element but traverse all it's child elements + return undefined; + } // ignore resolving external Schema Objects - if (!this.options.resolve.external && isExternalURL(retrievalURI)) { + if (!this.options.resolve.external && isExternalReference(retrievalURI)) { // skip traversing this schema element but traverse all it's child elements return undefined; } @@ -622,8 +661,13 @@ const OpenApi3_1DereferenceVisitor = stampit({ // we're assuming here that we're dealing with JSON Pointer here retrievalURI = this.toBaseURI(toValue($refBaseURI)); + // ignore resolving internal Schema Objects + if (!this.options.resolve.internal && isInternalReference(retrievalURI)) { + // skip traversing this schema element but traverse all it's child elements + return undefined; + } // ignore resolving external Schema Objects - if (!this.options.resolve.external && isExternalURL(retrievalURI)) { + if (!this.options.resolve.external && isExternalReference(retrievalURI)) { // skip traversing this schema element but traverse all it's child elements return undefined; }