chore: Couple fixes to improve error reporting (#16895)
* chore: Couple fixes to improve error reporting * tweak: Fix error message * refactor: Use findUniqueOrThrow instead of guard * fix: Broken test, missing ID - suspect it passes because only one record exists * chore: Minor refactor to split ZodEffect from ZodType * fix: Satify typescript
This commit is contained in:
@@ -2,7 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import handleCancelBooking from "@calcom/features/bookings/lib/handleCancelBooking";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import { schemaBookingCancelParams } from "@calcom/prisma/zod-utils";
|
||||
import { bookingCancelSchema } from "@calcom/prisma/zod-utils";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
@@ -65,7 +65,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
*/
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { id, allRemainingBookings, cancellationReason } = schemaQueryIdParseInt
|
||||
.merge(schemaBookingCancelParams.pick({ allRemainingBookings: true, cancellationReason: true }))
|
||||
.merge(bookingCancelSchema.pick({ allRemainingBookings: true, cancellationReason: true }))
|
||||
.parse({
|
||||
...req.query,
|
||||
allRemainingBookings: req.query.allRemainingBookings === "true",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type z from "zod";
|
||||
|
||||
import type { schemaBookingCancelParams } from "@calcom/prisma/zod-utils";
|
||||
import type { bookingCancelSchema } from "@calcom/prisma/zod-utils";
|
||||
|
||||
export function getMockRequestDataForCancelBooking(data: z.infer<typeof schemaBookingCancelParams>) {
|
||||
export function getMockRequestDataForCancelBooking(data: z.infer<typeof bookingCancelSchema>) {
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -28,11 +28,7 @@ import prisma, { bookingMinimalSelect } from "@calcom/prisma";
|
||||
import type { WebhookTriggerEvents } from "@calcom/prisma/enums";
|
||||
import { BookingStatus } from "@calcom/prisma/enums";
|
||||
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
|
||||
import {
|
||||
bookingMetadataSchema,
|
||||
EventTypeMetaDataSchema,
|
||||
schemaBookingCancelParams,
|
||||
} from "@calcom/prisma/zod-utils";
|
||||
import { bookingMetadataSchema, EventTypeMetaDataSchema, bookingCancelInput } from "@calcom/prisma/zod-utils";
|
||||
import type { EventTypeMetadata } from "@calcom/prisma/zod-utils";
|
||||
import { getAllWorkflowsFromEventType } from "@calcom/trpc/server/routers/viewer/workflows/util";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
@@ -43,7 +39,7 @@ import cancelAttendeeSeat from "./handleSeats/cancel/cancelAttendeeSeat";
|
||||
const log = logger.getSubLogger({ prefix: ["handleCancelBooking"] });
|
||||
|
||||
async function getBookingToDelete(id: number | undefined, uid: string | undefined) {
|
||||
return await prisma.booking.findUnique({
|
||||
return await prisma.booking.findUniqueOrThrow({
|
||||
where: {
|
||||
id,
|
||||
uid,
|
||||
@@ -160,7 +156,7 @@ export type HandleCancelBookingResponse = {
|
||||
|
||||
async function handler(req: CustomRequest) {
|
||||
const { id, uid, allRemainingBookings, cancellationReason, seatReferenceUid, cancelledBy } =
|
||||
schemaBookingCancelParams.parse(req.body);
|
||||
bookingCancelInput.parse(req.body);
|
||||
req.bookingToDelete = await getBookingToDelete(id, uid);
|
||||
const {
|
||||
bookingToDelete,
|
||||
@@ -172,11 +168,7 @@ async function handler(req: CustomRequest) {
|
||||
arePlatformEmailsEnabled,
|
||||
} = req;
|
||||
|
||||
if (!bookingToDelete || !bookingToDelete.user) {
|
||||
throw new HttpError({ statusCode: 400, message: "Booking not found" });
|
||||
}
|
||||
|
||||
if (!bookingToDelete.userId) {
|
||||
if (!bookingToDelete.userId || !bookingToDelete.user) {
|
||||
throw new HttpError({ statusCode: 400, message: "User not found" });
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { WorkflowRepository } from "@calcom/lib/server/repository/workflow";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { WebhookTriggerEvents } from "@calcom/prisma/enums";
|
||||
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
|
||||
import { schemaBookingCancelParams } from "@calcom/prisma/zod-utils";
|
||||
import { bookingCancelAttendeeSeatSchema } from "@calcom/prisma/zod-utils";
|
||||
import type { EventTypeMetadata } from "@calcom/prisma/zod-utils";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
|
||||
@@ -32,9 +32,10 @@ async function cancelAttendeeSeat(
|
||||
},
|
||||
eventTypeMetadata: EventTypeMetadata
|
||||
) {
|
||||
const { seatReferenceUid } = schemaBookingCancelParams.parse(req.body);
|
||||
const input = bookingCancelAttendeeSeatSchema.safeParse(req.body);
|
||||
const { webhooks, evt, eventTypeInfo } = dataForWebhooks;
|
||||
if (!seatReferenceUid) return;
|
||||
if (!input.success) return;
|
||||
const { seatReferenceUid } = input.data;
|
||||
const bookingToDelete = req.bookingToDelete;
|
||||
if (!bookingToDelete?.attendees.length || bookingToDelete.attendees.length < 2) return;
|
||||
|
||||
|
||||
@@ -2664,6 +2664,7 @@ describe("handleSeats", () => {
|
||||
|
||||
const mockBookingData = getMockRequestDataForBooking({
|
||||
data: {
|
||||
id: firstBookingId,
|
||||
eventTypeId: 1,
|
||||
responses: {
|
||||
email: booker.email,
|
||||
|
||||
@@ -17,12 +17,13 @@ export function defaultResponder<T>(f: Handle<T>) {
|
||||
return res.json(result);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
const error = getServerErrorFromUnknown(err);
|
||||
// dynamic import of Sentry so it's only loaded when something goes wrong.
|
||||
const captureException = (await import("@sentry/nextjs")).captureException;
|
||||
captureException(err);
|
||||
// return API route response
|
||||
// we don't want to report Bad Request errors to Sentry / console
|
||||
if (!(error.statusCode >= 400 && error.statusCode < 500)) {
|
||||
console.error(err);
|
||||
const captureException = (await import("@sentry/nextjs")).captureException;
|
||||
captureException(err);
|
||||
}
|
||||
return res
|
||||
.status(error.statusCode)
|
||||
.json({ message: error.message, url: error.url, method: error.method });
|
||||
|
||||
@@ -28,7 +28,6 @@ function parseZodErrorIssues(issues: ZodIssue[]): string {
|
||||
|
||||
export function getServerErrorFromUnknown(cause: unknown): HttpError {
|
||||
if (isZodError(cause)) {
|
||||
console.log("cause", cause);
|
||||
return new HttpError({
|
||||
statusCode: 400,
|
||||
message: parseZodErrorIssues(cause.issues),
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { z } from "zod";
|
||||
|
||||
import { SUCCESS_STATUS } from "@calcom/platform-constants";
|
||||
import type { ApiResponse, ApiErrorResponse } from "@calcom/platform-types";
|
||||
import type { schemaBookingCancelParams } from "@calcom/prisma/zod-utils";
|
||||
import type { bookingCancelSchema } from "@calcom/prisma/zod-utils";
|
||||
|
||||
import http from "../lib/http";
|
||||
|
||||
@@ -12,7 +12,7 @@ interface IUseCancelBooking {
|
||||
onError?: (err: ApiErrorResponse | Error) => void;
|
||||
}
|
||||
|
||||
type inputParams = z.infer<typeof schemaBookingCancelParams>;
|
||||
type inputParams = z.infer<typeof bookingCancelSchema>;
|
||||
|
||||
export const useCancelBooking = (
|
||||
{ onSuccess, onError }: IUseCancelBooking = {
|
||||
|
||||
@@ -314,7 +314,7 @@ export const bookingCreateBodySchemaForApi = extendedBookingCreateBody.merge(
|
||||
bookingCreateSchemaLegacyPropsForApi.partial()
|
||||
);
|
||||
|
||||
export const schemaBookingCancelParams = z.object({
|
||||
export const bookingCancelSchema = z.object({
|
||||
id: z.number().optional(),
|
||||
uid: z.string().optional(),
|
||||
allRemainingBookings: z.boolean().optional(),
|
||||
@@ -323,6 +323,15 @@ export const schemaBookingCancelParams = z.object({
|
||||
cancelledBy: z.string().email({ message: "Invalid email" }).optional(),
|
||||
});
|
||||
|
||||
export const bookingCancelAttendeeSeatSchema = z.object({
|
||||
seatReferenceUid: z.string(),
|
||||
});
|
||||
|
||||
export const bookingCancelInput = bookingCancelSchema.refine(
|
||||
(data) => !!data.id || !!data.uid,
|
||||
"At least one of the following required: 'id', 'uid'."
|
||||
);
|
||||
|
||||
export const vitalSettingsUpdateSchema = z.object({
|
||||
connected: z.boolean().optional(),
|
||||
selectedParam: z.string().optional(),
|
||||
|
||||
Reference in New Issue
Block a user