@larscom/ngrx-store-storagesync
Version:
Highly configurable state sync library between localStorage/sessionStorage and @ngrx/store (Angular)
1 lines • 14.4 kB
Source Map (JSON)
{"version":3,"file":"larscom-ngrx-store-storagesync.mjs","sources":["../../../projects/ngrx-store-storagesync/src/lib/actions.ts","../../../projects/ngrx-store-storagesync/src/lib/util.ts","../../../projects/ngrx-store-storagesync/src/lib/rehydrate-state.ts","../../../projects/ngrx-store-storagesync/src/lib/sync-with-storage.ts","../../../projects/ngrx-store-storagesync/src/lib/storage-sync.ts","../../../projects/ngrx-store-storagesync/src/larscom-ngrx-store-storagesync.ts"],"sourcesContent":["export const INIT_ACTION = '@ngrx/store/init'\nexport const INIT_ACTION_EFFECTS = '@ngrx/effects/init'\nexport const UPDATE_ACTION = '@ngrx/store/update-reducers'\n","export const isObjectLike = (value: any): boolean => typeof value === 'object' && value !== null\n\nexport const isPlainObject = (value: any) => value?.constructor === Object\n\nexport const isPlainObjectAndEmpty = (value: any): boolean => isPlainObject(value) && Object.keys(value).length === 0\n","import { IStorageSyncOptions } from './storage-sync-options'\nimport { isPlainObjectAndEmpty } from './util'\n\nconst dateMatcher = /(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})/\n\n/**\n * @internal Restores the resolved state from a storage location\n */\nexport const rehydrateState = <T>({\n storage,\n storageKeySerializer,\n features,\n storageError\n}: IStorageSyncOptions<T>): T | undefined => {\n const rehydratedState = features.reduce((acc, curr) => {\n const { storageKeySerializerForFeature, stateKey, deserialize, storageForFeature } = curr\n\n const key = storageKeySerializerForFeature\n ? storageKeySerializerForFeature(stateKey)\n : storageKeySerializer!(stateKey)\n\n try {\n const featureState = storageForFeature ? storageForFeature.getItem(key) : storage.getItem(key)\n return featureState\n ? {\n ...acc,\n ...{\n [stateKey]: deserialize\n ? deserialize(featureState)\n : JSON.parse(featureState, (_: string, value: any) => {\n return dateMatcher.test(String(value)) && !isNaN(Date.parse(value)) ? new Date(value) : value\n })\n }\n }\n : acc\n } catch (e) {\n if (storageError) {\n storageError(e)\n } else {\n throw e\n }\n }\n }, Object()) as T\n\n return !isPlainObjectAndEmpty(rehydratedState) ? rehydratedState : undefined\n}\n","import { IStorageSyncOptions } from './storage-sync-options'\nimport { clone } from 'ramda'\nimport { isObjectLike, isPlainObject, isPlainObjectAndEmpty } from './util'\n\n/**\n * @internal Remove empty objects\n */\nconst removeEmptyObjects = (object: any): any => {\n for (const key in object) {\n if (!isPlainObject(object[key])) {\n continue\n }\n\n if (!isPlainObjectAndEmpty(object[key])) {\n removeEmptyObjects(object[key])\n }\n\n if (isPlainObjectAndEmpty(object[key])) {\n delete object[key]\n }\n }\n\n return object\n}\n\n/**\n * @internal Exclude properties from featureState\n */\nconst excludePropsFromState = <T>(featureState: T[keyof T], excludeKeys?: string[]): T[keyof T] => {\n if (!excludeKeys || !excludeKeys.length) {\n return featureState\n }\n\n const keyPairs = excludeKeys.map((key) => ({\n leftKey: key.split('.')[0],\n rightKey: key.split('.')[1]\n }))\n\n for (const key in featureState) {\n const keyPair = keyPairs.find((pair) => pair.leftKey === key)\n const leftKey = keyPair?.leftKey\n const rightKey = keyPair?.rightKey\n\n if (isObjectLike(featureState[key])) {\n if (leftKey && rightKey) {\n excludePropsFromState(featureState[key], [...excludeKeys, rightKey])\n } else if (leftKey) {\n delete featureState[key]\n } else {\n excludePropsFromState(featureState[key], excludeKeys)\n }\n } else if (leftKey) {\n delete featureState[key]\n }\n }\n\n return removeEmptyObjects(featureState)\n}\n\n/**\n * @internal Sync state with storage\n */\nexport const syncWithStorage = <T>(\n state: T,\n { features, storage, storageKeySerializer, storageError }: IStorageSyncOptions<T>\n): void => {\n features\n .filter(({ stateKey }) => state[stateKey as keyof T] !== undefined)\n .filter(({ stateKey, shouldSync }) => (shouldSync ? shouldSync(state[stateKey as keyof T], state) : true))\n .forEach(({ stateKey, excludeKeys, storageKeySerializerForFeature, serialize, storageForFeature }) => {\n const featureStateClone = clone(state[stateKey as keyof T])\n const featureState = excludePropsFromState(featureStateClone, excludeKeys)\n\n if (isPlainObjectAndEmpty(featureState)) {\n return\n }\n\n const key = storageKeySerializerForFeature\n ? storageKeySerializerForFeature(stateKey)\n : storageKeySerializer!(stateKey)\n\n const value = serialize ? serialize(featureState) : JSON.stringify(featureState)\n\n try {\n if (storageForFeature) {\n storageForFeature.setItem(key, value)\n } else {\n storage.setItem(key, value)\n }\n } catch (e) {\n if (storageError) {\n storageError(e)\n } else {\n throw e\n }\n }\n })\n}\n","import { Action } from '@ngrx/store'\nimport { mergeDeepRight } from 'ramda'\nimport { INIT_ACTION, INIT_ACTION_EFFECTS, UPDATE_ACTION } from './actions'\nimport { rehydrateState } from './rehydrate-state'\nimport { IStorageSyncOptions } from './storage-sync-options'\nimport { syncWithStorage } from './sync-with-storage'\n\n/**\n * The StorageSync Meta Reducer for @ngrx/store.\n *\n * @param options The configuration for the meta reducer\n *\n * Check out github for more information.\n * @see https://github.com/larscom/ngrx-store-storagesync\n *\n * @returns the meta reducer function\n */\nexport const storageSync =\n <T>(options: IStorageSyncOptions<T>) =>\n (reducer: (state: T | undefined, action: Action) => T): ((state: T | undefined, action: Action) => T) => {\n const config: IStorageSyncOptions<T> = {\n rehydrate: true,\n storageKeySerializer: (key: string) => key,\n rehydrateStateMerger: (nextState, rehydratedState) => mergeDeepRight<any, any>(nextState, rehydratedState),\n ...options\n }\n\n const { rehydrate, rehydrateStateMerger } = config\n\n const shouldRehydrate = rehydrate! && isCompatibleVersion(config)\n const rehydratedState = shouldRehydrate ? rehydrateState(config) : undefined\n\n return (state: T | undefined, action: Action): T => {\n const nextState = action.type === INIT_ACTION ? reducer(state, action) : ({ ...state } as T)\n const shouldMerge = rehydratedState !== undefined && [INIT_ACTION, UPDATE_ACTION].includes(action.type)\n const mergedState = reducer(shouldMerge ? rehydrateStateMerger!(nextState, rehydratedState) : nextState, action)\n\n if (![INIT_ACTION, INIT_ACTION_EFFECTS].includes(action.type)) {\n updateNewVersion(config)\n syncWithStorage(mergedState, config)\n }\n\n return mergedState\n }\n }\n\n/**\n * @internal Load version from storage to see if it matches the\n * version from the config\n *\n * @examples\n * Storage.version = 1 and Config.version = 2 --> incompatible, skip hydration\n *\n * Storage.version = undefined and Config.version = 1 --> incompatible, skip hydration\n *\n * Storage.version = 1 and Config.version = undefined --> unknown, incompatible, skip hydration\n *\n * Storage.version = 1 and Config.version = 1 --> compatible, hydrate\n */\nconst isCompatibleVersion = <T>({\n storage,\n storageError,\n storageKeySerializer,\n version,\n versionKey = 'ngrx-store-storagesync.version'\n}: IStorageSyncOptions<T>): boolean => {\n const key = storageKeySerializer!(versionKey)\n try {\n const item = storage!.getItem(key)\n if (item == null && version == null) {\n return true\n }\n\n return Number(item) === version\n } catch (e) {\n if (storageError) {\n storageError(e)\n } else {\n throw e\n }\n }\n\n return false\n}\n\n/**\n * @internal Update Storage with new config version\n * Remove item from Storage if version from config is undefined\n */\nconst updateNewVersion = <T>({\n storage,\n storageError,\n storageKeySerializer,\n version,\n versionKey = 'ngrx-store-storagesync.version'\n}: IStorageSyncOptions<T>): void => {\n const key = storageKeySerializer!(versionKey)\n try {\n if (version) {\n storage!.setItem(key, String(version))\n } else {\n storage!.removeItem(key)\n }\n } catch (e) {\n if (storageError) {\n storageError(e)\n } else {\n throw e\n }\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}