forked from AsyncBanana/micropatch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
52 lines (47 loc) · 1.33 KB
/
index.ts
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
interface Difference {
type: "CREATE" | "REMOVE" | "CHANGE";
path: (string | number)[];
value?: any;
oldValue?: any;
}
export default function patch(
obj: Record<string, any> | any[],
diffs: Difference[]
): Record<string, any> | any[] {
let arrayDelQueue = [];
const removeSymbol = Symbol("micropatch-delete");
for (const diff of diffs) {
if (!diff.path || diff.path.length === 0) continue;
let currObj = obj;
let diffPathLength = diff.path.length;
let lastPathElement = diff.path[diffPathLength - 1];
let secondLastPathElement = diff.path[diffPathLength - 2];
for (let i = 0; i < diffPathLength - 1; i++) {
currObj = currObj[diff.path[i]];
}
switch (diff.type) {
case "CREATE":
case "CHANGE":
currObj[lastPathElement] = diff.value;
break;
case "REMOVE":
if (Array.isArray(currObj)) {
(currObj as any)[lastPathElement] = removeSymbol;
arrayDelQueue.push(() => {
if (secondLastPathElement !== undefined) {
(currObj as any)[secondLastPathElement] = (currObj as any)[
secondLastPathElement
].filter((e: any) => e !== removeSymbol);
} else {
obj = obj.filter((e: any) => e !== removeSymbol);
}
});
} else {
delete currObj[lastPathElement];
}
break;
}
}
arrayDelQueue.forEach((arrayDeletion) => arrayDeletion());
return obj;
}