@tacky/store
Version:
State management framework based on react
116 lines (96 loc) • 3.8 kB
JavaScript
import _regeneratorRuntime from "@babel/runtime/regenerator";
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
import { ctx } from '../const/config';
import { store } from '../core/store';
import { CURRENT_MATERIAL_TYPE } from '../const/symbol';
import { bind, convert2UniqueString, includes } from '../utils/common';
import { EMaterialType } from '../interfaces';
import { invariant } from '../utils/error';
import { quacksLikeADecorator } from '../utils/decorator';
import { materialCallStack } from '../core/domain';
import { historyCollector } from '../core/collector';
/**
* @todo: enhance effect feature, such as takeLead, takeLast
*/
function createEffect(target, name, original) {
var stringMethodName = convert2UniqueString(name);
return /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
var _len,
payload,
_key,
length,
_args = arguments;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
this[CURRENT_MATERIAL_TYPE] = EMaterialType.EFFECT;
materialCallStack.push(this[CURRENT_MATERIAL_TYPE]);
for (_len = _args.length, payload = new Array(_len), _key = 0; _key < _len; _key++) {
payload[_key] = _args[_key];
}
_context.next = 5;
return store.dispatch({
name: stringMethodName,
payload: payload,
type: EMaterialType.EFFECT,
domain: this,
original: bind(original, this)
});
case 5:
materialCallStack.pop();
length = materialCallStack.length;
this[CURRENT_MATERIAL_TYPE] = materialCallStack[length - 1] || EMaterialType.DEFAULT;
if (ctx.timeTravel.isActive && !includes(materialCallStack, EMaterialType.EFFECT)) {
historyCollector.save();
historyCollector.endBatch();
}
case 9:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
}
/**
* decorator @effect, handle some async process and effect.
*/
export function effect() {
var decorator = function decorator(target, name, descriptor) {
invariant(ctx.middleware.effect, 'If you want to use @effect decorator, please turn on the built-in effect middleware. By \"config(...)\".'); // typescript only: @effect method = async () => {}
if (descriptor === void 0) {
var effectFunc;
Object.defineProperty(target, name, {
enumerable: true,
configurable: true,
get: function get() {
return effectFunc;
},
set: function set(original) {
effectFunc = createEffect(target, name, original);
}
});
return;
} // babel/typescript: @effect method() {}
if (descriptor.value !== void 0) {
var original = descriptor.value;
descriptor.value = createEffect(target, name, original);
return descriptor;
} // babel only: @effect method = () => {}
var initializer = descriptor.initializer;
descriptor.initializer = function () {
invariant(!!initializer, 'The initializer of the descriptor doesn\'t exist, please compile it by using babel and correspond decorator plugin.');
return createEffect(target, name, initializer && initializer.call(this));
};
return descriptor;
};
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
if (quacksLikeADecorator(args)) {
// @effect
return decorator.apply(null, args);
} // @effect(args)
return decorator;
}