-
Notifications
You must be signed in to change notification settings - Fork 762
/
all-of.js
91 lines (70 loc) · 2.84 KB
/
all-of.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import isEmpty from 'lodash/isEmpty';
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 (isEmpty(originalDefinitionObj)) {
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;
});
// 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;
},
};