immutablepatch
Advanced tools
Comparing version 0.2.0 to 0.2.1
{ | ||
"name": "immutablepatch", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "Apply RFC 6902 style patches to Immutable.JS data structures", | ||
@@ -5,0 +5,0 @@ "main": "src/patch.js", |
144
src/patch.js
@@ -6,83 +6,97 @@ 'use strict'; | ||
var mapPatch = function(map, patches) { | ||
return map.withMutations(function(updateMap) { | ||
patches.map(function(patch){ | ||
var pathArray = patch.get('path').split('/').slice(1).map(path.unescape); | ||
var op = patch.get('op'); | ||
var tryParseInt = function(n) { | ||
var int = parseInt(n); | ||
return isNaN(int) ? n : int; | ||
}; | ||
if(op === 'add' || op === 'replace'){ | ||
updateMap.setIn(pathArray, patch.get('value')); | ||
} | ||
else if(op === 'remove'){ | ||
updateMap.removeIn(pathArray) | ||
} | ||
}); | ||
}); | ||
var primitivePatch = function (op, value) { | ||
if (op === 'add' || op === 'replace') { | ||
return value; | ||
} else if (op === 'remove') { | ||
return null; | ||
} | ||
}; | ||
/** | ||
* TODO: use `withMutations` when this gets fixed: | ||
* https://github.com/facebook/immutable-js/issues/196 | ||
*/ | ||
var sequencePatch = function (sequence, patches) { | ||
var updateSeq = sequence; | ||
patches.map(function(patch){ | ||
var pathArray = patch.get('path').split('/').slice(1).map(parsePath); | ||
var op = patch.get('op'); | ||
var mapPatch = function(map, firstPath, restPath, op, value) { | ||
if (op === 'add') { | ||
if (restPath.length > 0 && map.get(firstPath) === undefined) { | ||
var baseValue = (restPath[0].match(/^\d+$/)) ? Immutable.List() : Immutable.Map(); | ||
return map.set(firstPath, anyPatch(baseValue, restPath, op, value)); | ||
} else { | ||
return map.set(firstPath, anyPatch(map.get(firstPath), restPath, op, value)); | ||
} | ||
} else if (op === 'replace') { | ||
return map.set(firstPath, anyPatch(map.get(firstPath), restPath, op, value)); | ||
} else if (op === 'remove') { | ||
if (restPath.length > 0) { | ||
return map.set(firstPath, anyPatch(map.get(firstPath), restPath, op, value)); | ||
} else { | ||
return map.remove(firstPath); | ||
} | ||
} else { | ||
throw new Error('map patch Error, unknown op: ' + op); | ||
} | ||
}; | ||
if(op === 'add'){ | ||
var parentPath = pathArray.slice(0, -1); | ||
var parent = updateSeq.getIn(parentPath); | ||
if(Immutable.Iterable.isIndexed(parent)){ | ||
updateSeq = updateSeq.updateIn(parentPath, function(list){ | ||
return list.splice(pathArray[pathArray.length-1], 0, patch.get('value')); | ||
}); | ||
var sequencePatch = function(sequence, firstPath, restPath, op, value) { | ||
firstPath = tryParseInt(firstPath); | ||
if (op === 'add') { | ||
if (sequence.get(firstPath) === undefined) { | ||
if (restPath.length > 0) { | ||
var baseValue = (restPath[0].match(/^\d+$/)) ? Immutable.List() : Immutable.Map(); | ||
return sequence.set(firstPath, anyPatch(baseValue, restPath, op, value)); | ||
} else { | ||
// special case, return the value | ||
return sequence.splice(firstPath, 0, value); | ||
} | ||
else{ | ||
updateSeq = updateSeq.setIn(pathArray, patch.get('value')); | ||
} else { | ||
if (restPath.length > 0) { | ||
return sequence.set(firstPath, anyPatch(sequence.get(firstPath), restPath, op, value)); | ||
} else { | ||
// special case, return the value | ||
return sequence.splice(firstPath, 0, value); | ||
} | ||
} | ||
else if(op === 'replace'){ | ||
updateSeq = updateSeq.setIn(pathArray, patch.get('value')); | ||
} else if (op === 'replace') { | ||
return sequence.set(firstPath, anyPatch(sequence.get(firstPath), restPath, op, value)); | ||
} else if (op === 'remove') { | ||
if (restPath.length > 0) { | ||
return sequence.set(firstPath, anyPatch(sequence.get(firstPath), restPath, op, value)); | ||
} else { | ||
return sequence.remove(firstPath); | ||
} | ||
else if(op === 'remove'){ | ||
updateSeq = updateSeq.removeIn(pathArray) | ||
} | ||
}); | ||
return updateSeq; | ||
} else { | ||
throw new Error('sequence patch Error, unknown op: ' + op); | ||
} | ||
}; | ||
var primitivePatch = function (value, patches) { | ||
var op = patches.get(0).get('op'); | ||
var anyPatch = function(any, pathArray, op, value) { | ||
var firstPath, restPath; | ||
if(op === 'add' || op === 'replace'){ | ||
return patches.get(0).get('value'); | ||
if (Immutable.Iterable.isKeyed(any)) { | ||
if (pathArray.length === 0) { return any; } | ||
firstPath = pathArray[0]; | ||
restPath = pathArray.slice(1); | ||
return mapPatch(any, firstPath, restPath, op, value); | ||
} else if (Immutable.Iterable.isIndexed(any)) { | ||
if (pathArray.length === 0) { return any; } | ||
firstPath = pathArray[0]; | ||
restPath = pathArray.slice(1); | ||
return sequencePatch(any, firstPath, restPath, op, value); | ||
} else { | ||
if (pathArray.length === 0) { return value; } | ||
return primitivePatch(op, value); | ||
} | ||
else if (op === 'remove'){ | ||
return null; | ||
} | ||
}; | ||
var tryParseInt = function(n) { | ||
var int = parseInt(n); | ||
return isNaN(int) ? n : int; | ||
}; | ||
var eachPatch = function(value, patches) { | ||
if (patches.count() === 0) { return value; } | ||
var firstPatch = patches.get(0); | ||
var restPatches = patches.slice(1); | ||
var parsePath = function(n){ | ||
return tryParseInt(path.unescape(n)); | ||
var pathArray = firstPatch.get('path').split('/').slice(1).map(path.unescape); | ||
var result = anyPatch(value, pathArray, firstPatch.get('op'), firstPatch.get('value')); | ||
return eachPatch(result, restPatches); | ||
}; | ||
module.exports = function(value, patches){ | ||
if(patches.count() === 0){ return value; } | ||
if(Immutable.Iterable.isKeyed(value)){ | ||
return mapPatch(value, patches); | ||
} | ||
else if(Immutable.Iterable.isIndexed(value)){ | ||
return sequencePatch(value, patches); | ||
} | ||
else{ | ||
return primitivePatch(value, patches); | ||
} | ||
}; | ||
module.exports = eachPatch; |
@@ -52,3 +52,3 @@ 'use strict'; | ||
}); | ||
it('removes value in map', function() { | ||
@@ -182,3 +182,3 @@ var map = Immutable.Map({a: 1, b: 2}); | ||
var ops = Immutable.fromJS([ | ||
{op: 'add', path: '/b/2', value: 4} | ||
{op: 'replace', path: '/b/2', value: 4} | ||
]); | ||
@@ -185,0 +185,0 @@ |
@@ -29,2 +29,14 @@ 'use strict'; | ||
it('adds value among a list', function () { | ||
var list = Immutable.fromJS({a: [1, 2, 3, 4]}) | ||
var ops = Immutable.fromJS([ | ||
{op: 'add', path: '/a/1', value: 'x'} | ||
]); | ||
var result = patch(list, ops); | ||
var expected = Immutable.fromJS({a: [1,'x',2,3,4]}) | ||
assert.ok(Immutable.is(result, expected)); | ||
}); | ||
it('adds values in empty list', function () { | ||
@@ -31,0 +43,0 @@ var list = Immutable.List(); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25945
14
654