json-diff-ts 5.0.0-alpha.7 → 5.0.0-alpha.9
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/index.cjs +68 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +68 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -427,12 +427,14 @@ var compareArray = (oldObj, newObj, path, keyPath, options) => {
|
|
|
427
427
|
const isFunctionKey = typeof uniqKey === "function" && uniqKey.length === 2;
|
|
428
428
|
if (diffs.length) {
|
|
429
429
|
const resolvedKey = isFunctionKey ? uniqKey(newObj[0] ?? oldObj[0], true) : uniqKey;
|
|
430
|
+
const sampleEl = newObj[0] ?? oldObj[0];
|
|
431
|
+
const isNestedPath = typeof resolvedKey === "string" && resolvedKey.includes(".") && NESTED_PATH_RE.test(resolvedKey) && (isFunctionKey || !(sampleEl != null && typeof sampleEl === "object" && resolvedKey in sampleEl));
|
|
430
432
|
return [
|
|
431
433
|
{
|
|
432
434
|
type: "UPDATE" /* UPDATE */,
|
|
433
435
|
key: getKey(path),
|
|
434
436
|
embeddedKey: resolvedKey,
|
|
435
|
-
...
|
|
437
|
+
...isNestedPath ? { embeddedKeyIsPath: true } : {},
|
|
436
438
|
changes: diffs
|
|
437
439
|
}
|
|
438
440
|
];
|
|
@@ -473,7 +475,8 @@ var convertArrayToObj = (arr, uniqKey) => {
|
|
|
473
475
|
obj[i] = value;
|
|
474
476
|
}
|
|
475
477
|
} else {
|
|
476
|
-
const
|
|
478
|
+
const maybeNestedPath = typeof uniqKey === "string" && uniqKey.includes(".") && NESTED_PATH_RE.test(uniqKey);
|
|
479
|
+
const keyFunction = typeof uniqKey === "string" ? maybeNestedPath ? (item) => item != null && typeof item === "object" && uniqKey in item ? item[uniqKey] : resolveProperty(item, uniqKey, true) : (item) => item[uniqKey] : uniqKey;
|
|
477
480
|
obj = keyBy(arr, keyFunction);
|
|
478
481
|
}
|
|
479
482
|
return obj;
|
|
@@ -520,7 +523,7 @@ var indexOfItemInArray = (arr, key, value, isPath) => {
|
|
|
520
523
|
const item = arr[i];
|
|
521
524
|
if (item == null) continue;
|
|
522
525
|
const resolved = resolveProperty(item, key, isPath);
|
|
523
|
-
if (resolved
|
|
526
|
+
if (resolved !== void 0 && String(resolved) === String(value)) {
|
|
524
527
|
return i;
|
|
525
528
|
}
|
|
526
529
|
}
|
|
@@ -576,7 +579,7 @@ var applyArrayChange = (arr, change) => {
|
|
|
576
579
|
} else {
|
|
577
580
|
element = arr.find((el) => {
|
|
578
581
|
const resolved = resolveProperty(el, change.embeddedKey, change.embeddedKeyIsPath);
|
|
579
|
-
return resolved
|
|
582
|
+
return resolved !== void 0 && String(resolved) === String(subchange.key);
|
|
580
583
|
});
|
|
581
584
|
}
|
|
582
585
|
if (element) {
|
|
@@ -646,7 +649,7 @@ var revertArrayChange = (arr, change) => {
|
|
|
646
649
|
} else {
|
|
647
650
|
element = arr.find((el) => {
|
|
648
651
|
const resolved = resolveProperty(el, change.embeddedKey, change.embeddedKeyIsPath);
|
|
649
|
-
return resolved
|
|
652
|
+
return resolved !== void 0 && String(resolved) === String(subchange.key);
|
|
650
653
|
});
|
|
651
654
|
}
|
|
652
655
|
if (element) {
|
|
@@ -1294,14 +1297,16 @@ function walkChanges(changes, basePath, oldCtx, newCtx, ops, options) {
|
|
|
1294
1297
|
const childOld = change.key === "$root" ? oldCtx : oldCtx?.[change.key];
|
|
1295
1298
|
const childNew = change.key === "$root" ? newCtx : newCtx?.[change.key];
|
|
1296
1299
|
if (change.embeddedKey) {
|
|
1297
|
-
|
|
1300
|
+
const orderedChildChanges = orderArrayChildChanges(change.changes, change.embeddedKey);
|
|
1301
|
+
for (const childChange of orderedChildChanges) {
|
|
1298
1302
|
const filterPath = buildCanonicalFilterPath(
|
|
1299
1303
|
childPath,
|
|
1300
1304
|
change.embeddedKey,
|
|
1301
1305
|
childChange.key,
|
|
1302
1306
|
childOld,
|
|
1303
1307
|
childNew,
|
|
1304
|
-
childChange
|
|
1308
|
+
childChange,
|
|
1309
|
+
change.embeddedKeyIsPath
|
|
1305
1310
|
);
|
|
1306
1311
|
if (childChange.changes) {
|
|
1307
1312
|
const oldEl = findElement(childOld, change.embeddedKey, childChange.key);
|
|
@@ -1320,6 +1325,46 @@ function walkChanges(changes, basePath, oldCtx, newCtx, ops, options) {
|
|
|
1320
1325
|
}
|
|
1321
1326
|
}
|
|
1322
1327
|
}
|
|
1328
|
+
function orderArrayChildChanges(changes, embeddedKey) {
|
|
1329
|
+
if (embeddedKey !== "$index") {
|
|
1330
|
+
return changes;
|
|
1331
|
+
}
|
|
1332
|
+
const groups = [];
|
|
1333
|
+
const pureRemoves = [];
|
|
1334
|
+
for (let i = 0; i < changes.length; i++) {
|
|
1335
|
+
const current = changes[i];
|
|
1336
|
+
const next = changes[i + 1];
|
|
1337
|
+
if (current.type === "REMOVE" /* REMOVE */ && next && next.type === "ADD" /* ADD */ && String(current.key) === String(next.key)) {
|
|
1338
|
+
groups.push({ kind: "preserved", changes: [current, next] });
|
|
1339
|
+
i++;
|
|
1340
|
+
continue;
|
|
1341
|
+
}
|
|
1342
|
+
if (current.type === "REMOVE" /* REMOVE */) {
|
|
1343
|
+
pureRemoves.push(current);
|
|
1344
|
+
groups.push({ kind: "pure-remove" });
|
|
1345
|
+
continue;
|
|
1346
|
+
}
|
|
1347
|
+
groups.push({ kind: "preserved", changes: [current] });
|
|
1348
|
+
}
|
|
1349
|
+
if (pureRemoves.length < 2) {
|
|
1350
|
+
return changes;
|
|
1351
|
+
}
|
|
1352
|
+
const removeIndices = pureRemoves.map((change) => Number(change.key));
|
|
1353
|
+
if (removeIndices.some((idx) => !Number.isInteger(idx))) {
|
|
1354
|
+
return changes;
|
|
1355
|
+
}
|
|
1356
|
+
pureRemoves.sort((a, b) => Number(b.key) - Number(a.key));
|
|
1357
|
+
const ordered = [];
|
|
1358
|
+
let removeIndex = 0;
|
|
1359
|
+
for (const group of groups) {
|
|
1360
|
+
if (group.kind === "pure-remove") {
|
|
1361
|
+
ordered.push(pureRemoves[removeIndex++]);
|
|
1362
|
+
} else {
|
|
1363
|
+
ordered.push(...group.changes);
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
return ordered;
|
|
1367
|
+
}
|
|
1323
1368
|
function emitLeafOp(change, path, ops, options) {
|
|
1324
1369
|
switch (change.type) {
|
|
1325
1370
|
case "ADD" /* ADD */: {
|
|
@@ -1344,7 +1389,7 @@ function emitLeafOp(change, path, ops, options) {
|
|
|
1344
1389
|
}
|
|
1345
1390
|
}
|
|
1346
1391
|
}
|
|
1347
|
-
function buildCanonicalFilterPath(basePath, embeddedKey, changeKey, oldArr, newArr, change) {
|
|
1392
|
+
function buildCanonicalFilterPath(basePath, embeddedKey, changeKey, oldArr, newArr, change, embeddedKeyIsPath) {
|
|
1348
1393
|
if (embeddedKey === "$index") {
|
|
1349
1394
|
return `${basePath}[${changeKey}]`;
|
|
1350
1395
|
}
|
|
@@ -1364,9 +1409,11 @@ function buildCanonicalFilterPath(basePath, embeddedKey, changeKey, oldArr, newA
|
|
|
1364
1409
|
const memberAccess2 = typeof keyName === "string" && SIMPLE_PROPERTY_RE2.test(keyName) ? `.${keyName}` : `.${changeKey}`;
|
|
1365
1410
|
return `${basePath}[?(@${memberAccess2}=='${changeKey}')]`;
|
|
1366
1411
|
}
|
|
1367
|
-
const
|
|
1368
|
-
const
|
|
1369
|
-
const
|
|
1412
|
+
const isNestedPath = embeddedKeyIsPath && NESTED_PATH_RE3.test(embeddedKey);
|
|
1413
|
+
const element = findElementByKey(oldArr, newArr, embeddedKey, changeKey, change.type, isNestedPath);
|
|
1414
|
+
const resolved = element !== void 0 ? resolveNestedKey(element, embeddedKey, !!isNestedPath) : void 0;
|
|
1415
|
+
const typedVal = resolved !== void 0 ? resolved : changeKey;
|
|
1416
|
+
const memberAccess = SIMPLE_PROPERTY_RE2.test(embeddedKey) || isNestedPath ? `.${embeddedKey}` : `['${embeddedKey.replace(/'/g, "''")}']`;
|
|
1370
1417
|
return `${basePath}[?(@${memberAccess}==${formatFilterLiteral(typedVal)})]`;
|
|
1371
1418
|
}
|
|
1372
1419
|
function findActualValue(oldArr, newArr, stringKey, opType) {
|
|
@@ -1405,13 +1452,20 @@ function findElement(arr, embeddedKey, changeKey) {
|
|
|
1405
1452
|
}
|
|
1406
1453
|
return arr.find((item) => item && String(item[embeddedKey]) === changeKey);
|
|
1407
1454
|
}
|
|
1408
|
-
function
|
|
1455
|
+
function resolveNestedKey(item, key, isPath) {
|
|
1456
|
+
if (isPath) {
|
|
1457
|
+
return key.split(".").reduce((c, s) => c?.[s], item);
|
|
1458
|
+
}
|
|
1459
|
+
return item?.[key];
|
|
1460
|
+
}
|
|
1461
|
+
function findElementByKey(oldArr, newArr, embeddedKey, changeKey, opType, isPath) {
|
|
1462
|
+
const match = (item) => item && String(resolveNestedKey(item, embeddedKey, !!isPath)) === changeKey;
|
|
1409
1463
|
if (opType === "REMOVE" /* REMOVE */ || opType === "UPDATE" /* UPDATE */) {
|
|
1410
|
-
const el = oldArr?.find(
|
|
1464
|
+
const el = oldArr?.find(match);
|
|
1411
1465
|
if (el) return el;
|
|
1412
1466
|
}
|
|
1413
1467
|
if (opType === "ADD" /* ADD */ || opType === "UPDATE" /* UPDATE */) {
|
|
1414
|
-
const el = newArr?.find(
|
|
1468
|
+
const el = newArr?.find(match);
|
|
1415
1469
|
if (el) return el;
|
|
1416
1470
|
}
|
|
1417
1471
|
return void 0;
|