swagger-client
Version:
SwaggerJS - a collection of interfaces for OAI specs
84 lines (76 loc) • 3.14 kB
JavaScript
import { isFreelyNamed, generateAbsoluteRefPatches } from '../helpers.js';
export default {
key: 'allOf',
plugin: (val, key, fullPath, specmap, patch) => {
// Ignore replace patches created by $ref because the changes will
// occur in the original "add" patch and we don't want this plugin
// to redundantly processes those "relace" patches.
if (patch.meta && patch.meta.$$ref) {
return undefined;
}
const parent = fullPath.slice(0, -1);
if (isFreelyNamed(parent)) {
return undefined;
}
if (!Array.isArray(val)) {
const err = new TypeError('allOf must be an array');
err.fullPath = fullPath; // This is an array
return err;
}
let alreadyAddError = false;
// Find the original definition from the `patch.value` object
// Remove the `allOf` property so it doesn't get added to the result of the `allOf` plugin
let originalDefinitionObj = patch.value;
parent.forEach(part => {
if (!originalDefinitionObj) return; // bail out if we've lost sight of our target
originalDefinitionObj = originalDefinitionObj[part];
});
originalDefinitionObj = {
...originalDefinitionObj
};
// when we've lost sight, interrupt prematurely
if (Object.keys(originalDefinitionObj).length === 0) {
return undefined;
}
delete originalDefinitionObj.allOf;
const patches = [];
// remove existing content
patches.push(specmap.replace(parent, {}));
val.forEach((toMerge, i) => {
if (!specmap.isObject(toMerge)) {
if (alreadyAddError) {
return null;
}
alreadyAddError = true;
const err = new TypeError('Elements in allOf must be objects');
err.fullPath = fullPath; // This is an array
return patches.push(err);
}
// Deeply merge the member's contents onto the parent location
patches.push(specmap.mergeDeep(parent, toMerge));
// Generate patches that migrate $ref values based on ContextTree information
// remove ["allOf"], which will not be present when these patches are applied
const collapsedFullPath = fullPath.slice(0, -1);
const absoluteRefPatches = generateAbsoluteRefPatches(toMerge, collapsedFullPath, {
getBaseUrlForNodePath: nodePath => specmap.getContext([...fullPath, i, ...nodePath]).baseDoc,
specmap
});
patches.push(...absoluteRefPatches);
return undefined;
});
// If there was an example in the original definition,
// keep it instead of merging with examples from other schema
if (originalDefinitionObj.example) {
// Delete other schema examples
patches.push(specmap.remove([].concat(parent, 'example')));
}
// Merge back the values from the original definition
patches.push(specmap.mergeDeep(parent, originalDefinitionObj));
// If there was not an original $$ref value, make sure to remove
// any $$ref value that may exist from the result of `allOf` merges
if (!originalDefinitionObj.$$ref) {
patches.push(specmap.remove([].concat(parent, '$$ref')));
}
return patches;
}
};