import { UserRoleMap } from "../../../core/enums"; import { paginationModel } from "../../../core/pagination.utils"; import { encodeCursor } from "../../../core/string.utils"; import z from "zod"; const usernameModel = z .string() .min(2) .max(128) .regex(/^[a-zA-Z0-9_-]+$/, { message: "Username can only contain letters, numbers, underscores, and hyphens.", }); export const emailModel = z.string().email().min(5).max(128); export const discountPercentModel = z .number() .min(0) .max(100) .default(0) .nullish(); const roleModel = z.enum(Object.values(UserRoleMap) as [string, ...string[]]); export const createUserPayloadModel = z.object({ username: usernameModel, email: emailModel, password: z.string().min(8).max(128), role: roleModel, }); export type CreateUserPayloadModel = z.infer; export type GetUserByPayload = { id?: string; username?: string }; export const updateUserInfoInputModel = z.object({ email: emailModel, username: usernameModel, discountPercent: discountPercentModel, banned: z.boolean().nullable().optional(), }); export type UpdateUserInfoInputModel = z.infer; export const userModel = updateUserInfoInputModel.merge( z.object({ id: z.coerce.string(), role: roleModel.nullable().optional(), discountPercent: discountPercentModel, createdAt: z.coerce.date(), updatedAt: z.coerce.date(), parentId: z.coerce.string().nullable().optional(), }), ); export type UserModel = z.infer; export const limitedUserModel = userModel.pick({ id: true, username: true, email: true, }); export type LimitedUserModel = z.infer; export const userFullModel = userModel.merge( z.object({ banned: z.boolean(), banReason: z.string().optional(), banExpires: z.date().optional(), twoFactorEnabled: z.boolean().default(false), }), ); export type UserFullModel = z.infer; export const usersCursorModel = z.object({ firstItemUsername: z.string(), lastItemUsername: z.string(), query: z.string().default(""), }); export type UsersCursorModel = z.infer; export function getDefaultUsersCursor() { return usersCursorModel.parse({ firstItemUsername: "", lastItemUsername: "", query: "", }); } export const paginatedUserModel = paginationModel.merge( z.object({ data: z.array(userModel) }), ); export type PaginatedUserModel = z.infer; export function getDefaultPaginatedUserModel(): PaginatedUserModel { return { data: [], cursor: encodeCursor(getDefaultUsersCursor()), limit: 20, asc: true, totalItemCount: 0, totalPages: 0, page: 0, }; }