feat: adds availabilitesi and attendees endpoints, some cleanup less try/catch more if/else
This commit is contained in:
@@ -45,6 +45,7 @@ yarn-error.log*
|
||||
.idea
|
||||
|
||||
### VisualStudioCode template
|
||||
.vscode/
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
export const stringifyISODate = (date: Date|undefined): string => {
|
||||
return `${date?.toISOString()}`
|
||||
}
|
||||
|
||||
// FIXME: debug this, supposed to take an array/object and auto strinfy date-like values
|
||||
export const autoStringifyDateValues = ([key, value]: [string, unknown]): [string, unknown] => {
|
||||
console.log(key,value)
|
||||
return [key, typeof value === "object" && value instanceof Date ? stringifyISODate(value) : value]
|
||||
}
|
||||
@@ -9,7 +9,8 @@ const schemaApiKey = z
|
||||
expiresAt: z.date().optional(), // default is 30 days
|
||||
note: z.string().min(1).optional(),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
.strict();
|
||||
|
||||
const withValidApiKey = withValidation({
|
||||
schema: schemaApiKey,
|
||||
type: "Zod",
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaAttendee = z
|
||||
.object({
|
||||
id: z.number(),
|
||||
email: z.string().min(3),
|
||||
name: z.string().min(3).email(),
|
||||
timeZone: z.string().default("Europe/London"),
|
||||
locale: z.string().optional(),
|
||||
bookingId: z.number(),
|
||||
})
|
||||
.strict();
|
||||
const withValidAttendee = withValidation({
|
||||
schema: schemaAttendee,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaAttendee, withValidAttendee };
|
||||
@@ -0,0 +1,65 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaAvailability = z
|
||||
.object({
|
||||
uid: z.string().min(3),
|
||||
title: z.string().min(3),
|
||||
description: z.string().min(3).optional(),
|
||||
startTime: z.date().or(z.string()),
|
||||
endTime: z.date(),
|
||||
location: z.string().min(3).optional(),
|
||||
createdAt: z.date().or(z.string()),
|
||||
updatedAt: z.date(),
|
||||
confirmed: z.boolean().default(true),
|
||||
rejected: z.boolean().default(false),
|
||||
paid: z.boolean().default(false),
|
||||
|
||||
// bufferTime: z.number().default(0),
|
||||
// // attendees: z.array((schemaSchedule)).optional(),
|
||||
|
||||
// startTime: z.string().min(3),
|
||||
// endTime: z.string().min(3),
|
||||
// email: z.string().email(), // max is a full day.
|
||||
// emailVerified: z.date().optional(),
|
||||
// password: z.string().optional(),
|
||||
// bio: z.string().min(3).optional(),
|
||||
// avatar: z.string().optional(),
|
||||
// timeZone: z.string().default("Europe/London"),
|
||||
// weekStart: z.string().default("Sunday"),
|
||||
// bufferTime: z.number().default(0),
|
||||
// theme: z.string().optional(),
|
||||
// trialEndsAt: z.date().optional(),
|
||||
// eventTypes: z.array((schemaEventType)).optional(),
|
||||
// // credentials: z.array((schemaCredentials)).optional(),
|
||||
// // teams: z.array((schemaMembership)).optional(),
|
||||
// // bookings: z.array((schemaAvailability)).optional(),
|
||||
// // schedules: z.array((schemaSchedule)).optional(),
|
||||
// defaultScheduleId: z.number().optional(),
|
||||
// // selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
// completedOnboarding: z.boolean().default(false),
|
||||
// locale: z.string().optional(),
|
||||
// timeFormat: z.number().optional().default(12),
|
||||
// twoFactorEnabled: z.boolean().default(false),
|
||||
// twoFactorSecret: z.string().optional(),
|
||||
// identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
// identityProviderId: z.string().optional(),
|
||||
// // availavility: z.array((schemaAvailavility)).optional(),
|
||||
// invitedTo: z.number().optional(),
|
||||
// plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// // webhooks: z.array((schemaWebhook)).optional(),
|
||||
// brandColor: z.string().default("#292929"),
|
||||
// darkBrandColor: z.string().default("#fafafa"),
|
||||
// // destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
// away: z.boolean().default(false),
|
||||
// metadata: z.object({}).optional(),
|
||||
// verified: z.boolean().default(false),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidAvailability = withValidation({
|
||||
schema: schemaAvailability,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaAvailability, withValidAvailability };
|
||||
@@ -0,0 +1,65 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaBooking = z
|
||||
.object({
|
||||
uid: z.string().min(3),
|
||||
title: z.string().min(3),
|
||||
description: z.string().min(3).optional(),
|
||||
startTime: z.date().or(z.string()),
|
||||
endTime: z.date(),
|
||||
location: z.string().min(3).optional(),
|
||||
createdAt: z.date().or(z.string()),
|
||||
updatedAt: z.date(),
|
||||
confirmed: z.boolean().default(true),
|
||||
rejected: z.boolean().default(false),
|
||||
paid: z.boolean().default(false),
|
||||
|
||||
// bufferTime: z.number().default(0),
|
||||
// // attendees: z.array((schemaSchedule)).optional(),
|
||||
|
||||
// startTime: z.string().min(3),
|
||||
// endTime: z.string().min(3),
|
||||
// email: z.string().email(), // max is a full day.
|
||||
// emailVerified: z.date().optional(),
|
||||
// password: z.string().optional(),
|
||||
// bio: z.string().min(3).optional(),
|
||||
// avatar: z.string().optional(),
|
||||
// timeZone: z.string().default("Europe/London"),
|
||||
// weekStart: z.string().default("Sunday"),
|
||||
// bufferTime: z.number().default(0),
|
||||
// theme: z.string().optional(),
|
||||
// trialEndsAt: z.date().optional(),
|
||||
// eventTypes: z.array((schemaEventType)).optional(),
|
||||
// // credentials: z.array((schemaCredentials)).optional(),
|
||||
// // teams: z.array((schemaMembership)).optional(),
|
||||
// // bookings: z.array((schemaBooking)).optional(),
|
||||
// // schedules: z.array((schemaSchedule)).optional(),
|
||||
// defaultScheduleId: z.number().optional(),
|
||||
// // selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
// completedOnboarding: z.boolean().default(false),
|
||||
// locale: z.string().optional(),
|
||||
// timeFormat: z.number().optional().default(12),
|
||||
// twoFactorEnabled: z.boolean().default(false),
|
||||
// twoFactorSecret: z.string().optional(),
|
||||
// identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
// identityProviderId: z.string().optional(),
|
||||
// // availavility: z.array((schemaAvailavility)).optional(),
|
||||
// invitedTo: z.number().optional(),
|
||||
// plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// // webhooks: z.array((schemaWebhook)).optional(),
|
||||
// brandColor: z.string().default("#292929"),
|
||||
// darkBrandColor: z.string().default("#fafafa"),
|
||||
// // destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
// away: z.boolean().default(false),
|
||||
// metadata: z.object({}).optional(),
|
||||
// verified: z.boolean().default(false),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidBooking = withValidation({
|
||||
schema: schemaBooking,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaBooking, withValidBooking };
|
||||
@@ -0,0 +1,65 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaBooking = z
|
||||
.object({
|
||||
uid: z.string().min(3),
|
||||
title: z.string().min(3),
|
||||
description: z.string().min(3).optional(),
|
||||
startTime: z.date().or(z.string()),
|
||||
endTime: z.date(),
|
||||
location: z.string().min(3).optional(),
|
||||
createdAt: z.date().or(z.string()),
|
||||
updatedAt: z.date(),
|
||||
confirmed: z.boolean().default(true),
|
||||
rejected: z.boolean().default(false),
|
||||
paid: z.boolean().default(false),
|
||||
|
||||
// bufferTime: z.number().default(0),
|
||||
// // attendees: z.array((schemaSchedule)).optional(),
|
||||
|
||||
// startTime: z.string().min(3),
|
||||
// endTime: z.string().min(3),
|
||||
// email: z.string().email(), // max is a full day.
|
||||
// emailVerified: z.date().optional(),
|
||||
// password: z.string().optional(),
|
||||
// bio: z.string().min(3).optional(),
|
||||
// avatar: z.string().optional(),
|
||||
// timeZone: z.string().default("Europe/London"),
|
||||
// weekStart: z.string().default("Sunday"),
|
||||
// bufferTime: z.number().default(0),
|
||||
// theme: z.string().optional(),
|
||||
// trialEndsAt: z.date().optional(),
|
||||
// eventTypes: z.array((schemaEventType)).optional(),
|
||||
// // credentials: z.array((schemaCredentials)).optional(),
|
||||
// // teams: z.array((schemaMembership)).optional(),
|
||||
// // bookings: z.array((schemaBooking)).optional(),
|
||||
// // schedules: z.array((schemaSchedule)).optional(),
|
||||
// defaultScheduleId: z.number().optional(),
|
||||
// // selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
// completedOnboarding: z.boolean().default(false),
|
||||
// locale: z.string().optional(),
|
||||
// timeFormat: z.number().optional().default(12),
|
||||
// twoFactorEnabled: z.boolean().default(false),
|
||||
// twoFactorSecret: z.string().optional(),
|
||||
// identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
// identityProviderId: z.string().optional(),
|
||||
// // availavility: z.array((schemaAvailavility)).optional(),
|
||||
// invitedTo: z.number().optional(),
|
||||
// plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// // webhooks: z.array((schemaWebhook)).optional(),
|
||||
// brandColor: z.string().default("#292929"),
|
||||
// darkBrandColor: z.string().default("#fafafa"),
|
||||
// // destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
// away: z.boolean().default(false),
|
||||
// metadata: z.object({}).optional(),
|
||||
// verified: z.boolean().default(false),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidBooking = withValidation({
|
||||
schema: schemaBooking,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaBooking, withValidBooking };
|
||||
@@ -0,0 +1,65 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaBooking = z
|
||||
.object({
|
||||
uid: z.string().min(3),
|
||||
title: z.string().min(3),
|
||||
description: z.string().min(3).optional(),
|
||||
startTime: z.date().or(z.string()),
|
||||
endTime: z.date(),
|
||||
location: z.string().min(3).optional(),
|
||||
createdAt: z.date().or(z.string()),
|
||||
updatedAt: z.date(),
|
||||
confirmed: z.boolean().default(true),
|
||||
rejected: z.boolean().default(false),
|
||||
paid: z.boolean().default(false),
|
||||
|
||||
// bufferTime: z.number().default(0),
|
||||
// // attendees: z.array((schemaSchedule)).optional(),
|
||||
|
||||
// startTime: z.string().min(3),
|
||||
// endTime: z.string().min(3),
|
||||
// email: z.string().email(), // max is a full day.
|
||||
// emailVerified: z.date().optional(),
|
||||
// password: z.string().optional(),
|
||||
// bio: z.string().min(3).optional(),
|
||||
// avatar: z.string().optional(),
|
||||
// timeZone: z.string().default("Europe/London"),
|
||||
// weekStart: z.string().default("Sunday"),
|
||||
// bufferTime: z.number().default(0),
|
||||
// theme: z.string().optional(),
|
||||
// trialEndsAt: z.date().optional(),
|
||||
// eventTypes: z.array((schemaEventType)).optional(),
|
||||
// // credentials: z.array((schemaCredentials)).optional(),
|
||||
// // teams: z.array((schemaMembership)).optional(),
|
||||
// // bookings: z.array((schemaBooking)).optional(),
|
||||
// // schedules: z.array((schemaSchedule)).optional(),
|
||||
// defaultScheduleId: z.number().optional(),
|
||||
// // selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
// completedOnboarding: z.boolean().default(false),
|
||||
// locale: z.string().optional(),
|
||||
// timeFormat: z.number().optional().default(12),
|
||||
// twoFactorEnabled: z.boolean().default(false),
|
||||
// twoFactorSecret: z.string().optional(),
|
||||
// identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
// identityProviderId: z.string().optional(),
|
||||
// // availavility: z.array((schemaAvailavility)).optional(),
|
||||
// invitedTo: z.number().optional(),
|
||||
// plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// // webhooks: z.array((schemaWebhook)).optional(),
|
||||
// brandColor: z.string().default("#292929"),
|
||||
// darkBrandColor: z.string().default("#fafafa"),
|
||||
// // destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
// away: z.boolean().default(false),
|
||||
// metadata: z.object({}).optional(),
|
||||
// verified: z.boolean().default(false),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidBooking = withValidation({
|
||||
schema: schemaBooking,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaBooking, withValidBooking };
|
||||
@@ -0,0 +1,65 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaBooking = z
|
||||
.object({
|
||||
uid: z.string().min(3),
|
||||
title: z.string().min(3),
|
||||
description: z.string().min(3).optional(),
|
||||
startTime: z.date().or(z.string()),
|
||||
endTime: z.date(),
|
||||
location: z.string().min(3).optional(),
|
||||
createdAt: z.date().or(z.string()),
|
||||
updatedAt: z.date(),
|
||||
confirmed: z.boolean().default(true),
|
||||
rejected: z.boolean().default(false),
|
||||
paid: z.boolean().default(false),
|
||||
|
||||
// bufferTime: z.number().default(0),
|
||||
// // attendees: z.array((schemaSchedule)).optional(),
|
||||
|
||||
// startTime: z.string().min(3),
|
||||
// endTime: z.string().min(3),
|
||||
// email: z.string().email(), // max is a full day.
|
||||
// emailVerified: z.date().optional(),
|
||||
// password: z.string().optional(),
|
||||
// bio: z.string().min(3).optional(),
|
||||
// avatar: z.string().optional(),
|
||||
// timeZone: z.string().default("Europe/London"),
|
||||
// weekStart: z.string().default("Sunday"),
|
||||
// bufferTime: z.number().default(0),
|
||||
// theme: z.string().optional(),
|
||||
// trialEndsAt: z.date().optional(),
|
||||
// eventTypes: z.array((schemaEventType)).optional(),
|
||||
// // credentials: z.array((schemaCredentials)).optional(),
|
||||
// // teams: z.array((schemaMembership)).optional(),
|
||||
// // bookings: z.array((schemaBooking)).optional(),
|
||||
// // schedules: z.array((schemaSchedule)).optional(),
|
||||
// defaultScheduleId: z.number().optional(),
|
||||
// // selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
// completedOnboarding: z.boolean().default(false),
|
||||
// locale: z.string().optional(),
|
||||
// timeFormat: z.number().optional().default(12),
|
||||
// twoFactorEnabled: z.boolean().default(false),
|
||||
// twoFactorSecret: z.string().optional(),
|
||||
// identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
// identityProviderId: z.string().optional(),
|
||||
// // availavility: z.array((schemaAvailavility)).optional(),
|
||||
// invitedTo: z.number().optional(),
|
||||
// plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// // webhooks: z.array((schemaWebhook)).optional(),
|
||||
// brandColor: z.string().default("#292929"),
|
||||
// darkBrandColor: z.string().default("#fafafa"),
|
||||
// // destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
// away: z.boolean().default(false),
|
||||
// metadata: z.object({}).optional(),
|
||||
// verified: z.boolean().default(false),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidBooking = withValidation({
|
||||
schema: schemaBooking,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaBooking, withValidBooking };
|
||||
@@ -0,0 +1,65 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaBooking = z
|
||||
.object({
|
||||
uid: z.string().min(3),
|
||||
title: z.string().min(3),
|
||||
description: z.string().min(3).optional(),
|
||||
startTime: z.date().or(z.string()),
|
||||
endTime: z.date(),
|
||||
location: z.string().min(3).optional(),
|
||||
createdAt: z.date().or(z.string()),
|
||||
updatedAt: z.date(),
|
||||
confirmed: z.boolean().default(true),
|
||||
rejected: z.boolean().default(false),
|
||||
paid: z.boolean().default(false),
|
||||
|
||||
// bufferTime: z.number().default(0),
|
||||
// // attendees: z.array((schemaSchedule)).optional(),
|
||||
|
||||
// startTime: z.string().min(3),
|
||||
// endTime: z.string().min(3),
|
||||
// email: z.string().email(), // max is a full day.
|
||||
// emailVerified: z.date().optional(),
|
||||
// password: z.string().optional(),
|
||||
// bio: z.string().min(3).optional(),
|
||||
// avatar: z.string().optional(),
|
||||
// timeZone: z.string().default("Europe/London"),
|
||||
// weekStart: z.string().default("Sunday"),
|
||||
// bufferTime: z.number().default(0),
|
||||
// theme: z.string().optional(),
|
||||
// trialEndsAt: z.date().optional(),
|
||||
// eventTypes: z.array((schemaEventType)).optional(),
|
||||
// // credentials: z.array((schemaCredentials)).optional(),
|
||||
// // teams: z.array((schemaMembership)).optional(),
|
||||
// // bookings: z.array((schemaBooking)).optional(),
|
||||
// // schedules: z.array((schemaSchedule)).optional(),
|
||||
// defaultScheduleId: z.number().optional(),
|
||||
// // selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
// completedOnboarding: z.boolean().default(false),
|
||||
// locale: z.string().optional(),
|
||||
// timeFormat: z.number().optional().default(12),
|
||||
// twoFactorEnabled: z.boolean().default(false),
|
||||
// twoFactorSecret: z.string().optional(),
|
||||
// identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
// identityProviderId: z.string().optional(),
|
||||
// // availavility: z.array((schemaAvailavility)).optional(),
|
||||
// invitedTo: z.number().optional(),
|
||||
// plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// // webhooks: z.array((schemaWebhook)).optional(),
|
||||
// brandColor: z.string().default("#292929"),
|
||||
// darkBrandColor: z.string().default("#fafafa"),
|
||||
// // destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
// away: z.boolean().default(false),
|
||||
// metadata: z.object({}).optional(),
|
||||
// verified: z.boolean().default(false),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidBooking = withValidation({
|
||||
schema: schemaBooking,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaBooking, withValidBooking };
|
||||
@@ -0,0 +1,65 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaBooking = z
|
||||
.object({
|
||||
uid: z.string().min(3),
|
||||
title: z.string().min(3),
|
||||
description: z.string().min(3).optional(),
|
||||
startTime: z.date().or(z.string()),
|
||||
endTime: z.date(),
|
||||
location: z.string().min(3).optional(),
|
||||
createdAt: z.date().or(z.string()),
|
||||
updatedAt: z.date(),
|
||||
confirmed: z.boolean().default(true),
|
||||
rejected: z.boolean().default(false),
|
||||
paid: z.boolean().default(false),
|
||||
|
||||
// bufferTime: z.number().default(0),
|
||||
// // attendees: z.array((schemaSchedule)).optional(),
|
||||
|
||||
// startTime: z.string().min(3),
|
||||
// endTime: z.string().min(3),
|
||||
// email: z.string().email(), // max is a full day.
|
||||
// emailVerified: z.date().optional(),
|
||||
// password: z.string().optional(),
|
||||
// bio: z.string().min(3).optional(),
|
||||
// avatar: z.string().optional(),
|
||||
// timeZone: z.string().default("Europe/London"),
|
||||
// weekStart: z.string().default("Sunday"),
|
||||
// bufferTime: z.number().default(0),
|
||||
// theme: z.string().optional(),
|
||||
// trialEndsAt: z.date().optional(),
|
||||
// eventTypes: z.array((schemaEventType)).optional(),
|
||||
// // credentials: z.array((schemaCredentials)).optional(),
|
||||
// // teams: z.array((schemaMembership)).optional(),
|
||||
// // bookings: z.array((schemaBooking)).optional(),
|
||||
// // schedules: z.array((schemaSchedule)).optional(),
|
||||
// defaultScheduleId: z.number().optional(),
|
||||
// // selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
// completedOnboarding: z.boolean().default(false),
|
||||
// locale: z.string().optional(),
|
||||
// timeFormat: z.number().optional().default(12),
|
||||
// twoFactorEnabled: z.boolean().default(false),
|
||||
// twoFactorSecret: z.string().optional(),
|
||||
// identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
// identityProviderId: z.string().optional(),
|
||||
// // availavility: z.array((schemaAvailavility)).optional(),
|
||||
// invitedTo: z.number().optional(),
|
||||
// plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// // webhooks: z.array((schemaWebhook)).optional(),
|
||||
// brandColor: z.string().default("#292929"),
|
||||
// darkBrandColor: z.string().default("#fafafa"),
|
||||
// // destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
// away: z.boolean().default(false),
|
||||
// metadata: z.object({}).optional(),
|
||||
// verified: z.boolean().default(false),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidBooking = withValidation({
|
||||
schema: schemaBooking,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaBooking, withValidBooking };
|
||||
@@ -0,0 +1,65 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaBooking = z
|
||||
.object({
|
||||
uid: z.string().min(3),
|
||||
title: z.string().min(3),
|
||||
description: z.string().min(3).optional(),
|
||||
startTime: z.date().or(z.string()),
|
||||
endTime: z.date(),
|
||||
location: z.string().min(3).optional(),
|
||||
createdAt: z.date().or(z.string()),
|
||||
updatedAt: z.date(),
|
||||
confirmed: z.boolean().default(true),
|
||||
rejected: z.boolean().default(false),
|
||||
paid: z.boolean().default(false),
|
||||
|
||||
// bufferTime: z.number().default(0),
|
||||
// // attendees: z.array((schemaSchedule)).optional(),
|
||||
|
||||
// startTime: z.string().min(3),
|
||||
// endTime: z.string().min(3),
|
||||
// email: z.string().email(), // max is a full day.
|
||||
// emailVerified: z.date().optional(),
|
||||
// password: z.string().optional(),
|
||||
// bio: z.string().min(3).optional(),
|
||||
// avatar: z.string().optional(),
|
||||
// timeZone: z.string().default("Europe/London"),
|
||||
// weekStart: z.string().default("Sunday"),
|
||||
// bufferTime: z.number().default(0),
|
||||
// theme: z.string().optional(),
|
||||
// trialEndsAt: z.date().optional(),
|
||||
// eventTypes: z.array((schemaEventType)).optional(),
|
||||
// // credentials: z.array((schemaCredentials)).optional(),
|
||||
// // teams: z.array((schemaMembership)).optional(),
|
||||
// // bookings: z.array((schemaBooking)).optional(),
|
||||
// // schedules: z.array((schemaSchedule)).optional(),
|
||||
// defaultScheduleId: z.number().optional(),
|
||||
// // selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
// completedOnboarding: z.boolean().default(false),
|
||||
// locale: z.string().optional(),
|
||||
// timeFormat: z.number().optional().default(12),
|
||||
// twoFactorEnabled: z.boolean().default(false),
|
||||
// twoFactorSecret: z.string().optional(),
|
||||
// identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
// identityProviderId: z.string().optional(),
|
||||
// // availavility: z.array((schemaAvailavility)).optional(),
|
||||
// invitedTo: z.number().optional(),
|
||||
// plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// // webhooks: z.array((schemaWebhook)).optional(),
|
||||
// brandColor: z.string().default("#292929"),
|
||||
// darkBrandColor: z.string().default("#fafafa"),
|
||||
// // destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
// away: z.boolean().default(false),
|
||||
// metadata: z.object({}).optional(),
|
||||
// verified: z.boolean().default(false),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidBooking = withValidation({
|
||||
schema: schemaBooking,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaBooking, withValidBooking };
|
||||
@@ -0,0 +1,65 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaBooking = z
|
||||
.object({
|
||||
uid: z.string().min(3),
|
||||
title: z.string().min(3),
|
||||
description: z.string().min(3).optional(),
|
||||
startTime: z.date().or(z.string()),
|
||||
endTime: z.date(),
|
||||
location: z.string().min(3).optional(),
|
||||
createdAt: z.date().or(z.string()),
|
||||
updatedAt: z.date(),
|
||||
confirmed: z.boolean().default(true),
|
||||
rejected: z.boolean().default(false),
|
||||
paid: z.boolean().default(false),
|
||||
|
||||
// bufferTime: z.number().default(0),
|
||||
// // attendees: z.array((schemaSchedule)).optional(),
|
||||
|
||||
// startTime: z.string().min(3),
|
||||
// endTime: z.string().min(3),
|
||||
// email: z.string().email(), // max is a full day.
|
||||
// emailVerified: z.date().optional(),
|
||||
// password: z.string().optional(),
|
||||
// bio: z.string().min(3).optional(),
|
||||
// avatar: z.string().optional(),
|
||||
// timeZone: z.string().default("Europe/London"),
|
||||
// weekStart: z.string().default("Sunday"),
|
||||
// bufferTime: z.number().default(0),
|
||||
// theme: z.string().optional(),
|
||||
// trialEndsAt: z.date().optional(),
|
||||
// eventTypes: z.array((schemaEventType)).optional(),
|
||||
// // credentials: z.array((schemaCredentials)).optional(),
|
||||
// // teams: z.array((schemaMembership)).optional(),
|
||||
// // bookings: z.array((schemaBooking)).optional(),
|
||||
// // schedules: z.array((schemaSchedule)).optional(),
|
||||
// defaultScheduleId: z.number().optional(),
|
||||
// // selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
// completedOnboarding: z.boolean().default(false),
|
||||
// locale: z.string().optional(),
|
||||
// timeFormat: z.number().optional().default(12),
|
||||
// twoFactorEnabled: z.boolean().default(false),
|
||||
// twoFactorSecret: z.string().optional(),
|
||||
// identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
// identityProviderId: z.string().optional(),
|
||||
// // availavility: z.array((schemaAvailavility)).optional(),
|
||||
// invitedTo: z.number().optional(),
|
||||
// plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// // webhooks: z.array((schemaWebhook)).optional(),
|
||||
// brandColor: z.string().default("#292929"),
|
||||
// darkBrandColor: z.string().default("#fafafa"),
|
||||
// // destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
// away: z.boolean().default(false),
|
||||
// metadata: z.object({}).optional(),
|
||||
// verified: z.boolean().default(false),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidBooking = withValidation({
|
||||
schema: schemaBooking,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaBooking, withValidBooking };
|
||||
@@ -3,7 +3,7 @@ import { z } from "zod";
|
||||
|
||||
// Extracted out as utility function so can be reused
|
||||
// at different endpoints that require this validation.
|
||||
const schemaQueryId = z
|
||||
const schemaQueryIdParseInt = z
|
||||
.object({
|
||||
// since nextjs parses query params as strings,
|
||||
// we need to cast them to numbers using z.transform() and parseInt()
|
||||
@@ -15,9 +15,9 @@ const schemaQueryId = z
|
||||
.strict();
|
||||
|
||||
const withValidQueryIdTransformParseInt = withValidation({
|
||||
schema: schemaQueryId,
|
||||
schema: schemaQueryIdParseInt,
|
||||
type: "Zod",
|
||||
mode: "query",
|
||||
});
|
||||
|
||||
export { schemaQueryId, withValidQueryIdTransformParseInt };
|
||||
export { schemaQueryIdParseInt, withValidQueryIdTransformParseInt };
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import { withValidation } from "next-validations";
|
||||
import { z } from "zod";
|
||||
|
||||
const schemaBooking = z
|
||||
.object({
|
||||
uid: z.string().min(3),
|
||||
title: z.string().min(3),
|
||||
description: z.string().min(3).optional(),
|
||||
startTime: z.date().or(z.string()),
|
||||
endTime: z.date(),
|
||||
location: z.string().min(3).optional(),
|
||||
createdAt: z.date().or(z.string()),
|
||||
updatedAt: z.date(),
|
||||
confirmed: z.boolean().default(true),
|
||||
rejected: z.boolean().default(false),
|
||||
paid: z.boolean().default(false),
|
||||
|
||||
// bufferTime: z.number().default(0),
|
||||
// // attendees: z.array((schemaSchedule)).optional(),
|
||||
|
||||
// startTime: z.string().min(3),
|
||||
// endTime: z.string().min(3),
|
||||
// email: z.string().email(), // max is a full day.
|
||||
// emailVerified: z.date().optional(),
|
||||
// password: z.string().optional(),
|
||||
// bio: z.string().min(3).optional(),
|
||||
// avatar: z.string().optional(),
|
||||
// timeZone: z.string().default("Europe/London"),
|
||||
// weekStart: z.string().default("Sunday"),
|
||||
// bufferTime: z.number().default(0),
|
||||
// theme: z.string().optional(),
|
||||
// trialEndsAt: z.date().optional(),
|
||||
// eventTypes: z.array((schemaEventType)).optional(),
|
||||
// // credentials: z.array((schemaCredentials)).optional(),
|
||||
// // teams: z.array((schemaMembership)).optional(),
|
||||
// // bookings: z.array((schemaBooking)).optional(),
|
||||
// // schedules: z.array((schemaSchedule)).optional(),
|
||||
// defaultScheduleId: z.number().optional(),
|
||||
// // selectedCalendars: z.array((schemaSelectedCalendar)).optional(),
|
||||
// completedOnboarding: z.boolean().default(false),
|
||||
// locale: z.string().optional(),
|
||||
// timeFormat: z.number().optional().default(12),
|
||||
// twoFactorEnabled: z.boolean().default(false),
|
||||
// twoFactorSecret: z.string().optional(),
|
||||
// identityProvider: z.enum(["CAL", "SAML", "GOOGLE"]).optional().default("CAL"),
|
||||
// identityProviderId: z.string().optional(),
|
||||
// // availavility: z.array((schemaAvailavility)).optional(),
|
||||
// invitedTo: z.number().optional(),
|
||||
// plan: z.enum(['FREE', 'TRIAL', 'PRO']).default("TRIAL"),
|
||||
// // webhooks: z.array((schemaWebhook)).optional(),
|
||||
// brandColor: z.string().default("#292929"),
|
||||
// darkBrandColor: z.string().default("#fafafa"),
|
||||
// // destinationCalendar: z.instanceof(schemaEventType).optional(), // FIXME: instanceof doesnt work here
|
||||
// away: z.boolean().default(false),
|
||||
// metadata: z.object({}).optional(),
|
||||
// verified: z.boolean().default(false),
|
||||
})
|
||||
.strict(); // Adding strict so that we can disallow passing in extra fields
|
||||
const withValidBooking = withValidation({
|
||||
schema: schemaBooking,
|
||||
type: "Zod",
|
||||
mode: "body",
|
||||
});
|
||||
|
||||
export { schemaBooking, withValidBooking };
|
||||
@@ -11,6 +11,7 @@ type ResponseData = {
|
||||
export async function apiKey(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryIdAsString.safeParse(query);
|
||||
|
||||
if (method === "DELETE" && safe.success) {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
await prisma.apiKey
|
||||
@@ -23,10 +24,8 @@ export async function apiKey(req: NextApiRequest, res: NextApiResponse<ResponseD
|
||||
// This catches the error thrown by prisma.apiKey.delete() if the resource is not found.
|
||||
res.status(404).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed" });
|
||||
}
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ message: "Only DELETE Method allowed" });
|
||||
}
|
||||
|
||||
export default withValidQueryIdString(apiKey);
|
||||
|
||||
@@ -26,10 +26,8 @@ export async function editApiKey(req: NextApiRequest, res: NextApiResponse<Respo
|
||||
}).catch(error => {
|
||||
res.status(404).json({ message: `apiKey with ID ${safeQuery.data.id} not found and wasn't updated`, error })
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only PATCH Method allowed for updating API keys" });
|
||||
}
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ message: "Only PATCH Method allowed for updating API keys" });
|
||||
}
|
||||
|
||||
export default withValidQueryIdString(withValidApiKey(editApiKey));
|
||||
|
||||
@@ -18,10 +18,8 @@ export async function apiKey(req: NextApiRequest, res: NextApiResponse<ResponseD
|
||||
const apiKey = await prisma.apiKey.findUnique({ where: { id: safe.data.id } });
|
||||
if (!apiKey) res.status(404).json({ message: "API key was not found" });
|
||||
else res.status(200).json({ data: apiKey });
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,17 +12,7 @@ type ResponseData = {
|
||||
export default async function apiKeys(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { method } = req;
|
||||
if (method === "GET") {
|
||||
// try {
|
||||
const apiKeys = await prisma.apiKey.findMany({});
|
||||
res.status(200).json({ data: { ...apiKeys } });
|
||||
// Without any params this never fails. not sure how to force test unavailable prisma query
|
||||
// } catch (error) {
|
||||
// // FIXME: Add zod for validation/error handling
|
||||
// res.status(400).json({ error: error });
|
||||
// }
|
||||
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
} else res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
|
||||
@@ -15,21 +15,13 @@ async function createApiKey(req: NextApiRequest, res: NextApiResponse<ResponseDa
|
||||
const { body, method } = req;
|
||||
const safe = schemaApiKey.safeParse(body);
|
||||
if (method === "POST" && safe.success) {
|
||||
const apiKey = await prisma.apiKey
|
||||
.create({
|
||||
data: {
|
||||
...safe.data, user: { connect: { id: 1 } }
|
||||
}
|
||||
})
|
||||
if (apiKey) {
|
||||
res.status(201).json({ data: apiKey });
|
||||
} else {
|
||||
res.status(404).json({message: "API Key not created"});
|
||||
}
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ error: "Only POST Method allowed" });
|
||||
}
|
||||
const apiKey = await prisma.apiKey
|
||||
.create({ data: { ...safe.data, user: { connect: { id: 1 } } } })
|
||||
|
||||
if (apiKey) res.status(201).json({ data: apiKey });
|
||||
else res.status(404).json({ message: "API Key not created" });
|
||||
|
||||
} else res.status(405).json({ error: "Only POST Method allowed" });
|
||||
}
|
||||
|
||||
export default withValidApiKey(createApiKey);
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
|
||||
type ResponseData = {
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export async function attendee(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
|
||||
if (method === "DELETE" && safe.success) {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
prisma.attendee
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
.then(() => {
|
||||
// We only remove the attendee type from the database if there's an existing resource.
|
||||
res.status(200).json({ message: `attendee-type with id: ${safe.data.id} deleted successfully` });
|
||||
})
|
||||
.catch((error) => {
|
||||
// This catches the error thrown by prisma.attendee.delete() if the resource is not found.
|
||||
res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed in /attendee-types/[id]/delete endpoint" });
|
||||
}
|
||||
}
|
||||
|
||||
export default withValidQueryIdTransformParseInt(attendee);
|
||||
@@ -0,0 +1,33 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { Attendee } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaAttendee, withValidAttendee } from "@lib/validations/attendee";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Attendee;
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export async function editAttendee(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, body, method } = req;
|
||||
const safeQuery = await schemaQueryIdParseInt.safeParse(query);
|
||||
const safeBody = await schemaAttendee.safeParse(body);
|
||||
|
||||
if (method === "PATCH" && safeQuery.success && safeBody.success) {
|
||||
await prisma.attendee.update({
|
||||
where: { id: safeQuery.data.id },
|
||||
data: safeBody.data,
|
||||
}).then(attendee => {
|
||||
res.status(200).json({ data: attendee });
|
||||
}).catch(error => {
|
||||
res.status(404).json({ message: `Event type with ID ${safeQuery.data.id} not found and wasn't updated`, error })
|
||||
});
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ message: "Only PATCH Method allowed for updating attendees" });
|
||||
}
|
||||
|
||||
export default withValidQueryIdTransformParseInt(withValidAttendee(editAttendee));
|
||||
@@ -0,0 +1,27 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { Attendee } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Attendee;
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export async function attendee(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
|
||||
if (method === "GET" && safe.success) {
|
||||
const attendee = await prisma.attendee.findUnique({ where: { id: safe.data.id } });
|
||||
|
||||
if (attendee) res.status(200).json({ data: attendee });
|
||||
if (!attendee) res.status(404).json({ message: "Event type not found" });
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
|
||||
export default withValidQueryIdTransformParseInt(attendee);
|
||||
@@ -0,0 +1,19 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { Attendee } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Attendee[];
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export default async function attendee(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
try {
|
||||
const attendees = await prisma.attendee.findMany();
|
||||
res.status(200).json({ data: { ...attendees } });
|
||||
} catch (error) {
|
||||
// FIXME: Add zod for validation/error handling
|
||||
res.status(400).json({ error: error });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { Attendee } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaAttendee, withValidAttendee } from "@lib/validations/attendee";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Attendee;
|
||||
message?: string;
|
||||
error?: string;
|
||||
};
|
||||
|
||||
async function createAttendee(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { body, method } = req;
|
||||
const safe = schemaAttendee.safeParse(body);
|
||||
|
||||
if (method === "POST" && safe.success) {
|
||||
await prisma.attendee
|
||||
.create({ data: safe.data })
|
||||
.then((attendee) => res.status(201).json({ data: attendee }))
|
||||
.catch((error) => res.status(400).json({ message: "Could not create attendee type", error: error }));
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ error: "Only POST Method allowed" });
|
||||
}
|
||||
|
||||
export default withValidAttendee(createAttendee);
|
||||
@@ -0,0 +1,27 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
|
||||
type ResponseData = {
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export async function availability(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
if (method === "DELETE" && safe.success && safe.data) {
|
||||
const availability = await prisma.availability
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
// We only remove the availability type from the database if there's an existing resource.
|
||||
if (availability) res.status(200).json({ message: `availability with id: ${safe.data.id} deleted successfully` });
|
||||
// This catches the error thrown by prisma.availability.delete() if the resource is not found.
|
||||
else res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`});
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ message: "Only DELETE Method allowed in /availabilities/[id]/delete endpoint" });
|
||||
}
|
||||
|
||||
export default withValidQueryIdTransformParseInt(availability);
|
||||
@@ -0,0 +1,33 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { Availability } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaAvailability, withValidAvailability,} from "@lib/validations/availability";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Availability;
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export async function editAvailability(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, body, method } = req;
|
||||
const safeQuery = await schemaQueryIdParseInt.safeParse(query);
|
||||
const safeBody = await schemaAvailability.safeParse(body);
|
||||
|
||||
if (method === "PATCH" && safeQuery.success && safeBody.success) {
|
||||
await prisma.availability.update({
|
||||
where: { id: safeQuery.data.id },
|
||||
data: safeBody.data,
|
||||
}).then(availability => {
|
||||
res.status(200).json({ data: availability });
|
||||
}).catch(error => {
|
||||
res.status(404).json({ message: `Event type with ID ${safeQuery.data.id} not found and wasn't updated`, error })
|
||||
});
|
||||
// Reject any other HTTP method than PATCH
|
||||
} else res.status(405).json({ message: "Only PATCH Method allowed for updating availabilities" });
|
||||
}
|
||||
|
||||
export default withValidQueryIdTransformParseInt(withValidAvailability(editAvailability));
|
||||
@@ -0,0 +1,28 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { Availability } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Availability;
|
||||
message?: string;
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export async function availability(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
|
||||
if (method === "GET" && safe.success) {
|
||||
const availability = await prisma.availability.findUnique({ where: { id: safe.data.id } });
|
||||
|
||||
if (availability) res.status(200).json({ data: availability });
|
||||
if (!availability) res.status(404).json({ message: "Event type not found" });
|
||||
// Reject any other HTTP method than POST
|
||||
} else res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
|
||||
|
||||
export default withValidQueryIdTransformParseInt(availability);
|
||||
@@ -0,0 +1,19 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { Availability } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Availability[];
|
||||
error?: unknown;
|
||||
};
|
||||
|
||||
export default async function availability(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
try {
|
||||
const availabilities = await prisma.availability.findMany();
|
||||
res.status(200).json({ data: { ...availabilities } });
|
||||
} catch (error) {
|
||||
// FIXME: Add zod for validation/error handling
|
||||
res.status(400).json({ error: error });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { Availability } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaAvailability, withValidAvailability } from "@lib/validations/availability";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Availability;
|
||||
message?: string;
|
||||
error?: string;
|
||||
};
|
||||
|
||||
async function createAvailability(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { body, method } = req;
|
||||
if (method === "POST") {
|
||||
const safe = schemaAvailability.safeParse(body);
|
||||
if (safe.success && safe.data) {
|
||||
await prisma.availability
|
||||
.create({ data: safe.data })
|
||||
.then((availability) => res.status(201).json({ data: availability }))
|
||||
.catch((error) => res.status(400).json({ message: "Could not create availability type", error: error }));
|
||||
}
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ error: "Only POST Method allowed" });
|
||||
}
|
||||
}
|
||||
|
||||
export default withValidAvailability(createAvailability);
|
||||
@@ -2,7 +2,7 @@ import prisma from "@calcom/prisma";
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
|
||||
type ResponseData = {
|
||||
@@ -12,24 +12,23 @@ type ResponseData = {
|
||||
|
||||
export async function booking(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryId.safeParse(query);
|
||||
if (safe.success) {
|
||||
if (method === "DELETE") {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
prisma.booking
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
.then(() => {
|
||||
// We only remove the booking type from the database if there's an existing resource.
|
||||
res.status(200).json({ message: `booking-type with id: ${safe.data.id} deleted successfully` });
|
||||
})
|
||||
.catch((error) => {
|
||||
// This catches the error thrown by prisma.booking.delete() if the resource is not found.
|
||||
res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed in /booking-types/[id]/delete endpoint" });
|
||||
}
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
|
||||
if (method === "DELETE" && safe.success) {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
prisma.booking
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
.then(() => {
|
||||
// We only remove the booking type from the database if there's an existing resource.
|
||||
res.status(200).json({ message: `booking-type with id: ${safe.data.id} deleted successfully` });
|
||||
})
|
||||
.catch((error) => {
|
||||
// This catches the error thrown by prisma.booking.delete() if the resource is not found.
|
||||
res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed in /booking-types/[id]/delete endpoint" });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Booking } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaBooking, withValidBooking } from "@lib/validations/booking";
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Booking;
|
||||
@@ -14,7 +14,7 @@ type ResponseData = {
|
||||
|
||||
export async function editBooking(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, body, method } = req;
|
||||
const safeQuery = await schemaQueryId.safeParse(query);
|
||||
const safeQuery = await schemaQueryIdParseInt.safeParse(query);
|
||||
const safeBody = await schemaBooking.safeParse(body);
|
||||
|
||||
if (method === "PATCH") {
|
||||
|
||||
@@ -3,7 +3,7 @@ import prisma from "@calcom/prisma";
|
||||
import { Booking } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Booking;
|
||||
@@ -13,17 +13,16 @@ type ResponseData = {
|
||||
|
||||
export async function booking(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryId.safeParse(query);
|
||||
if (safe.success) {
|
||||
if (method === "GET") {
|
||||
const booking = await prisma.booking.findUnique({ where: { id: safe.data.id } });
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
|
||||
if (booking) res.status(200).json({ data: booking });
|
||||
if (!booking) res.status(404).json({ message: "Event type not found" });
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
if (method === "GET" && safe.success) {
|
||||
const booking = await prisma.booking.findUnique({ where: { id: safe.data.id } });
|
||||
|
||||
if (booking) res.status(200).json({ data: booking });
|
||||
if (!booking) res.status(404).json({ message: "Event type not found" });
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import prisma from "@calcom/prisma";
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
|
||||
type ResponseData = {
|
||||
@@ -12,24 +12,22 @@ type ResponseData = {
|
||||
|
||||
export async function eventType(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryId.safeParse(query);
|
||||
if (safe.success) {
|
||||
if (method === "DELETE") {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
prisma.eventType
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
.then(() => {
|
||||
// We only remove the event type from the database if there's an existing resource.
|
||||
res.status(200).json({ message: `event-type with id: ${safe.data.id} deleted successfully` });
|
||||
})
|
||||
.catch((error) => {
|
||||
// This catches the error thrown by prisma.eventType.delete() if the resource is not found.
|
||||
res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed in /event-types/[id]/delete endpoint" });
|
||||
}
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
if (method === "DELETE" && safe.success) {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
prisma.eventType
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
.then(() => {
|
||||
// We only remove the event type from the database if there's an existing resource.
|
||||
res.status(200).json({ message: `event-type with id: ${safe.data.id} deleted successfully` });
|
||||
})
|
||||
.catch((error) => {
|
||||
// This catches the error thrown by prisma.eventType.delete() if the resource is not found.
|
||||
res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed in /event-types/[id]/delete endpoint" });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { EventType } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaEventType, withValidEventType } from "@lib/validations/eventType";
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: EventType;
|
||||
@@ -14,7 +14,7 @@ type ResponseData = {
|
||||
|
||||
export async function editEventType(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, body, method } = req;
|
||||
const safeQuery = await schemaQueryId.safeParse(query);
|
||||
const safeQuery = await schemaQueryIdParseInt.safeParse(query);
|
||||
const safeBody = await schemaEventType.safeParse(body);
|
||||
|
||||
if (method === "PATCH") {
|
||||
|
||||
@@ -3,7 +3,7 @@ import prisma from "@calcom/prisma";
|
||||
import { EventType } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: EventType;
|
||||
@@ -13,17 +13,16 @@ type ResponseData = {
|
||||
|
||||
export async function eventType(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryId.safeParse(query);
|
||||
if (safe.success) {
|
||||
if (method === "GET") {
|
||||
const event = await prisma.eventType.findUnique({ where: { id: safe.data.id } });
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
|
||||
if (event) res.status(200).json({ data: event });
|
||||
if (!event) res.status(404).json({ message: "Event type not found" });
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
if (method === "GET" && safe.success) {
|
||||
const event = await prisma.eventType.findUnique({ where: { id: safe.data.id } });
|
||||
|
||||
if (event) res.status(200).json({ data: event });
|
||||
if (!event) res.status(404).json({ message: "Event type not found" });
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import prisma from "@calcom/prisma";
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
|
||||
type ResponseData = {
|
||||
@@ -12,24 +12,22 @@ type ResponseData = {
|
||||
|
||||
export async function team(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryId.safeParse(query);
|
||||
if (safe.success) {
|
||||
if (method === "DELETE") {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
prisma.team
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
.then(() => {
|
||||
// We only remove the team type from the database if there's an existing resource.
|
||||
res.status(200).json({ message: `team-type with id: ${safe.data.id} deleted successfully` });
|
||||
})
|
||||
.catch((error) => {
|
||||
// This catches the error thrown by prisma.team.delete() if the resource is not found.
|
||||
res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed in /team-types/[id]/delete endpoint" });
|
||||
}
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
if (method === "DELETE" && safe.success) {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
prisma.team
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
.then(() => {
|
||||
// We only remove the team type from the database if there's an existing resource.
|
||||
res.status(200).json({ message: `team-type with id: ${safe.data.id} deleted successfully` });
|
||||
})
|
||||
.catch((error) => {
|
||||
// This catches the error thrown by prisma.team.delete() if the resource is not found.
|
||||
res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed in /team-types/[id]/delete endpoint" });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Team } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaTeam, withValidTeam } from "@lib/validations/team";
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Team;
|
||||
@@ -14,7 +14,7 @@ type ResponseData = {
|
||||
|
||||
export async function editTeam(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, body, method } = req;
|
||||
const safeQuery = await schemaQueryId.safeParse(query);
|
||||
const safeQuery = await schemaQueryIdParseInt.safeParse(query);
|
||||
const safeBody = await schemaTeam.safeParse(body);
|
||||
|
||||
if (method === "PATCH") {
|
||||
|
||||
@@ -3,7 +3,7 @@ import prisma from "@calcom/prisma";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: Team;
|
||||
@@ -13,17 +13,16 @@ type ResponseData = {
|
||||
|
||||
export async function team(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryId.safeParse(query);
|
||||
if (safe.success) {
|
||||
if (method === "GET") {
|
||||
const team = await prisma.team.findUnique({ where: { id: safe.data.id } });
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
|
||||
if (method === "GET" && safe.success) {
|
||||
const team = await prisma.team.findUnique({ where: { id: safe.data.id } });
|
||||
|
||||
if (team) res.status(200).json({ data: team });
|
||||
if (!team) res.status(404).json({ message: "Event type not found" });
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
if (team) res.status(200).json({ data: team });
|
||||
if (!team) res.status(404).json({ message: "Event type not found" });
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import prisma from "@calcom/prisma";
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
|
||||
type ResponseData = {
|
||||
@@ -12,24 +12,22 @@ type ResponseData = {
|
||||
|
||||
export async function user(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryId.safeParse(query);
|
||||
if (safe.success) {
|
||||
if (method === "DELETE") {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
prisma.user
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
.then(() => {
|
||||
// We only remove the user type from the database if there's an existing resource.
|
||||
res.status(200).json({ message: `user-type with id: ${safe.data.id} deleted successfully` });
|
||||
})
|
||||
.catch((error) => {
|
||||
// This catches the error thrown by prisma.user.delete() if the resource is not found.
|
||||
res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed in /user-types/[id]/delete endpoint" });
|
||||
}
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
if (method === "DELETE" && safe.success) {
|
||||
// DELETE WILL DELETE THE EVENT TYPE
|
||||
prisma.user
|
||||
.delete({ where: { id: safe.data.id } })
|
||||
.then(() => {
|
||||
// We only remove the user type from the database if there's an existing resource.
|
||||
res.status(200).json({ message: `user-type with id: ${safe.data.id} deleted successfully` });
|
||||
})
|
||||
.catch((error) => {
|
||||
// This catches the error thrown by prisma.user.delete() if the resource is not found.
|
||||
res.status(400).json({ message: `Resource with id:${safe.data.id} was not found`, error: error });
|
||||
});
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only DELETE Method allowed in /user-types/[id]/delete endpoint" });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { User } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaUser, withValidUser } from "@lib/validations/user";
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: User;
|
||||
@@ -14,7 +14,7 @@ type ResponseData = {
|
||||
|
||||
export async function editUser(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, body, method } = req;
|
||||
const safeQuery = await schemaQueryId.safeParse(query);
|
||||
const safeQuery = await schemaQueryIdParseInt.safeParse(query);
|
||||
const safeBody = await schemaUser.safeParse(body);
|
||||
|
||||
if (method === "PATCH") {
|
||||
|
||||
@@ -3,7 +3,7 @@ import prisma from "@calcom/prisma";
|
||||
import { User } from "@calcom/prisma/client";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { schemaQueryId, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
import { schemaQueryIdParseInt, withValidQueryIdTransformParseInt } from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
type ResponseData = {
|
||||
data?: User;
|
||||
@@ -13,17 +13,15 @@ type ResponseData = {
|
||||
|
||||
export async function user(req: NextApiRequest, res: NextApiResponse<ResponseData>) {
|
||||
const { query, method } = req;
|
||||
const safe = await schemaQueryId.safeParse(query);
|
||||
if (safe.success) {
|
||||
if (method === "GET") {
|
||||
const user = await prisma.user.findUnique({ where: { id: safe.data.id } });
|
||||
const safe = await schemaQueryIdParseInt.safeParse(query);
|
||||
if (method === "GET" && safe.success) {
|
||||
const user = await prisma.user.findUnique({ where: { id: safe.data.id } });
|
||||
|
||||
if (user) res.status(200).json({ data: user });
|
||||
if (!user) res.status(404).json({ message: "Event type not found" });
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
if (user) res.status(200).json({ data: user });
|
||||
if (!user) res.status(404).json({ message: "Event type not found" });
|
||||
} else {
|
||||
// Reject any other HTTP method than POST
|
||||
res.status(405).json({ message: "Only GET Method allowed" });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import handleBookingEdit from "@api/bookings/[id]/edit";
|
||||
import { createMocks } from "node-mocks-http";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
describe("PATCH /api/bookings/[id]/edit with valid id and body updates an booking", () => {
|
||||
it("returns a message with the specified bookings", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "PATCH",
|
||||
query: {
|
||||
id: "2",
|
||||
},
|
||||
body: {
|
||||
title: "Updated title",
|
||||
slug: "updated-slug",
|
||||
length: 1,
|
||||
},
|
||||
});
|
||||
const booking = await prisma.booking.findUnique({ where: { id: parseInt(req.query.id) } });
|
||||
await handleBookingEdit(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
if (booking) booking.title = "Updated title";
|
||||
expect(JSON.parse(res._getData())).toStrictEqual({ data: booking });
|
||||
});
|
||||
});
|
||||
|
||||
describe("PATCH /api/bookings/[id]/edit with invalid id returns 404", () => {
|
||||
it("returns a message with the specified bookings", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "PATCH",
|
||||
query: {
|
||||
id: "0",
|
||||
},
|
||||
body: {
|
||||
title: "Updated title",
|
||||
slug: "updated-slug",
|
||||
length: 1,
|
||||
},
|
||||
});
|
||||
const booking = await prisma.booking.findUnique({ where: { id: parseInt(req.query.id) } });
|
||||
await handleBookingEdit(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(404);
|
||||
if (booking) booking.title = "Updated title";
|
||||
expect(JSON.parse(res._getData())).toStrictEqual({ "error": {
|
||||
"clientVersion": "3.10.0",
|
||||
"code": "P2025",
|
||||
"meta": {
|
||||
"cause": "Record to update not found.",
|
||||
},
|
||||
},
|
||||
"message": "Event type with ID 0 not found and wasn't updated", });
|
||||
});
|
||||
});
|
||||
|
||||
describe("PATCH /api/bookings/[id]/edit with valid id and no body returns 400 error and zod validation errors", () => {
|
||||
it("returns a message with the specified bookings", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "PATCH",
|
||||
query: {
|
||||
id: "2",
|
||||
},
|
||||
});
|
||||
await handleBookingEdit(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(JSON.parse(res._getData())).toStrictEqual([{"code": "invalid_type", "expected": "string", "message": "Required", "path": ["title"], "received": "undefined"}, {"code": "invalid_type", "expected": "string", "message": "Required", "path": ["slug"], "received": "undefined"}, {"code": "invalid_type", "expected": "number", "message": "Required", "path": ["length"], "received": "undefined"}]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("POST /api/bookings/[id]/edit fails, only PATCH allowed", () => {
|
||||
it("returns a message with the specified bookings", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "POST", // This POST method is not allowed
|
||||
query: {
|
||||
id: "1",
|
||||
},
|
||||
body: {
|
||||
title: "Updated title",
|
||||
slug: "updated-slug",
|
||||
length: 1,
|
||||
},
|
||||
});
|
||||
await handleBookingEdit(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
expect(JSON.parse(res._getData())).toStrictEqual({ message: "Only PATCH Method allowed for updating bookings" });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import handleBooking from "@api/bookings/[id]";
|
||||
import { createMocks } from "node-mocks-http";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { stringifyISODate } from "@lib/utils/stringifyISODate";
|
||||
|
||||
describe("GET /api/bookings/[id] with valid id as string returns an booking", () => {
|
||||
it("returns a message with the specified events", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "GET",
|
||||
query: {
|
||||
id: "1",
|
||||
},
|
||||
});
|
||||
const booking = await prisma.booking.findUnique({ where: { id: 1 } });
|
||||
await handleBooking(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(JSON.parse(res._getData())).toEqual({
|
||||
data: {
|
||||
...booking,
|
||||
createdAt: stringifyISODate(booking?.createdAt),
|
||||
startTime: stringifyISODate(booking?.startTime),
|
||||
endTime: stringifyISODate(booking?.endTime)
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// This can never happen under our normal nextjs setup where query is always a string | string[].
|
||||
// But seemed a good example for testing an error validation
|
||||
describe("GET /api/bookings/[id] errors if query id is number, requires a string", () => {
|
||||
it("returns a message with the specified events", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "GET",
|
||||
query: {
|
||||
id: 1, // passing query as a number, which should fail as nextjs will try to parse it as a string
|
||||
},
|
||||
});
|
||||
await handleBooking(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(JSON.parse(res._getData())).toStrictEqual([
|
||||
{
|
||||
code: "invalid_type",
|
||||
expected: "string",
|
||||
received: "number",
|
||||
path: ["id"],
|
||||
message: "Expected string, received number",
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("GET /api/bookings/[id] an id not present in db like 0, throws 404 not found", () => {
|
||||
it("returns a message with the specified events", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "GET",
|
||||
query: {
|
||||
id: "0", // There's no booking type with id 0
|
||||
},
|
||||
});
|
||||
await handleBooking(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(404);
|
||||
expect(JSON.parse(res._getData())).toStrictEqual({ message: "Event type not found" });
|
||||
});
|
||||
});
|
||||
|
||||
describe("POST /api/bookings/[id] fails, only GET allowed", () => {
|
||||
it("returns a message with the specified events", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "POST", // This POST method is not allowed
|
||||
query: {
|
||||
id: "1",
|
||||
},
|
||||
});
|
||||
await handleBooking(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
expect(JSON.parse(res._getData())).toStrictEqual({ message: "Only GET Method allowed" });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import handleApiKeys from "@api/api-keys";
|
||||
import { createMocks } from "node-mocks-http";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import {stringifyISODate} from "@lib/utils/stringifyISODate";
|
||||
|
||||
describe("GET /api/api-keys without any params", () => {
|
||||
it("returns a message with the specified apiKeys", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "GET",
|
||||
query: {},
|
||||
});
|
||||
let apiKeys = await prisma.apiKey.findMany();
|
||||
await handleApiKeys(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
apiKeys = apiKeys.map(apiKey => (apiKey = {...apiKey, createdAt: stringifyISODate(apiKey?.createdAt), expiresAt: stringifyISODate(apiKey?.expiresAt)}));
|
||||
expect(JSON.parse(res._getData())).toStrictEqual(JSON.parse(JSON.stringify({ data: {...apiKeys} })));
|
||||
});
|
||||
});
|
||||
|
||||
describe("POST /api/api-keys/ fails, only GET allowed", () => {
|
||||
it("returns a message with the specified apiKeys", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "POST", // This POST method is not allowed
|
||||
});
|
||||
await handleApiKeys(req, res);
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
expect(JSON.parse(res._getData())).toStrictEqual({ message: "Only GET Method allowed" });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
import handleNewApiKey from "@api/api-keys/new";
|
||||
import { createMocks } from "node-mocks-http";
|
||||
|
||||
describe("POST /api/api-keys/new with a note", () => {
|
||||
it("returns a 201, and the created api key", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "POST", // This POST method is not allowed
|
||||
body: {
|
||||
note: "Updated note",
|
||||
},
|
||||
});
|
||||
await handleNewApiKey(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(201);
|
||||
expect(JSON.parse(res._getData()).data.note).toStrictEqual("Updated note");
|
||||
});
|
||||
});
|
||||
|
||||
describe("POST /api/api-keys/new with a slug param", () => {
|
||||
it("returns error 400, and the details about invalid slug body param", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "POST", // This POST method is not allowed
|
||||
body: {
|
||||
note: "Updated note",
|
||||
slug: "slug",
|
||||
},
|
||||
});
|
||||
await handleNewApiKey(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(JSON.parse(res._getData())).toStrictEqual(
|
||||
[{"code": "unrecognized_keys", "keys": ["slug"], "message": "Unrecognized key(s) in object: 'slug'", "path": []}]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("GET /api/api-keys/new fails, only POST allowed", () => {
|
||||
it("returns a message with the specified apiKeys", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "GET", // This POST method is not allowed
|
||||
});
|
||||
await handleNewApiKey(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(405);
|
||||
expect(JSON.parse(res._getData())).toStrictEqual({ error: "Only POST Method allowed" });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// FIXME: test 405 when prisma fails look for how to test prisma errors
|
||||
describe("GET /api/api-keys/new fails, only POST allowed", () => {
|
||||
it("returns a message with the specified apiKeys", async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: "POST", // This POST method is not allowed
|
||||
body: {
|
||||
nonExistentParam: true
|
||||
// note: '123',
|
||||
// slug: 12,
|
||||
},
|
||||
});
|
||||
await handleNewApiKey(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(400);
|
||||
expect(JSON.parse(res._getData())).toStrictEqual([{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": ["nonExistentParam"],
|
||||
"message": "Unrecognized key(s) in object: 'nonExistentParam'", "path": []
|
||||
}]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user