UNPKG

@datorama/akita

Version:

State Management Tailored-Made for JS Applications

1,923 lines (1,889 loc) 207 kB
import { __assign, __values, __spread, __read, __rest, __extends, __decorate, __metadata } from 'tslib'; import { BehaviorSubject, of, Subject, ReplaySubject, from, isObservable, combineLatest, merge, EMPTY } from 'rxjs'; import { tap, distinctUntilChanged, map, filter, switchMap, skip, delay, take, debounceTime, pairwise, auditTime } from 'rxjs/operators'; /** * @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 */ // @internal /** * @template T * @param {?} value * @return {?} */ function isArray(value) { return Array.isArray(value); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @template T * @param {?} arr * @return {?} */ function isEmpty(arr) { if (isArray(arr)) { return arr.length === 0; } return false; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @template E * @param {?} entities * @param {?} idKey * @param {?} preAddEntity * @return {?} */ function toEntitiesObject(entities, idKey, preAddEntity) { var e_1, _a; /** @type {?} */ var acc = { entities: {}, ids: [] }; try { for (var entities_1 = __values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) { var entity = entities_1_1.value; // evaluate the middleware first to support dynamic ids /** @type {?} */ var current = preAddEntity(entity); acc.entities[current[idKey]] = current; acc.ids.push(current[idKey]); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (entities_1_1 && !entities_1_1.done && (_a = entities_1.return)) _a.call(entities_1); } finally { if (e_1) throw e_1.error; } } return acc; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @template E * @param {?} entities * @param {?} id * @return {?} */ function hasEntity(entities, id) { return entities.hasOwnProperty(id); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @template E * @param {?} state * @return {?} */ function hasActiveState(state) { return state.hasOwnProperty('active'); } // @internal /** * @param {?} active * @return {?} */ function isMultiActiveState(active) { return isArray(active); } // @internal /** * @template E * @param {?} __0 * @return {?} */ function resolveActiveEntity(_a) { var active = _a.active, ids = _a.ids, entities = _a.entities; if (isMultiActiveState(active)) { return getExitingActives(active, ids); } if (hasEntity(entities, active) === false) { return null; } return active; } // @internal /** * @param {?} currentActivesIds * @param {?} newIds * @return {?} */ function getExitingActives(currentActivesIds, newIds) { /** @type {?} */ var filtered = currentActivesIds.filter((/** * @param {?} id * @return {?} */ function (id) { return newIds.indexOf(id) > -1; })); /** Return the same reference if nothing has changed */ if (filtered.length === currentActivesIds.length) { return currentActivesIds; } return filtered; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @template Entity * @param {?} state * @return {?} */ function isEntityState(state) { return state.entities && state.ids; } // @internal /** * @template E * @param {?} entities * @param {?} preAddEntity * @return {?} */ function applyMiddleware(entities, preAddEntity) { var e_1, _a; /** @type {?} */ var mapped = {}; try { for (var _b = __values(Object.keys(entities)), _c = _b.next(); !_c.done; _c = _b.next()) { var id = _c.value; mapped[id] = preAddEntity(entities[id]); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } return mapped; } // @internal /** * @template S, E * @param {?} __0 * @return {?} */ function setEntities(_a) { var state = _a.state, entities = _a.entities, idKey = _a.idKey, preAddEntity = _a.preAddEntity, isNativePreAdd = _a.isNativePreAdd; /** @type {?} */ var newEntities; /** @type {?} */ var newIds; if (isArray(entities)) { /** @type {?} */ var resolve = toEntitiesObject(entities, idKey, preAddEntity); newEntities = resolve.entities; newIds = resolve.ids; } else if (isEntityState(entities)) { newEntities = isNativePreAdd ? entities.entities : applyMiddleware(entities.entities, preAddEntity); newIds = entities.ids; } else { // it's an object newEntities = isNativePreAdd ? entities : applyMiddleware(entities, preAddEntity); newIds = Object.keys(newEntities).map((/** * @param {?} id * @return {?} */ function (id) { return (isNaN((/** @type {?} */ (id))) ? id : Number(id)); })); } /** @type {?} */ var newState = __assign({}, state, { entities: newEntities, ids: newIds, loading: false }); if (hasActiveState(state)) { newState.active = resolveActiveEntity((/** @type {?} */ (newState))); } return newState; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal var // @internal AkitaError = /** @class */ (function (_super) { __extends(AkitaError, _super); function AkitaError(message) { return _super.call(this, message) || this; } return AkitaError; }(Error)); // @internal /** * @param {?} name * @param {?} className * @return {?} */ function assertStoreHasName(name, className) { if (!name) { console.error("@StoreConfig({ name }) is missing in " + className); } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var currentAction = { type: null, entityIds: null, skip: false }; /** @type {?} */ var customActionActive = false; /** * @return {?} */ function resetCustomAction() { customActionActive = false; } // public API for custom actions. Custom action always wins /** * @param {?} type * @param {?=} entityIds * @return {?} */ function logAction(type, entityIds) { setAction(type, entityIds); customActionActive = true; } /** * @param {?} type * @param {?=} entityIds * @return {?} */ function setAction(type, entityIds) { if (customActionActive === false) { currentAction.type = type; currentAction.entityIds = entityIds; } } /** * @param {?=} skip * @return {?} */ function setSkipAction(skip$$1) { if (skip$$1 === void 0) { skip$$1 = true; } currentAction.skip = skip$$1; } /** * @param {?} action * @param {?=} entityIds * @return {?} */ function action(action, entityIds) { return (/** * @param {?} target * @param {?} propertyKey * @param {?} descriptor * @return {?} */ function (target, propertyKey, descriptor) { /** @type {?} */ var originalMethod = descriptor.value; descriptor.value = (/** * @param {...?} args * @return {?} */ function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } logAction(action, entityIds); return originalMethod.apply(this, args); }); return descriptor; }); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** @type {?} */ var transactionFinished = new Subject(); // @internal /** @type {?} */ var transactionInProcess = new BehaviorSubject(false); // @internal /** @type {?} */ var transactionManager = { activeTransactions: 0, batchTransaction: null }; // @internal /** * @return {?} */ function startBatch() { if (!isTransactionInProcess()) { transactionManager.batchTransaction = new Subject(); } transactionManager.activeTransactions++; transactionInProcess.next(true); } // @internal /** * @return {?} */ function endBatch() { if (--transactionManager.activeTransactions === 0) { transactionManager.batchTransaction.next(true); transactionManager.batchTransaction.complete(); transactionInProcess.next(false); transactionFinished.next(true); } } // @internal /** * @return {?} */ function isTransactionInProcess() { return transactionManager.activeTransactions > 0; } // @internal /** * @return {?} */ function commit() { return transactionManager.batchTransaction ? transactionManager.batchTransaction.asObservable() : of(true); } /** * A logical transaction. * Use this transaction to optimize the dispatch of all the stores. * The following code will update the store, BUT emits only once * * \@example * applyTransaction(() => { * this.todosStore.add(new Todo(1, title)); * this.todosStore.add(new Todo(2, title)); * }); * * @template T * @param {?} action * @param {?=} thisArg * @return {?} */ function applyTransaction(action$$1, thisArg) { if (thisArg === void 0) { thisArg = undefined; } startBatch(); try { return action$$1.apply(thisArg); } finally { logAction('@Transaction'); endBatch(); } } /** * A logical transaction. * Use this transaction to optimize the dispatch of all the stores. * * The following code will update the store, BUT emits only once. * * \@example * \@transaction * addTodos() { * this.todosStore.add(new Todo(1, title)); * this.todosStore.add(new Todo(2, title)); * } * * * @return {?} */ function transaction() { return (/** * @param {?} target * @param {?} propertyKey * @param {?} descriptor * @return {?} */ function (target, propertyKey, descriptor) { /** @type {?} */ var originalMethod = descriptor.value; descriptor.value = (/** * @param {...?} args * @return {?} */ function () { var _this = this; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return applyTransaction((/** * @return {?} */ function () { return originalMethod.apply(_this, args); }), this); }); return descriptor; }); } /** * * RxJS custom operator that wraps the callback inside transaction * * \@example * * return http.get().pipe( * withTransaction(response > { * store.setActive(1); * store.update(); * store.updateEntity(1, {}); * }) * ) * * @template T * @param {?} transactionFn * @return {?} */ function withTransaction(transactionFn) { return (/** * @param {?} source * @return {?} */ function (source) { return source.pipe(tap((/** * @param {?} value * @return {?} */ function (value) { return applyTransaction((/** * @return {?} */ function () { return transactionFn(value); })); }))); }); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @param {?} o * @return {?} */ function deepFreeze(o) { Object.freeze(o); /** @type {?} */ var oIsFunction = typeof o === 'function'; /** @type {?} */ var hasOwnProp = Object.prototype.hasOwnProperty; Object.getOwnPropertyNames(o).forEach((/** * @param {?} prop * @return {?} */ function (prop) { if (hasOwnProp.call(o, prop) && (oIsFunction ? prop !== 'caller' && prop !== 'callee' && prop !== 'arguments' : true) && o[prop] !== null && (typeof o[prop] === 'object' || typeof o[prop] === 'function') && !Object.isFrozen(o[prop])) { deepFreeze(o[prop]); } })); return o; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var configKey = 'akitaConfig'; /** * @param {?} metadata * @return {?} */ function StoreConfig(metadata) { return (/** * @param {?} constructor * @return {?} */ function (constructor) { constructor[configKey] = { idKey: 'id' }; for (var i = 0, keys = Object.keys(metadata); i < keys.length; i++) { /** @type {?} */ var key = keys[i]; /* name is preserved read only key */ if (key === 'name') { constructor[configKey]['storeName'] = metadata[key]; } else { constructor[configKey][key] = metadata[key]; } } }); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var CONFIG = { resettable: false }; /** * @param {?} config * @return {?} */ function akitaConfig(config) { CONFIG = __assign({}, CONFIG, config); } // @internal /** * @return {?} */ function getAkitaConfig() { return CONFIG; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @param {?} value * @return {?} */ function toBoolean(value) { return value != null && "" + value !== 'false'; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @param {?} value * @return {?} */ function isPlainObject(value) { return toBoolean(value) && value.constructor.name === 'Object'; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @param {?} value * @return {?} */ function isFunction(value) { return typeof value === 'function'; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** @type {?} */ var $$deleteStore = new Subject(); // @internal /** @type {?} */ var $$addStore = new ReplaySubject(50, 5000); // @internal /** @type {?} */ var $$updateStore = new Subject(); // @internal /** * @param {?} storeName * @return {?} */ function dispatchDeleted(storeName) { $$deleteStore.next(storeName); } // @internal /** * @param {?} storeName * @return {?} */ function dispatchAdded(storeName) { $$addStore.next(storeName); } // @internal /** * @param {?} storeName * @return {?} */ function dispatchUpdate(storeName) { $$updateStore.next(storeName); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var __DEV__ = true; /** * @return {?} */ function enableAkitaProdMode() { __DEV__ = false; } // @internal /** * @return {?} */ function isDev() { return __DEV__; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var isBrowser = typeof window !== 'undefined'; /** @type {?} */ var isNativeScript = typeof global !== 'undefined' && typeof ((/** @type {?} */ (global))).__runtimeVersion !== 'undefined'; // @internal /** @type {?} */ var isNotBrowser = !isBrowser && !isNativeScript; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** @type {?} */ var __stores__ = {}; // @internal /** @type {?} */ var __queries__ = {}; if (isBrowser && isDev()) { ((/** @type {?} */ (window))).$$stores = __stores__; ((/** @type {?} */ (window))).$$queries = __queries__; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * * Store for managing any type of data * * \@example * * export interface SessionState { * token: string; * userDetails: UserDetails * } * * export function createInitialState(): SessionState { * return { * token: '', * userDetails: null * }; * } * * \@StoreConfig({ name: 'session' }) * export class SessionStore extends Store<SessionState> { * constructor() { * super(createInitialState()); * } * } * @template S */ var /** * * Store for managing any type of data * * \@example * * export interface SessionState { * token: string; * userDetails: UserDetails * } * * export function createInitialState(): SessionState { * return { * token: '', * userDetails: null * }; * } * * \@StoreConfig({ name: 'session' }) * export class SessionStore extends Store<SessionState> { * constructor() { * super(createInitialState()); * } * } * @template S */ Store = /** @class */ (function () { function Store(initialState, options) { if (options === void 0) { options = {}; } this.options = options; this.inTransaction = false; this.cache = { active: new BehaviorSubject(false), ttl: null }; this.onInit((/** @type {?} */ (initialState))); } /** * Set the loading state * * @example * * store.setLoading(true) * */ /** * Set the loading state * * \@example * * store.setLoading(true) * * @param {?=} loading * @return {?} */ Store.prototype.setLoading = /** * Set the loading state * * \@example * * store.setLoading(true) * * @param {?=} loading * @return {?} */ function (loading) { if (loading === void 0) { loading = false; } if (loading !== ((/** @type {?} */ (this._value()))).loading) { isDev() && setAction('Set Loading'); this._setState((/** * @param {?} state * @return {?} */ function (state) { return ((/** @type {?} */ (__assign({}, state, { loading: loading })))); })); } }; /** * * Set whether the data is cached * * @example * * store.setHasCache(true) * store.setHasCache(false) * store.setHasCache(true, { restartTTL: true }) * */ /** * * Set whether the data is cached * * \@example * * store.setHasCache(true) * store.setHasCache(false) * store.setHasCache(true, { restartTTL: true }) * * @param {?} hasCache * @param {?=} options * @return {?} */ Store.prototype.setHasCache = /** * * Set whether the data is cached * * \@example * * store.setHasCache(true) * store.setHasCache(false) * store.setHasCache(true, { restartTTL: true }) * * @param {?} hasCache * @param {?=} options * @return {?} */ function (hasCache, options) { var _this = this; if (options === void 0) { options = { restartTTL: false }; } if (hasCache !== this.cache.active.value) { this.cache.active.next(hasCache); } if (options.restartTTL) { /** @type {?} */ var ttlConfig = this.cacheConfig && this.cacheConfig.ttl; if (ttlConfig) { if (this.cache.ttl !== null) { clearTimeout(this.cache.ttl); } this.cache.ttl = (/** @type {?} */ (setTimeout((/** * @return {?} */ function () { return _this.setHasCache(false); }), ttlConfig))); } } }; /** * Set the error state * * @example * * store.setError({text: 'unable to load data' }) * */ /** * Set the error state * * \@example * * store.setError({text: 'unable to load data' }) * * @template T * @param {?} error * @return {?} */ Store.prototype.setError = /** * Set the error state * * \@example * * store.setError({text: 'unable to load data' }) * * @template T * @param {?} error * @return {?} */ function (error) { if (error !== ((/** @type {?} */ (this._value()))).error) { isDev() && setAction('Set Error'); this._setState((/** * @param {?} state * @return {?} */ function (state) { return ((/** @type {?} */ (__assign({}, state, { error: error })))); })); } }; // @internal // @internal /** * @template R * @param {?} project * @return {?} */ Store.prototype._select = // @internal /** * @template R * @param {?} project * @return {?} */ function (project) { return this.store.asObservable().pipe(map(project), distinctUntilChanged()); }; // @internal // @internal /** * @return {?} */ Store.prototype._value = // @internal /** * @return {?} */ function () { return this.storeValue; }; // @internal // @internal /** * @return {?} */ Store.prototype._cache = // @internal /** * @return {?} */ function () { return this.cache.active; }; Object.defineProperty(Store.prototype, "config", { // @internal get: // @internal /** * @return {?} */ function () { return this.constructor[configKey] || {}; }, enumerable: true, configurable: true }); Object.defineProperty(Store.prototype, "storeName", { // @internal get: // @internal /** * @return {?} */ function () { return ((/** @type {?} */ (this.config))).storeName || ((/** @type {?} */ (this.options))).storeName || this.options.name; }, enumerable: true, configurable: true }); Object.defineProperty(Store.prototype, "deepFreeze", { // @internal get: // @internal /** * @return {?} */ function () { return this.config.deepFreezeFn || this.options.deepFreezeFn || deepFreeze; }, enumerable: true, configurable: true }); Object.defineProperty(Store.prototype, "cacheConfig", { // @internal get: // @internal /** * @return {?} */ function () { return this.config.cache || this.options.cache; }, enumerable: true, configurable: true }); Object.defineProperty(Store.prototype, "resettable", { // @internal get: // @internal /** * @return {?} */ function () { return this.config.resettable || this.options.resettable; }, enumerable: true, configurable: true }); // @internal // @internal /** * @param {?} newStateFn * @param {?=} _dispatchAction * @return {?} */ Store.prototype._setState = // @internal /** * @param {?} newStateFn * @param {?=} _dispatchAction * @return {?} */ function (newStateFn, _dispatchAction) { if (_dispatchAction === void 0) { _dispatchAction = true; } this.storeValue = __DEV__ ? this.deepFreeze(newStateFn(this._value())) : newStateFn(this._value()); if (!this.store) { this.store = new BehaviorSubject(this.storeValue); return; } if (isTransactionInProcess()) { this.handleTransaction(); return; } this.dispatch(this.storeValue, _dispatchAction); }; /** * * Reset the current store back to the initial value * * @example * * store.reset() * */ /** * * Reset the current store back to the initial value * * \@example * * store.reset() * * @return {?} */ Store.prototype.reset = /** * * Reset the current store back to the initial value * * \@example * * store.reset() * * @return {?} */ function () { var _this = this; if (this.isResettable()) { isDev() && setAction('Reset'); this._setState((/** * @return {?} */ function () { return Object.assign({}, _this._initialState); })); this.setHasCache(false); } else { isDev() && console.warn("You need to enable the reset functionality"); } }; /** * @param {?} stateOrCallback * @return {?} */ Store.prototype.update = /** * @param {?} stateOrCallback * @return {?} */ function (stateOrCallback) { var _this = this; isDev() && setAction('Update'); this._setState((/** * @param {?} state * @return {?} */ function (state) { /** @type {?} */ var newState = isFunction(stateOrCallback) ? stateOrCallback(state) : stateOrCallback; /** @type {?} */ var merged = _this.akitaPreUpdate(state, (/** @type {?} */ (__assign({}, state, newState)))); return isPlainObject(state) ? merged : new ((/** @type {?} */ (state))).constructor(merged); })); }; /** * @param {?} newOptions * @return {?} */ Store.prototype.updateStoreConfig = /** * @param {?} newOptions * @return {?} */ function (newOptions) { this.options = __assign({}, this.options, newOptions); }; // @internal // @internal /** * @param {?} _ * @param {?} nextState * @return {?} */ Store.prototype.akitaPreUpdate = // @internal /** * @param {?} _ * @param {?} nextState * @return {?} */ function (_, nextState) { return nextState; }; /** * @return {?} */ Store.prototype.ngOnDestroy = /** * @return {?} */ function () { this.destroy(); }; /** * * Destroy the store * * @example * * store.destroy() * */ /** * * Destroy the store * * \@example * * store.destroy() * * @return {?} */ Store.prototype.destroy = /** * * Destroy the store * * \@example * * store.destroy() * * @return {?} */ function () { if (isNotBrowser) return; if (!((/** @type {?} */ (window))).hmrEnabled && this === __stores__[this.storeName]) { delete __stores__[this.storeName]; dispatchDeleted(this.storeName); this.setHasCache(false); this.cache.active.complete(); } }; /** * @private * @param {?} initialState * @return {?} */ Store.prototype.onInit = /** * @private * @param {?} initialState * @return {?} */ function (initialState) { __stores__[this.storeName] = this; this._setState((/** * @return {?} */ function () { return initialState; })); dispatchAdded(this.storeName); if (this.isResettable()) { this._initialState = initialState; } isDev() && assertStoreHasName(this.storeName, this.constructor.name); }; /** * @private * @param {?} state * @param {?=} _dispatchAction * @return {?} */ Store.prototype.dispatch = /** * @private * @param {?} state * @param {?=} _dispatchAction * @return {?} */ function (state, _dispatchAction) { if (_dispatchAction === void 0) { _dispatchAction = true; } this.store.next(state); if (_dispatchAction) { dispatchUpdate(this.storeName); resetCustomAction(); } }; /** * @private * @return {?} */ Store.prototype.watchTransaction = /** * @private * @return {?} */ function () { var _this = this; commit().subscribe((/** * @return {?} */ function () { _this.inTransaction = false; _this.dispatch(_this._value()); })); }; /** * @private * @return {?} */ Store.prototype.isResettable = /** * @private * @return {?} */ function () { if (this.resettable === false) { return false; } return this.resettable || getAkitaConfig().resettable; }; /** * @private * @return {?} */ Store.prototype.handleTransaction = /** * @private * @return {?} */ function () { if (!this.inTransaction) { this.watchTransaction(); this.inTransaction = true; } }; return Store; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @param {?} v * @return {?} */ function isNil(v) { return v === null || v === undefined; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @param {?} value * @return {?} */ function isObject(value) { /** @type {?} */ var type = typeof value; return value != null && (type == 'object' || type == 'function'); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @param {?} idOrOptions * @param {?} ids * @param {?} currentActive * @return {?} */ function getActiveEntities(idOrOptions, ids, currentActive) { /** @type {?} */ var result; if (isArray(idOrOptions)) { result = idOrOptions; } else { if (isObject(idOrOptions)) { if (isNil(currentActive)) return; ((/** @type {?} */ (idOrOptions))) = Object.assign({ wrap: true }, idOrOptions); /** @type {?} */ var currentIdIndex = ids.indexOf((/** @type {?} */ (currentActive))); if (((/** @type {?} */ (idOrOptions))).prev) { /** @type {?} */ var isFirst = currentIdIndex === 0; if (isFirst && !((/** @type {?} */ (idOrOptions))).wrap) return; result = isFirst ? ids[ids.length - 1] : ((/** @type {?} */ (ids[currentIdIndex - 1]))); } else if (((/** @type {?} */ (idOrOptions))).next) { /** @type {?} */ var isLast = ids.length === currentIdIndex + 1; if (isLast && !((/** @type {?} */ (idOrOptions))).wrap) return; result = isLast ? ids[0] : ((/** @type {?} */ (ids[currentIdIndex + 1]))); } } else { if (idOrOptions === currentActive) return; result = (/** @type {?} */ (idOrOptions)); } } return result; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @template S, E * @param {?} __0 * @return {?} */ function addEntities(_a) { var state = _a.state, entities = _a.entities, idKey = _a.idKey, _b = _a.options, options = _b === void 0 ? {} : _b, preAddEntity = _a.preAddEntity; var e_1, _c; /** @type {?} */ var newEntities = {}; /** @type {?} */ var newIds = []; /** @type {?} */ var hasNewEntities = false; try { for (var entities_1 = __values(entities), entities_1_1 = entities_1.next(); !entities_1_1.done; entities_1_1 = entities_1.next()) { var entity = entities_1_1.value; if (hasEntity(state.entities, entity[idKey]) === false) { // evaluate the middleware first to support dynamic ids /** @type {?} */ var current = preAddEntity(entity); /** @type {?} */ var entityId = current[idKey]; newEntities[entityId] = current; if (options.prepend) newIds.unshift(entityId); else newIds.push(entityId); hasNewEntities = true; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (entities_1_1 && !entities_1_1.done && (_c = entities_1.return)) _c.call(entities_1); } finally { if (e_1) throw e_1.error; } } return hasNewEntities ? { newState: __assign({}, state, { entities: __assign({}, state.entities, newEntities), ids: options.prepend ? __spread(newIds, state.ids) : __spread(state.ids, newIds) }), newIds: newIds } : null; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @template T * @param {?} value * @return {?} */ function coerceArray(value) { if (isNil(value)) { return []; } return Array.isArray(value) ? value : [value]; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @template S, E * @param {?} __0 * @return {?} */ function removeEntities(_a) { var state = _a.state, ids = _a.ids; var e_1, _b; if (isNil(ids)) return removeAllEntities(state); /** @type {?} */ var entities = state.entities; /** @type {?} */ var newEntities = {}; try { for (var _c = __values(state.ids), _d = _c.next(); !_d.done; _d = _c.next()) { var id = _d.value; if (ids.includes(id) === false) { newEntities[id] = entities[id]; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_d && !_d.done && (_b = _c.return)) _b.call(_c); } finally { if (e_1) throw e_1.error; } } /** @type {?} */ var newState = __assign({}, state, { entities: newEntities, ids: state.ids.filter((/** * @param {?} current * @return {?} */ function (current) { return ids.includes(current) === false; })) }); if (hasActiveState(state)) { newState.active = resolveActiveEntity(newState); } return newState; } // @internal /** * @template S * @param {?} state * @return {?} */ function removeAllEntities(state) { return __assign({}, state, { entities: {}, ids: [], active: isMultiActiveState(state.active) ? [] : null }); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** @type {?} */ var getInitialEntitiesState = (/** * @return {?} */ function () { return ((/** @type {?} */ ({ entities: {}, ids: [], loading: true, error: null }))); }); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @param {?} val * @return {?} */ function isDefined(val) { return isNil(val) === false; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @template S, E * @param {?} __0 * @return {?} */ function updateEntities(_a) { var state = _a.state, ids = _a.ids, idKey = _a.idKey, newStateOrFn = _a.newStateOrFn, preUpdateEntity = _a.preUpdateEntity; var e_1, _b; /** @type {?} */ var updatedEntities = {}; /** @type {?} */ var isUpdatingIdKey = false; /** @type {?} */ var idToUpdate; try { for (var ids_1 = __values(ids), ids_1_1 = ids_1.next(); !ids_1_1.done; ids_1_1 = ids_1.next()) { var id = ids_1_1.value; // if the entity doesn't exist don't do anything if (hasEntity(state.entities, id) === false) { continue; } /** @type {?} */ var oldEntity = state.entities[id]; /** @type {?} */ var newState = isFunction(newStateOrFn) ? newStateOrFn(oldEntity) : newStateOrFn; /** @type {?} */ var isIdChanged = newState.hasOwnProperty(idKey) && newState[idKey] !== oldEntity[idKey]; /** @type {?} */ var newEntity = void 0; idToUpdate = id; if (isIdChanged) { isUpdatingIdKey = true; idToUpdate = newState[idKey]; } /** @type {?} */ var merged = __assign({}, oldEntity, newState); if (isPlainObject(oldEntity)) { newEntity = merged; } else { /** * In case that new state is class of it's own, there's * a possibility that it will be different than the old * class. * For example, Old state is an instance of animal class * and new state is instance of person class. * To avoid run over new person class with the old animal * class we check if the new state is a class of it's own. * If so, use it. Otherwise, use the old state class */ if (isPlainObject(newState)) { newEntity = new ((/** @type {?} */ (oldEntity))).constructor(merged); } else { newEntity = new ((/** @type {?} */ (newState))).constructor(merged); } } updatedEntities[idToUpdate] = preUpdateEntity(oldEntity, newEntity); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (ids_1_1 && !ids_1_1.done && (_b = ids_1.return)) _b.call(ids_1); } finally { if (e_1) throw e_1.error; } } /** @type {?} */ var updatedIds = state.ids; /** @type {?} */ var stateEntities = state.entities; if (isUpdatingIdKey) { var _c = __read(ids, 1), id_1 = _c[0]; var _d = state.entities, _e = id_1, deletedEntity = _d[_e], rest = __rest(_d, [typeof _e === "symbol" ? _e : _e + ""]); stateEntities = rest; updatedIds = state.ids.map((/** * @param {?} current * @return {?} */ function (current) { return (current === id_1 ? idToUpdate : current); })); } return __assign({}, state, { entities: __assign({}, stateEntities, updatedEntities), ids: updatedIds }); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @internal /** * @param {?} value * @return {?} */ function isUndefined(value) { return value === undefined; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @enum {number} */ var EntityActions = { Set: 0, Add: 1, Update: 2, Remove: 3, }; EntityActions[EntityActions.Set] = 'Set'; EntityActions[EntityActions.Add] = 'Add'; EntityActions[EntityActions.Update] = 'Update'; EntityActions[EntityActions.Remove] = 'Remove'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var DEFAULT_ID_KEY = 'id'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * * Store for managing a collection of entities * * \@example * * export interface WidgetsState extends EntityState<Widget> { } * * \@StoreConfig({ name: 'widgets' }) * export class WidgetsStore extends EntityStore<WidgetsState> { * constructor() { * super(); * } * } * * * @template S, EntityType, IDType */ var EntityStore = /** @class */ (function (_super) { __extends(EntityStore, _super); function EntityStore(initialState, options) { if (initialState === void 0) { initialState = {}; } if (options === void 0) { options = {}; } var _this = _super.call(this, __assign({}, getInitialEntitiesState(), initialState), options) || this; _this.options = options; _this.entityActions = new Subject(); return _this; } Object.defineProperty(EntityStore.prototype, "selectEntityAction$", { // @internal get: // @internal /** * @return {?} */ function () { return this.entityActions.asObservable(); }, enumerable: true, configurable: true }); Object.defineProperty(EntityStore.prototype, "idKey", { // @internal get: // @internal /** * @return {?} */ function () { return ((/** @type {?} */ (this.config))).idKey || this.options.idKey || DEFAULT_ID_KEY; }, enumerable: true, configurable: true }); /** * * Replace current collection with provided collection * * @example * * this.store.set([Entity, Entity]) * this.store.set({ids: [], entities: {}}) * this.store.set({ 1: {}, 2: {}}) * */ /** * * Replace current collection with provided collection * * \@example * * this.store.set([Entity, Entity]) * this.store.set({ids: [], entities: {}}) * this.store.set({ 1: {}, 2: {}}) * * @param {?} entities * @return {?} */ EntityStore.prototype.set = /** * * Replace current collection with provided collection * * \@example * * this.store.set([Entity, Entity]) * this.store.set({ids: [], entities: {}}) * this.store.set({ 1: {}, 2: {}}) * * @param {?} entities * @return {?} */ function (entities) { var _this = this; if (isNil(entities)) return; isDev() && setAction('Set Entity'); /** @type {?} */ var isNativePreAdd = this.akitaPreAddEntity === EntityStore.prototype.akitaPreAddEntity; this._setState((/** * @param {?} state * @return {?} */ function (state) { return setEntities({ state: state, entities: entities, idKey: _this.idKey, preAddEntity: _this.akitaPreAddEntity, isNativePreAdd: isNativePreAdd }); })); this.setHasCache(true, { restartTTL: true }); if (this.hasInitialUIState()) { this.handleUICreation(); } this.entityActions.next({ type: EntityActions.Set, ids: this.ids }); }; /** * Add entities * * @example * * this.store.add([Entity, Entity]) * this.store.add(Entity) * this.store.add(Entity, { prepend: true }) * * this.store.add(Entity, { loading: false }) */ /** * Add entities * * \@example * * this.store.add([Entity, Entity]) * this.store.add(Entity) * this.store.add(Entity, { prepend: true }) * * this.store.add(Entity, { loading: false }) * @param {?} entities * @param {?=} options * @return {?} */ EntityStore.prototype.add = /** * Add entities * * \@example * * this.store.add([Entity, Entity]) * this.store.add(Entity) * this.store.add(Entity, { prepend: true }) * * this.store.add(Entity, { loading: false }) * @param {?} entities * @param {?=} options * @return {?} */ function (entities, options) { if (options === void 0) { options = { loading: false }; } /** @type {?} */ var collection = coerceArray(entities); if (isEmpty(collection)) return; /** @type {?} */ var data = addEntities({ state: this._value(), preAddEntity: this.akitaPreAddEntity, entities: collection, idKey: this.idKey, options: options }); if (data) { isDev() && setAction('Add Entity'); data.newState.loading = options.loading; this._setState((/** * @return {?} */ function () { return data.newState; })); if (this.hasInitialUIState()) { this.handleUICreation(true); } this.entityActions.next({ type: EntityActions.Add, ids: data.newIds }); } }; /** * @param {?} idsOrFnOrState * @param {?=} newStateOrFn * @return {?} */ EntityStore.prototype.update = /** * @param {?} idsOrFnOrState * @param {?=} newStateOrFn * @return {?} */ function (idsOrFnOrState, newStateOrFn) { var _this = this; if (isUndefined(newStateOrFn)) { _super.prototype.update.call(this, (/** @type {?} */ (idsOrFnOrState))); return; } /** @type {?} */ var ids = []; if (isFunction(idsOrFnOrState)) { // We need to filter according the predicate function ids = this.ids.filter((/** * @param {?} id * @return {?} */ function (id) { return ((/** @type {?} */ (idsOrFnOrState)))(_this.entities[id]); })); } else { // If it's nil we want all of them ids = isNil(idsOrFnOrState) ? this.ids : coerceArray((/** @type {?} */ (idsOrFnOrState))); } if (isEmpty(ids)) return; isDev() && setAction('Update Entity', ids); this._setState((/** * @param {?} state * @return {?} */ function (state) { return updateEntities({ idKey: _this.idKey, ids: ids, preUpdateEntity: _this.akitaPreUpdateEntity, state: state, newStateOrFn: newStateOrFn }); })); this.entityActions.next({ type: EntityActions.Update, ids: ids }); }; /** * * Create or update * * @example * * store.upsert(1, { active: true }) * store.upsert([2, 3], { active: true }) * store.upsert([2, 3], entity => ({ isOpen: !entity.isOpen})) * */ /** * * Create or update * * \@example * * store.upsert(1, { active: true }) * store.upsert([2, 3], { active: true }) * store.upsert([2, 3], entity => ({ isOpen: !entity.isOpen})) * * @param {?} ids * @param {?} newState * @param {?=} options * @return {?} */ EntityStore.prototype.upsert = /** * * Create or update * * \@example * * store.upsert(1, { active: true }) * store.upsert([2, 3], { active: true }) * store.upsert([2, 3], entity => ({ isOpen: !entity.isOpen})) * * @param {?} ids * @param {?} newState * @param {?=} options * @return {?} */ function (ids, newState, options) { var _this = this; if (options === void 0) { options = {}; } /** @type {?} */ var toArray = coerceArray(ids); /** @type {?} */ var predicate = (/** * @param {?} isUpdate * @return {?} */ function (isUpdate) { return (/** * @param {?} id * @return {?} */ function (id) { return hasEntity(_this