diff --git a/package-lock.json b/package-lock.json index dbfcfe7..fec8202 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,7 +61,7 @@ "tailwind-merge": "^2.5.2", "tailwindcss-animate": "^1.0.7", "vaul": "^0.9.3", - "zod": "^3.23.8" + "zod": "^3.25.71" }, "devDependencies": { "@eslint/js": "^9.9.0", @@ -8244,9 +8244,9 @@ } }, "node_modules/zod": { - "version": "3.24.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz", - "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==", + "version": "3.25.71", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.71.tgz", + "integrity": "sha512-BsBc/NPk7h8WsUWYWYL+BajcJPY8YhjelaWu2NMLuzgraKAz4Lb4/6K11g9jpuDetjMiqhZ6YaexFLOC0Ogi3Q==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index eefa69c..94d0460 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "tailwind-merge": "^2.5.2", "tailwindcss-animate": "^1.0.7", "vaul": "^0.9.3", - "zod": "^3.23.8" + "zod": "^3.25.71" }, "devDependencies": { "@eslint/js": "^9.9.0", diff --git a/src/components/AppProvider.tsx b/src/components/AppProvider.tsx index d571e24..ebbbbe4 100644 --- a/src/components/AppProvider.tsx +++ b/src/components/AppProvider.tsx @@ -1,4 +1,5 @@ import { ReactNode, useEffect } from 'react'; +import { z } from 'zod'; import { useLocalStorage } from '@/hooks/useLocalStorage'; import { AppContext, type AppConfig, type AppContextType, type Theme } from '@/contexts/AppContext'; @@ -12,6 +13,12 @@ interface AppProviderProps { presetRelays?: { name: string; url: string }[]; } +// Zod schema for AppConfig validation +const AppConfigSchema: z.ZodType = z.object({ + theme: z.enum(['dark', 'light', 'system']), + relayUrl: z.string().url(), +}); + export function AppProvider(props: AppProviderProps) { const { children, @@ -21,7 +28,17 @@ export function AppProvider(props: AppProviderProps) { } = props; // App configuration state with localStorage persistence - const [config, setConfig] = useLocalStorage(storageKey, defaultConfig); + const [config, setConfig] = useLocalStorage( + storageKey, + defaultConfig, + { + serialize: JSON.stringify, + deserialize: (value: string) => { + const parsed = JSON.parse(value); + return AppConfigSchema.parse(parsed); + } + } + ); // Generic config updater with callback pattern const updateConfig = (updater: (currentConfig: AppConfig) => AppConfig) => {