@speclynx/apidom-core 4.0.1 → 4.0.3
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 +10 -0
- package/package.json +6 -7
- package/src/fields/fixed-fields.cjs +47 -0
- package/src/fields/fixed-fields.mjs +43 -0
- package/src/fields/fixed-fields.ts +61 -0
- package/src/fields/index.cjs +8 -0
- package/src/fields/index.mjs +1 -0
- package/src/fields/index.ts +2 -0
- package/src/identity/errors/ElementIdentityError.cjs +22 -0
- package/src/identity/errors/ElementIdentityError.mjs +19 -0
- package/src/identity/errors/ElementIdentityError.ts +26 -0
- package/src/identity/index.cjs +64 -0
- package/src/identity/index.mjs +58 -0
- package/src/identity/index.ts +64 -0
- package/src/index.cjs +48 -0
- package/src/index.mjs +41 -0
- package/src/index.ts +81 -0
- package/src/media-types.cjs +21 -0
- package/src/media-types.mjs +18 -0
- package/src/media-types.ts +24 -0
- package/src/merge/deepmerge.cjs +165 -0
- package/src/merge/deepmerge.mjs +149 -0
- package/src/merge/deepmerge.ts +274 -0
- package/src/merge/merge-left.cjs +16 -0
- package/src/merge/merge-left.mjs +11 -0
- package/src/merge/merge-left.ts +14 -0
- package/src/merge/merge-right.cjs +35 -0
- package/src/merge/merge-right.mjs +29 -0
- package/src/merge/merge-right.ts +42 -0
- package/src/namespace.cjs +10 -0
- package/src/namespace.mjs +7 -0
- package/src/namespace.ts +8 -0
- package/src/refractor/plugins/dispatcher/index.cjs +64 -0
- package/src/refractor/plugins/dispatcher/index.mjs +54 -0
- package/src/refractor/plugins/dispatcher/index.ts +102 -0
- package/src/refractor/plugins/element-identity.cjs +31 -0
- package/src/refractor/plugins/element-identity.mjs +26 -0
- package/src/refractor/plugins/element-identity.ts +31 -0
- package/src/refractor/plugins/semantic-element-identity.cjs +33 -0
- package/src/refractor/plugins/semantic-element-identity.mjs +29 -0
- package/src/refractor/plugins/semantic-element-identity.ts +32 -0
- package/src/refractor/toolbox.cjs +47 -0
- package/src/refractor/toolbox.mjs +41 -0
- package/src/refractor/toolbox.ts +88 -0
- package/src/specification.cjs +63 -0
- package/src/specification.mjs +59 -0
- package/src/specification.ts +68 -0
- package/src/transcluder/Transcluder.cjs +111 -0
- package/src/transcluder/Transcluder.mjs +107 -0
- package/src/transcluder/Transcluder.ts +147 -0
- package/src/transcluder/index.cjs +19 -0
- package/src/transcluder/index.mjs +13 -0
- package/src/transcluder/index.ts +15 -0
- package/src/transformers/dehydrate.cjs +15 -0
- package/src/transformers/dehydrate.mjs +10 -0
- package/src/transformers/dehydrate.ts +14 -0
- package/src/transformers/from.cjs +34 -0
- package/src/transformers/from.mjs +29 -0
- package/src/transformers/from.ts +34 -0
- package/src/transformers/serializers/json.cjs +75 -0
- package/src/transformers/serializers/json.mjs +70 -0
- package/src/transformers/serializers/json.ts +107 -0
- package/src/transformers/serializers/value.cjs +50 -0
- package/src/transformers/serializers/value.mjs +47 -0
- package/src/transformers/serializers/value.ts +70 -0
- package/src/transformers/serializers/yaml-1-2.cjs +142 -0
- package/src/transformers/serializers/yaml-1-2.mjs +137 -0
- package/src/transformers/serializers/yaml-1-2.ts +205 -0
- package/src/transformers/sexprs.cjs +31 -0
- package/src/transformers/sexprs.mjs +28 -0
- package/src/transformers/sexprs.ts +30 -0
- package/src/transformers/to-string.cjs +16 -0
- package/src/transformers/to-string.mjs +11 -0
- package/src/transformers/to-string.ts +15 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NotImplementedError } from '@speclynx/apidom-error';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
class MediaTypes extends Array {
|
|
7
|
+
unknownMediaType = 'application/octet-stream';
|
|
8
|
+
filterByFormat() {
|
|
9
|
+
throw new NotImplementedError('filterByFormat method in MediaTypes class is not yet implemented.');
|
|
10
|
+
}
|
|
11
|
+
findBy() {
|
|
12
|
+
throw new NotImplementedError('findBy method in MediaTypes class is not yet implemented.');
|
|
13
|
+
}
|
|
14
|
+
latest() {
|
|
15
|
+
throw new NotImplementedError('latest method in MediaTypes class is not yet implemented.');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export default MediaTypes;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { NotImplementedError } from '@speclynx/apidom-error';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
class MediaTypes<T> extends Array<T> {
|
|
7
|
+
unknownMediaType = 'application/octet-stream';
|
|
8
|
+
|
|
9
|
+
filterByFormat() {
|
|
10
|
+
throw new NotImplementedError(
|
|
11
|
+
'filterByFormat method in MediaTypes class is not yet implemented.',
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
findBy() {
|
|
16
|
+
throw new NotImplementedError('findBy method in MediaTypes class is not yet implemented.');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
latest() {
|
|
20
|
+
throw new NotImplementedError('latest method in MediaTypes class is not yet implemented.');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default MediaTypes;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
|
|
4
|
+
exports.__esModule = true;
|
|
5
|
+
exports.emptyElement = exports.defaultOptions = exports.default = void 0;
|
|
6
|
+
var _apidomDatamodel = require("@speclynx/apidom-datamodel");
|
|
7
|
+
var _value = _interopRequireDefault(require("../transformers/serializers/value.cjs"));
|
|
8
|
+
/**
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @public
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @public
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
const emptyElement = element => {
|
|
49
|
+
const meta = !element.isMetaEmpty ? element.meta.cloneDeep() : undefined;
|
|
50
|
+
const attributes = !element.isAttributesEmpty ? (0, _apidomDatamodel.cloneDeep)(element.attributes) : undefined;
|
|
51
|
+
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
return new element.constructor(undefined, meta, attributes);
|
|
54
|
+
};
|
|
55
|
+
exports.emptyElement = emptyElement;
|
|
56
|
+
const cloneUnlessOtherwiseSpecified = (element, options) => options.clone && options.isMergeableElement(element) ? deepmerge(emptyElement(element), element, options) : element;
|
|
57
|
+
const getMergeFunction = (keyElement, options) => {
|
|
58
|
+
if (typeof options.customMerge !== 'function') {
|
|
59
|
+
return deepmerge;
|
|
60
|
+
}
|
|
61
|
+
const customMerge = options.customMerge(keyElement, options);
|
|
62
|
+
return typeof customMerge === 'function' ? customMerge : deepmerge;
|
|
63
|
+
};
|
|
64
|
+
const getMetaMergeFunction = options => {
|
|
65
|
+
if (typeof options.customMetaMerge !== 'function') {
|
|
66
|
+
return targetMeta => targetMeta.cloneDeep();
|
|
67
|
+
}
|
|
68
|
+
return options.customMetaMerge;
|
|
69
|
+
};
|
|
70
|
+
const getAttributesMergeFunction = options => {
|
|
71
|
+
if (typeof options.customAttributesMerge !== 'function') {
|
|
72
|
+
return targetAttributes => (0, _apidomDatamodel.cloneDeep)(targetAttributes);
|
|
73
|
+
}
|
|
74
|
+
return options.customAttributesMerge;
|
|
75
|
+
};
|
|
76
|
+
const mergeArrayElement = (targetElement, sourceElement, options) => {
|
|
77
|
+
const Ctor = targetElement.constructor;
|
|
78
|
+
const merged = targetElement.concat(sourceElement);
|
|
79
|
+
return new Ctor(merged.map(item => cloneUnlessOtherwiseSpecified(item, options)));
|
|
80
|
+
};
|
|
81
|
+
const mergeObjectElement = (targetElement, sourceElement, options) => {
|
|
82
|
+
const destination = (0, _apidomDatamodel.isObjectElement)(targetElement) ? emptyElement(targetElement) : emptyElement(sourceElement);
|
|
83
|
+
if ((0, _apidomDatamodel.isObjectElement)(targetElement)) {
|
|
84
|
+
targetElement.forEach((value, key, member) => {
|
|
85
|
+
const clonedMember = (0, _apidomDatamodel.cloneShallow)(member);
|
|
86
|
+
clonedMember.value = cloneUnlessOtherwiseSpecified(value, options);
|
|
87
|
+
destination.content.push(clonedMember);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
sourceElement.forEach((value, key, member) => {
|
|
91
|
+
const keyValue = (0, _value.default)(key);
|
|
92
|
+
let clonedMember;
|
|
93
|
+
if ((0, _apidomDatamodel.isObjectElement)(targetElement) && targetElement.hasKey(keyValue) && options.isMergeableElement(value)) {
|
|
94
|
+
const targetValue = targetElement.get(keyValue);
|
|
95
|
+
clonedMember = (0, _apidomDatamodel.cloneShallow)(member);
|
|
96
|
+
clonedMember.value = getMergeFunction(key, options)(targetValue, value, options);
|
|
97
|
+
} else {
|
|
98
|
+
clonedMember = (0, _apidomDatamodel.cloneShallow)(member);
|
|
99
|
+
clonedMember.value = cloneUnlessOtherwiseSpecified(value, options);
|
|
100
|
+
}
|
|
101
|
+
destination.remove(keyValue);
|
|
102
|
+
destination.content.push(clonedMember);
|
|
103
|
+
});
|
|
104
|
+
return destination;
|
|
105
|
+
};
|
|
106
|
+
const defaultOptions = exports.defaultOptions = {
|
|
107
|
+
clone: true,
|
|
108
|
+
isMergeableElement: element => (0, _apidomDatamodel.isObjectElement)(element) || (0, _apidomDatamodel.isArrayElement)(element),
|
|
109
|
+
arrayElementMerge: mergeArrayElement,
|
|
110
|
+
objectElementMerge: mergeObjectElement,
|
|
111
|
+
customMerge: undefined,
|
|
112
|
+
customMetaMerge: undefined,
|
|
113
|
+
customAttributesMerge: undefined
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @public
|
|
118
|
+
*/
|
|
119
|
+
const deepmerge = (targetElement, sourceElement, options) => {
|
|
120
|
+
const mergedOptions = {
|
|
121
|
+
...defaultOptions,
|
|
122
|
+
...options
|
|
123
|
+
};
|
|
124
|
+
mergedOptions.isMergeableElement = mergedOptions.isMergeableElement ?? defaultOptions.isMergeableElement;
|
|
125
|
+
mergedOptions.arrayElementMerge = mergedOptions.arrayElementMerge ?? defaultOptions.arrayElementMerge;
|
|
126
|
+
mergedOptions.objectElementMerge = mergedOptions.objectElementMerge ?? defaultOptions.objectElementMerge;
|
|
127
|
+
const sourceIsArrayElement = (0, _apidomDatamodel.isArrayElement)(sourceElement);
|
|
128
|
+
const targetIsArrayElement = (0, _apidomDatamodel.isArrayElement)(targetElement);
|
|
129
|
+
const sourceAndTargetTypesMatch = sourceIsArrayElement === targetIsArrayElement;
|
|
130
|
+
if (!sourceAndTargetTypesMatch) {
|
|
131
|
+
return cloneUnlessOtherwiseSpecified(sourceElement, mergedOptions);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// merging two elements
|
|
135
|
+
const mergedElement = sourceIsArrayElement && typeof mergedOptions.arrayElementMerge === 'function' ? mergedOptions.arrayElementMerge(targetElement, sourceElement, mergedOptions) : mergedOptions.objectElementMerge(targetElement, sourceElement, mergedOptions);
|
|
136
|
+
|
|
137
|
+
// merging meta & attributes
|
|
138
|
+
if (!targetElement.isMetaEmpty && !sourceElement.isMetaEmpty) {
|
|
139
|
+
mergedElement.meta = getMetaMergeFunction(mergedOptions)(targetElement.meta, sourceElement.meta);
|
|
140
|
+
} else if (!targetElement.isMetaEmpty) {
|
|
141
|
+
mergedElement.meta = targetElement.meta.cloneDeep();
|
|
142
|
+
} else if (!sourceElement.isMetaEmpty) {
|
|
143
|
+
mergedElement.meta = sourceElement.meta.cloneDeep();
|
|
144
|
+
}
|
|
145
|
+
if (!targetElement.isAttributesEmpty && !sourceElement.isAttributesEmpty) {
|
|
146
|
+
mergedElement.attributes = getAttributesMergeFunction(mergedOptions)(targetElement.attributes, sourceElement.attributes);
|
|
147
|
+
} else if (!targetElement.isAttributesEmpty) {
|
|
148
|
+
mergedElement.attributes = (0, _apidomDatamodel.cloneDeep)(targetElement.attributes);
|
|
149
|
+
} else if (!sourceElement.isAttributesEmpty) {
|
|
150
|
+
mergedElement.attributes = (0, _apidomDatamodel.cloneDeep)(sourceElement.attributes);
|
|
151
|
+
}
|
|
152
|
+
return mergedElement;
|
|
153
|
+
};
|
|
154
|
+
deepmerge.all = (list, options) => {
|
|
155
|
+
if (!Array.isArray(list)) {
|
|
156
|
+
throw new TypeError('First argument of deepmerge should be an array.');
|
|
157
|
+
}
|
|
158
|
+
if (list.length === 0) {
|
|
159
|
+
return new _apidomDatamodel.ObjectElement();
|
|
160
|
+
}
|
|
161
|
+
return list.reduce((target, source) => {
|
|
162
|
+
return deepmerge(target, source, options);
|
|
163
|
+
}, emptyElement(list[0]));
|
|
164
|
+
};
|
|
165
|
+
var _default = exports.default = deepmerge;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { ObjectElement, isObjectElement, isArrayElement, cloneDeep, cloneShallow } from '@speclynx/apidom-datamodel';
|
|
2
|
+
import toValue from "../transformers/serializers/value.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* @public
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export const emptyElement = element => {
|
|
34
|
+
const meta = !element.isMetaEmpty ? element.meta.cloneDeep() : undefined;
|
|
35
|
+
const attributes = !element.isAttributesEmpty ? cloneDeep(element.attributes) : undefined;
|
|
36
|
+
|
|
37
|
+
// @ts-ignore
|
|
38
|
+
return new element.constructor(undefined, meta, attributes);
|
|
39
|
+
};
|
|
40
|
+
const cloneUnlessOtherwiseSpecified = (element, options) => options.clone && options.isMergeableElement(element) ? deepmerge(emptyElement(element), element, options) : element;
|
|
41
|
+
const getMergeFunction = (keyElement, options) => {
|
|
42
|
+
if (typeof options.customMerge !== 'function') {
|
|
43
|
+
return deepmerge;
|
|
44
|
+
}
|
|
45
|
+
const customMerge = options.customMerge(keyElement, options);
|
|
46
|
+
return typeof customMerge === 'function' ? customMerge : deepmerge;
|
|
47
|
+
};
|
|
48
|
+
const getMetaMergeFunction = options => {
|
|
49
|
+
if (typeof options.customMetaMerge !== 'function') {
|
|
50
|
+
return targetMeta => targetMeta.cloneDeep();
|
|
51
|
+
}
|
|
52
|
+
return options.customMetaMerge;
|
|
53
|
+
};
|
|
54
|
+
const getAttributesMergeFunction = options => {
|
|
55
|
+
if (typeof options.customAttributesMerge !== 'function') {
|
|
56
|
+
return targetAttributes => cloneDeep(targetAttributes);
|
|
57
|
+
}
|
|
58
|
+
return options.customAttributesMerge;
|
|
59
|
+
};
|
|
60
|
+
const mergeArrayElement = (targetElement, sourceElement, options) => {
|
|
61
|
+
const Ctor = targetElement.constructor;
|
|
62
|
+
const merged = targetElement.concat(sourceElement);
|
|
63
|
+
return new Ctor(merged.map(item => cloneUnlessOtherwiseSpecified(item, options)));
|
|
64
|
+
};
|
|
65
|
+
const mergeObjectElement = (targetElement, sourceElement, options) => {
|
|
66
|
+
const destination = isObjectElement(targetElement) ? emptyElement(targetElement) : emptyElement(sourceElement);
|
|
67
|
+
if (isObjectElement(targetElement)) {
|
|
68
|
+
targetElement.forEach((value, key, member) => {
|
|
69
|
+
const clonedMember = cloneShallow(member);
|
|
70
|
+
clonedMember.value = cloneUnlessOtherwiseSpecified(value, options);
|
|
71
|
+
destination.content.push(clonedMember);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
sourceElement.forEach((value, key, member) => {
|
|
75
|
+
const keyValue = toValue(key);
|
|
76
|
+
let clonedMember;
|
|
77
|
+
if (isObjectElement(targetElement) && targetElement.hasKey(keyValue) && options.isMergeableElement(value)) {
|
|
78
|
+
const targetValue = targetElement.get(keyValue);
|
|
79
|
+
clonedMember = cloneShallow(member);
|
|
80
|
+
clonedMember.value = getMergeFunction(key, options)(targetValue, value, options);
|
|
81
|
+
} else {
|
|
82
|
+
clonedMember = cloneShallow(member);
|
|
83
|
+
clonedMember.value = cloneUnlessOtherwiseSpecified(value, options);
|
|
84
|
+
}
|
|
85
|
+
destination.remove(keyValue);
|
|
86
|
+
destination.content.push(clonedMember);
|
|
87
|
+
});
|
|
88
|
+
return destination;
|
|
89
|
+
};
|
|
90
|
+
export const defaultOptions = {
|
|
91
|
+
clone: true,
|
|
92
|
+
isMergeableElement: element => isObjectElement(element) || isArrayElement(element),
|
|
93
|
+
arrayElementMerge: mergeArrayElement,
|
|
94
|
+
objectElementMerge: mergeObjectElement,
|
|
95
|
+
customMerge: undefined,
|
|
96
|
+
customMetaMerge: undefined,
|
|
97
|
+
customAttributesMerge: undefined
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @public
|
|
102
|
+
*/
|
|
103
|
+
const deepmerge = (targetElement, sourceElement, options) => {
|
|
104
|
+
const mergedOptions = {
|
|
105
|
+
...defaultOptions,
|
|
106
|
+
...options
|
|
107
|
+
};
|
|
108
|
+
mergedOptions.isMergeableElement = mergedOptions.isMergeableElement ?? defaultOptions.isMergeableElement;
|
|
109
|
+
mergedOptions.arrayElementMerge = mergedOptions.arrayElementMerge ?? defaultOptions.arrayElementMerge;
|
|
110
|
+
mergedOptions.objectElementMerge = mergedOptions.objectElementMerge ?? defaultOptions.objectElementMerge;
|
|
111
|
+
const sourceIsArrayElement = isArrayElement(sourceElement);
|
|
112
|
+
const targetIsArrayElement = isArrayElement(targetElement);
|
|
113
|
+
const sourceAndTargetTypesMatch = sourceIsArrayElement === targetIsArrayElement;
|
|
114
|
+
if (!sourceAndTargetTypesMatch) {
|
|
115
|
+
return cloneUnlessOtherwiseSpecified(sourceElement, mergedOptions);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// merging two elements
|
|
119
|
+
const mergedElement = sourceIsArrayElement && typeof mergedOptions.arrayElementMerge === 'function' ? mergedOptions.arrayElementMerge(targetElement, sourceElement, mergedOptions) : mergedOptions.objectElementMerge(targetElement, sourceElement, mergedOptions);
|
|
120
|
+
|
|
121
|
+
// merging meta & attributes
|
|
122
|
+
if (!targetElement.isMetaEmpty && !sourceElement.isMetaEmpty) {
|
|
123
|
+
mergedElement.meta = getMetaMergeFunction(mergedOptions)(targetElement.meta, sourceElement.meta);
|
|
124
|
+
} else if (!targetElement.isMetaEmpty) {
|
|
125
|
+
mergedElement.meta = targetElement.meta.cloneDeep();
|
|
126
|
+
} else if (!sourceElement.isMetaEmpty) {
|
|
127
|
+
mergedElement.meta = sourceElement.meta.cloneDeep();
|
|
128
|
+
}
|
|
129
|
+
if (!targetElement.isAttributesEmpty && !sourceElement.isAttributesEmpty) {
|
|
130
|
+
mergedElement.attributes = getAttributesMergeFunction(mergedOptions)(targetElement.attributes, sourceElement.attributes);
|
|
131
|
+
} else if (!targetElement.isAttributesEmpty) {
|
|
132
|
+
mergedElement.attributes = cloneDeep(targetElement.attributes);
|
|
133
|
+
} else if (!sourceElement.isAttributesEmpty) {
|
|
134
|
+
mergedElement.attributes = cloneDeep(sourceElement.attributes);
|
|
135
|
+
}
|
|
136
|
+
return mergedElement;
|
|
137
|
+
};
|
|
138
|
+
deepmerge.all = (list, options) => {
|
|
139
|
+
if (!Array.isArray(list)) {
|
|
140
|
+
throw new TypeError('First argument of deepmerge should be an array.');
|
|
141
|
+
}
|
|
142
|
+
if (list.length === 0) {
|
|
143
|
+
return new ObjectElement();
|
|
144
|
+
}
|
|
145
|
+
return list.reduce((target, source) => {
|
|
146
|
+
return deepmerge(target, source, options);
|
|
147
|
+
}, emptyElement(list[0]));
|
|
148
|
+
};
|
|
149
|
+
export default deepmerge;
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ObjectElement,
|
|
3
|
+
ArrayElement,
|
|
4
|
+
MemberElement,
|
|
5
|
+
Element,
|
|
6
|
+
Metadata,
|
|
7
|
+
isObjectElement,
|
|
8
|
+
isArrayElement,
|
|
9
|
+
cloneDeep,
|
|
10
|
+
cloneShallow,
|
|
11
|
+
} from '@speclynx/apidom-datamodel';
|
|
12
|
+
|
|
13
|
+
import toValue from '../transformers/serializers/value.ts';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export type ObjectOrArrayElement = ObjectElement | ArrayElement;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export type AnyElement = ObjectElement | ArrayElement | Element;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export type DeepMerge = (
|
|
29
|
+
targetElement: ObjectOrArrayElement,
|
|
30
|
+
sourceElement: ObjectOrArrayElement,
|
|
31
|
+
options?: DeepMergeOptions,
|
|
32
|
+
) => AnyElement;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
export type CustomMerge = (keyElement: Element, options: DeepMergeOptions) => DeepMerge;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
export type CustomMetaMerge = (
|
|
43
|
+
targetElementMeta: Metadata,
|
|
44
|
+
sourceElementMeta: Metadata,
|
|
45
|
+
) => Metadata;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @public
|
|
49
|
+
*/
|
|
50
|
+
export type CustomAttributesMerge = (
|
|
51
|
+
targetElementAttributes: ObjectElement,
|
|
52
|
+
sourceElementAttributes: ObjectElement,
|
|
53
|
+
) => ObjectElement;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @public
|
|
57
|
+
*/
|
|
58
|
+
export type ArrayElementMerge = (
|
|
59
|
+
targetElement: ArrayElement,
|
|
60
|
+
sourceElement: ArrayElement,
|
|
61
|
+
options: DeepMergeOptions,
|
|
62
|
+
) => ArrayElement;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @public
|
|
66
|
+
*/
|
|
67
|
+
export type ObjectElementMerge = (
|
|
68
|
+
targetElement: ObjectElement,
|
|
69
|
+
source: ObjectElement,
|
|
70
|
+
options: DeepMergeOptions,
|
|
71
|
+
) => ObjectElement;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export type DeepMergeUserOptions = {
|
|
77
|
+
clone?: boolean;
|
|
78
|
+
isMergeableElement?: (element: Element) => boolean;
|
|
79
|
+
arrayElementMerge?: ArrayElementMerge;
|
|
80
|
+
objectElementMerge?: ObjectElementMerge;
|
|
81
|
+
customMerge?: CustomMerge;
|
|
82
|
+
customMetaMerge?: CustomMetaMerge;
|
|
83
|
+
customAttributesMerge?: CustomAttributesMerge;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @public
|
|
88
|
+
*/
|
|
89
|
+
export type DeepMergeOptions = DeepMergeUserOptions & {
|
|
90
|
+
clone: boolean;
|
|
91
|
+
isMergeableElement: (element: Element) => boolean;
|
|
92
|
+
arrayElementMerge: ArrayElementMerge;
|
|
93
|
+
objectElementMerge: ObjectElementMerge;
|
|
94
|
+
customMerge: CustomMerge | undefined;
|
|
95
|
+
customMetaMerge: CustomMetaMerge | undefined;
|
|
96
|
+
customAttributesMerge: CustomAttributesMerge | undefined;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const emptyElement = (element: ObjectElement | ArrayElement) => {
|
|
100
|
+
const meta = !element.isMetaEmpty ? element.meta.cloneDeep() : undefined;
|
|
101
|
+
const attributes = !element.isAttributesEmpty ? cloneDeep(element.attributes) : undefined;
|
|
102
|
+
|
|
103
|
+
// @ts-ignore
|
|
104
|
+
return new element.constructor(undefined, meta, attributes);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const cloneUnlessOtherwiseSpecified = (
|
|
108
|
+
element: AnyElement,
|
|
109
|
+
options: DeepMergeOptions,
|
|
110
|
+
): AnyElement =>
|
|
111
|
+
options.clone && options.isMergeableElement(element)
|
|
112
|
+
? deepmerge(
|
|
113
|
+
emptyElement(element as ObjectOrArrayElement),
|
|
114
|
+
element as ObjectOrArrayElement,
|
|
115
|
+
options,
|
|
116
|
+
)
|
|
117
|
+
: element;
|
|
118
|
+
|
|
119
|
+
const getMergeFunction = (keyElement: Element, options: DeepMergeOptions): DeepMerge => {
|
|
120
|
+
if (typeof options.customMerge !== 'function') {
|
|
121
|
+
return deepmerge;
|
|
122
|
+
}
|
|
123
|
+
const customMerge = options.customMerge(keyElement, options);
|
|
124
|
+
return typeof customMerge === 'function' ? customMerge : deepmerge;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const getMetaMergeFunction = (options: DeepMergeOptions): CustomMetaMerge => {
|
|
128
|
+
if (typeof options.customMetaMerge !== 'function') {
|
|
129
|
+
return (targetMeta) => targetMeta.cloneDeep();
|
|
130
|
+
}
|
|
131
|
+
return options.customMetaMerge;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const getAttributesMergeFunction = (options: DeepMergeOptions): CustomAttributesMerge => {
|
|
135
|
+
if (typeof options.customAttributesMerge !== 'function') {
|
|
136
|
+
return (targetAttributes) => cloneDeep(targetAttributes);
|
|
137
|
+
}
|
|
138
|
+
return options.customAttributesMerge;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const mergeArrayElement: ArrayElementMerge = (targetElement, sourceElement, options) => {
|
|
142
|
+
const Ctor = targetElement.constructor as new (content: Element[]) => ArrayElement;
|
|
143
|
+
const merged = targetElement.concat(sourceElement) as ArrayElement;
|
|
144
|
+
return new Ctor(merged.map((item: Element) => cloneUnlessOtherwiseSpecified(item, options)));
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const mergeObjectElement: ObjectElementMerge = (targetElement, sourceElement, options) => {
|
|
148
|
+
const destination = isObjectElement(targetElement)
|
|
149
|
+
? emptyElement(targetElement)
|
|
150
|
+
: emptyElement(sourceElement);
|
|
151
|
+
|
|
152
|
+
if (isObjectElement(targetElement)) {
|
|
153
|
+
targetElement.forEach((value, key, member) => {
|
|
154
|
+
const clonedMember = cloneShallow(member as MemberElement);
|
|
155
|
+
clonedMember.value = cloneUnlessOtherwiseSpecified(value, options);
|
|
156
|
+
destination.content.push(clonedMember);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
sourceElement.forEach((value, key, member) => {
|
|
161
|
+
const keyValue = toValue(key) as string;
|
|
162
|
+
let clonedMember;
|
|
163
|
+
|
|
164
|
+
if (
|
|
165
|
+
isObjectElement(targetElement) &&
|
|
166
|
+
targetElement.hasKey(keyValue) &&
|
|
167
|
+
options.isMergeableElement(value)
|
|
168
|
+
) {
|
|
169
|
+
const targetValue = targetElement.get(keyValue)!;
|
|
170
|
+
clonedMember = cloneShallow(member as MemberElement);
|
|
171
|
+
clonedMember.value = getMergeFunction(key, options)(
|
|
172
|
+
targetValue as ObjectOrArrayElement,
|
|
173
|
+
value as ObjectOrArrayElement,
|
|
174
|
+
options,
|
|
175
|
+
);
|
|
176
|
+
} else {
|
|
177
|
+
clonedMember = cloneShallow(member as MemberElement);
|
|
178
|
+
clonedMember.value = cloneUnlessOtherwiseSpecified(value as AnyElement, options);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
destination.remove(keyValue);
|
|
182
|
+
destination.content.push(clonedMember);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
return destination;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
export const defaultOptions: DeepMergeOptions = {
|
|
189
|
+
clone: true,
|
|
190
|
+
isMergeableElement: (element) => isObjectElement(element) || isArrayElement(element),
|
|
191
|
+
arrayElementMerge: mergeArrayElement,
|
|
192
|
+
objectElementMerge: mergeObjectElement,
|
|
193
|
+
customMerge: undefined,
|
|
194
|
+
customMetaMerge: undefined,
|
|
195
|
+
customAttributesMerge: undefined,
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* @public
|
|
200
|
+
*/
|
|
201
|
+
const deepmerge = (
|
|
202
|
+
targetElement: ObjectOrArrayElement,
|
|
203
|
+
sourceElement: ObjectOrArrayElement,
|
|
204
|
+
options?: DeepMergeUserOptions,
|
|
205
|
+
): AnyElement => {
|
|
206
|
+
const mergedOptions: DeepMergeOptions = { ...defaultOptions, ...options };
|
|
207
|
+
mergedOptions.isMergeableElement =
|
|
208
|
+
mergedOptions.isMergeableElement ?? defaultOptions.isMergeableElement;
|
|
209
|
+
mergedOptions.arrayElementMerge =
|
|
210
|
+
mergedOptions.arrayElementMerge ?? defaultOptions.arrayElementMerge;
|
|
211
|
+
mergedOptions.objectElementMerge =
|
|
212
|
+
mergedOptions.objectElementMerge ?? defaultOptions.objectElementMerge;
|
|
213
|
+
|
|
214
|
+
const sourceIsArrayElement = isArrayElement(sourceElement);
|
|
215
|
+
const targetIsArrayElement = isArrayElement(targetElement);
|
|
216
|
+
const sourceAndTargetTypesMatch = sourceIsArrayElement === targetIsArrayElement;
|
|
217
|
+
|
|
218
|
+
if (!sourceAndTargetTypesMatch) {
|
|
219
|
+
return cloneUnlessOtherwiseSpecified(sourceElement, mergedOptions);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// merging two elements
|
|
223
|
+
const mergedElement =
|
|
224
|
+
sourceIsArrayElement && typeof mergedOptions.arrayElementMerge === 'function'
|
|
225
|
+
? mergedOptions.arrayElementMerge(
|
|
226
|
+
targetElement as ArrayElement,
|
|
227
|
+
sourceElement as ArrayElement,
|
|
228
|
+
mergedOptions,
|
|
229
|
+
)
|
|
230
|
+
: mergedOptions.objectElementMerge(
|
|
231
|
+
targetElement as ObjectElement,
|
|
232
|
+
sourceElement as ObjectElement,
|
|
233
|
+
mergedOptions,
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
// merging meta & attributes
|
|
237
|
+
if (!targetElement.isMetaEmpty && !sourceElement.isMetaEmpty) {
|
|
238
|
+
mergedElement.meta = getMetaMergeFunction(mergedOptions)(
|
|
239
|
+
targetElement.meta,
|
|
240
|
+
sourceElement.meta,
|
|
241
|
+
);
|
|
242
|
+
} else if (!targetElement.isMetaEmpty) {
|
|
243
|
+
mergedElement.meta = targetElement.meta.cloneDeep();
|
|
244
|
+
} else if (!sourceElement.isMetaEmpty) {
|
|
245
|
+
mergedElement.meta = sourceElement.meta.cloneDeep();
|
|
246
|
+
}
|
|
247
|
+
if (!targetElement.isAttributesEmpty && !sourceElement.isAttributesEmpty) {
|
|
248
|
+
mergedElement.attributes = getAttributesMergeFunction(mergedOptions)(
|
|
249
|
+
targetElement.attributes,
|
|
250
|
+
sourceElement.attributes,
|
|
251
|
+
);
|
|
252
|
+
} else if (!targetElement.isAttributesEmpty) {
|
|
253
|
+
mergedElement.attributes = cloneDeep(targetElement.attributes);
|
|
254
|
+
} else if (!sourceElement.isAttributesEmpty) {
|
|
255
|
+
mergedElement.attributes = cloneDeep(sourceElement.attributes);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return mergedElement;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
deepmerge.all = (list: ObjectOrArrayElement[], options?: DeepMergeUserOptions) => {
|
|
262
|
+
if (!Array.isArray(list)) {
|
|
263
|
+
throw new TypeError('First argument of deepmerge should be an array.');
|
|
264
|
+
}
|
|
265
|
+
if (list.length === 0) {
|
|
266
|
+
return new ObjectElement();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return list.reduce((target, source) => {
|
|
270
|
+
return deepmerge(target, source, options);
|
|
271
|
+
}, emptyElement(list[0]));
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
export default deepmerge;
|
|
@@ -0,0 +1,16 @@
|
|
|
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 _mergeRight = _interopRequireDefault(require("./merge-right.cjs"));
|
|
7
|
+
/**
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
const mergeLeft = (...[sourceElement, targetElement, options]) => {
|
|
11
|
+
return (0, _mergeRight.default)(targetElement, sourceElement, options);
|
|
12
|
+
};
|
|
13
|
+
mergeLeft.all = (...[list, options]) => {
|
|
14
|
+
return _mergeRight.default.all([...list].reverse(), options);
|
|
15
|
+
};
|
|
16
|
+
var _default = exports.default = mergeLeft;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import mergeRight from "./merge-right.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
const mergeLeft = (...[sourceElement, targetElement, options]) => {
|
|
6
|
+
return mergeRight(targetElement, sourceElement, options);
|
|
7
|
+
};
|
|
8
|
+
mergeLeft.all = (...[list, options]) => {
|
|
9
|
+
return mergeRight.all([...list].reverse(), options);
|
|
10
|
+
};
|
|
11
|
+
export default mergeLeft;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import mergeRight from './merge-right.ts';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
const mergeLeft: typeof mergeRight = (...[sourceElement, targetElement, options]) => {
|
|
7
|
+
return mergeRight(targetElement, sourceElement, options);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
mergeLeft.all = ((...[list, options]) => {
|
|
11
|
+
return mergeRight.all([...list].reverse(), options);
|
|
12
|
+
}) as typeof mergeRight.all;
|
|
13
|
+
|
|
14
|
+
export default mergeLeft;
|