Parse AppConfig with a zod schema

This commit is contained in:
Alex Gleason 2025-07-03 19:04:40 -05:00
parent fce2a3da23
commit 49952a10bf
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
3 changed files with 23 additions and 6 deletions

8
package-lock.json generated
View File

@ -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"

View File

@ -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",

View File

@ -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<AppConfig> = 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<AppConfig>(storageKey, defaultConfig);
const [config, setConfig] = useLocalStorage<AppConfig>(
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) => {