immutable-assign
Advanced tools
Comparing version 1.0.26 to 1.0.27
@@ -41,2 +41,10 @@ | ||
option?: IIassignOption): TObj; | ||
// functional programming friendly style, moved obj to the last parameters and supports currying | ||
fp<TObj, TProp, TContext>( | ||
getProp: getPropFunc<TObj, TProp, TContext>, | ||
setProp: setPropFunc<TProp>, | ||
context?: TContext, | ||
option?: IIassignOption, | ||
obj?: TObj): TObj; | ||
} | ||
@@ -43,0 +51,0 @@ } |
@@ -28,3 +28,28 @@ "use strict"; | ||
// } | ||
var autoCurry = (function () { | ||
var toArray = function toArray(arr, from) { | ||
return Array.prototype.slice.call(arr, from || 0); | ||
}; | ||
var curry = function curry(fn /* variadic number of args */) { | ||
var args = toArray(arguments, 1); | ||
return function curried() { | ||
return fn.apply(this, args.concat(toArray(arguments))); | ||
}; | ||
}; | ||
return function autoCurry(fn, numArgs) { | ||
numArgs = numArgs || fn.length; | ||
return function autoCurried() { | ||
if (arguments.length < numArgs) { | ||
return numArgs - arguments.length > 0 ? | ||
autoCurry(curry.apply(this, [fn].concat(toArray(arguments))), numArgs - arguments.length) : | ||
curry.apply(this, [fn].concat(toArray(arguments))); | ||
} | ||
else { | ||
return fn.apply(this, arguments); | ||
} | ||
}; | ||
}; | ||
}()); | ||
var iassign = _iassign; | ||
iassign.fp = autoCurry(_iassignFp); | ||
iassign.maxGetPropCacheSize = 100; | ||
@@ -66,2 +91,5 @@ // Immutable Assign | ||
} | ||
function _iassignFp(getPropOrSetProp, setPropOrOption, contextOrUndefined, optionOrUndefined, obj) { | ||
return _iassign(obj, getPropOrSetProp, setPropOrOption, contextOrUndefined, optionOrUndefined); | ||
} | ||
// For performance | ||
@@ -68,0 +96,0 @@ function copyOption(option) { |
@@ -161,4 +161,4 @@ // Karma configuration | ||
}, | ||
// customLaunchers: customLaunchers, | ||
// browsers: Object.keys(customLaunchers), | ||
customLaunchers: customLaunchers, | ||
browsers: Object.keys(customLaunchers), | ||
reporters: ['dots', 'saucelabs'], | ||
@@ -172,3 +172,3 @@ | ||
// Refer to http://karma-runner.github.io/1.0/config/browsers.html | ||
browsers: ["Chrome", "Firefox", "IE", "PhantomJS"], | ||
//browsers: ["Chrome", "Firefox", "IE", "PhantomJS"], | ||
@@ -175,0 +175,0 @@ // To Run Edge, please install https://github.com/nicolasmccurdy/karma-edge-launcher manually. |
{ | ||
"name": "immutable-assign", | ||
"version": "1.0.26", | ||
"version": "1.0.27", | ||
"description": "Lightweight immutable helper that allows you to continue working with Plain JavaScript Objects", | ||
@@ -45,3 +45,3 @@ "main": "src/iassign.js", | ||
"gulp-less": "^3.1.0", | ||
"gulp-typescript": "^2.13.6", | ||
"gulp-typescript": "^2.14.1", | ||
"immutable": "^3.8.1", | ||
@@ -48,0 +48,0 @@ "istanbul": "^0.4.3", |
@@ -51,3 +51,3 @@ # immutable-assign (iassign.js) | ||
// function overload 1: | ||
function iassign<TObj, TProp, TContext>( | ||
iassign = function<TObj, TProp, TContext>( | ||
obj: TObj, // POJO object to be getting the property from, it will not be modified. | ||
@@ -60,3 +60,3 @@ getProp: (obj: TObj, context: TContext) => TProp, // Function to get the property that needs to be updated. | ||
// function overload 2: you can skip getProp() if you trying to update the root object, refer to example 1 and 2 | ||
function iassign<TObj>( | ||
iassign = function<TObj>( | ||
obj: TObj, // POJO object to be getting the property from, it will not be modified. | ||
@@ -66,2 +66,9 @@ setProp: setPropFunc<TObj>, // Function to set the property. | ||
// functional programming friendly style, moved obj to the last parameter and supports currying, refer to example 8 | ||
iassign.fp = function <TObj, TProp, TContext>( | ||
getProp: getPropFunc<TObj, TProp, TContext>, | ||
setProp: setPropFunc<TProp>, | ||
context?: TContext, | ||
option?: IIassignOption, | ||
obj?: TObj): TObj; // POJO object to be getting the property from, it will not be modified. | ||
@@ -358,3 +365,54 @@ // Options, can be applied globally or individually | ||
####Example 8: Update nested structures using iassign.fp() and currying | ||
```javascript | ||
var iassign = require("immutable-assign"); | ||
var nested1 = { a: { b: { c: [3, 4, 5] } } }; | ||
// 8.1: Calling iassign() to assign d to nested1.a.b | ||
var iassignFp = iassign.fp(function (n) { return n.a.b; }) | ||
(function (b) { b.d = 6; return b; }) | ||
(undefined) | ||
(undefined); | ||
var nested2 = iassignFp(nested1); | ||
// nested2 = { a: { b: { c: [3, 4, 5], d: 6 } } }; | ||
// nested2 !== nested1 | ||
// 8.2: Calling iassign() to increment nested2.a.b.d | ||
iassignFp = iassign.fp(function (n) { return n.a.b.d; }) | ||
(function (d) { return d + 1; }) | ||
(undefined) | ||
(undefined); | ||
var nested3 = iassignFp(nested2); | ||
// nested3 = { a: { b: { c: [3, 4, 5], d: 7 } } }; | ||
// nested3 !== nested2 | ||
// 8.3: Calling iassign() to push item to nested3.a.b.c | ||
iassignFp = iassign.fp(function (n) { return n.a.b.c; }) | ||
(function (c) { c.push(6); return c; }) | ||
(undefined) | ||
(undefined); | ||
var nested4 = iassignFp(nested3); | ||
// nested4 = { a: { b: { c: [3, 4, 5, 6], d: 7 } } }; | ||
// nested4 !== nested3 | ||
// 8.4: Calling iassign() to push item to nested3.a.b.c[1] | ||
iassignFp = iassign.fp(function (n, ctx) { return n.a.b.c[ctx.i]; }) | ||
(function (ci) { return ci + 100; }) | ||
({i: 1}) | ||
(undefined); | ||
var nested5 = iassignFp(nested4); | ||
// nested5 = { a: { b: { c: [3, 104, 5, 6], d: 7 } } }; | ||
// nested5 !== nested4 | ||
``` | ||
##Constraints | ||
@@ -368,2 +426,3 @@ | ||
* 1.0.27 - Added iassign.fp() that support [currying](https://www.sitepoint.com/currying-in-functional-javascript), refer to [example 8](#example-8-update-nested-structures-using-iassignfp-and-currying) | ||
* 1.0.26 - Works with webpack, please refer to [ImmutableAssignTest](https://github.com/engineforce/ImmutableAssignTest) | ||
@@ -370,0 +429,0 @@ * 1.0.23 - Greatly improved performance. |
@@ -778,3 +778,108 @@ "use strict"; | ||
}); | ||
it("iassign.fp", function () { | ||
//var iassign = require("immutable-assign"); | ||
// Deep freeze both input and output, can be used in development to make sure they don't change. | ||
iassign.freeze = true; | ||
var nested1 = { a: { b: { c: [3, 4, 5] } } }; | ||
// 3.1: Calling iassign() to assign d to nested1.a.b | ||
var iassignFp = iassign.fp( | ||
function (n) { return n.a.b; }, | ||
function (b) { b.d = 6; return b; }, | ||
undefined, | ||
undefined | ||
); | ||
var nested2 = iassignFp(nested1); | ||
expect(nested1).toEqual({ a: { b: { c: [3, 4, 5] } } }); | ||
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } }); | ||
expect(nested2).not.toBe(nested1); | ||
// 3.2: Calling iassign() to increment nested2.a.b.d | ||
iassignFp = iassign.fp( | ||
function (n) { return n.a.b.d; }, | ||
function (d) { return d + 1; }, | ||
undefined, | ||
undefined | ||
); | ||
var nested3 = iassignFp(nested2); | ||
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } }); | ||
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } }); | ||
expect(nested3).not.toBe(nested2); | ||
// 3.3: Calling iassign() to push item to nested3.a.b.c | ||
iassignFp = iassign.fp( | ||
function (n) { return n.a.b.c; }, | ||
function (c) { c.push(6); return c; }, | ||
undefined, | ||
undefined | ||
); | ||
var nested4 = iassignFp(nested3); | ||
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } }); | ||
expect(nested4).toEqual({ a: { b: { c: [3, 4, 5, 6], d: 7 } } }); | ||
expect(nested4).not.toBe(nested3); | ||
}); | ||
it("iassign.fp 2", function () { | ||
//var iassign = require("immutable-assign"); | ||
// Deep freeze both input and output, can be used in development to make sure they don't change. | ||
iassign.freeze = true; | ||
var nested1 = { a: { b: { c: [3, 4, 5] } } }; | ||
// 8.1: Calling iassign() to assign d to nested1.a.b | ||
var iassignFp = iassign.fp(function (n) { return n.a.b; }) | ||
(function (b) { b.d = 6; return b; }) | ||
(undefined) | ||
(undefined); | ||
var nested2 = iassignFp(nested1); | ||
expect(nested1).toEqual({ a: { b: { c: [3, 4, 5] } } }); | ||
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } }); | ||
expect(nested2).not.toBe(nested1); | ||
// 8.2: Calling iassign() to increment nested2.a.b.d | ||
iassignFp = iassign.fp(function (n) { return n.a.b.d; }) | ||
(function (d) { return d + 1; }) | ||
(undefined) | ||
(undefined); | ||
var nested3 = iassignFp(nested2); | ||
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } }); | ||
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } }); | ||
expect(nested3).not.toBe(nested2); | ||
// 8.3: Calling iassign() to push item to nested3.a.b.c | ||
iassignFp = iassign.fp(function (n) { return n.a.b.c; }) | ||
(function (c) { c.push(6); return c; }) | ||
(undefined) | ||
(undefined); | ||
var nested4 = iassignFp(nested3); | ||
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } }); | ||
expect(nested4).toEqual({ a: { b: { c: [3, 4, 5, 6], d: 7 } } }); | ||
expect(nested4).not.toBe(nested3); | ||
// 8.4: Calling iassign() to push item to nested3.a.b.c[1] | ||
iassignFp = iassign.fp(function (n, ctx) { return n.a.b.c[ctx.i]; }) | ||
(function (ci) { return ci + 100; }) | ||
({i: 1}) | ||
(undefined); | ||
var nested5 = iassignFp(nested4); | ||
expect(nested4).toEqual({ a: { b: { c: [3, 4, 5, 6], d: 7 } } }); | ||
expect(nested5).toEqual({ a: { b: { c: [3, 104, 5, 6], d: 7 } } }); | ||
expect(nested5).not.toBe(nested4); | ||
}); | ||
}); | ||
}); |
@@ -563,3 +563,34 @@ "use strict"; | ||
}); | ||
it("Issue 3: nicer api", function () { | ||
iassign.freeze = true; | ||
var mutate = function (getter, setter, context) { return function (state) { return iassign(state, getter, setter, context, { freeze: true }); }; }; | ||
var nested1 = { a: { b: { c: [3, 4, 5] } } }; | ||
// 3.1: Calling iassign() to assign d to nested1.a.b | ||
var nested2 = mutate(function (n) { return n.a.b; }, function (b) { b.d = 6; return b; })(nested1); | ||
expect(nested1).toEqual({ a: { b: { c: [3, 4, 5] } } }); | ||
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } }); | ||
expect(nested2).not.toBe(nested1); | ||
}); | ||
it("iassign.fp", function () { | ||
//var iassign = require("immutable-assign"); | ||
// Deep freeze both input and output, can be used in development to make sure they don't change. | ||
iassign.freeze = true; | ||
var nested1 = { a: { b: { c: [3, 4, 5] } } }; | ||
// 3.1: Calling iassign() to assign d to nested1.a.b | ||
var nested2 = iassign.fp(function (n) { return n.a.b; }, function (b) { b.d = 6; return b; }, undefined, undefined, nested1); | ||
expect(nested1).toEqual({ a: { b: { c: [3, 4, 5] } } }); | ||
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } }); | ||
expect(nested2).not.toBe(nested1); | ||
// 3.2: Calling iassign() to increment nested2.a.b.d | ||
var nested3 = iassign.fp(function (n) { return n.a.b.d; }, function (d) { return d + 1; }, undefined, undefined, nested2); | ||
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } }); | ||
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } }); | ||
expect(nested3).not.toBe(nested2); | ||
// 3.3: Calling iassign() to push item to nested3.a.b.c | ||
var nested4 = iassign.fp(function (n) { return n.a.b.c; }, function (c) { c.push(6); return c; }, undefined, undefined, nested3); | ||
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } }); | ||
expect(nested4).toEqual({ a: { b: { c: [3, 4, 5, 6], d: 7 } } }); | ||
expect(nested4).not.toBe(nested3); | ||
}); | ||
}); | ||
}); |
@@ -838,5 +838,73 @@ | ||
it("Issue 3: nicer api", function () { | ||
iassign.freeze = true; | ||
const mutate = (getter, setter, context?) => (state) => iassign(state, getter, setter, context, { freeze: true }); | ||
var nested1 = { a: { b: { c: [3, 4, 5] } } }; | ||
// 3.1: Calling iassign() to assign d to nested1.a.b | ||
let nested2 = mutate(n => n.a.b, b => { b.d = 6; return b; })(nested1); | ||
expect(nested1).toEqual({ a: { b: { c: [3, 4, 5] } } }); | ||
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } }); | ||
expect(nested2).not.toBe(nested1); | ||
}); | ||
it("iassign.fp", function () { | ||
//var iassign = require("immutable-assign"); | ||
// Deep freeze both input and output, can be used in development to make sure they don't change. | ||
iassign.freeze = true; | ||
var nested1 = { a: { b: { c: [3, 4, 5] } } }; | ||
// 3.1: Calling iassign() to assign d to nested1.a.b | ||
var nested2 = iassign.fp( | ||
function (n) { return n.a.b; }, | ||
function (b: any) { b.d = 6; return b; }, | ||
undefined, | ||
undefined, | ||
nested1 | ||
); | ||
expect(nested1).toEqual({ a: { b: { c: [3, 4, 5] } } }); | ||
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } }); | ||
expect(nested2).not.toBe(nested1); | ||
// 3.2: Calling iassign() to increment nested2.a.b.d | ||
var nested3 = iassign.fp( | ||
function (n) { return (<any>n.a.b).d; }, | ||
function (d) { return d + 1; }, | ||
undefined, | ||
undefined, | ||
nested2 | ||
); | ||
expect(nested2).toEqual({ a: { b: { c: [3, 4, 5], d: 6 } } }); | ||
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } }); | ||
expect(nested3).not.toBe(nested2); | ||
// 3.3: Calling iassign() to push item to nested3.a.b.c | ||
var nested4 = iassign.fp( | ||
function (n) { return n.a.b.c; }, | ||
function (c) { c.push(6); return c; }, | ||
undefined, | ||
undefined, | ||
nested3 | ||
); | ||
expect(nested3).toEqual({ a: { b: { c: [3, 4, 5], d: 7 } } }); | ||
expect(nested4).toEqual({ a: { b: { c: [3, 4, 5, 6], d: 7 } } }); | ||
expect(nested4).not.toBe(nested3); | ||
}); | ||
}); | ||
}); |
@@ -41,2 +41,10 @@ | ||
option?: IIassignOption): TObj; | ||
// functional programming friendly style, moved obj to the last parameter and supports currying | ||
fp<TObj, TProp, TContext>( | ||
getProp: getPropFunc<TObj, TProp, TContext>, | ||
setProp: setPropFunc<TProp>, | ||
context?: TContext, | ||
option?: IIassignOption, | ||
obj?: TObj): TObj; | ||
} | ||
@@ -43,0 +51,0 @@ } |
@@ -28,3 +28,28 @@ "use strict"; | ||
// } | ||
var autoCurry = (function () { | ||
var toArray = function toArray(arr, from) { | ||
return Array.prototype.slice.call(arr, from || 0); | ||
}; | ||
var curry = function curry(fn /* variadic number of args */) { | ||
var args = toArray(arguments, 1); | ||
return function curried() { | ||
return fn.apply(this, args.concat(toArray(arguments))); | ||
}; | ||
}; | ||
return function autoCurry(fn, numArgs) { | ||
numArgs = numArgs || fn.length; | ||
return function autoCurried() { | ||
if (arguments.length < numArgs) { | ||
return numArgs - arguments.length > 0 ? | ||
autoCurry(curry.apply(this, [fn].concat(toArray(arguments))), numArgs - arguments.length) : | ||
curry.apply(this, [fn].concat(toArray(arguments))); | ||
} | ||
else { | ||
return fn.apply(this, arguments); | ||
} | ||
}; | ||
}; | ||
}()); | ||
var iassign = _iassign; | ||
iassign.fp = autoCurry(_iassignFp); | ||
iassign.maxGetPropCacheSize = 100; | ||
@@ -66,2 +91,5 @@ // Immutable Assign | ||
} | ||
function _iassignFp(getPropOrSetProp, setPropOrOption, contextOrUndefined, optionOrUndefined, obj) { | ||
return _iassign(obj, getPropOrSetProp, setPropOrOption, contextOrUndefined, optionOrUndefined); | ||
} | ||
// For performance | ||
@@ -68,0 +96,0 @@ function copyOption(option) { |
@@ -47,2 +47,10 @@ "use strict"; | ||
option?: IIassignOption): TObj; | ||
// functional programming friendly style, moved obj to the last parameter and supports currying | ||
fp<TObj, TProp, TContext>( | ||
getProp: getPropFunc<TObj, TProp, TContext>, | ||
setProp: setPropFunc<TProp>, | ||
context?: TContext, | ||
option?: IIassignOption, | ||
obj?: TObj): TObj; | ||
} | ||
@@ -76,3 +84,34 @@ | ||
var autoCurry = (function () { | ||
var toArray = function toArray(arr, from?) { | ||
return Array.prototype.slice.call(arr, from || 0); | ||
} | ||
var curry = function curry(fn /* variadic number of args */) { | ||
var args = toArray(arguments, 1); | ||
return function curried() { | ||
return fn.apply(this, args.concat(toArray(arguments))); | ||
}; | ||
}; | ||
return function autoCurry(fn, numArgs?) { | ||
numArgs = numArgs || fn.length; | ||
return function autoCurried() { | ||
if (arguments.length < numArgs) { | ||
return numArgs - arguments.length > 0 ? | ||
autoCurry(curry.apply(this, [fn].concat(toArray(arguments))), | ||
numArgs - arguments.length) : | ||
curry.apply(this, [fn].concat(toArray(arguments))); | ||
} | ||
else { | ||
return fn.apply(this, arguments); | ||
} | ||
}; | ||
}; | ||
}()); | ||
var iassign: IIassign = <any>_iassign; | ||
iassign.fp = autoCurry(_iassignFp); | ||
iassign.maxGetPropCacheSize = 100; | ||
@@ -126,2 +165,13 @@ | ||
function _iassignFp<TObj, TProp, TContext>( | ||
getPropOrSetProp: getPropFunc<TObj, TProp, TContext> | setPropFunc<TProp>, | ||
setPropOrOption: setPropFunc<TProp> | IIassignOption, | ||
contextOrUndefined?: TContext, | ||
optionOrUndefined?: IIassignOption, | ||
obj?: TObj | ||
): TObj { | ||
return _iassign<TObj, TProp, TContext>(obj, getPropOrSetProp, setPropOrOption, contextOrUndefined, optionOrUndefined); | ||
} | ||
// For performance | ||
@@ -128,0 +178,0 @@ function copyOption(option) { |
960321
25466
440