From de2f51e104ae1670e1580f58406c304ed5439240 Mon Sep 17 00:00:00 2001 From: Lauris Skraucis Date: Mon, 22 Jul 2024 19:09:54 +0200 Subject: [PATCH] feat: v2 API enable updating event type schedule (#15803) * refactor: event-types CREATE, UPDATE accept scheduleId and return scheduleId * chore: enable passing scheduleId to event-types create handler * chore: use platform-libraries at version 0.0.20 * fix: remove team output schedule * finish merge main into this branch * fix: dont allow adding scheduleId to event-type if user does not own schedule --- apps/api/v2/package.json | 2 +- .../bookings.controller.e2e-spec.ts | 2 +- .../controllers/bookings.controller.ts | 2 +- .../inputs/create-recurring-booking.input.ts | 2 +- .../services/apple-calendar.service.ts | 2 +- .../calendars/services/calendars.service.ts | 2 +- .../event-types.controller.e2e-spec.ts | 2 +- .../controllers/event-types.controller.ts | 1 + .../event-types.repository.ts | 2 +- .../services/event-types.service.ts | 2 +- .../event-types.controller.e2e-spec.ts | 92 ++++++++++++++++++- .../event-types.module.ts | 2 + .../event-types.repository.ts | 2 +- .../services/event-types.service.ts | 28 ++++-- .../services/input-event-types.service.ts | 5 +- .../services/output-event-types.service.ts | 12 +-- .../schedules.repository.ts | 11 +++ .../services/input-schedules.service.ts | 2 +- .../v2/src/filters/trpc-exception.filter.ts | 2 +- .../api/v2/src/modules/email/email.service.ts | 2 +- .../services/oauth-clients-users.service.ts | 2 +- .../organizations-event-types.e2e-spec.ts | 1 + .../organizations-event-types.service.ts | 2 +- .../services/event-types/output.service.ts | 2 +- .../services/organizations-users-service.ts | 2 +- .../slots/controllers/slots.controller.ts | 4 +- .../v2/src/modules/slots/slots.repository.ts | 2 +- .../controllers/timezones.controller.ts | 2 +- .../timezones/services/timezones.service.ts | 4 +- apps/api/v2/swagger/documentation.json | 28 +----- .../schedules.repository.fixture.ts | 6 ++ packages/platform/libraries/CHANGELOG.md | 4 + .../inputs/create-event-type.input.ts | 4 + .../inputs/update-event-type.input.ts | 4 + .../outputs/event-type.output.ts | 14 +-- packages/prisma/zod/custom/eventtype.ts | 1 + .../viewer/eventTypes/create.handler.ts | 3 +- yarn.lock | 26 +++--- 38 files changed, 199 insertions(+), 89 deletions(-) diff --git a/apps/api/v2/package.json b/apps/api/v2/package.json index b1f5701746..4b1a4e8384 100644 --- a/apps/api/v2/package.json +++ b/apps/api/v2/package.json @@ -25,8 +25,8 @@ }, "dependencies": { "@calcom/platform-constants": "*", - "@calcom/platform-libraries-0.0.19": "npm:@calcom/platform-libraries@0.0.19", "@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2", + "@calcom/platform-libraries-0.0.20": "npm:@calcom/platform-libraries@0.0.20", "@calcom/platform-types": "*", "@calcom/platform-utils": "*", "@calcom/prisma": "*", 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 cead965ba3..ecef942761 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 @@ -19,7 +19,7 @@ import { UserRepositoryFixture } from "test/fixtures/repository/users.repository import { withApiAuth } from "test/utils/withApiAuth"; import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants"; -import { handleNewBooking } from "@calcom/platform-libraries-0.0.19"; +import { handleNewBooking } from "@calcom/platform-libraries-0.0.20"; 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 315188dfb9..267e6116ee 100644 --- a/apps/api/v2/src/ee/bookings/controllers/bookings.controller.ts +++ b/apps/api/v2/src/ee/bookings/controllers/bookings.controller.ts @@ -46,7 +46,7 @@ import { getBookingInfo, handleCancelBooking, getBookingForReschedule, -} from "@calcom/platform-libraries-0.0.19"; +} from "@calcom/platform-libraries-0.0.20"; import { GetBookingsInput, CancelBookingInput, Status } from "@calcom/platform-types"; import { ApiResponse } from "@calcom/platform-types"; import { PrismaClient } from "@calcom/prisma"; 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 757b60dc22..a570ca6e03 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-0.0.19"; +import type { AppsStatus } from "@calcom/platform-libraries-0.0.20"; export class CreateRecurringBookingInput extends CreateBookingInput { @IsBoolean() diff --git a/apps/api/v2/src/ee/calendars/services/apple-calendar.service.ts b/apps/api/v2/src/ee/calendars/services/apple-calendar.service.ts index 4c0601466d..9061e1e3aa 100644 --- a/apps/api/v2/src/ee/calendars/services/apple-calendar.service.ts +++ b/apps/api/v2/src/ee/calendars/services/apple-calendar.service.ts @@ -5,7 +5,7 @@ import { BadRequestException, UnauthorizedException } from "@nestjs/common"; import { Injectable } from "@nestjs/common"; import { SUCCESS_STATUS, APPLE_CALENDAR_TYPE, APPLE_CALENDAR_ID } from "@calcom/platform-constants"; -import { symmetricEncrypt, CalendarService } from "@calcom/platform-libraries-0.0.19"; +import { symmetricEncrypt, CalendarService } from "@calcom/platform-libraries-0.0.20"; @Injectable() export class AppleCalendarService implements CredentialSyncCalendarApp { 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 4fbbba049e..9ea5178fbe 100644 --- a/apps/api/v2/src/ee/calendars/services/calendars.service.ts +++ b/apps/api/v2/src/ee/calendars/services/calendars.service.ts @@ -17,7 +17,7 @@ import { User } from "@prisma/client"; import { DateTime } from "luxon"; import { z } from "zod"; -import { getConnectedDestinationCalendars, getBusyCalendarTimes } from "@calcom/platform-libraries-0.0.19"; +import { getConnectedDestinationCalendars, getBusyCalendarTimes } from "@calcom/platform-libraries-0.0.20"; import { Calendar } from "@calcom/platform-types"; import { PrismaClient } from "@calcom/prisma"; diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.e2e-spec.ts b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.e2e-spec.ts index 9df8253bdd..e503597101 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.e2e-spec.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.e2e-spec.ts @@ -35,7 +35,7 @@ import { EventTypesPublic, eventTypeBookingFields, eventTypeLocations, -} from "@calcom/platform-libraries-0.0.19"; +} from "@calcom/platform-libraries-0.0.20"; import { ApiSuccessResponse } from "@calcom/platform-types"; describe("Event types Endpoints", () => { diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts index 9b5ba327c0..5b7ac79e95 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts @@ -40,6 +40,7 @@ import { ApiTags as DocsTags } from "@nestjs/swagger"; import { EVENT_TYPE_READ, EVENT_TYPE_WRITE, SUCCESS_STATUS } from "@calcom/platform-constants"; import { getPublicEvent, getEventTypesByViewer } from "@calcom/platform-libraries-0.0.2"; + import { PrismaClient } from "@calcom/prisma"; @Controller({ diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/event-types.repository.ts b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/event-types.repository.ts index e4e7b03f60..f285f35072 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/event-types.repository.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/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-0.0.19"; +import { getEventTypeById } from "@calcom/platform-libraries-0.0.20"; import type { PrismaClient } from "@calcom/prisma"; @Injectable() diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/services/event-types.service.ts b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/services/event-types.service.ts index dc4f4b881c..da136562ef 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/services/event-types.service.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/services/event-types.service.ts @@ -14,7 +14,7 @@ import { updateEventType, EventTypesPublic, getEventTypesPublic, -} from "@calcom/platform-libraries-0.0.19"; +} from "@calcom/platform-libraries-0.0.20"; import { EventType } from "@calcom/prisma/client"; @Injectable() diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts index c53d259472..58bc495d8c 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/controllers/event-types.controller.e2e-spec.ts @@ -9,10 +9,11 @@ import { UsersModule } from "@/modules/users/users.module"; import { INestApplication } from "@nestjs/common"; import { NestExpressApplication } from "@nestjs/platform-express"; import { Test } from "@nestjs/testing"; -import { PlatformOAuthClient, Team, User } from "@prisma/client"; +import { PlatformOAuthClient, Team, User, Schedule } from "@prisma/client"; import * as request from "supertest"; import { EventTypesRepositoryFixture } from "test/fixtures/repository/event-types.repository.fixture"; import { OAuthClientRepositoryFixture } from "test/fixtures/repository/oauth-client.repository.fixture"; +import { SchedulesRepositoryFixture } from "test/fixtures/repository/schedules.repository.fixture"; import { TeamRepositoryFixture } from "test/fixtures/repository/team.repository.fixture"; import { UserRepositoryFixture } from "test/fixtures/repository/users.repository.fixture"; import { withApiAuth } from "test/utils/withApiAuth"; @@ -63,12 +64,18 @@ describe("Event types Endpoints", () => { let oauthClientRepositoryFixture: OAuthClientRepositoryFixture; let teamRepositoryFixture: TeamRepositoryFixture; let eventTypesRepositoryFixture: EventTypesRepositoryFixture; + let schedulesRepostoryFixture: SchedulesRepositoryFixture; const userEmail = "event-types-test-e2e@api.com"; + const falseTestEmail = "false-event-types@api.com"; const name = "bob-the-builder"; const username = name; let eventType: EventTypeOutput_2024_06_14; let user: User; + let falseTestUser: User; + let firstSchedule: Schedule; + let secondSchedule: Schedule; + let falseTestSchedule: Schedule; beforeAll(async () => { const moduleRef = await withApiAuth( @@ -91,6 +98,7 @@ describe("Event types Endpoints", () => { userRepositoryFixture = new UserRepositoryFixture(moduleRef); teamRepositoryFixture = new TeamRepositoryFixture(moduleRef); eventTypesRepositoryFixture = new EventTypesRepositoryFixture(moduleRef); + schedulesRepostoryFixture = new SchedulesRepositoryFixture(moduleRef); organization = await teamRepositoryFixture.create({ name: "organization" }); oAuthClient = await createOAuthClient(organization.id); @@ -100,6 +108,30 @@ describe("Event types Endpoints", () => { username, }); + falseTestUser = await userRepositoryFixture.create({ + email: falseTestEmail, + name: "false-test", + username: falseTestEmail, + }); + + firstSchedule = await schedulesRepostoryFixture.create({ + userId: user.id, + name: "work", + timeZone: "Europe/Rome", + }); + + secondSchedule = await schedulesRepostoryFixture.create({ + userId: user.id, + name: "chill", + timeZone: "Europe/Rome", + }); + + falseTestSchedule = await schedulesRepostoryFixture.create({ + userId: falseTestUser.id, + name: "work", + timeZone: "Europe/Rome", + }); + await app.init(); }); @@ -123,6 +155,40 @@ describe("Event types Endpoints", () => { expect(user).toBeDefined(); }); + it("should not allow creating an event type with schedule user does not own", async () => { + const scheduleId = falseTestSchedule.id; + + const body: CreateEventTypeInput_2024_06_14 = { + title: "Coding class", + slug: "coding-class", + description: "Let's learn how to code like a pro.", + lengthInMinutes: 60, + locations: [ + { + type: "integration", + integration: "cal-video", + }, + ], + bookingFields: [ + { + type: "select", + label: "select which language you want to learn", + slug: "select-language", + required: true, + placeholder: "select language", + options: ["javascript", "python", "cobol"], + }, + ], + scheduleId, + }; + + return request(app.getHttpServer()) + .post("/api/v2/event-types") + .set(CAL_API_VERSION_HEADER, VERSION_2024_06_14) + .send(body) + .expect(404); + }); + it("should create an event type", async () => { const body: CreateEventTypeInput_2024_06_14 = { title: "Coding class", @@ -145,6 +211,7 @@ describe("Event types Endpoints", () => { options: ["javascript", "python", "cobol"], }, ], + scheduleId: firstSchedule.id, }; return request(app.getHttpServer()) @@ -162,6 +229,7 @@ describe("Event types Endpoints", () => { expect(createdEventType.locations).toEqual(body.locations); expect(createdEventType.bookingFields).toEqual(body.bookingFields); expect(createdEventType.ownerId).toEqual(user.id); + expect(createdEventType.scheduleId).toEqual(firstSchedule.id); eventType = responseBody.data; }); @@ -172,6 +240,7 @@ describe("Event types Endpoints", () => { const body: UpdateEventTypeInput_2024_06_14 = { title: newTitle, + scheduleId: secondSchedule.id, }; return request(app.getHttpServer()) @@ -191,11 +260,25 @@ describe("Event types Endpoints", () => { expect(updatedEventType.locations).toEqual(eventType.locations); expect(updatedEventType.bookingFields).toEqual(eventType.bookingFields); expect(updatedEventType.ownerId).toEqual(user.id); + expect(updatedEventType.scheduleId).toEqual(secondSchedule.id); eventType.title = newTitle; + eventType.scheduleId = secondSchedule.id; }); }); + it("should not allow to update event type with scheduleId user does not own", async () => { + const body: UpdateEventTypeInput_2024_06_14 = { + scheduleId: falseTestSchedule.id, + }; + + return request(app.getHttpServer()) + .patch(`/api/v2/event-types/${eventType.id}`) + .set(CAL_API_VERSION_HEADER, VERSION_2024_06_14) + .send(body) + .expect(404); + }); + it(`/GET/:id`, async () => { const response = await request(app.getHttpServer()) .get(`/api/v2/event-types/${eventType.id}`) @@ -272,7 +355,7 @@ describe("Event types Endpoints", () => { .expect(404); }); - it("should delete schedule", async () => { + it("should delete event type", async () => { return request(app.getHttpServer()).delete(`/api/v2/event-types/${eventType.id}`).expect(200); }); @@ -289,6 +372,11 @@ describe("Event types Endpoints", () => { } catch (e) { // User might have been deleted by the test } + try { + await userRepositoryFixture.delete(falseTestUser.id); + } catch (e) { + // User might have been deleted by the test + } await app.close(); }); }); diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts index 43fbc3e044..64dae68d31 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.module.ts @@ -3,6 +3,7 @@ import { EventTypesRepository_2024_06_14 } from "@/ee/event-types/event-types_20 import { EventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/event-types.service"; import { InputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/input-event-types.service"; import { OutputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/output-event-types.service"; +import { SchedulesRepository_2024_06_11 } from "@/ee/schedules/schedules_2024_06_11/schedules.repository"; import { MembershipsModule } from "@/modules/memberships/memberships.module"; import { PrismaModule } from "@/modules/prisma/prisma.module"; import { SelectedCalendarsModule } from "@/modules/selected-calendars/selected-calendars.module"; @@ -20,6 +21,7 @@ import { Module } from "@nestjs/common"; OutputEventTypesService_2024_06_14, UsersRepository, UsersService, + SchedulesRepository_2024_06_11, ], controllers: [EventTypesController_2024_06_14], exports: [ diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts index b410385852..c002610c86 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts @@ -7,7 +7,7 @@ import { getEventTypeById, transformApiEventTypeBookingFields, transformApiEventTypeLocations, -} from "@calcom/platform-libraries-0.0.19"; +} from "@calcom/platform-libraries-0.0.20"; import { CreateEventTypeInput_2024_06_14 } from "@calcom/platform-types"; import type { PrismaClient } from "@calcom/prisma"; diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts index 6a93b282a2..e352368696 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/event-types.service.ts @@ -2,6 +2,7 @@ import { DEFAULT_EVENT_TYPES } from "@/ee/event-types/event-types_2024_06_14/con import { EventTypesRepository_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.repository"; import { InputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/input-event-types.service"; import { OutputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/output-event-types.service"; +import { SchedulesRepository_2024_06_11 } from "@/ee/schedules/schedules_2024_06_11/schedules.repository"; import { MembershipsRepository } from "@/modules/memberships/memberships.repository"; import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository"; @@ -9,9 +10,9 @@ import { UsersService } from "@/modules/users/services/users.service"; import { UserWithProfile, UsersRepository } from "@/modules/users/users.repository"; import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from "@nestjs/common"; -import { createEventType, updateEventType } from "@calcom/platform-libraries-0.0.19"; -import { getEventTypesPublic, EventTypesPublic } from "@calcom/platform-libraries-0.0.19"; -import { dynamicEvent } from "@calcom/platform-libraries-0.0.19"; +import { createEventType, updateEventType } from "@calcom/platform-libraries-0.0.20"; +import { getEventTypesPublic, EventTypesPublic } from "@calcom/platform-libraries-0.0.20"; +import { dynamicEvent } from "@calcom/platform-libraries-0.0.20"; import { CreateEventTypeInput_2024_06_14, UpdateEventTypeInput_2024_06_14, @@ -30,7 +31,8 @@ export class EventTypesService_2024_06_14 { private readonly usersRepository: UsersRepository, private readonly usersService: UsersService, private readonly selectedCalendarsRepository: SelectedCalendarsRepository, - private readonly dbWrite: PrismaWriteService + private readonly dbWrite: PrismaWriteService, + private readonly schedulesRepository: SchedulesRepository_2024_06_11 ) {} async createUserEventType(user: UserWithProfile, body: CreateEventTypeInput_2024_06_14) { @@ -61,6 +63,7 @@ export class EventTypesService_2024_06_14 { if (existsWithSlug) { throw new BadRequestException("User already has an event type with this slug."); } + await this.checkUserOwnsSchedule(userId, body.scheduleId); } async getEventTypeByUsernameAndSlug(username: string, eventTypeSlug: string) { @@ -203,7 +206,7 @@ export class EventTypesService_2024_06_14 { } async updateEventType(eventTypeId: number, body: UpdateEventTypeInput_2024_06_14, user: UserWithProfile) { - this.checkCanUpdateEventType(user.id, eventTypeId); + await this.checkCanUpdateEventType(user.id, eventTypeId, body.scheduleId); const eventTypeUser = await this.getUserToUpdateEvent(user); const bodyTransformed = this.inputEventTypesService.transformInputUpdateEventType(body); await updateEventType({ @@ -225,12 +228,13 @@ export class EventTypesService_2024_06_14 { return this.outputEventTypesService.getResponseEventType(user.id, eventType); } - async checkCanUpdateEventType(userId: number, eventTypeId: number) { + async checkCanUpdateEventType(userId: number, eventTypeId: number, scheduleId: number | undefined) { const existingEventType = await this.getUserEventType(userId, eventTypeId); if (!existingEventType) { throw new NotFoundException(`Event type with id ${eventTypeId} not found`); } this.checkUserOwnsEventType(userId, { id: eventTypeId, userId: existingEventType.ownerId }); + await this.checkUserOwnsSchedule(userId, scheduleId); } async getUserToUpdateEvent(user: UserWithProfile) { @@ -255,4 +259,16 @@ export class EventTypesService_2024_06_14 { throw new ForbiddenException(`User with ID=${userId} does not own event type with ID=${eventType.id}`); } } + + async checkUserOwnsSchedule(userId: number, scheduleId: number | null | undefined) { + if (!scheduleId) { + return; + } + + const schedule = await this.schedulesRepository.getScheduleByIdAndUserId(scheduleId, userId); + + if (!schedule) { + throw new NotFoundException(`User with ID=${userId} does not own schedule with ID=${scheduleId}`); + } + } } diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts index 0cae1baf8c..ed5a3a69c3 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/input-event-types.service.ts @@ -3,7 +3,7 @@ import { Injectable } from "@nestjs/common"; import { transformApiEventTypeBookingFields, transformApiEventTypeLocations, -} from "@calcom/platform-libraries-0.0.19"; +} from "@calcom/platform-libraries-0.0.20"; import { CreateEventTypeInput_2024_06_14, UpdateEventTypeInput_2024_06_14 } from "@calcom/platform-types"; @Injectable() @@ -29,13 +29,14 @@ export class InputEventTypesService_2024_06_14 { } transformInputUpdateEventType(inputEventType: UpdateEventTypeInput_2024_06_14) { - const { lengthInMinutes, locations, bookingFields, ...rest } = inputEventType; + const { lengthInMinutes, locations, bookingFields, scheduleId, ...rest } = inputEventType; const eventType = { ...rest, length: lengthInMinutes, locations: locations ? this.transformInputLocations(locations) : undefined, bookingFields: bookingFields ? this.transformInputBookingFields(bookingFields) : undefined, + schedule: scheduleId, }; return eventType; diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts index a5c2335e8b..f33350daaa 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts @@ -9,7 +9,7 @@ import { parseRecurringEvent, TransformedLocationsSchema, BookingFieldsSchema, -} from "@calcom/platform-libraries-0.0.19"; +} from "@calcom/platform-libraries-0.0.20"; type EventTypeRelations = { users: User[]; schedule: Schedule | null }; type DatabaseEventType = EventType & EventTypeRelations; @@ -41,7 +41,7 @@ type Input = Pick< | "recurringEvent" | "metadata" | "users" - | "schedule" + | "scheduleId" >; @Injectable() @@ -68,13 +68,13 @@ export class OutputEventTypesService_2024_06_14 { successRedirectUrl, seatsShowAvailabilityCount, isInstantEvent, + scheduleId, } = databaseEventType; const locations = this.transformLocations(databaseEventType.locations); const bookingFields = this.transformBookingFields(databaseEventType.bookingFields); const recurringEvent = this.transformRecurringEvent(databaseEventType.recurringEvent); const metadata = this.transformMetadata(databaseEventType.metadata) || {}; - const schedule = await this.getSchedule(databaseEventType); const users = this.transformUsers(databaseEventType.users); return { @@ -104,7 +104,7 @@ export class OutputEventTypesService_2024_06_14 { seatsShowAvailabilityCount, isInstantEvent, users, - schedule, + scheduleId, }; } @@ -128,10 +128,6 @@ export class OutputEventTypesService_2024_06_14 { return EventTypeMetaDataSchema.parse(metadata); } - async getSchedule(databaseEventType: Input) { - return databaseEventType.schedule || null; - } - transformUsers(users: User[]) { return users.map((user) => { const metadata = user.metadata ? userMetadata.parse(user.metadata) : {}; diff --git a/apps/api/v2/src/ee/schedules/schedules_2024_06_11/schedules.repository.ts b/apps/api/v2/src/ee/schedules/schedules_2024_06_11/schedules.repository.ts index ad9cecc3a1..55480185eb 100644 --- a/apps/api/v2/src/ee/schedules/schedules_2024_06_11/schedules.repository.ts +++ b/apps/api/v2/src/ee/schedules/schedules_2024_06_11/schedules.repository.ts @@ -96,6 +96,17 @@ export class SchedulesRepository_2024_06_11 { return schedule; } + async getScheduleByIdAndUserId(scheduleId: number, userId: number) { + const schedule = await this.dbRead.prisma.schedule.findUnique({ + where: { + id: scheduleId, + userId, + }, + }); + + return schedule; + } + async updateSchedule( userId: number, scheduleId: number, diff --git a/apps/api/v2/src/ee/schedules/schedules_2024_06_11/services/input-schedules.service.ts b/apps/api/v2/src/ee/schedules/schedules_2024_06_11/services/input-schedules.service.ts index fe8adc8b4c..cbafc77a55 100644 --- a/apps/api/v2/src/ee/schedules/schedules_2024_06_11/services/input-schedules.service.ts +++ b/apps/api/v2/src/ee/schedules/schedules_2024_06_11/services/input-schedules.service.ts @@ -3,7 +3,7 @@ import { Injectable } from "@nestjs/common"; import { transformApiScheduleOverrides, transformApiScheduleAvailability, -} from "@calcom/platform-libraries-0.0.19"; +} from "@calcom/platform-libraries-0.0.20"; import { CreateScheduleInput_2024_06_11, ScheduleAvailabilityInput_2024_06_11 } from "@calcom/platform-types"; import { ScheduleOverrideInput_2024_06_11 } from "@calcom/platform-types"; diff --git a/apps/api/v2/src/filters/trpc-exception.filter.ts b/apps/api/v2/src/filters/trpc-exception.filter.ts index 07360463eb..3b1a76a9b4 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-0.0.19"; +import { TRPCError } from "@calcom/platform-libraries-0.0.20"; import { Response } from "@calcom/platform-types"; @Catch(TRPCError) diff --git a/apps/api/v2/src/modules/email/email.service.ts b/apps/api/v2/src/modules/email/email.service.ts index 0e004974ad..e308b38e39 100644 --- a/apps/api/v2/src/modules/email/email.service.ts +++ b/apps/api/v2/src/modules/email/email.service.ts @@ -1,6 +1,6 @@ import { Injectable } from "@nestjs/common"; -import { sendSignupToOrganizationEmail, getTranslation } from "@calcom/platform-libraries-0.0.19"; +import { sendSignupToOrganizationEmail, getTranslation } from "@calcom/platform-libraries-0.0.20"; @Injectable() export class EmailService { 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 0577fe3e36..8cf4e70821 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-0.0.19"; +import { createNewUsersConnectToOrgIfExists, slugify } from "@calcom/platform-libraries-0.0.20"; @Injectable() export class OAuthClientUsersService { diff --git a/apps/api/v2/src/modules/organizations/controllers/event-types/organizations-event-types.e2e-spec.ts b/apps/api/v2/src/modules/organizations/controllers/event-types/organizations-event-types.e2e-spec.ts index 0f18a9b4a6..4d1e009523 100644 --- a/apps/api/v2/src/modules/organizations/controllers/event-types/organizations-event-types.e2e-spec.ts +++ b/apps/api/v2/src/modules/organizations/controllers/event-types/organizations-event-types.e2e-spec.ts @@ -587,6 +587,7 @@ describe("Organizations Event Types Endpoints", () => { await userRepositoryFixture.deleteByEmail(userAdmin.email); await userRepositoryFixture.deleteByEmail(teammate1.email); await userRepositoryFixture.deleteByEmail(teammate2.email); + await userRepositoryFixture.deleteByEmail(falseTestUser.email); await teamsRepositoryFixture.delete(team.id); await organizationsRepositoryFixture.delete(org.id); await app.close(); diff --git a/apps/api/v2/src/modules/organizations/services/event-types/organizations-event-types.service.ts b/apps/api/v2/src/modules/organizations/services/event-types/organizations-event-types.service.ts index 5ddcafe750..780b593a3b 100644 --- a/apps/api/v2/src/modules/organizations/services/event-types/organizations-event-types.service.ts +++ b/apps/api/v2/src/modules/organizations/services/event-types/organizations-event-types.service.ts @@ -9,7 +9,7 @@ import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { UserWithProfile } from "@/modules/users/users.repository"; import { Injectable, NotFoundException } from "@nestjs/common"; -import { createEventType, updateEventType } from "@calcom/platform-libraries-0.0.19"; +import { createEventType, updateEventType } from "@calcom/platform-libraries-0.0.20"; import { CreateTeamEventTypeInput_2024_06_14, UpdateTeamEventTypeInput_2024_06_14, diff --git a/apps/api/v2/src/modules/organizations/services/event-types/output.service.ts b/apps/api/v2/src/modules/organizations/services/event-types/output.service.ts index 3eaf5eb009..df596aef00 100644 --- a/apps/api/v2/src/modules/organizations/services/event-types/output.service.ts +++ b/apps/api/v2/src/modules/organizations/services/event-types/output.service.ts @@ -35,7 +35,7 @@ type Input = Pick< | "recurringEvent" | "metadata" | "users" - | "schedule" + | "scheduleId" | "hosts" | "teamId" | "userId" diff --git a/apps/api/v2/src/modules/organizations/services/organizations-users-service.ts b/apps/api/v2/src/modules/organizations/services/organizations-users-service.ts index 4c6a964cc0..d65d9c03fe 100644 --- a/apps/api/v2/src/modules/organizations/services/organizations-users-service.ts +++ b/apps/api/v2/src/modules/organizations/services/organizations-users-service.ts @@ -6,7 +6,7 @@ import { CreateUserInput } from "@/modules/users/inputs/create-user.input"; import { Injectable, ConflictException } from "@nestjs/common"; import { plainToInstance } from "class-transformer"; -import { createNewUsersConnectToOrgIfExists } from "@calcom/platform-libraries-0.0.19"; +import { createNewUsersConnectToOrgIfExists } from "@calcom/platform-libraries-0.0.20"; import { Team } from "@calcom/prisma/client"; @Injectable() 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 f661ef6f8b..1b6ea67cfc 100644 --- a/apps/api/v2/src/modules/slots/controllers/slots.controller.ts +++ b/apps/api/v2/src/modules/slots/controllers/slots.controller.ts @@ -5,8 +5,8 @@ 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-0.0.19"; -import type { AvailableSlotsType } from "@calcom/platform-libraries-0.0.19"; +import { getAvailableSlots } from "@calcom/platform-libraries-0.0.20"; +import type { AvailableSlotsType } from "@calcom/platform-libraries-0.0.20"; import { RemoveSelectedSlotInput, ReserveSlotInput } from "@calcom/platform-types"; import { ApiResponse, GetAvailableSlotsInput } from "@calcom/platform-types"; diff --git a/apps/api/v2/src/modules/slots/slots.repository.ts b/apps/api/v2/src/modules/slots/slots.repository.ts index 9b96fb303f..f51fe8290c 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-0.0.19"; +import { MINUTES_TO_BOOK } from "@calcom/platform-libraries-0.0.20"; 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 e3661f7605..07e009fef9 100644 --- a/apps/api/v2/src/modules/timezones/controllers/timezones.controller.ts +++ b/apps/api/v2/src/modules/timezones/controllers/timezones.controller.ts @@ -4,7 +4,7 @@ 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-0.0.19"; +import type { CityTimezones } from "@calcom/platform-libraries-0.0.20"; import { ApiResponse } from "@calcom/platform-types"; @Controller({ 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 9abd98c8a6..ac8b98c803 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-0.0.19"; -import type { CityTimezones } from "@calcom/platform-libraries-0.0.19"; +import { cityTimezonesHandler } from "@calcom/platform-libraries-0.0.20"; +import type { CityTimezones } from "@calcom/platform-libraries-0.0.20"; @Injectable() export class TimezonesService { diff --git a/apps/api/v2/swagger/documentation.json b/apps/api/v2/swagger/documentation.json index ad8e6453f6..69152aa8a8 100644 --- a/apps/api/v2/swagger/documentation.json +++ b/apps/api/v2/swagger/documentation.json @@ -5961,22 +5961,6 @@ "freq" ] }, - "Schedule_2024_06_14": { - "type": "object", - "properties": { - "id": { - "type": "number" - }, - "timeZone": { - "type": "string", - "nullable": true - } - }, - "required": [ - "id", - "timeZone" - ] - }, "Host": { "type": "object", "properties": { @@ -6091,13 +6075,9 @@ "isInstantEvent": { "type": "boolean" }, - "schedule": { - "nullable": true, - "allOf": [ - { - "$ref": "#/components/schemas/Schedule_2024_06_14" - } - ] + "scheduleId": { + "type": "number", + "nullable": true }, "teamId": { "type": "number", @@ -6142,7 +6122,7 @@ "successRedirectUrl", "seatsShowAvailabilityCount", "isInstantEvent", - "schedule", + "scheduleId", "hosts" ] }, diff --git a/apps/api/v2/test/fixtures/repository/schedules.repository.fixture.ts b/apps/api/v2/test/fixtures/repository/schedules.repository.fixture.ts index f34be13c9f..abf4d1dcf0 100644 --- a/apps/api/v2/test/fixtures/repository/schedules.repository.fixture.ts +++ b/apps/api/v2/test/fixtures/repository/schedules.repository.fixture.ts @@ -3,6 +3,8 @@ import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; import { TestingModule } from "@nestjs/testing"; import { Schedule } from "@prisma/client"; +import { Prisma } from "@calcom/prisma/client"; + export class SchedulesRepositoryFixture { private primaReadClient: PrismaReadService["prisma"]; private prismaWriteClient: PrismaWriteService["prisma"]; @@ -12,6 +14,10 @@ export class SchedulesRepositoryFixture { this.prismaWriteClient = module.get(PrismaWriteService).prisma; } + async create(schedule: Prisma.ScheduleCreateArgs["data"]) { + return this.prismaWriteClient.schedule.create({ data: schedule }); + } + async getById(scheduleId: Schedule["id"]) { return this.primaReadClient.schedule.findFirst({ where: { id: scheduleId } }); } diff --git a/packages/platform/libraries/CHANGELOG.md b/packages/platform/libraries/CHANGELOG.md index 2756ba0441..4bb2717858 100644 --- a/packages/platform/libraries/CHANGELOG.md +++ b/packages/platform/libraries/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.20 +In event-types create handler (packages/trpc/server/routers/viewer/eventTypes/create.handler.ts) enable passing scheduleId so that when an event type is created it can be connected +to a specific schedule. + ## 0.0.19 Added - create event type handler was [updated](https://github.com/calcom/cal.com/pull/15774) for system admins not to be required to be part of org team when creating event type for team. Update libraries to include these changes. \ No newline at end of file diff --git a/packages/platform/types/event-types/event-types_2024_06_14/inputs/create-event-type.input.ts b/packages/platform/types/event-types/event-types_2024_06_14/inputs/create-event-type.input.ts index c7ff77802a..3ee014b583 100644 --- a/packages/platform/types/event-types/event-types_2024_06_14/inputs/create-event-type.input.ts +++ b/packages/platform/types/event-types/event-types_2024_06_14/inputs/create-event-type.input.ts @@ -68,6 +68,10 @@ export class CreateEventTypeInput_2024_06_14 { @IsInt() @IsOptional() afterEventBuffer?: number; + + @IsInt() + @IsOptional() + scheduleId?: number; } export enum HostPriority { diff --git a/packages/platform/types/event-types/event-types_2024_06_14/inputs/update-event-type.input.ts b/packages/platform/types/event-types/event-types_2024_06_14/inputs/update-event-type.input.ts index 01aea1b9b6..535e05adcb 100644 --- a/packages/platform/types/event-types/event-types_2024_06_14/inputs/update-event-type.input.ts +++ b/packages/platform/types/event-types/event-types_2024_06_14/inputs/update-event-type.input.ts @@ -54,6 +54,10 @@ export class UpdateEventTypeInput_2024_06_14 { @IsInt() @IsOptional() afterEventBuffer?: number; + + @IsInt() + @IsOptional() + scheduleId?: number; } export class UpdateTeamEventTypeInput_2024_06_14 { @IsOptional() diff --git a/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts b/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts index ff1161c500..345ea9c203 100644 --- a/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts +++ b/packages/platform/types/event-types/event-types_2024_06_14/outputs/event-type.output.ts @@ -25,14 +25,6 @@ enum SchedulingTypeEnum { export type SchedulingType = "ROUND_ROBIN" | "COLLECTIVE" | "MANAGED"; -class Schedule_2024_06_14 { - @IsInt() - id!: number; - - @IsString() - timeZone!: string | null; -} - class User_2024_06_14 { @IsInt() id!: number; @@ -143,7 +135,8 @@ export class EventTypeOutput_2024_06_14 { users!: User_2024_06_14[]; - schedule!: Schedule_2024_06_14 | null; + @IsInt() + scheduleId!: number | null; } export class TeamEventTypeOutput_2024_06_14 { @@ -226,7 +219,8 @@ export class TeamEventTypeOutput_2024_06_14 { @IsBoolean() isInstantEvent!: boolean; - schedule!: Schedule_2024_06_14 | null; + @IsInt() + scheduleId!: number | null; @IsInt() @IsOptional() diff --git a/packages/prisma/zod/custom/eventtype.ts b/packages/prisma/zod/custom/eventtype.ts index 26670450f0..03693f56b4 100755 --- a/packages/prisma/zod/custom/eventtype.ts +++ b/packages/prisma/zod/custom/eventtype.ts @@ -19,6 +19,7 @@ export const createEventTypeInput = z.object({ minimumBookingNotice: z.number().int().min(0).optional(), beforeEventBuffer: z.number().int().min(0).optional(), afterEventBuffer: z.number().int().min(0).optional(), + scheduleId: z.number().int().optional() }) .partial({ hidden: true, locations: true }) .refine((data) => (data.teamId ? data.teamId && data.schedulingType : true), { diff --git a/packages/trpc/server/routers/viewer/eventTypes/create.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/create.handler.ts index 10917b8575..4e3368b740 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/create.handler.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/create.handler.ts @@ -35,7 +35,7 @@ type CreateOptions = { }; export const createHandler = async ({ ctx, input }: CreateOptions) => { - const { schedulingType, teamId, metadata, locations: inputLocations, ...rest } = input; + const { schedulingType, teamId, metadata, locations: inputLocations, scheduleId, ...rest } = input; const userId = ctx.user.id; const isManagedEventType = schedulingType === SchedulingType.MANAGED; @@ -51,6 +51,7 @@ export const createHandler = async ({ ctx, input }: CreateOptions) => { // Only connecting the current user for non-managed event types and non team event types users: isManagedEventType || schedulingType ? undefined : { connect: { id: userId } }, locations, + schedule: scheduleId ? { connect: { id: scheduleId } } : undefined, }; if (teamId && schedulingType) { diff --git a/yarn.lock b/yarn.lock index f56363874d..b02ce66b97 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4065,8 +4065,8 @@ __metadata: resolution: "@calcom/api-v2@workspace:apps/api/v2" dependencies: "@calcom/platform-constants": "*" - "@calcom/platform-libraries-0.0.19": "npm:@calcom/platform-libraries@0.0.19" "@calcom/platform-libraries-0.0.2": "npm:@calcom/platform-libraries@0.0.2" + "@calcom/platform-libraries-0.0.20": "npm:@calcom/platform-libraries@0.0.20" "@calcom/platform-types": "*" "@calcom/platform-utils": "*" "@calcom/prisma": "*" @@ -5025,14 +5025,14 @@ __metadata: languageName: unknown linkType: soft -"@calcom/platform-libraries-0.0.19@npm:@calcom/platform-libraries@0.0.19": - version: 0.0.19 - resolution: "@calcom/platform-libraries@npm:0.0.19" +"@calcom/platform-libraries-0.0.20@npm:@calcom/platform-libraries@0.0.20": + version: 0.0.20 + resolution: "@calcom/platform-libraries@npm:0.0.20" dependencies: "@calcom/core": "*" "@calcom/features": "*" "@calcom/lib": "*" - checksum: e5c4f2ca63c927e811232d3c83b5341e306d33f3fd0bfdeaf6dcdbca7f31ae02892bd4f8244273cd411fc0b725d2ff7690b58498ae29f6556c22d19159943b08 + checksum: f17e9bd51429a1a70240944b8f3836be41790a8c0eba34ddeaa7336c4f98503c0ff8c70c4d79b15809895c3af8462cbf10cff14ca4ba0453cc751febf4dd86cb languageName: node linkType: hard @@ -9012,14 +9012,14 @@ __metadata: linkType: hard "@langchain/core@npm:>0.1.56 <0.3.0, @langchain/core@npm:>0.2.0 <0.3.0": - version: 0.2.17 - resolution: "@langchain/core@npm:0.2.17" + version: 0.2.18 + resolution: "@langchain/core@npm:0.2.18" dependencies: ansi-styles: ^5.0.0 camelcase: 6 decamelize: 1.2.0 js-tiktoken: ^1.0.12 - langsmith: ~0.1.30 + langsmith: ~0.1.39 ml-distance: ^4.0.0 mustache: ^4.2.0 p-queue: ^6.6.2 @@ -9027,7 +9027,7 @@ __metadata: uuid: ^10.0.0 zod: ^3.22.4 zod-to-json-schema: ^3.22.3 - checksum: 76d77a71b7f97ee5383a2d93b9b528349452105a35b0bec181bb5e318a27f95cc75a605975aa604ad176d490fb71d214d43f4ac9be69fbd8312fe6c8e417397a + checksum: f1090a300825a8cefdf873a38926f5a3a8f1208ebcdd9f65c4858e851082b8f89b7b7d7dba50c3907de997b0f2fad2856d611adf61096dffcf240e959809e4fc languageName: node linkType: hard @@ -32993,9 +32993,9 @@ __metadata: languageName: node linkType: hard -"langsmith@npm:~0.1.1, langsmith@npm:~0.1.30, langsmith@npm:~0.1.7": - version: 0.1.38 - resolution: "langsmith@npm:0.1.38" +"langsmith@npm:~0.1.1, langsmith@npm:~0.1.39, langsmith@npm:~0.1.7": + version: 0.1.39 + resolution: "langsmith@npm:0.1.39" dependencies: "@types/uuid": ^9.0.1 commander: ^10.0.1 @@ -33013,7 +33013,7 @@ __metadata: optional: true openai: optional: true - checksum: 25e9f68589ef935791258c25c0ac0473f6d45cb6d50970266e3f9ed25eb84530dd5cb8c1a6c13d8ddadf81d2364a56081d5d3798dadb75e685d7c93afac9f903 + checksum: df21332662ec3a2d2d5cf915acede52b96aedf2a286259435d683f230af5926500b129cab1f0275450e0d3de6d9d8476e410ac46f5e994beb43f2e2df8a1965f languageName: node linkType: hard