diff --git a/apps/api/v2/package.json b/apps/api/v2/package.json index ce0adc2d5d..c8195e03fd 100644 --- a/apps/api/v2/package.json +++ b/apps/api/v2/package.json @@ -38,7 +38,7 @@ "@axiomhq/winston": "^1.2.0", "@calcom/platform-constants": "*", "@calcom/platform-enums": "*", - "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.271", + "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.276", "@calcom/platform-types": "*", "@calcom/platform-utils": "*", "@calcom/prisma": "*", diff --git a/apps/api/v2/src/lib/modules/available-slots.module.ts b/apps/api/v2/src/lib/modules/available-slots.module.ts index 0eb223fc73..7d16984cc5 100644 --- a/apps/api/v2/src/lib/modules/available-slots.module.ts +++ b/apps/api/v2/src/lib/modules/available-slots.module.ts @@ -1,5 +1,6 @@ import { PrismaBookingRepository } from "@/lib/repositories/prisma-booking.repository"; import { PrismaEventTypeRepository } from "@/lib/repositories/prisma-event-type.repository"; +import { PrismaFeaturesRepository } from "@/lib/repositories/prisma-features.repository"; import { PrismaOOORepository } from "@/lib/repositories/prisma-ooo.repository"; import { PrismaRoutingFormResponseRepository } from "@/lib/repositories/prisma-routing-form-response.repository"; import { PrismaScheduleRepository } from "@/lib/repositories/prisma-schedule.repository"; @@ -7,6 +8,7 @@ import { PrismaSelectedSlotRepository } from "@/lib/repositories/prisma-selected import { PrismaTeamRepository } from "@/lib/repositories/prisma-team.repository"; import { PrismaUserRepository } from "@/lib/repositories/prisma-user.repository"; import { AvailableSlotsService } from "@/lib/services/available-slots.service"; +import { CacheService } from "@/lib/services/cache.service"; import { CheckBookingLimitsService } from "@/lib/services/check-booking-limits.service"; import { PrismaModule } from "@/modules/prisma/prisma.module"; import { Module } from "@nestjs/common"; @@ -22,7 +24,9 @@ import { Module } from "@nestjs/common"; PrismaEventTypeRepository, PrismaRoutingFormResponseRepository, PrismaTeamRepository, + PrismaFeaturesRepository, CheckBookingLimitsService, + CacheService, AvailableSlotsService, ], exports: [AvailableSlotsService], diff --git a/apps/api/v2/src/lib/repositories/prisma-features.repository.ts b/apps/api/v2/src/lib/repositories/prisma-features.repository.ts new file mode 100644 index 0000000000..9039675e10 --- /dev/null +++ b/apps/api/v2/src/lib/repositories/prisma-features.repository.ts @@ -0,0 +1,12 @@ +import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; +import { Injectable } from "@nestjs/common"; + +import { PrismaFeaturesRepository as PrismaFeaturesRepositoryLib } from "@calcom/platform-libraries/repositories"; +import { PrismaClient } from "@calcom/prisma"; + +@Injectable() +export class PrismaFeaturesRepository extends PrismaFeaturesRepositoryLib { + constructor(private readonly dbWrite: PrismaWriteService) { + super(dbWrite.prisma as unknown as PrismaClient); + } +} diff --git a/apps/api/v2/src/lib/services/available-slots.service.ts b/apps/api/v2/src/lib/services/available-slots.service.ts index df2850364d..2ced88dbb9 100644 --- a/apps/api/v2/src/lib/services/available-slots.service.ts +++ b/apps/api/v2/src/lib/services/available-slots.service.ts @@ -1,11 +1,13 @@ import { PrismaBookingRepository } from "@/lib/repositories/prisma-booking.repository"; import { PrismaEventTypeRepository } from "@/lib/repositories/prisma-event-type.repository"; +import { PrismaFeaturesRepository } from "@/lib/repositories/prisma-features.repository"; import { PrismaOOORepository } from "@/lib/repositories/prisma-ooo.repository"; import { PrismaRoutingFormResponseRepository } from "@/lib/repositories/prisma-routing-form-response.repository"; import { PrismaScheduleRepository } from "@/lib/repositories/prisma-schedule.repository"; import { PrismaSelectedSlotRepository } from "@/lib/repositories/prisma-selected-slot.repository"; import { PrismaTeamRepository } from "@/lib/repositories/prisma-team.repository"; import { PrismaUserRepository } from "@/lib/repositories/prisma-user.repository"; +import { CacheService } from "@/lib/services/cache.service"; import { CheckBookingLimitsService } from "@/lib/services/check-booking-limits.service"; import { Injectable } from "@nestjs/common"; @@ -21,7 +23,8 @@ export class AvailableSlotsService extends BaseAvailableSlotsService { bookingRepository: PrismaBookingRepository, selectedSlotRepository: PrismaSelectedSlotRepository, eventTypeRepository: PrismaEventTypeRepository, - userRepository: PrismaUserRepository + userRepository: PrismaUserRepository, + featuresRepository: PrismaFeaturesRepository ) { super({ oooRepo: oooRepoDependency, @@ -32,7 +35,8 @@ export class AvailableSlotsService extends BaseAvailableSlotsService { selectedSlotRepo: selectedSlotRepository, eventTypeRepo: eventTypeRepository, userRepo: userRepository, - checkBookingLimitsService: new CheckBookingLimitsService(bookingRepository), + checkBookingLimitsService: new CheckBookingLimitsService(bookingRepository) as any, + cacheService: new CacheService(featuresRepository), }); } } diff --git a/apps/api/v2/src/lib/services/cache.service.ts b/apps/api/v2/src/lib/services/cache.service.ts new file mode 100644 index 0000000000..fd8d8e3b59 --- /dev/null +++ b/apps/api/v2/src/lib/services/cache.service.ts @@ -0,0 +1,11 @@ +import { PrismaFeaturesRepository } from "@/lib/repositories/prisma-features.repository"; +import { Injectable } from "@nestjs/common"; + +import { CacheService as BaseCacheService } from "@calcom/platform-libraries"; + +@Injectable() +export class CacheService extends BaseCacheService { + constructor(featuresRepository: PrismaFeaturesRepository) { + super({ featuresRepository }); + } +} diff --git a/apps/web/app/(booking-page-wrapper)/team/[slug]/[type]/page.tsx b/apps/web/app/(booking-page-wrapper)/team/[slug]/[type]/page.tsx index 77b685ffb3..25070801c2 100644 --- a/apps/web/app/(booking-page-wrapper)/team/[slug]/[type]/page.tsx +++ b/apps/web/app/(booking-page-wrapper)/team/[slug]/[type]/page.tsx @@ -7,6 +7,7 @@ import { cookies, headers } from "next/headers"; import { getOrgFullOrigin } from "@calcom/features/ee/organizations/lib/orgDomains"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { loadTranslations } from "@calcom/lib/server/i18n"; +import { prisma } from "@calcom/prisma"; import { buildLegacyCtx, decodeParams } from "@lib/buildLegacyCtx"; import { getServerSideProps } from "@lib/team/[slug]/[type]/getServerSideProps"; @@ -17,7 +18,7 @@ import type { PageProps as LegacyPageProps } from "~/team/type-view"; import CachedTeamBooker, { generateMetadata as generateCachedMetadata } from "./pageWithCachedData"; async function isCachedTeamBookingEnabled(searchParams: SearchParams): Promise { - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const isGloballyEnabled = await featuresRepository.checkIfFeatureIsEnabledGlobally( "team-booking-page-cache" ); diff --git a/apps/web/app/(booking-page-wrapper)/team/[slug]/[type]/queries.ts b/apps/web/app/(booking-page-wrapper)/team/[slug]/[type]/queries.ts index ce6ac0701c..8f4df870a8 100644 --- a/apps/web/app/(booking-page-wrapper)/team/[slug]/[type]/queries.ts +++ b/apps/web/app/(booking-page-wrapper)/team/[slug]/[type]/queries.ts @@ -102,7 +102,7 @@ export async function getEnrichedEventType({ } export async function shouldUseApiV2ForTeamSlots(teamId: number): Promise { - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const teamHasApiV2Route = await featureRepo.checkIfTeamHasFeature(teamId, "use-api-v2-for-team-slots"); const useApiV2 = teamHasApiV2Route && Boolean(process.env.NEXT_PUBLIC_API_V2_URL); diff --git a/apps/web/app/(use-page-wrapper)/insights/layout.tsx b/apps/web/app/(use-page-wrapper)/insights/layout.tsx index 7e987011ad..e5518d9fd6 100644 --- a/apps/web/app/(use-page-wrapper)/insights/layout.tsx +++ b/apps/web/app/(use-page-wrapper)/insights/layout.tsx @@ -4,11 +4,12 @@ import { notFound } from "next/navigation"; import { CTA_CONTAINER_CLASS_NAME } from "@calcom/features/data-table/lib/utils"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import Shell from "@calcom/features/shell/Shell"; +import { prisma } from "@calcom/prisma"; import UpgradeTipWrapper from "./UpgradeTipWrapper"; export default async function InsightsLayout({ children }: { children: React.ReactNode }) { - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const insightsEnabled = await featuresRepository.checkIfFeatureIsEnabledGlobally("insights"); if (!insightsEnabled) { diff --git a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/layout.tsx b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/layout.tsx index 5082bbcf42..e767079a31 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/layout.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/layout.tsx @@ -9,6 +9,7 @@ import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { PermissionMapper } from "@calcom/features/pbac/domain/mappers/PermissionMapper"; import { Resource, CrudAction } from "@calcom/features/pbac/domain/types/permission-registry"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; +import { prisma } from "@calcom/prisma"; import { buildLegacyRequest } from "@lib/buildLegacyCtx"; @@ -17,7 +18,7 @@ import SettingsLayoutAppDirClient from "./SettingsLayoutAppDirClient"; const getTeamFeatures = unstable_cache( async (teamId: number) => { - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); return await featuresRepository.getTeamFeatures(teamId); }, ["team-features"], diff --git a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/roles/page.tsx b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/roles/page.tsx index 7b26a0c369..3b5466f46b 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/roles/page.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/roles/page.tsx @@ -11,6 +11,7 @@ import { Resource, CrudAction } from "@calcom/features/pbac/domain/types/permiss import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { RoleService } from "@calcom/features/pbac/services/role.service"; import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; +import { prisma } from "@calcom/prisma"; import { buildLegacyRequest } from "@lib/buildLegacyCtx"; @@ -29,7 +30,7 @@ const getCachedTeamRoles = unstable_cache( const getCachedTeamFeature = unstable_cache( async (teamId: number, feature: keyof AppFlags) => { - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const res = await featureRepo.checkIfTeamHasFeature(teamId, feature); return res; }, diff --git a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/teams/[id]/roles/page.tsx b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/teams/[id]/roles/page.tsx index 456b180c86..c89b0e2a62 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/teams/[id]/roles/page.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/teams/[id]/roles/page.tsx @@ -12,6 +12,7 @@ import { PermissionCheckService } from "@calcom/features/pbac/services/permissio import { RoleService } from "@calcom/features/pbac/services/role.service"; import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; import { getTeamWithMembers } from "@calcom/lib/server/queries/teams"; +import { prisma } from "@calcom/prisma"; import { buildLegacyRequest } from "@lib/buildLegacyCtx"; @@ -32,7 +33,7 @@ const getCachedTeamRoles = (teamId: number) => const getCachedTeamFeature = (teamId: number, feature: keyof AppFlags) => unstable_cache( async () => { - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const res = await featureRepo.checkIfTeamHasFeature(teamId, feature); return res; }, diff --git a/apps/web/app/api/auth/signup/route.ts b/apps/web/app/api/auth/signup/route.ts index bf011382a8..05326592fc 100644 --- a/apps/web/app/api/auth/signup/route.ts +++ b/apps/web/app/api/auth/signup/route.ts @@ -10,6 +10,7 @@ import getIP from "@calcom/lib/getIP"; import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; import { checkCfTurnstileToken } from "@calcom/lib/server/checkCfTurnstileToken"; +import { prisma } from "@calcom/prisma"; import { signupSchema } from "@calcom/prisma/zod-utils"; async function ensureSignupIsEnabled(body: Record) { @@ -22,7 +23,7 @@ async function ensureSignupIsEnabled(body: Record) { // Still allow signups if there is a team invite if (token) return; - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const signupDisabled = await featuresRepository.checkIfFeatureIsEnabledGlobally("disable-signup"); if (process.env.NEXT_PUBLIC_DISABLE_SIGNUP === "true" || signupDisabled) { diff --git a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx index 99e86c6692..e40ba6e826 100644 --- a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx +++ b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx @@ -120,7 +120,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) { // Check if team has API v2 feature flag enabled (same logic as team pages) let useApiV2 = false; if (isTeamEvent && hashedLink.eventType.team?.id) { - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const teamHasApiV2Route = await featureRepo.checkIfTeamHasFeature( hashedLink.eventType.team.id, "use-api-v2-for-team-slots" diff --git a/apps/web/lib/settings/organizations/new/getServerSideProps.tsx b/apps/web/lib/settings/organizations/new/getServerSideProps.tsx index 8e90d95a98..b045ec6431 100644 --- a/apps/web/lib/settings/organizations/new/getServerSideProps.tsx +++ b/apps/web/lib/settings/organizations/new/getServerSideProps.tsx @@ -1,9 +1,10 @@ import type { GetServerSidePropsResult } from "next"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import { prisma } from "@calcom/prisma"; export const getServerSideProps = async (): Promise> => { - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const organizations = await featuresRepository.checkIfFeatureIsEnabledGlobally("organizations"); // Check if organizations are enabled if (!organizations) { diff --git a/apps/web/lib/signup/getServerSideProps.tsx b/apps/web/lib/signup/getServerSideProps.tsx index 9645f69c14..8960cdd652 100644 --- a/apps/web/lib/signup/getServerSideProps.tsx +++ b/apps/web/lib/signup/getServerSideProps.tsx @@ -24,7 +24,7 @@ const querySchema = z.object({ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => { const prisma = await import("@calcom/prisma").then((mod) => mod.default); - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const emailVerificationEnabled = await featuresRepository.checkIfFeatureIsEnabledGlobally( "email-verification" ); diff --git a/apps/web/lib/team/[slug]/[type]/getServerSideProps.tsx b/apps/web/lib/team/[slug]/[type]/getServerSideProps.tsx index 689a3a1c58..d1719158b0 100644 --- a/apps/web/lib/team/[slug]/[type]/getServerSideProps.tsx +++ b/apps/web/lib/team/[slug]/[type]/getServerSideProps.tsx @@ -127,7 +127,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => const organizationSettings = getOrganizationSEOSettings(team); const allowSEOIndexing = organizationSettings?.allowSEOIndexing ?? false; - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const teamHasApiV2Route = await featureRepo.checkIfTeamHasFeature(team.id, "use-api-v2-for-team-slots"); const useApiV2 = teamHasApiV2Route && hasApiV2RouteInEnv(); diff --git a/apps/web/lib/team/[slug]/getServerSideProps.tsx b/apps/web/lib/team/[slug]/getServerSideProps.tsx index 45815f29ab..4acfba0e3a 100644 --- a/apps/web/lib/team/[slug]/getServerSideProps.tsx +++ b/apps/web/lib/team/[slug]/getServerSideProps.tsx @@ -71,7 +71,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => // Provided by Rewrite from next.config.js const isOrgProfile = context.query?.isOrgProfile === "1"; - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const organizationsEnabled = await featuresRepository.checkIfFeatureIsEnabledGlobally("organizations"); log.debug("getServerSideProps", { diff --git a/apps/web/lib/video/[uid]/getServerSideProps.ts b/apps/web/lib/video/[uid]/getServerSideProps.ts index 48ce4163b9..453d0ab463 100644 --- a/apps/web/lib/video/[uid]/getServerSideProps.ts +++ b/apps/web/lib/video/[uid]/getServerSideProps.ts @@ -247,7 +247,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { const videoReference = getCalVideoReference(bookingObj.references); - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const displayLogInOverlay = profile?.organizationId ? await featureRepo.checkIfTeamHasFeature(profile.organizationId, "cal-video-log-in-overlay") : false; diff --git a/packages/emails/templates/_base-email.ts b/packages/emails/templates/_base-email.ts index 4a7c10d0ba..a9b192c777 100644 --- a/packages/emails/templates/_base-email.ts +++ b/packages/emails/templates/_base-email.ts @@ -7,6 +7,7 @@ import { getErrorFromUnknown } from "@calcom/lib/errors"; import isSmsCalEmail from "@calcom/lib/isSmsCalEmail"; import { serverConfig } from "@calcom/lib/serverConfig"; import { setTestEmail } from "@calcom/lib/testEmails"; +import { prisma } from "@calcom/prisma"; import { sanitizeDisplayName } from "../lib/sanitizeDisplayName"; @@ -29,7 +30,7 @@ export default class BaseEmail { return {}; } public async sendEmail() { - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const emailsDisabled = await featuresRepository.checkIfFeatureIsEnabledGlobally("emails"); /** If email kill switch exists and is active, we prevent emails being sent. */ if (emailsDisabled) { diff --git a/packages/features/auth/lib/verifyEmail.ts b/packages/features/auth/lib/verifyEmail.ts index 3e7fde3ea9..fff51e469a 100644 --- a/packages/features/auth/lib/verifyEmail.ts +++ b/packages/features/auth/lib/verifyEmail.ts @@ -34,7 +34,7 @@ export const sendEmailVerification = async ({ }: VerifyEmailType) => { const token = randomBytes(32).toString("hex"); const translation = await getTranslation(language ?? "en", "common"); - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const emailVerification = await featuresRepository.checkIfFeatureIsEnabledGlobally("email-verification"); if (!emailVerification) { @@ -127,7 +127,7 @@ interface ChangeOfEmail { export const sendChangeOfEmailVerification = async ({ user, language }: ChangeOfEmail) => { const token = randomBytes(32).toString("hex"); const translation = await getTranslation(language ?? "en", "common"); - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const emailVerification = await featuresRepository.checkIfFeatureIsEnabledGlobally("email-verification"); if (!emailVerification) { diff --git a/packages/features/bookings/lib/handleNewBooking.ts b/packages/features/bookings/lib/handleNewBooking.ts index 109028e358..ebe8d1ec24 100644 --- a/packages/features/bookings/lib/handleNewBooking.ts +++ b/packages/features/bookings/lib/handleNewBooking.ts @@ -27,7 +27,6 @@ import getICalUID from "@calcom/emails/lib/getICalUID"; import { CalendarEventBuilder } from "@calcom/features/CalendarEventBuilder"; import { handleWebhookTrigger } from "@calcom/features/bookings/lib/handleWebhookTrigger"; import { isEventTypeLoggingEnabled } from "@calcom/features/bookings/lib/isEventTypeLoggingEnabled"; -import { getShouldServeCache } from "@calcom/features/calendar-cache/lib/getShouldServeCache"; import AssignmentReasonRecorder from "@calcom/features/ee/round-robin/assignmentReason/AssignmentReasonRecorder"; import { allowDisablingAttendeeConfirmationEmails, @@ -52,6 +51,7 @@ import { getFirstDelegationConferencingCredentialAppLocation, } from "@calcom/lib/delegationCredential/server"; import { getCheckBookingAndDurationLimitsService } from "@calcom/lib/di/containers/booking-limits"; +import { getCacheService } from "@calcom/lib/di/containers/cache"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { getErrorFromUnknown } from "@calcom/lib/errors"; import { getEventName, updateHostInEventName } from "@calcom/lib/event"; @@ -539,7 +539,8 @@ async function handler( } } - const shouldServeCache = await getShouldServeCache(_shouldServeCache, eventType.team?.id); + const cacheService = getCacheService(); + const shouldServeCache = await cacheService.getShouldServeCache(_shouldServeCache, eventType.team?.id); const isTeamEventType = !!eventType.schedulingType && ["COLLECTIVE", "ROUND_ROBIN"].includes(eventType.schedulingType); diff --git a/packages/features/calendar-cache/calendar-cache.ts b/packages/features/calendar-cache/calendar-cache.ts index dde2b98ea7..cddf821034 100644 --- a/packages/features/calendar-cache/calendar-cache.ts +++ b/packages/features/calendar-cache/calendar-cache.ts @@ -3,6 +3,7 @@ import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { getCredentialForCalendarCache } from "@calcom/lib/delegationCredential/server"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; +import prisma from "@calcom/prisma"; import type { Calendar } from "@calcom/types/Calendar"; import { CalendarCacheRepository } from "./calendar-cache.repository"; @@ -20,7 +21,7 @@ export class CalendarCache { return await CalendarCache.init(calendarForCalendarCache); } static async init(calendar: Calendar | null): Promise { - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const isCalendarCacheEnabledGlobally = await featureRepo.checkIfFeatureIsEnabledGlobally( "calendar-cache" ); diff --git a/packages/features/calendar-cache/lib/getShouldServeCache.ts b/packages/features/calendar-cache/lib/getShouldServeCache.ts index d28f77abff..d445d5e039 100644 --- a/packages/features/calendar-cache/lib/getShouldServeCache.ts +++ b/packages/features/calendar-cache/lib/getShouldServeCache.ts @@ -1,8 +1,15 @@ -import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import type { IFeaturesRepository } from "@calcom/features/flags/features.repository.interface"; -export async function getShouldServeCache(shouldServeCache?: boolean | undefined, teamId?: number) { - if (typeof shouldServeCache === "boolean") return shouldServeCache; - if (!teamId) return undefined; - const featureRepo = new FeaturesRepository(); - return await featureRepo.checkIfTeamHasFeature(teamId, "calendar-cache-serve"); +export interface ICacheService { + featuresRepository: IFeaturesRepository; +} + +export class CacheService { + constructor(private readonly dependencies: ICacheService) {} + + async getShouldServeCache(shouldServeCache?: boolean | undefined, teamId?: number) { + if (typeof shouldServeCache === "boolean") return shouldServeCache; + if (!teamId) return undefined; + return await this.dependencies.featuresRepository.checkIfTeamHasFeature(teamId, "calendar-cache-serve"); + } } diff --git a/packages/features/ee/organizations/pages/organization.tsx b/packages/features/ee/organizations/pages/organization.tsx index a9dcacda73..239443680d 100644 --- a/packages/features/ee/organizations/pages/organization.tsx +++ b/packages/features/ee/organizations/pages/organization.tsx @@ -6,7 +6,7 @@ import { MembershipRole } from "@calcom/prisma/client"; export const getServerSideProps = async ({ req }: GetServerSidePropsContext) => { const prisma = await import("@calcom/prisma").then((mod) => mod.default); - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const organizationsEnabled = await featuresRepository.checkIfFeatureIsEnabledGlobally("organizations"); // Check if organizations are enabled if (!organizationsEnabled) { diff --git a/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts b/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts index 5a30b048d6..5620cdaeec 100644 --- a/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts +++ b/packages/features/ee/workflows/lib/reminders/emailReminderManager.ts @@ -277,7 +277,7 @@ export const scheduleEmailReminder = async (args: scheduleEmailReminderArgs) => const isSendgridEnabled = !!(process.env.SENDGRID_API_KEY && process.env.SENDGRID_EMAIL); - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const isWorkflowSmtpEmailsEnabled = teamId ? await featureRepo.checkIfTeamHasFeature(teamId, "workflow-smtp-emails") diff --git a/packages/features/ee/workflows/lib/test/workflows.test.ts b/packages/features/ee/workflows/lib/test/workflows.test.ts index 612eec1fe8..e5c9e992d9 100644 --- a/packages/features/ee/workflows/lib/test/workflows.test.ts +++ b/packages/features/ee/workflows/lib/test/workflows.test.ts @@ -1103,7 +1103,6 @@ describe("Workflow SMTP Emails Feature Flag", () => { }); test("should use SMTP when team has workflow-smtp-emails feature", async () => { - const featuresRepository = new FeaturesRepository(); vi.spyOn(FeaturesRepository.prototype, "checkIfTeamHasFeature").mockResolvedValue(true); await scheduleEmailReminder({ @@ -1115,7 +1114,6 @@ describe("Workflow SMTP Emails Feature Flag", () => { }); test("should use SMTP when user has workflow-smtp-emails feature", async () => { - const featuresRepository = new FeaturesRepository(); vi.spyOn(FeaturesRepository.prototype, "checkIfUserHasFeature").mockResolvedValue(true); await scheduleEmailReminder({ @@ -1127,7 +1125,6 @@ describe("Workflow SMTP Emails Feature Flag", () => { }); test("should use SendGrid when workflow-smtp-emails feature is not enabled for team", async () => { - const featuresRepository = new FeaturesRepository(); vi.spyOn(FeaturesRepository.prototype, "checkIfTeamHasFeature").mockResolvedValue(false); await scheduleEmailReminder({ @@ -1140,7 +1137,6 @@ describe("Workflow SMTP Emails Feature Flag", () => { }); test("should use SendGrid when workflow-smtp-emails feature is not enabled for user", async () => { - const featuresRepository = new FeaturesRepository(); vi.spyOn(FeaturesRepository.prototype, "checkIfUserHasFeature").mockResolvedValue(false); await scheduleEmailReminder({ @@ -1153,9 +1149,9 @@ describe("Workflow SMTP Emails Feature Flag", () => { }); test("should use SMTP when SendGrid is not configured", async () => { - const featuresRepository = new FeaturesRepository(); - vi.spyOn(featuresRepository, "checkIfTeamHasFeature").mockResolvedValue(false); - vi.spyOn(featuresRepository, "checkIfUserHasFeature").mockResolvedValue(false); + vi.spyOn(FeaturesRepository.prototype, "checkIfTeamHasFeature").mockResolvedValue(false); + + vi.spyOn(FeaturesRepository.prototype, "checkIfUserHasFeature").mockResolvedValue(false); delete process.env.SENDGRID_API_KEY; delete process.env.SENDGRID_EMAIL; diff --git a/packages/features/flags/features.repository.integration-test.ts b/packages/features/flags/features.repository.integration-test.ts index 8bc1bf985c..94219769df 100644 --- a/packages/features/flags/features.repository.integration-test.ts +++ b/packages/features/flags/features.repository.integration-test.ts @@ -1,11 +1,11 @@ -import { PrismaClient } from "@prisma/client"; import { describe, expect, beforeAll, afterAll, beforeEach, it } from "vitest"; +import prisma from "@calcom/prisma"; + import type { AppFlags } from "./config"; import { FeaturesRepository } from "./features.repository"; -const prisma = new PrismaClient(); -const featuresRepository = new FeaturesRepository(); +const featuresRepository = new FeaturesRepository(prisma); // Access private clearCache method through type assertion const clearCache = () => { diff --git a/packages/features/flags/features.repository.ts b/packages/features/flags/features.repository.ts index deb2bebd29..343ba60852 100644 --- a/packages/features/flags/features.repository.ts +++ b/packages/features/flags/features.repository.ts @@ -1,7 +1,7 @@ import { Prisma } from "@prisma/client"; import { captureException } from "@sentry/nextjs"; -import db from "@calcom/prisma"; +import type { PrismaClient } from "@calcom/prisma"; import type { AppFlags, TeamFeatures } from "./config"; import type { IFeaturesRepository } from "./features.repository.interface"; @@ -18,6 +18,8 @@ interface CacheOptions { export class FeaturesRepository implements IFeaturesRepository { private static featuresCache: { data: any[]; expiry: number } | null = null; + constructor(private prismaClient: PrismaClient) {} + private clearCache() { FeaturesRepository.featuresCache = null; } @@ -32,7 +34,7 @@ export class FeaturesRepository implements IFeaturesRepository { return FeaturesRepository.featuresCache.data; } - const features = await db.feature.findMany({ + const features = await this.prismaClient.feature.findMany({ orderBy: { slug: "asc" }, cacheStrategy: { swr: 300, ttl: 300 }, }); @@ -64,7 +66,7 @@ export class FeaturesRepository implements IFeaturesRepository { * @returns Promise<{ [slug: string]: boolean } | null> */ public async getTeamFeatures(teamId: number) { - const result = await db.teamFeatures.findMany({ + const result = await this.prismaClient.teamFeatures.findMany({ where: { teamId, }, @@ -122,7 +124,7 @@ export class FeaturesRepository implements IFeaturesRepository { * FIXME refactor when upgrading prismock * https://github.com/morintd/prismock/issues/592 */ - const userHasFeature = await db.userFeatures.findFirst({ + const userHasFeature = await this.prismaClient.userFeatures.findFirst({ where: { userId, featureId: slug, @@ -180,7 +182,7 @@ export class FeaturesRepository implements IFeaturesRepository { LIMIT 1; `; - const result = await db.$queryRaw(query); + const result = await this.prismaClient.$queryRaw(query); return result.length > 0; } catch (err) { captureException(err); @@ -199,7 +201,7 @@ export class FeaturesRepository implements IFeaturesRepository { async checkIfTeamHasFeature(teamId: number, featureId: keyof AppFlags): Promise { try { // Early return if team has feature directly assigned - const teamHasFeature = await db.teamFeatures.findUnique({ + const teamHasFeature = await this.prismaClient.teamFeatures.findUnique({ where: { teamId_featureId: { teamId, @@ -238,7 +240,7 @@ export class FeaturesRepository implements IFeaturesRepository { LIMIT 1; `; - const result = await db.$queryRaw(query); + const result = await this.prismaClient.$queryRaw(query); return result.length > 0; } catch (err) { captureException(err); diff --git a/packages/features/flags/operations/check-if-user-has-feature.use-case.ts b/packages/features/flags/operations/check-if-user-has-feature.use-case.ts index 8a8ab3ed9e..323f0bd215 100644 --- a/packages/features/flags/operations/check-if-user-has-feature.use-case.ts +++ b/packages/features/flags/operations/check-if-user-has-feature.use-case.ts @@ -1,6 +1,7 @@ import { startSpan } from "@sentry/nextjs"; -import { FeaturesRepository } from "../features.repository"; +import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import { prisma } from "@calcom/prisma"; /** * Use Cases represent individual operations, like "Create Feature" or "Sign In" or "Toggle Feature". @@ -11,7 +12,7 @@ import { FeaturesRepository } from "../features.repository"; */ export function checkIfUserHasFeatureUseCase(userId: number, slug: string): Promise { return startSpan({ name: "checkIfUserHasFeature UseCase", op: "function" }, async () => { - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); return await featuresRepository.checkIfUserHasFeature(userId, slug); }); diff --git a/packages/features/flags/server/procedures/map.ts b/packages/features/flags/server/procedures/map.ts index d5fe9170b3..a699ffc067 100644 --- a/packages/features/flags/server/procedures/map.ts +++ b/packages/features/flags/server/procedures/map.ts @@ -1,12 +1,12 @@ +import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import prisma from "@calcom/prisma"; import publicProcedure from "@calcom/trpc/server/procedures/publicProcedure"; -import { FeaturesRepository } from "../../features.repository"; - /** * TRPC procedure that returns a map of all feature flags and their enabled status. * Uses the FeaturesRepository to handle caching and database access. */ export const map = publicProcedure.query(async () => { - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); return featuresRepository.getFeatureFlagMap(); }); diff --git a/packages/features/flags/server/router.ts b/packages/features/flags/server/router.ts index ee8ba00cdd..5327509c08 100644 --- a/packages/features/flags/server/router.ts +++ b/packages/features/flags/server/router.ts @@ -1,15 +1,16 @@ import { z } from "zod"; import type { AppFlags } from "@calcom/features/flags/config"; +import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import { prisma } from "@calcom/prisma"; import publicProcedure from "@calcom/trpc/server/procedures/publicProcedure"; import { router } from "@calcom/trpc/server/trpc"; -import { FeaturesRepository } from "../features.repository"; import { map } from "./procedures/map"; export const featureFlagRouter = router({ list: publicProcedure.query(async () => { - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); return featuresRepository.getAllFeatures(); }), checkTeamFeature: publicProcedure @@ -20,7 +21,7 @@ export const featureFlagRouter = router({ }) ) .query(async ({ input }) => { - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); return featuresRepository.checkIfTeamHasFeature(input.teamId, input.feature as keyof AppFlags); }), map, diff --git a/packages/features/pbac/lib/resource-permissions.ts b/packages/features/pbac/lib/resource-permissions.ts index 9fb2a2e067..de41d32d8b 100644 --- a/packages/features/pbac/lib/resource-permissions.ts +++ b/packages/features/pbac/lib/resource-permissions.ts @@ -1,4 +1,5 @@ import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import { prisma } from "@calcom/prisma"; import type { MembershipRole } from "@calcom/prisma/enums"; import { PermissionMapper } from "../domain/mappers/PermissionMapper"; @@ -53,7 +54,7 @@ export const getResourcePermissions = async ({ userRole, fallbackRoles = {}, }: ResourcePermissionsOptions): Promise => { - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const permissionService = new PermissionCheckService(); const pbacEnabled = await featureRepo.checkIfTeamHasFeature(teamId, "pbac"); diff --git a/packages/features/pbac/services/permission-check.service.ts b/packages/features/pbac/services/permission-check.service.ts index 7656b189f9..70566db684 100644 --- a/packages/features/pbac/services/permission-check.service.ts +++ b/packages/features/pbac/services/permission-check.service.ts @@ -1,6 +1,7 @@ import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import logger from "@calcom/lib/logger"; import { MembershipRepository } from "@calcom/lib/server/repository/membership"; +import prisma from "@calcom/prisma"; import type { MembershipRole } from "@calcom/prisma/enums"; import { PermissionMapper } from "../domain/mappers/PermissionMapper"; @@ -24,7 +25,7 @@ export class PermissionCheckService { constructor( private readonly repository: IPermissionRepository = new PermissionRepository(), - featuresRepository: FeaturesRepository = new FeaturesRepository(), + featuresRepository: FeaturesRepository = new FeaturesRepository(prisma), permissionService: PermissionService = new PermissionService() ) { this.featuresRepository = featuresRepository; diff --git a/packages/features/pbac/services/role-management.factory.ts b/packages/features/pbac/services/role-management.factory.ts index 9c0417e3b0..a2bb073c41 100644 --- a/packages/features/pbac/services/role-management.factory.ts +++ b/packages/features/pbac/services/role-management.factory.ts @@ -150,8 +150,7 @@ export class RoleManagementFactory { private permissionCheckService: PermissionCheckService; private constructor() { - this.featuresRepository = new FeaturesRepository(); - this.roleService = new RoleService(); + (this.featuresRepository = new FeaturesRepository(prisma)), (this.roleService = new RoleService()); this.permissionCheckService = new PermissionCheckService(); } diff --git a/packages/lib/EventManager.ts b/packages/lib/EventManager.ts index 8323933304..fd25434b77 100644 --- a/packages/lib/EventManager.ts +++ b/packages/lib/EventManager.ts @@ -1153,7 +1153,7 @@ export default class EventManager { private async createAllCRMEvents(event: CalendarEvent) { const createdEvents = []; - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const isTaskerEnabledForSalesforceCrm = event.team?.id ? await featureRepo.checkIfTeamHasFeature(event.team.id, "salesforce-crm-tasker") : false; diff --git a/packages/lib/di/containers/available-slots.ts b/packages/lib/di/containers/available-slots.ts index d5b81d9b54..55ff31fc60 100644 --- a/packages/lib/di/containers/available-slots.ts +++ b/packages/lib/di/containers/available-slots.ts @@ -6,8 +6,10 @@ import type { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/s import { availableSlotsModule } from "../modules/available-slots"; import { bookingRepositoryModule } from "../modules/booking"; +import { cacheModule } from "../modules/cache"; import { checkBookingLimitsModule } from "../modules/check-booking-limits"; import { eventTypeRepositoryModule } from "../modules/eventType"; +import { featuresRepositoryModule } from "../modules/features"; import { oooRepositoryModule } from "../modules/ooo"; import { routingFormResponseRepositoryModule } from "../modules/routingFormResponse"; import { scheduleRepositoryModule } from "../modules/schedule"; @@ -25,6 +27,8 @@ container.load(DI_TOKENS.USER_REPOSITORY_MODULE, userRepositoryModule); container.load(DI_TOKENS.BOOKING_REPOSITORY_MODULE, bookingRepositoryModule); container.load(DI_TOKENS.EVENT_TYPE_REPOSITORY_MODULE, eventTypeRepositoryModule); container.load(DI_TOKENS.ROUTING_FORM_RESPONSE_REPOSITORY_MODULE, routingFormResponseRepositoryModule); +container.load(DI_TOKENS.FEATURES_REPOSITORY_MODULE, featuresRepositoryModule); +container.load(DI_TOKENS.CACHE_SERVICE_MODULE, cacheModule); container.load(DI_TOKENS.CHECK_BOOKING_LIMITS_SERVICE_MODULE, checkBookingLimitsModule); container.load(DI_TOKENS.AVAILABLE_SLOTS_SERVICE_MODULE, availableSlotsModule); diff --git a/packages/lib/di/containers/cache.ts b/packages/lib/di/containers/cache.ts new file mode 100644 index 0000000000..958102de4a --- /dev/null +++ b/packages/lib/di/containers/cache.ts @@ -0,0 +1,17 @@ +import { createContainer } from "@evyweb/ioctopus"; + +import { DI_TOKENS } from "@calcom/lib/di/tokens"; +import { prismaModule } from "@calcom/prisma/prisma.module"; + +import type { CacheService } from "../../../features/calendar-cache/lib/getShouldServeCache"; +import { cacheModule } from "../modules/cache"; +import { featuresRepositoryModule } from "../modules/features"; + +const container = createContainer(); +container.load(DI_TOKENS.PRISMA_MODULE, prismaModule); +container.load(DI_TOKENS.FEATURES_REPOSITORY_MODULE, featuresRepositoryModule); +container.load(DI_TOKENS.CACHE_SERVICE_MODULE, cacheModule); + +export function getCacheService() { + return container.get(DI_TOKENS.CACHE_SERVICE); +} diff --git a/packages/lib/di/modules/available-slots.ts b/packages/lib/di/modules/available-slots.ts index f893eb2469..c9dd4012e6 100644 --- a/packages/lib/di/modules/available-slots.ts +++ b/packages/lib/di/modules/available-slots.ts @@ -15,5 +15,6 @@ availableSlotsModule.bind(DI_TOKENS.AVAILABLE_SLOTS_SERVICE).toClass(AvailableSl bookingRepo: DI_TOKENS.BOOKING_REPOSITORY, eventTypeRepo: DI_TOKENS.EVENT_TYPE_REPOSITORY, routingFormResponseRepo: DI_TOKENS.ROUTING_FORM_RESPONSE_REPOSITORY, + cacheService: DI_TOKENS.CACHE_SERVICE, checkBookingLimitsService: DI_TOKENS.CHECK_BOOKING_LIMITS_SERVICE, } satisfies Record); diff --git a/packages/lib/di/modules/cache.ts b/packages/lib/di/modules/cache.ts new file mode 100644 index 0000000000..204c888b94 --- /dev/null +++ b/packages/lib/di/modules/cache.ts @@ -0,0 +1,11 @@ +import { createModule } from "@evyweb/ioctopus"; + +import type { ICacheService } from "@calcom/features/calendar-cache/lib/getShouldServeCache"; +import { CacheService } from "@calcom/features/calendar-cache/lib/getShouldServeCache"; + +import { DI_TOKENS } from "../tokens"; + +export const cacheModule = createModule(); +cacheModule.bind(DI_TOKENS.CACHE_SERVICE).toClass(CacheService, { + featuresRepository: DI_TOKENS.FEATURES_REPOSITORY, +} satisfies Record); diff --git a/packages/lib/di/modules/features.ts b/packages/lib/di/modules/features.ts new file mode 100644 index 0000000000..90ecdae23b --- /dev/null +++ b/packages/lib/di/modules/features.ts @@ -0,0 +1,9 @@ +import { createModule } from "@evyweb/ioctopus"; + +import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import { DI_TOKENS } from "@calcom/lib/di/tokens"; + +export const featuresRepositoryModule = createModule(); +featuresRepositoryModule + .bind(DI_TOKENS.FEATURES_REPOSITORY) + .toClass(FeaturesRepository, [DI_TOKENS.PRISMA_CLIENT]); diff --git a/packages/lib/di/tokens.ts b/packages/lib/di/tokens.ts index 586c3dde23..58df899806 100644 --- a/packages/lib/di/tokens.ts +++ b/packages/lib/di/tokens.ts @@ -22,6 +22,10 @@ export const DI_TOKENS = { AVAILABLE_SLOTS_SERVICE_MODULE: Symbol("AvailableSlotsModule"), INSIGHTS_ROUTING_SERVICE: Symbol("InsightsRoutingService"), INSIGHTS_ROUTING_SERVICE_MODULE: Symbol("InsightsRoutingServiceModule"), + FEATURES_REPOSITORY: Symbol("FeaturesRepository"), + FEATURES_REPOSITORY_MODULE: Symbol("FeaturesRepositoryModule"), + CACHE_SERVICE: Symbol("CacheService"), + CACHE_SERVICE_MODULE: Symbol("CacheServiceModule"), CHECK_BOOKING_LIMITS_SERVICE: Symbol("CheckBookingLimitsService"), CHECK_BOOKING_LIMITS_SERVICE_MODULE: Symbol("CheckBookingLimitsServiceModule"), CHECK_BOOKING_AND_DURATION_LIMITS_SERVICE: Symbol("CheckBookingAndDurationLimitsService"), diff --git a/packages/lib/restrictionSchedule.ts b/packages/lib/restrictionSchedule.ts index af6df9db5b..306ea5c033 100644 --- a/packages/lib/restrictionSchedule.ts +++ b/packages/lib/restrictionSchedule.ts @@ -1,4 +1,5 @@ import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import prisma from "@calcom/prisma"; /** * Checks if the restriction schedule feature is enabled for a team @@ -10,6 +11,6 @@ export async function isRestrictionScheduleEnabled(teamId?: number): Promise { const user = ctx.user; const t = await getTranslation(user.locale ?? "en", "common"); - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); if (!user.organizationId) { throw new TRPCError({ diff --git a/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts b/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts index a8f4cca196..9936331b20 100644 --- a/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts +++ b/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts @@ -40,7 +40,7 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions) const billingService = new StripeBillingService(); const userMetadata = handleUserMetadata({ ctx, input }); const locale = input.locale || user.locale; - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const emailVerification = await featuresRepository.checkIfFeatureIsEnabledGlobally("email-verification"); const { travelSchedules, ...rest } = input; diff --git a/packages/trpc/server/routers/viewer/organizations/list.handler.ts b/packages/trpc/server/routers/viewer/organizations/list.handler.ts index 5c3c34e668..b6e64b0e69 100644 --- a/packages/trpc/server/routers/viewer/organizations/list.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/list.handler.ts @@ -1,5 +1,6 @@ import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { OrganizationRepository } from "@calcom/lib/server/repository/organization"; +import prisma from "@calcom/prisma"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; import { TRPCError } from "@trpc/server"; @@ -26,7 +27,7 @@ export const listHandler = async ({ ctx }: ListHandlerInput) => { return currentOrg; } - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const hasDelegationCredential = await featureRepo.checkIfTeamHasFeature( organizationId, "delegation-credential" diff --git a/packages/trpc/server/routers/viewer/organizations/listMembers.handler.ts b/packages/trpc/server/routers/viewer/organizations/listMembers.handler.ts index 117b506493..fc661b0b76 100644 --- a/packages/trpc/server/routers/viewer/organizations/listMembers.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/listMembers.handler.ts @@ -39,7 +39,7 @@ export const listMembersHandler = async ({ ctx, input }: GetOptions) => { const expand = input.expand; const filters = input.filters || []; - const featuresRepository = new FeaturesRepository(); + const featuresRepository = new FeaturesRepository(prisma); const pbacFeatureEnabled = await featuresRepository.checkIfTeamHasFeature(organizationId, "pbac"); const allAttributeOptions = await prisma.attributeOption.findMany({ diff --git a/packages/trpc/server/routers/viewer/pbac/_router.tsx b/packages/trpc/server/routers/viewer/pbac/_router.tsx index 2e6f70b8c4..d93a8eeefc 100644 --- a/packages/trpc/server/routers/viewer/pbac/_router.tsx +++ b/packages/trpc/server/routers/viewer/pbac/_router.tsx @@ -5,6 +5,7 @@ import { Resource, CrudAction, CustomAction } from "@calcom/features/pbac/domain import type { PermissionString } from "@calcom/features/pbac/domain/types/permission-registry"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { RoleService } from "@calcom/features/pbac/services/role.service"; +import prisma from "@calcom/prisma"; import { RoleType, MembershipRole } from "@calcom/prisma/enums"; import authedProcedure from "../../../procedures/authedProcedure"; @@ -193,7 +194,7 @@ export const permissionsRouter = router({ throw new Error("Unauthorized"); } - const featureRepo = new FeaturesRepository(); + const featureRepo = new FeaturesRepository(prisma); const teamHasPBACFeature = await featureRepo.checkIfTeamHasFeature(input.teamId, "pbac"); if (!teamHasPBACFeature) { diff --git a/packages/trpc/server/routers/viewer/slots/util.ts b/packages/trpc/server/routers/viewer/slots/util.ts index a7d1ae2988..e3f6ae93c1 100644 --- a/packages/trpc/server/routers/viewer/slots/util.ts +++ b/packages/trpc/server/routers/viewer/slots/util.ts @@ -7,7 +7,7 @@ import dayjs from "@calcom/dayjs"; import { orgDomainConfig } from "@calcom/ee/organizations/lib/orgDomains"; import { checkForConflicts } from "@calcom/features/bookings/lib/conflictChecker/checkForConflicts"; import { isEventTypeLoggingEnabled } from "@calcom/features/bookings/lib/isEventTypeLoggingEnabled"; -import { getShouldServeCache } from "@calcom/features/calendar-cache/lib/getShouldServeCache"; +import type { CacheService } from "@calcom/features/calendar-cache/lib/getShouldServeCache"; import { findQualifiedHostsWithDelegationCredentials } from "@calcom/lib/bookings/findQualifiedHostsWithDelegationCredentials"; import { shouldIgnoreContactOwner } from "@calcom/lib/bookings/routing/utils"; import { RESERVED_SUBDOMAINS } from "@calcom/lib/constants"; @@ -99,6 +99,7 @@ export interface IAvailableSlotsService { bookingRepo: BookingRepository; eventTypeRepo: EventTypeRepository; routingFormResponseRepo: RoutingFormResponseRepository; + cacheService: CacheService; checkBookingLimitsService: CheckBookingLimitsService; } @@ -909,8 +910,10 @@ export class AvailableSlotsService { throw new TRPCError({ code: "NOT_FOUND" }); } - // TODO: DI getShouldServeCache - const shouldServeCache = await getShouldServeCache(_shouldServeCache, eventType.team?.id); + const shouldServeCache = await this.dependencies.cacheService.getShouldServeCache( + _shouldServeCache, + eventType.team?.id + ); if (isEventTypeLoggingEnabled({ eventTypeId: eventType.id })) { logger.settings.minLevel = 2; } diff --git a/yarn.lock b/yarn.lock index 776a9e339d..93852f908f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2519,7 +2519,7 @@ __metadata: "@axiomhq/winston": ^1.2.0 "@calcom/platform-constants": "*" "@calcom/platform-enums": "*" - "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.271" + "@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.276" "@calcom/platform-types": "*" "@calcom/platform-utils": "*" "@calcom/prisma": "*" @@ -3575,13 +3575,13 @@ __metadata: languageName: unknown linkType: soft -"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.271": - version: 0.0.271 - resolution: "@calcom/platform-libraries@npm:0.0.271" +"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.276": + version: 0.0.276 + resolution: "@calcom/platform-libraries@npm:0.0.276" dependencies: "@calcom/features": "*" "@calcom/lib": "*" - checksum: 5b55a05c5cd1d471fe36c90b8b2f16e70f6155065b3b13e12c06bde73f3ceffde74de3921c3a9fe05d04eed7fb587836ac79a46a521d35fe83812d66b13d8733 + checksum: 4effc186c0301ec35496ebffbe32280f26261667b60057d18207b30636b038cdcc3783b95390eecc8460f3203d0cfe5d732e3b3f89031ff064b1a556321779a8 languageName: node linkType: hard