refactor: convert SelectedSlotsRepository to use dependency injection pattern (#22387)
* refactor: convert TeamRepository to use dependency injection pattern - Add constructor injection for PrismaClient in TeamRepository - Convert all static methods to instance methods using this.prismaClient - Update all usage sites to use two-step pattern: const teamRepo = new TeamRepository(prisma); teamRepo.method(...) - Optimize instance reuse within same function scopes where possible - Update test files to work with new instance pattern - Preserve all existing functionality and method signatures Follows the same dependency injection pattern as UserRepository refactoring Co-Authored-By: morgan@cal.com <morgan@cal.com> * refactor: convert SelectedSlotsRepository to use dependency injection pattern - Add constructor injection for PrismaClient/PrismaTransaction - Convert all static methods to instance methods using this.prismaClient - Update usage sites to use two-step instantiation pattern: const slotsRepo = new SelectedSlotsRepository(prisma); slotsRepo.method(...) - Optimize instance reuse in util.ts for multiple method calls - Update test mocks to handle new constructor-based pattern - Add explicit type annotations to resolve TypeScript inference issues Follows same dependency injection pattern as UserRepository and TeamRepository refactorings. Co-Authored-By: morgan@cal.com <morgan@cal.com> * chore: bump platform libs * fix: devin mistake prisma client * fix: devin typing mistakes * chore: bump platform libs --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: morgan@cal.com <morgan@cal.com> Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
This commit is contained in:
7 files changed
+29
-26
No files matched your search
@@ -38,7 +38,7 @@
|
||||
"@axiomhq/winston": "^1.2.0",
|
||||
"@calcom/platform-constants": "*",
|
||||
"@calcom/platform-enums": "*",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.253",
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.255",
|
||||
"@calcom/platform-types": "*",
|
||||
"@calcom/platform-utils": "*",
|
||||
"@calcom/prisma": "*",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
|
||||
import { prisma } from "@calcom/prisma";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
|
||||
type WhereCondition = {
|
||||
slotUtcStartDate?: Date | string;
|
||||
@@ -23,17 +23,19 @@ export type TimeSlot = {
|
||||
};
|
||||
|
||||
export class SelectedSlotsRepository {
|
||||
static async findMany({ where, select }: FindManyArgs) {
|
||||
return await prisma.selectedSlots.findMany({ where, select });
|
||||
constructor(private prismaClient: PrismaClient) {}
|
||||
|
||||
async findMany({ where, select }: FindManyArgs) {
|
||||
return await this.prismaClient.selectedSlots.findMany({ where, select });
|
||||
}
|
||||
|
||||
static async findFirst({ where }: { where: Prisma.SelectedSlotsWhereInput }) {
|
||||
return await prisma.selectedSlots.findFirst({
|
||||
async findFirst({ where }: { where: Prisma.SelectedSlotsWhereInput }) {
|
||||
return await this.prismaClient.selectedSlots.findFirst({
|
||||
where,
|
||||
});
|
||||
}
|
||||
|
||||
static async findReservedByOthers({
|
||||
async findReservedByOthers({
|
||||
slot,
|
||||
eventTypeId,
|
||||
uid,
|
||||
@@ -53,7 +55,7 @@ export class SelectedSlotsRepository {
|
||||
});
|
||||
}
|
||||
|
||||
static async findManyReservedByOthers(slots: TimeSlot[], eventTypeId: number, uid: string) {
|
||||
async findManyReservedByOthers(slots: TimeSlot[], eventTypeId: number, uid: string) {
|
||||
return await this.findMany({
|
||||
where: {
|
||||
OR: slots.map((slot) => ({
|
||||
@@ -71,14 +73,14 @@ export class SelectedSlotsRepository {
|
||||
});
|
||||
}
|
||||
|
||||
static async findManyUnexpiredSlots({
|
||||
async findManyUnexpiredSlots({
|
||||
userIds,
|
||||
currentTimeInUtc,
|
||||
}: {
|
||||
userIds: number[];
|
||||
currentTimeInUtc: string;
|
||||
}) {
|
||||
return prisma.selectedSlots.findMany({
|
||||
return this.prismaClient.selectedSlots.findMany({
|
||||
where: {
|
||||
userId: { in: userIds },
|
||||
releaseAt: { gt: currentTimeInUtc },
|
||||
@@ -95,14 +97,14 @@ export class SelectedSlotsRepository {
|
||||
});
|
||||
}
|
||||
|
||||
static async deleteManyExpiredSlots({
|
||||
async deleteManyExpiredSlots({
|
||||
eventTypeId,
|
||||
currentTimeInUtc,
|
||||
}: {
|
||||
eventTypeId: number;
|
||||
currentTimeInUtc: string;
|
||||
}) {
|
||||
return prisma.selectedSlots.deleteMany({
|
||||
return this.prismaClient.selectedSlots.deleteMany({
|
||||
where: {
|
||||
eventTypeId: { equals: eventTypeId },
|
||||
releaseAt: { lt: currentTimeInUtc },
|
||||
|
||||
@@ -40,9 +40,8 @@ export const isAvailableHandler = async ({
|
||||
|
||||
// Check each slot's availability
|
||||
// Without uid, we must not check for reserved slots because if uuid isn't set in cookie yet, but it is going to be through reserveSlot request soon, we could consider the slot as reserved accidentally.
|
||||
const reservedSlots = uid
|
||||
? await SelectedSlotsRepository.findManyReservedByOthers(slots, eventTypeId, uid)
|
||||
: [];
|
||||
const slotsRepo = new SelectedSlotsRepository(ctx.prisma);
|
||||
const reservedSlots = uid ? await slotsRepo.findManyReservedByOthers(slots, eventTypeId, uid) : [];
|
||||
|
||||
// Map all slots to their availability status
|
||||
const slotsWithStatus: TIsAvailableOutputSchema["slots"] = slots.map((slot) => {
|
||||
|
||||
@@ -10,12 +10,12 @@ import { vi, describe, it, expect, afterEach } from "vitest";
|
||||
// We alias the module path once we know WEBAPP_URL has been configured.
|
||||
const dynamicImportHandler = async () => await import("./reserveSlot.handler");
|
||||
|
||||
// The repository static method is used to check for an existing reservation by someone else.
|
||||
// The repository instance method is used to check for an existing reservation by someone else.
|
||||
// To keep this unit test isolated from the database layer, we stub this to always resolve falsey.
|
||||
vi.mock("@calcom/lib/server/repository/selectedSlots", () => ({
|
||||
SelectedSlotsRepository: {
|
||||
SelectedSlotsRepository: vi.fn().mockImplementation(() => ({
|
||||
findReservedByOthers: vi.fn().mockResolvedValue(null),
|
||||
},
|
||||
})),
|
||||
}));
|
||||
|
||||
// A tiny helper to build a canned handler context with stubbed Prisma methods.
|
||||
|
||||
@@ -64,7 +64,8 @@ export const reserveSlotHandler = async ({ ctx, input }: ReserveSlotOptions) =>
|
||||
}
|
||||
|
||||
// Check for existing reservations for the same slot
|
||||
const reservedBySomeoneElse = await SelectedSlotsRepository.findReservedByOthers({
|
||||
const slotsRepo = new SelectedSlotsRepository(prisma);
|
||||
const reservedBySomeoneElse = await slotsRepo.findReservedByOthers({
|
||||
slot: {
|
||||
utcStartIso: slotUtcStartDate,
|
||||
utcEndIso: slotUtcEndDate,
|
||||
|
||||
@@ -107,9 +107,10 @@ export class AvailableSlotsService {
|
||||
eventTypeId: number;
|
||||
}) {
|
||||
const currentTimeInUtc = dayjs.utc().format();
|
||||
const slotsRepo = new SelectedSlotsRepository(prisma);
|
||||
|
||||
const unexpiredSelectedSlots =
|
||||
(await SelectedSlotsRepository.findManyUnexpiredSlots({
|
||||
(await slotsRepo.findManyUnexpiredSlots({
|
||||
userIds: usersWithCredentials.map((user) => user.id),
|
||||
currentTimeInUtc,
|
||||
})) || [];
|
||||
@@ -123,7 +124,7 @@ export class AvailableSlotsService {
|
||||
return reservedSlots;
|
||||
|
||||
async function _cleanupExpiredSlots({ eventTypeId }: { eventTypeId: number }) {
|
||||
await SelectedSlotsRepository.deleteManyExpiredSlots({ eventTypeId, currentTimeInUtc });
|
||||
await slotsRepo.deleteManyExpiredSlots({ eventTypeId, currentTimeInUtc });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2519,7 +2519,7 @@ __metadata:
|
||||
"@axiomhq/winston": ^1.2.0
|
||||
"@calcom/platform-constants": "*"
|
||||
"@calcom/platform-enums": "*"
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.253"
|
||||
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.255"
|
||||
"@calcom/platform-types": "*"
|
||||
"@calcom/platform-utils": "*"
|
||||
"@calcom/prisma": "*"
|
||||
@@ -3565,13 +3565,13 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.253":
|
||||
version: 0.0.253
|
||||
resolution: "@calcom/platform-libraries@npm:0.0.253"
|
||||
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.255":
|
||||
version: 0.0.255
|
||||
resolution: "@calcom/platform-libraries@npm:0.0.255"
|
||||
dependencies:
|
||||
"@calcom/features": "*"
|
||||
"@calcom/lib": "*"
|
||||
checksum: 797435f9a72750dc7f8bc6d3b52b1b1fa93701451907f4ae29028403619365649bdc7c5632ac1db326bd6ed1b90e27544d14ae108e042fe18eaeac4ca11e8606
|
||||
checksum: 50ec08f31a1a30fde270335f93065554ff93d74ab96d059262cec44f9efcae2036c2a7c26177cb3a1a2f708dabea4736b26110629ab08691e97a62f9d3464cd9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in new issue
Block a user