feat: add sentry report wrapper to every api route in appDir (#19966)

* update oauth tests

* fix parseRequestData

* add logging

* add fallback

* use ??

* updates

* use parseUrlFormData in saml/callback

* update tests

* fix

* remove log

* update

* any -> unknown

* use HttpErrors

* addressed

* unknown -> any

* feat: Add entry report wrapper to every api route in appDir

* fix

* fix unit test

* fix
This commit is contained in:
Benny Joo
2025-03-11 23:38:49 -04:00
committed by GitHub
parent 1e9f3a8060
commit 87bc8d649a
49 changed files with 180 additions and 76 deletions
@@ -46,6 +46,4 @@ async function handler(req: NextRequest) {
}
}
const postHandler = defaultResponderForAppDir(handler);
export { postHandler as POST };
export const POST = defaultResponderForAppDir(handler);
+3 -2
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
@@ -14,5 +15,5 @@ async function handler(req: NextRequest) {
return NextResponse.json({ username: account.name }, { status: 201 });
}
export { handler as GET, handler as POST };
export const GET = defaultResponderForAppDir(handler);
export const POST = defaultResponderForAppDir(handler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { parseUrlFormData } from "app/api/parseRequestData";
import jwt from "jsonwebtoken";
import { NextResponse } from "next/server";
@@ -7,7 +8,7 @@ import prisma from "@calcom/prisma";
import { generateSecret } from "@calcom/trpc/server/routers/viewer/oAuth/addClient.handler";
import type { OAuthTokenPayload } from "@calcom/types/oauth";
export async function POST(req: NextRequest) {
async function handler(req: NextRequest) {
const { client_id, client_secret, grant_type } = await parseUrlFormData(req);
if (!client_id || !client_secret) {
@@ -63,3 +64,5 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ access_token }, { status: 200 });
}
export const POST = defaultResponderForAppDir(handler);
+4 -1
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { parseUrlFormData } from "app/api/parseRequestData";
import jwt from "jsonwebtoken";
import { NextResponse } from "next/server";
@@ -7,7 +8,7 @@ import prisma from "@calcom/prisma";
import { generateSecret } from "@calcom/trpc/server/routers/viewer/oAuth/addClient.handler";
import type { OAuthTokenPayload } from "@calcom/types/oauth";
export async function POST(req: NextRequest) {
async function handler(req: NextRequest) {
const { code, client_id, client_secret, grant_type, redirect_uri } = await parseUrlFormData(req);
if (grant_type !== "authorization_code") {
return NextResponse.json({ message: "grant_type invalid" }, { status: 400 });
@@ -88,3 +89,5 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ access_token, refresh_token }, { status: 200 });
}
export const POST = defaultResponderForAppDir(handler);
+1 -3
View File
@@ -36,6 +36,4 @@ async function handler(req: NextRequest) {
}
}
const getHandler = defaultResponderForAppDir(handler);
export { getHandler as GET };
export const GET = defaultResponderForAppDir(handler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { parseRequestData } from "app/api/parseRequestData";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -75,4 +76,4 @@ async function expireResetPasswordRequest(rawRequestId: string) {
});
}
export { handler as POST };
export const POST = defaultResponderForAppDir(handler);
@@ -22,8 +22,6 @@ async function handler(req: NextRequest) {
}
}
const getHandler = defaultResponderForAppDir(handler);
export { getHandler as GET };
export const GET = defaultResponderForAppDir(handler);
export const dynamic = "force-dynamic";
+1 -3
View File
@@ -20,6 +20,4 @@ async function handler(req: NextRequest) {
return NextResponse.json({ message: "No redirect URL provided" }, { status: 400 });
}
const postHandler = defaultResponderForAppDir(handler);
export { postHandler as POST };
export const POST = defaultResponderForAppDir(handler);
+1 -3
View File
@@ -12,6 +12,4 @@ async function handler(req: NextRequest) {
return NextResponse.json(tokenResponse);
}
const postHandler = defaultResponderForAppDir(handler);
export { postHandler as POST };
export const POST = defaultResponderForAppDir(handler);
+1 -3
View File
@@ -31,8 +31,6 @@ async function handler(req: NextRequest) {
return NextResponse.json(userInfo);
}
const getHandler = defaultResponderForAppDir(handler);
export { getHandler as GET };
export const GET = defaultResponderForAppDir(handler);
export const dynamic = "force-dynamic";
+1 -3
View File
@@ -59,6 +59,4 @@ async function handler(req: NextRequest) {
return NextResponse.json({ message: "First admin user created successfully." });
}
const postHandler = defaultResponderForAppDir(handler);
export { postHandler as POST };
export const POST = defaultResponderForAppDir(handler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { parseRequestData } from "app/api/parseRequestData";
import { cookies, headers } from "next/headers";
import { NextResponse } from "next/server";
@@ -13,7 +14,7 @@ import { IdentityProvider } from "@calcom/prisma/client";
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
export async function POST(req: NextRequest) {
async function handler(req: NextRequest) {
const body = await parseRequestData(req);
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
@@ -114,3 +115,5 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ message: "Two factor disabled" });
}
export const POST = defaultResponderForAppDir(handler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { parseRequestData } from "app/api/parseRequestData";
import { cookies, headers } from "next/headers";
import { NextResponse } from "next/server";
@@ -11,7 +12,7 @@ import prisma from "@calcom/prisma";
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
export async function POST(req: NextRequest) {
async function postHandler(req: NextRequest) {
const body = await parseRequestData(req);
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
@@ -67,3 +68,5 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ message: "Two-factor enabled" });
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { parseRequestData } from "app/api/parseRequestData";
import crypto from "crypto";
import { cookies, headers } from "next/headers";
@@ -15,7 +16,7 @@ import { IdentityProvider } from "@calcom/prisma/enums";
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
export async function POST(req: NextRequest) {
async function postHandler(req: NextRequest) {
const body = await parseRequestData(req);
const session = await getServerSession({ req: buildLegacyRequest(headers(), cookies()) });
@@ -81,3 +82,5 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ secret, keyUri, dataUri, backupCodes });
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { cookies, headers } from "next/headers";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -105,4 +106,6 @@ async function deleteHandler(req: NextRequest) {
return NextResponse.json({ message: "Calendar Selection Saved" });
}
export { deleteHandler as DELETE, postHandler as POST, getHandler as GET };
export const POST = defaultResponderForAppDir(postHandler);
export const DELETE = defaultResponderForAppDir(deleteHandler);
export const GET = defaultResponderForAppDir(getHandler);
+1 -3
View File
@@ -63,6 +63,4 @@ async function handler(req: NextRequest, { params }: { params: Params }) {
});
}
const getHandler = defaultResponderForAppDir(handler);
export { getHandler as GET };
export const GET = defaultResponderForAppDir(handler);
+2 -4
View File
@@ -26,7 +26,5 @@ async function handler(req: NextRequest) {
return NextResponse.json(result, { status: statusCode });
}
const deleteHandler = defaultResponderForAppDir(handler);
const postHandler = defaultResponderForAppDir(handler);
export { deleteHandler as DELETE, postHandler as POST };
export const DELETE = defaultResponderForAppDir(handler);
export const POST = defaultResponderForAppDir(handler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -11,7 +12,7 @@ import { BookingStatus, ReminderType } from "@calcom/prisma/enums";
import type { EventTypeMetadata } from "@calcom/prisma/zod-utils";
import type { CalendarEvent } from "@calcom/types/Calendar";
export async function POST(request: NextRequest) {
async function postHandler(request: NextRequest) {
const apiKey = request.headers.get("authorization") || request.nextUrl.searchParams.get("apiKey");
if (process.env.CRON_API_KEY !== apiKey) {
@@ -145,3 +146,5 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ notificationsSent });
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,9 +1,10 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import prisma from "@calcom/prisma";
export async function POST(request: NextRequest) {
async function postHandler(request: NextRequest) {
const apiKey = request.headers.get("authorization") || request.nextUrl.searchParams.get("apiKey");
if (![process.env.CRON_API_KEY, `Bearer ${process.env.CRON_SECRET}`].includes(`${apiKey}`)) {
@@ -21,3 +22,5 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ ok: true, count: deleted.count });
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -20,7 +21,7 @@ const travelScheduleSelect = {
},
};
export async function POST(request: NextRequest) {
async function postHandler(request: NextRequest) {
const apiKey = request.headers.get("authorization") || request.nextUrl.searchParams.get("apiKey");
if (process.env.CRON_API_KEY !== apiKey) {
@@ -167,3 +168,5 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ timeZonesChanged });
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { z } from "zod";
@@ -9,7 +10,7 @@ const querySchema = z.object({
page: z.coerce.number().min(0).optional().default(0),
});
export async function POST(request: NextRequest) {
async function postHandler(request: NextRequest) {
const apiKey = request.headers.get("authorization") || request.nextUrl.searchParams.get("apiKey");
if (process.env.CRON_API_KEY !== apiKey) {
@@ -51,3 +52,5 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ ok: true });
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,4 +1,5 @@
import type { Prisma } from "@prisma/client";
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { z } from "zod";
@@ -13,7 +14,7 @@ const querySchema = z.object({
page: z.coerce.number().min(0).optional().default(0),
});
export async function POST(request: NextRequest) {
async function postHandler(request: NextRequest) {
const apiKey = request.headers.get("authorization") || request.nextUrl.searchParams.get("apiKey");
if (process.env.CRON_API_KEY !== apiKey) {
@@ -313,3 +314,5 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ ok: true });
}
export const POST = defaultResponderForAppDir(postHandler);
+4 -1
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -15,7 +16,7 @@ const log = logger.getSubLogger({
* syncAppMeta makes sure any app metadata that has been replicated into the database
* remains synchronized with any changes made to the app config files.
*/
export async function POST(request: NextRequest) {
async function postHandler(request: NextRequest) {
const apiKey = request.headers.get("authorization") || request.nextUrl.searchParams.get("apiKey");
if (process.env.CRON_API_KEY !== apiKey) {
@@ -62,3 +63,5 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ ok: true });
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,10 +1,11 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { handleWebhookScheduledTriggers } from "@calcom/features/webhooks/lib/handleWebhookScheduledTriggers";
import prisma from "@calcom/prisma";
export async function POST(req: NextRequest) {
async function postHandler(req: NextRequest) {
const apiKey = req.headers.get("authorization") || req.nextUrl.searchParams.get("apiKey");
if (process.env.CRON_API_KEY !== apiKey) {
@@ -15,3 +16,5 @@ export async function POST(req: NextRequest) {
return NextResponse.json({ ok: true });
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,3 +1,5 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { handler } from "@calcom/features/ee/workflows/api/scheduleEmailReminders";
export { handler as POST };
export const POST = defaultResponderForAppDir(handler);
@@ -1,3 +1,5 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { handler } from "@calcom/features/ee/workflows/api/scheduleSMSReminders";
export { handler as POST };
export const POST = defaultResponderForAppDir(handler);
@@ -1,3 +1,5 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { handler } from "@calcom/features/ee/workflows/api/scheduleWhatsappReminders";
export { handler as POST };
export const POST = defaultResponderForAppDir(handler);
+4 -1
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { NextResponse } from "next/server";
import { renderEmail } from "@calcom/emails";
@@ -7,7 +8,7 @@ import { getTranslation } from "@calcom/lib/server/i18n";
/**
* This API endpoint is used for development purposes to preview email templates
*/
export async function GET() {
async function getHandler() {
// Only allow in development mode
if (IS_PRODUCTION) {
return new NextResponse("Only for development purposes", {
@@ -73,3 +74,5 @@ export async function GET() {
return response;
}
export const GET = defaultResponderForAppDir(getHandler);
+4 -1
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { cookies, headers } from "next/headers";
import { NextResponse } from "next/server";
@@ -6,7 +7,7 @@ import { FUTURE_ROUTES_OVERRIDE_COOKIE_NAME as COOKIE_NAME } from "@calcom/lib/c
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
export async function GET() {
async function getHandler() {
const headersList = headers();
const cookiesList = cookies();
const legacyReq = buildLegacyRequest(headersList, cookiesList);
@@ -35,3 +36,5 @@ export async function GET() {
return response;
}
export const GET = defaultResponderForAppDir(getHandler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { cookies, headers } from "next/headers";
import { NextResponse } from "next/server";
@@ -7,7 +8,7 @@ import prisma from "@calcom/prisma";
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
export async function POST() {
async function postHandler() {
const headersList = headers();
const cookiesList = cookies();
const legacyReq = buildLegacyRequest(headersList, cookiesList);
@@ -51,3 +52,5 @@ export async function POST() {
return NextResponse.json({ shortLink });
}
export const POST = defaultResponderForAppDir(postHandler);
+4 -1
View File
@@ -1,7 +1,8 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { headers } from "next/headers";
import { NextResponse } from "next/server";
export async function GET() {
async function getHandler() {
const headersList = headers();
const country = headersList.get("x-vercel-ip-country") || "Unknown";
@@ -10,3 +11,5 @@ export async function GET() {
return response;
}
export const GET = defaultResponderForAppDir(getHandler);
+4 -1
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { cookies, headers } from "next/headers";
import { NextResponse } from "next/server";
import crypto from "node:crypto";
@@ -6,7 +7,7 @@ import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
import { buildLegacyRequest } from "@lib/buildLegacyCtx";
export async function GET() {
async function getHandler() {
const headersList = headers();
const cookiesList = cookies();
const legacyReq = buildLegacyRequest(headersList, cookiesList);
@@ -28,3 +29,5 @@ export async function GET() {
return NextResponse.json({ hash });
}
export const GET = defaultResponderForAppDir(getHandler);
+4 -1
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { cookies, headers } from "next/headers";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -162,7 +163,7 @@ async function getTeamLogos(subdomain: string, isValidOrgDomain: boolean) {
/**
* This API endpoint is used to serve the logo associated with a team if no logo is found we serve our default logo
*/
export async function GET(request: NextRequest) {
async function getHandler(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const parsedQuery = logoApiSchema.parse(Object.fromEntries(searchParams.entries()));
@@ -217,3 +218,5 @@ export async function GET(request: NextRequest) {
return NextResponse.json({ error: "Failed fetching logo" }, { status: 404 });
}
}
export const GET = defaultResponderForAppDir(getHandler);
+4 -1
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { cookies, headers } from "next/headers";
import { NextResponse } from "next/server";
@@ -8,7 +9,7 @@ import { buildLegacyRequest } from "@lib/buildLegacyCtx";
let isCold = true;
export async function GET() {
async function getHandler() {
const prePrismaDate = performance.now();
const prisma = (await import("@calcom/prisma")).default;
const preSessionDate = performance.now();
@@ -48,3 +49,5 @@ export async function GET() {
return response;
}
export const GET = defaultResponderForAppDir(getHandler);
+6 -2
View File
@@ -1,9 +1,13 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { NextResponse } from "next/server";
export async function GET() {
async function getHandler() {
return NextResponse.json({ message: "Please don't" }, { status: 400 });
}
export async function POST() {
async function postHandler() {
return NextResponse.json({ message: "Please don't" }, { status: 400 });
}
export const GET = defaultResponderForAppDir(getHandler);
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { createHmac } from "crypto";
import { headers } from "next/headers";
import type { NextRequest } from "next/server";
@@ -48,7 +49,7 @@ const getDownloadLinkOfCalVideo = async (recordingId: string) => {
return downloadLink;
};
export async function POST(request: NextRequest) {
export async function postHandler(request: NextRequest) {
if (!process.env.SENDGRID_API_KEY || !process.env.SENDGRID_EMAIL) {
return NextResponse.json({ message: "No SendGrid API key or email" }, { status: 405 });
}
@@ -225,3 +226,5 @@ export async function POST(request: NextRequest) {
}
}
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,4 +1,5 @@
import type { DirectorySyncEvent, DirectorySyncRequest } from "@boxyhq/saml-jackson";
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -51,23 +52,23 @@ const handleEvents = async (event: DirectorySyncEvent) => {
};
// This is the handler for the SCIM API requests
export async function GET(request: NextRequest, { params }: { params: { directory?: string[] } }) {
async function getHandler(request: NextRequest, { params }: { params: { directory?: string[] } }) {
return handleScimRequest(request, "GET", params.directory);
}
export async function POST(request: NextRequest, { params }: { params: { directory?: string[] } }) {
async function postHandler(request: NextRequest, { params }: { params: { directory?: string[] } }) {
return handleScimRequest(request, "POST", params.directory);
}
export async function PUT(request: NextRequest, { params }: { params: { directory?: string[] } }) {
async function putHandler(request: NextRequest, { params }: { params: { directory?: string[] } }) {
return handleScimRequest(request, "PUT", params.directory);
}
export async function PATCH(request: NextRequest, { params }: { params: { directory?: string[] } }) {
async function patchHandler(request: NextRequest, { params }: { params: { directory?: string[] } }) {
return handleScimRequest(request, "PATCH", params.directory);
}
export async function DELETE(request: NextRequest, { params }: { params: { directory?: string[] } }) {
async function deleteHandler(request: NextRequest, { params }: { params: { directory?: string[] } }) {
return handleScimRequest(request, "DELETE", params.directory);
}
@@ -139,3 +140,8 @@ async function handleScimRequest(request: NextRequest, method: string, directory
return NextResponse.json(data, { status });
}
export const GET = defaultResponderForAppDir(getHandler);
export const POST = defaultResponderForAppDir(postHandler);
export const PATCH = defaultResponderForAppDir(patchHandler);
export const DELETE = defaultResponderForAppDir(deleteHandler);
export const PUT = defaultResponderForAppDir(putHandler);
+4 -1
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { createHmac } from "crypto";
import { headers } from "next/headers";
import { cookies } from "next/headers";
@@ -21,7 +22,7 @@ const helpscoutRequestBodySchema = z.object({
* API for Helpscout to retrieve key information about a user from a ticket
* Note: HelpScout expects a JSON with a `html` prop to show its content as HTML
*/
export async function POST(request: NextRequest) {
async function postHandler(request: NextRequest) {
const hsSignature = request.headers.get("x-helpscout-signature");
if (!hsSignature) return NextResponse.json({ message: "Missing signature" }, { status: 400 });
@@ -94,3 +95,5 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ message: "Internal server error" }, { status: 500 });
}
}
export const POST = defaultResponderForAppDir(postHandler);
+5 -1
View File
@@ -1 +1,5 @@
export { GET } from "@calcom/features/tasker/api/cleanup";
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { GET as handler } from "@calcom/features/tasker/api/cleanup";
export const GET = defaultResponderForAppDir(handler);
+5 -1
View File
@@ -1,4 +1,8 @@
export { GET } from "@calcom/features/tasker/api/cron";
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { GET as handler } from "@calcom/features/tasker/api/cron";
export const GET = defaultResponderForAppDir(handler);
/**
* This runs each minute and we need fresh data each time
@@ -1,3 +1,5 @@
import type { Params } from "app/_types";
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { cookies, headers } from "next/headers";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -19,7 +21,7 @@ const querySchema = z.object({
session_id: z.string().min(1),
});
export async function GET(req: NextRequest, { params }: { params: { team: string } }) {
async function getHandler(req: NextRequest, { params }: { params: Params }) {
try {
const searchParams = req.nextUrl.searchParams;
const { team: id, session_id } = querySchema.parse({
@@ -102,3 +104,5 @@ export async function GET(req: NextRequest, { params }: { params: { team: string
return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
}
}
export const GET = defaultResponderForAppDir(getHandler);
+2 -1
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import type Stripe from "stripe";
@@ -90,4 +91,4 @@ async function getHandler(req: NextRequest) {
);
}
export { getHandler as GET };
export const GET = defaultResponderForAppDir(getHandler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { OAuth2Client } from "googleapis-common";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -10,7 +11,7 @@ const scopes = [
"https://www.googleapis.com/auth/admin.directory.customer.readonly",
];
export async function GET(request: NextRequest) {
async function getHandler(request: NextRequest) {
try {
// Get appKeys from google-calendar
const { client_id, client_secret } = await getAppKeysFromSlug("google-calendar");
@@ -44,3 +45,5 @@ export async function GET(request: NextRequest) {
);
}
}
export const GET = defaultResponderForAppDir(getHandler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { OAuth2Client } from "googleapis-common";
import { cookies, headers } from "next/headers";
import type { NextRequest } from "next/server";
@@ -17,7 +18,7 @@ const stateSchema = z.object({
teamId: z.string(),
});
export async function GET(request: NextRequest) {
async function getHandler(request: NextRequest) {
try {
const headersList = headers();
const cookiesList = cookies();
@@ -84,3 +85,5 @@ export async function GET(request: NextRequest) {
return NextResponse.redirect(`${WEBAPP_URL}/teams`);
}
}
export const GET = defaultResponderForAppDir(getHandler);
+4 -1
View File
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { cookies, headers } from "next/headers";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
@@ -13,7 +14,7 @@ const bodySchema = z.object({
orgSlug: z.string().optional(),
});
export async function POST(request: NextRequest) {
async function postHandler(request: NextRequest) {
try {
const body = await request.json();
const { username, orgSlug } = bodySchema.parse(body);
@@ -31,3 +32,5 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ error: "Failed to check username availability" }, { status: 400 });
}
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { parseRequestData } from "app/api/parseRequestData";
import { headers, cookies } from "next/headers";
import type { NextRequest } from "next/server";
@@ -27,7 +28,7 @@ const querySchema = z.object({
userId: z.string(),
});
export async function GET(request: NextRequest) {
async function getHandler(request: NextRequest) {
const url = new URL(request.url);
const queryParams = Object.fromEntries(request.nextUrl.searchParams.entries());
@@ -50,7 +51,7 @@ export async function GET(request: NextRequest) {
}
}
export async function POST(request: NextRequest) {
async function postHandler(request: NextRequest) {
const url = new URL(request.url);
const queryParams = Object.fromEntries(request.nextUrl.searchParams.entries());
@@ -148,3 +149,6 @@ async function handleBookingAction(
return NextResponse.redirect(`/booking/${booking.uid}`);
}
export const GET = defaultResponderForAppDir(getHandler);
export const POST = defaultResponderForAppDir(postHandler);
+4 -1
View File
@@ -1,6 +1,9 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import { NextResponse } from "next/server";
import * as pjson from "package.json";
export async function GET() {
async function getHandler() {
return NextResponse.json({ version: pjson.version });
}
export const GET = defaultResponderForAppDir(getHandler);
@@ -1,3 +1,4 @@
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import z from "zod";
@@ -16,7 +17,7 @@ const appCredentialWebhookRequestBodySchema = z.object({
keys: z.string(),
});
export async function POST(request: NextRequest) {
async function postHandler(request: NextRequest) {
if (!APP_CREDENTIAL_SHARING_ENABLED) {
return NextResponse.json({ message: "Credential sharing is not enabled" }, { status: 403 });
}
@@ -101,3 +102,5 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ message: "Internal server error" }, { status: 500 });
}
}
export const POST = defaultResponderForAppDir(postHandler);
@@ -55,7 +55,7 @@ vi.mock("next/server", async () => {
});
// Now import the handler after mocking
const { POST: handler } = recordedDailyVideoRoute;
const { postHandler } = recordedDailyVideoRoute;
beforeAll(() => {
// Setup env vars
@@ -76,6 +76,12 @@ vi.mock("@calcom/lib/videoClient", () => {
};
});
vi.mock("app/api/defaultResponderForAppDir", () => {
return {
defaultResponderForAppDir: vi.fn(),
};
});
const BATCH_PROCESSOR_JOB_FINSISHED_PAYLOAD = {
version: "1.1.0",
type: "batch-processor.job-finished",
@@ -273,7 +279,7 @@ describe("Handler: /api/recorded-daily-video", () => {
// Handle the response differently
try {
const response = await handler(nextReq);
const response = await postHandler(nextReq);
// For App Router, we just need to check if the response exists
expect(response).toBeDefined();
} catch (error) {