UNPKG

@battle-racing/br-common-lib

Version:

Common library for all Battle Racing Repositorios

111 lines (91 loc) 3.13 kB
import { z } from 'zod'; import { userRoleSchema } from '../role'; import { USER_TYPE } from './User.const'; export const userTypeSchema = z.enum(USER_TYPE); export const PHONE_REGEX = /^([+]?[\\s0-9]+)?(\\d{3}|[(]?[0-9]+[)])?([-]?[\\s]?[0-9])+$/; const MIN_PASSWORD_LENGTH = 6; export const emailOrPhoneSchema = z .string() .min(1, 'Email or phone is required') .refine( (val) => { const isEmail = z.email().safeParse(val).success; const isPhone = PHONE_REGEX.test(val); return isEmail || isPhone; }, { message: 'Must be a valid email or phone number' }, ); const baseUserObj = z.object({ id: z.uuidv4(), name: z.string(), lastName: z.string(), email: z.email().toLowerCase().optional().nullable(), phoneNumber: z.string().regex(PHONE_REGEX, 'Invalid phone number format').optional().nullable(), // --- ACCESS CONTROL --- role: userRoleSchema, type: userTypeSchema, isActive: z.boolean().default(true), // TODO: Implement mechanism to validate users later by email or phone isEmailVerified: z.boolean().default(false), isPhoneVerified: z.boolean().default(false), defaultPlayerId: z.uuidv4().optional(), createdAt: z.date(), lastLoginAt: z.date().optional(), }); export const userSchema = baseUserObj.refine((data) => data.email || data.phoneNumber, { message: 'User must have either an email or a phone number', path: ['email', 'phoneNumber'], }); /** * The schema for the user returned on login */ export const authUserSchema = baseUserObj.extend({ authToken: z.string(), }); export const userWithPasswordSchema = userSchema.and( z.object({ password: z.string().min(MIN_PASSWORD_LENGTH), }), ); export const userInitialRegistrationSchema = z.object({ emailOrPhone: emailOrPhoneSchema, password: z.string().min(MIN_PASSWORD_LENGTH, `Password must be at least ${MIN_PASSWORD_LENGTH} characters`), }); export const userVerifySchema = z.object({ emailOrPhone: emailOrPhoneSchema, code: z.string().min(6, 'Code must be at least 6 characters').max(10, 'Code is too long'), }); export const userCompleteProfileSchema = baseUserObj .pick({ name: true, }) .extend({ lastName: z.string().optional(), nickname: z.string().min(2), birthDate: z.coerce.date(), waiverSignature: z.boolean().refine((val) => val === true, { message: 'You must accept the waiver signature', }), teamName: z.string().optional(), }); // Deprecated in favor of multi-step registration export const userRegistrationInputSchema = baseUserObj .pick({ name: true, lastName: true, email: true, phoneNumber: true, }) .extend({ password: z.string().min(6), nickname: z.string().min(2), birthDate: z.coerce.date(), }) .refine((data) => data.email || data.phoneNumber, { message: 'User must have either an email or a phone number', path: ['email', 'phoneNumber'], }); export const userLoginInputSchema = z.object({ emailOrPhone: emailOrPhoneSchema, password: z.string().min(MIN_PASSWORD_LENGTH, `Password must be at least ${MIN_PASSWORD_LENGTH} characters`), });