aboutsummaryrefslogtreecommitdiff
path: root/src/lib/validation.ts
diff options
context:
space:
mode:
authorschererleander <leander@schererleander.de>2025-07-02 22:17:57 +0200
committerschererleander <leander@schererleander.de>2025-07-02 22:17:57 +0200
commitab03900adf080da08a0b2a3628fd0dcf0af28420 (patch)
treea54ddb49b949929c5c6b4b0bd2b7ca5c504da54d /src/lib/validation.ts
parent198f95f079078e60e05d1ea6607ee14f79721a7e (diff)
feat: add libraries and utilities
Diffstat (limited to 'src/lib/validation.ts')
-rw-r--r--src/lib/validation.ts72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/lib/validation.ts b/src/lib/validation.ts
new file mode 100644
index 0000000..02983e4
--- /dev/null
+++ b/src/lib/validation.ts
@@ -0,0 +1,72 @@
+import { z } from 'zod'
+
+export const registerSchema = z.object({
+ name: z
+ .string()
+ .trim()
+ .min(2, 'Name must be at least 2 characters')
+ .max(50, 'Name must be at most 50 characters')
+ .regex(/^[a-zA-Z\s'-]+$/, 'Name can only contain letters, spaces, hyphens, and apostrophes'),
+ email: z
+ .string()
+ .trim()
+ .toLowerCase()
+ .email('Invalid email format')
+ .max(254, 'Email must be at most 254 characters'),
+ password: z
+ .string()
+ .min(8, 'Password must be at least 8 characters')
+ .max(128, 'Password must be at most 128 characters')
+ .regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$/,
+ 'Password must contain at least one uppercase letter, one lowercase letter, and one number')
+})
+
+export const loginSchema = z.object({
+ email: z
+ .string()
+ .trim()
+ .toLowerCase()
+ .email('Invalid email format')
+ .max(254, 'Email must be at most 254 characters'),
+ password: z
+ .string()
+ .max(128, 'Password must be at most 128 characters')
+})
+
+// Profile update schema (reusing name and email from registerSchema)
+export const updateProfileSchema = z.object({
+ name: registerSchema.shape.name,
+ email: registerSchema.shape.email,
+})
+
+// Password change schema (reusing password validation from registerSchema)
+export const updatePasswordSchema = z.object({
+ currentPassword: z.string().min(1, 'Current password is required'),
+ newPassword: registerSchema.shape.password,
+})
+
+// Type inference from schemas
+export type RegisterInput = z.infer<typeof registerSchema>
+export type LoginInput = z.infer<typeof loginSchema>
+export type UpdateProfileInput = z.infer<typeof updateProfileSchema>
+export type UpdatePasswordInput = z.infer<typeof updatePasswordSchema>
+
+export const emailSchema = z.object({
+ email: z
+ .string()
+ .trim()
+ .toLowerCase()
+ .email('Invalid email format')
+ .max(254, 'Email must be at most 254 characters')
+})
+
+export function formatZodError(error: z.ZodError) {
+ return error.errors.map(err => ({
+ field: err.path.join('.'),
+ message: err.message
+ }))
+}
+
+export function getFirstErrorMessage(error: z.ZodError): string {
+ return error.errors[0]?.message || 'Validation failed'
+} \ No newline at end of file