Skip to content

Commit 721b4cf

Browse files
committed
add config to exclude keys
1 parent 36b67b2 commit 721b4cf

File tree

10 files changed

+59
-13
lines changed

10 files changed

+59
-13
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,10 @@ export interface Config<T> {
6262
* @param state the last state known before it gets saved to storage
6363
*/
6464
saveIf: (state: T) => boolean
65+
66+
/**
67+
* These keys will not get saved to storage
68+
*/
69+
excludeKeys: Array<keyof T>
6570
}
6671
```

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"ng": "ng",
66
"start": "ng serve",
77
"test": "ng test ngrx-signals-storage",
8+
"test:watch": "ng test ngrx-signals-storage --watch",
89
"build": "ng build ngrx-signals-storage && cpx README.md dist/ngrx-signals-storage"
910
},
1011
"private": true,
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
module.exports = {
22
preset: 'jest-preset-angular',
3-
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$|@stomp/rx-stomp)']
3+
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$|@stomp/rx-stomp)'],
4+
setupFiles: ['./projects/ngrx-signals-storage/setup-jest.ts']
45
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Object.assign(global, { structuredClone: (val: any) => JSON.parse(JSON.stringify(val)) })

projects/ngrx-signals-storage/src/lib/config.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ export interface Config<T> {
2222
* @param state the last state known before it gets saved to storage
2323
*/
2424
saveIf: (state: T) => boolean
25+
26+
/**
27+
* These keys will not get saved to storage
28+
*/
29+
excludeKeys: Array<keyof T>
2530
}
2631

2732
export const defaultConfig: Config<any> = {
@@ -31,5 +36,7 @@ export const defaultConfig: Config<any> = {
3136

3237
deserialize: (state: string) => JSON.parse(state),
3338

34-
saveIf: (state: any) => true
39+
saveIf: (state: any) => true,
40+
41+
excludeKeys: []
3542
}

projects/ngrx-signals-storage/src/lib/with-storage.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,34 @@ describe('withStorage', () => {
269269

270270
expect(error).toHaveBeenCalledWith(Error('storage error'))
271271
})
272+
273+
it('should exclude keys from state when saving to storage', () => {
274+
const storage = new TestStorage()
275+
276+
const TestStore = signalStore(
277+
withState({
278+
count: 100,
279+
excludeMe: 1,
280+
skipMe: 'test'
281+
}),
282+
withStorage(storageKey, storage, { excludeKeys: ['excludeMe', 'skipMe'] })
283+
)
284+
285+
TestBed.configureTestingModule({
286+
providers: [TestStore]
287+
})
288+
289+
const store = TestBed.inject(TestStore)
290+
expect(store.count()).toBe(100)
291+
expect(store.excludeMe()).toBe(1)
292+
expect(store.skipMe()).toBe('test')
293+
294+
// trigger effect()
295+
TestBed.flushEffects()
296+
297+
expect(storage.length).toEqual(1)
298+
expect(JSON.parse(storage.getItem(storageKey)!)).toEqual({ count: 100 })
299+
})
272300
})
273301

274302
class TestStorage implements Storage {

projects/ngrx-signals-storage/src/lib/with-storage.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,12 @@ export function withStorage<State extends SignalStoreFeatureResult>(
5555
}
5656

5757
effect(() => {
58-
const state = getState(store)
58+
const state = structuredClone(getState(store))
5959
try {
6060
if (cfg.saveIf(state)) {
61+
cfg.excludeKeys.forEach((key) => {
62+
delete state[key as keyof State['state']]
63+
})
6164
storage.setItem(key, cfg.serialize(state))
6265
}
6366
} catch (e) {
@@ -69,7 +72,11 @@ export function withStorage<State extends SignalStoreFeatureResult>(
6972
}
7073
}
7174

72-
function getFromStorage<T>(key: string, storage: Storage, cfg: Config<T>): string | null {
75+
function getFromStorage<State extends SignalStoreFeatureResult>(
76+
key: string,
77+
storage: Storage,
78+
cfg: Config<State>
79+
): string | null {
7380
try {
7481
return storage.getItem(key)
7582
} catch (e) {

projects/ngrx-signals-storage/tsconfig.spec.json

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,7 @@
33
"extends": "../../tsconfig.json",
44
"compilerOptions": {
55
"outDir": "../../out-tsc/spec",
6-
"types": [
7-
"jest"
8-
]
6+
"types": ["jest", "node"]
97
},
10-
"include": [
11-
"**/*.spec.ts",
12-
"**/*.d.ts"
13-
]
8+
"include": ["**/*.spec.ts", "**/*.d.ts"]
149
}

src/app/app.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import { patchState, signalStore, withMethods, withState } from '@ngrx/signals'
88
export const CounterStore = signalStore(
99
withState({
1010
count: 100,
11+
test: 5,
1112
date: new Date()
1213
}),
13-
withStorage('state', sessionStorage),
14+
withStorage('state', sessionStorage, { excludeKeys: ['test'] }),
1415
withMethods(({ count, ...store }) => ({
1516
setDate(date: Date) {
1617
patchState(store, { date })

tsconfig.spec.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"compilerOptions": {
55
"outDir": "./out-tsc/spec",
66
"types": [
7-
"jest"
7+
"jest", "node"
88
]
99
},
1010
"include": [

0 commit comments

Comments
 (0)