perf: stop merging routers twice. (#21538)

* move away from merging twice

* move to use loggedIn Router directly

* fix router outputs types

* fix mocks in create button with teasm tests

---------

Co-authored-by: Alex van Andel <me@alexvanandel.com>
This commit is contained in:
sean-brydon
2025-05-27 15:42:14 +01:00
committed by GitHub
co-authored by Alex van Andel
parent ed4b3f082a
commit 08e35e4698
13 changed files with 93 additions and 82 deletions
@@ -131,7 +131,7 @@ function BookingListItem(booking: BookingItemProps) {
};
});
const noShowMutation = trpc.viewer.markNoShow.useMutation({
const noShowMutation = trpc.viewer.loggedInViewerRouter.markNoShow.useMutation({
onSuccess: async (data) => {
showToast(data.message, "success");
// Invalidate and refetch the bookings query to update the UI
@@ -938,7 +938,7 @@ const Attendee = (attendeeProps: AttendeeProps & NoShowProps) => {
const [openDropdown, setOpenDropdown] = useState(false);
const { copyToClipboard, isCopied } = useCopy();
const noShowMutation = trpc.viewer.markNoShow.useMutation({
const noShowMutation = trpc.viewer.loggedInViewerRouter.markNoShow.useMutation({
onSuccess: async (data) => {
showToast(data.message, "success");
utils.viewer.bookings.invalidate();
@@ -1030,7 +1030,7 @@ const GroupedAttendees = (groupedAttendeeProps: GroupedAttendeeProps) => {
};
});
const { t } = useLocale();
const noShowMutation = trpc.viewer.markNoShow.useMutation({
const noShowMutation = trpc.viewer.loggedInViewerRouter.markNoShow.useMutation({
onSuccess: async (data) => {
showToast(t(data.message), "success");
},
@@ -1133,7 +1133,7 @@ const NoShowAttendeesDialog = ({
}))
);
const noShowMutation = trpc.viewer.markNoShow.useMutation({
const noShowMutation = trpc.viewer.loggedInViewerRouter.markNoShow.useMutation({
onSuccess: async (data) => {
const newValue = data.attendees[0];
setNoShowAttendees((old) =>
@@ -44,7 +44,7 @@ const obtainNewUsernameChangeCondition = ({
}: {
userIsPremium: boolean;
isNewUsernamePremium: boolean;
stripeCustomer: RouterOutputs["viewer"]["stripeCustomer"] | undefined;
stripeCustomer: RouterOutputs["viewer"]["loggedInViewerRouter"]["stripeCustomer"] | undefined;
}) => {
if (!userIsPremium && isNewUsernamePremium) {
return UsernameChangeStatusEnum.UPGRADE;
@@ -72,7 +72,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
const [markAsError, setMarkAsError] = useState(false);
const recentAttemptPaymentStatus = searchParams?.get("recentAttemptPaymentStatus");
const [openDialogSaveUsername, setOpenDialogSaveUsername] = useState(false);
const { data: stripeCustomer } = trpc.viewer.stripeCustomer.useQuery();
const { data: stripeCustomer } = trpc.viewer.loggedInViewerRouter.stripeCustomer.useQuery();
const isCurrentUsernamePremium =
user && user.metadata && hasKeyInMetadata(user, "isPremium") ? !!user.metadata.isPremium : false;
const [isInputUsernamePremium, setIsInputUsernamePremium] = useState(false);
@@ -9,10 +9,10 @@ import { APP_NAME } from "@calcom/lib/constants";
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import { Icon } from "@calcom/ui/components/icon";
import { Select } from "@calcom/ui/components/form";
import { Avatar } from "@calcom/ui/components/avatar";
import { Button } from "@calcom/ui/components/button";
import { Select } from "@calcom/ui/components/form";
import { Icon } from "@calcom/ui/components/icon";
export default function Authorize() {
const { t } = useLocale();
@@ -39,7 +39,8 @@ export default function Authorize() {
}
);
const { data, isPending: isPendingProfiles } = trpc.viewer.teamsAndUserProfilesQuery.useQuery();
const { data, isPending: isPendingProfiles } =
trpc.viewer.loggedInViewerRouter.teamsAndUserProfilesQuery.useQuery();
const generateAuthCodeMutation = trpc.viewer.oAuth.generateAuthCode.useMutation({
onSuccess: (data) => {
@@ -26,7 +26,7 @@ function ConnectAndJoin() {
const session = useSession();
const isUserPartOfOrg = session.status === "authenticated" && !!session.data.user?.org;
const mutation = trpc.viewer.connectAndJoin.useMutation({
const mutation = trpc.viewer.loggedInViewerRouter.connectAndJoin.useMutation({
onSuccess: (res) => {
if (res.meetingUrl && !res.isBookingAlreadyAcceptedBySomeoneElse) {
router.push(res.meetingUrl);
@@ -259,7 +259,7 @@ export const InfiniteEventTypeList = ({
const [privateLinkCopyIndices, setPrivateLinkCopyIndices] = useState<Record<string, number>>({});
const utils = trpc.useUtils();
const mutation = trpc.viewer.eventTypeOrder.useMutation({
const mutation = trpc.viewer.loggedInViewerRouter.eventTypeOrder.useMutation({
onError: async (err) => {
console.error(err.message);
// REVIEW: Should we invalidate the entire router or just the `getByViewer` query?
@@ -121,7 +121,7 @@ const ProfileView = () => {
}
},
});
const unlinkConnectedAccountMutation = trpc.viewer.unlinkConnectedAccount.useMutation({
const unlinkConnectedAccountMutation = trpc.viewer.loggedInViewerRouter.unlinkConnectedAccount.useMutation({
onSuccess: async (res) => {
showToast(t(res.message), "success");
utils.viewer.me.invalidate();
@@ -131,7 +131,7 @@ const ProfileView = () => {
},
});
const addSecondaryEmailMutation = trpc.viewer.addSecondaryEmail.useMutation({
const addSecondaryEmailMutation = trpc.viewer.loggedInViewerRouter.addSecondaryEmail.useMutation({
onSuccess: (res) => {
setShowSecondaryEmailModalOpen(false);
setNewlyAddedSecondaryEmail(res?.data?.email);
@@ -0,0 +1,4 @@
import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler";
import { loggedInViewerRouter } from "@calcom/trpc/server/routers/loggedInViewer/_router";
export default createNextApiHandler(loggedInViewerRouter);
@@ -52,7 +52,7 @@ export default function RoutingForms({ appUrl }: { appUrl: string }) {
const utils = trpc.useUtils();
const [parent] = useAutoAnimate<HTMLUListElement>();
const mutation = trpc.viewer.routingFormOrder.useMutation({
const mutation = trpc.viewer.loggedInViewerRouter.routingFormOrder.useMutation({
onError: async (err) => {
console.error(err.message);
await utils.viewer.appRoutingForms.forms.cancel();
@@ -13,7 +13,9 @@ export function CreateButtonWithTeamsList(
includeOrg?: boolean;
}
) {
const query = trpc.viewer.teamsAndUserProfilesQuery.useQuery({ includeOrg: props.includeOrg });
const query = trpc.viewer.loggedInViewerRouter.teamsAndUserProfilesQuery.useQuery({
includeOrg: props.includeOrg,
});
if (!query.data) return null;
const teamsAndUserProfiles: Option[] = query.data
@@ -22,11 +22,13 @@ vi.mock("next/navigation", async (importOriginal) => {
const runtimeMock = async (data: Array<any>) => {
const updatedTrpc = {
viewer: {
teamsAndUserProfilesQuery: {
useQuery() {
return {
data: data,
};
loggedInViewerRouter: {
teamsAndUserProfilesQuery: {
useQuery() {
return {
data: data,
};
},
},
},
},
@@ -51,18 +53,20 @@ describe("Create Button Tests", () => {
vi.mock("@calcom/trpc/react", () => ({
trpc: {
viewer: {
teamsAndUserProfilesQuery: {
useQuery() {
return {
data: [
{
teamId: 1,
name: "test",
slug: "create-button-test",
image: "image",
},
],
};
loggedInViewerRouter: {
teamsAndUserProfilesQuery: {
useQuery() {
return {
data: [
{
teamId: 1,
name: "test",
slug: "create-button-test",
image: "image",
},
],
};
},
},
},
},
@@ -27,8 +27,10 @@ export function WebPushProvider({ children }: ProviderProps) {
const [isLoading, setIsLoading] = useState(false);
const [isSubscribed, setIsSubscribed] = useState(false);
const { mutate: addSubscription } = trpc.viewer.addNotificationsSubscription.useMutation();
const { mutate: removeSubscription } = trpc.viewer.removeNotificationsSubscription.useMutation();
const { mutate: addSubscription } =
trpc.viewer.loggedInViewerRouter.addNotificationsSubscription.useMutation();
const { mutate: removeSubscription } =
trpc.viewer.loggedInViewerRouter.removeNotificationsSubscription.useMutation();
useEffect(() => {
if (!("serviceWorker" in navigator)) return;
+1
View File
@@ -1,6 +1,7 @@
export * from "@trpc/react-query/shared";
export const ENDPOINTS = [
"loggedInViewerRouter",
"admin",
"apiKeys",
"appRoutingForms",
+45 -48
View File
@@ -4,7 +4,7 @@ import { userAdminRouter } from "@calcom/features/ee/users/server/trpc-router";
import { featureFlagRouter } from "@calcom/features/flags/server/router";
import { insightsRouter } from "@calcom/features/insights/server/trpc-router";
import { mergeRouters, router } from "../../trpc";
import { router } from "../../trpc";
import { loggedInViewerRouter } from "../loggedInViewer/_router";
import { publicViewerRouter } from "../publicViewer/_router";
import { timezonesRouter } from "../publicViewer/timezones/_router";
@@ -32,7 +32,7 @@ import { oAuthRouter } from "./oAuth/_router";
import { oooRouter } from "./ooo/_router";
import { viewerOrganizationsRouter } from "./organizations/_router";
import { paymentsRouter } from "./payments/_router";
// import { permissionsRouter } from "./pbac/_router";
import { permissionsRouter } from "./pbac/_router";
import { routingFormsRouter } from "./routing-forms/_router";
import { slotsRouter } from "./slots/_router";
import { ssoRouter } from "./sso/_router";
@@ -41,50 +41,47 @@ import { travelSchedulesRouter } from "./travelSchedules/_router";
import { webhookRouter } from "./webhook/_router";
import { workflowsRouter } from "./workflows/_router";
export const viewerRouter = mergeRouters(
export const viewerRouter = router({
loggedInViewerRouter,
router({
apps: appsRouter,
me: meRouter,
public: publicViewerRouter,
auth: authRouter,
deploymentSetup: deploymentSetupRouter,
bookings: bookingsRouter,
calendars: calendarsRouter,
calVideo: calVideoRouter,
credentials: credentialsRouter,
eventTypes: eventTypesRouter,
availability: availabilityRouter,
teams: viewerTeamsRouter,
timezones: timezonesRouter,
organizations: viewerOrganizationsRouter,
delegationCredential: delegationCredentialRouter,
webhook: webhookRouter,
apiKeys: apiKeysRouter,
slots: slotsRouter,
workflows: workflowsRouter,
saml: ssoRouter,
dsync: dsyncRouter,
i18n: i18nRouter,
insights: insightsRouter,
payments: paymentsRouter,
filterSegments: filterSegmentsRouter,
// pbac: permissionsRouter,
// NOTE: Add all app related routes in the bottom till the problem described in @calcom/app-store/trpc-routers.ts is solved.
// After that there would just one merge call here for all the apps.
appRoutingForms: app_RoutingForms,
appBasecamp3: app_Basecamp3,
features: featureFlagRouter,
users: userAdminRouter,
oAuth: oAuthRouter,
googleWorkspace: googleWorkspaceRouter,
admin: adminRouter,
attributes: attributesRouter,
highPerf: highPerfRouter,
routingForms: routingFormsRouter,
credits: creditsRouter,
ooo: oooRouter,
travelSchedules: travelSchedulesRouter,
})
);
apps: appsRouter,
me: meRouter,
public: publicViewerRouter,
auth: authRouter,
deploymentSetup: deploymentSetupRouter,
bookings: bookingsRouter,
calendars: calendarsRouter,
calVideo: calVideoRouter,
credentials: credentialsRouter,
eventTypes: eventTypesRouter,
availability: availabilityRouter,
teams: viewerTeamsRouter,
timezones: timezonesRouter,
organizations: viewerOrganizationsRouter,
delegationCredential: delegationCredentialRouter,
webhook: webhookRouter,
apiKeys: apiKeysRouter,
slots: slotsRouter,
workflows: workflowsRouter,
saml: ssoRouter,
dsync: dsyncRouter,
i18n: i18nRouter,
insights: insightsRouter,
payments: paymentsRouter,
filterSegments: filterSegmentsRouter,
pbac: permissionsRouter,
// NOTE: Add all app related routes in the bottom till the problem described in @calcom/app-store/trpc-routers.ts is solved.
// After that there would just one merge call here for all the apps.
appRoutingForms: app_RoutingForms,
appBasecamp3: app_Basecamp3,
features: featureFlagRouter,
users: userAdminRouter,
oAuth: oAuthRouter,
googleWorkspace: googleWorkspaceRouter,
admin: adminRouter,
attributes: attributesRouter,
highPerf: highPerfRouter,
routingForms: routingFormsRouter,
credits: creditsRouter,
ooo: oooRouter,
travelSchedules: travelSchedulesRouter,
});