fix build and pass lint

pull/9078/head
Agusti Fernandez Pardo 2022-05-17 19:33:18 +02:00
parent 3366627835
commit 5aa0b37443
30 changed files with 193 additions and 74 deletions

View File

@ -120,21 +120,21 @@ We aim to provide a fully tested API for our peace of mind, this is accomplished
## Endpoints matrix
| resource | get [id] | get all | create | edit | delete |
| ------------------------ | -------- | ------- | ------ | ---- | ------ |
| attendees | ✅ | ✅ | ✅ | ✅ | ✅ |
| availabilities | ✅ | ✅ | ✅ | ✅ | ✅ |
| booking-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| destination-calendars | ✅ | ✅ | ✅ | ✅ | ✅ |
| custom-inputs | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-types | ✅ | ✅ | ✅ | ✅ | ✅ |
| memberships | ✅ | ✅ | ✅ | ✅ | ✅ |
| payments | ✅ | ✅ | ❌ | ❌ | ❌ |
| schedules | ✅ | ✅ | ✅ | ✅ | ✅ |
| selected-calendars | ✅ | ✅ | ✅ | ✅ | ✅ |
| teams | ✅ | ✅ | ✅ | ✅ | ✅ |
| users | ✅ | 👤[1] | ✅ | ✅ | ✅ |
| resource | get [id] | get all | create | edit | delete |
| --------------------- | -------- | ------- | ------ | ---- | ------ |
| attendees | ✅ | ✅ | ✅ | ✅ | ✅ |
| availabilities | ✅ | ✅ | ✅ | ✅ | ✅ |
| booking-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-references | ✅ | ✅ | ✅ | ✅ | ✅ |
| destination-calendars | ✅ | ✅ | ✅ | ✅ | ✅ |
| custom-inputs | ✅ | ✅ | ✅ | ✅ | ✅ |
| event-types | ✅ | ✅ | ✅ | ✅ | ✅ |
| memberships | ✅ | ✅ | ✅ | ✅ | ✅ |
| payments | ✅ | ✅ | ❌ | ❌ | ❌ |
| schedules | ✅ | ✅ | ✅ | ✅ | ✅ |
| selected-calendars | ✅ | ✅ | ✅ | ✅ | ✅ |
| teams | ✅ | ✅ | ✅ | ✅ | ✅ |
| users | ✅ | 👤[1] | ✅ | ✅ | ✅ |
## Models from database that are not exposed

View File

@ -1,51 +1,92 @@
import { z } from "zod";
import { _EventTypeModel as EventType } from "@calcom/prisma/zod";
import { eventTypeLocations, recurringEvent } from "@calcom/prisma/zod-utils";
import { jsonSchema } from "./shared/jsonSchema";
export const schemaEventTypeBaseBodyParams = EventType.pick({
title: true,
slug: true,
length: true,
hidden: true,
position: true,
userId: true,
teamId: true,
eventName: true,
timeZone: true,
periodType: true,
periodStartDate: true,
periodEndDate: true,
periodDays: true,
periodCountCalendarDays: true,
requiresConfirmation: true,
disableGuests: true,
hideCalendarNotes: true,
minimumBookingNotice: true,
beforeEventBuffer: true,
afterEventBuffer: true,
schedulingType: true,
price: true,
currency: true,
slotInterval: true,
metadata: true,
successRedirectUrl: true,
}).partial();
const schemaEventTypeCreateParams = z
const schemaEventTypeBaseParams = z
.object({
title: z.string(),
slug: z.string(),
length: z.number(),
description: z.string().optional().nullable(),
length: z.number().int(),
locations: jsonSchema,
metadata: jsonSchema,
recurringEvent: jsonSchema,
})
.strict();
export const schemaEventTypeCreateBodyParams =
schemaEventTypeBaseBodyParams.merge(schemaEventTypeCreateParams);
export const schemaEventTypeCreateBodyParams = schemaEventTypeBaseBodyParams.merge(schemaEventTypeBaseParams);
const schemaEventTypeEditParams = z
.object({
title: z.string().optional(),
slug: z.string().optional(),
length: z.number().optional(),
length: z.number().int().optional(),
})
.strict();
export const schemaEventTypeEditBodyParams = schemaEventTypeBaseBodyParams.merge(schemaEventTypeEditParams);
export const schemaEventTypeReadPublic = EventType.pick({
id: true,
title: true,
slug: true,
length: true,
});
// import { z } from "zod";
// import { _EventTypeModel as EventType } from "@calcom/prisma/zod";
// export const schemaEventTypeBaseBodyParams = EventType.omit({ id: true }).partial();
// const schemaEventTypeRequiredParams = z.object({
// title: z.string(),
// slug: z.string(),
// length: z.number(),
// });
// export const schemaEventTypeBodyParams = schemaEventTypeBaseBodyParams.merge(schemaEventTypeRequiredParams);
// // @NOTE: Removing locations and metadata properties before validation, add them later if required
// export const schemaEventTypePublic = EventType.omit({ locations: true, metadata: true });
locations: true,
hidden: true,
position: true,
userId: true,
teamId: true,
eventName: true,
timeZone: true,
periodType: true,
periodStartDate: true,
periodEndDate: true,
periodDays: true,
periodCountCalendarDays: true,
requiresConfirmation: true,
recurringEvent: true,
disableGuests: true,
hideCalendarNotes: true,
minimumBookingNotice: true,
beforeEventBuffer: true,
afterEventBuffer: true,
schedulingType: true,
price: true,
currency: true,
slotInterval: true,
metadata: true,
successRedirectUrl: true,
})
.merge(schemaEventTypeBaseParams)
.partial();

View File

@ -4,6 +4,8 @@ import { _UserModel as User } from "@calcom/prisma/zod";
import { timeZone } from "@lib/validations/shared/timeZone";
import { jsonSchema } from "./shared/jsonSchema";
// @note: These are the ONLY values allowed as weekStart. So user don't introduce bad data.
enum weekdays {
MONDAY = "Monday",
@ -57,6 +59,7 @@ export const schemaUserBaseBodyParams = User.pick({
timeZone: true,
weekStart: true,
endTime: true,
metadata: true,
bufferTime: true,
theme: true,
defaultScheduleId: true,
@ -89,6 +92,7 @@ const schemaUserEditParams = z.object({
.refine((id: number) => id > 0)
.optional(),
locale: z.nativeEnum(locales).optional(),
metadata: jsonSchema,
});
// @note: These are the values that are editable via PATCH method on the user Model,
@ -104,6 +108,7 @@ export const schemaUserReadPublic = User.pick({
emailVerified: true,
bio: true,
avatar: true,
metadata: true,
timeZone: true,
weekStart: true,
endTime: true,

View File

@ -1,4 +1,4 @@
{
{
"name": "@calcom/api",
"version": "1.0.0",
"description": "Public API for Cal.com",
@ -8,7 +8,7 @@
"private": true,
"scripts": {
"dev": "next build && PORT=3002 next start",
"dev-real":"PORT=3002 next dev",
"dev-real": "PORT=3002 next dev",
"start": "PORT=3002 next start",
"build": "next build",
"lint": "next lint",

View File

@ -132,7 +132,6 @@ export async function bookingReferenceById(
console.log(safeBody.error);
res.status(400).json({ message: "Invalid request body", error: safeBody.error });
return;
// throw new Error("Invalid request body");
}
await prisma.bookingReference
.update({ where: { id: safeQuery.data.id }, data: safeBody.data })

View File

@ -97,17 +97,7 @@ async function createOrlistAllBookingReferences(
if (!safe.success) {
res.status(400).json({ message: "Bad request. BookingReference body is invalid", error: safe.error });
return;
// throw new Error("Invalid request body");
}
const userWithBookings = await prisma.user.findUnique({
where: { id: userId },
include: { bookings: true },
});
if (!userWithBookings) {
throw new Error("User not found");
}
const userBookingIds = userWithBookings.bookings.map((booking: { id: number }) => booking.id).flat();
if (!safe.data.bookingId) throw new Error("BookingReference: bookingId not found");
if (!userBookingIds.includes(safe.data.bookingId)) res.status(401).json({ message: "Unauthorized" });
else {

View File

@ -106,7 +106,6 @@ export async function bookingById(
console.log(safeBody.error);
res.status(400).json({ message: "Bad request", error: safeBody.error });
return;
// throw new Error("Invalid request body");
}
await prisma.booking
.update({

View File

@ -76,7 +76,6 @@ async function createOrlistAllBookings(
console.log(safe.error);
res.status(400).json({ message: "Bad request. Booking body is invalid." });
return;
// throw new Error("Invalid request body");
}
safe.data.userId = userId;
const data = await prisma.booking.create({ data: { ...safe.data } });

View File

@ -105,7 +105,10 @@ async function eventTypeById(
case "PATCH":
if (!safeBody.success) {
throw new Error("Invalid request body");
{
res.status(400).json({ message: "Invalid request body" });
return;
}
}
await prisma.eventTypeCustomInput
.update({ where: { id: safeQuery.data.id }, data: safeBody.data })

View File

@ -59,7 +59,10 @@ async function createOrlistAllEventTypeCustomInputs(
* description: Authorization information is missing or invalid.
*/
const safe = schemaEventTypeCustomInputBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body" });
return;
}
// Since we're supporting a create or connect relation on eventType, we need to treat them differently
// When using connect on event type, check if userId is the owner of the event
if (safe.data.eventType.connect && !userEventTypes.includes(safe.data.eventType.connect.id as number)) {

View File

@ -121,7 +121,10 @@ export async function destionationCalendarById(
*/
case "PATCH":
if (!safeBody.success) {
throw new Error("Invalid request body");
{
res.status(400).json({ message: "Invalid request body" });
return;
}
}
await prisma.destinationCalendar
.update({ where: { id: safeQuery.data.id }, data: safeBody.data })

View File

@ -57,7 +57,10 @@ async function createOrlistAllDestinationCalendars(
* description: Authorization information is missing or invalid.
*/
const safe = schemaDestinationCalendarCreateBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body" });
return;
}
const data = await prisma.destinationCalendar.create({ data: { ...safe.data, userId } });
const destination_calendar = schemaDestinationCalendarReadPublic.parse(data);

View File

@ -93,7 +93,10 @@ export async function dailyEventReferenceById(
*/
case "PATCH":
if (!safeBody.success) {
throw new Error("Invalid request body");
{
res.status(400).json({ message: "Invalid request body" });
return;
}
}
await prisma.dailyEventReference
.update({ where: { id: safeQuery.data.id }, data: safeBody.data })

View File

@ -64,7 +64,10 @@ async function createOrlistAllDailyEventReferences(
* description: Authorization information is missing or invalid.
*/
const safe = schemaDailyEventReferenceCreateBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body" });
return;
}
const data = await prisma.dailyEventReference.create({ data: safe.data });
const daily_event_reference = schemaDailyEventReferenceReadPublic.parse(data);

View File

@ -91,7 +91,10 @@ export async function eventTypeById(
case "PATCH":
const safeBody = schemaEventTypeEditBodyParams.safeParse(body);
if (!safeBody.success) {
throw new Error("Invalid request body");
{
res.status(400).json({ message: "Invalid request body" });
return;
}
}
await prisma.eventType
.update({ where: { id: safeQuery.data.id }, data: safeBody.data })

View File

@ -16,6 +16,7 @@ async function createOrlistAllEventTypes(
* /event-types:
* get:
* summary: Find all event types
* operationId: listEventTypes
* tags:
* - event-types
* externalDocs:
@ -43,6 +44,32 @@ async function createOrlistAllEventTypes(
* /event-types:
* post:
* summary: Creates a new event type
* operationId: addEventType
* requestBody:
* description: Create a new event-type related to your user or team
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - title
* - slug
* - length
* - metadata
* properties:
* length:
* type: number
* example: 30
* metadata:
* type: object
* example: {"smartContractAddress": "0x1234567890123456789012345678901234567890"}
* title:
* type: string
* example: My Event
* slug:
* type: string
* example: my-event
* tags:
* - event-types
* externalDocs:
@ -56,7 +83,10 @@ async function createOrlistAllEventTypes(
* description: Authorization information is missing or invalid.
*/
const safe = schemaEventTypeCreateBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body", error: safe.error });
return;
}
const data = await prisma.eventType.create({ data: { ...safe.data, userId } });
const event_type = schemaEventTypeReadPublic.parse(data);

View File

@ -85,7 +85,10 @@ export async function WebhookById(
case "PATCH":
const safeBody = schemaWebhookEditBodyParams.safeParse(body);
if (!safeBody.success) {
throw new Error("Invalid request body");
{
res.status(400).json({ message: "Invalid request body" });
return;
}
}
await prisma.webhook
.update({ where: { id: safeQuery.data.id }, data: safeBody.data })

View File

@ -56,7 +56,10 @@ async function createOrlistAllWebhooks(
* description: Authorization information is missing or invalid.
*/
const safe = schemaWebhookCreateBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body" });
return;
}
const data = await prisma.webhook.create({ data: { ...safe.data, userId } });
const webhook = schemaWebhookReadPublic.parse(data);

View File

@ -97,7 +97,10 @@ export async function membershipById(
case "PATCH":
const safeBody = schemaMembershipBodyParams.safeParse(body);
if (!safeBody.success) {
throw new Error("Invalid request body");
{
res.status(400).json({ message: "Invalid request body" });
return;
}
}
await prisma.membership
.update({

View File

@ -52,7 +52,10 @@ async function createOrlistAllMemberships(
* description: Authorization information is missing or invalid.
*/
const safe = schemaMembershipBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body" });
return;
}
const data = await prisma.membership.create({ data: { ...safe.data, userId } });
const membership = schemaMembershipPublic.parse(data);

View File

@ -83,7 +83,10 @@ export async function scheduleById(
*/
case "PATCH":
if (!safeBody.success) {
throw new Error("Invalid request body");
{
res.status(400).json({ message: "Invalid request body" });
return;
}
}
await prisma.schedule
.update({ where: { id: safeQuery.data.id }, data: safeBody.data })

View File

@ -54,7 +54,10 @@ async function createOrlistAllSchedules(
* description: Authorization information is missing or invalid.
*/
const safe = schemaScheduleBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body" });
return;
}
const data = await prisma.schedule.create({ data: { ...safe.data, userId } });
const schedule = schemaSchedulePublic.parse(data);

View File

@ -115,7 +115,10 @@ export async function selectedCalendarById(
*/
case "PATCH":
if (!safeBody.success) {
throw new Error("Invalid request body");
{
res.status(400).json({ message: "Invalid request body" });
return;
}
}
await prisma.selectedCalendar
.update({

View File

@ -70,7 +70,10 @@ async function createOrlistAllSelectedCalendars(
* description: Authorization information is missing or invalid.
*/
const safe = schemaSelectedCalendarBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body" });
return;
}
// Create new selectedCalendar connecting it to current userId
const data = await prisma.selectedCalendar.create({
data: { ...safe.data, user: { connect: { id: userId } } },

View File

@ -102,7 +102,10 @@ export async function teamById(
case "PATCH":
if (!safeBody.success) {
throw new Error("Invalid request body");
{
res.status(400).json({ message: "Invalid request body" });
return;
}
}
await prisma.team
.update({ where: { id: safeQuery.data.id }, data: safeBody.data })

View File

@ -58,7 +58,10 @@ async function createOrlistAllTeams(
* description: Authorization information is missing or invalid.
*/
const safe = schemaTeamBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body" });
return;
}
const team = await prisma.team.create({ data: safe.data });
// We're also creating the relation membership of team ownership in this call.
const membership = await prisma.membership

View File

@ -104,7 +104,7 @@ export async function userById(
const safeBody = schemaUserEditBodyParams.safeParse(body);
if (!safeBody.success) {
res.status(400).json({ message: "Bad request", error: safeBody.error });
// throw new Error("Invalid request body");
return;
}
const userSchedules = await prisma.schedule.findMany({

View File

@ -56,7 +56,10 @@ async function createOrlistAllPayments(
* description: Authorization information is missing or invalid.
*/
const safe = schemaPaymentBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body" });
return;
}
const payment = await prisma.payment.create({ data: safe.data });
const data = schemaPaymentPublic.parse(payment);

View File

@ -31,7 +31,10 @@ import { schemaResourceBodyParams, schemaResourcePublic, withValidResource } fro
*/
async function createResource({body}: NextApiRequest, res: NextApiResponse<ResourceResponse>) {
const safe = schemaResourceBodyParams.safeParse(body);
if (!safe.success) throw new Error("Invalid request body");
if (!safe.success) {
res.status(400).json({ message: "Invalid request body" });
return;
}
const resource = await prisma.resource.create({ data: safe.data });
const data = schemaResourcePublic.parse(resource);

1
types.d.ts vendored
View File

@ -1,2 +1 @@
declare module "modify-response-middleware";