@takeshape/schema 8.257.0 → 8.260.1
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/dist/util/merge.d.ts +10 -1
- package/dist/util/merge.d.ts.map +1 -1
- package/dist/util/merge.js +257 -0
- package/es/util/merge.js +244 -1
- package/package.json +5 -4
package/dist/util/merge.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
import { FormConfig, ObjectSchema } from '../project-schema';
|
|
1
|
+
import { FormConfig, ObjectSchema, ProjectSchema } from '../project-schema';
|
|
2
2
|
export declare function mergeObjectSchemas(...args: Array<ObjectSchema | undefined>): ObjectSchema;
|
|
3
3
|
export declare function mergeSchemaProperties(base: ObjectSchema, overrides: ObjectSchema): ObjectSchema;
|
|
4
|
+
export declare function rebaseSchemaProperties(to: ObjectSchema, base: ObjectSchema, from: ObjectSchema): ObjectSchema;
|
|
4
5
|
export declare function mergeFormProperties(base: FormConfig, overrides: FormConfig): FormConfig;
|
|
6
|
+
export declare function rebaseFormProperties(to: FormConfig, base: FormConfig, from: FormConfig): FormConfig;
|
|
5
7
|
export declare function mergeFormConfigs(...configs: FormConfig[]): FormConfig;
|
|
8
|
+
export declare function mergeProjectSchemas(to: ProjectSchema, base: ProjectSchema, from: ProjectSchema): {
|
|
9
|
+
error: string;
|
|
10
|
+
mergedSchema: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
error: undefined;
|
|
13
|
+
mergedSchema: ProjectSchema;
|
|
14
|
+
};
|
|
6
15
|
//# sourceMappingURL=merge.d.ts.map
|
package/dist/util/merge.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../../src/util/merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../../src/util/merge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,YAAY,EAAE,aAAa,EAAQ,MAAM,mBAAmB,CAAC;AAYjF,wBAAgB,kBAAkB,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,YAAY,GAAG,SAAS,CAAC,GAAG,YAAY,CAEzF;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,GAAG,YAAY,CAgB/F;AAED,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,GAAG,YAAY,CAiB7G;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,UAAU,CAevF;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CAgBnG;AAED,wBAAgB,gBAAgB,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,GAAG,UAAU,CAErE;AAmJD,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,aAAa,EACjB,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE,aAAa,GAClB;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,SAAS,CAAA;CAAC,GAAG;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,YAAY,EAAE,aAAa,CAAA;CAAC,CAqC5F"}
|
package/dist/util/merge.js
CHANGED
|
@@ -6,12 +6,31 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.mergeFormConfigs = mergeFormConfigs;
|
|
7
7
|
exports.mergeFormProperties = mergeFormProperties;
|
|
8
8
|
exports.mergeObjectSchemas = mergeObjectSchemas;
|
|
9
|
+
exports.mergeProjectSchemas = mergeProjectSchemas;
|
|
9
10
|
exports.mergeSchemaProperties = mergeSchemaProperties;
|
|
11
|
+
exports.rebaseFormProperties = rebaseFormProperties;
|
|
12
|
+
exports.rebaseSchemaProperties = rebaseSchemaProperties;
|
|
10
13
|
|
|
11
14
|
var _util = require("@takeshape/util");
|
|
12
15
|
|
|
13
16
|
var _union = _interopRequireDefault(require("lodash/union"));
|
|
14
17
|
|
|
18
|
+
var _difference = _interopRequireDefault(require("lodash/difference"));
|
|
19
|
+
|
|
20
|
+
var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
|
|
21
|
+
|
|
22
|
+
var _unset = _interopRequireDefault(require("lodash/unset"));
|
|
23
|
+
|
|
24
|
+
var _set = _interopRequireDefault(require("lodash/set"));
|
|
25
|
+
|
|
26
|
+
var _last = _interopRequireDefault(require("lodash/last"));
|
|
27
|
+
|
|
28
|
+
var _omit = _interopRequireDefault(require("lodash/omit"));
|
|
29
|
+
|
|
30
|
+
var _types = require("../types");
|
|
31
|
+
|
|
32
|
+
var _tinyInvariant = _interopRequireDefault(require("tiny-invariant"));
|
|
33
|
+
|
|
15
34
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
35
|
|
|
17
36
|
function mergeObjectSchemas(...args) {
|
|
@@ -36,6 +55,35 @@ function mergeSchemaProperties(base, overrides) {
|
|
|
36
55
|
return result;
|
|
37
56
|
}
|
|
38
57
|
|
|
58
|
+
function rebaseSchemaProperties(to, base, from) {
|
|
59
|
+
const {
|
|
60
|
+
properties: toProperties,
|
|
61
|
+
required: toRequired,
|
|
62
|
+
...toOther
|
|
63
|
+
} = to;
|
|
64
|
+
const {
|
|
65
|
+
properties: baseProperties,
|
|
66
|
+
required: baseRequired,
|
|
67
|
+
...baseOther
|
|
68
|
+
} = base;
|
|
69
|
+
const {
|
|
70
|
+
properties: fromProperties,
|
|
71
|
+
required: fromRequired,
|
|
72
|
+
...fromOther
|
|
73
|
+
} = from;
|
|
74
|
+
const newSchema = { ...(0, _util.rebaseObject)(toOther, baseOther, fromOther),
|
|
75
|
+
type: 'object',
|
|
76
|
+
properties: (0, _util.rebaseObject)(toProperties, baseProperties, fromProperties)
|
|
77
|
+
};
|
|
78
|
+
const required = (0, _util.rebaseArray)(toRequired ?? [], baseRequired ?? [], fromRequired ?? []);
|
|
79
|
+
|
|
80
|
+
if (required.length) {
|
|
81
|
+
newSchema.required = required;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return newSchema;
|
|
85
|
+
}
|
|
86
|
+
|
|
39
87
|
function mergeFormProperties(base, overrides) {
|
|
40
88
|
const result = { ...base,
|
|
41
89
|
properties: { ...base.properties,
|
|
@@ -51,9 +99,218 @@ function mergeFormProperties(base, overrides) {
|
|
|
51
99
|
return result;
|
|
52
100
|
}
|
|
53
101
|
|
|
102
|
+
function rebaseFormProperties(to, base, from) {
|
|
103
|
+
const {
|
|
104
|
+
properties: toProperties,
|
|
105
|
+
order: toOrder,
|
|
106
|
+
...toOther
|
|
107
|
+
} = to;
|
|
108
|
+
const {
|
|
109
|
+
properties: baseProperties,
|
|
110
|
+
order: baseOrder,
|
|
111
|
+
...baseOther
|
|
112
|
+
} = base;
|
|
113
|
+
const {
|
|
114
|
+
properties: fromProperties,
|
|
115
|
+
order: fromOrder,
|
|
116
|
+
...fromOther
|
|
117
|
+
} = from;
|
|
118
|
+
const newForm = { ...(0, _util.rebaseObject)(toOther, baseOther, fromOther),
|
|
119
|
+
properties: (0, _util.rebaseObject)(toProperties, baseProperties, fromProperties)
|
|
120
|
+
};
|
|
121
|
+
const order = (0, _util.rebaseArray)(toOrder ?? [], baseOrder ?? [], fromOrder ?? []);
|
|
122
|
+
|
|
123
|
+
if (order.length) {
|
|
124
|
+
newForm.order = order;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return newForm;
|
|
128
|
+
}
|
|
129
|
+
|
|
54
130
|
function mergeFormConfigs(...configs) {
|
|
55
131
|
return configs.reduce(mergeFormProperties, {
|
|
56
132
|
properties: {},
|
|
57
133
|
order: []
|
|
58
134
|
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const mergeableSections = ['shapes', 'mutations', 'queries', 'forms', 'services'];
|
|
138
|
+
|
|
139
|
+
function compareSection(section, original, updated) {
|
|
140
|
+
const changes = [];
|
|
141
|
+
const originalKeys = Object.keys(original);
|
|
142
|
+
const updatedKeys = Object.keys(updated);
|
|
143
|
+
|
|
144
|
+
for (const removedKey of (0, _difference.default)(originalKeys, updatedKeys)) {
|
|
145
|
+
changes.push({
|
|
146
|
+
path: [section, removedKey],
|
|
147
|
+
section,
|
|
148
|
+
op: 'remove'
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
for (const [key, value] of Object.entries(updated)) {
|
|
153
|
+
if (!original[key]) {
|
|
154
|
+
changes.push({
|
|
155
|
+
path: [section, key],
|
|
156
|
+
section,
|
|
157
|
+
op: 'add',
|
|
158
|
+
value
|
|
159
|
+
});
|
|
160
|
+
} else if (!(0, _isEqual.default)(original[key], updated[key])) {
|
|
161
|
+
changes.push({
|
|
162
|
+
path: [section, key],
|
|
163
|
+
section,
|
|
164
|
+
op: 'update',
|
|
165
|
+
value
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return changes;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function compareSections(base, branch) {
|
|
174
|
+
return mergeableSections.flatMap(section => base[section] || branch[section] ? compareSection(section, base[section] ?? {}, branch[section] ?? {}) : []);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function findChangedShape(schema, change) {
|
|
178
|
+
return schema.shapes[change.path[1]];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function getChangedShape(schema, change) {
|
|
182
|
+
const shape = findChangedShape(schema, change);
|
|
183
|
+
(0, _tinyInvariant.default)(shape, 'Expected shape not found');
|
|
184
|
+
return shape;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function attemptToMerge(to, base, from, change) {
|
|
188
|
+
const toShape = getChangedShape(to, change);
|
|
189
|
+
const fromShape = getChangedShape(from, change);
|
|
190
|
+
const toSchema = toShape.schema;
|
|
191
|
+
const fromSchema = fromShape.schema;
|
|
192
|
+
|
|
193
|
+
if ((0, _types.isObjectSchema)(toSchema) && (0, _types.isObjectSchema)(fromSchema)) {
|
|
194
|
+
const baseShape = findChangedShape(base, change);
|
|
195
|
+
const baseSchema = baseShape === null || baseShape === void 0 ? void 0 : baseShape.schema;
|
|
196
|
+
return { ...(baseShape ? (0, _util.rebaseObject)((0, _omit.default)(toShape, 'schema'), (0, _omit.default)(baseShape, 'schema'), (0, _omit.default)(fromShape, 'schema')) : { ...toShape,
|
|
197
|
+
...fromShape
|
|
198
|
+
}),
|
|
199
|
+
schema: change.op === 'update' && baseSchema && (0, _types.isObjectSchema)(baseSchema) ? rebaseSchemaProperties(toSchema, baseSchema, fromSchema) : mergeSchemaProperties(toSchema, fromSchema)
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if ((0, _types.isExtendsSchema)(toSchema) && (0, _types.isExtendsSchema)(fromSchema) && toSchema.extends.length === fromSchema.extends.length) {
|
|
204
|
+
const fromExtends = fromSchema.extends;
|
|
205
|
+
const toObj = (0, _last.default)(toSchema.extends);
|
|
206
|
+
const fromObj = (0, _last.default)(fromSchema.extends);
|
|
207
|
+
|
|
208
|
+
if (toObj && (0, _types.isObjectSchema)(toObj) && fromObj && (0, _types.isObjectSchema)(fromObj) && toSchema.extends.slice(0, toSchema.extends.length - 1).every((item, i) => (0, _isEqual.default)(item, fromExtends[i]))) {
|
|
209
|
+
var _findChangedShape;
|
|
210
|
+
|
|
211
|
+
let mergedObjSchema;
|
|
212
|
+
const baseSchema = (_findChangedShape = findChangedShape(base, change)) === null || _findChangedShape === void 0 ? void 0 : _findChangedShape.schema;
|
|
213
|
+
|
|
214
|
+
if (change.op === 'update' && baseSchema && (0, _types.isExtendsSchema)(baseSchema)) {
|
|
215
|
+
const baseObj = (0, _last.default)(baseSchema.extends);
|
|
216
|
+
|
|
217
|
+
if (baseObj && (0, _types.isObjectSchema)(baseObj)) {
|
|
218
|
+
mergedObjSchema = rebaseSchemaProperties(toObj, baseObj, fromObj);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (!mergedObjSchema) {
|
|
223
|
+
mergedObjSchema = mergeSchemaProperties(toObj, fromObj);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return { ...fromShape,
|
|
227
|
+
schema: {
|
|
228
|
+
extends: [...toSchema.extends.slice(0, toSchema.extends.length - 1), mergedObjSchema]
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function applyChange(to, base, from, change) {
|
|
236
|
+
if (change.op === 'remove') {
|
|
237
|
+
(0, _unset.default)(to, change.path);
|
|
238
|
+
} else if (change.op === 'add') {
|
|
239
|
+
(0, _set.default)(to, change.path, change.value);
|
|
240
|
+
} else if (change.op === 'update') {
|
|
241
|
+
if (change.section === 'shapes') {
|
|
242
|
+
const mergedShape = attemptToMerge(to, base, from, change);
|
|
243
|
+
|
|
244
|
+
if (mergedShape) {
|
|
245
|
+
(0, _set.default)(to, change.path, mergedShape);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
} else if (change.section === 'forms') {
|
|
249
|
+
var _to$forms, _to$forms$shapeName, _from$forms, _from$forms$shapeName;
|
|
250
|
+
|
|
251
|
+
const shapeName = change.path[1];
|
|
252
|
+
const toForm = (_to$forms = to.forms) === null || _to$forms === void 0 ? void 0 : (_to$forms$shapeName = _to$forms[shapeName]) === null || _to$forms$shapeName === void 0 ? void 0 : _to$forms$shapeName.default;
|
|
253
|
+
const fromForm = (_from$forms = from.forms) === null || _from$forms === void 0 ? void 0 : (_from$forms$shapeName = _from$forms[shapeName]) === null || _from$forms$shapeName === void 0 ? void 0 : _from$forms$shapeName.default;
|
|
254
|
+
|
|
255
|
+
if (toForm && fromForm) {
|
|
256
|
+
var _base$forms, _base$forms$shapeName;
|
|
257
|
+
|
|
258
|
+
const baseForm = (_base$forms = base.forms) === null || _base$forms === void 0 ? void 0 : (_base$forms$shapeName = _base$forms[shapeName]) === null || _base$forms$shapeName === void 0 ? void 0 : _base$forms$shapeName.default;
|
|
259
|
+
(0, _set.default)(to, change.path, {
|
|
260
|
+
default: baseForm ? rebaseFormProperties(toForm, baseForm, fromForm) : mergeFormConfigs(toForm, fromForm)
|
|
261
|
+
});
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
(0, _set.default)(to, change.path, change.value);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function mergeProjectSchemas(to, base, from) {
|
|
271
|
+
const changesTo = compareSections(base, to);
|
|
272
|
+
const changesFrom = compareSections(base, from);
|
|
273
|
+
const mergedSchema = (0, _util.deepClone)(to);
|
|
274
|
+
|
|
275
|
+
for (let change of changesFrom) {
|
|
276
|
+
const potentialConflict = changesTo.find(changeTo => (0, _isEqual.default)(changeTo.path, change.path));
|
|
277
|
+
|
|
278
|
+
if (potentialConflict) {
|
|
279
|
+
if (potentialConflict.op === 'remove' && change.op !== 'remove') {
|
|
280
|
+
return {
|
|
281
|
+
error: `Attempting to ${change.op} ${change.path.join('.')} which has already been removed`,
|
|
282
|
+
mergedSchema: undefined
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (potentialConflict.op === 'add' && change.op === 'add' || potentialConflict.op === 'update' && change.op === 'update') {
|
|
287
|
+
if (change.section === 'shapes') {
|
|
288
|
+
const mergedValue = attemptToMerge(to, base, from, change);
|
|
289
|
+
|
|
290
|
+
if (!mergedValue) {
|
|
291
|
+
return {
|
|
292
|
+
error: `Unable to merge ${change.path.join('.')} schemas conflict`,
|
|
293
|
+
mergedSchema: undefined
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
change = { ...change,
|
|
298
|
+
op: 'add',
|
|
299
|
+
value: mergedValue
|
|
300
|
+
};
|
|
301
|
+
} else if (change.section === 'forms') {
|
|
302
|
+
change = { ...change,
|
|
303
|
+
op: 'update'
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
applyChange(mergedSchema, base, from, change);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
error: undefined,
|
|
314
|
+
mergedSchema
|
|
315
|
+
};
|
|
59
316
|
}
|
package/es/util/merge.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import { isDefined } from '@takeshape/util';
|
|
1
|
+
import { deepClone, isDefined, rebaseArray, rebaseObject } from '@takeshape/util';
|
|
2
2
|
import union from 'lodash/union';
|
|
3
|
+
import difference from 'lodash/difference';
|
|
4
|
+
import isEqual from 'lodash/isEqual';
|
|
5
|
+
import unset from 'lodash/unset';
|
|
6
|
+
import set from 'lodash/set';
|
|
7
|
+
import last from 'lodash/last';
|
|
8
|
+
import omit from 'lodash/omit';
|
|
9
|
+
import { isExtendsSchema, isObjectSchema } from '../types';
|
|
10
|
+
import invariant from 'tiny-invariant';
|
|
3
11
|
export function mergeObjectSchemas(...args) {
|
|
4
12
|
return args.filter(isDefined).reduce(mergeSchemaProperties, {
|
|
5
13
|
type: 'object',
|
|
@@ -20,6 +28,34 @@ export function mergeSchemaProperties(base, overrides) {
|
|
|
20
28
|
|
|
21
29
|
return result;
|
|
22
30
|
}
|
|
31
|
+
export function rebaseSchemaProperties(to, base, from) {
|
|
32
|
+
const {
|
|
33
|
+
properties: toProperties,
|
|
34
|
+
required: toRequired,
|
|
35
|
+
...toOther
|
|
36
|
+
} = to;
|
|
37
|
+
const {
|
|
38
|
+
properties: baseProperties,
|
|
39
|
+
required: baseRequired,
|
|
40
|
+
...baseOther
|
|
41
|
+
} = base;
|
|
42
|
+
const {
|
|
43
|
+
properties: fromProperties,
|
|
44
|
+
required: fromRequired,
|
|
45
|
+
...fromOther
|
|
46
|
+
} = from;
|
|
47
|
+
const newSchema = { ...rebaseObject(toOther, baseOther, fromOther),
|
|
48
|
+
type: 'object',
|
|
49
|
+
properties: rebaseObject(toProperties, baseProperties, fromProperties)
|
|
50
|
+
};
|
|
51
|
+
const required = rebaseArray(toRequired ?? [], baseRequired ?? [], fromRequired ?? []);
|
|
52
|
+
|
|
53
|
+
if (required.length) {
|
|
54
|
+
newSchema.required = required;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return newSchema;
|
|
58
|
+
}
|
|
23
59
|
export function mergeFormProperties(base, overrides) {
|
|
24
60
|
const result = { ...base,
|
|
25
61
|
properties: { ...base.properties,
|
|
@@ -34,9 +70,216 @@ export function mergeFormProperties(base, overrides) {
|
|
|
34
70
|
|
|
35
71
|
return result;
|
|
36
72
|
}
|
|
73
|
+
export function rebaseFormProperties(to, base, from) {
|
|
74
|
+
const {
|
|
75
|
+
properties: toProperties,
|
|
76
|
+
order: toOrder,
|
|
77
|
+
...toOther
|
|
78
|
+
} = to;
|
|
79
|
+
const {
|
|
80
|
+
properties: baseProperties,
|
|
81
|
+
order: baseOrder,
|
|
82
|
+
...baseOther
|
|
83
|
+
} = base;
|
|
84
|
+
const {
|
|
85
|
+
properties: fromProperties,
|
|
86
|
+
order: fromOrder,
|
|
87
|
+
...fromOther
|
|
88
|
+
} = from;
|
|
89
|
+
const newForm = { ...rebaseObject(toOther, baseOther, fromOther),
|
|
90
|
+
properties: rebaseObject(toProperties, baseProperties, fromProperties)
|
|
91
|
+
};
|
|
92
|
+
const order = rebaseArray(toOrder ?? [], baseOrder ?? [], fromOrder ?? []);
|
|
93
|
+
|
|
94
|
+
if (order.length) {
|
|
95
|
+
newForm.order = order;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return newForm;
|
|
99
|
+
}
|
|
37
100
|
export function mergeFormConfigs(...configs) {
|
|
38
101
|
return configs.reduce(mergeFormProperties, {
|
|
39
102
|
properties: {},
|
|
40
103
|
order: []
|
|
41
104
|
});
|
|
105
|
+
}
|
|
106
|
+
const mergeableSections = ['shapes', 'mutations', 'queries', 'forms', 'services'];
|
|
107
|
+
|
|
108
|
+
function compareSection(section, original, updated) {
|
|
109
|
+
const changes = [];
|
|
110
|
+
const originalKeys = Object.keys(original);
|
|
111
|
+
const updatedKeys = Object.keys(updated);
|
|
112
|
+
|
|
113
|
+
for (const removedKey of difference(originalKeys, updatedKeys)) {
|
|
114
|
+
changes.push({
|
|
115
|
+
path: [section, removedKey],
|
|
116
|
+
section,
|
|
117
|
+
op: 'remove'
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (const [key, value] of Object.entries(updated)) {
|
|
122
|
+
if (!original[key]) {
|
|
123
|
+
changes.push({
|
|
124
|
+
path: [section, key],
|
|
125
|
+
section,
|
|
126
|
+
op: 'add',
|
|
127
|
+
value
|
|
128
|
+
});
|
|
129
|
+
} else if (!isEqual(original[key], updated[key])) {
|
|
130
|
+
changes.push({
|
|
131
|
+
path: [section, key],
|
|
132
|
+
section,
|
|
133
|
+
op: 'update',
|
|
134
|
+
value
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return changes;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function compareSections(base, branch) {
|
|
143
|
+
return mergeableSections.flatMap(section => base[section] || branch[section] ? compareSection(section, base[section] ?? {}, branch[section] ?? {}) : []);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function findChangedShape(schema, change) {
|
|
147
|
+
return schema.shapes[change.path[1]];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function getChangedShape(schema, change) {
|
|
151
|
+
const shape = findChangedShape(schema, change);
|
|
152
|
+
invariant(shape, 'Expected shape not found');
|
|
153
|
+
return shape;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function attemptToMerge(to, base, from, change) {
|
|
157
|
+
const toShape = getChangedShape(to, change);
|
|
158
|
+
const fromShape = getChangedShape(from, change);
|
|
159
|
+
const toSchema = toShape.schema;
|
|
160
|
+
const fromSchema = fromShape.schema;
|
|
161
|
+
|
|
162
|
+
if (isObjectSchema(toSchema) && isObjectSchema(fromSchema)) {
|
|
163
|
+
const baseShape = findChangedShape(base, change);
|
|
164
|
+
const baseSchema = baseShape === null || baseShape === void 0 ? void 0 : baseShape.schema;
|
|
165
|
+
return { ...(baseShape ? rebaseObject(omit(toShape, 'schema'), omit(baseShape, 'schema'), omit(fromShape, 'schema')) : { ...toShape,
|
|
166
|
+
...fromShape
|
|
167
|
+
}),
|
|
168
|
+
schema: change.op === 'update' && baseSchema && isObjectSchema(baseSchema) ? rebaseSchemaProperties(toSchema, baseSchema, fromSchema) : mergeSchemaProperties(toSchema, fromSchema)
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (isExtendsSchema(toSchema) && isExtendsSchema(fromSchema) && toSchema.extends.length === fromSchema.extends.length) {
|
|
173
|
+
const fromExtends = fromSchema.extends;
|
|
174
|
+
const toObj = last(toSchema.extends);
|
|
175
|
+
const fromObj = last(fromSchema.extends);
|
|
176
|
+
|
|
177
|
+
if (toObj && isObjectSchema(toObj) && fromObj && isObjectSchema(fromObj) && toSchema.extends.slice(0, toSchema.extends.length - 1).every((item, i) => isEqual(item, fromExtends[i]))) {
|
|
178
|
+
var _findChangedShape;
|
|
179
|
+
|
|
180
|
+
let mergedObjSchema;
|
|
181
|
+
const baseSchema = (_findChangedShape = findChangedShape(base, change)) === null || _findChangedShape === void 0 ? void 0 : _findChangedShape.schema;
|
|
182
|
+
|
|
183
|
+
if (change.op === 'update' && baseSchema && isExtendsSchema(baseSchema)) {
|
|
184
|
+
const baseObj = last(baseSchema.extends);
|
|
185
|
+
|
|
186
|
+
if (baseObj && isObjectSchema(baseObj)) {
|
|
187
|
+
mergedObjSchema = rebaseSchemaProperties(toObj, baseObj, fromObj);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (!mergedObjSchema) {
|
|
192
|
+
mergedObjSchema = mergeSchemaProperties(toObj, fromObj);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return { ...fromShape,
|
|
196
|
+
schema: {
|
|
197
|
+
extends: [...toSchema.extends.slice(0, toSchema.extends.length - 1), mergedObjSchema]
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function applyChange(to, base, from, change) {
|
|
205
|
+
if (change.op === 'remove') {
|
|
206
|
+
unset(to, change.path);
|
|
207
|
+
} else if (change.op === 'add') {
|
|
208
|
+
set(to, change.path, change.value);
|
|
209
|
+
} else if (change.op === 'update') {
|
|
210
|
+
if (change.section === 'shapes') {
|
|
211
|
+
const mergedShape = attemptToMerge(to, base, from, change);
|
|
212
|
+
|
|
213
|
+
if (mergedShape) {
|
|
214
|
+
set(to, change.path, mergedShape);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
} else if (change.section === 'forms') {
|
|
218
|
+
var _to$forms, _to$forms$shapeName, _from$forms, _from$forms$shapeName;
|
|
219
|
+
|
|
220
|
+
const shapeName = change.path[1];
|
|
221
|
+
const toForm = (_to$forms = to.forms) === null || _to$forms === void 0 ? void 0 : (_to$forms$shapeName = _to$forms[shapeName]) === null || _to$forms$shapeName === void 0 ? void 0 : _to$forms$shapeName.default;
|
|
222
|
+
const fromForm = (_from$forms = from.forms) === null || _from$forms === void 0 ? void 0 : (_from$forms$shapeName = _from$forms[shapeName]) === null || _from$forms$shapeName === void 0 ? void 0 : _from$forms$shapeName.default;
|
|
223
|
+
|
|
224
|
+
if (toForm && fromForm) {
|
|
225
|
+
var _base$forms, _base$forms$shapeName;
|
|
226
|
+
|
|
227
|
+
const baseForm = (_base$forms = base.forms) === null || _base$forms === void 0 ? void 0 : (_base$forms$shapeName = _base$forms[shapeName]) === null || _base$forms$shapeName === void 0 ? void 0 : _base$forms$shapeName.default;
|
|
228
|
+
set(to, change.path, {
|
|
229
|
+
default: baseForm ? rebaseFormProperties(toForm, baseForm, fromForm) : mergeFormConfigs(toForm, fromForm)
|
|
230
|
+
});
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
set(to, change.path, change.value);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function mergeProjectSchemas(to, base, from) {
|
|
240
|
+
const changesTo = compareSections(base, to);
|
|
241
|
+
const changesFrom = compareSections(base, from);
|
|
242
|
+
const mergedSchema = deepClone(to);
|
|
243
|
+
|
|
244
|
+
for (let change of changesFrom) {
|
|
245
|
+
const potentialConflict = changesTo.find(changeTo => isEqual(changeTo.path, change.path));
|
|
246
|
+
|
|
247
|
+
if (potentialConflict) {
|
|
248
|
+
if (potentialConflict.op === 'remove' && change.op !== 'remove') {
|
|
249
|
+
return {
|
|
250
|
+
error: `Attempting to ${change.op} ${change.path.join('.')} which has already been removed`,
|
|
251
|
+
mergedSchema: undefined
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (potentialConflict.op === 'add' && change.op === 'add' || potentialConflict.op === 'update' && change.op === 'update') {
|
|
256
|
+
if (change.section === 'shapes') {
|
|
257
|
+
const mergedValue = attemptToMerge(to, base, from, change);
|
|
258
|
+
|
|
259
|
+
if (!mergedValue) {
|
|
260
|
+
return {
|
|
261
|
+
error: `Unable to merge ${change.path.join('.')} schemas conflict`,
|
|
262
|
+
mergedSchema: undefined
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
change = { ...change,
|
|
267
|
+
op: 'add',
|
|
268
|
+
value: mergedValue
|
|
269
|
+
};
|
|
270
|
+
} else if (change.section === 'forms') {
|
|
271
|
+
change = { ...change,
|
|
272
|
+
op: 'update'
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
applyChange(mergedSchema, base, from, change);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
error: undefined,
|
|
283
|
+
mergedSchema
|
|
284
|
+
};
|
|
42
285
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takeshape/schema",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.260.1",
|
|
4
4
|
"description": "TakeShape Schema",
|
|
5
5
|
"homepage": "https://www.takeshape.io",
|
|
6
6
|
"repository": {
|
|
@@ -29,9 +29,10 @@
|
|
|
29
29
|
"minimatch": "^3.0.4",
|
|
30
30
|
"p-reduce": "^2.1.0",
|
|
31
31
|
"semver": "^7.3.2",
|
|
32
|
-
"
|
|
33
|
-
"@takeshape/
|
|
34
|
-
"@takeshape/json-schema": "8.
|
|
32
|
+
"tiny-invariant": "^1.2.0",
|
|
33
|
+
"@takeshape/errors": "8.260.1",
|
|
34
|
+
"@takeshape/json-schema": "8.260.1",
|
|
35
|
+
"@takeshape/util": "8.260.1"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"@takeshape/json-schema-to-typescript": "^11.0.0",
|