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