@speclynx/apidom-ns-openapi-3-0 4.0.5 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@speclynx/apidom-ns-openapi-3-0",
3
- "version": "4.0.5",
3
+ "version": "4.2.0",
4
4
  "description": "OpenAPI 3.0.x namespace for ApiDOM.",
5
5
  "keywords": [
6
6
  "apidom",
@@ -56,11 +56,12 @@
56
56
  "license": "Apache-2.0",
57
57
  "dependencies": {
58
58
  "@babel/runtime-corejs3": "^7.28.4",
59
- "@speclynx/apidom-core": "4.0.5",
60
- "@speclynx/apidom-datamodel": "4.0.5",
61
- "@speclynx/apidom-error": "4.0.5",
62
- "@speclynx/apidom-ns-json-schema-draft-4": "4.0.5",
63
- "@speclynx/apidom-traverse": "4.0.5",
59
+ "@speclynx/apidom-core": "4.2.0",
60
+ "@speclynx/apidom-datamodel": "4.2.0",
61
+ "@speclynx/apidom-error": "4.2.0",
62
+ "@speclynx/apidom-json-pointer": "4.2.0",
63
+ "@speclynx/apidom-ns-json-schema-draft-4": "4.2.0",
64
+ "@speclynx/apidom-traverse": "4.2.0",
64
65
  "ramda": "~0.32.0",
65
66
  "ramda-adjunct": "^6.0.0",
66
67
  "ts-mixer": "^6.0.4"
@@ -75,5 +76,5 @@
75
76
  "README.md",
76
77
  "CHANGELOG.md"
77
78
  ],
78
- "gitHead": "5a85d2a832eeefb07d03760faa391b457447e966"
79
+ "gitHead": "3485d180340f2d4fad149bcf062a6f618030ca9b"
79
80
  }
package/src/index.cjs CHANGED
@@ -3,8 +3,8 @@
3
3
  var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
4
  var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
5
5
  exports.__esModule = true;
6
- exports.isReferenceElement = exports.isPathsElement = exports.isPathItemElement = exports.isParameterElement = exports.isOperationElement = exports.isOpenapiElement = exports.isOpenApiExtension = exports.isOpenApi3_0Element = exports.isMediaTypeElement = exports.isLinkElement = exports.isLicenseElement = exports.isInfoElement = exports.isExternalDocumentationElement = exports.isExampleElement = exports.isContactElement = exports.isComponentsElement = exports.isCallbackElement = exports.default = exports.XmlElement = exports.Visitor = exports.TagsElement = exports.TagElement = exports.SpecificationVisitor = exports.SpecificationExtensionVisitor = exports.ServersElement = exports.ServerVariablesElement = exports.ServerVariableElement = exports.ServerElement = exports.SecuritySchemeElement = exports.SecurityRequirementElement = exports.SecurityElement = exports.SchemaElement = exports.ResponsesElement = exports.ResponseLinksElement = exports.ResponseHeadersElement = exports.ResponseElement = exports.ResponseContentElement = exports.RequestBodyElement = exports.RequestBodyContentElement = exports.ReferenceElement = exports.PatternedFieldsVisitor = exports.PathsElement = exports.PathItemServersElement = exports.PathItemParametersElement = exports.PathItemElement = exports.ParameterExamplesElement = exports.ParameterElement = exports.ParameterContentElement = exports.OperationTagsElement = exports.OperationServersElement = exports.OperationSecurityElement = exports.OperationParametersElement = exports.OperationElement = exports.OperationCallbacksElement = exports.OpenapiElement = exports.OpenApi3_0Element = exports.OpenAPIMediaTypes = exports.OAuthFlowsElement = exports.OAuthFlowScopesElement = exports.OAuthFlowElement = exports.MixedFieldsVisitorBase = exports.MixedFieldsVisitor = exports.MediaTypeExamplesElement = exports.MediaTypeEncodingElement = exports.MediaTypeElement = exports.MapVisitor = exports.LinkParametersElement = exports.LinkElement = exports.LicenseElement = exports.InfoElement = exports.HeaderExamplesElement = exports.HeaderElement = exports.HeaderContentElement = exports.FixedFieldsVisitor = exports.FallbackVisitor = exports.ExternalDocumentationElement = exports.ExampleElement = exports.EncodingHeadersElement = exports.EncodingElement = exports.DiscriminatorMappingElement = exports.DiscriminatorElement = exports.ContactElement = exports.ComponentsSecuritySchemesElement = exports.ComponentsSchemasElement = exports.ComponentsResponsesElement = exports.ComponentsRequestBodiesElement = exports.ComponentsParametersElement = exports.ComponentsLinksElement = exports.ComponentsHeadersElement = exports.ComponentsExamplesElement = exports.ComponentsElement = exports.ComponentsCallbacksElement = exports.CallbackElement = exports.BaseSpecificationVisitor = exports.BasePatternedFieldsVisitor = exports.BaseMixedFieldsVisitor = exports.BaseMapVisitor = exports.BaseFixedFieldsVisitor = exports.BaseAlternatingVisitor = exports.AlternatingVisitor = void 0;
7
- exports.specificationObj = exports.refractorPluginReplaceEmptyElement = exports.refractXml = exports.refractTag = exports.refractServerVariable = exports.refractServer = exports.refractSecurityScheme = exports.refractSecurityRequirement = exports.refractSchema = exports.refractResponses = exports.refractResponse = exports.refractRequestBody = exports.refractReference = exports.refractPaths = exports.refractPathItem = exports.refractParameter = exports.refractOperation = exports.refractOpenApi3_0 = exports.refractOAuthFlows = exports.refractOAuthFlow = exports.refractMediaType = exports.refractLink = exports.refractLicense = exports.refractInfo = exports.refractHeader = exports.refractExternalDocumentation = exports.refractExample = exports.refractEncoding = exports.refractDiscriminator = exports.refractContact = exports.refractComponents = exports.refractCallback = exports.refract = exports.mediaTypes = exports.isTagLikeElement = exports.isServersElement = exports.isServerVariableElement = exports.isServerLikeElement = exports.isServerElement = exports.isSecuritySchemeElement = exports.isSecurityRequirementElement = exports.isSchemaElement = exports.isResponsesElement = exports.isResponseElement = exports.isRequestBodyElement = exports.isReferenceLikeElement = void 0;
6
+ exports.isPathsElement = exports.isPathItemElement = exports.isParameterElement = exports.isOperationElement = exports.isOpenapiElement = exports.isOpenApiExtension = exports.isOpenApi3_0Element = exports.isMediaTypeElement = exports.isLinkElement = exports.isLicenseElement = exports.isInfoElement = exports.isExternalDocumentationElement = exports.isExampleElement = exports.isContactElement = exports.isComponentsElement = exports.isCallbackElement = exports.default = exports.createToolbox = exports.XmlElement = exports.Visitor = exports.TagsElement = exports.TagElement = exports.SpecificationVisitor = exports.SpecificationExtensionVisitor = exports.ServersElement = exports.ServerVariablesElement = exports.ServerVariableElement = exports.ServerElement = exports.SecuritySchemeElement = exports.SecurityRequirementElement = exports.SecurityElement = exports.SchemaElement = exports.ResponsesElement = exports.ResponseLinksElement = exports.ResponseHeadersElement = exports.ResponseElement = exports.ResponseContentElement = exports.RequestBodyElement = exports.RequestBodyContentElement = exports.ReferenceElement = exports.PatternedFieldsVisitor = exports.PathsElement = exports.PathItemServersElement = exports.PathItemParametersElement = exports.PathItemElement = exports.ParameterExamplesElement = exports.ParameterElement = exports.ParameterContentElement = exports.OperationTagsElement = exports.OperationServersElement = exports.OperationSecurityElement = exports.OperationParametersElement = exports.OperationElement = exports.OperationCallbacksElement = exports.OpenapiElement = exports.OpenApi3_0Element = exports.OpenAPIMediaTypes = exports.OAuthFlowsElement = exports.OAuthFlowScopesElement = exports.OAuthFlowElement = exports.MixedFieldsVisitorBase = exports.MixedFieldsVisitor = exports.MediaTypeExamplesElement = exports.MediaTypeEncodingElement = exports.MediaTypeElement = exports.MapVisitor = exports.LinkParametersElement = exports.LinkElement = exports.LicenseElement = exports.InfoElement = exports.HeaderExamplesElement = exports.HeaderElement = exports.HeaderContentElement = exports.FixedFieldsVisitor = exports.FallbackVisitor = exports.ExternalDocumentationElement = exports.ExampleElement = exports.EncodingHeadersElement = exports.EncodingElement = exports.DiscriminatorMappingElement = exports.DiscriminatorElement = exports.ContactElement = exports.ComponentsSecuritySchemesElement = exports.ComponentsSchemasElement = exports.ComponentsResponsesElement = exports.ComponentsRequestBodiesElement = exports.ComponentsParametersElement = exports.ComponentsLinksElement = exports.ComponentsHeadersElement = exports.ComponentsExamplesElement = exports.ComponentsElement = exports.ComponentsCallbacksElement = exports.CallbackElement = exports.BaseSpecificationVisitor = exports.BasePatternedFieldsVisitor = exports.BaseMixedFieldsVisitor = exports.BaseMapVisitor = exports.BaseFixedFieldsVisitor = exports.BaseAlternatingVisitor = exports.AlternatingVisitor = void 0;
7
+ exports.specificationObj = exports.refractorPluginReplaceEmptyElement = exports.refractorPluginNormalizeServers = exports.refractorPluginNormalizeSecurityRequirements = exports.refractorPluginNormalizeParameters = exports.refractXml = exports.refractTag = exports.refractServerVariable = exports.refractServer = exports.refractSecurityScheme = exports.refractSecurityRequirement = exports.refractSchema = exports.refractResponses = exports.refractResponse = exports.refractRequestBody = exports.refractReference = exports.refractPaths = exports.refractPathItem = exports.refractParameter = exports.refractOperation = exports.refractOpenApi3_0 = exports.refractOAuthFlows = exports.refractOAuthFlow = exports.refractMediaType = exports.refractLink = exports.refractLicense = exports.refractInfo = exports.refractHeader = exports.refractExternalDocumentation = exports.refractExample = exports.refractEncoding = exports.refractDiscriminator = exports.refractContact = exports.refractComponents = exports.refractCallback = exports.refract = exports.mediaTypes = exports.isTagLikeElement = exports.isServersElement = exports.isServerVariableElement = exports.isServerLikeElement = exports.isServerElement = exports.isSecuritySchemeElement = exports.isSecurityRequirementElement = exports.isSchemaElement = exports.isResponsesElement = exports.isResponseElement = exports.isRequestBodyElement = exports.isReferenceLikeElement = exports.isReferenceElement = void 0;
8
8
  var _mediaTypes = _interopRequireWildcard(require("./media-types.cjs"));
9
9
  exports.mediaTypes = _mediaTypes.default;
10
10
  exports.OpenAPIMediaTypes = _mediaTypes.OpenAPIMediaTypes;
@@ -12,6 +12,12 @@ var _namespace = _interopRequireDefault(require("./namespace.cjs"));
12
12
  exports.default = _namespace.default;
13
13
  var _replaceEmptyElement = _interopRequireDefault(require("./refractor/plugins/replace-empty-element.cjs"));
14
14
  exports.refractorPluginReplaceEmptyElement = _replaceEmptyElement.default;
15
+ var _normalizeParameters = _interopRequireDefault(require("./refractor/plugins/normalize-parameters.cjs"));
16
+ exports.refractorPluginNormalizeParameters = _normalizeParameters.default;
17
+ var _normalizeSecurityRequirements = _interopRequireDefault(require("./refractor/plugins/normalize-security-requirements.cjs"));
18
+ exports.refractorPluginNormalizeSecurityRequirements = _normalizeSecurityRequirements.default;
19
+ var _normalizeServers = _interopRequireDefault(require("./refractor/plugins/normalize-servers.cjs"));
20
+ exports.refractorPluginNormalizeServers = _normalizeServers.default;
15
21
  var _index = _interopRequireWildcard(require("./refractor/index.cjs"));
16
22
  exports.refract = _index.default;
17
23
  exports.refractOpenApi3_0 = _index.refractOpenApi3_0;
@@ -44,6 +50,8 @@ exports.refractSecurityScheme = _index.refractSecurityScheme;
44
50
  exports.refractOAuthFlows = _index.refractOAuthFlows;
45
51
  exports.refractOAuthFlow = _index.refractOAuthFlow;
46
52
  exports.refractSecurityRequirement = _index.refractSecurityRequirement;
53
+ var _toolbox = _interopRequireDefault(require("./refractor/toolbox.cjs"));
54
+ exports.createToolbox = _toolbox.default;
47
55
  var _specification = _interopRequireDefault(require("./refractor/specification.cjs"));
48
56
  exports.specificationObj = _specification.default;
49
57
  var _predicates = require("./predicates.cjs");
package/src/index.mjs CHANGED
@@ -1,7 +1,11 @@
1
1
  export { default as mediaTypes, OpenAPIMediaTypes } from "./media-types.mjs";
2
2
  export { default } from "./namespace.mjs";
3
3
  export { default as refractorPluginReplaceEmptyElement } from "./refractor/plugins/replace-empty-element.mjs";
4
+ export { default as refractorPluginNormalizeParameters } from "./refractor/plugins/normalize-parameters.mjs";
5
+ export { default as refractorPluginNormalizeSecurityRequirements } from "./refractor/plugins/normalize-security-requirements.mjs";
6
+ export { default as refractorPluginNormalizeServers } from "./refractor/plugins/normalize-servers.mjs";
4
7
  export { default as refract, refractOpenApi3_0, refractInfo, refractContact, refractLicense, refractServer, refractServerVariable, refractComponents, refractPaths, refractPathItem, refractOperation, refractExternalDocumentation, refractParameter, refractRequestBody, refractMediaType, refractEncoding, refractResponses, refractResponse, refractCallback, refractExample, refractLink, refractHeader, refractTag, refractReference, refractSchema, refractDiscriminator, refractXml, refractSecurityScheme, refractOAuthFlows, refractOAuthFlow, refractSecurityRequirement } from "./refractor/index.mjs";
8
+ export { default as createToolbox } from "./refractor/toolbox.mjs";
5
9
  export { default as specificationObj } from "./refractor/specification.mjs";
6
10
  export { isCallbackElement, isComponentsElement, isContactElement, isExampleElement, isExternalDocumentationElement, isInfoElement, isLicenseElement, isLinkElement, isOpenapiElement, isOpenApi3_0Element, isOperationElement, isParameterElement, isPathItemElement, isPathsElement, isReferenceElement, isRequestBodyElement, isResponseElement, isResponsesElement, isSchemaElement, isSecurityRequirementElement, isSecuritySchemeElement, isServerElement, isServerVariableElement, isMediaTypeElement, isServersElement } from "./predicates.mjs";
7
11
  export { isReferenceLikeElement, isServerLikeElement, isTagLikeElement, isOpenApiExtension } from "./refractor/predicates.mjs";
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
+ exports.__esModule = true;
5
+ exports.default = void 0;
6
+ var _ramda = require("ramda");
7
+ var _apidomCore = require("@speclynx/apidom-core");
8
+ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
9
+ var _OperationParameters = _interopRequireDefault(require("../../elements/nces/OperationParameters.cjs"));
10
+ var _index = _interopRequireDefault(require("./normalize-storage/index.cjs"));
11
+ var _predicates = require("../../predicates.cjs");
12
+ /**
13
+ * Inheritance of Parameter Objects.
14
+ *
15
+ * OpenAPI 3.0 specification excerpt that defines the inheritance behavior:
16
+ *
17
+ * A list of parameters that are applicable for this operation. If a parameter is already defined at the Path Item,
18
+ * the new definition will override it but can never remove it. The list MUST NOT include duplicated parameters.
19
+ * A unique parameter is defined by a combination of a name and location.
20
+ *
21
+ * NOTE: this plugin is idempotent
22
+ * @public
23
+ */
24
+
25
+ /**
26
+ * Establishes identity between two Parameter Objects.
27
+ * A unique parameter is defined by a combination of a name and location.
28
+ *
29
+ * {@link https://spec.openapis.org/oas/v3.0.4.html#operation-object}
30
+ */
31
+ const parameterEquals = (parameter1, parameter2) => {
32
+ if (!(0, _predicates.isParameterElement)(parameter1)) return false;
33
+ if (!(0, _predicates.isParameterElement)(parameter2)) return false;
34
+ if (!(0, _apidomDatamodel.isStringElement)(parameter1.name)) return false;
35
+ if (!(0, _apidomDatamodel.isStringElement)(parameter1.in)) return false;
36
+ if (!(0, _apidomDatamodel.isStringElement)(parameter2.name)) return false;
37
+ if (!(0, _apidomDatamodel.isStringElement)(parameter2.in)) return false;
38
+ return (0, _apidomCore.toValue)(parameter1.name) === (0, _apidomCore.toValue)(parameter2.name) && (0, _apidomCore.toValue)(parameter1.in) === (0, _apidomCore.toValue)(parameter2.in);
39
+ };
40
+
41
+ /**
42
+ * Inherits parameters from a PathItem into an Operation element.
43
+ * Operation parameters take precedence; PathItem parameters are merged in
44
+ * for any (name, in) combination not already defined at the Operation level.
45
+ * @public
46
+ */
47
+ const inheritParametersToOperation = (operationElement, pathItemElement) => {
48
+ const pathItemParams = (0, _apidomDatamodel.isArrayElement)(pathItemElement.parameters) ? [...pathItemElement.parameters] : [];
49
+ if (pathItemParams.length === 0) return;
50
+ const operationParams = (0, _apidomDatamodel.isArrayElement)(operationElement.parameters) ? [...operationElement.parameters] : [];
51
+
52
+ // prefers the first item if two items compare equal based on the predicate
53
+ const mergedParameters = (0, _ramda.uniqWith)(parameterEquals, [...operationParams, ...pathItemParams]);
54
+ operationElement.parameters = new _OperationParameters.default(mergedParameters);
55
+ };
56
+
57
+ /**
58
+ * @public
59
+ */
60
+ const plugin = ({
61
+ storageField = 'x-normalized'
62
+ } = {}) => toolbox => {
63
+ const {
64
+ predicates
65
+ } = toolbox;
66
+ let storage;
67
+ return {
68
+ visitor: {
69
+ OpenApi3_0Element: {
70
+ enter(path) {
71
+ const element = path.node;
72
+ storage = new _index.default(element, storageField, 'parameters');
73
+ },
74
+ leave() {
75
+ storage = undefined;
76
+ }
77
+ },
78
+ OperationElement: {
79
+ leave(path) {
80
+ const operationElement = path.node;
81
+ const ancestors = path.getAncestorNodes(); // parent to root order
82
+
83
+ // skip visiting this Operation
84
+ if (ancestors.some(predicates.isComponentsElement)) {
85
+ return;
86
+ }
87
+ const parentPathItemElement = ancestors.find(predicates.isPathItemElement);
88
+
89
+ // no parent Path Item to inherit from
90
+ if (!predicates.isPathItemElement(parentPathItemElement)) {
91
+ return;
92
+ }
93
+ const operationJSONPointer = path.formatPath();
94
+
95
+ // skip visiting this Operation Object if it's already normalized
96
+ if (storage.includes(operationJSONPointer)) {
97
+ return;
98
+ }
99
+ inheritParametersToOperation(operationElement, parentPathItemElement);
100
+ storage.append(operationJSONPointer);
101
+ }
102
+ }
103
+ }
104
+ };
105
+ };
106
+ plugin.inheritParametersToOperation = inheritParametersToOperation;
107
+ var _default = exports.default = plugin;
@@ -0,0 +1,101 @@
1
+ import { uniqWith } from 'ramda';
2
+ import { toValue } from '@speclynx/apidom-core';
3
+ import { isStringElement, isArrayElement } from '@speclynx/apidom-datamodel';
4
+ import OperationParametersElement from "../../elements/nces/OperationParameters.mjs";
5
+ import NormalizeStorage from "./normalize-storage/index.mjs";
6
+ import { isParameterElement } from "../../predicates.mjs";
7
+ /**
8
+ * Inheritance of Parameter Objects.
9
+ *
10
+ * OpenAPI 3.0 specification excerpt that defines the inheritance behavior:
11
+ *
12
+ * A list of parameters that are applicable for this operation. If a parameter is already defined at the Path Item,
13
+ * the new definition will override it but can never remove it. The list MUST NOT include duplicated parameters.
14
+ * A unique parameter is defined by a combination of a name and location.
15
+ *
16
+ * NOTE: this plugin is idempotent
17
+ * @public
18
+ */
19
+ /**
20
+ * Establishes identity between two Parameter Objects.
21
+ * A unique parameter is defined by a combination of a name and location.
22
+ *
23
+ * {@link https://spec.openapis.org/oas/v3.0.4.html#operation-object}
24
+ */
25
+ const parameterEquals = (parameter1, parameter2) => {
26
+ if (!isParameterElement(parameter1)) return false;
27
+ if (!isParameterElement(parameter2)) return false;
28
+ if (!isStringElement(parameter1.name)) return false;
29
+ if (!isStringElement(parameter1.in)) return false;
30
+ if (!isStringElement(parameter2.name)) return false;
31
+ if (!isStringElement(parameter2.in)) return false;
32
+ return toValue(parameter1.name) === toValue(parameter2.name) && toValue(parameter1.in) === toValue(parameter2.in);
33
+ };
34
+
35
+ /**
36
+ * Inherits parameters from a PathItem into an Operation element.
37
+ * Operation parameters take precedence; PathItem parameters are merged in
38
+ * for any (name, in) combination not already defined at the Operation level.
39
+ * @public
40
+ */
41
+ const inheritParametersToOperation = (operationElement, pathItemElement) => {
42
+ const pathItemParams = isArrayElement(pathItemElement.parameters) ? [...pathItemElement.parameters] : [];
43
+ if (pathItemParams.length === 0) return;
44
+ const operationParams = isArrayElement(operationElement.parameters) ? [...operationElement.parameters] : [];
45
+
46
+ // prefers the first item if two items compare equal based on the predicate
47
+ const mergedParameters = uniqWith(parameterEquals, [...operationParams, ...pathItemParams]);
48
+ operationElement.parameters = new OperationParametersElement(mergedParameters);
49
+ };
50
+
51
+ /**
52
+ * @public
53
+ */
54
+ const plugin = ({
55
+ storageField = 'x-normalized'
56
+ } = {}) => toolbox => {
57
+ const {
58
+ predicates
59
+ } = toolbox;
60
+ let storage;
61
+ return {
62
+ visitor: {
63
+ OpenApi3_0Element: {
64
+ enter(path) {
65
+ const element = path.node;
66
+ storage = new NormalizeStorage(element, storageField, 'parameters');
67
+ },
68
+ leave() {
69
+ storage = undefined;
70
+ }
71
+ },
72
+ OperationElement: {
73
+ leave(path) {
74
+ const operationElement = path.node;
75
+ const ancestors = path.getAncestorNodes(); // parent to root order
76
+
77
+ // skip visiting this Operation
78
+ if (ancestors.some(predicates.isComponentsElement)) {
79
+ return;
80
+ }
81
+ const parentPathItemElement = ancestors.find(predicates.isPathItemElement);
82
+
83
+ // no parent Path Item to inherit from
84
+ if (!predicates.isPathItemElement(parentPathItemElement)) {
85
+ return;
86
+ }
87
+ const operationJSONPointer = path.formatPath();
88
+
89
+ // skip visiting this Operation Object if it's already normalized
90
+ if (storage.includes(operationJSONPointer)) {
91
+ return;
92
+ }
93
+ inheritParametersToOperation(operationElement, parentPathItemElement);
94
+ storage.append(operationJSONPointer);
95
+ }
96
+ }
97
+ }
98
+ };
99
+ };
100
+ plugin.inheritParametersToOperation = inheritParametersToOperation;
101
+ export default plugin;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
+ exports.__esModule = true;
5
+ exports.default = void 0;
6
+ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
7
+ var _OperationSecurity = _interopRequireDefault(require("../../elements/nces/OperationSecurity.cjs"));
8
+ var _index = _interopRequireDefault(require("./normalize-storage/index.cjs"));
9
+ /**
10
+ * Override of Security Requirement Objects.
11
+ *
12
+ * OpenAPI 3.0 specification excerpt that defines the override behavior:
13
+ *
14
+ * Operation.security definition overrides any declared top-level security.
15
+ * To remove a top-level security declaration, an empty array can be used.
16
+ * When a list of Security Requirement Objects is defined on the OpenAPI Object or Operation Object,
17
+ * only one of the Security Requirement Objects in the list needs to be satisfied to authorize the request.
18
+ *
19
+ * NOTE: this plugin is idempotent
20
+ * @public
21
+ */
22
+
23
+ /**
24
+ * Inherits top-level security requirements into an Operation element.
25
+ * If Operation.security is missing and OpenAPI.security is defined, copies it down.
26
+ * @public
27
+ */
28
+ const inheritSecurityToOperation = (operationElement, openapiElement) => {
29
+ const missingOperationLevelSecurity = typeof operationElement.security === 'undefined';
30
+ const hasTopLevelSecurity = (0, _apidomDatamodel.isArrayElement)(openapiElement.security);
31
+ if (missingOperationLevelSecurity && hasTopLevelSecurity) {
32
+ operationElement.security = new _OperationSecurity.default([...openapiElement.security]);
33
+ }
34
+ };
35
+
36
+ /**
37
+ * @public
38
+ */
39
+ const plugin = ({
40
+ storageField = 'x-normalized'
41
+ } = {}) => toolbox => {
42
+ const {
43
+ predicates
44
+ } = toolbox;
45
+ let topLevelSecurity;
46
+ let storage;
47
+ return {
48
+ visitor: {
49
+ OpenApi3_0Element: {
50
+ enter(path) {
51
+ const openapiElement = path.node;
52
+ storage = new _index.default(openapiElement, storageField, 'security-requirements');
53
+ if (predicates.isArrayElement(openapiElement.security)) {
54
+ topLevelSecurity = openapiElement.security;
55
+ }
56
+ },
57
+ leave() {
58
+ storage = undefined;
59
+ topLevelSecurity = undefined;
60
+ }
61
+ },
62
+ OperationElement: {
63
+ leave(path) {
64
+ const operationElement = path.node;
65
+ const ancestors = path.getAncestorNodes(); // parent to root order
66
+
67
+ // skip visiting this Operation
68
+ if (ancestors.some(predicates.isComponentsElement)) {
69
+ return;
70
+ }
71
+ const operationJSONPointer = path.formatPath();
72
+
73
+ // skip visiting this Operation Object if it's already normalized
74
+ if (storage.includes(operationJSONPointer)) {
75
+ return;
76
+ }
77
+ const missingOperationLevelSecurity = typeof operationElement.security === 'undefined';
78
+ const hasTopLevelSecurity = typeof topLevelSecurity !== 'undefined';
79
+ if (missingOperationLevelSecurity && hasTopLevelSecurity) {
80
+ operationElement.security = new _OperationSecurity.default([...topLevelSecurity]);
81
+ storage.append(operationJSONPointer);
82
+ }
83
+ }
84
+ }
85
+ }
86
+ };
87
+ };
88
+ plugin.inheritSecurityToOperation = inheritSecurityToOperation;
89
+ var _default = exports.default = plugin;
@@ -0,0 +1,83 @@
1
+ import { isArrayElement } from '@speclynx/apidom-datamodel';
2
+ import OperationSecurityElement from "../../elements/nces/OperationSecurity.mjs";
3
+ import NormalizeStorage from "./normalize-storage/index.mjs";
4
+ /**
5
+ * Override of Security Requirement Objects.
6
+ *
7
+ * OpenAPI 3.0 specification excerpt that defines the override behavior:
8
+ *
9
+ * Operation.security definition overrides any declared top-level security.
10
+ * To remove a top-level security declaration, an empty array can be used.
11
+ * When a list of Security Requirement Objects is defined on the OpenAPI Object or Operation Object,
12
+ * only one of the Security Requirement Objects in the list needs to be satisfied to authorize the request.
13
+ *
14
+ * NOTE: this plugin is idempotent
15
+ * @public
16
+ */
17
+ /**
18
+ * Inherits top-level security requirements into an Operation element.
19
+ * If Operation.security is missing and OpenAPI.security is defined, copies it down.
20
+ * @public
21
+ */
22
+ const inheritSecurityToOperation = (operationElement, openapiElement) => {
23
+ const missingOperationLevelSecurity = typeof operationElement.security === 'undefined';
24
+ const hasTopLevelSecurity = isArrayElement(openapiElement.security);
25
+ if (missingOperationLevelSecurity && hasTopLevelSecurity) {
26
+ operationElement.security = new OperationSecurityElement([...openapiElement.security]);
27
+ }
28
+ };
29
+
30
+ /**
31
+ * @public
32
+ */
33
+ const plugin = ({
34
+ storageField = 'x-normalized'
35
+ } = {}) => toolbox => {
36
+ const {
37
+ predicates
38
+ } = toolbox;
39
+ let topLevelSecurity;
40
+ let storage;
41
+ return {
42
+ visitor: {
43
+ OpenApi3_0Element: {
44
+ enter(path) {
45
+ const openapiElement = path.node;
46
+ storage = new NormalizeStorage(openapiElement, storageField, 'security-requirements');
47
+ if (predicates.isArrayElement(openapiElement.security)) {
48
+ topLevelSecurity = openapiElement.security;
49
+ }
50
+ },
51
+ leave() {
52
+ storage = undefined;
53
+ topLevelSecurity = undefined;
54
+ }
55
+ },
56
+ OperationElement: {
57
+ leave(path) {
58
+ const operationElement = path.node;
59
+ const ancestors = path.getAncestorNodes(); // parent to root order
60
+
61
+ // skip visiting this Operation
62
+ if (ancestors.some(predicates.isComponentsElement)) {
63
+ return;
64
+ }
65
+ const operationJSONPointer = path.formatPath();
66
+
67
+ // skip visiting this Operation Object if it's already normalized
68
+ if (storage.includes(operationJSONPointer)) {
69
+ return;
70
+ }
71
+ const missingOperationLevelSecurity = typeof operationElement.security === 'undefined';
72
+ const hasTopLevelSecurity = typeof topLevelSecurity !== 'undefined';
73
+ if (missingOperationLevelSecurity && hasTopLevelSecurity) {
74
+ operationElement.security = new OperationSecurityElement([...topLevelSecurity]);
75
+ storage.append(operationJSONPointer);
76
+ }
77
+ }
78
+ }
79
+ }
80
+ };
81
+ };
82
+ plugin.inheritSecurityToOperation = inheritSecurityToOperation;
83
+ export default plugin;
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
+ exports.__esModule = true;
5
+ exports.default = void 0;
6
+ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
7
+ var _Servers = _interopRequireDefault(require("../../elements/nces/Servers.cjs"));
8
+ var _PathItemServers = _interopRequireDefault(require("../../elements/nces/PathItemServers.cjs"));
9
+ var _OperationServers = _interopRequireDefault(require("../../elements/nces/OperationServers.cjs"));
10
+ var _index = _interopRequireDefault(require("./normalize-storage/index.cjs"));
11
+ var _index2 = require("../index.cjs");
12
+ /**
13
+ * Override of Server Objects.
14
+ *
15
+ * List of Server Objects can be defined in OpenAPI 3.0 on multiple levels:
16
+ *
17
+ * - OpenAPI.servers
18
+ * - PathItem.servers
19
+ * - Operation.servers
20
+ *
21
+ * If a servers array is specified at the OpenAPI Object level, it will be overridden by `PathItem`.servers.
22
+ * If a servers array is specified at the Path Item Object or OpenAPI Object level, it will be overridden by Operation.servers.
23
+ * @public
24
+ */
25
+
26
+ /**
27
+ * Ensures the OpenAPI document has at least one server defined.
28
+ * If `servers` is missing or empty, adds a default server with `url: "/"`.
29
+ * @public
30
+ */
31
+ const ensureDefaultServer = openapiElement => {
32
+ const isServersUndefined = typeof openapiElement.servers === 'undefined';
33
+ const isServersArray = (0, _apidomDatamodel.isArrayElement)(openapiElement.servers);
34
+ const isServersEmpty = isServersArray && openapiElement.servers.length === 0;
35
+ const defaultServer = (0, _index2.refractServer)({
36
+ url: '/'
37
+ });
38
+ if (isServersUndefined || !isServersArray) {
39
+ openapiElement.servers = new _Servers.default([defaultServer]);
40
+ } else if (isServersArray && isServersEmpty) {
41
+ openapiElement.servers.push(defaultServer);
42
+ }
43
+ };
44
+
45
+ /**
46
+ * Inherits servers from the OpenAPI root into a PathItem element.
47
+ * If PathItem.servers is missing or empty, copies from OpenAPI.servers.
48
+ * @public
49
+ */
50
+ const inheritServersToPathItem = (pathItemElement, openapiElement) => {
51
+ const isServersUndefined = typeof pathItemElement.servers === 'undefined';
52
+ const isServersArray = (0, _apidomDatamodel.isArrayElement)(pathItemElement.servers);
53
+ const isServersEmpty = isServersArray && pathItemElement.servers.length === 0;
54
+ const openapiServers = [...(openapiElement.servers ?? [])];
55
+ if (isServersUndefined || !isServersArray) {
56
+ pathItemElement.servers = new _PathItemServers.default(openapiServers);
57
+ } else if (isServersArray && isServersEmpty) {
58
+ openapiServers.forEach(server => {
59
+ pathItemElement.servers.push(server);
60
+ });
61
+ }
62
+ };
63
+
64
+ /**
65
+ * Inherits servers from a PathItem into an Operation element.
66
+ * If Operation.servers is missing or empty, copies from PathItem.servers.
67
+ * @public
68
+ */
69
+ const inheritServersToOperation = (operationElement, pathItemElement) => {
70
+ const isServersUndefined = typeof operationElement.servers === 'undefined';
71
+ const isServersArray = (0, _apidomDatamodel.isArrayElement)(operationElement.servers);
72
+ const isServersEmpty = isServersArray && operationElement.servers.length === 0;
73
+ const pathItemServers = [...(pathItemElement.servers ?? [])];
74
+ if (isServersUndefined || !isServersArray) {
75
+ operationElement.servers = new _OperationServers.default(pathItemServers);
76
+ } else if (isServersArray && isServersEmpty) {
77
+ pathItemServers.forEach(server => {
78
+ operationElement.servers.push(server);
79
+ });
80
+ }
81
+ };
82
+
83
+ /**
84
+ * @public
85
+ */
86
+ const plugin = ({
87
+ storageField = 'x-normalized'
88
+ } = {}) => toolbox => {
89
+ const {
90
+ predicates
91
+ } = toolbox;
92
+ let storage;
93
+ return {
94
+ visitor: {
95
+ OpenApi3_0Element: {
96
+ enter(path) {
97
+ const openapiElement = path.node;
98
+ ensureDefaultServer(openapiElement);
99
+ storage = new _index.default(openapiElement, storageField, 'servers');
100
+ },
101
+ leave() {
102
+ storage = undefined;
103
+ }
104
+ },
105
+ PathItemElement(path) {
106
+ const pathItemElement = path.node;
107
+ const ancestors = path.getAncestorNodes(); // parent to root order
108
+
109
+ // skip visiting this Path Item
110
+ if (ancestors.some(predicates.isComponentsElement)) return;
111
+ if (!ancestors.some(predicates.isOpenApi3_0Element)) return;
112
+ const pathItemJSONPointer = path.formatPath();
113
+
114
+ // skip visiting this Path Item Object if it's already normalized
115
+ if (storage.includes(pathItemJSONPointer)) {
116
+ return;
117
+ }
118
+ const parentOpenapiElement = ancestors.find(predicates.isOpenApi3_0Element);
119
+ if (predicates.isOpenApi3_0Element(parentOpenapiElement)) {
120
+ inheritServersToPathItem(pathItemElement, parentOpenapiElement);
121
+ storage.append(pathItemJSONPointer);
122
+ }
123
+ },
124
+ OperationElement(path) {
125
+ const operationElement = path.node;
126
+ const ancestors = path.getAncestorNodes(); // parent to root order
127
+
128
+ // skip visiting this Operation
129
+ if (ancestors.some(predicates.isComponentsElement)) return;
130
+ if (!ancestors.some(predicates.isOpenApi3_0Element)) return;
131
+ const operationJSONPointer = path.formatPath();
132
+
133
+ // skip visiting this Operation Object if it's already normalized
134
+ if (storage.includes(operationJSONPointer)) {
135
+ return;
136
+ }
137
+ const parentPathItemElement = ancestors.find(predicates.isPathItemElement);
138
+ if (predicates.isPathItemElement(parentPathItemElement)) {
139
+ inheritServersToOperation(operationElement, parentPathItemElement);
140
+ storage.append(operationJSONPointer);
141
+ }
142
+ }
143
+ }
144
+ };
145
+ };
146
+ plugin.ensureDefaultServer = ensureDefaultServer;
147
+ plugin.inheritServersToPathItem = inheritServersToPathItem;
148
+ plugin.inheritServersToOperation = inheritServersToOperation;
149
+ var _default = exports.default = plugin;