immutable-lens
Advanced tools
Comparing version 0.0.5 to 0.0.6
@@ -1,2 +0,2 @@ | ||
import { FieldUpdates, FieldValues, Lens, NotAnArray, Update } from './Lens'; | ||
import { FieldUpdaters, FieldValues, Lens, NotAnArray, Updater } from './Lens'; | ||
export declare abstract class AbstractLens<T, Target> implements Lens<T, Target> { | ||
@@ -7,9 +7,9 @@ readonly abstract path: string; | ||
abstract read(source: T): Target; | ||
abstract setValue(newValue: Target): Update<T>; | ||
abstract setValue(newValue: Target): Updater<T>; | ||
abstract defaultTo<SafeTarget>(this: Lens<T, SafeTarget | undefined>, value: SafeTarget): Lens<T, SafeTarget>; | ||
abstract throwIfUndefined<SafeTarget extends Target>(this: Lens<T, SafeTarget | undefined>): Lens<T, SafeTarget>; | ||
update(update: Update<Target>): Update<T>; | ||
setFieldValues(newValues: FieldValues<Target>): Update<T>; | ||
updateFields(fieldUpdates: FieldUpdates<Target>): Update<T>; | ||
pipe(...updates: Update<Target>[]): Update<T>; | ||
update(updater: Updater<Target>): Updater<T>; | ||
setFieldValues(newValues: FieldValues<Target>): Updater<T>; | ||
updateFields(updaters: FieldUpdaters<Target>): Updater<T>; | ||
pipe(...updaters: Updater<Target>[]): Updater<T>; | ||
} |
@@ -5,11 +5,11 @@ "use strict"; | ||
var updateFields_1 = require("./updateFields"); | ||
var pipeUpdates_1 = require("./pipeUpdates"); | ||
var pipe_1 = require("./pipe"); | ||
var AbstractLens = (function () { | ||
function AbstractLens() { | ||
} | ||
AbstractLens.prototype.update = function (update) { | ||
AbstractLens.prototype.update = function (updater) { | ||
var _this = this; | ||
return function (source) { | ||
var value = _this.read(source); | ||
var newValue = update(value); | ||
var newValue = updater(value); | ||
if (newValue === value) | ||
@@ -30,7 +30,7 @@ return source; | ||
}; | ||
AbstractLens.prototype.updateFields = function (fieldUpdates) { | ||
AbstractLens.prototype.updateFields = function (updaters) { | ||
var _this = this; | ||
return function (source) { | ||
var currentTarget = _this.read(source); | ||
var updatedTarget = updateFields_1.updateFields(currentTarget, fieldUpdates); | ||
var updatedTarget = updateFields_1.updateFields(currentTarget, updaters); | ||
if (updatedTarget === currentTarget) | ||
@@ -42,7 +42,7 @@ return source; | ||
AbstractLens.prototype.pipe = function () { | ||
var updates = []; | ||
var updaters = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
updates[_i] = arguments[_i]; | ||
updaters[_i] = arguments[_i]; | ||
} | ||
return this.update(pipeUpdates_1.pipeUpdates.apply(void 0, updates)); | ||
return this.update(pipe_1.pipe.apply(void 0, updaters)); | ||
}; | ||
@@ -49,0 +49,0 @@ return AbstractLens; |
@@ -1,2 +0,2 @@ | ||
import { Lens, NotAnArray, Update } from './Lens'; | ||
import { Lens, NotAnArray, Updater } from './Lens'; | ||
import { AbstractLens } from './AbstractLens'; | ||
@@ -11,5 +11,5 @@ export declare class DefaultValueLens<T, Target> extends AbstractLens<T, Target> { | ||
read(source: T): Target; | ||
setValue(newValue: Target): Update<T>; | ||
setValue(newValue: Target): Updater<T>; | ||
defaultTo<SafeTarget>(this: DefaultValueLens<T, SafeTarget | undefined>, value: SafeTarget): Lens<T, SafeTarget>; | ||
throwIfUndefined<SafeTarget extends Target>(this: Lens<T, SafeTarget | undefined>): Lens<T, SafeTarget>; | ||
} |
export * from './Lens'; | ||
export * from './pipeUpdates'; | ||
export { createLens } from './createLens'; | ||
export { pipe } from './pipe'; |
"use strict"; | ||
function __export(m) { | ||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__export(require("./Lens")); | ||
__export(require("./pipeUpdates")); | ||
var createLens_1 = require("./createLens"); | ||
exports.createLens = createLens_1.createLens; | ||
var pipe_1 = require("./pipe"); | ||
exports.pipe = pipe_1.pipe; | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,2 @@ | ||
import { FieldUpdates, FieldValues, Lens, Update } from './Lens'; | ||
import { FieldUpdaters, FieldValues, Lens, Updater } from './Lens'; | ||
import { AbstractLens } from './AbstractLens'; | ||
@@ -11,7 +11,7 @@ export declare class IndexFocusedLens<T, Item> extends AbstractLens<T, Item> { | ||
read(source: T): Item; | ||
setValue(newValue: Item): Update<T>; | ||
setFieldValues(fields: FieldValues<Item>): Update<T>; | ||
updateFields(fields: FieldUpdates<Item>): Update<T>; | ||
setValue(newValue: Item): Updater<T>; | ||
setFieldValues(newValues: FieldValues<Item>): Updater<T>; | ||
updateFields(updaters: FieldUpdaters<Item>): Updater<T>; | ||
defaultTo<SafeTarget>(this: Lens<T, SafeTarget | undefined>, value: SafeTarget): Lens<T, SafeTarget>; | ||
throwIfUndefined<SafeTarget>(this: Lens<T, SafeTarget | undefined>): Lens<T, SafeTarget>; | ||
} |
@@ -51,6 +51,6 @@ "use strict"; | ||
}; | ||
IndexFocusedLens.prototype.setFieldValues = function (fields) { | ||
IndexFocusedLens.prototype.setFieldValues = function (newValues) { | ||
throw Error('setFieldValues() can NOT be called on a Lens focused on a possibly undefined value. Try calling defaultTo() first.'); | ||
}; | ||
IndexFocusedLens.prototype.updateFields = function (fields) { | ||
IndexFocusedLens.prototype.updateFields = function (updaters) { | ||
throw Error('updateFields() can NOT be called on a Lens focused on a possibly undefined value. Try calling defaultTo() first.'); | ||
@@ -57,0 +57,0 @@ }; |
@@ -1,2 +0,2 @@ | ||
import { Lens, NotAnArray, Update } from './Lens'; | ||
import { Lens, NotAnArray, Updater } from './Lens'; | ||
import { AbstractLens } from './AbstractLens'; | ||
@@ -11,5 +11,5 @@ export declare class KeyFocusedLens<T, ParentTarget extends object, K extends keyof ParentTarget, Target extends ParentTarget[K]> extends AbstractLens<T, Target> { | ||
read(source: T): Target; | ||
setValue(newValue: Target): Update<T>; | ||
setValue(newValue: Target): Updater<T>; | ||
defaultTo<SafeTarget>(this: Lens<T, SafeTarget | undefined>, value: SafeTarget): Lens<T, SafeTarget>; | ||
throwIfUndefined<SafeTarget>(this: Lens<T, SafeTarget | undefined>): Lens<T, SafeTarget>; | ||
} |
export interface NotAnArray { | ||
reduceRight?: 'NotAnArray'; | ||
} | ||
export declare type Update<T> = (value: T) => T; | ||
export interface Updater<T> { | ||
(value: T): T; | ||
} | ||
export declare type FieldValues<T> = object & NotAnArray & { | ||
[K in keyof T]?: T[K]; | ||
}; | ||
export declare type FieldUpdates<T> = object & NotAnArray & { | ||
[K in keyof T]?: Update<T[K]>; | ||
export declare type FieldUpdaters<T> = object & NotAnArray & { | ||
[K in keyof T]?: Updater<T[K]>; | ||
}; | ||
@@ -16,7 +18,7 @@ export interface Lens<T, Target> { | ||
read(source: T): Target; | ||
setValue(newValue: Target): Update<T>; | ||
update(update: Update<Target>): Update<T>; | ||
setFieldValues(this: Lens<T, Target & NotAnArray>, newValues: FieldValues<Target>): Update<T>; | ||
updateFields(this: Lens<T, Target & NotAnArray>, fieldUpdates: FieldUpdates<Target>): Update<T>; | ||
pipe(...updates: Update<Target>[]): Update<T>; | ||
setValue(newValue: Target): Updater<T>; | ||
update(updater: Updater<Target>): Updater<T>; | ||
setFieldValues(this: Lens<T, Target & NotAnArray>, newValues: FieldValues<Target>): Updater<T>; | ||
updateFields(this: Lens<T, Target & NotAnArray>, updaters: FieldUpdaters<Target>): Updater<T>; | ||
pipe(...updaters: Updater<Target>[]): Updater<T>; | ||
defaultTo<SafeTarget extends Target>(this: Lens<T, SafeTarget | undefined>, value: SafeTarget): Lens<T, SafeTarget>; | ||
@@ -27,2 +29,1 @@ throwIfUndefined<SafeTarget extends Target>(this: Lens<T, SafeTarget | undefined>): Lens<T, SafeTarget>; | ||
} | ||
export declare function createLens<T extends object>(instance?: T): UnfocusedLens<T>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var RootLens_1 = require("./RootLens"); | ||
function createLens(instance) { | ||
return new RootLens_1.RootLens(); | ||
} | ||
exports.createLens = createLens; | ||
//# sourceMappingURL=Lens.js.map |
@@ -1,2 +0,2 @@ | ||
import { FieldUpdates, FieldValues, Lens, UnfocusedLens, Update } from './Lens'; | ||
import { FieldUpdaters, FieldValues, Lens, UnfocusedLens, Updater } from './Lens'; | ||
export declare class RootLens<T extends object> implements UnfocusedLens<T> { | ||
@@ -7,9 +7,9 @@ readonly path: string; | ||
read(source: T): T; | ||
setValue(newValue: T): Update<T>; | ||
update(update: Update<T>): Update<T>; | ||
setFieldValues(fields: FieldValues<T>): Update<T>; | ||
updateFields(fields: FieldUpdates<T>): Update<T>; | ||
pipe(...updates: Update<T>[]): Update<T>; | ||
setValue(newValue: T): Updater<T>; | ||
update(updater: Updater<T>): Updater<T>; | ||
setFieldValues(newValues: FieldValues<T>): Updater<T>; | ||
updateFields(updaters: FieldUpdaters<T>): Updater<T>; | ||
pipe(...updaters: Updater<T>[]): Updater<T>; | ||
defaultTo<SafeTarget>(value: SafeTarget): Lens<T, SafeTarget>; | ||
throwIfUndefined<SafeTarget>(): Lens<T, SafeTarget>; | ||
} |
@@ -7,3 +7,3 @@ "use strict"; | ||
var setFieldValues_1 = require("./setFieldValues"); | ||
var pipeUpdates_1 = require("./pipeUpdates"); | ||
var pipe_1 = require("./pipe"); | ||
var RootLens = (function () { | ||
@@ -31,17 +31,17 @@ function RootLens() { | ||
}; | ||
RootLens.prototype.update = function (update) { | ||
return update; | ||
RootLens.prototype.update = function (updater) { | ||
return updater; | ||
}; | ||
RootLens.prototype.setFieldValues = function (fields) { | ||
return function (source) { return setFieldValues_1.setFieldValues(source, fields); }; | ||
RootLens.prototype.setFieldValues = function (newValues) { | ||
return function (source) { return setFieldValues_1.setFieldValues(source, newValues); }; | ||
}; | ||
RootLens.prototype.updateFields = function (fields) { | ||
return function (source) { return updateFields_1.updateFields(source, fields); }; | ||
RootLens.prototype.updateFields = function (updaters) { | ||
return function (source) { return updateFields_1.updateFields(source, updaters); }; | ||
}; | ||
RootLens.prototype.pipe = function () { | ||
var updates = []; | ||
var updaters = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
updates[_i] = arguments[_i]; | ||
updaters[_i] = arguments[_i]; | ||
} | ||
return pipeUpdates_1.pipeUpdates.apply(void 0, updates); | ||
return pipe_1.pipe.apply(void 0, updaters); | ||
}; | ||
@@ -48,0 +48,0 @@ // TODO Support optional types |
@@ -1,2 +0,2 @@ | ||
import { Lens, NotAnArray, Update } from './Lens'; | ||
import { Lens, NotAnArray, Updater } from './Lens'; | ||
import { AbstractLens } from './AbstractLens'; | ||
@@ -10,5 +10,5 @@ export declare class ThrowIfUndefinedLens<T, Target> extends AbstractLens<T, Target> { | ||
read(source: T): Target; | ||
setValue(newValue: Target): Update<T>; | ||
setValue(newValue: Target): Updater<T>; | ||
defaultTo<SafeTarget>(this: ThrowIfUndefinedLens<T, SafeTarget | undefined>, value: SafeTarget): Lens<T, SafeTarget>; | ||
throwIfUndefined<SafeTarget>(this: Lens<T, SafeTarget>): Lens<T, SafeTarget>; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { FieldUpdates } from './Lens'; | ||
export declare function updateFields<T, Target>(source: T, fieldUpdates: FieldUpdates<Target>): T; | ||
import { FieldUpdaters } from './Lens'; | ||
export declare function updateFields<T, Target>(source: T, fieldUpdaters: FieldUpdaters<Target>): T; |
@@ -11,22 +11,22 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
function updateFields(source, fieldUpdates) { | ||
if (typeof fieldUpdates === 'function') | ||
function updateFields(source, fieldUpdaters) { | ||
if (typeof fieldUpdaters === 'function') | ||
throw Error('Lens.updateFields() does NOT accept functions as argument'); | ||
if (Object.keys(fieldUpdates).length === 0) | ||
if (Object.keys(fieldUpdaters).length === 0) | ||
return source; | ||
var sourceObject = source; | ||
var updates = fieldUpdates; | ||
var copy = __assign({}, sourceObject); | ||
var updaters = fieldUpdaters; | ||
var shallowCopy = __assign({}, sourceObject); | ||
var hasChanged = false; | ||
for (var key in updates) { | ||
var update = updates[key]; | ||
var newValue = update(sourceObject[key]); | ||
for (var key in updaters) { | ||
var updater = updaters[key]; | ||
var newValue = updater(sourceObject[key]); | ||
if (newValue !== sourceObject[key]) { | ||
hasChanged = true; | ||
copy[key] = newValue; | ||
shallowCopy[key] = newValue; | ||
} | ||
} | ||
return hasChanged ? copy : source; | ||
return hasChanged ? shallowCopy : source; | ||
} | ||
exports.updateFields = updateFields; | ||
//# sourceMappingURL=updateFields.js.map |
{ | ||
"name": "immutable-lens", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"description": "Type-safe Lens API for immutable updates in complex data structures", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -8,5 +8,5 @@ # immutable-lens | ||
- Human-friendly API | ||
- Update your Redux store, your React component state... whatever ! | ||
- Use it with your favorite libraries (Ramda, lodash-fp, date-fns, Immutable.js...) | ||
- Optimized support for the strict equality checks performed in `React.PureComponent`, `connect()`... | ||
- Update your Redux store, your React component state, your Immutable.js collection... Whatever ! | ||
- Bring in your favorite libraries (Ramda, lodash-fp, date-fns...) | ||
- Optimized for the strict equality checks performed in `React.PureComponent`, `connect()`... | ||
- Written in TypeScript, designed for maximal type-safety | ||
@@ -72,8 +72,7 @@ | ||
#### Use `defaultTo()` to avoid undefined values when reading or updating optional types | ||
#### Compose updates with `pipe()` | ||
```ts | ||
type State = { | ||
loggedUser?: { | ||
user: { | ||
name: string | ||
age: number | ||
} | ||
@@ -83,21 +82,29 @@ } | ||
const state = { | ||
// optional loggedUser field is undefined | ||
user: { | ||
name: 'Bob', | ||
age: 18 | ||
} | ||
} | ||
const nameLens = createLens<State>() | ||
.focusOn('loggedUser') | ||
.defaultTo({name: 'Guest', age: 0}) | ||
.focusOn('user') | ||
.focusOn('name') | ||
const name = nameLens.read(state) // 'Guest' | ||
const setNameToJohn = nameLens.setValue('John') | ||
const uppercaseName = nameLens.update(name => name.toUpperCase()) | ||
const setNameToBob = nameLens.setValue('Bob') | ||
const updatedState = setNameToBob(state) // {user: {name: 'Bob', age: 0}} | ||
const setNameToJOHN = pipe( | ||
setNameToJohn, | ||
uppercaseName | ||
) | ||
const updatedState = setNameToJOHN(state) // {user: {name: 'JOHN', age: 18}} | ||
``` | ||
#### Use `pipe()` to compose updates | ||
#### Use `defaultTo()` to avoid undefined values when reading or updating optional types | ||
```ts | ||
type State = { | ||
user: { | ||
loggedUser?: { | ||
name: string | ||
age: number | ||
} | ||
@@ -107,21 +114,14 @@ } | ||
const state = { | ||
user: { | ||
name: 'Bob', | ||
age: 18 | ||
} | ||
// optional loggedUser field is undefined | ||
} | ||
const nameLens = createLens<State>() | ||
.focusOn('user') | ||
.focusOn('loggedUser') | ||
.defaultTo({name: 'Guest', age: 0}) | ||
.focusOn('name') | ||
const setNameToJohn = nameLens.setValue('John') | ||
const uppercaseName = nameLens.update(name => name.toUpperCase()) | ||
const name = nameLens.read(state) // 'Guest' | ||
const setNameToJOHN = pipeUpdates( | ||
setNameToJohn, | ||
uppercaseName | ||
) | ||
const updatedState = setNameToJOHN(state) // {user: {name: 'JOHN', age: 18}} | ||
const setNameToBob = nameLens.setValue('Bob') | ||
const updatedState = setNameToBob(state) // {user: {name: 'Bob', age: 0}} | ||
``` | ||
@@ -145,1 +145,4 @@ | ||
#### `getPath()` | ||
```ts | ||
``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
39935
39
558
144