diff --git a/source/server/utils/merge/apply.test.ts b/source/server/utils/merge/apply.test.ts index 32757ec2..3f4f47c7 100644 --- a/source/server/utils/merge/apply.test.ts +++ b/source/server/utils/merge/apply.test.ts @@ -32,4 +32,10 @@ describe("merge.apply()", function(){ expect(apply({a:"A"}, { b:[{name:"A1"}]} as any)).to.deep.equal({a:"A", b:[{name:"A1"}]}); }) + it("compacts arrays", function(){ + expect(apply({a:[{name: "A"}, {name: "B"}, {name: "C"}]}, {a:{0:{name: "A'"}, 1: DELETE_KEY}} as any)).to.deep.equal({a:[ + {name: "A'"}, + {name: "C"} // C gets pushed-back to index 2 + ]}); + }); }); \ No newline at end of file diff --git a/source/server/utils/merge/apply.ts b/source/server/utils/merge/apply.ts index 8d80ab5a..2f189c8d 100644 --- a/source/server/utils/merge/apply.ts +++ b/source/server/utils/merge/apply.ts @@ -14,13 +14,20 @@ export default function apply>(into :T, ...diffs : const value = diff[key] as T[Extract]; if(value === DELETE_KEY){ - delete into[key]; + if(Array.isArray(into)){ + into.splice(key as any, 1); + }else{ + delete into[key]; + } + }else if(typeof value !== "object" //primitive || typeof into[key] === "undefined" //undefined target ){ into[key] = value; }else if(Array.isArray(value)){ - //Replace arrays without looking + //Replace arrays without looking. + //This will generally not happen unles there is an exception in diff() that says so. + //Arrays are generally replaced by a number-indexed object. into[key] = value; }else{ //Default case : recurse. diff --git a/source/server/utils/merge/diff.ts b/source/server/utils/merge/diff.ts index 4ffdfcee..a6a2ff8b 100644 --- a/source/server/utils/merge/diff.ts +++ b/source/server/utils/merge/diff.ts @@ -4,6 +4,7 @@ import {Diff, DELETE_KEY} from "./pointers/types.js"; * Computes a diff between two objects. * Applying deepMerge(a, diff(a,b)) should yield b * deleted keys are represented using the DELETE_KEY symbol + * It treats arrays as primitives (ie. will overwrite blindly any array) * @param from origin document * @param to target document * @returns @@ -30,6 +31,7 @@ export default function diff>(from :T, to :T) :Diff } //Handle cases where `typeof from[key] === "object"` + if(to[key] == null){ //Null is special because it can't be fed back to diff() recursively if(from[key] != null ) r[key] = null as T[Extract];