67 lines
2.1 KiB
TypeScript
67 lines
2.1 KiB
TypeScript
// Copied from https://github.com/solidjs-community/solid-primitives/blob/main/packages/storage/src/types.ts
|
|
// Simplified version
|
|
|
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
import { defaultSettings } from '@typebot.io/schemas/features/typebot/settings/constants'
|
|
import type { Setter, Signal } from 'solid-js'
|
|
import { createSignal, untrack } from 'solid-js'
|
|
import { reconcile } from 'solid-js/store'
|
|
|
|
type Params = {
|
|
key: string
|
|
storage: 'local' | 'session' | undefined
|
|
onRecovered?: () => void
|
|
}
|
|
|
|
export function persist<T>(
|
|
signal: Signal<T>,
|
|
params: Params
|
|
): [...Signal<T>, () => boolean] {
|
|
const [isRecovered, setIsRecovered] = createSignal(false)
|
|
if (!params.storage) return [...signal, () => false]
|
|
|
|
const storage = parseRememberUserStorage(
|
|
params.storage || defaultSettings.general.rememberUser.storage
|
|
)
|
|
const serialize: (data: T) => string = JSON.stringify.bind(JSON)
|
|
const deserialize: (data: string) => T = JSON.parse.bind(JSON)
|
|
const init = storage.getItem(params.key)
|
|
const set =
|
|
typeof signal[0] === 'function'
|
|
? (data: string) => (signal[1] as any)(() => deserialize(data))
|
|
: (data: string) => (signal[1] as any)(reconcile(deserialize(data)))
|
|
|
|
if (init) {
|
|
set(init)
|
|
setIsRecovered(true)
|
|
params.onRecovered?.()
|
|
}
|
|
|
|
return [
|
|
signal[0],
|
|
typeof signal[0] === 'function'
|
|
? (value?: T | ((prev: T) => T)) => {
|
|
setIsRecovered(false)
|
|
const output = (signal[1] as Setter<T>)(value as any)
|
|
|
|
if (value) storage.setItem(params.key, serialize(output))
|
|
else storage.removeItem(params.key)
|
|
return output
|
|
}
|
|
: (...args: any[]) => {
|
|
setIsRecovered(false)
|
|
;(signal[1] as any)(...args)
|
|
const value = serialize(untrack(() => signal[0] as any))
|
|
storage.setItem(params.key, value)
|
|
},
|
|
isRecovered,
|
|
] as [...typeof signal, () => boolean]
|
|
}
|
|
|
|
const parseRememberUserStorage = (
|
|
storage: 'local' | 'session' | undefined
|
|
): typeof localStorage | typeof sessionStorage =>
|
|
(storage ?? defaultSettings.general.rememberUser.storage) === 'session'
|
|
? sessionStorage
|
|
: localStorage
|