/** * Zod validation schemas */ import { z } from 'zod' /** * Common validation schemas */ export const emailSchema = z.string().email('Invalid email address') export const urlSchema = z.string().url('Invalid URL') export const nonEmptyStringSchema = z.string().min(1, 'This field is required') /** * Resource validation schemas */ export const resourceNameSchema = z .string() .min(1, 'Resource name is required') .max(63, 'Resource name must be 63 characters or less') .regex( /^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/, 'Resource name must be lowercase alphanumeric with hyphens' ) export const memorySchema = z .string() .regex(/^\d+[KMGT]i?$/, 'Memory must be in format like 4Gi, 8Mi, etc.') export const diskSizeSchema = z .string() .regex(/^\d+[KMGT]i?$/, 'Disk size must be in format like 50Gi, 100Mi, etc.') export const cpuSchema = z.number().int().min(1).max(128) /** * VM creation schema */ export const vmCreateSchema = z.object({ name: resourceNameSchema, node: nonEmptyStringSchema, cpu: cpuSchema, memory: memorySchema, disk: diskSizeSchema, storage: nonEmptyStringSchema, network: nonEmptyStringSchema, image: nonEmptyStringSchema, site: nonEmptyStringSchema, userData: z.string().optional(), sshKeys: z.array(z.string()).optional(), }) export type VMCreateInput = z.infer /** * Form validation utilities */ export function validateForm(schema: z.ZodSchema, data: unknown): { success: boolean data?: T errors?: Record } { const result = schema.safeParse(data) if (result.success) { return { success: true, data: result.data } } const errors: Record = {} result.error.errors.forEach((error) => { const path = error.path.join('.') if (!errors[path]) { errors[path] = [] } errors[path].push(error.message) }) return { success: false, errors } }