2
0

first commit

This commit is contained in:
2024-08-09 00:39:27 +02:00
commit 79688abe2e
5698 changed files with 497838 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
declare module "@wojtekmaj/react-daterange-picker/dist/entry.nostyle" {
import { CalendarProps } from "react-calendar";
export type DateRangePickerCalendarProps = Omit<
CalendarProps,
"calendarClassName" | "onChange" | "value"
> & {
calendarClassName?: string;
onChange: (value: [Date, Date]) => void;
value: [Date, Date];
clearIcon: JSX.Element | null;
calendarIcon: JSX.Element | null;
rangeDivider: JSX.Element | null;
disabled?: boolean | null;
nextLabel?: JSX.Element | null;
prevLabel?: JSX.Element | null;
};
export default function DateRangePicker(props: DateRangePickerCalendarProps): JSX.Element;
}

184
calcom/packages/types/App.d.ts vendored Normal file
View File

@@ -0,0 +1,184 @@
import type { AppCategories, Prisma } from "@prisma/client";
import type { Tag } from "@calcom/app-store/types";
type CommonProperties = {
default?: false;
type: string;
label: string;
messageForOrganizer?: string;
iconUrl?: string;
variable?: "locationLink";
defaultValueVariable?: "link";
attendeeInputType?: null;
attendeeInputPlaceholder?: null;
};
type StaticLinkBasedEventLocation = {
linkType: "static";
urlRegExp: string;
organizerInputPlaceholder?: string;
organizerInputType?: "text" | "phone";
} & CommonProperties;
type DynamicLinkBasedEventLocation = {
linkType: "dynamic";
urlRegExp?: null;
organizerInputType?: null;
organizerInputPlaceholder?: null;
} & CommonProperties;
export type EventLocationTypeFromAppMeta = StaticLinkBasedEventLocation | DynamicLinkBasedEventLocation;
type PaidAppData = {
priceInUsd: number;
priceId: string;
trial?: number;
mode?: "subscription" | "one_time";
};
type AppData = {
/**
* TODO: We must assert that if `location` is set in App config.json, then it must have atleast Messaging or Conferencing as a category.
* This is because we fetch only those credentials(as an optimization) which match that category.
*/
location?: EventLocationTypeFromAppMeta;
tag?: Tag;
} | null;
/**
* This is the definition for an app store's app metadata.
* This is used to display App info, categorize or hide certain apps in the app store.
*/
export interface App {
/**
* @deprecated
* Whether if the app is installed or not. Usually we check for api keys in env
* variables to determine if this is true or not.
* */
installed?: boolean;
/** The app type */
type:
| `${string}_calendar`
| `${string}_messaging`
| `${string}_payment`
| `${string}_video`
| `${string}_other`
| `${string}_automation`
| `${string}_analytics`
| `${string}_crm`
| `${string}_other_calendar`;
/**
* @deprecated
*
* Use name instead. Remove this property after ensuring name has the required value everywhere
* */
title?: string;
/** The display name for the app */
name: string;
/** A brief description, usually found in the app's package.json */
description: string;
/** TODO determine if we should use this instead of category */
variant:
| "calendar"
| "payment"
| "conferencing"
| "video"
| "other"
| "other_calendar"
| "automation"
| "crm";
/** The slug for the app store public page inside `/apps/[slug] */
slug: string;
/** The category to which this app belongs. Remove all usages of category and then remove the prop */
/*
* @deprecated Use categories
*/
category?: string;
/** The category to which this app belongs. */
/**
* Messaging and Conferencing(Earlier called Video) are considered location apps and are fetched when configuring an event-type location.
*/
categories: AppCategories[];
/**
* `User` is the broadest category. `EventType` is when you want to add features to EventTypes.
* See https://app.gitbook.com/o/6snd8PyPYMhg0wUw6CeQ/s/VXRprBTuMlihk37NQgUU/~/changes/6xkqZ4qvJ3Xh9k8UaWaZ/engineering/product-specs/app-store#user-apps for more details
*/
extendsFeature?: "EventType" | "User";
/** An absolute url to the app logo */
logo: string;
/** Company or individual publishing this app */
publisher: string;
/** App's website */
url: string;
/** Optional documentation website URL */
docsUrl?: string;
/** Wether if the app is verified by Cal.com or not */
verified?: boolean;
/** Wether the app should appear in the trending section of the app store */
trending?: boolean;
/** Rating from 0 to 5, harcoded for now. Should be fetched later on. */
rating?: number;
/** Number of reviews, harcoded for now. Should be fetched later on. */
reviews?: number;
/**
* Whether if the app is installed globally or needs user intervention.
* Used to show Connect/Disconnect buttons in App Store
* */
isGlobal?: boolean;
/**
* For apps that are accessible on an alternate URL(which is simpler and shorter), this can be set.
* e.g. Routing Forms App is available as /routing-forms in addition to regular /apps/routing-forms.
*/
simplePath?: string;
/** A contact email, mainly to ask for support */
email: string;
/** Needed API Keys (usually for global apps) */
key?: Prisma.JsonValue;
/** If not free, what kind of fees does the app have */
feeType?: "monthly" | "usage-based" | "one-time" | "free";
/** 0 = free. if type="usage-based" it's the price per booking */
price?: number;
/** only required for "usage-based" billing. % of commission for paid bookings */
commission?: number;
licenseRequired?: boolean;
teamsPlanRequired?: {
upgradeUrl: string;
};
appData?: AppData;
/** Represents paid app data, such as price, trials, etc */
paid?: PaidAppData;
/**
* @deprecated
* Used only by legacy apps which had slug different from their directory name.
*/
dirName?: string;
isTemplate?: boolean;
__template?: string;
/** Slug of an app needed to be installed before the current app can be added */
dependencies?: string[];
/** Enables video apps to be used for team events. Non Video/Conferencing apps don't honor this as they support team installation always. */
concurrentMeetings?: boolean;
createdAt?: string;
/** Specifies if the App uses an OAuth flow */
isOAuth?: boolean;
}
export type AppFrontendPayload = Omit<App, "key"> & {
/** We should type error if keys are leaked to the frontend */
isDefault?: boolean;
key?: never;
dependencyData?: {
name?: string;
installed?: boolean;
}[];
/** Number of users who currently have this App installed */
installCount?: number;
};
export type AppMeta = App;

View File

@@ -0,0 +1,19 @@
import type { GetServerSidePropsContext, GetServerSidePropsResult } from "next";
import type { CalendsoSessionUser } from "next-auth";
import type prisma from "@calcom/prisma";
import type { ssrInit } from "@server/lib/ssr";
export type AppUser = CalendsoSessionUser | undefined;
export type AppPrisma = typeof prisma;
export type AppGetServerSidePropsContext = GetServerSidePropsContext<{
appPages: string[];
}>;
export type AppSsrInit = ssrInit;
export type AppGetServerSideProps = (
context: AppGetServerSidePropsContext,
prisma: AppPrisma,
user: AppUser,
ssrInit: AppSsrInit
) => GetServerSidePropsResult;

24
calcom/packages/types/AppHandler.d.ts vendored Normal file
View File

@@ -0,0 +1,24 @@
import type { NextApiHandler } from "next";
import type { Session } from "next-auth";
import type { Credential } from "@calcom/prisma/client";
export type AppDeclarativeHandler = {
appType: string;
slug: string;
variant: string;
supportsMultipleInstalls: false;
handlerType: "add";
createCredential: (arg: {
user: Session["user"];
appType: string;
slug: string;
teamId?: number;
}) => Promise<Credential>;
supportsMultipleInstalls: boolean;
redirect?: {
newTab?: boolean;
url: string;
};
};
export type AppHandler = AppDeclarativeHandler | NextApiHandler;

View File

@@ -0,0 +1,4 @@
export interface BufferedBusyTime {
start: string | Date;
end: string | Date;
}

265
calcom/packages/types/Calendar.d.ts vendored Normal file
View File

@@ -0,0 +1,265 @@
import type { BookingSeat, DestinationCalendar, Prisma, SelectedCalendar } from "@prisma/client";
import type { Dayjs } from "dayjs";
import type { calendar_v3 } from "googleapis";
import type { Time } from "ical.js";
import type { TFunction } from "next-i18next";
import type z from "zod";
import type { bookingResponse } from "@calcom/features/bookings/lib/getBookingResponsesSchema";
import type { Calendar } from "@calcom/features/calendars/weeklyview";
import type { TimeFormat } from "@calcom/lib/timeFormat";
import type { SchedulingType } from "@calcom/prisma/enums";
import type { Frequency } from "@calcom/prisma/zod-utils";
import type { CredentialPayload } from "@calcom/types/Credential";
import type { Ensure } from "./utils";
export type { VideoCallData } from "./VideoApiAdapter";
type PaymentInfo = {
link?: string | null;
reason?: string | null;
id?: string | null;
paymentOption?: string | null;
amount?: number;
currency?: string;
};
export type Person = {
name: string;
email: string;
timeZone: string;
language: { translate: TFunction; locale: string };
username?: string;
id?: number;
bookingId?: number | null;
locale?: string | null;
timeFormat?: TimeFormat;
bookingSeat?: BookingSeat | null;
};
export type TeamMember = {
id?: number;
name: string;
email: string;
timeZone: string;
language: { translate: TFunction; locale: string };
};
export type EventBusyDate = {
start: Date | string;
end: Date | string;
source?: string | null;
};
export type EventBusyDetails = EventBusyDate & {
title?: string;
source?: string | null;
userId?: number | null;
};
export type CalendarServiceType = typeof Calendar;
export type AdditionalInfo = Record<string, unknown> & { calWarnings?: string[] };
export type NewCalendarEventType = {
uid: string;
id: string;
thirdPartyRecurringEventId?: string | null;
type: string;
password: string;
url: string;
additionalInfo: AdditionalInfo;
iCalUID?: string | null;
location?: string | null;
hangoutLink?: string | null;
conferenceData?: ConferenceData;
};
export type CalendarEventType = {
uid: string;
etag: string;
/** This is the actual caldav event url, not the location url. */
url: string;
summary: string;
description: string;
location: string;
sequence: number;
startDate: Date | Dayjs;
endDate: Date | Dayjs;
duration: {
weeks: number;
days: number;
hours: number;
minutes: number;
seconds: number;
isNegative: boolean;
};
organizer: string;
attendees: any[][];
recurrenceId: Time;
timezone: any;
};
export type BatchResponse = {
responses: SubResponse[];
};
export type SubResponse = {
body: {
value: {
showAs: "free" | "tentative" | "away" | "busy" | "workingElsewhere";
start: { dateTime: string };
end: { dateTime: string };
}[];
};
};
export interface ConferenceData {
createRequest?: calendar_v3.Schema$CreateConferenceRequest;
}
export interface RecurringEvent {
dtstart?: Date | undefined;
interval: number;
count: number;
freq: Frequency;
until?: Date | undefined;
tzid?: string | undefined;
}
export type IntervalLimitUnit = "day" | "week" | "month" | "year";
export type IntervalLimit = Partial<Record<`PER_${Uppercase<IntervalLimitUnit>}`, number | undefined>>;
export type AppsStatus = {
appName: string;
type: (typeof App)["type"];
success: number;
failures: number;
errors: string[];
warnings?: string[];
};
export type CalEventResponses = Record<
string,
{
label: string;
value: z.infer<typeof bookingResponse>;
isHidden?: boolean;
}
>;
export interface ExistingRecurringEvent {
recurringEventId: string;
}
// If modifying this interface, probably should update builders/calendarEvent files
export interface CalendarEvent {
// Instead of sending this per event.
// TODO: Links sent in email should be validated and automatically redirected to org domain or regular app. It would be a much cleaner way. Maybe use existing /api/link endpoint
bookerUrl?: string;
type: string;
title: string;
startTime: string;
endTime: string;
organizer: Person;
attendees: Person[];
additionalNotes?: string | null;
customInputs?: Prisma.JsonObject | null;
description?: string | null;
team?: {
name: string;
members: TeamMember[];
id: number;
};
location?: string | null;
conferenceCredentialId?: number;
conferenceData?: ConferenceData;
additionalInformation?: AdditionalInformation;
uid?: string | null;
existingRecurringEvent?: ExistingRecurringEvent | null;
bookingId?: number;
videoCallData?: VideoCallData;
paymentInfo?: PaymentInfo | null;
requiresConfirmation?: boolean | null;
destinationCalendar?: DestinationCalendar[] | null;
cancellationReason?: string | null;
rejectionReason?: string | null;
hideCalendarNotes?: boolean;
recurrence?: string;
recurringEvent?: RecurringEvent | null;
eventTypeId?: number | null;
appsStatus?: AppsStatus[];
seatsShowAttendees?: boolean | null;
seatsShowAvailabilityCount?: boolean | null;
attendeeSeatId?: string;
seatsPerTimeSlot?: number | null;
schedulingType?: SchedulingType | null;
iCalUID?: string | null;
iCalSequence?: number | null;
// It has responses to all the fields(system + user)
responses?: CalEventResponses | null;
// It just has responses to only the user fields. It allows to easily iterate over to show only user fields
userFieldsResponses?: CalEventResponses | null;
platformClientId?: string | null;
platformRescheduleUrl?: string | null;
platformCancelUrl?: string | null;
platformBookingUrl?: string | null;
}
export interface EntryPoint {
entryPointType?: string;
uri?: string;
label?: string;
pin?: string;
accessCode?: string;
meetingCode?: string;
passcode?: string;
password?: string;
}
export interface AdditionalInformation {
conferenceData?: ConferenceData;
entryPoints?: EntryPoint[];
hangoutLink?: string;
}
export interface IntegrationCalendar extends Ensure<Partial<SelectedCalendar>, "externalId"> {
primary?: boolean;
name?: string;
readOnly?: boolean;
// For displaying the connected email address
email?: string;
primaryEmail?: string;
credentialId?: number | null;
integrationTitle?: string;
}
export interface Calendar {
createEvent(event: CalendarEvent, credentialId: number): Promise<NewCalendarEventType>;
updateEvent(
uid: string,
event: CalendarEvent,
externalCalendarId?: string | null
): Promise<NewCalendarEventType | NewCalendarEventType[]>;
deleteEvent(uid: string, event: CalendarEvent, externalCalendarId?: string | null): Promise<unknown>;
getAvailability(
dateFrom: string,
dateTo: string,
selectedCalendars: IntegrationCalendar[]
): Promise<EventBusyDate[]>;
listCalendars(event?: CalendarEvent): Promise<IntegrationCalendar[]>;
}
/**
* @see [How to inference class type that implements an interface](https://stackoverflow.com/a/64765554/6297100)
*/
type Class<I, Args extends any[] = any[]> = new (...args: Args) => I;
export type CalendarClass = Class<Calendar, [CredentialPayload]>;

15
calcom/packages/types/Credential.d.ts vendored Normal file
View File

@@ -0,0 +1,15 @@
import type { Prisma } from "@prisma/client";
/*
* The logic on this it's just using Credential Type doesn't reflect that some fields can be
* null sometimes, so with this we should get correct type.
* Also there may be a better place to save this.
*/
export type CredentialPayload = Prisma.CredentialGetPayload<{
select: typeof import("@calcom/prisma/selects/credential").credentialForCalendarServiceSelect;
}>;
export type CredentialFrontendPayload = Omit<CredentialPayload, "key"> & {
/** We should type error if keys are leaked to the frontend */
key?: never;
};

33
calcom/packages/types/CrmService.d.ts vendored Normal file
View File

@@ -0,0 +1,33 @@
import type { CalendarEvent } from "./Calendar";
export interface CrmData {
id: string;
type: string;
credentialId: number;
password?: string;
url?: string;
}
export interface ContactCreateInput {
email: string;
name: string;
}
export interface Contact {
id: string;
email: string;
ownerId?: string;
ownerEmail?: string;
}
export interface CrmEvent {
id: string;
}
export interface CRM {
createEvent: (event: CalendarEvent, contacts: Contact[]) => Promise<CrmEvent>;
updateEvent: (uid: string, event: CalendarEvent) => Promise<CrmEvent>;
deleteEvent: (uid: string) => Promise<void>;
getContacts: (emails: string | string[], includeOwner?: boolean) => Promise<Contact[]>;
createContacts: (contactsToCreate: ContactCreateInput[], organizerEmail?: string) => Promise<Contact[]>;
}

6
calcom/packages/types/Event.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
import type { NewCalendarEventType, AdditionalInformation } from "@calcom/types/Calendar";
import type { CrmData } from "./CrmService";
import type { VideoCallData } from "./VideoApiAdapter";
export type Event = AdditionalInformation | NewCalendarEventType | VideoCallData | CrmData;

40
calcom/packages/types/EventManager.d.ts vendored Normal file
View File

@@ -0,0 +1,40 @@
import type { CalendarEvent } from "./Calendar";
export interface PartialReference {
id?: number;
type: string;
uid: string;
meetingId?: string | null;
meetingPassword?: string | null;
thirdPartyRecurringEventId?: string | null;
meetingUrl?: string | null;
externalCalendarId?: string | null;
credentialId?: number | null;
}
export interface EventResult<T> {
type: string;
appName: string;
success: boolean;
uid: string;
iCalUID?: string | null;
createdEvent?: T;
updatedEvent?: T | T[];
originalEvent: CalendarEvent;
calError?: string;
calWarnings?: string[];
credentialId?: number;
externalId?: string | null;
}
export interface CreateUpdateResult {
results: Array<EventResult>;
referencesToCreate: Array<PartialReference>;
}
export interface PartialBooking {
id: number;
userId: number | null;
references: Array<PartialReference>;
credentialId?: number;
}

View File

@@ -0,0 +1,53 @@
import type { Payment, Prisma, Booking, PaymentOption } from "@prisma/client";
import type { PaymentService } from "@calcom/app-store/paypal/lib/PaymentService";
import type { CalendarEvent } from "@calcom/types/Calendar";
export interface PaymentApp {
lib?: {
PaymentService: typeof PaymentService;
};
}
export interface IAbstractPaymentService {
/* This method is for creating charges at the time of booking */
create(
payment: Pick<Prisma.PaymentUncheckedCreateInput, "amount" | "currency">,
bookingId: Booking["id"],
userId: Booking["userId"],
username: string | null,
bookerName: string | null,
bookerEmail: string,
paymentOption: PaymentOption,
eventTitle?: string,
bookingTitle?: string
): Promise<Payment>;
/* This method is to collect card details to charge at a later date ex. no-show fees */
collectCard(
payment: Pick<Prisma.PaymentUncheckedCreateInput, "amount" | "currency">,
bookingId: Booking["id"],
bookerEmail: string,
paymentOption: PaymentOption
): Promise<Payment>;
chargeCard(
payment: Pick<Prisma.PaymentUncheckedCreateInput, "amount" | "currency">,
bookingId?: Booking["id"]
): Promise<Payment>;
update(paymentId: Payment["id"], data: Partial<Prisma.PaymentUncheckedCreateInput>): Promise<Payment>;
refund(paymentId: Payment["id"]): Promise<Payment>;
getPaymentPaidStatus(): Promise<string>;
getPaymentDetails(): Promise<Payment>;
afterPayment(
event: CalendarEvent,
booking: {
user: { email: string | null; name: string | null; timeZone: string } | null;
id: number;
startTime: { toISOString: () => string };
uid: string;
},
paymentData: Payment
): Promise<void>;
deletePayment(paymentId: Payment["id"]): Promise<boolean>;
isSetupAlready(): boolean;
}

View File

@@ -0,0 +1,3 @@
import type { LucideProps } from "lucide-react";
export type SVGComponent = (props: Omit<LucideProps, "ref">) => JSX.Element;

36
calcom/packages/types/UserProfile.d.ts vendored Normal file
View File

@@ -0,0 +1,36 @@
import type { Team } from "@calcom/prisma/client";
type OrganizationWithRequestedSlug = Pick<Team, "name" | "id" | "slug" | "calVideoLogo", "bannerUrl"> & {
requestedSlug: string | null;
};
export type OrgProfile = {
id: number;
upId: string;
username: string;
organizationId: number;
organization: OrganizationWithRequestedSlug;
};
export type PersonalProfile = {
id: number;
upId: string;
username: string;
organizationId: null;
organization: null;
};
export type UserAsPersonalProfile = {
id: null;
upId: string;
username: string | null;
organizationId: null;
organization: null;
};
export type UserProfile = PersonalProfile | OrgProfile | UserAsPersonalProfile;
/**
* It's a unique identifier that can refer to a user moved to a profile(with format `usr-${user.id}`) or a profile itself(Profile.id)
*/
export type UpId = string;

View File

@@ -0,0 +1,47 @@
import type {
TSubmitBatchProcessorJobRes,
batchProcessorBody,
TGetTranscriptAccessLink,
} from "@calcom/app-store/dailyvideo/zod";
import type { GetRecordingsResponseSchema, GetAccessLinkResponseSchema } from "@calcom/prisma/zod-utils";
import type { EventBusyDate } from "./Calendar";
import type { CredentialPayload } from "./Credential";
export interface VideoCallData {
type: string;
id: string;
password: string;
url: string;
}
// VideoApiAdapter is defined by the Video App. The App currently can choose to not define it. So, consider in type that VideoApiAdapter can be undefined.
export type VideoApiAdapter =
| {
createMeeting(event: CalendarEvent): Promise<VideoCallData>;
updateMeeting(bookingRef: PartialReference, event: CalendarEvent): Promise<VideoCallData>;
deleteMeeting(uid: string): Promise<unknown>;
getAvailability(dateFrom?: string, dateTo?: string): Promise<EventBusyDate[]>;
getRecordings?(roomName: string): Promise<GetRecordingsResponseSchema>;
getRecordingDownloadLink?(recordingId: string): Promise<GetAccessLinkResponseSchema>;
createInstantCalVideoRoom?(endTime: string): Promise<VideoCallData>;
getAllTranscriptsAccessLinkFromRoomName?(roomName: string): Promise<Array<string>>;
submitBatchProcessorJob?(body: batchProcessorBody): Promise<TSubmitBatchProcessorJobRes>;
getTranscriptsAccessLinkFromRecordingId?(
recordingId: string
): Promise<TGetTranscriptAccessLink["transcription"] | { message: string }>;
checkIfRoomNameMatchesInRecording?(roomName: string, recordingId: string): Promise<boolean>;
}
| undefined;
export type VideoApiAdapterFactory = (credential: CredentialPayload) => VideoApiAdapter;

View File

@@ -0,0 +1,44 @@
import type { Dayjs, PluginFunc } from "dayjs";
declare const plugin: PluginFunc;
export as namespace plugin;
export = plugin;
declare namespace plugin {
interface BusinessDaysPluginOptions {
holidays?: string[];
holidayFormat?: string;
additionalWorkingDays?: string[];
additionalWorkingDayFormat?: string;
workingWeekdays?: number[];
}
interface BusinessDaysPlugin {
isHoliday(): boolean;
isBusinessDay(): boolean;
isAdditionalWorkingDay(): boolean;
businessDaysAdd(days: number): Dayjs;
businessDaysSubtract(days: number): Dayjs;
businessDiff(date: Dayjs): number;
nextBusinessDay(): Dayjs;
prevBusinessDay(): Dayjs;
businessDaysInMonth(): Dayjs[];
lastBusinessDayOfMonth(): Dayjs;
businessWeeksInMonth(): Dayjs[][];
}
}
declare module "dayjs" {
// eslint-disable-next-line @typescript-eslint/no-empty-interface, no-shadow
interface Dayjs extends plugin.BusinessDaysPlugin {}
function getWorkingWeekdays(): number[];
function setWorkingWeekdays(workingWeekdays: number[]): void;
function getHolidays(): string[];
function setHolidays(holidays: string[]): void;
function getHolidayFormat(): string | undefined;
function setHolidayFormat(holidayFormat: string): void;
function getAdditionalWorkingDays(): string[];
function setAdditionalWorkingDays(additionalWorkingDays: string[]): void;
function getAdditionalWorkingDayFormat(): string | undefined;
function setAdditionalWorkingDayFormat(additionalWorkingDayFormat: string): void;
}

67
calcom/packages/types/environment.d.ts vendored Normal file
View File

@@ -0,0 +1,67 @@
declare namespace NodeJS {
interface ProcessEnv {
readonly CALCOM_TELEMETRY_DISABLED: string | undefined;
readonly CALENDSO_ENCRYPTION_KEY: string | undefined;
readonly DATABASE_URL: string | undefined;
readonly GOOGLE_API_CREDENTIALS: string | undefined;
/** @deprecated use `NEXT_PUBLIC_WEBAPP_URL` */
readonly BASE_URL: string | undefined;
/** @deprecated use `NEXT_PUBLIC_WEBAPP_URL` */
readonly NEXT_PUBLIC_BASE_URL: string | undefined;
/** @deprecated use `NEXT_PUBLIC_WEBSITE_URL` */
readonly NEXT_PUBLIC_APP_URL: string | undefined;
readonly NEXTAUTH_SECRET: string | undefined;
readonly NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL: string | undefined;
readonly MS_GRAPH_CLIENT_ID: string | undefined;
readonly MS_GRAPH_CLIENT_SECRET: string | undefined;
readonly ZOOM_CLIENT_ID: string | undefined;
readonly ZOOM_CLIENT_SECRET: string | undefined;
readonly EMAIL_FROM: string | undefined;
readonly EMAIL_FROM_NAME: string | undefined;
readonly EMAIL_SERVER_HOST: string | undefined;
readonly EMAIL_SERVER_PORT: string | undefined;
readonly EMAIL_SERVER_USER: string | undefined;
readonly EMAIL_SERVER_PASSWORD: string | undefined;
readonly CRON_API_KEY: string | undefined;
readonly CRON_ENABLE_APP_SYNC: string | undefined;
readonly NEXT_PUBLIC_STRIPE_PUBLIC_KEY: string | undefined;
readonly STRIPE_PRIVATE_KEY: string | undefined;
readonly STRIPE_CLIENT_ID: string | undefined;
readonly STRIPE_WEBHOOK_SECRET: string | undefined;
readonly STRIPE_WEBHOOK_SECRET_APPS: string | undefined;
readonly PAYMENT_FEE_PERCENTAGE: number | undefined;
readonly PAYMENT_FEE_FIXED: number | undefined;
readonly NEXT_PUBLIC_INTERCOM_APP_ID: string | undefined;
readonly TANDEM_CLIENT_ID: string | undefined;
readonly TANDEM_CLIENT_SECRET: string | undefined;
readonly TANDEM_BASE_URL: string | undefined;
readonly WEBSITE_BASE_URL: string | undefined;
/** @deprecated use `NEXT_PUBLIC_WEBSITE_URL` */
readonly NEXT_PUBLIC_WEBSITE_BASE_URL: string;
readonly NEXT_PUBLIC_WEBSITE_URL: string;
readonly APP_BASE_URL: string | undefined;
/** @deprecated use `NEXT_PUBLIC_WEBAPP_URL` */
readonly NEXT_PUBLIC_APP_BASE_URL: string;
readonly NEXT_PUBLIC_WEBAPP_URL: string;
/** The Environment that the app is deployed an running on. */
readonly VERCEL_ENV: "production" | "preview" | "development" | undefined;
/** The URL of the deployment. Example: my-site-7q03y4pi5.vercel.app. */
readonly VERCEL_URL: string | undefined;
/**
* Set it to "1" if you need to run E2E tests locally
**/
readonly NEXT_PUBLIC_IS_E2E: "1" | undefined;
/**
* This is used so we can enable Mailhog in E2E tests.
*/
readonly E2E_TEST_MAILHOG_ENABLED: "1" | undefined;
readonly NEXT_PUBLIC_APP_NAME: string | "Cal";
readonly NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS: string | "help@cal.com";
readonly NEXT_PUBLIC_COMPANY_NAME: string | "Cal.com, Inc.";
/**
* "strict" -> Strict CSP
* "non-strict" -> Strict CSP except the usage of unsafe-inline for `style-src`
*/
readonly CSP_POLICY: "strict" | "non-strict";
}
}

269
calcom/packages/types/ical.d.ts vendored Normal file
View File

@@ -0,0 +1,269 @@
// SPDX-FileCopyrightText: © 2019 EteSync Authors
// SPDX-License-Identifier: GPL-3.0-only
// https://github.com/mozilla-comm/ical.js/issues/367#issuecomment-568493517
declare module "ical.js" {
function parse(input: string): unknown[];
export class helpers {
public updateTimezones(vcal: Component): Component;
}
class Component {
public fromString(str: string): Component;
public name: string;
constructor(jCal: unknown[] | string, parent?: Component);
public toJSON(): unknown[];
public getFirstSubcomponent(name?: string): Component | null;
public getAllSubcomponents(name?: string): Component[];
public getFirstPropertyValue<T = unknown>(name?: string): T;
public getFirstProperty(name?: string): Property;
public getAllProperties(name?: string): Property[];
public addProperty(property: Property): Property;
public addPropertyWithValue(name: string, value: string | number | Record<string, unknown>): Property;
public hasProperty(name?: string): boolean;
public updatePropertyWithValue(name: string, value: string | number | Record<string, unknown>): Property;
public removeAllProperties(name?: string): boolean;
public addSubcomponent(component: Component): Component;
}
export class Event {
public uid: string;
public summary: string;
public startDate: Time;
public endDate: Time;
public description: string;
public location: string;
public attendees: Property[];
/**
* The sequence value for this event. Used for scheduling.
*
* @type {number}
* @memberof Event
*/
public sequence: number;
/**
* The duration. This can be the result directly from the property, or the
* duration calculated from start date and end date. Setting the property
* will remove unknown `dtend` properties.
*
* @type {Duration}
* @memberof Event
*/
public duration: Duration;
/**
* The organizer value as an uri. In most cases this is a mailto: uri,
* but it can also be something else, like urn:uuid:...
*/
public organizer: string;
/** The sequence value for this event. Used for scheduling */
public sequence: number;
/** The recurrence id for this event */
public recurrenceId: Time;
public component: Component;
public constructor(
component?: Component | null,
options?: { strictExceptions: boolean; exepctions: Array<Component | Event> }
);
public isRecurring(): boolean;
public iterator(startTime?: Time): RecurExpansion;
public getOccurrenceDetails(occurrence: Time): OccurrenceDetails;
public getRecurrenceTypes(): FrequencyValues;
}
// https://mozilla-comm.github.io/ical.js/api/ICAL.Event.html#.occurrenceDetails
interface OccurrenceDetails {
recurrenceId: Time;
item: Event;
startDate: Time;
endDate: Time;
}
export class Property {
public name: string;
public type: string;
constructor(jCal: unknown[] | string, parent?: Component);
public getFirstValue<T = unknown>(): T;
public getValues<T = unknown>(): T[];
public setParameter(name: string, value: string | string[]): void;
public setValue(value: string | Record<string, unknown>): void;
public setValues(values: (string | Record<string, unknown>)[]): void;
public toJSON(): unknown;
}
interface TimeJsonData {
year?: number;
month?: number;
day?: number;
hour?: number;
minute?: number;
second?: number;
isDate?: boolean;
}
export class Time {
public static fromString(str: string): Time;
public static fromJSDate(aDate: Date | null, useUTC: boolean): Time;
public static fromData(aData: TimeJsonData): Time;
public static fromDateTimeString(aDate: string): Time;
public now(): Time;
public isDate: boolean;
public timezone: string;
public zone: Timezone;
public year: number;
public month: number;
public day: number;
public hour: number;
public minute: number;
public second: number;
constructor(data?: TimeJsonData);
public compare(aOther: Time): number;
public clone(): Time;
public convertToZone(zone: Timezone): Time;
public adjust(
aExtraDays: number,
aExtraHours: number,
aExtraMinutes: number,
aExtraSeconds: number,
aTimeopt?: Time
): void;
public addDuration(aDuration: Duration): void;
public subtractDateTz(aDate: Time): Duration;
public toUnixTime(): number;
public toJSDate(): Date;
public toJSON(): TimeJsonData;
public get icaltype(): "date" | "date-time";
}
export class Duration {
public weeks: number;
public days: number;
public hours: number;
public minutes: number;
public seconds: number;
public isNegative: boolean;
public icalclass: string;
public icaltype: string;
public toSeconds(): number;
}
export class RecurExpansion {
public complete: boolean;
public dtstart: Time;
public last: Time;
public next(): Time;
public fromData(options);
public toJSON();
constructor(options: {
/** Start time of the event */
dtstart: Time;
/** Component for expansion, required if not resuming. */
component?: Component;
});
}
export class Timezone {
public utcTimezone: Timezone;
public localTimezone: Timezone;
public convert_time(tt: Time, fromZone: Timezone, toZone: Timezone): Time;
public tzid: string;
public component: Component;
constructor(
data:
| Component
| {
component: string | Component;
tzid?: string;
location?: string;
tznames?: string;
latitude?: number;
longitude?: number;
}
);
}
export class TimezoneService {
public get(tzid: string): Timezone | null;
public has(tzid: string): boolean;
public register(tzid: string, zone: Timezone | Component);
public remove(tzid: string): Timezone | null;
}
export type FrequencyValues =
| "YEARLY"
| "MONTHLY"
| "WEEKLY"
| "DAILY"
| "HOURLY"
| "MINUTELY"
| "SECONDLY";
export enum WeekDay {
SU = 1,
MO,
TU,
WE,
TH,
FR,
SA,
}
export class RecurData {
public freq?: FrequencyValues;
public interval?: number;
public wkst?: WeekDay;
public until?: Time;
public count?: number;
public bysecond?: number[] | number;
public byminute?: number[] | number;
public byhour?: number[] | number;
public byday?: string[] | string;
public bymonthday?: number[] | number;
public byyearday?: number[] | number;
public byweekno?: number[] | number;
public bymonth?: number[] | number;
public bysetpos?: number[] | number;
}
export class RecurIterator {
public next(): Time;
}
export class Recur {
constructor(data?: RecurData);
public until: Time | null;
public freq: FrequencyValues;
public count: number | null;
public clone(): Recur;
public toJSON(): Omit<RecurData, "until"> & { until?: string };
public iterator(startTime?: Time): RecurIterator;
public isByCount(): boolean;
}
}

View File

@@ -0,0 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
type GetSSRResult<TProps> =
//
{ props: TProps } | { redirect: any } | { notFound: boolean };
type GetSSRFn<TProps> = (...args: any[]) => Promise<GetSSRResult<TProps>>;
export type inferSSRProps<TFn extends GetSSRFn<any>> = TFn extends GetSSRFn<infer TProps>
? NonNullable<TProps>
: never;

72
calcom/packages/types/next-auth.d.ts vendored Normal file
View File

@@ -0,0 +1,72 @@
import type { User as PrismaUser, UserPermissionRole } from "@prisma/client";
import type { DefaultUser } from "next-auth";
import type { MembershipRole } from "@calcom/prisma/enums";
import type { UserProfile } from "./UserProfile";
declare module "next-auth" {
/**
* Returned by `useSession`, `getSession` and received as a prop on the `Provider` React Context
*/
interface Session {
hasValidLicense: boolean;
profileId?: number | null;
upId: string;
user: User;
}
interface User extends Omit<DefaultUser, "id"> {
id: PrismaUser["id"];
emailVerified?: PrismaUser["emailVerified"];
email_verified?: boolean;
impersonatedBy?: {
id: number;
role: PrismaUser["role"];
};
belongsToActiveTeam?: boolean;
org?: {
id: number;
name?: string;
slug: string;
logoUrl?: string | null;
fullDomain: string;
domainSuffix: string;
role: MembershipRole;
};
username?: PrismaUser["username"];
avatarUrl?: PrismaUser["avatarUrl"];
role?: PrismaUser["role"] | "INACTIVE_ADMIN";
locale?: string | null;
profile?: UserProfile;
}
}
declare module "next-auth/jwt" {
interface JWT {
id?: string | number;
name?: string | null;
username?: string | null;
avatarUrl?: string | null;
email?: string | null;
upId?: string;
profileId?: number | null;
role?: UserPermissionRole | "INACTIVE_ADMIN" | null;
impersonatedBy?: {
id: number;
role: PrismaUser["role"];
};
belongsToActiveTeam?: boolean;
org?: {
id: number;
name?: string;
slug: string;
logoUrl?: string | null;
fullDomain: string;
domainSuffix: string;
role: MembershipRole;
};
organizationId?: number | null;
locale?: string;
}
}

27
calcom/packages/types/next.d.ts vendored Normal file
View File

@@ -0,0 +1,27 @@
import type { IncomingMessage } from "http";
import type { Session } from "next-auth";
import "./next-auth";
export declare module "next" {
interface NextApiRequest extends IncomingMessage {
// args is defined by /integrations/[...args] endpoint
query: Partial<{ [key: string]: string | string[] }> & { args: string[] };
session?: Session | null;
// ⬇ These are needed by @calcom/api
body: unkown;
userId: number;
method: string;
// session: { user: { id: number } };
// query: Partial<{ [key: string]: string | string[] }>;
isAdmin: boolean;
pagination: { take: number; skip: number };
}
}
export declare module "next/navigation" {
interface Params {
[key: string]: string;
}
export declare function useParams(): Params | null;
}

7
calcom/packages/types/oauth.d.ts vendored Normal file
View File

@@ -0,0 +1,7 @@
export type OAuthTokenPayload = {
userId?: number | null;
teamId?: number | null;
token_type: string;
scope: string[];
clientId: string;
};

View File

@@ -0,0 +1,6 @@
{
"name": "@calcom/types",
"version": "0.0.0",
"private": true,
"main": "index.js"
}

29
calcom/packages/types/schedule.d.ts vendored Normal file
View File

@@ -0,0 +1,29 @@
export type TimeRange = {
userId?: number | null;
start: Date;
end: Date;
};
export type Schedule = TimeRange[][];
/**
* ```text
* Ensure startTime and endTime in minutes since midnight; serialized to UTC by using the organizer timeZone, either by using the schedule timeZone or the user timeZone.
* @see lib/availability.ts getWorkingHours(timeZone: string, availability: Availability[])
* ```
*/
export type WorkingHours = {
days: number[];
startTime: number;
endTime: number;
userId?: number | null;
};
export type TravelSchedule = {
id: number;
timeZone: string;
userId: number;
startDate: Date;
endDate: Date | null;
prevTimeZone: string | null;
};

View File

@@ -0,0 +1,7 @@
import "@tanstack/react-table";
declare module "@tanstack/table-core" {
interface ColumnMeta<TData extends RowData, TValue> {
hasPermissions?: (data?: TData) => boolean; // We can conditionally render a column based on this callback -> User doesnt have admin for example.
}
}

View File

@@ -0,0 +1,5 @@
{
"extends": "@calcom/tsconfig/base.json",
"include": ["."],
"exclude": ["dist", "build", "node_modules"]
}

17
calcom/packages/types/utils.d.ts vendored Normal file
View File

@@ -0,0 +1,17 @@
/** Makes selected props from a record non optional */
export type Ensure<T, K extends keyof T> = Omit<T, K> & {
[EK in K]-?: NonNullable<T[EK]>;
};
/** Makes selected props from a record optional */
export type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;
/** Get the union type of all the values in an object, array or array-like type `T` */
export type ValuesType<T extends ReadonlyArray<unknown> | ArrayLike<unknown> | Record<unknown, unknown>> =
T extends ReadonlyArray<unknown>
? T[number]
: T extends ArrayLike<unknown>
? T[number]
: T extends object
? T[keyof T]
: never;

5
calcom/packages/types/window.d.ts vendored Normal file
View File

@@ -0,0 +1,5 @@
interface Window {
Meticulous?: {
isRunningAsTest: boolean;
};
}