ayanami
Version:
A better way to react with state
192 lines (191 loc) • 8.31 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Ikari = exports.destroyIkariFrom = exports.combineWithIkari = void 0;
var tslib_1 = require("tslib");
var rxjs_1 = require("rxjs");
var operators_1 = require("rxjs/operators");
var mapValues_1 = tslib_1.__importDefault(require("lodash/mapValues"));
var immer_1 = tslib_1.__importDefault(require("immer"));
var utils_1 = require("./utils");
var redux_devtools_extension_1 = require("../redux-devtools-extension");
var symbols_1 = require("./symbols");
var terminate_1 = require("../ssr/terminate");
var flag_1 = require("../ssr/flag");
function catchRxError() {
return operators_1.catchError(function (err) {
console.error(err);
return rxjs_1.NEVER;
});
}
function combineWithIkari(ayanami) {
var ikari = Ikari.getFrom(ayanami);
if (ikari) {
return ikari;
}
else {
var _a = utils_1.getOriginalFunctions(ayanami), effects = _a.effects, reducers = _a.reducers, immerReducers = _a.immerReducers, defineActions = _a.defineActions;
Object.assign(ayanami, mapValues_1.default(defineActions, function (_a) {
var observable = _a.observable;
return observable;
}));
return Ikari.createAndBindAt(ayanami, {
nameForLog: ayanami.constructor.name,
defaultState: ayanami.defaultState,
effects: effects,
reducers: reducers,
immerReducers: immerReducers,
defineActions: defineActions,
effectActionFactories: utils_1.getEffectActionFactories(ayanami),
});
}
}
exports.combineWithIkari = combineWithIkari;
function destroyIkariFrom(ayanami) {
var ikari = Ikari.getFrom(ayanami);
if (ikari) {
ikari.destroy();
Reflect.deleteMetadata(symbols_1.ikariSymbol, ayanami);
}
}
exports.destroyIkariFrom = destroyIkariFrom;
var Ikari = /** @class */ (function () {
// eslint-disable-next-line @typescript-eslint/explicit-member-accessibility
function Ikari(ayanami, config) {
var _this = this;
this.ayanami = ayanami;
this.config = config;
this.state = utils_1.createState(this.config.defaultState);
this.effectActionFactories = this.config.effectActionFactories;
this.triggerActions = {};
this.subscription = new rxjs_1.Subscription();
// @internal
this.terminate$ = new rxjs_1.Subject();
this.log = function (_a) {
var originalActionName = _a.originalActionName, effectAction = _a.effectAction, reducerAction = _a.reducerAction;
if (effectAction && effectAction !== terminate_1.TERMINATE_ACTION) {
redux_devtools_extension_1.logStateAction(_this.config.nameForLog, {
params: effectAction.params,
actionName: originalActionName + "/\uD83D\uDC49" + effectAction.ayanami.constructor.name + "/\uFE0F" + effectAction.actionName,
});
}
if (reducerAction) {
redux_devtools_extension_1.logStateAction(_this.config.nameForLog, {
params: reducerAction.params,
actionName: originalActionName,
state: reducerAction.nextState,
});
}
};
this.handleAction = function (_a) {
var effectAction = _a.effectAction, reducerAction = _a.reducerAction;
if (effectAction) {
if (effectAction !== terminate_1.TERMINATE_ACTION) {
var ayanami = effectAction.ayanami, actionName = effectAction.actionName, params = effectAction.params;
combineWithIkari(ayanami).triggerActions[actionName](params);
}
else {
_this.terminate$.next(effectAction);
}
}
if (reducerAction) {
_this.state.setState(reducerAction.nextState);
}
};
var _a = setupEffectActions(this.config.effects, this.state.state$), effectActions$ = _a[0], effectActions = _a[1];
var _b = setupReducerActions(this.config.reducers, this.state.getState), reducerActions$ = _b[0], reducerActions = _b[1];
var _c = setupImmerReducerActions(this.config.immerReducers, this.state.getState), immerReducerActions$ = _c[0], immerReducerActions = _c[1];
this.triggerActions = tslib_1.__assign(tslib_1.__assign(tslib_1.__assign(tslib_1.__assign({}, effectActions), reducerActions), immerReducerActions), mapValues_1.default(this.config.defineActions, function (_a) {
var next = _a.next;
return next;
}));
var effectActionsWithTerminate$;
if (!flag_1.isSSREnabled()) {
effectActionsWithTerminate$ = effectActions$;
}
else {
effectActionsWithTerminate$ = effectActions$.pipe(operators_1.takeUntil(this.terminate$.pipe(operators_1.filter(function (action) { return action === null; }))));
}
this.subscription.add(effectActionsWithTerminate$.subscribe(function (action) {
_this.log(action);
_this.handleAction(action);
}));
this.subscription.add(reducerActions$.subscribe(function (action) {
_this.log(action);
_this.handleAction(action);
}));
this.subscription.add(immerReducerActions$.subscribe(function (action) {
_this.log(action);
_this.handleAction(action);
}));
}
Ikari.createAndBindAt = function (target, config) {
var createdIkari = this.getFrom(target);
if (createdIkari) {
return createdIkari;
}
else {
var ikari = new Ikari(target, config);
Reflect.defineMetadata(symbols_1.ikariSymbol, ikari, target);
return ikari;
}
};
Ikari.getFrom = function (target) {
return Reflect.getMetadata(symbols_1.ikariSymbol, target);
};
Ikari.prototype.destroy = function () {
this.subscription.unsubscribe();
this.triggerActions = {};
};
return Ikari;
}());
exports.Ikari = Ikari;
function setupEffectActions(effectActions, state$) {
var actions = {};
var effects = [];
Object.keys(effectActions).forEach(function (actionName) {
var payload$ = new rxjs_1.Subject();
actions[actionName] = function (payload) { return payload$.next(payload); };
var effect$ = effectActions[actionName](payload$, state$);
effects.push(effect$.pipe(operators_1.map(function (effectAction) { return ({
effectAction: effectAction,
originalActionName: actionName,
}); }), catchRxError()));
});
return [rxjs_1.merge.apply(void 0, effects), actions];
}
function setupReducerActions(reducerActions, getState) {
var actions = {};
var reducers = [];
Object.keys(reducerActions).forEach(function (actionName) {
var reducer$ = new rxjs_1.Subject();
reducers.push(reducer$);
var reducer = reducerActions[actionName];
actions[actionName] = function (params) {
var nextState = reducer(getState(), params);
reducer$.next({
reducerAction: { params: params, actionName: actionName, nextState: nextState },
originalActionName: actionName,
});
};
});
return [rxjs_1.merge.apply(void 0, reducers), actions];
}
function setupImmerReducerActions(immerReducerActions, getState) {
var actions = {};
var immerReducers = [];
Object.keys(immerReducerActions).forEach(function (actionName) {
var immerReducer$ = new rxjs_1.Subject();
immerReducers.push(immerReducer$);
var immerReducer = immerReducerActions[actionName];
actions[actionName] = function (params) {
var nextState = immer_1.default(getState(), function (draft) {
immerReducer(draft, params);
});
immerReducer$.next({
reducerAction: { params: params, actionName: actionName, nextState: nextState },
originalActionName: actionName,
});
};
});
return [rxjs_1.merge.apply(void 0, immerReducers), actions];
}