Socket
Socket
Sign inDemoInstall

ngrx-store-localstorage

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ngrx-store-localstorage - npm Package Compare versions

Comparing version 8.0.0 to 9.0.0

.circleci/config.yml

25

CHANGELOG.md
# Change Log
## 9.0.0
### Breaking changes
- Remove deprecated `localStorageSyncAndClean` function
### Features
- Allow `@ngrx/store` v9 as a peer dependency [#142](https://github.com/btroncone/ngrx-store-localstorage/pull/142)
- Add `mergeReducer` option to define the reducer to use to merge the rehydrated state from storage with the state from the ngrx store [#135](https://github.com/btroncone/ngrx-store-localstorage/pull/135)
## 8.0.0
### Potentially breaking changes
- Switched from lodash to deepmerge to keep bundle size small and avoid lodash security issues. This is intended to have no impact. However we cannot guarantee merging old state from localstorage with new state will function 100% the same. See [#126](https://github.com/btroncone/ngrx-store-localstorage/pull/126) for more info.
- Objects will now lose their function definitions when rehydrated. Using such was already against the [Redux way](https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state) but was previously supported.
### Features
- Angular Universal support [#127](https://github.com/btroncone/ngrx-store-localstorage/pull/127)
- Slightly reduced bundle size by avoiding lodash.merge
## 5.0.0 (2018-02-17)

@@ -11,2 +34,2 @@

- Upgrade @ngrx/store peer dependency to v5
- Upgrade @ngrx/store peer dependency to v5

3

dist/index.d.ts
export declare const dateReviver: (key: string, value: any) => any;
export declare const rehydrateApplicationState: (keys: any[], storage: Storage, storageKeySerializer: (key: string) => string, restoreDates: boolean) => any;
export declare const syncStateUpdate: (state: any, keys: any[], storage: Storage, storageKeySerializer: (key: string) => string, removeOnUndefined: boolean, syncCondition?: (state: any) => any) => void;
export declare const defaultMergeReducer: (state: any, rehydratedState: any, action: any) => any;
export declare const localStorageSync: (config: LocalStorageConfig) => (reducer: any) => (state: any, action: any) => any;
export declare const localStorageSyncAndClean: (keys: any[], rehydrate?: boolean, removeOnUndefined?: boolean) => (reducer: any) => any;
export interface LocalStorageConfig {

@@ -15,2 +15,3 @@ keys: any[];

checkStorageAvailability?: boolean;
mergeReducer?: (state: any, rehydratedState: any, action: any) => any;
}

@@ -10,3 +10,2 @@ "use strict";

};
var _this = this;
Object.defineProperty(exports, "__esModule", { value: true });

@@ -45,4 +44,4 @@ var deepmerge = require("deepmerge");

var reviver = restoreDates ? exports.dateReviver : dummyReviver;
var deserialize = undefined;
var decrypt = undefined;
var deserialize;
var decrypt;
if (typeof key === 'object') {

@@ -64,3 +63,3 @@ key = Object.keys(key)[0];

}
// Ensure that encrypt and decrypt functions are both presents
// Ensure that encrypt and decrypt functions are both present
if (curr[key].encrypt && curr[key].decrypt) {

@@ -118,5 +117,5 @@ if (typeof curr[key].encrypt === 'function' &&

var stateSlice = state[key];
var replacer = undefined;
var space = undefined;
var encrypt = undefined;
var replacer;
var space;
var encrypt;
if (typeof key === 'object') {

@@ -132,3 +131,3 @@ var name_1 = Object.keys(key)[0];

// if serialize function is not specified filter on fields if an array has been provided.
var filter = undefined;
var filter = void 0;
if (key[name_1].reduce) {

@@ -158,5 +157,5 @@ filter = key[name_1];

/*
Replacer and space arguments to pass to JSON.stringify.
If these fields don't exist, undefined will be passed.
*/
Replacer and space arguments to pass to JSON.stringify.
If these fields don't exist, undefined will be passed.
*/
replacer = key[name_1].replacer;

@@ -193,2 +192,13 @@ space = key[name_1].space;

};
// Default merge strategy is a full deep merge.
exports.defaultMergeReducer = function (state, rehydratedState, action) {
if ((action.type === INIT_ACTION || action.type === UPDATE_ACTION) && rehydratedState) {
var overwriteMerge = function (destinationArray, sourceArray, options) { return sourceArray; };
var options = {
arrayMerge: overwriteMerge
};
state = deepmerge(state, rehydratedState, options);
}
return state;
};
exports.localStorageSync = function (config) { return function (reducer) {

@@ -205,2 +215,7 @@ if (config.storage === undefined &&

}
// Use default merge reducer.
var mergeReducer = config.mergeReducer;
if (mergeReducer === undefined || typeof (mergeReducer) !== 'function') {
mergeReducer = exports.defaultMergeReducer;
}
var stateKeys = validateStateKeys(config.keys);

@@ -220,9 +235,5 @@ var rehydratedState = config.rehydrate

}
if ((action.type === INIT_ACTION || action.type === UPDATE_ACTION) && rehydratedState) {
var overwriteMerge = function (destinationArray, sourceArray, options) { return sourceArray; };
var options = {
arrayMerge: overwriteMerge
};
nextState = deepmerge(nextState, rehydratedState, options);
}
// Merge the store state with the rehydrated state using
// either a user-defined reducer or the default.
nextState = mergeReducer(nextState, rehydratedState, action);
nextState = reducer(nextState, action);

@@ -235,22 +246,2 @@ if (action.type !== INIT_ACTION) {

}; };
/*
@deprecated: Use localStorageSync(LocalStorageConfig)
Wraps localStorageSync functionality acepting the removeOnUndefined boolean parameter in order
to clean/remove the state from the browser on situations like state reset or logout.
Defines localStorage as default storage.
*/
exports.localStorageSyncAndClean = function (keys, rehydrate, removeOnUndefined) {
if (rehydrate === void 0) { rehydrate = false; }
if (removeOnUndefined === void 0) { removeOnUndefined = false; }
return function (reducer) {
var config = {
keys: keys,
rehydrate: rehydrate,
storage: localStorage,
removeOnUndefined: removeOnUndefined
};
return _this.localStorageSync(config);
};
};
//# sourceMappingURL=index.js.map
{
"name": "ngrx-store-localstorage",
"version": "8.0.0",
"version": "9.0.0",
"description": "State and local storage syncing for @ngrx/store",

@@ -35,3 +35,3 @@ "main": "./dist/index.js",

"peerDependencies": {
"@ngrx/store": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
"@ngrx/store": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
},

@@ -45,3 +45,3 @@ "devDependencies": {

"@types/jasmine": "^2.5.47",
"@types/node": "^7.0.18",
"@types/node": "^12.12.11",
"crypto-js": "^3.1.9-1",

@@ -63,2 +63,2 @@ "es6-promise": "^3.0.2",

}
}
}
# ngrx-store-localstorage
Simple syncing between ngrx store and local storage.
## Dependencies
`ngrx-store-localstorage` depends on [@ngrx/store](https://github.com/ngrx/store) and [Angular 2+](https://github.com/angular/angular).
## Usage
```bash
npm install ngrx-store-localstorage --save
```
**UPDATE FOR NGRX 4**
1. Wrap localStorageSync in an exported function.
2. Include in your meta-reducers array in `StoreModule.forRoot`.
```ts

@@ -43,9 +46,13 @@ import { NgModule } from '@angular/core';

## API
### `localStorageSync(config: LocalStorageConfig): Reducer`
Provide state (reducer) keys to sync with local storage. *Returns a meta-reducer*.
#### Arguments
* `config` An object that matches with the `LocalStorageConfig` interface, `keys` is the only required property.
### **LocalStorageConfig**
An interface defining the configuration attributes to bootstrap `localStorageSync`. The following are properties which compose `LocalStorageConfig`:

@@ -63,56 +70,29 @@ * `keys` (required) State keys to sync with local storage. The keys can be defined in two different formats:

* serialize: A function that takes a state object and returns a plain json object to pass to json.stringify.
* `serialize`: A function that takes a state object and returns a plain json object to pass to json.stringify.
* deserialize: A function that takes that takes the raw JSON from JSON.parse and builds a state object.
* `deserialize`: A function that takes that takes the raw JSON from JSON.parse and builds a state object.
* replacer: A replacer function as specified in the [JSON.stringify documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
* `replacer`: A replacer function as specified in the [JSON.stringify documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
* space: The space value to pass JSON.stringify.
* `space`: The space value to pass JSON.stringify.
* reviver: A reviver function as specified in the [JSON.parse documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
* `reviver`: A reviver function as specified in the [JSON.parse documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
* filter: An array of properties which should be synced (same format as the stand-alone array specified above).
* `filter`: An array of properties which should be synced (same format as the stand-alone array specified above).
* `encrypt`: A function that takes a state string and returns an encrypted version of that string.
e.g. `(state: string) => btoa(state)`
* `decrypt`: A function that takes a state string and returns a decrypted version of that string.
e.g. `(state: string) => atob(state)`
* `rehydrate` (optional) `boolean`: Pull initial state from local storage on startup, this will default to `false`.
* `storage` (optional) `Storage`: Specify an object that conforms to the [Storage interface](https://github.com/Microsoft/TypeScript/blob/master/lib/lib.dom.d.ts#L9708) to use, this will default to `localStorage`.
* `removeOnUndefined` (optional) `boolean`: Specify if the state is removed from the storage when the new value is undefined, this will default to `false`.
* `storageKeySerializer` (optional) `(key: string) => string`: Сustom serialize function for storage keys, used to avoid Storage conflicts.
* `storageKeySerializer` (optional) `(key: string) => string`: Custom serialize function for storage keys, used to avoid Storage conflicts.
* `restoreDates` \(*boolean? = true*): Restore serialized date objects. If you work directly with ISO date strings, set this option to `false`.
* `syncCondition` (optional) `(state) => boolean`: When set, sync to storage medium will only occur when this function returns a true boolean. Example: `(state) => state.config.syncToStorage` will check the state tree under config.syncToStorage and if true, it will sync to the storage. If undefined or false it will not sync to storage. Often useful for "remember me" options in login.
* `checkStorageAvailability` \(*boolean? = false*): Specify if the storage availability checking is expected, i.e. for server side rendering / Universal.
* `mergeReducer` (optional) `(state: any, rehydratedState: any, action: any) => any`: Defines the reducer to use to merge the rehydrated state from storage with the state from the ngrx store. If unspecified, defaults to performing a full deepmerge on an `INIT_ACTION` or an `UPDATE_ACTION`.
Usage: `localStorageSync({keys: ['todos', 'visibilityFilter'], storageKeySerializer: (key) => 'cool_' + key, ... })`. In this example `Storage` will use keys `cool_todos` and `cool_visibilityFilter` keys to store `todos` and `visibilityFilter` slices of state). The key itself is used by default - `(key) => key`.
---
### ~~`localStorageSyncAndClean(keys: any[], rehydrate: boolean = false, removeOnUndefined: boolean = false): Reducer`~~
**This function is deprecated and soon will be removed, please use _localStorageSync(LocalStorageConfig)_.**
A shorthand that wraps the functionalities of `localStorageSync` and asumes `localStorage` as the storage.
#### Arguments
* `keys` State keys to sync with local storage. The keys can be defined in two different formats:
* \(*string[]*): Array of strings representing the state (reducer) keys. Full state will be synced (e.g. `localStorageSync(['todos'])`).
* \(*object[]*): Array of objects where for each object the key represents the state key and the value represents custom serialize/deserialize options. This can be one of the following:
* An array of properties which should be synced. This allows for the partial state sync (e.g. `localStorageSync([{todos: ['name', 'status'] }, ... ])`).
* A reviver function as specified in the [JSON.parse documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
* An object with properties that specify one or more of the following:
* serialize: A function that takes a state object and returns a plain json object to pass to json.stringify.
* deserialize: A function that takes that takes the raw JSON from JSON.parse and builds a state object.
* replacer: A replacer function as specified in the [JSON.stringify documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
* space: The space value to pass JSON.stringify.
* reviver: A reviver function as specified in the [JSON.parse documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).
* filter: An array of properties which should be synced (same format as the stand-along array specified above).
* `rehydrateState` \(*boolean? = false*): Pull initial state from local storage on startup.
* `removeOnUndefined` \(*boolean? = false*): Specify if the state is removed from the storage when the new value is undefined.
* `checkStorageAvailability` \(*boolean? = false*): Specify if the storage availability checking is expected, i.e. for server side rendering / Universal.

@@ -7,2 +7,3 @@ declare var it, describe, expect;

const INIT_ACTION = '@ngrx/store/init';
import * as deepmerge from 'deepmerge';

@@ -490,2 +491,43 @@ // Very simple classes to test serialization options. They cover string, number, date, and nested classes

});
it('should enable a complex merge of rehydrated storage and state', () => {
const initialState = {
app: { app1: false, app2: [], app3: {} },
feature1: { slice11: false, slice12: [], slice13: {} },
feature2: { slice21: false, slice22: [], slice23: {} },
};
// A legit case where state is saved in chunks rather than as a single object
localStorage.setItem('feature1', JSON.stringify({ slice11: true, slice12: [1, 2] }));
localStorage.setItem('feature2', JSON.stringify({ slice21: true, slice22: [1, 2] }));
// Set up reducers
const reducer = (state = initialState, action) => state;
const mergeReducer = (state, rehydratedState, action) => {
// Perform a merge where we only want a single property from feature1
// but a deepmerge with feature2
return {
...state,
feature1: {
slice11: rehydratedState.feature1.slice11
},
feature2: deepmerge(state.feature2, rehydratedState.feature2)
}
}
const metaReducer = localStorageSync({keys: [
{'feature1': ['slice11', 'slice12']},
{'feature2': ['slice21', 'slice22']},
], rehydrate: true, mergeReducer});
const action = {type: INIT_ACTION};
// Resultant state should merge the rehydrated partial state and our initial state
const finalState = metaReducer(reducer)(initialState, action);
expect(finalState).toEqual({
app: { app1: false, app2: [], app3: {} },
feature1: { slice11: true },
feature2: { slice21: true, slice22: [1, 2], slice23: {} },
});
});
});

@@ -48,4 +48,4 @@ import * as deepmerge from 'deepmerge';

let reviver = restoreDates ? dateReviver : dummyReviver;
let deserialize = undefined;
let decrypt = undefined;
let deserialize;
let decrypt;

@@ -68,3 +68,3 @@ if (typeof key === 'object') {

// Ensure that encrypt and decrypt functions are both presents
// Ensure that encrypt and decrypt functions are both present
if (curr[key].encrypt && curr[key].decrypt) {

@@ -139,5 +139,5 @@ if (

let stateSlice = state[key];
let replacer = undefined;
let space = undefined;
let encrypt = undefined;
let replacer;
let space;
let encrypt;

@@ -154,3 +154,3 @@ if (typeof key === 'object') {

// if serialize function is not specified filter on fields if an array has been provided.
let filter = undefined;
let filter;
if (key[name].reduce) {

@@ -184,5 +184,5 @@ filter = key[name];

/*
Replacer and space arguments to pass to JSON.stringify.
If these fields don't exist, undefined will be passed.
*/
Replacer and space arguments to pass to JSON.stringify.
If these fields don't exist, undefined will be passed.
*/
replacer = key[name].replacer;

@@ -227,2 +227,17 @@ space = key[name].space;

// Default merge strategy is a full deep merge.
export const defaultMergeReducer = (state: any, rehydratedState: any, action: any) => {
if ((action.type === INIT_ACTION || action.type === UPDATE_ACTION) && rehydratedState) {
const overwriteMerge = (destinationArray, sourceArray, options) => sourceArray;
const options: deepmerge.Options = {
arrayMerge: overwriteMerge
};
state = deepmerge(state, rehydratedState, options);
}
return state;
};
export const localStorageSync = (config: LocalStorageConfig) => (

@@ -245,2 +260,9 @@ reducer: any

// Use default merge reducer.
let mergeReducer = config.mergeReducer;
if (mergeReducer === undefined || typeof(mergeReducer) !== 'function') {
mergeReducer = defaultMergeReducer;
}
const stateKeys = validateStateKeys(config.keys);

@@ -267,10 +289,6 @@ const rehydratedState = config.rehydrate

if ((action.type === INIT_ACTION || action.type === UPDATE_ACTION) && rehydratedState) {
const overwriteMerge = (destinationArray, sourceArray, options) => sourceArray;
const options: deepmerge.Options = {
arrayMerge: overwriteMerge
};
nextState = deepmerge(nextState, rehydratedState, options);
}
// Merge the store state with the rehydrated state using
// either a user-defined reducer or the default.
nextState = mergeReducer(nextState, rehydratedState, action);
nextState = reducer(nextState, action);

@@ -293,24 +311,2 @@

/*
@deprecated: Use localStorageSync(LocalStorageConfig)
Wraps localStorageSync functionality acepting the removeOnUndefined boolean parameter in order
to clean/remove the state from the browser on situations like state reset or logout.
Defines localStorage as default storage.
*/
export const localStorageSyncAndClean = (
keys: any[],
rehydrate: boolean = false,
removeOnUndefined: boolean = false
) => (reducer: any) => {
let config: LocalStorageConfig = {
keys: keys,
rehydrate: rehydrate,
storage: localStorage,
removeOnUndefined: removeOnUndefined
};
return this.localStorageSync(config);
};
export interface LocalStorageConfig {

@@ -325,2 +321,3 @@ keys: any[];

checkStorageAvailability?: boolean;
mergeReducer?: (state: any, rehydratedState: any, action: any) => any;
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc