src/Context.js
import t from 'tcomb';
import applyPatch from 'immpatch';
import JSONPointer from './JSONPointer';
import { get, unbox, box } from './state';
const emptyInstance = {
type: t.Any,
state: box({})
};
/**
* Context is passed to all components.
*/
class Context {
/**
* Context constructors
*
* @param {Object} instance - instances sdds
* @param {Object} instance.state - states sd
* @param {Transform} instance.transform - transform sdds
*/
constructor(instance = {}) {
Object.assign(this, emptyInstance, instance);
Object.freeze(this);
}
/**
* create Context of state, transform is identity
* @param {object} state - state of ctx
* @return {Context}
*/
static ofState(state = {}) {
return new Context({
state: box(state)
});
}
/**
* get value from state
* @param {string|JSONPointer} path = '' - pointer to value
* @param {boolean} toJS = false - unbox value?
* @return {any} value
*/
get(path = '', toJS = false) {
if(t.Boolean.is(path)) return this.get('', path);
const result = get(this.state, JSONPointer.ofString(path));
return toJS ? unbox(result) : result;
}
/**
* check if ctx has changed
* @param {Context} last - the last COntext
* @return {boolean}
*/
changed(last) {
const keys = last.state.keySeq().toJS();
return keys.some(key => this.get(key) !== last.get(key));
}
update(patchSet) {
if(patchSet.length === 0) return this;
const newState = applyPatch(this.state, patchSet);
// assert type
const rawState = newState.toJS();
this.type(rawState);
return new Context({
type: this.type,
// transform: this.transform,
state: newState
});
}
}
export default Context;