@speclynx/apidom-ns-openapi-3-1 4.0.2 → 4.0.4

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