Midday / apps /api /src /schemas /users.ts
Jules
Final deployment with all fixes and verified content
c09f67c
import { z } from "@hono/zod-openapi";
import { isValidTimezone } from "@midday/location/timezones";
export const updateUserSchema = z.object({
fullName: z.string().min(2).max(32).optional().openapi({
description: "Full name of the user. Must be between 2 and 32 characters",
example: "Jane Doe",
}),
teamId: z.string().optional().openapi({
description: "Unique identifier of the team the user belongs to",
example: "team-abc123",
}),
email: z.string().email().optional().openapi({
description: "Email address of the user",
example: "jane.doe@acme.com",
}),
avatarUrl: z
.string()
.url()
.refine((url) => url.includes("midday.ai"), {
message: "avatarUrl must be a midday.ai domain URL",
})
.optional()
.openapi({
description:
"URL to the user's avatar image. Must be hosted on midday.ai domain",
example: "https://cdn.midday.ai/avatars/jane-doe.jpg",
}),
locale: z.string().optional().openapi({
description:
"User's preferred locale for internationalization (language and region)",
example: "en-US",
}),
weekStartsOnMonday: z.boolean().optional().openapi({
description:
"Whether the user's calendar week starts on Monday (true) or Sunday (false)",
example: true,
}),
timezone: z
.string()
.refine(isValidTimezone, {
message:
"Invalid timezone. Use IANA timezone format (e.g., 'America/New_York', 'UTC')",
})
.optional()
.openapi({
description:
"User's timezone identifier in IANA Time Zone Database format",
example: "America/New_York",
}),
timezoneAutoSync: z.boolean().optional().openapi({
description: "Whether to automatically sync timezone with browser timezone",
example: true,
}),
timeFormat: z.number().optional().openapi({
description:
"User's preferred time format: 12 for 12-hour format, 24 for 24-hour format",
example: 24,
}),
dateFormat: z
.enum(["dd/MM/yyyy", "MM/dd/yyyy", "yyyy-MM-dd", "dd.MM.yyyy"])
.optional()
.openapi({
description:
"User's preferred date format. Available options: 'dd/MM/yyyy', 'MM/dd/yyyy', 'yyyy-MM-dd', 'dd.MM.yyyy'",
example: "yyyy-MM-dd",
"x-speakeasy-enums": [
"ddSlashMMSlashyyyy",
"MMSlashddSlashyyyy",
"yyyyDashMMDashdd",
"ddDotMMDotyyyy",
],
}),
});
export const userSchema = z.object({
id: z.string().uuid().openapi({
description: "Unique identifier of the user",
example: "123e4567-e89b-12d3-a456-426614174000",
}),
fullName: z.string().openapi({
description: "Full name of the user",
example: "Jane Doe",
}),
email: z.string().email().openapi({
description: "Email address of the user",
example: "jane.doe@acme.com",
}),
avatarUrl: z.string().url().nullable().openapi({
description: "URL to the user's avatar image",
example: "https://cdn.midday.ai/avatars/jane-doe.jpg",
}),
locale: z.string().nullable().openapi({
description:
"User's preferred locale for internationalization (language and region)",
example: "en-US",
}),
weekStartsOnMonday: z.boolean().nullable().openapi({
description:
"Whether the user's calendar week starts on Monday (true) or Sunday (false)",
example: true,
}),
timezone: z.string().nullable().openapi({
description: "User's timezone identifier in IANA Time Zone Database format",
example: "America/New_York",
}),
timezoneAutoSync: z.boolean().nullable().openapi({
description: "Whether to automatically sync timezone with browser timezone",
example: true,
}),
timeFormat: z.number().nullable().openapi({
description:
"User's preferred time format: 12 for 12-hour format, 24 for 24-hour format",
example: 24,
}),
dateFormat: z
.enum(["dd/MM/yyyy", "MM/dd/yyyy", "yyyy-MM-dd", "dd.MM.yyyy"])
.nullable()
.openapi({
description:
"User's preferred date format. Available options: 'dd/MM/yyyy', 'MM/dd/yyyy', 'yyyy-MM-dd', 'dd.MM.yyyy'",
example: "yyyy-MM-dd",
"x-speakeasy-enums": [
"ddSlashMMSlashyyyy",
"MMSlashddSlashyyyy",
"yyyyDashMMDashdd",
"ddDotMMDotyyyy",
],
}),
fileKey: z.string().nullable().openapi({
description:
"Team file key (JWT token) for proxy/download access to team files. This compact JWT token contains the team ID and is shared by all team members. Use this token as the `fk` query parameter when accessing file endpoints (proxy, download). The token is team-scoped and provides access to files belonging to the user's team. Returns null if the user has no team.",
example:
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZWFtSWQiOiIxMjM0NTY3OC05YWJjLWRlZmctMTIzNC01Njc4OTBhYmNkZWYifQ.signature",
}),
team: z
.object({
id: z.string().uuid().openapi({
description: "Unique identifier of the team",
example: "123e4567-e89b-12d3-a456-426614174000",
}),
name: z.string().openapi({
description: "Name of the team or organization",
example: "Acme Corporation",
}),
logoUrl: z.string().url().openapi({
description: "URL to the team's logo image",
example: "https://cdn.midday.ai/logos/acme-corp.png",
}),
plan: z.string().openapi({
description: "Current subscription plan of the team",
example: "pro",
}),
})
.nullable()
.openapi({
description: "Team information that the user belongs to",
}),
});