From 6923b97cd20290fb4471a386c8e882233319aaa3 Mon Sep 17 00:00:00 2001 From: Keith Williams Date: Tue, 21 Oct 2025 16:02:03 -0300 Subject: [PATCH] feat: upgrade Prisma to 6.16.0 with no-rust engine (#23816) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: upgrade Prisma to 6.16.0 with no-rust engine - Update Prisma packages to 6.16.0 - Add PostgreSQL adapter dependency - Configure engineType: 'client' and provider: 'prisma-client' in schema - Update Prisma client instantiation with PostgreSQL adapter - Remove binaryTargets from generators (not needed with library engine) - Fix schema view issue by removing @id decorator from BookingTimeStatusDenormalized - Fix ESLint warning by removing non-null assertion Co-Authored-By: keith@cal.com * Web app running but types wrecked * web app running but build and type issues * Removed the connection pool * Fixed zod type issue * Fixed types in booking reference extension * Fixed test issues * Type checks passing it seems * Using cjs as moduleFormat * Fixing Prisma undefined * fix: update prismock initialization for Prisma 6.16 compatibility - Add @prisma/internals dependency for getDMMF() - Restructure prismock initialization to use createPrismock() with DMMF - Create Proxy that's returned from mock factory for proper spy support - Fixes 89 failing unit tests with 'Cannot read properties of undefined (reading datamodel)' error - Based on workaround from prismock issue #1482 All unit tests now pass (375 test files, 3323 tests passed) Co-Authored-By: keith@cal.com * fix: cast serviceAccountKey to Prisma.InputJsonValue in bookingScenario.ts - Apply type cast at lines 2493 and 2535 - Fixes type errors from Prisma 6.16 upgrade - Follows established pattern from delegationCredential.ts - Add eslint-disable for pre-existing any types - Rename unused appStoreLookupKey parameter to satisfy lint - All 3323 tests passing Co-Authored-By: keith@cal.com * chore: remove whitespace-only lines from bookingScenario.ts - Remove blank lines where eslint-disable comments were replaced - Cleanup from pre-commit hook formatting Co-Authored-By: keith@cal.com * Update is-prisma-available-check.ts * fix: remove datasources config when using Prisma Driver Adapters - Update customPrisma to create new adapter when datasources URL is provided - Remove datasources config from API v2 Prisma services (already in adapter) - Fixes 'Custom datasource configuration is not compatible with Prisma Driver Adapters' error Co-Authored-By: keith@cal.com * fix: use Pool instances for PrismaPg adapters in index.ts - Create Pool instance before passing to PrismaPg adapter - Update customPrisma to create Pool for custom connection strings - Matches working pattern from API v2 services - Fixes 'Invalid `prisma.$queryRawUnsafe()` invocation' error Co-Authored-By: keith@cal.com * Not using queryRawUnsafe * Trying anything at this point * Make sure the DB is ready first * Don't auto run migrations in CI mode * Revert "Make sure the DB is ready first" This reverts commit 2b20bd45c974f3d7e07d8b904bc7fcdae37cce03. * Dynamic import of prisma * Commenting where it seems to break * Backwards compatability for API v2 * fix: add explicit type annotations for map callbacks in API v2 - Add type annotation for map parameter in memberships.repository.ts - Add type annotation for map parameter in stripe.service.ts - Fixes implicit 'any' type errors from stricter Prisma 6.16.0 type inference Co-Authored-By: keith@cal.com * fix: add explicit type annotations for API v2 map callbacks - users.repository.ts:292: add Profile & { user: User } type - memberships.service.ts:19-20: add Membership type to filter callbacks Co-Authored-By: keith@cal.com * fix: add explicit type annotation for attributeToUser in organizations-users.repository.ts - organizations-users.repository.ts:63: add AttributeToUser with nested relations type Co-Authored-By: keith@cal.com * fix: add explicit Membership type annotations in teams.repository.ts Co-Authored-By: keith@cal.com * fix: use API v2 dedicated Prisma client to support adapter in PrismaClientOptions Co-Authored-By: keith@cal.com * Running API v2 build commands together so they all get the space size var * Fixing Maximum call depth exceeded error * fixed type issues * Trying to make the seed more stable * Revert "Trying to make the seed more stable" This reverts commit 1fd4495e6af7acd7981cda7dedec3168979b0e9d. * Fixed path to prisma client * Fixed type check * Fix eslint warnings * fix: externalize @prisma/adapter-pg and pg in platform-libraries Vite config - Add @prisma/adapter-pg and pg to external dependencies list - Add corresponding globals for these packages - Fix Prisma client aliases to point to packages/prisma/client instead of node_modules - Add Node.js resolve conditions to prefer Node.js exports - Keep commonjsOptions.include for proper CommonJS transformation - Add eslint-disable for __dirname in Vite config file - Remove problematic prettier/prettier eslint comment This fixes the 'Extensions.defineExtension is unable to run in this browser environment' error when running yarn generate-swagger in apps/api/v2 after upgrading to Prisma v6.16 with the no-rust engine approach. Co-Authored-By: keith@cal.com * fix: update Prisma imports in API v2 services to use package path - Change imports from '../../../generated/prisma/client' to '@calcom/prisma/client' - Fixes CI error: Cannot find module '../../../../../packages/prisma/generated/prisma/client.ts' - Aligns with backwards compatibility re-export structure after Prisma v6.16 upgrade Co-Authored-By: keith@cal.com * fix: remove .ts extension from Prisma client path mapping in tsconfig - Remove file extension from @calcom/prisma/client path mapping - Fixes runtime error: Cannot find module '../../../../../packages/prisma/generated/prisma/client.ts' - TypeScript path mappings should not include file extensions per best practices - Allows Node.js to correctly resolve to .js files at runtime Co-Authored-By: keith@cal.com * fix: resolve Prisma 6.16.0 type incompatibilities in bookingScenario tests - Changed InputPayment.data type from PaymentData to Prisma.InputJsonValue - Changed createCredentials key parameter from JsonValue to InputJsonValue - Removed unused PaymentData type definition - Resolves type errors at lines 709 and 1088 without using 'as any' casts Co-Authored-By: keith@cal.com * fix: remove non-existent Watchlist fields from test fixtures - Remove createdById from isLockedOrBlocked.test.ts (lines 15, 20) - Remove severity and createdById from _post.test.ts (line 110) - These fields don't exist in Watchlist model schema after Prisma 6.16.0 upgrade - Resolves TS2353 errors without using 'as any' casts Relates to PR #23816 Co-Authored-By: keith@cal.com * fix: api v2 imports generated prisma and platform libraries * fix: resolve type errors from Prisma 6.16 upgrade - Add missing markdownToSafeHTML import in AppCard.tsx - Fix organizationId null handling in fresh-booking.test.ts - Remove non-existent createdById field from Watchlist test utils Co-Authored-By: keith@cal.com * Put back some external rollups * Added back the resolve conditions * Stop using Pool directly * chore: remove prisma bookingReferenceExtension and update calls * fix: organizations-admin-not-team-member-event-types.e2e-spec.ts * chore: bring back POOL in api v2 prisma clients * chore: remove Pool but await connect * fixup! chore: remove Pool but await connect * chore: bring back Pool on all clients * chore: end pool manually * chore: test with pool max 1 * chore: e2e test prisma max pool of 1 connection * chore: give more control over pool for prisma module with env * remove pool from base prisma client * chore: prisma client in libraries use pool * Fixed types * chore: log pool events and improve pooling * Fixing some types and tests * Changing the parsing of USE_POOL * fix: ensure Prisma client is connected before seeding to prevent transaction errors Co-Authored-By: keith@cal.com * chore: adjust pools * chore: add process.env.USE_POOL to libraries vite config * fix: v1 _patch reference check bookingRef on the booking find * fix: v1 get references deleted null for system admin * test: add integration tests for bookingReference soft-delete behavior - Add bookingReference.integration-test.ts to test repository methods - Add handleDeleteCredential.integration-test.ts to test credential deletion cascade - Add booking-references.integration-test.ts for API v1 integration tests - All tests verify soft-delete behavior without using mocks - Tests use real database operations to ensure soft-deleted records persist - Cover scenarios: replacing references, credential deletion, querying with filters Co-Authored-By: keith@cal.com * refactor: convert booking-references test to actual API endpoint testing - Modified _get.ts to export handler function for testing - Refactored integration test to call API handler instead of directly testing Prisma - Added timestamps to test data to avoid conflicts - Tests now verify API layer correctly filters soft-deleted references - All 4 tests passing Co-Authored-By: keith@cal.com * fix: add explicit prisma.$connect() call to seed-insights script With Prisma 6.16 and the PostgreSQL adapter, scripts need to explicitly call $connect() before running database operations to ensure the connection pool is properly initialized. This prevents 'Transaction already closed' errors. Co-Authored-By: keith@cal.com * fix: add $connect() to main() execution in seed-insights Both main() and createPerformanceData() entry points need explicit prisma.$connect() calls with the Prisma 6.16 PostgreSQL adapter. Co-Authored-By: keith@cal.com * fix: always use connection pool for Prisma PostgreSQL adapter Enable connection pooling by default for the Prisma adapter to prevent transaction state issues during seed operations. Without a pool, each operation creates a new connection which can lead to 'Transaction already closed' errors during heavy database operations like seeding. Co-Authored-By: keith@cal.com * Revert "fix: always use connection pool for Prisma PostgreSQL adapter" This reverts commit 6724bb08e42bc0a94846069de83b04db0aeb8e8b. * fix: enable connection pool for db-seed in cache-db action Set USE_POOL=true when running yarn db-seed to use connection pooling with the Prisma PostgreSQL adapter. This prevents 'Transaction already closed' errors during seeding by maintaining stable database connections. Co-Authored-By: keith@cal.com * fix: add safety check for undefined ownerForEvent in seed script Prevent 'Cannot read properties of undefined' error when orgMembersInDBWithProfileId is empty. This can happen if organization members fail to create or when there's a duplicate constraint violation causing early return. Co-Authored-By: keith@cal.com * fix: v1 _patch reference check bookingRef * fix: increase pool size and add timeout settings to prevent transaction errors - Increase max connections from 5 to 10 - Add connectionTimeoutMillis: 30000 (30 seconds) - Add statement_timeout: 60000 (60 seconds) These settings help prevent 'Unknown transaction status' errors during heavy database operations like seeding by giving transactions more time to complete and allowing more concurrent connections. Co-Authored-By: keith@cal.com * Revert "fix: increase pool size and add timeout settings to prevent transaction errors" This reverts commit 148264f1f1861dfb09a082937a3e2b49e78fc41a. * fix: remove standalone execution in seed-app-store to prevent premature disconnect The seed-app-store.ts file had a standalone main() call at the bottom that would execute immediately when imported, including a prisma.$disconnect() in its .finally() block. This caused issues because: 1. seed.ts imports and calls mainAppStore() 2. The import triggers the standalone main() execution 3. This standalone execution disconnects prisma after completion 4. seed.ts then tries to call mainHugeEventTypesSeed() but prisma is disconnected 5. This leads to 'Unknown transaction status' errors Fixed by removing the standalone execution since mainAppStore() is already called programmatically from seed.ts which manages the connection lifecycle. Co-Authored-By: keith@cal.com * fix: use require.main check to prevent premature disconnect when imported Added require.main === module check so seed-app-store.ts: - Runs standalone with proper connection management when executed directly via 'yarn seed-app-store' or 'ts-node seed-app-store.ts' - Does NOT run standalone when imported as a module by seed.ts, preventing premature prisma disconnect This fixes 'Unknown transaction status' errors while maintaining backward compatibility for direct execution. Co-Authored-By: keith@cal.com * fix: seed apps before creating users to prevent foreign key constraint violation Reordered seeding operations to call mainAppStore() before main() because: - main() creates users with credentials that reference apps via appId foreign key - mainAppStore() seeds the App table with app records - Apps must exist before credentials can reference them This fixes the 'Foreign key constraint violated on Credential_appId_fkey' error that occurred when creating credentials before the apps they reference existed. Co-Authored-By: keith@cal.com * Apply suggestion from @cubic-dev-ai[bot] Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Removing functional changes of deleted: null * Apply suggestion from @keithwillcode * refactor: move seedAppData call to bottom of main() in seed.ts Moved seedAppData() call from seed-app-store.ts to the bottom of main() in seed.ts to ensure the 'pro' user is created before attempting to create routing form data for them. Changes: - Exported seedAppData function from seed-app-store.ts - Removed seedAppData() call from the main() export in seed-app-store.ts - Added seedAppData() call at the bottom of main() in seed.ts - Updated standalone execution in seed-app-store.ts to still call seedAppData() when run directly via 'yarn seed-app-store' This ensures proper ordering: apps seeded → users created → routing form data created for existing users. Co-Authored-By: keith@cal.com * refactor: move routing form seeding from seed-app-store.ts to seed.ts Moved the routing form seeding logic (previously in seedAppData function) from seed-app-store.ts to be inline at the bottom of main() in seed.ts. This ensures the 'pro' user is created before attempting to create routing form data for them. Changes: - Removed seedAppData function and seededForm export from seed-app-store.ts - Removed import of seedAppData from seed.ts - Added routing form seeding logic inline at bottom of main() in seed.ts Seeding order: apps → users (including 'pro') → routing forms Co-Authored-By: keith@cal.com * fix: add deleted: null filter to bookingReference update operations - Add deleted: null filter to API v1 PATCH endpoint to prevent updating soft-deleted booking references - Add deleted: null filter to DailyVideo updateMeetingTokenIfExpired and setEnableRecordingUIAndUserIdForOrganizer - Add comprehensive test coverage for PATCH endpoint soft-delete behavior - Tests verify that soft-deleted booking references cannot be updated - Tests verify that only active booking references can be updated successfully Co-Authored-By: keith@cal.com * revert: remove deleted: null filters to preserve existing functionality Per @keithwillcode's feedback, reverting the soft-delete filtering changes to preserve existing functionality in this PR. This PR should focus only on the Prisma upgrade itself. - Reverted API v1 PATCH endpoint change - Reverted DailyVideo adapter changes (updateMeetingTokenIfExpired and setEnableRecordingUIAndUserIdForOrganizer) - Removed test file that was added for soft-delete behavior testing Addresses comments: - https://github.com/calcom/cal.com/pull/23816#discussion_r2448854197 - https://github.com/calcom/cal.com/pull/23816#discussion_r2448860594 - https://github.com/calcom/cal.com/pull/23816#discussion_r2448860833 Co-Authored-By: keith@cal.com * test: restore and update booking reference tests to match existing functionality Updated tests to verify existing behavior where PATCH endpoint can update booking references regardless of their deleted status. This matches the current implementation after reverting the deleted: null filters. Changes: - Restored test file that was previously deleted - Updated PATCH tests to expect successful updates of soft-deleted references - Renamed test suite to 'Existing functionality' to clarify intent - Tests now verify that the PATCH endpoint preserves existing behavior Co-Authored-By: keith@cal.com * test: rename booking-references test to integration-test The test requires a database connection and should run in the integration test job, not the unit test job. Renamed from .test.ts to .integration-test.ts to match the repository's testing conventions. Co-Authored-By: keith@cal.com --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: cal.com Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> --- .github/actions/cache-db/action.yml | 2 +- .github/workflows/api-v2-production-build.yml | 6 +- .gitignore | 3 +- .../[id]/_auth-middleware.ts | 2 +- .../api/booking-references/[id]/_delete.ts | 2 +- .../pages/api/booking-references/[id]/_get.ts | 2 +- .../v1/pages/api/booking-references/_get.ts | 8 +- apps/api/v1/pages/api/slots/_get.ts | 4 +- .../booking-references.integration-test.ts | 486 ++++++++++++++ .../lib/bookings/[id]/recordings/_get.test.ts | 2 +- .../bookings/[id]/transcripts/_get.test.ts | 2 +- apps/api/v2/.gitignore | 3 +- apps/api/v2/src/config/app.ts | 4 + apps/api/v2/src/config/type.ts | 4 + .../booking-references.repository.ts | 3 +- .../services/event-types.service.ts | 4 +- apps/api/v2/src/env.ts | 4 + .../src/lib/modules/available-slots.module.ts | 4 +- .../lib/services/booking-cancel.service.ts | 4 +- .../interfaces/billing-service.interface.ts | 1 + .../memberships/memberships.repository.ts | 2 +- .../services/memberships.service.ts | 6 +- ...in-not-team-member-event-types.e2e-spec.ts | 27 +- ...ations-teams-invite.controller.e2e-spec.ts | 3 - .../organizations-teams-invite.controller.ts | 10 +- .../teams/invite/outputs/invite.output.ts | 5 +- .../index/organizations-users.repository.ts | 9 +- .../src/modules/prisma/prisma-read.service.ts | 67 +- .../modules/prisma/prisma-worker.module.ts | 40 ++ .../modules/prisma/prisma-write.service.ts | 67 +- .../v2/src/modules/prisma/prisma.module.ts | 33 +- .../workers/slots.worker.module.ts | 4 +- .../v2/src/modules/stripe/stripe.service.ts | 2 +- .../teams-memberships.repository.ts | 2 +- .../modules/teams/teams/teams.repository.ts | 6 +- .../v2/src/modules/users/users.repository.ts | 2 +- apps/api/v2/tsconfig.json | 2 +- .../team/[slug]/[type]/queries.ts | 4 +- .../(main-nav)/teams/page.tsx | 10 +- .../(main-nav)/teams/server-page.tsx | 8 +- .../routing-forms/[...pages]/RouteBuilder.tsx | 2 +- .../forms/[[...pages]]/Forms.tsx | 1 - .../getting-started/[[...step]]/page.tsx | 2 +- .../admin/organizations/[id]/edit/page.tsx | 2 +- .../SettingsLayoutAppDirClient.tsx | 2 - .../developer/webhooks/[id]/page.tsx | 2 +- .../organizations/roles/page.tsx | 2 +- .../teams/other/(main-page)/page.tsx | 2 +- .../app/api/availability/calendar/route.ts | 7 +- apps/web/app/api/cancel/route.ts | 2 +- .../api/cron/calendar-subscriptions/route.ts | 2 +- .../app/api/cron/selected-calendars/route.ts | 6 +- .../web/app/api/recorded-daily-video/route.ts | 8 +- .../web/app/api/support/conversation/route.ts | 4 +- .../calendar-subscription/[provider]/route.ts | 2 +- .../retell-ai/__tests__/route.test.ts | 10 +- apps/web/app/cache/membership.ts | 2 +- .../btcpayserver/BtcpayPaymentComponent.tsx | 2 +- apps/web/components/booking/bookingActions.ts | 4 +- apps/web/components/dialog/RerouteDialog.tsx | 2 +- .../[[...step]]/getServerSideProps.ts | 4 +- .../getServerSidePropsSingleForm.ts | 2 +- .../team/[slug]/[type]/getServerSideProps.ts | 2 +- apps/web/lib/pages/auth/verify-email.ts | 2 +- .../lib/team/[slug]/getServerSideProps.tsx | 2 +- .../web/lib/video/[uid]/getServerSideProps.ts | 8 +- .../installation/[[...step]]/step-view.tsx | 31 +- .../bookings/views/bookings-single-view.tsx | 10 +- apps/web/modules/signup-view.tsx | 4 +- apps/web/next.config.js | 2 +- apps/web/pages/api/book/event.ts | 2 +- .../cancellation-fee-warning.e2e.ts | 8 +- apps/web/playwright/fixtures/users.ts | 51 +- .../web/playwright/integrations-stripe.e2e.ts | 32 +- .../lib/[user]/[type]/getServerSideProps.ts | 4 +- .../sso/[provider]/getServerSideProps.tsx | 2 +- apps/web/test/lib/checkDurationLimits.test.ts | 5 +- .../test/lib/handleChildrenEventTypes.test.ts | 2 +- .../utils/bookingScenario/bookingScenario.ts | 35 +- package.json | 1 + packages/app-store/_appRegistry.ts | 4 +- packages/app-store/_utils/installation.ts | 2 +- .../_utils/oauth/getCurrentTokenObject.ts | 2 +- .../_utils/oauth/updateProfilePhotoGoogle.ts | 2 +- .../_utils/oauth/updateTokenObject.ts | 2 +- ...dTeamMembersMatchingAttributeLogic.test.ts | 8 +- .../findTeamMembersMatchingAttributeLogic.ts | 2 +- .../app-store/_utils/raqb/raqbUtils.test.ts | 2 +- .../_utils/throwIfNotHaveAdminAccessToTeam.ts | 2 +- .../dailyvideo/lib/VideoApiAdapter.ts | 4 +- packages/app-store/delegationCredential.ts | 8 +- .../app-store/dub/lib/AnalyticsService.ts | 2 +- .../app-store/googlecalendar/api/callback.ts | 2 +- .../googlecalendar/tests/testUtils.ts | 6 +- .../routing-forms/lib/formSubmissionUtils.ts | 2 +- .../routing-forms/lib/handleResponse.ts | 2 +- .../app-store/salesforce/lib/CrmService.ts | 1 + .../api/__tests__/portal.test.ts | 6 +- .../stripepayment/lib/PaymentService.ts | 2 +- .../lib/services/base/BillingPortalService.ts | 2 +- packages/app-store/utils.ts | 2 +- packages/app-store/vital/lib/reschedule.ts | 4 +- .../wipemycalother/lib/reschedule.ts | 4 +- packages/features/Segment.tsx | 2 +- packages/features/apps/components/AllApps.tsx | 2 +- packages/features/apps/components/AppCard.tsx | 8 +- .../features/auth/lib/getLocaleFromRequest.ts | 2 +- .../features/auth/lib/getServerSession.ts | 2 +- .../auth/lib/next-auth-custom-adapter.ts | 2 +- .../features/auth/lib/next-auth-options.ts | 9 +- .../getAggregatedAvailability.ts | 2 +- packages/features/bookings/Booker/Booker.tsx | 1 - .../components/DecoyBookingSuccessCard.tsx | 1 - .../Booker/components/InstantBooking.tsx | 2 +- .../Booker/components/OutOfOfficeInSlots.tsx | 2 +- .../Booker/components/hooks/useBookings.ts | 2 +- .../components/hooks/useDecoyBooking.ts | 1 - .../bookings/components/AvailableTimes.tsx | 2 +- .../di/RecurringBookingService.module.ts | 1 - .../di/RegularBookingService.module.ts | 2 - .../features/bookings/lib/EventManager.ts | 3 +- .../lib/bookingSuccessRedirect.test.ts | 10 +- .../getAllCredentials.ts | 2 +- .../refreshCredentials.ts | 2 +- .../features/bookings/lib/getBookingFields.ts | 5 +- .../bookings/lib/getCalEventResponses.ts | 4 +- .../features/bookings/lib/getLuckyUser.ts | 4 +- .../bookings/lib/handleBookingRequested.ts | 2 +- .../bookings/lib/handleCancelBooking.ts | 3 +- .../bookings/lib/handleConfirmation.ts | 8 +- .../checkBookingAndDurationLimits.ts | 2 +- .../handleNewBooking/ensureAvailableUsers.ts | 2 +- .../handleNewBooking/getEventTypesFromDB.ts | 2 +- .../handleNewBooking/loadAndValidateUsers.ts | 2 +- .../lib/handleNewBooking/loadUsers.ts | 4 +- .../originalRescheduledBookingUtils.ts | 8 +- .../test/fresh-booking.test.ts | 15 +- .../bookings/lib/handleSeats/handleSeats.ts | 4 +- .../lib/lastAttendeeDeleteBooking.ts | 2 +- .../filterHostsByLeadThreshold.ts | 2 +- .../filterHostsBySameRoundRobinHost.ts | 2 +- ...QualifiedHostsWithDelegationCredentials.ts | 4 +- .../bookings/lib/payment/getBooking.ts | 2 +- .../lib/payment/handleNoShowFee.test.ts | 7 +- .../bookings/lib/payment/handleNoShowFee.ts | 7 +- .../payment/processNoShowFeeOnCancellation.ts | 2 +- .../InstantBookingCreateService.test.ts | 5 +- .../lib/service/RegularBookingService.ts | 52 +- .../bot-detection/BotDetectionService.test.ts | 2 +- .../bot-detection/BotDetectionService.ts | 2 +- .../busyTimes/services/getBusyTimes.ts | 2 +- .../adapters/PrismaAgentRepositoryAdapter.ts | 1 + .../PhoneNumberRepositoryInterface.ts | 4 +- .../retellAI/RetellAIService.test.ts | 1 - .../providers/retellAI/RetellSDKClient.ts | 1 - .../features/calendar-cache/calendar-cache.ts | 2 +- .../lib/sync/CalendarSyncService.ts | 2 +- packages/features/calendars/DatePicker.tsx | 2 +- .../features/calendars/lib/CalendarManager.ts | 2 +- .../lib/getConnectedDestinationCalendars.ts | 2 +- .../credentials/deleteCredential.test.ts | 2 +- ...handleDeleteCredential.integration-test.ts | 462 +++++++++++++ .../credentials/handleDeleteCredential.ts | 3 +- .../filters/ColumnVisibilityButton.tsx | 4 +- .../features/di/containers/AvailableSlots.ts | 2 +- .../features/di/containers/BookingLimits.ts | 2 +- .../di/containers/GetUserAvailability.ts | 2 +- .../di/containers/NoSlotsNotification.ts | 2 +- packages/features/di/modules/Booking.ts | 2 +- packages/features/di/modules/Cache.ts | 2 + .../modules/CheckBookingAndDurationLimits.ts | 1 - .../features/di/modules/CheckBookingLimits.ts | 2 +- packages/features/di/modules/Features.ts | 2 +- packages/features/di/modules/LuckyUser.ts | 2 +- .../di/watchlist/modules/Watchlist.module.ts | 6 +- .../ee/billing/credit-service.test.ts | 4 +- .../features/ee/billing/credit-service.ts | 4 +- .../ee/dsync/lib/handleGroupEvents.ts | 4 +- .../lib/OrganizationPermissionService.ts | 2 +- .../organizations/lib/onboardingStore.test.ts | 621 +++++++++--------- .../lib/server/orgCreationUtils.ts | 2 +- .../pages/components/OtherTeamList.tsx | 2 +- .../pages/components/OtherTeamsListing.tsx | 2 +- .../repositories/OrganizationRepository.ts | 2 +- .../features/ee/payments/pages/payment.tsx | 2 +- .../AssignmentReasonRecorder.ts | 2 +- .../roundRobinManualReassignment.ts | 2 +- packages/features/ee/sso/lib/sso.ts | 2 +- .../ee/support/lib/intercom/useIntercom.ts | 6 +- packages/features/ee/teams/lib/queries.ts | 6 +- .../services/teamService.alternative.test.ts | 2 +- .../ee/teams/services/teamService.test.ts | 4 +- .../features/ee/teams/services/teamService.ts | 20 +- .../ee/workflows/api/scheduleSMSReminders.ts | 2 +- .../workflows/components/WorkflowListPage.tsx | 2 +- .../components/WorkflowStepContainer.tsx | 166 ++--- .../components/dialogs/ImportNumberDialog.tsx | 6 +- .../components/tabs/IncomingCallsTab.tsx | 4 +- .../lib/reminders/aiPhoneCallManager.ts | 2 +- .../lib/reminders/smsReminderManager.ts | 2 +- .../lib/reminders/whatsappReminderManager.ts | 2 +- .../features/ee/workflows/pages/index.tsx | 2 +- .../features/ee/workflows/pages/workflow.tsx | 2 +- .../repositories/WorkflowRepository.test.ts | 2 +- .../components/ChildrenEventTypeSelect.tsx | 10 +- .../components/CreateEventTypeForm.tsx | 2 +- .../components/locations/CalVideoSettings.tsx | 10 +- .../components/tabs/limits/EventLimitsTab.tsx | 63 +- .../eventtypes/lib/getEventTypeById.ts | 6 +- .../eventtypes/lib/getEventTypesByViewer.ts | 19 +- .../features/eventtypes/lib/getPublicEvent.ts | 8 +- .../repositories/eventTypeRepository.ts | 2 +- .../features/form-builder/FormBuilder.tsx | 4 +- packages/features/handleMarkNoShow.ts | 4 +- .../insights/server/routing-events.ts | 4 +- .../features/insights/server/trpc-router.ts | 4 +- .../services/InsightsBookingBaseService.ts | 4 +- .../services/InsightsRoutingBaseService.ts | 2 +- .../pbac/domain/types/permission-registry.ts | 1 - .../__tests__/event-type-permissions.test.ts | 12 +- .../services/legacy-role-manager.service.ts | 8 +- .../pbac/services/permission-check.service.ts | 2 +- .../lib/createAProfileForAnExistingUser.ts | 2 +- packages/features/profile/lib/hideBranding.ts | 2 +- .../routing-forms/lib/getRoutedUrl.test.ts | 2 +- .../routing-forms/lib/getRoutedUrl.ts | 7 +- packages/features/shell/SideBar.tsx | 2 +- .../tasks/analytics/sendAnalyticsEvent.ts | 2 +- .../tasker/tasks/crm/createCRMEvent.ts | 1 + .../components/AvailabilitySliderTable.tsx | 2 +- packages/features/users/lib/deleteUser.ts | 3 +- packages/features/users/lib/getRoutedUsers.ts | 2 +- .../users/repositories/UserRepository.test.ts | 2 +- .../users/services/userCreationService.ts | 2 +- .../watchlist/lib/service/SpamCheckService.ts | 4 +- packages/features/watchlist/lib/testUtils.ts | 1 - .../webhooks/lib/interface/repository.ts | 7 +- .../features/webhooks/pages/webhooks-view.tsx | 2 +- packages/lib/CalendarService.ts | 4 +- .../repository/PrismaPhoneNumberRepository.ts | 26 +- .../bookingReference.integration-test.ts | 382 +++++++++++ .../lib/server/repository/bookingReference.ts | 13 +- .../atoms/booker/BookerPlatformWrapper.tsx | 8 +- .../wrappers/EventAdvancedWebWrapper.tsx | 2 +- packages/platform/libraries/slots.ts | 2 +- packages/platform/libraries/vite.config.js | 16 +- packages/prisma/auto-migrations.ts | 4 + packages/prisma/client/index.ts | 2 + .../disallow-undefined-delete-update-many.ts | 6 +- packages/prisma/index.ts | 47 +- packages/prisma/is-prisma-available-check.ts | 7 +- .../prisma/middleware/bookingReference.ts | 50 -- packages/prisma/middleware/index.ts | 1 - packages/prisma/package.json | 8 +- packages/prisma/schema.prisma | 19 +- .../server/middlewares/sessionMiddleware.ts | 4 +- .../routing-forms/formMutation.handler.ts | 10 +- .../apps/routing-forms/forms.handler.ts | 5 +- .../viewer/aiVoiceAgent/listCalls.handler.ts | 2 +- .../aiVoiceAgent/setupInboundAgent.schema.ts | 2 +- .../updateInboundAgentEventType.handler.ts | 1 + .../updateInboundAgentEventType.schema.ts | 2 +- .../routers/viewer/apps/appById.handler.ts | 2 +- .../apps/queryForDependencies.handler.ts | 2 +- .../viewer/bookings/confirm.handler.ts | 8 +- .../viewer/bookings/editLocation.handler.ts | 6 +- .../bookings/requestReschedule.handler.ts | 6 +- ...ownloadLinkOfCalVideoRecordings.handler.ts | 2 +- .../viewer/credits/buyCredits.handler.ts | 6 +- .../credits/downloadExpenseLog.handler.ts | 2 +- .../viewer/credits/getAllCredits.handler.ts | 4 +- .../getAffectedMembersForDisable.handler.ts | 2 +- .../toggleEnabled.handler.ts | 6 +- .../viewer/delegationCredential/utils.ts | 2 +- .../getEventTypesFromGroup.handler.ts | 2 +- .../eventTypes/getUserEventGroups.handler.ts | 4 +- .../viewer/eventTypes/heavy/create.handler.ts | 2 +- .../eventTypes/heavy/duplicate.handler.ts | 12 +- .../viewer/eventTypes/heavy/update.handler.ts | 8 +- .../server/routers/viewer/eventTypes/util.ts | 6 +- .../viewer/eventTypes/utils/transformUtils.ts | 4 +- .../server/routers/viewer/me/get.handler.ts | 2 +- .../viewer/me/updateProfile.handler.ts | 6 +- .../viewer/organizations/create.handler.ts | 4 +- .../organizations/createTeams.handler.ts | 2 +- .../createWithPaymentIntent.schema.ts | 1 - .../viewer/organizations/getTeams.handler.ts | 2 +- .../viewer/organizations/list.handler.ts | 2 +- .../organizations/listMembers.handler.ts | 2 +- .../organizations/updateUser.handler.ts | 6 +- ...rsMatchingAttributeLogicOfRoute.handler.ts | 8 +- .../handleNotificationWhenNoSlots.test.ts | 2 +- .../slots/handleNotificationWhenNoSlots.ts | 4 +- .../viewer/slots/isAvailable.handler.ts | 2 +- .../trpc/server/routers/viewer/slots/util.ts | 2 - .../viewer/teams/changeMemberRole.handler.ts | 2 +- .../routers/viewer/teams/create.handler.ts | 2 +- .../viewer/teams/createInvite.handler.ts | 2 +- .../routers/viewer/teams/delete.handler.ts | 2 +- .../viewer/teams/hasActiveTeamPlan.handler.ts | 2 +- .../inviteMember/inviteMember.handler.ts | 2 +- .../viewer/teams/inviteMember/utils.ts | 6 +- .../viewer/teams/listMembers.handler.ts | 4 +- .../routers/viewer/teams/publish.handler.ts | 2 +- .../__tests__/PBACRemoveMemberService.test.ts | 2 +- .../getRoundRobinHostsToReasign.handler.ts | 4 +- .../roundRobinManualReassign.handler.ts | 2 +- .../roundRobin/roundRobinReassign.handler.ts | 2 +- .../viewer/teams/skipTeamTrials.handler.ts | 2 +- .../routers/viewer/teams/update.handler.ts | 2 +- .../workflows/activateEventType.handler.ts | 4 +- .../viewer/workflows/delete.handler.ts | 2 +- .../routers/viewer/workflows/list.handler.ts | 2 +- .../viewer/workflows/update.handler.ts | 2 +- .../server/routers/viewer/workflows/util.ts | 9 +- .../ui/components/avatar/UserAvatarGroup.tsx | 2 +- .../avatar/UserAvatarGroupWithOrg.tsx | 2 +- .../ui/components/form/inputs/TextField.tsx | 2 +- scripts/seed-app-store.ts | 183 +----- scripts/seed-insights.ts | 18 +- scripts/seed.ts | 179 ++++- tests/libs/__mocks__/prisma.ts | 113 +++- turbo.json | 6 +- yarn.lock | 281 +++++++- 324 files changed, 3221 insertions(+), 1401 deletions(-) create mode 100644 apps/api/v1/test/lib/booking-references.integration-test.ts create mode 100644 apps/api/v2/src/modules/prisma/prisma-worker.module.ts create mode 100644 packages/features/credentials/handleDeleteCredential.integration-test.ts create mode 100644 packages/lib/server/repository/bookingReference.integration-test.ts create mode 100644 packages/prisma/client/index.ts delete mode 100644 packages/prisma/middleware/bookingReference.ts delete mode 100644 packages/prisma/middleware/index.ts diff --git a/.github/actions/cache-db/action.yml b/.github/actions/cache-db/action.yml index f1b519f23f..7906afed02 100644 --- a/.github/actions/cache-db/action.yml +++ b/.github/actions/cache-db/action.yml @@ -26,7 +26,7 @@ runs: with: path: ${{ inputs.path }} key: ${{ runner.os }}-${{ env.cache-name }}-${{ inputs.path }}-${{ env.key-1 }}-${{ env.key-2 }}-${{ env.key-3 }} - - run: echo ${{ env.E2E_TEST_CALCOM_QA_GCAL_CREDENTIALS }} && yarn db-seed + - run: USE_POOL=true yarn db-seed if: steps.cache-db.outputs.cache-hit != 'true' shell: bash - name: Postgres Dump Backup diff --git a/.github/workflows/api-v2-production-build.yml b/.github/workflows/api-v2-production-build.yml index 4d95fd935d..8bdb3ec244 100644 --- a/.github/workflows/api-v2-production-build.yml +++ b/.github/workflows/api-v2-production-build.yml @@ -56,8 +56,8 @@ jobs: if: steps.cache-api-v2-build.outputs.cache-hit != 'true' run: | export NODE_OPTIONS="--max_old_space_size=8192" - yarn workspace @calcom/api-v2 run generate-schemas - rm -rf apps/api/v2/node_modules - yarn install + yarn workspace @calcom/api-v2 run generate-schemas && + rm -rf apps/api/v2/node_modules && + yarn install && yarn workspace @calcom/api-v2 run build shell: bash diff --git a/.gitignore b/.gitignore index 8574f3d252..7ddef52338 100644 --- a/.gitignore +++ b/.gitignore @@ -66,7 +66,8 @@ tsconfig.tsbuildinfo .turbo # Prisma generated files -packages/prisma/client/* +apps/api/v2/generated/prisma/* +packages/prisma/generated/prisma/* packages/prisma/zod/**/*.ts packages/prisma/enums diff --git a/apps/api/v1/pages/api/booking-references/[id]/_auth-middleware.ts b/apps/api/v1/pages/api/booking-references/[id]/_auth-middleware.ts index 542f16265b..5dd52285cb 100644 --- a/apps/api/v1/pages/api/booking-references/[id]/_auth-middleware.ts +++ b/apps/api/v1/pages/api/booking-references/[id]/_auth-middleware.ts @@ -12,7 +12,7 @@ async function authMiddleware(req: NextApiRequest) { if (isSystemWideAdmin) return; // Find all references where the user has bookings const bookingReference = await prisma.bookingReference.findFirst({ - where: { id, booking: { userId } }, + where: { id, booking: { userId }, deleted: null }, }); if (!bookingReference) throw new HttpError({ statusCode: 403, message: "Forbidden" }); } diff --git a/apps/api/v1/pages/api/booking-references/[id]/_delete.ts b/apps/api/v1/pages/api/booking-references/[id]/_delete.ts index 6f7328ed42..e3515d5ff5 100644 --- a/apps/api/v1/pages/api/booking-references/[id]/_delete.ts +++ b/apps/api/v1/pages/api/booking-references/[id]/_delete.ts @@ -37,7 +37,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform export async function deleteHandler(req: NextApiRequest) { const { query } = req; const { id } = schemaQueryIdParseInt.parse(query); - await prisma.bookingReference.delete({ where: { id } }); + await prisma.bookingReference.update({ where: { id }, data: { deleted: true } }); return { message: `BookingReference with id: ${id} deleted` }; } diff --git a/apps/api/v1/pages/api/booking-references/[id]/_get.ts b/apps/api/v1/pages/api/booking-references/[id]/_get.ts index d7d178bdba..1635dee7b0 100644 --- a/apps/api/v1/pages/api/booking-references/[id]/_get.ts +++ b/apps/api/v1/pages/api/booking-references/[id]/_get.ts @@ -38,7 +38,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform export async function getHandler(req: NextApiRequest) { const { query } = req; const { id } = schemaQueryIdParseInt.parse(query); - const booking_reference = await prisma.bookingReference.findUniqueOrThrow({ where: { id } }); + const booking_reference = await prisma.bookingReference.findUniqueOrThrow({ where: { id, deleted: null } }); return { booking_reference: schemaBookingReferenceReadPublic.parse(booking_reference) }; } diff --git a/apps/api/v1/pages/api/booking-references/_get.ts b/apps/api/v1/pages/api/booking-references/_get.ts index 8c4b350ea4..e328929c52 100644 --- a/apps/api/v1/pages/api/booking-references/_get.ts +++ b/apps/api/v1/pages/api/booking-references/_get.ts @@ -29,13 +29,13 @@ import { schemaBookingReferenceReadPublic } from "~/lib/validations/booking-refe * 404: * description: No booking references were found */ -async function getHandler(req: NextApiRequest) { +export async function handler(req: NextApiRequest) { const { userId, isSystemWideAdmin } = req; const args: Prisma.BookingReferenceFindManyArgs = isSystemWideAdmin - ? {} - : { where: { booking: { userId } } }; + ? { where: { deleted: null } } + : { where: { booking: { userId }, deleted: null } }; const data = await prisma.bookingReference.findMany(args); return { booking_references: data.map((br) => schemaBookingReferenceReadPublic.parse(br)) }; } -export default defaultResponder(getHandler); +export default defaultResponder(handler); diff --git a/apps/api/v1/pages/api/slots/_get.ts b/apps/api/v1/pages/api/slots/_get.ts index a344755f3e..c6dd674f1e 100644 --- a/apps/api/v1/pages/api/slots/_get.ts +++ b/apps/api/v1/pages/api/slots/_get.ts @@ -3,8 +3,8 @@ import utc from "dayjs/plugin/utc"; import type { NextApiRequest, NextApiResponse } from "next"; import dayjs from "@calcom/dayjs"; -import { isSupportedTimeZone } from "@calcom/lib/dayjs"; import { getAvailableSlotsService } from "@calcom/features/di/containers/AvailableSlots"; +import { isSupportedTimeZone } from "@calcom/lib/dayjs"; import { HttpError } from "@calcom/lib/http-error"; import { defaultResponder } from "@calcom/lib/server/defaultResponder"; import { createContext } from "@calcom/trpc/server/createContext"; @@ -48,7 +48,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { : availableSlots.slots; return { slots: slotsInProvidedTimeZone }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any + } catch (cause) { if (cause instanceof TRPCError) { const statusCode = getHTTPStatusCodeFromError(cause); diff --git a/apps/api/v1/test/lib/booking-references.integration-test.ts b/apps/api/v1/test/lib/booking-references.integration-test.ts new file mode 100644 index 0000000000..845b16ad6b --- /dev/null +++ b/apps/api/v1/test/lib/booking-references.integration-test.ts @@ -0,0 +1,486 @@ +import type { Request, Response } from "express"; +import type { NextApiRequest, NextApiResponse } from "next"; +import { createMocks } from "node-mocks-http"; +import { describe, it, expect, beforeAll, afterAll } from "vitest"; + +import prisma from "@calcom/prisma"; +import type { Booking, Credential, EventType, User } from "@calcom/prisma/client"; +import { BookingStatus } from "@calcom/prisma/enums"; + +import { patchHandler } from "../../pages/api/booking-references/[id]/_patch"; +import { handler } from "../../pages/api/booking-references/_get"; + +type CustomNextApiRequest = NextApiRequest & Request; +type CustomNextApiResponse = NextApiResponse & Response; + +describe("GET /api/booking-references - Soft-delete filtering", () => { + let testUser: User; + let testCredential: Credential; + let testEventType: EventType; + let testBooking: Booking; + const createdBookingReferenceIds: number[] = []; + + beforeAll(async () => { + testUser = await prisma.user.create({ + data: { + email: "api-bookingreference-test@example.com", + username: "api-bookingreference-test", + }, + }); + + testCredential = await prisma.credential.create({ + data: { + type: "google_calendar", + key: {}, + userId: testUser.id, + }, + }); + + testEventType = await prisma.eventType.create({ + data: { + title: "Test Event Type", + slug: "api-test-event-type", + length: 30, + userId: testUser.id, + }, + }); + + testBooking = await prisma.booking.create({ + data: { + uid: "api-test-booking-uid", + title: "API Test Booking", + startTime: new Date(Date.now() + 86400000), + endTime: new Date(Date.now() + 90000000), + userId: testUser.id, + eventTypeId: testEventType.id, + status: BookingStatus.ACCEPTED, + }, + }); + }); + + afterAll(async () => { + if (createdBookingReferenceIds.length > 0) { + await prisma.bookingReference.deleteMany({ + where: { + id: { + in: createdBookingReferenceIds, + }, + }, + }); + } + + await prisma.booking.delete({ + where: { + id: testBooking.id, + }, + }); + + await prisma.eventType.delete({ + where: { + id: testEventType.id, + }, + }); + + await prisma.credential.delete({ + where: { + id: testCredential.id, + }, + }); + + await prisma.user.delete({ + where: { + id: testUser.id, + }, + }); + }); + + it("should only return active booking references, excluding soft-deleted ones", async () => { + const timestamp = Date.now(); + const activeRef = await prisma.bookingReference.create({ + data: { + type: "google_calendar", + uid: `api-active-ref-${timestamp}`, + meetingId: `api-active-meeting-${timestamp}`, + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(activeRef.id); + + const deletedRef = await prisma.bookingReference.create({ + data: { + type: "google_calendar", + uid: `api-deleted-ref-${timestamp}`, + meetingId: `api-deleted-meeting-${timestamp}`, + credentialId: testCredential.id, + bookingId: testBooking.id, + deleted: true, + }, + }); + createdBookingReferenceIds.push(deletedRef.id); + + const { req } = createMocks({ + method: "GET", + }); + + req.userId = testUser.id; + + const responseData = await handler(req); + + expect(responseData.booking_references).toBeDefined(); + expect(Array.isArray(responseData.booking_references)).toBe(true); + + const returnedActiveRef = responseData.booking_references.find( + (ref: { id: number }) => ref.id === activeRef.id + ); + const returnedDeletedRef = responseData.booking_references.find( + (ref: { id: number }) => ref.id === deletedRef.id + ); + + expect(returnedActiveRef).toBeDefined(); + expect(returnedDeletedRef).toBeUndefined(); + }); + + it("should filter booking references by user when not system admin", async () => { + const timestamp = Date.now(); + const otherUser = await prisma.user.create({ + data: { + email: `other-user-bookingreference-${timestamp}@example.com`, + username: `other-user-bookingreference-${timestamp}`, + }, + }); + + const otherBooking = await prisma.booking.create({ + data: { + uid: `other-user-booking-uid-${timestamp}`, + title: "Other User Booking", + startTime: new Date(Date.now() + 86400000), + endTime: new Date(Date.now() + 90000000), + userId: otherUser.id, + eventTypeId: testEventType.id, + status: BookingStatus.ACCEPTED, + }, + }); + + const otherUserRef = await prisma.bookingReference.create({ + data: { + type: "zoom_video", + uid: `other-user-ref-${timestamp}`, + meetingId: `other-user-meeting-${timestamp}`, + credentialId: testCredential.id, + bookingId: otherBooking.id, + }, + }); + createdBookingReferenceIds.push(otherUserRef.id); + + const { req } = createMocks({ + method: "GET", + }); + + req.userId = testUser.id; + + const responseData = await handler(req); + + const userRefs = responseData.booking_references.filter( + (ref: { id: number }) => ref.id === otherUserRef.id + ); + + expect(userRefs).toHaveLength(0); + + await prisma.booking.delete({ where: { id: otherBooking.id } }); + await prisma.user.delete({ where: { id: otherUser.id } }); + }); + + it("should return only active booking references for user, not soft-deleted ones for system admin", async () => { + const timestamp = Date.now(); + const activeRef1 = await prisma.bookingReference.create({ + data: { + type: "daily_video", + uid: `admin-active-ref-1-${timestamp}`, + meetingId: `admin-active-meeting-1-${timestamp}`, + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(activeRef1.id); + + const activeRef2 = await prisma.bookingReference.create({ + data: { + type: "daily_video", + uid: `admin-active-ref-2-${timestamp}`, + meetingId: `admin-active-meeting-2-${timestamp}`, + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(activeRef2.id); + + const deletedRef = await prisma.bookingReference.create({ + data: { + type: "daily_video", + uid: `admin-deleted-ref-${timestamp}`, + meetingId: `admin-deleted-meeting-${timestamp}`, + credentialId: testCredential.id, + bookingId: testBooking.id, + deleted: true, + }, + }); + createdBookingReferenceIds.push(deletedRef.id); + + const { req } = createMocks({ + method: "GET", + }); + + req.userId = testUser.id; + + const responseData = await handler(req); + + const activeRefs = responseData.booking_references.filter( + (ref: { id: number }) => ref.id === activeRef1.id || ref.id === activeRef2.id + ); + const returnedDeletedRef = responseData.booking_references.find( + (ref: { id: number }) => ref.id === deletedRef.id + ); + + expect(activeRefs.length).toBe(2); + expect(returnedDeletedRef).toBeUndefined(); + }); + + it("should verify soft-deleted references are never returned through the API", async () => { + const timestamp = Date.now(); + const activeRef = await prisma.bookingReference.create({ + data: { + type: "office365_calendar", + uid: `never-return-active-${timestamp}`, + meetingId: `never-return-active-meeting-${timestamp}`, + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(activeRef.id); + + await prisma.bookingReference.update({ + where: { id: activeRef.id }, + data: { deleted: true }, + }); + + const { req } = createMocks({ + method: "GET", + }); + + req.userId = testUser.id; + + const responseData = await handler(req); + + const softDeletedRef = responseData.booking_references.find( + (ref: { id: number }) => ref.id === activeRef.id + ); + + expect(softDeletedRef).toBeUndefined(); + + const refInDb = await prisma.bookingReference.findUnique({ + where: { id: activeRef.id }, + }); + expect(refInDb).toBeDefined(); + expect(refInDb?.deleted).toBe(true); + }); +}); + +describe("PATCH /api/booking-references/[id] - Existing functionality", () => { + let testUser: User; + let testCredential: Credential; + let testEventType: EventType; + let testBooking: Booking; + const createdBookingReferenceIds: number[] = []; + + beforeAll(async () => { + testUser = await prisma.user.create({ + data: { + email: "api-bookingreference-patch-test@example.com", + username: "api-bookingreference-patch-test", + }, + }); + + testCredential = await prisma.credential.create({ + data: { + type: "google_calendar", + key: {}, + userId: testUser.id, + }, + }); + + testEventType = await prisma.eventType.create({ + data: { + title: "Test Event Type", + slug: "api-patch-test-event-type", + length: 30, + userId: testUser.id, + }, + }); + + testBooking = await prisma.booking.create({ + data: { + uid: "api-patch-test-booking-uid", + title: "API Patch Test Booking", + startTime: new Date(Date.now() + 86400000), + endTime: new Date(Date.now() + 90000000), + userId: testUser.id, + eventTypeId: testEventType.id, + status: BookingStatus.ACCEPTED, + }, + }); + }); + + afterAll(async () => { + if (createdBookingReferenceIds.length > 0) { + await prisma.bookingReference.deleteMany({ + where: { + id: { + in: createdBookingReferenceIds, + }, + }, + }); + } + + await prisma.booking.delete({ + where: { + id: testBooking.id, + }, + }); + + await prisma.eventType.delete({ + where: { + id: testEventType.id, + }, + }); + + await prisma.credential.delete({ + where: { + id: testCredential.id, + }, + }); + + await prisma.user.delete({ + where: { + id: testUser.id, + }, + }); + }); + + it("should successfully update an active booking reference", async () => { + const timestamp = Date.now(); + const activeRef = await prisma.bookingReference.create({ + data: { + type: "google_calendar", + uid: `patch-active-ref-${timestamp}`, + meetingId: `patch-active-meeting-${timestamp}`, + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(activeRef.id); + + const { req } = createMocks({ + method: "PATCH", + query: { id: activeRef.id.toString() }, + body: { + meetingPassword: "new-password-123", + }, + }); + + req.userId = testUser.id; + req.isSystemWideAdmin = false; + + const responseData = await patchHandler(req); + + expect(responseData.booking_reference).toBeDefined(); + expect(responseData.booking_reference.id).toBe(activeRef.id); + expect(responseData.booking_reference.meetingPassword).toBe("new-password-123"); + + const updatedRef = await prisma.bookingReference.findUnique({ + where: { id: activeRef.id }, + }); + expect(updatedRef?.meetingPassword).toBe("new-password-123"); + }); + + it("should allow updating a soft-deleted booking reference (existing functionality)", async () => { + const timestamp = Date.now(); + const deletedRef = await prisma.bookingReference.create({ + data: { + type: "google_calendar", + uid: `patch-deleted-ref-${timestamp}`, + meetingId: `patch-deleted-meeting-${timestamp}`, + credentialId: testCredential.id, + bookingId: testBooking.id, + deleted: true, + meetingPassword: "original-password", + }, + }); + createdBookingReferenceIds.push(deletedRef.id); + + const { req } = createMocks({ + method: "PATCH", + query: { id: deletedRef.id.toString() }, + body: { + meetingPassword: "updated-password", + }, + }); + + req.userId = testUser.id; + req.isSystemWideAdmin = false; + + const responseData = await patchHandler(req); + + expect(responseData.booking_reference).toBeDefined(); + expect(responseData.booking_reference.id).toBe(deletedRef.id); + expect(responseData.booking_reference.meetingPassword).toBe("updated-password"); + + const updatedRef = await prisma.bookingReference.findUnique({ + where: { id: deletedRef.id }, + }); + expect(updatedRef?.meetingPassword).toBe("updated-password"); + expect(updatedRef?.deleted).toBe(true); + }); + + it("should verify that booking references can be updated regardless of deleted status", async () => { + const timestamp = Date.now(); + const activeRef = await prisma.bookingReference.create({ + data: { + type: "zoom_video", + uid: `patch-verify-active-${timestamp}`, + meetingId: `patch-verify-active-meeting-${timestamp}`, + credentialId: testCredential.id, + bookingId: testBooking.id, + meetingPassword: "original-password", + }, + }); + createdBookingReferenceIds.push(activeRef.id); + + await prisma.bookingReference.update({ + where: { id: activeRef.id }, + data: { deleted: true }, + }); + + const { req } = createMocks({ + method: "PATCH", + query: { id: activeRef.id.toString() }, + body: { + meetingPassword: "updated-password", + }, + }); + + req.userId = testUser.id; + req.isSystemWideAdmin = false; + + const responseData = await patchHandler(req); + + expect(responseData.booking_reference).toBeDefined(); + expect(responseData.booking_reference.meetingPassword).toBe("updated-password"); + + const refInDb = await prisma.bookingReference.findUnique({ + where: { id: activeRef.id }, + }); + expect(refInDb?.meetingPassword).toBe("updated-password"); + expect(refInDb?.deleted).toBe(true); + }); +}); diff --git a/apps/api/v1/test/lib/bookings/[id]/recordings/_get.test.ts b/apps/api/v1/test/lib/bookings/[id]/recordings/_get.test.ts index 8cf1fe62f7..05a2a18070 100644 --- a/apps/api/v1/test/lib/bookings/[id]/recordings/_get.test.ts +++ b/apps/api/v1/test/lib/bookings/[id]/recordings/_get.test.ts @@ -5,11 +5,11 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { createMocks } from "node-mocks-http"; import { describe, expect, test, vi, afterEach } from "vitest"; -import { buildBooking } from "@calcom/lib/test/builder"; import { getRecordingsOfCalVideoByRoomName, getDownloadLinkOfCalVideoByRecordingId, } from "@calcom/features/conferencing/lib/videoClient"; +import { buildBooking } from "@calcom/lib/test/builder"; import { getAccessibleUsers } from "~/lib/utils/retrieveScopedAccessibleUsers"; diff --git a/apps/api/v1/test/lib/bookings/[id]/transcripts/_get.test.ts b/apps/api/v1/test/lib/bookings/[id]/transcripts/_get.test.ts index 053f5861de..b4b8bbc901 100644 --- a/apps/api/v1/test/lib/bookings/[id]/transcripts/_get.test.ts +++ b/apps/api/v1/test/lib/bookings/[id]/transcripts/_get.test.ts @@ -5,8 +5,8 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { createMocks } from "node-mocks-http"; import { describe, expect, test, vi, afterEach } from "vitest"; -import { buildBooking } from "@calcom/lib/test/builder"; import { getAllTranscriptsAccessLinkFromRoomName } from "@calcom/features/conferencing/lib/videoClient"; +import { buildBooking } from "@calcom/lib/test/builder"; import { getAccessibleUsers } from "~/lib/utils/retrieveScopedAccessibleUsers"; diff --git a/apps/api/v2/.gitignore b/apps/api/v2/.gitignore index d325e3b2eb..d60b8f7f21 100644 --- a/apps/api/v2/.gitignore +++ b/apps/api/v2/.gitignore @@ -42,4 +42,5 @@ lerna-debug.log* .env.* !.env.example !.env.appStore.example -/client/* \ No newline at end of file +/client/* +/generated/prisma/* diff --git a/apps/api/v2/src/config/app.ts b/apps/api/v2/src/config/app.ts index bbb2813cfb..a19f3b94a1 100644 --- a/apps/api/v2/src/config/app.ts +++ b/apps/api/v2/src/config/app.ts @@ -22,6 +22,10 @@ const loadConfig = (): AppConfig => { db: { readUrl: getEnv("DATABASE_READ_URL"), writeUrl: getEnv("DATABASE_WRITE_URL"), + readPoolMax: getEnv("DATABASE_READ_POOL_MAX", 9), + writePoolMax: getEnv("DATABASE_WRITE_POOL_MAX", 7), + workerReadPoolMax: getEnv("DATABASE_READ_WORKER_POOL_MAX", 4), + workerWritePoolMax: getEnv("DATABASE_WRITE_WORKER_POOL_MAX", 6), redisUrl: getEnv("REDIS_URL"), }, next: { diff --git a/apps/api/v2/src/config/type.ts b/apps/api/v2/src/config/type.ts index cd2fe252bf..102ad23739 100644 --- a/apps/api/v2/src/config/type.ts +++ b/apps/api/v2/src/config/type.ts @@ -13,6 +13,10 @@ export type AppConfig = { db: { readUrl: string; writeUrl: string; + readPoolMax: number; + writePoolMax: number; + workerReadPoolMax: number; + workerWritePoolMax: number; redisUrl: string; }; next: { diff --git a/apps/api/v2/src/ee/bookings/2024-08-13/booking-references.repository.ts b/apps/api/v2/src/ee/bookings/2024-08-13/booking-references.repository.ts index c48a316f5c..76a75130b3 100644 --- a/apps/api/v2/src/ee/bookings/2024-08-13/booking-references.repository.ts +++ b/apps/api/v2/src/ee/bookings/2024-08-13/booking-references.repository.ts @@ -9,7 +9,7 @@ export class BookingReferencesRepository_2024_08_13 { constructor(private readonly dbRead: PrismaReadService) {} async getBookingReferences(bookingId: number, filter?: BookingReferencesFilterInput_2024_08_13) { - const whereClause: Prisma.BookingReferenceWhereInput = { bookingId }; + const whereClause: Prisma.BookingReferenceWhereInput = { bookingId, deleted: null }; if (filter?.type) { whereClause.type = filter.type; @@ -30,6 +30,7 @@ export class BookingReferencesRepository_2024_08_13 { return this.dbRead.prisma.bookingReference.findFirst({ where: { uid: eventUid, + deleted: null, }, include: { credential: true, diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts index 11c060feb8..a932e5c54a 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts @@ -39,9 +39,11 @@ export class EventTypesService_2024_06_14 { } await this.checkCanCreateEventType(user.id, body); const eventTypeUser = await this.getUserToCreateEvent(user); - // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { destinationCalendar: _destinationCalendar, ...rest } = body; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore const { eventType: eventTypeCreated } = await createEventType({ input: rest, ctx: { diff --git a/apps/api/v2/src/env.ts b/apps/api/v2/src/env.ts index b3f359b853..be3cc6b143 100644 --- a/apps/api/v2/src/env.ts +++ b/apps/api/v2/src/env.ts @@ -34,6 +34,10 @@ export type Environment = { IS_TEAM_BILLING_ENABLED: boolean; // Used to enable/disable the rewrite of /api/v2 to /v2, active by default. REWRITE_API_V2_PREFIX: string; + DATABASE_READ_POOL_MAX: number; + DATABASE_WRITE_POOL_MAX: number; + DATABASE_READ_WORKER_POOL_MAX: number; + DATABASE_WRITE_WORKER_POOL_MAX: number; }; export const getEnv = (key: K, fallback?: Environment[K]): Environment[K] => { 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 8a30a8b140..894eb01469 100644 --- a/apps/api/v2/src/lib/modules/available-slots.module.ts +++ b/apps/api/v2/src/lib/modules/available-slots.module.ts @@ -16,12 +16,12 @@ import { FilterHostsService } from "@/lib/services/filter-hosts.service"; import { NoSlotsNotificationService } from "@/lib/services/no-slots-notification.service"; import { QualifiedHostsService } from "@/lib/services/qualified-hosts.service"; import { UserAvailabilityService } from "@/lib/services/user-availability.service"; -import { PrismaModule } from "@/modules/prisma/prisma.module"; +import { PrismaWorkerModule } from "@/modules/prisma/prisma-worker.module"; import { RedisService } from "@/modules/redis/redis.service"; import { Module } from "@nestjs/common"; @Module({ - imports: [PrismaModule], + imports: [PrismaWorkerModule], providers: [ PrismaOOORepository, PrismaScheduleRepository, diff --git a/apps/api/v2/src/lib/services/booking-cancel.service.ts b/apps/api/v2/src/lib/services/booking-cancel.service.ts index 1457ad2468..6433db3c67 100644 --- a/apps/api/v2/src/lib/services/booking-cancel.service.ts +++ b/apps/api/v2/src/lib/services/booking-cancel.service.ts @@ -5,9 +5,7 @@ import { BookingCancelService as BaseBookingCancelService } from "@calcom/featur @Injectable() export class BookingCancelService extends BaseBookingCancelService { - constructor( - prismaWriteService: PrismaWriteService, - ) { + constructor(prismaWriteService: PrismaWriteService) { super({ prismaClient: prismaWriteService.prisma, }); diff --git a/apps/api/v2/src/modules/billing/interfaces/billing-service.interface.ts b/apps/api/v2/src/modules/billing/interfaces/billing-service.interface.ts index 776e191476..9c2e1f2115 100644 --- a/apps/api/v2/src/modules/billing/interfaces/billing-service.interface.ts +++ b/apps/api/v2/src/modules/billing/interfaces/billing-service.interface.ts @@ -1,6 +1,7 @@ import { PlatformPlan } from "@/modules/billing/types"; import type { StripeService } from "@/modules/stripe/stripe.service"; import Stripe from "stripe"; + import { PlatformBilling, Team } from "@calcom/prisma/client"; export type BillingData = { diff --git a/apps/api/v2/src/modules/memberships/memberships.repository.ts b/apps/api/v2/src/modules/memberships/memberships.repository.ts index 15b1b5b76c..d7fdf149c7 100644 --- a/apps/api/v2/src/modules/memberships/memberships.repository.ts +++ b/apps/api/v2/src/modules/memberships/memberships.repository.ts @@ -107,7 +107,7 @@ export class MembershipsRepository { }, }); - return userOrgAdminMemberships.map((m) => m.teamId); + return userOrgAdminMemberships.map((m: { teamId: number }) => m.teamId); } async createMembership(teamId: number, userId: number, role: MembershipRole, accepted: boolean) { diff --git a/apps/api/v2/src/modules/memberships/services/memberships.service.ts b/apps/api/v2/src/modules/memberships/services/memberships.service.ts index 4e20533d12..11ae41dbcd 100644 --- a/apps/api/v2/src/modules/memberships/services/memberships.service.ts +++ b/apps/api/v2/src/modules/memberships/services/memberships.service.ts @@ -2,6 +2,8 @@ import { MembershipsRepository } from "@/modules/memberships/memberships.reposit import { Injectable } from "@nestjs/common"; import { intersectionBy } from "lodash"; +import type { Membership } from "@calcom/prisma/client"; + @Injectable() export class MembershipsService { constructor(private readonly membershipsRepository: MembershipsRepository) {} @@ -16,8 +18,8 @@ export class MembershipsService { const secondUserMemberships = await this.membershipsRepository.findUserMemberships(secondUserId); return intersectionBy( - firstUserMemberships.filter((m) => m.accepted), - secondUserMemberships.filter((m) => m.accepted), + firstUserMemberships.filter((m: Membership) => m.accepted), + secondUserMemberships.filter((m: Membership) => m.accepted), "teamId" ); } diff --git a/apps/api/v2/src/modules/organizations/event-types/organizations-admin-not-team-member-event-types.e2e-spec.ts b/apps/api/v2/src/modules/organizations/event-types/organizations-admin-not-team-member-event-types.e2e-spec.ts index 792618a6fe..441adab5c8 100644 --- a/apps/api/v2/src/modules/organizations/event-types/organizations-admin-not-team-member-event-types.e2e-spec.ts +++ b/apps/api/v2/src/modules/organizations/event-types/organizations-admin-not-team-member-event-types.e2e-spec.ts @@ -434,20 +434,19 @@ describe("Organizations Event Types Endpoints", () => { const responseTeamEvent = responseBody.data.find((event) => event.teamId === team.id); expect(responseTeamEvent).toBeDefined(); - expect(responseTeamEvent?.hosts).toEqual([ - { - userId: teammate1.id, - name: teammate1.name, - username: teammate1.username, - avatarUrl: teammate1.avatarUrl, - }, - { - userId: teammate2.id, - name: teammate2.name, - username: teammate2.username, - avatarUrl: teammate2.avatarUrl, - }, - ]); + expect(responseTeamEvent?.hosts?.find((host) => host.userId === teammate1.id)).toEqual({ + userId: teammate1.id, + name: teammate1.name, + username: teammate1.username, + avatarUrl: teammate1.avatarUrl, + }); + + expect(responseTeamEvent?.hosts?.find((host) => host.userId === teammate2.id)).toEqual({ + userId: teammate2.id, + name: teammate2.name, + username: teammate2.username, + avatarUrl: teammate2.avatarUrl, + }); if (!responseTeamEvent) { throw new Error("Team event not found"); diff --git a/apps/api/v2/src/modules/organizations/teams/invite/organizations-teams-invite.controller.e2e-spec.ts b/apps/api/v2/src/modules/organizations/teams/invite/organizations-teams-invite.controller.e2e-spec.ts index ead68061fc..0506a3f94a 100644 --- a/apps/api/v2/src/modules/organizations/teams/invite/organizations-teams-invite.controller.e2e-spec.ts +++ b/apps/api/v2/src/modules/organizations/teams/invite/organizations-teams-invite.controller.e2e-spec.ts @@ -122,7 +122,6 @@ describe("Organizations Teams Invite Endpoints", () => { .expect(404); }); - afterAll(async () => { await userRepositoryFixture.deleteByEmail(user.email); await organizationsRepositoryFixture.delete(org.id); @@ -131,5 +130,3 @@ describe("Organizations Teams Invite Endpoints", () => { }); }); }); - - diff --git a/apps/api/v2/src/modules/organizations/teams/invite/organizations-teams-invite.controller.ts b/apps/api/v2/src/modules/organizations/teams/invite/organizations-teams-invite.controller.ts index 1b6457be5c..271ba8066c 100644 --- a/apps/api/v2/src/modules/organizations/teams/invite/organizations-teams-invite.controller.ts +++ b/apps/api/v2/src/modules/organizations/teams/invite/organizations-teams-invite.controller.ts @@ -1,5 +1,9 @@ import { API_VERSIONS_VALUES } from "@/lib/api-versions"; -import { OPTIONAL_API_KEY_HEADER, OPTIONAL_X_CAL_CLIENT_ID_HEADER, OPTIONAL_X_CAL_SECRET_KEY_HEADER } from "@/lib/docs/headers"; +import { + OPTIONAL_API_KEY_HEADER, + OPTIONAL_X_CAL_CLIENT_ID_HEADER, + OPTIONAL_X_CAL_SECRET_KEY_HEADER, +} from "@/lib/docs/headers"; import { Roles } from "@/modules/auth/decorators/roles/roles.decorator"; import { ApiAuthGuard } from "@/modules/auth/guards/api-auth/api-auth.guard"; import { PlatformPlanGuard } from "@/modules/auth/guards/billing/platform-plan.guard"; @@ -11,10 +15,8 @@ import { Controller, UseGuards, Post, Param, ParseIntPipe, HttpCode, HttpStatus import { ApiHeader, ApiOperation, ApiTags as DocsTags } from "@nestjs/swagger"; import { SUCCESS_STATUS } from "@calcom/platform-constants"; - import { TeamService } from "@calcom/platform-libraries"; - import { CreateInviteOutputDto } from "./outputs/invite.output"; @Controller({ @@ -39,5 +41,3 @@ export class OrganizationsTeamsInviteController { return { status: SUCCESS_STATUS, data: result }; } } - - diff --git a/apps/api/v2/src/modules/organizations/teams/invite/outputs/invite.output.ts b/apps/api/v2/src/modules/organizations/teams/invite/outputs/invite.output.ts index af0dabb58c..059ca461e1 100644 --- a/apps/api/v2/src/modules/organizations/teams/invite/outputs/invite.output.ts +++ b/apps/api/v2/src/modules/organizations/teams/invite/outputs/invite.output.ts @@ -11,7 +11,8 @@ export class InviteDataDto { @ApiProperty({ description: "Complete invitation URL that can be shared with prospective members. Opens the signup page with the token and redirects to getting started after signup.", - example: "http://app.cal.com/signup?token=f6a5c8b1d2e34c7f90a1b2c3d4e5f6a5b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2&callbackUrl=/getting-started", + example: + "http://app.cal.com/signup?token=f6a5c8b1d2e34c7f90a1b2c3d4e5f6a5b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2&callbackUrl=/getting-started", }) inviteLink!: string; } @@ -23,5 +24,3 @@ export class CreateInviteOutputDto { @ApiProperty({ type: InviteDataDto }) data!: InviteDataDto; } - - diff --git a/apps/api/v2/src/modules/organizations/users/index/organizations-users.repository.ts b/apps/api/v2/src/modules/organizations/users/index/organizations-users.repository.ts index 4401d166e2..388da56e58 100644 --- a/apps/api/v2/src/modules/organizations/users/index/organizations-users.repository.ts +++ b/apps/api/v2/src/modules/organizations/users/index/organizations-users.repository.ts @@ -1,7 +1,8 @@ import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { Injectable } from "@nestjs/common"; -import type { Prisma } from "@calcom/prisma/client"; + +import type { Prisma, AttributeToUser, Membership, User, Profile } from "@calcom/prisma/client"; @Injectable() export class OrganizationsUsersRepository { @@ -60,7 +61,11 @@ export class OrganizationsUsersRepository { skip, take, }); - return attributeToUsersWithProfile.map((attributeToUser) => attributeToUser.member.user); + return attributeToUsersWithProfile.map( + ( + attributeToUser: AttributeToUser & { member: Membership & { user: User & { profiles: Profile[] } } } + ) => attributeToUser.member.user + ); } async getOrganizationUsersByEmails( diff --git a/apps/api/v2/src/modules/prisma/prisma-read.service.ts b/apps/api/v2/src/modules/prisma/prisma-read.service.ts index e61b15149c..07722c5c89 100644 --- a/apps/api/v2/src/modules/prisma/prisma-read.service.ts +++ b/apps/api/v2/src/modules/prisma/prisma-read.service.ts @@ -1,36 +1,79 @@ import type { OnModuleDestroy, OnModuleInit } from "@nestjs/common"; import { Injectable, Logger } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; +import { PrismaPg } from "@prisma/adapter-pg"; +import { Pool } from "pg"; import { PrismaClient } from "@calcom/prisma/client"; +const DB_MAX_POOL_CONNECTION = 10; + +export interface PrismaServiceOptions { + readUrl?: string; + maxReadConnections?: number; + e2e?: boolean; + type: "main" | "worker"; +} + @Injectable() export class PrismaReadService implements OnModuleInit, OnModuleDestroy { private logger = new Logger("PrismaReadService"); - public prisma: PrismaClient; + public prisma!: PrismaClient; + private pool!: Pool; + private options!: PrismaServiceOptions; - constructor(readonly configService: ConfigService) { - const dbUrl = configService.get("db.readUrl", { infer: true }); + constructor(private configService?: ConfigService) { + if (configService) { + // Use ConfigService defaults + const readUrl = configService.get("db.readUrl", { infer: true }); + const poolMax = parseInt( + configService.get("db.readPoolMax", { infer: true }) ?? DB_MAX_POOL_CONNECTION + ); + const e2e = configService.get("e2e", { infer: true }) ?? false; - this.prisma = new PrismaClient({ - datasources: { - db: { - url: dbUrl, - }, - }, + this.setOptions({ + readUrl, + maxReadConnections: poolMax, + e2e, + type: "main", + }); + } + } + + setOptions(options: PrismaServiceOptions) { + this.options = options; + + const dbUrl = options.readUrl; + const isE2E = options.e2e ?? false; + + this.pool = new Pool({ + connectionString: dbUrl, + max: isE2E ? 1 : options.maxReadConnections ?? DB_MAX_POOL_CONNECTION, + idleTimeoutMillis: 300000, }); + + const adapter = new PrismaPg(this.pool); + this.prisma = new PrismaClient({ adapter }); } async onModuleInit() { - this.prisma.$connect(); + if (!this.prisma) return; + + try { + await this.prisma.$connect(); + this.logger.log("Connected to read database"); + } catch (error) { + this.logger.error("Database connection failed", error); + } } async onModuleDestroy() { try { - await this.prisma.$disconnect(); + if (this.prisma) await this.prisma.$disconnect(); + if (this.pool) await this.pool.end(); } catch (error) { - this.logger.error(error); + this.logger.error("Error disconnecting from read database", error); } } } diff --git a/apps/api/v2/src/modules/prisma/prisma-worker.module.ts b/apps/api/v2/src/modules/prisma/prisma-worker.module.ts new file mode 100644 index 0000000000..4a84620e60 --- /dev/null +++ b/apps/api/v2/src/modules/prisma/prisma-worker.module.ts @@ -0,0 +1,40 @@ +import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; +import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; +import { Module } from "@nestjs/common"; +import { ConfigModule, ConfigService } from "@nestjs/config"; + +@Module({ + imports: [ConfigModule], + providers: [ + { + provide: PrismaReadService, + useFactory: (config: ConfigService) => { + const service = new PrismaReadService(); + service.setOptions({ + readUrl: config.get("db.readUrl", { infer: true }), + maxReadConnections: parseInt(config.get("db.workerReadPoolMax", { infer: true })), + e2e: config.get("e2e", { infer: true }) ?? false, + type: "worker", + }); + return service; + }, + inject: [ConfigService], + }, + { + provide: PrismaWriteService, + useFactory: (config: ConfigService) => { + const service = new PrismaWriteService(); + service.setOptions({ + writeUrl: config.get("db.writeUrl", { infer: true }), + maxWriteConnections: parseInt(config.get("db.workerWritePoolMax", { infer: true })), + e2e: config.get("e2e", { infer: true }) ?? false, + type: "worker", + }); + return service; + }, + inject: [ConfigService], + }, + ], + exports: [PrismaReadService, PrismaWriteService], +}) +export class PrismaWorkerModule {} diff --git a/apps/api/v2/src/modules/prisma/prisma-write.service.ts b/apps/api/v2/src/modules/prisma/prisma-write.service.ts index 986db859f8..cb60985f1e 100644 --- a/apps/api/v2/src/modules/prisma/prisma-write.service.ts +++ b/apps/api/v2/src/modules/prisma/prisma-write.service.ts @@ -1,36 +1,75 @@ -import { OnModuleDestroy, OnModuleInit } from "@nestjs/common"; -import { Injectable, Logger } from "@nestjs/common"; +import { OnModuleDestroy, OnModuleInit, Injectable, Logger } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; +import { PrismaPg } from "@prisma/adapter-pg"; +import { Pool } from "pg"; import { PrismaClient } from "@calcom/prisma/client"; +const DB_MAX_POOL_CONNECTION = 5; + +export interface PrismaServiceOptions { + writeUrl?: string; + maxWriteConnections?: number; + e2e?: boolean; + type: "main" | "worker"; +} + @Injectable() export class PrismaWriteService implements OnModuleInit, OnModuleDestroy { private logger = new Logger("PrismaWriteService"); + public prisma!: PrismaClient; + private pool!: Pool; + private options!: PrismaServiceOptions; - public prisma: PrismaClient; + constructor(private configService?: ConfigService) { + if (configService) { + const writeUrl = configService.get("db.writeUrl", { infer: true }); + const poolMax = parseInt( + configService.get("db.writePoolMax", { infer: true }) ?? DB_MAX_POOL_CONNECTION + ); + const e2e = configService.get("e2e", { infer: true }) ?? false; - constructor(readonly configService: ConfigService) { - const dbUrl = configService.get("db.writeUrl", { infer: true }); + this.setOptions({ + writeUrl, + maxWriteConnections: poolMax, + e2e, + type: "main", + }); + } + } - this.prisma = new PrismaClient({ - datasources: { - db: { - url: dbUrl, - }, - }, + setOptions(options: PrismaServiceOptions) { + this.options = options; + + const dbUrl = options.writeUrl; + const isE2E = options.e2e ?? false; + this.pool = new Pool({ + connectionString: dbUrl, + max: isE2E ? 1 : options.maxWriteConnections ?? DB_MAX_POOL_CONNECTION, + idleTimeoutMillis: 300000, }); + + const adapter = new PrismaPg(this.pool); + this.prisma = new PrismaClient({ adapter }); } async onModuleInit() { - this.prisma.$connect(); + if (!this.prisma) return; + + try { + await this.prisma.$connect(); + this.logger.log("Connected to write database"); + } catch (error) { + this.logger.error("Database connection failed", error); + } } async onModuleDestroy() { try { - await this.prisma.$disconnect(); + if (this.prisma) await this.prisma.$disconnect(); + if (this.pool) await this.pool.end(); } catch (error) { - this.logger.error(error); + this.logger.error("Error disconnecting from write database", error); } } } diff --git a/apps/api/v2/src/modules/prisma/prisma.module.ts b/apps/api/v2/src/modules/prisma/prisma.module.ts index e9a66a5fc4..3c5d0d7565 100644 --- a/apps/api/v2/src/modules/prisma/prisma.module.ts +++ b/apps/api/v2/src/modules/prisma/prisma.module.ts @@ -1,9 +1,40 @@ import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { Module } from "@nestjs/common"; +import { ConfigModule, ConfigService } from "@nestjs/config"; @Module({ - providers: [PrismaReadService, PrismaWriteService], + imports: [ConfigModule], + providers: [ + { + provide: PrismaReadService, + useFactory: (config: ConfigService) => { + const service = new PrismaReadService(); + service.setOptions({ + readUrl: config.get("db.readUrl", { infer: true }), + maxReadConnections: parseInt(config.get("db.readPoolMax", { infer: true })), + e2e: config.get("e2e", { infer: true }) ?? false, + type: "main", + }); + return service; + }, + inject: [ConfigService], + }, + { + provide: PrismaWriteService, + useFactory: (config: ConfigService) => { + const service = new PrismaWriteService(); + service.setOptions({ + writeUrl: config.get("db.writeUrl", { infer: true }), + maxWriteConnections: parseInt(config.get("db.writePoolMax", { infer: true })), + e2e: config.get("e2e", { infer: true }) ?? false, + type: "main", + }); + return service; + }, + inject: [ConfigService], + }, + ], exports: [PrismaReadService, PrismaWriteService], }) export class PrismaModule {} diff --git a/apps/api/v2/src/modules/slots/slots-2024-04-15/workers/slots.worker.module.ts b/apps/api/v2/src/modules/slots/slots-2024-04-15/workers/slots.worker.module.ts index c46a6b37e7..360da1726f 100644 --- a/apps/api/v2/src/modules/slots/slots-2024-04-15/workers/slots.worker.module.ts +++ b/apps/api/v2/src/modules/slots/slots-2024-04-15/workers/slots.worker.module.ts @@ -2,7 +2,7 @@ // Needed if ConfigService is used anywhere import appConfig from "@/config/app"; import { AvailableSlotsModule } from "@/lib/modules/available-slots.module"; -import { PrismaModule } from "@/modules/prisma/prisma.module"; +import { PrismaWorkerModule } from "@/modules/prisma/prisma-worker.module"; import { Module, Logger } from "@nestjs/common"; import { ConfigModule } from "@nestjs/config"; import { SentryModule } from "@sentry/nestjs/setup"; @@ -15,7 +15,7 @@ import { SentryModule } from "@sentry/nestjs/setup"; isGlobal: true, load: [appConfig], }), - PrismaModule, + PrismaWorkerModule, AvailableSlotsModule, ], providers: [Logger], diff --git a/apps/api/v2/src/modules/stripe/stripe.service.ts b/apps/api/v2/src/modules/stripe/stripe.service.ts index a562665def..9302c716c1 100644 --- a/apps/api/v2/src/modules/stripe/stripe.service.ts +++ b/apps/api/v2/src/modules/stripe/stripe.service.ts @@ -118,7 +118,7 @@ export class StripeService { userId ); - const credentialIdsToDelete = existingCredentials.map((item) => item.id); + const credentialIdsToDelete = existingCredentials.map((item: Credential) => item.id); if (credentialIdsToDelete.length > 0) { await this.appsRepository.deleteAppCredentials(credentialIdsToDelete, userId); } diff --git a/apps/api/v2/src/modules/teams/memberships/teams-memberships.repository.ts b/apps/api/v2/src/modules/teams/memberships/teams-memberships.repository.ts index d298ebd767..3c1c3c7271 100644 --- a/apps/api/v2/src/modules/teams/memberships/teams-memberships.repository.ts +++ b/apps/api/v2/src/modules/teams/memberships/teams-memberships.repository.ts @@ -17,7 +17,7 @@ export const MembershipUserSelect: Prisma.UserSelect = { name: true, metadata: true, bio: true, -}; +} satisfies Prisma.UserSelect; @Injectable() export class TeamsMembershipsRepository { diff --git a/apps/api/v2/src/modules/teams/teams/teams.repository.ts b/apps/api/v2/src/modules/teams/teams/teams.repository.ts index 8d25133132..2cd9ab58d6 100644 --- a/apps/api/v2/src/modules/teams/teams/teams.repository.ts +++ b/apps/api/v2/src/modules/teams/teams/teams.repository.ts @@ -3,7 +3,7 @@ import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { Injectable, NotFoundException } from "@nestjs/common"; import { teamMetadataSchema } from "@calcom/platform-libraries"; -import { Prisma } from "@calcom/prisma/client"; +import type { Membership, Prisma } from "@calcom/prisma/client"; @Injectable() export class TeamsRepository { @@ -41,7 +41,7 @@ export class TeamsRepository { return []; } - return teamMembers.map((member) => member.userId); + return teamMembers.map((member: Membership) => member.userId); } async getTeamManagedUsersIds(teamId: number) { @@ -57,7 +57,7 @@ export class TeamsRepository { return []; } - return teamMembers.map((member) => member.userId); + return teamMembers.map((member: Membership) => member.userId); } async getTeamsUserIsMemberOf(userId: number) { diff --git a/apps/api/v2/src/modules/users/users.repository.ts b/apps/api/v2/src/modules/users/users.repository.ts index 0453475220..1604fd38de 100644 --- a/apps/api/v2/src/modules/users/users.repository.ts +++ b/apps/api/v2/src/modules/users/users.repository.ts @@ -289,7 +289,7 @@ export class UsersRepository { user: true, }, }); - return profiles.map((profile) => profile.user); + return profiles.map((profile: Profile & { user: User }) => profile.user); } async setDefaultConferencingApp(userId: number, appSlug?: string, appLink?: string) { diff --git a/apps/api/v2/tsconfig.json b/apps/api/v2/tsconfig.json index 0709c3bef9..03473dcc05 100644 --- a/apps/api/v2/tsconfig.json +++ b/apps/api/v2/tsconfig.json @@ -14,7 +14,7 @@ "jsx": "react-jsx", "paths": { "@/*": ["./src/*"], - "@prisma/client/*": ["./client/*"], + "@calcom/prisma/client": ["../../../packages/prisma/generated/prisma/client"], "@calcom/prisma/enums": ["../../../packages/prisma/enums"], "@calcom/platform-constants": ["../../../packages/platform/constants/index.ts"], "@calcom/platform-types": ["../../../packages/platform/types/index.ts"], 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 fb608f3867..0e0894befb 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 @@ -3,6 +3,7 @@ import { unstable_cache } from "next/cache"; import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/app-store/zod-utils"; import { getTeamData } from "@calcom/features/ee/teams/lib/getTeamData"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { getEventTypeHosts, getProfileFromEvent, @@ -11,10 +12,9 @@ import { } from "@calcom/features/eventtypes/lib/getPublicEvent"; import { getTeamEventType } from "@calcom/features/eventtypes/lib/getTeamEventType"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { NEXTJS_CACHE_TTL } from "@calcom/lib/constants"; import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { prisma } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import type { SchedulingType } from "@calcom/prisma/enums"; diff --git a/apps/web/app/(use-page-wrapper)/(main-nav)/teams/page.tsx b/apps/web/app/(use-page-wrapper)/(main-nav)/teams/page.tsx index 114b4f1489..287a278b42 100644 --- a/apps/web/app/(use-page-wrapper)/(main-nav)/teams/page.tsx +++ b/apps/web/app/(use-page-wrapper)/(main-nav)/teams/page.tsx @@ -23,8 +23,14 @@ const ServerPage = async ({ searchParams: _searchParams }: ServerPageProps) => { const session = await getServerSession({ req: buildLegacyRequest(await headers(), await cookies()) }); const searchParams = await _searchParams; const token = Array.isArray(searchParams?.token) ? searchParams.token[0] : searchParams?.token; - const autoAccept = Array.isArray(searchParams?.autoAccept) ? searchParams.autoAccept[0] : searchParams?.autoAccept; - const callbackUrl = token ? `/teams?token=${encodeURIComponent(token)}${autoAccept ? `&autoAccept=${encodeURIComponent(autoAccept)}` : ''}` : null; + const autoAccept = Array.isArray(searchParams?.autoAccept) + ? searchParams.autoAccept[0] + : searchParams?.autoAccept; + const callbackUrl = token + ? `/teams?token=${encodeURIComponent(token)}${ + autoAccept ? `&autoAccept=${encodeURIComponent(autoAccept)}` : "" + }` + : null; if (!session) { redirect(callbackUrl ? `/auth/login?callbackUrl=${callbackUrl}` : "/auth/login"); diff --git a/apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx b/apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx index bca38f4981..5698aa509c 100644 --- a/apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx +++ b/apps/web/app/(use-page-wrapper)/(main-nav)/teams/server-page.tsx @@ -3,9 +3,9 @@ import type { Session } from "next-auth"; import { unstable_cache } from "next/cache"; import { TeamsListing } from "@calcom/features/ee/teams/components/TeamsListing"; -import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { TeamService } from "@calcom/features/ee/teams/services/teamService"; +import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import prisma from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; @@ -33,7 +33,9 @@ export const ServerTeamsListing = async ({ session: Session; }) => { const token = Array.isArray(searchParams?.token) ? searchParams.token[0] : searchParams?.token; - const autoAccept = Array.isArray(searchParams?.autoAccept) ? searchParams.autoAccept[0] : searchParams?.autoAccept; + const autoAccept = Array.isArray(searchParams?.autoAccept) + ? searchParams.autoAccept[0] + : searchParams?.autoAccept; const userId = session.user.id; let invitationAccepted = false; @@ -42,7 +44,7 @@ export const ServerTeamsListing = async ({ if (token) { try { - if (autoAccept === "true") { + if (autoAccept === "true") { await TeamService.acceptInvitationByToken(token, userId); invitationAccepted = true; } else { diff --git a/apps/web/app/(use-page-wrapper)/apps/routing-forms/[...pages]/RouteBuilder.tsx b/apps/web/app/(use-page-wrapper)/apps/routing-forms/[...pages]/RouteBuilder.tsx index 21142e225d..d1cbfdc813 100644 --- a/apps/web/app/(use-page-wrapper)/apps/routing-forms/[...pages]/RouteBuilder.tsx +++ b/apps/web/app/(use-page-wrapper)/apps/routing-forms/[...pages]/RouteBuilder.tsx @@ -308,7 +308,7 @@ const WeightedAttributesSelector = ({ />
- {!!attributeIdForWeights ? ( + {attributeIdForWeights ? ( { hookForm.reset({}); - // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const filters = getTeamsFiltersFromQuery(routerQuery); diff --git a/apps/web/app/(use-page-wrapper)/getting-started/[[...step]]/page.tsx b/apps/web/app/(use-page-wrapper)/getting-started/[[...step]]/page.tsx index 24667ec843..8de884532e 100644 --- a/apps/web/app/(use-page-wrapper)/getting-started/[[...step]]/page.tsx +++ b/apps/web/app/(use-page-wrapper)/getting-started/[[...step]]/page.tsx @@ -5,8 +5,8 @@ import { cookies, headers } from "next/headers"; import { redirect } from "next/navigation"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; -import { APP_NAME } from "@calcom/lib/constants"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; +import { APP_NAME } from "@calcom/lib/constants"; import prisma from "@calcom/prisma"; import { meRouter } from "@calcom/trpc/server/routers/viewer/me/_router"; diff --git a/apps/web/app/(use-page-wrapper)/settings/(admin-layout)/admin/organizations/[id]/edit/page.tsx b/apps/web/app/(use-page-wrapper)/settings/(admin-layout)/admin/organizations/[id]/edit/page.tsx index fb9f4cd6c9..5e35f5db78 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(admin-layout)/admin/organizations/[id]/edit/page.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(admin-layout)/admin/organizations/[id]/edit/page.tsx @@ -4,8 +4,8 @@ import { z } from "zod"; import LicenseRequired from "@calcom/features/ee/common/components/LicenseRequired"; import { OrgForm } from "@calcom/features/ee/organizations/pages/settings/admin/AdminOrgEditPage"; -import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; +import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; const orgIdSchema = z.object({ id: z.coerce.number() }); diff --git a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx index 4319041729..8a1dd35930 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/SettingsLayoutAppDirClient.tsx @@ -369,7 +369,6 @@ const TeamListCollapsible = ({ teamFeatures }: { teamFeatures?: Record bottom.dataset.testid === "vertical-tab-Members" )[1]; - // eslint-disable-next-line @calcom/eslint/no-scroll-into-view-embed -- Settings layout isn't embedded tabMembers?.scrollIntoView({ behavior: "smooth" }); }, 100); } @@ -568,7 +567,6 @@ const SettingsSidebarContainer = ({ const tabMembers = Array.from(document.getElementsByTagName("a")).filter( (bottom) => bottom.dataset.testid === "vertical-tab-Members" )[1]; - // eslint-disable-next-line @calcom/eslint/no-scroll-into-view-embed -- Settings layout isn't embedded tabMembers?.scrollIntoView({ behavior: "smooth" }); }, 100); } diff --git a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/developer/webhooks/[id]/page.tsx b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/developer/webhooks/[id]/page.tsx index c161793e88..1dd209cb0b 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/developer/webhooks/[id]/page.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/developer/webhooks/[id]/page.tsx @@ -2,9 +2,9 @@ import type { PageProps } from "app/_types"; import { getTranslate, _generateMetadata } from "app/_utils"; import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; +import { WebhookRepository } from "@calcom/features/webhooks/lib/repository/WebhookRepository"; import { EditWebhookView } from "@calcom/features/webhooks/pages/webhook-edit-view"; import { APP_NAME } from "@calcom/lib/constants"; -import { WebhookRepository } from "@calcom/features/webhooks/lib/repository/WebhookRepository"; export const generateMetadata = async ({ params }: { params: Promise<{ id: string }> }) => await _generateMetadata( 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 dcd08c327e..5b86ef0248 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 @@ -1,7 +1,7 @@ import { _generateMetadata, getTranslate } from "app/_utils"; import { unstable_cache } from "next/cache"; -import { notFound } from "next/navigation"; import { revalidatePath } from "next/cache"; +import { notFound } from "next/navigation"; import type { AppFlags } from "@calcom/features/flags/config"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; diff --git a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/teams/other/(main-page)/page.tsx b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/teams/other/(main-page)/page.tsx index 9160d5d47b..028a767e7e 100644 --- a/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/teams/other/(main-page)/page.tsx +++ b/apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/teams/other/(main-page)/page.tsx @@ -2,8 +2,8 @@ import { _generateMetadata, getTranslate } from "app/_utils"; import { redirect } from "next/navigation"; import { OtherTeamsListing } from "@calcom/features/ee/organizations/pages/components/OtherTeamsListing"; -import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; +import SettingsHeader from "@calcom/features/settings/appDir/SettingsHeader"; import { validateUserHasOrg } from "../../../actions/validateUserHasOrg"; diff --git a/apps/web/app/api/availability/calendar/route.ts b/apps/web/app/api/availability/calendar/route.ts index 2ac9b534e0..620cb1b0a3 100644 --- a/apps/web/app/api/availability/calendar/route.ts +++ b/apps/web/app/api/availability/calendar/route.ts @@ -6,11 +6,14 @@ import { z } from "zod"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { CalendarCache } from "@calcom/features/calendar-cache/calendar-cache"; -import { getCalendarCredentials, getConnectedCalendars } from "@calcom/features/calendars/lib/CalendarManager"; +import { + getCalendarCredentials, + getConnectedCalendars, +} from "@calcom/features/calendars/lib/CalendarManager"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { HttpError } from "@calcom/lib/http-error"; import notEmpty from "@calcom/lib/notEmpty"; import { SelectedCalendarRepository } from "@calcom/lib/server/repository/selectedCalendar"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import prisma from "@calcom/prisma"; import { buildLegacyRequest } from "@lib/buildLegacyCtx"; diff --git a/apps/web/app/api/cancel/route.ts b/apps/web/app/api/cancel/route.ts index c2eaabc8e5..a99ee46b73 100644 --- a/apps/web/app/api/cancel/route.ts +++ b/apps/web/app/api/cancel/route.ts @@ -13,7 +13,7 @@ async function handler(req: NextRequest) { let appDirRequestBody; try { appDirRequestBody = await req.json(); - } catch (error) { + } catch { return NextResponse.json({ success: false, message: "Invalid JSON" }, { status: 400 }); } const bookingData = bookingCancelWithCsrfSchema.parse(appDirRequestBody); diff --git a/apps/web/app/api/cron/calendar-subscriptions/route.ts b/apps/web/app/api/cron/calendar-subscriptions/route.ts index bd3e07fda6..61036eb7b4 100644 --- a/apps/web/app/api/cron/calendar-subscriptions/route.ts +++ b/apps/web/app/api/cron/calendar-subscriptions/route.ts @@ -1,6 +1,7 @@ import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; +import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import { DefaultAdapterFactory } from "@calcom/features/calendar-subscription/adapters/AdaptersFactory"; import { CalendarSubscriptionService } from "@calcom/features/calendar-subscription/lib/CalendarSubscriptionService"; import { CalendarCacheEventRepository } from "@calcom/features/calendar-subscription/lib/cache/CalendarCacheEventRepository"; @@ -8,7 +9,6 @@ import { CalendarCacheEventService } from "@calcom/features/calendar-subscriptio import { CalendarSyncService } from "@calcom/features/calendar-subscription/lib/sync/CalendarSyncService"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { SelectedCalendarRepository } from "@calcom/lib/server/repository/SelectedCalendarRepository"; -import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import { prisma } from "@calcom/prisma"; import { defaultResponderForAppDir } from "@calcom/web/app/api/defaultResponderForAppDir"; diff --git a/apps/web/app/api/cron/selected-calendars/route.ts b/apps/web/app/api/cron/selected-calendars/route.ts index 22a91932c4..77980294de 100644 --- a/apps/web/app/api/cron/selected-calendars/route.ts +++ b/apps/web/app/api/cron/selected-calendars/route.ts @@ -6,13 +6,13 @@ import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; -import GoogleCalendarService from "@calcom/app-store/googlecalendar/lib/CalendarService"; -import { CalendarAppDelegationCredentialInvalidGrantError } from "@calcom/lib/CalendarAppError"; import { findUniqueDelegationCalendarCredential } from "@calcom/app-store/delegationCredential"; +import GoogleCalendarService from "@calcom/app-store/googlecalendar/lib/CalendarService"; +import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; +import { CalendarAppDelegationCredentialInvalidGrantError } from "@calcom/lib/CalendarAppError"; import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; import { SelectedCalendarRepository } from "@calcom/lib/server/repository/selectedCalendar"; import type { CredentialForCalendarServiceWithEmail } from "@calcom/types/Credential"; import type { Ensure } from "@calcom/types/utils"; diff --git a/apps/web/app/api/recorded-daily-video/route.ts b/apps/web/app/api/recorded-daily-video/route.ts index c968a8eadb..8253835784 100644 --- a/apps/web/app/api/recorded-daily-video/route.ts +++ b/apps/web/app/api/recorded-daily-video/route.ts @@ -9,15 +9,15 @@ import { sendDailyVideoRecordingEmails, sendDailyVideoTranscriptEmails, } from "@calcom/emails/daily-video-emails"; +import { + getAllTranscriptsAccessLinkFromMeetingId, + submitBatchProcessorTranscriptionJob, +} from "@calcom/features/conferencing/lib/videoClient"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType"; import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { - getAllTranscriptsAccessLinkFromMeetingId, - submitBatchProcessorTranscriptionJob, -} from "@calcom/features/conferencing/lib/videoClient"; import { generateVideoToken } from "@calcom/lib/videoTokens"; import prisma from "@calcom/prisma"; import { getBooking } from "@calcom/web/lib/daily-webhook/getBooking"; diff --git a/apps/web/app/api/support/conversation/route.ts b/apps/web/app/api/support/conversation/route.ts index 5df9f5fe3d..3718f5cc14 100644 --- a/apps/web/app/api/support/conversation/route.ts +++ b/apps/web/app/api/support/conversation/route.ts @@ -6,11 +6,11 @@ import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { BillingPlanService } from "@calcom/features/ee/billing/domain/billing-plans"; import type { Contact } from "@calcom/features/ee/support/lib/intercom/intercom"; import { intercom } from "@calcom/features/ee/support/lib/intercom/intercom"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { WEBAPP_URL, WEBSITE_URL } from "@calcom/lib/constants"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { prisma } from "@calcom/prisma"; import { buildLegacyRequest } from "@lib/buildLegacyCtx"; diff --git a/apps/web/app/api/webhooks/calendar-subscription/[provider]/route.ts b/apps/web/app/api/webhooks/calendar-subscription/[provider]/route.ts index 60abe54140..bc703c9ce1 100644 --- a/apps/web/app/api/webhooks/calendar-subscription/[provider]/route.ts +++ b/apps/web/app/api/webhooks/calendar-subscription/[provider]/route.ts @@ -2,6 +2,7 @@ import type { Params } from "app/_types"; import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; +import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import type { CalendarSubscriptionProvider } from "@calcom/features/calendar-subscription/adapters/AdaptersFactory"; import { DefaultAdapterFactory } from "@calcom/features/calendar-subscription/adapters/AdaptersFactory"; import { CalendarSubscriptionService } from "@calcom/features/calendar-subscription/lib/CalendarSubscriptionService"; @@ -11,7 +12,6 @@ import { CalendarSyncService } from "@calcom/features/calendar-subscription/lib/ import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import logger from "@calcom/lib/logger"; import { SelectedCalendarRepository } from "@calcom/lib/server/repository/SelectedCalendarRepository"; -import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import { prisma } from "@calcom/prisma"; import { defaultResponderForAppDir } from "@calcom/web/app/api/defaultResponderForAppDir"; diff --git a/apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts b/apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts index 7d3d6d922a..a6dedcdf75 100644 --- a/apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts +++ b/apps/web/app/api/webhooks/retell-ai/__tests__/route.test.ts @@ -696,7 +696,15 @@ describe("Retell AI Webhook Handler", () => { describe("Web Call Tests", () => { const mockAgent: Pick< Agent, - "id" | "name" | "providerAgentId" | "enabled" | "userId" | "teamId" | "createdAt" | "updatedAt" | "inboundEventTypeId" + | "id" + | "name" + | "providerAgentId" + | "enabled" + | "userId" + | "teamId" + | "createdAt" + | "updatedAt" + | "inboundEventTypeId" > = { id: "agent-123", name: "Test Agent", diff --git a/apps/web/app/cache/membership.ts b/apps/web/app/cache/membership.ts index 9af484adde..112adfca32 100644 --- a/apps/web/app/cache/membership.ts +++ b/apps/web/app/cache/membership.ts @@ -2,8 +2,8 @@ import { revalidateTag, unstable_cache } from "next/cache"; -import { NEXTJS_CACHE_TTL } from "@calcom/lib/constants"; import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import { NEXTJS_CACHE_TTL } from "@calcom/lib/constants"; const CACHE_TAGS = { HAS_TEAM_PLAN: "MembershipRepository.findFirstAcceptedMembershipByUserId", diff --git a/apps/web/components/apps/btcpayserver/BtcpayPaymentComponent.tsx b/apps/web/components/apps/btcpayserver/BtcpayPaymentComponent.tsx index 870c5e8c0b..e89db5fab3 100644 --- a/apps/web/components/apps/btcpayserver/BtcpayPaymentComponent.tsx +++ b/apps/web/components/apps/btcpayserver/BtcpayPaymentComponent.tsx @@ -3,8 +3,8 @@ import { useEffect, useState } from "react"; import z from "zod"; -import type { PaymentPageProps } from "@calcom/features/ee/payments/pages/payment"; import { useBookingSuccessRedirect } from "@calcom/features/bookings/lib/bookingSuccessRedirect"; +import type { PaymentPageProps } from "@calcom/features/ee/payments/pages/payment"; import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; import { useCopy } from "@calcom/lib/hooks/useCopy"; import { useLocale } from "@calcom/lib/hooks/useLocale"; diff --git a/apps/web/components/booking/bookingActions.ts b/apps/web/components/booking/bookingActions.ts index 96457a65da..ed482b8711 100644 --- a/apps/web/components/booking/bookingActions.ts +++ b/apps/web/components/booking/bookingActions.ts @@ -115,7 +115,9 @@ export function getEditEventActions(context: BookingActionContext): ActionType[] icon: "clock", label: t("reschedule_booking"), href: `/reschedule/${booking.uid}${ - booking.seatsReferences.length && isAttendee && seatReferenceUid ? `?seatReferenceUid=${seatReferenceUid}` : "" + booking.seatsReferences.length && isAttendee && seatReferenceUid + ? `?seatReferenceUid=${seatReferenceUid}` + : "" }`, disabled: (isBookingInPast && !booking.eventType.allowReschedulingPastBookings) || isDisabledRescheduling, diff --git a/apps/web/components/dialog/RerouteDialog.tsx b/apps/web/components/dialog/RerouteDialog.tsx index 6b0d39dd07..96d4e03b94 100644 --- a/apps/web/components/dialog/RerouteDialog.tsx +++ b/apps/web/components/dialog/RerouteDialog.tsx @@ -187,7 +187,7 @@ const useReroutingState = ({ isOpenDialog }: Pick { if (!value) return ReroutingStatusEnum.REROUTING_NOT_INITIATED; if (value.error) return ReroutingStatusEnum.REROUTING_FAILED; - if (!!value.newBooking) return ReroutingStatusEnum.REROUTING_COMPLETE; + if (value.newBooking) return ReroutingStatusEnum.REROUTING_COMPLETE; return ReroutingStatusEnum.REROUTING_IN_PROGRESS; })(); diff --git a/apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts b/apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts index 18630b9af8..aff5221966 100644 --- a/apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts +++ b/apps/web/lib/apps/installation/[[...step]]/getServerSideProps.ts @@ -6,10 +6,10 @@ import type { LocationObject } from "@calcom/app-store/locations"; import { isConferencing as isConferencingApp } from "@calcom/app-store/utils"; import { getLocale } from "@calcom/features/auth/lib/getLocale"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { AppOnboardingSteps } from "@calcom/lib/apps/appOnboardingSteps"; import { CAL_URL } from "@calcom/lib/constants"; import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import prisma from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import { eventTypeBookingFields } from "@calcom/prisma/zod-utils"; @@ -281,7 +281,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => id: user.id, name: user.name, avatarUrl: user.avatarUrl, - alreadyInstalled: appInstalls.some((install) => !Boolean(install.teamId) && install.userId === user.id), + alreadyInstalled: appInstalls.some((install) => !install.teamId && install.userId === user.id), }; const teamsWithIsAppInstalled = hasTeams diff --git a/apps/web/lib/apps/routing-forms/[...pages]/getServerSidePropsSingleForm.ts b/apps/web/lib/apps/routing-forms/[...pages]/getServerSidePropsSingleForm.ts index 49a5c60fdb..75b19fe15d 100644 --- a/apps/web/lib/apps/routing-forms/[...pages]/getServerSidePropsSingleForm.ts +++ b/apps/web/lib/apps/routing-forms/[...pages]/getServerSidePropsSingleForm.ts @@ -1,8 +1,8 @@ import { enrichFormWithMigrationData } from "@calcom/app-store/routing-forms/enrichFormWithMigrationData"; import { getSerializableForm } from "@calcom/app-store/routing-forms/lib/getSerializableForm"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { Resource } from "@calcom/features/pbac/domain/types/permission-registry"; import { getResourcePermissions } from "@calcom/features/pbac/lib/resource-permissions"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { MembershipRole } from "@calcom/prisma/enums"; import type { AppGetServerSidePropsContext, AppPrisma, AppUser } from "@calcom/types/AppGetServerSideProps"; diff --git a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts index 52836d898d..23a5164a2c 100644 --- a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts +++ b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts @@ -5,8 +5,8 @@ import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { getMultipleDurationValue } from "@calcom/features/bookings/lib/get-booking"; import { getSlugOrRequestedSlug } from "@calcom/features/ee/organizations/lib/orgDomains"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; -import { shouldHideBrandingForTeamEvent } from "@calcom/features/profile/lib/hideBranding"; import { EventRepository } from "@calcom/features/eventtypes/repositories/EventRepository"; +import { shouldHideBrandingForTeamEvent } from "@calcom/features/profile/lib/hideBranding"; import slugify from "@calcom/lib/slugify"; import prisma from "@calcom/prisma"; diff --git a/apps/web/lib/pages/auth/verify-email.ts b/apps/web/lib/pages/auth/verify-email.ts index f2685246bf..f204688889 100644 --- a/apps/web/lib/pages/auth/verify-email.ts +++ b/apps/web/lib/pages/auth/verify-email.ts @@ -2,10 +2,10 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { z } from "zod"; import dayjs from "@calcom/dayjs"; +import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { IS_STRIPE_ENABLED } from "@calcom/lib/constants"; -import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; import { prisma } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; import { CreationSource } from "@calcom/prisma/enums"; diff --git a/apps/web/lib/team/[slug]/getServerSideProps.tsx b/apps/web/lib/team/[slug]/getServerSideProps.tsx index 96ca6d30f0..e2c7d71c95 100644 --- a/apps/web/lib/team/[slug]/getServerSideProps.tsx +++ b/apps/web/lib/team/[slug]/getServerSideProps.tsx @@ -1,5 +1,6 @@ import type { GetServerSidePropsContext } from "next"; +import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; import { getOrganizationSettings, @@ -9,7 +10,6 @@ import { getTeamWithMembers } from "@calcom/features/ee/teams/lib/queries"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { IS_CALCOM } from "@calcom/lib/constants"; import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; -import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; import logger from "@calcom/lib/logger"; import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; import slugify from "@calcom/lib/slugify"; diff --git a/apps/web/lib/video/[uid]/getServerSideProps.ts b/apps/web/lib/video/[uid]/getServerSideProps.ts index 4fdcc2caf3..a7f5b6b09e 100644 --- a/apps/web/lib/video/[uid]/getServerSideProps.ts +++ b/apps/web/lib/video/[uid]/getServerSideProps.ts @@ -7,14 +7,14 @@ import { updateMeetingTokenIfExpired, } from "@calcom/app-store/dailyvideo/lib/VideoApiAdapter"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; +import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; +import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { getCalVideoReference } from "@calcom/features/get-cal-video-reference"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { CAL_VIDEO_MEETING_LINK_FOR_TESTING } from "@calcom/lib/constants"; import { isENVDev } from "@calcom/lib/env"; -import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; -import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; import prisma from "@calcom/prisma"; const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true }); @@ -210,7 +210,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { exp: epochTimeFourteenDaysAfter, }); - const sessionUserId = !!session?.user?.impersonatedBy ? session.user.impersonatedBy.id : session?.user.id; + const sessionUserId = session?.user?.impersonatedBy ? session.user.impersonatedBy.id : session?.user.id; const isOrganizer = await checkIfUserIsHost({ booking: { eventTypeId: bookingObj.eventType?.id, @@ -238,7 +238,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { videoReferencePassword, sessionUserId ); - if (!!meetingPassword) { + if (meetingPassword) { bookingObj.references.forEach((bookRef) => { bookRef.meetingPassword = meetingPassword; }); diff --git a/apps/web/modules/apps/installation/[[...step]]/step-view.tsx b/apps/web/modules/apps/installation/[[...step]]/step-view.tsx index dfd8121369..76acc80eea 100644 --- a/apps/web/modules/apps/installation/[[...step]]/step-view.tsx +++ b/apps/web/modules/apps/installation/[[...step]]/step-view.tsx @@ -8,6 +8,7 @@ import type { z } from "zod"; import checkForMultiplePaymentApps from "@calcom/app-store/_utils/payments/checkForMultiplePaymentApps"; import useAddAppMutation from "@calcom/app-store/_utils/useAddAppMutation"; +import type { LocationObject } from "@calcom/app-store/locations"; import type { EventTypeAppSettingsComponentProps, EventTypeModel } from "@calcom/app-store/types"; import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/app-store/zod-utils"; import type { LocationFormValues } from "@calcom/features/eventtypes/lib/types"; @@ -15,7 +16,6 @@ import { AppOnboardingSteps } from "@calcom/lib/apps/appOnboardingSteps"; import { getAppOnboardingUrl } from "@calcom/lib/apps/getAppOnboardingUrl"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; -import type { LocationObject } from "@calcom/app-store/locations"; import type { Team } from "@calcom/prisma/client"; import type { eventTypeBookingFields } from "@calcom/prisma/zod-utils"; import type { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils"; @@ -309,21 +309,20 @@ const OnboardingPage = ({ handleSetUpLater={handleSetUpLater} /> )} - {currentStep === AppOnboardingSteps.CONFIGURE_STEP && - eventTypeGroups && ( - - )} + {currentStep === AppOnboardingSteps.CONFIGURE_STEP && eventTypeGroups && ( + + )}
diff --git a/apps/web/modules/bookings/views/bookings-single-view.tsx b/apps/web/modules/bookings/views/bookings-single-view.tsx index 6eb21c2e23..12444cc4ba 100644 --- a/apps/web/modules/bookings/views/bookings-single-view.tsx +++ b/apps/web/modules/bookings/views/bookings-single-view.tsx @@ -24,13 +24,9 @@ import { import { Price } from "@calcom/features/bookings/components/event-meta/Price"; import { getCalendarLinks, CalendarLinkType } from "@calcom/features/bookings/lib/getCalendarLinks"; import { RATING_OPTIONS, validateRating } from "@calcom/features/bookings/lib/rating"; -import { - SMS_REMINDER_NUMBER_FIELD, - SystemField, - TITLE_FIELD, -} from "@calcom/lib/bookings/SystemField"; import type { nameObjectSchema } from "@calcom/features/eventtypes/lib/eventNaming"; import { getEventName } from "@calcom/features/eventtypes/lib/eventNaming"; +import { SMS_REMINDER_NUMBER_FIELD, SystemField, TITLE_FIELD } from "@calcom/lib/bookings/SystemField"; import { APP_NAME } from "@calcom/lib/constants"; import { formatToLocalizedDate, formatToLocalizedTime, formatToLocalizedTimezone } from "@calcom/lib/dayjs"; import useGetBrandingColours from "@calcom/lib/getBrandColours"; @@ -771,7 +767,6 @@ export default function Success(props: PageProps) {
+ href="https://cal.com/blog/google-s-new-spam-policy-may-be-affecting-your-invitations" + rel="noreferrer"> {t("resolve")} diff --git a/apps/web/modules/signup-view.tsx b/apps/web/modules/signup-view.tsx index 712bbfec84..487f1581cb 100644 --- a/apps/web/modules/signup-view.tsx +++ b/apps/web/modules/signup-view.tsx @@ -274,7 +274,7 @@ export default function Signup({ }; const constructCallBackIfUrlNotPresent = () => { - if (!!isPlatformUser) { + if (isPlatformUser) { return `${WEBAPP_URL}/${gettingStartedWithPlatform}?from=signup`; } @@ -284,7 +284,7 @@ export default function Signup({ const constructCallBackUrl = () => { const callbackUrlSearchParams = searchParams?.get("callbackUrl"); - return !!callbackUrlSearchParams + return callbackUrlSearchParams ? constructCallBackIfUrlPresent() : constructCallBackIfUrlNotPresent(); }; diff --git a/apps/web/next.config.js b/apps/web/next.config.js index 5e4eb4283f..ab1238288b 100644 --- a/apps/web/next.config.js +++ b/apps/web/next.config.js @@ -405,7 +405,7 @@ const nextConfig = (phase) => { }, */ ]; - if (Boolean(process.env.NEXT_PUBLIC_API_V2_URL)) { + if (process.env.NEXT_PUBLIC_API_V2_URL) { afterFiles.push({ source: "/api/v2/:path*", destination: `${process.env.NEXT_PUBLIC_API_V2_URL}/:path*`, diff --git a/apps/web/pages/api/book/event.ts b/apps/web/pages/api/book/event.ts index 85a7480771..7f5aa63d87 100644 --- a/apps/web/pages/api/book/event.ts +++ b/apps/web/pages/api/book/event.ts @@ -3,13 +3,13 @@ import type { NextApiRequest } from "next"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { getRegularBookingService } from "@calcom/features/bookings/di/RegularBookingService.container"; import { BotDetectionService } from "@calcom/features/bot-detection"; +import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError"; import getIP from "@calcom/lib/getIP"; import { piiHasher } from "@calcom/lib/server/PiiHasher"; import { checkCfTurnstileToken } from "@calcom/lib/server/checkCfTurnstileToken"; import { defaultResponder } from "@calcom/lib/server/defaultResponder"; -import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import prisma from "@calcom/prisma"; import { CreationSource } from "@calcom/prisma/enums"; diff --git a/apps/web/playwright/cancellation-fee-warning.e2e.ts b/apps/web/playwright/cancellation-fee-warning.e2e.ts index 17fc152d1c..239944f8ea 100644 --- a/apps/web/playwright/cancellation-fee-warning.e2e.ts +++ b/apps/web/playwright/cancellation-fee-warning.e2e.ts @@ -1,6 +1,6 @@ import { expect } from "@playwright/test"; -import type Prisma from "@calcom/prisma/client"; +import type { EventType } from "@calcom/prisma/client"; import { test } from "./lib/fixtures"; import { IS_STRIPE_ENABLED, selectFirstAvailableTimeSlotNextMonth } from "./lib/testUtils"; @@ -13,7 +13,7 @@ test.describe("Cancellation Fee Warning E2E", () => { // eslint-disable-next-line playwright/no-skipped-test test.skip(!IS_STRIPE_ENABLED, "It should only run if Stripe is installed"); const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -41,7 +41,7 @@ test.describe("Cancellation Fee Warning E2E", () => { // eslint-disable-next-line playwright/no-skipped-test test.skip(!IS_STRIPE_ENABLED, "It should only run if Stripe is installed"); const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -69,7 +69,7 @@ test.describe("Cancellation Fee Warning E2E", () => { // eslint-disable-next-line playwright/no-skipped-test test.skip(!IS_STRIPE_ENABLED, "It should only run if Stripe is installed"); const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); diff --git a/apps/web/playwright/fixtures/users.ts b/apps/web/playwright/fixtures/users.ts index 67584a7cb5..c173994c49 100644 --- a/apps/web/playwright/fixtures/users.ts +++ b/apps/web/playwright/fixtures/users.ts @@ -6,13 +6,12 @@ import { v4 } from "uuid"; import updateChildrenEventTypes from "@calcom/features/ee/managed-event-types/lib/handleChildrenEventTypes"; import stripe from "@calcom/features/ee/payments/server/stripe"; +import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability"; import { WEBAPP_URL } from "@calcom/lib/constants"; -import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import { prisma } from "@calcom/prisma"; -import type Prisma from "@calcom/prisma/client"; import type { Team } from "@calcom/prisma/client"; -import type { Prisma as PrismaType } from "@calcom/prisma/client"; +import type { Prisma, User, EventType } from "@calcom/prisma/client"; import { MembershipRole, SchedulingType, TimeUnit, WorkflowTriggerEvents } from "@calcom/prisma/enums"; import { teamMetadataSchema } from "@calcom/prisma/zod-utils"; import type { Schedule } from "@calcom/types/schedule"; @@ -37,7 +36,7 @@ const userIncludes = { workflows: true, credentials: true, routingForms: true, -} satisfies PrismaType.UserInclude; +} satisfies Prisma.UserInclude; type InstallStripeParamsSkipTrue = { eventTypeIds?: number[]; @@ -63,16 +62,11 @@ type InstallStripeParams = InstallStripeParamsUnion & { page: Page; }; -const userWithEventTypes = { +const _userWithEventTypes = { include: userIncludes, -} satisfies PrismaType.UserDefaultArgs; +} satisfies Prisma.UserDefaultArgs; -const seededForm = { - id: "948ae412-d995-4865-875a-48302588de03", - name: "Seeded Form - Pro", -}; - -type UserWithIncludes = PrismaType.UserGetPayload; +type UserWithIncludes = Prisma.UserGetPayload; const createTeamWorkflow = async (user: { id: number }, team: { id: number }) => { return await prisma.workflow.create({ @@ -182,7 +176,7 @@ const createTeamAndAddUser = async ( teamSlug ?? orgRequestedSlug ?? `${isOrg ? "org" : "team"}-${workerInfo.workerIndex}-${Date.now()}${slugIndex}`; - const data: PrismaType.TeamCreateInput = { + const data: Prisma.TeamCreateInput = { name: `user-id-${user.id}'s ${isOrg ? "Org" : "Team"}`, isOrganization: isOrg, }; @@ -471,7 +465,7 @@ export const createUsersFixture = ( }, data: { orgProfiles: _user.profiles.length - ? { + ? { connect: _user.profiles.map((profile) => ({ id: profile.id })), } : { @@ -654,7 +648,6 @@ const createUserFixture = (user: UserWithIncludes, page: Page) => { // self is a reflective method that return the Prisma object that references this fixture. const self = async () => - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion (await prisma.user.findUnique({ where: { id: store.user.id }, include: { eventTypes: true }, @@ -791,9 +784,9 @@ const createUserFixture = (user: UserWithIncludes, page: Page) => { }, }); }, - setupEventWithPrice: async (eventType: Pick, slug: string) => + setupEventWithPrice: async (eventType: Pick, slug: string) => setupEventWithPrice(eventType, slug, store.page), - bookAndPayEvent: async (eventType: Pick) => + bookAndPayEvent: async (eventType: Pick) => bookAndPayEvent(user, eventType, store.page), makePaymentUsingStripe: async () => makePaymentUsingStripe(store.page), installStripePersonal: async (params: InstallStripeParamsUnion) => @@ -819,11 +812,11 @@ const createUserFixture = (user: UserWithIncludes, page: Page) => { }; }; -type SupportedTestEventTypes = PrismaType.EventTypeCreateInput & { - _bookings?: PrismaType.BookingCreateInput[]; +type SupportedTestEventTypes = Prisma.EventTypeCreateInput & { + _bookings?: Prisma.BookingCreateInput[]; }; -type SupportedTestWorkflows = PrismaType.WorkflowCreateInput; +type SupportedTestWorkflows = Prisma.WorkflowCreateInput; type CustomUserOptsKeys = | "username" @@ -836,7 +829,7 @@ type CustomUserOptsKeys = | "disableImpersonation" | "role" | "identityProvider"; -type CustomUserOpts = Partial> & { +type CustomUserOpts = Partial> & { timeZone?: TimeZoneEnum; eventTypes?: SupportedTestEventTypes[]; workflows?: SupportedTestWorkflows[]; @@ -857,7 +850,7 @@ const createUser = ( organizationId?: number | null; }) | null -): PrismaType.UserUncheckedCreateInput => { +): Prisma.UserUncheckedCreateInput => { const suffixToMakeUsernameUnique = `-${workerInfo.workerIndex}-${Date.now()}`; // build a unique name for our user const uname = @@ -983,7 +976,7 @@ async function confirmPendingPayment(page: Page) { // login using a replay of an E2E routine. export async function login( - user: Pick & Partial> & { password?: string | null }, + user: Pick & Partial> & { password?: string | null }, page: Page ) { // get locators @@ -997,7 +990,7 @@ export async function login( await page.waitForSelector("text=Welcome back"); await emailLocator.fill(user.email ?? `${user.username}@example.com`); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + await passwordLocator.fill(user.password ?? user.username!); // waiting for specific login request to resolve @@ -1007,7 +1000,7 @@ export async function login( } export async function apiLogin( - user: Pick & Partial> & { password: string | null }, + user: Pick & Partial> & { password: string | null }, page: Page, navigateToUrl?: string ) { @@ -1047,14 +1040,14 @@ export async function apiLogin( // Only wait if we're on a protected page that would trigger the session API call try { await page.waitForResponse("/api/auth/session", { timeout: 2000 }); - } catch (error) { + } catch { // Session API call not made (likely on a public page), continue anyway } return response; } -export async function setupEventWithPrice(eventType: Pick, slug: string, page: Page) { +export async function setupEventWithPrice(eventType: Pick, slug: string, page: Page) { await page.goto(`/event-types/${eventType?.id}?tabName=apps`); await page.locator(`[data-testid='${slug}-app-switch']`).first().click(); await page.getByPlaceholder("Price").fill("100"); @@ -1062,8 +1055,8 @@ export async function setupEventWithPrice(eventType: Pick, - eventType: Pick, + user: Pick, + eventType: Pick, page: Page ) { // booking process with stripe integration diff --git a/apps/web/playwright/integrations-stripe.e2e.ts b/apps/web/playwright/integrations-stripe.e2e.ts index df6fa114b5..578ba3dd90 100644 --- a/apps/web/playwright/integrations-stripe.e2e.ts +++ b/apps/web/playwright/integrations-stripe.e2e.ts @@ -2,7 +2,7 @@ import { expect } from "@playwright/test"; import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/app-store/zod-utils"; import prisma from "@calcom/prisma"; -import type Prisma from "@calcom/prisma/client"; +import type { EventType } from "@calcom/prisma/client"; import { SchedulingType } from "@calcom/prisma/enums"; import { test, todo } from "./lib/fixtures"; @@ -35,7 +35,7 @@ test.describe("Stripe integration skip true", () => { await user.installStripePersonal({ skip: true }); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.setupEventWithPrice(eventType, "stripe"); // Need to wait for the DB to be updated with the metadata @@ -102,7 +102,7 @@ test.describe("Stripe integration skip true", () => { }); test("Can book a paid booking", async ({ page, users }) => { const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -115,7 +115,7 @@ test.describe("Stripe integration skip true", () => { test("Pending payment booking should not be confirmed by default", async ({ page, users }) => { const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -139,7 +139,7 @@ test.describe("Stripe integration skip true", () => { test("Paid booking should be able to be rescheduled", async ({ page, users }) => { const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -162,7 +162,7 @@ test.describe("Stripe integration skip true", () => { test("Paid booking should be able to be cancelled", async ({ page, users }) => { const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -178,11 +178,11 @@ test.describe("Stripe integration skip true", () => { test.describe("When event is paid and confirmed", () => { let user: Awaited>; - let eventType: Prisma.EventType; + let eventType: EventType; test.beforeEach(async ({ page, users }) => { user = await users.create(); - eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -217,7 +217,7 @@ test.describe("Stripe integration skip true", () => { test.describe("Change stripe presented currency", () => { test("Should be able to change currency", async ({ page, users }) => { const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await user.installStripePersonal({ skip: true }); @@ -337,7 +337,7 @@ test.describe("Stripe integration with the new app install flow skip false", () }); test("Can book a paid booking skip false", async ({ page, users }) => { const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -348,7 +348,7 @@ test.describe("Stripe integration with the new app install flow skip false", () }); test("Pending payment booking should not be confirmed by default skip false", async ({ page, users }) => { const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -371,7 +371,7 @@ test.describe("Stripe integration with the new app install flow skip false", () test("Paid booking should be able to be rescheduled skip false", async ({ page, users }) => { const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -393,7 +393,7 @@ test.describe("Stripe integration with the new app install flow skip false", () test("Paid booking should be able to be cancelled skip false", async ({ page, users }) => { const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -408,11 +408,11 @@ test.describe("Stripe integration with the new app install flow skip false", () test.describe("When event is paid and confirmed skip false", () => { let user: Awaited>; - let eventType: Prisma.EventType; + let eventType: EventType; test.beforeEach(async ({ page, users }) => { user = await users.create(); - eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/installed"); @@ -449,7 +449,7 @@ test.describe("Stripe integration with the new app install flow skip false", () test.describe("Change stripe presented currency skip false", () => { test("Should be able to change currency skip false", async ({ page, users }) => { const user = await users.create(); - const eventType = user.eventTypes.find((e) => e.slug === "paid") as Prisma.EventType; + const eventType = user.eventTypes.find((e) => e.slug === "paid") as EventType; await user.apiLogin(); await page.goto("/apps/stripe"); diff --git a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts index ac3a14eeb6..2923b8674a 100644 --- a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts +++ b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts @@ -6,10 +6,10 @@ import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking"; import { getBookingForReschedule, getBookingForSeatedEvent } from "@calcom/features/bookings/lib/get-booking"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; -import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import { getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents"; -import { shouldHideBrandingForUserEvent } from "@calcom/features/profile/lib/hideBranding"; +import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import { EventRepository } from "@calcom/features/eventtypes/repositories/EventRepository"; +import { shouldHideBrandingForUserEvent } from "@calcom/features/profile/lib/hideBranding"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import slugify from "@calcom/lib/slugify"; import { prisma } from "@calcom/prisma"; diff --git a/apps/web/server/lib/auth/sso/[provider]/getServerSideProps.tsx b/apps/web/server/lib/auth/sso/[provider]/getServerSideProps.tsx index 857bbd69f1..2f84a5df34 100644 --- a/apps/web/server/lib/auth/sso/[provider]/getServerSideProps.tsx +++ b/apps/web/server/lib/auth/sso/[provider]/getServerSideProps.tsx @@ -6,8 +6,8 @@ import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomain import stripe from "@calcom/features/ee/payments/server/stripe"; import { hostedCal, isSAMLLoginEnabled, samlProductID, samlTenantID } from "@calcom/features/ee/sso/lib/saml"; import { ssoTenantProduct } from "@calcom/features/ee/sso/lib/sso"; -import { IS_PREMIUM_USERNAME_ENABLED } from "@calcom/lib/constants"; import { checkUsername } from "@calcom/features/profile/lib/checkUsername"; +import { IS_PREMIUM_USERNAME_ENABLED } from "@calcom/lib/constants"; import prisma from "@calcom/prisma"; import { asStringOrNull } from "@lib/asStringOrNull"; diff --git a/apps/web/test/lib/checkDurationLimits.test.ts b/apps/web/test/lib/checkDurationLimits.test.ts index f55f32bec1..2d2c435558 100644 --- a/apps/web/test/lib/checkDurationLimits.test.ts +++ b/apps/web/test/lib/checkDurationLimits.test.ts @@ -1,10 +1,7 @@ import { describe, expect, it, vi } from "vitest"; import dayjs from "@calcom/dayjs"; -import { - checkDurationLimit, - checkDurationLimits, -} from "@calcom/features/bookings/lib/checkDurationLimits"; +import { checkDurationLimit, checkDurationLimits } from "@calcom/features/bookings/lib/checkDurationLimits"; import { validateIntervalLimitOrder } from "@calcom/lib/intervalLimits/validateIntervalLimitOrder"; const mockGetTotalBookingDuration = vi.fn(); diff --git a/apps/web/test/lib/handleChildrenEventTypes.test.ts b/apps/web/test/lib/handleChildrenEventTypes.test.ts index f53459e734..a48a42c678 100644 --- a/apps/web/test/lib/handleChildrenEventTypes.test.ts +++ b/apps/web/test/lib/handleChildrenEventTypes.test.ts @@ -423,7 +423,7 @@ describe("handleChildrenEventTypes", () => { timeZone: _timeZone, parentId: _parentId, userId: _userId, - // eslint-disable-next-line @typescript-eslint/no-unused-vars + requiresBookerEmailVerification, lockTimeZoneToggleOnBookingPage, useEventTypeDestinationCalendarEmail, diff --git a/apps/web/test/utils/bookingScenario/bookingScenario.ts b/apps/web/test/utils/bookingScenario/bookingScenario.ts index ea8927f62f..ad5428a659 100644 --- a/apps/web/test/utils/bookingScenario/bookingScenario.ts +++ b/apps/web/test/utils/bookingScenario/bookingScenario.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ import i18nMock from "../../../../../tests/libs/__mocks__/libServerI18n"; import prismock from "../../../../../tests/libs/__mocks__/prisma"; @@ -118,17 +119,6 @@ type InputWorkflow = { verifiedAt?: Date; }; -type PaymentData = { - // Common payment data fields based on Stripe and other payment providers - paymentIntent?: string; - paymentMethodId?: string; - clientSecret?: string; - customerId?: string; - subscriptionId?: string; - metadata?: Record; - [key: string]: unknown; // Allow additional provider-specific fields -}; - type InputPayment = { id?: number; uid: string; @@ -139,7 +129,7 @@ type InputPayment = { currency: string; success: boolean; refunded: boolean; - data: PaymentData; + data: Prisma.InputJsonValue; externalId: string; paymentOption?: PaymentOption; }; @@ -580,7 +570,7 @@ export async function addEventTypes(eventTypes: InputEventType[], usersStore: In }; }); log.silly("TestData: Creating EventType", JSON.stringify(eventTypesWithUsers)); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Pretty complex type here + return await addEventTypesToDb(eventTypesWithUsers as unknown as any); } @@ -592,7 +582,6 @@ function addBookingReferencesToDB(bookingReferences: Prisma.BookingReferenceCrea async function addBookingsToDb( bookings: (Prisma.BookingCreateInput & { - // eslint-disable-next-line @typescript-eslint/no-explicit-any references: any[]; user?: { id: number }; })[] @@ -700,7 +689,6 @@ export async function addBookings(bookings: InputBooking[]) { ); } -// eslint-disable-next-line @typescript-eslint/no-explicit-any async function addWebhooksToDb(webhooks: any[]) { await prismock.webhook.createMany({ data: webhooks, @@ -993,7 +981,6 @@ export async function addUsers(users: InputUser[]) { return await addUsersToDb(prismaUsersCreate); } -// eslint-disable-next-line @typescript-eslint/no-explicit-any async function addAppsToDb(apps: any[]) { log.silly("TestData: Creating Apps", JSON.stringify({ apps })); await prismock.app.createMany({ @@ -1060,7 +1047,6 @@ export async function createOrganization(orgData: { slug: string; metadata?: z.infer; withTeam?: boolean; - // eslint-disable-next-line @typescript-eslint/no-explicit-any }): Promise; children: any }> { const org = await prismock.team.create({ data: { @@ -1099,7 +1085,7 @@ export async function createOrganization(orgData: { export async function createCredentials( credentialData: { type: string; - key: Prisma.JsonValue; + key: Prisma.InputJsonValue; id?: number; userId?: number | null; teamId?: number | null; @@ -2061,11 +2047,11 @@ export function mockVideoApp({ url: `http://mock-${metadataLookupKey}.example.com`, }; log.silly("mockVideoApp", JSON.stringify({ metadataLookupKey, appStoreLookupKey })); - // eslint-disable-next-line @typescript-eslint/no-explicit-any + const createMeetingCalls: any[] = []; - // eslint-disable-next-line @typescript-eslint/no-explicit-any + const updateMeetingCalls: any[] = []; - // eslint-disable-next-line @typescript-eslint/no-explicit-any + const deleteMeetingCalls: any[] = []; const mockVideoAdapter = (credential: unknown) => { @@ -2314,7 +2300,7 @@ export function getExpectedCalEventForBookingRequest({ eventType, }: { bookingRequest: ReturnType; - // eslint-disable-next-line @typescript-eslint/no-explicit-any + eventType: any; }) { return { @@ -2541,7 +2527,7 @@ export const createDelegationCredential = async (orgId: number, type: "google" | id: orgId, }, }, - serviceAccountKey: workspace.defaultServiceAccountKey, + serviceAccountKey: workspace.defaultServiceAccountKey as unknown as Prisma.InputJsonValue, }, }); @@ -2583,7 +2569,7 @@ export const createDelegationCredential = async (orgId: number, type: "google" | id: orgId, }, }, - serviceAccountKey: workspace.defaultServiceAccountKey, + serviceAccountKey: workspace.defaultServiceAccountKey as unknown as Prisma.InputJsonValue, }, }); @@ -2592,7 +2578,6 @@ export const createDelegationCredential = async (orgId: number, type: "google" | throw new Error(`Unsupported type: ${type}`); }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any export const buildDelegationCredential = ({ serviceAccountKey }: { serviceAccountKey: any }) => { return { id: -1, diff --git a/package.json b/package.json index 28c07378cb..8b5f9f12a9 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "@faker-js/faker": "9.2.0", "@jetstreamapp/soql-parser-js": "^6.1.0", "@playwright/test": "^1.45.3", + "@prisma/internals": "^6.16.2", "@snaplet/copycat": "^4.1.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^16.0.1", diff --git a/packages/app-store/_appRegistry.ts b/packages/app-store/_appRegistry.ts index 314f80f448..109d4cd78d 100644 --- a/packages/app-store/_appRegistry.ts +++ b/packages/app-store/_appRegistry.ts @@ -1,8 +1,8 @@ import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData"; -import { getAppFromSlug } from "@calcom/app-store/utils"; import { getAllDelegationCredentialsForUser } from "@calcom/app-store/delegationCredential"; -import getInstallCountPerApp from "@calcom/lib/apps/getInstallCountPerApp"; +import { getAppFromSlug } from "@calcom/app-store/utils"; import type { UserAdminTeams } from "@calcom/features/users/repositories/UserRepository"; +import getInstallCountPerApp from "@calcom/lib/apps/getInstallCountPerApp"; import prisma, { safeAppSelect, safeCredentialSelect } from "@calcom/prisma"; import { userMetadata } from "@calcom/prisma/zod-utils"; import type { AppFrontendPayload as App } from "@calcom/types/App"; diff --git a/packages/app-store/_utils/installation.ts b/packages/app-store/_utils/installation.ts index 611155c637..96c4157d1c 100644 --- a/packages/app-store/_utils/installation.ts +++ b/packages/app-store/_utils/installation.ts @@ -1,5 +1,5 @@ -import { HttpError } from "@calcom/lib/http-error"; import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; +import { HttpError } from "@calcom/lib/http-error"; import prisma from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import type { UserProfile } from "@calcom/types/UserProfile"; diff --git a/packages/app-store/_utils/oauth/getCurrentTokenObject.ts b/packages/app-store/_utils/oauth/getCurrentTokenObject.ts index a19095f64d..419b622099 100644 --- a/packages/app-store/_utils/oauth/getCurrentTokenObject.ts +++ b/packages/app-store/_utils/oauth/getCurrentTokenObject.ts @@ -1,6 +1,6 @@ +import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; import { isInMemoryDelegationCredential } from "@calcom/lib/delegationCredential"; import logger from "@calcom/lib/logger"; -import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; import type { CredentialForCalendarService } from "@calcom/types/Credential"; import { getTokenObjectFromCredential } from "./getTokenObjectFromCredential"; diff --git a/packages/app-store/_utils/oauth/updateProfilePhotoGoogle.ts b/packages/app-store/_utils/oauth/updateProfilePhotoGoogle.ts index 7a70232c82..f21265e884 100644 --- a/packages/app-store/_utils/oauth/updateProfilePhotoGoogle.ts +++ b/packages/app-store/_utils/oauth/updateProfilePhotoGoogle.ts @@ -1,9 +1,9 @@ import { oauth2_v2 } from "@googleapis/oauth2"; import type { OAuth2Client } from "googleapis-common"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import logger from "@calcom/lib/logger"; import { uploadAvatar } from "@calcom/lib/server/avatar"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { resizeBase64Image } from "@calcom/lib/server/resizeBase64Image"; import prisma from "@calcom/prisma"; diff --git a/packages/app-store/_utils/oauth/updateTokenObject.ts b/packages/app-store/_utils/oauth/updateTokenObject.ts index 2ca29cd597..906fc84ddb 100644 --- a/packages/app-store/_utils/oauth/updateTokenObject.ts +++ b/packages/app-store/_utils/oauth/updateTokenObject.ts @@ -1,7 +1,7 @@ import type z from "zod"; -import logger from "@calcom/lib/logger"; import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; +import logger from "@calcom/lib/logger"; import { prisma } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; diff --git a/packages/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic.test.ts b/packages/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic.test.ts index 6310626a02..8d04bd7faa 100644 --- a/packages/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic.test.ts +++ b/packages/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic.test.ts @@ -1,12 +1,12 @@ import type { BaseWidget } from "react-awesome-query-builder"; import { describe, it, expect, vi, beforeEach } from "vitest"; -import { RouteActionType } from "@calcom/app-store/routing-forms/zod"; -import { RaqbLogicResult } from "@calcom/lib/raqb/evaluateRaqbLogic"; import { findTeamMembersMatchingAttributeLogic, TroubleshooterCase, } from "@calcom/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic"; +import { RouteActionType } from "@calcom/app-store/routing-forms/zod"; +import { RaqbLogicResult } from "@calcom/lib/raqb/evaluateRaqbLogic"; import * as getAttributesModule from "@calcom/lib/service/attribute/server/getAttributes"; import type { AttributeType } from "@calcom/prisma/enums"; import { RoutingFormFieldType } from "@calcom/routing-forms/lib/FieldTypes"; @@ -64,13 +64,13 @@ function mockAttributesScenario({ Object.entries(member.attributes).map(([attributeId, value]) => { return [ attributeId, - + { attributeOption: value instanceof Array ? value.map((value) => ({ value, isGroup: false, contains: [] })) : { value, isGroup: false, contains: [] }, - + type: attributes.find((attribute) => attribute.id === attributeId)!.type, }, ]; diff --git a/packages/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic.ts b/packages/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic.ts index 15de66d9ff..c306b30580 100644 --- a/packages/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic.ts +++ b/packages/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic.ts @@ -159,7 +159,7 @@ async function getLogicResultForAllMembers( attributesQueryValue, }); attributesDataPerUser.set(member.userId, attributesData); - const result = !!jsonLogic.apply(attributeJsonLogic as any, attributesData) + const result = jsonLogic.apply(attributeJsonLogic as any, attributesData) ? RaqbLogicResult.MATCH : RaqbLogicResult.NO_MATCH; diff --git a/packages/app-store/_utils/raqb/raqbUtils.test.ts b/packages/app-store/_utils/raqb/raqbUtils.test.ts index 98d4c5005d..e56f60d609 100644 --- a/packages/app-store/_utils/raqb/raqbUtils.test.ts +++ b/packages/app-store/_utils/raqb/raqbUtils.test.ts @@ -93,7 +93,7 @@ const createComplexQueryValue = ({ }>; }): AttributesQueryValue => { const children1: Record = {}; - + rules.forEach((rule) => { children1[rule.ruleId] = createQueryValueRule({ type: "rule", diff --git a/packages/app-store/_utils/throwIfNotHaveAdminAccessToTeam.ts b/packages/app-store/_utils/throwIfNotHaveAdminAccessToTeam.ts index 3313029e17..f02193023b 100644 --- a/packages/app-store/_utils/throwIfNotHaveAdminAccessToTeam.ts +++ b/packages/app-store/_utils/throwIfNotHaveAdminAccessToTeam.ts @@ -1,5 +1,5 @@ -import { HttpError } from "@calcom/lib/http-error"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; +import { HttpError } from "@calcom/lib/http-error"; import prisma from "@calcom/prisma"; export const throwIfNotHaveAdminAccessToTeam = async ({ diff --git a/packages/app-store/dailyvideo/lib/VideoApiAdapter.ts b/packages/app-store/dailyvideo/lib/VideoApiAdapter.ts index 79c7b187c2..a82104a996 100644 --- a/packages/app-store/dailyvideo/lib/VideoApiAdapter.ts +++ b/packages/app-store/dailyvideo/lib/VideoApiAdapter.ts @@ -172,7 +172,7 @@ export const updateMeetingTokenIfExpired = async ({ try { await fetcher(`/meeting-tokens/${meetingToken}`).then(ZGetMeetingTokenResponseSchema.parse); - } catch (err) { + } catch { const organizerMeetingToken = await postToDailyAPI("/meeting-tokens", { properties: { room_name: roomName, @@ -426,7 +426,7 @@ const DailyVideoApiAdapter = (): VideoApiAdapter => { getRecordingsResponseSchema.parse ); return Promise.resolve(res); - } catch (err) { + } catch { throw new Error("Something went wrong! Unable to get recording"); } }, diff --git a/packages/app-store/delegationCredential.ts b/packages/app-store/delegationCredential.ts index b0bdefb1bf..4b984641db 100644 --- a/packages/app-store/delegationCredential.ts +++ b/packages/app-store/delegationCredential.ts @@ -3,6 +3,10 @@ import { metadata as googleCalendarMetadata } from "@calcom/app-store/googlecale import { metadata as googleMeetMetadata } from "@calcom/app-store/googlevideo/_metadata"; import { metadata as office365CalendarMetaData } from "@calcom/app-store/office365calendar/_metadata"; import { metadata as office365VideoMetaData } from "@calcom/app-store/office365video/_metadata"; +import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; +import type { ServiceAccountKey } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository"; +import { DelegationCredentialRepository } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { buildNonDelegationCredential, buildNonDelegationCredentials, @@ -10,10 +14,6 @@ import { } from "@calcom/lib/delegationCredential"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; -import type { ServiceAccountKey } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository"; -import { DelegationCredentialRepository } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { prisma } from "@calcom/prisma"; import type { SelectedCalendar } from "@calcom/prisma/client"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; diff --git a/packages/app-store/dub/lib/AnalyticsService.ts b/packages/app-store/dub/lib/AnalyticsService.ts index 71fd037a8b..1c8846cf92 100644 --- a/packages/app-store/dub/lib/AnalyticsService.ts +++ b/packages/app-store/dub/lib/AnalyticsService.ts @@ -1,7 +1,7 @@ import { Dub } from "dub-package"; -import logger from "@calcom/lib/logger"; import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; +import logger from "@calcom/lib/logger"; import type { AnalyticsService, SendEventProps } from "@calcom/types/AnalyticsService"; import type { CredentialPayload } from "@calcom/types/Credential"; diff --git a/packages/app-store/googlecalendar/api/callback.ts b/packages/app-store/googlecalendar/api/callback.ts index 283841c6b5..80ecd5ff00 100644 --- a/packages/app-store/googlecalendar/api/callback.ts +++ b/packages/app-store/googlecalendar/api/callback.ts @@ -3,6 +3,7 @@ import { OAuth2Client } from "googleapis-common"; import type { NextApiRequest, NextApiResponse } from "next"; import GoogleCalendarService from "@calcom/app-store/googlecalendar/lib/CalendarService"; +import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; import { renewSelectedCalendarCredentialId } from "@calcom/lib/connectedCalendar"; import { GOOGLE_CALENDAR_SCOPES, @@ -14,7 +15,6 @@ import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl"; import { HttpError } from "@calcom/lib/http-error"; import { defaultHandler } from "@calcom/lib/server/defaultHandler"; import { defaultResponder } from "@calcom/lib/server/defaultResponder"; -import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; import { Prisma } from "@calcom/prisma/client"; import getInstalledAppPath from "../../_utils/getInstalledAppPath"; diff --git a/packages/app-store/googlecalendar/tests/testUtils.ts b/packages/app-store/googlecalendar/tests/testUtils.ts index c7960fd3bd..b51d61640f 100644 --- a/packages/app-store/googlecalendar/tests/testUtils.ts +++ b/packages/app-store/googlecalendar/tests/testUtils.ts @@ -1,3 +1,4 @@ +import { calendar_v3 } from "@googleapis/calendar"; import type { Page } from "@playwright/test"; import { expect } from "@playwright/test"; @@ -29,7 +30,7 @@ export const createBookingAndFetchGCalEvent = async ( await page.locator("[data-testid=success-page]"); const bookingUrl = await page.url(); - const bookingUid = bookingUrl.match(/booking\/([^\/?]+)/); + const bookingUid = bookingUrl.match(/booking\/([^/?]+)/); assertValueExists(bookingUid, "bookingUid"); const [gCalReference, booking] = await Promise.all([ @@ -40,6 +41,7 @@ export const createBookingAndFetchGCalEvent = async ( }, type: metadata.type, credentialId: qaGCalCredential?.id, + deleted: null, }, select: { uid: true, @@ -107,7 +109,7 @@ export const createBookingAndFetchGCalEvent = async ( }; export const deleteBookingAndEvent = async ( - authedCalendar: any, + authedCalendar: calendar_v3.Calendar, bookingUid: string, gCalReferenceUid?: string ) => { diff --git a/packages/app-store/routing-forms/lib/formSubmissionUtils.ts b/packages/app-store/routing-forms/lib/formSubmissionUtils.ts index b05b86816c..0c2e8172b0 100644 --- a/packages/app-store/routing-forms/lib/formSubmissionUtils.ts +++ b/packages/app-store/routing-forms/lib/formSubmissionUtils.ts @@ -1,4 +1,5 @@ import dayjs from "@calcom/dayjs"; +import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import type { Tasker } from "@calcom/features/tasker/tasker"; import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks"; import { sendGenericWebhookPayload } from "@calcom/features/webhooks/lib/sendPayload"; @@ -6,7 +7,6 @@ import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId"; import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; import { withReporting } from "@calcom/lib/sentryWrapper"; -import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import { prisma } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import type { App_RoutingForms_Form, User } from "@calcom/prisma/client"; diff --git a/packages/app-store/routing-forms/lib/handleResponse.ts b/packages/app-store/routing-forms/lib/handleResponse.ts index c331f024bf..b8731e3fb3 100644 --- a/packages/app-store/routing-forms/lib/handleResponse.ts +++ b/packages/app-store/routing-forms/lib/handleResponse.ts @@ -1,9 +1,9 @@ import { z } from "zod"; +import { findTeamMembersMatchingAttributeLogic } from "@calcom/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic"; import { emailSchema } from "@calcom/lib/emailSchema"; import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; -import { findTeamMembersMatchingAttributeLogic } from "@calcom/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic"; import { safeStringify } from "@calcom/lib/safeStringify"; import { withReporting } from "@calcom/lib/sentryWrapper"; import { RoutingFormResponseRepository } from "@calcom/lib/server/repository/formResponse"; diff --git a/packages/app-store/salesforce/lib/CrmService.ts b/packages/app-store/salesforce/lib/CrmService.ts index 8efb084fac..447b6603e4 100644 --- a/packages/app-store/salesforce/lib/CrmService.ts +++ b/packages/app-store/salesforce/lib/CrmService.ts @@ -741,6 +741,7 @@ export default class SalesforceCRMService implements CRM { booking: { uid: bookingUid, }, + deleted: null, }, }); diff --git a/packages/app-store/stripepayment/api/__tests__/portal.test.ts b/packages/app-store/stripepayment/api/__tests__/portal.test.ts index 5d9880ce12..4a3a29253e 100644 --- a/packages/app-store/stripepayment/api/__tests__/portal.test.ts +++ b/packages/app-store/stripepayment/api/__tests__/portal.test.ts @@ -2,9 +2,9 @@ import type { NextApiRequest } from "next"; import type { Session } from "next-auth"; import { describe, it, expect, vi, beforeEach } from "vitest"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { WEBAPP_URL } from "@calcom/lib/constants"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { MembershipRole } from "@calcom/prisma/enums"; import { @@ -54,7 +54,7 @@ describe("Portal API - Service-Based Architecture", () => { user: { id: 123 }, hasValidLicense: true, upId: "test-upid", - expires: "2024-12-31T23:59:59.999Z" + expires: "2024-12-31T23:59:59.999Z", } as Session, } as RequestWithSession; @@ -77,7 +77,7 @@ describe("Portal API - Service-Based Architecture", () => { user: {} as any, hasValidLicense: true, upId: "test-upid", - expires: "2024-12-31T23:59:59.999Z" + expires: "2024-12-31T23:59:59.999Z", } as Session, } as RequestWithSession; diff --git a/packages/app-store/stripepayment/lib/PaymentService.ts b/packages/app-store/stripepayment/lib/PaymentService.ts index 676dc0195f..0e48dc560a 100644 --- a/packages/app-store/stripepayment/lib/PaymentService.ts +++ b/packages/app-store/stripepayment/lib/PaymentService.ts @@ -3,12 +3,12 @@ import { v4 as uuidv4 } from "uuid"; import z from "zod"; import { sendAwaitingPaymentEmailAndSMS } from "@calcom/emails"; +import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { getErrorFromUnknown } from "@calcom/lib/errors"; import { ErrorWithCode } from "@calcom/lib/errors"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import prisma from "@calcom/prisma"; import type { Booking, Payment, PaymentOption, Prisma } from "@calcom/prisma/client"; import type { EventTypeMetadata } from "@calcom/prisma/zod-utils"; diff --git a/packages/app-store/stripepayment/lib/services/base/BillingPortalService.ts b/packages/app-store/stripepayment/lib/services/base/BillingPortalService.ts index 4b92f57697..9f3ade6b73 100644 --- a/packages/app-store/stripepayment/lib/services/base/BillingPortalService.ts +++ b/packages/app-store/stripepayment/lib/services/base/BillingPortalService.ts @@ -1,10 +1,10 @@ import type { NextApiResponse } from "next"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl"; import logger from "@calcom/lib/logger"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import prisma from "@calcom/prisma"; import stripe from "../../server"; diff --git a/packages/app-store/utils.ts b/packages/app-store/utils.ts index 57f86594f9..f0675f4995 100644 --- a/packages/app-store/utils.ts +++ b/packages/app-store/utils.ts @@ -57,7 +57,7 @@ function getApps(credentials: CredentialDataWithTeamName[], filterOnCredentials? const credential = { id: 0, type: appMeta.type, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + key: appMeta.key!, userId: 0, user: { email: "" }, diff --git a/packages/app-store/vital/lib/reschedule.ts b/packages/app-store/vital/lib/reschedule.ts index 99df75be2d..f29ceab2cf 100644 --- a/packages/app-store/vital/lib/reschedule.ts +++ b/packages/app-store/vital/lib/reschedule.ts @@ -2,11 +2,11 @@ import type { TFunction } from "i18next"; import dayjs from "@calcom/dayjs"; import { sendRequestRescheduleEmailAndSMS } from "@calcom/emails"; +import { deleteMeeting } from "@calcom/features/conferencing/lib/videoClient"; import { CalendarEventBuilder } from "@calcom/lib/builders/CalendarEvent/builder"; import { CalendarEventDirector } from "@calcom/lib/builders/CalendarEvent/director"; import logger from "@calcom/lib/logger"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { deleteMeeting } from "@calcom/features/conferencing/lib/videoClient"; import prisma from "@calcom/prisma"; import type { Booking, BookingReference, User } from "@calcom/prisma/client"; import { BookingStatus } from "@calcom/prisma/enums"; @@ -119,7 +119,7 @@ const Reschedule = async (bookingUid: string, cancellationReason: string) => { ), organizer: userOwnerAsPeopleType, hideOrganizerEmail: bookingToReschedule.eventType?.hideOrganizerEmail, - team: !!bookingToReschedule.eventType?.team + team: bookingToReschedule.eventType?.team ? { name: bookingToReschedule.eventType.team.name, id: bookingToReschedule.eventType.team.id, diff --git a/packages/app-store/wipemycalother/lib/reschedule.ts b/packages/app-store/wipemycalother/lib/reschedule.ts index fe05984d65..95303b8925 100644 --- a/packages/app-store/wipemycalother/lib/reschedule.ts +++ b/packages/app-store/wipemycalother/lib/reschedule.ts @@ -2,11 +2,11 @@ import type { TFunction } from "i18next"; import dayjs from "@calcom/dayjs"; import { sendRequestRescheduleEmailAndSMS } from "@calcom/emails"; +import { deleteMeeting } from "@calcom/features/conferencing/lib/videoClient"; import { CalendarEventBuilder } from "@calcom/lib/builders/CalendarEvent/builder"; import { CalendarEventDirector } from "@calcom/lib/builders/CalendarEvent/director"; import logger from "@calcom/lib/logger"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { deleteMeeting } from "@calcom/features/conferencing/lib/videoClient"; import prisma from "@calcom/prisma"; import type { Booking, BookingReference, User } from "@calcom/prisma/client"; import { BookingStatus } from "@calcom/prisma/enums"; @@ -122,7 +122,7 @@ const Reschedule = async (bookingUid: string, cancellationReason: string) => { ), organizer: userOwnerAsPeopleType, hideOrganizerEmail: bookingToReschedule.eventType?.hideOrganizerEmail, - team: !!bookingToReschedule.eventType?.team + team: bookingToReschedule.eventType?.team ? { name: bookingToReschedule.eventType.team.name, id: bookingToReschedule.eventType.team.id, diff --git a/packages/features/Segment.tsx b/packages/features/Segment.tsx index 4e822000c3..65491ba444 100644 --- a/packages/features/Segment.tsx +++ b/packages/features/Segment.tsx @@ -5,6 +5,7 @@ import { Query, Builder, Utils as QbUtils } from "react-awesome-query-builder"; import type { ImmutableTree, BuilderProps } from "react-awesome-query-builder"; import type { JsonTree } from "react-awesome-query-builder"; +import { buildStateFromQueryValue } from "@calcom/app-store/_utils/raqb/raqbUtils"; import { withRaqbSettingsAndWidgets, ConfigFor, @@ -12,7 +13,6 @@ import { import { getQueryBuilderConfigForAttributes } from "@calcom/app-store/routing-forms/lib/getQueryBuilderConfig"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { isEqual } from "@calcom/lib/isEqual"; -import { buildStateFromQueryValue } from "@calcom/app-store/_utils/raqb/raqbUtils"; import type { AttributesQueryValue } from "@calcom/lib/raqb/types"; import { trpc, type RouterOutputs } from "@calcom/trpc"; import cn from "@calcom/ui/classNames"; diff --git a/packages/features/apps/components/AllApps.tsx b/packages/features/apps/components/AllApps.tsx index ff3c579d4e..5f1af6ebd5 100644 --- a/packages/features/apps/components/AllApps.tsx +++ b/packages/features/apps/components/AllApps.tsx @@ -4,8 +4,8 @@ import { useAutoAnimate } from "@formkit/auto-animate/react"; import type { UIEvent } from "react"; import { useEffect, useRef, useState } from "react"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { UserAdminTeams } from "@calcom/features/users/repositories/UserRepository"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { AppCategories } from "@calcom/prisma/client"; import type { AppFrontendPayload as App } from "@calcom/types/App"; import type { CredentialFrontendPayload as Credential } from "@calcom/types/Credential"; diff --git a/packages/features/apps/components/AppCard.tsx b/packages/features/apps/components/AppCard.tsx index 7c0351626c..d908739bc6 100644 --- a/packages/features/apps/components/AppCard.tsx +++ b/packages/features/apps/components/AppCard.tsx @@ -7,11 +7,12 @@ import { InstallAppButton } from "@calcom/app-store/InstallAppButton"; import { isRedirectApp } from "@calcom/app-store/_utils/redirectApps"; import useAddAppMutation from "@calcom/app-store/_utils/useAddAppMutation"; import { doesAppSupportTeamInstall, isConferencing } from "@calcom/app-store/utils"; +import type { UserAdminTeams } from "@calcom/features/users/repositories/UserRepository"; import { AppOnboardingSteps } from "@calcom/lib/apps/appOnboardingSteps"; import { getAppOnboardingUrl } from "@calcom/lib/apps/getAppOnboardingUrl"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; -import type { UserAdminTeams } from "@calcom/features/users/repositories/UserRepository"; +import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; import type { AppFrontendPayload as App } from "@calcom/types/App"; import type { CredentialFrontendPayload as Credential } from "@calcom/types/Credential"; import classNames from "@calcom/ui/classNames"; @@ -19,7 +20,6 @@ import { Badge } from "@calcom/ui/components/badge"; import { Button } from "@calcom/ui/components/button"; import type { ButtonProps } from "@calcom/ui/components/button"; import { showToast } from "@calcom/ui/components/toast"; -import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; interface AppCardProps { app: App; @@ -120,14 +120,14 @@ export function AppCard({ app, credentials, searchText, userAdminTeams }: AppCar
*/}

+ }} + />

{t("dont_want_to_wait")}
-
+
{disabled ? ( diff --git a/packages/features/bookings/Booker/components/OutOfOfficeInSlots.tsx b/packages/features/bookings/Booker/components/OutOfOfficeInSlots.tsx index a0fa7d76a1..6a7d90dd12 100644 --- a/packages/features/bookings/Booker/components/OutOfOfficeInSlots.tsx +++ b/packages/features/bookings/Booker/components/OutOfOfficeInSlots.tsx @@ -1,7 +1,7 @@ import { useRouter } from "next/navigation"; -import ServerTrans from "@calcom/lib/components/ServerTrans"; import type { IOutOfOfficeData } from "@calcom/features/availability/lib/getUserAvailability"; +import ServerTrans from "@calcom/lib/components/ServerTrans"; import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import classNames from "@calcom/ui/classNames"; diff --git a/packages/features/bookings/Booker/components/hooks/useBookings.ts b/packages/features/bookings/Booker/components/hooks/useBookings.ts index 87915e4b62..37095979b7 100644 --- a/packages/features/bookings/Booker/components/hooks/useBookings.ts +++ b/packages/features/bookings/Booker/components/hooks/useBookings.ts @@ -18,7 +18,6 @@ import { createRecurringBooking } from "@calcom/features/bookings/lib/create-rec import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking"; import type { BookerEvent } from "@calcom/features/bookings/types"; import { getFullName } from "@calcom/features/form-builder/utils"; -import { useBookingSuccessRedirect } from "../../../lib/bookingSuccessRedirect"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { localStorage } from "@calcom/lib/webstorage"; @@ -27,6 +26,7 @@ import { bookingMetadataSchema } from "@calcom/prisma/zod-utils"; import { trpc } from "@calcom/trpc"; import { showToast } from "@calcom/ui/components/toast"; +import { useBookingSuccessRedirect } from "../../../lib/bookingSuccessRedirect"; import type { UseBookingFormReturnType } from "./useBookingForm"; export interface IUseBookings { diff --git a/packages/features/bookings/Booker/components/hooks/useDecoyBooking.ts b/packages/features/bookings/Booker/components/hooks/useDecoyBooking.ts index 39356f04ba..483a52d007 100644 --- a/packages/features/bookings/Booker/components/hooks/useDecoyBooking.ts +++ b/packages/features/bookings/Booker/components/hooks/useDecoyBooking.ts @@ -28,4 +28,3 @@ export function useDecoyBooking(uid: string) { return bookingData; } - diff --git a/packages/features/bookings/components/AvailableTimes.tsx b/packages/features/bookings/components/AvailableTimes.tsx index bb58f211c7..3d2094da45 100644 --- a/packages/features/bookings/components/AvailableTimes.tsx +++ b/packages/features/bookings/components/AvailableTimes.tsx @@ -6,12 +6,12 @@ import { useMemo } from "react"; import { getPaymentAppData } from "@calcom/app-store/_utils/payments/getPaymentAppData"; import { useIsPlatform } from "@calcom/atoms/hooks/useIsPlatform"; import dayjs from "@calcom/dayjs"; +import type { IOutOfOfficeData } from "@calcom/features/availability/lib/getUserAvailability"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; import { OutOfOfficeInSlots } from "@calcom/features/bookings/Booker/components/OutOfOfficeInSlots"; import type { IUseBookingLoadingStates } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; import type { BookerEvent } from "@calcom/features/bookings/types"; import type { Slot } from "@calcom/features/schedules/lib/use-schedule/types"; -import type { IOutOfOfficeData } from "@calcom/features/availability/lib/getUserAvailability"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { localStorage } from "@calcom/lib/webstorage"; import classNames from "@calcom/ui/classNames"; diff --git a/packages/features/bookings/di/RecurringBookingService.module.ts b/packages/features/bookings/di/RecurringBookingService.module.ts index 4217d73306..c6846da3f3 100644 --- a/packages/features/bookings/di/RecurringBookingService.module.ts +++ b/packages/features/bookings/di/RecurringBookingService.module.ts @@ -1,5 +1,4 @@ import { RecurringBookingService } from "@calcom/features/bookings/lib/service/RecurringBookingService"; - import { createModule, bindModuleToClassOnToken } from "@calcom/features/di/di"; import { DI_TOKENS } from "@calcom/features/di/tokens"; diff --git a/packages/features/bookings/di/RegularBookingService.module.ts b/packages/features/bookings/di/RegularBookingService.module.ts index db8b56c5e5..e338f753c6 100644 --- a/packages/features/bookings/di/RegularBookingService.module.ts +++ b/packages/features/bookings/di/RegularBookingService.module.ts @@ -1,10 +1,8 @@ - import { RegularBookingService } from "@calcom/features/bookings/lib/service/RegularBookingService"; import { bindModuleToClassOnToken, createModule } from "@calcom/features/di/di"; import { moduleLoader as bookingRepositoryModuleLoader } from "@calcom/features/di/modules/Booking"; import { moduleLoader as cacheModuleLoader } from "@calcom/features/di/modules/Cache"; import { moduleLoader as checkBookingAndDurationLimitsModuleLoader } from "@calcom/features/di/modules/CheckBookingAndDurationLimits"; - import { moduleLoader as luckyUserServiceModuleLoader } from "@calcom/features/di/modules/LuckyUser"; import { moduleLoader as userRepositoryModuleLoader } from "@calcom/features/di/modules/User"; import { DI_TOKENS } from "@calcom/features/di/tokens"; diff --git a/packages/features/bookings/lib/EventManager.ts b/packages/features/bookings/lib/EventManager.ts index fe254500a2..eda5cf027e 100644 --- a/packages/features/bookings/lib/EventManager.ts +++ b/packages/features/bookings/lib/EventManager.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line no-restricted-imports import { cloneDeep, merge } from "lodash"; import { v5 as uuidv5 } from "uuid"; import type { z } from "zod"; @@ -10,6 +9,7 @@ import { getLocationFromApp, MeetLocationType, MSTeamsLocationType } from "@calc import getApps from "@calcom/app-store/utils"; import { createEvent, updateEvent, deleteEvent } from "@calcom/features/calendars/lib/CalendarManager"; import { createMeeting, updateMeeting, deleteMeeting } from "@calcom/features/conferencing/lib/videoClient"; +import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; import CrmManager from "@calcom/features/crmManager/crmManager"; import CRMScheduler from "@calcom/features/crmManager/crmScheduler"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; @@ -24,7 +24,6 @@ import { getPiiFreeCalendarEvent, } from "@calcom/lib/piiFreeData"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; import { prisma } from "@calcom/prisma"; import type { DestinationCalendar, BookingReference } from "@calcom/prisma/client"; import { createdEventSchema } from "@calcom/prisma/zod-utils"; diff --git a/packages/features/bookings/lib/bookingSuccessRedirect.test.ts b/packages/features/bookings/lib/bookingSuccessRedirect.test.ts index 9ab1da7932..9efdef3351 100644 --- a/packages/features/bookings/lib/bookingSuccessRedirect.test.ts +++ b/packages/features/bookings/lib/bookingSuccessRedirect.test.ts @@ -33,15 +33,7 @@ const WEBAPP_PARAMS = ["overlayCalendar"]; // Helper function to create a mock booking with sensible defaults type MockBooking = Pick< BookingResponse, - | "uid" - | "title" - | "description" - | "startTime" - | "endTime" - | "location" - | "attendees" - | "user" - | "responses" + "uid" | "title" | "description" | "startTime" | "endTime" | "location" | "attendees" | "user" | "responses" >; const createMockBooking = (overrides: Partial = {}): MockBooking => ({ diff --git a/packages/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials.ts b/packages/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials.ts index 90cc769326..6ed2b690c2 100644 --- a/packages/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials.ts +++ b/packages/features/bookings/lib/getAllCredentialsForUsersOnEvent/getAllCredentials.ts @@ -1,7 +1,7 @@ import type { z } from "zod"; -import { eventTypeAppMetadataOptionalSchema } from "@calcom/app-store/zod-utils"; import { enrichUserWithDelegationCredentialsIncludeServiceAccountKey } from "@calcom/app-store/delegationCredential"; +import { eventTypeAppMetadataOptionalSchema } from "@calcom/app-store/zod-utils"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import prisma from "@calcom/prisma"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; diff --git a/packages/features/bookings/lib/getAllCredentialsForUsersOnEvent/refreshCredentials.ts b/packages/features/bookings/lib/getAllCredentialsForUsersOnEvent/refreshCredentials.ts index e132c26c67..87f5a2e4e7 100644 --- a/packages/features/bookings/lib/getAllCredentialsForUsersOnEvent/refreshCredentials.ts +++ b/packages/features/bookings/lib/getAllCredentialsForUsersOnEvent/refreshCredentials.ts @@ -1,7 +1,7 @@ import async from "async"; -import { isDelegationCredential } from "@calcom/lib/delegationCredential"; import { buildAllCredentials } from "@calcom/app-store/delegationCredential"; +import { isDelegationCredential } from "@calcom/lib/delegationCredential"; import { withReporting } from "@calcom/lib/sentryWrapper"; import type { CredentialForCalendarService } from "@calcom/types/Credential"; diff --git a/packages/features/bookings/lib/getBookingFields.ts b/packages/features/bookings/lib/getBookingFields.ts index d3639ecda0..b572cb797c 100644 --- a/packages/features/bookings/lib/getBookingFields.ts +++ b/packages/features/bookings/lib/getBookingFields.ts @@ -1,12 +1,9 @@ import type { z } from "zod"; -import { - SMS_REMINDER_NUMBER_FIELD, - CAL_AI_AGENT_PHONE_NUMBER_FIELD, -} from "@calcom/lib/bookings/SystemField"; import type { Workflow } from "@calcom/features/ee/workflows/lib/types"; import { fieldsThatSupportLabelAsSafeHtml } from "@calcom/features/form-builder/fieldsThatSupportLabelAsSafeHtml"; import { getFieldIdentifier } from "@calcom/features/form-builder/utils/getFieldIdentifier"; +import { SMS_REMINDER_NUMBER_FIELD, CAL_AI_AGENT_PHONE_NUMBER_FIELD } from "@calcom/lib/bookings/SystemField"; import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; import slugify from "@calcom/lib/slugify"; import type { EventTypeCustomInput, EventType } from "@calcom/prisma/client"; diff --git a/packages/features/bookings/lib/getCalEventResponses.ts b/packages/features/bookings/lib/getCalEventResponses.ts index 14fe2a7665..a34e9dc91b 100644 --- a/packages/features/bookings/lib/getCalEventResponses.ts +++ b/packages/features/bookings/lib/getCalEventResponses.ts @@ -1,7 +1,7 @@ import type z from "zod"; -import { SystemField } from "@calcom/lib/bookings/SystemField"; import type { bookingResponsesDbSchema } from "@calcom/features/bookings/lib/getBookingResponsesSchema"; +import { SystemField } from "@calcom/lib/bookings/SystemField"; import { contructEmailFromPhoneNumber } from "@calcom/lib/contructEmailFromPhoneNumber"; import { getBookingWithResponses } from "@calcom/lib/getBooking"; import { HttpError } from "@calcom/lib/http-error"; @@ -47,7 +47,7 @@ export const getCalEventResponses = ({ if (!backwardCompatibleResponses) throw new Error("Couldn't get responses"); // To set placeholder email for the booking - if (!!!backwardCompatibleResponses.email) { + if (!backwardCompatibleResponses.email) { if (typeof backwardCompatibleResponses["attendeePhoneNumber"] !== "string") { log.error(`backwardCompatibleResponses: ${JSON.stringify(backwardCompatibleResponses)}`, { responses, diff --git a/packages/features/bookings/lib/getLuckyUser.ts b/packages/features/bookings/lib/getLuckyUser.ts index ceb7a27540..8d6c75d8bc 100644 --- a/packages/features/bookings/lib/getLuckyUser.ts +++ b/packages/features/bookings/lib/getLuckyUser.ts @@ -2,16 +2,16 @@ import { acrossQueryValueCompatiblity } from "@calcom/app-store/_utils/raqb/raqb import type { FormResponse, Fields } from "@calcom/app-store/routing-forms/types/types"; import { zodRoutes } from "@calcom/app-store/routing-forms/zod"; import dayjs from "@calcom/dayjs"; +import type { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import { getBusyCalendarTimes } from "@calcom/features/calendars/lib/CalendarManager"; import { mergeOverlappingRanges } from "@calcom/features/schedules/lib/date-ranges"; +import type { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import logger from "@calcom/lib/logger"; import { raqbQueryValueSchema } from "@calcom/lib/raqb/zod"; import { safeStringify } from "@calcom/lib/safeStringify"; import type { PrismaAttributeRepository } from "@calcom/lib/server/repository/PrismaAttributeRepository"; -import type { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import type { HostRepository } from "@calcom/lib/server/repository/host"; import type { PrismaOOORepository } from "@calcom/lib/server/repository/ooo"; -import type { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import type { Prisma } from "@calcom/prisma/client"; import type { User, Booking, SelectedCalendar } from "@calcom/prisma/client"; import type { AttributeType } from "@calcom/prisma/enums"; diff --git a/packages/features/bookings/lib/handleBookingRequested.ts b/packages/features/bookings/lib/handleBookingRequested.ts index d9813ce6f9..c1f66a3ab1 100644 --- a/packages/features/bookings/lib/handleBookingRequested.ts +++ b/packages/features/bookings/lib/handleBookingRequested.ts @@ -1,12 +1,12 @@ import { sendAttendeeRequestEmailAndSMS, sendOrganizerRequestEmail } from "@calcom/emails"; import { getWebhookPayloadForBooking } from "@calcom/features/bookings/lib/getWebhookPayloadForBooking"; +import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import type { Workflow } from "@calcom/features/ee/workflows/lib/types"; import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks"; import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload"; import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import type { Prisma } from "@calcom/prisma/client"; import { WebhookTriggerEvents, WorkflowTriggerEvents } from "@calcom/prisma/enums"; import type { EventTypeMetadata } from "@calcom/prisma/zod-utils"; diff --git a/packages/features/bookings/lib/handleCancelBooking.ts b/packages/features/bookings/lib/handleCancelBooking.ts index 71cfd3a9f7..6b24bb913c 100644 --- a/packages/features/bookings/lib/handleCancelBooking.ts +++ b/packages/features/bookings/lib/handleCancelBooking.ts @@ -524,10 +524,11 @@ async function handler(input: CancelBookingInput) { await eventManager.cancelEvent(evt, bookingToDelete.references, isBookingInRecurringSeries); - await prisma.bookingReference.deleteMany({ + await prisma.bookingReference.updateMany({ where: { bookingId: bookingToDelete.id, }, + data: { deleted: true }, }); } catch (error) { log.error(`Error deleting integrations`, safeStringify({ error })); diff --git a/packages/features/bookings/lib/handleConfirmation.ts b/packages/features/bookings/lib/handleConfirmation.ts index 91a59dd71f..839f773511 100644 --- a/packages/features/bookings/lib/handleConfirmation.ts +++ b/packages/features/bookings/lib/handleConfirmation.ts @@ -1,24 +1,24 @@ import { eventTypeAppMetadataOptionalSchema } from "@calcom/app-store/zod-utils"; import { scheduleMandatoryReminder } from "@calcom/ee/workflows/lib/reminders/scheduleMandatoryReminder"; import { sendScheduledEmailsAndSMS } from "@calcom/emails"; +import type { EventManagerUser } from "@calcom/features/bookings/lib/EventManager"; +import EventManager, { placeholderCreatedEvent } from "@calcom/features/bookings/lib/EventManager"; +import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import { allowDisablingAttendeeConfirmationEmails, allowDisablingHostConfirmationEmails, } from "@calcom/features/ee/workflows/lib/allowDisablingStandardEmails"; +import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import type { Workflow } from "@calcom/features/ee/workflows/lib/types"; import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks"; import { scheduleTrigger } from "@calcom/features/webhooks/lib/scheduleTrigger"; import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload"; import type { EventPayloadType, EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload"; import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser"; -import type { EventManagerUser } from "@calcom/features/bookings/lib/EventManager"; -import EventManager, { placeholderCreatedEvent } from "@calcom/features/bookings/lib/EventManager"; -import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId"; import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import type { PrismaClient } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import type { SchedulingType } from "@calcom/prisma/enums"; diff --git a/packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts b/packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts index 504d962466..a9a2fc39da 100644 --- a/packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts +++ b/packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts @@ -1,7 +1,7 @@ import dayjs from "@calcom/dayjs"; -import type { IntervalLimit } from "@calcom/lib/intervalLimits/intervalLimitSchema"; import type { CheckBookingLimitsService } from "@calcom/features/bookings/lib/checkBookingLimits"; import { checkDurationLimits } from "@calcom/features/bookings/lib/checkDurationLimits"; +import type { IntervalLimit } from "@calcom/lib/intervalLimits/intervalLimitSchema"; import { withReporting } from "@calcom/lib/sentryWrapper"; import type { NewBookingEventType } from "./getEventTypesFromDB"; diff --git a/packages/features/bookings/lib/handleNewBooking/ensureAvailableUsers.ts b/packages/features/bookings/lib/handleNewBooking/ensureAvailableUsers.ts index 57f6fe6090..a667994f4a 100644 --- a/packages/features/bookings/lib/handleNewBooking/ensureAvailableUsers.ts +++ b/packages/features/bookings/lib/handleNewBooking/ensureAvailableUsers.ts @@ -3,9 +3,9 @@ import type { Logger } from "tslog"; import dayjs from "@calcom/dayjs"; import type { Dayjs } from "@calcom/dayjs"; import { checkForConflicts } from "@calcom/features/bookings/lib/conflictChecker/checkForConflicts"; -import { buildDateRanges } from "@calcom/features/schedules/lib/date-ranges"; import { getBusyTimesService } from "@calcom/features/di/containers/BusyTimes"; import { getUserAvailabilityService } from "@calcom/features/di/containers/GetUserAvailability"; +import { buildDateRanges } from "@calcom/features/schedules/lib/date-ranges"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { parseBookingLimit } from "@calcom/lib/intervalLimits/isBookingLimits"; import { parseDurationLimit } from "@calcom/lib/intervalLimits/isDurationLimits"; diff --git a/packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts b/packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts index 26394861bf..b7646ce77f 100644 --- a/packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts +++ b/packages/features/bookings/lib/handleNewBooking/getEventTypesFromDB.ts @@ -2,9 +2,9 @@ import type { LocationObject } from "@calcom/app-store/locations"; import { workflowSelect } from "@calcom/ee/workflows/lib/getAllWorkflows"; import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/getBookingFields"; import type { DefaultEvent } from "@calcom/features/eventtypes/lib/defaultEvents"; +import { withSelectedCalendars } from "@calcom/features/users/repositories/UserRepository"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent"; -import { withSelectedCalendars } from "@calcom/features/users/repositories/UserRepository"; import { prisma } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; diff --git a/packages/features/bookings/lib/handleNewBooking/loadAndValidateUsers.ts b/packages/features/bookings/lib/handleNewBooking/loadAndValidateUsers.ts index bb9f1d4767..ff28f88ee0 100644 --- a/packages/features/bookings/lib/handleNewBooking/loadAndValidateUsers.ts +++ b/packages/features/bookings/lib/handleNewBooking/loadAndValidateUsers.ts @@ -3,6 +3,7 @@ import type { Logger } from "tslog"; import { enrichUsersWithDelegationCredentials } from "@calcom/app-store/delegationCredential"; import type { RoutingFormResponse } from "@calcom/features/bookings/lib/getLuckyUser"; import { getQualifiedHostsService } from "@calcom/features/di/containers/QualifiedHosts"; +import { withSelectedCalendars } from "@calcom/features/users/repositories/UserRepository"; import { sentrySpan } from "@calcom/features/watchlist/lib/telemetry"; import { checkIfUsersAreBlocked } from "@calcom/features/watchlist/operations/check-if-users-are-blocked.controller"; import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId"; @@ -10,7 +11,6 @@ import { HttpError } from "@calcom/lib/http-error"; import { getPiiFreeUser } from "@calcom/lib/piiFreeData"; import { safeStringify } from "@calcom/lib/safeStringify"; import { withReporting } from "@calcom/lib/sentryWrapper"; -import { withSelectedCalendars } from "@calcom/features/users/repositories/UserRepository"; import { userSelect } from "@calcom/prisma"; import prisma from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; diff --git a/packages/features/bookings/lib/handleNewBooking/loadUsers.ts b/packages/features/bookings/lib/handleNewBooking/loadUsers.ts index d52794c67f..004d3ac21d 100644 --- a/packages/features/bookings/lib/handleNewBooking/loadUsers.ts +++ b/packages/features/bookings/lib/handleNewBooking/loadUsers.ts @@ -4,10 +4,10 @@ import { findMatchingHostsWithEventSegment, getNormalizedHosts, } from "@calcom/features/users/lib/getRoutedUsers"; +import { withSelectedCalendars, UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { withSelectedCalendars, UserRepository } from "@calcom/features/users/repositories/UserRepository"; import prisma, { userSelect } from "@calcom/prisma"; import { Prisma } from "@calcom/prisma/client"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; @@ -100,7 +100,7 @@ const loadDynamicUsers = async (dynamicUserList: string[], currentOrgDomain: str } return findUsersByUsername({ usernameList: dynamicUserList, - orgSlug: !!currentOrgDomain ? currentOrgDomain : null, + orgSlug: currentOrgDomain ? currentOrgDomain : null, }); }; diff --git a/packages/features/bookings/lib/handleNewBooking/originalRescheduledBookingUtils.ts b/packages/features/bookings/lib/handleNewBooking/originalRescheduledBookingUtils.ts index 96efeebe6a..abebfe9c7a 100644 --- a/packages/features/bookings/lib/handleNewBooking/originalRescheduledBookingUtils.ts +++ b/packages/features/bookings/lib/handleNewBooking/originalRescheduledBookingUtils.ts @@ -1,9 +1,8 @@ +import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { HttpError } from "@calcom/lib/http-error"; -import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; -import type { Prisma } from "@calcom/prisma/client"; -import { BookingStatus } from "@calcom/prisma/enums"; import prisma from "@calcom/prisma"; +import { BookingStatus } from "@calcom/prisma/enums"; // TODO: Inject. export async function getOriginalRescheduledBooking(uid: string, seatsEventType?: boolean) { @@ -21,6 +20,5 @@ export async function getOriginalRescheduledBooking(uid: string, seatsEventType? return originalBooking; } -export type BookingType = Prisma.PromiseReturnType | null; - +export type BookingType = Awaited> | null; export type OriginalRescheduledBooking = Awaited> | null; diff --git a/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts b/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts index 26a9e577ca..2f0b2877a5 100644 --- a/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts +++ b/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts @@ -149,16 +149,18 @@ describe("handleNewBooking", () => { organizer, apps: [TestData.apps["google-calendar"], TestData.apps["daily-video"]], }, - org?.organization ? { - ...org.organization, - profileUsername: "username-in-org" - } : null + org?.organization + ? { + ...org.organization, + profileUsername: "username-in-org", + } + : null ) ); const orgProfiles = await prismaMock.profile.findMany({ where: { - organizationId: org?.organization.id, + organizationId: org?.organization.id ?? undefined, }, }); const orgProfile = orgProfiles[0]; @@ -257,8 +259,7 @@ describe("handleNewBooking", () => { booker, organizer: { ...organizer, - ...(orgProfile?.username ? - { usernameInOrg: orgProfile?.username } : null), + ...(orgProfile?.username ? { usernameInOrg: orgProfile?.username } : null), }, location: BookingLocations.CalVideo, subscriberUrl: "http://my-webhook.example.com", diff --git a/packages/features/bookings/lib/handleSeats/handleSeats.ts b/packages/features/bookings/lib/handleSeats/handleSeats.ts index 3473da579c..f424fb560a 100644 --- a/packages/features/bookings/lib/handleSeats/handleSeats.ts +++ b/packages/features/bookings/lib/handleSeats/handleSeats.ts @@ -1,10 +1,10 @@ -// eslint-disable-next-line no-restricted-imports + import dayjs from "@calcom/dayjs"; import { handleWebhookTrigger } from "@calcom/features/bookings/lib/handleWebhookTrigger"; +import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import type { EventPayloadType } from "@calcom/features/webhooks/lib/sendPayload"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { HttpError } from "@calcom/lib/http-error"; -import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import prisma from "@calcom/prisma"; import { BookingStatus } from "@calcom/prisma/enums"; diff --git a/packages/features/bookings/lib/handleSeats/lib/lastAttendeeDeleteBooking.ts b/packages/features/bookings/lib/handleSeats/lib/lastAttendeeDeleteBooking.ts index 1d50c02c8d..b7e68415b0 100644 --- a/packages/features/bookings/lib/handleSeats/lib/lastAttendeeDeleteBooking.ts +++ b/packages/features/bookings/lib/handleSeats/lib/lastAttendeeDeleteBooking.ts @@ -1,4 +1,4 @@ -// eslint-disable-next-line no-restricted-imports + import { getCalendar } from "@calcom/app-store/_utils/getCalendar"; import { getAllDelegationCredentialsForUserIncludeServiceAccountKey } from "@calcom/app-store/delegationCredential"; import { getDelegationCredentialOrFindRegularCredential } from "@calcom/app-store/delegationCredential"; diff --git a/packages/features/bookings/lib/host-filtering/filterHostsByLeadThreshold.ts b/packages/features/bookings/lib/host-filtering/filterHostsByLeadThreshold.ts index be3be96f6d..5d10129e9f 100644 --- a/packages/features/bookings/lib/host-filtering/filterHostsByLeadThreshold.ts +++ b/packages/features/bookings/lib/host-filtering/filterHostsByLeadThreshold.ts @@ -1,6 +1,6 @@ +import type { LuckyUserService, RoutingFormResponse } from "@calcom/features/bookings/lib/getLuckyUser"; import { getLuckyUserService } from "@calcom/features/di/containers/LuckyUser"; import logger from "@calcom/lib/logger"; -import type { LuckyUserService, RoutingFormResponse } from "@calcom/features/bookings/lib/getLuckyUser"; import type { RRResetInterval, SelectedCalendar } from "@calcom/prisma/client"; import { RRTimestampBasis } from "@calcom/prisma/enums"; import type { CredentialForCalendarService } from "@calcom/types/Credential"; diff --git a/packages/features/bookings/lib/host-filtering/filterHostsBySameRoundRobinHost.ts b/packages/features/bookings/lib/host-filtering/filterHostsBySameRoundRobinHost.ts index 587c37836d..398f5b9a4a 100644 --- a/packages/features/bookings/lib/host-filtering/filterHostsBySameRoundRobinHost.ts +++ b/packages/features/bookings/lib/host-filtering/filterHostsBySameRoundRobinHost.ts @@ -1,5 +1,5 @@ -import { isRerouting } from "@calcom/lib/bookings/routing/utils"; import type { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; +import { isRerouting } from "@calcom/lib/bookings/routing/utils"; export interface IFilterHostsService { bookingRepo: BookingRepository; diff --git a/packages/features/bookings/lib/host-filtering/findQualifiedHostsWithDelegationCredentials.ts b/packages/features/bookings/lib/host-filtering/findQualifiedHostsWithDelegationCredentials.ts index 27483c327c..7bffec2a18 100644 --- a/packages/features/bookings/lib/host-filtering/findQualifiedHostsWithDelegationCredentials.ts +++ b/packages/features/bookings/lib/host-filtering/findQualifiedHostsWithDelegationCredentials.ts @@ -1,11 +1,11 @@ +import type { RoutingFormResponse } from "@calcom/features/bookings/lib/getLuckyUser"; +import type { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import { findMatchingHostsWithEventSegment, getNormalizedHostsWithDelegationCredentials, } from "@calcom/features/users/lib/getRoutedUsers"; import type { EventType } from "@calcom/features/users/lib/getRoutedUsers"; import { withReporting } from "@calcom/lib/sentryWrapper"; -import type { RoutingFormResponse } from "@calcom/features/bookings/lib/getLuckyUser"; -import type { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import type { SelectedCalendar } from "@calcom/prisma/client"; import type { SchedulingType } from "@calcom/prisma/enums"; import type { CredentialForCalendarService, CredentialPayload } from "@calcom/types/Credential"; diff --git a/packages/features/bookings/lib/payment/getBooking.ts b/packages/features/bookings/lib/payment/getBooking.ts index 004f57d484..b1917a3469 100644 --- a/packages/features/bookings/lib/payment/getBooking.ts +++ b/packages/features/bookings/lib/payment/getBooking.ts @@ -1,6 +1,6 @@ +import { enrichUserWithDelegationCredentials } from "@calcom/app-store/delegationCredential"; import { workflowSelect } from "@calcom/ee/workflows/lib/getAllWorkflows"; import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses"; -import { enrichUserWithDelegationCredentials } from "@calcom/app-store/delegationCredential"; import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import { HttpError as HttpCode } from "@calcom/lib/http-error"; import { isPrismaObjOrUndefined } from "@calcom/lib/isPrismaObj"; diff --git a/packages/features/bookings/lib/payment/handleNoShowFee.test.ts b/packages/features/bookings/lib/payment/handleNoShowFee.test.ts index e2a9537a3c..abd9901e96 100644 --- a/packages/features/bookings/lib/payment/handleNoShowFee.test.ts +++ b/packages/features/bookings/lib/payment/handleNoShowFee.test.ts @@ -1,14 +1,13 @@ import { describe, expect, it, vi, beforeEach } from "vitest"; - import { PaymentServiceMap } from "@calcom/app-store/payment.services.generated"; import { sendNoShowFeeChargedEmail } from "@calcom/emails"; +import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { ErrorWithCode } from "@calcom/lib/errors"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { handleNoShowFee } from "./handleNoShowFee"; diff --git a/packages/features/bookings/lib/payment/handleNoShowFee.ts b/packages/features/bookings/lib/payment/handleNoShowFee.ts index 3725ba224b..bae0636869 100644 --- a/packages/features/bookings/lib/payment/handleNoShowFee.ts +++ b/packages/features/bookings/lib/payment/handleNoShowFee.ts @@ -1,15 +1,14 @@ -// eslint-disable-next-line import { PaymentServiceMap } from "@calcom/app-store/payment.services.generated"; import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/app-store/zod-utils"; import dayjs from "@calcom/dayjs"; import { sendNoShowFeeChargedEmail } from "@calcom/emails"; +import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { ErrorCode } from "@calcom/lib/errorCodes"; import { ErrorWithCode } from "@calcom/lib/errors"; import logger from "@calcom/lib/logger"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import prisma from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import type { CalendarEvent } from "@calcom/types/Calendar"; diff --git a/packages/features/bookings/lib/payment/processNoShowFeeOnCancellation.ts b/packages/features/bookings/lib/payment/processNoShowFeeOnCancellation.ts index 9015d72af5..151aa7256a 100644 --- a/packages/features/bookings/lib/payment/processNoShowFeeOnCancellation.ts +++ b/packages/features/bookings/lib/payment/processNoShowFeeOnCancellation.ts @@ -1,6 +1,6 @@ import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/app-store/zod-utils"; -import logger from "@calcom/lib/logger"; import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import logger from "@calcom/lib/logger"; import type { Payment } from "@calcom/prisma/client"; import { MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/features/bookings/lib/service/InstantBookingCreateService.test.ts b/packages/features/bookings/lib/service/InstantBookingCreateService.test.ts index 34080a43a8..45827697d8 100644 --- a/packages/features/bookings/lib/service/InstantBookingCreateService.test.ts +++ b/packages/features/bookings/lib/service/InstantBookingCreateService.test.ts @@ -13,10 +13,11 @@ import { import { describe, it, expect, vi, beforeEach } from "vitest"; -import type { CreateInstantBookingData } from "../dto/types"; -import { getInstantBookingCreateService } from "../../di/InstantBookingCreateService.container"; import { BookingStatus } from "@calcom/prisma/enums"; +import { getInstantBookingCreateService } from "../../di/InstantBookingCreateService.container"; +import type { CreateInstantBookingData } from "../dto/types"; + vi.mock("@calcom/features/notifications/sendNotification", () => ({ sendNotification: vi.fn(), })); diff --git a/packages/features/bookings/lib/service/RegularBookingService.ts b/packages/features/bookings/lib/service/RegularBookingService.ts index b2465a1999..ac071a6563 100644 --- a/packages/features/bookings/lib/service/RegularBookingService.ts +++ b/packages/features/bookings/lib/service/RegularBookingService.ts @@ -1,6 +1,6 @@ import short, { uuid } from "short-uuid"; import { v5 as uuidv5 } from "uuid"; -import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; + import processExternalId from "@calcom/app-store/_utils/calendars/processExternalId"; import { getPaymentAppData } from "@calcom/app-store/_utils/payments/getPaymentAppData"; import { @@ -23,7 +23,6 @@ import { scheduleMandatoryReminder } from "@calcom/ee/workflows/lib/reminders/sc import getICalUID from "@calcom/emails/lib/getICalUID"; import { CalendarEventBuilder } from "@calcom/features/CalendarEventBuilder"; import EventManager, { placeholderCreatedEvent } from "@calcom/features/bookings/lib/EventManager"; -import type { CheckBookingLimitsService } from "@calcom/features/bookings/lib/checkBookingLimits"; import type { BookingDataSchemaGetter } from "@calcom/features/bookings/lib/dto/types"; import type { CreateRegularBookingData, @@ -38,10 +37,13 @@ import type { CacheService } from "@calcom/features/calendar-cache/lib/getShould import { getSpamCheckService } from "@calcom/features/di/watchlist/containers/SpamCheckService.container"; import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import AssignmentReasonRecorder from "@calcom/features/ee/round-robin/assignmentReason/AssignmentReasonRecorder"; +import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import { WorkflowRepository } from "@calcom/features/ee/workflows/repositories/WorkflowRepository"; import { getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents"; import { getEventName, updateHostInEventName } from "@calcom/features/eventtypes/lib/eventNaming"; import { getFullName } from "@calcom/features/form-builder/utils"; +import { HashedLinkService } from "@calcom/features/hashedLink/services/hashedLinkService"; +import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import { handleAnalyticsEvents } from "@calcom/features/tasker/tasks/analytics/handleAnalyticsEvents"; import type { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { UsersRepository } from "@calcom/features/users/users.repository"; @@ -57,8 +59,6 @@ import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser"; import { groupHostsByGroupId } from "@calcom/lib/bookings/hostGroupUtils"; import { shouldIgnoreContactOwner } from "@calcom/lib/bookings/routing/utils"; import { DEFAULT_GROUP_ID } from "@calcom/lib/constants"; -import type { BookingRepository } from "../../repositories/BookingRepository"; - import { ErrorCode } from "@calcom/lib/errorCodes"; import { getErrorFromUnknown, ErrorWithCode } from "@calcom/lib/errors"; import { extractBaseEmail } from "@calcom/lib/extract-base-email"; @@ -69,8 +69,6 @@ import logger from "@calcom/lib/logger"; import { getPiiFreeCalendarEvent, getPiiFreeEventType } from "@calcom/lib/piiFreeData"; import { safeStringify } from "@calcom/lib/safeStringify"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { HashedLinkService } from "@calcom/features/hashedLink/services/hashedLinkService"; -import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat"; import type { PrismaClient } from "@calcom/prisma"; import type { DestinationCalendar, Prisma, User, AssignmentReasonEnum } from "@calcom/prisma/client"; @@ -93,6 +91,7 @@ import type { import type { CredentialForCalendarService } from "@calcom/types/Credential"; import type { EventResult, PartialReference } from "@calcom/types/EventManager"; +import type { BookingRepository } from "../../repositories/BookingRepository"; import { BookingActionMap, BookingEmailSmsHandler } from "../BookingEmailSmsHandler"; import { getAllCredentialsIncludeServiceAccountKey } from "../getAllCredentialsForUsersOnEvent/getAllCredentials"; import { refreshCredentials } from "../getAllCredentialsForUsersOnEvent/refreshCredentials"; @@ -1255,9 +1254,9 @@ async function handler( // This ensures that createMeeting isn't called for static video apps as bookingLocation becomes just a regular value for them. const { bookingLocation, conferenceCredentialId } = organizerOrFirstDynamicGroupMemberDefaultLocationUrl ? { - bookingLocation: organizerOrFirstDynamicGroupMemberDefaultLocationUrl, - conferenceCredentialId: undefined, - } + bookingLocation: organizerOrFirstDynamicGroupMemberDefaultLocationUrl, + conferenceCredentialId: undefined, + } : getLocationValueForDB(locationBodyString, eventType.locations); log.info("locationBodyString", locationBodyString); @@ -1303,8 +1302,8 @@ async function handler( const destinationCalendar = eventType.destinationCalendar ? [eventType.destinationCalendar] : organizerUser.destinationCalendar - ? [organizerUser.destinationCalendar] - : null; + ? [organizerUser.destinationCalendar] + : null; let organizerEmail = organizerUser.email || "Email-less"; if (eventType.useEventTypeDestinationCalendarEmail && destinationCalendar?.[0]?.primaryEmail) { @@ -1646,7 +1645,8 @@ async function handler( const changedOrganizer = !!originalRescheduledBooking && - (eventType.schedulingType === SchedulingType.ROUND_ROBIN || eventType.schedulingType === SchedulingType.COLLECTIVE) && + (eventType.schedulingType === SchedulingType.ROUND_ROBIN || + eventType.schedulingType === SchedulingType.COLLECTIVE) && originalRescheduledBooking.userId !== evt.organizer.id; const skipDeleteEventsAndMeetings = changedOrganizer; @@ -1922,14 +1922,14 @@ async function handler( } const updateManager = !skipCalendarSyncTaskCreation ? await eventManager.reschedule( - evt, - originalRescheduledBooking.uid, - undefined, - changedOrganizer, - previousHostDestinationCalendar, - isBookingRequestedReschedule, - skipDeleteEventsAndMeetings - ) + evt, + originalRescheduledBooking.uid, + undefined, + changedOrganizer, + previousHostDestinationCalendar, + isBookingRequestedReschedule, + skipDeleteEventsAndMeetings + ) : placeholderCreatedEvent; // This gets overridden when updating the event - to check if notes have been hidden or not. We just reset this back // to the default description when we are sending the emails. @@ -2227,8 +2227,8 @@ async function handler( const metadata = videoCallUrl ? { - videoCallUrl: getVideoCallUrlFromCalEvent(evt) || videoCallUrl, - } + videoCallUrl: getVideoCallUrlFromCalEvent(evt) || videoCallUrl, + } : undefined; const webhookData: EventPayloadType = { @@ -2290,9 +2290,9 @@ async function handler( ...eventType, metadata: eventType.metadata ? { - ...eventType.metadata, - apps: eventType.metadata?.apps as Prisma.JsonValue, - } + ...eventType.metadata, + apps: eventType.metadata?.apps as Prisma.JsonValue, + } : {}, }, paymentAppCredentials: eventTypePaymentAppCredential as IEventTypePaymentCredentialType, @@ -2606,7 +2606,7 @@ async function handler( * We are open to renaming it to something more descriptive. */ export class RegularBookingService implements IBookingService { - constructor(private readonly deps: IBookingServiceDependencies) { } + constructor(private readonly deps: IBookingServiceDependencies) {} async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) { return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps); diff --git a/packages/features/bot-detection/BotDetectionService.test.ts b/packages/features/bot-detection/BotDetectionService.test.ts index fc164d8bdb..09c396c91e 100644 --- a/packages/features/bot-detection/BotDetectionService.test.ts +++ b/packages/features/bot-detection/BotDetectionService.test.ts @@ -1,9 +1,9 @@ import type { IncomingHttpHeaders } from "http"; import { beforeEach, describe, expect, it, vi } from "vitest"; +import type { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import type { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { HttpError } from "@calcom/lib/http-error"; -import type { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { BotDetectionService } from "./BotDetectionService"; diff --git a/packages/features/bot-detection/BotDetectionService.ts b/packages/features/bot-detection/BotDetectionService.ts index 33e4716859..2f8a871219 100644 --- a/packages/features/bot-detection/BotDetectionService.ts +++ b/packages/features/bot-detection/BotDetectionService.ts @@ -1,10 +1,10 @@ import { checkBotId } from "botid/server"; import type { IncomingHttpHeaders } from "http"; +import type { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import type { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; -import type { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; interface BotDetectionConfig { eventTypeId?: number; diff --git a/packages/features/busyTimes/services/getBusyTimes.ts b/packages/features/busyTimes/services/getBusyTimes.ts index 27fc99985f..04e83de9f5 100644 --- a/packages/features/busyTimes/services/getBusyTimes.ts +++ b/packages/features/busyTimes/services/getBusyTimes.ts @@ -1,4 +1,5 @@ import dayjs from "@calcom/dayjs"; +import type { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import { getBusyCalendarTimes } from "@calcom/features/calendars/lib/CalendarManager"; import { getDefinedBufferTimes } from "@calcom/features/eventtypes/lib/getDefinedBufferTimes"; import { subtract } from "@calcom/features/schedules/lib/date-ranges"; @@ -9,7 +10,6 @@ import logger from "@calcom/lib/logger"; import { getPiiFreeBooking } from "@calcom/lib/piiFreeData"; import { withReporting } from "@calcom/lib/sentryWrapper"; import { performance } from "@calcom/lib/server/perfObserver"; -import type { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import prisma from "@calcom/prisma"; import type { Booking, EventType } from "@calcom/prisma/client"; import type { Prisma } from "@calcom/prisma/client"; diff --git a/packages/features/calAIPhone/providers/adapters/PrismaAgentRepositoryAdapter.ts b/packages/features/calAIPhone/providers/adapters/PrismaAgentRepositoryAdapter.ts index ec3f958e64..101cdf397e 100644 --- a/packages/features/calAIPhone/providers/adapters/PrismaAgentRepositoryAdapter.ts +++ b/packages/features/calAIPhone/providers/adapters/PrismaAgentRepositoryAdapter.ts @@ -1,5 +1,6 @@ import { PrismaAgentRepository } from "@calcom/lib/server/repository/PrismaAgentRepository"; import prisma from "@calcom/prisma"; + import type { AgentRepositoryInterface, AgentData, diff --git a/packages/features/calAIPhone/providers/interfaces/PhoneNumberRepositoryInterface.ts b/packages/features/calAIPhone/providers/interfaces/PhoneNumberRepositoryInterface.ts index 0aef238b49..a6108ae05d 100644 --- a/packages/features/calAIPhone/providers/interfaces/PhoneNumberRepositoryInterface.ts +++ b/packages/features/calAIPhone/providers/interfaces/PhoneNumberRepositoryInterface.ts @@ -83,7 +83,9 @@ export interface PhoneNumberRepositoryInterface { /** * Find inbound agent by phone number ID */ - findInboundAgentIdByPhoneNumberId(params: { phoneNumberId: number }): Promise<{ inboundAgentId: string | null } | null>; + findInboundAgentIdByPhoneNumberId(params: { + phoneNumberId: number; + }): Promise<{ inboundAgentId: string | null } | null>; } /** diff --git a/packages/features/calAIPhone/providers/retellAI/RetellAIService.test.ts b/packages/features/calAIPhone/providers/retellAI/RetellAIService.test.ts index 87c77bf719..3a52833e8e 100644 --- a/packages/features/calAIPhone/providers/retellAI/RetellAIService.test.ts +++ b/packages/features/calAIPhone/providers/retellAI/RetellAIService.test.ts @@ -11,7 +11,6 @@ import { RetellAIError } from "./errors"; import { createMockDatabaseAgent } from "./services/__tests__/test-utils"; import type { RetellAIRepository } from "./types"; - vi.mock("@calcom/app-store/stripepayment/lib/customer", () => ({ getStripeCustomerIdFromUserId: vi.fn(), })); diff --git a/packages/features/calAIPhone/providers/retellAI/RetellSDKClient.ts b/packages/features/calAIPhone/providers/retellAI/RetellSDKClient.ts index eed22b5b61..415c209f3b 100644 --- a/packages/features/calAIPhone/providers/retellAI/RetellSDKClient.ts +++ b/packages/features/calAIPhone/providers/retellAI/RetellSDKClient.ts @@ -273,7 +273,6 @@ export class RetellSDKClient implements RetellAIRepository { } async listVoices(): Promise { - try { const response = await this.client.voice.list(); diff --git a/packages/features/calendar-cache/calendar-cache.ts b/packages/features/calendar-cache/calendar-cache.ts index 2ca45693a7..2ae881f5e6 100644 --- a/packages/features/calendar-cache/calendar-cache.ts +++ b/packages/features/calendar-cache/calendar-cache.ts @@ -1,6 +1,6 @@ import { getCalendar } from "@calcom/app-store/_utils/getCalendar"; -import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { getCredentialForCalendarCache } from "@calcom/app-store/delegationCredential"; +import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import prisma from "@calcom/prisma"; diff --git a/packages/features/calendar-subscription/lib/sync/CalendarSyncService.ts b/packages/features/calendar-subscription/lib/sync/CalendarSyncService.ts index e283cc403f..2a2aff77f3 100644 --- a/packages/features/calendar-subscription/lib/sync/CalendarSyncService.ts +++ b/packages/features/calendar-subscription/lib/sync/CalendarSyncService.ts @@ -1,6 +1,6 @@ +import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import type { CalendarSubscriptionEventItem } from "@calcom/features/calendar-subscription/lib/CalendarSubscriptionPort.interface"; import logger from "@calcom/lib/logger"; -import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; import type { SelectedCalendar } from "@calcom/prisma/client"; const log = logger.getSubLogger({ prefix: ["CalendarSyncService"] }); diff --git a/packages/features/calendars/DatePicker.tsx b/packages/features/calendars/DatePicker.tsx index d5c2b8bccf..f68fa64d31 100644 --- a/packages/features/calendars/DatePicker.tsx +++ b/packages/features/calendars/DatePicker.tsx @@ -4,10 +4,10 @@ import { shallow } from "zustand/shallow"; import type { Dayjs } from "@calcom/dayjs"; import dayjs from "@calcom/dayjs"; import { useEmbedStyles } from "@calcom/embed-core/embed-iframe"; +import type { IFromUser, IToUser } from "@calcom/features/availability/lib/getUserAvailability"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; import { getAvailableDatesInMonth } from "@calcom/features/calendars/lib/getAvailableDatesInMonth"; import { daysInMonth, yyyymmdd } from "@calcom/lib/dayjs"; -import type { IFromUser, IToUser } from "@calcom/features/availability/lib/getUserAvailability"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { weekdayNames } from "@calcom/lib/weekday"; import type { PeriodData } from "@calcom/types/Event"; diff --git a/packages/features/calendars/lib/CalendarManager.ts b/packages/features/calendars/lib/CalendarManager.ts index d677806a00..7fdeb2dde0 100644 --- a/packages/features/calendars/lib/CalendarManager.ts +++ b/packages/features/calendars/lib/CalendarManager.ts @@ -1,4 +1,4 @@ -// eslint-disable-next-line no-restricted-imports + import { sortBy } from "lodash"; import { getCalendar } from "@calcom/app-store/_utils/getCalendar"; diff --git a/packages/features/calendars/lib/getConnectedDestinationCalendars.ts b/packages/features/calendars/lib/getConnectedDestinationCalendars.ts index 518e8e6a7a..5a2f339672 100644 --- a/packages/features/calendars/lib/getConnectedDestinationCalendars.ts +++ b/packages/features/calendars/lib/getConnectedDestinationCalendars.ts @@ -3,10 +3,10 @@ import { getCalendarCredentials, getConnectedCalendars, } from "@calcom/features/calendars/lib/CalendarManager"; +import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { isDelegationCredential } from "@calcom/lib/delegationCredential"; import logger from "@calcom/lib/logger"; import { DestinationCalendarRepository } from "@calcom/lib/server/repository/destinationCalendar"; -import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { SelectedCalendarRepository } from "@calcom/lib/server/repository/selectedCalendar"; import type { PrismaClient } from "@calcom/prisma"; import prisma from "@calcom/prisma"; diff --git a/packages/features/credentials/deleteCredential.test.ts b/packages/features/credentials/deleteCredential.test.ts index d2618056ef..f57fd9f917 100644 --- a/packages/features/credentials/deleteCredential.test.ts +++ b/packages/features/credentials/deleteCredential.test.ts @@ -7,9 +7,9 @@ import { describe, test, expect, beforeEach } from "vitest"; import { PrismaAppRepository } from "@calcom/features/apps/repository/PrismaAppRepository"; import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; -import { DestinationCalendarRepository } from "@calcom/lib/server/repository/destinationCalendar"; import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; +import { DestinationCalendarRepository } from "@calcom/lib/server/repository/destinationCalendar"; import prisma from "@calcom/prisma"; const testUser = { diff --git a/packages/features/credentials/handleDeleteCredential.integration-test.ts b/packages/features/credentials/handleDeleteCredential.integration-test.ts new file mode 100644 index 0000000000..5290da5f9f --- /dev/null +++ b/packages/features/credentials/handleDeleteCredential.integration-test.ts @@ -0,0 +1,462 @@ +import { describe, it, expect, beforeAll, afterAll, afterEach } from "vitest"; + +import handleDeleteCredential from "@calcom/features/credentials/handleDeleteCredential"; +import prisma from "@calcom/prisma"; +import type { Credential, EventType, User } from "@calcom/prisma/client"; +import { BookingStatus } from "@calcom/prisma/enums"; + +describe("handleDeleteCredential Integration Tests - BookingReference Soft Delete", () => { + let testUser: User; + let testCredential: Credential; + let testEventType: EventType; + const createdBookingReferenceIds: number[] = []; + const createdBookingIds: number[] = []; + + async function deleteCredentialWithMetadata(credentialId: number, userId: number) { + const user = await prisma.user.findUnique({ + where: { id: userId }, + select: { metadata: true }, + }); + + return handleDeleteCredential({ + userId, + userMetadata: user?.metadata ?? {}, + credentialId, + }); + } + + beforeAll(async () => { + testUser = await prisma.user.create({ + data: { + email: "delete-credential-test@example.com", + username: "delete-credential-test", + }, + }); + + testCredential = await prisma.credential.create({ + data: { + type: "stripe_payment", + key: { test_key: "test_value" }, + userId: testUser.id, + appId: "stripe", + }, + }); + + testEventType = await prisma.eventType.create({ + data: { + title: "Paid Event", + slug: "paid-event-test", + length: 30, + userId: testUser.id, + price: 1000, // $10 + currency: "usd", + }, + }); + }); + + afterEach(async () => { + if (createdBookingReferenceIds.length > 0) { + await prisma.bookingReference.deleteMany({ + where: { + id: { + in: createdBookingReferenceIds, + }, + }, + }); + createdBookingReferenceIds.splice(0, createdBookingReferenceIds.length); + } + + if (createdBookingIds.length > 0) { + await prisma.attendee.deleteMany({ + where: { + bookingId: { + in: createdBookingIds, + }, + }, + }); + + await prisma.booking.deleteMany({ + where: { + id: { + in: createdBookingIds, + }, + }, + }); + createdBookingIds.splice(0, createdBookingIds.length); + } + }); + + afterAll(async () => { + await prisma.eventType.delete({ + where: { + id: testEventType.id, + }, + }); + + try { + await prisma.credential.delete({ + where: { + id: testCredential.id, + }, + }); + } catch (error) { + // Credential already deleted by test + console.log("Credential deletion error:", error); + } + + await prisma.user.delete({ + where: { + id: testUser.id, + }, + }); + }); + + describe("Soft-delete bookingReferences when deleting payment credential", () => { + it("should soft-delete booking references for unpaid bookings when credential is deleted", async () => { + const unpaidBooking = await prisma.booking.create({ + data: { + uid: "unpaid-booking-uid-123", + title: "Unpaid Booking", + startTime: new Date(Date.now() + 86400000), // Tomorrow + endTime: new Date(Date.now() + 90000000), + userId: testUser.id, + eventTypeId: testEventType.id, + status: BookingStatus.PENDING, + paid: false, + attendees: { + create: [ + { + email: "attendee@test.com", + name: "Test Attendee", + timeZone: "America/New_York", + }, + ], + }, + }, + }); + createdBookingIds.push(unpaidBooking.id); + + const bookingRef1 = await prisma.bookingReference.create({ + data: { + type: "stripe_payment", + uid: "stripe-ref-123", + meetingId: "stripe-meeting-123", + credentialId: testCredential.id, + bookingId: unpaidBooking.id, + }, + }); + createdBookingReferenceIds.push(bookingRef1.id); + + const bookingRef2 = await prisma.bookingReference.create({ + data: { + type: "google_calendar", + uid: "gcal-ref-123", + meetingId: "gcal-meeting-123", + credentialId: testCredential.id, + bookingId: unpaidBooking.id, + }, + }); + createdBookingReferenceIds.push(bookingRef2.id); + + const refsBeforeDeletion = await prisma.bookingReference.findMany({ + where: { + bookingId: unpaidBooking.id, + }, + }); + expect(refsBeforeDeletion).toHaveLength(2); + expect(refsBeforeDeletion.every((ref) => ref.deleted === null)).toBe(true); + + await deleteCredentialWithMetadata(testCredential.id, testUser.id); + + const refsAfterDeletion = await prisma.bookingReference.findMany({ + where: { + bookingId: unpaidBooking.id, + }, + }); + + expect(refsAfterDeletion).toHaveLength(2); + expect(refsAfterDeletion.every((ref) => ref.deleted === true)).toBe(true); + + const cancelledBooking = await prisma.booking.findUnique({ + where: { id: unpaidBooking.id }, + }); + expect(cancelledBooking?.status).toBe(BookingStatus.CANCELLED); + }); + + it("should persist soft-deleted references in database", async () => { + const newCredential = await prisma.credential.create({ + data: { + type: "stripe_payment", + key: { test_key: "test_value" }, + userId: testUser.id, + appId: "stripe", + }, + }); + + const unpaidBooking = await prisma.booking.create({ + data: { + uid: "unpaid-booking-uid-456", + title: "Another Unpaid Booking", + startTime: new Date(Date.now() + 86400000), + endTime: new Date(Date.now() + 90000000), + userId: testUser.id, + eventTypeId: testEventType.id, + status: BookingStatus.PENDING, + paid: false, + attendees: { + create: [ + { + email: "attendee2@test.com", + name: "Test Attendee 2", + timeZone: "America/New_York", + }, + ], + }, + }, + }); + createdBookingIds.push(unpaidBooking.id); + + const bookingRef = await prisma.bookingReference.create({ + data: { + type: "stripe_payment", + uid: "stripe-ref-456", + meetingId: "stripe-meeting-456", + meetingUrl: "https://example.com/meeting", + credentialId: newCredential.id, + bookingId: unpaidBooking.id, + }, + }); + createdBookingReferenceIds.push(bookingRef.id); + + await deleteCredentialWithMetadata(newCredential.id, testUser.id); + + const deletedRef = await prisma.bookingReference.findUnique({ + where: { id: bookingRef.id }, + }); + + expect(deletedRef).toBeDefined(); + expect(deletedRef?.deleted).toBe(true); + expect(deletedRef?.uid).toBe("stripe-ref-456"); + expect(deletedRef?.meetingUrl).toBe("https://example.com/meeting"); + expect(deletedRef?.type).toBe("stripe_payment"); + }); + + it("should soft-delete references for multiple unpaid bookings when credential is deleted", async () => { + const newCredential = await prisma.credential.create({ + data: { + type: "stripe_payment", + key: { test_key: "test_value" }, + userId: testUser.id, + appId: "stripe", + }, + }); + + const booking1 = await prisma.booking.create({ + data: { + uid: "booking-1-uid", + title: "Booking 1", + startTime: new Date(Date.now() + 86400000), + endTime: new Date(Date.now() + 90000000), + userId: testUser.id, + eventTypeId: testEventType.id, + status: BookingStatus.PENDING, + paid: false, + attendees: { + create: [ + { + email: "attendee-b1@test.com", + name: "Attendee B1", + timeZone: "America/New_York", + }, + ], + }, + }, + }); + createdBookingIds.push(booking1.id); + + const booking2 = await prisma.booking.create({ + data: { + uid: "booking-2-uid", + title: "Booking 2", + startTime: new Date(Date.now() + 172800000), // 2 days from now + endTime: new Date(Date.now() + 176400000), + userId: testUser.id, + eventTypeId: testEventType.id, + status: BookingStatus.PENDING, + paid: false, + attendees: { + create: [ + { + email: "attendee-b2@test.com", + name: "Attendee B2", + timeZone: "America/New_York", + }, + ], + }, + }, + }); + createdBookingIds.push(booking2.id); + + const ref1 = await prisma.bookingReference.create({ + data: { + type: "stripe_payment", + uid: "stripe-ref-b1", + meetingId: "meeting-b1", + credentialId: newCredential.id, + bookingId: booking1.id, + }, + }); + createdBookingReferenceIds.push(ref1.id); + + const ref2 = await prisma.bookingReference.create({ + data: { + type: "stripe_payment", + uid: "stripe-ref-b2", + meetingId: "meeting-b2", + credentialId: newCredential.id, + bookingId: booking2.id, + }, + }); + createdBookingReferenceIds.push(ref2.id); + + await deleteCredentialWithMetadata(newCredential.id, testUser.id); + + const allRefsAfter = await prisma.bookingReference.findMany({ + where: { + id: { + in: [ref1.id, ref2.id], + }, + }, + }); + + expect(allRefsAfter).toHaveLength(2); + expect(allRefsAfter.every((ref) => ref.deleted === true)).toBe(true); + }); + + it("should not affect references of paid bookings when credential is deleted", async () => { + const newCredential = await prisma.credential.create({ + data: { + type: "stripe_payment", + key: { test_key: "test_value" }, + userId: testUser.id, + appId: "stripe", + }, + }); + + const paidBooking = await prisma.booking.create({ + data: { + uid: "paid-booking-uid", + title: "Paid Booking", + startTime: new Date(Date.now() + 86400000), + endTime: new Date(Date.now() + 90000000), + userId: testUser.id, + eventTypeId: testEventType.id, + status: BookingStatus.ACCEPTED, + paid: true, + attendees: { + create: [ + { + email: "paid-attendee@test.com", + name: "Paid Attendee", + timeZone: "America/New_York", + }, + ], + }, + }, + }); + createdBookingIds.push(paidBooking.id); + + const paidBookingRef = await prisma.bookingReference.create({ + data: { + type: "stripe_payment", + uid: "stripe-paid-ref", + meetingId: "stripe-paid-meeting", + credentialId: newCredential.id, + bookingId: paidBooking.id, + }, + }); + createdBookingReferenceIds.push(paidBookingRef.id); + + await deleteCredentialWithMetadata(newCredential.id, testUser.id); + + const refAfter = await prisma.bookingReference.findUnique({ + where: { id: paidBookingRef.id }, + }); + + expect(refAfter).toBeDefined(); + expect(refAfter?.deleted).toBe(null); + + const bookingAfter = await prisma.booking.findUnique({ + where: { id: paidBooking.id }, + }); + expect(bookingAfter?.status).toBe(BookingStatus.ACCEPTED); + }); + }); + + describe("Soft-delete behavior with queries after credential deletion", () => { + it("should exclude soft-deleted references from regular queries", async () => { + const newCredential = await prisma.credential.create({ + data: { + type: "stripe_payment", + key: { test_key: "test_value" }, + userId: testUser.id, + appId: "stripe", + }, + }); + + const unpaidBooking = await prisma.booking.create({ + data: { + uid: "query-test-booking-uid", + title: "Query Test Booking", + startTime: new Date(Date.now() + 86400000), + endTime: new Date(Date.now() + 90000000), + userId: testUser.id, + eventTypeId: testEventType.id, + status: BookingStatus.PENDING, + paid: false, + attendees: { + create: [ + { + email: "query-test@test.com", + name: "Query Test", + timeZone: "America/New_York", + }, + ], + }, + }, + }); + createdBookingIds.push(unpaidBooking.id); + + const ref = await prisma.bookingReference.create({ + data: { + type: "stripe_payment", + uid: "query-test-ref", + meetingId: "query-test-meeting", + credentialId: newCredential.id, + bookingId: unpaidBooking.id, + }, + }); + createdBookingReferenceIds.push(ref.id); + + await deleteCredentialWithMetadata(newCredential.id, testUser.id); + + const activeRefs = await prisma.bookingReference.findMany({ + where: { + bookingId: unpaidBooking.id, + deleted: null, + }, + }); + + expect(activeRefs).toHaveLength(0); + + const allRefs = await prisma.bookingReference.findMany({ + where: { + bookingId: unpaidBooking.id, + }, + }); + + expect(allRefs).toHaveLength(1); + expect(allRefs[0].deleted).toBe(true); + }); + }); +}); diff --git a/packages/features/credentials/handleDeleteCredential.ts b/packages/features/credentials/handleDeleteCredential.ts index dd58639ac8..b8787fd758 100644 --- a/packages/features/credentials/handleDeleteCredential.ts +++ b/packages/features/credentials/handleDeleteCredential.ts @@ -298,10 +298,11 @@ const handleDeleteCredential = async ({ }, }); - await prisma.bookingReference.deleteMany({ + await prisma.bookingReference.updateMany({ where: { bookingId: booking.id, }, + data: { deleted: true }, }); const attendeesListPromises = booking.attendees.map(async (attendee) => { diff --git a/packages/features/data-table/components/filters/ColumnVisibilityButton.tsx b/packages/features/data-table/components/filters/ColumnVisibilityButton.tsx index 1ccff683b9..c25894b97f 100644 --- a/packages/features/data-table/components/filters/ColumnVisibilityButton.tsx +++ b/packages/features/data-table/components/filters/ColumnVisibilityButton.tsx @@ -1,7 +1,7 @@ "use client"; import { type Table } from "@tanstack/react-table"; -// eslint-disable-next-line no-restricted-imports + import { forwardRef, useState } from "react"; import { useLocale } from "@calcom/lib/hooks/useLocale"; @@ -82,7 +82,7 @@ function ColumnVisibilityButtonComponent( }} className={classNames( buttonClasses({ color: "secondary" }), - "w-full justify-center text-center cursor-pointer mt-0" + "mt-0 w-full cursor-pointer justify-center text-center" )}> {t("show_all_columns")} diff --git a/packages/features/di/containers/AvailableSlots.ts b/packages/features/di/containers/AvailableSlots.ts index 4ddfd5b240..7ce09436e2 100644 --- a/packages/features/di/containers/AvailableSlots.ts +++ b/packages/features/di/containers/AvailableSlots.ts @@ -1,5 +1,5 @@ -import { redisModule } from "@calcom/features/redis/di/redisModule"; import { DI_TOKENS } from "@calcom/features/di/tokens"; +import { redisModule } from "@calcom/features/redis/di/redisModule"; import { prismaModule } from "@calcom/prisma/prisma.module"; import type { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util"; diff --git a/packages/features/di/containers/BookingLimits.ts b/packages/features/di/containers/BookingLimits.ts index 9aafc5e4df..e2d1f39d7e 100644 --- a/packages/features/di/containers/BookingLimits.ts +++ b/packages/features/di/containers/BookingLimits.ts @@ -1,5 +1,5 @@ -import { DI_TOKENS } from "@calcom/features/di/tokens"; import type { CheckBookingLimitsService } from "@calcom/features/bookings/lib/checkBookingLimits"; +import { DI_TOKENS } from "@calcom/features/di/tokens"; import { prismaModule } from "@calcom/prisma/prisma.module"; import type { CheckBookingAndDurationLimitsService } from "../../bookings/lib/handleNewBooking/checkBookingAndDurationLimits"; diff --git a/packages/features/di/containers/GetUserAvailability.ts b/packages/features/di/containers/GetUserAvailability.ts index a56890ea1e..6545f546cb 100644 --- a/packages/features/di/containers/GetUserAvailability.ts +++ b/packages/features/di/containers/GetUserAvailability.ts @@ -1,6 +1,6 @@ +import type { UserAvailabilityService } from "@calcom/features/availability/lib/getUserAvailability"; import { DI_TOKENS } from "@calcom/features/di/tokens"; import { redisModule } from "@calcom/features/redis/di/redisModule"; -import type { UserAvailabilityService } from "@calcom/features/availability/lib/getUserAvailability"; import { prismaModule } from "@calcom/prisma/prisma.module"; import { createContainer } from "../di"; diff --git a/packages/features/di/containers/NoSlotsNotification.ts b/packages/features/di/containers/NoSlotsNotification.ts index 6e909c42b9..8ffac5ace4 100644 --- a/packages/features/di/containers/NoSlotsNotification.ts +++ b/packages/features/di/containers/NoSlotsNotification.ts @@ -1,5 +1,5 @@ -import { redisModule } from "@calcom/features/redis/di/redisModule"; import { DI_TOKENS } from "@calcom/features/di/tokens"; +import { redisModule } from "@calcom/features/redis/di/redisModule"; import { prismaModule } from "@calcom/prisma/prisma.module"; import type { NoSlotsNotificationService } from "@calcom/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots"; diff --git a/packages/features/di/modules/Booking.ts b/packages/features/di/modules/Booking.ts index a1033f48a5..c2905fdbe6 100644 --- a/packages/features/di/modules/Booking.ts +++ b/packages/features/di/modules/Booking.ts @@ -1,5 +1,5 @@ -import { DI_TOKENS } from "@calcom/features/di/tokens"; import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; +import { DI_TOKENS } from "@calcom/features/di/tokens"; import { type Container, createModule } from "../di"; diff --git a/packages/features/di/modules/Cache.ts b/packages/features/di/modules/Cache.ts index dcb213c035..422aa4d4f8 100644 --- a/packages/features/di/modules/Cache.ts +++ b/packages/features/di/modules/Cache.ts @@ -1,7 +1,9 @@ import { CacheService } from "@calcom/features/calendar-cache/lib/getShouldServeCache"; + import { createModule, bindModuleToClassOnToken, type ModuleLoader } from "../di"; import { DI_TOKENS } from "../tokens"; import { moduleLoader as featuresRepositoryModuleLoader } from "./Features"; + export const cacheModule = createModule(); const token = DI_TOKENS.CACHE_SERVICE; const moduleToken = DI_TOKENS.CACHE_SERVICE_MODULE; diff --git a/packages/features/di/modules/CheckBookingAndDurationLimits.ts b/packages/features/di/modules/CheckBookingAndDurationLimits.ts index ced47d7df7..c2ea5d884b 100644 --- a/packages/features/di/modules/CheckBookingAndDurationLimits.ts +++ b/packages/features/di/modules/CheckBookingAndDurationLimits.ts @@ -1,4 +1,3 @@ - import { CheckBookingAndDurationLimitsService } from "@calcom/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits"; import { createModule, bindModuleToClassOnToken, type ModuleLoader } from "../di"; diff --git a/packages/features/di/modules/CheckBookingLimits.ts b/packages/features/di/modules/CheckBookingLimits.ts index 1dc5ae2731..eb6ba29c22 100644 --- a/packages/features/di/modules/CheckBookingLimits.ts +++ b/packages/features/di/modules/CheckBookingLimits.ts @@ -1,5 +1,5 @@ -import { DI_TOKENS } from "@calcom/features/di/tokens"; import { CheckBookingLimitsService } from "@calcom/features/bookings/lib/checkBookingLimits"; +import { DI_TOKENS } from "@calcom/features/di/tokens"; import { type Container, createModule } from "../di"; diff --git a/packages/features/di/modules/Features.ts b/packages/features/di/modules/Features.ts index 5207d3e0e3..f902098e52 100644 --- a/packages/features/di/modules/Features.ts +++ b/packages/features/di/modules/Features.ts @@ -1,5 +1,5 @@ -import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { DI_TOKENS } from "@calcom/features/di/tokens"; +import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { type Container, createModule } from "../di"; diff --git a/packages/features/di/modules/LuckyUser.ts b/packages/features/di/modules/LuckyUser.ts index 359b928af4..7ef9f35060 100644 --- a/packages/features/di/modules/LuckyUser.ts +++ b/packages/features/di/modules/LuckyUser.ts @@ -1,5 +1,5 @@ -import { DI_TOKENS } from "@calcom/features/di/tokens"; import { LuckyUserService } from "@calcom/features/bookings/lib/getLuckyUser"; +import { DI_TOKENS } from "@calcom/features/di/tokens"; import { bindModuleToClassOnToken, createModule, type ModuleLoader } from "../di"; import { moduleLoader as attributeRepositoryModuleLoader } from "./Attribute"; diff --git a/packages/features/di/watchlist/modules/Watchlist.module.ts b/packages/features/di/watchlist/modules/Watchlist.module.ts index 243c01eabb..5438e6e65c 100644 --- a/packages/features/di/watchlist/modules/Watchlist.module.ts +++ b/packages/features/di/watchlist/modules/Watchlist.module.ts @@ -4,18 +4,18 @@ import { DI_TOKENS } from "@calcom/features/di/tokens"; import { GlobalWatchlistRepository } from "@calcom/features/watchlist/lib/repository/GlobalWatchlistRepository"; import { OrganizationWatchlistRepository } from "@calcom/features/watchlist/lib/repository/OrganizationWatchlistRepository"; import { PrismaWatchlistAuditRepository } from "@calcom/features/watchlist/lib/repository/PrismaWatchlistAuditRepository"; - -import { WATCHLIST_DI_TOKENS } from "../Watchlist.tokens"; import { GlobalBlockingService } from "@calcom/features/watchlist/lib/service/GlobalBlockingService"; import { OrganizationBlockingService } from "@calcom/features/watchlist/lib/service/OrganizationBlockingService"; +import { WATCHLIST_DI_TOKENS } from "../Watchlist.tokens"; + export const watchlistModule = createModule(); watchlistModule.bind(WATCHLIST_DI_TOKENS.GLOBAL_BLOCKING_SERVICE).toClass(GlobalBlockingService, { globalRepo: DI_TOKENS.GLOBAL_WATCHLIST_REPOSITORY, }); -watchlistModule.bind(WATCHLIST_DI_TOKENS.ORGANIZATION_BLOCKING_SERVICE).toClass(OrganizationBlockingService,{ +watchlistModule.bind(WATCHLIST_DI_TOKENS.ORGANIZATION_BLOCKING_SERVICE).toClass(OrganizationBlockingService, { orgRepo: DI_TOKENS.ORGANIZATION_WATCHLIST_REPOSITORY, }); diff --git a/packages/features/ee/billing/credit-service.test.ts b/packages/features/ee/billing/credit-service.test.ts index b0bfa99cee..01c0f74d49 100644 --- a/packages/features/ee/billing/credit-service.test.ts +++ b/packages/features/ee/billing/credit-service.test.ts @@ -3,9 +3,9 @@ import { describe, it, expect, beforeEach, vi } from "vitest"; import dayjs from "@calcom/dayjs"; import * as EmailManager from "@calcom/emails/email-manager"; -import { CreditsRepository } from "@calcom/lib/server/repository/credits"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import { CreditsRepository } from "@calcom/lib/server/repository/credits"; import { CreditType } from "@calcom/prisma/enums"; import { CreditService } from "./credit-service"; diff --git a/packages/features/ee/billing/credit-service.ts b/packages/features/ee/billing/credit-service.ts index 2ea4332acb..b0d536e1ff 100644 --- a/packages/features/ee/billing/credit-service.ts +++ b/packages/features/ee/billing/credit-service.ts @@ -7,13 +7,13 @@ import { } from "@calcom/emails/email-manager"; import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service"; import { InternalTeamBilling } from "@calcom/features/ee/billing/teams/internal-team-billing"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { cancelScheduledMessagesAndScheduleEmails } from "@calcom/features/ee/workflows/lib/reminders/reminderScheduler"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { IS_SMS_CREDITS_ENABLED } from "@calcom/lib/constants"; import logger from "@calcom/lib/logger"; import { getTranslation } from "@calcom/lib/server/i18n"; import { CreditsRepository } from "@calcom/lib/server/repository/credits"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import prisma, { type PrismaTransaction } from "@calcom/prisma"; import type { CreditUsageType } from "@calcom/prisma/enums"; import { CreditType } from "@calcom/prisma/enums"; diff --git a/packages/features/ee/dsync/lib/handleGroupEvents.ts b/packages/features/ee/dsync/lib/handleGroupEvents.ts index 27cca705a1..26fb3226f2 100644 --- a/packages/features/ee/dsync/lib/handleGroupEvents.ts +++ b/packages/features/ee/dsync/lib/handleGroupEvents.ts @@ -1,10 +1,10 @@ import type { DirectorySyncEvent, Group } from "@boxyhq/saml-jackson"; +import { addNewMembersToEventTypes } from "@calcom/features/ee/teams/lib/queries"; +import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { addNewMembersToEventTypes } from "@calcom/features/ee/teams/lib/queries"; -import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import prisma from "@calcom/prisma"; import { IdentityProvider, MembershipRole } from "@calcom/prisma/enums"; import { diff --git a/packages/features/ee/organizations/lib/OrganizationPermissionService.ts b/packages/features/ee/organizations/lib/OrganizationPermissionService.ts index 6d6f8c3868..88f962e5a2 100644 --- a/packages/features/ee/organizations/lib/OrganizationPermissionService.ts +++ b/packages/features/ee/organizations/lib/OrganizationPermissionService.ts @@ -1,8 +1,8 @@ +import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; import { UserPermissionRole } from "@calcom/kysely/types"; import { ORGANIZATION_SELF_SERVE_MIN_SEATS, ORGANIZATION_SELF_SERVE_PRICE } from "@calcom/lib/constants"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; import { prisma } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/features/ee/organizations/lib/onboardingStore.test.ts b/packages/features/ee/organizations/lib/onboardingStore.test.ts index d16b0312a9..c850aafb20 100644 --- a/packages/features/ee/organizations/lib/onboardingStore.test.ts +++ b/packages/features/ee/organizations/lib/onboardingStore.test.ts @@ -1,13 +1,11 @@ /** * @vitest-environment jsdom */ - // @ts-nocheck - Test file with mock type compatibility issues that don't affect test functionality - -import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { renderHook, act, waitFor } from "@testing-library/react"; import { useSession } from "next-auth/react"; import { useSearchParams, useRouter, usePathname } from "next/navigation"; +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { UserPermissionRole } from "@calcom/prisma/enums"; @@ -19,135 +17,132 @@ import { useOnboardingStore, useOnboarding } from "./onboardingStore"; vi.mock("next-auth/react"); vi.mock("next/navigation"); vi.mock("@calcom/trpc/react", () => ({ - trpc: { - viewer: { - organizations: { - getOrganizationOnboarding: { - useQuery: vi.fn(), - }, - }, + trpc: { + viewer: { + organizations: { + getOrganizationOnboarding: { + useQuery: vi.fn(), }, + }, }, + }, })); // Mock constants vi.mock("@calcom/lib/constants", async () => { - const actual = await vi.importActual("@calcom/lib/constants"); - return { - ...actual, - IS_SELF_HOSTED: false, // Default to false, will be overridden in specific tests - }; + const actual = await vi.importActual("@calcom/lib/constants"); + return { + ...actual, + IS_SELF_HOSTED: false, // Default to false, will be overridden in specific tests + }; }); - function renderUseOnboardingStore() { - renderHook(() => useOnboarding(), { wrapper: createWrapper() }); - return renderHook(() => useOnboardingStore(), { wrapper: createWrapper() }); + renderHook(() => useOnboarding(), { wrapper: createWrapper() }); + return renderHook(() => useOnboardingStore(), { wrapper: createWrapper() }); } // Test Data Builders const createTestSession = (overrides?: { - email?: string; - role?: UserPermissionRole; - status?: "loading" | "authenticated" | "unauthenticated"; + email?: string; + role?: UserPermissionRole; + status?: "loading" | "authenticated" | "unauthenticated"; }) => { - const status = overrides?.status || "authenticated"; - - if (status === "loading") { - return { - data: null, - status: "loading" as const, - update: vi.fn(), - }; - } - - if (status === "unauthenticated") { - return { - data: null, - status: "unauthenticated" as const, - update: vi.fn(), - }; - } + const status = overrides?.status || "authenticated"; + if (status === "loading") { return { - data: { - user: { - email: overrides?.email || "test@example.com", - role: overrides?.role || UserPermissionRole.USER, - }, - }, - status: "authenticated" as const, - update: vi.fn(), + data: null, + status: "loading" as const, + update: vi.fn(), }; + } + + if (status === "unauthenticated") { + return { + data: null, + status: "unauthenticated" as const, + update: vi.fn(), + }; + } + + return { + data: { + user: { + email: overrides?.email || "test@example.com", + role: overrides?.role || UserPermissionRole.USER, + }, + }, + status: "authenticated" as const, + update: vi.fn(), + }; }; const createTestOrganizationOnboarding = (overrides?: { - isComplete?: boolean; - id?: string; - billingPeriod?: string; - pricePerSeat?: number; - seats?: number; - orgOwnerEmail?: string; - name?: string; - slug?: string; - bio?: string; - logo?: string; + isComplete?: boolean; + id?: string; + billingPeriod?: string; + pricePerSeat?: number; + seats?: number; + orgOwnerEmail?: string; + name?: string; + slug?: string; + bio?: string; + logo?: string; }) => ({ - id: overrides?.id || "test-onboarding-id", - isComplete: overrides?.isComplete ?? false, - billingPeriod: overrides?.billingPeriod || "MONTHLY", - pricePerSeat: overrides?.pricePerSeat ?? 20, - seats: overrides?.seats ?? 5, - orgOwnerEmail: overrides?.orgOwnerEmail || "test@example.com", - name: overrides?.name || "Test Organization", - slug: overrides?.slug || "test-org", - bio: overrides?.bio || "Test bio", - logo: overrides?.logo || "test-logo.png", + id: overrides?.id || "test-onboarding-id", + isComplete: overrides?.isComplete ?? false, + billingPeriod: overrides?.billingPeriod || "MONTHLY", + pricePerSeat: overrides?.pricePerSeat ?? 20, + seats: overrides?.seats ?? 5, + orgOwnerEmail: overrides?.orgOwnerEmail || "test@example.com", + name: overrides?.name || "Test Organization", + slug: overrides?.slug || "test-org", + bio: overrides?.bio || "Test bio", + logo: overrides?.logo || "test-logo.png", }); - - function mockOrganizationOnboardingFromDB(data: ReturnType | null) { - const organizationOnboarding = data ? createTestOrganizationOnboarding(data) : null; - (trpc.viewer.organizations.getOrganizationOnboarding.useQuery as ReturnType).mockReturnValue({ - data: organizationOnboarding, - isPending: false, - isLoading: false, - error: null, - refetch: vi.fn(), - }); + const organizationOnboarding = data ? createTestOrganizationOnboarding(data) : null; + (trpc.viewer.organizations.getOrganizationOnboarding.useQuery as ReturnType).mockReturnValue({ + data: organizationOnboarding, + isPending: false, + isLoading: false, + error: null, + refetch: vi.fn(), + }); } const createTestSearchParams = (params?: Record) => { - return new URLSearchParams(params); + return new URLSearchParams(params); }; // Mock localStorage const localStorageMock = { - getItem: vi.fn(), - setItem: vi.fn(), - removeItem: vi.fn(), - clear: vi.fn(), + getItem: vi.fn(), + setItem: vi.fn(), + removeItem: vi.fn(), + clear: vi.fn(), }; -Object.defineProperty(window, 'localStorage', { - value: localStorageMock, - writable: true, +Object.defineProperty(window, "localStorage", { + value: localStorageMock, + writable: true, }); // Mock implementations const mockRouterPush = vi.fn().mockImplementation((...args: string[]) => { - console.trace(); - console.log("mockRouterPush called", args[0]); + console.trace(); + console.log("mockRouterPush called", args[0]); }); const mockUseSession = vi.mocked(useSession); vi.mocked(useRouter).mockReturnValue({ - push: mockRouterPush, - replace: vi.fn(), - back: vi.fn(), - forward: vi.fn(), - refresh: vi.fn(), - prefetch: vi.fn(), + push: mockRouterPush, + replace: vi.fn(), + back: vi.fn(), + forward: vi.fn(), + refresh: vi.fn(), + prefetch: vi.fn(), }); const mockUsePathname = vi.mocked(usePathname); const mockUseSearchParams = vi.mocked(useSearchParams); @@ -156,234 +151,244 @@ const mockUseSearchParams = vi.mocked(useSearchParams); const createWrapper = () => undefined; describe("OnboardingStore", () => { - beforeEach(() => { - // Reset the store and let React do any side effects + beforeEach(() => { + // Reset the store and let React do any side effects + act(() => { + useOnboardingStore.getState().reset(); + }); + // Reset localStorage mock + localStorageMock.clear.mockClear(); + localStorageMock.getItem.mockClear(); + localStorageMock.setItem.mockClear(); + localStorageMock.removeItem.mockClear(); + + mockRouterPush.mockClear(); + + // Setup default mocks + mockUsePathname.mockReturnValue("/settings/organizations/new"); + mockUseSearchParams.mockReturnValue(createTestSearchParams()); + + ( + trpc.viewer.organizations.getOrganizationOnboarding.useQuery as ReturnType + ).mockReturnValue({ + data: undefined, + isPending: false, + isLoading: false, + error: null, + refetch: vi.fn(), + }); + }); + + afterEach(() => { + act(() => { + useOnboardingStore.getState().reset(); + }); + vi.clearAllMocks(); + mockRouterPush.mockClear(); + localStorageMock.clear.mockClear(); + localStorageMock.getItem.mockClear(); + localStorageMock.setItem.mockClear(); + localStorageMock.removeItem.mockClear(); + }); + + describe("Zustand Store Actions - Complex Logic", () => { + describe("Reset Functionality", () => { + it("should reset to initial state when called without parameters", () => { + const { result } = renderHook(() => useOnboardingStore(), { wrapper: createWrapper() }); + + // Set some values act(() => { - useOnboardingStore.getState().reset(); + result.current.setName("Test Org"); + result.current.setSlug("test-org"); + result.current.setBillingPeriod("ANNUALLY" as const); + result.current.setSeats(15); + result.current.addInvitedMember({ email: "test@example.com", name: "Test User" }); }); - // Reset localStorage mock - localStorageMock.clear.mockClear(); - localStorageMock.getItem.mockClear(); - localStorageMock.setItem.mockClear(); - localStorageMock.removeItem.mockClear(); - mockRouterPush.mockClear(); + // Reset + act(() => { + result.current.reset(); + }); - // Setup default mocks + expect(result.current.name).toBe(""); + expect(result.current.slug).toBe(""); + expect(result.current.billingPeriod).toBeUndefined(); + expect(result.current.seats).toBeNull(); + expect(result.current.invitedMembers).toEqual([]); + }); + + it("should set specific state when called with parameters", () => { + const { result } = renderHook(() => useOnboardingStore(), { wrapper: createWrapper() }); + const newState = { + name: "Partial Reset Org", + slug: "partial-reset", + seats: 25, + }; + + act(() => { + result.current.reset(newState); + }); + + expect(result.current.name).toBe("Partial Reset Org"); + expect(result.current.slug).toBe("partial-reset"); + expect(result.current.seats).toBe(25); + }); + + it("should clear localStorage when resetting without parameters", () => { + const { result } = renderHook(() => useOnboardingStore(), { wrapper: createWrapper() }); + + // Set some values to trigger localStorage save + act(() => { + result.current.setName("Test Org"); + }); + + // Reset + act(() => { + result.current.reset(); + }); + + // Verify localStorage removeItem was called + expect(localStorageMock.removeItem).toHaveBeenCalledWith("org-creation-onboarding"); + }); + }); + }); + + describe("useOnboarding Hook", () => { + beforeEach(() => { + mockUseSession.mockReturnValue(createTestSession()); + }); + + describe("Authentication Handling", () => { + it("should redirect to login when session is unauthenticated", async () => { + mockUseSession.mockReturnValue(createTestSession({ status: "unauthenticated" })); mockUsePathname.mockReturnValue("/settings/organizations/new"); mockUseSearchParams.mockReturnValue(createTestSearchParams()); - (trpc.viewer.organizations.getOrganizationOnboarding.useQuery as ReturnType).mockReturnValue({ - data: undefined, - isPending: false, - isLoading: false, - error: null, - refetch: vi.fn(), - }); - }); + renderHook(() => useOnboarding(), { wrapper: createWrapper() }); - afterEach(() => { - act(() => { - useOnboardingStore.getState().reset(); + await waitFor(() => { + expect(mockRouterPush).toHaveBeenCalledWith( + `/auth/login?callbackUrl=${WEBAPP_URL}/settings/organizations/new` + ); }); - vi.clearAllMocks(); mockRouterPush.mockClear(); - localStorageMock.clear.mockClear(); - localStorageMock.getItem.mockClear(); - localStorageMock.setItem.mockClear(); - localStorageMock.removeItem.mockClear(); + expect(mockRouterPush).not.toHaveBeenCalled(); + }); + + it("should not redirect when session is authenticated", () => { + expect(mockRouterPush).not.toHaveBeenCalled(); + mockUseSession.mockReturnValue(createTestSession({ status: "authenticated" })); + + renderHook(() => useOnboarding(), { wrapper: createWrapper() }); + + expect(mockRouterPush).not.toHaveBeenCalled(); + }); }); - describe("Zustand Store Actions - Complex Logic", () => { - describe("Reset Functionality", () => { - it("should reset to initial state when called without parameters", () => { - const { result } = renderHook(() => useOnboardingStore(), { wrapper: createWrapper() }); - - // Set some values - act(() => { - result.current.setName("Test Org"); - result.current.setSlug("test-org"); - result.current.setBillingPeriod("ANNUALLY" as const); - result.current.setSeats(15); - result.current.addInvitedMember({ email: "test@example.com", name: "Test User" }); - }); - - // Reset - act(() => { - result.current.reset(); - }); - - expect(result.current.name).toBe(""); - expect(result.current.slug).toBe(""); - expect(result.current.billingPeriod).toBeUndefined(); - expect(result.current.seats).toBeNull(); - expect(result.current.invitedMembers).toEqual([]); - }); - - it("should set specific state when called with parameters", () => { - const { result } = renderHook(() => useOnboardingStore(), { wrapper: createWrapper() }); - const newState = { - name: "Partial Reset Org", - slug: "partial-reset", - seats: 25, - }; - - act(() => { - result.current.reset(newState); - }); - - expect(result.current.name).toBe("Partial Reset Org"); - expect(result.current.slug).toBe("partial-reset"); - expect(result.current.seats).toBe(25); - }); - - it("should clear localStorage when resetting without parameters", () => { - const { result } = renderHook(() => useOnboardingStore(), { wrapper: createWrapper() }); - - // Set some values to trigger localStorage save - act(() => { - result.current.setName("Test Org"); - }); - - // Reset - act(() => { - result.current.reset(); - }); - - // Verify localStorage removeItem was called - expect(localStorageMock.removeItem).toHaveBeenCalledWith("org-creation-onboarding"); - }); - }); - }); - - describe("useOnboarding Hook", () => { - beforeEach(() => { - mockUseSession.mockReturnValue(createTestSession()); - }); - - describe("Authentication Handling", () => { - it("should redirect to login when session is unauthenticated", async () => { - mockUseSession.mockReturnValue(createTestSession({ status: "unauthenticated" })); - mockUsePathname.mockReturnValue("/settings/organizations/new"); - mockUseSearchParams.mockReturnValue(createTestSearchParams()); - - renderHook(() => useOnboarding(), { wrapper: createWrapper() }); - - await waitFor(() => { - expect(mockRouterPush).toHaveBeenCalledWith( - `/auth/login?callbackUrl=${WEBAPP_URL}/settings/organizations/new` - ); - }); - mockRouterPush.mockClear(); - expect(mockRouterPush).not.toHaveBeenCalled(); - }); - - it("should not redirect when session is authenticated", () => { - expect(mockRouterPush).not.toHaveBeenCalled(); - mockUseSession.mockReturnValue(createTestSession({ status: "authenticated" })); - - renderHook(() => useOnboarding(), { wrapper: createWrapper() }); - - expect(mockRouterPush).not.toHaveBeenCalled(); - }); - }); - - describe("Organization Onboarding State Sync", () => { - it("should return organization onboarding data when available", () => { - const organizationOnboarding = createTestOrganizationOnboarding({ - name: "Test Org", - slug: "test-org", - }); - - (trpc.viewer.organizations.getOrganizationOnboarding.useQuery as ReturnType).mockReturnValue({ - data: organizationOnboarding, - isPending: false, - isLoading: false, - error: null, - refetch: vi.fn(), - }); - - const { result } = renderHook(() => useOnboarding(), { wrapper: createWrapper() }); - - expect(result.current.dbOnboarding).toEqual(organizationOnboarding); - expect(result.current.isLoadingOrgOnboarding).toBe(false); - }); - - it("should set onboardingData from DB to zustand if not set already", async () => { - const organizationOnboarding = createTestOrganizationOnboarding({ - id: "sync-test-id", - name: "Synced Organization", - slug: "synced-org", - bio: "Synced bio content", - logo: "synced-logo.png", - billingPeriod: "ANNUALLY", - pricePerSeat: 25, - seats: 10, - orgOwnerEmail: "owner@synced.com", - }); - - (trpc.viewer.organizations.getOrganizationOnboarding.useQuery as ReturnType).mockReturnValue({ - data: organizationOnboarding, - isPending: false, - isLoading: false, - error: null, - refetch: vi.fn(), - }); - - renderHook(() => useOnboarding(), { wrapper: createWrapper() }); - const { result: storeResult } = renderHook(() => useOnboardingStore(), { wrapper: createWrapper() }); - - await waitFor(() => { - expect(storeResult.current.onboardingId).toBe("sync-test-id"); - }); - - expect(storeResult.current.name).toBe("Synced Organization"); - expect(storeResult.current.slug).toBe("synced-org"); - expect(storeResult.current.bio).toBe("Synced bio content"); - expect(storeResult.current.logo).toBe("synced-logo.png"); - expect(storeResult.current.billingPeriod).toBe("ANNUALLY"); - expect(storeResult.current.pricePerSeat).toBe(25); - expect(storeResult.current.seats).toBe(10); - expect(storeResult.current.orgOwnerEmail).toBe("owner@synced.com"); - }); - - it("should sync onboardingData from DB to zustand if set already", async () => { - mockOrganizationOnboardingFromDB(createTestOrganizationOnboarding({ - id: "onboarding1", - name: "Onboarding 1 Organization", - slug: "onboarding1-org", - bio: "Onboarding 1 bio content", - logo: "onboarding1-logo.png", - billingPeriod: "MONTHLY", - pricePerSeat: 15, - seats: 5, - orgOwnerEmail: "owner@onboarding1.com", - })) - - // Load the store to set the initial state - const { result: storeResultBefore } = renderUseOnboardingStore(); - - expect(storeResultBefore.current.name).toBe("Onboarding 1 Organization"); - expect(storeResultBefore.current.slug).toBe("onboarding1-org"); - - mockOrganizationOnboardingFromDB(createTestOrganizationOnboarding({ - id: "sync-test-id", - name: "Synced Organization", - slug: "synced-org", - bio: "Synced bio content", - logo: "synced-logo.png", - billingPeriod: "ANNUALLY", - pricePerSeat: 25, - seats: 10, - orgOwnerEmail: "owner@synced.com", - })); - - // Load the store to sync the new data - const { result: storeResultAfter } = renderUseOnboardingStore(); - // Verify the data is synced - expect(storeResultAfter.current.name).toBe("Synced Organization"); - expect(storeResultAfter.current.slug).toBe("synced-org"); - }); + describe("Organization Onboarding State Sync", () => { + it("should return organization onboarding data when available", () => { + const organizationOnboarding = createTestOrganizationOnboarding({ + name: "Test Org", + slug: "test-org", }); + + ( + trpc.viewer.organizations.getOrganizationOnboarding.useQuery as ReturnType + ).mockReturnValue({ + data: organizationOnboarding, + isPending: false, + isLoading: false, + error: null, + refetch: vi.fn(), + }); + + const { result } = renderHook(() => useOnboarding(), { wrapper: createWrapper() }); + + expect(result.current.dbOnboarding).toEqual(organizationOnboarding); + expect(result.current.isLoadingOrgOnboarding).toBe(false); + }); + + it("should set onboardingData from DB to zustand if not set already", async () => { + const organizationOnboarding = createTestOrganizationOnboarding({ + id: "sync-test-id", + name: "Synced Organization", + slug: "synced-org", + bio: "Synced bio content", + logo: "synced-logo.png", + billingPeriod: "ANNUALLY", + pricePerSeat: 25, + seats: 10, + orgOwnerEmail: "owner@synced.com", + }); + + ( + trpc.viewer.organizations.getOrganizationOnboarding.useQuery as ReturnType + ).mockReturnValue({ + data: organizationOnboarding, + isPending: false, + isLoading: false, + error: null, + refetch: vi.fn(), + }); + + renderHook(() => useOnboarding(), { wrapper: createWrapper() }); + const { result: storeResult } = renderHook(() => useOnboardingStore(), { wrapper: createWrapper() }); + + await waitFor(() => { + expect(storeResult.current.onboardingId).toBe("sync-test-id"); + }); + + expect(storeResult.current.name).toBe("Synced Organization"); + expect(storeResult.current.slug).toBe("synced-org"); + expect(storeResult.current.bio).toBe("Synced bio content"); + expect(storeResult.current.logo).toBe("synced-logo.png"); + expect(storeResult.current.billingPeriod).toBe("ANNUALLY"); + expect(storeResult.current.pricePerSeat).toBe(25); + expect(storeResult.current.seats).toBe(10); + expect(storeResult.current.orgOwnerEmail).toBe("owner@synced.com"); + }); + + it("should sync onboardingData from DB to zustand if set already", async () => { + mockOrganizationOnboardingFromDB( + createTestOrganizationOnboarding({ + id: "onboarding1", + name: "Onboarding 1 Organization", + slug: "onboarding1-org", + bio: "Onboarding 1 bio content", + logo: "onboarding1-logo.png", + billingPeriod: "MONTHLY", + pricePerSeat: 15, + seats: 5, + orgOwnerEmail: "owner@onboarding1.com", + }) + ); + + // Load the store to set the initial state + const { result: storeResultBefore } = renderUseOnboardingStore(); + + expect(storeResultBefore.current.name).toBe("Onboarding 1 Organization"); + expect(storeResultBefore.current.slug).toBe("onboarding1-org"); + + mockOrganizationOnboardingFromDB( + createTestOrganizationOnboarding({ + id: "sync-test-id", + name: "Synced Organization", + slug: "synced-org", + bio: "Synced bio content", + logo: "synced-logo.png", + billingPeriod: "ANNUALLY", + pricePerSeat: 25, + seats: 10, + orgOwnerEmail: "owner@synced.com", + }) + ); + + // Load the store to sync the new data + const { result: storeResultAfter } = renderUseOnboardingStore(); + // Verify the data is synced + expect(storeResultAfter.current.name).toBe("Synced Organization"); + expect(storeResultAfter.current.slug).toBe("synced-org"); + }); }); + }); }); diff --git a/packages/features/ee/organizations/lib/server/orgCreationUtils.ts b/packages/features/ee/organizations/lib/server/orgCreationUtils.ts index 6bc078f440..9aead5b715 100644 --- a/packages/features/ee/organizations/lib/server/orgCreationUtils.ts +++ b/packages/features/ee/organizations/lib/server/orgCreationUtils.ts @@ -3,6 +3,7 @@ import { type TFunction } from "i18next"; import { sendAdminOrganizationNotification } from "@calcom/emails"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { RESERVED_SUBDOMAINS, ORG_MINIMUM_PUBLISHED_TEAMS_SELF_SERVE, @@ -12,7 +13,6 @@ import { import { createDomain } from "@calcom/lib/domainManager/organization"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { prisma } from "@calcom/prisma"; import { UserPermissionRole } from "@calcom/prisma/enums"; diff --git a/packages/features/ee/organizations/pages/components/OtherTeamList.tsx b/packages/features/ee/organizations/pages/components/OtherTeamList.tsx index 8e501f1abf..aafcfac3bb 100644 --- a/packages/features/ee/organizations/pages/components/OtherTeamList.tsx +++ b/packages/features/ee/organizations/pages/components/OtherTeamList.tsx @@ -2,8 +2,8 @@ import { useState } from "react"; -import { trackFormbricksAction } from "@calcom/lib/formbricks-client"; import type { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; +import { trackFormbricksAction } from "@calcom/lib/formbricks-client"; import { trpc } from "@calcom/trpc/react"; import { showToast } from "@calcom/ui/components/toast"; diff --git a/packages/features/ee/organizations/pages/components/OtherTeamsListing.tsx b/packages/features/ee/organizations/pages/components/OtherTeamsListing.tsx index e76929207c..50c39cb32c 100644 --- a/packages/features/ee/organizations/pages/components/OtherTeamsListing.tsx +++ b/packages/features/ee/organizations/pages/components/OtherTeamsListing.tsx @@ -1,7 +1,7 @@ "use client"; -import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; +import { useLocale } from "@calcom/lib/hooks/useLocale"; import { EmptyScreen } from "@calcom/ui/components/empty-screen"; import OtherTeamList from "./OtherTeamList"; diff --git a/packages/features/ee/organizations/repositories/OrganizationRepository.ts b/packages/features/ee/organizations/repositories/OrganizationRepository.ts index a0990df4b7..ed038ba484 100644 --- a/packages/features/ee/organizations/repositories/OrganizationRepository.ts +++ b/packages/features/ee/organizations/repositories/OrganizationRepository.ts @@ -1,8 +1,8 @@ import type { z } from "zod"; import { getOrgUsernameFromEmail } from "@calcom/features/auth/signup/utils/getOrgUsernameFromEmail"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { createAProfileForAnExistingUser } from "@calcom/features/profile/lib/createAProfileForAnExistingUser"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import { getParsedTeam } from "@calcom/lib/server/repository/teamUtils"; diff --git a/packages/features/ee/payments/pages/payment.tsx b/packages/features/ee/payments/pages/payment.tsx index c3ee0b906c..f3e086fdb3 100644 --- a/packages/features/ee/payments/pages/payment.tsx +++ b/packages/features/ee/payments/pages/payment.tsx @@ -47,7 +47,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => if (!eventType) return { notFound: true } as const; - if (eventType.users.length === 0 && !!!eventType.team) return { notFound: true } as const; + if (eventType.users.length === 0 && !eventType.team) return { notFound: true } as const; const [user] = eventType?.users.length ? eventType.users diff --git a/packages/features/ee/round-robin/assignmentReason/AssignmentReasonRecorder.ts b/packages/features/ee/round-robin/assignmentReason/AssignmentReasonRecorder.ts index cfc972762c..50c7c9ff22 100644 --- a/packages/features/ee/round-robin/assignmentReason/AssignmentReasonRecorder.ts +++ b/packages/features/ee/round-robin/assignmentReason/AssignmentReasonRecorder.ts @@ -1,6 +1,6 @@ +import { acrossQueryValueCompatiblity } from "@calcom/app-store/_utils/raqb/raqbUtils"; import type { FormResponse, Fields } from "@calcom/app-store/routing-forms/types/types"; import { zodRoutes } from "@calcom/app-store/routing-forms/zod"; -import { acrossQueryValueCompatiblity } from "@calcom/app-store/_utils/raqb/raqbUtils"; import { withReporting } from "@calcom/lib/sentryWrapper"; import { getUsersAttributes } from "@calcom/lib/service/attribute/server/getAttributes"; import prisma from "@calcom/prisma"; diff --git a/packages/features/ee/round-robin/roundRobinManualReassignment.ts b/packages/features/ee/round-robin/roundRobinManualReassignment.ts index ff07e155e1..ea0a3e8717 100644 --- a/packages/features/ee/round-robin/roundRobinManualReassignment.ts +++ b/packages/features/ee/round-robin/roundRobinManualReassignment.ts @@ -14,6 +14,7 @@ import { getAllCredentialsIncludeServiceAccountKey } from "@calcom/features/book import getBookingResponsesSchema from "@calcom/features/bookings/lib/getBookingResponsesSchema"; import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses"; import { getEventTypesFromDB } from "@calcom/features/bookings/lib/handleNewBooking/getEventTypesFromDB"; +import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import AssignmentReasonRecorder, { RRReassignmentType, } from "@calcom/features/ee/round-robin/assignmentReason/AssignmentReasonRecorder"; @@ -26,7 +27,6 @@ import { scheduleWorkflowReminders } from "@calcom/features/ee/workflows/lib/rem import { getEventName } from "@calcom/features/eventtypes/lib/eventNaming"; import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser"; import { SENDER_NAME } from "@calcom/lib/constants"; -import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import { IdempotencyKeyService } from "@calcom/lib/idempotencyKey/idempotencyKeyService"; import { isPrismaObjOrUndefined } from "@calcom/lib/isPrismaObj"; import logger from "@calcom/lib/logger"; diff --git a/packages/features/ee/sso/lib/sso.ts b/packages/features/ee/sso/lib/sso.ts index 4915ee5dbc..f8007c18ea 100644 --- a/packages/features/ee/sso/lib/sso.ts +++ b/packages/features/ee/sso/lib/sso.ts @@ -1,6 +1,6 @@ import createUsersAndConnectToOrg from "@calcom/features/ee/dsync/lib/users/createUsersAndConnectToOrg"; -import { HOSTED_CAL_FEATURES } from "@calcom/lib/constants"; import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; +import { HOSTED_CAL_FEATURES } from "@calcom/lib/constants"; import type { PrismaClient } from "@calcom/prisma"; import { IdentityProvider } from "@calcom/prisma/enums"; diff --git a/packages/features/ee/support/lib/intercom/useIntercom.ts b/packages/features/ee/support/lib/intercom/useIntercom.ts index 56714f34a7..a639483c25 100644 --- a/packages/features/ee/support/lib/intercom/useIntercom.ts +++ b/packages/features/ee/support/lib/intercom/useIntercom.ts @@ -1,4 +1,3 @@ - import { noop } from "lodash"; import { useEffect } from "react"; import type { IntercomBootProps, IntercomProps } from "react-use-intercom"; @@ -13,18 +12,17 @@ import useMediaQuery from "@calcom/lib/hooks/useMediaQuery"; import { localStorage } from "@calcom/lib/webstorage"; import { trpc } from "@calcom/trpc/react"; - export const isInterComEnabled = z.string().min(1).safeParse(process.env.NEXT_PUBLIC_INTERCOM_APP_ID).success; const useIntercomHook = isInterComEnabled ? useIntercomLib : () => { return { - // eslint-disable-next-line + boot: (_props: IntercomBootProps) => {}, show: noop, shutdown: noop, - // eslint-disable-next-line + update: (_props: Partial) => {}, }; }; diff --git a/packages/features/ee/teams/lib/queries.ts b/packages/features/ee/teams/lib/queries.ts index 5a5b660338..461b49764a 100644 --- a/packages/features/ee/teams/lib/queries.ts +++ b/packages/features/ee/teams/lib/queries.ts @@ -1,13 +1,13 @@ import { z } from "zod"; import { getAppFromSlug } from "@calcom/app-store/utils"; -import { DATABASE_CHUNK_SIZE } from "@calcom/lib/constants"; import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; +import { getTeam, getOrg } from "@calcom/features/ee/teams/repositories/TeamRepository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; +import { DATABASE_CHUNK_SIZE } from "@calcom/lib/constants"; import { parseBookingLimit } from "@calcom/lib/intervalLimits/isBookingLimits"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { getTeam, getOrg } from "@calcom/features/ee/teams/repositories/TeamRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import prisma from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import type { Team } from "@calcom/prisma/client"; diff --git a/packages/features/ee/teams/services/teamService.alternative.test.ts b/packages/features/ee/teams/services/teamService.alternative.test.ts index 2d15dbcfaa..a2628d78e0 100644 --- a/packages/features/ee/teams/services/teamService.alternative.test.ts +++ b/packages/features/ee/teams/services/teamService.alternative.test.ts @@ -3,9 +3,9 @@ import { prisma } from "@calcom/prisma/__mocks__/prisma"; import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { TeamBilling } from "@calcom/features/ee/billing/teams"; -import { deleteDomain } from "@calcom/lib/domainManager/organization"; import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; +import { deleteDomain } from "@calcom/lib/domainManager/organization"; import { TeamService } from "./teamService"; diff --git a/packages/features/ee/teams/services/teamService.test.ts b/packages/features/ee/teams/services/teamService.test.ts index 657bb5f4ca..0c1df1c3f6 100644 --- a/packages/features/ee/teams/services/teamService.test.ts +++ b/packages/features/ee/teams/services/teamService.test.ts @@ -4,10 +4,10 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { TeamBilling } from "@calcom/features/ee/billing/teams"; import { updateNewTeamMemberEventTypes } from "@calcom/features/ee/teams/lib/queries"; -import { createAProfileForAnExistingUser } from "@calcom/features/profile/lib/createAProfileForAnExistingUser"; -import { deleteDomain } from "@calcom/lib/domainManager/organization"; import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; +import { createAProfileForAnExistingUser } from "@calcom/features/profile/lib/createAProfileForAnExistingUser"; +import { deleteDomain } from "@calcom/lib/domainManager/organization"; import type { Membership, Team, User, VerificationToken, Profile } from "@calcom/prisma/client"; import { MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/features/ee/teams/services/teamService.ts b/packages/features/ee/teams/services/teamService.ts index 66256e2e83..b7aa220aba 100644 --- a/packages/features/ee/teams/services/teamService.ts +++ b/packages/features/ee/teams/services/teamService.ts @@ -3,16 +3,16 @@ import { randomBytes } from "crypto"; import { TeamBilling } from "@calcom/features/ee/billing/teams"; import { deleteWorkfowRemindersOfRemovedMember } from "@calcom/features/ee/teams/lib/deleteWorkflowRemindersOfRemovedMember"; import { updateNewTeamMemberEventTypes } from "@calcom/features/ee/teams/lib/queries"; -import { WEBAPP_URL } from "@calcom/lib/constants"; -import { createAProfileForAnExistingUser } from "@calcom/features/profile/lib/createAProfileForAnExistingUser"; -import { deleteDomain } from "@calcom/lib/domainManager/organization"; -import logger from "@calcom/lib/logger"; -import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; +import { createAProfileForAnExistingUser } from "@calcom/features/profile/lib/createAProfileForAnExistingUser"; +import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; +import { WEBAPP_URL } from "@calcom/lib/constants"; +import { deleteDomain } from "@calcom/lib/domainManager/organization"; +import logger from "@calcom/lib/logger"; import { prisma } from "@calcom/prisma"; -import { Prisma } from "@calcom/prisma/client"; import type { Membership } from "@calcom/prisma/client"; +import { Prisma } from "@calcom/prisma/client"; import { MembershipRole } from "@calcom/prisma/enums"; import { TRPCError } from "@trpc/server"; @@ -269,13 +269,7 @@ export class TeamService { await updateNewTeamMemberEventTypes(userId, teamId); } - static async leaveTeamMembership({ - userId, - teamId, - }: { - userId: number; - teamId: number; - }) { + static async leaveTeamMembership({ userId, teamId }: { userId: number; teamId: number }) { try { const membership = await prisma.membership.delete({ where: { diff --git a/packages/features/ee/workflows/api/scheduleSMSReminders.ts b/packages/features/ee/workflows/api/scheduleSMSReminders.ts index 6959bd5f37..f724516ebc 100644 --- a/packages/features/ee/workflows/api/scheduleSMSReminders.ts +++ b/packages/features/ee/workflows/api/scheduleSMSReminders.ts @@ -5,9 +5,9 @@ import { NextResponse } from "next/server"; import dayjs from "@calcom/dayjs"; import { bulkShortenLinks } from "@calcom/ee/workflows/lib/reminders/utils"; import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses"; +import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import { isAttendeeAction } from "@calcom/features/ee/workflows/lib/actionHelperFunctions"; import { scheduleSmsOrFallbackEmail } from "@calcom/features/ee/workflows/lib/reminders/messageDispatcher"; -import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import { getTranslation } from "@calcom/lib/server/i18n"; import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat"; import prisma from "@calcom/prisma"; diff --git a/packages/features/ee/workflows/components/WorkflowListPage.tsx b/packages/features/ee/workflows/components/WorkflowListPage.tsx index bab32ccaab..1b831db1a0 100644 --- a/packages/features/ee/workflows/components/WorkflowListPage.tsx +++ b/packages/features/ee/workflows/components/WorkflowListPage.tsx @@ -229,7 +229,7 @@ export default function WorkflowListPage({ workflows }: Props) {
{workflow.team?.name && ( - + { const CalAIAgentDataSkeleton = () => { return ( -
-
+
+
- -
- - - + +
+ + +
-
- - +
+ +
@@ -517,7 +517,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { return ( <>
- +
{!!timeSectionText && ( -
- +
+
)} @@ -601,7 +601,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { {selectedOptions && setSelectedOptions && allOptions && (
{isOrganization ? ( -
+
@@ -668,7 +668,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
)} {!!timeSectionText && ( -
+

{t("testing_sms_workflow_info_message")}

@@ -815,12 +815,12 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { />
-
{t("sender_id_info")}
+
{t("sender_id_info")}
{form.formState.errors.steps && form.formState?.errors?.steps[step.stepNumber - 1]?.sender && ( -

{t("sender_id_error_message")}

+

{t("sender_id_error_message")}

)} ) : ( @@ -839,23 +839,23 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
)} {isCalAIAction(form.getValues(`steps.${step.stepNumber - 1}.action`)) && !stepAgentId && ( -
-
+
+
-

+

{t("cal_ai_agent")} - + {t("set_up_required")}

-

+

{t("no_phone_number_connected")}.

{form.formState.errors.steps && form.formState?.errors?.steps[step.stepNumber - 1]?.sendTo && ( -

+

{form.formState?.errors?.steps[step.stepNumber - 1]?.sendTo?.message || ""}

)} @@ -1176,9 +1176,9 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { ) : ( !props.readOnly && ( <> -
+
-
+
{form.formState.errors.steps && form.formState?.errors?.steps[step.stepNumber - 1]?.sendTo && ( -

+

{form.formState?.errors?.steps[step.stepNumber - 1]?.sendTo?.message || ""}

)} @@ -1295,7 +1295,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
)} {!isCalAIAction(form.getValues(`steps.${step.stepNumber - 1}.action`)) && ( -
+
{isEmailSubjectNeeded && (
@@ -1328,14 +1328,14 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { /> {form.formState.errors.steps && form.formState?.errors?.steps[step.stepNumber - 1]?.emailSubject && ( -

+

{form.formState?.errors?.steps[step.stepNumber - 1]?.emailSubject?.message || ""}

)}
)} -
-
)} {!props.readOnly && !isFormTrigger(trigger) && ( -
+
@@ -1503,23 +1503,23 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {

{t("how_booking_questions_as_variables")}

-
-

{t("format")}

-
    +
    +

    {t("format")}

    +
    • {t("uppercase_for_letters")}
    • {t("replace_whitespaces_underscores")}
    • {t("ignore_special_characters_booking_questions")}
    -

    {t("example_1")}

    -
    -
    +

    {t("example_1")}

    +
    +
    {t("booking_question_identifier")}
    -
    {t("company_size")}
    -
    {t("variable")}
    +
    {t("company_size")}
    +
    {t("variable")}
    -
    +
    {" "} {`{${t("company_size") .replace(/[^a-zA-Z0-9 ]/g, "") @@ -1530,14 +1530,14 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
    -

    {t("example_2")}

    -
    -
    +

    {t("example_2")}

    +
    +
    {t("booking_question_identifier")}
    -
    {t("what_help_needed")}
    -
    {t("variable")}
    -
    +
    {t("what_help_needed")}
    +
    {t("variable")}
    +
    {" "} {`{${t("what_help_needed") .replace(/[^a-zA-Z0-9 ]/g, "") @@ -1607,17 +1607,17 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
    -

    {t("do_you_still_want_to_unsubscribe")}

    +

    {t("do_you_still_want_to_unsubscribe")}

    {getActivePhoneNumbers( agentData?.outboundPhoneNumbers?.map((phone) => ({ ...phone, subscriptionStatus: phone.subscriptionStatus ?? undefined, })) ).length > 0 && ( -
    -
    - - +
    +
    + + {formatPhoneNumber( getActivePhoneNumbers( agentData?.outboundPhoneNumbers?.map((phone) => ({ @@ -1630,7 +1630,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
    )} -

    {t("the_action_will_disconnect_phone_number")}

    +

    {t("the_action_will_disconnect_phone_number")}

    - { - const isChecked = e.target.checked; - formMethods.setValue( - "periodDays", - Math.min(periodDaysWatch, ROLLING_WINDOW_PERIOD_MAX_DAYS_TO_CHECK) - ); - formMethods.setValue( - "periodType", - getPeriodTypeFromUiValue({ - value: PeriodType.ROLLING, - rollingExcludeUnavailableDays: isChecked, - }), - { shouldDirty: true } - ); - }} - /> - - { + const isChecked = e.target.checked; + formMethods.setValue( + "periodDays", + Math.min(periodDaysWatch, ROLLING_WINDOW_PERIOD_MAX_DAYS_TO_CHECK) + ); + formMethods.setValue( + "periodType", + getPeriodTypeFromUiValue({ + value: PeriodType.ROLLING, + rollingExcludeUnavailableDays: isChecked, + }), + { shouldDirty: true } + ); + }} /> - + + +
    diff --git a/packages/features/eventtypes/lib/getEventTypeById.ts b/packages/features/eventtypes/lib/getEventTypeById.ts index d2e38f4fe3..ae0bfaa840 100644 --- a/packages/features/eventtypes/lib/getEventTypeById.ts +++ b/packages/features/eventtypes/lib/getEventTypeById.ts @@ -4,16 +4,16 @@ import { getLocationGroupedOptions } from "@calcom/app-store/server"; import { getEventTypeAppData } from "@calcom/app-store/utils"; import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/app-store/zod-utils"; import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/getBookingFields"; +import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; +import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { WEBSITE_URL } from "@calcom/lib/constants"; import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; -import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import { parseBookingLimit } from "@calcom/lib/intervalLimits/isBookingLimits"; import { parseDurationLimit } from "@calcom/lib/intervalLimits/isDurationLimits"; import { parseEventTypeColor } from "@calcom/lib/isEventTypeColor"; import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import type { PrismaClient } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import { SchedulingType, MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/features/eventtypes/lib/getEventTypesByViewer.ts b/packages/features/eventtypes/lib/getEventTypesByViewer.ts index e064e24d34..12fb8886f4 100644 --- a/packages/features/eventtypes/lib/getEventTypesByViewer.ts +++ b/packages/features/eventtypes/lib/getEventTypesByViewer.ts @@ -1,19 +1,18 @@ -// eslint-disable-next-line no-restricted-imports import { orderBy } from "lodash"; -import { hasFilter } from "@calcom/features/filters/lib/hasFilter"; -import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; -import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; -import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; +import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; +import { hasFilter } from "@calcom/features/filters/lib/hasFilter"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; +import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; +import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; +import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; import logger from "@calcom/lib/logger"; import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; -import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import prisma from "@calcom/prisma"; import { MembershipRole, SchedulingType } from "@calcom/prisma/enums"; import { teamMetadataSchema } from "@calcom/prisma/zod-utils"; @@ -123,7 +122,7 @@ export const getEventTypesByViewer = async (user: User, filters?: Filters, forRo ...eventType, safeDescription: eventType?.description ? markdownToSafeHTML(eventType.description) : undefined, users: await Promise.all( - (!!eventType?.hosts?.length ? eventType?.hosts.map((host) => host.user) : eventType.users).map( + (eventType?.hosts?.length ? eventType?.hosts.map((host) => host.user) : eventType.users).map( async (u) => await userRepo.enrichUserWithItsProfile({ user: u, diff --git a/packages/features/eventtypes/lib/getPublicEvent.ts b/packages/features/eventtypes/lib/getPublicEvent.ts index 17c516dabe..75d3fc1fe3 100644 --- a/packages/features/eventtypes/lib/getPublicEvent.ts +++ b/packages/features/eventtypes/lib/getPublicEvent.ts @@ -4,15 +4,15 @@ import { getAppFromSlug } from "@calcom/app-store/utils"; import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/app-store/zod-utils"; import dayjs from "@calcom/dayjs"; import { getBookingFieldsWithSystemFields } from "@calcom/features/bookings/lib/getBookingFields"; +import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; import { getSlugOrRequestedSlug } from "@calcom/features/ee/organizations/lib/orgDomains"; +import { getDefaultEvent, getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { getOrgOrTeamAvatar } from "@calcom/lib/defaultAvatarImage"; import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; -import { getDefaultEvent, getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents"; import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; -import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; import { isRecurringEvent, parseRecurringEvent } from "@calcom/lib/isRecurringEvent"; import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import type { PrismaClient } from "@calcom/prisma"; import type { User as UserType } from "@calcom/prisma/client"; import type { Prisma } from "@calcom/prisma/client"; @@ -635,7 +635,7 @@ export async function getUsersFromEvent( ) { const { team, hosts, subsetOfHosts, owner, id } = event; if (team) { - const eventHosts = !!hosts?.length ? hosts : subsetOfHosts; + const eventHosts = hosts?.length ? hosts : subsetOfHosts; // getOwnerFromUsersArray is used here for backward compatibility when team event type has users[] but not hosts[] return eventHosts.length ? eventHosts.filter((host) => host.user.username).map(mapHostsToUsers) diff --git a/packages/features/eventtypes/repositories/eventTypeRepository.ts b/packages/features/eventtypes/repositories/eventTypeRepository.ts index bb6cfebc84..b90d013b8d 100644 --- a/packages/features/eventtypes/repositories/eventTypeRepository.ts +++ b/packages/features/eventtypes/repositories/eventTypeRepository.ts @@ -1,10 +1,10 @@ +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { LookupTarget, ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import type { UserWithLegacySelectedCalendars } from "@calcom/features/users/repositories/UserRepository"; import { withSelectedCalendars } from "@calcom/features/users/repositories/UserRepository"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import { eventTypeSelect } from "@calcom/lib/server/eventTypeSelect"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import type { PrismaClient } from "@calcom/prisma"; import { prisma, availabilityUserSelect } from "@calcom/prisma"; import type { EventType as PrismaEventType } from "@calcom/prisma/client"; diff --git a/packages/features/form-builder/FormBuilder.tsx b/packages/features/form-builder/FormBuilder.tsx index 0bf7f725e3..17f8fa9898 100644 --- a/packages/features/form-builder/FormBuilder.tsx +++ b/packages/features/form-builder/FormBuilder.tsx @@ -426,7 +426,7 @@ export const FormBuilder = function FormBuilder({ function Options({ label = "Options", value, - // eslint-disable-next-line @typescript-eslint/no-empty-function + onChange = () => {}, className = "", readOnly = false, @@ -700,7 +700,7 @@ function FieldEditDialog({ /> ) : null} - {!!fieldType?.supportsLengthCheck ? ( + {fieldType?.supportsLengthCheck ? ( ) : null} diff --git a/packages/features/handleMarkNoShow.ts b/packages/features/handleMarkNoShow.ts index b33cd78b68..177ffdceb8 100644 --- a/packages/features/handleMarkNoShow.ts +++ b/packages/features/handleMarkNoShow.ts @@ -4,12 +4,12 @@ import { BookingRepository } from "@calcom/features/bookings/repositories/Bookin import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import { workflowSelect } from "@calcom/features/ee/workflows/lib/getAllWorkflows"; import type { ExtendedCalendarEvent } from "@calcom/features/ee/workflows/lib/reminders/reminderScheduler"; +import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import { WebhookService } from "@calcom/features/webhooks/lib/WebhookService"; import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId"; import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat"; import { prisma } from "@calcom/prisma"; import { WebhookTriggerEvents, WorkflowTriggerEvents } from "@calcom/prisma/enums"; @@ -249,7 +249,7 @@ const handleMarkNoShow = async ({ : booking.user?.destinationCalendar ? [booking.user?.destinationCalendar] : []; - const team = !!booking.eventType?.team + const team = booking.eventType?.team ? { name: booking.eventType.team.name, id: booking.eventType.team.id, diff --git a/packages/features/insights/server/routing-events.ts b/packages/features/insights/server/routing-events.ts index 35725af575..5c17974cab 100644 --- a/packages/features/insights/server/routing-events.ts +++ b/packages/features/insights/server/routing-events.ts @@ -1,6 +1,6 @@ -// eslint-disable-next-line no-restricted-imports + import mapKeys from "lodash/mapKeys"; -// eslint-disable-next-line no-restricted-imports + import startCase from "lodash/startCase"; import { diff --git a/packages/features/insights/server/trpc-router.ts b/packages/features/insights/server/trpc-router.ts index 65022aae2b..0367ecf671 100644 --- a/packages/features/insights/server/trpc-router.ts +++ b/packages/features/insights/server/trpc-router.ts @@ -1,6 +1,8 @@ import { z } from "zod"; import dayjs from "@calcom/dayjs"; +import { getInsightsBookingService } from "@calcom/features/di/containers/InsightsBooking"; +import { getInsightsRoutingService } from "@calcom/features/di/containers/InsightsRouting"; import { extractDateRangeFromColumnFilters, replaceDateRangeColumnFilter, @@ -13,8 +15,6 @@ import { routedToPerPeriodCsvInputSchema, bookingRepositoryBaseInputSchema, } from "@calcom/features/insights/server/raw-data.schema"; -import { getInsightsBookingService } from "@calcom/features/di/containers/InsightsBooking"; -import { getInsightsRoutingService } from "@calcom/features/di/containers/InsightsRouting"; import type { PrismaClient } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import authedProcedure from "@calcom/trpc/server/procedures/authedProcedure"; diff --git a/packages/features/insights/services/InsightsBookingBaseService.ts b/packages/features/insights/services/InsightsBookingBaseService.ts index 6272aa0c94..4f35a6d50b 100644 --- a/packages/features/insights/services/InsightsBookingBaseService.ts +++ b/packages/features/insights/services/InsightsBookingBaseService.ts @@ -12,11 +12,11 @@ import { isNumberFilterValue, isDateRangeFilterValue, } from "@calcom/features/data-table/lib/utils"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { extractDateRangeFromColumnFilters } from "@calcom/features/insights/lib/bookingUtils"; import type { DateRange } from "@calcom/features/insights/server/insightsDateUtils"; -import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; +import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import type { PrismaClient } from "@calcom/prisma"; import { Prisma } from "@calcom/prisma/client"; import { MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/features/insights/services/InsightsRoutingBaseService.ts b/packages/features/insights/services/InsightsRoutingBaseService.ts index 7c19cfb788..a2680a71e0 100644 --- a/packages/features/insights/services/InsightsRoutingBaseService.ts +++ b/packages/features/insights/services/InsightsRoutingBaseService.ts @@ -10,9 +10,9 @@ import { isNumberFilterValue, isSingleSelectFilterValue, } from "@calcom/features/data-table/lib/utils"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import type { DateRange } from "@calcom/features/insights/server/insightsDateUtils"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import type { PrismaClient } from "@calcom/prisma"; import { Prisma } from "@calcom/prisma/client"; import type { BookingStatus } from "@calcom/prisma/enums"; diff --git a/packages/features/pbac/domain/types/permission-registry.ts b/packages/features/pbac/domain/types/permission-registry.ts index b54b70e3f7..7511b7ae85 100644 --- a/packages/features/pbac/domain/types/permission-registry.ts +++ b/packages/features/pbac/domain/types/permission-registry.ts @@ -121,7 +121,6 @@ export const isValidPermissionString = (val: unknown): val is PermissionString = * @returns A new object without the _resource property */ export const filterResourceConfig = (config: ResourceConfig): Omit => { - const { _resource, ...rest } = config; return rest; }; diff --git a/packages/features/pbac/lib/__tests__/event-type-permissions.test.ts b/packages/features/pbac/lib/__tests__/event-type-permissions.test.ts index adf7904bec..8f9494a9c5 100644 --- a/packages/features/pbac/lib/__tests__/event-type-permissions.test.ts +++ b/packages/features/pbac/lib/__tests__/event-type-permissions.test.ts @@ -423,11 +423,9 @@ describe("getEventTypePermissions", () => { }); it("should use org MEMBER role when user has no team membership", async () => { - (prisma.membership.findFirst as Mock) - .mockResolvedValueOnce(null) - .mockResolvedValueOnce({ - role: MembershipRole.MEMBER, - }); + (prisma.membership.findFirst as Mock).mockResolvedValueOnce(null).mockResolvedValueOnce({ + role: MembershipRole.MEMBER, + }); const result = await getEventTypePermissions(1, 2); @@ -459,9 +457,7 @@ describe("getEventTypePermissions", () => { describe("error handling", () => { it("should propagate errors from FeaturesRepository", async () => { - mockFeaturesRepository.checkIfTeamHasFeature.mockRejectedValue( - new Error("Database connection failed") - ); + mockFeaturesRepository.checkIfTeamHasFeature.mockRejectedValue(new Error("Database connection failed")); await expect(getEventTypePermissions(1, 2)).rejects.toThrow("Database connection failed"); }); diff --git a/packages/features/pbac/services/legacy-role-manager.service.ts b/packages/features/pbac/services/legacy-role-manager.service.ts index b1a6cdab90..14e0c807ce 100644 --- a/packages/features/pbac/services/legacy-role-manager.service.ts +++ b/packages/features/pbac/services/legacy-role-manager.service.ts @@ -112,7 +112,7 @@ export class LegacyRoleManager implements IRoleManager { organizationId: number, role: MembershipRole | string, // Used in other implementation - // eslint-disable-next-line @typescript-eslint/no-unused-vars + _membershipId: number ): Promise { await prisma.membership.update({ @@ -129,7 +129,7 @@ export class LegacyRoleManager implements IRoleManager { } // Used in other implementation - // eslint-disable-next-line @typescript-eslint/no-unused-vars + async getAllRoles(_organizationId: number): Promise<{ id: string; name: string }[]> { return [ { id: MembershipRole.OWNER, name: "Owner" }, @@ -139,7 +139,7 @@ export class LegacyRoleManager implements IRoleManager { } // Used in other implementation - // eslint-disable-next-line @typescript-eslint/no-unused-vars + async getTeamRoles(_teamId: number): Promise<{ id: string; name: string }[]> { return [ { id: MembershipRole.OWNER, name: "Owner" }, @@ -147,4 +147,4 @@ export class LegacyRoleManager implements IRoleManager { { id: MembershipRole.MEMBER, name: "Member" }, ]; } -} \ No newline at end of file +} diff --git a/packages/features/pbac/services/permission-check.service.ts b/packages/features/pbac/services/permission-check.service.ts index 56398690bf..370449ed35 100644 --- a/packages/features/pbac/services/permission-check.service.ts +++ b/packages/features/pbac/services/permission-check.service.ts @@ -1,6 +1,6 @@ import { FeaturesRepository } from "@calcom/features/flags/features.repository"; -import logger from "@calcom/lib/logger"; import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import logger from "@calcom/lib/logger"; import prisma from "@calcom/prisma"; import type { MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/features/profile/lib/createAProfileForAnExistingUser.ts b/packages/features/profile/lib/createAProfileForAnExistingUser.ts index 860e675fcc..6bd2f6f720 100644 --- a/packages/features/profile/lib/createAProfileForAnExistingUser.ts +++ b/packages/features/profile/lib/createAProfileForAnExistingUser.ts @@ -1,10 +1,10 @@ import { getOrgFullOrigin } from "@calcom/ee/organizations/lib/orgDomains"; import { getOrgUsernameFromEmail } from "@calcom/features/auth/signup/utils/getOrgUsernameFromEmail"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import prisma from "@calcom/prisma"; import { RedirectType } from "@calcom/prisma/enums"; diff --git a/packages/features/profile/lib/hideBranding.ts b/packages/features/profile/lib/hideBranding.ts index e82c2ecf4d..9603bae5ce 100644 --- a/packages/features/profile/lib/hideBranding.ts +++ b/packages/features/profile/lib/hideBranding.ts @@ -1,7 +1,7 @@ +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import logger from "@calcom/lib/logger"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { prisma } from "@calcom/prisma"; const log = logger.getSubLogger({ name: "hideBranding" }); diff --git a/packages/features/routing-forms/lib/getRoutedUrl.test.ts b/packages/features/routing-forms/lib/getRoutedUrl.test.ts index 25b0bf4d5b..7b5e4a7255 100644 --- a/packages/features/routing-forms/lib/getRoutedUrl.test.ts +++ b/packages/features/routing-forms/lib/getRoutedUrl.test.ts @@ -12,9 +12,9 @@ import { findMatchingRoute } from "@calcom/app-store/routing-forms/lib/processRo import { substituteVariables } from "@calcom/app-store/routing-forms/lib/substituteVariables"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; import { isAuthorizedToViewFormOnOrgDomain } from "@calcom/features/routing-forms/lib/isAuthorizedToViewForm"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError"; import { PrismaRoutingFormRepository } from "@calcom/lib/server/repository/PrismaRoutingFormRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { getRoutedUrl } from "./getRoutedUrl"; import { getUrlSearchParamsToForward } from "./getUrlSearchParamsToForward"; diff --git a/packages/features/routing-forms/lib/getRoutedUrl.ts b/packages/features/routing-forms/lib/getRoutedUrl.ts index cb58c40f84..d354740261 100644 --- a/packages/features/routing-forms/lib/getRoutedUrl.ts +++ b/packages/features/routing-forms/lib/getRoutedUrl.ts @@ -16,17 +16,18 @@ import { substituteVariables } from "@calcom/app-store/routing-forms/lib/substit import type { FormResponse } from "@calcom/app-store/routing-forms/types/types"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; import { isAuthorizedToViewFormOnOrgDomain } from "@calcom/features/routing-forms/lib/isAuthorizedToViewForm"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError"; +import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import { withReporting } from "@calcom/lib/sentryWrapper"; import { PrismaRoutingFormRepository } from "@calcom/lib/server/repository/PrismaRoutingFormRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import prisma from "@calcom/prisma"; + import { TRPCError } from "@trpc/server"; import { getUrlSearchParamsToForward } from "./getUrlSearchParamsToForward"; -import { HttpError } from "@calcom/lib/http-error"; const log = logger.getSubLogger({ prefix: ["[routing-forms]", "[router]"] }); const querySchema = z @@ -181,7 +182,7 @@ const _getRoutedUrl = async (context: Pick { const existingBookingReferences = await prisma.bookingReference.findMany({ where: { bookingId: booking.id, + deleted: null, }, }); diff --git a/packages/features/timezone-buddy/components/AvailabilitySliderTable.tsx b/packages/features/timezone-buddy/components/AvailabilitySliderTable.tsx index 75a12ce69e..23c6dbc5da 100644 --- a/packages/features/timezone-buddy/components/AvailabilitySliderTable.tsx +++ b/packages/features/timezone-buddy/components/AvailabilitySliderTable.tsx @@ -9,8 +9,8 @@ import dayjs from "@calcom/dayjs"; import { DataTableProvider } from "@calcom/features/data-table/DataTableProvider"; import { DataTable, DataTableToolbar } from "@calcom/features/data-table/components"; import { useDataTable } from "@calcom/features/data-table/hooks"; -import { APP_NAME, WEBAPP_URL } from "@calcom/lib/constants"; import type { DateRange } from "@calcom/features/schedules/lib/date-ranges"; +import { APP_NAME, WEBAPP_URL } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { CURRENT_TIMEZONE } from "@calcom/lib/timezoneConstants"; import type { MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/features/users/lib/deleteUser.ts b/packages/features/users/lib/deleteUser.ts index 555ce45823..8dcbb3b3e1 100644 --- a/packages/features/users/lib/deleteUser.ts +++ b/packages/features/users/lib/deleteUser.ts @@ -1,7 +1,6 @@ -import type { User } from "@calcom/prisma/client"; - import { deleteStripeCustomer } from "@calcom/app-store/stripepayment/lib/customer"; import prisma from "@calcom/prisma"; +import type { User } from "@calcom/prisma/client"; export async function deleteUser(user: Pick) { // If 2FA is disabled or totpCode is valid then delete the user from stripe and database diff --git a/packages/features/users/lib/getRoutedUsers.ts b/packages/features/users/lib/getRoutedUsers.ts index b3c4ea2009..8e84b28279 100644 --- a/packages/features/users/lib/getRoutedUsers.ts +++ b/packages/features/users/lib/getRoutedUsers.ts @@ -1,7 +1,7 @@ +import { findTeamMembersMatchingAttributeLogic } from "@calcom/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic"; import { enrichHostsWithDelegationCredentials } from "@calcom/app-store/delegationCredential"; import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId"; import logger from "@calcom/lib/logger"; -import { findTeamMembersMatchingAttributeLogic } from "@calcom/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic"; import type { AttributesQueryValue } from "@calcom/lib/raqb/types"; import { safeStringify } from "@calcom/lib/safeStringify"; import type { RRResetInterval } from "@calcom/prisma/client"; diff --git a/packages/features/users/repositories/UserRepository.test.ts b/packages/features/users/repositories/UserRepository.test.ts index fbe2b30fca..10c26ae85b 100644 --- a/packages/features/users/repositories/UserRepository.test.ts +++ b/packages/features/users/repositories/UserRepository.test.ts @@ -1,4 +1,4 @@ -// eslint-disable-next-line @typescript-eslint/no-unused-vars + import prismock from "../../../../tests/libs/__mocks__/prisma"; import { describe, test, vi, expect, beforeEach } from "vitest"; diff --git a/packages/features/users/services/userCreationService.ts b/packages/features/users/services/userCreationService.ts index 59ac593e19..5fb9f9f2ee 100644 --- a/packages/features/users/services/userCreationService.ts +++ b/packages/features/users/services/userCreationService.ts @@ -1,8 +1,8 @@ +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { sentrySpan } from "@calcom/features/watchlist/lib/telemetry"; import { checkIfEmailIsBlockedInWatchlistController } from "@calcom/features/watchlist/operations/check-if-email-in-watchlist.controller"; import { hashPassword } from "@calcom/lib/auth/hashPassword"; import logger from "@calcom/lib/logger"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import slugify from "@calcom/lib/slugify"; import prisma from "@calcom/prisma"; import type { CreationSource, UserPermissionRole, IdentityProvider } from "@calcom/prisma/enums"; diff --git a/packages/features/watchlist/lib/service/SpamCheckService.ts b/packages/features/watchlist/lib/service/SpamCheckService.ts index 7b2d6a0bf3..1965d11667 100644 --- a/packages/features/watchlist/lib/service/SpamCheckService.ts +++ b/packages/features/watchlist/lib/service/SpamCheckService.ts @@ -17,9 +17,9 @@ export class SpamCheckService { constructor( private readonly globalBlockingService: GlobalBlockingService, private readonly organizationBlockingService: OrganizationBlockingService - ) { } + ) {} - startCheck({ email, organizationId }: { email: string, organizationId: number | null }): void { + startCheck({ email, organizationId }: { email: string; organizationId: number | null }): void { this.spamCheckPromise = this.isBlocked(email, organizationId ?? undefined).catch((error) => { logger.error("Error starting spam check", safeStringify(error)); return { isBlocked: false }; diff --git a/packages/features/watchlist/lib/testUtils.ts b/packages/features/watchlist/lib/testUtils.ts index c0f93e3b5c..ed2d6b173a 100644 --- a/packages/features/watchlist/lib/testUtils.ts +++ b/packages/features/watchlist/lib/testUtils.ts @@ -11,7 +11,6 @@ export const createWatchlistEntry = async (input: WatchlistInput) => { await prismock.watchlist.create({ data: { ...input, - createdById: 0, }, }); }; diff --git a/packages/features/webhooks/lib/interface/repository.ts b/packages/features/webhooks/lib/interface/repository.ts index 3e89392210..6a4792147c 100644 --- a/packages/features/webhooks/lib/interface/repository.ts +++ b/packages/features/webhooks/lib/interface/repository.ts @@ -1,5 +1,5 @@ -import type { WebhookTriggerEvents, UserPermissionRole } from "@calcom/prisma/enums"; import type { Webhook } from "@calcom/prisma/client"; +import type { WebhookTriggerEvents, UserPermissionRole } from "@calcom/prisma/enums"; import type { WebhookSubscriber } from "../dto/types"; @@ -42,10 +42,7 @@ export interface IWebhookRepository { time: number | null; timeUnit: string | null; }>; - getFilteredWebhooksForUser(options: { - userId: number; - userRole?: UserPermissionRole; - }): Promise<{ + getFilteredWebhooksForUser(options: { userId: number; userRole?: UserPermissionRole }): Promise<{ webhookGroups: WebhookGroup[]; profiles: { teamId: number | null | undefined; diff --git a/packages/features/webhooks/pages/webhooks-view.tsx b/packages/features/webhooks/pages/webhooks-view.tsx index 5905d1e834..d6c3460e06 100644 --- a/packages/features/webhooks/pages/webhooks-view.tsx +++ b/packages/features/webhooks/pages/webhooks-view.tsx @@ -41,7 +41,7 @@ const WebhooksList = ({ webhooksByViewer }: { webhooksByViewer: WebhooksByViewer description={t("add_webhook_description", { appName: APP_NAME })} CTA={webhooksByViewer.webhookGroups.length > 0 ? : null} borderInShellHeader={false}> - {!!webhookGroups.length ? ( + {webhookGroups.length ? (
    {webhookGroups.map((group) => (
    diff --git a/packages/lib/CalendarService.ts b/packages/lib/CalendarService.ts index 47d692a4e9..ec090504df 100644 --- a/packages/lib/CalendarService.ts +++ b/packages/lib/CalendarService.ts @@ -17,7 +17,6 @@ import { v4 as uuidv4 } from "uuid"; import dayjs from "@calcom/dayjs"; import sanitizeCalendarObject from "@calcom/lib/sanitizeCalendarObject"; -import type { Prisma } from "@calcom/prisma/client"; import type { Person as AttendeeInCalendarEvent } from "@calcom/types/Calendar"; import type { Calendar, @@ -707,7 +706,8 @@ export default abstract class BaseCalendarService implements Calendar { } private async getEventsByUID(uid: string): Promise { - const events: Prisma.PromiseReturnType = []; + type EventsType = Awaited>; + const events: EventsType = []; const calendars = await this.listCalendars(); for (const cal of calendars) { diff --git a/packages/lib/server/repository/PrismaPhoneNumberRepository.ts b/packages/lib/server/repository/PrismaPhoneNumberRepository.ts index d56a424bb7..1739249697 100644 --- a/packages/lib/server/repository/PrismaPhoneNumberRepository.ts +++ b/packages/lib/server/repository/PrismaPhoneNumberRepository.ts @@ -86,7 +86,9 @@ export class PrismaPhoneNumberRepository { const phoneNumberIds = phoneNumbers.map((pn) => pn.id); const agents = phoneNumberIds.length > 0 - ? await this.prismaClient.$queryRaw<(AgentRawResult & { phoneNumberId: number; agentType: string })[]>` + ? await this.prismaClient.$queryRaw< + (AgentRawResult & { phoneNumberId: number; agentType: string })[] + >` SELECT a.id, a.name, @@ -236,15 +238,7 @@ export class PrismaPhoneNumberRepository { }); } - async findByIdWithTeamAccess({ - id, - teamId, - userId, - }: { - id: number; - teamId: number; - userId: number; - }) { + async findByIdWithTeamAccess({ id, teamId, userId }: { id: number; teamId: number; userId: number }) { const accessibleTeamIds = await this.getUserAccessibleTeamIds(userId); if (!accessibleTeamIds.includes(teamId)) { @@ -380,7 +374,9 @@ export class PrismaPhoneNumberRepository { const phoneNumberIds = phoneNumbers.map((pn) => pn.id); const agents = phoneNumberIds.length > 0 - ? await this.prismaClient.$queryRaw<(AgentRawResult & { phoneNumberId: number; agentType: string })[]>` + ? await this.prismaClient.$queryRaw< + (AgentRawResult & { phoneNumberId: number; agentType: string })[] + >` SELECT a.id, a.name, @@ -522,13 +518,7 @@ export class PrismaPhoneNumberRepository { }); } - async updateInboundAgentId({ - id, - agentId, - }: { - id: number; - agentId: string; - }) { + async updateInboundAgentId({ id, agentId }: { id: number; agentId: string }) { // Atomic update: only set if inboundAgentId is currently null return await this.prismaClient.calAiPhoneNumber.updateMany({ where: { diff --git a/packages/lib/server/repository/bookingReference.integration-test.ts b/packages/lib/server/repository/bookingReference.integration-test.ts new file mode 100644 index 0000000000..b1e01a49bd --- /dev/null +++ b/packages/lib/server/repository/bookingReference.integration-test.ts @@ -0,0 +1,382 @@ +import { describe, it, expect, beforeAll, afterAll, afterEach } from "vitest"; + +import { BookingReferenceRepository } from "@calcom/lib/server/repository/bookingReference"; +import prisma from "@calcom/prisma"; +import type { Booking, Credential, User } from "@calcom/prisma/client"; + +describe("BookingReferenceRepository Integration Tests", () => { + let testUser: User; + let testCredential: Credential; + let testBooking: Booking; + const createdBookingReferenceIds: number[] = []; + + beforeAll(async () => { + testUser = await prisma.user.create({ + data: { + email: "bookingreference-test@example.com", + username: "bookingreference-test", + }, + }); + + testCredential = await prisma.credential.create({ + data: { + type: "google_calendar", + key: {}, + userId: testUser.id, + }, + }); + + testBooking = await prisma.booking.create({ + data: { + uid: "test-booking-uid-123", + title: "Test Booking", + startTime: new Date(), + endTime: new Date(), + userId: testUser.id, + }, + }); + }); + + afterEach(async () => { + if (createdBookingReferenceIds.length > 0) { + await prisma.bookingReference.deleteMany({ + where: { + id: { + in: createdBookingReferenceIds, + }, + }, + }); + createdBookingReferenceIds.splice(0, createdBookingReferenceIds.length); + } + }); + + afterAll(async () => { + await prisma.booking.delete({ + where: { + id: testBooking.id, + }, + }); + + await prisma.credential.delete({ + where: { + id: testCredential.id, + }, + }); + + await prisma.user.delete({ + where: { + id: testUser.id, + }, + }); + }); + + describe("replaceBookingReferences", () => { + it("should soft-delete existing references and create new ones", async () => { + const existingReference1 = await prisma.bookingReference.create({ + data: { + type: "google_calendar", + uid: "old-ref-1", + meetingId: "old-meeting-1", + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(existingReference1.id); + + const existingReference2 = await prisma.bookingReference.create({ + data: { + type: "google_calendar", + uid: "old-ref-2", + meetingId: "old-meeting-2", + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(existingReference2.id); + + const newReferences = [ + { + type: "google_calendar", + uid: "new-ref-1", + meetingId: "new-meeting-1", + credentialId: testCredential.id, + }, + { + type: "google_calendar", + uid: "new-ref-2", + meetingId: "new-meeting-2", + credentialId: testCredential.id, + }, + ]; + + await BookingReferenceRepository.replaceBookingReferences({ + bookingId: testBooking.id, + newReferencesToCreate: newReferences, + }); + + const allReferences = await prisma.bookingReference.findMany({ + where: { + bookingId: testBooking.id, + }, + }); + + const oldReferences = allReferences.filter((ref) => ref.uid === "old-ref-1" || ref.uid === "old-ref-2"); + const newlyCreatedReferences = allReferences.filter( + (ref) => ref.uid === "new-ref-1" || ref.uid === "new-ref-2" + ); + + expect(oldReferences).toHaveLength(2); + expect(oldReferences.every((ref) => ref.deleted === true)).toBe(true); + + expect(newlyCreatedReferences).toHaveLength(2); + expect(newlyCreatedReferences.every((ref) => ref.deleted === null)).toBe(true); + + newlyCreatedReferences.forEach((ref) => { + createdBookingReferenceIds.push(ref.id); + }); + }); + + it("should only soft-delete references of the same type as new references being created", async () => { + const googleRef = await prisma.bookingReference.create({ + data: { + type: "google_calendar", + uid: "google-ref", + meetingId: "google-meeting", + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(googleRef.id); + + const zoomRef = await prisma.bookingReference.create({ + data: { + type: "zoom_video", + uid: "zoom-ref", + meetingId: "zoom-meeting", + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(zoomRef.id); + + const newGoogleReferences = [ + { + type: "google_calendar", + uid: "new-google-ref", + meetingId: "new-google-meeting", + credentialId: testCredential.id, + }, + ]; + + await BookingReferenceRepository.replaceBookingReferences({ + bookingId: testBooking.id, + newReferencesToCreate: newGoogleReferences, + }); + + const googleRefAfter = await prisma.bookingReference.findUnique({ + where: { id: googleRef.id }, + }); + expect(googleRefAfter?.deleted).toBe(true); + + const zoomRefAfter = await prisma.bookingReference.findUnique({ + where: { id: zoomRef.id }, + }); + expect(zoomRefAfter?.deleted).toBe(null); + + const newRef = await prisma.bookingReference.findFirst({ + where: { + uid: "new-google-ref", + bookingId: testBooking.id, + }, + }); + expect(newRef).toBeDefined(); + expect(newRef?.deleted).toBe(null); + if (newRef) { + createdBookingReferenceIds.push(newRef.id); + } + }); + + it("should persist soft-deleted records in database", async () => { + const reference = await prisma.bookingReference.create({ + data: { + type: "daily_video", + uid: "daily-ref", + meetingId: "daily-meeting", + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(reference.id); + + const newReferences = [ + { + type: "daily_video", + uid: "new-daily-ref", + meetingId: "new-daily-meeting", + credentialId: testCredential.id, + }, + ]; + + await BookingReferenceRepository.replaceBookingReferences({ + bookingId: testBooking.id, + newReferencesToCreate: newReferences, + }); + + const deletedRefInDb = await prisma.bookingReference.findUnique({ + where: { id: reference.id }, + }); + expect(deletedRefInDb).toBeDefined(); + expect(deletedRefInDb?.deleted).toBe(true); + expect(deletedRefInDb?.uid).toBe("daily-ref"); + + const newRef = await prisma.bookingReference.findFirst({ + where: { + uid: "new-daily-ref", + bookingId: testBooking.id, + }, + }); + if (newRef) { + createdBookingReferenceIds.push(newRef.id); + } + }); + }); + + describe("findDailyVideoReferenceByRoomName", () => { + it("should find active daily video references", async () => { + const roomName = "test-daily-room-123"; + const dailyRef = await prisma.bookingReference.create({ + data: { + type: "daily_video", + uid: roomName, + meetingId: roomName, + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(dailyRef.id); + + const result = await BookingReferenceRepository.findDailyVideoReferenceByRoomName({ + roomName, + }); + + expect(result).toBeDefined(); + expect(result?.id).toBe(dailyRef.id); + expect(result?.uid).toBe(roomName); + expect(result?.deleted).toBe(null); + }); + + it("should exclude soft-deleted daily video references", async () => { + const roomName = "test-daily-room-deleted-456"; + const dailyRef = await prisma.bookingReference.create({ + data: { + type: "daily_video", + uid: roomName, + meetingId: roomName, + credentialId: testCredential.id, + bookingId: testBooking.id, + deleted: true, + }, + }); + createdBookingReferenceIds.push(dailyRef.id); + + const result = await BookingReferenceRepository.findDailyVideoReferenceByRoomName({ + roomName, + }); + + expect(result).toBeNull(); + }); + + it("should return null when room name does not exist", async () => { + const result = await BookingReferenceRepository.findDailyVideoReferenceByRoomName({ + roomName: "non-existent-room", + }); + + expect(result).toBeNull(); + }); + + it("should not return daily video references without a booking", async () => { + const roomName = "test-daily-room-no-booking"; + const dailyRef = await prisma.bookingReference.create({ + data: { + type: "daily_video", + uid: roomName, + meetingId: roomName, + credentialId: testCredential.id, + bookingId: null, + }, + }); + createdBookingReferenceIds.push(dailyRef.id); + + const result = await BookingReferenceRepository.findDailyVideoReferenceByRoomName({ + roomName, + }); + + expect(result).toBeNull(); + }); + }); + + describe("Soft-delete behavior verification", () => { + it("should not return soft-deleted references in regular queries", async () => { + const activeRef = await prisma.bookingReference.create({ + data: { + type: "zoom_video", + uid: "active-zoom", + meetingId: "active-zoom-meeting", + credentialId: testCredential.id, + bookingId: testBooking.id, + }, + }); + createdBookingReferenceIds.push(activeRef.id); + + const deletedRef = await prisma.bookingReference.create({ + data: { + type: "zoom_video", + uid: "deleted-zoom", + meetingId: "deleted-zoom-meeting", + credentialId: testCredential.id, + bookingId: testBooking.id, + deleted: true, + }, + }); + createdBookingReferenceIds.push(deletedRef.id); + + const foundReferences = await prisma.bookingReference.findMany({ + where: { + bookingId: testBooking.id, + type: "zoom_video", + deleted: null, + }, + }); + + expect(foundReferences).toHaveLength(1); + expect(foundReferences[0].id).toBe(activeRef.id); + expect(foundReferences[0].uid).toBe("active-zoom"); + }); + + it("should allow querying soft-deleted references explicitly", async () => { + const deletedRef = await prisma.bookingReference.create({ + data: { + type: "office365_calendar", + uid: "deleted-office365", + meetingId: "deleted-office365-meeting", + credentialId: testCredential.id, + bookingId: testBooking.id, + deleted: true, + }, + }); + createdBookingReferenceIds.push(deletedRef.id); + + const foundDeletedReferences = await prisma.bookingReference.findMany({ + where: { + bookingId: testBooking.id, + deleted: true, + }, + }); + + expect(foundDeletedReferences.length).toBeGreaterThan(0); + const ourDeletedRef = foundDeletedReferences.find((ref) => ref.id === deletedRef.id); + expect(ourDeletedRef).toBeDefined(); + expect(ourDeletedRef?.uid).toBe("deleted-office365"); + }); + }); +}); diff --git a/packages/lib/server/repository/bookingReference.ts b/packages/lib/server/repository/bookingReference.ts index 29fdd886fd..f5d49a9c3f 100644 --- a/packages/lib/server/repository/bookingReference.ts +++ b/packages/lib/server/repository/bookingReference.ts @@ -16,7 +16,13 @@ const bookingReferenceSelect = { export class BookingReferenceRepository { static async findDailyVideoReferenceByRoomName({ roomName }: { roomName: string }) { return prisma.bookingReference.findFirst({ - where: { type: "daily_video", uid: roomName, meetingId: roomName, bookingId: { not: null } }, + where: { + type: "daily_video", + uid: roomName, + meetingId: roomName, + bookingId: { not: null }, + deleted: null, + }, select: bookingReferenceSelect, }); } @@ -33,13 +39,16 @@ export class BookingReferenceRepository { }) { const newReferenceTypes = newReferencesToCreate.map((reference) => reference.type); - await prisma.bookingReference.deleteMany({ + await prisma.bookingReference.updateMany({ where: { bookingId, type: { in: newReferenceTypes, }, }, + data: { + deleted: true, + }, }); await prisma.bookingReference.createMany({ diff --git a/packages/platform/atoms/booker/BookerPlatformWrapper.tsx b/packages/platform/atoms/booker/BookerPlatformWrapper.tsx index 5e20dbf4e7..ae5fbffc4a 100644 --- a/packages/platform/atoms/booker/BookerPlatformWrapper.tsx +++ b/packages/platform/atoms/booker/BookerPlatformWrapper.tsx @@ -1,6 +1,6 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { useQueryClient } from "@tanstack/react-query"; -// eslint-disable-next-line no-restricted-imports + import debounce from "lodash/debounce"; import { useMemo, useEffect, useCallback, useState, useRef, useContext } from "react"; import { shallow } from "zustand/shallow"; @@ -19,10 +19,10 @@ import { useLocalSet } from "@calcom/features/bookings/Booker/components/hooks/u import { usePrefetch } from "@calcom/features/bookings/Booker/components/hooks/usePrefetch"; import { useInitializeBookerStore } from "@calcom/features/bookings/Booker/store"; import { useTimePreferences } from "@calcom/features/bookings/lib"; +import type { ConnectedDestinationCalendars } from "@calcom/features/calendars/lib/getConnectedDestinationCalendars"; +import { getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents"; import { useTimesForSchedule } from "@calcom/features/schedules/lib/use-schedule/useTimesForSchedule"; import { getRoutedTeamMemberIdsFromSearchParams } from "@calcom/lib/bookings/getRoutedTeamMemberIdsFromSearchParams"; -import { getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents"; -import type { ConnectedDestinationCalendars } from "@calcom/features/calendars/lib/getConnectedDestinationCalendars"; import { localStorage } from "@calcom/lib/webstorage"; import { BookerLayouts } from "@calcom/prisma/zod-utils"; @@ -364,7 +364,7 @@ const BookerPlatformWrapperComponent = ( schedule.refetch(); props.onCreateRecurringBookingSuccess?.(data); - if (!!event?.data?.successRedirectUrl) { + if (event?.data?.successRedirectUrl) { window.location.href = event?.data?.successRedirectUrl; } }, diff --git a/packages/platform/atoms/event-types/wrappers/EventAdvancedWebWrapper.tsx b/packages/platform/atoms/event-types/wrappers/EventAdvancedWebWrapper.tsx index 5d67a53ea1..e262bcdf59 100644 --- a/packages/platform/atoms/event-types/wrappers/EventAdvancedWebWrapper.tsx +++ b/packages/platform/atoms/event-types/wrappers/EventAdvancedWebWrapper.tsx @@ -1,7 +1,7 @@ import type { EventAdvancedBaseProps } from "@calcom/features/eventtypes/components/tabs/advanced/EventAdvancedTab"; import { EventAdvancedTab } from "@calcom/features/eventtypes/components/tabs/advanced/EventAdvancedTab"; -import { trpc } from "@calcom/trpc/react"; import { localeOptions } from "@calcom/lib/i18n"; +import { trpc } from "@calcom/trpc/react"; const EventAdvancedWebWrapper = ({ ...props }: EventAdvancedBaseProps) => { const connectedCalendarsQuery = trpc.viewer.calendars.connectedCalendars.useQuery(); diff --git a/packages/platform/libraries/slots.ts b/packages/platform/libraries/slots.ts index e4679c1e53..d3925543f2 100644 --- a/packages/platform/libraries/slots.ts +++ b/packages/platform/libraries/slots.ts @@ -1,7 +1,7 @@ -import { validateRoundRobinSlotAvailability } from "@calcom/features/ee/round-robin/utils/validateRoundRobinSlotAvailability"; import { FilterHostsService } from "@calcom/features/bookings/lib/host-filtering/filterHostsBySameRoundRobinHost"; import { QualifiedHostsService } from "@calcom/features/bookings/lib/host-filtering/findQualifiedHostsWithDelegationCredentials"; import { BusyTimesService } from "@calcom/features/busyTimes/services/getBusyTimes"; +import { validateRoundRobinSlotAvailability } from "@calcom/features/ee/round-robin/utils/validateRoundRobinSlotAvailability"; import { NoSlotsNotificationService } from "@calcom/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots"; import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util"; diff --git a/packages/platform/libraries/vite.config.js b/packages/platform/libraries/vite.config.js index 62cc96342d..da6a1981ef 100644 --- a/packages/platform/libraries/vite.config.js +++ b/packages/platform/libraries/vite.config.js @@ -1,3 +1,4 @@ +/* eslint-disable no-undef */ // vite.config.ts import react from "@vitejs/plugin-react"; import { resolve } from "path"; @@ -7,6 +8,9 @@ import dts from "vite-plugin-dts"; // https://vitejs.dev/guide/build.html#library-mode export default defineConfig({ + define: { + "process.env.USE_POOL": `"true"`, + }, esbuild: { target: "node18", platform: "node", @@ -50,6 +54,8 @@ export default defineConfig({ "fs/promises", "perf_hooks", "@prisma/client", + "@prisma/adapter-pg", + "pg", "async", "libphonenumber-js", "lodash", @@ -121,6 +127,8 @@ export default defineConfig({ "fs/promises": "fs/promises", perf_hooks: "perf_hooks", "@prisma/client": "@prisma/client", + "@prisma/adapter-pg": "@prisma/adapter-pg", + pg: "pg", async: "async", "libphonenumber-js": "libphonenumber-js", lodash: "lodash", @@ -187,6 +195,7 @@ export default defineConfig({ }, plugins: [react(), dts()], resolve: { + conditions: ["node", "import", "require", "default"], alias: { "@calcom/lib/server/i18n": path.resolve(__dirname, "./i18n.ts"), "./server/i18n": path.resolve(__dirname, "./i18n.ts"), @@ -195,13 +204,10 @@ export default defineConfig({ "@calcom/lib": path.resolve(__dirname, "../../lib"), "@calcom/trpc": resolve("../../trpc"), "lru-cache": resolve("../../../node_modules/lru-cache/dist/cjs/index.js"), - "@calcom/prisma/client/runtime/library": resolve( - "../../../node_modules/@calcom/prisma/client/runtime/library.js" - ), - "@calcom/prisma/client": resolve("../../../node_modules/@calcom/prisma/client/index.js"), + "@calcom/prisma/client/runtime/library": resolve("../../prisma/client/runtime/library"), + "@calcom/prisma/client": resolve("../../prisma/client"), "@calcom/platform-constants": path.resolve(__dirname, "../constants/index.ts"), "@calcom/platform-types": path.resolve(__dirname, "../types/index.ts"), - // eslint-disable-next-line prettier/prettier tslog: path.resolve(__dirname, "../../../apps/api/v2/src/lib/logger.bridge.ts"), }, }, diff --git a/packages/prisma/auto-migrations.ts b/packages/prisma/auto-migrations.ts index 2286f5d801..9af3fe3a38 100644 --- a/packages/prisma/auto-migrations.ts +++ b/packages/prisma/auto-migrations.ts @@ -26,6 +26,10 @@ async function main(): Promise { console.info("No DATABASE_DIRECT_URL found, skipping migrations"); return; } + if (process.env.CI) { + console.info("Running in CI mode, skipping migrations"); + return; + } if (!(await isPrismaAvailableCheck())) { console.info("Prisma can't be initialized, skipping migrations"); return; diff --git a/packages/prisma/client/index.ts b/packages/prisma/client/index.ts new file mode 100644 index 0000000000..bd6691c4bf --- /dev/null +++ b/packages/prisma/client/index.ts @@ -0,0 +1,2 @@ +// INFO: This is to keep backwards compatibility with hundreds of imports before v6.16 of Prisma +export * from "../generated/prisma/client"; diff --git a/packages/prisma/extensions/disallow-undefined-delete-update-many.ts b/packages/prisma/extensions/disallow-undefined-delete-update-many.ts index a25a1ce9fb..0c2b2b17a3 100644 --- a/packages/prisma/extensions/disallow-undefined-delete-update-many.ts +++ b/packages/prisma/extensions/disallow-undefined-delete-update-many.ts @@ -1,4 +1,4 @@ -import { Prisma } from "@calcom/prisma/client"; +import { Prisma } from "../client"; export const checkUndefinedInValue = (where: any) => { if (where) { @@ -28,10 +28,14 @@ export function disallowUndefinedDeleteUpdateManyExtension() { return Prisma.defineExtension({ query: { $allModels: { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore async deleteMany({ args, query }) { checkUndefinedInValue(args.where); return query(args); }, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore async updateMany({ args, query }) { checkUndefinedInValue(args.where); return query(args); diff --git a/packages/prisma/index.ts b/packages/prisma/index.ts index c014de6c7d..cebded00bf 100644 --- a/packages/prisma/index.ts +++ b/packages/prisma/index.ts @@ -1,18 +1,31 @@ -import { PrismaClient, type Prisma } from "@calcom/prisma/client"; +import { PrismaPg } from "@prisma/adapter-pg"; +import { Pool } from "pg"; import { bookingIdempotencyKeyExtension } from "./extensions/booking-idempotency-key"; import { disallowUndefinedDeleteUpdateManyExtension } from "./extensions/disallow-undefined-delete-update-many"; import { excludeLockedUsersExtension } from "./extensions/exclude-locked-users"; import { excludePendingPaymentsExtension } from "./extensions/exclude-pending-payment-teams"; import { usageTrackingExtention } from "./extensions/usage-tracking"; -import { bookingReferenceMiddleware } from "./middleware"; +import { PrismaClient, type Prisma } from "./generated/prisma/client"; -const prismaOptions: Prisma.PrismaClientOptions = {}; +const connectionString = process.env.DATABASE_URL || ""; +const pool = + process.env.USE_POOL === "true" || process.env.USE_POOL === "1" + ? new Pool({ + connectionString: connectionString, + max: 5, + idleTimeoutMillis: 300000, + }) + : undefined; + +const adapter = pool ? new PrismaPg(pool) : new PrismaPg({ connectionString }); +const prismaOptions: Prisma.PrismaClientOptions = { + adapter, +}; const globalForPrisma = global as unknown as { baseClient: PrismaClient; }; - const loggerLevel = parseInt(process.env.NEXT_PUBLIC_LOGGER_LEVEL ?? "", 10); if (!isNaN(loggerLevel)) { @@ -33,20 +46,32 @@ if (!isNaN(loggerLevel)) { break; } } - const baseClient = globalForPrisma.baseClient || new PrismaClient(prismaOptions); -export const customPrisma = (options?: Prisma.PrismaClientOptions) => - new PrismaClient({ ...prismaOptions, ...options }) +export const customPrisma = (options?: Prisma.PrismaClientOptions) => { + let finalOptions = { ...prismaOptions }; + + if (options?.datasources?.db?.url) { + const customConnectionString = options.datasources.db.url; + const customAdapter = new PrismaPg({ connectionString: customConnectionString }); + + const { datasources: _datasources, ...restOptions } = options; + finalOptions = { + ...prismaOptions, + ...restOptions, + adapter: customAdapter, + }; + } else if (options) { + finalOptions = { ...prismaOptions, ...options }; + } + + return new PrismaClient(finalOptions) .$extends(usageTrackingExtention(baseClient)) .$extends(excludeLockedUsersExtension()) .$extends(excludePendingPaymentsExtension()) .$extends(bookingIdempotencyKeyExtension()) .$extends(disallowUndefinedDeleteUpdateManyExtension()) as unknown as PrismaClient; - -// If any changed on middleware server restart is required -// TODO: Migrate it to $extends -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'` diff --git a/packages/prisma/is-prisma-available-check.ts b/packages/prisma/is-prisma-available-check.ts index 9c94a867cc..98dcc2a039 100644 --- a/packages/prisma/is-prisma-available-check.ts +++ b/packages/prisma/is-prisma-available-check.ts @@ -1,11 +1,10 @@ -import { Prisma } from "./client"; +import { Prisma } from "@calcom/prisma/client"; export async function isPrismaAvailableCheck(): Promise { try { - const { PrismaClient } = await import("./client"); - const prisma = new PrismaClient(); + const { prisma } = await import("./index"); - await prisma.$queryRawUnsafe("SELECT 1"); + await prisma.$queryRaw(Prisma.sql`SELECT 1`); await prisma.$disconnect(); return true; } catch (e: unknown) { diff --git a/packages/prisma/middleware/bookingReference.ts b/packages/prisma/middleware/bookingReference.ts deleted file mode 100644 index 057933b7f0..0000000000 --- a/packages/prisma/middleware/bookingReference.ts +++ /dev/null @@ -1,50 +0,0 @@ -import type { PrismaClient } from "../client"; - -function middleware(prisma: PrismaClient) { - /***********************************/ - /* SOFT DELETE MIDDLEWARE */ - /***********************************/ - prisma.$use(async (params, next) => { - // Check incoming query type - - if (params.model === "BookingReference") { - if (params.action === "delete") { - // Delete queries - // Change action to an update - params.action = "update"; - params.args["data"] = { deleted: true }; - } - if (params.action === "deleteMany") { - // Delete many queries - params.action = "updateMany"; - if (params.args.data !== undefined) { - params.args.data["deleted"] = true; - } else { - params.args["data"] = { deleted: true }; - } - } - if (params.action === "findUnique") { - // Change to findFirst - you cannot filter - // by anything except ID / unique with findUnique - params.action = "findFirst"; - // Add 'deleted' filter - // ID filter maintained - params.args.where["deleted"] = null; - } - if (params.action === "findMany" || params.action === "findFirst") { - // Find many queries - if (params.args.where !== undefined) { - if (params.args.where.deleted === undefined) { - // Exclude deleted records if they have not been explicitly requested - params.args.where["deleted"] = null; - } - } else { - params.args["where"] = { deleted: null }; - } - } - } - return next(params); - }); -} - -export default middleware; diff --git a/packages/prisma/middleware/index.ts b/packages/prisma/middleware/index.ts deleted file mode 100644 index 90097ed181..0000000000 --- a/packages/prisma/middleware/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as bookingReferenceMiddleware } from "./bookingReference"; diff --git a/packages/prisma/package.json b/packages/prisma/package.json index 3f2b7178d1..c8254f5c4d 100644 --- a/packages/prisma/package.json +++ b/packages/prisma/package.json @@ -23,10 +23,11 @@ }, "dependencies": { "@calcom/lib": "workspace:*", - "@prisma/client": "^6.7.0", + "@prisma/adapter-pg": "^6.16.0", + "@prisma/client": "^6.16.0", "@prisma/extension-accelerate": "^1.3.0", - "@prisma/generator-helper": "^6.7.0", - "prisma": "^6.7.0", + "@prisma/generator-helper": "^6.16.0", + "prisma": "^6.16.0", "prisma-kysely": "2.2.0", "ts-node": "^10.9.1", "zod": "^3.22.4", @@ -39,6 +40,7 @@ "types": "index.d.ts", "files": [ "client", + "generated/prisma", "zod", "zod-utils.ts" ], diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 0b2d04e7e5..707c4466ec 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -8,17 +8,12 @@ datasource db { } generator client { - provider = "prisma-client-js" - previewFeatures = ["views"] - output = "./client" - binaryTargets = ["native", "debian-openssl-1.1.x"] -} - -generator client_for_api_v2 { - provider = "prisma-client-js" - previewFeatures = ["views"] - output = "../../apps/api/v2/client" - binaryTargets = ["native", "debian-openssl-1.1.x"] + provider = "prisma-client" + previewFeatures = ["views"] + output = "./generated/prisma" + engineType = "client" + moduleFormat = "cjs" + importFileExtension = "" } generator zod { @@ -29,6 +24,8 @@ generator zod { addIncludeType = false addSelectType = false validateWhereUniqueInput = false + prismaClientPath = "../../generated/prisma/client" + moduleFormat = "cjs" /// createRelationValuesTypes = true } diff --git a/packages/trpc/server/middlewares/sessionMiddleware.ts b/packages/trpc/server/middlewares/sessionMiddleware.ts index d7b9a19f85..ffddaa0198 100644 --- a/packages/trpc/server/middlewares/sessionMiddleware.ts +++ b/packages/trpc/server/middlewares/sessionMiddleware.ts @@ -1,11 +1,11 @@ import { setUser as SentrySetUser } from "@sentry/nextjs"; import type { Session } from "next-auth"; +import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { WEBAPP_URL } from "@calcom/lib/constants"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import prisma from "@calcom/prisma"; import { teamMetadataSchema, userMetadata } from "@calcom/prisma/zod-utils"; diff --git a/packages/trpc/server/routers/apps/routing-forms/formMutation.handler.ts b/packages/trpc/server/routers/apps/routing-forms/formMutation.handler.ts index 36d66ce286..c114336ad0 100644 --- a/packages/trpc/server/routers/apps/routing-forms/formMutation.handler.ts +++ b/packages/trpc/server/routers/apps/routing-forms/formMutation.handler.ts @@ -1,6 +1,3 @@ -import type { App_RoutingForms_Form } from "@calcom/prisma/client"; -import { Prisma } from "@calcom/prisma/client"; - import { createFallbackRoute } from "@calcom/app-store/routing-forms/lib/createFallbackRoute"; import { getSerializableForm } from "@calcom/app-store/routing-forms/lib/getSerializableForm"; import { isFallbackRoute } from "@calcom/app-store/routing-forms/lib/isFallbackRoute"; @@ -8,9 +5,14 @@ import isRouter from "@calcom/app-store/routing-forms/lib/isRouter"; import isRouterLinkedField from "@calcom/app-store/routing-forms/lib/isRouterLinkedField"; import type { SerializableForm } from "@calcom/app-store/routing-forms/types/types"; import { zodFields, zodRouterRoute, zodRoutes } from "@calcom/app-store/routing-forms/zod"; +import { + entityPrismaWhereClause, + canEditEntity, +} from "@calcom/features/pbac/lib/entityPermissionUtils.server"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; -import { entityPrismaWhereClause, canEditEntity } from "@calcom/features/pbac/lib/entityPermissionUtils.server"; import type { PrismaClient } from "@calcom/prisma"; +import type { App_RoutingForms_Form } from "@calcom/prisma/client"; +import { Prisma } from "@calcom/prisma/client"; import { MembershipRole } from "@calcom/prisma/enums"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; diff --git a/packages/trpc/server/routers/apps/routing-forms/forms.handler.ts b/packages/trpc/server/routers/apps/routing-forms/forms.handler.ts index 8501f83a63..17d6d2675f 100644 --- a/packages/trpc/server/routers/apps/routing-forms/forms.handler.ts +++ b/packages/trpc/server/routers/apps/routing-forms/forms.handler.ts @@ -3,7 +3,10 @@ import type { z } from "zod"; import { getSerializableForm } from "@calcom/app-store/routing-forms/lib/getSerializableForm"; import type { zodFields, zodRoutes } from "@calcom/app-store/routing-forms/zod"; import { hasFilter } from "@calcom/features/filters/lib/hasFilter"; -import { entityPrismaWhereClause, canEditEntity } from "@calcom/features/pbac/lib/entityPermissionUtils.server"; +import { + entityPrismaWhereClause, + canEditEntity, +} from "@calcom/features/pbac/lib/entityPermissionUtils.server"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import type { PrismaClient } from "@calcom/prisma"; diff --git a/packages/trpc/server/routers/viewer/aiVoiceAgent/listCalls.handler.ts b/packages/trpc/server/routers/viewer/aiVoiceAgent/listCalls.handler.ts index e66ce00aea..96170be00e 100644 --- a/packages/trpc/server/routers/viewer/aiVoiceAgent/listCalls.handler.ts +++ b/packages/trpc/server/routers/viewer/aiVoiceAgent/listCalls.handler.ts @@ -1,7 +1,7 @@ import { createDefaultAIPhoneServiceProvider } from "@calcom/features/calAIPhone"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import logger from "@calcom/lib/logger"; import { CalAiPhoneNumberRepository } from "@calcom/lib/server/repository/calAiPhoneNumber"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { MembershipRole } from "@calcom/prisma/enums"; import { TRPCError } from "@trpc/server"; diff --git a/packages/trpc/server/routers/viewer/aiVoiceAgent/setupInboundAgent.schema.ts b/packages/trpc/server/routers/viewer/aiVoiceAgent/setupInboundAgent.schema.ts index 6babe71a18..b689859d0d 100644 --- a/packages/trpc/server/routers/viewer/aiVoiceAgent/setupInboundAgent.schema.ts +++ b/packages/trpc/server/routers/viewer/aiVoiceAgent/setupInboundAgent.schema.ts @@ -6,4 +6,4 @@ export const ZSetupInboundAgentInputSchema = z.object({ workflowStepId: z.number(), }); -export type TSetupInboundAgentInputSchema = z.infer; \ No newline at end of file +export type TSetupInboundAgentInputSchema = z.infer; diff --git a/packages/trpc/server/routers/viewer/aiVoiceAgent/updateInboundAgentEventType.handler.ts b/packages/trpc/server/routers/viewer/aiVoiceAgent/updateInboundAgentEventType.handler.ts index c24805fa52..f20048cbce 100644 --- a/packages/trpc/server/routers/viewer/aiVoiceAgent/updateInboundAgentEventType.handler.ts +++ b/packages/trpc/server/routers/viewer/aiVoiceAgent/updateInboundAgentEventType.handler.ts @@ -3,6 +3,7 @@ import { replaceEventTypePlaceholders } from "@calcom/features/ee/workflows/comp import logger from "@calcom/lib/logger"; import { PrismaAgentRepository } from "@calcom/lib/server/repository/PrismaAgentRepository"; import prisma from "@calcom/prisma"; + import type { TrpcSessionUser } from "../../../types"; import type { TUpdateInboundAgentEventTypeInputSchema } from "./updateInboundAgentEventType.schema"; diff --git a/packages/trpc/server/routers/viewer/aiVoiceAgent/updateInboundAgentEventType.schema.ts b/packages/trpc/server/routers/viewer/aiVoiceAgent/updateInboundAgentEventType.schema.ts index a6960d46e8..caca28c2b9 100644 --- a/packages/trpc/server/routers/viewer/aiVoiceAgent/updateInboundAgentEventType.schema.ts +++ b/packages/trpc/server/routers/viewer/aiVoiceAgent/updateInboundAgentEventType.schema.ts @@ -6,4 +6,4 @@ export const ZUpdateInboundAgentEventTypeInputSchema = z.object({ teamId: z.number().optional(), }); -export type TUpdateInboundAgentEventTypeInputSchema = z.infer; \ No newline at end of file +export type TUpdateInboundAgentEventTypeInputSchema = z.infer; diff --git a/packages/trpc/server/routers/viewer/apps/appById.handler.ts b/packages/trpc/server/routers/viewer/apps/appById.handler.ts index 9b45a322d6..3737db59cf 100644 --- a/packages/trpc/server/routers/viewer/apps/appById.handler.ts +++ b/packages/trpc/server/routers/viewer/apps/appById.handler.ts @@ -24,7 +24,7 @@ export const appByIdHandler = async ({ ctx, input }: AppByIdOptions) => { throw new TRPCError({ code: "BAD_REQUEST", message: `Could not find app ${appId}` }); } - // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { credential: _, credentials: _1, ...app } = appFromDb; return { isInstalled: appFromDb.credentials.length, diff --git a/packages/trpc/server/routers/viewer/apps/queryForDependencies.handler.ts b/packages/trpc/server/routers/viewer/apps/queryForDependencies.handler.ts index 19c441953f..48b9849716 100644 --- a/packages/trpc/server/routers/viewer/apps/queryForDependencies.handler.ts +++ b/packages/trpc/server/routers/viewer/apps/queryForDependencies.handler.ts @@ -1,5 +1,5 @@ -import { getAppFromSlug } from "@calcom/app-store/utils"; import { getAllDelegationCredentialsForUserByAppSlug } from "@calcom/app-store/delegationCredential"; +import { getAppFromSlug } from "@calcom/app-store/utils"; import { prisma } from "@calcom/prisma"; import type { TrpcSessionUser } from "../../../types"; diff --git a/packages/trpc/server/routers/viewer/bookings/confirm.handler.ts b/packages/trpc/server/routers/viewer/bookings/confirm.handler.ts index f975a7f8d3..b1545acdd2 100644 --- a/packages/trpc/server/routers/viewer/bookings/confirm.handler.ts +++ b/packages/trpc/server/routers/viewer/bookings/confirm.handler.ts @@ -7,16 +7,16 @@ import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventR import { handleConfirmation } from "@calcom/features/bookings/lib/handleConfirmation"; import { handleWebhookTrigger } from "@calcom/features/bookings/lib/handleWebhookTrigger"; import { processPaymentRefund } from "@calcom/features/bookings/lib/payment/processPaymentRefund"; +import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import { workflowSelect } from "@calcom/features/ee/workflows/lib/getAllWorkflows"; +import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import type { GetSubscriberOptions } from "@calcom/features/webhooks/lib/getWebhooks"; import type { EventPayloadType, EventTypeInfo } from "@calcom/features/webhooks/lib/sendPayload"; -import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId"; import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType"; import { isPrismaObjOrUndefined } from "@calcom/lib/isPrismaObj"; import { parseRecurringEvent } from "@calcom/lib/isRecurringEvent"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { WorkflowService } from "@calcom/features/ee/workflows/lib/service/WorkflowService"; import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat"; import { prisma } from "@calcom/prisma"; import { Prisma } from "@calcom/prisma/client"; @@ -239,7 +239,7 @@ export const confirmHandler = async ({ ctx, input }: ConfirmOptions) => { hideCalendarEventDetails: booking.eventType?.hideCalendarEventDetails, eventTypeId: booking.eventType?.id, customReplyToEmail: booking.eventType?.customReplyToEmail, - team: !!booking.eventType?.team + team: booking.eventType?.team ? { name: booking.eventType.team.name, id: booking.eventType.team.id, @@ -326,7 +326,7 @@ export const confirmHandler = async ({ ctx, input }: ConfirmOptions) => { }); } else { // handle refunds - if (!!booking.payment.length) { + if (booking.payment.length) { await processPaymentRefund({ booking: booking, teamId: booking.eventType?.teamId, diff --git a/packages/trpc/server/routers/viewer/bookings/editLocation.handler.ts b/packages/trpc/server/routers/viewer/bookings/editLocation.handler.ts index 48ab05b92a..94a61f29d3 100644 --- a/packages/trpc/server/routers/viewer/bookings/editLocation.handler.ts +++ b/packages/trpc/server/routers/viewer/bookings/editLocation.handler.ts @@ -5,14 +5,14 @@ import { getEventLocationType, OrganizerDefaultConferencingAppType } from "@calc import { getAppFromSlug } from "@calcom/app-store/utils"; import { sendLocationChangeEmailsAndSMS } from "@calcom/emails"; import EventManager from "@calcom/features/bookings/lib/EventManager"; +import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; +import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { getVideoCallUrlFromCalEvent } from "@calcom/lib/CalEventParser"; import { buildCalEventFromBooking } from "@calcom/lib/buildCalEventFromBooking"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; -import { CredentialRepository } from "@calcom/features/credentials/repositories/CredentialRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { prisma } from "@calcom/prisma"; import type { Booking, BookingReference } from "@calcom/prisma/client"; import type { userMetadata } from "@calcom/prisma/zod-utils"; diff --git a/packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts b/packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts index a41f304843..0168c20931 100644 --- a/packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts +++ b/packages/trpc/server/routers/viewer/bookings/requestReschedule.handler.ts @@ -7,6 +7,8 @@ import dayjs from "@calcom/dayjs"; import { sendRequestRescheduleEmailAndSMS } from "@calcom/emails"; import { getCalEventResponses } from "@calcom/features/bookings/lib/getCalEventResponses"; import { deleteMeeting } from "@calcom/features/conferencing/lib/videoClient"; +import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; +import { WorkflowRepository } from "@calcom/features/ee/workflows/repositories/WorkflowRepository"; import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks"; import { deleteWebhookScheduledTriggers, @@ -15,13 +17,11 @@ import { import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload"; import { CalendarEventBuilder } from "@calcom/lib/builders/CalendarEvent/builder"; import { CalendarEventDirector } from "@calcom/lib/builders/CalendarEvent/director"; -import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId"; import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { WorkflowRepository } from "@calcom/features/ee/workflows/repositories/WorkflowRepository"; import { BookingWebhookFactory } from "@calcom/lib/server/service/BookingWebhookFactory"; import { prisma } from "@calcom/prisma"; import type { BookingReference, EventType } from "@calcom/prisma/client"; @@ -208,7 +208,7 @@ export const requestRescheduleHandler = async ({ ctx, input }: RequestReschedule organizer, iCalUID: bookingToReschedule.iCalUID, customReplyToEmail: bookingToReschedule.eventType?.customReplyToEmail, - team: !!bookingToReschedule.eventType?.team + team: bookingToReschedule.eventType?.team ? { name: bookingToReschedule.eventType.team.name, id: bookingToReschedule.eventType.team.id, diff --git a/packages/trpc/server/routers/viewer/calVideo/getDownloadLinkOfCalVideoRecordings.handler.ts b/packages/trpc/server/routers/viewer/calVideo/getDownloadLinkOfCalVideoRecordings.handler.ts index 6be2f16969..e6f3d14db0 100644 --- a/packages/trpc/server/routers/viewer/calVideo/getDownloadLinkOfCalVideoRecordings.handler.ts +++ b/packages/trpc/server/routers/viewer/calVideo/getDownloadLinkOfCalVideoRecordings.handler.ts @@ -1,6 +1,6 @@ /// -import { IS_SELF_HOSTED } from "@calcom/lib/constants"; import { getDownloadLinkOfCalVideoByRecordingId } from "@calcom/features/conferencing/lib/videoClient"; +import { IS_SELF_HOSTED } from "@calcom/lib/constants"; import { TRPCError } from "@trpc/server"; diff --git a/packages/trpc/server/routers/viewer/credits/buyCredits.handler.ts b/packages/trpc/server/routers/viewer/credits/buyCredits.handler.ts index e3a61baff2..bbce6372b8 100644 --- a/packages/trpc/server/routers/viewer/credits/buyCredits.handler.ts +++ b/packages/trpc/server/routers/viewer/credits/buyCredits.handler.ts @@ -1,9 +1,9 @@ import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service"; -import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; -import { WEBAPP_URL } from "@calcom/lib/constants"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { TeamService } from "@calcom/features/ee/teams/services/teamService"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; +import { WEBAPP_URL } from "@calcom/lib/constants"; import prisma from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; diff --git a/packages/trpc/server/routers/viewer/credits/downloadExpenseLog.handler.ts b/packages/trpc/server/routers/viewer/credits/downloadExpenseLog.handler.ts index 2a50b81f10..640143a6f2 100644 --- a/packages/trpc/server/routers/viewer/credits/downloadExpenseLog.handler.ts +++ b/packages/trpc/server/routers/viewer/credits/downloadExpenseLog.handler.ts @@ -1,6 +1,6 @@ +import { TeamService } from "@calcom/features/ee/teams/services/teamService"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { CreditsRepository } from "@calcom/lib/server/repository/credits"; -import { TeamService } from "@calcom/features/ee/teams/services/teamService"; import { MembershipRole } from "@calcom/prisma/enums"; import { TRPCError } from "@trpc/server"; diff --git a/packages/trpc/server/routers/viewer/credits/getAllCredits.handler.ts b/packages/trpc/server/routers/viewer/credits/getAllCredits.handler.ts index a65d56bf3b..a13fa34323 100644 --- a/packages/trpc/server/routers/viewer/credits/getAllCredits.handler.ts +++ b/packages/trpc/server/routers/viewer/credits/getAllCredits.handler.ts @@ -1,6 +1,6 @@ -import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { TeamService } from "@calcom/features/ee/teams/services/teamService"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { MembershipRole } from "@calcom/prisma/enums"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; diff --git a/packages/trpc/server/routers/viewer/delegationCredential/getAffectedMembersForDisable.handler.ts b/packages/trpc/server/routers/viewer/delegationCredential/getAffectedMembersForDisable.handler.ts index e821fc8f03..46d5e9e1e1 100644 --- a/packages/trpc/server/routers/viewer/delegationCredential/getAffectedMembersForDisable.handler.ts +++ b/packages/trpc/server/routers/viewer/delegationCredential/getAffectedMembersForDisable.handler.ts @@ -1,6 +1,6 @@ -import logger from "@calcom/lib/logger"; import { DelegationCredentialRepository } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository"; import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import logger from "@calcom/lib/logger"; import type { TDelegationCredentialGetAffectedMembersForDisableSchema } from "./schema"; diff --git a/packages/trpc/server/routers/viewer/delegationCredential/toggleEnabled.handler.ts b/packages/trpc/server/routers/viewer/delegationCredential/toggleEnabled.handler.ts index 44f68fa2c1..9dd32a3c03 100644 --- a/packages/trpc/server/routers/viewer/delegationCredential/toggleEnabled.handler.ts +++ b/packages/trpc/server/routers/viewer/delegationCredential/toggleEnabled.handler.ts @@ -1,11 +1,11 @@ import type { z } from "zod"; -import { sendDelegationCredentialDisabledEmail } from "@calcom/emails/email-manager"; import { checkIfSuccessfullyConfiguredInWorkspace } from "@calcom/app-store/delegationCredential"; -import logger from "@calcom/lib/logger"; -import { getTranslation } from "@calcom/lib/server/i18n"; +import { sendDelegationCredentialDisabledEmail } from "@calcom/emails/email-manager"; import { DelegationCredentialRepository } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository"; import type { ServiceAccountKey } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository"; +import logger from "@calcom/lib/logger"; +import { getTranslation } from "@calcom/lib/server/i18n"; import { getAffectedMembersForDisable } from "./getAffectedMembersForDisable.handler"; import type { DelegationCredentialToggleEnabledSchema } from "./schema"; diff --git a/packages/trpc/server/routers/viewer/delegationCredential/utils.ts b/packages/trpc/server/routers/viewer/delegationCredential/utils.ts index a237225cb0..9d05fd3870 100644 --- a/packages/trpc/server/routers/viewer/delegationCredential/utils.ts +++ b/packages/trpc/server/routers/viewer/delegationCredential/utils.ts @@ -1,8 +1,8 @@ import { z } from "zod"; +import { DelegationCredentialRepository } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { DelegationCredentialRepository } from "@calcom/features/delegation-credentials/repositories/DelegationCredentialRepository"; import type { Prisma } from "@calcom/prisma/client"; import { TRPCError } from "@trpc/server"; diff --git a/packages/trpc/server/routers/viewer/eventTypes/getEventTypesFromGroup.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/getEventTypesFromGroup.handler.ts index 9c92be1b29..d5a55ac4db 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/getEventTypesFromGroup.handler.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/getEventTypesFromGroup.handler.ts @@ -1,7 +1,7 @@ +import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { hasFilter } from "@calcom/features/filters/lib/hasFilter"; import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError"; import logger from "@calcom/lib/logger"; -import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { prisma } from "@calcom/prisma"; import type { PrismaClient } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; diff --git a/packages/trpc/server/routers/viewer/eventTypes/getUserEventGroups.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/getUserEventGroups.handler.ts index 1d2a82c7b1..0fd58452af 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/getUserEventGroups.handler.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/getUserEventGroups.handler.ts @@ -1,7 +1,7 @@ -import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; -import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError"; import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; +import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError"; import type { PrismaClient } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/trpc/server/routers/viewer/eventTypes/heavy/create.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/heavy/create.handler.ts index 509e7dfa2d..f9f34feecd 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/heavy/create.handler.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/heavy/create.handler.ts @@ -2,8 +2,8 @@ import type { z } from "zod"; import { getDefaultLocations } from "@calcom/app-store/_utils/getDefaultLocations"; import { DailyLocationType } from "@calcom/app-store/constants"; -import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; +import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import type { PrismaClient } from "@calcom/prisma"; import { Prisma } from "@calcom/prisma/client"; import { MembershipRole, SchedulingType } from "@calcom/prisma/enums"; diff --git a/packages/trpc/server/routers/viewer/eventTypes/heavy/duplicate.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/heavy/duplicate.handler.ts index bf26c9c6c2..67a136bad8 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/heavy/duplicate.handler.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/heavy/duplicate.handler.ts @@ -1,6 +1,6 @@ +import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { generateHashedLink } from "@calcom/lib/generateHashedLink"; import { CalVideoSettingsRepository } from "@calcom/lib/server/repository/calVideoSettings"; -import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { prisma } from "@calcom/prisma"; import { Prisma } from "@calcom/prisma/client"; @@ -94,13 +94,13 @@ export const duplicateHandler = async ({ ctx, input }: DuplicateOptions) => { workflows, hashedLink, destinationCalendar, - // eslint-disable-next-line @typescript-eslint/no-unused-vars + id: _id, - // eslint-disable-next-line @typescript-eslint/no-unused-vars + webhooks: _webhooks, - // eslint-disable-next-line @typescript-eslint/no-unused-vars + schedule: _schedule, - // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/ban-ts-comment + // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - descriptionAsSafeHTML is added on the fly using a prisma middleware it shouldn't be used to create event type. Such a property doesn't exist on schema descriptionAsSafeHTML: _descriptionAsSafeHTML, secondaryEmailId, @@ -146,7 +146,7 @@ export const duplicateHandler = async ({ ctx, input }: DuplicateOptions) => { }; // Validate the secondary email - if (!!secondaryEmailId) { + if (secondaryEmailId) { const secondaryEmail = await prisma.secondaryEmail.findUnique({ where: { id: secondaryEmailId, diff --git a/packages/trpc/server/routers/viewer/eventTypes/heavy/update.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/heavy/update.handler.ts index ec23c4e1d0..bca595b4ea 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/heavy/update.handler.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/heavy/update.handler.ts @@ -599,13 +599,13 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => { }, update: { ...aiPhoneCallConfig, - guestEmail: !!aiPhoneCallConfig?.guestEmail ? aiPhoneCallConfig.guestEmail : null, - guestCompany: !!aiPhoneCallConfig?.guestCompany ? aiPhoneCallConfig.guestCompany : null, + guestEmail: aiPhoneCallConfig?.guestEmail ? aiPhoneCallConfig.guestEmail : null, + guestCompany: aiPhoneCallConfig?.guestCompany ? aiPhoneCallConfig.guestCompany : null, }, create: { ...aiPhoneCallConfig, - guestEmail: !!aiPhoneCallConfig?.guestEmail ? aiPhoneCallConfig.guestEmail : null, - guestCompany: !!aiPhoneCallConfig?.guestCompany ? aiPhoneCallConfig.guestCompany : null, + guestEmail: aiPhoneCallConfig?.guestEmail ? aiPhoneCallConfig.guestEmail : null, + guestCompany: aiPhoneCallConfig?.guestCompany ? aiPhoneCallConfig.guestCompany : null, eventTypeId: id, }, }); diff --git a/packages/trpc/server/routers/viewer/eventTypes/util.ts b/packages/trpc/server/routers/viewer/eventTypes/util.ts index aba7dab84b..13f5d6308c 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/util.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/util.ts @@ -1,10 +1,10 @@ import { z } from "zod"; +import type { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import type { PermissionString } from "@calcom/features/pbac/domain/types/permission-registry"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; -import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; -import type { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; +import { markdownToSafeHTML } from "@calcom/lib/markdownToSafeHTML"; import prisma from "@calcom/prisma"; import type { MembershipRole } from "@calcom/prisma/enums"; import { PeriodType } from "@calcom/prisma/enums"; @@ -315,7 +315,7 @@ export const mapEventType = async (eventType: EventType) => ({ ...eventType, safeDescription: eventType?.description ? markdownToSafeHTML(eventType.description) : undefined, users: await Promise.all( - (!!eventType?.hosts?.length ? eventType?.hosts.map((host) => host.user) : eventType.users).map( + (eventType?.hosts?.length ? eventType?.hosts.map((host) => host.user) : eventType.users).map( async (u) => await new UserRepository(prisma).enrichUserWithItsProfile({ user: u, diff --git a/packages/trpc/server/routers/viewer/eventTypes/utils/transformUtils.ts b/packages/trpc/server/routers/viewer/eventTypes/utils/transformUtils.ts index fc7b32415f..3d1de82e8f 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/utils/transformUtils.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/utils/transformUtils.ts @@ -1,7 +1,7 @@ -import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; -import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; +import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; +import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; import type { MembershipRole } from "@calcom/prisma/enums"; import { teamMetadataSchema } from "@calcom/prisma/zod-utils"; diff --git a/packages/trpc/server/routers/viewer/me/get.handler.ts b/packages/trpc/server/routers/viewer/me/get.handler.ts index e860c01a10..dfca7e93b8 100644 --- a/packages/trpc/server/routers/viewer/me/get.handler.ts +++ b/packages/trpc/server/routers/viewer/me/get.handler.ts @@ -1,8 +1,8 @@ import type { Session } from "next-auth"; -import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; +import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; import prisma from "@calcom/prisma"; import { IdentityProvider, MembershipRole } from "@calcom/prisma/enums"; import { userMetadata } from "@calcom/prisma/zod-utils"; diff --git a/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts b/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts index 2056a038dc..70c5212308 100644 --- a/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts +++ b/packages/trpc/server/routers/viewer/me/updateProfile.handler.ts @@ -1,4 +1,4 @@ -// eslint-disable-next-line no-restricted-imports + import { keyBy } from "lodash"; import type { GetServerSidePropsContext, NextApiResponse } from "next"; @@ -7,11 +7,11 @@ import { sendChangeOfEmailVerification } from "@calcom/features/auth/lib/verifyE import { StripeBillingService } from "@calcom/features/ee/billing/stripe-billing-service"; import { updateNewTeamMemberEventTypes } from "@calcom/features/ee/teams/lib/queries"; import { FeaturesRepository } from "@calcom/features/flags/features.repository"; +import { checkUsername } from "@calcom/features/profile/lib/checkUsername"; import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata"; import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; import { uploadAvatar } from "@calcom/lib/server/avatar"; -import { checkUsername } from "@calcom/features/profile/lib/checkUsername"; import { getTranslation } from "@calcom/lib/server/i18n"; import { resizeBase64Image } from "@calcom/lib/server/resizeBase64Image"; import slugify from "@calcom/lib/slugify"; @@ -312,7 +312,7 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions) username: updatedUser.username ?? "Nameless User", emailFrom: user.email, // We know email has been changed here so we can use input - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + emailTo: input.email!, }, }); diff --git a/packages/trpc/server/routers/viewer/organizations/create.handler.ts b/packages/trpc/server/routers/viewer/organizations/create.handler.ts index 5b0f09d929..6d848e27e8 100644 --- a/packages/trpc/server/routers/viewer/organizations/create.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/create.handler.ts @@ -4,6 +4,8 @@ import { getOrgFullOrigin } from "@calcom/ee/organizations/lib/orgDomains"; import { isNotACompanyEmail } from "@calcom/ee/organizations/lib/server/orgCreationUtils"; import { sendAdminOrganizationNotification, sendOrganizationCreationEmail } from "@calcom/emails"; import { sendEmailVerification } from "@calcom/features/auth/lib/verifyEmail"; +import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability"; import { RESERVED_SUBDOMAINS, @@ -13,8 +15,6 @@ import { } from "@calcom/lib/constants"; import { createDomain } from "@calcom/lib/domainManager/organization"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { prisma } from "@calcom/prisma"; import { UserPermissionRole } from "@calcom/prisma/enums"; diff --git a/packages/trpc/server/routers/viewer/organizations/createTeams.handler.ts b/packages/trpc/server/routers/viewer/organizations/createTeams.handler.ts index b008162c38..ba83378688 100644 --- a/packages/trpc/server/routers/viewer/organizations/createTeams.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/createTeams.handler.ts @@ -2,9 +2,9 @@ import { getOrgFullOrigin } from "@calcom/ee/organizations/lib/orgDomains"; import { CreditService } from "@calcom/features/ee/billing/credit-service"; import stripe from "@calcom/features/ee/payments/server/stripe"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import slugify from "@calcom/lib/slugify"; import { prisma } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; diff --git a/packages/trpc/server/routers/viewer/organizations/createWithPaymentIntent.schema.ts b/packages/trpc/server/routers/viewer/organizations/createWithPaymentIntent.schema.ts index 7ee2074d52..3e569866fb 100644 --- a/packages/trpc/server/routers/viewer/organizations/createWithPaymentIntent.schema.ts +++ b/packages/trpc/server/routers/viewer/organizations/createWithPaymentIntent.schema.ts @@ -2,7 +2,6 @@ * @deprecated This schema is deprecated. Use ZIntentToCreateOrgInputSchema instead. * See createWithPaymentIntent.handler.ts for migration guide. */ - import type { z } from "zod"; import { createOrganizationSchema } from "@calcom/features/ee/organizations/types/schemas"; diff --git a/packages/trpc/server/routers/viewer/organizations/getTeams.handler.ts b/packages/trpc/server/routers/viewer/organizations/getTeams.handler.ts index 1027bdd7fa..cfe21d91bc 100644 --- a/packages/trpc/server/routers/viewer/organizations/getTeams.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/getTeams.handler.ts @@ -1,6 +1,6 @@ import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; -import { MembershipRole } from "@calcom/prisma/enums"; import { prisma } from "@calcom/prisma"; +import { MembershipRole } from "@calcom/prisma/enums"; import { TRPCError } from "@trpc/server"; diff --git a/packages/trpc/server/routers/viewer/organizations/list.handler.ts b/packages/trpc/server/routers/viewer/organizations/list.handler.ts index 924adc517b..216c2a47b7 100644 --- a/packages/trpc/server/routers/viewer/organizations/list.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/list.handler.ts @@ -1,5 +1,5 @@ -import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import { OrganizationRepository } from "@calcom/features/ee/organizations/repositories/OrganizationRepository"; +import { FeaturesRepository } from "@calcom/features/flags/features.repository"; import prisma from "@calcom/prisma"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; diff --git a/packages/trpc/server/routers/viewer/organizations/listMembers.handler.ts b/packages/trpc/server/routers/viewer/organizations/listMembers.handler.ts index e158a017d5..a172b86774 100644 --- a/packages/trpc/server/routers/viewer/organizations/listMembers.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/listMembers.handler.ts @@ -25,7 +25,7 @@ const isAllString = (array: (string | number)[]): array is string[] => { return array.every((value) => typeof value === "string"); }; function getUserConditions(oAuthClientId?: string) { - if (!!oAuthClientId) { + if (oAuthClientId) { return { platformOAuthClients: { some: { id: oAuthClientId }, diff --git a/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts b/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts index 3cc26caac7..049781a3c6 100644 --- a/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts @@ -6,7 +6,7 @@ import { checkRegularUsername } from "@calcom/features/profile/lib/checkRegularU import { uploadAvatar } from "@calcom/lib/server/avatar"; import { resizeBase64Image } from "@calcom/lib/server/resizeBase64Image"; import { prisma } from "@calcom/prisma"; -import type { Prisma, PrismaPromise, User, Membership, Profile } from "@calcom/prisma/client"; +import type { Prisma } from "@calcom/prisma/client"; import type { MembershipRole } from "@calcom/prisma/enums"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; @@ -132,7 +132,9 @@ export const updateUserHandler = async ({ ctx, input }: UpdateUserOptions) => { } // Update user - const transactions: PrismaPromise[] = [ + type TransactionPromise = ReturnType | ReturnType; + + const transactions: TransactionPromise[] = [ prisma.user.update({ where: { id: input.userId, diff --git a/packages/trpc/server/routers/viewer/routing-forms/findTeamMembersMatchingAttributeLogicOfRoute.handler.ts b/packages/trpc/server/routers/viewer/routing-forms/findTeamMembersMatchingAttributeLogicOfRoute.handler.ts index e71d5950eb..357b89fa38 100644 --- a/packages/trpc/server/routers/viewer/routing-forms/findTeamMembersMatchingAttributeLogicOfRoute.handler.ts +++ b/packages/trpc/server/routers/viewer/routing-forms/findTeamMembersMatchingAttributeLogicOfRoute.handler.ts @@ -6,15 +6,15 @@ import type { ServerResponse } from "http"; import type { NextApiResponse } from "next"; +import { findTeamMembersMatchingAttributeLogic } from "@calcom/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic"; import { enrichHostsWithDelegationCredentials } from "@calcom/app-store/delegationCredential"; import { enrichFormWithMigrationData } from "@calcom/app-store/routing-forms/enrichFormWithMigrationData"; import { getLuckyUserService } from "@calcom/features/di/containers/LuckyUser"; -import { getUrlSearchParamsToForwardForTestPreview } from "@calcom/features/routing-forms/lib/getUrlSearchParamsToForward"; -import { entityPrismaWhereClause } from "@calcom/features/pbac/lib/entityPermissionUtils.server"; -import { fromEntriesWithDuplicateKeys } from "@calcom/lib/fromEntriesWithDuplicateKeys"; -import { findTeamMembersMatchingAttributeLogic } from "@calcom/app-store/_utils/raqb/findTeamMembersMatchingAttributeLogic"; import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; +import { entityPrismaWhereClause } from "@calcom/features/pbac/lib/entityPermissionUtils.server"; +import { getUrlSearchParamsToForwardForTestPreview } from "@calcom/features/routing-forms/lib/getUrlSearchParamsToForward"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; +import { fromEntriesWithDuplicateKeys } from "@calcom/lib/fromEntriesWithDuplicateKeys"; import type { PrismaClient } from "@calcom/prisma"; import type { App_RoutingForms_Form } from "@calcom/prisma/client"; import { getAbsoluteEventTypeRedirectUrl } from "@calcom/routing-forms/getEventTypeRedirectUrl"; diff --git a/packages/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots.test.ts b/packages/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots.test.ts index e962ba6676..3531c2a38c 100644 --- a/packages/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots.test.ts +++ b/packages/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots.test.ts @@ -5,8 +5,8 @@ import { vi, describe, it, beforeAll, afterAll, expect, beforeEach, afterEach } import dayjs from "@calcom/dayjs"; import * as CalcomEmails from "@calcom/emails"; -import { RedisService } from "@calcom/features/redis/RedisService"; import { getNoSlotsNotificationService } from "@calcom/features/di/containers/NoSlotsNotification"; +import { RedisService } from "@calcom/features/redis/RedisService"; vi.mock("@calcom/features/redis/RedisService", () => { const mockedRedis = vi.fn(); diff --git a/packages/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots.ts b/packages/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots.ts index e0027751b1..c94c6324f5 100644 --- a/packages/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots.ts +++ b/packages/trpc/server/routers/viewer/slots/handleNotificationWhenNoSlots.ts @@ -1,10 +1,10 @@ import type { Dayjs } from "@calcom/dayjs"; import { sendOrganizationAdminNoSlotsNotification } from "@calcom/emails"; +import type { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; +import type { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import type { IRedisService } from "@calcom/features/redis/IRedisService"; import { IS_PRODUCTION, WEBAPP_URL } from "@calcom/lib/constants"; import { getTranslation } from "@calcom/lib/server/i18n"; -import type { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; -import type { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; type EventDetails = { username: string; diff --git a/packages/trpc/server/routers/viewer/slots/isAvailable.handler.ts b/packages/trpc/server/routers/viewer/slots/isAvailable.handler.ts index 1be3c06711..0727af5498 100644 --- a/packages/trpc/server/routers/viewer/slots/isAvailable.handler.ts +++ b/packages/trpc/server/routers/viewer/slots/isAvailable.handler.ts @@ -1,9 +1,9 @@ import type { NextApiRequest } from "next"; +import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import { HttpError } from "@calcom/lib/http-error"; import { getPastTimeAndMinimumBookingNoticeBoundsStatus } from "@calcom/lib/isOutOfBounds"; import { PrismaSelectedSlotRepository } from "@calcom/lib/server/repository/PrismaSelectedSlotRepository"; -import { EventTypeRepository } from "@calcom/features/eventtypes/repositories/eventTypeRepository"; import type { PrismaClient } from "@calcom/prisma"; import type { TIsAvailableInputSchema, TIsAvailableOutputSchema } from "./isAvailable.schema"; diff --git a/packages/trpc/server/routers/viewer/slots/util.ts b/packages/trpc/server/routers/viewer/slots/util.ts index 5f5e369ece..68f12eadc5 100644 --- a/packages/trpc/server/routers/viewer/slots/util.ts +++ b/packages/trpc/server/routers/viewer/slots/util.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line no-restricted-imports import type { Logger } from "tslog"; import { v4 as uuid } from "uuid"; @@ -253,7 +252,6 @@ export class AvailableSlotsService { ); const eventTypeId = input.eventTypeId || - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion (await this.getEventTypeId({ slug: usernameList?.[0], eventTypeSlug: eventTypeSlug, diff --git a/packages/trpc/server/routers/viewer/teams/changeMemberRole.handler.ts b/packages/trpc/server/routers/viewer/teams/changeMemberRole.handler.ts index 850b652993..aadfe8135a 100644 --- a/packages/trpc/server/routers/viewer/teams/changeMemberRole.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/changeMemberRole.handler.ts @@ -1,5 +1,5 @@ -import { RoleManagementFactory } from "@calcom/features/pbac/services/role-management.factory"; import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; +import { RoleManagementFactory } from "@calcom/features/pbac/services/role-management.factory"; import { prisma } from "@calcom/prisma"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; diff --git a/packages/trpc/server/routers/viewer/teams/create.handler.ts b/packages/trpc/server/routers/viewer/teams/create.handler.ts index e5cc55ce13..8dcbb87dfa 100644 --- a/packages/trpc/server/routers/viewer/teams/create.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/create.handler.ts @@ -1,7 +1,7 @@ import { generateTeamCheckoutSession } from "@calcom/features/ee/teams/lib/payments"; +import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants"; import { uploadLogo } from "@calcom/lib/server/avatar"; -import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import { resizeBase64Image } from "@calcom/lib/server/resizeBase64Image"; import { prisma } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/trpc/server/routers/viewer/teams/createInvite.handler.ts b/packages/trpc/server/routers/viewer/teams/createInvite.handler.ts index 03a68a8c56..a4bad516b5 100644 --- a/packages/trpc/server/routers/viewer/teams/createInvite.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/createInvite.handler.ts @@ -1,5 +1,5 @@ -import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { TeamService } from "@calcom/features/ee/teams/services/teamService"; +import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { prisma } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; diff --git a/packages/trpc/server/routers/viewer/teams/delete.handler.ts b/packages/trpc/server/routers/viewer/teams/delete.handler.ts index 9d460b4beb..f382a18013 100644 --- a/packages/trpc/server/routers/viewer/teams/delete.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/delete.handler.ts @@ -1,5 +1,5 @@ -import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { TeamService } from "@calcom/features/ee/teams/services/teamService"; +import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { prisma } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts b/packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts index 69db80c7c8..90d5c8fa9e 100644 --- a/packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts @@ -1,6 +1,6 @@ import { InternalTeamBilling } from "@calcom/ee/billing/teams/internal-team-billing"; -import { IS_SELF_HOSTED } from "@calcom/lib/constants"; import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; +import { IS_SELF_HOSTED } from "@calcom/lib/constants"; import { prisma } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; diff --git a/packages/trpc/server/routers/viewer/teams/inviteMember/inviteMember.handler.ts b/packages/trpc/server/routers/viewer/teams/inviteMember/inviteMember.handler.ts index 554aa56d58..dcb6e105a7 100644 --- a/packages/trpc/server/routers/viewer/teams/inviteMember/inviteMember.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/inviteMember/inviteMember.handler.ts @@ -1,12 +1,12 @@ import { type TFunction } from "i18next"; import { TeamBilling } from "@calcom/ee/billing/teams"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import { getTranslation } from "@calcom/lib/server/i18n"; import { isOrganisationOwner } from "@calcom/lib/server/queries/organisations"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import prisma from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; import type { CreationSource } from "@calcom/prisma/enums"; diff --git a/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts b/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts index f9b78a438b..3ff0895bc6 100644 --- a/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts +++ b/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts @@ -6,15 +6,15 @@ import { sendTeamInviteEmail } from "@calcom/emails"; import { checkAdminOrOwner } from "@calcom/features/auth/lib/checkAdminOrOwner"; import { updateNewTeamMemberEventTypes } from "@calcom/features/ee/teams/lib/queries"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; +import { createAProfileForAnExistingUser } from "@calcom/features/profile/lib/createAProfileForAnExistingUser"; +import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; +import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability"; import { ENABLE_PROFILE_SWITCHER, WEBAPP_URL } from "@calcom/lib/constants"; -import { createAProfileForAnExistingUser } from "@calcom/features/profile/lib/createAProfileForAnExistingUser"; import logger from "@calcom/lib/logger"; import { safeStringify } from "@calcom/lib/safeStringify"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; import { getParsedTeam } from "@calcom/lib/server/repository/teamUtils"; -import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import slugify from "@calcom/lib/slugify"; import { prisma } from "@calcom/prisma"; import type { Membership, OrganizationSettings, Team } from "@calcom/prisma/client"; diff --git a/packages/trpc/server/routers/viewer/teams/listMembers.handler.ts b/packages/trpc/server/routers/viewer/teams/listMembers.handler.ts index 5ae0aef261..1e0bb521d5 100644 --- a/packages/trpc/server/routers/viewer/teams/listMembers.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/listMembers.handler.ts @@ -1,3 +1,5 @@ +import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { Resource, CustomAction, @@ -6,8 +8,6 @@ import { import { getSpecificPermissions } from "@calcom/features/pbac/lib/resource-permissions"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { RoleManagementFactory } from "@calcom/features/pbac/services/role-management.factory"; -import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { UserRepository } from "@calcom/features/users/repositories/UserRepository"; import { prisma } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; diff --git a/packages/trpc/server/routers/viewer/teams/publish.handler.ts b/packages/trpc/server/routers/viewer/teams/publish.handler.ts index 5d7a12daa5..979e576d23 100644 --- a/packages/trpc/server/routers/viewer/teams/publish.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/publish.handler.ts @@ -1,8 +1,8 @@ import { purchaseTeamOrOrgSubscription } from "@calcom/features/ee/teams/lib/payments"; +import { TeamService } from "@calcom/features/ee/teams/services/teamService"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants"; import { Redirect } from "@calcom/lib/redirect"; -import { TeamService } from "@calcom/features/ee/teams/services/teamService"; import type { Prisma } from "@calcom/prisma/client"; import { MembershipRole } from "@calcom/prisma/enums"; import { teamMetadataSchema } from "@calcom/prisma/zod-utils"; diff --git a/packages/trpc/server/routers/viewer/teams/removeMember/__tests__/PBACRemoveMemberService.test.ts b/packages/trpc/server/routers/viewer/teams/removeMember/__tests__/PBACRemoveMemberService.test.ts index b0b2302340..309623db5e 100644 --- a/packages/trpc/server/routers/viewer/teams/removeMember/__tests__/PBACRemoveMemberService.test.ts +++ b/packages/trpc/server/routers/viewer/teams/removeMember/__tests__/PBACRemoveMemberService.test.ts @@ -1,10 +1,10 @@ import { describe, expect, it, vi, beforeEach, type Mock } from "vitest"; import * as teamQueries from "@calcom/features/ee/teams/lib/queries"; +import { TeamService } from "@calcom/features/ee/teams/services/teamService"; import { PermissionMapper } from "@calcom/features/pbac/domain/mappers/PermissionMapper"; import { Resource, CustomAction } from "@calcom/features/pbac/domain/types/permission-registry"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; -import { TeamService } from "@calcom/features/ee/teams/services/teamService"; import { prisma } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; diff --git a/packages/trpc/server/routers/viewer/teams/roundRobin/getRoundRobinHostsToReasign.handler.ts b/packages/trpc/server/routers/viewer/teams/roundRobin/getRoundRobinHostsToReasign.handler.ts index 3e51fa5e9b..72ee49149f 100644 --- a/packages/trpc/server/routers/viewer/teams/roundRobin/getRoundRobinHostsToReasign.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/roundRobin/getRoundRobinHostsToReasign.handler.ts @@ -1,10 +1,10 @@ +import { enrichUsersWithDelegationCredentials } from "@calcom/app-store/delegationCredential"; import dayjs from "@calcom/dayjs"; import { ensureAvailableUsers } from "@calcom/features/bookings/lib/handleNewBooking/ensureAvailableUsers"; import type { IsFixedAwareUser } from "@calcom/features/bookings/lib/handleNewBooking/types"; -import { enrichUsersWithDelegationCredentials } from "@calcom/app-store/delegationCredential"; +import { withSelectedCalendars } from "@calcom/features/users/repositories/UserRepository"; import { ErrorCode } from "@calcom/lib/errorCodes"; import logger from "@calcom/lib/logger"; -import { withSelectedCalendars } from "@calcom/features/users/repositories/UserRepository"; import type { PrismaClient } from "@calcom/prisma"; import { userSelect } from "@calcom/prisma"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; diff --git a/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinManualReassign.handler.ts b/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinManualReassign.handler.ts index 587c45a0ed..b05c87718d 100644 --- a/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinManualReassign.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinManualReassign.handler.ts @@ -1,5 +1,5 @@ -import { roundRobinManualReassignment } from "@calcom/features/ee/round-robin/roundRobinManualReassignment"; import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; +import { roundRobinManualReassignment } from "@calcom/features/ee/round-robin/roundRobinManualReassignment"; import { prisma } from "@calcom/prisma"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; diff --git a/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinReassign.handler.ts b/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinReassign.handler.ts index f0d8c2fed3..c407c00909 100644 --- a/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinReassign.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/roundRobin/roundRobinReassign.handler.ts @@ -1,5 +1,5 @@ -import { roundRobinReassignment } from "@calcom/features/ee/round-robin/roundRobinReassignment"; import { BookingRepository } from "@calcom/features/bookings/repositories/BookingRepository"; +import { roundRobinReassignment } from "@calcom/features/ee/round-robin/roundRobinReassignment"; import { prisma } from "@calcom/prisma"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; diff --git a/packages/trpc/server/routers/viewer/teams/skipTeamTrials.handler.ts b/packages/trpc/server/routers/viewer/teams/skipTeamTrials.handler.ts index fae063d4c4..433eaee3a7 100644 --- a/packages/trpc/server/routers/viewer/teams/skipTeamTrials.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/skipTeamTrials.handler.ts @@ -1,7 +1,7 @@ import { InternalTeamBilling } from "@calcom/ee/billing/teams/internal-team-billing"; +import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { IS_SELF_HOSTED } from "@calcom/lib/constants"; import logger from "@calcom/lib/logger"; -import { MembershipRepository } from "@calcom/features/membership/repositories/MembershipRepository"; import { prisma } from "@calcom/prisma"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; diff --git a/packages/trpc/server/routers/viewer/teams/update.handler.ts b/packages/trpc/server/routers/viewer/teams/update.handler.ts index 9d3cec5adc..55022aad5a 100644 --- a/packages/trpc/server/routers/viewer/teams/update.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/update.handler.ts @@ -1,10 +1,10 @@ import { getOrgFullOrigin } from "@calcom/ee/organizations/lib/orgDomains"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants"; import type { IntervalLimit } from "@calcom/lib/intervalLimits/intervalLimitSchema"; import { validateIntervalLimitOrder } from "@calcom/lib/intervalLimits/validateIntervalLimitOrder"; import { uploadLogo } from "@calcom/lib/server/avatar"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { prisma } from "@calcom/prisma"; import type { Prisma } from "@calcom/prisma/client"; import { MembershipRole, RedirectType, RRTimestampBasis } from "@calcom/prisma/enums"; diff --git a/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts b/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts index 52ee9bce61..ac0b2f3cab 100644 --- a/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts +++ b/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts @@ -1,9 +1,9 @@ +import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import { scheduleEmailReminder } from "@calcom/features/ee/workflows/lib/reminders/emailReminderManager"; import { scheduleSMSReminder } from "@calcom/features/ee/workflows/lib/reminders/smsReminderManager"; import { scheduleWhatsappReminder } from "@calcom/features/ee/workflows/lib/reminders/whatsappReminderManager"; -import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; -import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import { WorkflowRepository } from "@calcom/features/ee/workflows/repositories/WorkflowRepository"; +import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat"; import { prisma } from "@calcom/prisma"; import { BookingStatus } from "@calcom/prisma/enums"; diff --git a/packages/trpc/server/routers/viewer/workflows/delete.handler.ts b/packages/trpc/server/routers/viewer/workflows/delete.handler.ts index 1d8e6e89df..d9d0efdf0c 100644 --- a/packages/trpc/server/routers/viewer/workflows/delete.handler.ts +++ b/packages/trpc/server/routers/viewer/workflows/delete.handler.ts @@ -1,9 +1,9 @@ import { createDefaultAIPhoneServiceProvider } from "@calcom/features/calAIPhone"; import { WorkflowRepository } from "@calcom/features/ee/workflows/repositories/WorkflowRepository"; +import logger from "@calcom/lib/logger"; import { prisma } from "@calcom/prisma"; import { WorkflowActions } from "@calcom/prisma/enums"; import type { TrpcSessionUser } from "@calcom/trpc/server/types"; -import logger from "@calcom/lib/logger"; import { TRPCError } from "@trpc/server"; diff --git a/packages/trpc/server/routers/viewer/workflows/list.handler.ts b/packages/trpc/server/routers/viewer/workflows/list.handler.ts index 82118b0d88..393487c6f8 100644 --- a/packages/trpc/server/routers/viewer/workflows/list.handler.ts +++ b/packages/trpc/server/routers/viewer/workflows/list.handler.ts @@ -1,6 +1,6 @@ +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import type { WorkflowType } from "@calcom/features/ee/workflows/components/WorkflowListPage"; import { WorkflowRepository } from "@calcom/features/ee/workflows/repositories/WorkflowRepository"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; // import dayjs from "@calcom/dayjs"; // import { getErrorFromUnknown } from "@calcom/lib/errors"; import { addPermissionsToWorkflows } from "@calcom/lib/server/repository/workflow-permissions"; diff --git a/packages/trpc/server/routers/viewer/workflows/update.handler.ts b/packages/trpc/server/routers/viewer/workflows/update.handler.ts index 935bf7259e..ee00d0ba92 100755 --- a/packages/trpc/server/routers/viewer/workflows/update.handler.ts +++ b/packages/trpc/server/routers/viewer/workflows/update.handler.ts @@ -1,4 +1,5 @@ import { createDefaultAIPhoneServiceProvider } from "@calcom/features/calAIPhone"; +import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { isEmailAction, isFormTrigger } from "@calcom/features/ee/workflows/lib/actionHelperFunctions"; import { WorkflowReminderRepository } from "@calcom/features/ee/workflows/lib/repository/workflowReminder"; import { WorkflowRepository } from "@calcom/features/ee/workflows/repositories/WorkflowRepository"; @@ -8,7 +9,6 @@ import { IS_SELF_HOSTED, SCANNING_WORKFLOW_STEPS } from "@calcom/lib/constants"; import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata"; import logger from "@calcom/lib/logger"; import { PrismaAgentRepository } from "@calcom/lib/server/repository/PrismaAgentRepository"; -import { TeamRepository } from "@calcom/features/ee/teams/repositories/TeamRepository"; import { addPermissionsToWorkflow } from "@calcom/lib/server/repository/workflow-permissions"; import { WorkflowRelationsRepository } from "@calcom/lib/server/repository/workflowRelations"; import { WorkflowStepRepository } from "@calcom/lib/server/repository/workflowStep"; diff --git a/packages/trpc/server/routers/viewer/workflows/util.ts b/packages/trpc/server/routers/viewer/workflows/util.ts index 4d3e8c1ab8..ec7c1eaa7d 100644 --- a/packages/trpc/server/routers/viewer/workflows/util.ts +++ b/packages/trpc/server/routers/viewer/workflows/util.ts @@ -9,25 +9,22 @@ import emailRatingTemplate from "@calcom/ee/workflows/lib/reminders/templates/em import emailReminderTemplate from "@calcom/ee/workflows/lib/reminders/templates/emailReminderTemplate"; import { scheduleWhatsappReminder } from "@calcom/ee/workflows/lib/reminders/whatsappReminderManager"; import type { Workflow as WorkflowType } from "@calcom/ee/workflows/lib/types"; -import { - SMS_REMINDER_NUMBER_FIELD, - CAL_AI_AGENT_PHONE_NUMBER_FIELD, -} from "@calcom/lib/bookings/SystemField"; import { getSmsReminderNumberField, getSmsReminderNumberSource, getAIAgentCallPhoneNumberField, getAIAgentCallPhoneNumberSource, } from "@calcom/features/bookings/lib/getBookingFields"; +import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; +import { WorkflowRepository } from "@calcom/features/ee/workflows/repositories/WorkflowRepository"; import { removeBookingField, upsertBookingField } from "@calcom/features/eventtypes/lib/bookingFieldsManager"; import type { PermissionString } from "@calcom/features/pbac/domain/types/permission-registry"; import { PermissionCheckService } from "@calcom/features/pbac/services/permission-check.service"; +import { SMS_REMINDER_NUMBER_FIELD, CAL_AI_AGENT_PHONE_NUMBER_FIELD } from "@calcom/lib/bookings/SystemField"; import { SENDER_ID, SENDER_NAME } from "@calcom/lib/constants"; -import { getBookerBaseUrl } from "@calcom/features/ee/organizations/lib/getBookerUrlServer"; import getOrgIdFromMemberOrTeamId from "@calcom/lib/getOrgIdFromMemberOrTeamId"; import { getTeamIdFromEventType } from "@calcom/lib/getTeamIdFromEventType"; import { getTranslation } from "@calcom/lib/server/i18n"; -import { WorkflowRepository } from "@calcom/features/ee/workflows/repositories/WorkflowRepository"; import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat"; import prisma from "@calcom/prisma"; import { WorkflowType as PrismaWorkflowType, type Workflow } from "@calcom/prisma/client"; diff --git a/packages/ui/components/avatar/UserAvatarGroup.tsx b/packages/ui/components/avatar/UserAvatarGroup.tsx index 27cbd6b5f0..b4701e4574 100644 --- a/packages/ui/components/avatar/UserAvatarGroup.tsx +++ b/packages/ui/components/avatar/UserAvatarGroup.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; -import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; +import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; import type { User } from "@calcom/prisma/client"; import type { UserProfile } from "@calcom/types/UserProfile"; diff --git a/packages/ui/components/avatar/UserAvatarGroupWithOrg.tsx b/packages/ui/components/avatar/UserAvatarGroupWithOrg.tsx index be1db5b8b8..b37e77abbb 100644 --- a/packages/ui/components/avatar/UserAvatarGroupWithOrg.tsx +++ b/packages/ui/components/avatar/UserAvatarGroupWithOrg.tsx @@ -1,7 +1,7 @@ import { useIsEmbed } from "@calcom/embed-core/embed-iframe"; +import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; import { getPlaceholderAvatar } from "@calcom/lib/defaultAvatarImage"; import { getUserAvatarUrl } from "@calcom/lib/getAvatarUrl"; -import { getBookerBaseUrlSync } from "@calcom/features/ee/organizations/lib/getBookerBaseUrlSync"; import type { Team, User } from "@calcom/prisma/client"; import { AvatarGroup } from "./AvatarGroup"; diff --git a/packages/ui/components/form/inputs/TextField.tsx b/packages/ui/components/form/inputs/TextField.tsx index a5e1146a22..ec6ee1a503 100644 --- a/packages/ui/components/form/inputs/TextField.tsx +++ b/packages/ui/components/form/inputs/TextField.tsx @@ -125,7 +125,7 @@ export const InputField = forwardRef(function readOnly, showAsteriskIndicator, onClickAddon, - // eslint-disable-next-line @typescript-eslint/no-unused-vars + t: __t, dataTestid, size, diff --git a/scripts/seed-app-store.ts b/scripts/seed-app-store.ts index 85df186b5e..a69c30fdcd 100644 --- a/scripts/seed-app-store.ts +++ b/scripts/seed-app-store.ts @@ -12,166 +12,6 @@ import { AppCategories } from "@calcom/prisma/enums"; dotEnv.config({ path: path.resolve(__dirname, "../.env.appStore") }); -export const seededForm = { - id: "948ae412-d995-4865-875a-48302588de03", - name: "Seeded Form - Pro", -}; - -async function seedAppData() { - const form = await prisma.app_RoutingForms_Form.findUnique({ - where: { - id: seededForm.id, - }, - }); - if (form) { - console.log(`Skipping Routing Form - Form Seed, "Seeded Form - Pro" already exists`); - return; - } - - const proUser = await prisma.user.findFirst({ - where: { - username: "pro", - }, - }); - - if (!proUser) { - console.log(`Skipping Routing Form - Seeding - Pro User not found`); - return; - } - - const multiSelectLegacyFieldId = "d2292635-9f12-17b1-9153-c3a854649182"; - await prisma.app_RoutingForms_Form.create({ - data: { - id: seededForm.id, - routes: [ - { - id: "8a898988-89ab-4cde-b012-31823f708642", - 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: "c1296635-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: "c1296635-9f12-47b1-8153-c3a854649182", - value: ["custom-page"], - operator: "equal", - valueSrc: ["value"], - valueType: ["text"], - }, - }, - }, - }, - }, - { - id: "a8ba9aab-4567-489a-bcde-f1823f71b4ad", - action: { type: "externalRedirectUrl", value: "https://cal.com" }, - queryValue: { - id: "a8ba9aab-4567-489a-bcde-f1823f71b4ad", - type: "group", - children1: { - "998b9b9a-0123-4456-b89a-b1823f7232b9": { - type: "rule", - properties: { - field: "c1296635-9f12-47b1-8153-c3a854649182", - value: ["external-redirect"], - operator: "equal", - valueSrc: ["value"], - valueType: ["text"], - }, - }, - }, - }, - }, - { - id: "aa8ba8b9-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: multiSelectLegacyFieldId, - value: [["Option-2"]], - 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: [ - { id: "c1296635-9f12-47b1-8153-c3a854649182", type: "text", label: "Test field", required: true }, - { - id: multiSelectLegacyFieldId, - type: "multiselect", - label: "Multi Select(with legacy `selectText`)", - identifier: "multi", - selectText: "Option-1\nOption-2", - required: false, - }, - { - id: "d3292635-9f12-17b1-9153-c3a854649182", - type: "multiselect", - label: "Multi Select", - identifier: "multi", - options: [ - { - id: "d1234635-9f12-17b1-9153-c3a854649182", - label: "Option-1", - }, - { - id: "d1235635-9f12-17b1-9153-c3a854649182", - label: "Option-2", - }, - ], - required: false, - }, - ], - user: { - connect: { - email_username: { - username: "pro", - email: "pro@example.com", - }, - }, - }, - name: seededForm.name, - }, - }); -} - async function createApp( /** The App identifier in the DB also used for public page in `/apps/[slug]` */ slug: Prisma.AppCreateInput["slug"], @@ -410,15 +250,18 @@ export default async function main() { app.isTemplate ); } - - await seedAppData(); } -main() - .catch((e) => { - console.error(e); - process.exit(1); - }) - .finally(async () => { - await prisma.$disconnect(); - }); +if (require.main === module) { + (async () => { + await main(); + await seedAppData(); + })() + .catch((e) => { + console.error(e); + process.exit(1); + }) + .finally(async () => { + await prisma.$disconnect(); + }); +} diff --git a/scripts/seed-insights.ts b/scripts/seed-insights.ts index 83a5237035..64413c8f9e 100644 --- a/scripts/seed-insights.ts +++ b/scripts/seed-insights.ts @@ -4,7 +4,7 @@ import { v4 as uuidv4 } from "uuid"; import dayjs from "@calcom/dayjs"; import { hashPassword } from "@calcom/lib/auth/hashPassword"; import type { Prisma } from "@calcom/prisma/client"; -import { PrismaClient } from "@calcom/prisma/client"; +import { prisma } from "@calcom/prisma/client"; import { BookingStatus, AssignmentReasonEnum } from "@calcom/prisma/enums"; import { seedAttributes, seedRoutingFormResponses, seedRoutingForms } from "./seed-utils"; @@ -132,7 +132,6 @@ async function seedBookingAssignments() { }); } -const prisma = new PrismaClient(); async function main() { // First find the organization we want to add insights to const organization = await prisma.team.findFirst({ @@ -366,7 +365,13 @@ async function main() { await seedBookingAssignments(); } -main() + +async function runMain() { + await prisma.$connect(); + await main(); +} + +runMain() .then(async () => { await prisma.$disconnect(); }) @@ -525,7 +530,12 @@ async function createPerformanceData() { } } -createPerformanceData() +async function runSeed() { + await prisma.$connect(); + await createPerformanceData(); +} + +runSeed() .then(async () => { await prisma.$disconnect(); }) diff --git a/scripts/seed.ts b/scripts/seed.ts index cb52433c21..8c40971880 100644 --- a/scripts/seed.ts +++ b/scripts/seed.ts @@ -556,6 +556,12 @@ async function createOrganizationAndAddMembersAndTeams({ ); const ownerForEvent = orgMembersInDBWithProfileId[0]; + if (!ownerForEvent) { + console.log( + `Warning: No organization members with profiles found for creating team event, skipping event creation for team ${team.teamData.slug}` + ); + continue; + } // Create event for each team await prisma.eventType.create({ data: { @@ -1364,11 +1370,178 @@ async function main() { }, ], }); + + const seededForm = { + id: "948ae412-d995-4865-875a-48302588de03", + name: "Seeded Form - Pro", + }; + + const form = await prisma.app_RoutingForms_Form.findUnique({ + where: { + id: seededForm.id, + }, + }); + if (form) { + console.log(`Skipping Routing Form - Form Seed, "Seeded Form - Pro" already exists`); + } else { + const proUser = await prisma.user.findFirst({ + where: { + username: "pro", + }, + }); + + if (!proUser) { + console.log(`Skipping Routing Form - Seeding - Pro User not found`); + } else { + const multiSelectLegacyFieldId = "d2292635-9f12-17b1-9153-c3a854649182"; + await prisma.app_RoutingForms_Form.create({ + data: { + id: seededForm.id, + routes: [ + { + id: "8a898988-89ab-4cde-b012-31823f708642", + 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: "c1296635-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: "c1296635-9f12-47b1-8153-c3a854649182", + value: ["custom-page"], + operator: "equal", + valueSrc: ["value"], + valueType: ["text"], + }, + }, + }, + }, + }, + { + id: "a8ba9aab-4567-489a-bcde-f1823f71b4ad", + action: { type: "externalRedirectUrl", value: "https://cal.com" }, + queryValue: { + id: "a8ba9aab-4567-489a-bcde-f1823f71b4ad", + type: "group", + children1: { + "998b9b9a-0123-4456-b89a-b1823f7232b9": { + type: "rule", + properties: { + field: "c1296635-9f12-47b1-8153-c3a854649182", + value: ["external-redirect"], + operator: "equal", + valueSrc: ["value"], + valueType: ["text"], + }, + }, + }, + }, + }, + { + id: "aa8ba8b9-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: multiSelectLegacyFieldId, + value: [["Option-2"]], + 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: [ + { + id: "c1296635-9f12-47b1-8153-c3a854649182", + type: "text", + label: "Test field", + required: true, + }, + { + id: multiSelectLegacyFieldId, + type: "multiselect", + label: "Multi Select(with legacy `selectText`)", + identifier: "multi", + selectText: "Option-1\nOption-2", + required: false, + }, + { + id: "d3292635-9f12-17b1-9153-c3a854649182", + type: "multiselect", + label: "Multi Select", + identifier: "multi", + options: [ + { + id: "d1234635-9f12-17b1-9153-c3a854649182", + label: "Option-1", + }, + { + id: "d1235635-9f12-17b1-9153-c3a854649182", + label: "Option-2", + }, + ], + required: false, + }, + ], + user: { + connect: { + email_username: { + username: "pro", + email: "pro@example.com", + }, + }, + }, + name: seededForm.name, + }, + }); + } + } } -main() - .then(() => mainAppStore()) - .then(() => mainHugeEventTypesSeed()) +async function runSeed() { + await prisma.$connect(); + + await mainAppStore(); + await main(); + await mainHugeEventTypesSeed(); +} + +runSeed() .catch((e) => { console.error(e); process.exit(1); diff --git a/tests/libs/__mocks__/prisma.ts b/tests/libs/__mocks__/prisma.ts index ae47d5f0b4..54385db05b 100644 --- a/tests/libs/__mocks__/prisma.ts +++ b/tests/libs/__mocks__/prisma.ts @@ -1,20 +1,16 @@ -import { createPrismock } from "prismock"; +import { type DMMF } from "@prisma/client/runtime/client"; +import { getDMMF } from "@prisma/internals"; +import { readFileSync } from "fs"; import { beforeEach, vi } from "vitest"; +import { createPrismock } from "prismock/build/main/lib/client"; import logger from "@calcom/lib/logger"; -import { Prisma as PrismaType } from "@calcom/prisma/client"; +import type { PrismaClient } from "@calcom/prisma"; import * as selects from "@calcom/prisma/selects"; vi.stubEnv("DATABASE_URL", "postgresql://user:password@localhost:5432/testdb"); -vi.mock("@calcom/prisma", () => ({ - default: prismaMock, - prisma: prismaMock, - readonlyPrisma: prismaMock, - ...selects, -})); - -const handlePrismockBugs = () => { +const handlePrismockBugs = (prismock: any) => { const __findManyWebhook = prismock.webhook.findMany; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -30,16 +26,93 @@ const handlePrismockBugs = () => { }; }; -const PrismockClientConstructor = createPrismock(PrismaType); -const prismock = new PrismockClientConstructor(); +let prismockInstance: any; +const proxyTarget = {} as PrismaClient; -const prismaMock = prismock; - -beforeEach(() => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - prismock.reset(); - handlePrismockBugs(); +const prismaMockProxy = new Proxy(proxyTarget, { + get(target, prop) { + if (!prismockInstance) { + throw new Error("Prismock not initialized yet"); + } + if (prop in target) { + return (target as any)[prop]; + } + return prismockInstance[prop]; + }, + getOwnPropertyDescriptor(target, prop) { + if (!prismockInstance) { + return undefined; + } + const targetDescriptor = Object.getOwnPropertyDescriptor(target, prop); + if (targetDescriptor) { + return targetDescriptor; + } + return Object.getOwnPropertyDescriptor(prismockInstance, prop); + }, + has(target, prop) { + if (!prismockInstance) { + return false; + } + if (prop in target) { + return true; + } + return prop in prismockInstance; + }, + ownKeys(target) { + if (!prismockInstance) { + return []; + } + return Reflect.ownKeys(prismockInstance); + }, + set(target, prop, value) { + if (!prismockInstance) { + throw new Error("Prismock not initialized yet"); + } + (target as any)[prop] = value; + return true; + } }); -export default prismaMock; +vi.mock("@calcom/prisma", async (importOriginal) => { + const original = await importOriginal(); + const { Prisma } = original; + + const schemaContent = readFileSync("packages/prisma/schema.prisma", "utf-8"); + const dmmf = await getDMMF({ datamodel: schemaContent }); + const PrismaWithDMMF = { ...Prisma, dmmf }; + + const PrismockClientClass = createPrismock( + PrismaWithDMMF as unknown as typeof Prisma & { dmmf: DMMF.Document } + ); + + prismockInstance = new PrismockClientClass(); + + if (!prismockInstance.$queryRaw) { + Object.defineProperty(prismockInstance, "$queryRaw", { + value: async () => { + throw new Error("$queryRaw is not implemented in prismock. Use vi.spyOn to mock it in your test."); + }, + writable: true, + configurable: true, + enumerable: false, + }); + } + + return { + default: prismaMockProxy, + prisma: prismaMockProxy, + readonlyPrisma: prismaMockProxy, + ...selects, + }; +}); + +beforeEach(() => { + if (prismockInstance) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + prismockInstance.reset(); + handlePrismockBugs(prismockInstance); + } +}); + +export default prismaMockProxy; diff --git a/turbo.json b/turbo.json index 4faebfbf65..b4d4ca4c3b 100644 --- a/turbo.json +++ b/turbo.json @@ -289,7 +289,8 @@ "MICROSOFT_WEBHOOK_URL", "_CAL_INTERNAL_PAST_BOOKING_RESCHEDULE_CHANGE_TEAM_IDS", "ENTERPRISE_SLUGS", - "PLATFORM_ENTERPRISE_SLUGS" + "PLATFORM_ENTERPRISE_SLUGS", + "USE_POOL" ], "tasks": { "@calcom/web#copy-app-store-static": { @@ -381,7 +382,8 @@ "DATABASE_READ_URL", "DATABASE_WRITE_URL", "LOG_LEVEL", - "NEXTAUTH_SECRET" + "NEXTAUTH_SECRET", + "USE_POOL" ] }, "@calcom/ai#build": { diff --git a/yarn.lock b/yarn.lock index 1039e6a43f..bbf231c41a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3875,11 +3875,12 @@ __metadata: resolution: "@calcom/prisma@workspace:packages/prisma" dependencies: "@calcom/lib": "workspace:*" - "@prisma/client": ^6.7.0 + "@prisma/adapter-pg": ^6.16.0 + "@prisma/client": ^6.16.0 "@prisma/extension-accelerate": ^1.3.0 - "@prisma/generator-helper": ^6.7.0 + "@prisma/generator-helper": ^6.16.0 npm-run-all: ^4.1.5 - prisma: ^6.7.0 + prisma: ^6.16.0 prisma-kysely: 2.2.0 ts-node: ^10.9.1 zod: ^3.22.4 @@ -11496,6 +11497,17 @@ __metadata: languageName: node linkType: hard +"@prisma/adapter-pg@npm:^6.16.0": + version: 6.16.1 + resolution: "@prisma/adapter-pg@npm:6.16.1" + dependencies: + "@prisma/driver-adapter-utils": 6.16.1 + pg: ^8.11.3 + postgres-array: 3.0.4 + checksum: 8d09acaaddf4096bd4d65a8132875ffa8233065e18bac0060987c22f987dc949d0955b4c864d9c1e70fc330e0dfa78c3e2600eea260e086d8f2e07ef3d097dae + languageName: node + linkType: hard + "@prisma/client@npm:6.7.0": version: 6.7.0 resolution: "@prisma/client@npm:6.7.0" @@ -11511,9 +11523,9 @@ __metadata: languageName: node linkType: hard -"@prisma/client@npm:^6.7.0": - version: 6.8.2 - resolution: "@prisma/client@npm:6.8.2" +"@prisma/client@npm:^6.16.0": + version: 6.16.1 + resolution: "@prisma/client@npm:6.16.1" peerDependencies: prisma: "*" typescript: ">=5.1.0" @@ -11522,7 +11534,7 @@ __metadata: optional: true typescript: optional: true - checksum: e6acce8c93818a921b6db650bcca9df7c18965a32c697ed6b112705a28b926bcfa15fed4178c365251709b5f92625ef42c92096a60017a79a0e34b7c0e68131d + checksum: da713d17461226433cbf17e85fe2ac0ad0f589ec66e775723b1529b0f10632b6e6bc25ec119305baeea0616be1ded7d4a9135887d62a431373e0761da2c06fa8 languageName: node linkType: hard @@ -11538,6 +11550,30 @@ __metadata: languageName: node linkType: hard +"@prisma/config@npm:6.16.1": + version: 6.16.1 + resolution: "@prisma/config@npm:6.16.1" + dependencies: + c12: 3.1.0 + deepmerge-ts: 7.1.5 + effect: 3.16.12 + empathic: 2.0.0 + checksum: 1e2227fc4dd5def1d85528e356916e5b1a5087e9efd76d8fe797e9912afdc4e957d209e431e3fd424a5340a78466cbdf50bb3ebfb610ce6f232aee5bc4667937 + languageName: node + linkType: hard + +"@prisma/config@npm:6.16.2": + version: 6.16.2 + resolution: "@prisma/config@npm:6.16.2" + dependencies: + c12: 3.1.0 + deepmerge-ts: 7.1.5 + effect: 3.16.12 + empathic: 2.0.0 + checksum: 59a9d1a24fc686108b268eda8fa022475700837f404bf287025a600459f911df61c6b24395dd746e494c87eb0ddac748df1afc3681b761d8615cae7970b52092 + languageName: node + linkType: hard + "@prisma/config@npm:6.8.2": version: 6.8.2 resolution: "@prisma/config@npm:6.8.2" @@ -11561,6 +11597,20 @@ __metadata: languageName: node linkType: hard +"@prisma/debug@npm:6.16.1": + version: 6.16.1 + resolution: "@prisma/debug@npm:6.16.1" + checksum: 7ca097ff01e67d44a97f1dc24f14d2d4b276adffac967479168c015c6bcaaa859ed42a3655a5ec91f37ca6d9f4ad7b7288d442260e2443b5abdebc4b5e5706ea + languageName: node + linkType: hard + +"@prisma/debug@npm:6.16.2": + version: 6.16.2 + resolution: "@prisma/debug@npm:6.16.2" + checksum: 6ce1bfe29215d2ac8c6f708fec81a81b84f14603e09301dede0bbfbcdf4153e657274a182f13e2dd75e57960f9aeffc1e74543af0547c38f14ea8afbf1972e88 + languageName: node + linkType: hard + "@prisma/debug@npm:6.8.2": version: 6.8.2 resolution: "@prisma/debug@npm:6.8.2" @@ -11575,6 +11625,20 @@ __metadata: languageName: node linkType: hard +"@prisma/dmmf@npm:6.16.1": + version: 6.16.1 + resolution: "@prisma/dmmf@npm:6.16.1" + checksum: 1cc703ee233e3439c2fb094c61d59e7aca4484ef58a26eda586b07351b10a43061d5cccb40e0f48ce76c6c53143cf19540cf5f0a0703d8a6f899c798fae994d1 + languageName: node + linkType: hard + +"@prisma/dmmf@npm:6.16.2": + version: 6.16.2 + resolution: "@prisma/dmmf@npm:6.16.2" + checksum: ffb143e37d991ec9b6ae5ec265051e8a15e636752d363ef149a24e5c3d628a7eab558895902054c1128454c863edf52f4fe75061cd52639dd4a9b28a90350343 + languageName: node + linkType: hard + "@prisma/dmmf@npm:6.8.2": version: 6.8.2 resolution: "@prisma/dmmf@npm:6.8.2" @@ -11591,6 +11655,24 @@ __metadata: languageName: node linkType: hard +"@prisma/driver-adapter-utils@npm:6.16.1": + version: 6.16.1 + resolution: "@prisma/driver-adapter-utils@npm:6.16.1" + dependencies: + "@prisma/debug": 6.16.1 + checksum: 8c68391ff5555535aa6da7033ef7ddf97df0980cd1c2cefcec848b1e7e2b566f11fab551b14b40f8b8b9f44cd8d119841e3f9b353a644716e767e023ea15aebc + languageName: node + linkType: hard + +"@prisma/driver-adapter-utils@npm:6.16.2": + version: 6.16.2 + resolution: "@prisma/driver-adapter-utils@npm:6.16.2" + dependencies: + "@prisma/debug": 6.16.2 + checksum: 965aa80cca4b78bed6f6f0d6359b955b317972a69b3fcbb3d3fb11989fdad54b36f856234b72d20d818819a87d6f70e4ebbe1f4f3d78a00bcd1a9f7e72890ae7 + languageName: node + linkType: hard + "@prisma/engines-version@npm:5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2": version: 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 resolution: "@prisma/engines-version@npm:5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2" @@ -11605,6 +11687,13 @@ __metadata: languageName: node linkType: hard +"@prisma/engines-version@npm:6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43": + version: 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43 + resolution: "@prisma/engines-version@npm:6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43" + checksum: 87f53c054075e9fcc3ac580600c41c798fca1019ae69cbe61e207235585e0e762329aa87eb1f5c9bce114e6748aac16511617c3e7bb574a39b74c9ee7a5cf68f + languageName: node + linkType: hard + "@prisma/engines-version@npm:6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e": version: 6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e resolution: "@prisma/engines-version@npm:6.8.0-43.2060c79ba17c6bb9f5823312b6f6b7f4a845738e" @@ -11636,6 +11725,30 @@ __metadata: languageName: node linkType: hard +"@prisma/engines@npm:6.16.1": + version: 6.16.1 + resolution: "@prisma/engines@npm:6.16.1" + dependencies: + "@prisma/debug": 6.16.1 + "@prisma/engines-version": 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43 + "@prisma/fetch-engine": 6.16.1 + "@prisma/get-platform": 6.16.1 + checksum: 1316e2e01e2e23929547ac411d67782ef06e5345e38e72729940a8a20802dad2f700c2618e59e5f106425daa91d3c647bf48eaa84038be9b93c6484fc2e261ff + languageName: node + linkType: hard + +"@prisma/engines@npm:6.16.2": + version: 6.16.2 + resolution: "@prisma/engines@npm:6.16.2" + dependencies: + "@prisma/debug": 6.16.2 + "@prisma/engines-version": 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43 + "@prisma/fetch-engine": 6.16.2 + "@prisma/get-platform": 6.16.2 + checksum: dfe7ef818df719891882f107db15258f873d1f86baff336fae380144d2c9342772c77dd7d5e3955700caae66e99a769b699fad75b582b2001cf206d128dbbbbb + languageName: node + linkType: hard + "@prisma/engines@npm:6.8.2": version: 6.8.2 resolution: "@prisma/engines@npm:6.8.2" @@ -11679,6 +11792,28 @@ __metadata: languageName: node linkType: hard +"@prisma/fetch-engine@npm:6.16.1": + version: 6.16.1 + resolution: "@prisma/fetch-engine@npm:6.16.1" + dependencies: + "@prisma/debug": 6.16.1 + "@prisma/engines-version": 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43 + "@prisma/get-platform": 6.16.1 + checksum: d8d329231b9ea2d6c9221e3c411d4fd30dc837cfd6cb663a1e3d363fbfc3c2035876bf305b3d72b255d88ae3a2dd638c440cbc5fca13c3856d5a6c2f18f7180d + languageName: node + linkType: hard + +"@prisma/fetch-engine@npm:6.16.2": + version: 6.16.2 + resolution: "@prisma/fetch-engine@npm:6.16.2" + dependencies: + "@prisma/debug": 6.16.2 + "@prisma/engines-version": 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43 + "@prisma/get-platform": 6.16.2 + checksum: 0fe048e0df96d578d3aa2f8350804abd49e80bcf23b8bca756f9b67096dd74d6dd6a9100d5627762f56a4c391da24205be69dcd44b0ea7747ac400aa9521e5a4 + languageName: node + linkType: hard + "@prisma/fetch-engine@npm:6.8.2": version: 6.8.2 resolution: "@prisma/fetch-engine@npm:6.8.2" @@ -11710,7 +11845,29 @@ __metadata: languageName: node linkType: hard -"@prisma/generator-helper@npm:^6.3.0, @prisma/generator-helper@npm:^6.7.0": +"@prisma/generator-helper@npm:6.16.2": + version: 6.16.2 + resolution: "@prisma/generator-helper@npm:6.16.2" + dependencies: + "@prisma/debug": 6.16.2 + "@prisma/dmmf": 6.16.2 + "@prisma/generator": 6.16.2 + checksum: 284a7812b335e904399178415a4272fa59cbda4a37a3cbd0bc032f347f25a61a1afef1199bef7b454e769017e8b5f0612caf1b3ff9228a1904f6078122d2e79a + languageName: node + linkType: hard + +"@prisma/generator-helper@npm:^6.16.0": + version: 6.16.1 + resolution: "@prisma/generator-helper@npm:6.16.1" + dependencies: + "@prisma/debug": 6.16.1 + "@prisma/dmmf": 6.16.1 + "@prisma/generator": 6.16.1 + checksum: 337397ff7dbc14fd478e7158b75cdc1cafe7b8d417bb7826a7e58bdae35e3d73a2ab2c666d487a0a21c19df202bcfa7f05a101994c78729c6fa4e6d763401dff + languageName: node + linkType: hard + +"@prisma/generator-helper@npm:^6.3.0": version: 6.8.2 resolution: "@prisma/generator-helper@npm:6.8.2" dependencies: @@ -11728,6 +11885,20 @@ __metadata: languageName: node linkType: hard +"@prisma/generator@npm:6.16.1": + version: 6.16.1 + resolution: "@prisma/generator@npm:6.16.1" + checksum: 4e27447fdd42acf69518a6c6693ea80234008ea0bd52f3f13ad235b0376874b9b0c5cb148d306379904aea55bd9c2a29cbaa0c4075d0514ae9aac90fe3e439f7 + languageName: node + linkType: hard + +"@prisma/generator@npm:6.16.2": + version: 6.16.2 + resolution: "@prisma/generator@npm:6.16.2" + checksum: 4a01037d13bf34bddf41df5103d2a1fdab994604dee6c0ca0470e1958917c1c7fe1dba64a750b7de25cb19e1202e88c509a53d924b34aca29309a081b9e230e9 + languageName: node + linkType: hard + "@prisma/generator@npm:6.8.2": version: 6.8.2 resolution: "@prisma/generator@npm:6.8.2" @@ -11753,6 +11924,24 @@ __metadata: languageName: node linkType: hard +"@prisma/get-platform@npm:6.16.1": + version: 6.16.1 + resolution: "@prisma/get-platform@npm:6.16.1" + dependencies: + "@prisma/debug": 6.16.1 + checksum: 63e48e49a94197610707e128958be1f9d657f408aee2424d426c072c6d0aea43f37a36046d57d860a9c3c246219c34d1ce6f2138e2fbae9e26d13f1c17edda47 + languageName: node + linkType: hard + +"@prisma/get-platform@npm:6.16.2": + version: 6.16.2 + resolution: "@prisma/get-platform@npm:6.16.2" + dependencies: + "@prisma/debug": 6.16.2 + checksum: 427e044c9b171c95e6353123f749ee93d8b664b6fa601e9775628541cc20f5bcc0e0e57d6ef8d3b88b49827472edd7c65e604ee21b59078bbf66c244e4018ff1 + languageName: node + linkType: hard + "@prisma/get-platform@npm:6.8.2": version: 6.8.2 resolution: "@prisma/get-platform@npm:6.8.2" @@ -11828,6 +12017,33 @@ __metadata: languageName: node linkType: hard +"@prisma/internals@npm:^6.16.2": + version: 6.16.2 + resolution: "@prisma/internals@npm:6.16.2" + dependencies: + "@prisma/config": 6.16.2 + "@prisma/debug": 6.16.2 + "@prisma/dmmf": 6.16.2 + "@prisma/driver-adapter-utils": 6.16.2 + "@prisma/engines": 6.16.2 + "@prisma/fetch-engine": 6.16.2 + "@prisma/generator": 6.16.2 + "@prisma/generator-helper": 6.16.2 + "@prisma/get-platform": 6.16.2 + "@prisma/prisma-schema-wasm": 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43 + "@prisma/schema-engine-wasm": 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43 + "@prisma/schema-files-loader": 6.16.2 + arg: 5.0.2 + prompts: 2.4.2 + peerDependencies: + typescript: ">=5.1.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 0b638f692e9032d6745072e8c435e9bdecb4b1781ac2710a2e5436466b63a50933e4d90cdab4dfee8f9ad5ec6ee52c14d4d6f424c915905cd39b59366bd8887a + languageName: node + linkType: hard + "@prisma/nextjs-monorepo-workaround-plugin@npm:^6.16.1": version: 6.16.1 resolution: "@prisma/nextjs-monorepo-workaround-plugin@npm:6.16.1" @@ -11849,6 +12065,13 @@ __metadata: languageName: node linkType: hard +"@prisma/prisma-schema-wasm@npm:6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43": + version: 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43 + resolution: "@prisma/prisma-schema-wasm@npm:6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43" + checksum: 17326c084fd002475638ecece65dcf81927e5cb6bd76ca9b6fd3d7681b9467132b1a7756a331989ba8b827cf6299d5d1bbe641be53ba5d004723ab8bdb836e6c + languageName: node + linkType: hard + "@prisma/schema-engine-wasm@npm:6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb": version: 6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb resolution: "@prisma/schema-engine-wasm@npm:6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb" @@ -11856,6 +12079,13 @@ __metadata: languageName: node linkType: hard +"@prisma/schema-engine-wasm@npm:6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43": + version: 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43 + resolution: "@prisma/schema-engine-wasm@npm:6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43" + checksum: 07017d00b8168e4f364ea692d486e5d2ef821430e9d23d0053154945aec0ae86285dd1e9cb24769d0d259f2cf3ec2c974fa7415764dedfec139c65a7a7af12e9 + languageName: node + linkType: hard + "@prisma/schema-files-loader@npm:5.22.0": version: 5.22.0 resolution: "@prisma/schema-files-loader@npm:5.22.0" @@ -11876,6 +12106,16 @@ __metadata: languageName: node linkType: hard +"@prisma/schema-files-loader@npm:6.16.2": + version: 6.16.2 + resolution: "@prisma/schema-files-loader@npm:6.16.2" + dependencies: + "@prisma/prisma-schema-wasm": 6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43 + fs-extra: 11.3.0 + checksum: b3db96a505ad0dff6176f5d8f57141f6de3e76fb4facb7acfa1e9ce882fa19b099c47c8d2444ff564bb714d0063371153df01c3eb0559e06afb8cdff032cf59e + languageName: node + linkType: hard + "@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": version: 1.1.2 resolution: "@protobufjs/aspromise@npm:1.1.2" @@ -22141,6 +22381,7 @@ __metadata: "@jetstreamapp/soql-parser-js": ^6.1.0 "@next/third-parties": ^14.2.5 "@playwright/test": ^1.45.3 + "@prisma/internals": ^6.16.2 "@snaplet/copycat": ^4.1.0 "@testing-library/jest-dom": ^5.16.5 "@testing-library/react": ^16.0.1 @@ -39709,6 +39950,13 @@ __metadata: languageName: node linkType: hard +"postgres-array@npm:3.0.4": + version: 3.0.4 + resolution: "postgres-array@npm:3.0.4" + checksum: 9d0fed9f8a4674cbc31a4e568dc5d068f6e32b4b5c62deae2c4908c75303be0c5aef023fc04dfb8feaf6d63af1a17257e528ef606e8128bffe1f9d6844ad8ffa + languageName: node + linkType: hard + "postgres-array@npm:~2.0.0": version: 2.0.0 resolution: "postgres-array@npm:2.0.0" @@ -40036,6 +40284,23 @@ __metadata: languageName: node linkType: hard +"prisma@npm:^6.16.0": + version: 6.16.1 + resolution: "prisma@npm:6.16.1" + dependencies: + "@prisma/config": 6.16.1 + "@prisma/engines": 6.16.1 + peerDependencies: + typescript: ">=5.1.0" + peerDependenciesMeta: + typescript: + optional: true + bin: + prisma: build/index.js + checksum: 6d462b169c250b4c5b287ef52c33b4586a04e02a81ce0e2848f570ef844a67b61a79fadba96bcfe3db1100e59947ea3965cccf8c648a59eccc3f61dad95bb401 + languageName: node + linkType: hard + "prisma@npm:^6.7.0": version: 6.8.2 resolution: "prisma@npm:6.8.2"