Skip to content

Commit

Permalink
[WIP] rework pointers to dereference every indexable array property
Browse files Browse the repository at this point in the history
  • Loading branch information
sdumetz committed Jan 25, 2024
1 parent c4a8756 commit bce8758
Show file tree
Hide file tree
Showing 18 changed files with 606 additions and 367 deletions.
1 change: 1 addition & 0 deletions source/server/__test_fixtures/documents/01_simple.svx.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"units": "cm"
}],
"nodes": [{
"name": "Camera",
"camera": 0
}, {
"name": "Lights",
Expand Down
2 changes: 1 addition & 1 deletion source/server/utils/merge/apply.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import {DELETE_KEY} from "./types.js";
import {DELETE_KEY} from "./pointers/types.js";
import apply from "./apply.js";

describe("merge.apply()", function(){
Expand Down
73 changes: 17 additions & 56 deletions source/server/utils/merge/apply.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';
import {Diff, DELETE_KEY} from "./types.js";
import {Diff, DELETE_KEY} from "./pointers/types.js";

/**
* Deep assign two or more objects
Expand All @@ -12,78 +12,39 @@ export default function apply<T extends Record<string, any>>(into :T, ...diffs :
for(const diff of diffs){
for(const key in diff){
const value = diff[key] as T[Extract<keyof T, string>];
if(apply_core(into, key, value)){
continue;
}

//Then handle arrays to apply edge cases
if(Array.isArray(into[key])){
apply_array(into[key], value);
continue;
}
//Default case : recurse.
into[key] ??= {} as any;
apply(into[key], value);
}
}
return into;
}

/**
* Handle special merge conditions for arrays
* In particular:
* - for arrays of native types, replace the whole array
* - for arrays of objects with a "name" or "id", tries to merge objects with a matching id/name, appends the rest
*
*/
function apply_array<T extends Array<any>>(into :T, ...diffs :Diff<T>[]):T{
for (const diff of diffs){
for(const idx in diff){
const value = diff[idx];
if(apply_core(into, idx, value)){
continue;
}
if(typeof into[idx] !== undefined){
//When an item already exist, check
let append = ["id", "name"].some(key =>{
if(!value[key]) return false;
const ref_id = into[idx][key];
if(!ref_id || ref_id == value[key]) return false;
return true;
});

if(append){
into.push(value);
continue;
if(value === DELETE_KEY){
delete into[key];
}else if(typeof value !== "object" //primitive
|| typeof into[key] === "undefined" //undefined target
){
into[key] = value;
}else if(Array.isArray(value)){
if(value.some((v:any) => typeof v === "object")){
console.warn("Applying array of non-native types : ", value);
}
into[key] = value;
}else{
//Default case : recurse.
into[key] ??= {} as any;
apply(into[key], value);
}
//Default case : recurse as apply() would.
into[idx] ??= {} as any;
apply(into[idx], value);
}
}
return into;
}


/**
* Return true if the value was applied, false if it needs further processing.
* Handles the trivial cases:
* - Applies DELETE_KEY
* - Applies primitives (typeof value !== "object")
* -
* - Applies properties that don't exist in the target
*/
function apply_core<T extends Record<string, any>>(into :T, key:keyof T, value :any):boolean{

if(value === DELETE_KEY){
delete into[key];
return true;
}

if(typeof value !== "object" || typeof into[key] === "undefined"){
//Handle primitives and undefined values
into[key] = value;
return true;
}

return false;
}
2 changes: 1 addition & 1 deletion source/server/utils/merge/diff.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import {DELETE_KEY} from "./types.js";
import {DELETE_KEY} from "./pointers/types.js";

import diff from "./diff.js";

Expand Down
2 changes: 1 addition & 1 deletion source/server/utils/merge/diff.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Diff, DELETE_KEY} from "./types.js";
import {Diff, DELETE_KEY} from "./pointers/types.js";

/**
* Computes a diff between two objects.
Expand Down
4 changes: 2 additions & 2 deletions source/server/utils/merge/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

import {Diff, DELETE_KEY, DerefDocument} from "./types.js";
import {Diff, DELETE_KEY, DerefDocument} from "./pointers/types.js";
import apply from "./apply.js";
import diff from "./diff.js";
import { IDocument } from "../schema/document.js";
import { fromPointers, toPointers } from "./pointers.js";
import { fromPointers, toPointers } from "./pointers/index.js";

export {
Diff,
Expand Down
Loading

0 comments on commit bce8758

Please sign in to comment.