Skip to content

Commit

Permalink
feat(persist): add persistFilter option & deprecate whitelist/blackli…
Browse files Browse the repository at this point in the history
…st (pmndrs#463)
  • Loading branch information
AnatoleLucet authored Oct 7, 2021
1 parent 2367abb commit 3d42979
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 2 deletions.
26 changes: 24 additions & 2 deletions src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,14 @@ export const combine =
)
)

type DeepPartial<T extends Object> = {
[P in keyof T]?: DeepPartial<T[P]>
}
export type StateStorage = {
getItem: (name: string) => string | null | Promise<string | null>
setItem: (name: string, value: string) => void | Promise<void>
}
type StorageValue<S> = { state: S; version?: number }
type StorageValue<S> = { state: DeepPartial<S>; version?: number }
type PersistOptions<S, PersistedState extends Partial<S> = Partial<S>> = {
/** Name of the storage (must be unique) */
name: string
Expand Down Expand Up @@ -218,12 +221,22 @@ type PersistOptions<S, PersistedState extends Partial<S> = Partial<S>> = {
) => StorageValue<PersistedState> | Promise<StorageValue<PersistedState>>
/**
* Prevent some items from being stored.
*
* @deprecated This options is deprecated and will be removed in the next version. Please use the `partialize` option instead.
*/
blacklist?: (keyof S)[]
/**
* Only store the listed properties.
*
* @deprecated This options is deprecated and will be removed in the next version. Please use the `partialize` option instead.
*/
whitelist?: (keyof S)[]
/**
* Filter the persisted value.
*
* @params state The state's value
*/
partialize?: (state: S) => DeepPartial<S>
/**
* A function returning another (optional) function.
* The main function will be called before the state rehydration.
Expand Down Expand Up @@ -296,6 +309,7 @@ export const persist =
deserialize = JSON.parse as (str: string) => StorageValue<Partial<S>>,
blacklist,
whitelist,
partialize = (state: S) => state,
onRehydrateStorage,
version = 0,
migrate,
Expand All @@ -305,6 +319,14 @@ export const persist =
}),
} = options || {}

if (blacklist || whitelist) {
console.warn(
`The ${
blacklist ? 'blacklist' : 'whitelist'
} option is deprecated and will be removed in the next version. Please use the 'partialize' option instead.`
)
}

let storage: StateStorage | undefined

try {
Expand All @@ -329,7 +351,7 @@ export const persist =
const thenableSerialize = toThenable(serialize)

const setItem = (): Thenable<void> => {
const state = { ...get() }
const state = partialize({ ...get() })

if (whitelist) {
;(Object.keys(state) as (keyof S)[]).forEach((key) => {
Expand Down
64 changes: 64 additions & 0 deletions tests/persistSync.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,68 @@ describe('persist middleware with sync configuration', () => {
count: 1,
})
})

it('can filter the persisted value', () => {
const setItemSpy = jest.fn()

const storage = {
getItem: () => '',
setItem: setItemSpy,
}

const useStore = create(
persist(
() => ({
object: {
first: '0',
second: '1',
},
array: [
{
value: '0',
},
{
value: '1',
},
{
value: '2',
},
],
}),
{
name: 'test-storage',
getStorage: () => storage,
partialize: (state) => {
return {
object: {
first: state.object.first,
},
array: state.array.filter((e) => e.value !== '1'),
}
},
}
)
)

useStore.setState({})
expect(setItemSpy).toBeCalledWith(
'test-storage',
JSON.stringify({
state: {
object: {
first: '0',
},
array: [
{
value: '0',
},
{
value: '2',
},
],
},
version: 0,
})
)
})
})

0 comments on commit 3d42979

Please sign in to comment.