refactor: replace timeZone string validation with timeZoneSchema (#20719)

* refactor: replace timeZone string validation with timeZoneSchema - Replace all instances of timeZone: z.string() with timeZoneSchema - Preserve modifiers (.optional(), .default(), .nullish()) where present - Fix VideoApiAdapter to use organizer's timezone value - Remove redundant isSupportedTimeZone import from booking.ts - Add timeZoneSchema import where needed

* Update index.ts

* fix: conflicts

Signed-off-by: Omar López <zomars@me.com>

* Update yarn.lock

* Discard changes to yarn.lock

* Update booking.ts

* Discard changes to packages/platform/types/me.ts

* Discard changes to packages/platform/types/me/outputs/me.ts

* Discard changes to packages/platform/types/schedules/schedules-2024-04-15/schedules.ts

* Discard changes to packages/features/ee/cal-ai-phone/zod-utils.ts

---------

Signed-off-by: Omar López <zomars@me.com>
This commit is contained in:
Omar López
2025-04-21 14:37:07 +01:00
committed by GitHub
parent 46c6582328
commit d81b905ad7
10 changed files with 31 additions and 11 deletions
+2 -1
View File
@@ -7,6 +7,7 @@ import { z } from "zod";
import dayjs from "@calcom/dayjs";
import { UserRepository } from "@calcom/lib/server/repository/user";
import { timeZoneSchema } from "@calcom/lib/dayjs/timeZone.schema";
import { userMetadata } from "@calcom/prisma/zod-utils";
import { CardComponent } from "@lib/plain/card-components";
@@ -443,7 +444,7 @@ const inputSchema = z.object({
name: z.string().optional(),
email: z.string().email(),
username: z.string().optional(),
timeZone: z.string().optional(),
timeZone: timeZoneSchema.optional(),
emailVerified: z.boolean().optional(),
identityProvider: z.string().optional(),
twoFactorEnabled: z.boolean().optional(),
@@ -6,6 +6,7 @@ import { Controller, useForm, useFormContext } from "react-hook-form";
import { z } from "zod";
import { TimezoneSelect } from "@calcom/features/components/timezone-select";
import { timeZoneSchema } from "@calcom/lib/dayjs/timeZone.schema";
import { emailSchema } from "@calcom/lib/emailSchema";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { MembershipRole } from "@calcom/prisma/enums";
@@ -58,7 +59,7 @@ const editSchema = z.object({
avatar: z.string(),
bio: z.string(),
role: z.enum([MembershipRole.MEMBER, MembershipRole.ADMIN, MembershipRole.OWNER]),
timeZone: z.string(),
timeZone: timeZoneSchema,
// schedules: z.array(z.string()),
// teams: z.array(z.string()),
attributes: z.array(attributeSchema).optional(),
+8
View File
@@ -0,0 +1,8 @@
import { z } from "zod";
import { isSupportedTimeZone } from "./index";
// Schema for validating IANA timezone strings compatible with Intl.DateTimeFormat
export const timeZoneSchema = z.string().refine((timeZone) => isSupportedTimeZone(timeZone), {
message: "Invalid timezone. Must be a valid IANA timezone string.",
});
+2 -2
View File
@@ -1,6 +1,6 @@
// `responses` is merged with it during handleNewBooking call because `responses` schema is dynamic and depends on eventType
import z, { ZodNullable, ZodObject, ZodOptional } from "zod";
import { isSupportedTimeZone } from "@calcom/lib/dayjs";
import { timeZoneSchema } from "@calcom/lib/dayjs/timeZone.schema";
// TODO: Move this out of here. Importing from app-store is a circular package dependency.
import { routingFormResponseInDbSchema } from "@calcom/app-store/routing-forms/zod";
@@ -12,7 +12,7 @@ export const bookingCreateBodySchema = z.object({
recurringEventId: z.string().optional(),
rescheduledBy: z.string().email({ message: "Invalid email" }).optional(),
start: z.string(),
timeZone: z.string().refine((value: string) => isSupportedTimeZone(value), { message: "Invalid timezone" }),
timeZone: timeZoneSchema,
user: z.union([z.string(), z.array(z.string())]).optional(),
language: z.string(),
bookingUid: z.string().optional(),
@@ -1,8 +1,10 @@
import { z } from "zod";
import { timeZoneSchema } from "@calcom/lib/dayjs/timeZone.schema";
export const ZUpdateInputSchema = z.object({
scheduleId: z.number(),
timeZone: z.string().optional(),
timeZone: timeZoneSchema.optional(),
name: z.string().optional(),
isDefault: z.boolean().optional(),
schedule: z
@@ -1,6 +1,7 @@
import { z } from "zod";
import { FULL_NAME_LENGTH_MAX_LIMIT } from "@calcom/lib/constants";
import { timeZoneSchema } from "@calcom/lib/dayjs/timeZone.schema";
import { bookerLayouts, userMetadata } from "@calcom/prisma/zod-utils";
export const updateUserMetadataAllowedKeys = z.object({
@@ -14,7 +15,7 @@ export const ZUpdateProfileInputSchema = z.object({
email: z.string().optional(),
bio: z.string().optional(),
avatarUrl: z.string().nullable().optional(),
timeZone: z.string().optional(),
timeZone: timeZoneSchema.optional(),
weekStart: z.string().optional(),
hideBranding: z.boolean().optional(),
allowDynamicBooking: z.boolean().optional(),
@@ -33,7 +34,7 @@ export const ZUpdateProfileInputSchema = z.object({
.array(
z.object({
id: z.number().optional(),
timeZone: z.string(),
timeZone: timeZoneSchema,
endDate: z.date().optional(),
startDate: z.date(),
})
@@ -1,5 +1,6 @@
import { z } from "zod";
import { timeZoneSchema } from "@calcom/lib/dayjs/timeZone.schema";
import { teamMetadataSchema } from "@calcom/prisma/zod-utils";
export const ZUpdateInputSchema = z.object({
@@ -24,7 +25,7 @@ export const ZUpdateInputSchema = z.object({
brandColor: z.string().optional(),
darkBrandColor: z.string().optional(),
theme: z.string().optional().nullable(),
timeZone: z.string().optional(),
timeZone: timeZoneSchema.optional(),
weekStart: z.string().optional(),
timeFormat: z.number().optional(),
metadata: teamMetadataSchema.unwrap().optional(),
@@ -1,5 +1,7 @@
import { z } from "zod";
import { timeZoneSchema } from "@calcom/lib/dayjs/timeZone.schema";
import { assignUserToAttributeSchema } from "../attributes/assignUserToAttribute.schema";
export const ZUpdateUserInputSchema = z.object({
@@ -10,7 +12,7 @@ export const ZUpdateUserInputSchema = z.object({
email: z.string().optional(),
avatar: z.string().optional(),
role: z.enum(["ADMIN", "MEMBER", "OWNER"]),
timeZone: z.string(),
timeZone: timeZoneSchema,
attributeOptions: assignUserToAttributeSchema.optional(),
});
@@ -1,6 +1,8 @@
import type { IncomingMessage } from "http";
import { z } from "zod";
import { timeZoneSchema } from "@calcom/lib/dayjs/timeZone.schema";
export const getScheduleSchema = z
.object({
// startTime ISOString
@@ -12,7 +14,7 @@ export const getScheduleSchema = z
// Event type slug
eventTypeSlug: z.string().optional(),
// invitee timezone
timeZone: z.string().optional(),
timeZone: timeZoneSchema.optional(),
// or list of users (for dynamic events)
usernameList: z.array(z.string()).min(1).optional(),
debug: z.boolean().optional(),
@@ -1,9 +1,11 @@
import { z } from "zod";
import { timeZoneSchema } from "@calcom/lib/dayjs/timeZone.schema";
export const ZGetMemberAvailabilityInputSchema = z.object({
teamId: z.number(),
memberId: z.number(),
timezone: z.string(),
timezone: timeZoneSchema,
dateFrom: z.string(),
dateTo: z.string(),
});