Skip to content

chore: [Booking flow refactor - 2] Integrate Booking services#23156

Merged
keithwillcode merged 3 commits intomainfrom
hariom/pri-305-bookingcreateservice
Oct 9, 2025
Merged

chore: [Booking flow refactor - 2] Integrate Booking services#23156
keithwillcode merged 3 commits intomainfrom
hariom/pri-305-bookingcreateservice

Conversation

@hariombalhara
Copy link
Copy Markdown
Member

@hariombalhara hariombalhara commented Aug 18, 2025

What does this PR do?

  • Integrates the newly introduced Booking services throughout various endpoints in API V2, V1 and webapp
  • Provide correct types for input.bookingData. Earlier it was just Record<string, any>
  • Updated all bookingScenario tests that integration test the new booking flow to use the new container based approach so that we test what is being used.

@linear
Copy link
Copy Markdown

linear bot commented Aug 18, 2025

PRI-305

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Aug 18, 2025

Walkthrough

Replaces direct booking handler usage with DI-backed services across the codebase: RegularBookingService, RecurringBookingService, and InstantBookingCreateService. API handlers, tests, and platform-library consumers now obtain services from new DI containers/modules (moduleLoader/container files) and call service.createBooking variants; booking metadata fields are nested under bookingMeta. Adds DTO types (RegularBookingCreateResult, InstantBookingCreateResult), refactors booking schemas (ExtendedBookingCreateBody and recurring partial), introduces NestJS modules and service wrappers, and removes legacy platform-library handler exports (handleNewBooking, handleNewRecurringBooking, handleInstantMeeting).

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title succinctly captures the primary change—integrating the new Booking services across the codebase—making it directly relevant to the refactor.
Description Check ✅ Passed The description clearly outlines integrating the new Booking services, tightening input types, and updating tests to use the container-based approach, all of which align directly with the changeset’s objectives.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch hariom/pri-305-bookingcreateservice

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 266b3d5 and d26282c.

📒 Files selected for processing (1)
  • packages/features/bookings/lib/handleNewBooking.ts (11 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/features/bookings/lib/handleNewBooking.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
🧬 Code graph analysis (1)
packages/features/bookings/lib/handleNewBooking.ts (4)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/features/di/modules/LuckyUser.ts (1)
  • LuckyUserService (33-33)
packages/features/bookings/lib/dto/types.d.ts (4)
  • BookingHandlerInput (43-45)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (35-41)
  • BookingDataSchemaGetter (13-13)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Aug 18, 2025

Hey there and thank you for opening this pull request! 👋🏼

We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted.

Details:

No release type found in pull request title "Hariom/pri-305-bookingcreateservice". Add a prefix to indicate what kind of release this pull request corresponds to. For reference, see https://www.conventionalcommits.org/

Available types:
 - feat: A new feature
 - fix: A bug fix
 - docs: Documentation only changes
 - style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
 - refactor: A code change that neither fixes a bug nor adds a feature
 - perf: A code change that improves performance
 - test: Adding missing tests or correcting existing tests
 - build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
 - ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
 - chore: Other changes that don't modify src or test files
 - revert: Reverts a previous commit

@keithwillcode keithwillcode added core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO labels Aug 18, 2025
@hariombalhara hariombalhara force-pushed the hariom/pri-305-bookingcreateservice branch from 1ef7ace to deb45db Compare August 18, 2025 10:54
@vercel
Copy link
Copy Markdown

vercel bot commented Aug 18, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Oct 9, 2025 5:13pm
cal-eu Ignored Ignored Oct 9, 2025 5:13pm

attendee.email === input.bookingData.responses.email ||
(input.bookingData.responses.attendeePhoneNumber &&
attendee.phoneNumber === input.bookingData.responses.attendeePhoneNumber)
attendee.email === bookingData.responses.email ||
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using bookingData instead of input.bookingData here because bookingData is parsed by schema and thus has responses always while input.bookingData doesn't have it always.

In a followup PR we are removing input.bookingData usage from everwhere.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
packages/features/bookings/lib/handleNewBooking.ts (4)

591-596: Payment gating logic likely inverted — may suppress payment form when none exists.

Use hasPayments to indicate paid evidence; don’t treat “no payments” as paid.

-      const hasPayments = existingBooking.payment.length > 0;
-      const isPaidBooking = existingBooking.paid || !hasPayments;
+      const hasPayments = existingBooking.payment.length > 0;
+      const isPaidBooking = existingBooking.paid || hasPayments;

1173-1189: Spreading possibly null responses will throw.

Guard when building eventNameObject.

-  const responses = reqBody.responses || null;
+  const responses = reqBody.responses ?? null;
...
-    bookingFields: { ...responses },
+    bookingFields: responses ? { ...responses } : {},

1221-1227: Unsafe write: calEventResponses["location"] may be undefined.

Protect access or initialize the key.

-  if (reqBody.calEventResponses)
-    reqBody.calEventResponses["location"].value = {
+  if (reqBody.calEventResponses?.location) {
+    reqBody.calEventResponses.location.value = {
       value: platformBookingLocation ?? bookingLocation,
       optionValue: "",
-    };
+    };
+  }

472-495: Name collision: luckyUsers (IDs from first booking) vs. local array of host objects. Causes incorrect filtering.

Alias the destructured IDs and use them below.

@@
-    luckyUsers,
+    luckyUsers: luckyUserIdsFromFirstBooking,
@@
-      const luckyUsersFromFirstBooking = luckyUsers
-        ? eventTypeWithUsers.users.filter((user) => luckyUsers.find((luckyUserId) => luckyUserId === user.id))
-        : [];
+      const luckyUsersFromFirstBooking = Array.isArray(luckyUserIdsFromFirstBooking)
+        ? eventTypeWithUsers.users.filter((user) => luckyUserIdsFromFirstBooking.includes(user.id))
+        : [];

Also applies to: 1042-1047

♻️ Duplicate comments (5)
apps/web/pages/api/book/recurring-event.ts (1)

46-58: Sanitize bookingData; avoid sentinel userId; pass hostname/forcedSlug

Strip cfToken, don’t inject -1, and forward hostname/forcedSlug.

-  const recurringBookingService = getRecurringBookingService();
-  const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
-    bookingData: req.body,
-    bookingMeta: {
-      userId: session?.user?.id || -1,
+  const recurringBookingService = getRecurringBookingService();
+  const bookingDataInput = req.body;
+  const sanitizedBookingData = Array.isArray(bookingDataInput)
+    ? bookingDataInput.map(({ cfToken, ...rest }) => rest)
+    : bookingDataInput;
+  const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
+    bookingData: sanitizedBookingData,
+    bookingMeta: {
+      userId: session?.user?.id ?? undefined,
+      hostname: req.hostname,
+      forcedSlug: req.forcedSlug,
       platformClientId: req.platformClientId,
       platformCancelUrl: req.platformCancelUrl,
       platformBookingUrl: req.platformBookingUrl,
       platformRescheduleUrl: req.platformRescheduleUrl,
       platformBookingLocation: req.platformBookingLocation,
       noEmail: req.noEmail,
     },
   });
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

57-66: Bug: first recurring result not returned; series ID not propagated

Push the first result and seed thirdPartyRecurringEventId for subsequent slots.

-    const firstBookingResult = await regularBookingService.createBooking({
+    const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-    luckyUsers = firstBookingResult.luckyUsers;
+    createdBookings.push(firstBookingResult);
+    if (!thirdPartyRecurringEventId && firstBookingResult.references?.length) {
+      const ref = firstBookingResult.references.find((r) => r.thirdPartyRecurringEventId);
+      if (ref?.thirdPartyRecurringEventId) thirdPartyRecurringEventId = ref.thirdPartyRecurringEventId;
+    }
+    luckyUsers = firstBookingResult.luckyUsers;
apps/web/pages/api/book/event.ts (1)

34-41: Don’t inject sentinel userId; remove cfToken before service call

Use undefined (or 401) instead of -1 and strip cfToken.

-  const regularBookingService = getRegularBookingService();
-  const booking = await regularBookingService.createBooking({
-    bookingData: req.body,
-    bookingMeta: {
-      userId: session?.user?.id || -1,
+  const regularBookingService = getRegularBookingService();
+  const { cfToken, ...sanitized } = (req.body ?? {}) as Record<string, unknown>;
+  const booking = await regularBookingService.createBooking({
+    bookingData: sanitized,
+    bookingMeta: {
+      userId: session?.user?.id ?? undefined,
       hostname: req.headers.host || "",
       forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
     },
   });
packages/features/bookings/lib/handleNewBooking.ts (2)

1607-1613: Attendee lookup should use bookerEmail/bookerPhoneNumber, not bookingData.responses.

-        const currentAttendee = booking.attendees.find(
-          (attendee) =>
-            attendee.email === bookingData.responses.email ||
-            (bookingData.responses.attendeePhoneNumber &&
-              attendee.phoneNumber === bookingData.responses.attendeePhoneNumber)
-        );
+        const currentAttendee = booking.attendees.find(
+          (attendee) =>
+            attendee.email === bookerEmail ||
+            (bookerPhoneNumber && attendee.phoneNumber === bookerPhoneNumber)
+        );

2425-2431: Spreading possibly undefined bookingMeta will throw.

Default it to {} in both methods.

   async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }
@@
   async rescheduleBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }
🧹 Nitpick comments (11)
packages/features/bookings/lib/dto/types.d.ts (1)

53-55: Avoid ReturnType tie to service method; define explicit result type

Coupling a public type to RegularBookingService["createBooking"] hinders refactors and can cause circular type deps. Define a concrete RegularBookingCreateResult DTO here and let the service return it.

-// TODO: In a followup PR, we working on defining the type here itself instead of inferring it.
-export type RegularBookingCreateResult = Awaited<ReturnType<RegularBookingService["createBooking"]>>;
+// Stable public DTO (align fields with handler’s output)
+export type RegularBookingCreateResult = {
+  id: number;
+  uid: string;
+  userId: number | null;
+  startTime: Date;
+  endTime: Date;
+  references?: { thirdPartyRecurringEventId?: string }[];
+  luckyUsers?: unknown;
+  fromReschedule?: boolean;
+  // add any other serialized fields actually returned
+};
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (2)

188-202: Propagate noEmail in bookingMeta for regular bookings

Currently only set in body by createNextApiBookingRequest; bookingMeta should carry it per new contract.

       const booking = await regularBookingService.createBooking({
         bookingData: bookingRequest.body,
         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           forcedSlug: orgSlug,
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          noEmail: !bookingRequest.arePlatformEmailsEnabled,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },
       });

363-367: Remove unused req.userId assignment in instant flow

createNextApiBookingRequest computes userId internally; the earlier set at Line 361 is redundant. Also we only need body for createBooking.

-      const instantBookingService = getInstantBookingCreateService();
-      const bookingReq =  await this.createNextApiBookingRequest(req, oAuthClientId, undefined, isEmbed);
-      const instantMeeting = await instantBookingService.createBooking({
-        bookingData: bookingReq.body,
-      });
+      const instantBookingService = getInstantBookingCreateService();
+      const bookingReq = await this.createNextApiBookingRequest(req, oAuthClientId, undefined, isEmbed);
+      const instantMeeting = await instantBookingService.createBooking({ bookingData: bookingReq.body });

Follow-up (optional): delete Line 361 (req.userId = …).

packages/features/bookings/lib/handleNewRecurringBooking.ts (2)

92-92: Use strict equality

Prefer === over ==.

-      isFirstRecurringSlot: key == 0,
+      isFirstRecurringSlot: key === 0,

100-107: Inline await; temporary promise variable is unnecessary

Slight tidy-up.

-    const promiseEachRecurringBooking = regularBookingService.createBooking({
+    const eachRecurringBooking = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-
-    const eachRecurringBooking = await promiseEachRecurringBooking;
packages/features/bookings/lib/handleNewBooking.ts (6)

1196-1201: Prisma: select only needed fields.

Follow repo guideline; only organizationId is used.

-  const organizerOrganizationProfile = await prisma.profile.findFirst({
-    where: {
-      userId: organizerUser.id,
-      username: dynamicUserList[0],
-    },
-  });
+  const organizerOrganizationProfile = await prisma.profile.findFirst({
+    where: { userId: organizerUser.id, username: dynamicUserList[0] },
+    select: { organizationId: true },
+  });

554-556: Use schema-validated bookingData instead of input.bookingData.

Avoid mixing sources; use the parsed data.

-  const isNormalBookingOrFirstRecurringSlot = input.bookingData.allRecurringDates
-    ? !!input.bookingData.isFirstRecurringSlot
+  const isNormalBookingOrFirstRecurringSlot = bookingData.allRecurringDates
+    ? !!bookingData.isFirstRecurringSlot
     : true;

789-793: Standardize on bookingData (parsed) instead of input.bookingData.

Multiple branches read from input.bookingData.*. For consistency and correctness (schema guarantees), switch to bookingData.* in these spots.

Also applies to: 803-810, 842-842, 957-971, 1038-1040, 1297-1300, 1541-1541


812-824: Avoid for..in over arrays.

Use for..of to iterate actual items, not enumerable keys.

-          for (const key in fixedUsers) {
-            await ensureAvailableUsers(
-              { ...eventTypeWithUsers, users: [fixedUsers[key]] },
+          for (const fixedUser of fixedUsers) {
+            await ensureAvailableUsers(
+              { ...eventTypeWithUsers, users: [fixedUser] },
               {
                 dateFrom: dayjs(start).tz(reqBody.timeZone).format(),
                 dateTo: dayjs(end).tz(reqBody.timeZone).format(),
                 timeZone: reqBody.timeZone,
                 originalRescheduledBooking: originalRescheduledBooking ?? null,
               },
               loggerWithEventDetails,
               shouldServeCache
             );
           }

826-826: Remove no-op access.

eventTypeWithUsers.users[0].credentials; has no effect.

-          eventTypeWithUsers.users[0].credentials;

1129-1135: Avoid logging guest emails (PII) at info level.

Consider redacting or sampling to reduce PII in logs.

-  if (guestsRemoved.length > 0) {
-    log.info("Removed guests from the booking", guestsRemoved);
-  }
+  if (guestsRemoved.length > 0) {
+    log.debug("Removed guests from the booking", { count: guestsRemoved.length });
+  }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e87e5d8 and 9ab9a77.

📒 Files selected for processing (28)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (7 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (3 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (20)
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/index.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/types.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/platform/libraries/bookings.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • apps/web/pages/api/book/recurring-event.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • apps/web/pages/api/book/recurring-event.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • apps/web/pages/api/book/recurring-event.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
🧠 Learnings (16)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • apps/web/pages/api/book/recurring-event.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-22T16:38:00.225Z
Learnt from: bandhan-majumder
PR: calcom/cal.com#23192
File: packages/lib/server/service/InsightsBookingBaseService.ts:814-816
Timestamp: 2025-08-22T16:38:00.225Z
Learning: In the InsightsBookingBaseService (packages/lib/server/service/InsightsBookingBaseService.ts), when filtering for "accepted" bookings in getMembersStatsWithCount(), using `endTime <= now()` in the SQL condition should be avoided as it conflicts with existing date filtering logic. The components already handle completion filtering by setting `endDate: currentTime` in their query parameters, making additional SQL-level endTime filtering unnecessary and potentially problematic.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
🧬 Code graph analysis (7)
apps/web/pages/api/book/recurring-event.ts (2)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (7)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • moduleLoader (18-21)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)
  • moduleLoader (21-24)
packages/lib/di/modules/Attribute.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Host.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Ooo.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/LuckyUser.ts (1)
  • moduleLoader (28-31)
packages/lib/di/modules/User.ts (1)
  • moduleLoader (18-21)
apps/web/pages/api/book/event.ts (2)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/features/auth/lib/next-auth-options.ts (1)
  • session (746-771)
packages/features/bookings/lib/dto/types.d.ts (2)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (5)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
packages/features/bookings/lib/handleNewBooking.ts (5)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1046)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (32-38)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (4)
packages/features/bookings/lib/dto/types.d.ts (1)

7-7: Good fix: import SchedulingType

Resolves the missing symbol error.

packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)

32-37: Resolved — IBookingServiceDependencies includes the new deps
IBookingServiceDependencies in packages/features/bookings/lib/handleNewBooking.ts declares luckyUserService, hostRepository, oooRepository, userRepository, and attributeRepository (lines 414–425).

packages/features/bookings/lib/handleNewBooking.ts (2)

414-426: DI surface verified — all deps are bound.

All keys from IBookingServiceDependencies (packages/features/bookings/lib/handleNewBooking.ts) are present in packages/lib/di/bookings/modules/RegularBookingService.module.ts.


2071-2090: Double-check credential.key never leaks — server-side selects are OK only if redaction is enforced.

  • Findings: credential.key is selected in server flows for payment/calendar (e.g. packages/features/bookings/lib/handleNewBooking.ts — prisma.findMany select { key: true }; packages/lib/server/repository/credential.ts — findFirstByIdWithKeyAndUser select { ... key: true }; packages/lib/server/getUsersCredentialsIncludeServiceAccountKey uses credentialForCalendarServiceSelect which includes key). packages/prisma/selects/credential.ts defines credentialForCalendarServiceSelect (key: true) and safeCredentialSelect (omits key).
  • Required checks (quick, exact places to verify):
    • packages/lib/delegationCredential/server.ts — confirm buildNonDelegationCredential and enrichUserWithDelegationCredentialsIncludeServiceAccountKey remove/redact the key before returning credential objects.
    • packages/lib/server/repository/credential.ts — findFirstByIdWithKeyAndUser returns buildNonDelegationCredential; ensure that returned object does not expose key.
    • apps/api/v1/pages/api/credential-sync/* (post/patch/delete/get) — ensure they only return safe fields (id/appId/type) and never pass a full credential object containing key to the response.
    • Any TRPC/Controller handlers that call getUsersCredentialsIncludeServiceAccountKey (e.g. packages/trpc/server/routers/viewer/*) — verify they filter out credential/key before sending responses (appById.handler already strips credential fields; confirm others do likewise).
    • Grep for logging of credential objects (safeStringify/console.log/log.*) and confirm logs use getPiiFreeCredential or otherwise redact the key (examples to check: calendar-cache safeStringify usages — the local variable name key is a cache key there, not credential.key; still verify callers).
  • If any handler must return credential metadata to clients, return a DTO/safe select that explicitly excludes key (use safeCredentialSelect or DTOs). If you find any direct returns of credential objects that may include key, redact the key field before returning and add a unit test.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
packages/features/bookings/lib/handleNewBooking.ts (2)

1175-1188: Bug: spreading possibly null responses will throw.

responses can be null; { ...responses } crashes. Use a safe fallback.

-    bookingFields: { ...responses },
+    bookingFields: responses ?? {},

1196-1201: Prisma: select only needed fields.

Per guidelines, avoid returning full rows. Only organizationId is used.

   const organizerOrganizationProfile = await prisma.profile.findFirst({
     where: {
       userId: organizerUser.id,
       username: dynamicUserList[0],
     },
+    select: { organizationId: true },
   });
packages/features/instant-meeting/handleInstantMeeting.ts (3)

73-89: Fix: promises are never awaited (map callback doesn't return).

subscribers.map uses a block body without return, so Promise.all receives an array of undefined and webhooks aren’t awaited.

Apply:

-    const promises = subscribers.map((sub) => {
-      sendGenericWebhookPayload({
-        secretKey: sub.secret,
-        triggerEvent: eventTrigger,
-        createdAt: new Date().toISOString(),
-        webhook: sub,
-        data: webhookData,
-      }).catch((e) => {
-        console.error(
-          `Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}`,
-          sub,
-          e
-        );
-      });
-    });
+    const promises = subscribers.map((sub) =>
+      sendGenericWebhookPayload({
+        secretKey: sub.secret,
+        triggerEvent: eventTrigger,
+        createdAt: new Date().toISOString(),
+        webhook: sub,
+        data: webhookData,
+      }).catch((e) => {
+        console.error(
+          `Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}, webhookId: ${sub.id}`,
+          { id: sub.id, subscriberUrl: sub.subscriberUrl },
+          e
+        );
+      })
+    );

81-85: Don’t log webhook secrets.

Console error logs the entire webhook record (includes secret). Log only non-sensitive fields.

See diff in previous comment; it redacts secret by logging { id, subscriberUrl } instead of sub.

Also applies to: 63-69


259-266: Prisma: replace include with select (repo guideline).

include eagerly loads attendees but they’re unused. Select only needed fields.

-  const createBookingObj = {
-    include: {
-      attendees: true,
-    },
-    data: newBookingData,
-  };
-
-  const newBooking = await prisma.booking.create(createBookingObj);
+  const newBooking = await prisma.booking.create({
+    data: newBookingData,
+    select: {
+      id: true,
+      uid: true,
+      title: true,
+      responses: true,
+      customInputs: true,
+      userId: true,
+    },
+  });
♻️ Duplicate comments (10)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (2)

22-28: Import ErrorCode (referenced but not imported).

Without this import, the file won’t type-check when those tests are enabled.

Apply:

 import { WEBAPP_URL, WEBSITE_URL } from "@calcom/lib/constants";
+import { ErrorCode } from "@calcom/lib/errorCodes";
 import { getRecurringBookingService } from "@calcom/lib/di/bookings/containers/RecurringBookingService.container";

375-383: Fix rejects assertion and move userId under bookingMeta.

rejects must receive a Promise, not a function. Also, the new API expects bookingMeta.userId, not a top‑level userId.

Apply:

-          const recurringBookingService = getRecurringBookingService();
-          await expect(
-            async () =>
-              await recurringBookingService.createBooking({
-                bookingData: bookingDataArray,
-                userId: -1,
-              })
-          ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);
+          const recurringBookingService = getRecurringBookingService();
+          await expect(
+            recurringBookingService.createBooking({
+              bookingData: bookingDataArray,
+              bookingMeta: { userId: -1 },
+            })
+          ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)

60-76: Good split: recurring schema partial + end now optional.

This addresses the earlier concern about undefined end values in recurring slots.

packages/features/bookings/lib/dto/types.d.ts (1)

7-7: Importing SchedulingType fixes the missing symbol error.

packages/features/bookings/lib/handleNewBooking.ts (2)

1607-1613: Seat attendee lookup uses bookingData.responses; switch to parsed bookerEmail/Phone.

bookingData.responses may be undefined; use bookerEmail/bookerPhoneNumber parsed above.

-        const currentAttendee = booking.attendees.find(
-          (attendee) =>
-            attendee.email === bookingData.responses.email ||
-            (bookingData.responses.attendeePhoneNumber &&
-              attendee.phoneNumber === bookingData.responses.attendeePhoneNumber)
-        );
+        const currentAttendee = booking.attendees.find(
+          (attendee) =>
+            attendee.email === bookerEmail ||
+            (bookerPhoneNumber && attendee.phoneNumber === bookerPhoneNumber)
+        );

2425-2431: Bug: spreading possibly undefined bookingMeta can throw.

input.bookingMeta is optional; spreading undefined crashes. Default to {}.

-  async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
-  }
+  async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
+  }

-  async rescheduleBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
-  }
+  async rescheduleBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
+  }
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (4)

499-511: Add missing noEmail to bookingMeta (recurring seated).

Email behavior will diverge from other flows without it.

       bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },

757-769: Add missing noEmail to bookingMeta (reschedule).

Keeps reschedule email behavior consistent with creation.

         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          noEmail: bookingRequest.noEmail,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },

524-537: Add missing noEmail to bookingMeta (regular booking).

Aligns with createRecurringBooking and API v2 controller.

       bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },

559-572: Add missing noEmail to bookingMeta (seated booking).

Prevents unintended emails in seated flow.

         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          noEmail: bookingRequest.noEmail,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },
🧹 Nitpick comments (7)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)

548-554: Align skipped Round‑robin test with service API and proper rejects usage.

Replace legacy handleNewRecurringBooking call with the DI service and fix the assertion.

Apply:

-        await expect(() =>
-          handleNewRecurringBooking({
-            bookingData: bookingDataArray,
-            userId: -1,
-          })
-        ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);
+        const recurringBookingService = getRecurringBookingService();
+        await expect(
+          recurringBookingService.createBooking({
+            bookingData: bookingDataArray,
+            bookingMeta: { userId: -1 },
+          })
+        ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)

40-43: Type the exported moduleLoader for consistency with other modules.

Use the common ModuleLoader annotation.

+import type { ModuleLoader } from "../../di";-export const moduleLoader = {
+export const moduleLoader: ModuleLoader = {
   token,
   loadModule,
 };
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)

78-98: customInputs as z.undefined() is surprising; clarify intent or enforce with z.never().

If the goal is to forbid customInputs at this layer (non-API), prefer z.never() (property disallowed) rather than allowing presence with undefined. bookingCreateBodySchemaForApi later re-enables it, which is fine.

-      customInputs: z.undefined().optional(),
+      // Disallow at this layer; API schema re-enables it via merge with legacy props
+      customInputs: z.never().optional(),

If you intentionally need the key present-but-undefined, keep as-is and note it in a comment.

packages/features/bookings/lib/handleNewBooking.ts (3)

790-841: Hot path: heavy Day.js ops inside nested loops. Consider precomputing.

Repeated tz/format in loops impacts perf under large recurring sets. Precompute Day.js objects or use .utc() where possible; pass Date instances when acceptable to downstream functions.


812-825: Use for…of over for…in for array iteration.

for…in iterates string keys; for…of is clearer and avoids accidental prototype keys.

-          for (const key in fixedUsers) {
-            await ensureAvailableUsers(
-              { ...eventTypeWithUsers, users: [fixedUsers[key]] },
+          for (const u of fixedUsers) {
+            await ensureAvailableUsers(
+              { ...eventTypeWithUsers, users: [u] },
               {
                 dateFrom: dayjs(start).tz(reqBody.timeZone).format(),
                 dateTo: dayjs(end).tz(reqBody.timeZone).format(),
                 timeZone: reqBody.timeZone,
                 originalRescheduledBooking: originalRescheduledBooking ?? null,
               },
               loggerWithEventDetails,
               shouldServeCache
             );
           }

301-306: Consistent enum usage for SchedulingType.

You compare against string "COLLECTIVE" here but use SchedulingType.* elsewhere. Normalize to enum for consistency and type safety.

Also applies to: 1181-1183

packages/features/instant-meeting/handleInstantMeeting.ts (1)

283-300: Nit: use Date object for DateTime fields.

updatedAt should be a Date, not ISO string.

-      updatedAt: new Date().toISOString(),
+      updatedAt: new Date(),
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e87e5d8 and 9ab9a77.

📒 Files selected for processing (28)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (7 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (3 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (17)
  • packages/features/bookings/lib/index.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/web/pages/api/book/event.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/create-instant-booking.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/platform/libraries/bookings.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/platform/libraries/bookings.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/platform/libraries/bookings.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧠 Learnings (17)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/platform/libraries/bookings.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
📚 Learning: 2025-08-22T16:38:00.225Z
Learnt from: bandhan-majumder
PR: calcom/cal.com#23192
File: packages/lib/server/service/InsightsBookingBaseService.ts:814-816
Timestamp: 2025-08-22T16:38:00.225Z
Learning: In the InsightsBookingBaseService (packages/lib/server/service/InsightsBookingBaseService.ts), when filtering for "accepted" bookings in getMembersStatsWithCount(), using `endTime <= now()` in the SQL condition should be avoided as it conflicts with existing date filtering logic. The components already handle completion filtering by setting `endDate: currentTime` in their query parameters, making additional SQL-level endTime filtering unnecessary and potentially problematic.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
🧬 Code graph analysis (8)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • moduleLoader (40-43)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (7)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • moduleLoader (18-21)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)
  • moduleLoader (21-24)
packages/lib/di/modules/Attribute.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Host.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/LuckyUser.ts (1)
  • moduleLoader (28-31)
packages/lib/di/modules/Ooo.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/User.ts (1)
  • moduleLoader (18-21)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (5)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (4)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
packages/platform/libraries/bookings.ts (3)
  • getInstantBookingCreateService (7-7)
  • getRecurringBookingService (5-5)
  • getRegularBookingService (6-6)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/features/bookings/lib/dto/types.d.ts (3)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/platform/libraries/bookings.ts (2)
  • InstantBookingCreateResult (9-9)
  • RegularBookingCreateResult (10-10)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/instant-meeting/handleInstantMeeting.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateInstantBookingData (17-17)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/interfaces/IBookingCreateService.ts (1)
  • IBookingCreateService (4-7)
packages/features/bookings/lib/handleNewBooking.ts (7)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1046)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/lib/server/repository/host.ts (1)
  • HostRepository (3-40)
packages/lib/server/repository/user.ts (1)
  • UserRepository (123-1071)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (32-38)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (2)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/platform/libraries/bookings.ts (1)
  • getRecurringBookingService (5-5)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Tests / E2E API v2
  • GitHub Check: Tests / E2E (1/4)
🔇 Additional comments (17)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)

155-162: Good migration to DI service + bookingMeta.

Using getRecurringBookingService().createBooking({ bookingData, bookingMeta: { userId } }) aligns with the new API.

packages/features/bookings/lib/bookingCreateBodySchema.ts (1)

100-101: Exported ExtendedBookingCreateBody type looks correct.

packages/features/bookings/lib/dto/types.d.ts (2)

15-21: Uniformly moving Create*BookingData to ExtendedBookingCreateBody is consistent.


53-55: Be cautious with cross-file ReturnType on a class method.

Type-only import avoids runtime cycles, but this tight coupling complicates external consumption. Consider defining a stable explicit result type in this file in a follow‑up.

packages/features/bookings/lib/handleNewBooking.ts (2)

414-426: IBookingServiceDependencies surface looks complete. Ensure DI provides all keys at runtime.

Run the deps/interface comparison script from my earlier comment on RegularBookingService.module.ts. It should report no missing keys.


2080-2089: Credential.key is selected — ensure it never leaks beyond server internals.

Selection here is fine for internal payment handling. Confirm it’s never logged or exposed via API/tRPC.

packages/platform/libraries/bookings.ts (1)

5-11: Aggregator exports look good and align with DI-based services.

Type re-exports keep platform libs in sync with the new flow.

packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)

32-37: Deps map now aligns with IBookingServiceDependencies — verified.
Confirmed no missing or extra keys (Missing in depsMap: [], Extra in depsMap: []).

packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)

21-24: Exported moduleLoader is consistent with RegularBookingService.module.

No issues.


11-19: DI wiring looks correct.

RecurringBookingService's constructor accepts IRecurringBookingServiceDependencies, which defines regularBookingService — the depsMap key matches.

apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)

58-58: Imports align with service-based API.

Switch to service getters + InstantBookingCreateResult type looks good.


188-201: Regular booking: service call + bookingMeta LGTM.

Payload shape matches the new contract.


319-331: Recurring booking: service call LGTM.

Consistent with the refactor.


358-368: Instant booking: body-only contract correctly applied.

Passing only bookingData to the service is appropriate here.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)

65-65: Service getters import OK.

Matches the new platform-libraries surface.


451-454: Instant booking path: service usage LGTM.

Correct delegation to InstantBookingCreateService.


472-486: Recurring booking: includes noEmail (good).

Consistent with platform email settings.

Copy link
Copy Markdown
Contributor

@Udit-takkar Udit-takkar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (1)

498-511: Missing noEmail in bookingMeta.

The recurring booking service call omits the noEmail property that's present in regular bookings, which could lead to inconsistent email behavior.

Apply this diff to include the missing parameter:

 bookingMeta: {
   userId: bookingRequest.userId,
   hostname: bookingRequest.headers?.host || "",
   platformClientId: bookingRequest.platformClientId,
   platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
   platformCancelUrl: bookingRequest.platformCancelUrl,
   platformBookingUrl: bookingRequest.platformBookingUrl,
   platformBookingLocation: bookingRequest.platformBookingLocation,
+  noEmail: bookingRequest.noEmail,
   areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
 },
packages/features/bookings/lib/dto/types.d.ts (1)

53-54: Consider defining the type explicitly.

While inferring from the service method works, an explicit type definition would provide better maintainability and documentation.

Consider defining the type explicitly instead of inferring it:

-// TODO: In a followup PR, we working on defining the type here itself instead of inferring it.
-export type RegularBookingCreateResult = Awaited<ReturnType<RegularBookingService["createBooking"]>>;
+export type RegularBookingCreateResult = {
+  // Define the actual structure based on the service implementation
+  uid: string;
+  id: number;
+  // ... other properties
+};
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 9ab9a77 and 99a4c9f.

📒 Files selected for processing (28)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (7 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (3 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (16)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • packages/platform/libraries/bookings.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/index.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧠 Learnings (19)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-09-18T13:38:50.936Z
Learnt from: hariombalhara
PR: calcom/cal.com#23913
File: packages/features/bookings/Booker/components/hooks/usePrefetch.ts:43-50
Timestamp: 2025-09-18T13:38:50.936Z
Learning: In usePrefetch hook in packages/features/bookings/Booker/components/hooks/usePrefetch.ts, the !isNaN() checks before comparing monthAfterAdding1Month !== monthAfterAddingExtraDaysColumnView are intentional to prevent the NaN !== NaN issue where NaN values would incorrectly be considered different, leading to wrong monthCount calculations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T07:15:58.056Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.056Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
🧬 Code graph analysis (10)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • moduleLoader (40-43)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (2)
packages/lib/di/di.ts (1)
  • createContainer (114-114)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)
  • RecurringBookingService (25-25)
  • recurringBookingServiceModule (9-9)
apps/web/pages/api/book/recurring-event.ts (2)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/features/auth/lib/next-auth-options.ts (1)
  • session (746-771)
packages/features/bookings/lib/dto/types.d.ts (3)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/platform/libraries/bookings.ts (2)
  • InstantBookingCreateResult (9-9)
  • RegularBookingCreateResult (10-10)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/bookings/types.ts (2)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (54-54)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (4)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
packages/platform/libraries/bookings.ts (3)
  • getInstantBookingCreateService (7-7)
  • getRecurringBookingService (5-5)
  • getRegularBookingService (6-6)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (2)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (2)
  • InstantBookingCreateService (17-17)
  • instantBookingCreateServiceModule (6-6)
packages/features/bookings/lib/handleNewBooking.ts (5)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1046)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (32-38)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (7)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/platform/types/api.ts (1)
  • ApiResponse (33-35)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
🔇 Additional comments (42)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)

4-5: LGTM! Module loader pattern implementation is consistent.

The migration to the lazy-loading moduleLoader pattern is well-structured and aligns with the broader DI architecture changes in this PR.


21-24: LGTM! Consistent moduleLoader export pattern.

The moduleLoader export follows the established pattern used across other booking service modules.


11-19: Dependency mapping complete — no action required.
IRecurringBookingServiceDependencies declares only regularBookingService, and the module's depsMap maps it to regularBookingServiceModuleLoader.

packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (2)

4-4: LGTM! Clean import aliasing.

The import statement correctly aliases the moduleLoader to instantBookingCreateServiceModule for consistency.


10-11: LGTM! Proper module loading pattern.

The container correctly loads the module and retrieves the service using the moduleLoader pattern. This is consistent with the other service containers in the codebase.

packages/features/bookings/lib/bookingCreateBodySchema.ts (4)

60-76: LGTM! Schema refactoring improves modularity.

The extraction of recurring booking fields into a separate partial schema improves code organization and follows the TODO's plan for separate schemas for different booking types.


71-71: LGTM! Optional end field handling is correct.

The optional end field in allRecurringDates is correctly handled as noted in past review comments.


78-98: LGTM! Schema merge pattern is well-structured.

The merge of the base schema with the new object and recurring partial schema maintains backward compatibility while improving type safety.


100-100: LGTM! Public type export added.

The ExtendedBookingCreateBody type export provides proper type access for consumers.

packages/features/bookings/lib/handleNewBooking.ts (8)

414-426: DI interface is comprehensive but needs verification of module mappings.

The IBookingServiceDependencies interface covers all the necessary dependencies. However, as noted in previous reviews, ensure all these dependencies are properly mapped in the DI modules.


428-432: LGTM! Handler signature updated for DI pattern.

The handler now correctly accepts the deps parameter for dependency injection, which aligns with the service-based architecture.


446-452: LGTM! Clean dependency destructuring.

The destructuring of dependencies from the deps parameter is clean and follows good DI patterns.


583-589: LGTM! Repository method call updated correctly.

The call to bookingRepository.getValidBookingFromEventTypeForAttendee using the injected dependency is correct.


1608-1614: Attendee lookup should use parsed variables, not raw responses.

As noted in past reviews, the attendee lookup should use bookerEmail and bookerPhoneNumber instead of bookingData.responses.email and bookingData.responses.attendeePhoneNumber.


2425-2427: Fix undefined bookingMeta spreading.

The spreading of input.bookingMeta can throw when undefined. Apply the suggested fix to use input.bookingMeta ?? {} as the default.

Also applies to: 2396-2398


2433-2450: LGTM! Deprecation notice for API v1 method.

The deprecation comment clearly indicates the transition plan, and the method implementation correctly uses the same handler with proper parameter handling.


14-28: Imports validated — DTO types are exported in dto/types.d.ts

CreateRegularBookingData (line 15), CreateBookingMeta (line 32), and BookingHandlerInput (line 40) are exported from packages/features/bookings/lib/dto/types.d.ts; imports are correct.

packages/features/bookings/types.ts (2)

3-4: LGTM! Import path updates are correct.

The import changes align with the new DTO structure and enum location changes.


97-98: LGTM! Type alias simplification improves maintainability.

The direct alias to RegularBookingCreateResult simplifies the type definition while maintaining backward compatibility. The TODO comment appropriately documents the future unification plan.

packages/lib/di/bookings/containers/RecurringBookingService.container.ts (2)

4-4: LGTM! Consistent moduleLoader import pattern.

The import aliasing follows the established pattern across the DI refactor.


10-12: LGTM! Module loading pattern correctly implemented.

The container function properly loads the module and retrieves the service using the moduleLoader token, consistent with the other service containers.

apps/web/pages/api/book/recurring-event.ts (2)

6-6: LGTM! Service import follows DI pattern.

The import of getRecurringBookingService from the container follows the established DI pattern.


46-58: Security and data sanitization issues need attention.

As noted in previous review comments, several issues need to be addressed:

  1. Strip cfToken from req.body before passing to the service
  2. Change userId: session?.user?.id || -1 to userId: session?.user?.id ?? undefined to avoid sentinel values
  3. Add missing hostname and forcedSlug fields to bookingMeta

Apply the suggested diff from the previous review to address these issues.

packages/features/bookings/lib/handleNewRecurringBooking.ts (6)

13-16: LGTM! Handler signature updated for DI pattern.

The updated function signature correctly accepts the deps parameter for dependency injection, maintaining consistency with the regular booking handler.


18-18: LGTM! Clean dependency extraction.

The destructuring of regularBookingService from deps follows the established DI pattern.


57-64: LGTM! Service call updated correctly for first booking.

The call to regularBookingService.createBooking with proper bookingMeta wrapping is correctly implemented.


100-107: LGTM! Consistent service usage in recurring loop.

The recurring booking creation uses the same service pattern as the first booking, maintaining consistency.


127-129: LGTM! Clear dependency interface.

The IRecurringBookingServiceDependencies interface is simple and focused, requiring only the RegularBookingService dependency.


142-150: LGTM! Service implementation follows established pattern.

Both createBooking and rescheduleBooking methods correctly delegate to the handler with proper parameter transformation.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (6)

65-65: Align with NestJS DI best practices.

According to NestJS best practices, API v2 should leverage NestJS's native DI container instead of external service getters. The current approach bypasses NestJS's IoC container and defeats the purpose of dependency injection.


472-486: Use NestJS DI instead of external service getter.

This pattern bypasses NestJS's native dependency injection, making testing and mocking difficult.


524-537: Use NestJS DI instead of external service getter.

This pattern bypasses NestJS's native dependency injection, making testing and mocking difficult.


559-572: Use NestJS DI instead of external service getter.

This pattern bypasses NestJS's native dependency injection, making testing and mocking difficult.


757-770: Use NestJS DI instead of external service getter.

This pattern bypasses NestJS's native dependency injection, making testing and mocking difficult.


451-454: Use NestJS DI instead of external service getter.

This pattern bypasses NestJS's native dependency injection, making testing and mocking difficult.

Inject the service through the constructor instead:

+import { InstantBookingCreateService } from "@calcom/platform-libraries/bookings";

 @Injectable()
 export class BookingsService_2024_08_13 {
   constructor(
+    private readonly instantBookingCreateService: InstantBookingCreateService,
     // ... other dependencies
   ) {}
   
   async createInstantBooking(
     request: Request,
     body: CreateInstantBookingInput_2024_08_13,
     eventType: EventTypeWithOwnerAndTeam
   ) {
-    const instantBookingService = getInstantBookingCreateService();
-    const booking = await instantBookingService.createBooking({
+    const booking = await this.instantBookingCreateService.createBooking({
       bookingData: bookingRequest.body,
     });

You'll also need to register InstantBookingCreateService in the module's providers array.

packages/features/bookings/lib/dto/types.d.ts (3)

7-7: LGTM!

The import for SchedulingType correctly fixes the TypeScript error.


15-21: LGTM!

The type definitions correctly use ExtendedBookingCreateBody as the foundation for all booking data types, providing consistent structure across regular, instant, and recurring bookings.


44-51: LGTM!

The InstantBookingCreateResult type provides a clear, well-defined structure for instant booking responses.

apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)

58-58: LGTM!

The import changes correctly bring in the new service getters and types from the platform libraries.


319-331: Missing noEmail in recurring booking meta.

The recurring booking service call omits the noEmail property that's present in regular bookings, which could lead to inconsistent email behavior.


188-202: Use NestJS DI instead of external service getter.

This pattern bypasses NestJS's native dependency injection, making testing and mocking difficult.


363-367: Use NestJS DI instead of external service getter.

This pattern bypasses NestJS's native dependency injection, making testing and mocking difficult.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (7)
packages/features/bookings/lib/dto/types.d.ts (2)

53-54: Fix TODO grammar; avoid type-level coupling to service implementation

  • Minor copy fix — apply diff below.
  • packages/features/bookings/lib/dto/types.d.ts currently imports RegularBookingService from ../handleNewBooking, creating a type-level coupling. Export the result type from a neutral "contracts" (shared) module consumed by both the service and DTOs to decouple the public surface.
-// TODO: In a followup PR, we working on defining the type here itself instead of inferring it.
+// TODO: In a follow-up PR, we are defining the type here instead of inferring it.

19-21: Extract a CreateRecurringBookingItem type and keep schedulingType optional.

Introduce a single-item alias for readability; keep schedulingType optional — DB schema marks it nullable and callsites treat it as absent (packages/prisma/schema.prisma:189, packages/features/bookings/lib/handleNewBooking.ts:279).

+export type CreateRecurringBookingItem = ExtendedBookingCreateBody & {
+  schedulingType?: SchedulingType;
+};
-export type CreateRecurringBookingData = (ExtendedBookingCreateBody & {
-  schedulingType?: SchedulingType;
-})[];
+export type CreateRecurringBookingData = CreateRecurringBookingItem[];
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)

22-25: Optionally type moduleLoader to ModuleLoader.

For IDE help and consistency with other modules, export moduleLoader as ModuleLoader.

-export const moduleLoader = {
+export const moduleLoader: ModuleLoader = {
   token,
   loadModule,
 };
apps/web/pages/api/book/recurring-event.ts (1)

32-37: Guard cfToken access for array shape.

Avoid potential runtime errors when body isn’t an array.

-  if (process.env.NEXT_PUBLIC_CLOUDFLARE_USE_TURNSTILE_IN_BOOKER === "1") {
-    await checkCfTurnstileToken({
-      token: req.body[0]["cfToken"] as string,
-      remoteIp: userIp,
-    });
-  }
+  if (process.env.NEXT_PUBLIC_CLOUDFLARE_USE_TURNSTILE_IN_BOOKER === "1") {
+    const token = Array.isArray(req.body) ? req.body[0]?.cfToken : undefined;
+    await checkCfTurnstileToken({ token: String(token ?? ""), remoteIp: userIp });
+  }
apps/web/pages/api/book/event.ts (1)

15-20: Sanitize cfToken before passing bookingData.

Remove Turnstile token from the payload.

   if (process.env.NEXT_PUBLIC_CLOUDFLARE_USE_TURNSTILE_IN_BOOKER === "1") {
-    await checkCfTurnstileToken({
-      token: req.body["cfToken"] as string,
-      remoteIp: userIp,
-    });
+    const token = (req.body as any)?.cfToken;
+    await checkCfTurnstileToken({ token: String(token ?? ""), remoteIp: userIp });
   }
@@
-  const regularBookingService = getRegularBookingService();
-  const booking = await regularBookingService.createBooking({
-    bookingData: req.body,
+  const { cfToken, ...sanitized } = (req.body ?? {}) as Record<string, unknown>;
+  const regularBookingService = getRegularBookingService();
+  const booking = await regularBookingService.createBooking({
+    bookingData: sanitized,
     bookingMeta: {
       userId: session?.user?.id || -1,
       hostname: req.headers.host || "",
       forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
     },
   });

Also applies to: 34-41

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (1)

521-551: Remove unused createNextApiRecurringBookingRequest

Declared at apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts:521; no call-sites found — delete or implement to avoid drifting from createNextApiBookingRequest.

apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)

521-551: Remove unused helper: createNextApiRecurringBookingRequest

Defined in apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (≈ lines 521–551) but not referenced anywhere — delete it or update the recurring booking flow to use it.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 99a4c9f and 725a4bd.

📒 Files selected for processing (36)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (9 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (5 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (13)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/bookings/types.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • packages/platform/libraries/bookings.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/web/lib/types/booking.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • packages/features/bookings/lib/index.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
🧠 Learnings (20)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/web/pages/api/book/event.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-18T13:38:50.936Z
Learnt from: hariombalhara
PR: calcom/cal.com#23913
File: packages/features/bookings/Booker/components/hooks/usePrefetch.ts:43-50
Timestamp: 2025-09-18T13:38:50.936Z
Learning: In usePrefetch hook in packages/features/bookings/Booker/components/hooks/usePrefetch.ts, the !isNaN() checks before comparing monthAfterAdding1Month !== monthAfterAddingExtraDaysColumnView are intentional to prevent the NaN !== NaN issue where NaN values would incorrectly be considered different, leading to wrong monthCount calculations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
📚 Learning: 2025-09-12T07:15:58.056Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.056Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
🧬 Code graph analysis (19)
apps/api/v2/src/lib/modules/instant-booking.module.ts (5)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
apps/api/v2/src/lib/modules/recurring-booking.module.ts (1)
  • Module (5-10)
apps/api/v2/src/lib/modules/regular-booking.module.ts (1)
  • Module (15-32)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v2/src/lib/modules/recurring-booking.module.ts (7)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
apps/api/v2/src/lib/modules/instant-booking.module.ts (1)
  • Module (4-8)
apps/api/v2/src/lib/modules/regular-booking.module.ts (1)
  • Module (15-32)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)
  • RecurringBookingService (26-26)
packages/platform/libraries/bookings.ts (1)
  • RecurringBookingService (6-6)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • moduleLoader (42-45)
apps/web/pages/api/book/recurring-event.ts (1)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
apps/api/v2/src/lib/modules/regular-booking.module.ts (5)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
apps/api/v2/src/lib/modules/instant-booking.module.ts (1)
  • Module (4-8)
apps/api/v2/src/lib/modules/recurring-booking.module.ts (1)
  • Module (5-10)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v1/pages/api/bookings/_post.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
apps/api/v2/src/lib/services/instant-booking-create.service.ts (5)
apps/api/v2/src/lib/services/recurring-booking.service.ts (1)
  • Injectable (6-13)
apps/api/v2/src/lib/services/regular-booking.service.ts (1)
  • Injectable (17-46)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • InstantBookingCreateService (18-18)
packages/platform/libraries/bookings.ts (1)
  • InstantBookingCreateService (7-7)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/handleNewBooking.ts (5)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1046)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (32-38)
apps/api/v2/src/lib/services/recurring-booking.service.ts (3)
apps/api/v2/src/lib/services/instant-booking-create.service.ts (1)
  • Injectable (5-6)
apps/api/v2/src/lib/services/regular-booking.service.ts (1)
  • Injectable (17-46)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (2)
packages/features/bookings/lib/dto/types.d.ts (1)
  • BookingHandlerInput (40-42)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)
  • RecurringBookingService (26-26)
  • recurringBookingServiceModule (10-10)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (8)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • moduleLoader (19-22)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)
  • moduleLoader (22-25)
packages/lib/di/modules/Attribute.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/LuckyUser.ts (1)
  • moduleLoader (28-31)
packages/lib/di/modules/Host.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Ooo.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/User.ts (1)
  • moduleLoader (18-21)
packages/prisma/prisma.module.ts (1)
  • moduleLoader (13-19)
packages/features/instant-meeting/handleInstantMeeting.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateInstantBookingData (17-17)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/interfaces/IBookingCreateService.ts (1)
  • IBookingCreateService (4-7)
packages/features/bookings/lib/dto/types.d.ts (2)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
apps/web/pages/api/book/event.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
apps/api/v2/src/lib/services/regular-booking.service.ts (4)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (1)
  • Injectable (90-1142)
apps/api/v2/src/lib/services/instant-booking-create.service.ts (1)
  • Injectable (5-6)
apps/api/v2/src/lib/services/recurring-booking.service.ts (1)
  • Injectable (6-13)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Production builds / Build Docs
  • GitHub Check: Production builds / Build Web App
  • GitHub Check: Production builds / Build Atoms
  • GitHub Check: Production builds / Build API v2
  • GitHub Check: Production builds / Build API v1
  • GitHub Check: Type check / check-types
  • GitHub Check: Tests / Unit
  • GitHub Check: Linters / lint
🔇 Additional comments (37)
packages/features/bookings/lib/bookingCreateBodySchema.ts (2)

60-76: Schema refactoring properly separates recurring booking concerns.

The extraction of recurringBookingCreateBodyPartialSchema cleanly separates recurring booking fields from the base schema. The optional end field on line 71 is correctly handled as mentioned in past review comments.


79-98: Clarify legacy handling of customInputs

customInputs is intentionally z.undefined().optional() in the extended schema — the actual schema lives in bookingCreateSchemaLegacyPropsForApi (packages/features/bookings/lib/bookingCreateBodySchema.ts: customInputs: z.array(z.object({ label: z.string(), value: z.union([z.string(), z.boolean()]) }))) and is merged into bookingCreateBodySchemaForApi for API compatibility. Action: add a one-line inline comment at the z.undefined() site explaining this legacy/merge behavior, or only change the schema if you intend to accept customInputs on the new shape.

Likely an incorrect or invalid review comment.

packages/features/instant-meeting/handleInstantMeeting.ts (2)

158-158: Function rename from _handler to handler improves clarity.

The removal of the underscore prefix makes the function name more conventional and clearer.


339-341: Service implementation follows consistent pattern.

The InstantBookingCreateService correctly implements the IBookingCreateService interface and follows the same pattern as RegularBookingService and RecurringBookingService, which promotes consistency across the codebase.

apps/api/v2/src/lib/modules/recurring-booking.module.ts (1)

1-10: Approve — RecurringBookingModule correctly imports RegularBookingModule

RecurringBookingService's constructor receives RegularBookingService and forwards it to the base class, so importing RegularBookingModule to provide that dependency is correct.

apps/api/v2/src/lib/modules/instant-booking.module.ts (1)

1-8: Approve — InstantBookingModule verified

InstantBookingModule correctly provides and exports InstantBookingCreateService; apps/api/v2/src/lib/services/instant-booking-create.service.ts exists and the service simply extends BaseInstantBookingCreateService from @calcom/platform-libraries/bookings.

apps/api/v1/pages/api/bookings/_post.ts (1)

242-252: Service integration lazy loading verified
getRegularBookingService creates a new Container on each call and only invokes moduleLoader.loadModule—no modules are loaded at import time and there’s no global caching or singleton behavior.

apps/api/v2/src/lib/services/instant-booking-create.service.ts (1)

1-6: LGTM! Appropriate service wrapper implementation.

The service correctly extends the base InstantBookingCreateService and uses the @Injectable decorator for NestJS DI. This follows the same pattern established in the other booking services.

apps/api/v2/src/lib/services/recurring-booking.service.ts (1)

1-13: LGTM! Clean dependency injection pattern.

The service correctly extends the base service and properly injects RegularBookingService as a dependency, passing it to the parent constructor. This establishes the expected relationship where recurring bookings can delegate to regular booking logic.

apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2)

19-21: LGTM! Proper module imports for booking services.

The three booking modules (InstantBookingModule, RecurringBookingModule, RegularBookingModule) are correctly imported to provide the necessary booking services.


64-66: LGTM! Module registration is consistent.

The booking modules are properly registered in the imports array, making the booking services available to the module's controllers and providers.

apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2)

9-11: LGTM! Consistent module import pattern.

The booking modules are imported following the same pattern as the 2024-08-13 version, maintaining consistency across API versions.


41-43: LGTM! Proper module registration.

The booking modules are correctly added to the imports array, ensuring the services are available for dependency injection.

packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (2)

4-14: LGTM! Proper migration to service-based approach.

The handler correctly:

  • Uses the new service-based pattern with getRegularBookingService()
  • Properly destructures input into bookingData and bookingMeta
  • Calls the service's createBooking method with the correct parameters

This aligns with the broader architectural shift to service-based booking flows.


16-18: LGTM! Clean function export.

The getNewBookingHandler function correctly returns the handler, maintaining the expected API while internally using the new service-based implementation.

packages/lib/di/bookings/modules/RegularBookingService.module.ts (3)

3-3: LGTM! Comprehensive dependency expansion.

The module correctly adds the new dependencies (attributeRepository, hostRepository, luckyUserService, oooRepository, userRepository) with their corresponding module loaders, properly expanding the RegularBookingService capabilities.

Also applies to: 10-13


34-38: LGTM! Consistent dependency mapping.

The dependency map correctly includes all the new services with their respective module loaders, maintaining consistency with the existing pattern.


42-45: LGTM! Proper moduleLoader export pattern.

The export follows the established moduleLoader pattern used by other modules in the codebase, providing consistent lazy loading behavior.

apps/api/v2/src/lib/modules/regular-booking.module.ts (2)

15-32: LGTM! Well-structured NestJS module.

The module correctly:

  • Imports PrismaModule for database access
  • Provides all necessary repositories and services as dependencies
  • Exports RegularBookingService for use by other modules
  • Follows NestJS module conventions

1-14: Import paths and named exports verified — no changes required.

All referenced repository and service files exist under apps/api/v2/src/lib and export the expected named classes (PrismaAttributeRepository, PrismaBookingRepository, PrismaFeaturesRepository, PrismaHostRepository, PrismaOOORepository, PrismaUserRepository, CacheService, CheckBookingAndDurationLimitsService, CheckBookingLimitsService, LuckyUserService, RegularBookingService).

packages/lib/di/bookings/containers/RecurringBookingService.container.ts (2)

4-4: LGTM! Consistent moduleLoader import pattern.

The import correctly uses the moduleLoader pattern that's being adopted across the booking service modules.


9-13: LGTM! Proper moduleLoader usage pattern.

The function correctly:

  • Loads the module using the moduleLoader pattern
  • Retrieves the service using the moduleLoader's token
  • Returns the properly typed RecurringBookingService

This follows the same pattern established in other container files.

packages/features/bookings/lib/dto/types.d.ts (5)

2-2: Docstring LGTM

Clear scope statement for “domain types”.


7-7: SchedulingType import fixed

The missing import noted earlier is now present.


9-10: Type‑only imports: good

Keeps runtime clean; no action needed.


15-15: Mapping to ExtendedBookingCreateBody looks correct

Consistent with the new input schema.

Also applies to: 17-17


12-12: Resolved — BookingCreateBody is exported

packages/features/bookings/lib/bookingCreateBodySchema.ts exports BookingCreateBody (line 58), so the re‑export in packages/features/bookings/lib/dto/types.d.ts is valid.

packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)

12-20: DI binding looks correct and matches constructor keys.

depsMap key regularBookingService aligns with RecurringBookingService’s constructor. No issues.


8-10: DI tokens exist and are unique.

RECURRING_BOOKING_SERVICE and RECURRING_BOOKING_SERVICE_MODULE are defined as Symbol(...) in packages/lib/di/bookings/tokens.ts and are included in DI_TOKENS via ...BOOKING_DI_TOKENS in packages/lib/di/tokens.ts — no action required.

apps/api/v2/src/lib/services/regular-booking.service.ts (1)

17-46: Nest DI wiring LGTM.

Constructor deps map cleanly to base service; Prisma client injection approach is acceptable here.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (1)

456-460: Instant booking path LGTM.

DI usage and payload shape align with platform service expectations.

apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)

194-207: Regular booking service integration LGTM.

Meta includes forcedSlug and areCalendarEventsEnabled; matches platform service expectations.

apps/web/pages/api/book/recurring-event.ts (1)

46-57: Don’t pass -1 userId; strip cfToken; include hostname/forcedSlug.

Sanitize input and avoid sentinel IDs; pass host context for routing.

-  const recurringBookingService = getRecurringBookingService();
-  const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
-    bookingData: req.body,
-    bookingMeta: {
-      userId: session?.user?.id || -1,
+  const recurringBookingService = getRecurringBookingService();
+  const inputBody = req.body;
+  const bookingData = Array.isArray(inputBody)
+    ? inputBody.map(({ cfToken, ...rest }) => rest)
+    : inputBody;
+  const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
+    bookingData,
+    bookingMeta: {
+      userId: session?.user?.id ?? undefined,
+      hostname: req.hostname,
+      forcedSlug: req.forcedSlug,
       platformClientId: req.platformClientId,
       platformCancelUrl: req.platformCancelUrl,
       platformBookingUrl: req.platformBookingUrl,
       platformRescheduleUrl: req.platformRescheduleUrl,
       platformBookingLocation: req.platformBookingLocation,
       noEmail: req.noEmail,
     },
   });
apps/web/pages/api/book/event.ts (1)

34-41: Don’t proceed unauthenticated; avoid -1 sentinel.

Return 401 (or omit userId) instead of injecting -1.

-  const regularBookingService = getRegularBookingService();
-  const booking = await regularBookingService.createBooking({
+  if (!session?.user?.id) {
+    throw new Error("Unauthorized");
+  }
+  const regularBookingService = getRegularBookingService();
+  const booking = await regularBookingService.createBooking({
     bookingData: req.body,
     bookingMeta: {
-      userId: session?.user?.id || -1,
+      userId: session.user.id,
       hostname: req.headers.host || "",
       forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
     },
   });
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

57-66: Bug: first recurring RR slot isn’t added; series ID not propagated.

You await the first slot but don’t push it to results or seed thirdPartyRecurringEventId.

-    const firstBookingResult = await regularBookingService.createBooking({
+    const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-    luckyUsers = firstBookingResult.luckyUsers;
+    // include first slot and propagate series id for subsequent slots
+    createdBookings.push(firstBookingResult);
+    if (!thirdPartyRecurringEventId && firstBookingResult.references?.length) {
+      const ref = firstBookingResult.references.find((r) => r.thirdPartyRecurringEventId);
+      if (ref?.thirdPartyRecurringEventId) {
+        thirdPartyRecurringEventId = ref.thirdPartyRecurringEventId;
+      }
+    }
+    luckyUsers = firstBookingResult.luckyUsers;
packages/features/bookings/lib/handleNewBooking.ts (2)

2425-2431: Fix runtime crash when bookingMeta is undefined.

Spreading input.bookingMeta throws if undefined. Default to {}.

   async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }
@@
   async rescheduleBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }

1607-1613: Attendee lookup uses possibly undefined responses; use parsed booker fields.

Match against bookerEmail/bookerPhoneNumber instead of bookingData.responses.

-        const currentAttendee = booking.attendees.find(
-          (attendee) =>
-            attendee.email === bookingData.responses.email ||
-            (bookingData.responses.attendeePhoneNumber &&
-              attendee.phoneNumber === bookingData.responses.attendeePhoneNumber)
-        );
+        const currentAttendee = booking.attendees.find(
+          (attendee) => attendee.email === bookerEmail || (bookerPhoneNumber && attendee.phoneNumber === bookerPhoneNumber)
+        );

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (2)

501-512: Remove duplicate bookingMeta in recurring seated bookings.

The bookingMeta structure appears identical to lines 478-488. Consider extracting a helper function to avoid code duplication and ensure consistency.

private buildBookingMeta(bookingRequest: any) {
  return {
    userId: bookingRequest.userId,
    hostname: bookingRequest.headers?.host || "",
    platformClientId: bookingRequest.platformClientId,
    platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
    platformCancelUrl: bookingRequest.platformCancelUrl,
    platformBookingUrl: bookingRequest.platformBookingUrl,
    platformBookingLocation: bookingRequest.platformBookingLocation,
    noEmail: bookingRequest.noEmail,
    areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
  };
}

526-526: Remove debug console.log before production.

The debug console statement should be removed from production code.

-    console.log('Regularrr Booking service from Nest DI')
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

29-33: Guard against empty bookingData array.

Accessing data[0] without a precondition will throw on empty input.

-  const firstBooking = data[0];
+  if (data.length === 0) return [];
+  const firstBooking = data[0];
packages/features/bookings/lib/handleNewBooking.ts (1)

1196-1201: Prisma: select only required fields.

Return only organizationId to reduce data/PII surface.

-  const organizerOrganizationProfile = await prisma.profile.findFirst({
-    where: {
-      userId: organizerUser.id,
-      username: dynamicUserList[0],
-    },
-  });
+  const organizerOrganizationProfile = await prisma.profile.findFirst({
+    where: {
+      userId: organizerUser.id,
+      username: dynamicUserList[0],
+    },
+    select: { organizationId: true },
+  });
packages/features/bookings/lib/dto/types.d.ts (1)

44-51: Define a transport DTO for HTTP responses

InstantBookingCreateResult.expires is a Date (domain) and will be serialized to ISO strings over HTTP. Introduce a transport type with expires: string and update your controller to use it:

// packages/features/bookings/lib/dto/types.d.ts
export type InstantBookingCreateTransport =
  Omit<InstantBookingCreateResult, "expires"> & { expires: string };

In apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts:362, change the return type to ApiResponse<InstantBookingCreateTransport> and map expires.toISOString() before returning.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 725a4bd and 4e38f10.

📒 Files selected for processing (36)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (5 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (20)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • packages/platform/libraries/bookings.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/index.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/web/lib/types/booking.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧠 Learnings (20)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/types.ts
📚 Learning: 2025-09-18T13:38:50.936Z
Learnt from: hariombalhara
PR: calcom/cal.com#23913
File: packages/features/bookings/Booker/components/hooks/usePrefetch.ts:43-50
Timestamp: 2025-09-18T13:38:50.936Z
Learning: In usePrefetch hook in packages/features/bookings/Booker/components/hooks/usePrefetch.ts, the !isNaN() checks before comparing monthAfterAdding1Month !== monthAfterAddingExtraDaysColumnView are intentional to prevent the NaN !== NaN issue where NaN values would incorrectly be considered different, leading to wrong monthCount calculations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T07:15:58.056Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.056Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧬 Code graph analysis (14)
apps/api/v1/pages/api/bookings/_post.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
apps/api/v2/src/lib/modules/regular-booking.module.ts (5)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
apps/api/v2/src/lib/modules/instant-booking.module.ts (1)
  • Module (4-8)
apps/api/v2/src/lib/modules/recurring-booking.module.ts (1)
  • Module (5-10)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
apps/web/pages/api/book/recurring-event.ts (3)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • moduleLoader (42-45)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (3)
packages/lib/di/di.ts (1)
  • createContainer (114-114)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (2)
  • InstantBookingCreateService (18-18)
  • instantBookingCreateServiceModule (7-7)
apps/web/pages/api/book/instant-event.ts (1)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (3)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (7)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • moduleLoader (19-22)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)
  • moduleLoader (22-25)
packages/lib/di/modules/Attribute.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Host.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/LuckyUser.ts (1)
  • moduleLoader (28-31)
packages/lib/di/modules/Ooo.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/User.ts (1)
  • moduleLoader (18-21)
packages/features/bookings/lib/handleNewBooking.ts (5)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1046)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (32-38)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/bookings/lib/dto/types.d.ts (2)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/types.ts (5)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/index.ts (1)
  • BookingResponse (9-9)
packages/platform/libraries/index.ts (1)
  • BookingResponse (49-49)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (54-54)
packages/platform/libraries/bookings.ts (1)
  • RegularBookingCreateResult (10-10)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
🔇 Additional comments (31)
packages/features/bookings/lib/bookingCreateBodySchema.ts (3)

60-76: LGTM! Schema restructuring for recurring booking flow.

The recurringBookingCreateBodyPartialSchema properly encapsulates recurring-specific fields. Line 71 correctly makes end optional as noted by the maintainer, since handleNewRecurringBooking may pass undefined values.


78-98: Good schema composition using merge pattern.

The updated extendedBookingCreateBody cleanly merges the base schema with new top-level fields (noEmail, appsStatus, luckyUsers, customInputs) and the recurring partial schema. This prepares well for the TODO's planned separate schemas for different booking types.


100-100: Export the new type for proper typing.

ExtendedBookingCreateBody correctly provides proper types for input.bookingData, replacing the previous Record<string, any> typing mentioned in the PR objectives.

packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (2)

4-4: Clean moduleLoader aliasing pattern.

The alias moduleLoader as instantBookingCreateServiceModule maintains backward compatibility while adopting the new pattern. This approach is consistent with the broader DI refactoring.


10-11: Proper token-based service resolution.

The container now correctly loads the module first, then retrieves the service using the module's token instead of hardcoded DI_TOKENS. This aligns with the lazy-loading strategy.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (5)

9-11: Service imports align with new DI architecture.

The imports of InstantBookingCreateService, RecurringBookingService, and RegularBookingService from their respective services properly integrate with the new service-based booking flow.


112-114: Constructor properly wired for NestJS DI.

The new service dependencies are correctly injected via NestJS constructor DI, replacing the direct handler calls as intended by the refactoring.


456-458: Instant booking flow simplified with service call.

The transition from direct handleInstantMeeting to instantBookingCreateService.createBooking maintains the same payload structure while delegating to the DI-managed service. Payload remains as bookingData only since instant bookings don't need bookingMeta.


476-489: Consistent bookingMeta structure for recurring bookings.

The bookingMeta object properly includes all necessary platform-specific metadata (userId, hostname, platformClientId, etc.) and flags (noEmail, areCalendarEventsEnabled). This aligns with the new service interface expectations.


527-538: Regular booking implementation looks correct.

The service call with proper bookingMeta structure follows the expected pattern established for other booking types.

packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)

6-6: Verify RegularBookingService module dependency.

The import and dependency on regularBookingServiceModuleLoader is correct since RecurringBookingService depends on RegularBookingService for its implementation.


12-20: Proper moduleLoader setup with dependency mapping.

The bindModuleToClassOnToken correctly maps the regularBookingService dependency to regularBookingServiceModuleLoader in the depsMap. This ensures the dependency is loaded when the RecurringBookingService is instantiated.


22-25: Consistent moduleLoader export pattern.

The moduleLoader export with token and loadModule follows the same pattern as other booking service modules, maintaining consistency in the DI architecture.

packages/features/bookings/types.ts (1)

97-98: Type alias correctly simplifies public API.

The type alias BookingResponse = RegularBookingCreateResult provides backward compatibility while migrating to the new service-based types. The TODO comment appropriately notes the planned consolidation in a future PR.

apps/web/pages/api/book/instant-event.ts (2)

5-5: Proper service container import.

The import of getInstantBookingCreateService aligns with the new DI container pattern for service resolution.


23-28: Service-based booking flow with proper payload structure.

The transition from direct handleInstantMeeting call to service-based instantBookingService.createBooking({ bookingData: req.body }) maintains the same runtime validation while using the new architecture. The TODO comment correctly identifies the opportunity to move runtime validation to the API layer.

apps/api/v2/src/lib/modules/regular-booking.module.ts (2)

15-31: Complete NestJS module setup for RegularBookingService.

The module properly imports PrismaModule and provides all necessary dependencies (repositories, services, limits checking, cache) that RegularBookingService requires according to the IBookingServiceDependencies interface. The exports correctly make RegularBookingService available to other modules.


1-32: Verified — no Prisma 'include' usage found. Scanned apps/api/v2/src/lib/repositories (those imported by RegularBookingModule); no include: occurrences detected.

packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)

1-22: Verify moduleLoader pattern is consistent across booking modules.

Verified: moduleLoader is exported in packages/lib/di/bookings/modules/{InstantBookingCreateService.module.ts, RecurringBookingService.module.ts, RegularBookingService.module.ts}; containers call .loadModule(...), DI tokens align, and the empty depsMap is appropriate.

apps/api/v1/pages/api/bookings/_post.ts (1)

242-252: Service wiring for API v1 LGTM.

createBookingForApiV1 is correctly supplied with bookingMeta and schema getter.

packages/features/bookings/lib/handleNewBooking.ts (3)

2433-2449: API v1 shim correctly defaults bookingMeta; good.

The safer spread with bookingMeta ?? {} is applied here.


1609-1613: Bug: attendee lookup uses bookingData.responses; use parsed bookerEmail/Phone.

bookingData.responses may be absent; prefer the already parsed bookerEmail/bookerPhoneNumber.

-        const currentAttendee = booking.attendees.find(
-          (attendee) =>
-            attendee.email === bookingData.responses.email ||
-            (bookingData.responses.attendeePhoneNumber &&
-              attendee.phoneNumber === bookingData.responses.attendeePhoneNumber)
-        );
+        const currentAttendee = booking.attendees.find(
+          (attendee) =>
+            attendee.email === bookerEmail ||
+            (bookerPhoneNumber && attendee.phoneNumber === bookerPhoneNumber)
+        );

2425-2431: Spreading possibly undefined bookingMeta throws at runtime.

Object spread with undefined crashes. Default to {} first.

   async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }

   async rescheduleBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (3)

194-207: Regular booking service integration LGTM.

Metadata parity (hostname, forcedSlug, platform params, areCalendarEventsEnabled) is preserved.


324-334: Recurring booking service wiring is consistent.

Note: Omitting areCalendarEventsEnabled/noEmail matches stated existing behavior.


368-371: Instant booking: passing only body is correct.

Constructor no longer needs the full request context.

packages/features/bookings/lib/dto/types.d.ts (1)

9-21: Type imports/re-exports look correct.

SchedulingType import and ExtendedBookingCreateBody usage align with upstream types.

apps/web/pages/api/book/recurring-event.ts (1)

46-58: Avoid sentinel userId (-1); sanitize bookingData (strip cfToken); pass hostname/forcedSlug.

Passing -1 risks leaking invalid user IDs. Also strip cfToken from the payload and include hostname/forcedSlug for parity with other routes.

-  const recurringBookingService = getRecurringBookingService();
-  const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
-    bookingData: req.body,
-    bookingMeta: {
-      userId: session?.user?.id || -1,
-      platformClientId: req.platformClientId,
-      platformCancelUrl: req.platformCancelUrl,
-      platformBookingUrl: req.platformBookingUrl,
-      platformRescheduleUrl: req.platformRescheduleUrl,
-      platformBookingLocation: req.platformBookingLocation,
-      noEmail: req.noEmail,
-    },
-  });
+  const recurringBookingService = getRecurringBookingService();
+  const bookingDataInput = req.body;
+  const sanitizedBookingData = Array.isArray(bookingDataInput)
+    ? bookingDataInput.map(({ cfToken, ...rest }) => rest)
+    : bookingDataInput;
+
+  const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
+    bookingData: sanitizedBookingData,
+    bookingMeta: {
+      userId: session?.user?.id ?? undefined,
+      hostname: req.headers?.host || "",
+      forcedSlug: (req.headers?.["x-cal-force-slug"] as string | undefined) ?? undefined,
+      platformClientId: req.platformClientId,
+      platformCancelUrl: req.platformCancelUrl,
+      platformBookingUrl: req.platformBookingUrl,
+      platformRescheduleUrl: req.platformRescheduleUrl,
+      platformBookingLocation: req.platformBookingLocation,
+      noEmail: req.noEmail,
+    },
+  });
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

57-66: First recurring booking result is dropped; also seed series ID from first result.

You await the first booking but don’t push it, and you don’t propagate thirdPartyRecurringEventId for subsequent slots.

-    const firstBookingResult = await regularBookingService.createBooking({
+    const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-    luckyUsers = firstBookingResult.luckyUsers;
+    // include first slot and propagate series id for later slots
+    createdBookings.push(firstBookingResult);
+    if (!thirdPartyRecurringEventId && firstBookingResult.references?.length) {
+      const ref = firstBookingResult.references.find((r) => r.thirdPartyRecurringEventId);
+      if (ref?.thirdPartyRecurringEventId) {
+        thirdPartyRecurringEventId = ref.thirdPartyRecurringEventId;
+      }
+    }
+    luckyUsers = firstBookingResult.luckyUsers;
packages/lib/di/bookings/modules/RegularBookingService.module.ts (2)

34-38: Deps map keys match IBookingServiceDependencies — approved.
Verified: depsMap keys exactly match the IBookingServiceDependencies properties; no drift found.


42-45: Export rename verified — imports updated

Module now exports moduleLoader and callers import it (often aliased back to regularBookingServiceModule); e.g. packages/lib/di/bookings/containers/RegularBookingService.container.ts and packages/lib/di/bookings/modules/RecurringBookingService.module.ts. No direct imports of regularBookingServiceModule found.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)

376-383: Fix async rejection assertion and new API shape.

Pass the promise to expect.rejected and use bookingMeta for userId.

-          await expect(
-            async () =>
-              await recurringBookingService.createBooking({
-                bookingData: bookingDataArray,
-                userId: -1,
-              })
-          ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);
+          await expect(
+            recurringBookingService.createBooking({
+              bookingData: bookingDataArray,
+              bookingMeta: { userId: -1 },
+            })
+          ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);
🧹 Nitpick comments (8)
packages/features/instant-meeting/handleInstantMeeting.ts (2)

258-263: Use Prisma select (no include) per repo guideline.

Return only needed fields; avoid include.

Apply:

-  const createBookingObj = {
-    include: {
-      attendees: true,
-    },
-    data: newBookingData,
-  };
+  const createBookingObj = {
+    select: {
+      id: true,
+      uid: true,
+      userId: true,
+      title: true,
+      responses: true,
+      customInputs: true,
+      smsReminderNumber: true,
+    },
+    data: newBookingData,
+  };

1196-1201: Prisma: select only required fields.

findFirst is fetching full profile; select organizationId.

-  const organizerOrganizationProfile = await prisma.profile.findFirst({
-    where: {
-      userId: organizerUser.id,
-      username: dynamicUserList[0],
-    },
-  });
+  const organizerOrganizationProfile = await prisma.profile.findFirst({
+    where: {
+      userId: organizerUser.id,
+      username: dynamicUserList[0],
+    },
+    select: { organizationId: true },
+  });
packages/features/bookings/lib/handleNewBooking.ts (2)

1196-1201: Prisma: select only required fields.

Limit profile query to organizationId.

-  const organizerOrganizationProfile = await prisma.profile.findFirst({
+  const organizerOrganizationProfile = await prisma.profile.findFirst({
     where: {
       userId: organizerUser.id,
       username: dynamicUserList[0],
     },
+    select: { organizationId: true },
   });

789-841: Micro‑perf: avoid repeated dayjs.tz/format in loops.

Precompute formatted dates or reuse Day.js instances; reduces allocations in multi‑slot checks.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (1)

476-489: Optional: deduplicate bookingMeta construction.

Extract a private buildBookingMeta(bookingRequest, extras?) to avoid drift and repeated literals.

Example (outside this diff for illustration):

private buildBookingMeta(req: any, extras?: Partial<Record<string, unknown>>) {
  return {
    userId: req.userId,
    hostname: req.headers?.host || "",
    platformClientId: req.platformClientId,
    platformRescheduleUrl: req.platformRescheduleUrl,
    platformCancelUrl: req.platformCancelUrl,
    platformBookingUrl: req.platformBookingUrl,
    platformBookingLocation: req.platformBookingLocation,
    areCalendarEventsEnabled: req.areCalendarEventsEnabled,
    ...(extras || {}),
  };
}

Also applies to: 501-513, 526-537, 560-571, 757-768

packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

29-34: Guard empty bookingData arrays.

Accessing data[0] throws when array is empty.

-  const firstBooking = data[0];
-  const isRoundRobin = firstBooking.schedulingType === SchedulingType.ROUND_ROBIN;
+  if (!Array.isArray(data) || data.length === 0) return [];
+  const firstBooking = data[0];
+  const isRoundRobin = firstBooking.schedulingType === SchedulingType.ROUND_ROBIN;
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)

363-371: Swagger/typing: expires should be string on the wire.

ApiResponse uses InstantBookingCreateResult (expires: Date). Ensure the OpenAPI schema reflects expires as string (ISO).

packages/features/bookings/lib/dto/types.d.ts (1)

44-51: Expose a transport DTO for HTTP surfaces (expires as string).

Keep domain type as Date, but export an HTTP-safe variant to avoid leaking Date in API typings.

 export type InstantBookingCreateResult = {
   message: string;
   meetingTokenId: number;
   bookingId: number;
   bookingUid: string;
   expires: Date;
   userId: number | null;
 };
+
+// Transport-safe DTO for HTTP/JSON responses
+export type InstantBookingCreateResultHttp = Omit<InstantBookingCreateResult, "expires"> & {
+  expires: string;
+};
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4e38f10 and 076576a.

📒 Files selected for processing (36)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (5 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (21)
  • packages/features/bookings/lib/index.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/web/lib/types/booking.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/platform/libraries/bookings.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/event.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/event.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/event.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧠 Learnings (20)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-18T08:50:49.906Z
Learnt from: eunjae-lee
PR: calcom/cal.com#23752
File: packages/lib/server/service/InsightsBookingBaseService.ts:340-371
Timestamp: 2025-09-18T08:50:49.906Z
Learning: In the InsightsBookingBaseService (packages/lib/server/service/InsightsBookingBaseService.ts), the startTime date range filter intentionally uses different fields for the lower and upper bounds: `startDate <= "startTime" AND "endTime" <= endDate`. This ensures bookings start within the selected range but don't extend beyond the end date, which is the intended business logic and not an inconsistency.

Applied to files:

  • packages/features/bookings/lib/create-instant-booking.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/event.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/event.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/types.ts
📚 Learning: 2025-09-18T13:38:50.936Z
Learnt from: hariombalhara
PR: calcom/cal.com#23913
File: packages/features/bookings/Booker/components/hooks/usePrefetch.ts:43-50
Timestamp: 2025-09-18T13:38:50.936Z
Learning: In usePrefetch hook in packages/features/bookings/Booker/components/hooks/usePrefetch.ts, the !isNaN() checks before comparing monthAfterAdding1Month !== monthAfterAddingExtraDaysColumnView are intentional to prevent the NaN !== NaN issue where NaN values would incorrectly be considered different, leading to wrong monthCount calculations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T07:15:58.056Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.056Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
🧬 Code graph analysis (13)
packages/features/bookings/lib/create-instant-booking.ts (3)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)
  • createInstantBooking (357-390)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
packages/lib/fetch-wrapper.ts (1)
  • post (28-36)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • moduleLoader (42-45)
apps/web/pages/api/book/recurring-event.ts (1)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/features/instant-meeting/handleInstantMeeting.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateInstantBookingData (17-17)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/interfaces/IBookingCreateService.ts (1)
  • IBookingCreateService (4-7)
apps/api/v1/pages/api/bookings/_post.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (2)
packages/features/bookings/lib/dto/types.d.ts (1)
  • BookingHandlerInput (40-42)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/features/bookings/lib/dto/types.d.ts (2)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/types.ts (2)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (54-54)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/web/pages/api/book/event.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
🔇 Additional comments (19)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)

12-20: Good DI wiring with moduleLoader.

Binding RecurringBookingService with RegularBookingService via depsMap looks correct and consistent with the new loader pattern.


22-25: Export shape LGTM.

moduleLoader exposes token and loadModule as expected.

apps/api/v1/pages/api/bookings/_post.ts (1)

241-252: Service integration and typed booking flow look solid.

createBookingForApiV1 + bookingMeta + schema getter are wired correctly.

packages/features/instant-meeting/handleInstantMeeting.ts (1)

339-341: API surface is clean.

InstantBookingCreateService delegates to handler and returns typed result. 👍

packages/features/bookings/types.ts (2)

3-5: Type source updates look correct.

Switch to enums import and alias BookingResponse → RegularBookingCreateResult is consistent with the new service API.


97-99: Transitional alias acknowledged.

Keeping BookingResponse as alias is fine until follow‑up rename.

packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1)

4-13: Test helper now exercises the real service — good.

Dynamic import of the container keeps tests light and mirrors prod wiring.

packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)

155-162: Service usage in tests looks correct.

Passing bookingMeta with userId to RecurringBookingService aligns with the new API.

Ensure all other tests moved off handleNewRecurringBooking to the service (there’s still a call later in this file under a skipped test).

packages/features/bookings/lib/handleNewBooking.ts (2)

1608-1613: Bug: attendee lookup should use parsed email/phone, not bookingData.responses.

Use bookerEmail/bookerPhoneNumber to avoid undefined access.

-        const currentAttendee = booking.attendees.find(
-          (attendee) =>
-            attendee.email === bookingData.responses.email ||
-            (bookingData.responses.attendeePhoneNumber &&
-              attendee.phoneNumber === bookingData.responses.attendeePhoneNumber)
-        );
+        const currentAttendee = booking.attendees.find(
+          (attendee) =>
+            attendee.email === bookerEmail ||
+            (bookerPhoneNumber && attendee.phoneNumber === bookerPhoneNumber)
+        );

2426-2431: Runtime crash: spreading possibly undefined bookingMeta.

...input.bookingMeta throws when bookingMeta is undefined. Default it.

-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    return handler({ bookingData: input.bookingData, ...(input.bookingMeta ?? {}) }, this.deps);
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    return handler({ bookingData: input.bookingData, ...(input.bookingMeta ?? {}) }, this.deps);
apps/web/pages/api/book/event.ts (1)

34-42: Return 401 when unauthenticated; don’t pass userId = -1.

Proceeding with -1 can cause confusing downstream behavior.

-  const regularBookingService = getRegularBookingService();
-  const booking = await regularBookingService.createBooking({
-    bookingData: req.body,
-    bookingMeta: {
-      userId: session?.user?.id || -1,
-      hostname: req.headers.host || "",
-      forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
-    },
-  });
+  if (!session?.user?.id) {
+    throw new Error("Unauthorized");
+  }
+  const regularBookingService = getRegularBookingService();
+  const booking = await regularBookingService.createBooking({
+    bookingData: req.body,
+    bookingMeta: {
+      userId: session.user.id,
+      hostname: req.headers.host || "",
+      forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
+    },
+  });
apps/web/pages/api/book/recurring-event.ts (1)

46-58: Sanitize bookingData, avoid sentinel -1, and pass hostname/forcedSlug.

Strip cfToken before calling the service, don’t send -1 as userId, and include hostname/forcedSlug in bookingMeta.

   const recurringBookingService = getRecurringBookingService();
-  const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
-    bookingData: req.body,
+  const bookingDataInput = req.body;
+  const sanitizedBookingData = Array.isArray(bookingDataInput)
+    ? bookingDataInput.map(({ cfToken, ...rest }) => rest)
+    : bookingDataInput;
+  const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
+    bookingData: sanitizedBookingData,
     bookingMeta: {
-      userId: session?.user?.id || -1,
+      userId: session?.user?.id ?? undefined,
+      hostname: req.hostname,
+      forcedSlug: (req as any).forcedSlug,
       platformClientId: req.platformClientId,
       platformCancelUrl: req.platformCancelUrl,
       platformBookingUrl: req.platformBookingUrl,
       platformRescheduleUrl: req.platformRescheduleUrl,
       platformBookingLocation: req.platformBookingLocation,
       noEmail: req.noEmail,
     },
   });
packages/features/bookings/lib/create-instant-booking.ts (1)

9-11: Use transport type: serialize Date to string in HTTP response.

HTTP returns ISO strings, not Date. Type the response accordingly.

   const response = await post<
     BookingCreateBody,
-    // TODO: Fetch response can't have a Date type, it must be a string. We need to type expires as a string here but it breaks types down the line, fix it in a follow-up PR.
-    InstantBookingCreateResult
+    // transport DTO: expires serialized as string
+    (Omit<InstantBookingCreateResult, "expires"> & { expires: string })
   >("/api/book/instant-event", data);
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (2)

456-458: LGTM: instant bookings now use the dedicated service.


501-513: noEmail omitted for recurring seated bookings — confirm intent.

Regular/recurring paths include noEmail elsewhere; it’s missing here.

apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (3)

110-117: LGTM: services injected via Nest DI.


194-207: LGTM: regular booking routed through service with bookingMeta (incl. forcedSlug, calendarEvents).


324-335: Recurring bookingMeta omits areCalendarEventsEnabled/noEmail — verify this is intentional.

Behavior differs from regular bookings.

packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

57-66: Round‑robin bug: first slot not added and series ID not seeded.

You await firstBookingResult but don’t push it, and you don’t propagate thirdPartyRecurringEventId.

     const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-    luckyUsers = firstBookingResult.luckyUsers;
+    // include the first slot
+    createdBookings.push(firstBookingResult);
+    // seed series id for subsequent slots
+    if (!thirdPartyRecurringEventId && firstBookingResult.references?.length) {
+      const ref = firstBookingResult.references.find((r) => r.thirdPartyRecurringEventId);
+      if (ref?.thirdPartyRecurringEventId) {
+        thirdPartyRecurringEventId = ref.thirdPartyRecurringEventId;
+      }
+    }
+    luckyUsers = firstBookingResult.luckyUsers;

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)

376-383: Fix rejection assertion and payload shape

  • rejects must receive a Promise, not a function.
  • Payload should use bookingMeta, not top-level userId.

Apply:

-          await expect(
-            async () =>
-              await recurringBookingService.createBooking({
-                bookingData: bookingDataArray,
-                userId: -1,
-              })
-          ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);
+          await expect(
+            recurringBookingService.createBooking({
+              bookingData: bookingDataArray,
+              bookingMeta: {
+                userId: -1,
+              },
+            })
+          ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);

Also ensure ErrorCode is imported at the top:

import { ErrorCode } from "@calcom/lib/errorCodes";
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)

396-399: Config key mismatch for API key prefix (owner resolution may fail)

Using different config keys for check vs strip can break API key auth.

-        if (isApiKey(bearerToken, this.config.get<string>("api.apiKeyPrefix") ?? "cal_")) {
-          const strippedApiKey = stripApiKey(bearerToken, this.config.get<string>("api.keyPrefix"));
+        if (isApiKey(bearerToken, this.config.get<string>("api.apiKeyPrefix") ?? "cal_")) {
+          const strippedApiKey = stripApiKey(
+            bearerToken,
+            this.config.get<string>("api.apiKeyPrefix") ?? "cal_"
+          );
packages/features/bookings/lib/handleNewBooking.ts (1)

1196-1202: Prisma: select only required fields

Per guidelines, avoid fetching entire rows. Select organizationId only.

   const organizerOrganizationProfile = await prisma.profile.findFirst({
     where: {
       userId: organizerUser.id,
       username: dynamicUserList[0],
     },
+    select: { organizationId: true },
   });
🧹 Nitpick comments (12)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1)

5-8: Optional: memoize the container import to avoid reloading per call

In tests this is fine, but you can cache the resolved service across calls to shave overhead.

You could keep the dynamic import (to avoid restricted-import linting and cycles) but memoize the instance:

// outside handler
let regularBookingServiceSingleton: ReturnType<typeof getRegularBookingService> | null = null;

async function handler(input: BookingHandlerInput) {
  if (!regularBookingServiceSingleton) {
    const { getRegularBookingService } = await import("@calcom/lib/di/bookings/containers/RegularBookingService.container");
    regularBookingServiceSingleton = getRegularBookingService();
  }
  const { bookingData, ...bookingMeta } = input;
  return regularBookingServiceSingleton.createBooking({ bookingData, bookingMeta });
}
packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (1)

41-41: Minor: avoid repeated handler creation

Consider hoisting const handleNewBooking = getNewBookingHandler(); to a beforeEach to reuse within the suite.

Also applies to: 101-101, 164-164, 225-225, 290-290

packages/features/instant-meeting/handleInstantMeeting.test.ts (1)

39-39: Minor: instantiate service once per suite

Hoist const instantBookingCreateService = getInstantBookingCreateService(); to a beforeEach or the describe scope to avoid repeated container loads.

Also applies to: 138-138

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (1)

757-769: Call the explicit reschedule method for clarity

Functionally equivalent today, but rescheduleBooking is clearer and future-proof if behaviors diverge.

Apply:

-      const booking = await this.regularBookingService.createBooking({
+      const booking = await this.regularBookingService.rescheduleBooking({
         bookingData: bookingRequest.body,
         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },
       });
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)

78-98: Intentional override — add a short inline comment

Confirmed. extendedBookingCreateBody intentionally sets customInputs to z.undefined().optional() so internal flows prefer/new responses shape; bookingCreateBodySchemaForApi then reintroduces legacy customInputs via .merge(bookingCreateSchemaLegacyPropsForApi.partial()) (Zod merge gives precedence to the later shape). Add a short inline comment at packages/features/bookings/lib/bookingCreateBodySchema.ts (around the extendedBookingCreateBody and bookingCreateBodySchemaForApi merges) documenting this override and the Zod precedence to avoid regression.

apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)

209-214: Avoid awaiting fire-and-forget usage metering

If non-blocking is intended, drop await inside void to prevent unnecessary latency.

-      if (booking.userId && booking.uid && booking.startTime) {
-        void (await this.billingService.increaseUsageByUserId(booking.userId, {
-          uid: booking.uid,
-          startTime: booking.startTime,
-          fromReschedule: booking.fromReschedule,
-        }));
-      }
+      if (booking.userId && booking.uid && booking.startTime) {
+        void this.billingService.increaseUsageByUserId(booking.userId, {
+          uid: booking.uid,
+          startTime: booking.startTime,
+          fromReschedule: booking.fromReschedule,
+        });
+      }

324-334: Prefer for...of over async forEach for metering loop

forEach with async is not awaited and mixes control flow. Use for...of and drop inner await if fire-and-forget.

-      createdBookings.forEach(async (booking) => {
-        if (booking.userId && booking.uid && booking.startTime) {
-          void (await this.billingService.increaseUsageByUserId(booking.userId, {
-            uid: booking.uid,
-            startTime: booking.startTime,
-          }));
-        }
-      });
+      for (const booking of createdBookings) {
+        if (booking.userId && booking.uid && booking.startTime) {
+          void this.billingService.increaseUsageByUserId(booking.userId, {
+            uid: booking.uid,
+            startTime: booking.startTime,
+          });
+        }
+      }

Also applies to: 337-344


362-370: Instant booking: pass body only (good); drop await in fire-and-forget metering

Service usage is correct; consider removing await inside void.

-        void (await this.billingService.increaseUsageByUserId(instantMeeting.userId, {
+        void this.billingService.increaseUsageByUserId(instantMeeting.userId, {
           uid: instantMeeting.bookingUid,
           startTime: now,
-        }));
+        });

Also applies to: 376-380


521-551: Unused helper createNextApiRecurringBookingRequest

This function isn’t used in this controller. Remove, or use it for the recurring endpoint for consistency.

packages/features/bookings/lib/handleNewBooking.ts (2)

789-807: Day.js in hot loops

Multiple dayjs.tz/utc calls in loops; cache formatted strings or precompute to reduce overhead.

Also applies to: 965-985


826-826: No-op property access

eventTypeWithUsers.users[0].credentials; has no effect. Remove.

-          eventTypeWithUsers.users[0].credentials;
packages/features/bookings/lib/dto/types.d.ts (1)

53-55: Decouple RegularBookingCreateResult from service method signature

Define the result shape here to avoid cross-module type coupling; aligns with the TODO.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 076576a and a7c8bc0.

📒 Files selected for processing (36)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (5 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
🚧 Files skipped from review as they are similar to previous changes (18)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • apps/web/lib/types/booking.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/bookings/lib/index.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/web/pages/api/book/recurring-event.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/platform/libraries/bookings.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧠 Learnings (20)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/event.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-18T13:38:50.936Z
Learnt from: hariombalhara
PR: calcom/cal.com#23913
File: packages/features/bookings/Booker/components/hooks/usePrefetch.ts:43-50
Timestamp: 2025-09-18T13:38:50.936Z
Learning: In usePrefetch hook in packages/features/bookings/Booker/components/hooks/usePrefetch.ts, the !isNaN() checks before comparing monthAfterAdding1Month !== monthAfterAddingExtraDaysColumnView are intentional to prevent the NaN !== NaN issue where NaN values would incorrectly be considered different, leading to wrong monthCount calculations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/web/pages/api/book/event.ts
📚 Learning: 2025-09-12T07:15:58.056Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.056Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
🧬 Code graph analysis (15)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (2)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (2)
  • InstantBookingCreateService (18-18)
  • instantBookingCreateServiceModule (7-7)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (2)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)
  • RecurringBookingService (26-26)
  • recurringBookingServiceModule (10-10)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (1)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1)
  • getNewBookingHandler (16-18)
apps/api/v1/pages/api/bookings/_post.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/features/bookings/lib/handleNewBooking.ts (4)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1046)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (32-38)
packages/features/instant-meeting/handleInstantMeeting.test.ts (1)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (11)
packages/lib/di/modules/Attribute.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Host.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/LuckyUser.ts (1)
  • moduleLoader (28-31)
packages/lib/di/modules/Ooo.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/User.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Booking.ts (1)
  • moduleLoader (11-16)
packages/lib/di/modules/Cache.ts (1)
  • moduleLoader (14-19)
packages/lib/di/modules/CheckBookingAndDurationLimits.ts (1)
  • moduleLoader (14-19)
packages/lib/di/modules/CheckBookingLimits.ts (1)
  • moduleLoader (13-18)
packages/lib/di/modules/Features.ts (1)
  • moduleLoader (11-16)
packages/prisma/prisma.module.ts (1)
  • moduleLoader (13-19)
packages/features/bookings/lib/dto/types.d.ts (2)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (5)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
apps/web/pages/api/book/event.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (2)
packages/features/bookings/lib/dto/types.d.ts (1)
  • BookingHandlerInput (40-42)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • moduleLoader (42-45)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (27)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1)

4-13: Service-based handler LGTM

Solid switch to RegularBookingService.createBooking with typed BookingHandlerInput and bookingMeta separation.

packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (1)

22-23: Switch to getNewBookingHandler helper looks good

Consistent usage across tests; aligns with the service-based flow.

Also applies to: 41-41, 101-101, 164-164, 225-225, 290-290

packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (2)

26-26: Container import LGTM

getRecurringBookingService usage matches the DI/container pattern.


155-162: BookingMeta wrapping and service call LGTM

Correctly passing { bookingData, bookingMeta: { userId: -1 } } to createBooking.

packages/lib/di/bookings/modules/RecurringBookingService.module.ts (4)

1-25: DI module refactor LGTM

The bindModuleToClassOnToken usage and moduleLoader export are consistent with the new DI pattern.


8-10: Token wiring verified — RECURRING_BOOKING_SERVICE and RECURRING_BOOKING_SERVICE_MODULE exist in DI_TOKENS
Defined in packages/lib/di/bookings/tokens.ts (BOOKING_DI_TOKENS) and merged into DI_TOKENS via ...BOOKING_DI_TOKENS in packages/lib/di/tokens.ts.


12-20: Resolved — depsMap key 'regularBookingService' matches constructor

IRecurringBookingServiceDependencies in packages/features/bookings/lib/handleNewRecurringBooking.ts declares regularBookingService and the module's depsMap uses the same key — no change required.


22-25: No action required — container already uses moduleLoader

packages/lib/di/bookings/containers/RecurringBookingService.container.ts imports moduleLoader (aliased as recurringBookingServiceModule) and calls loadModule / uses token, so no change needed.

packages/features/instant-meeting/handleInstantMeeting.test.ts (1)

17-17: Instant booking service adoption LGTM

Correct switch to getInstantBookingCreateService().createBooking({ bookingData }) and assertions look good.

Also applies to: 39-39, 113-115, 138-138, 194-198

packages/lib/di/bookings/modules/RegularBookingService.module.ts (3)

42-45: Module loader export shape looks consistent

Token + loadModule shape matches other modules.


26-26: No change required — classs is the declared parameter name. bindModuleToClassOnToken defines and uses classs in packages/lib/di/di.ts and other modules consistently reference it; no fix needed.


28-38: Verified — depsMap matches RegularBookingService constructor & IBookingServiceDependencies

IBookingServiceDependencies contains luckyUserService, hostRepository, oooRepository, userRepository, attributeRepository; depsMap and RegularBookingService constructor use the same keys (prisma is mapped from prismaWriteService.prisma). No action required.

packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)

10-12: Good switch to moduleLoader pattern

Container uses moduleLoader.loadModule + token consistently.

packages/features/bookings/lib/bookingCreateBodySchema.ts (1)

60-76: Recurring partial schema extraction looks good

Explicit optional end aligns with downstream usage.

apps/web/pages/api/book/event.ts (1)

38-41: Don’t proceed with unauthenticated user; return 401 instead

Avoid passing userId: -1. Short-circuit with 401 when session is missing.

Apply:

-  const booking = await regularBookingService.createBooking({
+  if (!session?.user?.id) {
+    throw new Error("Unauthorized");
+  }
+  const booking = await regularBookingService.createBooking({
     bookingData: req.body,
     bookingMeta: {
-      userId: session?.user?.id || -1,
+      userId: session.user.id,
       hostname: req.headers.host || "",
       forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
     },
   });
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)

10-13: ModuleLoader usage is consistent

Matches the pattern used by other containers.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (2)

501-513: noEmail omitted for recurring seated flow (intentional?)

This differs from recurring non-seated where noEmail is passed. If that was intentional per existing behavior, ignore; otherwise, include it for parity.


111-115: No action needed — services are provided via imported modules

bookings.module.ts imports RegularBookingModule, RecurringBookingModule and InstantBookingModule which export RegularBookingService, RecurringBookingService and InstantBookingCreateService respectively (see apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts and apps/api/v2/src/lib/modules/{regular-booking.module.ts,recurring-booking.module.ts,instant-booking.module.ts}).

packages/features/bookings/lib/handleNewRecurringBooking.ts (2)

100-107: LGTM on passing bookingMeta to service

Consistent with the new service contract.


57-66: Bug: first round‑robin slot result is dropped and series ID not seeded

You await the first booking but don’t push it to createdBookings or seed thirdPartyRecurringEventId, returning N‑1 results and risking broken series linkage.

Fix:

     const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-    luckyUsers = firstBookingResult.luckyUsers;
+    // include first slot and propagate series id for subsequent slots
+    createdBookings.push(firstBookingResult);
+    // seed third-party recurring series id if available
+    if (
+      !thirdPartyRecurringEventId &&
+      firstBookingResult.references &&
+      firstBookingResult.references.length > 0
+    ) {
+      for (const reference of firstBookingResult.references) {
+        if (reference.thirdPartyRecurringEventId) {
+          thirdPartyRecurringEventId = reference.thirdPartyRecurringEventId;
+          break;
+        }
+      }
+    }
+    luckyUsers = firstBookingResult.luckyUsers;
apps/api/v1/pages/api/bookings/_post.ts (1)

242-252: LGTM — bookingDataSchemaGetter returns the API schema

getBookingDataSchemaForApi composes the API-specific zod schema (imports bookingCreateBodySchemaForApi / bookingCreateSchemaLegacyPropsForApi), so passing it as bookingDataSchemaGetter into createBookingForApiV1 is correct.

apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (2)

110-117: DI services wiring looks correct

Constructor injects the three booking services and UsersService as expected for the refactor.


194-207: LGTM: bookingMeta consolidation for regular bookings

Passing hostname, forcedSlug, platform params, and areCalendarEventsEnabled under bookingMeta is consistent with the new service API.

packages/features/bookings/lib/handleNewBooking.ts (2)

1608-1613: Use parsed bookerEmail/phoneNumber for attendee matching (not bookingData.responses)

-        const currentAttendee = booking.attendees.find(
-          (attendee) =>
-            attendee.email === bookingData.responses.email ||
-            (bookingData.responses.attendeePhoneNumber &&
-              attendee.phoneNumber === bookingData.responses.attendeePhoneNumber)
-        );
+        const currentAttendee = booking.attendees.find(
+          (attendee) =>
+            attendee.email === bookerEmail ||
+            (bookerPhoneNumber && attendee.phoneNumber === bookerPhoneNumber)
+        );

2425-2431: Spreading possibly undefined bookingMeta throws at runtime

Object spread of undefined/null will crash. Default before spreading.

   async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }

   async rescheduleBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }
packages/features/bookings/lib/dto/types.d.ts (2)

6-8: Correct: SchedulingType import added

Resolves the reference in CreateRecurringBookingData.


44-52: Accepting existing API Date serialization for expires

Keeping expires as Date in domain type is fine; transport can address string conversion later.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

45-66: Critical: First booking result not added to createdBookings array.

When isRoundRobin is true, the first booking is created but never added to the createdBookings array. This will cause the function to return N-1 results instead of N, and the first booking won't be included in the response.

Apply this fix to include the first booking result:

     const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
+    createdBookings.push(firstBookingResult);
     luckyUsers = firstBookingResult.luckyUsers;
+    
+    // Extract the third-party recurring event ID from the first booking
+    if (!thirdPartyRecurringEventId && firstBookingResult.references?.length) {
+      const ref = firstBookingResult.references.find((r) => r.thirdPartyRecurringEventId);
+      if (ref?.thirdPartyRecurringEventId) {
+        thirdPartyRecurringEventId = ref.thirdPartyRecurringEventId;
+      }
+    }
🧹 Nitpick comments (2)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)

64-66: Consider re-exporting these modules if downstream modules need their providers transitively

If other modules import BookingsModule_2024_08_13 and expect these providers without importing the lib modules directly, add them to this module’s exports. Otherwise, current setup is fine.

Would you like to make them available transitively? If yes, update the exports as below:

@@
   controllers: [BookingsController_2024_08_13],
-  exports: [InputBookingsService_2024_08_13, OutputBookingsService_2024_08_13, BookingsService_2024_08_13],
+  exports: [
+    InputBookingsService_2024_08_13,
+    OutputBookingsService_2024_08_13,
+    BookingsService_2024_08_13,
+    RegularBookingModule,
+    RecurringBookingModule,
+    InstantBookingModule,
+  ],
apps/api/v1/pages/api/bookings/_post.ts (1)

242-243: Optional: hoist service initialization to module scope to avoid per-request load

If getRegularBookingService() and its deps are safe to reuse across requests, initialize once at module scope to reduce per-request overhead. Keep as-is if per-request scoping is intentional.

Module-scope snippet to consider:

// at module scope
const regularBookingService = getRegularBookingService();

// inside handler: reuse the instance
// const regularBookingService = getRegularBookingService();
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a7c8bc0 and d4e4120.

📒 Files selected for processing (36)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (5 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (22)
  • apps/web/lib/types/booking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/bookings/lib/index.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/platform/libraries/bookings.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/web/pages/api/book/event.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧠 Learnings (20)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-18T13:38:50.936Z
Learnt from: hariombalhara
PR: calcom/cal.com#23913
File: packages/features/bookings/Booker/components/hooks/usePrefetch.ts:43-50
Timestamp: 2025-09-18T13:38:50.936Z
Learning: In usePrefetch hook in packages/features/bookings/Booker/components/hooks/usePrefetch.ts, the !isNaN() checks before comparing monthAfterAdding1Month !== monthAfterAddingExtraDaysColumnView are intentional to prevent the NaN !== NaN issue where NaN values would incorrectly be considered different, leading to wrong monthCount calculations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T07:15:58.056Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.056Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
🧬 Code graph analysis (12)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (7)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • moduleLoader (19-22)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)
  • moduleLoader (22-25)
packages/lib/di/modules/Attribute.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Ooo.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Host.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/LuckyUser.ts (1)
  • moduleLoader (28-31)
packages/lib/di/modules/User.ts (1)
  • moduleLoader (18-21)
apps/api/v2/src/lib/services/recurring-booking.service.ts (2)
apps/api/v2/src/lib/services/regular-booking.service.ts (1)
  • Injectable (17-46)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • moduleLoader (42-45)
apps/web/pages/api/book/recurring-event.ts (3)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/instant-meeting/handleInstantMeeting.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateInstantBookingData (17-17)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/interfaces/IBookingCreateService.ts (1)
  • IBookingCreateService (4-7)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/handleNewBooking.ts (4)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (32-38)
apps/api/v1/pages/api/bookings/_post.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (4)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)
  • moduleLoader (22-25)
packages/features/bookings/lib/dto/types.d.ts (4)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/platform/libraries/bookings.ts (3)
  • InstantBookingCreateResult (9-9)
  • RegularBookingCreateResult (10-10)
  • RegularBookingService (5-5)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • RegularBookingService (47-47)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Production builds / Build Docs
  • GitHub Check: Production builds / Build Web App
  • GitHub Check: Production builds / Build API v2
  • GitHub Check: Production builds / Build API v1
  • GitHub Check: Tests / Unit
  • GitHub Check: Production builds / Build Atoms
  • GitHub Check: Type check / check-types
  • GitHub Check: Linters / lint
🔇 Additional comments (29)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)

19-21: Booking modules wiring OK — providers exported and no DI cycle found

InstantBookingModule exports InstantBookingCreateService; RecurringBookingModule exports RecurringBookingService (and imports RegularBookingModule); RegularBookingModule exports RegularBookingService. No references to BookingsModule_2024_08_13 found in those modules.

apps/api/v1/pages/api/bookings/_post.ts (1)

4-4: Good move: switch to DI container for booking service

This aligns this route with the new service-based flow and keeps concerns out of the handler.

packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (2)

1-1: LGTM! Clean DI module migration.

The migration to the moduleLoader pattern is well-implemented. The module correctly implements the pattern established across other booking modules, with consistent token/loadModule structure.


15-15: Empty depsMap is correct for InstantBookingCreateService. The class declares no constructor or DI dependencies (see packages/features/instant-meeting/handleInstantMeeting.ts), so depsMap: {} is valid.

packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

127-129: Well-structured dependency interface.

The IRecurringBookingServiceDependencies interface properly defines the dependency on RegularBookingService, maintaining clean separation of concerns and enabling proper dependency injection.

apps/api/v2/src/lib/services/recurring-booking.service.ts (1)

1-13: LGTM! Clean NestJS service implementation.

The service correctly extends the base RecurringBookingService and properly wires the RegularBookingService dependency through the constructor. The implementation follows NestJS patterns and maintains proper dependency injection.

packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)

1-26: LGTM! Consistent moduleLoader implementation.

The module properly implements the moduleLoader pattern with correct dependency wiring to RegularBookingService. The implementation is consistent with other booking modules.

packages/lib/di/bookings/modules/RegularBookingService.module.ts (2)

42-45: Module export naming is consistent.

The change from regularBookingServiceModule to moduleLoader aligns with the pattern established across all other DI modules in the codebase, improving consistency.


27-39: DepsMap matches updated IBookingServiceDependencies

IBookingServiceDependencies (packages/features/bookings/lib/handleNewBooking.ts:414-426) defines the 11 properties; depsMap in packages/lib/di/bookings/modules/RegularBookingService.module.ts:27-39 matches them.

apps/web/pages/api/book/recurring-event.ts (1)

47-58: Sanitize bookingData, avoid sentinel userId, and include hostname/forcedSlug

Several issues need to be addressed based on the past review comments:

  1. The cfToken field should be removed from req.body before passing it to createBooking
  2. Change userId: session?.user?.id || -1 to userId: session?.user?.id ?? undefined to avoid sentinel values
  3. Add hostname: req.hostname and forcedSlug: req.forcedSlug to the bookingMeta object

Apply this diff to address these issues:

+  const bookingDataInput = req.body;
+  const sanitizedBookingData = Array.isArray(bookingDataInput)
+    ? bookingDataInput.map(({ cfToken, ...rest }) => rest)
+    : (() => {
+        const { cfToken, ...rest } = (bookingDataInput ?? {}) as Record<string, unknown>;
+        return rest;
+      })();
+
   const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
-    bookingData: req.body,
+    bookingData: sanitizedBookingData,
     bookingMeta: {
-      userId: session?.user?.id || -1,
+      userId: session?.user?.id ?? undefined,
+      hostname: req.hostname,
+      forcedSlug: req.forcedSlug,
       platformClientId: req.platformClientId,
       platformCancelUrl: req.platformCancelUrl,
       platformBookingUrl: req.platformBookingUrl,
       platformRescheduleUrl: req.platformRescheduleUrl,
       platformBookingLocation: req.platformBookingLocation,
       noEmail: req.noEmail,
     },
   });
packages/features/instant-meeting/handleInstantMeeting.ts (2)

158-158: LGTM! Clean function signature update

The handler function now accepts only bookingData parameter, which is correctly typed as CreateInstantBookingData. This aligns well with the service-based approach where instant meetings need only the booking data without additional metadata.


339-341: LGTM! Service implementation follows DI pattern correctly

The InstantBookingCreateService correctly implements IBookingCreateService and delegates to the internal handler with proper input extraction. The signature is clean and consistent with other booking services.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)

111-116: LGTM! Service dependencies properly injected

The new booking services are correctly injected as private readonly dependencies. This follows NestJS DI patterns and provides clean separation between the API service and the underlying booking logic.


456-458: LGTM! Instant booking service integration

The instant booking service is correctly used with only bookingData, which matches the simplified signature for instant bookings that don't require additional metadata.


476-489: Consistent bookingMeta construction across booking flows

The bookingMeta construction is consistent with other booking flows in this service, including all necessary platform parameters and settings. The metadata properly includes areCalendarEventsEnabled and other platform-specific configurations.

apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (5)

10-12: LGTM! Service imports correctly updated

The new service imports replace the legacy handler imports cleanly. The service-based approach provides better separation of concerns and enables proper DI.


113-116: LGTM! Constructor dependencies properly injected

The booking services are correctly injected as constructor dependencies following NestJS patterns. This enables proper DI and testing.


194-207: LGTM! RegularBookingService integration with proper metadata

The service is correctly used with both bookingData and bookingMeta. The metadata includes all necessary fields like userId, hostname, forcedSlug, and platform-specific configurations. The structure matches the expected service interface.


324-335: Note: Existing behavior preserved for recurring bookings

The recurring booking service omits forcedSlug, areCalendarEventsEnabled, and noEmail from the bookingMeta, which differs from regular bookings. Based on maintainer feedback, this reflects existing behavior and is intentional.


368-370: LGTM! InstantBookingCreateService correctly integrated

The instant booking service correctly uses only bookingData without bookingMeta, matching the simplified interface for instant bookings. The return type is properly typed as InstantBookingCreateResult.

packages/features/bookings/lib/handleNewBooking.ts (5)

414-426: LGTM! Comprehensive dependency interface for DI

The IBookingServiceDependencies interface properly defines all the dependencies needed by the booking service. The interface includes all necessary repositories, services, and clients required for booking operations.


428-432: LGTM! Handler signature updated for DI support

The handler now accepts deps parameter of type IBookingServiceDependencies, enabling proper dependency injection. The signature is clean and maintains backward compatibility with the optional bookingDataSchemaGetter.


446-452: LGTM! Dependencies destructured from injected deps

The dependencies are properly extracted from the deps parameter, replacing the previous direct service instantiation pattern. This enables proper testing and DI.


2425-2427: Fix: Guard against undefined bookingMeta

The spread of input.bookingMeta can throw at runtime if it's undefined. Use nullish coalescing to provide a safe default.

Apply this fix:

 async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-  return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+  return handler({ bookingData: input.bookingData, ...(input.bookingMeta ?? {}) }, this.deps);
 }

Also apply the same fix to rescheduleBooking at lines 2429-2431.


2436-2450: LGTM! Deprecated API v1 method with proper handling

The createBookingForApiV1 method is properly marked as deprecated and safely handles the optional bookingMeta parameter. The method will be removed when API v1 is deprecated, providing a clean migration path.

packages/features/bookings/lib/dto/types.d.ts (4)

1-4: LGTM! Clear documentation for domain types

The comment clearly indicates these are framework-agnostic domain types for booking services, which aligns well with the DI architecture.


15-21: LGTM! Consistent data types using ExtendedBookingCreateBody

All booking data types now consistently use ExtendedBookingCreateBody as the base, providing type safety and consistency across regular, instant, and recurring bookings. The recurring booking data properly extends with schedulingType as needed.


44-51: LGTM! InstantBookingCreateResult type properly defined

The type correctly defines the instant booking result structure with appropriate field types. The expires field as Date is consistent with the domain model, and serialization concerns are appropriately handled at API boundaries.


53-54: LGTM! RegularBookingCreateResult inferred from service

Using Awaited<ReturnType<>> ensures type safety and keeps the result type synchronized with the actual service implementation. The TODO note indicates future consolidation plans.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/features/instant-meeting/handleInstantMeeting.ts (2)

73-90: Bug: promises from webhook dispatch aren’t returned, so Promise.all doesn’t wait.
The map callback doesn’t return the promise; Promise.all(promises) resolves immediately and doesn’t truly await webhook calls.

Apply this diff to return the promises so awaiting works as intended:

-    const promises = subscribers.map((sub) => {
-      sendGenericWebhookPayload({
+    const promises = subscribers.map((sub) => {
+      return sendGenericWebhookPayload({
         secretKey: sub.secret,
         triggerEvent: eventTrigger,
         createdAt: new Date().toISOString(),
         webhook: sub,
         data: webhookData,
-      }).catch((e) => {
+      }).catch((e) => {
         console.error(
           `Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}`,
           sub,
           e
         );
-      });
+      });
     });
 
     await Promise.all(promises);

Alternatively, drop the per-call catch and use Promise.allSettled(promises) to avoid short-circuiting on one failure.


258-263: Use Prisma select instead of include; and select only needed fields.
Per repo guidelines, avoid include. Also, attendees aren’t used later, so fetching them is wasted I/O.

Apply this diff:

-  const createBookingObj = {
-    include: {
-      attendees: true,
-    },
-    data: newBookingData,
-  };
+  const createBookingObj = {
+    select: {
+      id: true,
+      uid: true,
+      userId: true,
+      responses: true,
+      customInputs: true,
+      title: true,
+    },
+    data: newBookingData,
+  };
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

29-33: Guard against empty bookingData

Accessing data[0] will throw when bookingData is empty. Add an explicit check.

Apply:

   // for round robin, the first slot needs to be handled first to define the lucky user
-  const firstBooking = data[0];
+  if (data.length === 0) {
+    throw new Error("bookingData must contain at least one slot for recurring booking");
+  }
+  const firstBooking = data[0];
🧹 Nitpick comments (11)
packages/features/instant-meeting/handleInstantMeeting.ts (1)

132-137: Guard JSON.parse to avoid throwing for malformed subscriptions.
A malformed DB value will throw before Zod validation and break the whole notification fanout.

Apply this diff:

-    const parsedSubscription = subscriptionSchema.safeParse(JSON.parse(subscription));
+    let raw;
+    try {
+      raw = JSON.parse(subscription);
+    } catch (e) {
+      logger.error("Invalid subscription JSON", { error: String(e) });
+      return Promise.resolve();
+    }
+    const parsedSubscription = subscriptionSchema.safeParse(raw);
packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (4)

33-35: Use resetAllMocks to avoid leaking stubbed implementations across tests

clearAllMocks resets call history only; resetAllMocks also resets mock implementations, preventing cross-test coupling.

Apply:

-  beforeEach(() => {
-    vi.clearAllMocks();
-  });
+  beforeEach(() => {
+    vi.resetAllMocks();
+  });

86-91: Prefer rejects.toMatchObject for object property assertions

toThrow is intended for message/class matching. Use toMatchObject to assert error object shape.

-        await expect(handleNewBooking({ bookingData: mockBookingData })).rejects.toThrow(
-          expect.objectContaining({
-            statusCode: 400,
-            message: "email_verification_required",
-          })
-        );
+        await expect(handleNewBooking({ bookingData: mockBookingData })).rejects.toMatchObject({
+          statusCode: 400,
+          message: "email_verification_required",
+        });

149-154: Use rejects.toMatchObject to assert error details

Improves correctness over toThrow with asymmetric matchers.

-        await expect(handleNewBooking({ bookingData: mockBookingData })).rejects.toThrow(
-          expect.objectContaining({
-            statusCode: 400,
-            message: "invalid_verification_code",
-          })
-        );
+        await expect(handleNewBooking({ bookingData: mockBookingData })).rejects.toMatchObject({
+          statusCode: 400,
+          message: "invalid_verification_code",
+        });

275-280: Use rejects.toMatchObject for rate limit mapping assertion

Ensures robust matching of the mapped error object.

-        await expect(handleNewBooking({ bookingData: mockBookingData })).rejects.toThrow(
-          expect.objectContaining({
-            statusCode: 400,
-            message: "invalid_verification_code",
-          })
-        );
+        await expect(handleNewBooking({ bookingData: mockBookingData })).rejects.toMatchObject({
+          statusCode: 400,
+          message: "invalid_verification_code",
+        });
apps/api/v2/src/lib/services/instant-booking-create.service.ts (1)

1-6: Nest wrapper over platform service — OK

Thin injectable wrapper is appropriate for Nest DI.

If/when introducing method overrides or logging, consider adding a constructor with DI-injected logger for parity with other services.

packages/features/bookings/lib/bookingCreateBodySchema.ts (1)

79-98: Avoid shadowing customInputs unless strictly required

Defining customInputs: z.undefined().optional() in extendedBookingCreateBody then overriding it in bookingCreateBodySchemaForApi works, but is slightly surprising. If the goal is to ban customInputs except for API, consider omitting it here entirely and documenting that only the API merge adds it.

       luckyUsers: z.array(z.number()).optional(),
-      customInputs: z.undefined().optional(),
     })
     .merge(recurringBookingCreateBodyPartialSchema)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (1)

476-489: Avoid empty-string hostname; prefer undefined/nullish when absent

Passing "" can be misinterpreted downstream. Use undefined if header is missing.

       bookingMeta: {
         userId: bookingRequest.userId,
-        hostname: bookingRequest.headers?.host || "",
+        hostname: bookingRequest.headers?.host,
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
         noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)

337-344: Avoid async forEach with awaited calls

The current pattern makes the awaits inside callbacks meaningless and surprising. Either fire-and-forget without await or await deterministically.

Apply (fire-and-forget, sequential iteration):

-      createdBookings.forEach(async (booking) => {
-        if (booking.userId && booking.uid && booking.startTime) {
-          void (await this.billingService.increaseUsageByUserId(booking.userId, {
-            uid: booking.uid,
-            startTime: booking.startTime,
-          }));
-        }
-      });
+      for (const booking of createdBookings) {
+        if (booking.userId && booking.uid && booking.startTime) {
+          void this.billingService.increaseUsageByUserId(booking.userId, {
+            uid: booking.uid,
+            startTime: booking.startTime,
+          });
+        }
+      }
packages/lib/di/bookings/modules/RegularBookingService.module.ts (2)

8-9: Remove unnecessary no-restricted-imports disable (likely redundant).

The import is from our DI modules namespace and shouldn’t be restricted. Prefer removing the disable unless there’s a specific rule violation.

Apply:

-// eslint-disable-next-line no-restricted-imports
 import { moduleLoader as featuresRepositoryModuleLoader } from "@calcom/lib/di/modules/Features";

If lint still fails after removal, keep the disable and add a brief reason.


42-45: Type the exported moduleLoader for consistency with other modules.

Adds compile-time checks and aligns with Attribute/Host/User/etc. modules.

Apply:

-export const moduleLoader = {
+export const moduleLoader: ModuleLoader = {
   token,
   loadModule,
 };

Also import the type (adjust if your DI types are exported elsewhere):

// At the existing import from "../../di"
import { bindModuleToClassOnToken, createModule, type ModuleLoader } from "../../di";
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d4e4120 and 5171538.

📒 Files selected for processing (36)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (5 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (20)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • packages/platform/libraries/bookings.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/web/pages/api/book/event.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/index.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/web/pages/api/book/recurring-event.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/web/pages/api/book/recurring-event.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/web/pages/api/book/recurring-event.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
🧠 Learnings (20)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/types.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/web/pages/api/book/recurring-event.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-18T13:38:50.936Z
Learnt from: hariombalhara
PR: calcom/cal.com#23913
File: packages/features/bookings/Booker/components/hooks/usePrefetch.ts:43-50
Timestamp: 2025-09-18T13:38:50.936Z
Learning: In usePrefetch hook in packages/features/bookings/Booker/components/hooks/usePrefetch.ts, the !isNaN() checks before comparing monthAfterAdding1Month !== monthAfterAddingExtraDaysColumnView are intentional to prevent the NaN !== NaN issue where NaN values would incorrectly be considered different, leading to wrong monthCount calculations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T07:15:58.056Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.056Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
🧬 Code graph analysis (14)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (8)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • moduleLoader (19-22)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)
  • moduleLoader (22-25)
packages/lib/di/modules/Attribute.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/LuckyUser.ts (1)
  • moduleLoader (28-31)
packages/lib/di/modules/Ooo.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/User.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Host.ts (1)
  • moduleLoader (18-21)
packages/prisma/prisma.module.ts (1)
  • moduleLoader (13-19)
apps/api/v2/src/lib/services/instant-booking-create.service.ts (5)
apps/api/v2/src/lib/services/recurring-booking.service.ts (1)
  • Injectable (6-13)
apps/api/v2/src/lib/services/regular-booking.service.ts (1)
  • Injectable (17-46)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • InstantBookingCreateService (18-18)
packages/platform/libraries/bookings.ts (1)
  • InstantBookingCreateService (7-7)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/web/pages/api/book/instant-event.ts (1)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
packages/features/bookings/types.ts (2)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (54-54)
packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (1)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1)
  • getNewBookingHandler (16-18)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (2)
  • InstantBookingCreateService (18-18)
  • instantBookingCreateServiceModule (7-7)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/dto/types.d.ts (2)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
apps/web/pages/api/book/recurring-event.ts (3)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/auth/lib/next-auth-options.ts (1)
  • session (746-771)
apps/api/v2/src/lib/services/regular-booking.service.ts (2)
apps/api/v2/src/lib/services/recurring-booking.service.ts (1)
  • Injectable (6-13)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/instant-meeting/handleInstantMeeting.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateInstantBookingData (17-17)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/interfaces/IBookingCreateService.ts (1)
  • IBookingCreateService (4-7)
packages/features/bookings/lib/handleNewBooking.ts (5)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1046)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (32-38)
🔇 Additional comments (50)
packages/features/instant-meeting/handleInstantMeeting.ts (5)

5-5: Import of Cal Video client looks correct.
No issues spotted with this import change.


9-10: Type migration to InstantBookingCreateResult is sound.
Ensure downstream call sites expect the new result shape.


158-158: Internal handler rename is fine.
Signature and usage look consistent with the service wrapper.


332-332: Good: compile-time check with satisfies InstantBookingCreateResult.
Keeps the return payload aligned with the public contract.


339-341: Service method signature and delegation look correct.
Typed input/output and reuse of handler are appropriate.

packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6)

41-41: Per-test handler retrieval — OK

Creating/getting the handler per test is fine and keeps DI state isolated.


101-101: Per-test handler retrieval — OK

Consistent with the new helper pattern.


165-165: Per-test handler retrieval — OK

Matches the migration approach used elsewhere in the suite.


225-225: Per-test handler retrieval — OK

No issues.


290-290: Per-test handler retrieval — OK

Consistent and clear.


22-23: DI-backed handler import — LGTM

Confirmed: getNewBookingHandler imports getRegularBookingService and the returned handler delegates to regularBookingService.createBooking({ bookingData, bookingMeta }).

packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)

4-11: Verify moduleLoader export and container lifecycle

Confirm that InstantBookingCreateService.module exports moduleLoader and token as used here, and that repeated loadModule(container) calls are idempotent with the singleton container.

apps/web/pages/api/book/instant-event.ts (2)

5-5: Import switch to DI container looks good


23-28: Service-based instant booking call — looks good

Clean replacement of the legacy handler with createBooking({ bookingData }).

Please verify that CreateInstantBookingData schema includes creationSource or treats it as optional so the runtime validation passes unchanged.

packages/features/bookings/lib/bookingCreateBodySchema.ts (2)

60-76: Recurring partial schema extraction is a good move

This improves reuse and keeps the base schema lean.


100-101: Type export LGTM

ExtendedBookingCreateBody based on z.input is consistent with consumer-side input types.

packages/features/bookings/types.ts (2)

3-4: Type import updates look correct

Using RegularBookingCreateResult aligns app/web with the new service flow.


97-99: Alias BookingResponse to RegularBookingCreateResult — OK

This minimizes churn while moving to the new naming.

Confirm all downstream imports of BookingResponse are type-only and do not rely on removed InstantBookingResponse.

apps/web/pages/api/book/recurring-event.ts (2)

6-6: DI import for recurring service — OK


46-58: Don’t pass sentinel -1; include host context; strip cfToken from bookingData

Passing -1 risks leaking a sentinel into downstream logic. Also, include hostname/forcedSlug if present, and avoid forwarding cfToken in bookingData.

   const recurringBookingService = getRecurringBookingService();
   const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
-    bookingData: req.body,
+    bookingData: Array.isArray(req.body) ? req.body.map(({ cfToken, ...rest }) => rest) : req.body,
     bookingMeta: {
-      userId: session?.user?.id || -1,
+      userId: session?.user?.id ?? undefined,
+      hostname: (req as any).hostname ?? req.headers?.host,
+      forcedSlug: (req as any).forcedSlug,
       platformClientId: req.platformClientId,
       platformCancelUrl: req.platformCancelUrl,
       platformBookingUrl: req.platformBookingUrl,
       platformRescheduleUrl: req.platformRescheduleUrl,
       platformBookingLocation: req.platformBookingLocation,
       noEmail: req.noEmail,
     },
   });

Please confirm forcedSlug is present on this request type in all callers; if not, omit it or gate it.

apps/api/v2/src/lib/services/regular-booking.service.ts (1)

1-46: Nest RegularBookingService wiring looks correct

Dependencies mirror the platform service’s expected deps; Prisma client is correctly sourced from PrismaWriteService.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (7)

9-11: Importing new booking services — OK


111-115: Constructor DI additions — OK

Services injected here match usage below.


455-458: Instant booking via service — LGTM


501-513: Add noEmail for recurring seated flow

Other flows pass noEmail; recur-seated should too for consistency.

       bookingMeta: {
         userId: bookingRequest.userId,
-        hostname: bookingRequest.headers?.host || "",
+        hostname: bookingRequest.headers?.host,
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },

526-538: Add noEmail for regular booking meta

Bring this in line with recurring flow’s meta to control email delivery.

       bookingMeta: {
         userId: bookingRequest.userId,
-        hostname: bookingRequest.headers?.host || "",
+        hostname: bookingRequest.headers?.host,
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },

560-572: Add noEmail for seated booking meta

Maintain consistent email toggling across flows.

       bookingMeta: {
         userId: bookingRequest.userId,
-        hostname: bookingRequest.headers?.host || "",
+        hostname: bookingRequest.headers?.host,
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },

757-769: Consider passing noEmail on reschedule as well

If reschedules should suppress emails in some contexts, thread noEmail through here too. Otherwise, explicitly document why it’s omitted.

       bookingMeta: {
         userId: bookingRequest.userId,
-        hostname: bookingRequest.headers?.host || "",
+        hostname: bookingRequest.headers?.host,
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },

Please confirm expected behavior for reschedule email notifications; if emails must always fire on reschedule, keep it omitted.

packages/features/bookings/lib/handleNewRecurringBooking.ts (3)

13-16: Signature refactor looks good

DI via deps is clear and contained.


20-21: Type tightening for recurring dates is correct

start as string and end as string | undefined aligns with downstream usage.


57-66: Round-robin: first result not added and series ID not propagated

You don’t push the firstBookingResult to createdBookings and you don’t seed thirdPartyRecurringEventId from it. This returns N-1 results and may break series linkage for subsequent slots.

Apply:

     const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-    luckyUsers = firstBookingResult.luckyUsers;
+    // include first slot and propagate series id for subsequent slots
+    createdBookings.push(firstBookingResult);
+    if (!thirdPartyRecurringEventId && firstBookingResult.references?.length) {
+      const ref = firstBookingResult.references.find((r) => r.thirdPartyRecurringEventId);
+      if (ref?.thirdPartyRecurringEventId) {
+        thirdPartyRecurringEventId = ref.thirdPartyRecurringEventId;
+      }
+    }
+    luckyUsers = firstBookingResult.luckyUsers;
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)

10-12: Service imports aligned with DI

Using InstantBookingCreateService, RecurringBookingService, RegularBookingService is consistent with the new flow.


113-117: Constructor injection looks correct

All three services are injected and used in handlers.


194-207: Pass-through bookingMeta is complete

areCalendarEventsEnabled included; matches regular booking path requirements.


362-371: Instant booking flow is correct

Passing only bookingData to the service matches the new contract.

packages/features/bookings/lib/handleNewBooking.ts (8)

24-28: Public types import is appropriate

Good move to centralized DTOs and handler input types.


414-426: Deps surface is comprehensive

Interface covers all needed collaborators for DI.


430-452: Handler now DI-driven

Passing deps in is a solid refactor and removes hidden singletons.


555-556: Boolean coercion is correct

Ensures isFirstRecurringSlot is a boolean when present.


789-793: Recurring availability checks gated properly

Nullish-safe checks for recurring context avoid runtime errors.


1610-1613: Use parsed bookerEmail/Phone for attendee matching (not bookingData.responses)

Apply:

-        const currentAttendee = booking.attendees.find(
-          (attendee) =>
-            attendee.email === bookingData.responses.email ||
-            (bookingData.responses.attendeePhoneNumber &&
-              attendee.phoneNumber === bookingData.responses.attendeePhoneNumber)
-        );
+        const currentAttendee = booking.attendees.find(
+          (attendee) =>
+            attendee.email === bookerEmail ||
+            (bookerPhoneNumber && attendee.phoneNumber === bookerPhoneNumber)
+        );

2441-2449: Good: guarded spread for API v1 path

bookingMeta defaulting avoids runtime errors here.


2425-2431: Bug: spreading possibly undefined bookingMeta throws

{ ...input.bookingMeta } will crash when bookingMeta is undefined. Default it.

Apply:

   async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }

   async rescheduleBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }
packages/features/bookings/lib/dto/types.d.ts (4)

7-8: Fix for missing SchedulingType import

Importing as type resolves earlier TS error.


15-22: Type aliases read well

CreateRegular/Instant map to ExtendedBookingCreateBody; recurring extends for schedulingType — consistent with usage.


44-52: InstantBookingCreateResult export is coherent

Fields/types align with feature code; domain-level Date is acceptable here.


53-55: RegularBookingCreateResult alias is fine

Keeps consumers in sync with service return type.

packages/lib/di/bookings/modules/RegularBookingService.module.ts (3)

1-2: Scoped ESLint disable is fine here.

Using the service class directly for DI wiring is consistent with the pattern. Scoped to a single import — LGTM.


3-3: New DI module loaders look correct — exports verified.
Confirmed export const moduleLoader exists in packages/lib/di/modules/Attribute.ts, Host.ts, LuckyUser.ts, Ooo.ts, User.ts.


34-39: Verified — IBookingServiceDependencies contains the new keys.

All of luckyUserService, hostRepository, oooRepository, userRepository and attributeRepository are present in packages/features/bookings/lib/handleNewBooking.ts.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
packages/features/bookings/lib/handleNewBooking.ts (1)

1545-1546: Use injected UsersRepository instead of instantiating a new one

Bypassing DI may use a different Prisma/logging context and breaks testability.

Apply this diff:

-      if (booking?.userId) {
-        const usersRepository = new UsersRepository();
-        await usersRepository.updateLastActiveAt(booking.userId);
+      if (booking?.userId) {
+        await deps.userRepository.updateLastActiveAt(booking.userId);
packages/features/instant-meeting/handleInstantMeeting.ts (4)

73-90: Fix: return promises from map and avoid logging secrets

The promises aren’t returned from the map callback, so Promise.all resolves immediately. Also, logging sub leaks the webhook secret. Return the promise and log a sanitized subset; prefer Promise.allSettled since each call already catches errors.

-    const promises = subscribers.map((sub) => {
-      sendGenericWebhookPayload({
-        secretKey: sub.secret,
-        triggerEvent: eventTrigger,
-        createdAt: new Date().toISOString(),
-        webhook: sub,
-        data: webhookData,
-      }).catch((e) => {
-        console.error(
-          `Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}`,
-          sub,
-          e
-        );
-      });
-    });
-
-    await Promise.all(promises);
+    const promises = subscribers.map((sub) => {
+      const webhook = {
+        id: sub.id,
+        subscriberUrl: sub.subscriberUrl,
+        payloadTemplate: sub.payloadTemplate,
+        appId: sub.appId,
+      };
+      return sendGenericWebhookPayload({
+        secretKey: sub.secret,
+        triggerEvent: eventTrigger,
+        createdAt: new Date().toISOString(),
+        webhook,
+        data: webhookData,
+      }).catch((e) => {
+        logger.error(
+          `Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}`,
+          { id: sub.id, url: sub.subscriberUrl, error: (e as Error)?.message }
+        );
+      });
+    });
+
+    await Promise.allSettled(promises);

258-266: Prisma: replace include with select (avoid returning unneeded data)

Per guidelines, don’t use include; select only required fields.

-  const createBookingObj = {
-    include: {
-      attendees: true,
-    },
-    data: newBookingData,
-  };
+  const createBookingObj = {
+    data: newBookingData,
+    select: {
+      id: true,
+      uid: true,
+      responses: true,
+      customInputs: true,
+      title: true,
+      userId: true,
+    },
+  };

283-300: Prisma: select only needed fields from instantMeetingToken.create

You only use id and expires; restrict the return.

-  const instantMeetingToken = await prisma.instantMeetingToken.create({
-    data: {
+  const instantMeetingToken = await prisma.instantMeetingToken.create({
+    data: {
       token,
       // current time + offset Seconds
       expires: new Date(new Date().getTime() + 1000 * instantMeetingExpiryTimeOffsetInSeconds),
       team: {
         connect: {
           id: eventType.team.id,
         },
       },
       booking: {
         connect: {
           id: newBooking.id,
         },
       },
       updatedAt: new Date().toISOString(),
-    },
-  });
+    },
+    select: { id: true, expires: true },
+  });

298-299: Remove manual updatedAt on InstantMeetingToken creation

packages/prisma/schema.prisma: InstantMeetingToken.updatedAt is declared DateTime @updatedat — Prisma manages this field; remove the manually set updatedAt from the create call in packages/features/instant-meeting/handleInstantMeeting.ts (line ~298).

🧹 Nitpick comments (11)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (1)

134-134: Reduce repetition with a local alias for the response type

Define a local alias once and use it across tests to cut noise and ease future renames.

Add near the imports (outside selected range):

type RegularBookingResponse = ApiSuccessResponse<RegularBookingCreateResult>;

Then apply this change here:

-const responseBody: ApiSuccessResponse<RegularBookingCreateResult> = response.body;
+const responseBody: RegularBookingResponse = response.body;

You can apply the same replacement at Lines 233, 290, and 387.

packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)

10-11: Avoid re-loading the module on every call (make load idempotent).

Repeated loadModule calls can rebind providers if the container doesn’t guard by moduleToken. Guard the load with a local “loaded” flag.

Apply this diff:

 const container = createContainer();

 export function getInstantBookingCreateService(): InstantBookingCreateService {
-  instantBookingCreateServiceModule.loadModule(container);
+  // Ensure we only bind once per process
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  const anyContainer = container as any;
+  anyContainer.__instantBookingCreateServiceLoaded ||= false;
+  if (!anyContainer.__instantBookingCreateServiceLoaded) {
+    instantBookingCreateServiceModule.loadModule(container);
+    anyContainer.__instantBookingCreateServiceLoaded = true;
+  }
   return container.get<InstantBookingCreateService>(instantBookingCreateServiceModule.token);
 }
apps/web/pages/api/book/instant-event.ts (1)

23-28: Consider validating req.body here before passing to the service.

You noted the TODO; moving runtime validation to the handler (Zod schema) will let createBooking drop internal validation later and remove any from req.body.

I can wire a lightweight Zod schema here and type req.body to CreateInstantBookingInput_2024_08_13. Want me to draft it?

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (4)

501-513: Include noEmail in bookingMeta for seated recurring bookings for parity

Other flows pass noEmail; seated recurring does not. This can cause inconsistent email behavior.

Apply this diff:

       bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },

525-538: Include noEmail in bookingMeta for regular bookings

Keep email behavior consistent across flows.

Apply this diff:

       bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },

560-571: Include noEmail in bookingMeta for seated bookings

Align with other create flows.

Apply this diff:

         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          noEmail: bookingRequest.noEmail,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },

757-769: Include noEmail in bookingMeta for reschedule

Parities reschedule with create flows.

Apply this diff:

       bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },
packages/features/bookings/lib/handleNewRecurringBooking.ts (3)

92-97: Use strict equality for slot index checks

-      isFirstRecurringSlot: key == 0,
+      isFirstRecurringSlot: key === 0,

27-27: Refine type of thirdPartyRecurringEventId

-  let thirdPartyRecurringEventId = null;
+  let thirdPartyRecurringEventId: string | null = null;

100-111: Inline await instead of intermediate promise variable

-    const promiseEachRecurringBooking = regularBookingService.createBooking({
-      bookingData: recurringEventData,
-      bookingMeta: {
-        hostname: input.hostname || "",
-        forcedSlug: input.forcedSlug as string | undefined,
-        ...handleBookingMeta,
-      },
-    });
-
-    const eachRecurringBooking = await promiseEachRecurringBooking;
+    const eachRecurringBooking = await regularBookingService.createBooking({
+      bookingData: recurringEventData,
+      bookingMeta: {
+        hostname: input.hostname || "",
+        forcedSlug: input.forcedSlug as string | undefined,
+        ...handleBookingMeta,
+      },
+    });
packages/features/instant-meeting/handleInstantMeeting.ts (1)

303-311: Review webhook payload for PII exposure

Sending raw responses and customInputs to webhooks can include PII, unlike the restricted booking DTOs used elsewhere. If consumers don’t need these full structures, wrap this event in a constrained DTO.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5171538 and 0680f44.

📒 Files selected for processing (36)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (5 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (20)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/bookings/lib/index.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/web/pages/api/book/event.ts
  • packages/platform/libraries/bookings.ts
  • packages/features/bookings/types.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧠 Learnings (22)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/web/pages/api/book/instant-event.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-08T10:07:30.026Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/larkcalendar/api/callback.ts:109-117
Timestamp: 2025-09-08T10:07:30.026Z
Learning: In office365calendar and zohocalendar callback handlers, vijayraghav-io chose to manually call BookingReferenceRepository.reconnectWithNewCredential() after credential creation instead of using SelectedCalendarRepository.upsert(), to avoid disturbing existing error handling logic in catch blocks while still ensuring booking reference reconnection happens.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-09-23T08:00:07.590Z
Learnt from: hariombalhara
PR: calcom/cal.com#23918
File: packages/features/schedules/lib/use-schedule/useTimesForSchedule.test.ts:16-23
Timestamp: 2025-09-23T08:00:07.590Z
Learning: In calcom/cal.com test files, particularly packages/features/schedules/lib/use-schedule/useTimesForSchedule.test.ts, the TIMEZONE_OFFSETS mapping is intentionally limited to only UTC variants and Asia/Kolkata. This is by design and should not be flagged as incomplete in future reviews (confirmed by maintainer hariombalhara).

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-18T13:38:50.936Z
Learnt from: hariombalhara
PR: calcom/cal.com#23913
File: packages/features/bookings/Booker/components/hooks/usePrefetch.ts:43-50
Timestamp: 2025-09-18T13:38:50.936Z
Learning: In usePrefetch hook in packages/features/bookings/Booker/components/hooks/usePrefetch.ts, the !isNaN() checks before comparing monthAfterAdding1Month !== monthAfterAddingExtraDaysColumnView are intentional to prevent the NaN !== NaN issue where NaN values would incorrectly be considered different, leading to wrong monthCount calculations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T07:15:58.056Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.056Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
🧬 Code graph analysis (14)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (2)
  • InstantBookingCreateService (18-18)
  • instantBookingCreateServiceModule (7-7)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (3)
packages/lib/di/di.ts (1)
  • createContainer (114-114)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)
  • RecurringBookingService (26-26)
  • recurringBookingServiceModule (10-10)
apps/web/pages/api/book/instant-event.ts (1)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (2)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (54-54)
packages/platform/types/api.ts (1)
  • ApiSuccessResponse (8-8)
packages/features/bookings/lib/handleNewRecurringBooking.ts (3)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/instant-meeting/handleInstantMeeting.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateInstantBookingData (17-17)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/interfaces/IBookingCreateService.ts (1)
  • IBookingCreateService (4-7)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (2)
packages/features/bookings/lib/dto/types.d.ts (1)
  • BookingHandlerInput (40-42)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • moduleLoader (42-45)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/dto/types.d.ts (2)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
apps/api/v1/pages/api/bookings/_post.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/features/bookings/lib/handleNewBooking.ts (5)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1046)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (32-38)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Linters / lint
  • GitHub Check: Production builds / Build API v1
  • GitHub Check: Tests / Unit
  • GitHub Check: Production builds / Build Web App
  • GitHub Check: Production builds / Build Docs
  • GitHub Check: Production builds / Build Atoms
  • GitHub Check: Production builds / Build API v2
  • GitHub Check: Type check / check-types
🔇 Additional comments (45)
apps/api/v1/pages/api/bookings/_post.ts (2)

4-4: Good DI migration to RegularBookingService.

This aligns with the container/moduleLoader pattern and decouples the route from legacy handlers.


242-252: Fix unsafe header cast for x-cal-force-slug (can be string[]).

Normalize the header to a string to avoid leaking a string[] at runtime. This was flagged previously; proposing a concrete inline fix.

Apply this diff:

-    return await regularBookingService.createBookingForApiV1({
+    const forcedSlugHeader = req.headers["x-cal-force-slug"];
+    const forcedSlug = Array.isArray(forcedSlugHeader) ? forcedSlugHeader[0] : forcedSlugHeader;
+
+    return await regularBookingService.createBookingForApiV1({
       bookingData: req.body,
       bookingMeta: {
         userId,
         hostname: req.headers.host || "",
-        forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
+        forcedSlug,
       },
       bookingDataSchemaGetter: getBookingDataSchemaForApi,
     });
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (5)

24-24: Good switch to a type‑only import

Prevents runtime coupling and avoids circular dep risks. Looks correct.


44-44: Typing createdBooking to the public result type is appropriate

Keeps tests aligned with the new service contract.


233-233: Same alias refactor as above applies here

Replace the verbose generic with the local alias.


290-290: Same alias refactor as above applies here

Replace the verbose generic with the local alias.


387-387: Same alias refactor as above applies here

Replace the verbose generic with the local alias.

packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)

4-5: LGTM on moduleLoader usage

Switch to moduleLoader/token is consistent with the new DI pattern.

apps/web/pages/api/book/instant-event.ts (1)

5-5: LGTM: using DI container for instant bookings

Importing getInstantBookingCreateService aligns this route with the service-based flow.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (4)

9-11: LGTM: injected booking services

Service imports are correct and match the refactor direction.


111-115: LGTM: Nest DI for new services

Constructor injection follows Nest standards and addresses prior feedback to rely on native DI.


455-458: LGTM: instant booking via service

createInstantBooking delegates correctly to instantBookingCreateService.


476-489: LGTM: recurring booking passes full bookingMeta (incl. noEmail)

Parity looks good here.

packages/features/bookings/lib/handleNewBooking.ts (9)

14-17: LGTM: metadata schema import

Using eventTypeMetaDataSchemaWithTypedApps is correct here.


24-28: LGTM: explicit DTO/type imports

Clearer type surface; matches the refactor direction.


428-432: LGTM: handler now receives deps explicitly

Signature change is sound and keeps default schema getter.


446-452: LGTM: minimal deps destructuring

Only what’s needed is destructured; the rest remain available via deps when needed.


555-556: Guarded recurring-slot check is correct

Using !! for isFirstRecurringSlot avoids falsy pitfalls after adding proper types.


789-793: Safe gating for multi-slot availability checks

All guards present before entering the loop.


2425-2431: Fix: spreading possibly undefined bookingMeta throws

Spreading undefined crashes. Default bookingMeta to {} as done in createBookingForApiV1.

Apply this diff:

   async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }

   async rescheduleBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }

1607-1613: Fix: possible crash accessing bookingData.responses; use bookerEmail/phone

bookingData.responses can be undefined; currentAttendee lookup should rely on already-parsed bookerEmail/bookerPhoneNumber.

Apply this diff:

-      if (booking && booking.id && eventType.seatsPerTimeSlot) {
-        const currentAttendee = booking.attendees.find(
-          (attendee) =>
-            attendee.email === bookingData.responses.email ||
-            (bookingData.responses.attendeePhoneNumber &&
-              attendee.phoneNumber === bookingData.responses.attendeePhoneNumber)
-        );
+      if (booking && booking.id && eventType.seatsPerTimeSlot) {
+        const currentAttendee = booking.attendees.find(
+          (attendee) =>
+            attendee.email === bookerEmail ||
+            (bookerPhoneNumber && attendee.phoneNumber === bookerPhoneNumber)
+        );

414-426: Resolved — DI module binds all IBookingServiceDependencies keys

RegularBookingService.module.ts's depsMap provides bindings for every property in IBookingServiceDependencies (see packages/lib/di/bookings/modules/RegularBookingService.module.ts).

packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)

12-20: LGTM: moduleLoader with depsMap (regularBookingService) wired correctly

Binding RecurringBookingService via bindModuleToClassOnToken with regularBookingService dependency matches the constructor.


22-25: LGTM: exported moduleLoader surface

token + loadModule exported in the standard pattern.

packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1)

4-13: Service-based test handler: LGTM

Typed input, DI lookup, and bookingMeta destructuring look correct.

packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (3)

26-26: Switched to DI getter for recurring bookings: LGTM

Using getRecurringBookingService() aligns tests with the service flow.


155-162: Service invocation with bookingMeta: LGTM

Correct payload shape: bookingData array + bookingMeta.userId.


376-383: Fix async rejection assertion and bookingMeta shape

  • Use expect(promise).rejects, not expect(() => promise).rejects.
  • Pass userId inside bookingMeta.

Apply:

-      await expect(
-        async () =>
-          await recurringBookingService.createBooking({
-            bookingData: bookingDataArray,
-            userId: -1,
-          })
-      ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);
+      await expect(
+        recurringBookingService.createBooking({
+          bookingData: bookingDataArray,
+          bookingMeta: { userId: -1 },
+        })
+      ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);

Also ensure ErrorCode is imported at the top:
import { ErrorCode } from "@calcom/lib/errorCodes";

packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)

9-13: Module loader-based DI container: LGTM

Idempotent load + token-based get are consistent with the new pattern.

packages/features/bookings/lib/bookingCreateBodySchema.ts (3)

60-76: Recurring booking partial schema: LGTM

Optional end in allRecurringDates matches handler expectations.


78-98: Extended schema merge: LGTM

Separation of recurring fields into a partial keeps the base schema clean.


100-101: Exported ExtendedBookingCreateBody type: LGTM

apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6)

10-12: Import DI-backed booking services: LGTM


114-117: Constructor DI for services: LGTM


194-207: Regular booking via service with bookingMeta: LGTM

Forwarded hostname, forcedSlug, and platform params correctly.


324-335: Recurring booking via service: LGTM

Correctly passes bookingData array and platform/user metadata.


362-362: Instant booking response type update: LGTM


367-371: Instant booking via service with body-only input: LGTM

packages/features/bookings/lib/dto/types.d.ts (2)

19-22: CreateRecurringBookingData shape: LGTM

Array type with optional SchedulingType aligns with handler expectations.


44-51: InstantBookingCreateResult: LGTM

Types match existing behavior; no changes needed here.

packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

57-66: Round-robin: first slot not returned and series ID not propagated

You create the first slot but don’t push it to results or seed thirdPartyRecurringEventId. This returns N-1 items and may break series linkage.

Apply:

     const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-    luckyUsers = firstBookingResult.luckyUsers;
+    createdBookings.push(firstBookingResult);
+    if (!thirdPartyRecurringEventId && firstBookingResult.references?.length) {
+      for (const ref of firstBookingResult.references) {
+        if (ref.thirdPartyRecurringEventId) {
+          thirdPartyRecurringEventId = ref.thirdPartyRecurringEventId;
+          break;
+        }
+      }
+    }
+    luckyUsers = firstBookingResult.luckyUsers;
packages/features/instant-meeting/handleInstantMeeting.ts (4)

158-158: Typed input LGTM

Switch to typed bookingData: CreateInstantBookingData is correct and aligns with DI-based services.


332-333: Return shape checked with satisfies — good

Ensures the response conforms to InstantBookingCreateResult at compile time.


339-341: Service method signature LGTM

createBooking(input: { bookingData }) returning InstantBookingCreateResult aligns with IBookingCreateService usage.


243-246: No change needed — "integrations:daily" is the canonical Cal Video location

The codebase maps "cal-video" ↔ "integrations:daily" (e.g. packages/app-store/constants.ts DailyLocationType, apps/api/v2/.../transformers internal/locations.ts), so using location: "integrations:daily" is correct.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/features/instant-meeting/handleInstantMeeting.ts (2)

81-86: Avoid logging webhook secrets

console.error(..., sub, ...) prints sub.secret. Don’t log secrets.

-      }).catch((e) => {
-        console.error(
-          `Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}`,
-          sub,
-          e
-        );
-      });
+      }).catch((e) => {
+        console.error(
+          `Error executing webhook for event: ${eventTrigger}, URL: ${sub.subscriberUrl}, id: ${sub.id}`,
+          e
+        );
+      });

259-263: Use select instead of include and return only needed fields

No code later uses attendees. Follow our Prisma guideline: select only what you need.

-  const createBookingObj = {
-    include: {
-      attendees: true,
-    },
-    data: newBookingData,
-  };
+  const createBookingObj = {
+    select: {
+      id: true,
+      uid: true,
+      userId: true,
+      responses: true,
+      customInputs: true,
+    },
+    data: newBookingData,
+  };
apps/web/pages/api/book/event.ts (1)

27-33: Return 401 when unauthenticated; don’t proceed with userId: -1

Continuing with a sentinel ID risks confusing downstream behavior.

   const session = await getServerSession({ req });
   /* To mimic API behavior and comply with types */
   req.body = {
     ...req.body,
     creationSource: CreationSource.WEBAPP,
   };
+  if (!session?.user?.id) {
+    throw new Error("Unauthorized");
+  }
🧹 Nitpick comments (7)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

25-25: Prefer using provided availability check count (when present)

Hardcoding 1 ignores client-provided intent. Derive from input with a sane default.

-const numSlotsToCheckForAvailability = 1;
+const numSlotsToCheckForAvailability =
+  (Array.isArray(input.bookingData) && input.bookingData[0]?.numSlotsToCheckForAvailability) ?? 1;
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)

324-335: Parity: pass areCalendarEventsEnabled to recurring bookings too

Regular bookings receive this flag; recurring path omits it. If this difference isn’t intentional, add it for consistency.

       const createdBookings: BookingResponse[] = await this.recurringBookingService.createBooking({
         bookingData: bookingRequest.body,
         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },
       });

If divergence is intentional, consider adding a brief comment to prevent future regressions.

packages/features/bookings/lib/dto/types.d.ts (1)

53-54: Define explicit RegularBookingCreateResult type (or confirm deferral)

createBooking is implemented at packages/features/bookings/lib/handleNewBooking.ts and currently has no explicit return annotation, so RegularBookingCreateResult is inferred (currently: export type RegularBookingCreateResult = Awaited<ReturnType<RegularBookingService['createBooking']>>;). Because BookingResponse is widely consumed, either: define an explicit DTO in packages/features/bookings/lib/dto/types.d.ts, or keep the inference but remove the TODO and add a short comment justifying why inference is acceptable.

packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)

22-25: Optional: Type the moduleLoader for better DX

Annotating moduleLoader with a ModuleLoader type can improve IntelliSense and guard against shape drift.

-export const moduleLoader = {
+export const moduleLoader /* : ModuleLoader */ = {
   token,
   loadModule,
 };

1-1: Minimize eslint escape hatch

If feasible, remove the no-restricted-imports override once the public import surface stabilizes or add a TODO so it’s not forgotten.

packages/lib/di/bookings/containers/RecurringBookingService.container.ts (2)

4-12: Use a clearer alias and allow passing a custom container

  • Rename the alias to recurringBookingServiceModuleLoader for clarity/consistency with other modules.
  • Allow an optional container param for testability and composability; default to a shared container.
 import { createContainer } from "../../di";
 import {
   type RecurringBookingService,
-  moduleLoader as recurringBookingServiceModule,
+  moduleLoader as recurringBookingServiceModuleLoader,
 } from "../modules/RecurringBookingService.module";

-const container = createContainer();
+const defaultContainer = createContainer();

-export function getRecurringBookingService(): RecurringBookingService {
-  recurringBookingServiceModule.loadModule(container);
-
-  return container.get<RecurringBookingService>(recurringBookingServiceModule.token);
+export function getRecurringBookingService(container = defaultContainer): RecurringBookingService {
+  recurringBookingServiceModuleLoader.loadModule(container);
+  return container.get<RecurringBookingService>(recurringBookingServiceModuleLoader.token);
 }

10-12: Confirm container.load behavior / guard repeated loads

container.load (from @evyweb/ioctopus) allows repeated loads and rebinds bindings ("last loaded wins") — it won't throw. recurringBookingServiceModule.loadModule(container) (packages/lib/di/bookings/containers/RecurringBookingService.container.ts:10) calls container.load via bindModuleToClassOnToken (packages/lib/di/di.ts:101–112). If you need true idempotency or to avoid stale cached instances, guard the loader or call container.unload before reloading.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0680f44 and a04e401.

📒 Files selected for processing (36)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (5 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (23)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • apps/web/lib/types/booking.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/platform/libraries/bookings.ts
  • packages/features/bookings/lib/index.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/web/pages/api/book/recurring-event.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/features/bookings/types.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/features/bookings/types.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/features/bookings/types.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧠 Learnings (20)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/features/bookings/types.ts
  • apps/web/pages/api/book/event.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/dto/types.d.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
📚 Learning: 2025-09-18T13:38:50.936Z
Learnt from: hariombalhara
PR: calcom/cal.com#23913
File: packages/features/bookings/Booker/components/hooks/usePrefetch.ts:43-50
Timestamp: 2025-09-18T13:38:50.936Z
Learning: In usePrefetch hook in packages/features/bookings/Booker/components/hooks/usePrefetch.ts, the !isNaN() checks before comparing monthAfterAdding1Month !== monthAfterAddingExtraDaysColumnView are intentional to prevent the NaN !== NaN issue where NaN values would incorrectly be considered different, leading to wrong monthCount calculations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-12T07:15:58.056Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.056Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
🧬 Code graph analysis (11)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • moduleLoader (42-45)
packages/features/bookings/types.ts (2)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (54-54)
apps/web/pages/api/book/event.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (2)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)
  • RecurringBookingService (26-26)
  • recurringBookingServiceModule (10-10)
packages/features/bookings/lib/handleNewBooking.ts (5)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1046)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (4)
  • BookingHandlerInput (40-42)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (32-38)
  • BookingDataSchemaGetter (13-13)
apps/web/pages/api/book/instant-event.ts (1)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (3)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/platform/libraries/bookings.ts (3)
  • InstantBookingCreateResult (9-9)
  • RegularBookingCreateResult (10-10)
  • RegularBookingService (5-5)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/instant-meeting/handleInstantMeeting.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateInstantBookingData (17-17)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/interfaces/IBookingCreateService.ts (1)
  • IBookingCreateService (4-7)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (24)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8)

9-11: Verify Nest provider wiring for new services

Ensure InstantBookingCreateService, RecurringBookingService, and RegularBookingService are registered as providers in the corresponding module (bookings.module.ts) so Nest can inject them here.


111-115: LGTM: constructor DI for booking services

Constructor-based Nest DI aligns with api-v2 guidelines.


456-458: LGTM: Instant bookings routed via service

Correctly delegates to InstantBookingCreateService.createBooking with bookingData only.


476-489: LGTM: Recurring bookings pass bookingMeta (incl. noEmail)

Good shape and fields forwarded.


526-538: Include noEmail in bookingMeta for regular bookings; consider DRY helper

Regular flow currently omits noEmail, diverging from recurring flow. This can trigger emails despite client intent.

Apply this diff:

       bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },

Optional: extract a private buildBookingMeta(bookingRequest) to avoid drift across flows.
(centralization was suggested earlier)


560-571: Include noEmail in bookingMeta for seated regular bookings

Same inconsistency: seated regular bookings omit noEmail, risking unintended notifications.

Apply this diff:

         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          noEmail: bookingRequest.noEmail,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },

501-513: Include noEmail in bookingMeta for seated recurring bookings

noEmail is passed for non-seated recurring bookings (Lines 476-489) but omitted here. This inconsistency can cause unintended emails in seated recurring flows.

Apply this diff:

       bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },

757-769: Use rescheduleBooking API and include noEmail in bookingMeta

  • Semantics/readability: prefer RegularBookingService.rescheduleBooking over createBooking during reschedule.
  • Behavior: noEmail omitted here; reschedules may send emails unexpectedly.

Apply this diff:

-      const booking = await this.regularBookingService.createBooking({
+      const booking = await this.regularBookingService.rescheduleBooking({
         bookingData: bookingRequest.body,
         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          noEmail: bookingRequest.noEmail,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },
       });
apps/web/pages/api/book/instant-event.ts (1)

23-28: LGTM: moved to service and kept runtime validation in service

Service retrieval and call shape look correct; creationSource set before call is good.

If we want parity with event booking’s CF Turnstile gate, confirm whether instant bookings should also enforce it.

packages/features/bookings/types.ts (1)

97-99: LGTM: unify BookingResponse to service result type

Alias to RegularBookingCreateResult simplifies typings without behavior change.

packages/features/bookings/lib/bookingCreateBodySchema.ts (3)

60-76: Good extraction of recurring fields into a partial schema

Clearer separation of concerns; optionality aligns with current shared schema usage.


78-98: LGTM: merged top-level extras with recurring partial

The merge keeps existing callers working while paving way for specialized schemas later.


100-101: Nice: exported input type for Extended schema

Improves reuse across DTOs and services.

packages/features/bookings/lib/handleNewBooking.ts (1)

1609-1613: Bug: attendee lookup uses possibly undefined bookingData.responses

Use the already parsed bookerEmail/bookerPhoneNumber. Current code can dereference undefined and fail to match the correct attendee.

-        const currentAttendee = booking.attendees.find(
-          (attendee) =>
-            attendee.email === bookingData.responses.email ||
-            (bookingData.responses.attendeePhoneNumber &&
-              attendee.phoneNumber === bookingData.responses.attendeePhoneNumber)
-        );
+        const currentAttendee = booking.attendees.find(
+          (attendee) =>
+            attendee.email === bookerEmail ||
+            (bookerPhoneNumber && attendee.phoneNumber === bookerPhoneNumber)
+        );
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

57-66: First RR booking result is dropped and series ID not propagated

You await the first result but never push it, and you don't seed thirdPartyRecurringEventId for later slots. This returns N-1 results and can break third‑party series linkage.

Apply:

     const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-    luckyUsers = firstBookingResult.luckyUsers;
+    // include first slot and propagate series id for subsequent slots
+    createdBookings.push(firstBookingResult);
+    if (!thirdPartyRecurringEventId && firstBookingResult.references?.length) {
+      const ref = firstBookingResult.references.find((r) => r.thirdPartyRecurringEventId);
+      if (ref?.thirdPartyRecurringEventId) {
+        thirdPartyRecurringEventId = ref.thirdPartyRecurringEventId;
+      }
+    }
+    luckyUsers = firstBookingResult.luckyUsers;
packages/features/bookings/lib/dto/types.d.ts (6)

2-3: LGTM! Descriptive comment clarifies the purpose.

The added comment effectively explains that these are framework-agnostic domain types for booking operations.


7-10: LGTM! Imports are properly aligned with usage.

The new imports for SchedulingType, ExtendedBookingCreateBody, and RegularBookingService are correctly sourced and align with their usage in the type definitions.


12-12: LGTM! Consistent with named export preference.

Converting BookingCreateBody to a type-only export aligns with the coding guidelines that encourage named exports over default exports.


15-21: LGTM! Type unification improves consistency.

The migration from BaseCreateBookingData to ExtendedBookingCreateBody provides better type consistency across the booking services. The addition of schedulingType?: SchedulingType to CreateRecurringBookingData is logically sound for recurring booking scenarios.


23-42: LGTM! Well-structured metadata types.

The new type definitions (PlatformParams, CreateBookingMeta, BookingHandlerInput) provide clear separation of concerns and improve type safety for booking operations. The structure is logical and the field purposes are evident.


44-51: LGTM! Type rename improves clarity.

The rename from CreateInstantBookingResponse to InstantBookingCreateResult follows a consistent naming pattern and better reflects the nature of the type as a result rather than a response. The field types remain appropriate.

packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)

12-20: Good migration to moduleLoader with explicit deps map

The DI wiring via bindModuleToClassOnToken and the dependency on RegularBookingService through depsMap looks correct and consistent with the new pattern.


8-9: DI tokens present and unique — no conflicts found
RECURRING_BOOKING_SERVICE and RECURRING_BOOKING_SERVICE_MODULE are defined in packages/lib/di/bookings/tokens.ts and only referenced in packages/lib/di/bookings/modules/RecurringBookingService.module.ts; no other definitions or collisions found.


17-19: Verified — depsMap keys match IRecurringBookingServiceDependencies

IRecurringBookingServiceDependencies declares regularBookingService (packages/features/bookings/lib/handleNewRecurringBooking.ts:127-129), which matches the depsMap entry in RecurringBookingService.module.ts; no changes required.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)

376-383: Update skipped test to use the new service contract

RecurringBookingService.createBooking no longer accepts userId at the top level. Passing it here causes a TS compile error, and wrapping the async call in a function means the rejection assertion never runs. Inline the promise and move userId under bookingMeta.

-          const recurringBookingService = getRecurringBookingService();
-          await expect(
-            async () =>
-              await recurringBookingService.createBooking({
-                bookingData: bookingDataArray,
-                userId: -1,
-              })
-          ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);
+          const recurringBookingService = getRecurringBookingService();
+          await expect(
+            recurringBookingService.createBooking({
+              bookingData: bookingDataArray,
+              bookingMeta: {
+                userId: -1,
+              },
+            })
+          ).rejects.toThrow(ErrorCode.NoAvailableUsersFound);
packages/features/instant-meeting/handleInstantMeeting.ts (1)

158-169: Guard null eventType before property access.

getEventTypesFromDB can return null; spreading or accessing .team would throw.

Apply:

 async function handler(bookingData: CreateInstantBookingData) {
-  let eventType = await getEventTypesFromDB(bookingData.eventTypeId);
+  let eventType = await getEventTypesFromDB(bookingData.eventTypeId);
+  if (!eventType) {
+    throw new Error("Event type not found");
+  }
   const isOrgTeamEvent = !!eventType?.team && !!eventType?.team?.parentId;
   eventType = {
     ...eventType,
     bookingFields: getBookingFieldsWithSystemFields({ ...eventType, isOrgTeamEvent }),
   };
 
-  if (!eventType.team?.id) {
+  if (!eventType.team?.id) {
     throw new Error("Only Team Event Types are supported for Instant Meeting");
   }
🧹 Nitpick comments (8)
apps/api/v2/src/lib/modules/instant-booking.module.ts (1)

1-1: Consider using named import for better tree-shaking.

Using relative imports with default exports can hurt tree-shaking. Consider using a named export from the service file. As per coding guidelines

-import { InstantBookingCreateService } from "@/lib/services/instant-booking-create.service";
+import { InstantBookingCreateService } from "@/lib/services/instant-booking-create.service";

(Note: This assumes the service file exports InstantBookingCreateService as a named export)

packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)

9-13: Make module load idempotent to avoid repeated bindings.

Guard loadModule so it runs once per process.

Apply:

 const container = createContainer();
 
 export function getRecurringBookingService(): RecurringBookingService {
-  recurringBookingServiceModule.loadModule(container);
-
-  return container.get<RecurringBookingService>(recurringBookingServiceModule.token);
+  // Load once
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
+  const loaded = (container as any).__recurringBookingLoaded as boolean | undefined;
+  if (!loaded) {
+    recurringBookingServiceModule.loadModule(container);
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+    (container as any).__recurringBookingLoaded = true;
+  }
+  return container.get<RecurringBookingService>(recurringBookingServiceModule.token);
 }
packages/features/instant-meeting/handleInstantMeeting.ts (1)

259-263: Use Prisma select over include to limit data fetched.

Replace include: { attendees: true } with a minimal select set.

As per coding guidelines:

-  const createBookingObj = {
-    include: {
-      attendees: true,
-    },
-    data: newBookingData,
-  };
+  const createBookingObj = {
+    select: {
+      id: true,
+      uid: true,
+      userId: true,
+      responses: true,
+      customInputs: true,
+      metadata: true,
+      // add other fields only if used below
+    },
+    data: newBookingData,
+  };

As per coding guidelines

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (2)

476-489: BookingMeta consistency: add noEmail where missing.

noEmail is passed for recurring (non-seated) but omitted in other flows. For consistent behavior, include it everywhere if available in bookingRequest.

Apply:

@@ createRecurringBooking
       bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
         noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },
@@ createRecurringSeatedBooking
-      bookingMeta: {
+      bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },
@@ createRegularBooking
-      bookingMeta: {
+      bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },
@@ createSeatedBooking
-        bookingMeta: {
+        bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          noEmail: bookingRequest.noEmail,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },
@@ rescheduleBooking
-        bookingMeta: {
+        bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          noEmail: bookingRequest.noEmail,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },

If this is intentionally omitted for some flows, please confirm and point to tests or specs; otherwise the above keeps behavior aligned.

Also applies to: 501-513, 526-538, 560-572, 757-769


520-539: Optional: centralize bookingMeta construction.

Extract a private helper (e.g., buildBookingMeta(bookingRequest)) to avoid drift across flows.

apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)

194-206: Consider propagating noEmail via bookingMeta for consistency

If the handler reads noEmail as a top-level flag (not from bookingData), add it to bookingMeta to avoid divergence with other entry points.

Proposed change:

       const booking = await this.regularBookingService.createBooking({
         bookingData: bookingRequest.body,
         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           forcedSlug: orgSlug,
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
+          noEmail: !bookingRequest.arePlatformEmailsEnabled,
         },
       });
packages/features/bookings/lib/dto/types.d.ts (2)

9-11: Avoid coupling DTOs to service implementations

Having RegularBookingCreateResult depend on RegularBookingService["createBooking"] ties DTOs to implementation and risks cycles. Prefer a stable, explicit result type exported alongside BookingResponse (or define a dedicated DTO here).

Follow-up: define RegularBookingCreateResult as an explicit interface/type independent of the service signature, then have the service use that type. Based on learnings


53-55: Minor: fix TODO wording and consider defining explicit type

Grammar nit and a reminder to avoid inferring from service signatures.

Proposed change:

-// TODO: In a followup PR, we working on defining the type here itself instead of inferring it.
+// TODO: In a follow-up PR, we're working on defining this type here instead of inferring it.
 export type RegularBookingCreateResult = Awaited<ReturnType<RegularBookingService["createBooking"]>>;
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a04e401 and 5ff4ae2.

📒 Files selected for processing (36)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (2 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (10 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (5 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts (1 hunks)
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1 hunks)
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts (2 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • apps/web/pages/api/book/event.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • packages/features/bookings/lib/index.ts
  • packages/platform/libraries/bookings.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/types.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/web/pages/api/book/recurring-event.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/types.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/web/pages/api/book/recurring-event.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/types.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/web/pages/api/book/recurring-event.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
🧠 Learnings (24)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/lib/di/bookings/containers/RegularBookingService.container.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/features/bookings/types.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
  • packages/lib/di/bookings/modules/RecurringBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/web/pages/api/book/recurring-event.ts
📚 Learning: 2025-09-09T08:58:55.970Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/lib/di/containers/InsightsBooking.ts:10-12
Timestamp: 2025-09-09T08:58:55.970Z
Learning: The moduleLoader pattern is being implemented incrementally, focusing only on modules that are directly or indirectly used by Booking modules. Other modules like InsightsBooking are intentionally excluded from this migration phase.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/lib/di/bookings/modules/RegularBookingService.module.ts
  • packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/lib/di/bookings/containers/RecurringBookingService.container.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-27T12:15:43.830Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/testCall.handler.ts:41-44
Timestamp: 2025-08-27T12:15:43.830Z
Learning: In calcom/cal.com, the AgentService.getAgent() method in packages/features/calAIPhone/providers/retellAI/services/AgentService.ts does NOT include authorization checks - it only validates the agentId parameter and directly calls the repository without verifying user/team access. This contrasts with other methods like getAgentWithDetails() which properly use findByIdWithUserAccessAndDetails() for authorization. When reviewing updateToolsFromAgentId() calls, always verify both agent ownership and eventType ownership are checked.

Applied to files:

  • apps/web/lib/types/booking.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-07-15T12:59:34.389Z
Learnt from: eunjae-lee
PR: calcom/cal.com#22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

Applied to files:

  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-08T09:29:11.681Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts:118-143
Timestamp: 2025-08-08T09:29:11.681Z
Learning: In calcom/cal.com PR #22919, packages/features/calAIPhone/interfaces/AIPhoneService.interface.ts (TypeScript), the AIPhoneServiceAgentListItem is required to include user.email in listAgents responses (per maintainer Udit-takkar). Future reviews should not flag this as unnecessary PII unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-08T09:27:23.896Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22919
File: packages/features/calAIPhone/providers/retellAI/services/AgentService.ts:195-216
Timestamp: 2025-08-08T09:27:23.896Z
Learning: In PR calcom/cal.com#22919, file packages/features/calAIPhone/providers/retellAI/services/AgentService.ts, the updateAgentConfiguration method intentionally does not persist the optional `name` parameter to the repository for now, per maintainer (Udit-takkar). Future reviews should not flag this unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-08T07:27:42.903Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/feishucalendar/api/callback.ts:72-79
Timestamp: 2025-09-08T07:27:42.903Z
Learning: Four calendar integrations in Cal.com still use direct prisma.selectedCalendar.create instead of SelectedCalendarRepository.create: feishucalendar, zohocalendar, office365calendar, and larkcalendar. These bypass repository hooks and won't trigger reconnection logic for BookingReferences.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-14T10:48:52.586Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/ai/_router.ts:46-84
Timestamp: 2025-08-14T10:48:52.586Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/ai/_router.ts, the voiceId input parameter in the create endpoint is intentionally not forwarded to aiService.createAgent() as voice customization is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-09-18T13:38:50.958Z
Learnt from: hariombalhara
PR: calcom/cal.com#23913
File: packages/features/bookings/Booker/components/hooks/usePrefetch.ts:43-50
Timestamp: 2025-09-18T13:38:50.958Z
Learning: In usePrefetch hook in packages/features/bookings/Booker/components/hooks/usePrefetch.ts, the !isNaN() checks before comparing monthAfterAdding1Month !== monthAfterAddingExtraDaysColumnView are intentional to prevent the NaN !== NaN issue where NaN values would incorrectly be considered different, leading to wrong monthCount calculations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In BookingPaymentInitiatedDTO and other webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking field is a restricted structure containing only specific fields (id, eventTypeId, userId) rather than the full database booking object, so there are no security or PII leakage concerns when passing the booking object to buildEventPayload.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
📚 Learning: 2025-09-12T07:15:58.056Z
Learnt from: hbjORbj
PR: calcom/cal.com#23475
File: packages/features/credentials/handleDeleteCredential.ts:5-10
Timestamp: 2025-09-12T07:15:58.056Z
Learning: When EventTypeAppMetadataSchema is used only in z.infer<typeof EventTypeAppMetadataSchema> type annotations or type casts, it can be imported as a type-only import since this usage is purely at the TypeScript type level and doesn't require the runtime value.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma select uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-09-03T11:54:05.409Z
Learnt from: supalarry
PR: calcom/cal.com#23514
File: apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts:579-582
Timestamp: 2025-09-03T11:54:05.409Z
Learning: In calcom/cal.com bookings repository methods, when Prisma include uses `eventType: true`, all eventType fields including seatsShowAttendees are automatically included in the selection. Explicit field selection is not required when using `true` for nested relations.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-21T12:28:42.018Z
Learnt from: alishaz-polymath
PR: calcom/cal.com#23247
File: packages/features/webhooks/lib/factory/WebhookPayloadFactory.ts:274-282
Timestamp: 2025-08-21T12:28:42.018Z
Learning: In webhook DTOs in packages/features/webhooks/lib/dto/types.ts, the booking fields are restricted structures containing only specific fields (id, eventTypeId, userId, and sometimes additional fields like startTime or smsReminderNumber) rather than full database booking objects, so there are no security or PII leakage concerns when using these booking objects in webhook payloads.

Applied to files:

  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-09-18T08:50:49.925Z
Learnt from: eunjae-lee
PR: calcom/cal.com#23752
File: packages/lib/server/service/InsightsBookingBaseService.ts:340-371
Timestamp: 2025-09-18T08:50:49.925Z
Learning: In the InsightsBookingBaseService (packages/lib/server/service/InsightsBookingBaseService.ts), the startTime date range filter intentionally uses different fields for the lower and upper bounds: `startDate <= "startTime" AND "endTime" <= endDate`. This ensures bookings start within the selected range but don't extend beyond the end date, which is the intended business logic and not an inconsistency.

Applied to files:

  • packages/features/bookings/lib/create-instant-booking.ts
📚 Learning: 2025-09-08T10:07:30.026Z
Learnt from: vijayraghav-io
PR: calcom/cal.com#16878
File: packages/app-store/larkcalendar/api/callback.ts:109-117
Timestamp: 2025-09-08T10:07:30.026Z
Learning: In office365calendar and zohocalendar callback handlers, vijayraghav-io chose to manually call BookingReferenceRepository.reconnectWithNewCredential() after credential creation instead of using SelectedCalendarRepository.upsert(), to avoid disturbing existing error handling logic in catch blocks while still ensuring booking reference reconnection happens.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-09-23T08:00:07.619Z
Learnt from: hariombalhara
PR: calcom/cal.com#23918
File: packages/features/schedules/lib/use-schedule/useTimesForSchedule.test.ts:16-23
Timestamp: 2025-09-23T08:00:07.619Z
Learning: In calcom/cal.com test files, particularly packages/features/schedules/lib/use-schedule/useTimesForSchedule.test.ts, the TIMEZONE_OFFSETS mapping is intentionally limited to only UTC variants and Asia/Kolkata. This is by design and should not be flagged as incomplete in future reviews (confirmed by maintainer hariombalhara).

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
🧬 Code graph analysis (24)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (2)
packages/lib/di/di.ts (1)
  • createContainer (114-114)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (2)
  • InstantBookingCreateService (18-18)
  • instantBookingCreateServiceModule (7-7)
apps/api/v1/pages/api/bookings/_post.ts (1)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
  • getRegularBookingService (9-13)
packages/features/instant-meeting/handleInstantMeeting.test.ts (1)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (1)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1)
  • getNewBookingHandler (16-18)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (13)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • moduleLoader (19-22)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)
  • moduleLoader (22-25)
packages/lib/di/modules/Attribute.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/LuckyUser.ts (1)
  • moduleLoader (28-31)
packages/lib/di/modules/Host.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Ooo.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/User.ts (1)
  • moduleLoader (18-21)
packages/lib/di/modules/Booking.ts (1)
  • moduleLoader (11-16)
packages/lib/di/modules/Cache.ts (1)
  • moduleLoader (14-19)
packages/lib/di/modules/Features.ts (1)
  • moduleLoader (11-16)
packages/lib/di/modules/CheckBookingAndDurationLimits.ts (1)
  • moduleLoader (14-19)
packages/lib/di/modules/CheckBookingLimits.ts (1)
  • moduleLoader (13-18)
packages/prisma/prisma.module.ts (1)
  • moduleLoader (13-19)
apps/web/lib/types/booking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (54-54)
packages/platform/libraries/bookings.ts (1)
  • RegularBookingCreateResult (10-10)
packages/features/bookings/types.ts (5)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/index.ts (1)
  • BookingResponse (9-9)
packages/platform/libraries/index.ts (1)
  • BookingResponse (49-49)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (54-54)
packages/platform/libraries/bookings.ts (1)
  • RegularBookingCreateResult (10-10)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (2)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v2/src/lib/modules/instant-booking.module.ts (5)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • InstantBookingCreateService (18-18)
packages/platform/libraries/bookings.ts (1)
  • InstantBookingCreateService (7-7)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
apps/api/v2/src/lib/services/instant-booking-create.service.ts (6)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (1)
  • Injectable (89-1141)
apps/api/v2/src/lib/services/recurring-booking.service.ts (1)
  • Injectable (6-13)
apps/api/v2/src/lib/services/regular-booking.service.ts (1)
  • Injectable (17-46)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
  • InstantBookingCreateService (18-18)
packages/platform/libraries/bookings.ts (1)
  • InstantBookingCreateService (7-7)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (2)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (2)
  • RecurringBookingService (26-26)
  • recurringBookingServiceModule (10-10)
apps/api/v2/src/lib/services/recurring-booking.service.ts (2)
apps/api/v2/src/lib/services/regular-booking.service.ts (1)
  • Injectable (17-46)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (3)
packages/lib/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/lib/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (1)
  • moduleLoader (42-45)
packages/features/bookings/lib/handleNewBooking.ts (3)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1046)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (2)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (40-42)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (32-38)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/bookings/lib/create-instant-booking.ts (3)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)
  • createInstantBooking (357-390)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (44-51)
packages/lib/fetch-wrapper.ts (1)
  • post (28-36)
apps/web/pages/api/book/instant-event.ts (1)
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (9-12)
packages/features/instant-meeting/handleInstantMeeting.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateInstantBookingData (17-17)
  • InstantBookingCreateResult (44-51)
packages/features/bookings/lib/interfaces/IBookingCreateService.ts (1)
  • IBookingCreateService (4-7)
apps/api/v2/src/lib/modules/regular-booking.module.ts (4)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
apps/api/v2/src/lib/modules/recurring-booking.module.ts (1)
  • Module (5-10)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2422-2451)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
apps/web/pages/api/book/recurring-event.ts (2)
packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (9-13)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

45-66: Include the first round-robin booking in the results

For round-robin flows we now create the first slot up front, but we never push that result into createdBookings nor seed thirdPartyRecurringEventId. As it stands the API returns N‑1 bookings and later slots miss the series identifier. Push the initial result onto createdBookings and capture its recurring reference before iterating the remaining slots.

     const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-    luckyUsers = firstBookingResult.luckyUsers;
+    createdBookings.push(firstBookingResult);
+    if (!thirdPartyRecurringEventId && firstBookingResult.references?.length) {
+      const recurringRef = firstBookingResult.references.find((ref) => ref.thirdPartyRecurringEventId);
+      if (recurringRef?.thirdPartyRecurringEventId) {
+        thirdPartyRecurringEventId = recurringRef.thirdPartyRecurringEventId;
+      }
+    }
+    luckyUsers = firstBookingResult.luckyUsers;
♻️ Duplicate comments (4)
apps/api/v1/pages/api/bookings/_post.ts (1)

246-252: Fix unsafe header cast for x-cal-force-slug (can be string[])

req.headers["x-cal-force-slug"] can be string | string[] | undefined. Casting to string is unsafe and can leak a string[] to downstream code at runtime. Normalize it.

Apply this diff:

+        const forceSlugHeader = req.headers["x-cal-force-slug"];
+        const forcedSlug = Array.isArray(forceSlugHeader) ? forceSlugHeader[0] : forceSlugHeader;
         bookingMeta: {
           userId,
           hostname: req.headers.host || "",
-          forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
+          forcedSlug,
         },
apps/web/pages/api/book/event.ts (1)

48-56: The userId: -1 fallback issue remains.

As noted in the previous review, passing userId: -1 when the session is missing can lead to confusing downstream errors. The handler should return a 401 response early instead.

packages/features/bookings/lib/handleNewBooking.ts (1)

2455-2462: Guard against bookingMeta being undefined

bookingMeta remains optional in the method signature, but spreading an undefined value throws (TypeError: Cannot convert undefined or null to object). Any caller that omits meta (and plenty existed before this refactor) will now crash. Default the meta to {} before spreading in both methods.

   async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }

   async rescheduleBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)

324-334: Propagate noEmail to the recurring service

createNextApiBookingRequest still sets bookingRequest.noEmail, but we drop it when constructing bookingMeta. Because handleNewRecurringBooking treats an undefined flag as “mute emails for every slot after the first”, this silently disables notifications for the rest of the series. Please wire the flag through (and mirror it in the seated branch).

       const createdBookings: BookingResponse[] = await this.recurringBookingService.createBooking({
         bookingData: bookingRequest.body,
         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          noEmail: bookingRequest.noEmail,
         },
       });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5ff4ae2 and 071c6b2.

📒 Files selected for processing (33)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/di/InstantBookingCreateService.container.ts (1 hunks)
  • packages/features/bookings/di/InstantBookingCreateService.module.ts (1 hunks)
  • packages/features/bookings/di/RecurringBookingService.container.ts (1 hunks)
  • packages/features/bookings/di/RecurringBookingService.module.ts (1 hunks)
  • packages/features/bookings/di/RegularBookingService.container.ts (1 hunks)
  • packages/features/bookings/di/RegularBookingService.module.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (3 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (11 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (4 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/di/tokens.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/index.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/bookings/di/RecurringBookingService.container.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/di/RecurringBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/di/InstantBookingCreateService.container.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/di/RegularBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/di/tokens.ts
  • packages/features/bookings/di/RegularBookingService.container.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/features/bookings/di/RecurringBookingService.container.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/di/RecurringBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/di/InstantBookingCreateService.container.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/di/RegularBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/di/tokens.ts
  • packages/features/bookings/di/RegularBookingService.container.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/features/bookings/di/RecurringBookingService.container.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/di/RecurringBookingService.module.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/di/InstantBookingCreateService.container.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/di/RegularBookingService.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/di/tokens.ts
  • packages/features/bookings/di/RegularBookingService.container.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/lib/services/recurring-booking.service.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧠 Learnings (8)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-09-23T08:00:07.619Z
Learnt from: hariombalhara
PR: calcom/cal.com#23918
File: packages/features/schedules/lib/use-schedule/useTimesForSchedule.test.ts:16-23
Timestamp: 2025-09-23T08:00:07.619Z
Learning: In calcom/cal.com test files, particularly packages/features/schedules/lib/use-schedule/useTimesForSchedule.test.ts, the TIMEZONE_OFFSETS mapping is intentionally limited to only UTC variants and Asia/Kolkata. This is by design and should not be flagged as incomplete in future reviews (confirmed by maintainer hariombalhara).

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/bookings/di/RegularBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/pages/api/book/event.ts
  • packages/features/bookings/lib/handleNewBooking.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
🧬 Code graph analysis (21)
packages/features/bookings/di/RecurringBookingService.container.ts (3)
packages/features/di/di.ts (1)
  • createContainer (114-114)
packages/features/bookings/di/RecurringBookingService.module.ts (2)
  • RecurringBookingService (25-25)
  • recurringBookingServiceModule (9-9)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
apps/web/lib/types/booking.ts (2)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (57-57)
packages/features/bookings/lib/create-instant-booking.ts (3)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)
  • createInstantBooking (357-390)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (47-54)
packages/lib/fetch-wrapper.ts (1)
  • post (28-36)
packages/features/bookings/di/RecurringBookingService.module.ts (4)
packages/features/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/features/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/bookings/di/RegularBookingService.module.ts (1)
  • moduleLoader (39-42)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)
packages/features/bookings/di/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (10-14)
packages/features/bookings/types.ts (2)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (57-57)
apps/api/v2/src/lib/services/recurring-booking.service.ts (2)
apps/api/v2/src/lib/services/regular-booking.service.ts (1)
  • Injectable (17-46)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (47-54)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (43-45)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (35-41)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/bookings/di/InstantBookingCreateService.container.ts (3)
packages/features/di/di.ts (1)
  • createContainer (114-114)
packages/features/bookings/di/InstantBookingCreateService.module.ts (2)
  • InstantBookingCreateService (16-16)
  • instantBookingCreateServiceModule (5-5)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v1/pages/api/bookings/_post.ts (1)
packages/features/bookings/di/RegularBookingService.container.ts (1)
  • getRegularBookingService (10-14)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (2)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (57-57)
packages/platform/types/api.ts (1)
  • ApiSuccessResponse (8-8)
apps/api/v2/src/lib/services/regular-booking.service.ts (5)
apps/api/v2/src/lib/services/instant-booking-create.service.ts (1)
  • Injectable (5-6)
apps/api/v2/src/lib/services/recurring-booking.service.ts (1)
  • Injectable (6-13)
packages/features/bookings/di/RegularBookingService.module.ts (1)
  • RegularBookingService (44-44)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
packages/platform/libraries/bookings.ts (1)
  • RegularBookingService (5-5)
apps/web/pages/api/book/instant-event.ts (1)
packages/features/bookings/di/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (10-13)
packages/features/bookings/di/RegularBookingService.module.ts (2)
packages/features/bookings/di/InstantBookingCreateService.module.ts (1)
  • moduleLoader (17-20)
packages/features/bookings/di/RecurringBookingService.module.ts (1)
  • moduleLoader (21-24)
apps/web/pages/api/book/recurring-event.ts (2)
packages/features/bookings/di/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (10-14)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/bookings/di/InstantBookingCreateService.module.ts (3)
packages/features/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/features/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (2)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
apps/web/pages/api/book/event.ts (1)
packages/features/bookings/di/RegularBookingService.container.ts (1)
  • getRegularBookingService (10-14)
packages/features/bookings/lib/handleNewBooking.ts (7)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1049)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/lib/server/repository/host.ts (1)
  • HostRepository (3-40)
packages/lib/server/repository/user.ts (1)
  • UserRepository (123-1071)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (43-45)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (35-41)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Type check / check-types
  • GitHub Check: Tests / Unit
  • GitHub Check: Linters / lint
🔇 Additional comments (24)
packages/features/di/tokens.ts (1)

1-1: LGTM!

The import path change from relative to absolute aligns with the monorepo's absolute import strategy and improves clarity.

packages/features/bookings/di/RecurringBookingService.container.ts (1)

1-14: LGTM!

The DI container implementation follows the established pattern used by RegularBookingService.container and InstantBookingCreateService.container, ensuring consistency across booking services.

packages/features/bookings/di/RegularBookingService.module.ts (2)

39-42: LGTM!

The export rename to moduleLoader maintains consistency with InstantBookingCreateService.module and RecurringBookingService.module, standardizing the DI module pattern across booking services.


24-36: IBookingServiceDependencies matches depsMap The interface now declares all 11 dependencies present in depsMap.

packages/features/bookings/di/InstantBookingCreateService.container.ts (1)

1-13: LGTM!

The DI container implementation is consistent with the pattern used by RegularBookingService.container and RecurringBookingService.container, maintaining uniformity across all booking service containers.

apps/web/lib/types/booking.ts (1)

1-3: LGTM!

The type definition is simplified and correctly aliases RegularBookingCreateResult, aligning with the new service-based booking architecture.

Note: A past review comment flagged that some consumers (e.g., apps/web/pages/api/book/recurring-event.ts) import BookingResponse from the package path instead of this local re-export. Consider standardizing imports across the codebase for consistency.

packages/features/bookings/di/RegularBookingService.container.ts (2)

1-1: LGTM!

The import path change to absolute package path improves consistency across the monorepo.


5-6: LGTM!

The moduleLoader alias as regularBookingServiceModule maintains backward compatibility while aligning with the updated module export pattern.

apps/api/v2/src/lib/services/recurring-booking.service.ts (1)

1-13: LGTM!

The NestJS service implementation correctly extends BaseRecurringBookingService and follows the established DI pattern, consistent with RegularBookingService in the v2 API layer.

apps/web/pages/api/book/instant-event.ts (2)

4-4: LGTM!

The import change to use the DI container for InstantBookingCreateService aligns with the broader service-based refactoring pattern.


23-28: LGTM!

The service-based approach is correctly implemented. The TODO comment clearly acknowledges the runtime validation trade-off and plans to address the any type in a follow-up.

packages/features/bookings/di/RecurringBookingService.module.ts (1)

1-25: LGTM!

The DI module correctly wires RecurringBookingService with its dependency on RegularBookingService. The depsMap structure aligns with the service's constructor signature shown in the relevant code snippets.

packages/features/bookings/di/InstantBookingCreateService.module.ts (1)

1-20: LGTM!

The DI module correctly sets up InstantBookingCreateService with an empty depsMap, which aligns with the service having no constructor dependencies as shown in the relevant code snippets.

apps/web/pages/api/book/event.ts (1)

4-4: LGTM!

The import change to use the DI container for RegularBookingService is consistent with the service-based refactoring pattern.

packages/features/bookings/lib/create-instant-booking.ts (2)

3-4: LGTM!

The import changes align with the broader DTO type refactoring effort, consolidating types in a dedicated dto/types module.


9-10: Date serialization issue deferred but documented.

The TODO clearly acknowledges that expires: Date should be serialized as a string for the HTTP response. While the previous concern about non-existent startTime/endTime fields is resolved, the expires field serialization remains unaddressed.

Consider verifying that downstream consumers properly handle the expires field serialization when the fix is implemented.

packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (4)

24-24: LGTM!

The import of getRecurringBookingService aligns with the service-based testing approach.


27-27: LGTM!

Good practice removing unused imports while keeping necessary ones like BookingStatus.


154-161: LGTM!

The test correctly uses the new service-based approach with the bookingMeta structure. Using userId: -1 is appropriate in the test context to simulate an anonymous booking scenario.


222-223: Minor formatting adjustment.

packages/features/bookings/types.ts (2)

3-4: LGTM!

Import changes align with the DTO type consolidation effort and correct enum imports from Prisma.


97-98: LGTM!

The type alias provides a clean migration path while maintaining backward compatibility. The TODO clearly documents the plan to consolidate naming in a follow-up PR.

packages/features/bookings/lib/bookingCreateBodySchema.ts (2)

60-76: LGTM!

The new recurringBookingCreateBodyPartialSchema properly encapsulates recurring-related fields. The TODO clearly documents the plan to create separate schemas for different booking types. The optional end field in allRecurringDates aligns with the previous comment about handleNewRecurringBooking potentially passing it as undefined.


78-100: LGTM!

The schema merge structure is clean and modular. Extracting recurring-related fields into a partial schema and then merging improves maintainability. The new ExtendedBookingCreateBody type export provides a useful type alias for consumers.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

45-66: Include the first round‑robin booking in the response

For round‑robin series we await the first slot but never push it into createdBookings, so the API returns N‑1 results. We also leave thirdPartyRecurringEventId unset for later slots. Please add the first result (when defined) and seed the recurring ID from its references before continuing.

     const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
-    luckyUsers = firstBookingResult.luckyUsers;
+    if (firstBookingResult) {
+      createdBookings.push(firstBookingResult);
+      luckyUsers = firstBookingResult.luckyUsers;
+      if (!thirdPartyRecurringEventId && firstBookingResult.references?.length) {
+        thirdPartyRecurringEventId =
+          firstBookingResult.references.find((ref) => ref.thirdPartyRecurringEventId)?.thirdPartyRecurringEventId ??
+          null;
+      }
+    }
♻️ Duplicate comments (5)
apps/api/v1/pages/api/bookings/_post.ts (1)

242-252: Normalize x-cal-force-slug header before passing to bookingMeta

req.headers["x-cal-force-slug"] can be string | string[] | undefined. Casting it straight to string can leak a string[] into CreateBookingMeta, breaking code paths that expect a scalar slug. Normalize the header first.

       bookingMeta: {
         userId,
         hostname: req.headers.host || "",
-        forcedSlug: req.headers["x-cal-force-slug"] as string | undefined,
+        forcedSlug: Array.isArray(req.headers["x-cal-force-slug"])
+          ? req.headers["x-cal-force-slug"][0]
+          : req.headers["x-cal-force-slug"],
       },
apps/web/pages/api/book/recurring-event.ts (1)

48-57: Sanitize bookingData and stop leaking sentinel userId

createBooking now validates the payload against a strict schema; passing cfToken straight through causes the Zod parse to fail, and forcing -1 into userId still leaks a sentinel into downstream logic. We also lose hostname/forcedSlug, so platform flows can no longer resolve the organizer slug. Please strip cfToken, keep userId undefined when unauthenticated, and forward the missing meta fields before calling the service.

-  const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
-    bookingData: req.body,
-    bookingMeta: {
-      userId: session?.user?.id || -1,
-      platformClientId: req.platformClientId,
-      platformCancelUrl: req.platformCancelUrl,
-      platformBookingUrl: req.platformBookingUrl,
-      platformRescheduleUrl: req.platformRescheduleUrl,
-      platformBookingLocation: req.platformBookingLocation,
-      noEmail: req.noEmail,
-    },
-  });
+  const rawBookingData = req.body;
+  const sanitizedBookingData = Array.isArray(rawBookingData)
+    ? rawBookingData.map(({ cfToken, ...rest }) => rest)
+    : rawBookingData;
+
+  const createdBookings: BookingResponse[] = await recurringBookingService.createBooking({
+    bookingData: sanitizedBookingData,
+    bookingMeta: {
+      userId: session?.user?.id ?? undefined,
+      hostname: req.hostname,
+      forcedSlug: req.forcedSlug,
+      platformClientId: req.platformClientId,
+      platformCancelUrl: req.platformCancelUrl,
+      platformBookingUrl: req.platformBookingUrl,
+      platformRescheduleUrl: req.platformRescheduleUrl,
+      platformBookingLocation: req.platformBookingLocation,
+      noEmail: req.noEmail,
+    },
+  });
packages/features/bookings/lib/handleNewBooking.ts (1)

2455-2461: Guard bookingMeta before spreading

createBooking/rescheduleBooking now spread input.bookingMeta directly; when callers omit the optional meta (the common case) we end up executing { ...undefined }, which throws. Default the meta to {} before spreading.

-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
@@
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (1)

518-526: Forward noEmail for seated recurring bookings

When noEmail is omitted the recurring handler defaults to suppressing emails for every slot after the first one. Seated recurring bookings still need the caller’s email preference, so please pass bookingRequest.noEmail through.

       bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
         areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
       },
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)

322-333: Pass noEmail into recurring bookingMeta

Without forwarding bookingRequest.noEmail, the recurring service assumes noEmail is true for every slot after the first, so platform bookings silently drop follow-up mail. Please propagate the flag.

       bookingMeta: {
         userId: bookingRequest.userId,
         hostname: bookingRequest.headers?.host || "",
         platformClientId: bookingRequest.platformClientId,
         platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
         platformCancelUrl: bookingRequest.platformCancelUrl,
         platformBookingUrl: bookingRequest.platformBookingUrl,
         platformBookingLocation: bookingRequest.platformBookingLocation,
+        noEmail: bookingRequest.noEmail,
       },
🧹 Nitpick comments (1)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)

154-160: Refresh the comment to match the new service call

We no longer call handleNewRecurringBooking directly; updating the comment keeps the test self-documenting.

-          // Call handleNewRecurringBooking directly instead of through API
+          // Call the recurring booking service directly instead of going through the API layer
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 071c6b2 and 55c0ba0.

📒 Files selected for processing (41)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/di/InstantBookingCreateService.container.ts (1 hunks)
  • packages/features/bookings/di/InstantBookingCreateService.module.ts (1 hunks)
  • packages/features/bookings/di/RecurringBookingService.container.ts (1 hunks)
  • packages/features/bookings/di/RecurringBookingService.module.ts (1 hunks)
  • packages/features/bookings/di/RegularBookingService.container.ts (1 hunks)
  • packages/features/bookings/di/RegularBookingService.module.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (3 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (11 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (4 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/di/bookings/containers/InstantBookingCreateService.container.ts (0 hunks)
  • packages/features/di/bookings/containers/RecurringBookingService.container.ts (0 hunks)
  • packages/features/di/bookings/modules/InstantBookingCreateService.module.ts (0 hunks)
  • packages/features/di/bookings/modules/RecurringBookingService.module.ts (0 hunks)
  • packages/features/di/tokens.ts (1 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (5)
  • packages/features/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/features/di/bookings/containers/RecurringBookingService.container.ts
  • packages/features/di/bookings/modules/RecurringBookingService.module.ts
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (15)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • packages/features/bookings/di/RecurringBookingService.module.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/di/InstantBookingCreateService.container.ts
  • packages/features/di/tokens.ts
  • packages/features/bookings/di/RecurringBookingService.container.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/web/pages/api/book/event.ts
  • packages/platform/libraries/bookings.ts
  • packages/features/bookings/lib/index.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/di/RegularBookingService.module.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
  • packages/features/bookings/di/RegularBookingService.container.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/di/RegularBookingService.module.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
  • packages/features/bookings/di/RegularBookingService.container.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • packages/features/bookings/di/RegularBookingService.module.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/bookings/types.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
  • packages/features/bookings/di/RegularBookingService.container.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
🧠 Learnings (7)
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/features/bookings/di/RegularBookingService.module.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-09-23T08:00:07.619Z
Learnt from: hariombalhara
PR: calcom/cal.com#23918
File: packages/features/schedules/lib/use-schedule/useTimesForSchedule.test.ts:16-23
Timestamp: 2025-09-23T08:00:07.619Z
Learning: In calcom/cal.com test files, particularly packages/features/schedules/lib/use-schedule/useTimesForSchedule.test.ts, the TIMEZONE_OFFSETS mapping is intentionally limited to only UTC variants and Asia/Kolkata. This is by design and should not be flagged as incomplete in future reviews (confirmed by maintainer hariombalhara).

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
🧬 Code graph analysis (19)
apps/api/v2/src/lib/modules/instant-booking.module.ts (7)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
apps/api/v2/src/lib/modules/recurring-booking.module.ts (1)
  • Module (5-10)
apps/api/v2/src/lib/modules/regular-booking.module.ts (1)
  • Module (15-32)
packages/features/bookings/di/InstantBookingCreateService.module.ts (1)
  • InstantBookingCreateService (16-16)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/platform/libraries/bookings.ts (1)
  • InstantBookingCreateService (7-7)
packages/features/instant-meeting/handleInstantMeeting.test.ts (1)
packages/features/bookings/di/InstantBookingCreateService.container.ts (1)
  • getInstantBookingCreateService (10-13)
packages/features/bookings/di/RegularBookingService.module.ts (2)
packages/features/bookings/di/InstantBookingCreateService.module.ts (1)
  • moduleLoader (17-20)
packages/features/bookings/di/RecurringBookingService.module.ts (1)
  • moduleLoader (21-24)
apps/api/v2/src/lib/services/regular-booking.service.ts (4)
apps/api/v2/src/lib/services/instant-booking-create.service.ts (1)
  • Injectable (5-6)
apps/api/v2/src/lib/services/recurring-booking.service.ts (1)
  • Injectable (6-13)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
packages/prisma/index.ts (1)
  • PrismaClient (84-84)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)
packages/features/bookings/di/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (10-14)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (43-45)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (35-41)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (2)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (57-57)
packages/platform/types/api.ts (1)
  • ApiSuccessResponse (8-8)
packages/features/instant-meeting/handleInstantMeeting.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateInstantBookingData (17-17)
  • InstantBookingCreateResult (47-54)
packages/features/bookings/lib/interfaces/IBookingCreateService.ts (1)
  • IBookingCreateService (4-7)
apps/api/v1/pages/api/bookings/_post.ts (1)
packages/features/bookings/di/RegularBookingService.container.ts (1)
  • getRegularBookingService (10-14)
packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (3)
packages/features/bookings/lib/dto/types.d.ts (1)
  • BookingHandlerInput (43-45)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • BookingHandlerInput (9-11)
packages/features/bookings/di/RegularBookingService.container.ts (1)
  • getRegularBookingService (10-14)
packages/features/bookings/lib/handleNewBooking.ts (6)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1049)
packages/platform/libraries/repositories.ts (4)
  • BookingRepository (4-4)
  • FeaturesRepository (10-10)
  • HostRepository (12-12)
  • UserRepository (9-9)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (43-45)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (35-41)
packages/features/bookings/lib/dto/types.d.ts (2)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v2/src/lib/modules/recurring-booking.module.ts (5)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
apps/api/v2/src/lib/modules/instant-booking.module.ts (1)
  • Module (4-8)
apps/api/v2/src/lib/modules/regular-booking.module.ts (1)
  • Module (15-32)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
apps/web/pages/api/book/recurring-event.ts (1)
packages/features/bookings/di/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (10-14)
packages/features/bookings/types.ts (2)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (57-57)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (47-54)
packages/features/bookings/di/InstantBookingCreateService.module.ts (3)
packages/features/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/features/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v2/src/lib/services/recurring-booking.service.ts (3)
apps/api/v2/src/lib/services/regular-booking.service.ts (1)
  • Injectable (17-46)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/platform/libraries/bookings.ts (2)
  • RecurringBookingService (6-6)
  • RegularBookingService (5-5)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Production builds / Build Docs
  • GitHub Check: Tests / Unit
  • GitHub Check: Production builds / Build API v1
  • GitHub Check: Production builds / Build Web App
  • GitHub Check: Production builds / Build API v2
  • GitHub Check: Production builds / Build Atoms
  • GitHub Check: Type check / check-types
  • GitHub Check: Linters / lint
🔇 Additional comments (14)
apps/api/v2/src/lib/modules/instant-booking.module.ts (1)

1-8: LGTM!

The module structure is consistent with the existing booking modules (RegularBookingModule, RecurringBookingModule) and follows NestJS conventions. The service is correctly registered as both a provider and an export, making it available for DI in consuming modules.

packages/features/bookings/di/InstantBookingCreateService.module.ts (1)

1-20: LGTM!

The DI module setup is correct. The empty depsMap: {} on line 13 is intentional and valid because InstantBookingCreateService doesn't require any dependencies in its constructor (it only wraps a handler function). This follows the same DI binding pattern used for other booking services in the codebase.

packages/features/bookings/types.ts (2)

3-4: LGTM!

The import updates correctly reference the new type location (RegularBookingCreateResult from dto/types) and use the proper enum location (SchedulingType from @calcom/prisma/enums).


97-98: LGTM!

The type alias consolidation is a good step toward consistency. The TODO comment appropriately acknowledges that the dual naming (BookingResponse vs RegularBookingCreateResult) should be unified in a follow-up PR to avoid churn in this already substantial refactoring.

packages/features/bookings/lib/dto/types.d.ts (2)

30-32: LGTM!

The new optional platform parameters (skipAvailabilityCheck, skipEventLimitsCheck, skipCalendarSyncTaskCreation) are appropriately typed as optional booleans and provide clear feature flag semantics for platform clients to control booking behavior.


47-57: LGTM!

The type definitions are consistent with the service-based architecture:

  • InstantBookingCreateResult provides a clear contract for instant booking responses
  • RegularBookingCreateResult is correctly inferred from the service method, ensuring type safety

Note: The expires: Date field (line 52) will serialize to an ISO string in HTTP responses—this is existing behavior that's being preserved, as discussed in previous review comments.

packages/features/bookings/di/RegularBookingService.module.ts (3)

3-12: LGTM!

The new module loader imports correctly reference the required dependencies for the expanded RegularBookingService functionality. The additions include repository and service dependencies that align with the service's expanded scope.


31-35: LGTM!

The five new dependencies (luckyUserService, hostRepository, oooRepository, userRepository, attributeRepository) are correctly wired into the DI dependency map, expanding the service's capabilities beyond the original six dependencies noted in the learnings.

Based on learnings


39-42: LGTM!

The export rename from regularBookingServiceModule to moduleLoader aligns with the consistent naming pattern used in sibling modules (InstantBookingCreateService.module.ts, RecurringBookingService.module.ts), improving consistency across the DI module surface.

packages/features/instant-meeting/handleInstantMeeting.test.ts (3)

17-17: LGTM!

The import correctly references the new DI container for obtaining the InstantBookingCreateService instance, aligning the tests with the service-based architecture.


39-115: LGTM!

The test correctly updates to use the service-based API (instantBookingCreateService.createBooking({ bookingData })) instead of the direct handler invocation. The test structure and assertions remain unchanged, confirming API equivalence between the old and new implementations.


138-198: LGTM!

The error path test is correctly updated to use the same service-based API, and the expected error message remains consistent with the previous implementation, ensuring no behavioral changes.

packages/features/bookings/di/RegularBookingService.container.ts (1)

1-6: LGTM!

The import path update to the absolute import @calcom/features/di/di improves maintainability. The alias (moduleLoader as regularBookingServiceModule) preserves the existing container API surface while adopting the new moduleLoader naming convention from the module file.

apps/api/v2/src/lib/services/recurring-booking.service.ts (1)

1-13: LGTM!

The NestJS service implementation correctly extends the platform's BaseRecurringBookingService and follows the established DI pattern used by RegularBookingService. The constructor properly injects the required RegularBookingService dependency and passes it to the base class via super().

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)

45-123: Include first round‑robin slot and propagate series ID

When isRoundRobin is true we await the first slot but never push it into createdBookings. With a single-slot series this means we return [], and with multi-slot series we drop the first booking. We also leave thirdPartyRecurringEventId unset, so subsequent slots generate a fresh ID instead of sharing the first booking’s series. Please push the first result and seed thirdPartyRecurringEventId from its references before looping over the remaining slots.

     const firstBookingResult = await regularBookingService.createBooking({
       bookingData: recurringEventData,
       bookingMeta: {
         hostname: input.hostname || "",
         forcedSlug: input.forcedSlug as string | undefined,
         ...handleBookingMeta,
       },
     });
+    createdBookings.push(firstBookingResult);
+    if (firstBookingResult.references?.length) {
+      const recurringRef = firstBookingResult.references.find(
+        (reference) => reference.thirdPartyRecurringEventId
+      );
+      if (recurringRef?.thirdPartyRecurringEventId) {
+        thirdPartyRecurringEventId = recurringRef.thirdPartyRecurringEventId;
+      }
+    }
     luckyUsers = firstBookingResult.luckyUsers;
♻️ Duplicate comments (2)
apps/api/v1/pages/api/bookings/_post.ts (1)

242-252: Service integration looks good, but address the header cast issue.

The migration to RegularBookingService via DI is correctly implemented. The bookingDataSchemaGetter parameter is properly passed.

However, the unsafe header cast at line 249 remains unaddressed from a previous review.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (1)

515-526: Add missing noEmail to recurring seated booking.

The recurring seated booking call is missing noEmail: bookingRequest.noEmail, in the bookingMeta. This inconsistency means recurring seated bookings might suppress emails unexpectedly. Add it for consistency with the non-seated recurring booking flow (line 500).

Apply this diff:

       const bookings = await this.recurringBookingService.createBooking({
         bookingData: bookingRequest.body,
         bookingMeta: {
           userId: bookingRequest.userId,
           hostname: bookingRequest.headers?.host || "",
           platformClientId: bookingRequest.platformClientId,
           platformRescheduleUrl: bookingRequest.platformRescheduleUrl,
           platformCancelUrl: bookingRequest.platformCancelUrl,
           platformBookingUrl: bookingRequest.platformBookingUrl,
           platformBookingLocation: bookingRequest.platformBookingLocation,
+          noEmail: bookingRequest.noEmail,
           areCalendarEventsEnabled: bookingRequest.areCalendarEventsEnabled,
         },
       });
🧹 Nitpick comments (3)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)

540-551: Consider adding noEmail to regular bookings for consistency.

The regular booking flow omits noEmail from bookingMeta, while recurring bookings include it (line 500). If noEmail should be respected for regular bookings, add noEmail: bookingRequest.noEmail, to maintain consistency across booking types.

If this is intentional behavior (recurring bookings handle email differently), consider adding a comment explaining why regular bookings don't pass noEmail.


574-585: Same noEmail consideration applies to seated bookings.

Similar to regular bookings, seated bookings omit noEmail from bookingMeta. Consider adding it if email suppression should be respected for seated bookings.


771-782: Same noEmail consideration applies to reschedule bookings.

Reschedule bookings also omit noEmail from bookingMeta. For consistency, consider whether this field should be included across all booking flows that accept bookingMeta.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 55c0ba0 and d134d11.

📒 Files selected for processing (41)
  • apps/api/v1/pages/api/bookings/_post.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (6 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (2 hunks)
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (8 hunks)
  • apps/api/v2/src/lib/modules/instant-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/modules/regular-booking.module.ts (1 hunks)
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/recurring-booking.service.ts (1 hunks)
  • apps/api/v2/src/lib/services/regular-booking.service.ts (1 hunks)
  • apps/web/lib/types/booking.ts (1 hunks)
  • apps/web/pages/api/book/event.ts (2 hunks)
  • apps/web/pages/api/book/instant-event.ts (2 hunks)
  • apps/web/pages/api/book/recurring-event.ts (2 hunks)
  • packages/features/bookings/di/InstantBookingCreateService.container.ts (1 hunks)
  • packages/features/bookings/di/InstantBookingCreateService.module.ts (1 hunks)
  • packages/features/bookings/di/RecurringBookingService.container.ts (1 hunks)
  • packages/features/bookings/di/RecurringBookingService.module.ts (1 hunks)
  • packages/features/bookings/di/RegularBookingService.container.ts (1 hunks)
  • packages/features/bookings/di/RegularBookingService.module.ts (2 hunks)
  • packages/features/bookings/lib/bookingCreateBodySchema.ts (1 hunks)
  • packages/features/bookings/lib/create-instant-booking.ts (1 hunks)
  • packages/features/bookings/lib/dto/types.d.ts (3 hunks)
  • packages/features/bookings/lib/handleNewBooking.ts (11 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts (6 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts (1 hunks)
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (4 hunks)
  • packages/features/bookings/lib/handleNewRecurringBooking.ts (4 hunks)
  • packages/features/bookings/lib/index.ts (1 hunks)
  • packages/features/bookings/types.ts (2 hunks)
  • packages/features/di/bookings/containers/InstantBookingCreateService.container.ts (0 hunks)
  • packages/features/di/bookings/containers/RecurringBookingService.container.ts (0 hunks)
  • packages/features/di/bookings/modules/InstantBookingCreateService.module.ts (0 hunks)
  • packages/features/di/bookings/modules/RecurringBookingService.module.ts (0 hunks)
  • packages/features/di/tokens.ts (1 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.test.ts (5 hunks)
  • packages/features/instant-meeting/handleInstantMeeting.ts (3 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (5)
  • packages/features/di/bookings/modules/InstantBookingCreateService.module.ts
  • packages/features/di/bookings/modules/RecurringBookingService.module.ts
  • packages/features/di/bookings/containers/InstantBookingCreateService.container.ts
  • packages/platform/libraries/index.ts
  • packages/features/di/bookings/containers/RecurringBookingService.container.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/features/di/tokens.ts
🚧 Files skipped from review as they are similar to previous changes (14)
  • packages/features/bookings/lib/handleNewBooking/test/email-verification-booking.test.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts
  • apps/api/v2/src/lib/services/instant-booking-create.service.ts
  • packages/platform/libraries/bookings.ts
  • packages/features/bookings/di/RecurringBookingService.container.ts
  • packages/features/bookings/di/RecurringBookingService.module.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts
  • apps/web/pages/api/book/event.ts
  • apps/web/pages/api/book/recurring-event.ts
  • packages/features/bookings/lib/handleNewBooking/test/getNewBookingHandler.ts
  • apps/web/pages/api/book/instant-event.ts
  • packages/features/bookings/di/RegularBookingService.module.ts
  • packages/features/instant-meeting/handleInstantMeeting.test.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/bookings/lib/index.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/di/RegularBookingService.container.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/features/bookings/di/InstantBookingCreateService.container.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/bookings/lib/index.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/di/RegularBookingService.container.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/features/bookings/di/InstantBookingCreateService.container.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • apps/api/v2/src/lib/modules/instant-booking.module.ts
  • packages/features/bookings/lib/index.ts
  • packages/features/bookings/lib/create-instant-booking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts
  • packages/features/bookings/di/RegularBookingService.container.ts
  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • packages/features/bookings/types.ts
  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • packages/features/bookings/di/InstantBookingCreateService.container.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • packages/features/bookings/lib/bookingCreateBodySchema.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • apps/web/lib/types/booking.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • apps/api/v1/pages/api/bookings/_post.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • apps/api/v2/src/lib/modules/recurring-booking.module.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/lib/services/recurring-booking.service.ts
🧠 Learnings (8)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • apps/api/v2/src/lib/services/regular-booking.service.ts
  • apps/api/v2/src/lib/modules/regular-booking.module.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • packages/features/bookings/lib/dto/types.d.ts
  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/bookings/di/InstantBookingCreateService.module.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: The test file packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.test.ts explicitly documents on line 236 that the current behavior of forceRescheduleForCancelledBooking affecting both CANCELLED and REJECTED bookings is known to be incorrect, but is preserved as "Current Behavior" for backward compatibility. The test comment states the expected behavior should be that REJECTED bookings redirect to booking details even when forceRescheduleForCancelledBooking=true.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-07-22T11:42:47.623Z
Learnt from: CarinaWolli
PR: calcom/cal.com#22296
File: packages/lib/bookings/filterHostsBySameRoundRobinHost.ts:41-42
Timestamp: 2025-07-22T11:42:47.623Z
Learning: The filterHostsBySameRoundRobinHost function in packages/lib/bookings/filterHostsBySameRoundRobinHost.ts has a known limitation where it doesn't work correctly with fixed hosts or round robin groups. This is pre-existing technical debt that was already broken before the round robin groups feature. CarinaWolli has documented this in Linear issue CAL-6134 for future fix.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
📚 Learning: 2025-09-23T08:00:07.619Z
Learnt from: hariombalhara
PR: calcom/cal.com#23918
File: packages/features/schedules/lib/use-schedule/useTimesForSchedule.test.ts:16-23
Timestamp: 2025-09-23T08:00:07.619Z
Learning: In calcom/cal.com test files, particularly packages/features/schedules/lib/use-schedule/useTimesForSchedule.test.ts, the TIMEZONE_OFFSETS mapping is intentionally limited to only UTC variants and Asia/Kolkata. This is by design and should not be flagged as incomplete in future reviews (confirmed by maintainer hariombalhara).

Applied to files:

  • packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts
📚 Learning: 2025-08-27T13:32:46.887Z
Learnt from: supalarry
PR: calcom/cal.com#23364
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/transformers/internal-to-api/internal-to-api.spec.ts:295-296
Timestamp: 2025-08-27T13:32:46.887Z
Learning: In calcom/cal.com, when transforming booking fields from internal to API format, tests in organizations-event-types.e2e-spec.ts already expect name field label and placeholder to be empty strings ("") rather than undefined. PR changes that set these to explicit empty strings are typically fixing implementation to match existing test expectations rather than breaking changes.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
📚 Learning: 2025-08-17T22:00:16.329Z
Learnt from: Udit-takkar
PR: calcom/cal.com#22995
File: packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts:117-126
Timestamp: 2025-08-17T22:00:16.329Z
Learning: In calcom/cal.com PR #22995, packages/trpc/server/routers/viewer/aiVoiceAgent/_router.ts, the enabled input parameter in the update endpoint is intentionally not forwarded to aiService.updateAgentConfiguration() as the enabled/disabled agent functionality is not required at the moment (per maintainer Udit-takkar). Future reviews should not flag this as missing functionality unless requirements change.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
📚 Learning: 2025-09-12T11:23:34.158Z
Learnt from: hariombalhara
PR: calcom/cal.com#23736
File: packages/features/bookings/lib/reschedule/determineReschedulePreventionRedirect.ts:73-84
Timestamp: 2025-09-12T11:23:34.158Z
Learning: In the Cal.com codebase, the forceRescheduleForCancelledBooking flag historically affects both CANCELLED and REJECTED booking statuses, despite its name suggesting it should only affect cancelled bookings. This behavior existed before PR #23736 and was preserved during the refactoring.

Applied to files:

  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
🧬 Code graph analysis (18)
apps/api/v2/src/lib/modules/instant-booking.module.ts (7)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
apps/api/v2/src/lib/modules/recurring-booking.module.ts (1)
  • Module (5-10)
apps/api/v2/src/lib/modules/regular-booking.module.ts (1)
  • Module (15-32)
packages/features/bookings/di/InstantBookingCreateService.module.ts (1)
  • InstantBookingCreateService (16-16)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/platform/libraries/bookings.ts (1)
  • InstantBookingCreateService (7-7)
packages/features/bookings/lib/create-instant-booking.ts (3)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (1)
  • createInstantBooking (357-390)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (47-54)
packages/lib/fetch-wrapper.ts (1)
  • post (28-36)
packages/features/instant-meeting/handleInstantMeeting.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateInstantBookingData (17-17)
  • InstantBookingCreateResult (47-54)
packages/features/bookings/lib/interfaces/IBookingCreateService.ts (1)
  • IBookingCreateService (4-7)
apps/api/v2/src/lib/services/regular-booking.service.ts (4)
apps/api/v2/src/lib/services/instant-booking-create.service.ts (1)
  • Injectable (5-6)
apps/api/v2/src/lib/services/recurring-booking.service.ts (1)
  • Injectable (6-13)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
packages/prisma/index.ts (1)
  • PrismaClient (84-84)
packages/features/bookings/types.ts (2)
apps/web/lib/types/booking.ts (1)
  • BookingResponse (3-3)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (57-57)
packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)
packages/features/bookings/di/RecurringBookingService.container.ts (1)
  • getRecurringBookingService (10-14)
apps/api/v2/src/lib/modules/regular-booking.module.ts (5)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
apps/api/v2/src/lib/modules/instant-booking.module.ts (1)
  • Module (4-8)
apps/api/v2/src/lib/modules/recurring-booking.module.ts (1)
  • Module (5-10)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
packages/features/bookings/di/InstantBookingCreateService.container.ts (3)
packages/features/di/di.ts (1)
  • createContainer (114-114)
packages/features/bookings/di/InstantBookingCreateService.module.ts (2)
  • InstantBookingCreateService (16-16)
  • instantBookingCreateServiceModule (5-5)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (3)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts (4)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
packages/features/bookings/lib/dto/types.d.ts (1)
  • InstantBookingCreateResult (47-54)
packages/features/bookings/lib/dto/types.d.ts (4)
packages/features/bookings/lib/bookingCreateBodySchema.ts (1)
  • ExtendedBookingCreateBody (100-100)
packages/platform/libraries/bookings.ts (3)
  • InstantBookingCreateResult (9-9)
  • RegularBookingCreateResult (10-10)
  • RegularBookingService (5-5)
packages/features/bookings/di/RegularBookingService.module.ts (1)
  • RegularBookingService (44-44)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
apps/web/lib/types/booking.ts (3)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
packages/features/bookings/lib/dto/types.d.ts (1)
  • RegularBookingCreateResult (57-57)
packages/platform/libraries/bookings.ts (1)
  • RegularBookingCreateResult (10-10)
packages/features/bookings/lib/handleNewBooking.ts (6)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/platform/libraries/bookings.ts (3)
  • CheckBookingAndDurationLimitsService (4-4)
  • CheckBookingLimitsService (3-3)
  • LuckyUserService (1-1)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1049)
packages/lib/server/getLuckyUser.ts (1)
  • LuckyUserService (193-1133)
packages/features/bookings/lib/dto/types.d.ts (4)
  • BookingHandlerInput (43-45)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (35-41)
  • BookingDataSchemaGetter (13-13)
apps/api/v1/pages/api/bookings/_post.ts (1)
packages/features/bookings/di/RegularBookingService.container.ts (1)
  • getRegularBookingService (10-14)
packages/features/bookings/lib/handleNewRecurringBooking.ts (2)
packages/features/bookings/lib/dto/types.d.ts (2)
  • CreateRecurringBookingData (19-21)
  • CreateBookingMeta (35-41)
packages/features/bookings/types.ts (1)
  • BookingResponse (98-98)
apps/api/v2/src/lib/modules/recurring-booking.module.ts (5)
apps/api/v2/src/ee/bookings/2024-04-15/bookings.module.ts (1)
  • Module (29-61)
apps/api/v2/src/ee/bookings/2024-08-13/bookings.module.ts (1)
  • Module (47-98)
apps/api/v2/src/lib/modules/instant-booking.module.ts (1)
  • Module (4-8)
apps/api/v2/src/lib/modules/regular-booking.module.ts (1)
  • Module (15-32)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/bookings/di/InstantBookingCreateService.module.ts (3)
packages/features/di/di.ts (1)
  • bindModuleToClassOnToken (57-113)
packages/features/di/tokens.ts (1)
  • DI_TOKENS (3-58)
packages/features/instant-meeting/handleInstantMeeting.ts (1)
  • InstantBookingCreateService (338-342)
apps/api/v2/src/lib/services/recurring-booking.service.ts (4)
apps/api/v2/src/lib/services/instant-booking-create.service.ts (1)
  • Injectable (5-6)
apps/api/v2/src/lib/services/regular-booking.service.ts (1)
  • Injectable (17-46)
packages/features/bookings/lib/handleNewRecurringBooking.ts (1)
  • RecurringBookingService (134-152)
packages/features/bookings/lib/handleNewBooking.ts (1)
  • RegularBookingService (2452-2481)
🔇 Additional comments (17)
packages/features/bookings/di/RegularBookingService.container.ts (1)

1-14: LGTM! Clean DI container setup.

The import path update and module loader aliasing are correct. The getRegularBookingService function properly instantiates the service through the DI container following the established pattern.

apps/api/v2/src/lib/modules/instant-booking.module.ts (1)

1-8: LGTM! Well-structured NestJS module.

The module correctly declares and exports InstantBookingCreateService, following NestJS conventions. This aligns with the DI-based booking service pattern introduced in this PR.

packages/features/bookings/lib/index.ts (1)

9-9: LGTM! Type export aligns with refactoring.

The BookingResponse type export centralizes the booking result type, supporting the shift from dynamic ReturnType to explicit RegularBookingCreateResult.

packages/features/bookings/di/InstantBookingCreateService.container.ts (1)

1-13: LGTM! Consistent DI container pattern.

The container setup for InstantBookingCreateService follows the same pattern as RegularBookingService, ensuring consistency across the booking service architecture.

apps/web/lib/types/booking.ts (1)

1-3: LGTM! Improved type definition.

Replacing the dynamic Awaited<ReturnType<...>> with an explicit RegularBookingCreateResult improves type clarity and maintainability. This aligns with the service-based refactoring.

apps/api/v2/src/lib/services/recurring-booking.service.ts (1)

1-13: LGTM! Proper NestJS service extension.

The RecurringBookingService correctly extends the base class and properly injects RegularBookingService through NestJS DI. The constructor delegation to super follows the expected pattern.

packages/features/bookings/di/InstantBookingCreateService.module.ts (1)

1-20: LGTM! DI module correctly configured.

The module setup properly binds InstantBookingCreateService with an empty dependencies map, which is correct since this service has no constructor dependencies. The moduleLoader export pattern is consistent with other booking service modules.

apps/api/v2/src/lib/modules/recurring-booking.module.ts (1)

1-10: LGTM!

The module wiring is clean and follows NestJS conventions. The RecurringBookingService correctly depends on RegularBookingModule, which provides the RegularBookingService it needs.

apps/api/v2/src/lib/modules/regular-booking.module.ts (1)

15-31: LGTM!

The module correctly wires all dependencies for RegularBookingService. The provider list includes all repositories and services needed, and properly exports RegularBookingService for consumption by other modules. Based on learnings, this aligns with the expected IBookingServiceDependencies pattern and extends it with additional v2-specific dependencies.

Based on learnings.

packages/features/bookings/lib/create-instant-booking.ts (1)

9-10: Acknowledged technical debt for serialization.

The TODO correctly identifies that expires: Date in the type will be serialized to a string over-the-wire. This is acceptable technical debt for a follow-up PR.

packages/features/bookings/types.ts (1)

97-98: LGTM!

The type alias consolidates BookingResponse to use RegularBookingCreateResult, aligning with the service-based refactor. The TODO appropriately acknowledges the naming inconsistency will be addressed in a follow-up PR.

packages/features/bookings/lib/handleNewBooking/test/handleNewRecurringBooking.test.ts (1)

154-161: LGTM!

The test correctly migrates to the service-based approach using getRecurringBookingService() and the new payload structure with bookingData and bookingMeta. The -1 userId appropriately simulates an anonymous user scenario.

packages/features/bookings/lib/bookingCreateBodySchema.ts (2)

60-76: LGTM!

The new recurringBookingCreateBodyPartialSchema appropriately modularizes recurring-specific fields. The optional end field (line 71) is intentional to handle cases where handleNewRecurringBooking may pass end as undefined. As per coding guidelines.


78-100: LGTM!

The restructured schema cleanly separates recurring-specific fields into the partial schema, improving maintainability. The exported ExtendedBookingCreateBody type provides proper typing for consumers.

apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts (2)

113-115: LGTM!

The three new service dependencies (RegularBookingService, RecurringBookingService, InstantBookingCreateService) are correctly injected via the constructor, replacing the previous platform library handler approach.


470-472: LGTM!

Instant bookings correctly use instantBookingCreateService.createBooking with only bookingData (no bookingMeta), which aligns with the instant booking flow that doesn't require metadata like userId or platform URLs.

apps/api/v2/src/lib/services/regular-booking.service.ts (1)

17-46: Verify type cast necessity.

The service correctly extends BaseRegularBookingService and wires dependencies through NestJS DI. However, the type cast on line 35 (prismaWriteService.prisma as unknown as PrismaClient) suggests a type mismatch between the v2 Prisma service and the base service's expected type.

Verify that this type cast is necessary and that there are no type safety concerns. Check if prismaWriteService.prisma and PrismaClient are compatible:

@volnei
Copy link
Copy Markdown
Contributor

volnei commented Oct 9, 2025

@coderabbitai can you please resume where any logic is being changed, if we have any changes.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Oct 9, 2025

Tip

For best results, initiate chat on the files or code changes.

@volnei, based on the AI-generated summaries, this PR is primarily an architectural refactoring with minimal logic changes. Here's a breakdown:

🏗️ Architectural Changes (No Logic Impact)

  1. Dependency Injection Introduction:

    • Replaces direct function calls (handleNewBooking, handleNewRecurringBooking, handleInstantMeeting) with service-based approach
    • New services: RegularBookingService, RecurringBookingService, InstantBookingCreateService
    • Handlers now accept dependencies explicitly via deps parameter instead of constructing them internally
  2. Data Structure Changes:

    • Fields like userId, hostname, forcedSlug, platformClientId, etc. moved from top-level to nested bookingMeta object
    • No change in what data is passed, just how it's structured
  3. Type System Improvements:

    • Replaces Record<string, any> with proper types like RegularBookingCreateResult, InstantBookingCreateResult
    • Better type safety but same runtime behavior
  4. Module Wiring:

    • New DI container files for service instantiation
    • New NestJS modules in API v2 for proper dependency management

🔄 Minimal Logic Changes

The booking creation logic itself appears preserved. The core algorithms, validation, error handling, and booking flow remain unchanged—they're just wrapped in service classes now.

One subtle potential change mentioned in the summaries:

  • In handleNewRecurringBooking.ts: allRecurringDates.start type changed from string | undefined to string (stricter typing)

📍 Files Updated

API Endpoints (all use new services):

  • apps/api/v1/pages/api/bookings/_post.ts
  • apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.ts
  • apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
  • apps/web/pages/api/book/event.ts
  • apps/web/pages/api/book/instant-event.ts
  • apps/web/pages/api/book/recurring-event.ts

Core Logic (now with DI):

  • packages/features/bookings/lib/handleNewBooking.ts
  • packages/features/bookings/lib/handleNewRecurringBooking.ts
  • packages/features/instant-meeting/handleInstantMeeting.ts

Summary: This is a well-structured refactoring that improves testability and maintainability without altering the booking business logic. The changes are primarily about how the code is organized and invoked, not what it does.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/features/bookings/lib/handleNewBooking.ts (1)

1635-1640: Fix attendee lookup to use parsed booker variables.

The attendee lookup should use the already-parsed bookerEmail and bookerPhoneNumber variables instead of accessing bookingData.responses directly, which may have unexpected structure or be undefined.

Apply this diff:

         const currentAttendee = booking.attendees.find(
           (attendee) =>
-            attendee.email === bookingData.responses.email ||
-            (bookingData.responses.attendeePhoneNumber &&
-              attendee.phoneNumber === bookingData.responses.attendeePhoneNumber)
+            attendee.email === bookerEmail ||
+            (bookerPhoneNumber && attendee.phoneNumber === bookerPhoneNumber)
         );
🧹 Nitpick comments (1)
packages/features/bookings/lib/handleNewBooking.ts (1)

2460-2466: Consider consistent bookingMeta handling for clarity.

While spreading undefined is safe in JavaScript (it's a no-op), consider explicitly defaulting bookingMeta to {} for consistency with createBookingForApiV1 (line 2476).

Apply this diff for consistency:

   async createBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }

   async rescheduleBooking(input: { bookingData: CreateRegularBookingData; bookingMeta?: CreateBookingMeta }) {
-    return handler({ bookingData: input.bookingData, ...input.bookingMeta }, this.deps);
+    const bookingMeta = input.bookingMeta ?? {};
+    return handler({ bookingData: input.bookingData, ...bookingMeta }, this.deps);
   }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d134d11 and 266b3d5.

📒 Files selected for processing (3)
  • packages/features/bookings/lib/handleNewBooking.ts (12 hunks)
  • packages/platform/libraries/bookings.ts (1 hunks)
  • packages/platform/libraries/index.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/platform/libraries/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/platform/libraries/bookings.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/features/bookings/lib/handleNewBooking.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

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.

Files:

  • packages/features/bookings/lib/handleNewBooking.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.

Applied to files:

  • packages/features/bookings/lib/handleNewBooking.ts
🧬 Code graph analysis (1)
packages/features/bookings/lib/handleNewBooking.ts (4)
packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
  • CacheService (7-15)
packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
  • CheckBookingAndDurationLimitsService (21-54)
packages/lib/server/repository/booking.ts (1)
  • BookingRepository (124-1049)
packages/features/bookings/lib/dto/types.d.ts (3)
  • BookingHandlerInput (43-45)
  • CreateRegularBookingData (15-15)
  • CreateBookingMeta (35-41)
🪛 Biome (2.1.2)
packages/features/bookings/lib/handleNewBooking.ts

[error] 57-57: Shouldn't redeclare 'enrichHostsWithDelegationCredentials'. Consider to delete it or rename it.

'enrichHostsWithDelegationCredentials' is defined here:

(lint/suspicious/noRedeclare)


[error] 58-58: Shouldn't redeclare 'getFirstDelegationConferencingCredentialAppLocation'. Consider to delete it or rename it.

'getFirstDelegationConferencingCredentialAppLocation' is defined here:

(lint/suspicious/noRedeclare)

⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (2)
packages/features/bookings/lib/handleNewBooking.ts (2)

418-430: LGTM: DI interface is comprehensive.

The IBookingServiceDependencies interface properly defines all required dependencies for the booking service, enabling constructor-based dependency injection.

Based on learnings


432-459: LGTM: DI implementation is clean.

The handler signature and dependency usage correctly implement the dependency injection pattern, accepting deps as a parameter and extracting only the dependencies needed in the immediate scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bookings area: bookings, availability, timezones, double booking core area: core, team members only enterprise area: enterprise, audit log, organisation, SAML, SSO ✨ feature New feature or request ready-for-e2e size/XXL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants