UNPKG

ayanami

Version:
187 lines (186 loc) 7.82 kB
import { __assign } from "tslib"; import { merge, Subject, Subscription, NEVER } from 'rxjs'; import { map, catchError, takeUntil, filter } from 'rxjs/operators'; import mapValues from 'lodash/mapValues'; import produce from 'immer'; import { createState, getEffectActionFactories, getOriginalFunctions } from './utils'; import { logStateAction } from '../redux-devtools-extension'; import { ikariSymbol } from './symbols'; import { TERMINATE_ACTION } from '../ssr/terminate'; import { isSSREnabled } from '../ssr/flag'; function catchRxError() { return catchError(function (err) { console.error(err); return NEVER; }); } export function combineWithIkari(ayanami) { var ikari = Ikari.getFrom(ayanami); if (ikari) { return ikari; } else { var _a = getOriginalFunctions(ayanami), effects = _a.effects, reducers = _a.reducers, immerReducers = _a.immerReducers, defineActions = _a.defineActions; Object.assign(ayanami, mapValues(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: getEffectActionFactories(ayanami), }); } } export function destroyIkariFrom(ayanami) { var ikari = Ikari.getFrom(ayanami); if (ikari) { ikari.destroy(); Reflect.deleteMetadata(ikariSymbol, ayanami); } } 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 = createState(this.config.defaultState); this.effectActionFactories = this.config.effectActionFactories; this.triggerActions = {}; this.subscription = new Subscription(); // @internal this.terminate$ = new Subject(); this.log = function (_a) { var originalActionName = _a.originalActionName, effectAction = _a.effectAction, reducerAction = _a.reducerAction; if (effectAction && effectAction !== TERMINATE_ACTION) { logStateAction(_this.config.nameForLog, { params: effectAction.params, actionName: originalActionName + "/\uD83D\uDC49" + effectAction.ayanami.constructor.name + "/\uFE0F" + effectAction.actionName, }); } if (reducerAction) { 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_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 = __assign(__assign(__assign(__assign({}, effectActions), reducerActions), immerReducerActions), mapValues(this.config.defineActions, function (_a) { var next = _a.next; return next; })); var effectActionsWithTerminate$; if (!isSSREnabled()) { effectActionsWithTerminate$ = effectActions$; } else { effectActionsWithTerminate$ = effectActions$.pipe(takeUntil(this.terminate$.pipe(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(ikariSymbol, ikari, target); return ikari; } }; Ikari.getFrom = function (target) { return Reflect.getMetadata(ikariSymbol, target); }; Ikari.prototype.destroy = function () { this.subscription.unsubscribe(); this.triggerActions = {}; }; return Ikari; }()); export { Ikari }; function setupEffectActions(effectActions, state$) { var actions = {}; var effects = []; Object.keys(effectActions).forEach(function (actionName) { var payload$ = new Subject(); actions[actionName] = function (payload) { return payload$.next(payload); }; var effect$ = effectActions[actionName](payload$, state$); effects.push(effect$.pipe(map(function (effectAction) { return ({ effectAction: effectAction, originalActionName: actionName, }); }), catchRxError())); }); return [merge.apply(void 0, effects), actions]; } function setupReducerActions(reducerActions, getState) { var actions = {}; var reducers = []; Object.keys(reducerActions).forEach(function (actionName) { var reducer$ = new 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 [merge.apply(void 0, reducers), actions]; } function setupImmerReducerActions(immerReducerActions, getState) { var actions = {}; var immerReducers = []; Object.keys(immerReducerActions).forEach(function (actionName) { var immerReducer$ = new Subject(); immerReducers.push(immerReducer$); var immerReducer = immerReducerActions[actionName]; actions[actionName] = function (params) { var nextState = produce(getState(), function (draft) { immerReducer(draft, params); }); immerReducer$.next({ reducerAction: { params: params, actionName: actionName, nextState: nextState }, originalActionName: actionName, }); }; }); return [merge.apply(void 0, immerReducers), actions]; }