From 3a22fdb4280efdcf76ff1a9ffcd0dd8ca883c543 Mon Sep 17 00:00:00 2001 From: Keith Williams Date: Tue, 4 Jun 2024 12:05:39 -0300 Subject: [PATCH] feat: API v2 subversioning (#15135) * feat: API v2 subversioning * Update app.ts * Added multiple versions to existing controllers * Updated the slots controller * chore: version platform library package with npm package alias * chore: use consts to version * chore: use consts to version * chore: version api for cal provider * chore: remove timezone controller subversion poc * fixup! Merge branch 'main' into feat/api-v2-subversioning --------- Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: Morgan Vernay --- apps/api/v2/package.json | 2 +- apps/api/v2/src/app.module.ts | 2 -- apps/api/v2/src/app.ts | 33 ++++++++++++++++--- .../bookings.controller.e2e-spec.ts | 2 +- .../controllers/bookings.controller.ts | 9 ++--- .../inputs/create-recurring-booking.input.ts | 2 +- .../controllers/calendars.controller.ts | 5 +-- .../calendars/services/calendars.service.ts | 4 +-- .../event-types.controller.e2e-spec.ts | 2 +- .../controllers/event-types.controller.ts | 9 ++--- .../ee/event-types/event-types.repository.ts | 2 +- .../services/event-types.service.ts | 4 +-- apps/api/v2/src/ee/gcal/gcal.controller.ts | 5 +-- apps/api/v2/src/ee/me/me.controller.ts | 5 +-- .../v2/src/ee/provider/provider.controller.ts | 5 +-- .../controllers/schedules.controller.ts | 5 +-- .../schedules/services/schedules.service.ts | 6 ++-- .../v2/src/filters/trpc-exception.filter.ts | 2 +- apps/api/v2/src/lib/api-versions.ts | 7 ++++ .../billing/controllers/billing.controller.ts | 5 +-- .../oauth-client-users.controller.ts | 5 +-- .../oauth-clients/oauth-clients.controller.ts | 5 +-- .../oauth-flow/oauth-flow.controller.ts | 5 +-- .../services/oauth-clients-users.service.ts | 2 +- .../slots/controllers/slots.controller.ts | 9 ++--- .../v2/src/modules/slots/slots.repository.ts | 2 +- .../controllers/timezones.controller.ts | 7 ++-- .../timezones/services/timezones.service.ts | 4 +-- .../atoms/cal-provider/CalProvider.tsx | 15 +++++++-- packages/platform/atoms/lib/http.ts | 12 +++++-- packages/platform/constants/api.ts | 8 ++++- 31 files changed, 128 insertions(+), 62 deletions(-) create mode 100644 apps/api/v2/src/lib/api-versions.ts diff --git a/apps/api/v2/package.json b/apps/api/v2/package.json index da0cde4891..c2dc3fd31a 100644 --- a/apps/api/v2/package.json +++ b/apps/api/v2/package.json @@ -25,7 +25,7 @@ }, "dependencies": { "@calcom/platform-constants": "*", - "@calcom/platform-libraries": "0.0.2", + "@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2", "@calcom/platform-types": "*", "@calcom/platform-utils": "*", "@calcom/prisma": "*", diff --git a/apps/api/v2/src/app.module.ts b/apps/api/v2/src/app.module.ts index 7b42702be6..ea4ab52594 100644 --- a/apps/api/v2/src/app.module.ts +++ b/apps/api/v2/src/app.module.ts @@ -50,8 +50,6 @@ import { AppController } from "./app.controller"; EndpointsModule, AuthModule, JwtModule, - //register prefix for all routes in EndpointsModule - RouterModule.register([{ path: "/v2", module: EndpointsModule }]), ], controllers: [AppController], providers: [ diff --git a/apps/api/v2/src/app.ts b/apps/api/v2/src/app.ts index eb798b2cc5..76fe3f209d 100644 --- a/apps/api/v2/src/app.ts +++ b/apps/api/v2/src/app.ts @@ -9,18 +9,33 @@ import { HttpAdapterHost } from "@nestjs/core"; import type { NestExpressApplication } from "@nestjs/platform-express"; import * as Sentry from "@sentry/node"; import * as cookieParser from "cookie-parser"; +import { Request } from "express"; import helmet from "helmet"; -import { X_CAL_CLIENT_ID, X_CAL_SECRET_KEY } from "@calcom/platform-constants"; +import { + API_VERSIONS, + VERSION_2024_04_15, + API_VERSIONS_ENUM, + CAL_API_VERSION_HEADER, + X_CAL_CLIENT_ID, + X_CAL_SECRET_KEY, +} from "@calcom/platform-constants"; import { TRPCExceptionFilter } from "./filters/trpc-exception.filter"; export const bootstrap = (app: NestExpressApplication): NestExpressApplication => { app.enableShutdownHooks(); + app.enableVersioning({ - type: VersioningType.URI, - prefix: "v", - defaultVersion: "1", + type: VersioningType.CUSTOM, + extractor: (request: unknown) => { + const headerVersion = (request as Request)?.headers[CAL_API_VERSION_HEADER] as string | undefined; + if (headerVersion && API_VERSIONS.includes(headerVersion as API_VERSIONS_ENUM)) { + return headerVersion; + } + return VERSION_2024_04_15; + }, + defaultVersion: VERSION_2024_04_15, }); app.use(helmet()); @@ -28,7 +43,15 @@ export const bootstrap = (app: NestExpressApplication): NestExpressApplication = app.enableCors({ origin: "*", methods: ["GET", "PATCH", "DELETE", "HEAD", "POST", "PUT", "OPTIONS"], - allowedHeaders: [X_CAL_CLIENT_ID, X_CAL_SECRET_KEY, "Accept", "Authorization", "Content-Type", "Origin"], + allowedHeaders: [ + X_CAL_CLIENT_ID, + X_CAL_SECRET_KEY, + CAL_API_VERSION_HEADER, + "Accept", + "Authorization", + "Content-Type", + "Origin", + ], maxAge: 86_400, }); diff --git a/apps/api/v2/src/ee/bookings/controllers/bookings.controller.e2e-spec.ts b/apps/api/v2/src/ee/bookings/controllers/bookings.controller.e2e-spec.ts index 891a8e7b62..bce678bc80 100644 --- a/apps/api/v2/src/ee/bookings/controllers/bookings.controller.e2e-spec.ts +++ b/apps/api/v2/src/ee/bookings/controllers/bookings.controller.e2e-spec.ts @@ -20,7 +20,7 @@ import { UserRepositoryFixture } from "test/fixtures/repository/users.repository import { withAccessTokenAuth } from "test/utils/withAccessTokenAuth"; import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants"; -import { handleNewBooking } from "@calcom/platform-libraries"; +import { handleNewBooking } from "@calcom/platform-libraries-0.0.2"; import { ApiSuccessResponse, ApiResponse } from "@calcom/platform-types"; describe("Bookings Endpoints", () => { diff --git a/apps/api/v2/src/ee/bookings/controllers/bookings.controller.ts b/apps/api/v2/src/ee/bookings/controllers/bookings.controller.ts index 0453964828..32b48bb6a6 100644 --- a/apps/api/v2/src/ee/bookings/controllers/bookings.controller.ts +++ b/apps/api/v2/src/ee/bookings/controllers/bookings.controller.ts @@ -2,6 +2,7 @@ import { CreateBookingInput } from "@/ee/bookings/inputs/create-booking.input"; import { CreateRecurringBookingInput } from "@/ee/bookings/inputs/create-recurring-booking.input"; import { GetBookingOutput } from "@/ee/bookings/outputs/get-booking.output"; import { GetBookingsOutput } from "@/ee/bookings/outputs/get-bookings.output"; +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator"; import { Permissions } from "@/modules/auth/decorators/permissions/permissions.decorator"; import { AccessTokenGuard } from "@/modules/auth/guards/access-token/access-token.guard"; @@ -37,14 +38,14 @@ import { getBookingInfo, handleCancelBooking, getBookingForReschedule, -} from "@calcom/platform-libraries"; +} from "@calcom/platform-libraries-0.0.2"; import { handleNewBooking, BookingResponse, HttpError, handleNewRecurringBooking, handleInstantMeeting, -} from "@calcom/platform-libraries"; +} from "@calcom/platform-libraries-0.0.2"; import { GetBookingsInput, CancelBookingInput, Status } from "@calcom/platform-types"; import { ApiResponse } from "@calcom/platform-types"; import { PrismaClient } from "@calcom/prisma"; @@ -72,8 +73,8 @@ const DEFAULT_PLATFORM_PARAMS = { }; @Controller({ - path: "/bookings", - version: "2", + path: "/v2/bookings", + version: API_VERSIONS_VALUES, }) @UseGuards(PermissionsGuard) @DocsTags("Bookings") diff --git a/apps/api/v2/src/ee/bookings/inputs/create-recurring-booking.input.ts b/apps/api/v2/src/ee/bookings/inputs/create-recurring-booking.input.ts index 471e8ab8df..138215b8d5 100644 --- a/apps/api/v2/src/ee/bookings/inputs/create-recurring-booking.input.ts +++ b/apps/api/v2/src/ee/bookings/inputs/create-recurring-booking.input.ts @@ -1,7 +1,7 @@ import { CreateBookingInput } from "@/ee/bookings/inputs/create-booking.input"; import { IsBoolean, IsNumber, IsOptional } from "class-validator"; -import type { AppsStatus } from "@calcom/platform-libraries"; +import type { AppsStatus } from "@calcom/platform-libraries-0.0.2"; export class CreateRecurringBookingInput extends CreateBookingInput { @IsBoolean() diff --git a/apps/api/v2/src/ee/calendars/controllers/calendars.controller.ts b/apps/api/v2/src/ee/calendars/controllers/calendars.controller.ts index 2cfb9b4de9..0d95327fc3 100644 --- a/apps/api/v2/src/ee/calendars/controllers/calendars.controller.ts +++ b/apps/api/v2/src/ee/calendars/controllers/calendars.controller.ts @@ -3,6 +3,7 @@ import { ConnectedCalendarsOutput } from "@/ee/calendars/outputs/connected-calen import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { GoogleCalendarService } from "@/ee/calendars/services/gcal.service"; import { OutlookService } from "@/ee/calendars/services/outlook.service"; +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator"; import { Permissions } from "@/modules/auth/decorators/permissions/permissions.decorator"; import { AccessTokenGuard } from "@/modules/auth/guards/access-token/access-token.guard"; @@ -30,8 +31,8 @@ import { SUCCESS_STATUS, CALENDARS, GOOGLE_CALENDAR, OFFICE_365_CALENDAR } from import { ApiResponse, CalendarBusyTimesInput } from "@calcom/platform-types"; @Controller({ - path: "/calendars", - version: "2", + path: "/v2/calendars", + version: API_VERSIONS_VALUES, }) @DocsTags("Calendars") export class CalendarsController { diff --git a/apps/api/v2/src/ee/calendars/services/calendars.service.ts b/apps/api/v2/src/ee/calendars/services/calendars.service.ts index 7d6ab93891..37b7ed44a1 100644 --- a/apps/api/v2/src/ee/calendars/services/calendars.service.ts +++ b/apps/api/v2/src/ee/calendars/services/calendars.service.ts @@ -17,8 +17,8 @@ import { User } from "@prisma/client"; import { DateTime } from "luxon"; import { z } from "zod"; -import { getConnectedDestinationCalendars } from "@calcom/platform-libraries"; -import { getBusyCalendarTimes } from "@calcom/platform-libraries"; +import { getConnectedDestinationCalendars } from "@calcom/platform-libraries-0.0.2"; +import { getBusyCalendarTimes } from "@calcom/platform-libraries-0.0.2"; import { Calendar } from "@calcom/platform-types"; import { PrismaClient } from "@calcom/prisma"; diff --git a/apps/api/v2/src/ee/event-types/controllers/event-types.controller.e2e-spec.ts b/apps/api/v2/src/ee/event-types/controllers/event-types.controller.e2e-spec.ts index c561bcd2f1..b589944e38 100644 --- a/apps/api/v2/src/ee/event-types/controllers/event-types.controller.e2e-spec.ts +++ b/apps/api/v2/src/ee/event-types/controllers/event-types.controller.e2e-spec.ts @@ -30,7 +30,7 @@ import { EventTypesPublic, eventTypeBookingFields, eventTypeLocations, -} from "@calcom/platform-libraries"; +} from "@calcom/platform-libraries-0.0.2"; import { ApiSuccessResponse } from "@calcom/platform-types"; describe("Event types Endpoints", () => { diff --git a/apps/api/v2/src/ee/event-types/controllers/event-types.controller.ts b/apps/api/v2/src/ee/event-types/controllers/event-types.controller.ts index 557f55809b..21e28c5654 100644 --- a/apps/api/v2/src/ee/event-types/controllers/event-types.controller.ts +++ b/apps/api/v2/src/ee/event-types/controllers/event-types.controller.ts @@ -9,6 +9,7 @@ import { GetEventTypesPublicOutput } from "@/ee/event-types/outputs/get-event-ty import { GetEventTypesData, GetEventTypesOutput } from "@/ee/event-types/outputs/get-event-types.output"; import { UpdateEventTypeOutput } from "@/ee/event-types/outputs/update-event-type.output"; import { EventTypesService } from "@/ee/event-types/services/event-types.service"; +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator"; import { Permissions } from "@/modules/auth/decorators/permissions/permissions.decorator"; import { AccessTokenGuard } from "@/modules/auth/guards/access-token/access-token.guard"; @@ -33,13 +34,13 @@ import { import { ApiTags as DocsTags } from "@nestjs/swagger"; import { EVENT_TYPE_READ, EVENT_TYPE_WRITE, SUCCESS_STATUS } from "@calcom/platform-constants"; -import { getPublicEvent } from "@calcom/platform-libraries"; -import { getEventTypesByViewer } from "@calcom/platform-libraries"; +import { getPublicEvent } from "@calcom/platform-libraries-0.0.2"; +import { getEventTypesByViewer } from "@calcom/platform-libraries-0.0.2"; import { PrismaClient } from "@calcom/prisma"; @Controller({ - path: "event-types", - version: "2", + path: "/v2/event-types", + version: API_VERSIONS_VALUES, }) @UseGuards(PermissionsGuard) @DocsTags("Event types") diff --git a/apps/api/v2/src/ee/event-types/event-types.repository.ts b/apps/api/v2/src/ee/event-types/event-types.repository.ts index cc696cdd12..c879aa080e 100644 --- a/apps/api/v2/src/ee/event-types/event-types.repository.ts +++ b/apps/api/v2/src/ee/event-types/event-types.repository.ts @@ -4,7 +4,7 @@ import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { UserWithProfile } from "@/modules/users/users.repository"; import { Injectable } from "@nestjs/common"; -import { getEventTypeById } from "@calcom/platform-libraries"; +import { getEventTypeById } from "@calcom/platform-libraries-0.0.2"; import type { PrismaClient } from "@calcom/prisma"; @Injectable() diff --git a/apps/api/v2/src/ee/event-types/services/event-types.service.ts b/apps/api/v2/src/ee/event-types/services/event-types.service.ts index 3b84a609d9..83c5e264fc 100644 --- a/apps/api/v2/src/ee/event-types/services/event-types.service.ts +++ b/apps/api/v2/src/ee/event-types/services/event-types.service.ts @@ -9,8 +9,8 @@ import { SelectedCalendarsRepository } from "@/modules/selected-calendars/select import { UserWithProfile, UsersRepository } from "@/modules/users/users.repository"; import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from "@nestjs/common"; -import { createEventType, updateEventType } from "@calcom/platform-libraries"; -import { getEventTypesPublic, EventTypesPublic } from "@calcom/platform-libraries"; +import { createEventType, updateEventType } from "@calcom/platform-libraries-0.0.2"; +import { getEventTypesPublic, EventTypesPublic } from "@calcom/platform-libraries-0.0.2"; import { EventType } from "@calcom/prisma/client"; @Injectable() diff --git a/apps/api/v2/src/ee/gcal/gcal.controller.ts b/apps/api/v2/src/ee/gcal/gcal.controller.ts index 6eff8d60eb..6afb1eb282 100644 --- a/apps/api/v2/src/ee/gcal/gcal.controller.ts +++ b/apps/api/v2/src/ee/gcal/gcal.controller.ts @@ -2,6 +2,7 @@ import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { GcalAuthUrlOutput } from "@/ee/gcal/outputs/auth-url.output"; import { GcalCheckOutput } from "@/ee/gcal/outputs/check.output"; import { GcalSaveRedirectOutput } from "@/ee/gcal/outputs/save-redirect.output"; +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { GCalService } from "@/modules/apps/services/gcal.service"; import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator"; import { Permissions } from "@/modules/auth/decorators/permissions/permissions.decorator"; @@ -40,8 +41,8 @@ const CALENDAR_SCOPES = [ // Controller for the GCalConnect Atom @Controller({ - path: "/gcal", - version: "2", + path: "/v2/gcal", + version: API_VERSIONS_VALUES, }) @DocsTags("Google Calendar") export class GcalController { diff --git a/apps/api/v2/src/ee/me/me.controller.ts b/apps/api/v2/src/ee/me/me.controller.ts index 2c64df0397..584ff571ff 100644 --- a/apps/api/v2/src/ee/me/me.controller.ts +++ b/apps/api/v2/src/ee/me/me.controller.ts @@ -1,6 +1,7 @@ import { GetMeOutput } from "@/ee/me/outputs/get-me.output"; import { UpdateMeOutput } from "@/ee/me/outputs/update-me.output"; import { SchedulesService } from "@/ee/schedules/services/schedules.service"; +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator"; import { Permissions } from "@/modules/auth/decorators/permissions/permissions.decorator"; import { AccessTokenGuard } from "@/modules/auth/guards/access-token/access-token.guard"; @@ -14,8 +15,8 @@ import { PROFILE_READ, PROFILE_WRITE, SUCCESS_STATUS } from "@calcom/platform-co import { userSchemaResponse } from "@calcom/platform-types"; @Controller({ - path: "/me", - version: "2", + path: "/v2/me", + version: API_VERSIONS_VALUES, }) @UseGuards(AccessTokenGuard, PermissionsGuard) @DocsTags("Me") diff --git a/apps/api/v2/src/ee/provider/provider.controller.ts b/apps/api/v2/src/ee/provider/provider.controller.ts index 40230e2a27..3059f6818c 100644 --- a/apps/api/v2/src/ee/provider/provider.controller.ts +++ b/apps/api/v2/src/ee/provider/provider.controller.ts @@ -1,5 +1,6 @@ import { ProviderVerifyAccessTokenOutput } from "@/ee/provider/outputs/verify-access-token.output"; import { ProviderVerifyClientOutput } from "@/ee/provider/outputs/verify-client.output"; +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator"; import { AccessTokenGuard } from "@/modules/auth/guards/access-token/access-token.guard"; import { OAuthClientRepository } from "@/modules/oauth-clients/oauth-client.repository"; @@ -20,8 +21,8 @@ import { ApiTags as DocsTags } from "@nestjs/swagger"; import { SUCCESS_STATUS } from "@calcom/platform-constants"; @Controller({ - path: "/provider", - version: "2", + path: "/v2/provider", + version: API_VERSIONS_VALUES, }) @DocsTags("Cal provider") export class CalProviderController { diff --git a/apps/api/v2/src/ee/schedules/controllers/schedules.controller.ts b/apps/api/v2/src/ee/schedules/controllers/schedules.controller.ts index b2860cfe5e..50cb8e0897 100644 --- a/apps/api/v2/src/ee/schedules/controllers/schedules.controller.ts +++ b/apps/api/v2/src/ee/schedules/controllers/schedules.controller.ts @@ -5,6 +5,7 @@ import { GetScheduleOutput } from "@/ee/schedules/outputs/get-schedule.output"; import { GetSchedulesOutput } from "@/ee/schedules/outputs/get-schedules.output"; import { UpdateScheduleOutput } from "@/ee/schedules/outputs/update-schedule.output"; import { SchedulesService } from "@/ee/schedules/services/schedules.service"; +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator"; import { Permissions } from "@/modules/auth/decorators/permissions/permissions.decorator"; import { AccessTokenGuard } from "@/modules/auth/guards/access-token/access-token.guard"; @@ -31,8 +32,8 @@ import { UpdateScheduleInput } from "@calcom/platform-types"; import { CreateScheduleInput } from "../inputs/create-schedule.input"; @Controller({ - path: "schedules", - version: "2", + path: "/v2/schedules", + version: API_VERSIONS_VALUES, }) @UseGuards(AccessTokenGuard, PermissionsGuard) @DocsTags("Schedules") diff --git a/apps/api/v2/src/ee/schedules/services/schedules.service.ts b/apps/api/v2/src/ee/schedules/services/schedules.service.ts index c91176e422..2e40a5c5dd 100644 --- a/apps/api/v2/src/ee/schedules/services/schedules.service.ts +++ b/apps/api/v2/src/ee/schedules/services/schedules.service.ts @@ -7,13 +7,13 @@ import { BadRequestException, ForbiddenException, Injectable, NotFoundException import { Schedule } from "@prisma/client"; import { User } from "@prisma/client"; -import type { ScheduleWithAvailabilities } from "@calcom/platform-libraries"; -import { updateScheduleHandler } from "@calcom/platform-libraries"; +import type { ScheduleWithAvailabilities } from "@calcom/platform-libraries-0.0.2"; +import { updateScheduleHandler } from "@calcom/platform-libraries-0.0.2"; import { transformWorkingHoursForClient, transformAvailabilityForClient, transformDateOverridesForClient, -} from "@calcom/platform-libraries"; +} from "@calcom/platform-libraries-0.0.2"; import { UpdateScheduleInput } from "@calcom/platform-types"; @Injectable() diff --git a/apps/api/v2/src/filters/trpc-exception.filter.ts b/apps/api/v2/src/filters/trpc-exception.filter.ts index 47dbcd00b4..5c195349f9 100644 --- a/apps/api/v2/src/filters/trpc-exception.filter.ts +++ b/apps/api/v2/src/filters/trpc-exception.filter.ts @@ -2,7 +2,7 @@ import { ArgumentsHost, Catch, ExceptionFilter, Logger } from "@nestjs/common"; import { Request } from "express"; import { ERROR_STATUS } from "@calcom/platform-constants"; -import { TRPCError } from "@calcom/platform-libraries"; +import { TRPCError } from "@calcom/platform-libraries-0.0.2"; import { Response } from "@calcom/platform-types"; @Catch(TRPCError) diff --git a/apps/api/v2/src/lib/api-versions.ts b/apps/api/v2/src/lib/api-versions.ts new file mode 100644 index 0000000000..57537d5e80 --- /dev/null +++ b/apps/api/v2/src/lib/api-versions.ts @@ -0,0 +1,7 @@ +import { VersionValue } from "@nestjs/common/interfaces"; + +import { API_VERSIONS, VERSION_2024_04_15, VERSION_2024_05_21 } from "@calcom/platform-constants"; + +export const API_VERSIONS_VALUES: VersionValue = API_VERSIONS as unknown as VersionValue; +export const VERSION_2024_05_21_VALUE: VersionValue = VERSION_2024_05_21 as unknown as VersionValue; +export const VERSION_2024_04_15_VALUE: VersionValue = VERSION_2024_04_15 as unknown as VersionValue; diff --git a/apps/api/v2/src/modules/billing/controllers/billing.controller.ts b/apps/api/v2/src/modules/billing/controllers/billing.controller.ts index f216b41ae4..828ada839f 100644 --- a/apps/api/v2/src/modules/billing/controllers/billing.controller.ts +++ b/apps/api/v2/src/modules/billing/controllers/billing.controller.ts @@ -1,4 +1,5 @@ import { AppConfig } from "@/config/type"; +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { Roles } from "@/modules/auth/decorators/roles/roles.decorator"; import { NextAuthGuard } from "@/modules/auth/guards/next-auth/next-auth.guard"; import { OrganizationRolesGuard } from "@/modules/auth/guards/organization-roles/organization-roles.guard"; @@ -29,8 +30,8 @@ import { Stripe } from "stripe"; import { ApiResponse } from "@calcom/platform-types"; @Controller({ - path: "/billing", - version: "2", + path: "/v2/billing", + version: API_VERSIONS_VALUES, }) @ApiExcludeController(true) export class BillingController { diff --git a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.ts b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.ts index 12345efa5f..8a1f4f1935 100644 --- a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.ts +++ b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.ts @@ -1,3 +1,4 @@ +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { CreateManagedUserOutput } from "@/modules/oauth-clients/controllers/oauth-client-users/outputs/create-managed-user.output"; import { GetManagedUserOutput } from "@/modules/oauth-clients/controllers/oauth-client-users/outputs/get-managed-user.output"; import { GetManagedUsersOutput } from "@/modules/oauth-clients/controllers/oauth-client-users/outputs/get-managed-users.output"; @@ -33,8 +34,8 @@ import { SUCCESS_STATUS } from "@calcom/platform-constants"; import { Pagination } from "@calcom/platform-types"; @Controller({ - path: "oauth-clients/:clientId/users", - version: "2", + path: "/v2/oauth-clients/:clientId/users", + version: API_VERSIONS_VALUES, }) @UseGuards(OAuthClientCredentialsGuard) @DocsTags("Managed users") diff --git a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-clients/oauth-clients.controller.ts b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-clients/oauth-clients.controller.ts index 93fe11003e..dba95be466 100644 --- a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-clients/oauth-clients.controller.ts +++ b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-clients/oauth-clients.controller.ts @@ -1,4 +1,5 @@ import { getEnv } from "@/env"; +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator"; import { Roles } from "@/modules/auth/decorators/roles/roles.decorator"; import { NextAuthGuard } from "@/modules/auth/guards/next-auth/next-auth.guard"; @@ -46,8 +47,8 @@ const AUTH_DOCUMENTATION = `⚠️ First, this endpoint requires \`Cookie: next- Second, make sure that the logged in user has organizationId set to pass the OrganizationRolesGuard guard.`; @Controller({ - path: "oauth-clients", - version: "2", + path: "/v2/oauth-clients", + version: API_VERSIONS_VALUES, }) @UseGuards(NextAuthGuard, OrganizationRolesGuard) @DocsExcludeController(getEnv("NODE_ENV") === "production") diff --git a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-flow/oauth-flow.controller.ts b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-flow/oauth-flow.controller.ts index c7d82b69be..975db6df0e 100644 --- a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-flow/oauth-flow.controller.ts +++ b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-flow/oauth-flow.controller.ts @@ -1,4 +1,5 @@ import { getEnv } from "@/env"; +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { GetUser } from "@/modules/auth/decorators/get-user/get-user.decorator"; import { NextAuthGuard } from "@/modules/auth/guards/next-auth/next-auth.guard"; import { KeysResponseDto } from "@/modules/oauth-clients/controllers/oauth-flow/responses/KeysResponse.dto"; @@ -33,8 +34,8 @@ import { Response as ExpressResponse } from "express"; import { SUCCESS_STATUS, X_CAL_SECRET_KEY } from "@calcom/platform-constants"; @Controller({ - path: "oauth/:clientId", - version: "2", + path: "/v2/oauth/:clientId", + version: API_VERSIONS_VALUES, }) @DocsExcludeController(getEnv("NODE_ENV") === "production") @DocsTags("OAuth - development only") diff --git a/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts b/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts index a595b377ff..51c27cf440 100644 --- a/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts +++ b/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts @@ -7,7 +7,7 @@ import { UsersRepository } from "@/modules/users/users.repository"; import { BadRequestException, Injectable } from "@nestjs/common"; import { User } from "@prisma/client"; -import { createNewUsersConnectToOrgIfExists, slugify } from "@calcom/platform-libraries"; +import { createNewUsersConnectToOrgIfExists, slugify } from "@calcom/platform-libraries-0.0.2"; @Injectable() export class OAuthClientUsersService { diff --git a/apps/api/v2/src/modules/slots/controllers/slots.controller.ts b/apps/api/v2/src/modules/slots/controllers/slots.controller.ts index b8fcf941cd..4ab18d70ae 100644 --- a/apps/api/v2/src/modules/slots/controllers/slots.controller.ts +++ b/apps/api/v2/src/modules/slots/controllers/slots.controller.ts @@ -1,3 +1,4 @@ +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { AccessTokenGuard } from "@/modules/auth/guards/access-token/access-token.guard"; import { SlotsService } from "@/modules/slots/services/slots.service"; import { Query, Body, Controller, Get, Delete, Post, Req, Res, UseGuards } from "@nestjs/common"; @@ -5,14 +6,14 @@ import { ApiTags as DocsTags } from "@nestjs/swagger"; import { Response as ExpressResponse, Request as ExpressRequest } from "express"; import { SUCCESS_STATUS } from "@calcom/platform-constants"; -import { getAvailableSlots } from "@calcom/platform-libraries"; -import type { AvailableSlotsType } from "@calcom/platform-libraries"; +import { getAvailableSlots } from "@calcom/platform-libraries-0.0.2"; +import type { AvailableSlotsType } from "@calcom/platform-libraries-0.0.2"; import { RemoveSelectedSlotInput, ReserveSlotInput } from "@calcom/platform-types"; import { ApiResponse, GetAvailableSlotsInput } from "@calcom/platform-types"; @Controller({ - path: "slots", - version: "2", + path: "/v2/slots", + version: API_VERSIONS_VALUES, }) @DocsTags("Slots") export class SlotsController { diff --git a/apps/api/v2/src/modules/slots/slots.repository.ts b/apps/api/v2/src/modules/slots/slots.repository.ts index 8ef589f9f8..abf5d916bb 100644 --- a/apps/api/v2/src/modules/slots/slots.repository.ts +++ b/apps/api/v2/src/modules/slots/slots.repository.ts @@ -3,7 +3,7 @@ import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { Injectable } from "@nestjs/common"; import { DateTime } from "luxon"; -import { MINUTES_TO_BOOK } from "@calcom/platform-libraries"; +import { MINUTES_TO_BOOK } from "@calcom/platform-libraries-0.0.2"; import { ReserveSlotInput } from "@calcom/platform-types"; @Injectable() diff --git a/apps/api/v2/src/modules/timezones/controllers/timezones.controller.ts b/apps/api/v2/src/modules/timezones/controllers/timezones.controller.ts index 4882e154f3..7d2707c270 100644 --- a/apps/api/v2/src/modules/timezones/controllers/timezones.controller.ts +++ b/apps/api/v2/src/modules/timezones/controllers/timezones.controller.ts @@ -1,14 +1,15 @@ +import { API_VERSIONS_VALUES } from "@/lib/api-versions"; import { TimezonesService } from "@/modules/timezones/services/timezones.service"; import { Controller, Get } from "@nestjs/common"; import { ApiTags as DocsTags } from "@nestjs/swagger"; import { SUCCESS_STATUS } from "@calcom/platform-constants"; -import type { CityTimezones } from "@calcom/platform-libraries"; +import type { CityTimezones } from "@calcom/platform-libraries-0.0.2"; import { ApiResponse } from "@calcom/platform-types"; @Controller({ - path: "timezones", - version: "2", + path: "/v2/timezones", + version: API_VERSIONS_VALUES, }) @DocsTags("Timezones") export class TimezonesController { diff --git a/apps/api/v2/src/modules/timezones/services/timezones.service.ts b/apps/api/v2/src/modules/timezones/services/timezones.service.ts index be623bebdc..7fc1657b9e 100644 --- a/apps/api/v2/src/modules/timezones/services/timezones.service.ts +++ b/apps/api/v2/src/modules/timezones/services/timezones.service.ts @@ -1,8 +1,8 @@ import { RedisService } from "@/modules/redis/redis.service"; import { Injectable } from "@nestjs/common"; -import { cityTimezonesHandler } from "@calcom/platform-libraries"; -import type { CityTimezones } from "@calcom/platform-libraries"; +import { cityTimezonesHandler } from "@calcom/platform-libraries-0.0.2"; +import type { CityTimezones } from "@calcom/platform-libraries-0.0.2"; @Injectable() export class TimezonesService { diff --git a/packages/platform/atoms/cal-provider/CalProvider.tsx b/packages/platform/atoms/cal-provider/CalProvider.tsx index 3a5aa0c96b..9ec6d10ed0 100644 --- a/packages/platform/atoms/cal-provider/CalProvider.tsx +++ b/packages/platform/atoms/cal-provider/CalProvider.tsx @@ -1,6 +1,10 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import type { ReactNode } from "react"; +import { useEffect, type ReactNode } from "react"; +import type { API_VERSIONS_ENUM } from "@calcom/platform-constants"; +import { VERSION_2024_04_15 } from "@calcom/platform-constants"; + +import http from "../lib/http"; import { BaseCalProvider } from "./BaseCalProvider"; const queryClient = new QueryClient(); @@ -12,6 +16,7 @@ export type CalProviderProps = { options: { refreshUrl?: string; apiUrl: string }; autoUpdateTimezone?: boolean; onTimezoneChange?: () => void; + version?: API_VERSIONS_ENUM; }; /** @@ -35,7 +40,12 @@ export function CalProvider({ children, autoUpdateTimezone = true, onTimezoneChange, + version = VERSION_2024_04_15, }: CalProviderProps) { + useEffect(() => { + http.setVersionHeader(version); + }, [version]); + return ( + options={options} + version={version}> {children} diff --git a/packages/platform/atoms/lib/http.ts b/packages/platform/atoms/lib/http.ts index 952a9d703b..37275a4d62 100644 --- a/packages/platform/atoms/lib/http.ts +++ b/packages/platform/atoms/lib/http.ts @@ -1,5 +1,7 @@ import axios from "axios"; +import { CAL_API_VERSION_HEADER, X_CAL_CLIENT_ID } from "@calcom/platform-constants"; + // Immediately Invoked Function Expression to create simple singleton class like const http = (function () { @@ -35,10 +37,16 @@ const http = (function () { return instance.defaults.headers.common?.["Authorization"]?.toString() ?? ""; }, setClientIdHeader: (clientId: string) => { - instance.defaults.headers.common["x-cal-client-id"] = clientId; + instance.defaults.headers.common[X_CAL_CLIENT_ID] = clientId; }, getClientIdHeader: () => { - return instance.defaults.headers.common?.["x-cal-client-id"]?.toString() ?? ""; + return instance.defaults.headers.common?.[X_CAL_CLIENT_ID]?.toString() ?? ""; + }, + setVersionHeader: (clientId: string) => { + instance.defaults.headers.common[CAL_API_VERSION_HEADER] = clientId; + }, + getVersionHeader: () => { + return instance.defaults.headers.common?.[X_CAL_CLIENT_ID]?.toString() ?? ""; }, refreshTokens: async (refreshUrl: string): Promise => { const response = await fetch(`${refreshUrl}`, { diff --git a/packages/platform/constants/api.ts b/packages/platform/constants/api.ts index 1120ef73d7..0d54cb963b 100644 --- a/packages/platform/constants/api.ts +++ b/packages/platform/constants/api.ts @@ -1,5 +1,4 @@ export const BASE_URL = "http://localhost:5555"; -export const API_VERSION = "v2"; export const V2_ENDPOINTS = { me: "me", availability: "schedules", @@ -51,3 +50,10 @@ export const X_CAL_CLIENT_ID = "x-cal-client-id"; // HTTP status codes export const HTTP_CODE_TOKEN_EXPIRED = 498; + +export const VERSION_2024_04_15 = "2024-04-15"; +export const VERSION_2024_05_21 = "2024-05-21"; +export const API_VERSIONS = [VERSION_2024_04_15, VERSION_2024_05_21] as const; +export type API_VERSIONS_ENUM = (typeof API_VERSIONS)[number]; +export type API_VERSIONS_TYPE = typeof API_VERSIONS; +export const CAL_API_VERSION_HEADER = "cal-api-version";