Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: v2 bookings #16200

Merged
merged 109 commits into from
Sep 23, 2024
Merged

refactor: v2 bookings #16200

merged 109 commits into from
Sep 23, 2024

Conversation

supalarry
Copy link
Contributor

@supalarry supalarry commented Aug 14, 2024

To use this version add cal-api-version: 2024-08-13 request header.

This PR versions existing bookings endpoints under 2024-04-15/controllers/bookings.controller.ts and introduces new endpoints under bookings/2024-08-13/controllers/bookings.controller.ts. There are following endpoints:

  1. Create booking, recurring booking and instant booking
  2. Get booking, recurring booking, or individual recurrence of recurring booking by uid
  3. Get all bookings using filters
  4. Reschedule booking
  5. Cancel booking
  6. Mark host or attendee as absent

2024-08-13/controllers/bookings.controller.e2e-spec.ts tests all of these features and also team event type bookings.

Fixes #16512

1. Create booking, recurring booking and instant booking

POST /v2/bookings is used to create regular bookings, recurring bookings and instant bookings. The request bodies for all 3 are almost the same except:

  1. If eventTypeId in the request body is id of a regular event, then regular booking is created. If it is an id of a recurring event type, then recurring booking is created. Meaning that the request bodies are equal but the outcome depends on what kind of event type it is with the goal of making it as seamless for developers as possible.
  2. For team event types it is possible to create instant meeting. To do that just pass "instant": true to the request body.
  3. the start needs to be in UTC aka if the timezone is GMT+2 in Rome and meeting should start at 11, then UTC time should have hours 09:00 aka without time zone.

Booking

Request body:

{
  "start": "2025-02-21T09:00:00",
  "eventTypeId": 3652,
  "attendee": {
    "timeZone": "Europe/Rome",
    "email": "lauris@example.net",
    "name": "lauris",
    "language": "lv"
  },
  "meetingUrl": "https://daily.co/abc-xyz"
}

Response:

{
  "status": "success",
  "data": {
    "id": 1189,
    "uid": "r66HAHqdmsfUAKxr6yXfjh",
    "hosts": [
      {
        "id": 2457,
        "name": "John Jones",
        "timeZone": "Europe/Madrid"
      }
    ],
    "status": "accepted",
    "start": "2025-02-21T09:00:00.000Z",
    "end": "2025-02-21T10:00:00.000Z",
    "duration": 60,
    "eventTypeId": 3652,
    "attendees": [
      {
        "name": "lauris",
        "timeZone": "Europe/Rome",
        "language": "lv",
        "absent": false
      }
    ],
    "meetingUrl": "https://daily.co/abc-xyz",
    "absentHost": false
  }
}

Recurring booking

The eventTypeId equals to recurring event type.

Request body:

{
  "start": "2025-02-21T10:00:00",
  "eventTypeId": 3687,
  "attendee": {
    "timeZone": "Europe/Rome",
    "email": "lauris@example.net",
    "name": "lauris",
    "language": "lv"
  }
}

Response:

{
  "status": "success",
  "data": [
    {
      "id": 1190,
      "uid": "1pvo6RVzqbgr1hhP6AV4qB",
      "hosts": [
        {
          "id": 2465,
          "name": "twenty-clywuonwt0001regwyzy6subr-onecorp",
          "timeZone": "Europe/Rome"
        }
      ],
      "status": "accepted",
      "start": "2025-02-21T10:00:00.000Z",
      "end": "2025-02-21T11:00:00.000Z",
      "duration": 60,
      "eventTypeId": 3687,
      "recurringBookingUid": "89e7ef26-ec0b-4898-9733-6488264ac438",
      "attendees": [
        {
          "name": "lauris",
          "timeZone": "Europe/Rome",
          "language": "lv",
          "absent": false
        }
      ],
      "meetingUrl": "integrations:daily",
      "absentHost": false
    },
    {
      "id": 1191,
      "uid": "xwiP3mQhdbzNHd1tgyroer",
      "hosts": [
        {
          "id": 2465,
          "name": "twenty-clywuonwt0001regwyzy6subr-onecorp",
          "timeZone": "Europe/Rome"
        }
      ],
      "status": "accepted",
      "start": "2025-02-28T10:00:00.000Z",
      "end": "2025-02-28T11:00:00.000Z",
      "duration": 60,
      "eventTypeId": 3687,
      "recurringBookingUid": "89e7ef26-ec0b-4898-9733-6488264ac438",
      "attendees": [
        {
          "name": "lauris",
          "timeZone": "Europe/Rome",
          "language": "lv",
          "absent": false
        }
      ],
      "meetingUrl": "integrations:daily",
      "absentHost": false
    },
    {
      "id": 1192,
      "uid": "cRveyJUq8169yFL4kBQee7",
      "hosts": [
        {
          "id": 2465,
          "name": "twenty-clywuonwt0001regwyzy6subr-onecorp",
          "timeZone": "Europe/Rome"
        }
      ],
      "status": "accepted",
      "start": "2025-03-07T10:00:00.000Z",
      "end": "2025-03-07T11:00:00.000Z",
      "duration": 60,
      "eventTypeId": 3687,
      "recurringBookingUid": "89e7ef26-ec0b-4898-9733-6488264ac438",
      "attendees": [
        {
          "name": "lauris",
          "timeZone": "Europe/Rome",
          "language": "lv",
          "absent": false
        }
      ],
      "meetingUrl": "integrations:daily",
      "absentHost": false
    }
  ]
}

Instant Booking

The "eventTypeId" must be a team event type and simply add "instant" : true to the request body.

Request:

{
  "instant": true,
  "start": "2026-02-21T09:00:00",
  "eventTypeId": 3680,
  "attendee": {
    "timeZone": "Europe/Rome",
    "email": "lauris@example.net",
    "name": "lauris",
    "language": "lv"
  }
}

2. Get booking, recurring booking, or individual recurrence of recurring booking by uid

Similarly, getting bookings has been simplified. Fetch booking using GET /v2/bookings/:bookingUid . The :bookingUid can be:

  1. uid of a regular booking above e.g. "r66HAHqdmsfUAKxr6yXfjh" above.

  2. uid of one of the recurrences within recurring bookings e.g. "1pvo6RVzqbgr1hhP6AV4qB" above (if its recurring booking with 3 recurrences, then return will be 1 object containing 1 of the 3 occurences)

  3. uid of the recurring booking e.g. "89e7ef26-ec0b-4898-9733-6488264ac438” above stored in the recurringBookingUid key (will return an array of all 3 recurrences)

  4. GET normal booking api/v2/bookings/r66HAHqdmsfUAKxr6yXfjh response:

{
  "status": "success",
  "data": {
    "id": 1189,
    "uid": "r66HAHqdmsfUAKxr6yXfjh",
    "hosts": [
      {
        "id": 2457,
        "name": "John Jones",
        "timeZone": "Europe/Madrid"
      }
    ],
    "status": "accepted",
    "start": "2025-02-21T09:00:00.000Z",
    "end": "2025-02-21T10:00:00.000Z",
    "duration": 60,
    "eventTypeId": 3652,
    "attendees": [
      {
        "name": "lauris",
        "timeZone": "Europe/Rome",
        "language": "lv",
        "absent": false
      }
    ],
    "meetingUrl": "https://daily.co/abc-xyz",
    "absentHost": false
  }
}
  1. GET individual recurrence api/v2/bookings/1pvo6RVzqbgr1hhP6AV4qB response:
    As you see it has recurringBookingUid key.
{
  "status": "success",
  "data": {
    "id": 1190,
    "uid": "1pvo6RVzqbgr1hhP6AV4qB",
    "hosts": [
      {
        "id": 2465,
        "name": "twenty-clywuonwt0001regwyzy6subr-onecorp",
        "timeZone": "Europe/Rome"
      }
    ],
    "status": "accepted",
    "start": "2025-02-21T10:00:00.000Z",
    "end": "2025-02-21T11:00:00.000Z",
    "duration": 60,
    "eventTypeId": 3687,
    "recurringBookingUid": "89e7ef26-ec0b-4898-9733-6488264ac438",
    "attendees": [
      {
        "name": "lauris",
        "timeZone": "Europe/Rome",
        "language": "lv",
        "absent": false
      }
    ],
    "meetingUrl": "integrations:daily",
    "absentHost": false
  }
}
  1. GET recurring booking api/v2/bookings/89e7ef26-ec0b-4898-9733-6488264ac438 response:
{
  "status": "success",
  "data": [
    {
      "id": 1190,
      "uid": "1pvo6RVzqbgr1hhP6AV4qB",
      "hosts": [
        {
          "id": 2465,
          "name": "twenty-clywuonwt0001regwyzy6subr-onecorp",
          "timeZone": "Europe/Rome"
        }
      ],
      "status": "accepted",
      "start": "2025-02-21T10:00:00.000Z",
      "end": "2025-02-21T11:00:00.000Z",
      "duration": 60,
      "eventTypeId": 3687,
      "recurringBookingUid": "89e7ef26-ec0b-4898-9733-6488264ac438",
      "attendees": [
        {
          "name": "lauris",
          "timeZone": "Europe/Rome",
          "language": "lv",
          "absent": false
        }
      ],
      "meetingUrl": "integrations:daily",
      "absentHost": false
    },
    {
      "id": 1191,
      "uid": "xwiP3mQhdbzNHd1tgyroer",
      "hosts": [
        {
          "id": 2465,
          "name": "twenty-clywuonwt0001regwyzy6subr-onecorp",
          "timeZone": "Europe/Rome"
        }
      ],
      "status": "accepted",
      "start": "2025-02-28T10:00:00.000Z",
      "end": "2025-02-28T11:00:00.000Z",
      "duration": 60,
      "eventTypeId": 3687,
      "recurringBookingUid": "89e7ef26-ec0b-4898-9733-6488264ac438",
      "attendees": [
        {
          "name": "lauris",
          "timeZone": "Europe/Rome",
          "language": "lv",
          "absent": false
        }
      ],
      "meetingUrl": "integrations:daily",
      "absentHost": false
    },
    {
      "id": 1192,
      "uid": "cRveyJUq8169yFL4kBQee7",
      "hosts": [
        {
          "id": 2465,
          "name": "twenty-clywuonwt0001regwyzy6subr-onecorp",
          "timeZone": "Europe/Rome"
        }
      ],
      "status": "accepted",
      "start": "2025-03-07T10:00:00.000Z",
      "end": "2025-03-07T11:00:00.000Z",
      "duration": 60,
      "eventTypeId": 3687,
      "recurringBookingUid": "89e7ef26-ec0b-4898-9733-6488264ac438",
      "attendees": [
        {
          "name": "lauris",
          "timeZone": "Europe/Rome",
          "language": "lv",
          "absent": false
        }
      ],
      "meetingUrl": "integrations:daily",
      "absentHost": false
    }
  ]
}

3. Get all bookings using filters

Now let’s see how can we fetch multiple bookings and filters we can use. If you send GET /v2/bookings then you will see all bookings created (1 normal booking + 3 recurrences of a recurring booking). Notably, by default it returns upcoming bookings sorted by soonest meeting on the top.

You can use filters, sorting and pagination query parameters to fetch results as you want.

filters:

  1. status - upcoming, recurring, past, cancelled, unconfirmed e.g.?status=upcoming. Notably, you can pass multiple statuses ?status=past,cancelled which will return past and cancelled meetings.
  2. attendeeEmail - who booked the meeting e.g.?attendeeEmail=lauris@cal.com
  3. attendeeName - who booked the meeting e.g. ?attendeeName=lauris
  4. eventTypeIds - comma separated string containing event type ids for which you want to fetch bookings e.g.
    ?eventTypeIds=3686,3687
  5. eventTypeId - event type for which you want to fetch bookings e.g. ?eventTypeId=3686
  6. teamIds - comma separated string to get bookings of teams where user associated with the auth access token is part of e.g. ?teamIds=686,687
  7. teamId - bookings of a team where user associated with the auth access token is part of e.g. ?teamId=686
  8. afterStart - all bookings with start after this date string e.g. ?afterStart=2025-03-07T10:00:00.000Z
  9. beforeEnd - all bookings with end before this date string e.g. ?beforeEnd=2025-03-07T11:00:00.000Z

sort:

  1. sortStart - sort results by their start time in ascending e.g. ?sortStart=asc or descending ?sortStart=desc order.
  2. sortEnd - sort results by their end time in ascending e.g. ?sortEnd=asc or descending ?sortEnd=desc order.
  3. sortCreated - sort results by their time when the booking was done in ascending ?sortCreated=asc or descending ?sortCreated=desc order.

pagination:

  1. skip - how many results to skip.
  2. take - how many results to return. min value is 1 and max is 250. By default its 100.

4. Reschedule booking

It is possible to reschedule a regular booking or one of the recurrences of a recurring booking by sending a POST request to api/v2/bookings/:bookingUid/reschedule. After rescheduling the new booking will contain reference rescheduledFromUid and rescheduledReason provided in request body.

1. Reschedule normal booking

Request: api/v2/bookings/qM56A2BTnwCKuhitWc1pH5/reschedule
Body: provide new start time in UTC and optionally rescheduling reason:

{
   "start": "2030-01-21T10:00:00",
    "reschedulingReason": "wont have internet"
}

Response:

{
  "status": "success",
  "data": {
    "id": 1194,
    "uid": "qKcFyCSn9qfuj1Ba435EXE",
    "hosts": [
      {
        "id": 2465,
        "name": "twenty-clywuonwt0001regwyzy6subr-onecorp",
        "timeZone": "Europe/Rome"
      }
    ],
    "status": "accepted",
    "reschedulingReason": "wont have internet",
    "rescheduledFromUid": "qM56A2BTnwCKuhitWc1pH5",
    "start": "2030-01-21T10:00:00.000Z",
    "end": "2030-01-21T11:00:00.000Z",
    "duration": 60,
    "eventTypeId": 3686,
    "attendees": [
      {
        "name": "lauris",
        "timeZone": "Europe/Rome",
        "language": "lv",
        "absent": false
      }
    ],
    "meetingUrl": "https://daily.co/abc-xyz",
    "absentHost": false
  }
}

2. Reschedule recurrence of a recurring event

Request URL: api/v2/bookings/1pvo6RVzqbgr1hhP6AV4qB/reschedule
Body:

{
   "start": "2030-01-21T12:00:00",
    "reschedulingReason": "laptop broke"
}

Response:

{
  "status": "success",
  "data": {
    "id": 1212,
    "uid": "fsxHwC9xhrcpV77cx2uzhn",
    "hosts": [
      {
        "id": 2465,
        "name": "twenty-clywuonwt0001regwyzy6subr-onecorp",
        "timeZone": "Europe/Rome"
      }
    ],
    "status": "accepted",
    "reschedulingReason": "laptop broke",
    "rescheduledFromUid": "1pvo6RVzqbgr1hhP6AV4qB",
    "start": "2030-01-23T13:00:00.000Z",
    "end": "2030-01-23T14:00:00.000Z",
    "duration": 60,
    "eventTypeId": 3687,
    "recurringBookingUid": "ce796451-9ca0-453e-bf1c-976f4245b08d",
    "attendees": [
      {
        "name": "lauris",
        "timeZone": "Europe/Rome",
        "language": "lv",
        "absent": false
      }
    ],
    "meetingUrl": "integrations:daily",
    "absentHost": false
  }
}

If we now fetch the recurring booking that has 3 occurences by recurringBookingUid ce796451-9ca0-453e-bf1c-976f4245b08d then we will have array of 4 entries - 1 was changed to status = cancelled aka the one that was rescheduled and there is now a new 4th entry as a reason of the reschedule.

5. Cancel booking

Make request to v2/bookings/:bookingUid/cancel. If :bookingUid is equal to recurringBookingUid of a recurrence of a recurring booking, then all remaining recurrences will be cancelled.

6. Mark host or attendee as absent

Request URL: api/v2/bookings/:bookingUid/mark-absent

Body to mark host absent:

{
   "host": true
}

Body to mark one of the attendees absent:

{
   "attendees": [{email: "supa@gmail.com", absent: true}]
}

Tests

npx jest apps/api/v2/src/ee/bookings/2024-04-15/controllers/bookings.controller.e2e-spec.ts --config jest-e2e.json --detectOpenHandles
npx jest src/ee/bookings/2024-08-13/controllers/bookings.controller.e2e-spec.ts --config jest-e2e.json

Copy link

vercel bot commented Aug 14, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Skipped Deployments
Name Status Preview Comments Updated (UTC)
cal ⬜️ Ignored (Inspect) Visit Preview Sep 23, 2024 11:39am
calcom-web-canary ⬜️ Ignored (Inspect) Visit Preview Sep 23, 2024 11:39am

Copy link

socket-security bot commented Aug 15, 2024

👍 Dependency issues cleared. Learn more about Socket for GitHub ↗︎

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report↗︎

Copy link

socket-security bot commented Sep 21, 2024

New and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher
npm/@esbuild/aix-ppc64@0.21.5 None 0 10.5 MB evanw
npm/@esbuild/android-arm@0.21.5 None 0 11.7 MB evanw
npm/@esbuild/android-arm64@0.21.5 None 0 9.96 MB evanw
npm/@esbuild/android-x64@0.21.5 None 0 11.7 MB evanw
npm/@esbuild/darwin-arm64@0.21.5 None 0 9.86 MB evanw
npm/@esbuild/darwin-x64@0.21.5 None 0 10.3 MB evanw
npm/@esbuild/freebsd-arm64@0.21.5 None 0 8.98 MB evanw
npm/@esbuild/freebsd-x64@0.21.5 None 0 9.71 MB evanw
npm/@esbuild/linux-arm@0.21.5 None 0 9.31 MB evanw
npm/@esbuild/linux-arm64@0.21.5 None 0 8.98 MB evanw
npm/@esbuild/linux-ia32@0.21.5 None 0 9.25 MB evanw
npm/@esbuild/linux-loong64@0.21.5 None 0 9.5 MB evanw
npm/@esbuild/linux-mips64el@0.21.5 None 0 10.6 MB evanw
npm/@esbuild/linux-ppc64@0.21.5 None 0 9.24 MB evanw
npm/@esbuild/linux-riscv64@0.21.5 None 0 9.24 MB evanw
npm/@esbuild/linux-s390x@0.21.5 None 0 10.2 MB evanw
npm/@esbuild/linux-x64@0.21.5 None 0 9.71 MB evanw
npm/@esbuild/netbsd-x64@0.21.5 None 0 9.69 MB evanw
npm/@esbuild/openbsd-x64@0.21.5 None 0 9.73 MB evanw
npm/@esbuild/sunos-x64@0.21.5 None 0 9.69 MB evanw
npm/@esbuild/win32-arm64@0.21.5 None 0 9.08 MB evanw
npm/@esbuild/win32-ia32@0.21.5 None 0 9.56 MB evanw
npm/@esbuild/win32-x64@0.21.5 None 0 9.91 MB evanw
npm/@humanwhocodes/module-importer@1.0.1 unsafe 0 21.2 kB nzakas
npm/@nodelib/fs.scandir@2.1.5 filesystem 0 22.2 kB mrmlnc
npm/@nodelib/fs.stat@2.0.5 filesystem 0 11.8 kB mrmlnc
npm/@nodelib/fs.walk@1.2.8 None 0 26.4 kB mrmlnc
npm/@types/estree@1.0.5 None 0 25.7 kB types
npm/@types/ms@0.7.31 None 0 2.88 kB types
npm/@vitest/expect@2.1.1 None 0 149 kB vitestbot
npm/@vitest/mocker@2.1.1 None 0 121 kB vitestbot
npm/@vitest/pretty-format@2.1.1 environment 0 45.3 kB vitestbot
npm/@vitest/runner@2.1.1 None 0 87.9 kB vitestbot
npm/@vitest/snapshot@2.1.1 None 0 0 B
npm/@vitest/spy@2.1.1 None 0 19.1 kB vitestbot
npm/@vitest/utils@2.1.1 None 0 153 kB antfu, oreanno, patak, ...1 more
npm/acorn-jsx@5.3.2 None 0 24.4 kB rreverser
npm/ajv@6.12.6 eval 0 929 kB esp
npm/ansi-styles@4.3.0 None 0 17 kB sindresorhus
npm/array-union@2.1.0 None 0 3.17 kB sindresorhus
npm/assertion-error@2.0.1 None 0 5.83 kB chaijs
npm/balanced-match@1.0.2 None 0 6.94 kB juliangruber
npm/cac@6.7.14 None 0 81.8 kB egoist
npm/callsites@3.1.0 None 0 6.33 kB sindresorhus
npm/chai@5.1.1 None 0 506 kB chaijs
npm/check-error@2.1.1 None 0 11.4 kB chaijs
npm/chownr@2.0.0 filesystem 0 5.75 kB isaacs
npm/color-convert@2.0.1 None 0 27.2 kB qix
npm/concat-map@0.0.1 None 0 4.86 kB substack
npm/cross-spawn@7.0.3 environment, filesystem, shell 0 21.2 kB satazor
npm/debug@4.3.4 environment 0 42.4 kB qix
npm/deep-eql@5.0.2 None 0 23.9 kB chaijs
npm/deep-is@0.1.4 None 0 8.11 kB thlorenz
npm/dir-glob@3.0.1 None 0 5.42 kB sindresorhus
npm/doctrine@3.0.0 None 0 106 kB eslint
npm/encoding@0.1.13 None 0 7.12 kB andris
npm/env-paths@2.2.1 None 0 10.2 kB sindresorhus
npm/err-code@2.0.3 None 0 12.3 kB achingbrain
npm/esbuild@0.21.5 environment, filesystem, network, shell 0 133 kB evanw
npm/escalade@3.1.1 filesystem 0 11.4 kB lukeed
npm/esrecurse@4.3.0 None 0 13.5 kB michaelficarra
npm/estraverse@5.3.0 None 0 37.1 kB michaelficarra
npm/estree-walker@3.0.3 None 0 17.6 kB rich_harris
npm/esutils@2.0.3 None 0 50.6 kB michaelficarra
npm/execa@5.1.1 environment, shell 0 57.5 kB sindresorhus
npm/fast-deep-equal@3.1.3 None 0 13 kB esp
npm/fast-json-stable-stringify@2.1.0 None 0 17 kB esp
npm/fast-levenshtein@2.0.6 None 0 9.44 kB hiddentao
npm/file-entry-cache@6.0.1 filesystem 0 25.6 kB royriojas
npm/find-up@5.0.0 None 0 11.8 kB sindresorhus
npm/flat-cache@3.0.4 filesystem 0 30 kB royriojas
npm/get-caller-file@2.0.5 None 0 4.72 kB stefanpenner
npm/get-func-name@2.0.2 None 0 8.68 kB keithamus
npm/get-stream@6.0.1 None 0 12.2 kB sindresorhus
npm/globby@11.1.0 filesystem 0 21.8 kB sindresorhus
npm/http-cache-semantics@4.1.1 None 0 35.9 kB kornel
npm/human-signals@2.1.0 None 0 44.3 kB ehmicky
npm/import-fresh@3.3.0 None 0 4.87 kB sindresorhus
npm/imurmurhash@0.1.4 None 0 11.9 kB jensyt
npm/indent-string@4.0.0 None 0 4.4 kB sindresorhus
npm/is-extglob@2.1.1 None 0 6.22 kB jonschlinkert
npm/is-fullwidth-code-point@3.0.0 None 0 4.99 kB sindresorhus
npm/is-glob@4.0.3 None 0 13.6 kB phated
npm/is-lambda@1.0.1 None 0 2.94 kB watson
npm/is-number@7.0.0 None 0 9.62 kB jonschlinkert
npm/is-path-inside@3.0.3 None 0 4.12 kB sindresorhus
npm/js-yaml@4.1.0 None 0 405 kB vitaly
npm/json-stable-stringify-without-jsonify@1.0.1 None 0 14.2 kB samn
npm/levn@0.4.1 None 0 24.9 kB gkz
npm/locate-path@6.0.0 filesystem 0 7.02 kB sindresorhus
npm/lodash.merge@4.6.2 None 0 54.1 kB jdalton
npm/loupe@3.1.1 None 0 60.5 kB chaijs
npm/magic-string@0.30.11 None 0 464 kB antfu
npm/merge-stream@2.0.0 None 0 4.31 kB stevemao
npm/merge2@1.4.1 None 0 8.9 kB zensh
npm/mimic-fn@2.1.0 None 0 4.46 kB sindresorhus
npm/minipass-flush@1.0.5 None 0 3.77 kB isaacs
npm/minipass-pipeline@1.2.4 None 0 7 kB isaacs
npm/minipass-sized@1.0.3 None 0 124 kB isaacs
npm/minizlib@2.1.2 None 0 17.3 kB isaacs
npm/mkdirp@1.0.4 environment, filesystem 0 19.1 kB isaacs
npm/ms@2.1.2 None 0 6.84 kB styfle
npm/nanoid@3.3.7 None 0 24.4 kB ai
npm/natural-compare@1.4.0 None 0 5.65 kB megawac
npm/negotiator@0.6.3 None 0 27.4 kB dougwilson
npm/npm-run-path@4.0.1 environment 0 8.13 kB sindresorhus
npm/onetime@5.1.2 None 0 6.17 kB sindresorhus
npm/p-limit@3.1.0 None 0 7.75 kB sindresorhus
npm/p-locate@5.0.0 None 0 7.24 kB sindresorhus
npm/parent-module@1.0.1 None 0 3.92 kB sindresorhus
npm/path-parse@1.0.7 None 0 4.51 kB jbgutierrez
npm/path-type@4.0.0 filesystem 0 5.41 kB sindresorhus
npm/pathe@1.1.2 None 0 30.8 kB pi0
npm/pathval@2.0.0 None 0 15 kB chaijs
npm/picocolors@1.1.0 environment 0 11.4 kB alexeyraspopov
npm/picomatch@2.3.1 None 0 90 kB mrmlnc
npm/prelude-ls@1.2.1 None 0 36.7 kB gkz
npm/promise-inflight@1.0.1 None 0 3.04 kB iarna
npm/promise-retry@2.0.1 None 0 15.6 kB achingbrain
npm/punycode@2.1.1 None 0 32.4 kB mathias
npm/require-directory@2.1.1 filesystem 0 12.1 kB troygoode
npm/resolve-from@4.0.0 filesystem, unsafe 0 4.64 kB sindresorhus
npm/retry@0.12.0 None 0 32.2 kB tim-kos
npm/reusify@1.0.4 None 0 9.44 kB matteo.collina
npm/rimraf@3.0.2 filesystem 0 17.3 kB isaacs
npm/safer-buffer@2.1.2 None 0 42.3 kB chalker
npm/shebang-regex@3.0.0 None 0 2.83 kB sindresorhus
npm/siginfo@2.0.0 None 0 4.79 kB emilbayes
npm/slash@3.0.0 None 0 3.51 kB sindresorhus
npm/smart-buffer@4.2.0 None 0 138 kB joshglazebrook
npm/source-map-js@1.2.1 None 0 140 kB 7rulnik
npm/spdx-expression-parse@3.0.1 None 0 11.8 kB kemitchell
npm/stackback@0.0.2 None 0 6.88 kB shtylman
npm/std-env@3.7.0 None 0 26.2 kB pi0
npm/string-width@4.2.3 None 0 5.16 kB sindresorhus
npm/strip-final-newline@2.0.0 None 0 3.05 kB sindresorhus
npm/strip-json-comments@3.1.1 None 0 6.96 kB sindresorhus
npm/supports-preserve-symlinks-flag@1.0.0 None 0 9.18 kB ljharb
npm/text-table@0.2.0 None 0 11 kB substack
npm/tinybench@2.9.0 None 0 62.9 kB aslemammad
npm/tinyexec@0.3.0 environment, shell 0 45.4 kB 43081j
npm/tinypool@1.0.1 filesystem, shell, unsafe 0 49.9 kB ariperkkio
npm/tinyrainbow@1.2.0 None 0 7.91 kB oreanno
npm/tinyspy@3.0.2 None 0 17.6 kB antfu, aslemammad, oreanno
npm/to-regex-range@5.0.1 None 0 22.9 kB jonschlinkert
npm/tslib@2.6.2 None 0 84 kB typescript-bot
npm/type-check@0.4.0 None 0 21.2 kB gkz
npm/uri-js@4.4.1 None 0 470 kB garycourt
npm/validate-npm-package-license@3.0.4 None 0 16.6 kB kemitchell
npm/vite-node@2.1.1 None 0 202 kB antfu, oreanno, patak, ...1 more
npm/why-is-node-running@2.3.0 filesystem, unsafe 0 7.3 kB mafintosh

🚮 Removed packages: npm/@formkit/auto-animate@1.0.0-beta.5

View full report↗︎

@ThyMinimalDev ThyMinimalDev merged commit 0eabe7f into main Sep 23, 2024
38 checks passed
@ThyMinimalDev ThyMinimalDev deleted the v2-refactor-bookings branch September 23, 2024 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api area: API, enterprise API, access token, OAuth bookings area: bookings, availability, timezones, double booking core area: core, team members only ✨ feature New feature or request Medium priority Created by Linear-GitHub Sync platform Anything related to our platform plan ready-for-e2e
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bookings approved via the api do not land on destination calendars
4 participants