import { buildJsonSchemas } from "fastify-zod"; import mongoose, { InferSchemaType } from "mongoose"; import { z } from "zod"; import { roles } from "../utils/roles"; const userSchema = new mongoose.Schema({ tenantId: { type: String, required: true, }, pid: { type: String, unique: true, required: true, }, orgId: mongoose.Types.ObjectId, firstName: String, lastName: String, name: String, email: { type: String, unique: true, required: true, }, avatar: String, status: String, role: { type: String, required: true, }, defaultClient: { type: mongoose.Types.ObjectId, ref: "organization", }, passKeys: [new mongoose.Schema({}, { _id: false, strict: false })], challenge: new mongoose.Schema( { value: String, expiry: Date, }, { _id: false } ), token: new mongoose.Schema( { value: String, expiry: Date, }, { _id: false } ), createdAt: Date, createdBy: mongoose.Types.ObjectId, lastLogin: Date, }); export const userModel = mongoose.model("user", userSchema); export type User = InferSchemaType; const userCore = { firstName: z.string().max(30), lastName: z.string().max(30), email: z .string({ required_error: "Email is required", invalid_type_error: "Email must be a valid string", }) .email(), avatar: z.string().optional(), role: z.enum(roles), orgId: z.string().optional(), }; const createUserInput = z .object({ ...userCore, }) .superRefine((data, ctx) => { if (data.role == "builder" && !data.orgId) { ctx.addIssue({ path: ["orgId"], message: 'orgId is required when role is "builder"', code: z.ZodIssueCode.custom, }); } }); const updateUserInput = z.object({ firstName: z.string().max(30).optional(), lastName: z.string().max(30).optional(), email: z .string({ required_error: "Email is required", invalid_type_error: "Email must be a valid string", }) .email() .optional(), avatar: z.string().url().optional(), role: z.enum(roles).optional(), defaultClient: z.string().optional(), }); const userResponse = z.object({ _id: z.string(), pid: z.string(), orgId: z.string().optional(), firstName: z.string().optional(), lastName: z.string().optional(), name: z.string().optional(), email: z.string().optional(), role: z.string().optional(), avatar: z.string().optional(), status: z.string().optional(), createdAt: z.string().optional(), createdBy: z.string().optional(), lastLogin: z.string().optional(), }); export type CreateUserInput = z.infer; export type UpdateUserInput = z.infer; export const { schemas: userSchemas, $ref: $user } = buildJsonSchemas( { createUserInput, updateUserInput, userResponse, }, { $id: "user" } );