* Use previous header for android
* use activity instead of ternary statements
* update layout to use header buttons in availability screen
* fix styles and add context menu
* add set as default action
---------
Co-authored-by: Dhairyashil <dhairyashil10101010@gmail.com>
Booking confirmation pages contain PII (names, emails, phone numbers)
and should not be indexed by search engines
- Add robots noindex to /booking/[uid]/page.tsx
- Add robots noindex to /booking/[uid]/embed/page.tsx
Follows same pattern as not-found.tsx
- Add list-event-types.mdx with Quick start, Props, Demo video, and Combining with EventTypeSettings sections
- Add list_event_types_light.png screenshot
- Update mint.json navigation to include new page
* feat: add environment-based favicons (prod vs dev)
- Add cal-prod.png (dark/gray) favicon for production environments
- Add cal-dev.png (red) favicon for development/localhost environments
- Update FAVICON_16 and FAVICON_32 constants to switch based on IS_PRODUCTION
Co-Authored-By: peer@cal.com <peer@cal.com>
* feat: add higher resolution icons for all icon types (apple-touch, android-chrome, mstile)
- Add 180x180 apple-touch-icon for prod and dev
- Add 150x150 mstile icons for prod and dev
- Add 192x192 and 256x256 android-chrome icons for prod and dev
- Update all icon constants to use IS_PRODUCTION switching
Co-Authored-By: peer@cal.com <peer@cal.com>
* refactor: simplify favicon to single new design
- Remove environment-based favicon switching
- Update all icon files with new Cal favicon design
- Remove dev/prod icon variants
- Update constants to use static icon paths
Co-Authored-By: peer@cal.com <peer@cal.com>
* feat: add favicon.ico with new Cal favicon design
Co-Authored-By: peer@cal.com <peer@cal.com>
* chore: update favicon icons with final design
Co-Authored-By: peer@cal.com <peer@cal.com>
* chore: update favicon icons with final design v3
Co-Authored-By: peer@cal.com <peer@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: add name property to delegation credentials for type compatibility
The MultiDisconnectIntegration component expects credentials with user.name property,
but delegation credentials only had user.email. This caused a type mismatch when
spreading both credential types together in appCredentialsByType handler.
Added name: null to the delegation credentials user object to ensure type compatibility.
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: update getUserDisplayName to check value instead of just property existence
The narrowing logic was causing TypeScript to infer 'never' type because
after adding name property to delegation credentials, the 'name in user'
check always passes. Now we check if name has a truthy value before using it.
Also fixed lint warning by using optional chaining for onSuccess callback.
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: add explicit return type and typeof checks to getUserDisplayName
The function now has an explicit return type of string | null and uses
typeof checks to ensure proper type narrowing. This prevents TypeScript
from inferring a wider return type that includes {} when the user object
has properties with non-string types.
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* test: update delegation credential test to include name property
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: flaky E2E tests and refactor
* fix
* fix: week limit tests to use same week for pre-booking and UI booking
The week limit tests were failing because the pre-booking was created in
week 1 but the UI booking was done in week 2. Since weekly limits are
per-week, the pre-booking didn't count toward the limit in week 2.
Fixed by keeping both bookings in the same week:
- Pre-booking on Monday (satisfies daily limit, counts toward weekly)
- UI booking on Tuesday (same week, hits weekly limit of 2)
This ensures the weekly limit is properly tested and all remaining
weekdays in the week get blocked after hitting the limit.
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix(companion): separate dev and prod build scripts to prevent localhost in production
- Add ext:build-dev and ext:build-prod scripts with clear separation
- Add BUILD_FOR_STORE flag to force production URL in store builds
- Add visual build indicators (store / dev) for clarity
- Prevent EXPO_PUBLIC_COMPANION_DEV_URL from leaking into production builds
* update commands to work for ci
* update version
---------
Co-authored-by: Volnei Munhoz <volnei@cal.com>
- Add CalComPageStatus handling in NotFound and ErrorPage components using useLayoutEffect
- Remove redundant pageStatus logic from PageWrapperAppDir.tsx since App Router error/notFound pages set status themselves
- Refactor embed-iframe.ts: split checkPageStatusAndHandleError into hasPageError() and handlePageError()
- Add page status checks before firing linkReady to catch errors set after initialization
- Ensures linkFailed event fires correctly for all error status codes in embed scenarios
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(booking-audit): extract core audit system changes from PR 25125
This PR extracts core audit infrastructure changes without integration changes:
1. New action services introduced:
- SeatBookedAuditActionService
- SeatRescheduledAuditActionService
2. Simplification of ActionService interface:
- Streamlined IAuditActionService interface
- Reduced TypeScript burden with cleaner type definitions
3. ActionSource support:
- Added BookingAuditSource enum (API_V1, API_V2, WEBAPP, WEBHOOK, UNKNOWN)
- Added source and operationId fields to BookingAudit model
4. New AuditAction types:
- SEAT_BOOKED
- SEAT_RESCHEDULED
- APP actor type
5. New BookingAuditAccessService:
- Permission-based access control for audit logs
- Added readTeamAuditLogs and readOrgAuditLogs permissions
6. Fixes in the logs viewer flow:
- Enhanced BookingAuditViewerService with improved filtering
- Local AttendeeRepository for actor enrichment
Changes are contained within packages/features/booking-audit with minimal
outside changes (permission registry only).
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor(booking-audit): streamline action handling and enhance localization
- Replaced action icon retrieval with a mapping object for improved clarity and performance.
- Introduced constants for actor role labels to simplify role retrieval.
- Added new localization strings for audit log permission errors and organization requirements.
- Updated various service and repository interfaces to enhance type safety and clarity.
- Removed deprecated architecture documentation and adjusted related imports for consistency.
These changes aim to improve code maintainability and user experience in the booking audit system.
* fix(booking-audit): enhance actor role localization and operation ID tracking
- Updated actor role labels in the booking logs view to use lowercase for consistency.
- Improved localization by wrapping actor role display in a translation function.
- Added operationId field to audit logs for better correlation of actions across multiple bookings.
- Enhanced BookingAuditViewerService to include operationId in enriched audit logs.
- Updated integration tests to verify consistent operationId across related audit logs.
These changes aim to improve localization accuracy and facilitate better tracking of user actions in the booking audit system.
* feat: integrate credential repository and enhance app actor handling
- Added CredentialRepository to manage app credentials, including a method to find credentials by ID.
- Updated BookingAudit system to support app actors identified by credential ID, improving actor attribution and audit clarity.
- Introduced a new utility function to map app slugs to display names, enhancing the user experience in audit logs.
- Modified relevant interfaces and types to accommodate the new credential handling and app actor structure.
- Enhanced BookingAuditViewerService to display app names based on credentials, ensuring accurate representation in audit logs.
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: allow required check to pass when E2E tests are skipped due to missing label
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* revert: remove unnecessary integration-test condition change
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* chore: trigger fresh CI run
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* all should pass to allow merge
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add enabled column to UserFeatures and TeamFeatures for tri-state semantics
- Add enabled Boolean column to UserFeatures model with default true
- Add enabled Boolean column to TeamFeatures model with default true
- Update FeaturesRepository to use tri-state semantics:
- enabled=true: feature is explicitly enabled
- enabled=false: feature is explicitly disabled (blocks inheritance)
- No row: inherit from team/org level
- Update SQL queries to check enabled=true for feature access
- Add enableFeatureForTeam method to interface and implementation
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* update comments
* add integration tests
* add more test
* select enabled only
* no @default(true)
* fix types and tests
* add missing enabled
* add missing enabled
* rename enableFeatureForTeam to updateFeatureForTeam and support FeatureState
* refactor: rename updateFeatureForTeam to setTeamFeatureState
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix integration test
* fix tests
* add more tests
* add missing enabled
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* add webhook version schema
* version the code
* update version from numeric to date val
* migration
* update schema and build factory
* update string
* move version picker
* tooltip instead of infobadge
* --
* fix type
* --
* fix type
* fix type
* --
* fix messed up merge
* improvements to payloadfactory
* extract version off of DB and instead keep it in IWebhookRepository
* fix webhookform
* fix type safety and routing ambiguity
* scalable with easier factory extensions and base definition
* fix types
* --
* --
* clean up prisma/client type imports
* fix
* type fix
* type fix
* cleanup
* add tests and registry changes
* unintended file inclusion
* type-fix
* select in repo
* --
* explicit return type
* --
* fix type
* fixes
* feedback 1
* feedback 2
* use enum instead of string
* fixes
* Isolate companion build
* Fix typo
* Update .github/workflows/pr.yml
* Improve branch protection
* integration tests missing
* fix typo
* fix to only have required
* fix to only have required
* fix to only have required
* adjust to keep as before
---------
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
* chore: Change atoms build command to build-npm to avoid turbo compilations
* Updated turbo.json atoms#build reference
* Updated atoms production build for CI
* fix: prevent Prisma conditional types from leaking into .d.ts files
This PR addresses TypeScript performance issues caused by Prisma's conditional types leaking through the type graph:
1. Replace Prisma.UserGetPayload with explicit UpdatedUserResult type in updateProfile.handler.ts
2. Replace Prisma.EventTypeGetPayload with explicit UpdatedEventTypeResult type in update.handler.ts
3. Replace Prisma.OutOfOfficeEntryGetPayload with explicit OOOEntryResult type in outOfOfficeCreateOrUpdate.handler.ts
4. Replace Prisma.CredentialGetPayload with explicit Credential type in getUserConnectedApps.handler.ts
5. Fix inconsistent DI usage in EventTypeRepository - use this.prismaClient instead of global prisma singleton
These changes prevent massive recursive Prisma types from propagating through the type graph and being emitted in .d.ts files, which improves TypeScript performance.
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* fix: correct reasonId type to number | null in OOOEntryResult
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* perf: add z.ZodType annotations to reduce .d.ts file sizes
- Annotate exported Zod schemas with z.ZodType<T> to prevent full Zod generic tree from being emitted in declaration files
- eventTypes/types.d.ts reduced from 231KB to 115KB (50% reduction)
- _app.d.ts reduced from 782KB to 753KB (3.7% reduction)
- viewer/_router.d.ts reduced from 722KB to 695KB (3.7% reduction)
- workflows/getAllActiveWorkflows.schema.d.ts significantly reduced
- routing-forms/formMutation.schema.d.ts significantly reduced
Files modified:
- packages/trpc/server/routers/viewer/eventTypes/types.ts
- packages/trpc/server/routers/viewer/workflows/getAllActiveWorkflows.schema.ts
- packages/trpc/server/routers/apps/routing-forms/formMutation.schema.ts
- packages/features/eventtypes/lib/types.ts
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* perf: comprehensive z.ZodType annotations to reduce .d.ts file sizes
Applied z.ZodType<T> annotations to 89 schema files across the tRPC package.
This prevents TypeScript from emitting the full Zod generic tree in .d.ts files,
reducing declaration file sizes for downstream consumers.
Files modified include schemas in:
- viewer/teams (round-robin, managed events, invitations, etc.)
- viewer/bookings (get, find, confirm, etc.)
- viewer/eventTypes (get, delete, getByViewer, etc.)
- viewer/workflows (list, delete, verify, etc.)
- viewer/auth (changePassword, verifyPassword, etc.)
- viewer/apiKeys (create, delete, edit, etc.)
- viewer/sso (get, update, delete, updateOIDC)
- viewer/oAuth (addClient, generateAuthCode)
- viewer/calendars (setDestinationCalendar)
- viewer/deploymentSetup (update, validateLicense)
- apps/routing-forms (formQuery, deleteForm, etc.)
- publicViewer (submitRating, markHostAsNoShow, etc.)
- loggedInViewer (eventTypeOrder, routingFormOrder, etc.)
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* fix: revert slots/types.ts z.ZodType annotation that caused type mismatch
The slots/types.ts schema has a transform that converts duration from
string to number, which makes the z.ZodType<T> annotation incompatible.
Reverting to original to fix Unit test failure.
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* fix: use 3-generic z.ZodType pattern for schemas with .default() modifiers
For schemas with .default() modifiers, the input and output types differ:
- Input type: field is optional (what callers send)
- Output type: field is required (what handlers receive after parsing)
This commit:
1. Fixes get.schema.ts (offset has .default(0))
2. Fixes removeMember.schema.ts (isOrg has .default(false))
3. Fixes resendInvitation.schema.ts (isOrg has .default(false))
4. Fixes listMembers.schema.ts (limit has .default(10))
5. Fixes getByViewer.schema.ts (limit has .default(10))
6. Reverts eventTypes/types.ts (complex transforms hard to model)
7. Reverts features/eventtypes/lib/types.ts (complex transforms hard to model)
The 3-generic pattern z.ZodType<Output, z.ZodTypeDef, Input> properly models
the difference between input and output types while still preventing the full
Zod generic tree from being emitted in .d.ts files.
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* fix: use 3-generic z.ZodType pattern for schemas with transforms/defaults
- organizations/update.schema.ts: orgId has .transform() that converts string to number, so input type is string | number but output type is number
- publicViewer/event.schema.ts: fromRedirectOfNonOrgLink has .default(false), so input has it optional but output has it required
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* fix: use 3-generic z.ZodType pattern for updateProfile.schema.ts
Address reviewer feedback: isDeleted field in secondaryEmails has .default(false),
so input type has it optional but output type has it required.
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* chore: remove explanatory comments from schema files
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* fix: use 3-generic z.ZodType pattern for addClient.schema.ts enablePkce field
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* fix: address Hariom's PR feedback
- Rename TGetInputSchemaInput to TGetInputRawSchema in get.schema.ts
- Use Prisma-free JsonValue type from @calcom/types/Json in updateProfile.handler.ts
- Fix publish.schema.ts with 3-generic pattern for z.coerce.number()
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
* fix: add sort field to TGetInputSchema types
Added sort field to both TGetInputRawSchema and TGetInputSchema types
to match the Zod schema that was updated in main branch.
Co-Authored-By: keith@cal.com <keithwillcode@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Hey team,
[**Lingo.dev**](https://lingo.dev) here with fresh translations!
### In this update
- Added missing translations
- Performed brand voice, context and glossary checks
- Enhanced translations using Lingo.dev Localization Engine
### Next Steps
- [x] Review the changes
- [x] Merge when ready
* chore: update dependencies and update event types screen header
* refactor: simplify EventTypeListItem component by removing unused imports and code
- Removed unnecessary imports such as Tooltip and Svg.
- Cleaned up the component by eliminating commented-out code and unused props.
- Streamlined the button rendering in the context menu for better readability.
* feat: enhance EventTypes header with blur effect and clean up code
- Added blurEffect property to Stack.Header for improved visual aesthetics.
- Removed commented-out code to streamline the EventTypes component.
- Updated search bar properties for better user experience.
* refactor: update TabLayout and EventTypes for improved platform handling
- Simplified TabLayout by removing the liquid glass effect check and adding a WebTabs fallback for web support.
- Updated EventTypes header to conditionally apply blur effect based on liquid glass availability, enhancing visual consistency across platforms.
* feat: enhance TabLayout with MaterialCommunityIcons for improved UI
- Updated TabLayout to use MaterialCommunityIcons for tab icons, enhancing visual consistency.
- Added softwareKeyboardLayoutMode to app.json for better keyboard handling on mobile devices.
* feat: update TabLayout to prevent transparent background on iOS 18
- Added disableTransparentOnScrollEdge prop to NativeTabs to ensure a solid background on iOS 18 and older versions.
The event type description is stored as HTML from the rich text editor.
When converting to plain text for calendar events, the HTML tags were
being stripped without preserving the formatting, causing:
- Newlines to be lost (text runs together)
- Links to be broken
This fix:
- Converts <br>, </p>, </div>, </li>, </h1-6> tags to newlines
- Preserves links in readable format: 'text (url)' or just 'url'
- Normalizes multiple newlines to max 2 for cleaner output
Affects all calendar integrations (Google, Outlook, etc.)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor(data-table): clean up DateRangeFilter range options
- Replace 'past' | 'custom' with 'past' | 'future' | 'any' | 'customOnly'
- Add direction field to PresetOption for preset compatibility filtering
- Derive presets visibility automatically based on compatible presets
- Update bookings list to use new range values:
- past -> 'past'
- upcoming -> 'future'
- unconfirmed/recurring/cancelled -> 'any'
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat(playground): add DateRangeFilter playground page with E2E tests
- Add playground page at /settings/admin/playground/date-range-filter
- Demonstrate all 4 range options: past, future, any, customOnly
- Add link to playground index page
- Add E2E tests for presets visibility and date restrictions
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix(playground): use correct meta.filter pattern for column filter config
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* clean up the playground esign
* add unit tests instead of e2e
* fix the implementation
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(bookings): conditionally show heading/subtitle based on view
- Add heading and subtitle props back to ShellMainAppDir in page.tsx
- Use headerClassName marker to identify the heading element
- Add useLayoutEffect in BookingCalendarContainer to hide heading when calendar view is mounted
- Restore heading visibility when switching back to list view
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor(bookings): extract shell heading visibility into reusable hook
- Create useBookingsShellHeadingVisibility hook with explicit visible parameter
- Move visibility logic from BookingCalendarContainer to BookingsContent
- Use data attribute to track if we hid the header (idempotent/Strict-Mode-safe)
- Explicit show/hide based on view state instead of relying on unmount
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor(bookings): simplify shell heading visibility hook
Remove HIDDEN_DATA_ATTR tracking since the header wrapper won't have
a hidden class from any other source
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(companion): improve extension UX for new tab and fix mobile app issues
- Open cal.com/app when extension clicked on restricted pages (chrome://newtab, etc.)
- Auto-open sidebar when redirected to cal.com/app with ?openExtension=true
- Fix duplicate search bar in event types on web/extension
- Fix tab order mismatch on extension (Event Types, Bookings, Availability, More)
- Add logout confirmation modal for web since Alert.alert doesn't work
- Default COMPANION_DEV_URL to empty string for production builds
* fix(companion): use URL API for query parameter cleanup
Replace regex-based URL cleanup with URL API to properly handle
all query parameter positions. The previous regex produced invalid
URLs when openExtension=true was the first of multiple parameters
(e.g., ?openExtension=true&foo=bar became &foo=bar instead of ?foo=bar). fix(companion): wait for page load before auto-opening sidebar
Fix race condition where sidebar wouldn't auto-open on first visit
to cal.com/app. On uncached pages, now waits for the load event
before opening, while cached pages use a shorter delay.
* fix: update email validation to include pm.me domain and improve error handling in extractDomainFromEmail function
* feat(organizations): add pm.me and additional personal email domains
- Add pm.me (ProtonMail short domain) to personal email providers list
- Add googlemail.com, ymail.com, msn.com, mac.com, and other common personal email domains
- Add Mail.com variants (email.com, post.com, consultant.com, etc.)
- Add protonmail.ch, gmx.de, naver.com, and other regional providers
- Update all three locations: utils.ts, orgCreationUtils.ts, and test file
- Fix ESLint warnings for unnecessary escape characters in regex
* fix: allow organizations to sign up with existing usernames
- Update usernameCheck to check organization context when currentOrgDomain is provided
- Organizations can now use usernames that exist in other orgs or global namespace
- Only checks username availability within the specific organization
- Fixes issue where org signups were blocked by global username conflicts
Refs #25800
* Update username.ts
* chore: replace GH_ACCESS_TOKEN with GitHub App token
Replace personal access token (GH_ACCESS_TOKEN) with GitHub App token
generation using actions/create-github-app-token@v1 for improved security.
Updated workflows:
- draft-release.yml
- post-release.yml
- cleanup.yml
- cleanup-report.yml
- publish-report.yml
- i18n.yml
Benefits:
- Short-lived tokens (1 hour) vs long-lived PATs
- Fine-grained, scoped permissions
- Not tied to individual user accounts
- Better audit trail
Required setup:
- Create a GitHub App with contents:write permission
- Install the app on calcom/cal.com and calcom/test-results-2
- Add RELEASE_APP_ID and RELEASE_APP_PRIVATE_KEY secrets
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* chore: rename secrets to CI_CAL_APP_ID and CI_CAL_APP_PRIVATE_KEY
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* chore: use reusable workflow from calcom-ci-secrets for token generation
This isolates the GitHub App private key in a separate repository,
ensuring that compromised actions in cal.com can only access short-lived
tokens, not the key itself.
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* chore: use explicit secret passing instead of secrets: inherit
Only pass the two required secrets (CI_CAL_APP_ID, CI_CAL_APP_PRIVATE_KEY)
to the reusable workflow instead of inheriting all secrets.
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* chore: remove secrets block - using environment secrets from calcom-ci-secrets
Secrets are now loaded from the ci-github-app environment in
calcom-ci-secrets, so cal.com workflows no longer need to pass them.
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* chore: revert to explicit secret passing
Environment secrets in cross-repo reusable workflows don't work as expected.
Secrets must be passed explicitly from the caller repository.
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
* chore: generate GitHub App token directly in workflows
Remove dependency on calcom-ci-secrets reusable workflow.
Token generation is now inline using actions/create-github-app-token
pinned to SHA 7e473efe3cb98aa54f8d4bac15400b15fad77d94 (v2.2.0).
Co-Authored-By: alex@cal.com <me@alexvanandel.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
* fix: add dark mode support to emptypage skeleton and layout
* style: remove dark blur effect from EmptyPage component
* style: add dark mode divide subtle to EmptyPage component
* feat(insights): include all booking question fields in CSV export for non-seated events
- For non-seated events: export all custom booking question fields (phone, text, number, select, multiselect, url, checkbox, textarea) excluding system fields
- For seated events: preserve existing behavior (only phone-type fields)
- Add extractFieldValue helper to handle all field value types
- Fix phone fallback logic to only use actual phone field values
- Optimize cache lookup with single get() instead of has() + get()
* refactor(insights): extract CSV data transformation logic into separate module
- Extract manipulation logic from getCsvData into csvDataTransformer.ts
- Add extractFieldValue, isSystemField, and other helper functions
- Add processBookingsForCsv and transformBookingsForCsv functions
- Add comprehensive snapshot tests with dummy data
- Tests demonstrate how input becomes output for various scenarios
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix(insights): update BookingWithAttendees type to match Prisma query result
- Change noShow field type from boolean to boolean | null
- Fixes type error TS2345 in InsightsBookingBaseService.ts
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: eunjae@cal.com <hey@eunjae.dev>
* refactor: migrate workflows utilities from trpc to features layer
Move workflow utility functions from packages/trpc/server/routers/viewer/workflows/util.ts
to packages/features/ee/workflows/lib/workflowUtils.ts to break circular dependencies.
Functions migrated:
- isAuthorized
- getAllWorkflowsFromEventType
- scheduleWorkflowNotifications
- scheduleBookingReminders
Changes:
- Created new workflowUtils.ts in features layer with migrated functions
- Added getBookingsForWorkflowReminders to WorkflowRepository (no prisma outside repositories)
- Updated all imports in features layer to use new location
- Updated trpc util.ts to re-export from features for backward compatibility
- Fixed pre-existing lint warning (any -> unknown) in handleMarkNoShow.ts
This is part of the effort to remove circular dependencies between
packages/features and packages/trpc.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: remove re-exports from trpc util.ts, update imports to use features layer
Per user request, removed the backward compatibility re-exports from
packages/trpc/server/routers/viewer/workflows/util.ts and updated all
imports in the trpc package to import directly from the features layer.
Files updated to import from @calcom/features/ee/workflows/lib/workflowUtils:
- confirm.handler.ts (getAllWorkflowsFromEventType)
- delete.handler.ts (isAuthorized)
- update.handler.ts (isAuthorized, scheduleWorkflowNotifications)
- getAllActiveWorkflows.handler.ts (getAllWorkflowsFromEventType)
- get.handler.ts (isAuthorized)
- util.test.ts (isAuthorized)
- delete.handler.test.ts (isAuthorized)
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update test imports to use features layer for workflow utilities
Updated test files to import scheduleBookingReminders and
scheduleWorkflowNotifications from @calcom/features/ee/workflows/lib/workflowUtils
instead of @calcom/trpc/server/routers/viewer/workflows/util.
Files updated:
- packages/features/ee/workflows/lib/test/workflows.test.ts
- packages/features/tasker/tasks/scanWorkflowBody.test.ts
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: split workflowUtils.ts into individual files
Split the monolithic workflowUtils.ts into separate files for each function:
- isAuthorized.ts - Authorization check for workflow access
- getAllWorkflowsFromEventType.ts - Get workflows for an event type
- scheduleWorkflowNotifications.ts - Schedule workflow notifications
- scheduleBookingReminders.ts - Schedule booking reminders
The workflowUtils.ts now re-exports from these individual files for
backward compatibility.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix import
* fix more
* wip
* wip
* remove workflowUtils
* wip
* refactor deleteRemindersOfActiveOnIds
* fix
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor(holidays): improve code quality and address PR review feedback
- Move HolidaysView.tsx from /features to /apps/web/modules following
the pattern of keeping trpc-using components in /apps/web/modules
- Fix prisma import to use named import: `import { prisma }`
- Fix timezone bug in checkConflicts: use dayjs.utc() for consistent
date boundaries regardless of server timezone
- Fix toggleHoliday validation to include both current and next year
holidays, matching the holidays displayed to users
- Implement dependency injection pattern for holiday repository:
- Create PrismaHolidayRepository with instance methods
- Add HOLIDAY_REPOSITORY DI token and module
- Update containers to load holiday repository module
- Update calculateHolidayBlockedDates to use injected repository
- Remove stale HOLIDAY_CACHE_DAYS env declaration (now a constant)
- Update tests to mock repository instead of prisma directly
* feat(holidays): improve UI responsiveness and add country flags
- Add country flag emojis to holidays dropdown using Unicode regional
indicator symbols
- Handle edge cases for religious holidays (Hindu, Christian, etc.)
which dont have 2-letter country codes
- Increase country dropdown width to 180px for better readability
- Make OOO/Holidays tabs responsive: use Select dropdown on mobile,
ToggleGroup on desktop
- Make + Add button responsive: show only + icon on mobile,
full text on desktop
- Fix PrismaHolidayRepository import to use @calcom/prisma for
consistency with other repositories
* feat(holidays): add contextual emojis for holidays
- Add keyword-based emoji mapping for 80+ holidays
- Display holiday emojis in styled containers on settings page
- Add country flag emojis to dropdown using Unicode regional indicators
- Use dynamic emojis on booking page unavailable dates
* fix(holidays): address PR review feedback
- Fix emoji ordering: move Chinese/Lunar New Year before generic new year to prevent incorrect match
- Fix i18n: use t() instead of hardcoded text more in conflict warning
- Fix a11y: use sr-only pattern for mobile button to maintain screen reader accessibility
* fix failing test: packages/features/availability/lib/calculateHolidayBlockedDates.test.ts
* fix failing test: packages/features/availability/lib/calculateHolidayBlockedDates.test.ts
* fix failing tests and builds
* fix: improve E2E test stability and reduce flakiness
- Replace hardcoded waits with proper Playwright waitFor assertions in slot selection
- Add explicit waits for calendar and time slot elements to be visible before clicking
- Replace fixed 2s wait in gotoRoutingLink with networkidle wait
- Replace fixed 5s email wait with retry logic (10 retries, 500ms intervals)
- Use unique usernames with timestamps to avoid parallel test collisions
- Use features fixture instead of direct prisma calls for feature flag mutations
- Fix login.e2e.ts to use unique username instead of hardcoded 'pro'
- Fix signup.e2e.ts to use unique usernames and proper feature flag handling
- Remove unused 'users' parameter from tests that don't need it
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* perf: replace waitForTimeout with smart waits for faster E2E tests
- Replace 30 waitForTimeout calls with proper Playwright waits
- Use waitFor({ state: 'visible' }) for element visibility
- Use waitForLoadState('networkidle') for page load completion
- Use waitForFunction for localStorage state changes
Performance improvements:
- limit-tab.e2e.ts: 10s fixed wait -> element visibility wait
- booking-duplicate-api-calls.e2e.ts: 5s fixed wait -> networkidle
- change-theme.e2e.ts: 3s fixed wait -> localStorage state check
- team-invitation.e2e.ts: multiple 500ms-3s waits -> element waits
- booking-seats.e2e.ts: 2s waits -> dropdown visibility waits
- embed-code-generator.e2e.ts: 1s waits -> iframe visibility waits
- organization-privacy.e2e.ts: 500ms waits -> element/networkidle waits
- organization-invitation.e2e.ts: 500ms-1s waits -> element waits
- analyticsApps.e2e.ts: 1s wait -> networkidle
- integrations.e2e.ts: 1s wait -> calendar element wait
- fixtures/apps.ts: 1s waits -> element visibility waits
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add holidays feature for automatic availability blocking- Add UserHolidaySettings model for storing user preferences- Generate static holiday data for 20 countries using date-holidays- Create HolidayService for runtime holiday queries- Add TRPC router with endpoints for country selection and holiday toggles- Create Holidays tab UI in Availability page with conflict warnings- Integrate holiday blocking into getUserAvailability calculation- Show holiday indicator on blocked dates in booker page- Add warning in OOO modal when dates overlap with holidays
* feat: add optimizations, tests, and code quality improvements
- Add memoization/caching to HolidayService for better performance
- Optimize checkConflicts DB query with OR conditions for specific dates
- Add HolidayService unit tests (10 tests)
- Add error handling with Alert component for failed queries
- Memoize HolidayListItem component to prevent unnecessary re-renders
- Extract magic numbers into constants.ts
- Use TRPCError consistently in handlers
- Add missing i18n keys for error messages
- Update handlers to follow Cal.com patterns (default exports, minimal comments)
- Add regeneration instructions in constants
* refactor: replace static JSON with Google Calendar API integration
- Add GoogleHolidayService to fetch holidays from Google Calendar public calendars
- Add HolidayCache Prisma model for caching API responses
- Add GOOGLE_CALENDAR_API_KEY and HOLIDAY_CACHE_DAYS env variables
- Support 38 countries via Google Calendar holiday calendars
- Update HolidayService methods to async with database caching
- Update all TRPC handlers for async holiday methods
- Fix UI to display holiday dates correctly
- Remove static holidays.json and generate script
* use we instead of calcom in i18n message
* address cubics comments
* move holidays from availability to ooo
* public holidays filter for holidays
* follow i18n _one and _other pattern
* remove holiday feature flag
* revert lint command code change
* revert lint command code change 2.0
* revert lint command code change 3.0
* bye bye my christmas emoji :crying-emoji
* remove comments
* refactor(holidays): add repository pattern, split services, and add tests
- Create HolidayRepository for database operations
- Split GoogleHolidayService into GoogleCalendarClient and HolidayCacheService
- Add dependency injection to HolidayService and HolidayCacheService
- Update TRPC handlers to use HolidayRepository
- Add tests for HolidayRepository and calculateHolidayBlockedDates
- Update calendar IDs to use official holiday format (244 countries + religions)
* fix: address PR review feedback
- Remove unused date-holidays package
- Add pluralization for and_more_holidays_with_conflicts translation
- DRY: spread GOOGLE_RELIGIOUS_HOLIDAY_CALENDARS into GOOGLE_HOLIDAY_CALENDARS
- Add select to userHolidaySettings query in getUserAvailability
- Optimize checkConflicts with pre-computed timestamps
* refactor(holidays): apply proxy pattern and move logic to service
- Rename HolidayCacheService to HolidayServiceCachingProxy (proxy pattern)
- Remove HOLIDAY_CACHE_DAYS env var, use constant directly
- Add isSupportedCountry() method to HolidayService
- Add getUserSettings() and updateSettings() to HolidayService
- Move toggleHoliday logic from handler to service
- Move checkConflicts logic from handler to service
- Add findBookingsInDateRanges() to HolidayRepository
- Simplify all handlers to just call service methods
* feat(bookings): add backend validation to prevent booking on holidays
Adds explicit holiday conflict validation during booking creation to
handle the race condition where a host enables a holiday after a guest
selects a date but before they submit the booking.
Changes:
- Add checkHolidayConflict validation with HolidayRepository integration
- Integrate ensureNoHolidayConflict in RegularBookingService
- Add BookingOnHoliday error code with proper HTTP 400 response
- Handle holiday error display in BookEventForm with name interpolation
- Hide trace ID for expected validation errors
- Add unit tests for holiday conflict validation
* fix failing type check
* fix: address PR review comments for holiday feature
- Change error code from BAD_REQUEST to INTERNAL_SERVER_ERROR in
toggleHoliday handler (errors are internal failures, not bad input)
- Refactor ensureNoHolidayConflict to use Promise.all for parallel
user checking instead of sequential loop
* refactor: use Promise.all with logging in loop for holiday check
- Check all users in parallel using Promise.all
- Log conflicts inside the loop as they are detected
- Wait for all checks to complete before throwing error
* fix(holidays): use host timezone for holiday conflict checks
The holiday feature was checking booking dates against holidays using
server/local timezone instead of the host's timezone. This caused
bookings near midnight boundaries to incorrectly pass or fail the
holiday check.
Example: A booking at Dec 24th 8PM UTC (which is Dec 25th in IST)
was not being blocked for an Indian host with Christmas as a holiday.
Changes:
- Add .utc() to holiday date formatting for consistency
- Fetch host's timezone in checkHolidayConflict
- Convert booking time to host's timezone before comparison
- Add findUserSettingsWithTimezone to HolidayRepository
- Update error message to clarify it's the host's local time
- Add timezone edge case tests
* fix(holidays): align holiday blocking with OOO pattern for consistent timezone handling
- Simplify calculateHolidayBlockedDates to match OOO pattern using dayjs.utc()
- Fix date range query to use full day bounds (startOfDay/endOfDay) so holidays
stored at midnight UTC are correctly found during booking validation
- Remove separate checkHolidayConflict booking-time validation - holidays now
block through oooExcludedDateRanges like OOO does
- Remove getHolidayOnDate from HolidayService (no longer needed)
- Remove findUserSettingsWithTimezone from HolidayRepository (no longer needed)
- Clean up related tests
Holiday blocking now works exactly like OOO:
1. Holidays are added to datesOutOfOffice in calculateHolidayBlockedDates
2. buildDateRanges processes them via processOOO with .tz(timeZone, true)
3. oooExcludedDateRanges excludes those dates from availability
4. ensureAvailableUsers uses oooExcludedDateRanges to block bookings
This ensures consistent timezone handling where Dec 25th blocks all hours
of Dec 25th in the host's timezone, regardless of booker's timezone.
* update test
* update .env.example file
* display UTM parameters
* persist view (list | calendar) in localStorage
* move to next page on clicking "next" of last item in the page
improve navigation
^ Conflicts:
^ apps/web/modules/bookings/components/BookingCalendarContainer.tsx
* fix navigation on calendar view
* Delete apps/web/modules/bookings/NAVIGATION_IMPLEMENTATION.md
* avoid page size being 0
* check feature flag on user level
* use map to improve useBookingListData
* address feedback
* feat(bookings): add smart navigation for calendar view
- Add sort option to tRPC bookings.get schema and handler
- Create NAVIGATION_PROBE_WINDOW_MONTHS constant (3 months)
- Create useNearestFutureBooking hook to find nearest future booking
- Create useNearestPastBooking hook to find nearest past booking
- Update useCalendarNavigationCapabilities to use probe results
- Update BookingCalendarContainer to wire up probe hooks
This enables the booking details sheet to:
- Disable next/prev buttons when no bookings exist in that direction
- Jump directly to the week containing the nearest booking
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix type error
* feat: add booking selection state when using slideover (#25637)
* implement booking selection when using slideover
* remove pixel shift
* fix
* auto scroll to selected event on calendar
* make DateValues header sticky when scrolling
---------
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
* prefetch previous / next weeks on calendar view
* clean up classes
* handle "fetched & but no data" situation more correctly in useCalendarAutoSelector
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com>
* feat: add gradient indicator for scrollable event descriptions
- Create EventDescription component with dynamic gradient overlay
- Show gradient only when description content overflows (180px max-height)
- Use Tailwind v4 gradient utilities for optimal styling
- Replace inline description rendering in EventMeta with new component
- Minimal implementation: 28 lines, no useEffect, single state variable
* add top gradient and optimize ScrollableWithGradients component
* add top gradient and optimize ScrollableWithGradients component
* refactor: extract reusable ScrollableWithGradients component with top/bottom gradients
* adjust gradient fades
* feat: extract core booking audit infrastructure from PR 25125
This PR contains only the core booking audit infrastructure changes from PR 25125,
excluding integration changes with booking flows.
Included:
- All packages/features/booking-audit/* (core audit services, actions, repository)
- packages/features/di/containers/BookingAuditViewerService.container.ts
- packages/features/tasker/tasker.ts (audit task types)
- packages/features/bookings/lib/types/actor.ts (actor types for audit)
- packages/features/bookings/repositories/BookingRepository.ts (getFromRescheduleUid method)
- apps/web/modules/booking/logs/views/booking-logs-view.tsx (UI for viewing audit logs)
- apps/web/public/static/locales/en/common.json (translations)
Excluded (integration changes):
- packages/trpc/server/* (tRPC handlers)
- packages/features/ee/round-robin/* (round-robin integration)
- packages/features/bookings/lib/handleCancelBooking.ts
- packages/features/bookings/lib/handleConfirmation.ts
- packages/features/bookings/lib/onBookingEvents/BookingEventHandlerService.ts
- packages/features/bookings/lib/service/RegularBookingService.ts
- apps/api/v2/* (API v2 integration)
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: make booking audit interfaces backwards-compatible with main
- Add queueAudit method back to BookingAuditProducerService interface for backwards compatibility
- Implement queueAudit method in BookingAuditTaskerProducerService
- Make userTimeZone parameter optional in BookingAuditViewerService
- Add BookingAuditTaskProducerActionData type for legacy queueAudit method
- Use any generics in BookingAuditActionServiceRegistry (matching PR 25125)
- Fix type assertions in BookingAuditTaskConsumer
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix switch eslint and ts
* feat: enhance BookingAuditViewerService with logging and type improvements
- Added ISimpleLogger dependency to BookingAuditViewerService for better error handling.
- Updated actor type in enriched audit logs to use AuditActorType for improved type safety.
- Replaced console.error with logger for error reporting when no rescheduled log is found.
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
- Update weekly view to display OOO when showNotePublicly is true
- Update column view to include days with public notes in schedule
- Add notes and showNotePublicly props to weekly view calendar
- Disable show note publicly checkbox when notes field is empty
* update imports
* move trpc router from features to trpc
* update imports
* wip
* update imports
* wip
* wip
* wip
* fix import
* create objectToCsv.ts
* rename
* fix: restore proper types and static imports in insights handlers
- Add proper type definitions for all handler options instead of using 'any'
- Restore static imports for PermissionCheckService and MembershipRole
- Remove dynamic imports that were introduced during refactoring
This ensures the refactoring is pure with no behavioral changes.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: update getEventTypeList import path after utils.ts deletion
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* remove handlers
* fix
* refactor
* wip
* rm
* wip
* select only needed + fix type error
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
* fix: filter slots by requested date range to prevent date override leakage
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* refactor: move filterSlotsByRequestedDateRange to private method
Co-Authored-By: morgan@cal.com <morgan@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: use relative redirects in booking confirmation routes to fix localhost redirect issue
When Cal.com runs behind a reverse proxy, request.url may return the internal
server URL (localhost:3000) instead of the external URL. This causes users to
be redirected to localhost after confirming bookings via email links.
This fix changes the redirect URLs from using url.origin (which could be
localhost) to using relative URLs via new URL(path, request.url). This ensures
the browser resolves the redirect against whatever domain the user actually
requested, fixing the issue for self-hosted deployments behind proxies.
Fixes#20358
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* test: add tests for booking confirmation redirect URL construction
Add unit tests for verify-booking-token and link API routes to ensure:
- Redirect URLs preserve the request origin (not hardcoded localhost)
- Redirect URLs use the correct booking path (/booking/{uid})
- Error messages are properly encoded in query params
- POST handler returns correct 303 status code
These tests verify the fix for #20358 where users were redirected to
localhost:3000 instead of the proper production URL after confirming
bookings via email links.
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
* fix: add second argument to GET/POST calls in test files to fix type errors
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: Add async spam check integration and decoy booking response
- Integrate SpamCheckService with handleNewBooking workflow
- Implement parallel spam check execution for minimal performance impact
- Add decoy booking response with localStorage-based success page
- Extract organization ID from event type for org-specific blocking
- Add comprehensive test coverage for spam detection scenarios
- Create reusable components for booking success cards
- Implement fail-open behavior to never block legitimate bookings
This builds on the spam blocker DI infrastructure from PR #24040 by
adding the actual integration into the booking flow and implementing
the decoy response mechanism to avoid revealing spam detection to
malicious actors.
Related: #24040
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Do checks in paralle
* Fix leaking host name in title
* Reduce expoiry time localstorage
* refactor: Use sessionStorage instead of localStorage for decoy booking data
- Replace localStorage with sessionStorage for automatic expiration on tab close
- Remove timestamp tracking and TTL logic (no longer needed)
- Improve privacy by auto-clearing data when browser tab/window closes
- Update documentation to reflect sessionStorage behavior
This change addresses privacy concerns by ensuring decoy booking data
(including attendee email) is automatically removed when the user closes
the tab, rather than persisting for 5 minutes or requiring manual cleanup.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* feat: Add sessionStorage wrapper to webstorage module
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* Reset RegularBookingService.ts to main's version exactly
* feat: Add 5-minute expiration timeout to decoy booking data
- Adds timestamp to DecoyBookingData interface
- Checks expiration when retrieving booking data
- Automatically removes expired data from sessionStorage
- Provides defense-in-depth against potential misuse
- Works alongside sessionStorage auto-clear on tab close
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: hide insights submenu for free users
* fix: allow navigation access while plan pending
* refactor: update upgrade link to insights in navigation
* fix: addressed all the issues
* fix: prevent flash of premium features for free users during loading
Change from optimistic to pessimistic loading so free users don't
briefly see the Insights submenu while plan status is being fetched.
---------
Co-authored-by: Dhairyashil <dhairyashil10101010@gmail.com>
* fix: show hidden badge on mobile view for event types
* fix: update event type hidden toggle in infinite list
---------
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
* feat: highlight recurring bookings with time shift badge across DST
* Update packages/lib/__tests__/timeShift.test.ts
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* refactor: show time shift badge only on first shift in bookings view and occurrences
* refactor: update recurring bookings display logic and wrap booking title text
* refactor: add getFirstShiftFlags helper for time shift flags and update components
---------
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* fix(settings): improve spacing between navigation child items
* chore: removing prettier formatting
* style: update dropdown item class names for consistent rounding
* style: add spacing and hover margin to navigation items
* style: add hover margin top to navigation item
* apply same ui changes for team profile menu
---------
Co-authored-by: Dhairyashil <dhairyashil10101010@gmail.com>
* feat: add embed prerendering support and enhance event handling
- Introduced `useIsEmbedPrerendering` hook to determine if the embed is in prerender mode.
- Updated `useAvailabilityEvents` to prevent firing events during prerendering.
- Added `bookerLoadedEvent` and `availabilityRefreshed` types to `EventDataMap`.
- Implemented `useFirebookerLoadedEvent` to manage firing the booker loaded event conditionally.
- Refactored event firing logic in `useSchedule` and `BookerWebWrapper` components to utilize new hooks.
* feat: add embed prerendering support and enhance event handling
- Introduced `useIsEmbedPrerendering` hook to determine if the embed is in prerender mode.
- Updated `useAvailabilityEvents` to prevent firing events during prerendering.
- Added `bookerLoadedEvent` and `availabilityRefreshed` types to `EventDataMap`.
- Implemented `useFirebookerLoadedEvent` to manage firing the booker loaded event conditionally.
- Refactored event firing logic in `useSchedule` and `BookerWebWrapper` components to utilize new hooks.
* feat: enhance embed event handling and introduce link reopening detection
- Added `useEmbedReopened` hook to track when the embed is reopened.
- Updated `BookerWebWrapper` to reset event firing state upon embed reopening.
- Refactored event firing logic to use `bookerViewed` instead of `bookerLoadedEvent`.
- Introduced scheduling for event firing in `useSchedule` to ensure correct order of events during prerendering.
* feat: add lifecycle diagrams for inline and modal embeds
- Introduced `inline-embed-lifecycle.mermaid` and `modal-embed-lifecycle.mermaid` files to visualize the lifecycle events and states of inline and modal embeds.
- Updated `LIFECYCLE.md` to reference the new diagrams and provide a clearer explanation of the embed lifecycle processes.
- Added `modal-prerendering-flow.mermaid` to illustrate the prerendering flow for modal embeds.
- Enhanced the routing playground with new features and improved event handling for availability and booking events.
* refactor: update event handling for booker lifecycle events
- Replaced `availabilityLoaded` event with `bookerReady` to better reflect the state when the booker view is fully loaded and ready for interaction.
- Updated related documentation and diagrams to reflect changes in event triggers and descriptions.
- Adjusted internal state management to track `viewId` instead of `reopenCount` for distinguishing between initial views and reopens.
- Added tests for new event handling logic to ensure correct firing of `bookerViewed`, `bookerReopened`, and `bookerReady` events.
* refactor: enhance embed event handling and state management
- Updated event handling for booker lifecycle events, replacing `resetViewVariables` with `resetPageData` to manage page-specific state.
- Introduced new utility functions for managing event firing states and reload initiation.
- Refactored `fireBookerViewedEvent` and `fireBookerReadyEvent` to utilize the new state management functions.
- Added comprehensive tests for the updated event handling logic and state resets to ensure correct functionality across various scenarios.
* refactor: update embed iframe configuration and utility functions
- Reduced `slotsStaleTimeMs` from 30 seconds to 10 seconds and `iframeForceReloadThresholdMs` from 100 seconds to 30 seconds for improved responsiveness.
- Refactored utility functions to use `isBrowser` for client-side checks instead of `isClientSide`.
- Removed unused `isPrerendering` function and updated related documentation for clarity.
- Enhanced event handling by exporting `useBookerEmbedEvents` from the appropriate module for better accessibility.
* refactor: update embed iframe configuration and utility functions
- Reduced `slotsStaleTimeMs` from 30 seconds to 10 seconds and `iframeForceReloadThresholdMs` from 100 seconds to 30 seconds for improved responsiveness.
- Refactored utility functions to use `isBrowser` for client-side checks instead of `isClientSide`.
- Removed unused `isPrerendering` function and updated related documentation for clarity.
- Enhanced event handling by exporting `useBookerEmbedEvents` from the appropriate module for better accessibility.
* fix cubic feedback
- Add early return when only one user is available
- Prevents unnecessary database queries, calendar API calls, and OOO checks
- Add comprehensive test to verify optimization works correctly
Fixes#19503 [CAL-5212]
* feat: ooo message on booking page
* make ooo days selectable even when no redirect booking
* handle long notes
* remove unused i18n key
* Private notes stay private on the server, No accidental data leaks through client-side payloads
* address cubics comments
* fix: replace toggle with checkbox for OOO note visibility
- Replace Switch with Checkbox for "show note publicly" option
- Remove "OOO Message:" prefix from displayed notes on booking page
- Update i18n text to "Show note on public booking page"
- Remove unused ooo_message i18n key
* fix the accessibility issue by using proper htmlFor and id association
* only allow selecting OOO dates when the note is public
* fix: cloudflare turnstile token reset
* fix: silently reset turnstile on invalid token error
* refactor: remove unused forwardRef logic from Turnstile component
- Remove forwardRef, useImperativeHandle, and useRef imports
- Remove unused TurnstileInstance type export
- Simplify to a plain function component
- The ref-based reset was replaced by key-based remount in signup-view
* refactor: remove redundant cfToken validation check
The submit button is already disabled when cfToken is missing,
making this defensive check unreachable during normal form flow.
* revert prettier formatiing
* chore: revert yarn.lock changes
* refactor(auth): use shared constant for cloudflare token error message
Replace hardcoded "Invalid cloudflare token" string with an exported
constant to prevent silent breakage if the error message changes.
* fix(validation): disallow whitespace-only team name
* fix validation at team profile
* fix validation for title at event type
---------
Co-authored-by: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com>
* use booking.uid instead of booking.id for url param
* show timezone on calendar
* fix type
* restore horizontal tab and remove header and subtitle
* clean up sidebar items
* fix event propagation from attendees
* fetch all statuses except for cancelled on calendar view
* clean up styles of the badges on BookingListItem
* fix useMediaQuery
* add close button to the header
* add assignment reason to the details sheet
* use separator row
* use ToggleGroup for the top bookings tab
* move ViewToggleButton
* resize the action button
* remove wrong prop
* fix type error
* fix type error
* hide view toggle button on mobile (and fix the breakpoint)
* remove unused e2e tests
* fix e2e tests
* hide toggle button when feature flag is off
* update skeleton
* improve attendees on booking list item and slide over
* improve attendee dropdown
* fix type error
* move query to containers
* select attendee email
* infinite fetching for calendar view
* update styles
* fix compatibility
* fix: add backward compatibility for status field in getAllUserBookings
* increase calendar height
* fix type error
* support Member filter only for admin / owners
* add debug log (TEMP)
* add event border color
* show Reject / Accept buttons on BookingDetailsSheet
* move description section to the top
* update When section
* update style of Who section
* add CancelBookingDialog WIP
* fix CancelBookingDialog
* increase clickable area
* add schedule info section WIP
* fix flaky reject button
* fixing reschedule info WIP
* add fromReschedule index to Booking
* improve rescheduled information
* improve reassignment
* fix type error
* fix unit test
* respect user's weekStart value on the booking calendar view
* update debug log
* improve payment section
* clean up
* fix log message
* reposition filters on list view
* fix bookings controller api2 e2e test
* clean up file by extracting logic into custom hooks
* rename files
* merge BookingCalendar into its container
* extract logic into separate hook files
* remove redundant logic
* rearrange items on calendar view
* add WeekPicker
* extract filter button
* responsive header on list view
* horizontal scroll for ToggleGroup WIP
* fix type error
* fix cancelling recurring event
* address feedback
* fix e2e tests
* fix unit test
* fix e2e tests
* make hover style more visible for ToggleGroup
* fix margin on CancelBookingDialog
* update styles on the slide over (mostly font weight)
* update style of CancelBookingDialog
* update styles
* update margin top for the header
* refactor getBookingDetails handler
* fix gap in who section
* auto-filter the current user on the calendar view
* calculate calendar height considering top banners
* improve booking details sheet interaction without overlay
* update calendar event styles
* update reject dialog style
* put uid first in the query params
* fix class name
* memoize functions in useMediaQuery
* query attendee with id instead of email
* update margins
* replace TRPCError with ErrorWithCode
* move calculation outside loop
* remove dead code
* feat: add hostSubsetIds parameter for round robin host filtering
Add support for filtering round robin event type hosts via API v2.
When hostSubsetIds is provided, only the specified hosts are considered
for availability calculation and booking assignment.
Changes:
- Add hostSubsetIds to slots API input (GET /slots/available)
- Add hostSubsetIds to booking API input (POST /bookings)
- Update _findQualifiedHostsWithDelegationCredentials to filter by hostSubsetIds
- Pass hostSubsetIds through all layers: API -> tRPC -> slots/booking services
This allows API consumers to request availability and create bookings
for a subset of hosts within a round robin event type.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* chore: add e2e tests
* chore: add enableHostSubset team event-type setting
* fixup! chore: add enableHostSubset team event-type setting
* fix tests
* fix tests
* improve isWithinRRHostSubset
* rename to rrHost subset
* fix ai review
* fix: add booker platform wrapper rrHostSubsetIds prop
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: preserve metadata fields during partial event type updates
- Fix multipleDuration (lengthInMinutesOptions) being reset to undefined on partial updates
- Fix bookerLayouts being reset to undefined on partial updates
- Fix requiresConfirmationThreshold being reset to undefined on partial updates
- Add e2e test for lengthInMinutesOptions preservation
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* test: expand metadata preservation test to include bookerLayouts and confirmationPolicy
Co-Authored-By: morgan@cal.com <morgan@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add toggle to opt out of booking title translation in instant meetings (#25547)
* feat: add toggle to opt out of booking title translation in instant meetings
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add autoTranslateTitleEnabled to test builder
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: respect autoTranslateTitleEnabled toggle in InstantBookingCreateService
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: fetch autoTranslateTitleEnabled directly in InstantBookingCreateService
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: rename autoTranslateTitleEnabled to autoTranslateInstantMeetingTitleEnabled
- Renamed field to clarify it only applies to instant meeting title translation
- Moved Prisma query to EventTypeRepository.findInstantMeetingConfigById()
- Removed title translation logic from update.handler.ts (flag only controls instant meeting title)
- Updated all references across the codebase
- Added new i18n translation keys for the renamed field
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add autoTranslateInstantMeetingTitleEnabled to test destructuring patterns
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: use Prisma.TeamCreateInput type for metadata in test helper
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add autoTranslateInstantMeetingTitleEnabled to mockUpdatedEventType in test
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: use generic findByIdMinimal instead of business-specific method
- Add autoTranslateInstantMeetingTitleEnabled to eventTypeSelect constant
- Remove findInstantMeetingConfigById from EventTypeRepository
- Update InstantBookingCreateService to use findByIdMinimal
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: remove autoTranslateInstantMeetingTitleEnabled from eventTypeSelect (not needed for findByIdMinimal)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: add autoTranslateInstantMeetingTitleEnabled to event type form defaults
- Rename shouldTranslateTitle to shouldAutoTranslateInstantMeetingTitle for clarity
- Add autoTranslateInstantMeetingTitleEnabled to findById and findByIdForOrgAdmin selects
- Add autoTranslateInstantMeetingTitleEnabled to useEventTypeForm defaultValues
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: only update autoTranslateInstantMeetingTitleEnabled when explicitly provided
Fixes issue where omitting the field in update requests would overwrite
the saved opt-out setting with the default value (true). Now the field
is only included in the update payload when explicitly provided.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: Create standard for rate limits
---------
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: remove TRPCError handling from getServerErrorFromUnknown
This removes the @trpc/server dependency from packages/lib by removing
TRPCError handling from getServerErrorFromUnknown.ts.
packages/lib is meant to be a general utility library that other packages
depend on, so it shouldn't import tRPC. The callers that need to handle
TRPCError (like onErrorHandler.ts and defaultResponder.ts) already handle
it explicitly before calling getServerErrorFromUnknown, so this change
has no behavioral impact.
Changes:
- Remove TRPCError and getHTTPStatusCodeFromError imports
- Remove TRPCError instanceof check from getServerErrorFromUnknown
- Update docstring to note that TRPCError is not handled
- Remove TRPCError-related tests (they belong in the tRPC layer)
- Fix lint warnings in Prisma error tests (replace 'as any' with proper type)
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* wip
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Create docs/platform/guides/managed-orgs.mdx with guide for creating managed organizations and their OAuth clients via the API
- Add entry to docs/mint.json navigation menu in the Platform Guides section
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: lauris@cal.com <lauris@cal.com>
* fix: block Google Meet installation without Google Calendar dependency
- Prevent users from installing Google Meet when Google Calendar is not connected
- Update AppDependencyComponent to show error state for unmet dependencies
- Fix InstallAppButtonChild to respect disabled prop from dependencies check
- Ensure consistent dependency validation across App Store and app detail pages
Fixes#25497
* test: add unit tests for dependency validation
- Add tests for AppDependencyComponent (8 tests)
- Add tests for InstallAppButtonChild (5 tests)
- Cover dependency blocking behavior
- Test visual state changes (bg-error/bg-subtle)
* test: resolve type-check error in InstallAppButtonChild tests
- Add complete MockCredential type definition
- Create factory function to generate typed mock credentials
- Eliminate code duplication across test cases
* fix: remove redundant disabled prop assignment
Disabled state is already passed through via props.disableInstall
which gets converted to props.disabled in InstallAppButtonWithoutPlanCheck.
This change addresses the review comment to avoid unnecessary duplication
---------
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
* feat: add toggle to opt out of booking title translation in instant meetings
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add autoTranslateTitleEnabled to test builder
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: respect autoTranslateTitleEnabled toggle in InstantBookingCreateService
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: fetch autoTranslateTitleEnabled directly in InstantBookingCreateService
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: rename autoTranslateTitleEnabled to autoTranslateInstantMeetingTitleEnabled
- Renamed field to clarify it only applies to instant meeting title translation
- Moved Prisma query to EventTypeRepository.findInstantMeetingConfigById()
- Removed title translation logic from update.handler.ts (flag only controls instant meeting title)
- Updated all references across the codebase
- Added new i18n translation keys for the renamed field
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add autoTranslateInstantMeetingTitleEnabled to test destructuring patterns
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: use Prisma.TeamCreateInput type for metadata in test helper
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add autoTranslateInstantMeetingTitleEnabled to mockUpdatedEventType in test
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: use generic findByIdMinimal instead of business-specific method
- Add autoTranslateInstantMeetingTitleEnabled to eventTypeSelect constant
- Remove findInstantMeetingConfigById from EventTypeRepository
- Update InstantBookingCreateService to use findByIdMinimal
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: remove autoTranslateInstantMeetingTitleEnabled from eventTypeSelect (not needed for findByIdMinimal)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: add autoTranslateInstantMeetingTitleEnabled to event type form defaults
- Rename shouldTranslateTitle to shouldAutoTranslateInstantMeetingTitle for clarity
- Add autoTranslateInstantMeetingTitleEnabled to findById and findByIdForOrgAdmin selects
- Add autoTranslateInstantMeetingTitleEnabled to useEventTypeForm defaultValues
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: only update autoTranslateInstantMeetingTitleEnabled when explicitly provided
Fixes issue where omitting the field in update requests would overwrite
the saved opt-out setting with the default value (true). Now the field
is only included in the update payload when explicitly provided.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: email not sending on form submission
* Remove handleCheckoutSessionExpired function
Removed the handleCheckoutSessionExpired function and its registration in webhookHandlers.
* fix: Add custom payload template support for form submission webhooks
* delete
* Update applyTemplate function signature
Refactor applyTemplate function to accept specific data type.
## What does this PR do?
This PR adds user UUID plumbing from API v2 controllers through to packages/features functions. This is preparatory work extracted from PR #25125 to support future audit logging functionality.
**Key changes:**
- API v2 controllers (2024-04-15, 2024-08-13) now extract and pass `userUuid` to downstream functions
- `handleMarkNoShow` and `CancelBookingInput` types now accept optional `userUuid` parameter
- `UserRepository.findUnlockedUserForSession` now selects `uuid` field
- Session middleware now includes `uuid` in the returned user object
- Fixed lint warning: changed `PromiseSettledResult<any>` to `PromiseSettledResult<unknown>`
**Refactoring (optimization):**
- Renamed `getOwnerId` → `getOwner` and `getOwnerIdRescheduledBooking` → `getOwnerRescheduledBooking`
- These methods now return `{ id: number; uuid: string } | null` instead of just `number | undefined`
- This eliminates redundant database calls by fetching user id and uuid in a single query
**Important:** This is plumbing-only - packages/features receives the `userUuid` but does not use it directly (note the `_userUuid` prefix). The actual audit logging usage will come in a follow-up PR.
Requested by: @hariombalhara (hariom@cal.com)
Link to Devin run: https://app.devin.ai/sessions/545209189f6347cd807bf1b336f9ac40
## Mandatory Tasks (DO NOT REMOVE)
- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - no documentation changes needed.
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works. N/A - plumbing only, existing tests cover the functionality.
## How should this be tested?
1. Run type checks: `yarn type-check:ci --force`
2. Verify the changes compile without new type errors related to uuid
3. The `userUuid` parameters are optional, so existing functionality should work unchanged
## Checklist
- [x] My code follows the style guidelines of this project
- [x] I have checked if my changes generate no new warnings
## Human Review Checklist
- [ ] Verify the `userUuid` parameter is intentionally unused (prefixed with `_userUuid`) - this is plumbing for future audit logging
- [ ] Verify all callers of `getOwner` and `getOwnerRescheduledBooking` correctly handle the new `{ id, uuid } | null` return type
- [ ] Confirm the change from `undefined` to `null` as the "not found" return value is handled consistently
- [ ] Verify the `uuid` field exists in the User model schema
## What does this PR do?
This PR introduces the booking audit infrastructure with a viewer service to fetch, enrich, and format audit logs. This is the first iteration that includes only the CREATED action with versioned schema
Note: Additional audit actions, UI improvements to match with Figma will be taken care of in followup PRs, to ensure the PR size remains as small as possible(as it is large enough already)
Demo - Loom - https://www.loom.com/share/22c2f38b052b480b8be3716e1608eaf6
### Key Changes
**New Booking Audit Package** (`packages/features/booking-audit/`):
- `BookingAuditViewerService` - Fetches, enriches, and formats audit logs for display
- `BookingAuditTaskConsumer` - Processes audit tasks asynchronously via Tasker
- `CreatedAuditActionService` (v1) - Handles RECORD_CREATED action with versioned schema
**Repository Layer**:
- `BookingAuditRepository` - CRUD operations for audit records
- `AuditActorRepository` - Actor management (users, guests, system)
- `UserRepository.findByUuid()` - User lookup for actor enrichment
**UI Components**:
- New page at `/booking/logs/[bookinguid]` for viewing audit history
- Filterable audit log list with search, type, and actor filters
- Expandable log entries showing detailed change information
**Infrastructure**:
- `bookingAudit` Tasker task type for async processing
- `booking-audit` feature flag (disabled by default)
- tRPC endpoint `viewer.bookings.getAuditLogs`
### Updates since last revision
- **Refactored `Task` class to `TaskRepository`**: Converted all static methods to instance methods following the repository pattern. A singleton `Task` is exported for backward compatibility, so existing call sites continue to work unchanged.
### Important Notes for Reviewers
- **Permission check is TODO**: `checkPermissions()` in `BookingAuditViewerService` is not yet implemented
- **Only CREATED action supported**: Other actions will throw an error - additional actions will be added iteratively in follow-up PRs
- **Feature flag controlled**: System is behind `booking-audit` flag, disabled by default
- **UI strings need i18n**: Some UI text in `booking-logs-view.tsx` may need translation
### Human Review Checklist
- [ ] Verify permission enforcement strategy for audit log access
- [ ] Review DI wiring in module files
- [ ] Confirm error handling in `BookingAuditTaskConsumer` is appropriate for retry scenarios
- [ ] Check if UI strings need to be added to translation files
- [ ] Verify `TaskRepository` refactoring maintains backward compatibility (singleton export `Task` should work for all existing call sites)
## Mandatory Tasks (DO NOT REMOVE)
- [ ] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - internal infrastructure
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works.
## How should this be tested?
Run the integration tests:
```bash
TZ=UTC yarn test packages/features/booking-audit/lib/service/BookingAuditViewerService.integration-test.ts
TZ=UTC yarn test packages/features/booking-audit/lib/service/BookingAuditTaskConsumer.integration-test.ts
```
To test the UI:
1. Enable the `booking-audit` feature flag in the database
2. Create a booking (only CREATED action is supported in this PR)
3. Navigate to `/booking/logs/{bookingUid}` to view the audit trail
## Checklist
- [x] I have read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- [x] My code follows the style guidelines of this project
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have checked if my changes generate no new warnings
<!-- Link to Devin run: https://app.devin.ai/sessions/a8ae61c253b549429401c9651dcbcf44 -->
<!-- Requested by: hariom@cal.com (@hariombalhara) -->
* perf: link old event-type with workflows using create/findMany
* test: fix handleChildrenEventTypes test mocks for new workflow linking implementation
Update test to match the new implementation that uses findMany + createMany
instead of upsert for linking workflows to old event types.
- Add mock for workflowsOnEventTypes.findMany to return empty array
- Update assertion from upsert to findMany + createMany
Co-Authored-By: morgan@cal.com <morgan@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* perf: handleChildrenEventType eventtype user connect raw sql
* fixup! perf: handleChildrenEventType eventtype user connect raw sql
* remove user connect with prisma
Move handleNotificationWhenNoSlots.ts and its test file from
packages/trpc/server/routers/viewer/slots/ to packages/features/slots/
to resolve circular dependency issue where packages/features imports
from packages/trpc.
This file is not TRPC-specific and belongs in the features package.
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(api): PATCH Event Type V2 API to support all current locations
* docs(api): update locations documentation and add E2E tests for new integrations
- Updated locations property documentation in create-event-type.input.ts
and update-event-type.input.ts to clarify app installation requirements
- Explained that only Google Meet, MS Teams, and Zoom can be installed via API
- Noted that Cal Video is installed by default
- Added E2E tests for creating and updating event types with newly supported
integration locations (jitsi, zoom, google-meet, whereby, huddle, element-call)
- Regenerated openapi.json with updated API documentation
Addresses feedback from Lauris regarding platform API location support.
* fix(api): use supportedIntegrations list for app validation
Updated checkAppIsValidAndConnected to use the full supportedIntegrations
list from locations.input.ts instead of hardcoded array. This allows all
27 supported conferencing apps to be set as event type locations via API,
as long as they are already connected by the user.
* fix(api): add slug mapping for all conferencing integrations
Added comprehensive slug mapping to translate API integration names
(e.g., 'facetime-video', 'whereby-video') to actual app slugs
(e.g., 'facetime', 'whereby'). This ensures the app lookup works
correctly for all 27 supported conferencing integrations.
Addresses AI bot feedback about slug mismatches.
* fix(api): add missing huddle to huddle01 slug mapping
Added mapping for huddle -> huddle01. Other apps like tandem, jitsi,
cal-video, google-meet, and zoom don't need mapping as their API names
already match their app slugs (handled by the fallback || appSlug).
* update key
* update ket
* test(api): update E2E tests to validate newly supported integrations
Replaced end-to-end tests with validation-focused tests that follow
the existing pattern. The new test creates event types with various
newly supported integrations (jitsi, whereby-video, huddle, tandem,
element-call-video) directly in the database (bypassing app connection
checks) and verifies the API correctly returns them.
This approach tests that the input validation accepts all 27 supported
integration types without requiring actual app installations in the
test environment.
* fix(api): correct slug mappings for whatsapp, shimmer, and jelly integrations
- Fixed whatsapp-video mapping from 'whatsappvideo' to 'whatsapp'
- Fixed shimmer-video mapping from 'shimmer' to 'shimmervideo'
- Fixed jelly-conferencing mapping from 'jelly-conferencing' to 'jelly'
All slug mappings now correctly match the actual app slugs in
packages/app-store/*/config.json files. This ensures proper app
validation when users create/update event types with these locations.
Addresses feedback from @pedroccastro
* updated openapi.json file because of main branch code
* test(api): add negative test for unsupported integration locations
- Added E2E test to validate 400 error when creating event type with unsupported integration
- Test verifies exact error message listing all supported integrations
- Uses imported supportedIntegrations constant for maintainability
- Follows same pattern as booking fields validation tests
Addresses feedback from @supalarry
* test(api): add negative test for patching event type with unconnected integration
- Added E2E test to validate 400 error when user tries to PATCH event type with jitsi integration they haven't connected
- Test verifies exact error message 'jitsi not connected.'
- Follows existing test patterns with proper cleanup
* feat: api-v2-event-types-ordering
* sort team and org event types
* revert: remove accidental changes to api-auth.strategy.ts
* docs: add ordering documentation and test for event types endpoints
- Added test assertion to verify event types are returned in descending order by ID (newest first)
- Added API documentation to user event types endpoint describing default ordering behavior
- Added API documentation to team event types endpoint describing default ordering behavior
- Added API documentation to organization event types endpoints describing default ordering behavior
Addresses PR feedback to document and test the ordering behavior introduced in the API v2 event types ordering feature.
* feat: add optional sortCreatedAt parameter to event types endpoints
- Add sortCreatedAt query parameter (SortOrderType: "asc" | "desc") to all event types endpoints
- Define SortOrder enum and SortOrderType in pagination.input.ts for reusability
- When not provided, no explicit ordering is applied (backward compatible)
- Update user, team, and organization event types endpoints
- Add comprehensive e2e tests for all sorting scenarios
- Fix circular dependency in platform-types import
- Thread sortCreatedAt through all service layers
- Use spread pattern for conditional orderBy to avoid empty array issues
Addresses PR feedback to make ordering opt-in rather than changing default behavior
* fix: improve Vercel domain 'forbidden' error message
The 'forbidden' error code from Vercel is a generic permission denial,
not specifically 'domain owned by another team'. It can occur for various
reasons: wrong teamId, token lacking project access, account-level
restrictions, or domain ownership by another team.
Updated the error message to be more accurate and changed the HTTP status
code from 400 to 403 to better reflect the permission error nature.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: add message and invalidToken fields to Vercel error response schema
This allows better logging of Vercel API error responses, especially when
tokens become invalid. The new fields help with debugging permission issues.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: revert status code to 400 for Vercel forbidden errors
Keep the status code at 400 to avoid potential downstream side effects
while still using the improved error message and schema fields.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: use .nullish() instead of .optional() for message and invalidToken fields
.nullish() handles both null and undefined, which is safer for API responses.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: lint error
* feat: support `hideEventTypeDetails` via query param
Allow the event type details to be hidden based on the
hideEventTypeDetails query parameter when not in embed mode
* feat: add hideEventTypeDetails prop to EventMeta
---------
Co-authored-by: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com>
When updating an event type, fields like autoTranslateDescriptionEnabled
and disableGuests were being overwritten with false/default values even
when they weren't explicitly provided in the update request.
Changes:
- autoTranslateDescriptionEnabled: Only set when explicitly provided
(not undefined) to avoid overwriting existing true values with false
- disableGuests: Only set when bookingFields is explicitly provided,
since it's derived from the guests field in bookingFields
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: auto-scroll sidebar to active team on navigation
When navigating to team settings via "Edit team" from the teams list,
the sidebar now scrolls to show the selected team and expands its section.
- Extract team ID from URL path (/settings/teams/{id}/...)
- Use existing aria-controls attribute to find team element
- Scroll with smooth behavior centered in viewport
* revert formatting changes by prettier
---------
Co-authored-by: Pallav <90088723+Pallava-Joshi@users.noreply.github.com>
* reset store
* Update apps/web/modules/onboarding/getting-started/onboarding-view.tsx
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
---------
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
* fix: change slugification to uri encoding
* fix: add conditional joiner symbol between event type redirect url and all other search params
* fix: update integration test to expect encoded variable
* test: add tests for query parameters joiner logic
## What does this PR do?
Fixes the issue where form state wasnt corectly recorded in QA
## Visual Demo (For contributors especially)
A visual demonstration is strongly recommended, for both the original and new change **(video / image - any one)**.
#### Video Demo (if applicable):
- Show screen recordings of the issue or feature.
- Demonstrate how to reproduce the issue, the behavior before and after the change.
#### Image Demo (if applicable):
- Add side-by-side screenshots of the original and updated change.
- Highlight any significant change(s).
## Mandatory Tasks (DO NOT REMOVE)
- [ ] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [ ] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). If N/A, write N/A here and check the checkbox.
- [ ] I confirm automated tests are in place that prove my fix is effective or that my feature works.
## How should this be tested?
<!-- Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration. Write details that help to start the tests -->
- Are there environment variables that should be set?
- What are the minimal test data to have?
- What is expected (happy path) to have (input and output)?
- Any other important info that could help to test that PR
## Checklist
<!-- Remove bullet points below that don't apply to you -->
- I haven't read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- My code doesn't follow the style guidelines of this project
- I haven't commented my code, particularly in hard-to-understand areas
- I haven't checked if my changes generate no new warnings
* feat(embed-core): add public close() API for modal-based embeds
Add a proper public API method close() to the CalApi class that allows
users to programmatically close modal-based embeds (ModalBox and FloatingButton).
This replaces the need for the undocumented hack:
cal.instance.actionManager.fire('__closeIframe')
The new API is cleaner and more intuitive:
cal('close')
Key features:
- Works for modal-based embeds only (ModalBox and FloatingButton)
- Throws a clear error if called on inline embeds
- Well-documented with JSDoc comments explaining usage and limitations
Example usage:
cal('on', {
action: 'bookingSuccessful',
callback: () => {
cal('close');
}
});
Also fixed pre-existing lint issues: unused variable in catch block and
eslint-disable comment for missing rule definition.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor(embed-core): rename close() to closeModal() for clarity
Rename the close() method to closeModal() to make it immediately clear
from the API name itself that this method is for modal-based embeds only.
This makes the API more self-documenting:
- Before: cal('close')
- After: cal('closeModal')
Updated:
- Method name from close() to closeModal()
- JSDoc example to use cal('closeModal')
- Error message to reference closeModal()
The TypeScript types automatically recognize the new action name through
the SingleInstructionMap type system.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* cleanup
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: wrkflow reminder issue
* Update EmailWorkflowService.ts
* update
* Refactor team member email extraction for clarity
* add tests
* Undo changes in EmailWorkflowService
* Get team members assigned to the booking
* fix: Update test to match EmailWorkflowService behavior for ROUND_ROBIN
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: Update CalendarEventBuilder tests to include host emails in attendees
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Apply suggestion from @cubic-dev-ai[bot]
Filter organizer our of `hostsToInclude`
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* Only include organizer and host destination calendar
* Type fix
* Type fix
---------
Co-authored-by: Joe Au-Yeung <j.auyeung419@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* feat: add data region dropdown to signup page
Add a dropdown to the signup page that allows users to select their data region (United States or European Union). When a region is selected, the user is navigated to the appropriate domain (app.cal.com or app.cal.eu).
- Add SelectField component to signup page below the description text
- Detect current domain and set appropriate default value
- Navigate to correct domain when selection changes
- Add translation strings for data_region, united_states, and european_union
Co-Authored-By: peer@cal.com <peer@cal.com>
* added localhost
* fix: improve data region dropdown - SSR hydration, query params, and self-hosted protection (#25463)
* fix/remove-eu-us-dropdown-from-self-hosted-signup
* fix: remove localhost bypass and fix SSR hydration for data region dropdown
- Remove localhost bypass from IS_CALCOM check to prevent self-hosted instances from seeing Cal.com-specific dropdown
- Fix SSR hydration mismatch by using WEBAPP_URL instead of window.location for region detection
- Fix hostname replacement to preserve query parameters by modifying hostname directly instead of entire URL string
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com>
Co-authored-by: Dhairyashil <dhairyashil10101010@gmail.com>
* fix: unaable to edit member as owner/admin
* Clean up comments in EditMemberSheet.test.tsx
Removed comments explaining the fix for permissions prop.
* revert
* feat: simplify date range picker to Airbnb-style selection
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* feat: apply Airbnb-style selection to allowPastDates branch
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: extract date range selection logic and add unit tests
- Extract date range selection logic into pure function (dateRangeLogic.ts)
- Remove unused allowPastDates parameter from selection logic
- Add comprehensive unit tests (11 test cases covering all scenarios)
- Simplify DateRangePicker component (30+ lines -> 5 lines)
- Improve separation of concerns: allowPastDates only controls calendar date restrictions
* style update
* feat: add hover highlighting for date range selection
When a start date is selected and user hovers over other dates,
the potential range between start and hovered date now shows
bg-emphasis background for better visual feedback.
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* memoize hovering range and update styles
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: companion expo and chrome
* fix: api-v2-fetch-bookings (#25023)
* migrated to app expo router
* feat(companion): added availability screen and fix event type fetch (#25025)
* fix(companion): add host check in bookings (#25036)
* using liquid glass bottom nav experimental
* added action sheet
* added icons to event type tabs
* added action bar for event-type details
* long press for edit event types
* added limits
* added more limits
* added more limits
* added username to event types
* feat(companion): config to set and show all the available meeting options a user has stalled (#25081)
* feat: Add tailwind support using nativewind. (#25028)
* init nativewind
* replace styles with tailwind classes
* changes
* feat(companion): all locations options, icons, and apply nativewind to remaining files (#25143)
* feat: all locations options and icons and apply nativwind to reamaining files
* icon bug fix
* cal video icon
* other location frontend
* other location api
* address cubics comment about correctly detects SVGs
* feat(companion): edit availability (#25149)
* feat: companion-edit-availability
* date override and use correct config for patch api endpoint
* Android Alert supports a maximum of 3 buttons
* feat: companion-ui-release-1 (#25150)
* feat(companion): Add event type & schedule creation flows with API expansion (#25187)
* feat(companion): event schedule creation and apis
* profile section
* limits, advanced, recurring tab
* Clean Folder Structure
* addressed cubics comments
* fix cubiics comments
* replaced text with cal.com svg logo
* added correct more button for event-types
* added copy link button
* added extension popup
* added chrome extension sidebar
* achieved liquid glass buttons
* nit
* more progress
* fixed ios bug, added icon
* added cal icon to gmail
* nit
* nit
* added dialog for one-off meeting
* added one-time dialog
* feat(companion): gmail plugin (#25327)
* Update Cal.com Companion to version 1.7.0 with enhanced background and content scripts. The background script now handles fetching event types from the Cal.com API and improved error handling. The content script has been updated to manage sidebar visibility and respond to messages more effectively. Removed deprecated dev background script and updated manifest permissions for better functionality.
* chore: update companion .gitignore to exclude build outputs and env files
* feat: insert Cal.com event link directly at cursor position in Gmail compose
- Add insertTextAtCursor function to insert booking link where user is typing
- Automatically positions cursor after inserted link for seamless typing
- Fallback to clipboard copy if compose field not found
- Improved UX: no need to manually paste the link
* feat(companion): improve notification UI and add event types caching
- Update notification to Cal.com brand style (black bg, check icon, smooth fade)
- Change notification text to 'Link inserted' for subtlety
- Move notification to bottom-right position (matching Cal.com toasts)
- Add event types caching (5min duration) to reduce API calls
- Cache automatically refreshes on page reload
- Fix TypeScript error with composeBody.focus() type assertion
* Notification toast border
* conditional description
* conditional description
* feat(companion): Enhance UI with action buttons, tooltips, and Gmail extension improvements (#25353)
* feat: companion-and-gmail-ui-upgrade
* feat: companion-and-gmail-ui-upgrade
* feat: companion-and-gmail-ui-upgrade
* feat: companion-and-gmail-ui-upgrade
* feat(companion): one-off links (#25355)
* added one off prototype
* resolve merge conflicts
---------
Co-authored-by: Dhairyashil <dhairyashil10101010@gmail.com>
* fixed sidebar iframe
* fix: enable pointer events on sidebar while maintaining click-through on transparent area
- Added pointerEvents: 'auto' to sidebar View component in _layout.tsx
- Changed iframe width from 100% to 400px to match sidebar width
- Changed iframe pointerEvents from 'none' to 'auto' to enable clicking
- This allows sidebar items to be clickable while transparent area remains click-through
* feat(companion): center all modals on full screen in browser extension (#25380)
* fix: companion-full-width-iframe
* center the popups on extension view
* feat(companion): center all modals on full screen in browser extension
- Created FullScreenModal component that expands iframe to full width
- Updated content script to handle instant iframe expansion/collapse
- Converted 17 modals across 6 files to use FullScreenModal
- All modals now appear centered on full browser viewport
- Removed animations for instant modal appearance
- Mobile app behavior remains unchanged
Files updated:
- companion/components/FullScreenModal.tsx (new)
- companion/extension/entrypoints/content.ts
- companion/app/(tabs)/event-types.tsx (5 modals)
- companion/app/(tabs)/bookings.tsx (2 modals)
- companion/app/(tabs)/availability.tsx (3 modals)
- companion/app/booking-detail.tsx (2 modals)
- companion/app/availability-detail.tsx (4 modals)
- companion/components/Header.tsx (1 modal)
* security(companion): validate postMessage origin in content script
Add origin and source validation to postMessage listener to prevent
malicious scripts on host pages from manipulating the companion iframe.
- Verify event.source matches iframe.contentWindow
- Verify event.origin matches iframe origin (localhost:8081)
- Reject all unauthorized messages before processing
This prevents external scripts from:
- Forcing full-screen overlays
- Intercepting pointer events
- Manipulating the companion UI
* fix(companion): center 'Add new event type' modal on full screen
Replace KeyboardAvoidingView with TouchableOpacity pattern in the
create event type modal to ensure it appears centered on the full
screen like all other modals.
This was the last remaining modal that wasn't properly centered.
* fix(companion): resolve modal transition timing issue
Fixed the 'Add new event type' modal not centering properly by:
- Added 100ms delay when transitioning between modals
- Prevents conflicting expand/collapse messages
- Removed redundant postMessage calls from modal handlers
- Added max-height constraint to modal content
- Cleaned up debug console logs
The issue was that when clicking 'New Event Type' from the 'New' menu,
both modals were transitioning simultaneously, causing the create modal
to collapse immediately. The delay ensures proper sequencing.
All 17 modals now work correctly and appear centered on full screen.
* added working date range
* removed all of one-off event code
* nit
* feat(companion): Suggest `Cal.com` links and Embed using Gemini Ai in Gmail (#25406)
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
* add companion build on CI
* feat: oauth companion (#25526)
* first implemenation of oauth
* fix logout for web
* revert app name
* remove isUsingOAuth
* clean up log out button
* remove logs
* clean up authcontext
* simplify code generation
* code clean up
* clean up oauthService.ts
* oauth browser extension
* add redirect uri to .env.example
* remove api key support
* clean up _layout file
* add identity
* fix + clean up
* improvements to oauth flow
* code clean up
* remove comments
* clean up comments
* add log out dialog
* add confirm modal
---------
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
---------
Co-authored-by: Dhairyashil Shinde <93669429+dhairyashiil@users.noreply.github.com>
Co-authored-by: Abhijeet Singh <asingh9829@gmail.com>
Co-authored-by: Dhairyashil <dhairyashil10101010@gmail.com>
Co-authored-by: Volnei Munhoz <volnei.munhoz@gmail.com>
Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com>
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
* fix: preserve seatsPerTimeSlot during partial event type updates
When doing a partial update on the PATCH /v2/organizations/{orgId}/teams/{teamId}/event-types/{eventTypeId} endpoint, providing a partial body would reset seatsPerTimeSlot back to null because the transformSeatsApiToInternal function was always called even when seats was undefined.
This fix ensures that the seat options are only transformed when the seats field is explicitly provided in the update request, preserving existing values during partial updates.
Also adds e2e test to verify partial updates preserve seatsPerTimeSlot.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: handle TypeScript union type narrowing for seatsPerTimeSlot
When seats is not provided in a partial update, the transformed body
may not have seatsPerTimeSlot property. This fix uses 'in' operator
to safely check for the property before accessing it.
Also fixes the e2e test to properly narrow the union type for seats
using type guards.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* refactor: simplify seatsPerTimeSlot handling per review feedback
Per supalarry's suggestion, instead of using 'in' operator checks in
multiple validation calls, we now return {seatsPerTimeSlot: undefined}
when seats is not provided. This keeps the validation code unchanged
and only requires modifying one line in the transformation.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: make individual component for generic and event type specific calendar views
* fixup
* update examples app
* fix: show busy times from calendars in week view
* fix: use calendar busy times not working
* chore: add changesets
* fixup
* chore: implement PR feedback
* fix: merge conflicts
* chore: implement PR feedback
* fixup
* chore: implement PR feedback
* Add /router to isBookingPages
* Remove Dynamic Posthog Provider from AppProvider.tsx because that is only used by the pages router, and the pages router is only in use by the /router endpoint, which is a booking page and we havent implemented corresponding GeoProvider support for it
* fix: improve availability working hours layout spacing and editable heading icon gap
* refactor: wrap DateOverride in styled container in AvailabilitySettings
* refactor: replace TRPCError with ErrorWithCode in packages/features
This refactor moves error handling from throwing TRPCError directly in
packages/features to throwing ErrorWithCode instead. The conversion to
TRPCError now happens at the TRPC layer.
Changes:
- Add generic ErrorCode values (Unauthorized, Forbidden, NotFound,
BadRequest, InternalServerError) to errorCodes.ts
- Update getServerErrorFromUnknown to map new ErrorCodes to proper
HTTP status codes
- Create toTRPCError helper in packages/trpc/server/lib
- Create errorMappingMiddleware in packages/trpc/server/middlewares
- Migrate TRPCError throws in packages/features to ErrorWithCode:
- teamService.ts
- getEventTypeById.ts
- eventTypeRepository.ts
- OrganizationPermissionService.ts
- OrganizationPaymentService.ts
- sso.ts
- handleCreatePhoneCall.ts
- userCanCreateTeamGroupMapping.ts
This improves separation of concerns by making packages/features
transport-agnostic, allowing the same feature code to be reused from
tRPC, API routes, workers, etc.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: remove isTrpcCall parameter and fix lint warning
- Remove isTrpcCall parameter from get.handler.ts call since the
feature layer no longer needs to know about tRPC
- Fix unsafe optional chaining lint warning in getEventTypesByViewer.ts
by precomputing usersSource variable
- Complete migration of getEventTypesByViewer.ts to ErrorWithCode
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* revert
* add eslint rule
* add comment
* fix: add isTrpcCall back to getEventTypeById interface
The user reverted the removal of isTrpcCall parameter from the handler,
so we need to add it back to the interface to fix the type error.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* test: update teamService tests to expect ErrorWithCode instead of TRPCError
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor
* wip
* feat: integrate errorMappingMiddleware into base TRPC procedure
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* connect middlewares
* revert
* revert
* refactor
* rename
* fix: handle ErrorWithCode in teams server-page error handling
The error handling was checking for TRPCError, but teamService now throws
ErrorWithCode. This caused the 'This invitation is not for your account'
error message to not be displayed when a wrong user tries to use an
invitation link.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix
* fix
* fix
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: allow false for custom field 'fieldRequired' by using z.boolean()
* updated to z.boolean().optional()
---------
Co-authored-by: Pallav <90088723+Pallava-Joshi@users.noreply.github.com>
* wip
* wip
* feature: Booking Tasker without DI yet
* feature: Booking Tasker with DI
* fix type check 1
* fix type check 2
* fix
* comment booking tasker for now
* fix: DI regularBookingService api v2
* fix: convert trigger.dev SDK imports to dynamic imports to fix unit tests
The unit tests were failing because BookingEmailAndSmsTriggerTasker.ts had static imports of trigger files that depend on @trigger.dev/sdk. This caused Vitest to try to resolve the SDK at module load time, even though it should be optional.
Changed all imports in BookingEmailAndSmsTriggerTasker.ts from static to dynamic (using await import()) so the trigger files are only loaded when the tasker methods are actually called, not at module load time during tests.
This fixes the 'Failed to load url @trigger.dev/sdk' errors that were causing 28+ test failures.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix unit tests
* keep inline smsAndEmailHandler.send calls
* chore: add team feature flag
* add satisfies ModuleLoader
* fix type check app flags
* move trigger in feature
* fix: add trigger.dev prisma generator
* fix: email app statuses
* fix: CalEvtBuilder unit test
* chore: improvements, schema, config, retry
* fixup! chore: improvements, schema, config, retry
* chore: cleanup code
* chore: cleanup code
* chore: clean code and give full payload
* remove log
* add booking notifications queue
* add attendee phone number for sms
* bump trigger to 4.1.0
* add missing booking seat data in attendee
* update config
* fix logger regular booking service
* fix: prisma as external deps of trigger
* fix yarn.lock
* revert change to example app booking page
* fix: resolve circular dependencies and improve cold start performance in trigger tasks
- Convert BookingRepository import to type-only in CalendarEventBuilder.ts to eliminate circular dependency risk
- Convert EventNameObjectType, CalendarEvent, and JsonObject imports to type-only in BookingEmailAndSmsTaskService.ts
- Use dynamic imports in all trigger notification tasks (confirm, request, reschedule, rr-reschedule) to reduce cold start time
- Move heavy imports (BookingEmailSmsHandler, BookingRepository, prisma, TriggerDevLogger, BookingEmailAndSmsTaskService) inside run functions
- Eliminates module-level prisma import which violates repo guidelines and adds cold start overhead
- Reduces initial module dependency graph by deferring heavy imports (email templates, workflows, large repositories) until task execution
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: improve cold start performance in reminderScheduler with dynamic imports
- Remove module-level prisma import (violates 'No prisma outside repositories' guideline)
- Use dynamic imports for UserRepository (1,168 lines) - only loaded when needed in EMAIL_ATTENDEE action
- Use dynamic imports for twilio provider (386 lines) - only loaded in cancelScheduledMessagesAndScheduleEmails
- Use dynamic imports for all manager functions by action type:
- scheduleSMSReminder (387 lines) - loaded only for SMS actions
- scheduleEmailReminder (459 lines) - loaded only for Email actions
- scheduleWhatsappReminder (266 lines) - loaded only for WhatsApp actions
- scheduleAIPhoneCall (478 lines) - loaded only for AI phone call actions
- Use dynamic imports for sendOrScheduleWorkflowEmails in cancelScheduledMessagesAndScheduleEmails
- Significantly reduces cold start time by deferring heavy module loading until execution paths need them
- Eliminates module-level prisma import that violated repository pattern guidelines
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: improve cold start performance in BookingEmailSmsHandler with dynamic imports
- Remove module-level imports of all email-manager functions (653 LOC + 30+ email templates)
- Add dynamic imports in each method (_handleRescheduled, _handleRoundRobinRescheduled, _handleConfirmed, _handleRequested, handleAddGuests)
- Defer heavy email-manager loading until method execution
- Verified no circular dependencies between email-manager and bookings
- Significantly reduces cold start time for RegularBookingService and BookingEmailAndSmsTaskService
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: use dynamic imports
* update yarn lock
* code review
* trigger config project ref in env
* update yarn lock
* add .env.example trigger variables
* add .env.example trigger variables
* fix: cleanup error handling and loggin
* fix: trigger config from env
* fix: small typo fix
* fix: ai review comments
* fix: ai review comments
* ai review
* Add `create` on `WorkflowReminderRepository`
* `sendWorkflowEmails` tasker to accept lazy payload
* Add `scheduleLazyEmailWorkflow` to `WorkflowService
* Process scheduled date in `scheduleLazyEmailWorkflow`
* Type fixes
* Use `WorkflowService` to schedule
* Refactor `scheduleEmailReminderForEvt` to use
`WorkflowService.processWorkflowScheduledDate`
* Pass seat reference to lazy scheduled workflow reminder
* Refactor `WorkflowReminderRepository` to accept prisma as constructor
* Abstract `FormSubmissionData` type
* Abstract select statement and add get by uid to `BookingRepository`
* Add `FormSubmissionData` type
* Add `findByIdIncludeStepAndWorkflow` to `WorkflowReminderRepository`
* Tasker payload to accept `workflowReminderId`
* Create `BookingSeatRepository`
* Write `workflowReminderId` to tasker payload
* Add `generateCommonScheduleFunctionParams` to `WorkflowService`
* Init
* Use services in tasker
* Abstract types
* In reminderScheduler use workflowService to generate common params
* Type fix
* Return params from emailWorkflowService.generateParametersToBuildEmailWorkflowContent
* Use emailWorkflowService to generate params
* Abstract types
* Generate email content and send in EmailWorkflowService
* Move check to caller
* Use EmailWorkflowService to generate email payload in
emailReminderManager
* Fix initalizing repository
* Use evt.videoCallData first before the booking metadata
* Only get non-deleted references to build calendar event
* Remove check for videoCallData.id
* Dynamic import credit service
* BookingRepository.getByUid to only return what we need from attendee
* Type fixes
* test: Add comprehensive tests for lazy email workflow generation and fix broken tests
- Fix prisma mocks in sms-manager.test.ts and outOfOfficeCreateOrUpdate.handler.test.ts
to export both 'default' and named 'prisma' exports
- Add EmailWorkflowService.test.ts with 4 tests for error handling paths
- Add sendWorkflowEmails.test.ts with 7 tests for schema validation and email sending
- Add tests to WorkflowService.test.ts for scheduleLazyEmailWorkflow,
processWorkflowScheduledDate, and generateCommonScheduleFunctionParams methods
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Write `seatReferenceUid`
* Return promise
* Fix log
* Change to `Promise.allSettled`
* Type fix
* Fix failing test
* fix: reorder workflow step checks to fix test failure
The test 'should throw error if workflow step not found on reminder' was failing because the code checked workflowStep.verifiedAt before checking if workflowStep exists. When workflowStep is null, this caused the error message to include 'undefined' instead of the expected workflow step id.
Fixed by reordering the checks:
1. First check if workflowStep exists
2. Then check if workflowStep.verifiedAt exists
Also updated the test expectation to match the correct error message.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
---------
Co-authored-by: cal.com <morgan@cal.com>
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: hbjORbj <sldisek783@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Alex van Andel <me@alexvanandel.com>
* fix: integer to text comparison in routing insights query
Add explicit integer array cast to prevent PostgreSQL type mismatch error when comparing bookingUserId (integer) with user_id array values in getRoutedToPerPeriodData query
* add e2e tests
* refactor: remove LoadingInsight component and handle loading in ChartCard
- Enhanced ChartCard to render default loading UI when isPending is true
- Replaced all LoadingInsight usages with ChartCard that accepts isPending/isError props
- Removed LoadingInsight component and updated exports
- Updated 16 chart components to use the new pattern
- ChartCard now shows spinner and skeleton title during loading state
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* fix: make children prop optional in ChartCard when isPending is true
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: remove unused loadingState prop from ChartCard
- Remove loadingState prop and ChartLoadingState type export
- Simplify computedLoadingState to derive state only from isPending/isError
- No functional changes - loadingState was not being used by any components
- data-loading-state attribute behavior remains unchanged for E2E tests
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: remove duplicate isPending early returns from chart components
- Update all 16 chart components to use single ChartCard return pattern
- Gate children rendering with !isPending && isSuccess && data checks
- Prevents data processing code from executing during loading state
- Improves code consistency and maintainability across all charts
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* refactor: remove redundant !isPending check from chart conditionals
- Simplify conditional rendering to use just 'isSuccess && data' or 'isSuccess'
- In TanStack Query, isSuccess and isPending are mutually exclusive
- The !isPending check was redundant since isSuccess already implies !isPending
- Applied to all 16 chart components for consistency
- Components with safe defaults (data ?? []) use just 'isSuccess'
- Components requiring data check use 'isSuccess && data'
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* revert the mistake
* apply feedback
* apply feedback
* fix e2e
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* refactor: use Button component instead of plain button in CopyButton
Co-Authored-By: eunjae@cal.com <hey@eunjae.dev>
* add shrink-0 to StartIcon and EndIcon of Button
* remove unused class names
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: made playground page use same layout as other pages
* update: added feature key
* Change link display from table to list format
Refactor page layout to use a list instead of a table for links.
---------
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
## What does this PR do?
Fixes a bug in the seed-insights script where `AWAITING_HOST` status was randomly assigned to bookings along with a `userId`, which violates the correct behavior of instant meetings.
**Problem:**
- The seed script randomly picked from all 5 booking statuses (including `AWAITING_HOST`)
- When `AWAITING_HOST` was selected, the script still assigned a `userId`
- Real instant meetings with `AWAITING_HOST` status should have `userId = NULL` until a host joins
- This created incorrect test data that doesn't match production behavior
**Solution:**
- Filter out `AWAITING_HOST` from `BookingStatus` values using `Object.values(BookingStatus).filter()`
- This approach is more maintainable than listing valid statuses explicitly - if new statuses are added in the future, they will automatically be included
- Moved `validStatusesForSeed` to module level so it's calculated once at load time instead of on every shuffle call
- Added comments explaining why this status requires special handling
## Mandatory Tasks (DO NOT REMOVE)
- [x] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). N/A - seed script only.
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works. N/A - this is a seed script for test data generation.
## How should this be tested?
1. Run the seed script: `yarn seed-insights`
2. Verify no `AWAITING_HOST` bookings are created with a `userId`:
```sql
SELECT COUNT(*) FROM "Booking"
WHERE status = 'awaiting_host' AND "userId" IS NOT NULL
AND "createdAt" > NOW() - INTERVAL '1 day';
-- Should return 0 for newly seeded data
```
3. Verify other statuses are still generated:
```sql
SELECT status, COUNT(*) FROM "Booking"
WHERE "createdAt" > NOW() - INTERVAL '1 day'
GROUP BY status;
-- Should show ACCEPTED, PENDING, CANCELLED, REJECTED (but not AWAITING_HOST)
```
## Checklist
- [x] I have read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- [x] My code follows the style guidelines of this project
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have checked if my changes generate no new warnings
---
> **Link to Devin run:** https://app.devin.ai/sessions/08f634e7210d415982d71c8f687b4468
> **Requested by:** eunjae@cal.com (@eunjae-lee)
* fix: stabilize date range calculation in column view
* fix: restore eslint-disable for scrollIntoViewSmooth
---------
Co-authored-by: Pallav <90088723+Pallava-Joshi@users.noreply.github.com>
* wip
* wip
* feature: Booking Tasker without DI yet
* feature: Booking Tasker with DI
* fix type check 1
* fix type check 2
* fix
* comment booking tasker for now
* fix: DI regularBookingService api v2
* fix: convert trigger.dev SDK imports to dynamic imports to fix unit tests
The unit tests were failing because BookingEmailAndSmsTriggerTasker.ts had static imports of trigger files that depend on @trigger.dev/sdk. This caused Vitest to try to resolve the SDK at module load time, even though it should be optional.
Changed all imports in BookingEmailAndSmsTriggerTasker.ts from static to dynamic (using await import()) so the trigger files are only loaded when the tasker methods are actually called, not at module load time during tests.
This fixes the 'Failed to load url @trigger.dev/sdk' errors that were causing 28+ test failures.
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix unit tests
* keep inline smsAndEmailHandler.send calls
* chore: add team feature flag
* add satisfies ModuleLoader
* fix type check app flags
* move trigger in feature
* fix: add trigger.dev prisma generator
* fix: email app statuses
* fix: CalEvtBuilder unit test
* chore: improvements, schema, config, retry
* fixup! chore: improvements, schema, config, retry
* chore: cleanup code
* chore: cleanup code
* chore: clean code and give full payload
* remove log
* add booking notifications queue
* add attendee phone number for sms
* bump trigger to 4.1.0
* add missing booking seat data in attendee
* update config
* fix logger regular booking service
* fix: prisma as external deps of trigger
* fix yarn.lock
* revert change to example app booking page
* fix: resolve circular dependencies and improve cold start performance in trigger tasks
- Convert BookingRepository import to type-only in CalendarEventBuilder.ts to eliminate circular dependency risk
- Convert EventNameObjectType, CalendarEvent, and JsonObject imports to type-only in BookingEmailAndSmsTaskService.ts
- Use dynamic imports in all trigger notification tasks (confirm, request, reschedule, rr-reschedule) to reduce cold start time
- Move heavy imports (BookingEmailSmsHandler, BookingRepository, prisma, TriggerDevLogger, BookingEmailAndSmsTaskService) inside run functions
- Eliminates module-level prisma import which violates repo guidelines and adds cold start overhead
- Reduces initial module dependency graph by deferring heavy imports (email templates, workflows, large repositories) until task execution
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: improve cold start performance in reminderScheduler with dynamic imports
- Remove module-level prisma import (violates 'No prisma outside repositories' guideline)
- Use dynamic imports for UserRepository (1,168 lines) - only loaded when needed in EMAIL_ATTENDEE action
- Use dynamic imports for twilio provider (386 lines) - only loaded in cancelScheduledMessagesAndScheduleEmails
- Use dynamic imports for all manager functions by action type:
- scheduleSMSReminder (387 lines) - loaded only for SMS actions
- scheduleEmailReminder (459 lines) - loaded only for Email actions
- scheduleWhatsappReminder (266 lines) - loaded only for WhatsApp actions
- scheduleAIPhoneCall (478 lines) - loaded only for AI phone call actions
- Use dynamic imports for sendOrScheduleWorkflowEmails in cancelScheduledMessagesAndScheduleEmails
- Significantly reduces cold start time by deferring heavy module loading until execution paths need them
- Eliminates module-level prisma import that violated repository pattern guidelines
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: improve cold start performance in BookingEmailSmsHandler with dynamic imports
- Remove module-level imports of all email-manager functions (653 LOC + 30+ email templates)
- Add dynamic imports in each method (_handleRescheduled, _handleRoundRobinRescheduled, _handleConfirmed, _handleRequested, handleAddGuests)
- Defer heavy email-manager loading until method execution
- Verified no circular dependencies between email-manager and bookings
- Significantly reduces cold start time for RegularBookingService and BookingEmailAndSmsTaskService
Co-Authored-By: morgan@cal.com <morgan@cal.com>
* fix: use dynamic imports
* update yarn lock
* code review
* trigger config project ref in env
* update yarn lock
* add .env.example trigger variables
* add .env.example trigger variables
* fix: cleanup error handling and loggin
* fix: trigger config from env
* fix: small typo fix
* fix: ai review comments
* fix: ai review comments
* ai review
* prettier
---------
Co-authored-by: hbjORbj <sldisek783@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* fix: Add PBAC permission checks for insights access
- Add checkInsightsPermission() helper that properly checks insights.read permission with PBAC support
- Update userBelongsToTeamProcedure to use PBAC-aware permission check for org-level access
- Update teamListForUser query to filter teams based on insights.read permission instead of only checking base ADMIN/OWNER roles
- Maintain backward compatibility with fallback to traditional role checks (ADMIN/OWNER) when PBAC is disabled
- Org admins (base role ADMIN/OWNER) continue to have automatic insights access as a privileged position
- Team-level admins with custom roles now properly checked for insights.read permission
Fixes issue where users with custom PBAC roles couldn't access insights even if they had insights.read permission.
Related: CAL-XXXX
* perf: Optimize team permission checks to avoid N+1 queries
Replace individual permission checks per team with bulk query using getTeamIdsWithPermission().
This reduces database queries from N (one per team) to a single optimized query.
- Use PermissionCheckService.getTeamIdsWithPermission() for bulk permission checking
- Filter teams based on returned team IDs instead of individual checks
- Maintains same functionality with significantly better performance for users with many teams
* perf: Fetch only teams with insights access instead of filtering after
Move permission check before team query to filter at database level.
Previously fetched all teams then filtered in JavaScript.
Now only fetches teams the user has insights access to.
- Check permissions first using getTeamIdsWithPermission()
- Add teamId filter to membership query (teamId: { in: teamIdsWithAccess })
- Remove JavaScript filter step (done at DB level)
- Reduces data transfer and improves query efficiency
* fix: break circular dependency in messageDispatcher via dependency injection
Break the 4-file circular dependency chain:
credit-service → reminderScheduler → smsReminderManager → messageDispatcher → credit-service
Solution:
- Add optional creditCheckFn parameter to messageDispatcher functions
- Thread creditCheckFn through the call chain: scheduleWorkflowReminders → scheduleSMSReminder/scheduleWhatsappReminder → messageDispatcher
- When creditCheckFn is provided, use it; otherwise fall back to dynamic CreditService import for backward compatibility
- This breaks the workflows → billing import while preserving immediate fallback behavior
Changes:
- messageDispatcher: Accept optional creditCheckFn parameter, use it if provided
- smsReminderManager: Thread creditCheckFn through scheduleSMSReminder
- whatsappReminderManager: Thread creditCheckFn through scheduleWhatsappReminder
- reminderScheduler: Add creditCheckFn to ScheduleWorkflowRemindersArgs and pass through processWorkflowStep
All type checks, lint checks, and unit tests pass.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* feat: wire creditCheckFn from all callers to complete circular dependency fix
- Add creditCheckFn parameter to WorkflowService.scheduleFormWorkflows
- Wire creditCheckFn from all 10 entry points that call workflow scheduling:
* formSubmissionUtils.ts (form submissions)
* roundRobinManualReassignment.ts (round-robin reassignment)
* triggerFormSubmittedNoEventWorkflow.ts (form workflow trigger)
* handleBookingRequested.ts (booking requests)
* RegularBookingService.ts (2 calls - payment initiated & new bookings)
* handleSeats.ts (seated bookings)
* handleConfirmation.ts (2 calls - confirmation & payment)
* handleMarkNoShow.ts (no-show updates)
* confirm.handler.ts (booking rejection)
- Update test expectations to use expect.objectContaining()
- Fix pre-existing lint warning in handleMarkNoShow.ts (any type)
- This completes the messageDispatcher circular dependency fix by ensuring
creditCheckFn is actually passed through the call chain, breaking the
4-file circular dependency at runtime
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: use generic type with type guard in logFailedResults to fix type check error
- Replace constrained type with generic type parameter
- Add proper type guard for rejected promises
- Fixes CI type check failure in handleMarkNoShow.ts:385
- Avoids 'any' type while accepting any fulfilled value shape
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* wip
* wip
* wip
* revert
* revert
* feat: wire creditCheckFn from all remaining callers to eliminate fallbacks
- Wire creditCheckFn in packages/sms/sms-manager.ts (can safely import CreditService)
- Create makeHandler factory pattern for CRON endpoints (scheduleSMSReminders.ts, scheduleWhatsappReminders.ts)
- Wire creditCheckFn from apps/web CRON routes to factories
- Add warning log in messageDispatcher when fallback is used
- Complete creditCheckFn wiring from all direct callers (activateEventType.handler.ts, util.ts)
This eliminates all fallbacks to dynamic import except as a safety net for unforeseen call sites.
The circular dependency (workflows ↔ billing) remains acceptable as discussed with user (Option C).
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* test: update formSubmissionUtils tests to expect creditCheckFn parameter
The scheduleFormWorkflows function now receives creditCheckFn as a parameter.
Updated test assertions to use expect.objectContaining() with creditCheckFn: expect.any(Function)
to account for the new dependency injection parameter.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* test: update sms-manager test to expect creditCheckFn parameter
The sendSmsOrFallbackEmail function now receives creditCheckFn as a parameter.
Updated test assertion to use expect.objectContaining() with creditCheckFn: expect.any(Function)
to account for the new dependency injection parameter. Also removed teamId: undefined
assertion as the key may be omitted entirely from the actual call.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* feat: make creditCheckFn required to fully break circular dependency
This commit completes the circular dependency fix by making creditCheckFn
required throughout the call chain, eliminating the dynamic import fallback
entirely.
Changes:
- Make creditCheckFn required in messageDispatcher functions (sendSmsOrFallbackEmail, scheduleSmsOrFallbackEmail)
- Remove dynamic import fallback and warning log from messageDispatcher
- Make creditCheckFn required in ScheduleTextReminderArgs (smsReminderManager)
- Make creditCheckFn required in processWorkflowStep and ScheduleWorkflowRemindersArgs (reminderScheduler)
- Add creditCheckFn to SendCancelledRemindersArgs and wire from handleCancelBooking
The circular dependency is now fully broken - no more dynamic imports of
CreditService from within the workflows package. All callers must explicitly
provide creditCheckFn via dependency injection.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: make creditCheckFn required in WorkflowService.scheduleFormWorkflows
This commit fixes the CI type check error by making creditCheckFn required
in WorkflowService.scheduleFormWorkflows. Previously, creditCheckFn was
optional in scheduleFormWorkflows but required in scheduleWorkflowReminders,
causing a type mismatch.
Changes:
- Make creditCheckFn required in scheduleFormWorkflows signature
- Update WorkflowService.test.ts to pass mock creditCheckFn in all test cases
- Add responseId and routedEventTypeId to test calls for completeness
All callers of scheduleFormWorkflows already pass creditCheckFn, so this
change is safe and completes the circular dependency fix.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* remove
* fix
* refactor
* refactor
* refactor
* wip
* fix
* fix
* rm
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: Fix circular dependency in tanstack-table.d.ts
* fix: Re-export TextFilterOperator
* Unable to export non-type values from @calcom/types
* Refactor data-table types in a way that ensures type-safety as before
* Add FilterPopover and further fixups
* Fix further type errors missed earlier
* More hidden type errors
* Type error in useFilterValue
* add public client
* implement PKCE
* pass codeChallenge and codeChallengeMethod to handler
* fixes for secure oauth flow
* fix type error
* clean up refresh token endpoint
* only support S256
* fix type error
* remove comment
* add tests
* fix type errors in route.test.ts
* add missing support for refresh token
* add e2e test for public client refresh tokens
* allow pkce for confidential clients
* fix type error
* fix e2e
* fix option pkce for confidential clients
* e2e test improvements
* fix test
* remove only
* add delay
* fix e2e tests
* remove only
* don't skip pkce if codeChallenge is set
* add service functions for token endpoint
* use service function in refreshToken endpoint
* use repository
* remove return types
* e2e test fixes
* fix e2e test
* remove .only in e2e test
* remove pause
* fix error responses in token endpoints
* adjust tests to new error responses
* fix error responses
* e2e improvements
* redirect on error
* adjust tests
* Update apps/web/modules/auth/oauth2/authorize-view.tsx
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: CarinaWolli <wollencarina@gmail.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
## What does this PR do?
This PR implements attributes PBAC - router checks + UI
## Visual Demo (For contributors especially)
A visual demonstration is strongly recommended, for both the original and new change **(video / image - any one)**.
#### Video Demo (if applicable):
- Show screen recordings of the issue or feature.
- Demonstrate how to reproduce the issue, the behavior before and after the change.
#### Image Demo (if applicable):
- Add side-by-side screenshots of the original and updated change.
- Highlight any significant change(s).
## Mandatory Tasks (DO NOT REMOVE)
- [ ] I have self-reviewed the code (A decent size PR without self-review might be rejected).
- [ ] I have updated the developer docs in /docs if this PR makes changes that would require a [documentation change](https://cal.com/docs). If N/A, write N/A here and check the checkbox.
- [ ] I confirm automated tests are in place that prove my fix is effective or that my feature works.
## How should this be tested?
Enable PBAC on an org
Create a custom role -> advanced -> organizations -> "editUser"
Assign it to a user
impersonate user
test they have access to all things attributes
remove permissions
check they dont have permissions.
## Checklist
<!-- Remove bullet points below that don't apply to you -->
- I haven't read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- My code doesn't follow the style guidelines of this project
- I haven't commented my code, particularly in hard-to-understand areas
- I haven't checked if my changes generate no new warnings
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds a new PBAC “editUsers” permission and read gating for Attributes, updating the UI and backend so users can view and edit attributes only when allowed.
- **New Features**
- Added CustomAction.EditUsers to the permission registry for organization-scoped attribute editing.
- Settings computes canViewAttributes and shows the Attributes tab only when allowed.
- Members page fetches Attributes permissions and exposes canViewAttributes and canEditAttributesForUser to the UI.
- User Edit Sheet hides attributes without read permission and shows attribute editing and the bulk “Mass Assign Attributes” action only with editUsers; other user edits depend on changeMemberRole.
- Attributes TRPC router gates create/edit/delete/toggle via PBAC and requires organization.attributes.editUsers for assign/bulk-assign; added a helper to create PBAC-aware procedures.
- **Migration**
- Run the new Prisma migration to seed the admin role with editUsers.
- If using custom roles, grant Edit Users under Attributes as needed.
<sup>Written for commit 856aa2e8e1521fc22cd71cb0fa6d720036efe8a2. Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
* fix: prevent calendar credentials from leaking into video adapter calls
Split getCredentialAndWarnIfNotFound into two category-specific functions:
- getVideoCredentialAndWarnIfNotFound: only searches video credentials
- getCalendarCredentialAndWarnIfNotFound: only searches calendar credentials
This prevents the bug where calendar credentials (like google_calendar) were
being passed to getVideoAdapters() during booking deletion, causing
'Couldn't get adapter for googlecalendar' errors.
The root cause was the fallback logic that searched both videoCredentials
and calendarCredentials when a credential wasn't found by ID. Now each
function only searches within its own credential category and validates
the returned credential has the expected type suffix (_video/_conferencing
or _calendar).
Also fixed pre-existing ESLint warnings in EventManager.ts:
- Prefixed unused delegatedCredentialLast with underscore
- Replaced 'any' types with 'unknown' for better type safety
- Fixed unused variable warning in updateAllCalendarEvents error handler
Fixes the issue where deleteVideoEventForBookingReference could receive
a calendar credential when the video credential was missing, leading to
errors in getVideoAdapters.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor: remove shared helper and implement logic directly in each function
- Removed getCredentialInternal shared helper
- Implemented logic directly in getVideoCredentialAndWarnIfNotFound
- Implemented logic directly in getCalendarCredentialAndWarnIfNotFound
- Changed fallback to explicitly use this.videoCredentials and this.calendarCredentials
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* remove duplicate
* revert
* revert
* revert
* refactor
* add tests
* address
* clean up
* simplify
* simplify
* rename
* rename
* rename
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
* chore: refactor config files to prevent migration tool errors
* refactor: upgrade with the tailwind migration tool
* chore: restore pre-commit command + mc
* refactor(wip): update dependencies and migrate to Tailwind CSS v4 (mainly web)
* chore: resolve Tailwind v4 migration conflicts from merging main
* chore: remove unused Tailwind packages from config and update dependencies for v4 migration
* chore: uncomment Tailwind CSS utility classes in globals.css
* fix: resolve token conflicts between calcom and coss ui
* fix: textarea scrollbar
* Fix CUI-16
* fix: added @tailwindcss/forms plugin and cleaned up CSS classes in various components to remove unnecessary dark mode styles
* fix: selects and inputs of different sizes
* fix: remove unnecessary leading-20 class from modal titles in various components
* fix: update Checkbox component styles to remove unnecessary border on checked state
* fix: clean up styles in RequiresConfirmationController, Checkbox, and Radio components to enhance consistency
* fix: update button and filter component styles to remove unnecessary rounded classes for consistency
* fix: calendar
* fix: update KBarSearch
* fix: refine styles in Empty and Checkbox components for improved consistency
* Fix focus state email input
* fix: update button hover and active states to use 'not-disabled' instead of 'enabled'
* fix: line-height issues
* fix: update class name for muted background in BookingListItem component
* fix: sidebar spacing
* chore: update class names to use new Tailwind CSS color utilities
* fix embed
* chore: upgrade Tailwind CSS to version 4.1.16 and update related dependencies
* Map css variables and add a playground test for heavy css customization
* suggestion for coss-ui
* refactor: update CSS variable usage and clean up styles
- Replace instances of `--cal-brand-color` with `--cal-brand` in embed-related HTML files.
- Remove the now-unnecessary `addAppCssVars` function from the embed core.
- Import theme tokens in the embed core styles for better consistency.
- Clean up whitespace and formatting in CSS files for improved readability.
- Add a comment in `tokens.css` regarding its usage in both embed and webapp contexts.
* Handle within tokens.css instead of fixing coss-ui
* Remove initial, not needed. Also, remove tailwind.config.js as tailwidn scans the html automaically
* fix: examples app breaking
* fix: modal not resizing correctly
* feat: upgrade atoms to tailwind v4
* fix: atoms build breaking
* fix: atoms build breaking
* chore: upgrate examples/base to tailwind 4
* chore: update globals.css
* fix: add missing scheduler css variables
* fix: PlatformAdditionalCalendarSelector
* chore: update global styles
* chore: update tailwindcss and postcss dependencies to stable versions
* chore: remove unneeded class
* fix: dialog and toast animation
* fix: replace flex-shrink-0 with shrink-0 for consistent styling in various components
* fix: dialog modal for Apple connect
* add margin in SaveFilterSegmentButton
* Fix radix button nested states
* add cursor pointer to buttons but keep dsabled state
* Fix commandK selectors and adds cursor pointer
* Fix teams filter
* fix - round checkboxes
* fix filter checkbox
* fix select indicator's margin
* command group font size
* style: fix badge and tooltip radius
* chore: remove unneeded files
* Delete PR_REVIEW_MANAGED_EVENT_REASSIGNMENT.md
* remove ui-playground leftover
* fix: add missing react phone input styles in atoms
* Delete managed-event-reassignment-flow-and-architecture.mermaid
* fix: inter font not loading
* Add theme to skeleton container so that it can support dark mode
* fix: create custom stack-y-* utilities post tw4 upgrade
* fix: typo
* fix: atoms stack class + remove unused css file
* fix default radius valiue
* fix space-y in embed
* fix skeleton background
* Hardcode radius values to match production
* fix border in embed
* add missing externalThemeClass
* feat: create a custom stack-y-* utility
* fix: add stack utility to atom global css
* fix: Skeleton loader class modalbox
* Add stack-y utility in embed
* fix: add missing stack utilities in atoms globals.css
* update yarn.lock
* add popover portla
* update
---------
Co-authored-by: Sean Brydon <sean@cal.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
Co-authored-by: Ryukemeister <sahalrajiv6900@gmail.com>
Co-authored-by: cal.com <morgan@cal.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
Co-authored-by: Anik Dhabal Babu <adhabal2002@gmail.com>
* feat: google ads conversion tracking
* gaClientid
* store gclid in stripe metadata
* tracking only in the us
* track google campaign id as well
* rename gclid -> google ads
* fix: build
* fix
* refactor
* fix: type check
* fix: type check
* fix: type check
* fix: type check
* fix: store it in cookie
* refactor
* fix
* cleanup
* linked ads tracking
* refactor checkout session tracking
## What does this PR do?
This PR changes the order of creating the team -> paying -> invite users.
The old approach was create team -> invite -> pay. But we are matching the current implementation of how billing works with usage based billing
## How should this be tested?
Enable onboarding-v3 flag on your instance
Ensure you have stripe enabled + stripe:listen running
login as onboarding@example.com, onboarding
Go through the team setup flow
Pay
Invite
Ensure uers were added to team
Create a new account
disable billing
Test again
## Checklist
<!-- Remove bullet points below that don't apply to you -->
- I haven't read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- My code doesn't follow the style guidelines of this project
- I haven't commented my code, particularly in hard-to-understand areas
- I haven't checked if my changes generate no new warnings
* Change arg name from `bookingUId` to `bookingUid`
* Lint fix
* Use `BookingRepository` to find booking to reschedule
* Move early return further up if no booking is found
* Use `PermissionCheckService` if request rescheduling a team booking
* Remove redundent check
* Remove redundent eventType query
* Using `BookingRepository` to update the booking to rescheduled
* Update type in `getUsersCredentialsIncludeServiceAccountKey` to only
require params that are required
* Get booking organizer credentials
* Type fixes
* test: Add tests for team admin request reschedule with organizer credentials
- Add test for team admin requesting reschedule with proper permissions
- Add test verifying organizer's credentials are used (not requester's)
- Add test for team member without permissions (should fail)
These tests cover the fix in PR #24645 which ensures that when a team admin
requests a reschedule, the booking organizer's credentials are used to delete
calendar events instead of the requester's credentials.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: Address code review comments for request reschedule
- Change user: true to user: { select: { id, email } } to only fetch required fields
- Change eventType include to select with explicit fields including teamId
- Remove sensitive information (user object, cancellationReason) from debug log
- All integration tests passing locally
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Type fix
* Remove businesss logic references from repository methods.
* Move business logic to handler
* Type fix
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
## What does this PR do?
Improves the visual presentation of overlapping calendar events in the weekly view with two key enhancements:
- **Dynamic startHour per scenario**: Each playground scenario now displays the calendar starting at an appropriate hour based
on its earliest event time, rather than always starting at 6am
- **Full width for non-overlapping events**: Single events and non-overlapping events now display at 100% width (previously
80%) for maximum visibility
## Key Changes
### Overlapping Event Layout Algorithm
Replaces the previous uniform-width, fixed-offset layout with an intelligent spread algorithm:
**Previous behavior:**
- All overlapping events: 80% width with 8% offset steps
- Events clustered on the left side
**New behavior:**
- **2 overlapping events**: 80% and 50% widths
- **3 overlapping events**: 55%, ~42%, and 33% widths
- **4+ overlapping events**: Progressive narrowing from 40% down to minimum 25%
- **Spread algorithm**: Events distribute across the full width with the last event aligned to the right edge
- **Right edge distribution**: `ri = Rmin + (Rmax - Rmin) × i/(n-1)` for even spacing
### Visual Improvements
- Single/non-overlapping events: **100% width** (was 80%)
- Overlapping events: **Variable widths** based on cascade position (leftmost events wider, rightmost narrower)
- Last overlapping event: **Aligned to right border** for maximum scatter
- Minimum width: **25%** maintained for readability
**Devin session:** https://app.devin.ai/sessions/168d2227f5304c49ae4d34d17da5b025
**Requested by:** eunjae@cal.com (@eunjae-lee)
## Visual Demo
https://github.com/user-attachments/assets/693546fa-448d-470a-b041-c08f4697c177
## Mandatory Tasks (DO NOT REMOVE)
- [x] I have self-reviewed the code
- [x] I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. **N/A** - playground-only changes
- [x] I confirm automated tests are in place that prove my fix is effective or that my feature works.
## How should this be tested?
1. Navigate to `/settings/admin/playground/weekly-calendar`
2. Verify each scenario:
- **Non-Overlapping Events**: Both events should be 100% width, no offset
- **Touching Events**: Both events should be 100% width, no offset
- **Two Overlapping Events**: First event 80% width, second 50% width aligned to right
- **Three Overlapping Events**: Progressive narrowing with spread across full width
- **Four Overlapping Events**: Four events spread across full width
3. Verify startHour values:
- Most scenarios should start at 9am (events start at 10am)
- Dense day scenario should start at 8am (events start at 9am)
- Mixed statuses scenario should start at 1pm (events start at 2pm)
4. Test with real calendar data to ensure overlapping events look visually distinct
**Environment variables:** Standard Cal.com development setup
**Test data:** Use playground scenarios or create overlapping events in your calendar
## Human Review Checklist
**⚠️ CRITICAL ITEMS:**
1. **Visual verification in playground** (MOST IMPORTANT):
- Open `/settings/admin/playground/weekly-calendar`
- Verify non-overlapping events are 100% width (not 80%)
- Verify overlapping events spread properly across full width
- Verify last overlapping event aligns to right edge
- Verify each scenario starts at appropriate hour
2. **Algorithm correctness**:
- Single events: 100% width (was 80%)
- Two overlapping: 80%, 50% widths with last aligned to right
- Three overlapping: 55%, ~42%, 33% widths spread across full width
- Right-edge distribution: `ri = Rmin + (Rmax - Rmin) * i/(n-1)`
3. **Edge cases**:
- Test with 10+ overlapping events to ensure no overflow
- Verify minimum width (25%) is respected
- Verify backward compatibility: custom `baseWidthPercent`/`offsetStepPercent` should use legacy behavior
4. **Type safety**:
- `startHour` parameter now properly typed as `Hours` (union of 0-23)
- All scenarios use valid `Hours` values
**Known limitations:**
- Local visual testing was not completed due to environment issues
- Easing curve parameters (curveExponent: 1.3) were chosen based on examples but may need visual tuning
- No E2E tests for visual appearance (only unit tests for layout calculations)
## Checklist
- [x] I have read the [contributing guide](https://github.com/calcom/cal.com/blob/main/CONTRIBUTING.md)
- [x] My code follows the style guidelines of this project
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have checked if my changes generate no new warnings
* fix: break circular dependency between reminderScheduler and credit-service
- Created WorkflowReminderRepository to handle workflow reminder queries
- Refactored cancelScheduledMessagesAndScheduleEmails to accept userIdsWithoutCredits parameter
- Moved credit-checking logic from workflows to CreditService
- Changed dynamic import to static import in CreditService
- Updated tests to pass userIdsWithoutCredits parameter
- Removed unused imports (prisma, WorkflowMethods)
This creates a one-way dependency (billing -> workflows) and follows the repository pattern by removing direct Prisma usage from reminderScheduler.
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* fix: resolve type check errors in circular dependency fix
- Use MembershipRepository.listAcceptedTeamMemberIds instead of findAllAcceptedPublishedTeamMemberships
- Re-add prisma import to reminderScheduler.ts for UserRepository
- Update WorkflowReminderRepository to use WorkflowActions enum instead of string
Co-Authored-By: benny@cal.com <sldisek783@gmail.com>
* refactor
* refactor
* wip
* wip
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add backend validation for conflicting team slugs during org onboarding
- Added findOwnedTeamsByUserId method to TeamRepository
- Created buildTeamsAndInvites method in BaseOnboardingService that automatically:
- Detects teams with same slug as organization
- Marks conflicting teams for migration (isBeingMigrated: true)
- Filters empty team names and invite emails
- Updated BillingEnabledOrgOnboardingService to use new method
- Updated SelfHostedOnboardingService to use new method
- Added comprehensive tests for slug conflict scenarios
This ensures backend validation even if frontend is bypassed, preventing
slug conflicts during organization creation. All inheriting classes
automatically get this validation without code changes.
* refactor: use TeamRepository in listOwnedTeamsHandler
Refactored listOwnedTeamsHandler to use TeamRepository.findOwnedTeamsByUserId
instead of direct Prisma queries. This:
- Reduces code duplication
- Ensures consistency across the codebase
- Follows repository pattern
- Makes the handler more maintainable
* fix: update tests to use renamed buildTeamsAndInvites method
- Renamed testFilterTeamsAndInvites to testBuildTeamsAndInvites
- Made test wrapper method async to match the async buildTeamsAndInvites
- Added orgSlug parameter to all test calls
- Updated all 9 test cases to use await with the new method signature
- Fixed lint warnings by using proper types instead of 'any'
- Imported OnboardingIntentResult and User types
- Used Pick<User> for mockUser type
- Removed all 'as any' type casts
Fixes test failures where filterTeamsAndInvites was renamed to buildTeamsAndInvites in the base service.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* fix: mock TeamRepository in tests to prevent database calls
Added vi.mock for TeamRepository to avoid database calls in unit tests.
The buildTeamsAndInvites method now calls ensureConflictingSlugTeamIsMigrated
which uses TeamRepository.findOwnedTeamsByUserId(). Mocking this prevents
Prisma errors in CI while keeping the tests focused on filtering logic.
The mock returns an empty array so no teams are found for migration,
allowing the tests to verify the filtering behavior without database access.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
* refactor: improve readability of ensureConflictingSlugTeamIsMigrated
Refactored the conditional logic in ensureConflictingSlugTeamIsMigrated
for better readability while preserving exact behavior. Changed from
manual array manipulation to using .map() for updating team migration
status. This is a cosmetic change with no functional differences.
Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
* hotfix
* type fix and test fix
* update env example
* improvements
* more fix
* tada
---------
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
* Add check that event type belongs to team
* Add `findAcceptedMembershipsByUserIdsInTeam` to `MembershipRepository`
* Validate that passed `userIds` belong to a team
* Add tests
* Typo fix
* Improve add users to org
* Improve add users to org
* test: Add comprehensive tests for handleUserEvents cross-tenant hijack prevention
- Add tests for cross-tenant hijack prevention security fix
- Test that users belonging to different organizations are blocked
- Test that users with null organizationId are blocked (prevents legacy user hijacking)
- Test that users belonging to correct organization succeed
- Test new user creation flow
- Test user activation/deactivation flows
- Test custom attribute syncing
- All 8 tests passing locally with proper type safety (no 'as any' usage)
Co-Authored-By: Volnei Munhoz <volnei.munhoz@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: Add trial days to organization subscriptions and workspace warning
- Add ORGANIZATION_TRIAL_DAYS environment variable for configurable trial periods
- Implement trial days in Stripe checkout session (only when env var is set)
- Add warning message to organization setup page about workspace structure
- Add translation string for organization trial workspace warning
- Add ORGANIZATION_TRIAL_DAYS to turbo.json env vars
- Fix pre-existing linting warnings in CreateANewOrganizationForm.tsx
- Add ESLint disable comments for turbo/no-undeclared-env-vars warnings
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Rename variable
* Add trial days to `purchaseTeamOrOrgSubscription`
* fix: Move organization trial warning to spot 3 below form card
- Add optional footer prop to WizardLayout component
- Use footer prop in create-new-view.tsx to render warning at spot 3
- Remove warning from inside CreateANewOrganizationForm component
- Warning now appears below the form card as requested
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* feat: Add organization trial warning to all wizard steps
- Add warning footer to step 2 (about-view.tsx)
- Add warning footer to step 3 (add-teams-view.tsx)
- Add warning footer to step 4 (onboard-members-view.tsx)
- Add warning footer to step 5 (payment-status-view.tsx)
- Add warning footer to resume-view.tsx (step 1 resume page)
- Warning now appears on all steps of the organization creation wizard
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: Correct environment variable name to STRIPE_ORG_TRIAL_DAYS
- Changed ORGANIZATION_TRIAL_DAYS to STRIPE_ORG_TRIAL_DAYS in turbo.json
- This matches the actual usage in OrganizationPaymentService.ts and payments.ts
- Ensures the environment variable is properly recognized by the build system
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: Create shared OrganizationWizardLayout component
- Create OrganizationWizardLayout component that wraps WizardLayout
- Centralizes the trial warning footer logic in one place
- Update all 6 wizard pages to use the shared component:
- create-new-view.tsx
- about-view.tsx
- add-teams-view.tsx
- onboard-members-view.tsx
- payment-status-view.tsx
- resume-view.tsx
- Remove duplicate useLocale/Alert imports and footer props from pages
- Simplifies maintenance by having warning logic in a single location
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Fix lint error
* Add `ORG_TRIAL_DAYS` as constant
* Add comment
* Ensure no negative number is passed
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
* fix: exclude booking responses from calendar/CRM integrations for seated events
For seated events (events with seatsPerTimeSlot), booking responses are now excluded from being sent to calendar integrations (Google Calendar, etc.), CRM integrations (HubSpot, Salesforce, etc.), and other integrations.
This applies to both creating new seated bookings and rescheduling seated bookings.
The calendar event and CRM records are still created, but without the custom booking field responses included in the description/notes.
Co-Authored-By: anik@cal.com <adhabal2002@gmail.com>
* test
* Refactor Office 365 Calendar OAuth redirect URI
Removed debug logging for redirect URI and client ID.
* test
* check
* Update Prisma connection logic for integration tests
Refactor database connection handling for integration tests.
* update
* Refactor conditionals and simplify role handling
* Add test comment in index.ts
* Remove integration test flag from index.ts
Remove integration test flag from database connection logic.
* update
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* chore: Remove all code related to the old cache system
* Removed some redundant tests, some type fixes
* Further type fixes
* More type fixes re. tests
* Next iteration, couple of fixes remaining
* Remove cache from CredentialActionsDropdown
* Fix tests by mocking credential, instead of db queries
* Remove Cache DI wiring from v2
* Make sure apiv2 build passes
* Remove another cache cron
* Remove old tokens for calendar-cache v1
## Problem
When users clicked on a plan card in the Cal.com Platform pricing UI, the loading
spinner would appear on ALL plan cards simultaneously instead of just the selected one.
This gave a confusing UX impression that all plans were being processed at the same time.
## Solution
Track the currently loading plan using a `loadingPlan` state variable that stores
which plan the user clicked on, rather than relying solely on the pending state from
the mutation hook.
## Changes
- Added `loadingPlan` state to track which specific plan is loading
- Update `loadingPlan` when a plan subscription is initiated
- Reset `loadingPlan` on error to ensure UI returns to normal state
- Modified `isLoading` prop condition to check if the current plan matches
the `loadingPlan` before showing the spinner
This ensures that only the plan card the user clicked on displays the loading indicator,
while other plans remain in their normal state.
- Add hashedLink field to CalendarEvent type definition
- Add withHashedLink method to CalendarEventBuilder
- Pass hashedLink from booking request to CalendarEvent in RegularBookingService
- hashedLink will now be included in webhook payloads when booking via private API links
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: add validation for null values in bookingFieldsResponses
- Add test case to verify 400 error when bookingFieldsResponses contains null values
- Create ValidateBookingFieldsResponses decorator to reject null values in booking field responses
- Apply validator to CreateBookingInput_2024_08_13.bookingFieldsResponses property
- Ensure all booking field response values are non-null strings
* feat: transform null values to empty strings in bookingFieldsResponses
- Remove ValidateBookingFieldsResponses validator that rejected null values
- Add Transform decorator to convert null values to empty strings in bookingFieldsResponses
- Update test to verify null values are transformed to empty strings instead of returning 400 error
* remove extra spaces
* test: add rescheduleReason null value test case
---------
Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Revamps onboarding with subtle route transitions, new org/teams illustrations, and clearer invite flows with real-time previews. Adds “Skip for now” on invites and guardrails to avoid incomplete team creation.
- **New Features**
- Added email invite pages for organizations and teams with shared EmailInviteForm and RoleSelector.
- Built a live invite browser preview that renders a 3×3 grid and updates as you type; works for orgs and teams.
- Applied route-keyed framer-motion transitions to layout, cards, and browser views for smoother page changes.
- Continuation prompt now detects saved org or team and routes to the right next step; localized copy.
- Added loading state to plan selection to prevent double navigation.
- Refreshed Organizations welcome modal with a new animated ring illustration and better scrolling.
- Added “Skip for now” to org and team invite-by-email steps to proceed without invites.
- Calendar browser preview now focuses on a time window around “now” for a more realistic demo.
- Added an optional floating footer to keep actions visible on long, scrollable lists.
- **Refactors and Fixes**
- Unified invite browser and replaced the org preview on the org email step.
- Split and simplified legacy invite views; team and org routes are cleaner and easier to extend.
- Streamlined the team invite step by removing a redundant action; non-admins are redirected to the email invite page.
- Prevented creating teams with empty details by redirecting back to team details.
- Minor UI cleanup: tighter borders, padding, and mobile max-heights across onboarding screens.
- Hide team select on org invites when no teams exist.
<sup>Written for commit ae7f5277ab998560ae6e2f3f9144852a7b4959a7. Summary will update automatically on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
* feat: add avatarUrl to /v2/me endpoint response
- Add avatarUrl field to userSchemaResponse schema in packages/platform/types/me.ts
- Update e2e tests to verify avatarUrl is returned in GET and PATCH /v2/me responses
- Field is nullable to match User model in Prisma schema
- Fix pre-existing lint warnings by removing 'as any' type assertions in test file
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* feat: add avatarUrl to MeOutput DTO for OpenAPI docs
- Add avatarUrl field to MeOutput class in apps/api/v2/src/ee/me/outputs/me.output.ts
- Field is nullable to match the Zod schema and Prisma model
- This ensures OpenAPI documentation will include avatarUrl when regenerated
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
* feat: add bio field to /v2/me endpoint response
- Add bio field to userSchemaResponse Zod schema in packages/platform/types/me.ts
- Add bio field to MeOutput NestJS DTO in apps/api/v2/src/ee/me/outputs/me.output.ts
- Update e2e tests to verify bio is returned in both GET and PATCH responses
- Field is nullable to match the User model in Prisma schema
Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: chauhan_s <somaychauhan98@gmail.com>
* fix: prevent bulk update of locked locations in child managed event types
- Filter out child managed event types with locked locations in getBulkUserEventTypes
- Add validation in bulkUpdateEventsToDefaultLocation to prevent updating locked fields
- Implements defense in depth with validation at multiple layers
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Abstract filtering logic
* test: add comprehensive tests for bulk location update filtering
- Add unit tests for filterEventTypesWhereLocationUpdateIsAllowed
- Add unit tests for bulkUpdateEventsToDefaultLocation
- Add integration tests for getBulkUserEventTypes
- Fix bug: change unlockedFields?.locations check from !== undefined to === true
This ensures that locations: false is properly treated as locked, addressing
the security issue identified in PR review comments
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: filter locked managed event types on app installation page
- Add parentId to eventTypeSelect in getEventTypes function
- Apply filterEventTypesWhereLocationUpdateIsAllowed to both team and user event types
- Only filter when isConferencing is true to avoid affecting other app types
- Fixes issue where locked managed event types were showing in the event type selection list on /apps/installation/event-types page
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix(embed-react): remove obsolete availabilityLoaded event listener
The availabilityLoaded event does not exist in the EventDataMap type system
in embed-core. This code was causing 5 TypeScript errors in CI:
- Type 'availabilityLoaded' does not satisfy constraint 'keyof EventDataMap'
- 'data' is of type 'unknown' (2 occurrences)
- Type 'availabilityLoaded' is not assignable to action union (2 occurrences)
Since this is an example file and the event is not defined in the type system,
removing this obsolete code resolves the type errors.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: correct Prisma type for metadata in test helper function
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: use flexible PrismaLike type for better test compatibility
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: properly type mock Prisma objects in test files
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: properly mock Prisma methods in test file
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Filter out metadata
* Undo change in embed file
* Address feedback
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* Revert "fix: revert bookings redesign (#25172)"
This reverts commit 1f102bf3b4.
* add bookings-v3 feature flag
* put things behind a feature flag
* remove no longer needed test
* revert e2e tests
* put back description
* revert AvatarGroup
* apply feedback
* remove "view" booking action
* remove Alert (When the bookings query errors, this branch now renders only the alert and skips the data-table filter/segment controls. Those controls moved into BookingsList, so in error states users can no longer clear or tweak filters to recover from the failure, effectively trapping them behind the alert.)
* address feedback
* revert useMediaQuery
* Move TeamBillingRepositories
* WIP refactor team internal billing service
* Remove duplicate billing repository files
* Remove logic check in repository for billing is enabled
* Rename repository to `TeamBillingData`
* Use repository factory in main service
* Fix new import paths
* Rename to
* Ensure `IS_TEAM_BILLING_ENABLED` is of type boolean
* Rename classes to TeamBillingService and TeamBillingServiceFactory
* Implement DI in `BookingServiceFactory`
* `TeamBillingService` use repository in `getOrgIfNeeded`
* DI `isTeamBillingEnabled` to `TeamBillingServiceFactory`
* Rename files for consistency
* Return stub BillingRepository if billing is not enabled
* Move Stripe billing service to service folder
* Rename file
* `StripeBillingService.getSubscriptionStatus` return `SubscriptionStatus`
* Type fices in StripeBillingService
* Type fix in `stubTeamBillingService`
* DI the `BillingProviderService` into the `TeamBillingService`
* Implement DI in `skipTeamTrials.handler`
* Implement DI for team billing in `inviteMember.handler`
* `skipTeamTrials.handler` use `team.isOrganization`
* Implement DI for billing in `hasActiveTeamPlan.handler`
* Type fixes
* Implement DI in `bulkDeleteUsers.handler`
* Implement `BillingProviderServiceFactory` in `updateProfile.handler`
* Implment `BillingProviderServiceFactory` in `buyCredits.handler`
* Fix import in `stripeCustomer.handler`
* Add a constructor to `teamBillingServiceFactory`
* Add DI to `PrismaTeamBillingRepository`
* Add DI to `StripeBillingService`
* Implement singleton in `BillingProviderServiceFactory`
* Add DI folder and contents to billing folder
* Use `getTeamBillingServiceFactory` in `inviteMember.handler`
* Add `saveTeamBilling` method to `ITeamBillingService`
* Implement DI in new team route
* Implement DI in `teamService`
* Implement DI in `OrganizationPaymentService`
* Implement DI in `credit-service`
* In `StripeBillingService` remove `static` from status methods
* Implemnt DI in `_invoice.paid.org`
* Refactor `hasActiveTeamPlan` to use `getTeamBillingFactory`
* Refactor `skipTeamTrials` to use `getTeamBillingFactory`
* Refactor `skipTeamTrials` to use `getTeamBillingServiceFactory`
* `stripeCustomer.handler` to use `getBillingProviderService`
* Remove old factories
* Type fix
* Remove unused factory
* Refactor `updateProfile.handler` to use `getBillingProviderService`
* Change name to `TeamBillingDataRepositoryFactory`
* Type Prisma return in `prisma.module`
* Type fix
* Refactor `buyCredits.handler` to use `getBillingProviderService`
* Refactor `credit-service` to use billing DI containers
* Type fix
* Add `getTeamBillingDataRepository`
* Refactor `_invoice.paid.org` to use DI container
* Refactor `_customer.subscription.deleted.team-plan` to use DI container
* Refactor `calcomHandler` to use DI container
* Refactor `getCustomerAndCheckoutSession` to use DI container
* Refactor `verify-email` to use DI containers
* Refactor `api/create/route` to use DI container
* Refactor downgradeUsers to use DI container
* Type fix
* Clean up console.logs
* Add await to `this.billingRepository.create` in `saveTeamBilling`
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* Fix type errors
* Address comments
* fix: update tests to work with new DI pattern
- Update teamBillingService.test.ts to properly inject DI dependencies
- Remove unused billingModule import and mock
- Fix import naming in teamService.integration-test.ts (remove unused rename)
- Fix import path for TeamBillingPublishResponseStatus
All tests now properly mock IBillingProviderService, ITeamBillingDataRepository,
and IBillingRepository instead of using the old BillingRepositoryFactory pattern.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: add compatibility layer and env setup for unit tests
- Add STRIPE_PRIVATE_KEY dummy value to vitest.config.ts to prevent DI module errors
- Fix import paths in credit-service.test.ts (StripeBillingService, TeamBillingService)
- Create compatibility barrel at packages/features/ee/billing/teams/index.ts for test mocking
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: update unit tests to mock DI container properly
- Update teamService.test.ts to mock getTeamBillingServiceFactory() instead of TeamBilling.findAndInit
- Update teamService.alternative.test.ts to mock DI container
- Update credit-service.test.ts to mock getBillingProviderService() and use SubscriptionStatus enum values
- Update OrganizationPaymentService.test.ts to mock DI container instead of direct StripeBillingService import
- Remove all 'as any' type casting to comply with Cal.com coding standards
- Fix unused variable warnings by prefixing with underscore
All 53 tests now passing (16 + 1 + 30 + 6)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: update remaining unit tests to use DI pattern
- Fix StripeBillingService.test.ts to inject mock Stripe client directly
- Fix teamBillingFactory.test.ts to mock getTeamBillingServiceFactory() from DI container
- Fix skipTeamTrials.test.ts to mock DI container and use SubscriptionStatus enum
All 11 previously failing tests now pass (5 + 5 + 1)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Undo changes made to Prisma module
* fix: address test-related PR comments
- Fix OrganizationPaymentService.test.ts mock path from @calcom/ee to @calcom/features/ee
- Refactor teamBillingFactory.test.ts to test real factory logic instead of mocking container
- Remove duplicate teamBillingService.test..ts file with incorrect double-dot filename
All three test files now pass successfully with proper DI patterns.
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Address feedback
* fix: update teamService integration test to mock new DI factory pattern
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: remove duplicate imports in credit-service.test.ts
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* Remove unused index file
* `getBySubscriptionId` to return team or null
* Address feedback
* Merge fix
* Refactor file names
* fix: correct mockStripe variable name to stripeMock in StripeBillingService.test.ts
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* refactor: update internal-team-billing.test.ts to use new DI structure with TeamBillingService
- Replace InternalTeamBilling with TeamBillingService
- Use constructor injection with mock dependencies instead of factory pattern
- Remove BillingRepositoryFactory mock and import
- Update all test cases to use mockBillingProviderService, mockTeamBillingDataRepository, and mockBillingRepository
- Simplify saveTeamBilling tests to focus on repository.create calls
- All 11 tests now pass with the new DI structure
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
* fix: update createWithPaymentIntent.handler.test.ts to mock DI container's getBillingProviderService
- OrganizationPaymentService now uses getBillingProviderService() from DI container
- Test was mocking @calcom/features/ee/payments/server/stripe directly, which no longer works
- Added mock for @calcom/features/ee/billing/di/containers/Billing module
- Mock returns fake billing provider that delegates to mockSharedStripe
- Preserves all existing test assertions and helpers
- Fixed lint error by prefixing unused lastCreatedSessionId with underscore
- All 11 tests now pass (1 skipped as expected)
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
---------
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Syed Ali Shahbaz <52925846+alishaz-polymath@users.noreply.github.com>
instructions:"Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module."
GET /v2/event-types/{eventTypeId} added to the 'data' response property 'oneOf' list for the response status '200'
GET /v2/event-types/{eventTypeId} added '#/components/schemas/EventTypeOutput_2024_06_14, #/components/schemas/TeamEventTypeOutput_2024_06_14' to the 'data' response property 'oneOf' list for the response status '200'
GET /v2/bookings/{bookingUid}/recordings added the new required 'header' request parameter 'Authorization'
GET /v2/bookings/{bookingUid}/transcripts added the new required 'header' request parameter 'Authorization'
- **Framework**: Next.js 13+ (App Router in some areas)
- **Language**: TypeScript (strict)
- **Database**: PostgreSQL with Prisma ORM
- **API**: tRPC for type-safe APIs
- **Auth**: NextAuth.js
- **Styling**: Tailwind CSS
- **Testing**: Vitest (unit), Playwright (E2E)
- **i18n**: next-i18next
## Code Examples
### Good error handling
```typescript
// Good - Descriptive error with context
thrownewError(`Unable to create booking: User ${userId} has no available time slots for ${date}`);
// Bad - Generic error
thrownewError("Booking failed");
```
For which error class to use (`ErrorWithCode` vs `TRPCError`) and concrete examples, see [Error Types in knowledge-base.md](agents/knowledge-base.md#error-types).
### Good Prisma query
```typescript
// Good - Use select for performance and security
constbooking=awaitprisma.booking.findFirst({
select:{
id: true,
title: true,
user:{
select:{
id: true,
name: true,
email: true,
}
}
}
});
// Bad - Include fetches all fields including sensitive ones
constbooking=awaitprisma.booking.findFirst({
include:{user: true}
});
```
### Good imports
```typescript
// Good - Type imports and direct paths
importtype{User}from"@prisma/client";
import{Button}from"@calcom/ui/components/button";
// Bad - Regular import for types, barrel imports
import{User}from"@prisma/client";
import{Button}from"@calcom/ui";
```
## PR Checklist
- [ ] Title follows conventional commits: `feat(scope): description`
- [ ] Type check passes: `yarn type-check:ci --force`
- [ ] Lint passes: `yarn lint:fix`
- [ ] Relevant tests pass
- [ ] Diff is small and focused (<500 lines, <10 files)
- [ ] No secrets or API keys committed
- [ ] UI strings added to translation files
- [ ] Created as draft PR
## When Stuck
- Ask a clarifying question before making large speculative changes
- Propose a short plan for complex tasks
- Open a draft PR with notes if unsure about approach
- Fix type errors before test failures - they're often the root cause
- Run `yarn prisma generate` if you see missing enum/type errors
## Extended Documentation
For detailed information, see the `agents/` directory:
- **[agents/README.md](agents/README.md)** - Architecture overview and patterns
- We won't be able to use already built calendar-cache when Delegation Credential is enabled because existing CalendarCache entries don't have userId set.
## Approach of always using SelectedCalendar.credentialId for CalendarCache even for DelegationCredentials
- Delete Credentials when DelegationCredential is disabled
1. Open [HubSpot Developer](https://developer.hubspot.com/) and sign into your account, or create a new one.
2. From within the home of the Developer account page, go to "Manage apps".
3. Click "Create app" button top right.
3. Click "Create legacy app" button top right and select public app.
4. Fill in any information you want in the "App info" tab
5. Go to tab "Auth"
6. Now copy the Client ID and Client Secret to your `.env` file into the `HUBSPOT_CLIENT_ID` and `HUBSPOT_CLIENT_SECRET` fields.
7. Set the Redirect URL for OAuth `<Cal.com URL>/api/integrations/hubspot/callback` replacing Cal.com URL with the URI at which your application runs.
8. In the "Scopes" section at the bottom of the page, make sure you select "Read" and "Write" for scope called `crm.objects.contacts`
8. In the "Scopes" section at the bottom of the page, make sure you select "Read" and "Write" for scopes called `crm.objects.contacts` and `crm.lists`.
9. Click the "Save" button at the bottom footer.
10. You're good to go. Now you can see any booking in Cal.com created as a meeting in HubSpot for your contacts.
@@ -225,16 +225,38 @@ throw new Error("Booking failed");
### Error Types
Use `ErrorWithCode` for files that are not directly coupled to tRPC. The tRPC package has a middleware called `errorConversionMiddleware` that automatically converts `ErrorWithCode` instances into `TRPCError` instances.
```typescript
// ✅ Good - Use proper error classes
// ✅ Good - Use ErrorWithCode in non-tRPC files (services, repositories, utilities)
import { ErrorCode } from "@calcom/lib/errorCodes";
import { ErrorWithCode } from "@calcom/lib/errors";
// Option 1: Using constructor with ErrorCode enum
throw new ErrorWithCode(ErrorCode.BookingNotFound, "Booking not found");
// Option 2: Using the Factory pattern for common HTTP errors
throw ErrorWithCode.Factory.Forbidden("You don't have permission to view this");
throw ErrorWithCode.Factory.NotFound("Resource not found");
// ✅ Good - Use TRPCError only in tRPC routers/procedures
import { TRPCError } from "@trpc/server";
throw new TRPCError({
code: "BAD_REQUEST",
message: "Invalid booking time slot",
});
// ❌ Bad - Using TRPCError in non-tRPC files
import { TRPCError } from "@trpc/server";
// Don't use TRPCError in services, repositories, or utility files
```
### packages/features Import Restrictions
Files in `packages/features/**` should NOT import from `trpc`. This keeps the features package decoupled from the tRPC layer, making the code more reusable and testable. Use `ErrorWithCode` for error handling in these files, and let the tRPC middleware handle the conversion.
## Basic Performance Guidelines
- Aim for O(n) or O(n log n) complexity, avoid O(n²)
@@ -306,9 +328,54 @@ import { Button } from "@calcom/ui/components/button";
- **Tests**: Same as source file + `.test.ts` or `.spec.ts`
- **Avoid**: Dot-suffixes like `.service.ts`, `.repository.ts` (except for tests, types, specs)
## Repository Method Conventions
## Repository + DTO Pattern and Method Conventions
Repositories should follow consistent naming and design patterns to promote reusability and maintainability.
We use a Repository + DTO pattern to isolate Prisma and the database from business logic. Repositories are the only layer that talks to Prisma and database models. All services, tRPC handlers, API controllers, workflows, and UI should depend on DTOs or domain types, not Prisma types.
DTOs (Data Transfer Objects) are simple TypeScript types or interfaces that represent our domain data in an ORM-agnostic way and are returned from repositories.
### Why this pattern?
- **Prevent type leaks**: Prisma type changes stay inside repositories instead of breaking services, handlers, and UI across dozens of files.
- **Enable safe refactors**: Business logic works against stable DTOs, so you can change storage details without touching higher layers.
- **Keep ORM swappable**: If we ever change ORM, only repository implementations change; services and handlers stay the same.
### What not to do: tight Prisma coupling in business logic
Do not import Prisma types in business logic. Prisma types belong only in the data access layer.
```typescript
// ❌ Bad – business logic depends on Prisma
import type { Webhook } from "@calcom/prisma/client";
export function sendPayload(webhook: Webhook) { /* ... */ }
// ✅ Good – business logic depends on DTO + repository
export async function sendPayload(repo: IWebhookRepository, id: string) {
const webhook = await repo.findById(id);
// ...
}
```
### DTOs in repositories
Repositories should expose DTOs from their public methods and keep Prisma types internal. Inside the repository, use `Prisma.*GetPayload` and map rows to DTOs. The public methods should only return DTOs, never Prisma models.
```typescript
// DTO – ORM-agnostic type exported from the repository module
export interface BookingDTO {
id: string;
userId: number;
startTime: Date;
status: "PENDING" | "CONFIRMED" | "CANCELLED";
}
```
### Prisma boundaries
- **Allowed**: `packages/prisma`, repository implementations (`packages/features/**/repositories/*Repository.ts`), and low-level data access infrastructure.
- **Not allowed**: `packages/features/**` business logic (non-repository), `packages/trpc/**` handlers, `apps/web/**`, `apps/api/v2/**` services/controllers, and workflow/webhook/service layers.
@@ -226,4 +227,16 @@ export class CreateBookingInput_2024_04_15 {
@IsOptional()
@ApiPropertyOptional()
crmOwnerRecordType?: string;
/* @ApiPropertyOptional({
type: [Number],
description:
"For round robin event types, filter available hosts to only consider the specified subset of host user IDs. This allows you to book with specific hosts within a round robin event type.",
description:`Fetches all the recordings for the booking \`:bookingUid\`
description:`Fetches all the recordings for the booking \`:bookingUid\`. Requires authentication and proper authorization. Access is granted if you are the booking organizer, team admin or org admin/owner.
<Note>Please make sure to pass in the cal-api-version header value as mentioned in the Headers section. Not passing the correct value will default to an older version of this endpoint.</Note>
<Note>cal-api-version: \`2024-08-13\` is required in the request header.</Note>
@@ -223,16 +230,26 @@ export class BookingsController_2024_08_13 {
return{
status: SUCCESS_STATUS,
data: recordings,
message:
"This endpoint will require authentication in a future release. Please update your integration to include valid credentials. See https://cal.com/docs/api-reference/v2/introduction#authentication for details.",
summary:"Get Cal Video real time transcript download links for the booking",
description:`Fetches all the transcripts download links for the booking \`:bookingUid\`
description:`Fetches all the transcript download links for the booking \`:bookingUid\`
<Note>Please make sure to pass in the cal-api-version header value as mentioned in the Headers section. Not passing the correct value will default to an older version of this endpoint.</Note>
<Note>
Transcripts are generated when clicking "Transcribe" during a Cal Video meeting. Download links are valid for 1 hour only - make a new request to generate fresh links after expiration.
Please make sure to pass in the cal-api-version header value as mentioned in the Headers section. Not passing the correct value will default to an older version of this endpoint.
@@ -241,6 +258,8 @@ export class BookingsController_2024_08_13 {
return{
status: SUCCESS_STATUS,
data: transcripts??[],
message:
"This endpoint will require authentication in a future release. Please update your integration to include valid credentials. See https://cal.com/docs/api-reference/v2/introduction#authentication for details.",
};
}
@@ -378,18 +397,18 @@ export class BookingsController_2024_08_13 {
<Note>Please make sure to pass in the cal-api-version header value as mentioned in the Headers section. Not passing the correct value will default to an older version of this endpoint.</Note>
`Can't reschedule booking with uid=${rescheduledBooking.uid} because it has been cancelled and rescheduled already to booking with uid=${newBooking.uid}. You probably want to reschedule ${newBooking.uid} instead by passing it within the request URL.`
`Can't reschedule booking with uid=${rescheduledBooking.uid} because it has been cancelled and rescheduled already to booking with uid=${newBooking.uid}. You probably want to reschedule ${newBooking.uid} instead by passing it within the request URL.`
`Bookings can only be marked as absent after their scheduled start time. Current time in UTC+0: ${nowUtc.toISO()}, Booking start time in UTC+0: ${bookingStartTimeUtc.toISO()}`
);
}
if(nowUtc<bookingStartTimeUtc){
thrownewBadRequestException(
`Bookings can only be marked as absent after their scheduled start time. Current time in UTC+0: ${nowUtc.toISO()}, Booking start time in UTC+0: ${bookingStartTimeUtc.toISO()}`
@@ -155,6 +155,8 @@ export class EventTypesController_2024_06_14 {
summary:"Get all event types",
description:`Hidden event types are returned only if authentication is provided and it belongs to the event type owner.
Use the optional \`sortCreatedAt\` query parameter to order results by creation date (by ID). Accepts "asc" (oldest first) or "desc" (newest first). When not provided, no explicit ordering is applied.
<Note>Please make sure to pass in the cal-api-version header value as mentioned in the Headers section. Not passing the correct value will default to an older version of this endpoint.</Note>
'Use the optional `sortCreatedAt` query parameter to order results by creation date (by ID). Accepts "asc" (oldest first) or "desc" (newest first). When not provided, no explicit ordering is applied.',
@ApiOperation({summary:"Get all team event types"})
@ApiOperation({
summary:"Get all team event types",
description:
'Use the optional `sortCreatedAt` query parameter to order results by creation date (by ID). Accepts "asc" (oldest first) or "desc" (newest first). When not provided, no explicit ordering is applied.',
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.