Download src/lib/validation.ts from simikkk/test9: direct link, hf CLI and curl.
- Browser
- Download file 4.44 kB
-
https://huggingface.co/spaces/simikkk/test9/resolve/main/src/lib/validation.ts
- Command line
-
hf download hf://spaces/simikkk/test9/src/lib/validation.ts
-
curl -L -o validation.ts https://huggingface.co/spaces/simikkk/test9/resolve/main/src/lib/validation.ts
4.44 kB
| import { z } from 'zod'; | |
| // ─── Auth Schemas ───────────────────────────────────────────────────────────── | |
| export const loginSchema = z.object({ | |
| email: z.string().email('Please enter a valid email address'), | |
| password: z.string().min(1, 'Password is required'), | |
| }); | |
| export const signupSchema = z | |
| .object({ | |
| name: z | |
| .string() | |
| .min(2, 'Name must be at least 2 characters') | |
| .max(100, 'Name must be at most 100 characters'), | |
| email: z.string().email('Please enter a valid email address'), | |
| password: z | |
| .string() | |
| .min(8, 'Password must be at least 8 characters') | |
| .refine( | |
| (pwd) => /[A-Z]/.test(pwd), | |
| 'Password must contain at least one uppercase letter' | |
| ) | |
| .refine( | |
| (pwd) => /[a-z]/.test(pwd), | |
| 'Password must contain at least one lowercase letter' | |
| ) | |
| .refine( | |
| (pwd) => /[0-9]/.test(pwd), | |
| 'Password must contain at least one number' | |
| ), | |
| termsAccepted: z.literal(true, { | |
| message: 'You must accept the terms and conditions', | |
| }), | |
| }); | |
| export const changePasswordSchema = z | |
| .object({ | |
| currentPassword: z.string().min(1, 'Current password is required'), | |
| newPassword: z | |
| .string() | |
| .min(8, 'Password must be at least 8 characters') | |
| .refine( | |
| (pwd) => /[A-Z]/.test(pwd), | |
| 'Password must contain at least one uppercase letter' | |
| ) | |
| .refine( | |
| (pwd) => /[a-z]/.test(pwd), | |
| 'Password must contain at least one lowercase letter' | |
| ) | |
| .refine( | |
| (pwd) => /[0-9]/.test(pwd), | |
| 'Password must contain at least one number' | |
| ), | |
| confirmPassword: z.string().min(1, 'Please confirm your new password'), | |
| }) | |
| .refine((data) => data.newPassword === data.confirmPassword, { | |
| message: 'New passwords do not match', | |
| path: ['confirmPassword'], | |
| }); | |
| // ─── Upload Validation ──────────────────────────────────────────────────────── | |
| const ALLOWED_MIME_TYPES = [ | |
| 'application/pdf', | |
| 'image/jpeg', | |
| 'image/png', | |
| 'image/tiff', | |
| ]; | |
| const ALLOWED_EXTENSIONS = ['pdf', 'jpg', 'jpeg', 'png', 'tiff', 'tif']; | |
| const MAX_FILE_SIZE = 20 * 1024 * 1024; // 20 MB | |
| export function validateFile(file: File): string | null { | |
| // Check file size | |
| if (file.size > MAX_FILE_SIZE) { | |
| return `File "${file.name}" exceeds the 20 MB size limit (${(file.size / 1024 / 1024).toFixed(1)} MB)`; | |
| } | |
| // Check MIME type | |
| if (!ALLOWED_MIME_TYPES.includes(file.type)) { | |
| return `File "${file.name}" has unsupported type "${file.type}". Allowed: PDF, JPEG, PNG, TIFF`; | |
| } | |
| // Check extension | |
| const ext = file.name.split('.').pop()?.toLowerCase() ?? ''; | |
| if (!ALLOWED_EXTENSIONS.includes(ext)) { | |
| return `File "${file.name}" has unsupported extension ".${ext}". Allowed: .pdf, .jpg, .jpeg, .png, .tiff, .tif`; | |
| } | |
| return null; // No error | |
| } | |
| // ─── Chat Schema ────────────────────────────────────────────────────────────── | |
| export const chatSchema = z.object({ | |
| message: z | |
| .string() | |
| .min(1, 'Message cannot be empty') | |
| .max(500, 'Message must be at most 500 characters'), | |
| history: z | |
| .array( | |
| z.object({ | |
| role: z.enum(['user', 'assistant', 'system']), | |
| content: z.string(), | |
| }) | |
| ) | |
| .optional() | |
| .default([]), | |
| }); | |
| // ─── Invoice ID Schema ──────────────────────────────────────────────────────── | |
| export const invoiceIdSchema = z.object({ | |
| id: z.string().min(1, 'Invoice ID is required'), | |
| }); | |
| // ─── Helper: Get Client IP ──────────────────────────────────────────────────── | |
| export function getClientIp(request: Request): string { | |
| const forwarded = request.headers.get('x-forwarded-for'); | |
| if (forwarded) { | |
| return forwarded.split(',')[0].trim(); | |
| } | |
| const realIp = request.headers.get('x-real-ip'); | |
| if (realIp) return realIp.trim(); | |
| return 'unknown'; | |
| } |