homelab-dashboard/src/lib/config/schema.ts
Bilal Teke 764223db6c v3.2
2026-04-16 13:56:28 +02:00

65 lines
2.1 KiB
TypeScript

import { z } from 'zod';
const safeRelativePathSchema = z
.string()
.min(1)
.max(200)
.refine((value) => !value.startsWith('/') && !value.startsWith('\\'), {
message: 'Path must be relative to the project root',
})
.refine((value) => !value.split(/[\\/]+/).includes('..'), {
message: 'Path must not contain parent directory segments',
});
// Healthcheck Schema
export const healthcheckSchema = z.object({
acceptableStatusCodes: z.array(z.number().int().min(100).max(599)).min(1).default([200]),
timeoutMs: z.number().int().positive().default(5000),
}).strict();
// Service Schema
export const serviceSchema = z.object({
id: z.string().min(1).max(50),
name: z.string().min(1).max(100),
description: z.string().min(1).max(500),
url: z.string().url(),
monitorUrl: z.string().url(),
category: z.string().min(1).max(50),
healthcheck: healthcheckSchema.optional(),
}).strict();
// App Config Schema
export const appConfigSchema = z.object({
title: z.string().min(1).max(100),
subtitle: z.string().min(1).max(200),
description: z.string().min(1).max(500),
servicesFile: safeRelativePathSchema,
refreshInterval: z.number().int().min(1000).max(300000).default(30000), // 1s to 5min
categories: z.array(z.string().min(1).max(50)).min(1),
theme: z.enum(['light', 'dark', 'auto']).default('auto'),
loggingLevel: z.enum(['error', 'warn', 'info', 'debug']).default('info'),
}).strict();
// Services Array Schema
export const servicesArraySchema = z.array(serviceSchema).superRefine((services, ctx) => {
const ids = new Set<string>();
services.forEach((service, index) => {
if (ids.has(service.id)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `Duplicate service id: ${service.id}`,
path: [index, 'id'],
});
return;
}
ids.add(service.id);
});
});
// Type exports
export type Service = z.infer<typeof serviceSchema>;
export type Healthcheck = z.infer<typeof healthcheckSchema>;
export type AppConfig = z.infer<typeof appConfigSchema>;
export type Services = z.infer<typeof servicesArraySchema>;