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.cjs
CHANGED
|
@@ -487,12 +487,14 @@ var compareArray = (oldObj, newObj, path, keyPath, options) => {
|
|
|
487
487
|
const isFunctionKey = typeof uniqKey === "function" && uniqKey.length === 2;
|
|
488
488
|
if (diffs.length) {
|
|
489
489
|
const resolvedKey = isFunctionKey ? uniqKey(newObj[0] ?? oldObj[0], true) : uniqKey;
|
|
490
|
+
const sampleEl = newObj[0] ?? oldObj[0];
|
|
491
|
+
const isNestedPath = typeof resolvedKey === "string" && resolvedKey.includes(".") && NESTED_PATH_RE.test(resolvedKey) && (isFunctionKey || !(sampleEl != null && typeof sampleEl === "object" && resolvedKey in sampleEl));
|
|
490
492
|
return [
|
|
491
493
|
{
|
|
492
494
|
type: "UPDATE" /* UPDATE */,
|
|
493
495
|
key: getKey(path),
|
|
494
496
|
embeddedKey: resolvedKey,
|
|
495
|
-
...
|
|
497
|
+
...isNestedPath ? { embeddedKeyIsPath: true } : {},
|
|
496
498
|
changes: diffs
|
|
497
499
|
}
|
|
498
500
|
];
|
|
@@ -533,7 +535,8 @@ var convertArrayToObj = (arr, uniqKey) => {
|
|
|
533
535
|
obj[i] = value;
|
|
534
536
|
}
|
|
535
537
|
} else {
|
|
536
|
-
const
|
|
538
|
+
const maybeNestedPath = typeof uniqKey === "string" && uniqKey.includes(".") && NESTED_PATH_RE.test(uniqKey);
|
|
539
|
+
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;
|
|
537
540
|
obj = keyBy(arr, keyFunction);
|
|
538
541
|
}
|
|
539
542
|
return obj;
|
|
@@ -580,7 +583,7 @@ var indexOfItemInArray = (arr, key, value, isPath) => {
|
|
|
580
583
|
const item = arr[i];
|
|
581
584
|
if (item == null) continue;
|
|
582
585
|
const resolved = resolveProperty(item, key, isPath);
|
|
583
|
-
if (resolved
|
|
586
|
+
if (resolved !== void 0 && String(resolved) === String(value)) {
|
|
584
587
|
return i;
|
|
585
588
|
}
|
|
586
589
|
}
|
|
@@ -636,7 +639,7 @@ var applyArrayChange = (arr, change) => {
|
|
|
636
639
|
} else {
|
|
637
640
|
element = arr.find((el) => {
|
|
638
641
|
const resolved = resolveProperty(el, change.embeddedKey, change.embeddedKeyIsPath);
|
|
639
|
-
return resolved
|
|
642
|
+
return resolved !== void 0 && String(resolved) === String(subchange.key);
|
|
640
643
|
});
|
|
641
644
|
}
|
|
642
645
|
if (element) {
|
|
@@ -706,7 +709,7 @@ var revertArrayChange = (arr, change) => {
|
|
|
706
709
|
} else {
|
|
707
710
|
element = arr.find((el) => {
|
|
708
711
|
const resolved = resolveProperty(el, change.embeddedKey, change.embeddedKeyIsPath);
|
|
709
|
-
return resolved
|
|
712
|
+
return resolved !== void 0 && String(resolved) === String(subchange.key);
|
|
710
713
|
});
|
|
711
714
|
}
|
|
712
715
|
if (element) {
|
|
@@ -1354,14 +1357,16 @@ function walkChanges(changes, basePath, oldCtx, newCtx, ops, options) {
|
|
|
1354
1357
|
const childOld = change.key === "$root" ? oldCtx : oldCtx?.[change.key];
|
|
1355
1358
|
const childNew = change.key === "$root" ? newCtx : newCtx?.[change.key];
|
|
1356
1359
|
if (change.embeddedKey) {
|
|
1357
|
-
|
|
1360
|
+
const orderedChildChanges = orderArrayChildChanges(change.changes, change.embeddedKey);
|
|
1361
|
+
for (const childChange of orderedChildChanges) {
|
|
1358
1362
|
const filterPath = buildCanonicalFilterPath(
|
|
1359
1363
|
childPath,
|
|
1360
1364
|
change.embeddedKey,
|
|
1361
1365
|
childChange.key,
|
|
1362
1366
|
childOld,
|
|
1363
1367
|
childNew,
|
|
1364
|
-
childChange
|
|
1368
|
+
childChange,
|
|
1369
|
+
change.embeddedKeyIsPath
|
|
1365
1370
|
);
|
|
1366
1371
|
if (childChange.changes) {
|
|
1367
1372
|
const oldEl = findElement(childOld, change.embeddedKey, childChange.key);
|
|
@@ -1380,6 +1385,46 @@ function walkChanges(changes, basePath, oldCtx, newCtx, ops, options) {
|
|
|
1380
1385
|
}
|
|
1381
1386
|
}
|
|
1382
1387
|
}
|
|
1388
|
+
function orderArrayChildChanges(changes, embeddedKey) {
|
|
1389
|
+
if (embeddedKey !== "$index") {
|
|
1390
|
+
return changes;
|
|
1391
|
+
}
|
|
1392
|
+
const groups = [];
|
|
1393
|
+
const pureRemoves = [];
|
|
1394
|
+
for (let i = 0; i < changes.length; i++) {
|
|
1395
|
+
const current = changes[i];
|
|
1396
|
+
const next = changes[i + 1];
|
|
1397
|
+
if (current.type === "REMOVE" /* REMOVE */ && next && next.type === "ADD" /* ADD */ && String(current.key) === String(next.key)) {
|
|
1398
|
+
groups.push({ kind: "preserved", changes: [current, next] });
|
|
1399
|
+
i++;
|
|
1400
|
+
continue;
|
|
1401
|
+
}
|
|
1402
|
+
if (current.type === "REMOVE" /* REMOVE */) {
|
|
1403
|
+
pureRemoves.push(current);
|
|
1404
|
+
groups.push({ kind: "pure-remove" });
|
|
1405
|
+
continue;
|
|
1406
|
+
}
|
|
1407
|
+
groups.push({ kind: "preserved", changes: [current] });
|
|
1408
|
+
}
|
|
1409
|
+
if (pureRemoves.length < 2) {
|
|
1410
|
+
return changes;
|
|
1411
|
+
}
|
|
1412
|
+
const removeIndices = pureRemoves.map((change) => Number(change.key));
|
|
1413
|
+
if (removeIndices.some((idx) => !Number.isInteger(idx))) {
|
|
1414
|
+
return changes;
|
|
1415
|
+
}
|
|
1416
|
+
pureRemoves.sort((a, b) => Number(b.key) - Number(a.key));
|
|
1417
|
+
const ordered = [];
|
|
1418
|
+
let removeIndex = 0;
|
|
1419
|
+
for (const group of groups) {
|
|
1420
|
+
if (group.kind === "pure-remove") {
|
|
1421
|
+
ordered.push(pureRemoves[removeIndex++]);
|
|
1422
|
+
} else {
|
|
1423
|
+
ordered.push(...group.changes);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
return ordered;
|
|
1427
|
+
}
|
|
1383
1428
|
function emitLeafOp(change, path, ops, options) {
|
|
1384
1429
|
switch (change.type) {
|
|
1385
1430
|
case "ADD" /* ADD */: {
|
|
@@ -1404,7 +1449,7 @@ function emitLeafOp(change, path, ops, options) {
|
|
|
1404
1449
|
}
|
|
1405
1450
|
}
|
|
1406
1451
|
}
|
|
1407
|
-
function buildCanonicalFilterPath(basePath, embeddedKey, changeKey, oldArr, newArr, change) {
|
|
1452
|
+
function buildCanonicalFilterPath(basePath, embeddedKey, changeKey, oldArr, newArr, change, embeddedKeyIsPath) {
|
|
1408
1453
|
if (embeddedKey === "$index") {
|
|
1409
1454
|
return `${basePath}[${changeKey}]`;
|
|
1410
1455
|
}
|
|
@@ -1424,9 +1469,11 @@ function buildCanonicalFilterPath(basePath, embeddedKey, changeKey, oldArr, newA
|
|
|
1424
1469
|
const memberAccess2 = typeof keyName === "string" && SIMPLE_PROPERTY_RE2.test(keyName) ? `.${keyName}` : `.${changeKey}`;
|
|
1425
1470
|
return `${basePath}[?(@${memberAccess2}=='${changeKey}')]`;
|
|
1426
1471
|
}
|
|
1427
|
-
const
|
|
1428
|
-
const
|
|
1429
|
-
const
|
|
1472
|
+
const isNestedPath = embeddedKeyIsPath && NESTED_PATH_RE3.test(embeddedKey);
|
|
1473
|
+
const element = findElementByKey(oldArr, newArr, embeddedKey, changeKey, change.type, isNestedPath);
|
|
1474
|
+
const resolved = element !== void 0 ? resolveNestedKey(element, embeddedKey, !!isNestedPath) : void 0;
|
|
1475
|
+
const typedVal = resolved !== void 0 ? resolved : changeKey;
|
|
1476
|
+
const memberAccess = SIMPLE_PROPERTY_RE2.test(embeddedKey) || isNestedPath ? `.${embeddedKey}` : `['${embeddedKey.replace(/'/g, "''")}']`;
|
|
1430
1477
|
return `${basePath}[?(@${memberAccess}==${formatFilterLiteral(typedVal)})]`;
|
|
1431
1478
|
}
|
|
1432
1479
|
function findActualValue(oldArr, newArr, stringKey, opType) {
|
|
@@ -1465,13 +1512,20 @@ function findElement(arr, embeddedKey, changeKey) {
|
|
|
1465
1512
|
}
|
|
1466
1513
|
return arr.find((item) => item && String(item[embeddedKey]) === changeKey);
|
|
1467
1514
|
}
|
|
1468
|
-
function
|
|
1515
|
+
function resolveNestedKey(item, key, isPath) {
|
|
1516
|
+
if (isPath) {
|
|
1517
|
+
return key.split(".").reduce((c, s) => c?.[s], item);
|
|
1518
|
+
}
|
|
1519
|
+
return item?.[key];
|
|
1520
|
+
}
|
|
1521
|
+
function findElementByKey(oldArr, newArr, embeddedKey, changeKey, opType, isPath) {
|
|
1522
|
+
const match = (item) => item && String(resolveNestedKey(item, embeddedKey, !!isPath)) === changeKey;
|
|
1469
1523
|
if (opType === "REMOVE" /* REMOVE */ || opType === "UPDATE" /* UPDATE */) {
|
|
1470
|
-
const el = oldArr?.find(
|
|
1524
|
+
const el = oldArr?.find(match);
|
|
1471
1525
|
if (el) return el;
|
|
1472
1526
|
}
|
|
1473
1527
|
if (opType === "ADD" /* ADD */ || opType === "UPDATE" /* UPDATE */) {
|
|
1474
|
-
const el = newArr?.find(
|
|
1528
|
+
const el = newArr?.find(match);
|
|
1475
1529
|
if (el) return el;
|
|
1476
1530
|
}
|
|
1477
1531
|
return void 0;
|