@cerebral/fluent
Advanced tools
Comparing version 1.0.0-1521047171357 to 1.0.0-1521140905511
@@ -12,2 +12,3 @@ var __extends = (this && this.__extends) || (function () { | ||
import { observable, untracked, transaction, extras, ObservableMap as MobxObservableMap, useStrict } from 'mobx'; | ||
import { CreateModuleProvider } from './providers'; | ||
import { BaseControllerClass } from 'cerebral'; | ||
@@ -48,2 +49,3 @@ import { extractModuleProp, getModule, throwError } from 'cerebral/internal'; | ||
}); | ||
_this.contextProviders.module = CreateModuleProvider(_this.model.state, _this.devtools, _this.model, options.useLegacyStateApi || false); | ||
return _this; | ||
@@ -50,0 +52,0 @@ } |
@@ -574,2 +574,188 @@ /* eslint-env mocha */ | ||
}); | ||
it('should manage module state', function () { | ||
var actionCount = 0; | ||
var Sequence = SequenceFactory(); | ||
var sequence = Sequence(function (s) { | ||
return s | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._set = 'bar2'; | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._push.push('bar2'); | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._pop.pop(); | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._shift.shift(); | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._splice.splice(1, 0, 'baz'); | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._unshift.unshift('bar'); | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._observableMapSet.set('foo', 'bar'); | ||
}); | ||
}); | ||
var fooModule = Module({ | ||
state: { | ||
_set: 'foo', | ||
_push: [], | ||
_pop: ['foo'], | ||
_shift: ['foo'], | ||
_splice: ['foo', 'bar'], | ||
_unshift: ['foo'], | ||
_observableMapSet: Dictionary({}) | ||
}, | ||
signals: { | ||
test: sequence | ||
} | ||
}); | ||
var rootModule = Module({ | ||
modules: { | ||
foo: fooModule | ||
} | ||
}); | ||
var controller = Controller(rootModule, { | ||
devtools: { | ||
init: function () { }, | ||
send: function () { }, | ||
updateComponentsMap: function () { }, | ||
sendExecutionData: function (data) { | ||
switch (actionCount) { | ||
case 0: | ||
assert.deepEqual(data, { | ||
type: 'mutation', | ||
method: 'module.set', | ||
args: [['foo', '_set'], 'bar2'] | ||
}); | ||
break; | ||
case 1: | ||
assert.deepEqual(data, { | ||
type: 'mutation', | ||
method: 'module.push', | ||
args: [['foo', '_push'], 'bar2'] | ||
}); | ||
break; | ||
case 2: | ||
assert.deepEqual(data, { | ||
type: 'mutation', | ||
method: 'module.pop', | ||
args: [['foo', '_pop']] | ||
}); | ||
break; | ||
case 3: | ||
assert.deepEqual(data, { | ||
type: 'mutation', | ||
method: 'module.shift', | ||
args: [['foo', '_shift']] | ||
}); | ||
break; | ||
case 4: | ||
assert.deepEqual(data, { | ||
type: 'mutation', | ||
method: 'module.splice', | ||
args: [['foo', '_splice'], 1, 0, 'baz'] | ||
}); | ||
break; | ||
case 5: | ||
assert.deepEqual(data, { | ||
type: 'mutation', | ||
method: 'module.unshift', | ||
args: [['foo', '_unshift'], 'bar'] | ||
}); | ||
break; | ||
case 6: | ||
assert.deepEqual(data, { | ||
type: 'mutation', | ||
method: 'module.set', | ||
args: [['foo', '_observableMapSet', 'foo'], 'bar'] | ||
}); | ||
break; | ||
} | ||
actionCount++; | ||
} | ||
} | ||
}); | ||
controller.signals.foo.test(); | ||
assert.equal(controller.state.foo._set, 'bar2'); | ||
assert.equal(controller.state.foo._push[0], 'bar2'); | ||
assert.equal(controller.state.foo._pop.length, 0); | ||
assert.equal(controller.state.foo._shift.length, 0); | ||
assert.equal(controller.state.foo._splice.join('.'), 'foo.baz.bar'); | ||
assert.equal(controller.state.foo._unshift[0], 'bar'); | ||
assert.equal(controller.state.foo._observableMapSet.get('foo'), 'bar'); | ||
assert.equal(actionCount, 7); | ||
}); | ||
it('should manage module state without devtools', function () { | ||
var Sequence = SequenceFactory(); | ||
var sequence = Sequence(function (s) { | ||
return s | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._set = 'bar2'; | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._push.push('bar2'); | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._pop.pop(); | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._shift.shift(); | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._splice.splice(1, 0, 'baz'); | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._unshift.unshift('bar'); | ||
}) | ||
.action(function test(_a) { | ||
var module = _a.module; | ||
module._observableMapSet.set('foo', 'bar'); | ||
}); | ||
}); | ||
var fooModule = Module({ | ||
state: { | ||
_set: 'foo', | ||
_push: [], | ||
_pop: ['foo'], | ||
_shift: ['foo'], | ||
_splice: ['foo', 'bar'], | ||
_unshift: ['foo'], | ||
_observableMapSet: Dictionary({}) | ||
}, | ||
signals: { | ||
test: sequence | ||
} | ||
}); | ||
var rootModule = Module({ | ||
modules: { | ||
foo: fooModule | ||
} | ||
}); | ||
var controller = Controller(rootModule); | ||
controller.signals.foo.test(); | ||
assert.equal(controller.state.foo._set, 'bar2'); | ||
assert.equal(controller.state.foo._push[0], 'bar2'); | ||
assert.equal(controller.state.foo._pop.length, 0); | ||
assert.equal(controller.state.foo._shift.length, 0); | ||
assert.equal(controller.state.foo._splice.join('.'), 'foo.baz.bar'); | ||
assert.equal(controller.state.foo._unshift[0], 'bar'); | ||
assert.equal(controller.state.foo._observableMapSet.get('foo'), 'bar'); | ||
}); | ||
}); |
259
lib/Model.js
@@ -12,263 +12,6 @@ var __extends = (this && this.__extends) || (function () { | ||
import { extractModuleProp, isObject, BaseModel } from 'cerebral/internal'; | ||
import { Provider } from 'cerebral'; | ||
import { observable, isObservable, isObservableMap, extendObservable, ObservableMap } from 'mobx'; | ||
import { ComputedClass } from './Computed'; | ||
import { updateIn, traverse } from './utils'; | ||
var mutationMethods = ['concat', 'pop', 'push', 'shift', 'splice', 'unshift']; | ||
var nonMutationObservableMapKeys = [ | ||
'has', | ||
'keys', | ||
'values', | ||
'entries', | ||
'isValidKey', | ||
'_hasMap', | ||
'forEach' | ||
]; | ||
function cleanPath(state, key, path) { | ||
var pathCopy = key ? path.concat(key) : path.slice(); | ||
var isValid = false; | ||
while (!isValid) { | ||
var value = pathCopy.reduce(function (currentState, pathKey) { | ||
if (currentState === undefined) { | ||
return; | ||
} | ||
if (isObservableMap(currentState)) { | ||
return currentState.get(pathKey.toString()); | ||
} | ||
if (typeof currentState === 'object' && pathKey in currentState) { | ||
return currentState[pathKey]; | ||
} | ||
return; | ||
}, state); | ||
if (value === undefined) { | ||
pathCopy.splice(pathCopy.length - 2, 1); | ||
} | ||
else { | ||
isValid = true; | ||
} | ||
} | ||
return pathCopy; | ||
} | ||
function createValidator(state, execution, functionDetails, props, devtools) { | ||
var path = []; | ||
var validator = { | ||
get: function (target, key) { | ||
if (isObservableMap(target)) { | ||
switch (key) { | ||
case 'size': | ||
path = cleanPath(state, null, path); | ||
return target[key]; | ||
case 'forEach': | ||
var originalFunc = target[key]; | ||
return function (cb) { | ||
return target.keys().forEach(function (forEachKey) { | ||
var args = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
args[_i - 1] = arguments[_i]; | ||
} | ||
path = cleanPath(state, forEachKey, path); | ||
cb.apply(void 0, [new Proxy(target.get(forEachKey), validator)].concat(args)); | ||
}); | ||
}; | ||
case 'entries': { | ||
var originalFunc_1 = target[key]; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
var value = originalFunc_1.apply(target, args); | ||
path = cleanPath(state, null, path); | ||
return value; | ||
}; | ||
} | ||
case 'get': { | ||
var originalFunc_2 = target[key]; | ||
return function (mapKey) { | ||
path = cleanPath(state, mapKey, path); | ||
var value = originalFunc_2.call(target, mapKey); | ||
return new Proxy(value, validator); | ||
}; | ||
} | ||
case 'delete': { | ||
var originalFunction_1 = target[key]; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
devtools.sendExecutionData({ | ||
type: 'mutation', | ||
method: 'unset', | ||
args: [path.concat(args[0])] | ||
}, execution, functionDetails, props); | ||
path = cleanPath(state, args[0], path); | ||
return originalFunction_1.apply(target, args); | ||
}; | ||
} | ||
case 'clear': { | ||
var originalFunction_2 = target[key]; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
devtools.sendExecutionData({ | ||
type: 'mutation', | ||
method: 'set', | ||
args: [path, {}] | ||
}, execution, functionDetails, props); | ||
path = cleanPath(state, null, path); | ||
return originalFunction_2.apply(target, args); | ||
}; | ||
} | ||
case 'merge': { | ||
var originalFunction_3 = target[key]; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
devtools.sendExecutionData({ | ||
type: 'mutation', | ||
method: 'merge', | ||
args: [path, args[0]] | ||
}, execution, functionDetails, props); | ||
path = cleanPath(state, null, path); | ||
return originalFunction_3.apply(target, args); | ||
}; | ||
} | ||
case 'replace': | ||
var originalFunction_4 = target[key]; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
devtools.sendExecutionData({ | ||
type: 'mutation', | ||
method: 'set', | ||
args: [path, args[0]] | ||
}, execution, functionDetails, props); | ||
path = cleanPath(state, null, path); | ||
return originalFunction_4.apply(target, args); | ||
}; | ||
case 'set': { | ||
var originalFunction_5 = target[key]; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
devtools.sendExecutionData({ | ||
type: 'mutation', | ||
method: 'set', | ||
args: [path.concat(args[0]), args[1]] | ||
}, execution, functionDetails, props); | ||
path = cleanPath(state, null, path); | ||
return originalFunction_5.apply(target, args); | ||
}; | ||
} | ||
default: | ||
return target[key]; | ||
} | ||
} | ||
else if (target[key] instanceof ComputedClass) { | ||
return target[key]; | ||
} | ||
else if (typeof target[key] === 'object' && target[key] !== null) { | ||
path = cleanPath(state, key, path); | ||
return new Proxy(target[key], validator); | ||
} | ||
else { | ||
if (typeof target[key] === 'function' && mutationMethods.indexOf(key) >= 0) { | ||
var originalFunction_6 = target[key]; | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
devtools.sendExecutionData({ | ||
type: 'mutation', | ||
method: key, | ||
args: [path].concat(args) | ||
}, execution, functionDetails, props); | ||
path = cleanPath(state, key, path); | ||
return originalFunction_6.apply(target, args); | ||
}; | ||
} | ||
return target[key]; | ||
} | ||
}, | ||
set: function (target, key, value) { | ||
path = cleanPath(state, key, path); | ||
devtools.sendExecutionData({ | ||
type: 'mutation', | ||
method: 'set', | ||
args: [path, isObservable(value) ? value.value : value] | ||
}, execution, functionDetails, props); | ||
Reflect.set(target, key, value); | ||
return true; | ||
} | ||
}; | ||
return validator; | ||
} | ||
var legacyApi = [ | ||
'get', | ||
'set', | ||
'toggle', | ||
'push', | ||
'merge', | ||
'pop', | ||
'shift', | ||
'unshift', | ||
'splice', | ||
'concat', | ||
'increment', | ||
'unset' | ||
]; | ||
function CreateStateProvider(state, devtools, model, useLegacyStateApi) { | ||
if (!devtools && useLegacyStateApi) { | ||
legacyApi.forEach(function (method) { | ||
Object.defineProperty(state, method, { | ||
value: function (path) { | ||
var args = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
args[_i - 1] = arguments[_i]; | ||
} | ||
return model[method].apply(model, [path.split('.')].concat(args)); | ||
} | ||
}); | ||
}); | ||
} | ||
return Provider(state, { | ||
wrap: devtools | ||
? function (context) { | ||
if (useLegacyStateApi) { | ||
legacyApi.forEach(function (method) { | ||
Object.defineProperty(state, method, { | ||
writable: true, | ||
value: function (path) { | ||
var args = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
args[_i - 1] = arguments[_i]; | ||
} | ||
if (method !== 'get') { | ||
devtools.sendExecutionData({ | ||
type: 'mutation', | ||
method: method, | ||
args: [path.split('.')].concat(args.map(function (value) { return (isObservable(value) ? value.value : value); })) | ||
}, context.execution, context.functionDetails, context.props); | ||
} | ||
return model[method].apply(model, [path.split('.')].concat(args)); | ||
} | ||
}); | ||
}); | ||
} | ||
return new Proxy(state, createValidator(state, context.execution, context.functionDetails, context.props, devtools)); | ||
} | ||
: false, | ||
ignoreDefinition: true | ||
}); | ||
} | ||
import { CreateStateProvider } from './providers'; | ||
var Model = /** @class */ (function (_super) { | ||
@@ -275,0 +18,0 @@ __extends(Model, _super); |
{ | ||
"name": "@cerebral/fluent", | ||
"version": "1.0.0-1521047171357", | ||
"version": "1.0.0-1521140905511", | ||
"description": "Makes Cerebral typescript friendly", | ||
@@ -27,3 +27,3 @@ "main": "index.js", | ||
"dependencies": { | ||
"cerebral": "^5.0.0-1521047171357", | ||
"cerebral": "^5.0.0-1521140905511", | ||
"mobx": "^3.4.1" | ||
@@ -30,0 +30,0 @@ }, |
81718
32
1932