functions/param-names-unique.js (44 lines of code) (raw):
// Check that the parameters of an operation -- including those specified on the path -- are
// are case-insensitive unique regardless of "in".
// Return the "canonical" casing for a string.
// Currently just lowercase but should be extended to convert kebab/camel/snake/Pascal.
function canonical(name) {
return typeof (name) === 'string' ? name.toLowerCase() : name;
}
// Accept an array and return a list of unique duplicate entries in canonical form.
// This function is intended to work on strings but is resilient to non-strings.
function dupIgnoreCase(arr) {
if (!Array.isArray(arr)) {
return [];
}
const isDup = (value, index, self) => self.indexOf(value) !== index;
return [...new Set(arr.map((v) => canonical(v)).filter(isDup))];
}
// targetVal should be a [path item object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#pathItemObject).
// The code assumes it is running on a resolved doc
module.exports = (pathItem, _opts, paths) => {
if (pathItem === null || typeof pathItem !== 'object') {
return [];
}
const path = paths.path || paths.target || [];
const errors = [];
const pathParams = pathItem.parameters ? pathItem.parameters.map((p) => p.name) : [];
// Check path params for dups
const pathDups = dupIgnoreCase(pathParams);
// Report all dups
pathDups.forEach((dup) => {
// get the index of all names that match dup
const dupKeys = [...pathParams.keys()].filter((k) => canonical(pathParams[k]) === dup);
// Report errors for all the others
dupKeys.slice(1).forEach((key) => {
errors.push({
message: `Duplicate parameter name (ignoring case): ${dup}.`,
path: [...path, 'parameters', key, 'name'],
});
});
});
['get', 'post', 'put', 'patch', 'delete', 'options', 'head'].forEach((method) => {
// If this method exists and it has parameters, check them
if (pathItem[method] && Array.isArray(pathItem[method].parameters)) {
const allParams = [...pathParams, ...pathItem[method].parameters.map((p) => p.name)];
// Check method params for dups -- including path params
const dups = dupIgnoreCase(allParams);
// Report all dups
dups.forEach((dup) => {
// get the index of all names that match dup
const dupKeys = [...allParams.keys()].filter((k) => canonical(allParams[k]) === dup);
// Report errors for any others that are method parameters
dupKeys.slice(1).filter((k) => k >= pathParams.length).forEach((key) => {
errors.push({
message: `Duplicate parameter name (ignoring case): ${dup}.`,
path: [...path, method, 'parameters', key - pathParams.length, 'name'],
});
});
});
}
});
return errors;
};