@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.
- package/CHANGELOG.md +87 -0
- package/LICENSE +202 -0
- package/LICENSES/AFL-3.0.txt +182 -0
- package/LICENSES/Apache-2.0.txt +202 -0
- package/LICENSES/BSD-3-Clause.txt +26 -0
- package/LICENSES/MIT.txt +9 -0
- package/NOTICE +65 -0
- package/README.md +472 -0
- package/dist/apidom-ns-openapi-3-1.browser.js +36144 -0
- package/dist/apidom-ns-openapi-3-1.browser.min.js +1 -0
- package/package.json +70 -0
- package/src/elements/Callback.cjs +10 -0
- package/src/elements/Callback.mjs +7 -0
- package/src/elements/Components.cjs +17 -0
- package/src/elements/Components.mjs +14 -0
- package/src/elements/Contact.cjs +10 -0
- package/src/elements/Contact.mjs +7 -0
- package/src/elements/Discriminator.cjs +10 -0
- package/src/elements/Discriminator.mjs +7 -0
- package/src/elements/Encoding.cjs +10 -0
- package/src/elements/Encoding.mjs +7 -0
- package/src/elements/Example.cjs +10 -0
- package/src/elements/Example.mjs +7 -0
- package/src/elements/ExternalDocumentation.cjs +10 -0
- package/src/elements/ExternalDocumentation.mjs +7 -0
- package/src/elements/Header.cjs +17 -0
- package/src/elements/Header.mjs +13 -0
- package/src/elements/Info.cjs +23 -0
- package/src/elements/Info.mjs +19 -0
- package/src/elements/JsonSchemaDialect.cjs +16 -0
- package/src/elements/JsonSchemaDialect.mjs +13 -0
- package/src/elements/License.cjs +17 -0
- package/src/elements/License.mjs +14 -0
- package/src/elements/Link.cjs +10 -0
- package/src/elements/Link.mjs +7 -0
- package/src/elements/MediaType.cjs +17 -0
- package/src/elements/MediaType.mjs +13 -0
- package/src/elements/OAuthFlow.cjs +10 -0
- package/src/elements/OAuthFlow.mjs +7 -0
- package/src/elements/OAuthFlows.cjs +10 -0
- package/src/elements/OAuthFlows.mjs +7 -0
- package/src/elements/OpenApi3-1.cjs +77 -0
- package/src/elements/OpenApi3-1.mjs +73 -0
- package/src/elements/Openapi.cjs +10 -0
- package/src/elements/Openapi.mjs +7 -0
- package/src/elements/Operation.cjs +17 -0
- package/src/elements/Operation.mjs +13 -0
- package/src/elements/Parameter.cjs +17 -0
- package/src/elements/Parameter.mjs +13 -0
- package/src/elements/PathItem.cjs +59 -0
- package/src/elements/PathItem.mjs +55 -0
- package/src/elements/Paths.cjs +10 -0
- package/src/elements/Paths.mjs +7 -0
- package/src/elements/Reference.cjs +28 -0
- package/src/elements/Reference.mjs +25 -0
- package/src/elements/RequestBody.cjs +10 -0
- package/src/elements/RequestBody.mjs +7 -0
- package/src/elements/Response.cjs +10 -0
- package/src/elements/Response.mjs +7 -0
- package/src/elements/Responses.cjs +10 -0
- package/src/elements/Responses.mjs +7 -0
- package/src/elements/Schema.cjs +50 -0
- package/src/elements/Schema.mjs +46 -0
- package/src/elements/SecurityRequirement.cjs +10 -0
- package/src/elements/SecurityRequirement.mjs +7 -0
- package/src/elements/SecurityScheme.cjs +10 -0
- package/src/elements/SecurityScheme.mjs +7 -0
- package/src/elements/Server.cjs +10 -0
- package/src/elements/Server.mjs +7 -0
- package/src/elements/ServerVariable.cjs +10 -0
- package/src/elements/ServerVariable.mjs +7 -0
- package/src/elements/Tag.cjs +10 -0
- package/src/elements/Tag.mjs +7 -0
- package/src/elements/Xml.cjs +10 -0
- package/src/elements/Xml.mjs +7 -0
- package/src/elements/nces/ComponentsPathItems.cjs +16 -0
- package/src/elements/nces/ComponentsPathItems.mjs +13 -0
- package/src/elements/nces/Webhooks.cjs +16 -0
- package/src/elements/nces/Webhooks.mjs +13 -0
- package/src/index.cjs +158 -0
- package/src/index.mjs +28 -0
- package/src/media-types.cjs +34 -0
- package/src/media-types.mjs +30 -0
- package/src/namespace.cjs +82 -0
- package/src/namespace.mjs +76 -0
- package/src/predicates.cjs +365 -0
- package/src/predicates.mjs +357 -0
- package/src/refractor/index.cjs +45 -0
- package/src/refractor/index.mjs +39 -0
- package/src/refractor/plugins/normalize-header-examples/NormalizeStorage.cjs +38 -0
- package/src/refractor/plugins/normalize-header-examples/NormalizeStorage.mjs +34 -0
- package/src/refractor/plugins/normalize-header-examples/index.cjs +105 -0
- package/src/refractor/plugins/normalize-header-examples/index.mjs +99 -0
- package/src/refractor/plugins/normalize-operation-ids.cjs +159 -0
- package/src/refractor/plugins/normalize-operation-ids.mjs +154 -0
- package/src/refractor/plugins/normalize-parameter-examples.cjs +105 -0
- package/src/refractor/plugins/normalize-parameter-examples.mjs +99 -0
- package/src/refractor/plugins/normalize-parameters.cjs +103 -0
- package/src/refractor/plugins/normalize-parameters.mjs +97 -0
- package/src/refractor/plugins/normalize-security-requirements.cjs +71 -0
- package/src/refractor/plugins/normalize-security-requirements.mjs +65 -0
- package/src/refractor/plugins/normalize-servers.cjs +118 -0
- package/src/refractor/plugins/normalize-servers.mjs +112 -0
- package/src/refractor/plugins/replace-empty-element.cjs +665 -0
- package/src/refractor/plugins/replace-empty-element.mjs +658 -0
- package/src/refractor/registration.cjs +102 -0
- package/src/refractor/registration.mjs +66 -0
- package/src/refractor/specification.cjs +492 -0
- package/src/refractor/specification.mjs +487 -0
- package/src/refractor/toolbox.cjs +70 -0
- package/src/refractor/toolbox.mjs +60 -0
- package/src/refractor/visitors/open-api-3-1/JsonSchemaDialectVisitor.cjs +25 -0
- package/src/refractor/visitors/open-api-3-1/JsonSchemaDialectVisitor.mjs +19 -0
- package/src/refractor/visitors/open-api-3-1/WebhooksVisitor.cjs +44 -0
- package/src/refractor/visitors/open-api-3-1/WebhooksVisitor.mjs +38 -0
- package/src/refractor/visitors/open-api-3-1/callback/index.cjs +37 -0
- package/src/refractor/visitors/open-api-3-1/callback/index.mjs +32 -0
- package/src/refractor/visitors/open-api-3-1/components/PathItemsVisitor.cjs +34 -0
- package/src/refractor/visitors/open-api-3-1/components/PathItemsVisitor.mjs +28 -0
- package/src/refractor/visitors/open-api-3-1/components/SchemasVisitor.cjs +22 -0
- package/src/refractor/visitors/open-api-3-1/components/SchemasVisitor.mjs +19 -0
- package/src/refractor/visitors/open-api-3-1/components/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/components/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/contact/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/contact/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/distriminator/index.cjs +22 -0
- package/src/refractor/visitors/open-api-3-1/distriminator/index.mjs +17 -0
- package/src/refractor/visitors/open-api-3-1/encoding/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/encoding/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/example/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/example/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/external-documentation/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/external-documentation/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/header/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/header/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/index.cjs +31 -0
- package/src/refractor/visitors/open-api-3-1/index.mjs +25 -0
- package/src/refractor/visitors/open-api-3-1/info/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/info/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/license/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/license/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/link/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/link/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/media-type/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/media-type/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/oauth-flow/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/oauth-flow/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/oauth-flows/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/oauth-flows/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/operation/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/operation/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/parameter/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/parameter/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/path-item/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/path-item/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/paths/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/paths/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/reference/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/reference/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/request-body/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/request-body/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/response/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/response/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/responses/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/responses/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/schema/$defsVisitor.cjs +19 -0
- package/src/refractor/visitors/open-api-3-1/schema/$defsVisitor.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/schema/AllOfVisitor.cjs +15 -0
- package/src/refractor/visitors/open-api-3-1/schema/AllOfVisitor.mjs +11 -0
- package/src/refractor/visitors/open-api-3-1/schema/AnyOfVisitor.cjs +15 -0
- package/src/refractor/visitors/open-api-3-1/schema/AnyOfVisitor.mjs +11 -0
- package/src/refractor/visitors/open-api-3-1/schema/DependentSchemasVisitor.cjs +15 -0
- package/src/refractor/visitors/open-api-3-1/schema/DependentSchemasVisitor.mjs +11 -0
- package/src/refractor/visitors/open-api-3-1/schema/OneOfVisitor.cjs +15 -0
- package/src/refractor/visitors/open-api-3-1/schema/OneOfVisitor.mjs +11 -0
- package/src/refractor/visitors/open-api-3-1/schema/PatternPropertiesVisitor.cjs +15 -0
- package/src/refractor/visitors/open-api-3-1/schema/PatternPropertiesVisitor.mjs +11 -0
- package/src/refractor/visitors/open-api-3-1/schema/PrefixItemsVisitor.cjs +15 -0
- package/src/refractor/visitors/open-api-3-1/schema/PrefixItemsVisitor.mjs +11 -0
- package/src/refractor/visitors/open-api-3-1/schema/PropertiesVisitor.cjs +15 -0
- package/src/refractor/visitors/open-api-3-1/schema/PropertiesVisitor.mjs +11 -0
- package/src/refractor/visitors/open-api-3-1/schema/index.cjs +75 -0
- package/src/refractor/visitors/open-api-3-1/schema/index.mjs +69 -0
- package/src/refractor/visitors/open-api-3-1/security-requirement/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/security-requirement/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/security-scheme/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/security-scheme/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/server/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/server/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/server-variable/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/server-variable/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/tag/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/tag/index.mjs +16 -0
- package/src/refractor/visitors/open-api-3-1/xml/index.cjs +21 -0
- package/src/refractor/visitors/open-api-3-1/xml/index.mjs +16 -0
- package/src/traversal/visitor.cjs +57 -0
- package/src/traversal/visitor.mjs +54 -0
- 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;
|