Skip to content

Commit

Permalink
✨ add factory function (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
prazdevs committed Mar 6, 2022
1 parent b88713c commit 761a873
Show file tree
Hide file tree
Showing 3 changed files with 417 additions and 283 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,27 @@ export const useUserStore = defineStore('ssr', {
})
```

## 🔧 Factory function configuration

Need to override default options? You can import and use `createPersistedState(options)`:

```ts
import { createPinia } from 'pinia'
import { createPersistedState } from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(createPersistedState({
storage: sessionStorage,
beforeRestore: () => {},
afterRestore: () => {},
serializer: {
serialize: JSON.stringify,
deserialize: JSON.parse,
}
}))
```

The options passed will be used in any store declaring `persist: true`. You can still override these defaults with per-store options.

## ⚠️ Limitations

### **References do not persist**
Expand Down
100 changes: 56 additions & 44 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface Serializer {
* @default JSON.stringify
*/
serialize: (value: StateTree) => string

/**
* Deserializes string into state before hydrating
* @default JSON.parse
Expand Down Expand Up @@ -58,6 +59,11 @@ export interface PersistedStateOptions {
afterRestore?: (context: PiniaPluginContext) => void
}

export type PersistedStateFactoryOptions = Pick<
PersistedStateOptions,
'storage' | 'serializer' | 'afterRestore' | 'beforeRestore'
>

declare module 'pinia' {
export interface DefineStoreOptionsBase<S extends StateTree, Store> {
/**
Expand All @@ -68,48 +74,54 @@ declare module 'pinia' {
}
}

/**
* Pinia plugin to persist stores in a storage based on vuex-persistedstate.
*/
export default function PiniaPersistState(context: PiniaPluginContext): void {
const {
options: { persist },
store,
} = context

if (!persist) return

const {
storage = localStorage,
key = store.$id,
paths = null,
beforeRestore = null,
afterRestore = null,
serializer = {
serialize: JSON.stringify,
deserialize: JSON.parse,
} as Serializer,
} = typeof persist != 'boolean' ? persist : {}

beforeRestore?.(context)

try {
const fromStorage = storage.getItem(key)
if (fromStorage) {
store.$patch(serializer.deserialize(fromStorage))
}
} catch (_error) {}

afterRestore?.(context)

store.$subscribe(
(_mutation: SubscriptionCallbackMutation<StateTree>, state: StateTree) => {
try {
const toStore = Array.isArray(paths) ? pick(state, paths) : state

storage.setItem(key, serializer.serialize(toStore as StateTree))
} catch (_error) {}
},
{ detached: true },
)
export function createPersistedState(
factoryOptions: PersistedStateFactoryOptions = {},
) {
return function (context: PiniaPluginContext): void {
const {
options: { persist },
store,
} = context

if (!persist) return

const {
storage = factoryOptions.storage ?? localStorage,
beforeRestore = factoryOptions.beforeRestore ?? null,
afterRestore = factoryOptions.afterRestore ?? null,
serializer = factoryOptions.serializer ?? {
serialize: JSON.stringify,
deserialize: JSON.parse,
},
key = store.$id,
paths = null,
} = typeof persist != 'boolean' ? persist : {}

beforeRestore?.(context)

try {
const fromStorage = storage.getItem(key)
if (fromStorage) {
store.$patch(serializer.deserialize(fromStorage))
}
} catch (_error) {}

afterRestore?.(context)

store.$subscribe(
(
_mutation: SubscriptionCallbackMutation<StateTree>,
state: StateTree,
) => {
try {
const toStore = Array.isArray(paths) ? pick(state, paths) : state

storage.setItem(key, serializer.serialize(toStore as StateTree))
} catch (_error) {}
},
{ detached: true },
)
}
}

export default createPersistedState()

0 comments on commit 761a873

Please sign in to comment.