Files
Sankofa/src/lib/validation/schemas.ts
defiQUG 6f28146ac3 Initial Phoenix Sankofa Cloud setup
- Complete project structure with Next.js frontend
- GraphQL API backend with Apollo Server
- Portal application with NextAuth
- Crossplane Proxmox provider
- GitOps configurations
- CI/CD pipelines
- Testing infrastructure (Vitest, Jest, Go tests)
- Error handling and monitoring
- Security hardening
- UI component library
- Documentation
2025-11-28 12:54:33 -08:00

83 lines
1.9 KiB
TypeScript

/**
* 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<typeof vmCreateSchema>
/**
* Form validation utilities
*/
export function validateForm<T>(schema: z.ZodSchema<T>, data: unknown): {
success: boolean
data?: T
errors?: Record<string, string[]>
} {
const result = schema.safeParse(data)
if (result.success) {
return { success: true, data: result.data }
}
const errors: Record<string, string[]> = {}
result.error.errors.forEach((error) => {
const path = error.path.join('.')
if (!errors[path]) {
errors[path] = []
}
errors[path].push(error.message)
})
return { success: false, errors }
}