2022-01-21 18:35:31 -03:00
|
|
|
import { z } from "zod";
|
|
|
|
|
2022-07-26 21:45:10 -03:00
|
|
|
import { LocationType } from "@calcom/app-store/locations";
|
2022-06-28 17:40:58 -03:00
|
|
|
import dayjs from "@calcom/dayjs";
|
2022-02-21 15:45:35 -03:00
|
|
|
import { slugify } from "@calcom/lib/slugify";
|
2022-01-21 18:35:31 -03:00
|
|
|
|
2022-06-09 21:32:34 -03:00
|
|
|
// Let's not import 118kb just to get an enum
|
|
|
|
export enum Frequency {
|
|
|
|
YEARLY = 0,
|
|
|
|
MONTHLY = 1,
|
|
|
|
WEEKLY = 2,
|
|
|
|
DAILY = 3,
|
|
|
|
HOURLY = 4,
|
|
|
|
MINUTELY = 5,
|
|
|
|
SECONDLY = 6,
|
|
|
|
}
|
|
|
|
|
2022-01-21 18:35:31 -03:00
|
|
|
export const eventTypeLocations = z.array(
|
2022-03-13 12:56:56 -03:00
|
|
|
z.object({
|
2022-08-25 21:48:50 -03:00
|
|
|
// TODO: Couldn't find a way to make it a union of types from App Store locations
|
|
|
|
// Creating a dynamic union by iterating over the object doesn't seem to make TS happy
|
|
|
|
type: z.string(),
|
2022-03-13 12:56:56 -03:00
|
|
|
address: z.string().optional(),
|
|
|
|
link: z.string().url().optional(),
|
2022-05-25 17:34:08 -03:00
|
|
|
displayLocationPublicly: z.boolean().optional(),
|
2022-05-16 12:50:12 -03:00
|
|
|
hostPhoneNumber: z.string().optional(),
|
2022-03-13 12:56:56 -03:00
|
|
|
})
|
2022-01-21 18:35:31 -03:00
|
|
|
);
|
|
|
|
|
2022-05-05 18:16:25 -03:00
|
|
|
// Matching RRule.Options: rrule/dist/esm/src/types.d.ts
|
2022-06-09 21:32:34 -03:00
|
|
|
export const recurringEventType = z
|
|
|
|
.object({
|
|
|
|
dtstart: z.date().optional(),
|
|
|
|
interval: z.number(),
|
|
|
|
count: z.number(),
|
|
|
|
freq: z.nativeEnum(Frequency),
|
|
|
|
until: z.date().optional(),
|
|
|
|
tzid: z.string().optional(),
|
|
|
|
})
|
|
|
|
.nullable();
|
2022-05-05 18:16:25 -03:00
|
|
|
|
2022-02-21 13:53:16 -03:00
|
|
|
export const eventTypeSlug = z.string().transform((val) => slugify(val.trim()));
|
2022-06-09 21:32:34 -03:00
|
|
|
|
2022-01-21 18:35:31 -03:00
|
|
|
export const stringToDate = z.string().transform((a) => new Date(a));
|
2022-06-09 21:32:34 -03:00
|
|
|
|
|
|
|
export const stringOrNumber = z.union([
|
|
|
|
z.string().transform((v, ctx) => {
|
|
|
|
const parsed = parseInt(v);
|
|
|
|
if (isNaN(parsed)) {
|
|
|
|
ctx.addIssue({
|
|
|
|
code: z.ZodIssueCode.custom,
|
|
|
|
message: "Not a number",
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return parsed;
|
|
|
|
}),
|
|
|
|
z.number().int(),
|
|
|
|
]);
|
|
|
|
|
|
|
|
export const stringToDayjs = z.string().transform((val) => dayjs(val));
|
2022-06-10 15:38:46 -03:00
|
|
|
|
|
|
|
export const bookingCreateBodySchema = z.object({
|
|
|
|
email: z.string(),
|
|
|
|
end: z.string(),
|
|
|
|
web3Details: z
|
|
|
|
.object({
|
|
|
|
userWallet: z.string(),
|
|
|
|
userSignature: z.string(),
|
|
|
|
})
|
|
|
|
.optional(),
|
|
|
|
eventTypeId: z.number(),
|
2022-06-11 18:30:52 -03:00
|
|
|
eventTypeSlug: z.string().optional(),
|
2022-06-10 15:38:46 -03:00
|
|
|
guests: z.array(z.string()).optional(),
|
|
|
|
location: z.string(),
|
|
|
|
name: z.string(),
|
|
|
|
notes: z.string().optional(),
|
|
|
|
rescheduleUid: z.string().optional(),
|
|
|
|
recurringEventId: z.string().optional(),
|
|
|
|
start: z.string(),
|
|
|
|
timeZone: z.string(),
|
|
|
|
user: z.union([z.string(), z.array(z.string())]).optional(),
|
|
|
|
language: z.string(),
|
|
|
|
bookingUid: z.string().optional(),
|
|
|
|
customInputs: z.array(z.object({ label: z.string(), value: z.union([z.string(), z.boolean()]) })),
|
|
|
|
metadata: z.record(z.string()),
|
2022-06-11 18:30:52 -03:00
|
|
|
hasHashedBookingLink: z.boolean().optional(),
|
2022-06-10 15:38:46 -03:00
|
|
|
hashedLink: z.string().nullish(),
|
|
|
|
});
|
|
|
|
|
2022-06-11 18:30:52 -03:00
|
|
|
export type BookingCreateBody = z.input<typeof bookingCreateBodySchema>;
|
|
|
|
|
2022-08-26 18:58:08 -03:00
|
|
|
export const bookingConfirmPatchBodySchema = z.object({
|
|
|
|
bookingId: z.number(),
|
|
|
|
confirmed: z.boolean(),
|
|
|
|
recurringEventId: z.string().optional(),
|
|
|
|
reason: z.string().optional(),
|
|
|
|
});
|
|
|
|
|
2022-06-10 15:38:46 -03:00
|
|
|
export const extendedBookingCreateBody = bookingCreateBodySchema.merge(
|
|
|
|
z.object({
|
|
|
|
noEmail: z.boolean().optional(),
|
|
|
|
recurringCount: z.number().optional(),
|
|
|
|
rescheduleReason: z.string().optional(),
|
2022-07-13 21:10:45 -03:00
|
|
|
smsReminderNumber: z.string().optional(),
|
2022-06-10 15:38:46 -03:00
|
|
|
})
|
|
|
|
);
|
2022-06-14 17:07:54 -03:00
|
|
|
|
|
|
|
export const vitalSettingsUpdateSchema = z.object({
|
|
|
|
connected: z.boolean().optional(),
|
|
|
|
selectedParam: z.string().optional(),
|
|
|
|
sleepValue: z.number().optional(),
|
|
|
|
});
|
|
|
|
|
|
|
|
export const userMetadata = z
|
|
|
|
.object({
|
2022-06-16 16:33:23 -03:00
|
|
|
proPaidForByTeamId: z.number().optional(),
|
2022-06-14 17:07:54 -03:00
|
|
|
stripeCustomerId: z.string().optional(),
|
|
|
|
vitalSettings: vitalSettingsUpdateSchema.optional(),
|
2022-07-06 16:31:07 -03:00
|
|
|
isPremium: z.boolean().optional(),
|
|
|
|
intentUsername: z.string().optional(),
|
2022-06-14 17:07:54 -03:00
|
|
|
})
|
|
|
|
.nullable();
|
2022-08-01 18:44:08 -03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Ensures that it is a valid HTTP URL
|
|
|
|
* It automatically avoids
|
|
|
|
* - XSS attempts through javascript:alert('hi')
|
|
|
|
* - mailto: links
|
|
|
|
*/
|
|
|
|
export const successRedirectUrl = z
|
2022-08-01 21:45:47 -03:00
|
|
|
.union([
|
|
|
|
z.literal(""),
|
|
|
|
z
|
|
|
|
.string()
|
|
|
|
.url()
|
|
|
|
.regex(/^http(s)?:\/\/.*/),
|
|
|
|
])
|
|
|
|
.optional();
|