From e8890156a1df85db7b765ecbc6278d6f325227aa Mon Sep 17 00:00:00 2001 From: Benny Joo Date: Thu, 6 Feb 2025 23:16:38 +0000 Subject: [PATCH] chore: migrate `api/cancel` to App Router (#19074) * Add app/api/cancel/route.ts * remove pages router api/cancel * refactors needed * refactor --- apps/web/app/api/cancel/route.ts | 34 +++++++++++++++++++ apps/web/pages/api/cancel.ts | 17 ---------- .../bookings/lib/handleCancelBooking.ts | 10 +++--- .../handleSeats/cancel/cancelAttendeeSeat.ts | 9 +++-- 4 files changed, 46 insertions(+), 24 deletions(-) create mode 100644 apps/web/app/api/cancel/route.ts delete mode 100644 apps/web/pages/api/cancel.ts diff --git a/apps/web/app/api/cancel/route.ts b/apps/web/app/api/cancel/route.ts new file mode 100644 index 0000000000..fbb4ba6ad6 --- /dev/null +++ b/apps/web/app/api/cancel/route.ts @@ -0,0 +1,34 @@ +import { cookies, headers } from "next/headers"; +import { NextResponse } from "next/server"; +import type { NextRequest } from "next/server"; + +import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; +import handleCancelBooking from "@calcom/features/bookings/lib/handleCancelBooking"; + +import { buildLegacyRequest } from "@lib/buildLegacyCtx"; + +async function handler(req: NextRequest) { + let appDirRequestBody; + try { + appDirRequestBody = await req.json(); + } catch (error) { + return NextResponse.json({ success: false, message: "Invalid JSON" }, { status: 400 }); + } + const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) }); + const result = await handleCancelBooking({ + appDirRequestBody, + userId: session?.user?.id || -1, + }); + + const statusCode = result.success ? 200 : 400; + + return NextResponse.json(result, { status: statusCode }); +} + +export async function DELETE(req: NextRequest) { + return handler(req); +} + +export async function POST(req: NextRequest) { + return handler(req); +} diff --git a/apps/web/pages/api/cancel.ts b/apps/web/pages/api/cancel.ts deleted file mode 100644 index d6b78c07e9..0000000000 --- a/apps/web/pages/api/cancel.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { NextApiRequest } from "next"; - -import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; -import handleCancelBooking from "@calcom/features/bookings/lib/handleCancelBooking"; -import { defaultResponder, defaultHandler } from "@calcom/lib/server"; - -async function handler(req: NextApiRequest & { userId?: number }) { - const session = await getServerSession({ req }); - /* To mimic API behavior and comply with types */ - req.userId = session?.user?.id || -1; - return await handleCancelBooking(req); -} - -export default defaultHandler({ - DELETE: Promise.resolve({ default: defaultResponder(handler) }), - POST: Promise.resolve({ default: defaultResponder(handler) }), -}); diff --git a/packages/features/bookings/lib/handleCancelBooking.ts b/packages/features/bookings/lib/handleCancelBooking.ts index 38d3e0034b..aca62f41dd 100644 --- a/packages/features/bookings/lib/handleCancelBooking.ts +++ b/packages/features/bookings/lib/handleCancelBooking.ts @@ -140,7 +140,8 @@ async function getBookingToDelete(id: number | undefined, uid: string | undefine export type BookingToDelete = Awaited>; -export type CustomRequest = NextApiRequest & { +export type AppRouterRequest = { appDirRequestBody: unknown }; +export type CustomRequest = (NextApiRequest | AppRouterRequest) & { userId?: number; bookingToDelete?: BookingToDelete; platformClientId?: string; @@ -159,6 +160,7 @@ export type HandleCancelBookingResponse = { }; async function handler(req: CustomRequest) { + const body = (req as AppRouterRequest).appDirRequestBody ?? (req as NextApiRequest).body; const { id, uid, @@ -168,7 +170,7 @@ async function handler(req: CustomRequest) { cancelledBy, cancelSubsequentBookings, internalNote, - } = bookingCancelInput.parse(req.body); + } = bookingCancelInput.parse(body); req.bookingToDelete = await getBookingToDelete(id, uid); const { bookingToDelete, @@ -568,7 +570,7 @@ async function handler(req: CustomRequest) { await handleInternalNote({ internalNote, booking: bookingToDelete, - userId, + userId: userId || -1, teamId: teamId, }); } @@ -586,7 +588,7 @@ async function handler(req: CustomRequest) { } catch (error) { console.error("Error deleting event", error); } - req.statusCode = 200; + (req as NextApiRequest).statusCode = 200; return { success: true, message: "Booking successfully cancelled.", diff --git a/packages/features/bookings/lib/handleSeats/cancel/cancelAttendeeSeat.ts b/packages/features/bookings/lib/handleSeats/cancel/cancelAttendeeSeat.ts index c12e49cff6..d753fb2d07 100644 --- a/packages/features/bookings/lib/handleSeats/cancel/cancelAttendeeSeat.ts +++ b/packages/features/bookings/lib/handleSeats/cancel/cancelAttendeeSeat.ts @@ -1,3 +1,5 @@ +import type { NextApiRequest } from "next"; + import { getCalendar } from "@calcom/app-store/_utils/getCalendar"; import { updateMeeting } from "@calcom/core/videoClient"; import { sendCancelledSeatEmailsAndSMS } from "@calcom/emails"; @@ -15,7 +17,7 @@ import { bookingCancelAttendeeSeatSchema } from "@calcom/prisma/zod-utils"; import type { EventTypeMetadata } from "@calcom/prisma/zod-utils"; import type { CalendarEvent } from "@calcom/types/Calendar"; -import type { CustomRequest } from "../../handleCancelBooking"; +import type { AppRouterRequest, CustomRequest } from "../../handleCancelBooking"; async function cancelAttendeeSeat( req: CustomRequest, @@ -32,7 +34,8 @@ async function cancelAttendeeSeat( }, eventTypeMetadata: EventTypeMetadata ) { - const input = bookingCancelAttendeeSeatSchema.safeParse(req.body); + const body = (req as AppRouterRequest).appDirRequestBody ?? (req as NextApiRequest).body; + const input = bookingCancelAttendeeSeatSchema.safeParse(body); const { webhooks, evt, eventTypeInfo } = dataForWebhooks; if (!input.success) return; const { seatReferenceUid } = input.data; @@ -61,7 +64,7 @@ async function cancelAttendeeSeat( }, }), ]); - req.statusCode = 200; + (req as NextApiRequest).statusCode = 200; const attendee = bookingToDelete?.attendees.find((attendee) => attendee.id === seatReference.attendeeId);