@speclynx/apidom-ns-openapi-3-1 1.12.1

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.
Files changed (198) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +202 -0
  3. package/LICENSES/AFL-3.0.txt +182 -0
  4. package/LICENSES/Apache-2.0.txt +202 -0
  5. package/LICENSES/BSD-3-Clause.txt +26 -0
  6. package/LICENSES/MIT.txt +9 -0
  7. package/NOTICE +65 -0
  8. package/README.md +472 -0
  9. package/dist/apidom-ns-openapi-3-1.browser.js +36144 -0
  10. package/dist/apidom-ns-openapi-3-1.browser.min.js +1 -0
  11. package/package.json +70 -0
  12. package/src/elements/Callback.cjs +10 -0
  13. package/src/elements/Callback.mjs +7 -0
  14. package/src/elements/Components.cjs +17 -0
  15. package/src/elements/Components.mjs +14 -0
  16. package/src/elements/Contact.cjs +10 -0
  17. package/src/elements/Contact.mjs +7 -0
  18. package/src/elements/Discriminator.cjs +10 -0
  19. package/src/elements/Discriminator.mjs +7 -0
  20. package/src/elements/Encoding.cjs +10 -0
  21. package/src/elements/Encoding.mjs +7 -0
  22. package/src/elements/Example.cjs +10 -0
  23. package/src/elements/Example.mjs +7 -0
  24. package/src/elements/ExternalDocumentation.cjs +10 -0
  25. package/src/elements/ExternalDocumentation.mjs +7 -0
  26. package/src/elements/Header.cjs +17 -0
  27. package/src/elements/Header.mjs +13 -0
  28. package/src/elements/Info.cjs +23 -0
  29. package/src/elements/Info.mjs +19 -0
  30. package/src/elements/JsonSchemaDialect.cjs +16 -0
  31. package/src/elements/JsonSchemaDialect.mjs +13 -0
  32. package/src/elements/License.cjs +17 -0
  33. package/src/elements/License.mjs +14 -0
  34. package/src/elements/Link.cjs +10 -0
  35. package/src/elements/Link.mjs +7 -0
  36. package/src/elements/MediaType.cjs +17 -0
  37. package/src/elements/MediaType.mjs +13 -0
  38. package/src/elements/OAuthFlow.cjs +10 -0
  39. package/src/elements/OAuthFlow.mjs +7 -0
  40. package/src/elements/OAuthFlows.cjs +10 -0
  41. package/src/elements/OAuthFlows.mjs +7 -0
  42. package/src/elements/OpenApi3-1.cjs +77 -0
  43. package/src/elements/OpenApi3-1.mjs +73 -0
  44. package/src/elements/Openapi.cjs +10 -0
  45. package/src/elements/Openapi.mjs +7 -0
  46. package/src/elements/Operation.cjs +17 -0
  47. package/src/elements/Operation.mjs +13 -0
  48. package/src/elements/Parameter.cjs +17 -0
  49. package/src/elements/Parameter.mjs +13 -0
  50. package/src/elements/PathItem.cjs +59 -0
  51. package/src/elements/PathItem.mjs +55 -0
  52. package/src/elements/Paths.cjs +10 -0
  53. package/src/elements/Paths.mjs +7 -0
  54. package/src/elements/Reference.cjs +28 -0
  55. package/src/elements/Reference.mjs +25 -0
  56. package/src/elements/RequestBody.cjs +10 -0
  57. package/src/elements/RequestBody.mjs +7 -0
  58. package/src/elements/Response.cjs +10 -0
  59. package/src/elements/Response.mjs +7 -0
  60. package/src/elements/Responses.cjs +10 -0
  61. package/src/elements/Responses.mjs +7 -0
  62. package/src/elements/Schema.cjs +50 -0
  63. package/src/elements/Schema.mjs +46 -0
  64. package/src/elements/SecurityRequirement.cjs +10 -0
  65. package/src/elements/SecurityRequirement.mjs +7 -0
  66. package/src/elements/SecurityScheme.cjs +10 -0
  67. package/src/elements/SecurityScheme.mjs +7 -0
  68. package/src/elements/Server.cjs +10 -0
  69. package/src/elements/Server.mjs +7 -0
  70. package/src/elements/ServerVariable.cjs +10 -0
  71. package/src/elements/ServerVariable.mjs +7 -0
  72. package/src/elements/Tag.cjs +10 -0
  73. package/src/elements/Tag.mjs +7 -0
  74. package/src/elements/Xml.cjs +10 -0
  75. package/src/elements/Xml.mjs +7 -0
  76. package/src/elements/nces/ComponentsPathItems.cjs +16 -0
  77. package/src/elements/nces/ComponentsPathItems.mjs +13 -0
  78. package/src/elements/nces/Webhooks.cjs +16 -0
  79. package/src/elements/nces/Webhooks.mjs +13 -0
  80. package/src/index.cjs +158 -0
  81. package/src/index.mjs +28 -0
  82. package/src/media-types.cjs +34 -0
  83. package/src/media-types.mjs +30 -0
  84. package/src/namespace.cjs +82 -0
  85. package/src/namespace.mjs +76 -0
  86. package/src/predicates.cjs +365 -0
  87. package/src/predicates.mjs +357 -0
  88. package/src/refractor/index.cjs +45 -0
  89. package/src/refractor/index.mjs +39 -0
  90. package/src/refractor/plugins/normalize-header-examples/NormalizeStorage.cjs +38 -0
  91. package/src/refractor/plugins/normalize-header-examples/NormalizeStorage.mjs +34 -0
  92. package/src/refractor/plugins/normalize-header-examples/index.cjs +105 -0
  93. package/src/refractor/plugins/normalize-header-examples/index.mjs +99 -0
  94. package/src/refractor/plugins/normalize-operation-ids.cjs +159 -0
  95. package/src/refractor/plugins/normalize-operation-ids.mjs +154 -0
  96. package/src/refractor/plugins/normalize-parameter-examples.cjs +105 -0
  97. package/src/refractor/plugins/normalize-parameter-examples.mjs +99 -0
  98. package/src/refractor/plugins/normalize-parameters.cjs +103 -0
  99. package/src/refractor/plugins/normalize-parameters.mjs +97 -0
  100. package/src/refractor/plugins/normalize-security-requirements.cjs +71 -0
  101. package/src/refractor/plugins/normalize-security-requirements.mjs +65 -0
  102. package/src/refractor/plugins/normalize-servers.cjs +118 -0
  103. package/src/refractor/plugins/normalize-servers.mjs +112 -0
  104. package/src/refractor/plugins/replace-empty-element.cjs +665 -0
  105. package/src/refractor/plugins/replace-empty-element.mjs +658 -0
  106. package/src/refractor/registration.cjs +102 -0
  107. package/src/refractor/registration.mjs +66 -0
  108. package/src/refractor/specification.cjs +492 -0
  109. package/src/refractor/specification.mjs +487 -0
  110. package/src/refractor/toolbox.cjs +70 -0
  111. package/src/refractor/toolbox.mjs +60 -0
  112. package/src/refractor/visitors/open-api-3-1/JsonSchemaDialectVisitor.cjs +25 -0
  113. package/src/refractor/visitors/open-api-3-1/JsonSchemaDialectVisitor.mjs +19 -0
  114. package/src/refractor/visitors/open-api-3-1/WebhooksVisitor.cjs +44 -0
  115. package/src/refractor/visitors/open-api-3-1/WebhooksVisitor.mjs +38 -0
  116. package/src/refractor/visitors/open-api-3-1/callback/index.cjs +37 -0
  117. package/src/refractor/visitors/open-api-3-1/callback/index.mjs +32 -0
  118. package/src/refractor/visitors/open-api-3-1/components/PathItemsVisitor.cjs +34 -0
  119. package/src/refractor/visitors/open-api-3-1/components/PathItemsVisitor.mjs +28 -0
  120. package/src/refractor/visitors/open-api-3-1/components/SchemasVisitor.cjs +22 -0
  121. package/src/refractor/visitors/open-api-3-1/components/SchemasVisitor.mjs +19 -0
  122. package/src/refractor/visitors/open-api-3-1/components/index.cjs +21 -0
  123. package/src/refractor/visitors/open-api-3-1/components/index.mjs +16 -0
  124. package/src/refractor/visitors/open-api-3-1/contact/index.cjs +21 -0
  125. package/src/refractor/visitors/open-api-3-1/contact/index.mjs +16 -0
  126. package/src/refractor/visitors/open-api-3-1/distriminator/index.cjs +22 -0
  127. package/src/refractor/visitors/open-api-3-1/distriminator/index.mjs +17 -0
  128. package/src/refractor/visitors/open-api-3-1/encoding/index.cjs +21 -0
  129. package/src/refractor/visitors/open-api-3-1/encoding/index.mjs +16 -0
  130. package/src/refractor/visitors/open-api-3-1/example/index.cjs +21 -0
  131. package/src/refractor/visitors/open-api-3-1/example/index.mjs +16 -0
  132. package/src/refractor/visitors/open-api-3-1/external-documentation/index.cjs +21 -0
  133. package/src/refractor/visitors/open-api-3-1/external-documentation/index.mjs +16 -0
  134. package/src/refractor/visitors/open-api-3-1/header/index.cjs +21 -0
  135. package/src/refractor/visitors/open-api-3-1/header/index.mjs +16 -0
  136. package/src/refractor/visitors/open-api-3-1/index.cjs +31 -0
  137. package/src/refractor/visitors/open-api-3-1/index.mjs +25 -0
  138. package/src/refractor/visitors/open-api-3-1/info/index.cjs +21 -0
  139. package/src/refractor/visitors/open-api-3-1/info/index.mjs +16 -0
  140. package/src/refractor/visitors/open-api-3-1/license/index.cjs +21 -0
  141. package/src/refractor/visitors/open-api-3-1/license/index.mjs +16 -0
  142. package/src/refractor/visitors/open-api-3-1/link/index.cjs +21 -0
  143. package/src/refractor/visitors/open-api-3-1/link/index.mjs +16 -0
  144. package/src/refractor/visitors/open-api-3-1/media-type/index.cjs +21 -0
  145. package/src/refractor/visitors/open-api-3-1/media-type/index.mjs +16 -0
  146. package/src/refractor/visitors/open-api-3-1/oauth-flow/index.cjs +21 -0
  147. package/src/refractor/visitors/open-api-3-1/oauth-flow/index.mjs +16 -0
  148. package/src/refractor/visitors/open-api-3-1/oauth-flows/index.cjs +21 -0
  149. package/src/refractor/visitors/open-api-3-1/oauth-flows/index.mjs +16 -0
  150. package/src/refractor/visitors/open-api-3-1/operation/index.cjs +21 -0
  151. package/src/refractor/visitors/open-api-3-1/operation/index.mjs +16 -0
  152. package/src/refractor/visitors/open-api-3-1/parameter/index.cjs +21 -0
  153. package/src/refractor/visitors/open-api-3-1/parameter/index.mjs +16 -0
  154. package/src/refractor/visitors/open-api-3-1/path-item/index.cjs +21 -0
  155. package/src/refractor/visitors/open-api-3-1/path-item/index.mjs +16 -0
  156. package/src/refractor/visitors/open-api-3-1/paths/index.cjs +21 -0
  157. package/src/refractor/visitors/open-api-3-1/paths/index.mjs +16 -0
  158. package/src/refractor/visitors/open-api-3-1/reference/index.cjs +21 -0
  159. package/src/refractor/visitors/open-api-3-1/reference/index.mjs +16 -0
  160. package/src/refractor/visitors/open-api-3-1/request-body/index.cjs +21 -0
  161. package/src/refractor/visitors/open-api-3-1/request-body/index.mjs +16 -0
  162. package/src/refractor/visitors/open-api-3-1/response/index.cjs +21 -0
  163. package/src/refractor/visitors/open-api-3-1/response/index.mjs +16 -0
  164. package/src/refractor/visitors/open-api-3-1/responses/index.cjs +21 -0
  165. package/src/refractor/visitors/open-api-3-1/responses/index.mjs +16 -0
  166. package/src/refractor/visitors/open-api-3-1/schema/$defsVisitor.cjs +19 -0
  167. package/src/refractor/visitors/open-api-3-1/schema/$defsVisitor.mjs +16 -0
  168. package/src/refractor/visitors/open-api-3-1/schema/AllOfVisitor.cjs +15 -0
  169. package/src/refractor/visitors/open-api-3-1/schema/AllOfVisitor.mjs +11 -0
  170. package/src/refractor/visitors/open-api-3-1/schema/AnyOfVisitor.cjs +15 -0
  171. package/src/refractor/visitors/open-api-3-1/schema/AnyOfVisitor.mjs +11 -0
  172. package/src/refractor/visitors/open-api-3-1/schema/DependentSchemasVisitor.cjs +15 -0
  173. package/src/refractor/visitors/open-api-3-1/schema/DependentSchemasVisitor.mjs +11 -0
  174. package/src/refractor/visitors/open-api-3-1/schema/OneOfVisitor.cjs +15 -0
  175. package/src/refractor/visitors/open-api-3-1/schema/OneOfVisitor.mjs +11 -0
  176. package/src/refractor/visitors/open-api-3-1/schema/PatternPropertiesVisitor.cjs +15 -0
  177. package/src/refractor/visitors/open-api-3-1/schema/PatternPropertiesVisitor.mjs +11 -0
  178. package/src/refractor/visitors/open-api-3-1/schema/PrefixItemsVisitor.cjs +15 -0
  179. package/src/refractor/visitors/open-api-3-1/schema/PrefixItemsVisitor.mjs +11 -0
  180. package/src/refractor/visitors/open-api-3-1/schema/PropertiesVisitor.cjs +15 -0
  181. package/src/refractor/visitors/open-api-3-1/schema/PropertiesVisitor.mjs +11 -0
  182. package/src/refractor/visitors/open-api-3-1/schema/index.cjs +75 -0
  183. package/src/refractor/visitors/open-api-3-1/schema/index.mjs +69 -0
  184. package/src/refractor/visitors/open-api-3-1/security-requirement/index.cjs +21 -0
  185. package/src/refractor/visitors/open-api-3-1/security-requirement/index.mjs +16 -0
  186. package/src/refractor/visitors/open-api-3-1/security-scheme/index.cjs +21 -0
  187. package/src/refractor/visitors/open-api-3-1/security-scheme/index.mjs +16 -0
  188. package/src/refractor/visitors/open-api-3-1/server/index.cjs +21 -0
  189. package/src/refractor/visitors/open-api-3-1/server/index.mjs +16 -0
  190. package/src/refractor/visitors/open-api-3-1/server-variable/index.cjs +21 -0
  191. package/src/refractor/visitors/open-api-3-1/server-variable/index.mjs +16 -0
  192. package/src/refractor/visitors/open-api-3-1/tag/index.cjs +21 -0
  193. package/src/refractor/visitors/open-api-3-1/tag/index.mjs +16 -0
  194. package/src/refractor/visitors/open-api-3-1/xml/index.cjs +21 -0
  195. package/src/refractor/visitors/open-api-3-1/xml/index.mjs +16 -0
  196. package/src/traversal/visitor.cjs +57 -0
  197. package/src/traversal/visitor.mjs +54 -0
  198. package/types/apidom-ns-openapi-3-1.d.ts +2745 -0
@@ -0,0 +1,99 @@
1
+ import { cloneDeep } from '@speclynx/apidom-core';
2
+ import NormalizeStorage from "./NormalizeStorage.mjs";
3
+ /**
4
+ * Override of Schema.example and Schema.examples field inside the Header Objects.
5
+ *
6
+ * Header Object has two fixed fields:
7
+ * - `example` of type `Any`
8
+ * - `examples` of type `Map[string, Example Object | Reference Object]`
9
+ *
10
+ * OpenAPI 3.1 specification excerpt that defines the override behavior:
11
+ *
12
+ * The example value SHALL override the example provided by the schema.
13
+ * Furthermore, if referencing a schema that contains an example, the examples value SHALL override the example provided by the schema.
14
+ *
15
+ * NOTE: this plugin is idempotent
16
+ * @public
17
+ */
18
+ /**
19
+ * @public
20
+ */
21
+ const plugin = ({
22
+ storageField = 'x-normalized'
23
+ } = {}) => toolbox => {
24
+ const {
25
+ predicates,
26
+ ancestorLineageToJSONPointer
27
+ } = toolbox;
28
+ let storage;
29
+ return {
30
+ visitor: {
31
+ OpenApi3_1Element: {
32
+ enter(element) {
33
+ storage = new NormalizeStorage(element, storageField, 'header-examples');
34
+ },
35
+ leave() {
36
+ storage = undefined;
37
+ }
38
+ },
39
+ HeaderElement: {
40
+ leave(headerElement, key, parent, path, ancestors) {
41
+ // skip visiting this Header Object
42
+ if (ancestors.some(predicates.isComponentsElement)) {
43
+ return;
44
+ }
45
+
46
+ // no Header.schema field present
47
+ if (typeof headerElement.schema === 'undefined' || !predicates.isSchemaElement(headerElement.schema)) {
48
+ return;
49
+ }
50
+ // Schema contains no example
51
+ if (typeof headerElement.schema?.example === 'undefined' && typeof headerElement.schema?.examples === 'undefined') {
52
+ return;
53
+ }
54
+ const headerJSONPointer = ancestorLineageToJSONPointer([...ancestors, parent, headerElement]);
55
+
56
+ // skip visiting this Header Object if it's already normalized
57
+ if (storage.includes(headerJSONPointer)) {
58
+ return;
59
+ }
60
+
61
+ /**
62
+ * Header.examples and Schema.examples have preferences over the older
63
+ * and deprected `example` field.
64
+ */
65
+ if (typeof headerElement.examples !== 'undefined' && predicates.isObjectElement(headerElement.examples)) {
66
+ // @ts-ignore
67
+ const examples = headerElement.examples.map(example => {
68
+ return cloneDeep.safe(example.value);
69
+ });
70
+ if (typeof headerElement.schema.examples !== 'undefined') {
71
+ headerElement.schema.set('examples', examples);
72
+ storage.append(headerJSONPointer);
73
+ }
74
+ if (typeof headerElement.schema.example !== 'undefined') {
75
+ headerElement.schema.set('example', examples[0]);
76
+ storage.append(headerJSONPointer);
77
+ }
78
+ return;
79
+ }
80
+
81
+ /**
82
+ * Handle deprecated `example` field.
83
+ */
84
+ if (typeof headerElement.example !== 'undefined') {
85
+ if (typeof headerElement.schema.examples !== 'undefined') {
86
+ headerElement.schema.set('examples', [cloneDeep(headerElement.example)]);
87
+ storage.append(headerJSONPointer);
88
+ }
89
+ if (typeof headerElement.schema.example !== 'undefined') {
90
+ headerElement.schema.set('example', cloneDeep(headerElement.example));
91
+ storage.append(headerJSONPointer);
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ };
98
+ };
99
+ export default plugin;
@@ -0,0 +1,159 @@
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 _NormalizeStorage = _interopRequireDefault(require("./normalize-header-examples/NormalizeStorage.cjs"));
9
+ const removeSpaces = operationId => {
10
+ return operationId.replace(/\s/g, '');
11
+ };
12
+ const replaceSpecialCharsWithUnderscore = operationId => {
13
+ return operationId.replace(/\W/gi, '_');
14
+ };
15
+ const createNormalizedOperationId = (path, method) => {
16
+ const normalizedMethod = replaceSpecialCharsWithUnderscore(removeSpaces(method.toLowerCase()));
17
+ const normalizedPath = replaceSpecialCharsWithUnderscore(removeSpaces(path));
18
+ return `${normalizedMethod}${normalizedPath}`;
19
+ };
20
+ const normalizeOperationId = (operationId, path, method) => {
21
+ const withoutSpaces = removeSpaces(operationId);
22
+ if (withoutSpaces.length > 0) {
23
+ return replaceSpecialCharsWithUnderscore(withoutSpaces);
24
+ }
25
+ return createNormalizedOperationId(path, method);
26
+ };
27
+
28
+ /**
29
+ * Normalization of Operation.operationId field.
30
+ *
31
+ * This normalization is not guided by OpenAPI 3.1 specification.
32
+ *
33
+ * Existing Operation.operationId fields are normalized into snake case form.
34
+ *
35
+ * Operation Objects, that do not define operationId field, are left untouched.
36
+ *
37
+ * Original operationId is stored in meta and as new `__originalOperationId` field.
38
+ *
39
+ * This plugin also guarantees the uniqueness of all defined Operation.operationId fields,
40
+ * and make sure Link.operationId fields are pointing to correct and normalized Operation.operationId fields.
41
+ *
42
+ * NOTE: this plugin is idempotent
43
+ * @public
44
+ */
45
+
46
+ /**
47
+ * @public
48
+ */
49
+ const plugin = ({
50
+ storageField = 'x-normalized',
51
+ operationIdNormalizer = normalizeOperationId
52
+ } = {}) => toolbox => {
53
+ const {
54
+ predicates,
55
+ ancestorLineageToJSONPointer,
56
+ namespace
57
+ } = toolbox;
58
+ const pathTemplates = [];
59
+ const normalizedOperations = [];
60
+ const links = [];
61
+ let storage;
62
+ return {
63
+ visitor: {
64
+ OpenApi3_1Element: {
65
+ enter(element) {
66
+ storage = new _NormalizeStorage.default(element, storageField, 'operation-ids');
67
+ },
68
+ leave() {
69
+ // group normalized operations by normalized operationId
70
+ const normalizedOperationGroups = (0, _ramda.groupBy)(operationElement => {
71
+ return (0, _apidomCore.toValue)(operationElement.operationId);
72
+ }, normalizedOperations);
73
+
74
+ // append incremental numerical suffixes to identical operationIds
75
+ Object.entries(normalizedOperationGroups).forEach(([normalizedOperationId, operationElements]) => {
76
+ if (!Array.isArray(operationElements)) return;
77
+ if (operationElements.length <= 1) return;
78
+ operationElements.forEach((operationElement, index) => {
79
+ const indexedNormalizedOperationId = `${normalizedOperationId}${index + 1}`;
80
+ // @ts-ignore
81
+ operationElement.operationId = new namespace.elements.String(indexedNormalizedOperationId);
82
+ });
83
+ });
84
+
85
+ // rectify possibly broken Link.operationId fields
86
+ links.forEach(linkElement => {
87
+ if (typeof linkElement.operationId === 'undefined') return;
88
+ const linkOperationId = String((0, _apidomCore.toValue)(linkElement.operationId));
89
+ const operationElement = normalizedOperations.find(normalizedOperationElement => {
90
+ const originalOperationId = (0, _apidomCore.toValue)(normalizedOperationElement.meta.get('originalOperationId'));
91
+ return originalOperationId === linkOperationId;
92
+ });
93
+
94
+ // Link Object doesn't need to be rectified
95
+ if (typeof operationElement === 'undefined') return;
96
+ linkElement.operationId = _apidomCore.cloneDeep.safe(operationElement.operationId);
97
+ linkElement.meta.set('originalOperationId', linkOperationId);
98
+ linkElement.set('__originalOperationId', linkOperationId);
99
+ });
100
+
101
+ // cleanup the references
102
+ normalizedOperations.length = 0;
103
+ links.length = 0;
104
+ storage = undefined;
105
+ }
106
+ },
107
+ PathItemElement: {
108
+ enter(pathItemElement) {
109
+ // `path` meta may not be always available, e.g. in Callback Object or Components Object
110
+ const pathTemplate = (0, _ramda.defaultTo)('path', (0, _apidomCore.toValue)(pathItemElement.meta.get('path')));
111
+ pathTemplates.push(pathTemplate);
112
+ },
113
+ leave() {
114
+ pathTemplates.pop();
115
+ }
116
+ },
117
+ OperationElement: {
118
+ enter(operationElement, key, parent, path, ancestors) {
119
+ // operationId field is undefined, needs no normalization
120
+ if (typeof operationElement.operationId === 'undefined') return;
121
+ const operationJSONPointer = ancestorLineageToJSONPointer([...ancestors, parent, operationElement]);
122
+
123
+ // skip visiting this Operation Object if it's already normalized
124
+ if (storage.includes(operationJSONPointer)) {
125
+ return;
126
+ }
127
+
128
+ // cast operationId to string type
129
+ const originalOperationId = String((0, _apidomCore.toValue)(operationElement.operationId));
130
+ // perform operationId normalization
131
+ const pathTemplate = (0, _ramda.last)(pathTemplates);
132
+ // `http-method` meta may not be always available, e.g. in Callback Object or Components Object
133
+ const method = (0, _ramda.defaultTo)('method', (0, _apidomCore.toValue)(operationElement.meta.get('http-method')));
134
+ const normalizedOperationId = operationIdNormalizer(originalOperationId, pathTemplate, method);
135
+
136
+ // normalization is not necessary
137
+ if (originalOperationId === normalizedOperationId) return;
138
+
139
+ // @ts-ignore
140
+ operationElement.operationId = new namespace.elements.String(normalizedOperationId);
141
+ operationElement.set('__originalOperationId', originalOperationId);
142
+ operationElement.meta.set('originalOperationId', originalOperationId);
143
+ normalizedOperations.push(operationElement);
144
+ storage.append(operationJSONPointer);
145
+ }
146
+ },
147
+ LinkElement: {
148
+ leave(linkElement) {
149
+ // make sure this Link elements doesn't come from base namespace
150
+ if (!predicates.isLinkElement(linkElement)) return;
151
+ // ignore Link Objects with undefined operationId
152
+ if (typeof linkElement.operationId === 'undefined') return;
153
+ links.push(linkElement);
154
+ }
155
+ }
156
+ }
157
+ };
158
+ };
159
+ var _default = exports.default = plugin;
@@ -0,0 +1,154 @@
1
+ import { last, defaultTo, groupBy } from 'ramda';
2
+ import { toValue, cloneDeep } from '@speclynx/apidom-core';
3
+ import NormalizeStorage from "./normalize-header-examples/NormalizeStorage.mjs";
4
+ const removeSpaces = operationId => {
5
+ return operationId.replace(/\s/g, '');
6
+ };
7
+ const replaceSpecialCharsWithUnderscore = operationId => {
8
+ return operationId.replace(/\W/gi, '_');
9
+ };
10
+ const createNormalizedOperationId = (path, method) => {
11
+ const normalizedMethod = replaceSpecialCharsWithUnderscore(removeSpaces(method.toLowerCase()));
12
+ const normalizedPath = replaceSpecialCharsWithUnderscore(removeSpaces(path));
13
+ return `${normalizedMethod}${normalizedPath}`;
14
+ };
15
+ const normalizeOperationId = (operationId, path, method) => {
16
+ const withoutSpaces = removeSpaces(operationId);
17
+ if (withoutSpaces.length > 0) {
18
+ return replaceSpecialCharsWithUnderscore(withoutSpaces);
19
+ }
20
+ return createNormalizedOperationId(path, method);
21
+ };
22
+
23
+ /**
24
+ * Normalization of Operation.operationId field.
25
+ *
26
+ * This normalization is not guided by OpenAPI 3.1 specification.
27
+ *
28
+ * Existing Operation.operationId fields are normalized into snake case form.
29
+ *
30
+ * Operation Objects, that do not define operationId field, are left untouched.
31
+ *
32
+ * Original operationId is stored in meta and as new `__originalOperationId` field.
33
+ *
34
+ * This plugin also guarantees the uniqueness of all defined Operation.operationId fields,
35
+ * and make sure Link.operationId fields are pointing to correct and normalized Operation.operationId fields.
36
+ *
37
+ * NOTE: this plugin is idempotent
38
+ * @public
39
+ */
40
+
41
+ /**
42
+ * @public
43
+ */
44
+ const plugin = ({
45
+ storageField = 'x-normalized',
46
+ operationIdNormalizer = normalizeOperationId
47
+ } = {}) => toolbox => {
48
+ const {
49
+ predicates,
50
+ ancestorLineageToJSONPointer,
51
+ namespace
52
+ } = toolbox;
53
+ const pathTemplates = [];
54
+ const normalizedOperations = [];
55
+ const links = [];
56
+ let storage;
57
+ return {
58
+ visitor: {
59
+ OpenApi3_1Element: {
60
+ enter(element) {
61
+ storage = new NormalizeStorage(element, storageField, 'operation-ids');
62
+ },
63
+ leave() {
64
+ // group normalized operations by normalized operationId
65
+ const normalizedOperationGroups = groupBy(operationElement => {
66
+ return toValue(operationElement.operationId);
67
+ }, normalizedOperations);
68
+
69
+ // append incremental numerical suffixes to identical operationIds
70
+ Object.entries(normalizedOperationGroups).forEach(([normalizedOperationId, operationElements]) => {
71
+ if (!Array.isArray(operationElements)) return;
72
+ if (operationElements.length <= 1) return;
73
+ operationElements.forEach((operationElement, index) => {
74
+ const indexedNormalizedOperationId = `${normalizedOperationId}${index + 1}`;
75
+ // @ts-ignore
76
+ operationElement.operationId = new namespace.elements.String(indexedNormalizedOperationId);
77
+ });
78
+ });
79
+
80
+ // rectify possibly broken Link.operationId fields
81
+ links.forEach(linkElement => {
82
+ if (typeof linkElement.operationId === 'undefined') return;
83
+ const linkOperationId = String(toValue(linkElement.operationId));
84
+ const operationElement = normalizedOperations.find(normalizedOperationElement => {
85
+ const originalOperationId = toValue(normalizedOperationElement.meta.get('originalOperationId'));
86
+ return originalOperationId === linkOperationId;
87
+ });
88
+
89
+ // Link Object doesn't need to be rectified
90
+ if (typeof operationElement === 'undefined') return;
91
+ linkElement.operationId = cloneDeep.safe(operationElement.operationId);
92
+ linkElement.meta.set('originalOperationId', linkOperationId);
93
+ linkElement.set('__originalOperationId', linkOperationId);
94
+ });
95
+
96
+ // cleanup the references
97
+ normalizedOperations.length = 0;
98
+ links.length = 0;
99
+ storage = undefined;
100
+ }
101
+ },
102
+ PathItemElement: {
103
+ enter(pathItemElement) {
104
+ // `path` meta may not be always available, e.g. in Callback Object or Components Object
105
+ const pathTemplate = defaultTo('path', toValue(pathItemElement.meta.get('path')));
106
+ pathTemplates.push(pathTemplate);
107
+ },
108
+ leave() {
109
+ pathTemplates.pop();
110
+ }
111
+ },
112
+ OperationElement: {
113
+ enter(operationElement, key, parent, path, ancestors) {
114
+ // operationId field is undefined, needs no normalization
115
+ if (typeof operationElement.operationId === 'undefined') return;
116
+ const operationJSONPointer = ancestorLineageToJSONPointer([...ancestors, parent, operationElement]);
117
+
118
+ // skip visiting this Operation Object if it's already normalized
119
+ if (storage.includes(operationJSONPointer)) {
120
+ return;
121
+ }
122
+
123
+ // cast operationId to string type
124
+ const originalOperationId = String(toValue(operationElement.operationId));
125
+ // perform operationId normalization
126
+ const pathTemplate = last(pathTemplates);
127
+ // `http-method` meta may not be always available, e.g. in Callback Object or Components Object
128
+ const method = defaultTo('method', toValue(operationElement.meta.get('http-method')));
129
+ const normalizedOperationId = operationIdNormalizer(originalOperationId, pathTemplate, method);
130
+
131
+ // normalization is not necessary
132
+ if (originalOperationId === normalizedOperationId) return;
133
+
134
+ // @ts-ignore
135
+ operationElement.operationId = new namespace.elements.String(normalizedOperationId);
136
+ operationElement.set('__originalOperationId', originalOperationId);
137
+ operationElement.meta.set('originalOperationId', originalOperationId);
138
+ normalizedOperations.push(operationElement);
139
+ storage.append(operationJSONPointer);
140
+ }
141
+ },
142
+ LinkElement: {
143
+ leave(linkElement) {
144
+ // make sure this Link elements doesn't come from base namespace
145
+ if (!predicates.isLinkElement(linkElement)) return;
146
+ // ignore Link Objects with undefined operationId
147
+ if (typeof linkElement.operationId === 'undefined') return;
148
+ links.push(linkElement);
149
+ }
150
+ }
151
+ }
152
+ };
153
+ };
154
+ export default plugin;
@@ -0,0 +1,105 @@
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 _apidomCore = require("@speclynx/apidom-core");
7
+ var _NormalizeStorage = _interopRequireDefault(require("./normalize-header-examples/NormalizeStorage.cjs"));
8
+ /**
9
+ * Override of Schema.example and Schema.examples field inside the Parameter Objects.
10
+ *
11
+ * Parameter Object has two fixed fields:
12
+ * - `example` of type `Any`
13
+ * - `examples` of type `Map[string, Example Object | Reference Object]`
14
+ *
15
+ * OpenAPI 3.1 specification excerpt that defines the override behavior:
16
+ *
17
+ * The example value SHALL override the example provided by the schema.
18
+ * Furthermore, if referencing a schema that contains an example, the examples value SHALL override the example provided by the schema.
19
+ *
20
+ * NOTE: this plugin is idempotent
21
+ * @public
22
+ */
23
+
24
+ /**
25
+ * @public
26
+ */
27
+ const plugin = ({
28
+ storageField = 'x-normalized'
29
+ } = {}) => toolbox => {
30
+ const {
31
+ predicates,
32
+ ancestorLineageToJSONPointer
33
+ } = toolbox;
34
+ let storage;
35
+ return {
36
+ visitor: {
37
+ OpenApi3_1Element: {
38
+ enter(element) {
39
+ storage = new _NormalizeStorage.default(element, storageField, 'parameter-examples');
40
+ },
41
+ leave() {
42
+ storage = undefined;
43
+ }
44
+ },
45
+ ParameterElement: {
46
+ leave(parameterElement, key, parent, path, ancestors) {
47
+ // skip visiting this Parameter Object
48
+ if (ancestors.some(predicates.isComponentsElement)) {
49
+ return;
50
+ }
51
+
52
+ // no Parameter.schema field present
53
+ if (typeof parameterElement.schema === 'undefined' || !predicates.isSchemaElement(parameterElement.schema)) {
54
+ return;
55
+ }
56
+ // Schema contains no example
57
+ if (typeof parameterElement.schema?.example === 'undefined' && typeof parameterElement.schema?.examples === 'undefined') {
58
+ return;
59
+ }
60
+ const parameterJSONPointer = ancestorLineageToJSONPointer([...ancestors, parent, parameterElement]);
61
+
62
+ // skip visiting this Parameter Object if it's already normalized
63
+ if (storage.includes(parameterJSONPointer)) {
64
+ return;
65
+ }
66
+
67
+ /**
68
+ * Parameter.examples and Schema.examples have preferences over the older
69
+ * and deprected `example` field.
70
+ */
71
+ if (typeof parameterElement.examples !== 'undefined' && predicates.isObjectElement(parameterElement.examples)) {
72
+ // @ts-ignore
73
+ const examples = parameterElement.examples.map(example => {
74
+ return _apidomCore.cloneDeep.safe(example.value);
75
+ });
76
+ if (typeof parameterElement.schema.examples !== 'undefined') {
77
+ parameterElement.schema.set('examples', examples);
78
+ storage.append(parameterJSONPointer);
79
+ }
80
+ if (typeof parameterElement.schema.example !== 'undefined') {
81
+ parameterElement.schema.set('example', examples[0]);
82
+ storage.append(parameterJSONPointer);
83
+ }
84
+ return;
85
+ }
86
+
87
+ /**
88
+ * Handle deprecated `example` field.
89
+ */
90
+ if (typeof parameterElement.example !== 'undefined') {
91
+ if (typeof parameterElement.schema.examples !== 'undefined') {
92
+ parameterElement.schema.set('examples', [(0, _apidomCore.cloneDeep)(parameterElement.example)]);
93
+ storage.append(parameterJSONPointer);
94
+ }
95
+ if (typeof parameterElement.schema.example !== 'undefined') {
96
+ parameterElement.schema.set('example', (0, _apidomCore.cloneDeep)(parameterElement.example));
97
+ storage.append(parameterJSONPointer);
98
+ }
99
+ }
100
+ }
101
+ }
102
+ }
103
+ };
104
+ };
105
+ var _default = exports.default = plugin;
@@ -0,0 +1,99 @@
1
+ import { cloneDeep } from '@speclynx/apidom-core';
2
+ import NormalizeStorage from "./normalize-header-examples/NormalizeStorage.mjs";
3
+ /**
4
+ * Override of Schema.example and Schema.examples field inside the Parameter Objects.
5
+ *
6
+ * Parameter Object has two fixed fields:
7
+ * - `example` of type `Any`
8
+ * - `examples` of type `Map[string, Example Object | Reference Object]`
9
+ *
10
+ * OpenAPI 3.1 specification excerpt that defines the override behavior:
11
+ *
12
+ * The example value SHALL override the example provided by the schema.
13
+ * Furthermore, if referencing a schema that contains an example, the examples value SHALL override the example provided by the schema.
14
+ *
15
+ * NOTE: this plugin is idempotent
16
+ * @public
17
+ */
18
+ /**
19
+ * @public
20
+ */
21
+ const plugin = ({
22
+ storageField = 'x-normalized'
23
+ } = {}) => toolbox => {
24
+ const {
25
+ predicates,
26
+ ancestorLineageToJSONPointer
27
+ } = toolbox;
28
+ let storage;
29
+ return {
30
+ visitor: {
31
+ OpenApi3_1Element: {
32
+ enter(element) {
33
+ storage = new NormalizeStorage(element, storageField, 'parameter-examples');
34
+ },
35
+ leave() {
36
+ storage = undefined;
37
+ }
38
+ },
39
+ ParameterElement: {
40
+ leave(parameterElement, key, parent, path, ancestors) {
41
+ // skip visiting this Parameter Object
42
+ if (ancestors.some(predicates.isComponentsElement)) {
43
+ return;
44
+ }
45
+
46
+ // no Parameter.schema field present
47
+ if (typeof parameterElement.schema === 'undefined' || !predicates.isSchemaElement(parameterElement.schema)) {
48
+ return;
49
+ }
50
+ // Schema contains no example
51
+ if (typeof parameterElement.schema?.example === 'undefined' && typeof parameterElement.schema?.examples === 'undefined') {
52
+ return;
53
+ }
54
+ const parameterJSONPointer = ancestorLineageToJSONPointer([...ancestors, parent, parameterElement]);
55
+
56
+ // skip visiting this Parameter Object if it's already normalized
57
+ if (storage.includes(parameterJSONPointer)) {
58
+ return;
59
+ }
60
+
61
+ /**
62
+ * Parameter.examples and Schema.examples have preferences over the older
63
+ * and deprected `example` field.
64
+ */
65
+ if (typeof parameterElement.examples !== 'undefined' && predicates.isObjectElement(parameterElement.examples)) {
66
+ // @ts-ignore
67
+ const examples = parameterElement.examples.map(example => {
68
+ return cloneDeep.safe(example.value);
69
+ });
70
+ if (typeof parameterElement.schema.examples !== 'undefined') {
71
+ parameterElement.schema.set('examples', examples);
72
+ storage.append(parameterJSONPointer);
73
+ }
74
+ if (typeof parameterElement.schema.example !== 'undefined') {
75
+ parameterElement.schema.set('example', examples[0]);
76
+ storage.append(parameterJSONPointer);
77
+ }
78
+ return;
79
+ }
80
+
81
+ /**
82
+ * Handle deprecated `example` field.
83
+ */
84
+ if (typeof parameterElement.example !== 'undefined') {
85
+ if (typeof parameterElement.schema.examples !== 'undefined') {
86
+ parameterElement.schema.set('examples', [cloneDeep(parameterElement.example)]);
87
+ storage.append(parameterJSONPointer);
88
+ }
89
+ if (typeof parameterElement.schema.example !== 'undefined') {
90
+ parameterElement.schema.set('example', cloneDeep(parameterElement.example));
91
+ storage.append(parameterJSONPointer);
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ };
98
+ };
99
+ export default plugin;