From a15c191f7d8fc2a6f03cdcf4b476e10038f138be Mon Sep 17 00:00:00 2001 From: Oliwia Rogala Date: Mon, 8 Jul 2024 10:07:52 +0200 Subject: [PATCH 1/5] fix(resolver): don't skip normalization of OpenAPI 3.1.0 specs Refs #1396 --- .../strategies/openapi-3-1-apidom/normalize.js | 3 --- src/subtree-resolver/index.js | 3 ++- .../__snapshots__/index.js.snap | 18 ------------------ .../normalize/__snapshots__/index.js.snap | 6 ------ .../__snapshots__/index.js.snap | 1 - 5 files changed, 2 insertions(+), 29 deletions(-) diff --git a/src/resolver/strategies/openapi-3-1-apidom/normalize.js b/src/resolver/strategies/openapi-3-1-apidom/normalize.js index 081e51148..e299166b1 100644 --- a/src/resolver/strategies/openapi-3-1-apidom/normalize.js +++ b/src/resolver/strategies/openapi-3-1-apidom/normalize.js @@ -17,7 +17,6 @@ import opId from '../../../helpers/op-id.js'; const normalize = (element) => { if (!isObjectElement(element)) return element; - if (element.hasKey('$$normalized')) return element; const plugins = [ refractorPluginNormalizeOperationIds({ @@ -36,7 +35,6 @@ const normalize = (element) => { visitorOptions: { keyMap, nodeTypeGetter: getNodeType }, }); - normalized.set('$$normalized', true); return normalized; }; @@ -46,7 +44,6 @@ const normalize = (element) => { * Plain Old JavaScript Objects and returns Plain Old JavaScript Objects. */ export const pojoAdapter = (normalizeFn) => (spec) => { - if (spec?.$$normalized) return spec; if (pojoAdapter.cache.has(spec)) return pojoAdapter.cache.get(spec); const openApiElement = OpenApi3_1Element.refract(spec); diff --git a/src/subtree-resolver/index.js b/src/subtree-resolver/index.js index dcc3ecc76..706e26b23 100644 --- a/src/subtree-resolver/index.js +++ b/src/subtree-resolver/index.js @@ -24,6 +24,7 @@ import resolve from '../resolver/index.js'; import genericResolverStrategy from '../resolver/strategies/generic/index.js'; import openApi2ResolverStrategy from '../resolver/strategies/openapi-2/index.js'; import openApi30ResolverStrategy from '../resolver/strategies/openapi-3-0/index.js'; +import { isOpenAPI31 } from '../helpers/openapi-predicates.js'; const resolveSubtree = async (obj, path, options = {}) => { const { @@ -53,7 +54,7 @@ const resolveSubtree = async (obj, path, options = {}) => { ...resolveOptions, spec: normalized, allowMetaPatches: true, - skipNormalization: true, + skipNormalization: !isOpenAPI31(normalized), }); if (!returnEntireTree && Array.isArray(path) && path.length) { diff --git a/test/resolver/strategies/openapi-3-1-apidom/__snapshots__/index.js.snap b/test/resolver/strategies/openapi-3-1-apidom/__snapshots__/index.js.snap index f75dcb0f5..eb72dfc8e 100644 --- a/test/resolver/strategies/openapi-3-1-apidom/__snapshots__/index.js.snap +++ b/test/resolver/strategies/openapi-3-1-apidom/__snapshots__/index.js.snap @@ -4,7 +4,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via URL a { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -317,7 +316,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via URL a { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -637,7 +635,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via URL a { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "User": { @@ -677,7 +674,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via URL a { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "User": { @@ -724,7 +720,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via URL s { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -1037,7 +1032,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -1357,7 +1351,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -1670,7 +1663,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "parameters": { "Baz": { @@ -1773,7 +1765,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec option and modelPropertyMacro is provided as a function given the function throws error should collect error 1`] = ` { - "$$normalized": true, "components": { "schemas": { "Pet": { @@ -1811,7 +1802,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -1903,7 +1893,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -2221,7 +2210,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec option and parameterMacro is provided sa a function given the function throws error should collect error 1`] = ` { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -2450,7 +2438,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -2681,7 +2668,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "parameters": { "limit": { @@ -2719,7 +2705,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -3032,7 +3017,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -3316,7 +3300,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { @@ -3905,7 +3888,6 @@ exports[`resolve OpenAPI 3.1.0 strategy given OpenAPI 3.1.0 definition via spec { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { diff --git a/test/resolver/strategies/openapi-3-1-apidom/normalize/__snapshots__/index.js.snap b/test/resolver/strategies/openapi-3-1-apidom/normalize/__snapshots__/index.js.snap index 9f4d56677..52084fb7d 100644 --- a/test/resolver/strategies/openapi-3-1-apidom/normalize/__snapshots__/index.js.snap +++ b/test/resolver/strategies/openapi-3-1-apidom/normalize/__snapshots__/index.js.snap @@ -2,7 +2,6 @@ exports[`helpers normalize OpenAPI 3.1 given denormalized Header Object examples should normalize 1`] = ` { - "$$normalized": true, "openapi": "3.1.0", "paths": { "/": { @@ -59,7 +58,6 @@ exports[`helpers normalize OpenAPI 3.1 given denormalized Header Object examples exports[`helpers normalize OpenAPI 3.1 given denormalized Operation.id fields should normalize 1`] = ` { - "$$normalized": true, "openapi": "3.1.0", "paths": { "/": { @@ -99,7 +97,6 @@ exports[`helpers normalize OpenAPI 3.1 given denormalized Operation.id fields sh exports[`helpers normalize OpenAPI 3.1 given denormalized Parameter Object examples should normalize 1`] = ` { - "$$normalized": true, "openapi": "3.1.0", "paths": { "/": { @@ -145,7 +142,6 @@ exports[`helpers normalize OpenAPI 3.1 given denormalized Parameter Object examp exports[`helpers normalize OpenAPI 3.1 given denormalized Parameter Objects should normalize 1`] = ` { - "$$normalized": true, "openapi": "3.1.0", "paths": { "/": { @@ -203,7 +199,6 @@ exports[`helpers normalize OpenAPI 3.1 given denormalized Parameter Objects shou exports[`helpers normalize OpenAPI 3.1 given denormalized Security Requirements Objects should normalize 1`] = ` { - "$$normalized": true, "openapi": "3.1.0", "paths": { "/": { @@ -256,7 +251,6 @@ exports[`helpers normalize OpenAPI 3.1 given denormalized Security Requirements exports[`helpers normalize OpenAPI 3.1 given denormalized Servers Objects should normalize 1`] = ` { - "$$normalized": true, "openapi": "3.1.0", "paths": { "/": { diff --git a/test/subtree-resolver/strategies/openapi-3-1-apidom/__snapshots__/index.js.snap b/test/subtree-resolver/strategies/openapi-3-1-apidom/__snapshots__/index.js.snap index cac66d956..0fa59ea88 100644 --- a/test/subtree-resolver/strategies/openapi-3-1-apidom/__snapshots__/index.js.snap +++ b/test/subtree-resolver/strategies/openapi-3-1-apidom/__snapshots__/index.js.snap @@ -4,7 +4,6 @@ exports[`subtree-resolver OpenAPI 3.1.0 strategy should not resolve an untargete { "errors": [], "spec": { - "$$normalized": true, "components": { "schemas": { "Error": { From b1376b3fbe5351d0fc90d37269e9fc24565a0881 Mon Sep 17 00:00:00 2001 From: Oliwia Rogala Date: Tue, 9 Jul 2024 14:51:54 +0200 Subject: [PATCH 2/5] chore: bump ApiDOM to 1.0.0-alpha.6 --- package-lock.json | 88 +++++++++++++++++++++++------------------------ package.json | 10 +++--- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/package-lock.json b/package-lock.json index abe84dc72..8bbbd3a3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,11 +10,11 @@ "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.22.15", - "@swagger-api/apidom-core": ">=1.0.0-alpha.5 <1.0.0-beta.0", - "@swagger-api/apidom-error": ">=1.0.0-alpha.5 <1.0.0-beta.0", - "@swagger-api/apidom-json-pointer": ">=1.0.0-alpha.5 <1.0.0-beta.0", - "@swagger-api/apidom-ns-openapi-3-1": ">=1.0.0-alpha.5 <1.0.0-beta.0", - "@swagger-api/apidom-reference": ">=1.0.0-alpha.5 <1.0.0-beta.0", + "@swagger-api/apidom-core": ">=1.0.0-alpha.6 <1.0.0-beta.0", + "@swagger-api/apidom-error": ">=1.0.0-alpha.6 <1.0.0-beta.0", + "@swagger-api/apidom-json-pointer": ">=1.0.0-alpha.6 <1.0.0-beta.0", + "@swagger-api/apidom-ns-openapi-3-1": ">=1.0.0-alpha.6 <1.0.0-beta.0", + "@swagger-api/apidom-reference": ">=1.0.0-alpha.6 <1.0.0-beta.0", "cookie": "~0.6.0", "deepmerge": "~4.3.0", "fast-json-patch": "^3.0.0-1", @@ -3470,12 +3470,12 @@ } }, "node_modules/@swagger-api/apidom-ast": { - "version": "1.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-1.0.0-alpha.5.tgz", - "integrity": "sha512-ZH3xryzmwd8OvUdOJH4ujNAyQMXN6NCrRT0HGR8z9TnA0nFPFoOAswq7317mCn77VJmViu/tpCuvmRS0a9BROg==", + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-1.0.0-alpha.6.tgz", + "integrity": "sha512-uzDNIeTLFeITzK7yX9PSsu3dl92rHP/gKMNAlJhmDRr7r+OLr5dCpAzyZ0WvONRxjxR8Otj5LX4AD12+EX32fg==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-error": "^1.0.0-alpha.5", + "@swagger-api/apidom-error": "^1.0.0-alpha.6", "@types/ramda": "~0.30.0", "ramda": "~0.30.0", "ramda-adjunct": "^5.0.0", @@ -3483,13 +3483,13 @@ } }, "node_modules/@swagger-api/apidom-core": { - "version": "1.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-1.0.0-alpha.5.tgz", - "integrity": "sha512-iArtPxwcQ/EpQU/VqwBDrD+F0lngyUyLVCa8zR4gT+7mP6fpiU7jcerizw0hDpFmvieXddx5UdfO28Pxuq204g==", + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-core/-/apidom-core-1.0.0-alpha.6.tgz", + "integrity": "sha512-5u7dK3+8cF2h5bHEI/qrA6JrfXX+HIHSmUgPGbeMAqSCEfpsjnsngXK6gHtd4ktLlPz3TplNZAQl88wIp+39nw==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^1.0.0-alpha.5", - "@swagger-api/apidom-error": "^1.0.0-alpha.5", + "@swagger-api/apidom-ast": "^1.0.0-alpha.6", + "@swagger-api/apidom-error": "^1.0.0-alpha.6", "@types/ramda": "~0.30.0", "minim": "~0.23.8", "ramda": "~0.30.0", @@ -3499,21 +3499,21 @@ } }, "node_modules/@swagger-api/apidom-error": { - "version": "1.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-1.0.0-alpha.5.tgz", - "integrity": "sha512-5UEgSZuQPdkqKSKDtRXQ0cm7x1o4EPyusLBVsCG4l8QtJvAhG1OOpEzJbTZ48/nRt7VkbK7MTj/up+oEILzVvw==", + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-error/-/apidom-error-1.0.0-alpha.6.tgz", + "integrity": "sha512-eOcqaXwLitjp5CIGYR0W2oM6p4UiTL7EjNdkCcfrELKHdgNS6U7kZdl3KCBlOuMb14CijwtZNEJbIGhhGZUYHg==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7" } }, "node_modules/@swagger-api/apidom-json-pointer": { - "version": "1.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-1.0.0-alpha.5.tgz", - "integrity": "sha512-eDAz7/UaGpGCvB0y1GoRjFwxFWseCsF/0ZYIQvvq9PS025inc/I6M+XX8dWMmkpNpbbf+KfD7WlwfqnUZLv/MQ==", + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-json-pointer/-/apidom-json-pointer-1.0.0-alpha.6.tgz", + "integrity": "sha512-8ULBcQRQ1UPgqJ+ZuuKjmeKeuxqbuIUHwWHRRA848jK5+IHmNw/Cp68MhNiwYXLmTLkTIGaDubcOplMeHCxSyA==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^1.0.0-alpha.5", - "@swagger-api/apidom-error": "^1.0.0-alpha.5", + "@swagger-api/apidom-core": "^1.0.0-alpha.6", + "@swagger-api/apidom-error": "^1.0.0-alpha.6", "@types/ramda": "~0.30.0", "ramda": "~0.30.0", "ramda-adjunct": "^5.0.0" @@ -3527,13 +3527,13 @@ "optional": true }, "node_modules/@swagger-api/apidom-ns-json-schema-draft-4": { - "version": "1.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-1.0.0-alpha.5.tgz", - "integrity": "sha512-aDmcpGikL5JZmDTg7J6EJfLFjtUmX/MfduS4hQeopFCkw91dZsqxO10j7KEiRVVuJBuGStbYoHI5aIsQTlebzA==", + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-json-schema-draft-4/-/apidom-ns-json-schema-draft-4-1.0.0-alpha.6.tgz", + "integrity": "sha512-E8JjqdDgopnLd4HXEXGSrc6rkbDyB8Qk6sYgmyT6lB8caFUMRdJ5Rp57fPePETnVpegb8cAuKjBdjTImX1gQ3Q==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^1.0.0-alpha.5", - "@swagger-api/apidom-core": "^1.0.0-alpha.5", + "@swagger-api/apidom-ast": "^1.0.0-alpha.6", + "@swagger-api/apidom-core": "^1.0.0-alpha.6", "@types/ramda": "~0.30.0", "ramda": "~0.30.0", "ramda-adjunct": "^5.0.0", @@ -3548,14 +3548,14 @@ "optional": true }, "node_modules/@swagger-api/apidom-ns-openapi-3-0": { - "version": "1.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-1.0.0-alpha.5.tgz", - "integrity": "sha512-UAOGZaGMDVRQ10l8OgXCAfxS9PxGoCW66o/vFmhPfrK8NwU1GEo6sYHYoo1mflNMHCN2eVYyM5LxA+qYm0SJgQ==", + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-0/-/apidom-ns-openapi-3-0-1.0.0-alpha.6.tgz", + "integrity": "sha512-kE4s17j69DDvXrf7xeRTunmSQJLiX52fCX1YnfC81e1IPm3q/mdpkZiysM87FuJQQj522fX2G+QUIJlDkD5U9w==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^1.0.0-alpha.5", - "@swagger-api/apidom-error": "^1.0.0-alpha.5", - "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-alpha.5", + "@swagger-api/apidom-core": "^1.0.0-alpha.6", + "@swagger-api/apidom-error": "^1.0.0-alpha.6", + "@swagger-api/apidom-ns-json-schema-draft-4": "^1.0.0-alpha.6", "@types/ramda": "~0.30.0", "ramda": "~0.30.0", "ramda-adjunct": "^5.0.0", @@ -3563,15 +3563,15 @@ } }, "node_modules/@swagger-api/apidom-ns-openapi-3-1": { - "version": "1.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-1.0.0-alpha.5.tgz", - "integrity": "sha512-8VkdZ2MfxXIdmzQZrV0qGk18MG7XNJKIL3GT9lad9NyXyiKSvBVFJDmS4S43qcQTL0rjHXF6ds25yErDSTprjg==", + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ns-openapi-3-1/-/apidom-ns-openapi-3-1-1.0.0-alpha.6.tgz", + "integrity": "sha512-2QA2z9beyaVyZDOXbLg4Nu8o8xKWo9L0WHWOP+hg/haGRyyPHXgyg2XdwRuFBozBI9wBaIfEg1lvNC+J0taDjg==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-ast": "^1.0.0-alpha.5", - "@swagger-api/apidom-core": "^1.0.0-alpha.5", - "@swagger-api/apidom-json-pointer": "^1.0.0-alpha.5", - "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-alpha.5", + "@swagger-api/apidom-ast": "^1.0.0-alpha.6", + "@swagger-api/apidom-core": "^1.0.0-alpha.6", + "@swagger-api/apidom-json-pointer": "^1.0.0-alpha.6", + "@swagger-api/apidom-ns-openapi-3-0": "^1.0.0-alpha.6", "@types/ramda": "~0.30.0", "ramda": "~0.30.0", "ramda-adjunct": "^5.0.0", @@ -3692,12 +3692,12 @@ "optional": true }, "node_modules/@swagger-api/apidom-reference": { - "version": "1.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-1.0.0-alpha.5.tgz", - "integrity": "sha512-zPMTScWI8oVUAT//RdAhl9GJuwtQLibP8iCrqFQDGjBzKQS5Uxz4hSXr/jqKPdkCJXbEoP94yYjvQjtI5yrv1A==", + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/@swagger-api/apidom-reference/-/apidom-reference-1.0.0-alpha.6.tgz", + "integrity": "sha512-DbsxxgQCVd8ZTJag3EOtzJ2rtsaq4z5z/A4nEgzVQhStuHdRwrbQfxem1g7p6dOK2VrGEGf73UllGJvGV+uPpg==", "dependencies": { "@babel/runtime-corejs3": "^7.20.7", - "@swagger-api/apidom-core": "^1.0.0-alpha.5", + "@swagger-api/apidom-core": "^1.0.0-alpha.6", "@types/ramda": "~0.30.0", "axios": "^1.4.0", "minimatch": "^7.4.3", diff --git a/package.json b/package.json index cb0bd4cfc..cdf9a75c3 100644 --- a/package.json +++ b/package.json @@ -73,11 +73,11 @@ "license": "Apache-2.0", "dependencies": { "@babel/runtime-corejs3": "^7.22.15", - "@swagger-api/apidom-core": ">=1.0.0-alpha.5 <1.0.0-beta.0", - "@swagger-api/apidom-error": ">=1.0.0-alpha.5 <1.0.0-beta.0", - "@swagger-api/apidom-json-pointer": ">=1.0.0-alpha.5 <1.0.0-beta.0", - "@swagger-api/apidom-ns-openapi-3-1": ">=1.0.0-alpha.5 <1.0.0-beta.0", - "@swagger-api/apidom-reference": ">=1.0.0-alpha.5 <1.0.0-beta.0", + "@swagger-api/apidom-core": ">=1.0.0-alpha.6 <1.0.0-beta.0", + "@swagger-api/apidom-error": ">=1.0.0-alpha.6 <1.0.0-beta.0", + "@swagger-api/apidom-json-pointer": ">=1.0.0-alpha.6 <1.0.0-beta.0", + "@swagger-api/apidom-ns-openapi-3-1": ">=1.0.0-alpha.6 <1.0.0-beta.0", + "@swagger-api/apidom-reference": ">=1.0.0-alpha.6 <1.0.0-beta.0", "cookie": "~0.6.0", "deepmerge": "~4.3.0", "fast-json-patch": "^3.0.0-1", From 85ea469c7c3b7eed4ae67036161f74ad3c9f394f Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Fri, 12 Jul 2024 16:02:12 +0200 Subject: [PATCH 3/5] refactor: change the architecture to adopt idempotent normalization --- src/resolver/index.js | 2 +- src/resolver/strategies/generic/index.js | 2 +- src/resolver/strategies/generic/resolve.js | 16 ++++++++++------ src/resolver/strategies/openapi-2/index.js | 4 ++-- src/resolver/strategies/openapi-3-0/index.js | 4 ++-- .../strategies/openapi-3-1-apidom/index.js | 17 ++++++++++++++--- .../strategies/openapi-3-1-apidom/normalize.js | 15 +++++++++------ .../strategies/openapi-3-1-apidom/resolve.js | 5 +++-- src/subtree-resolver/index.js | 9 +++++---- 9 files changed, 47 insertions(+), 27 deletions(-) diff --git a/src/resolver/index.js b/src/resolver/index.js index 0714ee6d5..376f24b20 100644 --- a/src/resolver/index.js +++ b/src/resolver/index.js @@ -13,7 +13,7 @@ const resolve = async (options) => { spec || (await makeFetchJSON(httpClient, { requestInterceptor, responseInterceptor })(retrievalURI)); const strategyOptions = { ...options, spec: retrievedSpec }; - const strategy = options.strategies.find((strg) => strg.match(strategyOptions)); + const strategy = options.strategies.find((strg) => strg.match(retrievedSpec)); return strategy.resolve(strategyOptions); }; diff --git a/src/resolver/strategies/generic/index.js b/src/resolver/strategies/generic/index.js index 853462a34..e1ce90ae2 100644 --- a/src/resolver/strategies/generic/index.js +++ b/src/resolver/strategies/generic/index.js @@ -11,7 +11,7 @@ const genericStrategy = { match() { return true; }, - normalize({ spec }) { + normalize(spec) { const { spec: normalized } = normalize({ spec }); return normalized; }, diff --git a/src/resolver/strategies/generic/resolve.js b/src/resolver/strategies/generic/resolve.js index 14f558132..4604732aa 100644 --- a/src/resolver/strategies/generic/resolve.js +++ b/src/resolver/strategies/generic/resolve.js @@ -1,5 +1,4 @@ import mapSpec, { plugins } from '../../specmap/index.js'; -import normalize from './normalize.js'; import { makeFetchJSON } from '../../utils/index.js'; import * as optionsUtil from '../../utils/options.js'; @@ -13,16 +12,18 @@ export default async function resolveGenericStrategy(options) { parameterMacro, requestInterceptor, responseInterceptor, - skipNormalization, + skipNormalization = false, useCircularStructures, + strategies, } = options; const retrievalURI = optionsUtil.retrievalURI(options); const httpClient = optionsUtil.httpClient(options); + const strategy = strategies.find((strg) => strg.match(spec)); return doResolve(spec); - function doResolve(_spec) { + async function doResolve(_spec) { if (retrievalURI) { plugins.refs.docCache[retrievalURI] = _spec; } @@ -45,7 +46,7 @@ export default async function resolveGenericStrategy(options) { } // mapSpec is where the hard work happens - return mapSpec({ + const result = await mapSpec({ spec: _spec, context: { baseDoc: retrievalURI }, plugins: plugs, @@ -54,7 +55,10 @@ export default async function resolveGenericStrategy(options) { parameterMacro, modelPropertyMacro, useCircularStructures, - // eslint-disable-next-line camelcase - }).then(skipNormalization ? async (a) => a : normalize); + }); + + result.spec = skipNormalization ? result.spec : strategy.normalize(result.spec); + + return result; } } diff --git a/src/resolver/strategies/openapi-2/index.js b/src/resolver/strategies/openapi-2/index.js index 9cd82c450..3a29f47a3 100644 --- a/src/resolver/strategies/openapi-2/index.js +++ b/src/resolver/strategies/openapi-2/index.js @@ -6,10 +6,10 @@ export { clearCache } from '../generic/index.js'; const openApi2Strategy = { name: 'openapi-2', - match({ spec }) { + match(spec) { return isOpenAPI2(spec); }, - normalize({ spec }) { + normalize(spec) { const { spec: normalized } = normalize({ spec }); return normalized; }, diff --git a/src/resolver/strategies/openapi-3-0/index.js b/src/resolver/strategies/openapi-3-0/index.js index 991e30264..59ae4d9b6 100644 --- a/src/resolver/strategies/openapi-3-0/index.js +++ b/src/resolver/strategies/openapi-3-0/index.js @@ -6,10 +6,10 @@ export { clearCache } from '../generic/index.js'; const openApi30Strategy = { name: 'openapi-3-0', - match({ spec }) { + match(spec) { return isOpenAPI30(spec); }, - normalize({ spec }) { + normalize(spec) { const { spec: normalized } = normalize({ spec }); return normalized; }, diff --git a/src/resolver/strategies/openapi-3-1-apidom/index.js b/src/resolver/strategies/openapi-3-1-apidom/index.js index 8c2b18c7a..fc3c8879d 100644 --- a/src/resolver/strategies/openapi-3-1-apidom/index.js +++ b/src/resolver/strategies/openapi-3-1-apidom/index.js @@ -1,14 +1,25 @@ +import { isElement } from '@swagger-api/apidom-core'; + import resolveOpenAPI31Strategy from './resolve.js'; import normalize, { pojoAdapter } from './normalize.js'; import { isOpenAPI31 } from '../../../helpers/openapi-predicates.js'; const openApi31ApiDOMStrategy = { name: 'openapi-3-1-apidom', - match({ spec }) { + match(spec) { return isOpenAPI31(spec); }, - normalize({ spec }) { - return pojoAdapter(normalize)(spec); + normalize(spec) { + /** + * We need to perform pre-normalization only once before the first lazy dereference. + * We always need to perform post-normalization after every lazy dereference. + */ + if (isElement(spec)) { + // post-normalization - happens after the dereferencing and in ApiDOM context + return normalize(spec); + } + // pre-normalization - happens only once before the first lazy dereferencing and in JavaScript context + return spec?.$$normalized ? spec : pojoAdapter(normalize)(spec); }, async resolve(options) { return resolveOpenAPI31Strategy(options); diff --git a/src/resolver/strategies/openapi-3-1-apidom/normalize.js b/src/resolver/strategies/openapi-3-1-apidom/normalize.js index e299166b1..8448d656e 100644 --- a/src/resolver/strategies/openapi-3-1-apidom/normalize.js +++ b/src/resolver/strategies/openapi-3-1-apidom/normalize.js @@ -14,6 +14,7 @@ import { } from '@swagger-api/apidom-ns-openapi-3-1'; import opId from '../../../helpers/op-id.js'; +import resolveOpenAPI31Strategy from './resolve.js'; const normalize = (element) => { if (!isObjectElement(element)) return element; @@ -44,17 +45,19 @@ const normalize = (element) => { * Plain Old JavaScript Objects and returns Plain Old JavaScript Objects. */ export const pojoAdapter = (normalizeFn) => (spec) => { - if (pojoAdapter.cache.has(spec)) return pojoAdapter.cache.get(spec); - const openApiElement = OpenApi3_1Element.refract(spec); + openApiElement.classes.push('result'); + const normalized = normalizeFn(openApiElement); - const value = toValue(normalized); - pojoAdapter.cache.set(spec, value); + /** + * We're setting the cache here to avoid repeated refracting + * in `openapi-3-1-apidom` strategy resolve method. + */ + resolveOpenAPI31Strategy.cache.set(spec, normalized); - return value; + return toValue(normalized); }; -pojoAdapter.cache = new WeakMap(); export default normalize; /* eslint-enable camelcase */ diff --git a/src/resolver/strategies/openapi-3-1-apidom/resolve.js b/src/resolver/strategies/openapi-3-1-apidom/resolve.js index a8ce88417..4dd77ff14 100644 --- a/src/resolver/strategies/openapi-3-1-apidom/resolve.js +++ b/src/resolver/strategies/openapi-3-1-apidom/resolve.js @@ -25,7 +25,6 @@ import OpenAPI3_1ResolveStrategy from '@swagger-api/apidom-reference/resolve/str import { DEFAULT_BASE_URL } from '../../../constants.js'; import * as optionsUtil from '../../utils/options.js'; -import normalize from './normalize.js'; import HTTPResolverSwaggerClient from '../../apidom/reference/resolve/resolvers/http-swagger-client/index.js'; import JSONParser from '../../apidom/reference/parse/parsers/json/index.js'; import YAMLParser from '../../apidom/reference/parse/parsers/yaml-1-2/index.js'; @@ -62,9 +61,11 @@ const resolveOpenAPI31Strategy = async (options) => { parameterMacro = null, modelPropertyMacro = null, mode = 'non-strict', + strategies, } = options; try { const { cache } = resolveOpenAPI31Strategy; + const strategy = strategies.find((strg) => strg.match(spec)); // determining BaseURI const cwd = url.isHttpUrl(url.cwd()) ? url.cwd() : DEFAULT_BASE_URL; @@ -155,7 +156,7 @@ const resolveOpenAPI31Strategy = async (options) => { }, }); const transcluded = transclude(fragmentElement, dereferenced, openApiElement); - const normalized = skipNormalization ? transcluded : normalize(transcluded); + const normalized = skipNormalization ? transcluded : strategy.normalize(transcluded); return { spec: toValue(normalized), errors }; } catch (error) { diff --git a/src/subtree-resolver/index.js b/src/subtree-resolver/index.js index 706e26b23..6a41f0794 100644 --- a/src/subtree-resolver/index.js +++ b/src/subtree-resolver/index.js @@ -48,13 +48,14 @@ const resolveSubtree = async (obj, path, options = {}) => { useCircularStructures, strategies, }; - const strategy = strategies.find((strg) => strg.match(resolveOptions)); - const normalized = strategy.normalize(resolveOptions); + const strategy = strategies.find((strg) => strg.match(obj)); + const normalized = strategy.normalize(obj); + const result = await resolve({ - ...resolveOptions, spec: normalized, + ...resolveOptions, allowMetaPatches: true, - skipNormalization: !isOpenAPI31(normalized), + skipNormalization: !isOpenAPI31(obj), }); if (!returnEntireTree && Array.isArray(path) && path.length) { From e566e27bec2545ddbba306c60c63cc9c1ea7a5f6 Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Fri, 12 Jul 2024 16:25:31 +0200 Subject: [PATCH 4/5] fix: additional fixes --- src/resolver/strategies/generic/resolve.js | 4 +++- src/resolver/strategies/openapi-3-1-apidom/normalize.js | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/resolver/strategies/generic/resolve.js b/src/resolver/strategies/generic/resolve.js index 4604732aa..d22efd99a 100644 --- a/src/resolver/strategies/generic/resolve.js +++ b/src/resolver/strategies/generic/resolve.js @@ -57,7 +57,9 @@ export default async function resolveGenericStrategy(options) { useCircularStructures, }); - result.spec = skipNormalization ? result.spec : strategy.normalize(result.spec); + if (!skipNormalization) { + result.spec = strategy.normalize(result.spec); + } return result; } diff --git a/src/resolver/strategies/openapi-3-1-apidom/normalize.js b/src/resolver/strategies/openapi-3-1-apidom/normalize.js index 8448d656e..22eeea757 100644 --- a/src/resolver/strategies/openapi-3-1-apidom/normalize.js +++ b/src/resolver/strategies/openapi-3-1-apidom/normalize.js @@ -49,12 +49,13 @@ export const pojoAdapter = (normalizeFn) => (spec) => { openApiElement.classes.push('result'); const normalized = normalizeFn(openApiElement); + const value = toValue(normalized); /** * We're setting the cache here to avoid repeated refracting * in `openapi-3-1-apidom` strategy resolve method. */ - resolveOpenAPI31Strategy.cache.set(spec, normalized); + resolveOpenAPI31Strategy.cache.set(value, normalized); return toValue(normalized); }; From 7c9ff6dce8059f2f79b8df2ec662172462288f0e Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Fri, 12 Jul 2024 16:48:14 +0200 Subject: [PATCH 5/5] fix: pre-normalization --- .../strategies/openapi-3-1-apidom/index.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/resolver/strategies/openapi-3-1-apidom/index.js b/src/resolver/strategies/openapi-3-1-apidom/index.js index fc3c8879d..1e69f054e 100644 --- a/src/resolver/strategies/openapi-3-1-apidom/index.js +++ b/src/resolver/strategies/openapi-3-1-apidom/index.js @@ -1,3 +1,4 @@ +import { isPlainObject } from 'ramda-adjunct'; import { isElement } from '@swagger-api/apidom-core'; import resolveOpenAPI31Strategy from './resolve.js'; @@ -10,16 +11,18 @@ const openApi31ApiDOMStrategy = { return isOpenAPI31(spec); }, normalize(spec) { - /** - * We need to perform pre-normalization only once before the first lazy dereference. - * We always need to perform post-normalization after every lazy dereference. - */ + // pre-normalization - happens only once before the first lazy dereferencing and in JavaScript context + if (!isElement(spec) && isPlainObject(spec) && !spec.$$normalized) { + const preNormalized = pojoAdapter(normalize)(spec); + preNormalized.$$normalized = true; + return preNormalized; + } + // post-normalization - happens after each dereferencing and in ApiDOM context if (isElement(spec)) { - // post-normalization - happens after the dereferencing and in ApiDOM context return normalize(spec); } - // pre-normalization - happens only once before the first lazy dereferencing and in JavaScript context - return spec?.$$normalized ? spec : pojoAdapter(normalize)(spec); + + return spec; }, async resolve(options) { return resolveOpenAPI31Strategy(options);