UNPKG

@jbt/ng-rx

Version:

Configurable ngrx

817 lines (792 loc) 21.3 kB
import { Subscriber, merge, isObservable, of } from 'rxjs'; import { mergeAll, filter, concatMap, concatAll, mergeMap, map } from 'rxjs/operators'; import { Repository, ObjectUtils } from '@jbt/utils'; import { combineReducers, createSelector, select, StoreModule, Store } from '@ngrx/store'; import { NgModule } from '@angular/core'; import { EffectsModule, Actions, EffectSources } from '@ngrx/effects'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @enum {string} */ const EFFECT_TYPE = { ACTION: 'action', SEQUENCE: 'sequence', PARALLEL: 'parallel', }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const ERRORS = { HEADER: ` MergeHotStreamHandlerArraySubscriber Error. `, NOT_A_FUNCTION: ` Supplied handler ignored: It is not a function `, NOT_AN_OBSERVABLE: ` Supplied handler ignored: It does not return an observable ` }; class MergeHotStreamHandlerArraySubscriber extends Subscriber { /** * @param {?} sub * @param {?} effects */ constructor(sub, effects) { super(sub); this._handlers = []; this._handlers = effects || this._handlers; } /** * @param {?} value * @return {?} */ _next(value) { /** @type {?} */ const inner$ = merge(this._handlers .filter((/** * @param {?} handler * @return {?} */ (handler) => { /** @type {?} */ const condition = typeof handler === 'function'; if (!condition) { console.warn(ERRORS.HEADER + ERRORS.NOT_A_FUNCTION, handler); } return condition; })) .filter((/** * @param {?} handler * @return {?} */ (handler) => { /** @type {?} */ const condition = isObservable(handler(value)); if (!condition) { console.warn(ERRORS.HEADER + ERRORS.NOT_AN_OBSERVABLE, handler); } return condition; })) .map((/** * @param {?} handler * @return {?} */ (handler) => { return handler(value); }))).pipe(mergeAll()); inner$.subscribe({ next: (/** * @param {?} v * @return {?} */ (v) => { this.destination.next(v); }) }); } } if (false) { /** * @type {?} * @private */ MergeHotStreamHandlerArraySubscriber.prototype._handlers; } /** @type {?} */ const mergeHotStreamHandlerArray = (/** * @param {?} handlers * @return {?} */ handlers => (/** * @param {?} source * @return {?} */ source => source.lift({ /** * @param {?} sub * @param {?} s * @return {?} */ call(sub, s) { s.subscribe(new MergeHotStreamHandlerArraySubscriber(sub, handlers)); } }))); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * *************************************************** * * EffectsConfigurator * * **************************************************** */ class EffectsConfigurator { /** * @param {?} effectsRepository * @param {?} actions$ * @param {?} store */ constructor(effectsRepository, actions$, store) { this._setupMethodMap = { [EFFECT_TYPE.SEQUENCE]: this._setUpSequentialEffect, [EFFECT_TYPE.PARALLEL]: this._setUpParallelEffect, [EFFECT_TYPE.ACTION]: this._setUpActionEffect }; this._effects = []; this._effectsRepository = effectsRepository; this._effect = actions$.pipe(mergeHotStreamHandlerArray(this._effects), filter((/** * @param {?} action * @return {?} */ action => this._isAction(action)))); this._effect.subscribe((/** * @param {?} action * @return {?} */ (action) => { store.dispatch(action); })); } /** * @param {?=} effectsConfig * @return {?} */ addEffects(effectsConfig = []) { effectsConfig.forEach((/** * @param {?} config * @return {?} */ config => { /** @type {?} */ const method = this._setupMethodMap[config.type].call(this, config); this._effects.push(method); })); } /** * @private * @param {?} action * @return {?} */ _isAction(action) { return action && action.type && (typeof action.type === 'string'); } /** * @private * @param {?} config * @return {?} */ _setUpSequentialEffect(config) { return (/** * @param {?} action * @return {?} */ (action) => of(action).pipe(filter((/** * @param {?} action * @return {?} */ action => this._filterAction(action, config))), concatMap((/** * @param {?} action * @return {?} */ action => config.handlers.map((/** * @param {?} handler * @return {?} */ handler => { /** @type {?} */ const handlerFn = this._getHandler(handler, config); return handlerFn(action, config); })))), concatAll())); } /** * @private * @param {?} config * @return {?} */ _setUpParallelEffect(config) { return (/** * @param {?} action * @return {?} */ action => of(action).pipe(filter((/** * @param {?} action * @return {?} */ action => this._filterAction(action, config))), mergeMap((/** * @param {?} action * @return {?} */ action => config.handlers.map((/** * @param {?} handler * @return {?} */ handler => { /** @type {?} */ const handlerFn = this._getHandler(handler, config); return handlerFn(action, config); })))), mergeAll())); } /** * @private * @param {?} config * @return {?} */ _setUpActionEffect(config) { return (/** * @param {?} action * @return {?} */ action => of(action).pipe(filter((/** * @param {?} action * @return {?} */ action => this._filterAction(action, config))), map((/** * @param {?} action * @return {?} */ action => { return { type: config.result, payload: action['payload'] }; })))); } /** * @private * @param {?} action * @param {?} effectsConfig * @return {?} */ _filterAction(action, effectsConfig) { /** @type {?} */ const isCause = effectsConfig.causes.indexOf(action.type) > -1; /** @type {?} */ const isWildcard = effectsConfig.causes.indexOf('*') > -1; return isWildcard || isCause; } /** * @private * @param {?} handler * @param {?} config * @return {?} */ _getHandler(handler, config) { return (typeof handler === 'function') ? handler : this._effectsRepository.get(handler); } } if (false) { /** * @type {?} * @private */ EffectsConfigurator.prototype._setupMethodMap; /** * @type {?} * @private */ EffectsConfigurator.prototype._effectsRepository; /** * @type {?} * @private */ EffectsConfigurator.prototype._effect; /** * @type {?} * @private */ EffectsConfigurator.prototype._effects; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class EffectsRepository extends Repository { constructor() { super({ id: 'EffectsRepository', fallbackKey: 'default' }); this.addByMap({ default: (/** * @return {?} */ () => of({ type: 'VOID' })) }); } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @record */ function ReducerSingleConfiguration() { } if (false) { /** @type {?} */ ReducerSingleConfiguration.prototype.id; /** @type {?|undefined} */ ReducerSingleConfiguration.prototype.initialState; /** @type {?|undefined} */ ReducerSingleConfiguration.prototype.handlers; } /** * @record */ function ReducerGroupConfiguration() { } if (false) { /** @type {?} */ ReducerGroupConfiguration.prototype.id; /** @type {?} */ ReducerGroupConfiguration.prototype.children; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class ReducersRepository extends Repository { constructor() { super({ id: 'ReducersRepository', fallbackKey: 'default' }); this.addByMap({ default: (/** * @param {?} state * @return {?} */ state => state) }); } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class ReducersConfigurator { /** * @param {?} store * @param {?} reducersRepository */ constructor(store, reducersRepository) { this._config = {}; this._store = store; this._reducersRepository = reducersRepository; } /** * @param {?} config * @return {?} */ addReducers(config) { this._config[config.id] = (this._config[config.id]) ? ObjectUtils.mergeTrees(this._config[config.id], config) : config; Object.keys(this._config).forEach((/** * @param {?} key * @return {?} */ key => this._addReducer(this._config[key]))); } /** * @private * @param {?} reducerConfig * @return {?} */ _addReducer(reducerConfig) { this._store.addReducer(reducerConfig.id, this._createReducerFn(reducerConfig)); } /** * @private * @param {?} config * @return {?} */ _createReducerFn(config) { return (config.children) ? this._createReducersByConfig(config.children) : (/** * @param {?} state * @param {?} action * @return {?} */ (state, action) => this._mainReducer(state, action, config)); } /** * @private * @param {?=} config * @return {?} */ _createReducersByConfig(config = []) { /** @type {?} */ const self = this; return combineReducers(config.reduce((/** * @param {?} reducers * @param {?} item * @return {?} */ (reducers, item) => { reducers[item.id] = self._createReducerFn(item); return reducers; }), {})); } /** * @param {?} state * @param {?} action * @param {?} config * @return {?} */ _mainReducer(state, action, config) { if (!state) { return config.initialState; } config.handlers = config.handlers || {}; /** @type {?} */ const handler = this._getReducerHandlers(config.handlers[action.type]); return handler(state, action); } /** * @private * @param {?} handler * @return {?} */ _getReducerHandlers(handler) { return (typeof handler === 'function') ? handler : this._reducersRepository.get(handler); } } if (false) { /** * @type {?} * @private */ ReducersConfigurator.prototype._store; /** * @type {?} * @private */ ReducersConfigurator.prototype._reducersRepository; /** * @type {?} * @private */ ReducersConfigurator.prototype._config; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class DefaultReducerHandlers { /** * @param {?} state * @param {?} action * @return {?} */ static set(state, action) { return action.payload; } /** * @param {?} state * @param {?} action * @return {?} */ static override(state, action) { return Object.assign({}, state, action.payload); } /** * @param {?} state * @param {?} action * @return {?} */ static noop(state, action) { return state; } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class Selector { /** * @param {?} path * @return {?} */ static selectByPath(path) { /** @type {?} */ const slices = path.split('.'); /** @type {?} */ const sel = slices .slice(1) .reduce((/** * @param {?} acc * @param {?} current * @return {?} */ (acc, current) => createSelector(acc, (/** * @param {?} state * @return {?} */ state => state[current]))), createSelector((/** * @param {?} state * @return {?} */ state => state[slices[0]]), (/** * @param {?} state * @return {?} */ state => state))); return select(sel); } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class State { /** * @param {?} store * @param {?} reducersConfigurator * @param {?} effectsConfigurator * @param {?} reducersRepository * @param {?} effectsRepository */ constructor(store, reducersConfigurator, effectsConfigurator, reducersRepository, effectsRepository) { this._store = store; this._reducersConfigurator = reducersConfigurator; this._effectsConfigurator = effectsConfigurator; this._reducersRepository = reducersRepository; this._effectsRepository = effectsRepository; } /** * @param {?} config * @return {?} */ configure(config) { if (config.state) { this.configureReducers(config.state); } if (config.effects) { this.configureEffects(config.effects); } } /** * @param {?} config * @return {?} */ configureReducers(config) { this._reducersConfigurator.addReducers(config); } /** * @param {?} config * @return {?} */ configureEffects(config) { this._effectsConfigurator.addEffects(config); } /** * @param {?} reducersMap * @return {?} */ addReducerHandlers(reducersMap) { this._reducersRepository.addByMap(reducersMap); } /** * @param {?} effectsMap * @return {?} */ addEffectHandlers(effectsMap) { this._effectsRepository.addByMap(effectsMap); } /** * @param {?} type * @param {?=} payload * @return {?} */ dispatch(type, payload) { this._store.dispatch({ type: type, payload: payload }); } /** * @param {?} path * @return {?} */ select(path) { return this._store.pipe(Selector.selectByPath(path)); } } if (false) { /** * @type {?} * @private */ State.prototype._store; /** * @type {?} * @private */ State.prototype._reducersConfigurator; /** * @type {?} * @private */ State.prototype._reducersRepository; /** * @type {?} * @private */ State.prototype._effectsConfigurator; /** * @type {?} * @private */ State.prototype._effectsRepository; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class ProviderFactory { /** * @param {?} store * @param {?} reducersRepository * @return {?} */ static createReducersConfigurator(store, reducersRepository) { return new ReducersConfigurator(store, reducersRepository); } /** * @param {?} effectsRepository * @param {?} actions$ * @param {?} store * @return {?} */ static createEffectsConfigurator(effectsRepository, actions$, store) { return new EffectsConfigurator(effectsRepository, actions$, store); } } class InternalsModule { } InternalsModule.decorators = [ { type: NgModule, args: [{ imports: [ StoreModule.forRoot({}), EffectsModule.forRoot([]) ], providers: [{ provide: ReducersConfigurator, useFactory: ProviderFactory.createReducersConfigurator, deps: [ Store, ReducersRepository ] }, { provide: EffectsConfigurator, useFactory: ProviderFactory.createEffectsConfigurator, deps: [ EffectsRepository, Actions, Store, EffectSources, ] }, EffectsRepository, ReducersRepository, ], exports: [ StoreModule ] },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @param {?} store * @param {?} reducer * @param {?} effects * @param {?} reducersRepository * @param {?} effectsRepository * @return {?} */ function createState(store, reducer, effects, reducersRepository, effectsRepository) { return new State(store, reducer, effects, reducersRepository, effectsRepository); } class StateModule { /** * @return {?} */ static forRoot() { return { ngModule: StateModule, providers: [{ provide: State, useFactory: createState, deps: [ Store, ReducersConfigurator, EffectsConfigurator, ReducersRepository, EffectsRepository ] }] }; } /** * @return {?} */ static forChild() { return { ngModule: StateModule, providers: [] }; } } StateModule.decorators = [ { type: NgModule, args: [{ imports: [InternalsModule], },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { EFFECT_TYPE, State, StateModule, createState as ɵa, EffectsConfigurator as ɵb, EffectsRepository as ɵc, ReducersRepository as ɵd, ReducersConfigurator as ɵe, ProviderFactory as ɵf, InternalsModule as ɵg }; //# sourceMappingURL=jbt-ng-rx.js.map