Files
calendar/apps/api/v2
2881961859 feat: add custom calendar reminder for Google Calendar events (#26078)
* feat: add custom calendar reminder for Google Calendar events

Allows users to set default reminder notifications (10, 30, or 60 minutes)
for events created via Cal.com bookings in Google Calendar. This addresses
the issue where Google Calendar's default reminders don't apply to
API-created events.

- Add customCalendarReminder field to DestinationCalendar model
- Create reminder selector UI in destination calendar settings
- Update GoogleCalendarService to apply custom reminders (popup + email)
- Add TRPC endpoint for updating reminder settings

* fix: address code review feedback

- Use z.union with literal values (10, 30, 60) for stricter schema validation
- Add localization for toast messages using t()
- Fix test data to use null for customCalendarReminder to match test intent

* fix: add customCalendarReminder to DestinationCalendar types

Update manually-defined DestinationCalendar types to include the new
customCalendarReminder field added in the previous commit. This fixes
type mismatches when passing Prisma-persisted destination calendars to
functions using these local type definitions.

* fix: update customCalendarReminder type in test to match Prisma schema

The customCalendarReminder field is defined as a non-nullable Int with
default value of 10 in the Prisma schema. Changed test value from null
to 10 to fix TS2345 type error.

* feat: add 'just in time' reminder option for Google Calendar events

- Add 0 (just in time) as a valid reminder option alongside 10, 30, 60 minutes
- Update TRPC schema to accept 0 as valid reminder value
- Add 'Just in time' option to reminder dropdown selector UI
- Add translation for 'just_in_time' key in English locale
- Include comprehensive test case for 0-minute (just in time) reminders
- Remove unused import from test file

This addresses reviewer feedback to provide flexible 'just in time' option that allows reminders to fire at exact event start time.

🤖 Generated with Claude Code

* fix: add customCalendarReminder to calendars service mock

- Add missing customCalendarReminder field to destination calendar mock
- Matches the Prisma schema requirement
- Fixes type error in calendars controller e2e test

* fix: add customCalendarReminder to destination calendars controller test

- Add missing customCalendarReminder field to mock destination calendar
- Matches Prisma schema requirement
- Fixes type error in destination-calendars controller e2e test

* fix: cast customCalendarReminder to ReminderMinutes type

- Add type cast for reminderValue to ensure type safety
- Use nullish coalescing (??) to preserve 0 as valid reminder value
- Ensures database number type is properly cast to ReminderMinutes union

* refactor: simplify translation logic in DestinationReminderSelector

- Remove conditional check for 'just_in_time' label
- Pass count parameter to all translations uniformly
- Translation function handles unused parameters gracefully

Addresses review feedback from @Khaan25

* refactor: make custom calendar reminder opt-in and use repository pattern

- Change default from 10 to null (opt-in feature)
- Add DestinationCalendarRepository to avoid direct Prisma usage
- Add 'Use default reminders' option to UI

* refactor: remove redundant migration file

The original migration already creates customCalendarReminder as nullable,
so this second migration to make it nullable is not needed.

* fix: type error for customCalendarReminder in destination calendar settings

* refactor: validate customCalendarReminder with Zod schema instead of type casting

* refactor: use instance methods in DestinationCalendarRepository

Changed from static to instance methods with getInstance() pattern as requested in review.

* refactor: replace singleton with DI for DestinationCalendarRepository

- Remove getInstance() singleton pattern
- Add DI tokens, module, and container
- Update GoogleCalendarService and tRPC handler to use DI

---------

Co-authored-by: Volnei Munhoz <volnei@cal.com>
Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
2026-01-14 12:32:00 +01:00
..
2026-01-02 12:47:00 +00:00

Nest Logo

A progressive Node.js framework for building efficient and scalable server-side applications.

NPM Version Package License NPM Downloads CircleCI Coverage Discord Backers on Open Collective Sponsors on Open Collective Support us

Description

Cal.com is using the Nest framework TypeScript starter repository.

Installation

$ yarn install

Prisma setup

$ yarn prisma generate

Env setup

Copy .env.example to .env and fill values.

Add license Key to Deployment table in DB

id, logo, theme, licenseKey, agreedLicenseAt:- 1, null, null, '00000000-0000-0000-0000-000000000000', '2023-05-15 21:39:47.611'

Replace with your actual license key.

your CALCOM_LICENSE_KEY env var need to contain the same value

.env CALCOM_LICENSE_KEY=00000000-0000-0000-0000-000000000000

Running the app

Development

$ yarn run start

OR if you don't want to use docker, you can run following command.

$ yarn dev:no-docker

Additionally you can run following command(in different terminal) to ensure that any change in any of the dependencies is rebuilt and detected. It watches platform-libraries, platform-constants, platform-enums, platform-utils, platform-types.

$ yarn run dev:build:watch

If you are making changes in packages/platform/libraries, you should run the following command too that would connect your local packages/platform/libraries to the api/v2

$ yarn local

watch mode

$ yarn run start:dev

production mode

$ yarn run start:prod





## Test

```bash
# unit tests
$ yarn run test

# e2e tests
$ yarn run test:e2e

# e2e tests in watch mode
$ yarn test:e2e:watch 

# run specific e2e test file in watch mode
$ yarn test:e2e:watch --testPathPattern=filePath

# test coverage
$ yarn run test:cov

Conventions

Guards

  1. In case a guard would return "false" for "canActivate" instead throw ForbiddenException with an error message containing guard name and the error.
  2. In case a guard would return "false" for "canActivate" DO NOT cache the result in redis, because we don't want that someone is forbidden, updates whatever was the problem, and then has to wait for cache to expire. We only cache in redis guard results where "canAccess" is "true".
  3. If you use ApiAuthGuard but want that only specific auth method is allowed, for example, api key, then you also need to add @ApiAuthGuardOnlyAllow(["API_KEY"]) under the @UseGuards(ApiAuthGuard). Shortly, use ApiAuthGuardOnlyAllow to specify which auth methods are allowed by ApiAuthGuard. If ApiAuthGuardOnlyAllow is not used or nothing is passed to it or empty array it means that all auth methods are allowed.

Support

Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please read more here.

Stay in touch

License

Nest is MIT licensed.