Skip to content

Commit

Permalink
add config
Browse files Browse the repository at this point in the history
  • Loading branch information
larscom committed Dec 25, 2023
1 parent f7b2e9a commit d07b7af
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 9 deletions.
37 changes: 32 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ npm install @larscom/ngrx-signals-storage

`@larscom/ngrx-signals-storage` depends on [@ngrx/signals](https://ngrx.io/guide/signals/install) and [Angular](https://github.com/angular/angular)

```bash
npm install @ngrx/signals
```

## Usage

Import `withStorage` function
Expand All @@ -33,6 +29,37 @@ export const CounterStore = signalStore(
count: 0
}),
// state will be saved to sessionStorage under the key: 'myKey'
withStorage('myKey', sessionStorage)
// extra config can be passed as 3th argument
withStorage('myKey', sessionStorage, { error: (error: any) => console.error(error) })
)
```

## Configuration

```ts
export interface Config<T> {
/**
* Function that gets executed on a storage error (get/set)
* @param error the error that occurred
*/
error: (error: any) => void

/**
* Serializer for the state, by default it uses `JSON.stringify()`
* @param state the last state known before it gets saved to storage
*/
serialize: (state: T) => string

/**
* Deserializer for the state, by default it uses `JSON.parse()`
* @param state the last state known from the storage location
*/
deserialize: (state: string) => T

/**
* Save to storage will only occur when this function returns true
* @param state the last state known before it gets saved to storage
*/
shouldSave: (state: T) => boolean
}
```
35 changes: 35 additions & 0 deletions projects/ngrx-signals-storage/src/lib/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export interface Config<T> {
/**
* Function that gets executed on a storage error (get/set)
* @param error the error that occurred
*/
error: (error: any) => void

/**
* Serializer for the state, by default it uses `JSON.stringify()`
* @param state the last state known before it gets saved to storage
*/
serialize: (state: T) => string

/**
* Deserializer for the state, by default it uses `JSON.parse()`
* @param state the last state known from the storage location
*/
deserialize: (state: string) => T

/**
* Save to storage will only occur when this function returns true
* @param state the last state known before it gets saved to storage
*/
shouldSave: (state: T) => boolean
}

export const defaultConfig: Config<any> = {
error: (error: any) => {},

serialize: (state: any) => JSON.stringify(state),

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

shouldSave: (state: any) => true
}
27 changes: 23 additions & 4 deletions projects/ngrx-signals-storage/src/lib/with-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { effect } from '@angular/core'

import { getState, patchState } from '@ngrx/signals'
import { EmptyFeatureResult, SignalStoreFeature, SignalStoreFeatureResult } from '@ngrx/signals/src/signal-store-models'
import { Config, defaultConfig } from './config'

/**
* The `withStorage` function that lets you save the state to localstorage/sessionstorage
Expand All @@ -23,10 +24,13 @@ import { EmptyFeatureResult, SignalStoreFeature, SignalStoreFeatureResult } from
*/
export function withStorage<State extends SignalStoreFeatureResult>(
key: string,
storage: Storage
storage: Storage,
config?: Partial<Config<State['state']>>
): SignalStoreFeature<State, EmptyFeatureResult> {
const item = storage.getItem(key)
const storageState: State['state'] | null = item ? JSON.parse(item) : null
const cfg = { ...defaultConfig, ...config }

const item = getFromStorage(key, storage, cfg)
const storageState: State['state'] | null = item ? cfg.deserialize(item) : null

let hydrated = false

Expand All @@ -52,9 +56,24 @@ export function withStorage<State extends SignalStoreFeatureResult>(

effect(() => {
const state = getState(store)
storage.setItem(key, JSON.stringify(state))
try {
if (cfg.shouldSave(state)) {
storage.setItem(key, cfg.serialize(state))
}
} catch (e) {
cfg.error(e)
}
})

return store
}
}

function getFromStorage<T>(key: string, storage: Storage, cfg: Config<T>): string | null {
try {
return storage.getItem(key)
} catch (e) {
cfg.error(e)
return null
}
}
1 change: 1 addition & 0 deletions projects/ngrx-signals-storage/src/public-api.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { withStorage } from './lib/with-storage'
export { type Config } from './lib/config'

0 comments on commit d07b7af

Please sign in to comment.