perf: Create 'heavy' eventTypes router (#23664)

* perf: Create 'heavy' eventTypes router

* Fixing type checks

* Fixing platform libraries imports
This commit is contained in:
Keith Williams
2025-09-08 08:24:30 +00:00
committed by GitHub
parent 411a14dd3d
commit 86dcd6f0ff
33 changed files with 107 additions and 75 deletions
+6 -1
View File
@@ -15,6 +15,7 @@ const resolveEndpoint = (links: any) => {
// to the correct API endpoints.
// - viewer.me - 2 segment paths like this are for logged in requests
// - viewer.public.i18n - 3 segments paths can be public or authed
// - viewer.eventTypes.heavy.create - 4 segments paths for heavy sub-router
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (ctx: any) => {
const parts = ctx.op.path.split(".");
@@ -23,7 +24,11 @@ const resolveEndpoint = (links: any) => {
if (parts.length == 2) {
endpoint = parts[0] as keyof typeof links;
path = parts[1];
} else {
} else if (parts.length >= 3 && parts[2] === "heavy") {
endpoint = parts[1] + "/heavy" as keyof typeof links;
path = parts[3];
}
else {
endpoint = parts[1] as keyof typeof links;
path = parts.splice(2, parts.length - 2).join(".");
}
@@ -37,7 +37,7 @@ const UserProfile = ({ user }: UserProfileProps) => {
const [imageSrc, setImageSrc] = useState<string>(user?.avatar || "");
const utils = trpc.useUtils();
const router = useRouter();
const createEventType = trpc.viewer.eventTypes.create.useMutation();
const createEventType = trpc.viewer.eventTypes.heavy.create.useMutation();
const telemetry = useTelemetry();
const [firstRender, setFirstRender] = useState(true);
@@ -177,7 +177,7 @@ const OnboardingPage = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [eventTypeGroups]);
const updateMutation = trpc.viewer.eventTypes.update.useMutation({
const updateMutation = trpc.viewer.eventTypes.heavy.update.useMutation({
onSuccess: async (data) => {
showToast(t("event_type_updated_successfully", { eventTypeTitle: data.eventType?.title }), "success");
},
@@ -268,7 +268,7 @@ export const InfiniteEventTypeList = ({
},
});
const setHiddenMutation = trpc.viewer.eventTypes.update.useMutation({
const setHiddenMutation = trpc.viewer.eventTypes.heavy.update.useMutation({
onMutate: async (data) => {
await utils.viewer.eventTypes.getEventTypesFromGroup.cancel();
const previousValue = utils.viewer.eventTypes.getEventTypesFromGroup.getInfiniteData({
@@ -0,0 +1,4 @@
import { createNextApiHandler } from "@calcom/trpc/server/createNextApiHandler";
import { eventTypesRouter } from "@calcom/trpc/server/routers/viewer/eventTypes/heavy/_router";
export default createNextApiHandler(eventTypesRouter);
@@ -113,7 +113,7 @@ test("multiple duration selection updates event length correctly", async ({ page
await page.getByTestId("vertical-tab-event_advanced_tab_title").click();
await page.fill('[name="eventName"]', "{Event duration} event btwn {Organiser} {Scheduler}");
await page.locator('[data-testid="update-eventtype"]').click();
await page.waitForResponse("/api/trpc/eventTypes/update?batch=1");
await page.waitForResponse("/api/trpc/eventTypes/heavy/update?batch=1");
});
await page.goto(`/${user.username}/multiple-duration`);
+5 -5
View File
@@ -131,7 +131,7 @@ test.describe("Event Types tests", () => {
expect(formTitle).toBe(firstTitle);
expect(formSlug).toContain(firstSlug);
const submitPromise = page.waitForResponse("/api/trpc/eventTypes/duplicate?batch=1");
const submitPromise = page.waitForResponse("/api/trpc/eventTypes/heavy/duplicate?batch=1");
await page.getByTestId("continue").click();
const response = await submitPromise;
expect(response.status()).toBe(200);
@@ -144,7 +144,7 @@ test.describe("Event Types tests", () => {
await page.waitForURL((url) => {
return !!url.pathname.match(/\/event-types\/.+/);
});
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
});
@@ -167,7 +167,7 @@ test.describe("Event Types tests", () => {
await page.locator("[data-testid=add-location]").click();
await fillLocation(page, locationData[2], 2);
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
@@ -314,7 +314,7 @@ test.describe("Event Types tests", () => {
const locationAddress = "New Delhi";
await fillLocation(page, locationAddress, 0, false);
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
@@ -429,7 +429,7 @@ test.describe("Event Types tests", () => {
await page.locator('[aria-label="Timezone Select"]').fill("New York");
await page.keyboard.press("Enter");
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
await page.goto("/event-types");
@@ -50,7 +50,7 @@ export function createBookingPageFixture(page: Page) {
await page.goto("/event-types");
},
updateEventType: async () => {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
},
+4 -4
View File
@@ -42,7 +42,7 @@ test.describe("private links creation and usage", () => {
const $url = await page.locator('[data-testid="private-link-url"]').inputValue();
// click update
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
// book using generated url hash
@@ -74,7 +74,7 @@ test.describe("private links creation and usage", () => {
await page.locator("[data-testid=event-slug]").first().fill("somethingrandom");
await expect(page.locator('[data-testid="event-slug"]').first()).toHaveValue("somethingrandom");
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
await page.locator("[data-testid=vertical-tab-event_advanced_tab_title]").click();
@@ -113,7 +113,7 @@ test.describe("private links creation and usage", () => {
await page.locator('[data-testid="private-link-expiration-settings-save"]').click();
await page.waitForLoadState("networkidle");
// click update
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
// book using generated url hash
@@ -164,7 +164,7 @@ test.describe("private links creation and usage", () => {
await page.locator('[data-testid="private-link-expiration-settings-save"]').click();
await page.waitForLoadState("networkidle");
// click update
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
// book using generated url hash
+1 -1
View File
@@ -476,7 +476,7 @@ export async function gotoBookingPage(page: Page) {
}
export async function saveEventType(page: Page) {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
}
@@ -677,7 +677,7 @@ async function openBookingFormInPreviewTab(context: PlaywrightTestArgs["context"
}
async function saveEventType(page: Page) {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
}
@@ -239,5 +239,5 @@ async function gotoBookingPage(page: Page) {
}
async function saveAndWaitForResponse(page: Page) {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1");
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1");
}
@@ -407,7 +407,7 @@ test.describe("Bookings", () => {
await page.goto(`/event-types/${teamEvent.id}?tabName=advanced`);
await page.getByTestId("requires-confirmation").click();
await page.getByTestId("update-eventtype").click();
await page.waitForResponse((response) => response.url().includes("/api/trpc/eventTypes/update"));
await page.waitForResponse((response) => response.url().includes("/api/trpc/eventTypes/heavy/update"));
await doOnOrgDomain(
{
@@ -783,7 +783,7 @@ const markPhoneNumberAsRequiredAndEmailAsOptional = async (page: Page, eventId:
const emailRequiredFiled = await page.locator('[data-testid="field-required"]').first();
await emailRequiredFiled.click();
await page.getByTestId("field-add-save").click();
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
};
@@ -797,7 +797,7 @@ const markPhoneNumberAsRequiredField = async (page: Page, eventId: number) => {
const phoneRequiredFiled = await page.locator('[data-testid="field-required"]').first();
await phoneRequiredFiled.click();
await page.getByTestId("field-add-save").click();
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
};
@@ -458,7 +458,7 @@ test.describe("Organization", () => {
await page.locator('[data-testid="fixed-hosts-select"]').click();
await page.locator(`text="${invitedUserEmail}"`).click();
await page.locator('[data-testid="update-eventtype"]').click();
await page.waitForResponse("/api/trpc/eventTypes/update?batch=1");
await page.waitForResponse("/api/trpc/eventTypes/heavy/update?batch=1");
await expectPageToBeNotFound({ page, url: `/team/${team.slug}/${teamEvent.slug}` });
await doOnOrgDomain(
+1 -1
View File
@@ -35,7 +35,7 @@ test.describe("Payment app", () => {
await page.getByPlaceholder("Price").click();
await page.getByPlaceholder("Price").fill("200");
await page.getByText("SatoshissatsCurrencyBTCPayment optionCollect payment on booking").click();
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/update?batch=1", {
await submitAndWaitForResponse(page, "/api/trpc/eventTypes/heavy/update?batch=1", {
action: () => page.locator("[data-testid=update-eventtype]").click(),
});
@@ -70,7 +70,7 @@ const DuplicateDialog = () => {
}
}, [searchParams?.get("dialog")]);
const duplicateMutation = trpc.viewer.eventTypes.duplicate.useMutation({
const duplicateMutation = trpc.viewer.eventTypes.heavy.duplicate.useMutation({
onSuccess: async ({ eventType }) => {
await router.replace(`/event-types/${eventType.id}`);
+1 -1
View File
@@ -178,7 +178,7 @@ export type LocationFormValues = Pick<FormValues, "id" | "locations" | "bookingF
export type EventTypeAssignedUsers = RouterOutputs["viewer"]["eventTypes"]["get"]["eventType"]["children"];
export type EventTypeHosts = RouterOutputs["viewer"]["eventTypes"]["get"]["eventType"]["hosts"];
export type EventTypeUpdateInput = RouterInputs["viewer"]["eventTypes"]["update"];
export type EventTypeUpdateInput = RouterInputs["viewer"]["eventTypes"]["heavy"]["update"];
export type TabMap = {
advanced: React.ReactNode;
ai?: React.ReactNode;
+1 -1
View File
@@ -46,7 +46,7 @@ export const useCreateEventType = (
const [searchTerm, setSearchTerm] = useState("");
const debouncedSearchTerm = useDebounce(searchTerm, 500);
const createMutation = trpc.viewer.eventTypes.create.useMutation({
const createMutation = trpc.viewer.eventTypes.heavy.create.useMutation({
onSuccess: async ({ eventType }) => {
onSuccessMutation(eventType);
@@ -131,7 +131,7 @@ const EventTypeWeb = ({
teamId: eventType.team?.id || eventType.parent?.teamId,
onlyInstalled: true,
});
const updateMutation = trpc.viewer.eventTypes.update.useMutation({
const updateMutation = trpc.viewer.eventTypes.heavy.update.useMutation({
onSuccess: async () => {
const currentValues = form.getValues();
+4 -4
View File
@@ -4,10 +4,10 @@ export { getPublicEvent, type PublicEventType } from "@calcom/features/eventtype
export { getBulkUserEventTypes, getBulkTeamEventTypes } from "@calcom/lib/event-types/getBulkEventTypes";
export { createHandler as createEventType } from "@calcom/trpc/server/routers/viewer/eventTypes/create.handler";
export { updateHandler as updateEventType } from "@calcom/trpc/server/routers/viewer/eventTypes/update.handler";
export { createHandler as createEventType } from "@calcom/trpc/server/routers/viewer/eventTypes/heavy/create.handler";
export { updateHandler as updateEventType } from "@calcom/trpc/server/routers/viewer/eventTypes/heavy/update.handler";
export type { TUpdateInputSchema as TUpdateEventTypeInputSchema } from "@calcom/trpc/server/routers/viewer/eventTypes/update.schema";
export type { TUpdateInputSchema as TUpdateEventTypeInputSchema } from "@calcom/trpc/server/routers/viewer/eventTypes/heavy/update.schema";
export type { EventTypesPublic } from "@calcom/lib/event-types/getEventTypesPublic";
export { getEventTypesPublic } from "@calcom/lib/event-types/getEventTypesPublic";
export { parseEventTypeColor } from "@calcom/lib/isEventTypeColor";
@@ -24,7 +24,7 @@ export { getEventTypeById } from "@calcom/lib/event-types/getEventTypeById";
export { getEventTypesByViewer } from "@calcom/lib/event-types/getEventTypesByViewer";
export type { EventType } from "@calcom/lib/event-types/getEventTypeById";
export type { EventTypesByViewer } from "@calcom/lib/event-types/getEventTypesByViewer";
export type { UpdateEventTypeReturn } from "@calcom/trpc/server/routers/viewer/eventTypes/update.handler";
export type { UpdateEventTypeReturn } from "@calcom/trpc/server/routers/viewer/eventTypes/heavy/update.handler";
export { updateNewTeamMemberEventTypes } from "@calcom/lib/server/queries/teams";
export { bulkUpdateEventsToDefaultLocation } from "@calcom/lib/bulkUpdateEventsToDefaultLocation";
+1
View File
@@ -16,6 +16,7 @@ export const ENDPOINTS = [
"deploymentSetup",
"dsync",
"eventTypes",
"eventTypes/heavy",
"features",
"i18n",
"insights",
+4
View File
@@ -27,6 +27,7 @@ const resolveEndpoint = (links: any) => {
// to the correct API endpoints.
// - viewer.me - 2 segment paths like this are for logged in requests
// - viewer.public.i18n - 3 segments paths can be public or authed
// - viewer.eventTypes.heavy.create - 4 segments paths for heavy sub-router
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (ctx: any) => {
const parts = ctx.op.path.split(".");
@@ -35,6 +36,9 @@ const resolveEndpoint = (links: any) => {
if (parts.length == 2) {
endpoint = parts[0] as keyof typeof links;
path = parts[1];
} else if (parts.length >= 3 && parts[2] === "heavy") {
endpoint = parts[1] + "/heavy" as keyof typeof links;
path = parts[3];
} else {
endpoint = parts[1] as keyof typeof links;
path = parts.splice(2, parts.length - 2).join(".");
@@ -2,7 +2,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 { router } from "../../trpc";
import { router, mergeRouters } from "../../trpc";
import app_Basecamp3 from "../apps/basecamp3/_router";
import app_RoutingForms from "../apps/routing-forms/_router";
import { loggedInViewerRouter } from "../loggedInViewer/_router";
@@ -24,6 +24,7 @@ import { delegationCredentialRouter } from "./delegationCredential/_router";
import { deploymentSetupRouter } from "./deploymentSetup/_router";
import { dsyncRouter } from "./dsync/_router";
import { eventTypesRouter } from "./eventTypes/_router";
import { eventTypesRouter as heavyEventTypesRouter } from "./eventTypes/heavy/_router";
import { filterSegmentsRouter } from "./filterSegments/_router";
import { googleWorkspaceRouter } from "./googleWorkspace/_router";
import { i18nRouter } from "./i18n/_router";
@@ -53,7 +54,12 @@ export const viewerRouter = router({
calendars: calendarsRouter,
calVideo: calVideoRouter,
credentials: credentialsRouter,
eventTypes: eventTypesRouter,
eventTypes: mergeRouters(
eventTypesRouter,
router({
heavy: heavyEventTypesRouter,
})
),
availability: availabilityRouter,
teams: viewerTeamsRouter,
timezones: timezonesRouter,
@@ -4,15 +4,12 @@ import { logP } from "@calcom/lib/perf";
import authedProcedure from "../../../procedures/authedProcedure";
import { router } from "../../../trpc";
import { ZCreateInputSchema } from "./create.schema";
import { ZDeleteInputSchema } from "./delete.schema";
import { ZDuplicateInputSchema } from "./duplicate.schema";
import { ZEventTypeInputSchema, ZGetEventTypesFromGroupSchema } from "./getByViewer.schema";
import { ZGetHashedLinkInputSchema } from "./getHashedLink.schema";
import { ZGetHashedLinksInputSchema } from "./getHashedLinks.schema";
import { ZGetTeamAndEventTypeOptionsSchema } from "./getTeamAndEventTypeOptions.schema";
import { get } from "./procedures/get";
import { ZUpdateInputSchema } from "./update.schema";
import { eventOwnerProcedure } from "./util";
type BookingsRouterHandlerCache = {
@@ -22,11 +19,8 @@ type BookingsRouterHandlerCache = {
getTeamAndEventTypeOptions?: typeof import("./getTeamAndEventTypeOptions.handler").getTeamAndEventTypeOptions;
list?: typeof import("./list.handler").listHandler;
listWithTeam?: typeof import("./listWithTeam.handler").listWithTeamHandler;
create?: typeof import("./create.handler").createHandler;
get?: typeof import("./get.handler").getHandler;
update?: typeof import("./update.handler").updateHandler;
delete?: typeof import("./delete.handler").deleteHandler;
duplicate?: typeof import("./duplicate.handler").duplicateHandler;
bulkEventFetch?: typeof import("./bulkEventFetch.handler").bulkEventFetchHandler;
bulkUpdateToDefaultLocation?: typeof import("./bulkUpdateToDefaultLocation.handler").bulkUpdateToDefaultLocationHandler;
};
@@ -115,26 +109,8 @@ export const eventTypesRouter = router({
});
}),
create: authedProcedure.input(ZCreateInputSchema).mutation(async ({ ctx, input }) => {
const { createHandler } = await import("./create.handler");
return createHandler({
ctx,
input,
});
}),
get,
update: eventOwnerProcedure.input(ZUpdateInputSchema).mutation(async ({ ctx, input }) => {
const { updateHandler } = await import("./update.handler");
return updateHandler({
ctx,
input,
});
}),
delete: eventOwnerProcedure.input(ZDeleteInputSchema).mutation(async ({ ctx, input }) => {
const { deleteHandler } = await import("./delete.handler");
@@ -144,15 +120,6 @@ export const eventTypesRouter = router({
});
}),
duplicate: eventOwnerProcedure.input(ZDuplicateInputSchema).mutation(async ({ ctx, input }) => {
const { duplicateHandler } = await import("./duplicate.handler");
return duplicateHandler({
ctx,
input,
});
}),
bulkEventFetch: authedProcedure.query(async ({ ctx }) => {
const { bulkEventFetchHandler } = await import("./bulkEventFetch.handler");
@@ -0,0 +1,45 @@
import { z } from "zod";
import { logP } from "@calcom/lib/perf";
import authedProcedure from "../../../../procedures/authedProcedure";
import { router } from "../../../../trpc";
import { ZCreateInputSchema } from "./create.schema";
import { ZDuplicateInputSchema } from "./duplicate.schema";
import { eventOwnerProcedure } from "../util";
import { ZUpdateInputSchema } from "./update.schema";
type BookingsRouterHandlerCache = {
create?: typeof import("./create.handler").createHandler;
duplicate?: typeof import("./duplicate.handler").duplicateHandler;
update?: typeof import("./update.handler").updateHandler;
};
const UNSTABLE_HANDLER_CACHE: BookingsRouterHandlerCache = {};
export const eventTypesRouter = router({
create: authedProcedure.input(ZCreateInputSchema).mutation(async ({ ctx, input }) => {
const { createHandler } = await import("./create.handler");
return createHandler({
ctx,
input,
});
}),
duplicate: eventOwnerProcedure.input(ZDuplicateInputSchema).mutation(async ({ ctx, input }) => {
const { duplicateHandler } = await import("./duplicate.handler");
return duplicateHandler({
ctx,
input,
});
}),
update: eventOwnerProcedure.input(ZUpdateInputSchema).mutation(async ({ ctx, input }) => {
const { updateHandler } = await import("./update.handler");
return updateHandler({
ctx,
input,
});
})
});
@@ -9,7 +9,7 @@ import type { EventTypeLocation } from "@calcom/prisma/zod/custom/eventtype";
import { TRPCError } from "@trpc/server";
import type { TrpcSessionUser } from "../../../types";
import type { TrpcSessionUser } from "../../../../types";
import type { TCreateInputSchema } from "./create.schema";
type SessionUser = NonNullable<TrpcSessionUser>;
@@ -1,4 +1,4 @@
import prismaMock from "../../../../../../tests/libs/__mocks__/prismaMock";
import prismaMock from "../../../../../../../tests/libs/__mocks__/prismaMock";
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
import { describe, it, expect, vi, beforeEach } from "vitest";
@@ -7,8 +7,8 @@ import { prisma } from "@calcom/prisma";
import { TRPCError } from "@trpc/server";
import type { TrpcSessionUser } from "../../../types";
import { setDestinationCalendarHandler } from "../../viewer/calendars/setDestinationCalendar.handler";
import type { TrpcSessionUser } from "../../../../types";
import { setDestinationCalendarHandler } from "../../../viewer/calendars/setDestinationCalendar.handler";
import type { TDuplicateInputSchema } from "./duplicate.schema";
type DuplicateOptions = {
@@ -26,15 +26,15 @@ import { eventTypeLocations } from "@calcom/prisma/zod-utils";
import { TRPCError } from "@trpc/server";
import type { TrpcSessionUser } from "../../../types";
import { setDestinationCalendarHandler } from "../../viewer/calendars/setDestinationCalendar.handler";
import type { TrpcSessionUser } from "../../../../types";
import { setDestinationCalendarHandler } from "../../../viewer/calendars/setDestinationCalendar.handler";
import type { TUpdateInputSchema } from "./update.schema";
import {
ensureUniqueBookingFields,
ensureEmailOrPhoneNumberIsPresent,
handleCustomInputs,
handlePeriodType,
} from "./util";
} from "../util";
type SessionUser = NonNullable<TrpcSessionUser>;
@@ -0,0 +1,2 @@
export { ZUpdateInputSchema } from "../types";
export type { TUpdateInputSchema } from "../types";
@@ -1,2 +0,0 @@
export { ZUpdateInputSchema } from "./types";
export type { TUpdateInputSchema } from "./types";