Skip to content

Commit 15b1675

Browse files
perf: reduce TypeScript type bloat in tRPC package via z.ZodType annotations (calcom#25845)
* fix: prevent Prisma conditional types from leaking into .d.ts files This PR addresses TypeScript performance issues caused by Prisma's conditional types leaking through the type graph: 1. Replace Prisma.UserGetPayload with explicit UpdatedUserResult type in updateProfile.handler.ts 2. Replace Prisma.EventTypeGetPayload with explicit UpdatedEventTypeResult type in update.handler.ts 3. Replace Prisma.OutOfOfficeEntryGetPayload with explicit OOOEntryResult type in outOfOfficeCreateOrUpdate.handler.ts 4. Replace Prisma.CredentialGetPayload with explicit Credential type in getUserConnectedApps.handler.ts 5. Fix inconsistent DI usage in EventTypeRepository - use this.prismaClient instead of global prisma singleton These changes prevent massive recursive Prisma types from propagating through the type graph and being emitted in .d.ts files, which improves TypeScript performance. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: correct reasonId type to number | null in OOOEntryResult Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * perf: add z.ZodType annotations to reduce .d.ts file sizes - Annotate exported Zod schemas with z.ZodType<T> to prevent full Zod generic tree from being emitted in declaration files - eventTypes/types.d.ts reduced from 231KB to 115KB (50% reduction) - _app.d.ts reduced from 782KB to 753KB (3.7% reduction) - viewer/_router.d.ts reduced from 722KB to 695KB (3.7% reduction) - workflows/getAllActiveWorkflows.schema.d.ts significantly reduced - routing-forms/formMutation.schema.d.ts significantly reduced Files modified: - packages/trpc/server/routers/viewer/eventTypes/types.ts - packages/trpc/server/routers/viewer/workflows/getAllActiveWorkflows.schema.ts - packages/trpc/server/routers/apps/routing-forms/formMutation.schema.ts - packages/features/eventtypes/lib/types.ts Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * perf: comprehensive z.ZodType annotations to reduce .d.ts file sizes Applied z.ZodType<T> annotations to 89 schema files across the tRPC package. This prevents TypeScript from emitting the full Zod generic tree in .d.ts files, reducing declaration file sizes for downstream consumers. Files modified include schemas in: - viewer/teams (round-robin, managed events, invitations, etc.) - viewer/bookings (get, find, confirm, etc.) - viewer/eventTypes (get, delete, getByViewer, etc.) - viewer/workflows (list, delete, verify, etc.) - viewer/auth (changePassword, verifyPassword, etc.) - viewer/apiKeys (create, delete, edit, etc.) - viewer/sso (get, update, delete, updateOIDC) - viewer/oAuth (addClient, generateAuthCode) - viewer/calendars (setDestinationCalendar) - viewer/deploymentSetup (update, validateLicense) - apps/routing-forms (formQuery, deleteForm, etc.) - publicViewer (submitRating, markHostAsNoShow, etc.) - loggedInViewer (eventTypeOrder, routingFormOrder, etc.) Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: revert slots/types.ts z.ZodType annotation that caused type mismatch The slots/types.ts schema has a transform that converts duration from string to number, which makes the z.ZodType<T> annotation incompatible. Reverting to original to fix Unit test failure. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: use 3-generic z.ZodType pattern for schemas with .default() modifiers For schemas with .default() modifiers, the input and output types differ: - Input type: field is optional (what callers send) - Output type: field is required (what handlers receive after parsing) This commit: 1. Fixes get.schema.ts (offset has .default(0)) 2. Fixes removeMember.schema.ts (isOrg has .default(false)) 3. Fixes resendInvitation.schema.ts (isOrg has .default(false)) 4. Fixes listMembers.schema.ts (limit has .default(10)) 5. Fixes getByViewer.schema.ts (limit has .default(10)) 6. Reverts eventTypes/types.ts (complex transforms hard to model) 7. Reverts features/eventtypes/lib/types.ts (complex transforms hard to model) The 3-generic pattern z.ZodType<Output, z.ZodTypeDef, Input> properly models the difference between input and output types while still preventing the full Zod generic tree from being emitted in .d.ts files. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: use 3-generic z.ZodType pattern for schemas with transforms/defaults - organizations/update.schema.ts: orgId has .transform() that converts string to number, so input type is string | number but output type is number - publicViewer/event.schema.ts: fromRedirectOfNonOrgLink has .default(false), so input has it optional but output has it required Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: use 3-generic z.ZodType pattern for updateProfile.schema.ts Address reviewer feedback: isDeleted field in secondaryEmails has .default(false), so input type has it optional but output type has it required. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * chore: remove explanatory comments from schema files Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: use 3-generic z.ZodType pattern for addClient.schema.ts enablePkce field Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: address Hariom's PR feedback - Rename TGetInputSchemaInput to TGetInputRawSchema in get.schema.ts - Use Prisma-free JsonValue type from @calcom/types/Json in updateProfile.handler.ts - Fix publish.schema.ts with 3-generic pattern for z.coerce.number() Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * fix: add sort field to TGetInputSchema types Added sort field to both TGetInputRawSchema and TGetInputSchema types to match the Zod schema that was updated in main branch. Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent c20f6cb commit 15b1675

93 files changed

Lines changed: 908 additions & 303 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/features/eventtypes/repositories/eventTypeRepository.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@ import logger from "@calcom/lib/logger";
88
import { safeStringify } from "@calcom/lib/safeStringify";
99
import { eventTypeSelect } from "@calcom/lib/server/eventTypeSelect";
1010
import type { PrismaClient } from "@calcom/prisma";
11-
import {
12-
prisma,
13-
availabilityUserSelect,
14-
userSelect as userSelectWithSelectedCalendars,
15-
} from "@calcom/prisma";
11+
import { availabilityUserSelect, userSelect as userSelectWithSelectedCalendars } from "@calcom/prisma";
1612
import type { EventType as PrismaEventType } from "@calcom/prisma/client";
1713
import type { Prisma } from "@calcom/prisma/client";
1814
import { MembershipRole } from "@calcom/prisma/enums";
@@ -490,7 +486,7 @@ export class EventTypeRepository {
490486

491487
if (!teamMembership) throw new ErrorWithCode(ErrorCode.Unauthorized, "User is not a member of this team");
492488

493-
return await prisma.eventType.findMany({
489+
return await this.prismaClient.eventType.findMany({
494490
where: {
495491
teamId,
496492
...where,

packages/trpc/server/routers/apps/routing-forms/deleteForm.schema.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import z from "zod";
22

3-
export const ZDeleteFormInputSchema = z.object({
3+
export type TDeleteFormInputSchema = {
4+
id: string;
5+
};
6+
7+
export const ZDeleteFormInputSchema: z.ZodType<TDeleteFormInputSchema> = z.object({
48
id: z.string(),
59
});
6-
7-
export type TDeleteFormInputSchema = z.infer<typeof ZDeleteFormInputSchema>;

packages/trpc/server/routers/apps/routing-forms/formQuery.schema.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { z } from "zod";
22

3-
export const ZFormQueryInputSchema = z.object({
3+
export type TFormQueryInputSchema = {
4+
id: string;
5+
};
6+
7+
export const ZFormQueryInputSchema: z.ZodType<TFormQueryInputSchema> = z.object({
48
id: z.string(),
59
});
6-
7-
export type TFormQueryInputSchema = z.infer<typeof ZFormQueryInputSchema>;

packages/trpc/server/routers/apps/routing-forms/getAttributesForTeam.schema.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { z } from "zod";
22

3-
export const ZGetAttributesForTeamInputSchema = z.object({
3+
export type TGetAttributesForTeamInputSchema = {
4+
teamId: number;
5+
};
6+
7+
export const ZGetAttributesForTeamInputSchema: z.ZodType<TGetAttributesForTeamInputSchema> = z.object({
48
teamId: z.number(),
59
});
6-
7-
export type TGetAttributesForTeamInputSchema = z.infer<typeof ZGetAttributesForTeamInputSchema>;
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import z from "zod";
22

3-
export const ZGetIncompleteBookingSettingsInputSchema = z.object({
4-
formId: z.string(),
5-
});
3+
export type TGetIncompleteBookingSettingsInputSchema = {
4+
formId: string;
5+
};
66

7-
export type TGetIncompleteBookingSettingsInputSchema = z.infer<
8-
typeof ZGetIncompleteBookingSettingsInputSchema
9-
>;
7+
export const ZGetIncompleteBookingSettingsInputSchema: z.ZodType<TGetIncompleteBookingSettingsInputSchema> =
8+
z.object({
9+
formId: z.string(),
10+
});
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { z } from "zod";
22

3-
export const ZFormByResponseIdInputSchema = z.object({
3+
export type TFormByResponseIdInputSchema = {
4+
formResponseId: number;
5+
};
6+
7+
export const ZFormByResponseIdInputSchema: z.ZodType<TFormByResponseIdInputSchema> = z.object({
48
formResponseId: z.number(),
59
});
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { z } from "zod";
22

3-
export const ZAddNotificationsSubscriptionInputSchema = z.object({
4-
subscription: z.string(),
5-
});
3+
export type TAddNotificationsSubscriptionInputSchema = {
4+
subscription: string;
5+
};
66

7-
export type TAddNotificationsSubscriptionInputSchema = z.infer<
8-
typeof ZAddNotificationsSubscriptionInputSchema
9-
>;
7+
export const ZAddNotificationsSubscriptionInputSchema: z.ZodType<TAddNotificationsSubscriptionInputSchema> =
8+
z.object({
9+
subscription: z.string(),
10+
});

packages/trpc/server/routers/loggedInViewer/addSecondaryEmail.schema.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { z } from "zod";
22

3-
export const ZAddSecondaryEmailInputSchema = z.object({
3+
export type TAddSecondaryEmailInputSchema = {
4+
email: string;
5+
};
6+
7+
export const ZAddSecondaryEmailInputSchema: z.ZodType<TAddSecondaryEmailInputSchema> = z.object({
48
email: z.string(),
59
});
6-
7-
export type TAddSecondaryEmailInputSchema = z.infer<typeof ZAddSecondaryEmailInputSchema>;

packages/trpc/server/routers/loggedInViewer/connectAndJoin.schema.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { z } from "zod";
22

3-
export const ZConnectAndJoinInputSchema = z.object({
3+
export type TConnectAndJoinInputSchema = {
4+
token: string;
5+
};
6+
7+
export const ZConnectAndJoinInputSchema: z.ZodType<TConnectAndJoinInputSchema> = z.object({
48
token: z.string(),
59
});
6-
7-
export type TConnectAndJoinInputSchema = z.infer<typeof ZConnectAndJoinInputSchema>;

packages/trpc/server/routers/loggedInViewer/eventTypeOrder.schema.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { z } from "zod";
22

3-
export const ZEventTypeOrderInputSchema = z.object({
3+
export type TEventTypeOrderInputSchema = {
4+
ids: number[];
5+
};
6+
7+
export const ZEventTypeOrderInputSchema: z.ZodType<TEventTypeOrderInputSchema> = z.object({
48
ids: z.array(z.number()),
59
});
6-
7-
export type TEventTypeOrderInputSchema = z.infer<typeof ZEventTypeOrderInputSchema>;

0 commit comments

Comments
 (0)