source: node_modules/@swagger-api/apidom-ns-openapi-3-1/es/refractor/plugins/normalize-operation-ids.mjs

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 16 months ago

Initial commit

  • Property mode set to 100644
File size: 5.4 KB
Line 
1import { last, defaultTo, groupBy } from 'ramda';
2import { toValue, cloneDeep } from '@swagger-api/apidom-core';
3const removeSpaces = operationId => {
4 return operationId.replace(/\s/g, '');
5};
6const replaceSpecialCharsWithUnderscore = operationId => {
7 return operationId.replace(/\W/gi, '_');
8};
9const createNormalizedOperationId = (path, method) => {
10 const normalizedMethod = replaceSpecialCharsWithUnderscore(removeSpaces(method.toLowerCase()));
11 const normalizedPath = replaceSpecialCharsWithUnderscore(removeSpaces(path));
12 return `${normalizedMethod}${normalizedPath}`;
13};
14const normalizeOperationId = (operationId, path, method) => {
15 const withoutSpaces = removeSpaces(operationId);
16 if (withoutSpaces.length > 0) {
17 return replaceSpecialCharsWithUnderscore(withoutSpaces);
18 }
19 return createNormalizedOperationId(path, method);
20};
21
22/**
23 * Normalization of Operation.operationId field.
24 *
25 * This normalization is not guided by OpenAPI 3.1 specification.
26 *
27 * Existing Operation.operationId fields are normalized into snake case form.
28 *
29 * Operation Objects, that do not define operationId field, are left untouched.
30 *
31 * Original operationId is stored in meta and as new `__originalOperationId` field.
32 *
33 * This plugin also guarantees the uniqueness of all defined Operation.operationId fields,
34 * and make sure Link.operationId fields are pointing to correct and normalized Operation.operationId fields.
35 *
36 */
37/* eslint-disable no-param-reassign */
38
39const plugin = ({
40 operationIdNormalizer = normalizeOperationId
41} = {}) => ({
42 predicates,
43 namespace
44}) => {
45 const paths = [];
46 const normalizedOperations = [];
47 const links = [];
48 return {
49 visitor: {
50 OpenApi3_1Element: {
51 leave() {
52 // group normalized operations by normalized operationId
53 const normalizedOperationGroups = groupBy(operationElement => {
54 return toValue(operationElement.operationId);
55 }, normalizedOperations);
56
57 // append incremental numerical suffixes to identical operationIds
58 Object.entries(normalizedOperationGroups).forEach(([normalizedOperationId, operationElements]) => {
59 if (!Array.isArray(operationElements)) return;
60 if (operationElements.length <= 1) return;
61 operationElements.forEach((operationElement, index) => {
62 const indexedNormalizedOperationId = `${normalizedOperationId}${index + 1}`;
63 // @ts-ignore
64 operationElement.operationId = new namespace.elements.String(indexedNormalizedOperationId);
65 });
66 });
67
68 // rectify possibly broken Link.operationId fields
69 links.forEach(linkElement => {
70 if (typeof linkElement.operationId === 'undefined') return;
71 const linkOperationId = String(toValue(linkElement.operationId));
72 const operationElement = normalizedOperations.find(normalizedOperationElement => {
73 const originalOperationId = toValue(normalizedOperationElement.meta.get('originalOperationId'));
74 return originalOperationId === linkOperationId;
75 });
76
77 // Link Object doesn't need to be rectified
78 if (typeof operationElement === 'undefined') return;
79 linkElement.operationId = cloneDeep.safe(operationElement.operationId);
80 linkElement.meta.set('originalOperationId', linkOperationId);
81 linkElement.set('__originalOperationId', linkOperationId);
82 });
83
84 // cleanup the references
85 normalizedOperations.length = 0;
86 links.length = 0;
87 }
88 },
89 PathItemElement: {
90 enter(pathItemElement) {
91 // `path` meta may not be always available, e.g. in Callback Object or Components Object
92 const path = defaultTo('path', toValue(pathItemElement.meta.get('path')));
93 paths.push(path);
94 },
95 leave() {
96 paths.pop();
97 }
98 },
99 OperationElement: {
100 enter(operationElement) {
101 // operationId field is undefined, needs no normalization
102 if (typeof operationElement.operationId === 'undefined') return;
103
104 // cast operationId to string type
105 const originalOperationId = String(toValue(operationElement.operationId));
106 // perform operationId normalization
107 const path = last(paths);
108 // `http-method` meta may not be always available, e.g. in Callback Object or Components Object
109 const method = defaultTo('method', toValue(operationElement.meta.get('http-method')));
110 const normalizedOperationId = operationIdNormalizer(originalOperationId, path, method);
111
112 // normalization is not necessary
113 if (originalOperationId === normalizedOperationId) return;
114
115 // @ts-ignore
116 operationElement.operationId = new namespace.elements.String(normalizedOperationId);
117 operationElement.set('__originalOperationId', originalOperationId);
118 operationElement.meta.set('originalOperationId', originalOperationId);
119 normalizedOperations.push(operationElement);
120 }
121 },
122 LinkElement: {
123 leave(linkElement) {
124 // make sure this Link elements doesn't come from base namespace
125 if (!predicates.isLinkElement(linkElement)) return;
126 // ignore Link Objects with undefined operationId
127 if (typeof linkElement.operationId === 'undefined') return;
128 links.push(linkElement);
129 }
130 }
131 }
132 };
133};
134/* eslint-enable */
135
136export default plugin;
Note: See TracBrowser for help on using the repository browser.