Files
kycnotme/web/src/lib/localstorage.ts
2025-06-09 10:00:55 +00:00

58 lines
1.4 KiB
TypeScript

import { z } from 'astro:schema'
import { zodParseJSON, type ZodJSON } from './json'
import { typedObjectEntries } from './objects'
function makeTypedLocalStorage<
Schemas extends Record<string, ZodJSON>,
T extends {
[K in keyof Schemas]: {
schema: Schemas[K]
default?: z.output<Schemas[K]> | undefined
key?: string
}
},
>(options: T) {
return Object.fromEntries(
typedObjectEntries(options).map(([originalKey, option]) => {
const key = option.key ?? originalKey
return [
key,
{
get: () => {
return zodParseJSON(option.schema, localStorage.getItem(key), option.default)
},
set: (value: z.input<typeof option.schema>) => {
localStorage.setItem(key, JSON.stringify(value))
},
remove: () => {
localStorage.removeItem(key)
},
default: option.default,
},
]
})
) as {
[K in keyof T]: {
get: () => z.output<T[K]['schema']> | (T[K] extends { default: infer D } ? D : undefined)
set: (value: z.input<T[K]['schema']>) => void
remove: () => void
default: z.output<T[K]['schema']> | undefined
}
}
}
export const typedLocalStorage = makeTypedLocalStorage({
pushNotificationsBannerDismissedAt: {
schema: z.coerce.date(),
},
browserNotificationsEnabled: {
schema: z.boolean(),
default: false,
},
})