diff --git a/apps/api/v1/pages/api/credential-sync/_patch.ts b/apps/api/v1/pages/api/credential-sync/_patch.ts index d5ccf7c008f24d..0bcaa3ad5086e0 100644 --- a/apps/api/v1/pages/api/credential-sync/_patch.ts +++ b/apps/api/v1/pages/api/credential-sync/_patch.ts @@ -3,7 +3,8 @@ import type { NextApiRequest } from "next"; import { OAuth2UniversalSchema } from "@calcom/app-store/_utils/oauth/universalSchema"; import { symmetricDecrypt } from "@calcom/lib/crypto"; import { defaultResponder } from "@calcom/lib/server/defaultResponder"; -import prisma from "@calcom/prisma"; +import { prisma } from "@calcom/prisma"; +import type { Prisma } from "@calcom/prisma/client"; import { schemaCredentialPatchParams, schemaCredentialPatchBody } from "~/lib/validations/credential-sync"; @@ -71,7 +72,7 @@ async function handler(req: NextApiRequest) { userId, }, data: { - key, + key: key as unknown as Prisma.InputJsonValue, }, select: { id: true, diff --git a/apps/api/v1/pages/api/credential-sync/_post.ts b/apps/api/v1/pages/api/credential-sync/_post.ts index 5a3ef66cfae74a..bdf1451266d11a 100644 --- a/apps/api/v1/pages/api/credential-sync/_post.ts +++ b/apps/api/v1/pages/api/credential-sync/_post.ts @@ -6,7 +6,8 @@ import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData"; import { symmetricDecrypt } from "@calcom/lib/crypto"; import { HttpError } from "@calcom/lib/http-error"; import { defaultResponder } from "@calcom/lib/server/defaultResponder"; -import prisma from "@calcom/prisma"; +import { prisma } from "@calcom/prisma"; +import type { Prisma } from "@calcom/prisma/client"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; import { schemaCredentialPostBody, schemaCredentialPostParams } from "~/lib/validations/credential-sync"; @@ -92,7 +93,7 @@ async function handler(req: NextApiRequest) { data: { userId, appId: appSlug, - key, + key: key as unknown as Prisma.InputJsonValue, type: appMetadata.type, }, select: credentialForCalendarServiceSelect, diff --git a/apps/api/v1/test/lib/attendees/_post.test.ts b/apps/api/v1/test/lib/attendees/_post.test.ts index dc4c0c3105bae2..b0b5773ad00284 100644 --- a/apps/api/v1/test/lib/attendees/_post.test.ts +++ b/apps/api/v1/test/lib/attendees/_post.test.ts @@ -77,7 +77,7 @@ describe("POST /api/attendees", () => { const userBooking = { id: 1 }; - prismaMock.booking.findFirst.mockResolvedValue(userBooking); + prismaMock.booking.findFirst.mockResolvedValue(userBooking as any); const attendeeData = { id: 1, diff --git a/apps/api/v1/test/lib/bookings/[id]/_delete.test.ts b/apps/api/v1/test/lib/bookings/[id]/_delete.test.ts index a6f6467606eb1f..53c1239572d566 100644 --- a/apps/api/v1/test/lib/bookings/[id]/_delete.test.ts +++ b/apps/api/v1/test/lib/bookings/[id]/_delete.test.ts @@ -25,7 +25,7 @@ beforeEach(() => { id: userId, email: "test@example.com", name: "Test User", - }); + } as any); }); afterEach(() => { diff --git a/apps/api/v1/test/lib/bookings/[id]/_patch.test.ts b/apps/api/v1/test/lib/bookings/[id]/_patch.test.ts index ec9fccc1689ee6..1799226e180cfa 100644 --- a/apps/api/v1/test/lib/bookings/[id]/_patch.test.ts +++ b/apps/api/v1/test/lib/bookings/[id]/_patch.test.ts @@ -20,7 +20,7 @@ beforeEach(() => { id: userId, email: "test@example.com", name: "Test User", - }); + } as any); }); afterEach(() => { diff --git a/apps/api/v1/test/lib/bookings/_get.test.ts b/apps/api/v1/test/lib/bookings/_get.test.ts index 52a0ecf07ab0bd..f9585cee880e62 100644 --- a/apps/api/v1/test/lib/bookings/_get.test.ts +++ b/apps/api/v1/test/lib/bookings/_get.test.ts @@ -30,12 +30,13 @@ beforeEach(() => { id: userId, email: "test@example.com", name: "Test User", - }); + } as any); (getAccessibleUsers as any).mockResolvedValue([userId]); (retrieveOrgScopedAccessibleUsers as any).mockResolvedValue([userId]); prismaMock.membership.findMany.mockResolvedValue([ { + // @ts-expect-error Will be fixed by Prisma 6.7.0 upgrade mock changes - which uses vitest-mock-extended team: { id: 1, isOrganization: true, @@ -48,7 +49,7 @@ beforeEach(() => { id: userId, email: "test@example.com", }, - ]); + ] as any); }); afterEach(() => { diff --git a/apps/api/v1/test/lib/bookings/_post.test.ts b/apps/api/v1/test/lib/bookings/_post.test.ts index 87d2a12b9b48e9..77978723b8d121 100644 --- a/apps/api/v1/test/lib/bookings/_post.test.ts +++ b/apps/api/v1/test/lib/bookings/_post.test.ts @@ -11,9 +11,9 @@ import { getEventTypesFromDB } from "@calcom/features/bookings/lib/handleNewBook import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { buildBooking, buildEventType, buildWebhook, buildUser } from "@calcom/lib/test/builder"; -import prisma from "@calcom/prisma"; +import { prisma } from "@calcom/prisma"; import type { Booking } from "@calcom/prisma/client"; -import { CreationSource } from "@calcom/prisma/enums"; +import { CreationSource, BookingStatus } from "@calcom/prisma/enums"; import handler from "../../../pages/api/bookings/_post"; @@ -303,6 +303,7 @@ describe("POST /api/bookings", () => { prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({ ...buildEventType({ recurringEvent: { freq: 2, count: 12, interval: 1 } }), + // @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now. profile: { organizationId: null }, hosts: [], users: [buildUser()], @@ -340,6 +341,7 @@ describe("POST /api/bookings", () => { prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({ ...buildEventType({ recurringEvent: { freq: 2, count: 12, interval: 1 } }), + // @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now. profile: { organizationId: null }, hosts: [], users: [buildUser()], @@ -376,6 +378,7 @@ describe("POST /api/bookings", () => { prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({ ...buildEventType({ profileId: null }), + // @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now. profile: { organizationId: null }, hosts: [], users: [buildUser()], @@ -417,6 +420,7 @@ describe("POST /api/bookings", () => { prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({ ...buildEventType({ profileId: null, length: 15 }), + // @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now. profile: { organizationId: null }, hosts: [], users: [buildUser()], @@ -468,7 +472,7 @@ describe("POST /api/bookings", () => { prismaMock.booking.findUnique.mockResolvedValue({ ...originalBooking, - status: "cancelled", + status: "CANCELLED", }); const { req, res } = createMocks({ @@ -492,6 +496,7 @@ describe("POST /api/bookings", () => { prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({ ...buildEventType({ profileId: null, length: 15 }), + // @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now. profile: { organizationId: null }, hosts: [], users: [buildUser()], @@ -532,7 +537,7 @@ describe("POST /api/bookings", () => { const previousBooking = await prisma.booking.findUnique({ where: { uid: "original-booking-uid" }, }); - expect(previousBooking?.status).toBe("cancelled"); + expect(previousBooking?.status).toBe(BookingStatus.CANCELLED); }); test("Creates source as api_v1", async () => { @@ -556,6 +561,7 @@ describe("POST /api/bookings", () => { prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({ ...buildEventType({ profileId: null, length: 15 }), + // @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now. profile: { organizationId: null }, hosts: [], users: [buildUser()], @@ -627,6 +633,7 @@ describe("POST /api/bookings", () => { prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({ ...buildEventType({ profileId: null, length: 15 }), + // @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now. profile: { organizationId: null }, hosts: [], users: [buildUser()], @@ -684,6 +691,7 @@ describe("POST /api/bookings", () => { prismaMock.eventType.findUniqueOrThrow.mockResolvedValue({ ...buildEventType({ recurringEvent: { freq: 2, count: 12, interval: 1 } }), + // @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now. profile: { organizationId: null }, hosts: [], users: [buildUser()], diff --git a/apps/api/v1/test/lib/event-types/[id]/_delete.test.ts b/apps/api/v1/test/lib/event-types/[id]/_delete.test.ts index 5b3143df670cfa..863317a2d5caad 100644 --- a/apps/api/v1/test/lib/event-types/[id]/_delete.test.ts +++ b/apps/api/v1/test/lib/event-types/[id]/_delete.test.ts @@ -50,6 +50,7 @@ describe("DELETE /api/event-types/[id]", () => { // Mocking team.findUnique prismaMock.team.findUnique.mockResolvedValue({ id: teamId, + // @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now. members: [ { userId: memberUser, role: MembershipRole.MEMBER, teamId: teamId }, { userId: adminUser, role: MembershipRole.ADMIN, teamId: teamId }, diff --git a/apps/api/v1/test/lib/event-types/[id]/_get.test.ts b/apps/api/v1/test/lib/event-types/[id]/_get.test.ts index 836246bbb99637..8f1db30a3a6705 100644 --- a/apps/api/v1/test/lib/event-types/[id]/_get.test.ts +++ b/apps/api/v1/test/lib/event-types/[id]/_get.test.ts @@ -84,6 +84,7 @@ describe("GET /api/event-types/[id]", () => { prismaMock.team.findFirst.mockResolvedValue({ id: teamId, + // @ts-expect-error requires mockDeep which will be introduced in the Prisma 6.7.0 upgrade, ignore for now. members: [ { userId, diff --git a/apps/web/playwright/lib/test-helpers/routingFormHelpers.ts b/apps/web/playwright/lib/test-helpers/routingFormHelpers.ts index 9b60e05de6330b..f4946c04b17a2c 100644 --- a/apps/web/playwright/lib/test-helpers/routingFormHelpers.ts +++ b/apps/web/playwright/lib/test-helpers/routingFormHelpers.ts @@ -29,8 +29,11 @@ interface RouteConfig { value: string; }; isFallback?: boolean; + // eslint-disable-next-line @typescript-eslint/no-explicit-any queryValue?: any; + // eslint-disable-next-line @typescript-eslint/no-explicit-any attributesQueryValue?: any; + // eslint-disable-next-line @typescript-eslint/no-explicit-any fallbackAttributesQueryValue?: any; } @@ -129,6 +132,7 @@ export async function createRoutingForm(config: CreateRoutingFormConfig) { const teamEventsConfig = config.attributeRouting.teamEvents; // Create team events + // eslint-disable-next-line @typescript-eslint/no-explicit-any const teamEvents: { [key: string]: any } = {}; for (const eventConfig of teamEventsConfig) { const eventType = await createRoundRobinTeamEventType({ @@ -149,10 +153,8 @@ export async function createRoutingForm(config: CreateRoutingFormConfig) { throw new Error("Attributes not found"); } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const skillAttribute = attributes.find((attr) => attr.name === "Skills")!; - const locationAttribute = attributes.find((attr) => attr.name === "Location")!; - - console.log("Attributes", JSON.stringify(attributes, null, 2)); const javascriptEventRoute = { id: "8a898988-89ab-4cde-b012-31823f708642", @@ -316,41 +318,44 @@ export async function createRoutingForm(config: CreateRoutingFormConfig) { queryValue: { id: "814899aa-4567-489a-bcde-f1823f708646", type: "group" }, }, ], - fields: config.form?.fields || [ - { - id: form.formFieldLocation.id, - type: "select", - label: "Location", - options: formFieldLocationOptions, - required: true, - }, - { - id: form.formFieldSkills.id, - type: "multiselect", - label: "skills", - options: formFieldSkillsOptions, - required: true, - }, - { - id: form.formFieldEmail.id, - type: "email", - label: "Email", - required: true, - }, - { - id: form.formFieldName.id, - identifier: "name", - type: "text", - label: "Name", - required: false, - }, - { - id: form.formFieldRating.id, - type: "number", - label: "Rating", - required: false, - }, - ], + fields: ( + config.form?.fields || + ([ + { + id: form.formFieldLocation.id, + type: "select", + label: "Location", + options: formFieldLocationOptions, + required: true, + }, + { + id: form.formFieldSkills.id, + type: "multiselect", + label: "skills", + options: formFieldSkillsOptions, + required: true, + }, + { + id: form.formFieldEmail.id, + type: "email", + label: "Email", + required: true, + }, + { + id: form.formFieldName.id, + identifier: "name", + type: "text", + label: "Name", + required: false, + }, + { + id: form.formFieldRating.id, + type: "number", + label: "Rating", + required: false, + }, + ] satisfies FieldConfig[]) + ).map((field) => ({ ...field })), team: { connect: { id: teamId, @@ -379,172 +384,178 @@ export async function createRoutingForm(config: CreateRoutingFormConfig) { const form = await prisma.app_RoutingForms_Form.create({ data: { - routes: config.form?.routes || [ - { - id: "8a898988-89ab-4cde-b012-31823f708642", - action: { type: "eventTypeRedirectUrl", value: "pro/30min" }, - queryValue: { + routes: ( + config.form?.routes || + ([ + { id: "8a898988-89ab-4cde-b012-31823f708642", - type: "group", - children1: { - "8988bbb8-0123-4456-b89a-b1823f70c5ff": { - type: "rule", - properties: { - field: "c4296635-9f12-47b1-8153-c3a854649182", - value: ["event-routing"], - operator: "equal", - valueSrc: ["value"], - valueType: ["text"], + action: { type: "eventTypeRedirectUrl", value: "pro/30min" }, + queryValue: { + id: "8a898988-89ab-4cde-b012-31823f708642", + type: "group", + children1: { + "8988bbb8-0123-4456-b89a-b1823f70c5ff": { + type: "rule", + properties: { + field: "c4296635-9f12-47b1-8153-c3a854649182", + value: ["event-routing"], + operator: "equal", + valueSrc: ["value"], + valueType: ["text"], + }, }, }, }, }, - }, - { - id: "aa8aaba9-cdef-4012-b456-71823f70f7ef", - action: { type: "customPageMessage", value: "Custom Page Result" }, - queryValue: { + { id: "aa8aaba9-cdef-4012-b456-71823f70f7ef", - type: "group", - children1: { - "b99b8a89-89ab-4cde-b012-31823f718ff5": { - type: "rule", - properties: { - field: "c4296635-9f12-47b1-8153-c3a854649182", - value: ["custom-page"], - operator: "equal", - valueSrc: ["value"], - valueType: ["text"], + action: { type: "customPageMessage", value: "Custom Page Result" }, + queryValue: { + id: "aa8aaba9-cdef-4012-b456-71823f70f7ef", + type: "group", + children1: { + "b99b8a89-89ab-4cde-b012-31823f718ff5": { + type: "rule", + properties: { + field: "c4296635-9f12-47b1-8153-c3a854649182", + value: ["custom-page"], + operator: "equal", + valueSrc: ["value"], + valueType: ["text"], + }, }, }, }, }, - }, - { - id: "a8ba9aab-4567-489a-bcde-f1823f71b4ad", - action: { type: "externalRedirectUrl", value: `${WEBAPP_URL}/pro` }, - queryValue: { + { id: "a8ba9aab-4567-489a-bcde-f1823f71b4ad", - type: "group", - children1: { - "998b9b9a-0123-4456-b89a-b1823f7232b9": { - type: "rule", - properties: { - field: "c4296635-9f12-47b1-8153-c3a854649182", - value: ["external-redirect"], - operator: "equal", - valueSrc: ["value"], - valueType: ["text"], + action: { type: "externalRedirectUrl", value: `${WEBAPP_URL}/pro` }, + queryValue: { + id: "a8ba9aab-4567-489a-bcde-f1823f71b4ad", + type: "group", + children1: { + "998b9b9a-0123-4456-b89a-b1823f7232b9": { + type: "rule", + properties: { + field: "c4296635-9f12-47b1-8153-c3a854649182", + value: ["external-redirect"], + operator: "equal", + valueSrc: ["value"], + valueType: ["text"], + }, }, }, }, }, - }, - { - id: "aa8ba8b9-0123-4456-b89a-b182623406d8", - action: { type: "customPageMessage", value: "Multiselect(Legacy) chosen" }, - queryValue: { + { id: "aa8ba8b9-0123-4456-b89a-b182623406d8", - type: "group", - children1: { - "b98a8abb-cdef-4012-b456-718262343d27": { - type: "rule", - properties: { - field: multiSelectLegacyFieldUuid, - value: [["Option-2"]], - operator: "multiselect_equals", - valueSrc: ["value"], - valueType: ["multiselect"], + action: { type: "customPageMessage", value: "Multiselect(Legacy) chosen" }, + queryValue: { + id: "aa8ba8b9-0123-4456-b89a-b182623406d8", + type: "group", + children1: { + "b98a8abb-cdef-4012-b456-718262343d27": { + type: "rule", + properties: { + field: multiSelectLegacyFieldUuid, + value: [["Option-2"]], + operator: "multiselect_equals", + valueSrc: ["value"], + valueType: ["multiselect"], + }, }, }, }, }, - }, - { - id: "bb9ea8b9-0123-4456-b89a-b182623406d8", - action: { type: "customPageMessage", value: "Multiselect chosen" }, - queryValue: { - id: "aa8ba8b9-0123-4456-b89a-b182623406d8", - type: "group", - children1: { - "b98a8abb-cdef-4012-b456-718262343d27": { - type: "rule", - properties: { - field: multiSelectFieldUuid, - value: [[multiSelectOption2Uuid]], - operator: "multiselect_equals", - valueSrc: ["value"], - valueType: ["multiselect"], + { + id: "bb9ea8b9-0123-4456-b89a-b182623406d8", + action: { type: "customPageMessage", value: "Multiselect chosen" }, + queryValue: { + id: "aa8ba8b9-0123-4456-b89a-b182623406d8", + type: "group", + children1: { + "b98a8abb-cdef-4012-b456-718262343d27": { + type: "rule", + properties: { + field: multiSelectFieldUuid, + value: [[multiSelectOption2Uuid]], + operator: "multiselect_equals", + valueSrc: ["value"], + valueType: ["multiselect"], + }, }, }, }, }, - }, - { - id: "898899aa-4567-489a-bcde-f1823f708646", - action: { type: "customPageMessage", value: "Fallback Message" }, - isFallback: true, - queryValue: { id: "898899aa-4567-489a-bcde-f1823f708646", type: "group" }, - }, - ], - fields: config.form?.fields || [ - { - id: "c4296635-9f12-47b1-8153-c3a854649182", - type: "text", - label: "Test field", - required: true, - }, - { - id: multiSelectLegacyFieldUuid, - type: "multiselect", - label: "Multi Select(with Legacy `selectText`)", - identifier: "multi", - selectText: "Option-1\nOption-2", - required: false, - }, - { - id: multiSelectFieldUuid, - type: "multiselect", - label: "Multi Select", - identifier: "multi-new-format", - options: [ - { - id: multiSelectOption1Uuid, - label: "Option-1", - }, - { - id: multiSelectOption2Uuid, - label: "Option-2", - }, - ], - required: false, - }, - { - id: legacySelectFieldUuid, - type: "select", - label: "Legacy Select", - identifier: "test-select", - selectText: "Option-1\nOption-2", - required: false, - }, - { - id: selectFieldUuid, - type: "select", - label: "Select", - identifier: "test-select-new-format", - options: [ - { - id: selectOption1Uuid, - label: "Option-1", - }, - { - id: selectOption2Uuid, - label: "Option-2", - }, - ], - required: false, - }, - ], + { + id: "898899aa-4567-489a-bcde-f1823f708646", + action: { type: "customPageMessage", value: "Fallback Message" }, + isFallback: true, + queryValue: { id: "898899aa-4567-489a-bcde-f1823f708646", type: "group" }, + }, + ] satisfies RouteConfig[]) + ).map((field) => ({ ...field })), + fields: ( + config.form?.fields || + ([ + { + id: "c4296635-9f12-47b1-8153-c3a854649182", + type: "text", + label: "Test field", + required: true, + }, + { + id: multiSelectLegacyFieldUuid, + type: "multiselect", + label: "Multi Select(with Legacy `selectText`)", + identifier: "multi", + selectText: "Option-1\nOption-2", + required: false, + }, + { + id: multiSelectFieldUuid, + type: "multiselect", + label: "Multi Select", + identifier: "multi-new-format", + options: [ + { + id: multiSelectOption1Uuid, + label: "Option-1", + }, + { + id: multiSelectOption2Uuid, + label: "Option-2", + }, + ], + required: false, + }, + { + id: legacySelectFieldUuid, + type: "select", + label: "Legacy Select", + identifier: "test-select", + selectText: "Option-1\nOption-2", + required: false, + }, + { + id: selectFieldUuid, + type: "select", + label: "Select", + identifier: "test-select-new-format", + options: [ + { + id: selectOption1Uuid, + label: "Option-1", + }, + { + id: selectOption2Uuid, + label: "Option-2", + }, + ], + required: false, + }, + ] satisfies FieldConfig[]) + ).map((field) => ({ ...field })), user: { connect: { id: userId, diff --git a/packages/app-store/_utils/oauth/updateTokenObject.ts b/packages/app-store/_utils/oauth/updateTokenObject.ts index 3c3653f4685a65..d7ba4ef6032ee4 100644 --- a/packages/app-store/_utils/oauth/updateTokenObject.ts +++ b/packages/app-store/_utils/oauth/updateTokenObject.ts @@ -1,9 +1,9 @@ -import type { Prisma } from "@prisma/client"; import type z from "zod"; import logger from "@calcom/lib/logger"; import { CredentialRepository } from "@calcom/lib/server/repository/credential"; -import prisma from "@calcom/prisma"; +import { prisma } from "@calcom/prisma"; +import type { Prisma } from "@calcom/prisma/client"; import type { OAuth2UniversalSchemaWithCalcomBackwardCompatibility } from "./universalSchema"; @@ -23,7 +23,7 @@ export const updateTokenObject = async ({ id: credentialId, }, data: { - key: tokenObject, + key: tokenObject as unknown as Prisma.InputJsonValue, }, }); }; diff --git a/packages/app-store/nextcloudtalk/lib/VideoApiAdapter.ts b/packages/app-store/nextcloudtalk/lib/VideoApiAdapter.ts index 3283ac7aa9f651..537deb898755c4 100644 --- a/packages/app-store/nextcloudtalk/lib/VideoApiAdapter.ts +++ b/packages/app-store/nextcloudtalk/lib/VideoApiAdapter.ts @@ -5,6 +5,7 @@ import { z } from "zod"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import prisma from "@calcom/prisma"; +import type { Prisma } from "@calcom/prisma/client"; import type { CalendarEvent } from "@calcom/types/Calendar"; import type { CredentialPayload } from "@calcom/types/Credential"; import type { PartialReference } from "@calcom/types/EventManager"; @@ -102,7 +103,7 @@ const NextcloudTalkVideoApiAdapter = (credential: CredentialPayload): VideoApiAd id: credential.id, }, data: { - key: newTokenObject, + key: newTokenObject as unknown as Prisma.InputJsonValue, }, }); }, diff --git a/packages/app-store/zoomvideo/lib/VideoApiAdapter.ts b/packages/app-store/zoomvideo/lib/VideoApiAdapter.ts index ca8afb527e03b3..5b81876693520f 100644 --- a/packages/app-store/zoomvideo/lib/VideoApiAdapter.ts +++ b/packages/app-store/zoomvideo/lib/VideoApiAdapter.ts @@ -10,7 +10,8 @@ import { import logger from "@calcom/lib/logger"; import { getPiiFreeCalendarEvent } from "@calcom/lib/piiFreeData"; import { safeStringify } from "@calcom/lib/safeStringify"; -import prisma from "@calcom/prisma"; +import { prisma } from "@calcom/prisma"; +import type { Prisma } from "@calcom/prisma/client"; import { Frequency } from "@calcom/prisma/zod-utils"; import type { CalendarEvent } from "@calcom/types/Calendar"; import type { CredentialPayload } from "@calcom/types/Credential"; @@ -316,7 +317,8 @@ const ZoomVideoApiAdapter = (credential: CredentialPayload): VideoApiAdapter => id: credential.id, }, data: { - key: newTokenObject, + // z.passthrough() is not allowed in Prisma, but we know this is trusted. + key: newTokenObject as unknown as Prisma.InputJsonValue, }, }); }, diff --git a/packages/features/flags/features.repository.ts b/packages/features/flags/features.repository.ts index 343ba60852f56c..4a10c978f78d33 100644 --- a/packages/features/flags/features.repository.ts +++ b/packages/features/flags/features.repository.ts @@ -36,7 +36,6 @@ export class FeaturesRepository implements IFeaturesRepository { const features = await this.prismaClient.feature.findMany({ orderBy: { slug: "asc" }, - cacheStrategy: { swr: 300, ttl: 300 }, }); FeaturesRepository.featuresCache = { diff --git a/packages/features/insights/server/trpc-router.ts b/packages/features/insights/server/trpc-router.ts index db06ca7403f75b..c16aae8e0a16f1 100644 --- a/packages/features/insights/server/trpc-router.ts +++ b/packages/features/insights/server/trpc-router.ts @@ -12,7 +12,7 @@ import { } from "@calcom/features/insights/server/raw-data.schema"; import { getInsightsBookingService } from "@calcom/lib/di/containers/InsightsBooking"; import { getInsightsRoutingService } from "@calcom/lib/di/containers/InsightsRouting"; -import type { readonlyPrisma } from "@calcom/prisma"; +import type { PrismaClient } from "@calcom/prisma"; import { BookingStatus } from "@calcom/prisma/enums"; import authedProcedure from "@calcom/trpc/server/procedures/authedProcedure"; import { router } from "@calcom/trpc/server/trpc"; @@ -31,7 +31,7 @@ const UserBelongsToTeamInput = z.object({ type BuildBaseWhereConditionCtxType = { userIsOwnerAdminOfParentTeam: boolean; userOrganizationId: number | null; - insightsDb: typeof readonlyPrisma; + insightsDb: PrismaClient; }; interface BuildBaseWhereConditionType { @@ -341,7 +341,7 @@ function createInsightsBookingService( } function createInsightsRoutingService( - ctx: { insightsDb: typeof readonlyPrisma; user: { id: number; organizationId: number | null } }, + ctx: { insightsDb: PrismaClient; user: { id: number; organizationId: number | null } }, input: z.infer ) { return getInsightsRoutingService({ @@ -1037,7 +1037,7 @@ export async function getEventTypeList({ isAll, user, }: { - prisma: typeof readonlyPrisma; + prisma: PrismaClient; teamId: number | null | undefined; userId: number | null | undefined; isAll: boolean | undefined; diff --git a/packages/lib/server/repository/booking.ts b/packages/lib/server/repository/booking.ts index 7f4b9a6492de28..d225202598e8e1 100644 --- a/packages/lib/server/repository/booking.ts +++ b/packages/lib/server/repository/booking.ts @@ -1,16 +1,24 @@ import type { Prisma } from "@prisma/client"; -import type { FormResponse } from "@calcom/app-store/routing-forms/types/types"; import { withReporting } from "@calcom/lib/sentryWrapper"; import type { PrismaClient } from "@calcom/prisma"; -import { bookingMinimalSelect } from "@calcom/prisma"; import type { Booking } from "@calcom/prisma/client"; -import { RRTimestampBasis } from "@calcom/prisma/enums"; -import { BookingStatus } from "@calcom/prisma/enums"; +import { RRTimestampBasis, BookingStatus } from "@calcom/prisma/enums"; +import { bookingMinimalSelect } from "@calcom/prisma/selects/booking"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; import { UserRepository } from "./user"; +export type FormResponse = Record< + // Field ID + string, + { + value: number | string | string[]; + label: string; + identifier?: string; + } +>; + type TeamBookingsParamsBase = { user: { id: number; email: string }; teamId: number; @@ -540,8 +548,10 @@ export class BookingRepository { }, data: { location, - metadata, - ...(responses && { responses }), + // FIXME: metadata is untyped + metadata: metadata as unknown as Prisma.InputJsonValue, + // FIXME: responses is untyped + ...(responses && { responses: responses as unknown as Prisma.InputJsonValue }), ...(iCalSequence !== undefined && { iCalSequence }), references: { create: referencesToCreate, @@ -681,9 +691,13 @@ export class BookingRepository { }, }, }, + // eslint-disable-next-line @calcom/eslint/no-prisma-include-true destinationCalendar: true, + // eslint-disable-next-line @calcom/eslint/no-prisma-include-true payment: true, + // eslint-disable-next-line @calcom/eslint/no-prisma-include-true references: true, + // eslint-disable-next-line @calcom/eslint/no-prisma-include-true workflowReminders: true, }, }); @@ -825,9 +839,13 @@ export class BookingRepository { status: filterForUnconfirmed ? BookingStatus.PENDING : BookingStatus.ACCEPTED, }, include: { + // eslint-disable-next-line @calcom/eslint/no-prisma-include-true attendees: true, + // eslint-disable-next-line @calcom/eslint/no-prisma-include-true references: true, + // eslint-disable-next-line @calcom/eslint/no-prisma-include-true user: true, + // eslint-disable-next-line @calcom/eslint/no-prisma-include-true payment: true, }, }); diff --git a/packages/lib/server/repository/delegationCredential.ts b/packages/lib/server/repository/delegationCredential.ts index e43afaa616b3c2..6f7581fa0e3cb4 100644 --- a/packages/lib/server/repository/delegationCredential.ts +++ b/packages/lib/server/repository/delegationCredential.ts @@ -97,7 +97,8 @@ export class DelegationCredentialRepository { id: data.organizationId, }, }, - serviceAccountKey: encryptedKey, + // z.passthrough() is not allowed in Prisma, but we know this is trusted. + serviceAccountKey: encryptedKey as unknown as Prisma.InputJsonValue, }, select: delegationCredentialSafeSelect, }); diff --git a/packages/lib/server/repository/membership.ts b/packages/lib/server/repository/membership.ts index efab4aac26672a..007b51ace6e5a1 100644 --- a/packages/lib/server/repository/membership.ts +++ b/packages/lib/server/repository/membership.ts @@ -1,6 +1,6 @@ -import { availabilityUserSelect, prisma, type PrismaTransaction, type PrismaClient } from "@calcom/prisma"; +import { availabilityUserSelect, prisma, type PrismaTransaction } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; -import type { Prisma, Membership } from "@calcom/prisma/client"; +import type { Prisma, Membership, PrismaClient } from "@calcom/prisma/client"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; import logger from "../../logger"; diff --git a/packages/lib/server/repository/workspacePlatform.ts b/packages/lib/server/repository/workspacePlatform.ts index e19da8e1dd184a..a243fe15713b77 100644 --- a/packages/lib/server/repository/workspacePlatform.ts +++ b/packages/lib/server/repository/workspacePlatform.ts @@ -1,6 +1,5 @@ -import { Prisma } from "@prisma/client"; - import { prisma } from "@calcom/prisma"; +import { Prisma } from "@calcom/prisma/client"; import type { TServiceAccountKeySchema } from "@calcom/prisma/zod-utils"; import { serviceAccountKeySchema } from "@calcom/prisma/zod-utils"; @@ -42,7 +41,7 @@ export class WorkspacePlatformRepository { : _defaultServiceAccountKey; return await prisma.workspacePlatform.create({ data: { - defaultServiceAccountKey, + defaultServiceAccountKey: defaultServiceAccountKey as unknown as Prisma.InputJsonValue, ...rest, }, select: safeWorkspacePlatformSelect, @@ -95,7 +94,10 @@ export class WorkspacePlatformRepository { }) { return await prisma.workspacePlatform.update({ where: { id }, - data, + data: { + ...data, + defaultServiceAccountKey: data.defaultServiceAccountKey as unknown as Prisma.InputJsonValue, + }, select: safeWorkspacePlatformSelect, }); } diff --git a/packages/lib/server/service/InsightsBookingBaseService.ts b/packages/lib/server/service/InsightsBookingBaseService.ts index 78b33a521ae5a0..9877bff2a66557 100644 --- a/packages/lib/server/service/InsightsBookingBaseService.ts +++ b/packages/lib/server/service/InsightsBookingBaseService.ts @@ -13,7 +13,7 @@ import { isNumberFilterValue, } from "@calcom/features/data-table/lib/utils"; import type { DateRange } from "@calcom/features/insights/server/insightsDateUtils"; -import type { readonlyPrisma } from "@calcom/prisma"; +import type { PrismaClient } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; import { MembershipRepository } from "../repository/membership"; @@ -142,7 +142,7 @@ const NOTHING_CONDITION = Prisma.sql`1=0`; const bookingDataKeys = new Set(Object.keys(bookingDataSchema.shape)); export class InsightsBookingBaseService { - private prisma: typeof readonlyPrisma; + private prisma: PrismaClient; private options: InsightsBookingServiceOptions | null; private filters: InsightsBookingServiceFilterOptions | null; private cachedAuthConditions?: Prisma.Sql; @@ -153,7 +153,7 @@ export class InsightsBookingBaseService { options, filters, }: { - prisma: typeof readonlyPrisma; + prisma: PrismaClient; options: InsightsBookingServicePublicOptions; filters?: InsightsBookingServiceFilterOptions; }) { diff --git a/packages/lib/server/service/InsightsRoutingBaseService.ts b/packages/lib/server/service/InsightsRoutingBaseService.ts index 9d01a829a70494..6f0975fbc46931 100644 --- a/packages/lib/server/service/InsightsRoutingBaseService.ts +++ b/packages/lib/server/service/InsightsRoutingBaseService.ts @@ -12,7 +12,7 @@ import { isSingleSelectFilterValue, } from "@calcom/features/data-table/lib/utils"; import type { DateRange } from "@calcom/features/insights/server/insightsDateUtils"; -import type { readonlyPrisma } from "@calcom/prisma"; +import type { PrismaClient } from "@calcom/prisma"; import type { BookingStatus } from "@calcom/prisma/enums"; import { MembershipRole } from "@calcom/prisma/enums"; @@ -136,7 +136,7 @@ type GetConditionsOptions = { }; export class InsightsRoutingBaseService { - private prisma: typeof readonlyPrisma; + private prisma: PrismaClient; private options: InsightsRoutingServiceOptions | null; private filters: InsightsRoutingServiceFilterOptions; @@ -145,7 +145,7 @@ export class InsightsRoutingBaseService { options, filters, }: { - prisma: typeof readonlyPrisma; + prisma: PrismaClient; options: InsightsRoutingServicePublicOptions; filters: InsightsRoutingServiceFilterOptions; }) { diff --git a/packages/lib/server/service/InsightsRoutingDIService.ts b/packages/lib/server/service/InsightsRoutingDIService.ts index be384eb6ae2cb2..ca182251f1fb14 100644 --- a/packages/lib/server/service/InsightsRoutingDIService.ts +++ b/packages/lib/server/service/InsightsRoutingDIService.ts @@ -1,4 +1,4 @@ -import type { readonlyPrisma } from "@calcom/prisma"; +import type { PrismaClient } from "@calcom/prisma"; import { InsightsRoutingBaseService, @@ -7,7 +7,7 @@ import { } from "./InsightsRoutingBaseService"; export interface IInsightsRoutingService { - prisma: typeof readonlyPrisma; + prisma: PrismaClient; } export class InsightsRoutingService { diff --git a/packages/prisma/extensions/usage-tracking.ts b/packages/prisma/extensions/usage-tracking.ts index e21ee60fae6ab6..07b1867943e086 100644 --- a/packages/prisma/extensions/usage-tracking.ts +++ b/packages/prisma/extensions/usage-tracking.ts @@ -1,11 +1,11 @@ import { Prisma } from "@prisma/client"; -import type { PrismaClient as PrismaClientWithoutExtensions } from "@prisma/client"; +import type { PrismaClient } from "@prisma/client"; import { waitUntil } from "@vercel/functions"; import { UsageEvent, LicenseKeySingleton } from "@calcom/ee/common/server/LicenseKeyService"; import { DeploymentRepository } from "@calcom/lib/server/repository/deployment"; -async function incrementUsage(prismaClient: PrismaClientWithoutExtensions, event?: UsageEvent) { +async function incrementUsage(prismaClient: PrismaClient, event?: UsageEvent) { const deploymentRepo = new DeploymentRepository(prismaClient); try { const licenseKeyService = await LicenseKeySingleton.getInstance(deploymentRepo); @@ -15,7 +15,7 @@ async function incrementUsage(prismaClient: PrismaClientWithoutExtensions, event } } -export function usageTrackingExtention(prismaClient: PrismaClientWithoutExtensions) { +export function usageTrackingExtention(prismaClient: PrismaClient) { return Prisma.defineExtension({ query: { booking: { diff --git a/packages/prisma/index.ts b/packages/prisma/index.ts index 44b22ebecfa94d..c0262203b9740a 100644 --- a/packages/prisma/index.ts +++ b/packages/prisma/index.ts @@ -1,6 +1,5 @@ import type { Prisma } from "@prisma/client"; -import { PrismaClient as PrismaClientWithoutExtension } from "@prisma/client"; -import { withAccelerate } from "@prisma/extension-accelerate"; +import { PrismaClient } from "@prisma/client"; import { bookingIdempotencyKeyExtension } from "./extensions/booking-idempotency-key"; import { disallowUndefinedDeleteUpdateManyExtension } from "./extensions/disallow-undefined-delete-update-many"; @@ -12,8 +11,7 @@ import { bookingReferenceMiddleware } from "./middleware"; const prismaOptions: Prisma.PrismaClientOptions = {}; const globalForPrisma = global as unknown as { - prismaWithoutClientExtensions: PrismaClientWithoutExtension; - prismaWithClientExtensions: PrismaClientWithExtensions; + baseClient: PrismaClient; }; const loggerLevel = parseInt(process.env.NEXT_PUBLIC_LOGGER_LEVEL ?? "", 10); @@ -37,34 +35,32 @@ if (!isNaN(loggerLevel)) { } } -// Prevents flooding with idle connections -const prismaWithoutClientExtensions = - globalForPrisma.prismaWithoutClientExtensions || new PrismaClientWithoutExtension(prismaOptions); +const baseClient = + globalForPrisma.baseClient || new PrismaClient(prismaOptions); export const customPrisma = (options?: Prisma.PrismaClientOptions) => - new PrismaClientWithoutExtension({ ...prismaOptions, ...options }) - .$extends(usageTrackingExtention(prismaWithoutClientExtensions)) + new PrismaClient({ ...prismaOptions, ...options }) + .$extends(usageTrackingExtention(baseClient)) .$extends(excludeLockedUsersExtension()) .$extends(excludePendingPaymentsExtension()) .$extends(bookingIdempotencyKeyExtension()) - .$extends(disallowUndefinedDeleteUpdateManyExtension()) - .$extends(withAccelerate()); + .$extends(disallowUndefinedDeleteUpdateManyExtension()) as unknown as PrismaClient; // If any changed on middleware server restart is required // TODO: Migrate it to $extends -bookingReferenceMiddleware(prismaWithoutClientExtensions); +bookingReferenceMiddleware(baseClient); // FIXME: Due to some reason, there are types failing in certain places due to the $extends. Fix it and then enable it // Specifically we get errors like `Type 'string | Date | null | undefined' is not assignable to type 'Exact'` -const prismaWithClientExtensions = prismaWithoutClientExtensions - .$extends(usageTrackingExtention(prismaWithoutClientExtensions)) + +// Explanation why we cast as PrismaClient. When we leave Prisma to its devices it tries to infer logic based on the extensions, but this is not a simple extends. +// this makes the PrismaClient export type-hint impossible and it also is a massive hit on Prisma type hinting performance. +export const prisma: PrismaClient = baseClient + .$extends(usageTrackingExtention(baseClient)) .$extends(excludeLockedUsersExtension()) .$extends(excludePendingPaymentsExtension()) .$extends(bookingIdempotencyKeyExtension()) - .$extends(disallowUndefinedDeleteUpdateManyExtension()) - .$extends(withAccelerate()); - -export const prisma = globalForPrisma.prismaWithClientExtensions || prismaWithClientExtensions; + .$extends(disallowUndefinedDeleteUpdateManyExtension()) as unknown as PrismaClient; // This prisma instance is meant to be used only for READ operations. // If self hosting, feel free to leave INSIGHTS_DATABASE_URL as empty and `readonlyPrisma` will default to `prisma`. @@ -75,24 +71,23 @@ export const readonlyPrisma = process.env.INSIGHTS_DATABASE_URL : prisma; if (process.env.NODE_ENV !== "production") { - globalForPrisma.prismaWithoutClientExtensions = prismaWithoutClientExtensions; - globalForPrisma.prismaWithClientExtensions = prisma; + globalForPrisma.baseClient = baseClient; } -type PrismaClientWithExtensions = typeof prismaWithClientExtensions; -export type PrismaClient = PrismaClientWithExtensions; - type OmitPrismaClient = Omit< PrismaClient, "$connect" | "$disconnect" | "$on" | "$transaction" | "$use" | "$extends" >; // we cant pass tx to functions as types miss match since we have a custom prisma client https://github.com/prisma/prisma/discussions/20924#discussioncomment-10077649 -export type PrismaTransaction = OmitPrismaClient; +export type { + OmitPrismaClient as PrismaTransaction, + // we re-export the native PrismaClient type for backwards-compatibility. + PrismaClient +}; /** * @deprecated Use named export `prisma` instead */ export default prisma; - export * from "./selects";