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 0.2.4 to 0.3.0

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) => 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) => void;

@@ -11,3 +11,4 @@ export declare const localStorageSync: (config: LocalStorageConfig) => (reducer: any) => (state: any, action: any) => any;

removeOnUndefined?: boolean;
restoreDates?: boolean;
storageKeySerializer?: (key: string) => string;
}

@@ -8,3 +8,3 @@ "use strict";

exports.dateReviver = function (key, value) {
if (typeof value === 'string' && (detectDate.test(value))) {
if (typeof value === 'string' && detectDate.test(value)) {
return new Date(value);

@@ -14,2 +14,3 @@ }

};
var dummyReviver = function (key, value) { return value; };
var validateStateKeys = function (keys) {

@@ -21,5 +22,5 @@ return keys.map(function (key) {

}
if (typeof (attr) !== 'string') {
throw new TypeError("localStorageSync Unknown Parameter Type: "
+ ("Expected type of string, got " + typeof attr));
if (typeof attr !== 'string') {
throw new TypeError("localStorageSync Unknown Parameter Type: " +
("Expected type of string, got " + typeof attr));
}

@@ -29,6 +30,6 @@ return key;

};
exports.rehydrateApplicationState = function (keys, storage, storageKeySerializer) {
exports.rehydrateApplicationState = function (keys, storage, storageKeySerializer, restoreDates) {
return keys.reduce(function (acc, curr) {
var key = curr;
var reviver = exports.dateReviver;
var reviver = restoreDates ? exports.dateReviver : dummyReviver;
var deserialize = undefined;

@@ -54,3 +55,4 @@ var decrypt = undefined;

if (curr[key].encrypt && curr[key].decrypt) {
if (typeof (curr[key].encrypt) === 'function' && typeof (curr[key].decrypt) === 'function') {
if (typeof curr[key].encrypt === 'function' &&
typeof curr[key].decrypt === 'function') {
decrypt = curr[key].decrypt;

@@ -73,3 +75,3 @@ }

}
var isObjectRegex = new RegExp('\{|\\[');
var isObjectRegex = new RegExp('{|\\[');
var raw = stateSlice;

@@ -79,3 +81,5 @@ if (isObjectRegex.test(stateSlice.charAt(0))) {

}
return Object.assign({}, acc, (_a = {}, _a[key] = deserialize ? deserialize(raw) : raw, _a));
return Object.assign({}, acc, (_a = {},
_a[key] = deserialize ? deserialize(raw) : raw,
_a));
}

@@ -95,3 +99,3 @@ return acc;

stateSlice = state[name_1];
if (typeof (stateSlice) !== 'undefined' && key[name_1]) {
if (typeof stateSlice !== 'undefined' && key[name_1]) {
// use serialize function if specified.

@@ -102,2 +106,3 @@ if (key[name_1].serialize) {

else {
// if serialize function is not specified filter on fields if an array has been provided.
var filter = undefined;

@@ -118,3 +123,3 @@ if (key[name_1].reduce) {

if (key[name_1].encrypt && key[name_1].decrypt) {
if (typeof (key[name_1].encrypt) === 'function') {
if (typeof key[name_1].encrypt === 'function') {
encrypt = key[name_1].encrypt;

@@ -129,5 +134,5 @@ }

/*
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;

@@ -138,9 +143,13 @@ space = key[name_1].space;

}
if (typeof (stateSlice) !== 'undefined') {
if (typeof stateSlice !== 'undefined') {
try {
if (encrypt) {
// ensure that a string message is passed
stateSlice = encrypt(typeof stateSlice === 'string' ? stateSlice : JSON.stringify(stateSlice, replacer, space));
stateSlice = encrypt(typeof stateSlice === 'string'
? stateSlice
: JSON.stringify(stateSlice, replacer, space));
}
storage.setItem(storageKeySerializer(key), typeof stateSlice === 'string' ? stateSlice : JSON.stringify(stateSlice, replacer, space));
storage.setItem(storageKeySerializer(key), typeof stateSlice === 'string'
? stateSlice
: JSON.stringify(stateSlice, replacer, space));
}

@@ -151,3 +160,3 @@ catch (e) {

}
else if (typeof (stateSlice) === 'undefined' && removeOnUndefined) {
else if (typeof stateSlice === 'undefined' && removeOnUndefined) {
try {

@@ -169,10 +178,15 @@ storage.removeItem(storageKeySerializer(key));

}
if (config.restoreDates === undefined) {
config.restoreDates = true;
}
var stateKeys = validateStateKeys(config.keys);
var rehydratedState = config.rehydrate ? exports.rehydrateApplicationState(stateKeys, config.storage, config.storageKeySerializer) : undefined;
var rehydratedState = config.rehydrate
? exports.rehydrateApplicationState(stateKeys, config.storage, config.storageKeySerializer, config.restoreDates)
: undefined;
return function (state, action) {
if (state === void 0) { state = rehydratedState; }
/*
Handle case where state is rehydrated AND initial state is supplied.
Any additional state supplied will override rehydrated state for the given key.
*/
Handle case where state is rehydrated AND initial state is supplied.
Any additional state supplied will override rehydrated state for the given key.
*/
if (action.type === INIT_ACTION && rehydratedState) {

@@ -179,0 +193,0 @@ state = Object.assign({}, state, rehydratedState);

{
"name": "ngrx-store-localstorage",
"version": "0.2.4",
"version": "0.3.0",
"description": "State and local storage syncing for @ngrx/store",

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

},
"keywords": [
"redux",
"ngrx",
"store",
"localstorage",
"rxjs"
],
"keywords": ["redux", "ngrx", "store", "localstorage", "rxjs"],
"author": "Brian Troncone",

@@ -30,0 +24,0 @@ "license": "MIT",

@@ -72,8 +72,9 @@ # ngrx-store-localstorage

* filter: An array of properties which should be synced (same format as the stand-along array specified above).
* filter: An array of properties which should be synced (same format as the stand-alone array specified above).
* `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 to use, this will default to `localStorage`.
* `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.
* `restoreDates` \(*boolean? = true*): Restore serialized date objects. If you work directly with ISO date strings, set this option to `false`.
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`.

@@ -80,0 +81,0 @@

@@ -86,3 +86,3 @@ declare var beforeEachProviders, it, describe, expect, inject;

3.14159,
new Date('1968-11-16T12:30:00'),
new Date('1968-11-16T12:30:00Z'),
new TypeB('Nested Class'));

@@ -126,3 +126,3 @@

let finalState: any = rehydrateApplicationState(['state'], s, skr);
let finalState: any = rehydrateApplicationState(['state'], s, skr, true);
expect(JSON.stringify(finalState)).toEqual(initialStateJson);

@@ -143,3 +143,3 @@

const finalState: any = rehydrateApplicationState(['state'], s, skr);
const finalState: any = rehydrateApplicationState(['state'], s, skr, true);
expect(finalState.state).toEqual(primitiveStr);

@@ -164,3 +164,3 @@ });

let finalState: any = rehydrateApplicationState(keys, s, skr);
let finalState: any = rehydrateApplicationState(keys, s, skr, true);
expect(JSON.stringify(finalState)).toEqual(JSON.stringify({ state: t1Filtered }));

@@ -182,3 +182,3 @@

let finalState: any = rehydrateApplicationState(keys, s, skr);
let finalState: any = rehydrateApplicationState(keys, s, skr, true);
expect(JSON.stringify(finalState)).toEqual(JSON.stringify(initialState));

@@ -199,3 +199,3 @@ expect(finalState.state instanceof TypeA).toBeTruthy();

let finalState: any = rehydrateApplicationState(keys, s, skr);
let finalState: any = rehydrateApplicationState(keys, s, skr, true);
expect(JSON.stringify(finalState)).toEqual(JSON.stringify(initialState));

@@ -220,3 +220,3 @@ expect(finalState.state instanceof TypeA).toBeTruthy();

let finalState: any = rehydrateApplicationState(keys, s, skr);
let finalState: any = rehydrateApplicationState(keys, s, skr, true);
expect(JSON.stringify(finalState)).toEqual(JSON.stringify({ filtered: t1Filtered }));

@@ -240,3 +240,3 @@

let finalState: any = rehydrateApplicationState(keys, s, skr);
let finalState: any = rehydrateApplicationState(keys, s, skr, true);
expect(JSON.stringify(finalState)).toEqual(JSON.stringify({ replacer: t1Filtered }));

@@ -265,3 +265,3 @@

let finalState: any = rehydrateApplicationState(keys, s, skr);
let finalState: any = rehydrateApplicationState(keys, s, skr, true);

@@ -284,3 +284,3 @@ expect(JSON.stringify(finalState)).toEqual('{"replacer":{"astring":"Testing","adate":"1968-11-16T12:30:00.000Z","anumber":3.14159}}');

let finalState: any = rehydrateApplicationState(keys, s, skr);
let finalState: any = rehydrateApplicationState(keys, s, skr, true);
expect(JSON.stringify(finalState)).toEqual(initialStateJson);

@@ -323,2 +323,15 @@ expect(finalState.state instanceof TypeA).toBeTruthy();

it('not restoreDates', () => {
// Tests that dates are not revived when the flag is set to false
let s = new MockStorage();
let skr = mockStorageKeySerializer;
const initalState = {state: t1Simple};
syncStateUpdate(initalState, ['state'], s, skr, false);
let finalState: any = rehydrateApplicationState(['state'], s, skr, false);
expect(finalState).toEqual(initalState, 'rehydrated state should equal initial state');
});
it('encrypt-decrypt', () => {

@@ -336,3 +349,3 @@ let s = new MockStorage();

// Retrieve the stored state with the rehydrateApplicationState function and
let storedState = rehydrateApplicationState(keys, s, skr);
let storedState = rehydrateApplicationState(keys, s, skr, true);
expect(initialStateJson).toEqual(JSON.stringify(storedState));

@@ -370,3 +383,3 @@ });

let finalState: any = rehydrateApplicationState(['state'], s, skr);
let finalState: any = rehydrateApplicationState(['state'], s, skr, true);
expect(JSON.stringify(finalState)).toEqual(initialStateJson);

@@ -373,0 +386,0 @@

@@ -6,183 +6,239 @@ const INIT_ACTION = '@ngrx/store/init';

export const dateReviver = (key: string, value: any) => {
if (typeof value === 'string' && (detectDate.test(value))) {
return new Date(value);
}
return value;
if (typeof value === 'string' && detectDate.test(value)) {
return new Date(value);
}
return value;
};
const dummyReviver = (key: string, value: any) => value;
const validateStateKeys = (keys: any[]) => {
return keys.map(key => {
let attr = key;
return keys.map(key => {
let attr = key;
if (typeof key === 'object') {
attr = Object.keys(key)[0];
}
if (typeof key === 'object') {
attr = Object.keys(key)[0];
}
if (typeof (attr) !== 'string') {
throw new TypeError(
`localStorageSync Unknown Parameter Type: `
+ `Expected type of string, got ${typeof attr}`
);
}
return key;
});
if (typeof attr !== 'string') {
throw new TypeError(
`localStorageSync Unknown Parameter Type: ` +
`Expected type of string, got ${typeof attr}`
);
}
return key;
});
};
export const rehydrateApplicationState = (keys: any[], storage: Storage, storageKeySerializer: (key: string) => string) => {
return keys.reduce((acc, curr) => {
let key = curr;
let reviver = dateReviver;
let deserialize = undefined;
let decrypt = undefined;
export const rehydrateApplicationState = (
keys: any[],
storage: Storage,
storageKeySerializer: (key: string) => string,
restoreDates: boolean
) => {
return keys.reduce((acc, curr) => {
let key = curr;
let reviver = restoreDates ? dateReviver : dummyReviver;
let deserialize = undefined;
let decrypt = undefined;
if (typeof key === 'object') {
key = Object.keys(key)[0];
// use the custom reviver function
if (typeof curr[key] === 'function') {
reviver = curr[key];
}
else {
// use custom reviver function if available
if (curr[key].reviver) {
reviver = curr[key].reviver;
}
// use custom serialize function if available
if (curr[key].deserialize) {
deserialize = curr[key].deserialize;
}
}
if (typeof key === 'object') {
key = Object.keys(key)[0];
// use the custom reviver function
if (typeof curr[key] === 'function') {
reviver = curr[key];
} else {
// use custom reviver function if available
if (curr[key].reviver) {
reviver = curr[key].reviver;
}
// use custom serialize function if available
if (curr[key].deserialize) {
deserialize = curr[key].deserialize;
}
}
// Ensure that encrypt and decrypt functions are both presents
if (curr[key].encrypt && curr[key].decrypt) {
if (typeof (curr[key].encrypt) === 'function' && typeof (curr[key].decrypt) === 'function') {
decrypt = curr[key].decrypt;
} else {
console.error(`Either encrypt or decrypt is not a function on '${curr[key]}' key object.`);
}
} else if (curr[key].encrypt || curr[key].decrypt) {
// Let know that one of the encryption functions is not provided
console.error(`Either encrypt or decrypt function is not present on '${curr[key]}' key object.`);
}
// Ensure that encrypt and decrypt functions are both presents
if (curr[key].encrypt && curr[key].decrypt) {
if (
typeof curr[key].encrypt === 'function' &&
typeof curr[key].decrypt === 'function'
) {
decrypt = curr[key].decrypt;
} else {
console.error(
`Either encrypt or decrypt is not a function on '${
curr[key]
}' key object.`
);
}
} else if (curr[key].encrypt || curr[key].decrypt) {
// Let know that one of the encryption functions is not provided
console.error(
`Either encrypt or decrypt function is not present on '${
curr[key]
}' key object.`
);
}
}
let stateSlice = storage.getItem(storageKeySerializer(key));
if (stateSlice) {
// Use provided decrypt function
if (decrypt) {
stateSlice = decrypt(stateSlice);
}
let stateSlice = storage.getItem(storageKeySerializer(key));
if (stateSlice) {
// Use provided decrypt function
if (decrypt) {
stateSlice = decrypt(stateSlice);
}
const isObjectRegex = new RegExp('\{|\\[');
let raw = stateSlice;
const isObjectRegex = new RegExp('{|\\[');
let raw = stateSlice;
if (isObjectRegex.test(stateSlice.charAt(0))) {
raw = JSON.parse(stateSlice, reviver);
}
if (isObjectRegex.test(stateSlice.charAt(0))) {
raw = JSON.parse(stateSlice, reviver);
}
return Object.assign({}, acc, { [key]: deserialize ? deserialize(raw) : raw });
}
return acc;
}, {});
return Object.assign({}, acc, {
[key]: deserialize ? deserialize(raw) : raw
});
}
return acc;
}, {});
};
export const syncStateUpdate = (state: any, keys: any[], storage: Storage, storageKeySerializer: (key: string) => string, removeOnUndefined: boolean) => {
keys.forEach(key => {
export const syncStateUpdate = (
state: any,
keys: any[],
storage: Storage,
storageKeySerializer: (key: string) => string,
removeOnUndefined: boolean
) => {
keys.forEach(key => {
let stateSlice = state[key];
let replacer = undefined;
let space = undefined;
let encrypt = undefined;
let stateSlice = state[key];
let replacer = undefined;
let space = undefined;
let encrypt = undefined;
if (typeof key === 'object') {
let name = Object.keys(key)[0];
stateSlice = state[name];
if (typeof key === 'object') {
let name = Object.keys(key)[0];
stateSlice = state[name];
if (typeof stateSlice !== 'undefined' && key[name]) {
// use serialize function if specified.
if (key[name].serialize) {
stateSlice = key[name].serialize(stateSlice);
} else {
// if serialize function is not specified filter on fields if an array has been provided.
let filter = undefined;
if (key[name].reduce) {
filter = key[name];
} else if (key[name].filter) {
filter = key[name].filter;
}
if (filter) {
stateSlice = filter.reduce((memo, attr) => {
memo[attr] = stateSlice[attr];
return memo;
}, {});
}
if (typeof (stateSlice) !== 'undefined' && key[name]) {
// use serialize function if specified.
if (key[name].serialize) {
stateSlice = key[name].serialize(stateSlice);
}
// if serialize function is not specified filter on fields if an array has been provided.
else {
let filter = undefined;
if (key[name].reduce) {
filter = key[name];
}
else if (key[name].filter) {
filter = key[name].filter;
}
if (filter) {
stateSlice = filter.reduce((memo, attr) => {
memo[attr] = stateSlice[attr];
return memo;
}, {});
}
// Check if encrypt and decrypt are present, also checked at this#rehydrateApplicationState()
if (key[name].encrypt && key[name].decrypt) {
if (typeof key[name].encrypt === 'function') {
encrypt = key[name].encrypt;
}
} else if (key[name].encrypt || key[name].decrypt) {
// If one of those is not present, then let know that one is missing
console.error(
`Either encrypt or decrypt function is not present on '${
key[name]
}' key object.`
);
}
}
// Check if encrypt and decrypt are present, also checked at this#rehydrateApplicationState()
if (key[name].encrypt && key[name].decrypt) {
if (typeof (key[name].encrypt) === 'function') {
encrypt = key[name].encrypt;
}
} else if (key[name].encrypt || key[name].decrypt) {
// If one of those is not present, then let know that one is missing
console.error(`Either encrypt or decrypt function is not present on '${key[name]}' key object.`);
}
}
/*
/*
Replacer and space arguments to pass to JSON.stringify.
If these fields don't exist, undefined will be passed.
*/
replacer = key[name].replacer;
space = key[name].space;
}
replacer = key[name].replacer;
space = key[name].space;
}
key = name;
}
key = name;
}
if (typeof (stateSlice) !== 'undefined') {
try {
if (encrypt) {
// ensure that a string message is passed
stateSlice = encrypt(typeof stateSlice === 'string' ? stateSlice : JSON.stringify(stateSlice, replacer, space));
}
storage.setItem(storageKeySerializer(key), typeof stateSlice === 'string' ? stateSlice : JSON.stringify(stateSlice, replacer, space));
} catch (e) {
console.warn('Unable to save state to localStorage:', e);
}
} else if (typeof (stateSlice) === 'undefined' && removeOnUndefined) {
try {
storage.removeItem(storageKeySerializer(key));
} catch (e) {
console.warn(`Exception on removing/cleaning undefined '${key}' state`, e);
}
if (typeof stateSlice !== 'undefined') {
try {
if (encrypt) {
// ensure that a string message is passed
stateSlice = encrypt(
typeof stateSlice === 'string'
? stateSlice
: JSON.stringify(stateSlice, replacer, space)
);
}
});
storage.setItem(
storageKeySerializer(key),
typeof stateSlice === 'string'
? stateSlice
: JSON.stringify(stateSlice, replacer, space)
);
} catch (e) {
console.warn('Unable to save state to localStorage:', e);
}
} else if (typeof stateSlice === 'undefined' && removeOnUndefined) {
try {
storage.removeItem(storageKeySerializer(key));
} catch (e) {
console.warn(
`Exception on removing/cleaning undefined '${key}' state`,
e
);
}
}
});
};
export const localStorageSync = (config: LocalStorageConfig) => (reducer: any) => {
export const localStorageSync = (config: LocalStorageConfig) => (
reducer: any
) => {
if (config.storage === undefined) {
config.storage = localStorage || window.localStorage;
}
if (config.storage === undefined) {
config.storage = localStorage || window.localStorage;
}
if (config.storageKeySerializer === undefined) {
config.storageKeySerializer = key => key;
}
if (config.storageKeySerializer === undefined) {
config.storageKeySerializer = (key) => key;
}
if (config.restoreDates === undefined) {
config.restoreDates = true;
}
const stateKeys = validateStateKeys(config.keys);
const rehydratedState = config.rehydrate ? rehydrateApplicationState(stateKeys, config.storage, config.storageKeySerializer) : undefined;
const stateKeys = validateStateKeys(config.keys);
const rehydratedState = config.rehydrate
? rehydrateApplicationState(
stateKeys,
config.storage,
config.storageKeySerializer,
config.restoreDates
)
: undefined;
return function (state = rehydratedState, action: any) {
/*
return function(state = rehydratedState, action: any) {
/*
Handle case where state is rehydrated AND initial state is supplied.
Any additional state supplied will override rehydrated state for the given key.
*/
if (action.type === INIT_ACTION && rehydratedState) {
state = Object.assign({}, state, rehydratedState);
}
const nextState = reducer(state, action);
syncStateUpdate(nextState, stateKeys, config.storage, config.storageKeySerializer, config.removeOnUndefined);
return nextState;
};
if (action.type === INIT_ACTION && rehydratedState) {
state = Object.assign({}, state, rehydratedState);
}
const nextState = reducer(state, action);
syncStateUpdate(
nextState,
stateKeys,
config.storage,
config.storageKeySerializer,
config.removeOnUndefined
);
return nextState;
};
};

@@ -197,20 +253,24 @@

*/
export const localStorageSyncAndClean = (keys: any[], rehydrate: boolean = false, removeOnUndefined: boolean = false) => (reducer: any) => {
export const localStorageSyncAndClean = (
keys: any[],
rehydrate: boolean = false,
removeOnUndefined: boolean = false
) => (reducer: any) => {
let config: LocalStorageConfig = {
keys: keys,
rehydrate: rehydrate,
storage: localStorage,
removeOnUndefined: removeOnUndefined
};
let config: LocalStorageConfig = {
keys: keys,
rehydrate: rehydrate,
storage: localStorage,
removeOnUndefined: removeOnUndefined
};
return this.localStorageSync(config);
return this.localStorageSync(config);
};
export interface LocalStorageConfig {
keys: any[];
rehydrate?: boolean;
storage?: Storage;
removeOnUndefined?: boolean;
storageKeySerializer?: (key: string) => string;
keys: any[];
rehydrate?: boolean;
storage?: Storage;
removeOnUndefined?: boolean;
restoreDates?: boolean;
storageKeySerializer?: (key: string) => string;
}

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