chore: DI repositories in AvailableSlotsService class (#22356)

* chore: DI available slots service repositories

* remove configService from worker module

* register scheduleRepo in availableSlotsModule

* chore: bump platform libs

* remove useless comment from prisma module

* fix: availableSlotsModule to class deps

* fix: repositoriesModule deps

* chore: container pattern

* refactor: move modules in DI folder

* fixup! refactor: move modules in DI folder
This commit is contained in:
Morgan
2025-07-09 19:55:55 +00:00
committed by GitHub
parent db84343581
commit 5c508bce6d
32 changed files with 266 additions and 59 deletions
+4 -2
View File
@@ -4,11 +4,11 @@ import type { NextApiRequest, NextApiResponse } from "next";
import dayjs from "@calcom/dayjs";
import { isSupportedTimeZone } from "@calcom/lib/dayjs";
import { getAvailableSlotsService } from "@calcom/lib/di/containers/available-slots";
import { HttpError } from "@calcom/lib/http-error";
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
import { createContext } from "@calcom/trpc/server/createContext";
import { getScheduleSchema } from "@calcom/trpc/server/routers/viewer/slots/types";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { TRPCError } from "@trpc/server";
import { getHTTPStatusCodeFromError } from "@trpc/server/http";
@@ -27,11 +27,13 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
}
const input = getScheduleSchema.parse({ usernameList: slugs, isTeamEvent: parsedIsTeamEvent, ...rest });
const timeZoneSupported = input.timeZone ? isSupportedTimeZone(input.timeZone) : false;
const availableSlotsService = new AvailableSlotsService();
const availableSlotsService = getAvailableSlotsService();
const availableSlots = await availableSlotsService.getAvailableSlots({
ctx: await createContext({ req, res }),
input,
});
const slotsInProvidedTimeZone = timeZoneSupported
? Object.keys(availableSlots.slots).reduce(
(acc: Record<string, { time: string; attendees?: number; bookingUid?: string }[]>, date) => {
+1 -1
View File
@@ -38,7 +38,7 @@
"@axiomhq/winston": "^1.2.0",
"@calcom/platform-constants": "*",
"@calcom/platform-enums": "*",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.243",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.249",
"@calcom/platform-types": "*",
"@calcom/platform-utils": "*",
"@calcom/prisma": "*",
@@ -0,0 +1,12 @@
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
import { Injectable } from "@nestjs/common";
import { PrismaOOORepository } from "@calcom/platform-libraries/repositories";
import { PrismaClient } from "@calcom/prisma";
@Injectable()
export class OOORepository extends PrismaOOORepository {
constructor(private readonly dbWrite: PrismaWriteService) {
super(dbWrite.prisma as unknown as PrismaClient);
}
}
@@ -0,0 +1,12 @@
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
import { Injectable } from "@nestjs/common";
import { PrismaScheduleRepository } from "@calcom/platform-libraries/repositories";
import { PrismaClient } from "@calcom/prisma";
@Injectable()
export class ScheduleRepository extends PrismaScheduleRepository {
constructor(private readonly dbWrite: PrismaWriteService) {
super(dbWrite.prisma as unknown as PrismaClient);
}
}
@@ -0,0 +1,15 @@
import { OOORepository } from "@/lib/repositories/PrismaOOORepository";
import { ScheduleRepository } from "@/lib/repositories/PrismaScheduleRepository";
import { Injectable } from "@nestjs/common";
import { AvailableSlotsService as BaseAvailableSlotsService } from "@calcom/platform-libraries/slots";
@Injectable()
export class AvailableSlotsService extends BaseAvailableSlotsService {
constructor(
private readonly oooRepoDependency: OOORepository,
private readonly scheduleRepoDependency: ScheduleRepository
) {
super({ oooRepo: oooRepoDependency, scheduleRepo: scheduleRepoDependency });
}
}
@@ -1,4 +1,5 @@
import { TRPC_ERROR_CODE, TRPC_ERROR_MAP, TRPCErrorCode } from "@/filters/trpc-exception.filter";
import { AvailableSlotsService } from "@/lib/services/AvailableSlots";
import { SlotsOutputService_2024_04_15 } from "@/modules/slots/slots-2024-04-15/services/slots-output.service";
import type { RangeSlots, TimeSlots } from "@/modules/slots/slots-2024-04-15/services/slots-output.service";
import { SlotsWorkerService_2024_04_15 } from "@/modules/slots/slots-2024-04-15/services/slots-worker.service";
@@ -17,7 +18,6 @@ import {
VERSION_2024_08_13,
} from "@calcom/platform-constants";
import { TRPCError } from "@calcom/platform-libraries";
import { AvailableSlotsService } from "@calcom/platform-libraries/slots";
import { RemoveSelectedSlotInput_2024_04_15, ReserveSlotInput_2024_04_15 } from "@calcom/platform-types";
import { ApiResponse, GetAvailableSlotsInput_2024_04_15 } from "@calcom/platform-types";
@@ -31,7 +31,8 @@ export class SlotsController_2024_04_15 {
private readonly slotsService: SlotsService_2024_04_15,
private readonly config: ConfigService,
private readonly slotsOutputService: SlotsOutputService_2024_04_15,
private readonly slotsWorkerService: SlotsWorkerService_2024_04_15
private readonly slotsWorkerService: SlotsWorkerService_2024_04_15,
private readonly availableSlotsService: AvailableSlotsService
) {}
@Post("/reserve")
@@ -170,7 +171,7 @@ export class SlotsController_2024_04_15 {
: query.isTeamEvent;
// Do not use workers in E2E, not supported by TS-JEST
const availableSlotsService = this.config.get<boolean>("e2e") ? new AvailableSlotsService() : null;
const availableSlotsService = this.config.get<boolean>("e2e") ? this.availableSlotsService : null;
const availableSlots = availableSlotsService
? await availableSlotsService.getAvailableSlots({
@@ -1,4 +1,7 @@
import { EventTypesModule_2024_04_15 } from "@/ee/event-types/event-types_2024_04_15/event-types.module";
import { OOORepository as PrismaOOORepository } from "@/lib/repositories/PrismaOOORepository";
import { ScheduleRepository as PrismaScheduleRepository } from "@/lib/repositories/PrismaScheduleRepository";
import { AvailableSlotsService } from "@/lib/services/AvailableSlots";
import { PrismaModule } from "@/modules/prisma/prisma.module";
import { SlotsController_2024_04_15 } from "@/modules/slots/slots-2024-04-15/controllers/slots.controller";
import { SlotsOutputService_2024_04_15 } from "@/modules/slots/slots-2024-04-15/services/slots-output.service";
@@ -14,6 +17,9 @@ import { Module } from "@nestjs/common";
SlotsService_2024_04_15,
SlotsOutputService_2024_04_15,
SlotsWorkerService_2024_04_15,
PrismaOOORepository,
PrismaScheduleRepository,
AvailableSlotsService,
],
controllers: [SlotsController_2024_04_15],
exports: [SlotsService_2024_04_15],
@@ -0,0 +1,24 @@
// apps/api/v2/src/modules/slots/slots-2024-04-15/workers/slots-worker.module.ts
// Needed if ConfigService is used anywhere
import appConfig from "@/config/app";
import { OOORepository as PrismaOOORepository } from "@/lib/repositories/PrismaOOORepository";
import { ScheduleRepository as PrismaScheduleRepository } from "@/lib/repositories/PrismaScheduleRepository";
import { AvailableSlotsService } from "@/lib/services/AvailableSlots";
import { PrismaModule } from "@/modules/prisma/prisma.module";
import { Module, Logger } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { SentryModule } from "@sentry/nestjs/setup";
@Module({
imports: [
SentryModule.forRoot(),
ConfigModule.forRoot({
ignoreEnvFile: true,
isGlobal: true,
load: [appConfig],
}),
PrismaModule,
],
providers: [Logger, PrismaOOORepository, PrismaScheduleRepository, AvailableSlotsService],
})
export class SlotsWorkerModule {}
@@ -1,19 +1,65 @@
import { parentPort } from "worker_threads";
import { AvailableSlotsService } from "@/lib/services/AvailableSlots";
import { Logger } from "@nestjs/common";
import { NestFactory } from "@nestjs/core";
import { IncomingMessage } from "http";
import { parentPort, isMainThread } from "worker_threads";
import { AvailableSlotsService } from "@calcom/platform-libraries/slots";
import { SlotsWorkerModule } from "./slots.worker.module";
const availableSlotsService = new AvailableSlotsService();
interface ContextForGetSchedule extends Record<string, unknown> {
req?: (IncomingMessage & { cookies: Partial<{ [key: string]: string }> }) | undefined;
}
parentPort?.on("message", async (data) => {
try {
const { input, ctx } = data;
interface WorkerMessage {
input: any; // Use a more specific type if available, e.g., TGetScheduleInputSchema
ctx?: ContextForGetSchedule;
}
const result = await availableSlotsService.getAvailableSlots({ input, ctx });
parentPort?.postMessage({ success: true, data: result });
} catch (error) {
parentPort?.postMessage({
success: false,
error: error instanceof Error ? error : new Error("Unknown error"),
});
interface WorkerResult {
success: boolean;
data?: any; // Use TimeSlots
error?: {
message: string;
code?: string;
stack?: string;
};
}
async function bootstrapWorkerApp() {
if (isMainThread) {
console.error("slots-worker-main.ts should only be run in a worker thread.");
process.exit(1);
}
});
const app = await NestFactory.createApplicationContext(SlotsWorkerModule);
const logger = app.get(Logger); // Get the NestJS Logger instance
logger.log("NestJS worker application bootstrapped successfully.");
const availableSlotsService = app.get(AvailableSlotsService);
parentPort?.on("message", async (data: WorkerMessage) => {
try {
const { input, ctx } = data;
const result = await availableSlotsService.getAvailableSlots({ input, ctx });
parentPort?.postMessage({ success: true, data: result } as WorkerResult);
} catch (error: any) {
parentPort?.postMessage({
success: false,
error: error instanceof Error ? error : new Error("Unknown error"),
});
}
});
parentPort?.on("close", async () => {
logger.log("Worker port closed. Shutting down NestJS worker application.");
await app.close();
});
parentPort?.on("disconnect", async () => {
logger.log("Worker port disconnected. Shutting down NestJS worker application.");
await app.close();
});
}
bootstrapWorkerApp();
@@ -1,4 +1,5 @@
import { EventTypesRepository_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.repository";
import { AvailableSlotsService } from "@/lib/services/AvailableSlots";
import { MembershipsRepository } from "@/modules/memberships/memberships.repository";
import { MembershipsService } from "@/modules/memberships/services/memberships.service";
import { TimeSlots } from "@/modules/slots/slots-2024-04-15/services/slots-output.service";
@@ -17,7 +18,6 @@ import {
import { DateTime } from "luxon";
import { z } from "zod";
import { AvailableSlotsService } from "@calcom/platform-libraries/slots";
import { GetSlotsInput_2024_09_04, ReserveSlotInput_2024_09_04 } from "@calcom/platform-types";
import { Booking, EventType } from "@calcom/prisma/client";
@@ -31,8 +31,6 @@ const DEFAULT_RESERVATION_DURATION = 5;
@Injectable()
export class SlotsService_2024_09_04 {
private readonly availableSlotsService: AvailableSlotsService;
constructor(
private readonly eventTypeRepository: EventTypesRepository_2024_06_14,
private readonly slotsRepository: SlotsRepository_2024_09_04,
@@ -40,10 +38,9 @@ export class SlotsService_2024_09_04 {
private readonly slotsInputService: SlotsInputService_2024_09_04,
private readonly membershipsService: MembershipsService,
private readonly membershipsRepository: MembershipsRepository,
private readonly teamsRepository: TeamsRepository
) {
this.availableSlotsService = new AvailableSlotsService();
}
private readonly teamsRepository: TeamsRepository,
private readonly availableSlotsService: AvailableSlotsService
) {}
async getAvailableSlots(query: GetSlotsInput_2024_09_04) {
try {
@@ -1,4 +1,7 @@
import { EventTypesModule_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.module";
import { OOORepository as PrismaOOORepository } from "@/lib/repositories/PrismaOOORepository";
import { ScheduleRepository as PrismaScheduleRepository } from "@/lib/repositories/PrismaScheduleRepository";
import { AvailableSlotsService } from "@/lib/services/AvailableSlots";
import { MembershipsModule } from "@/modules/memberships/memberships.module";
import { OrganizationsRepository } from "@/modules/organizations/index/organizations.repository";
import { OrganizationsTeamsRepository } from "@/modules/organizations/teams/index/organizations-teams.repository";
@@ -33,6 +36,9 @@ import { Module } from "@nestjs/common";
OrganizationsUsersRepository,
OrganizationsRepository,
OrganizationsTeamsRepository,
PrismaOOORepository,
PrismaScheduleRepository,
AvailableSlotsService,
],
controllers: [SlotsController_2024_09_04],
exports: [SlotsService_2024_09_04],
+2 -1
View File
@@ -25,7 +25,8 @@
"@calcom/platform-libraries/schedules": ["../../../packages/platform/libraries/schedules.ts"],
"@calcom/platform-libraries/app-store": ["../../../packages/platform/libraries/app-store.ts"],
"@calcom/platform-libraries/workflows": ["../../../packages/platform/libraries/workflows.ts"],
"@calcom/platform-libraries/conferencing": ["../../../packages/platform/libraries/conferencing.ts"]
"@calcom/platform-libraries/conferencing": ["../../../packages/platform/libraries/conferencing.ts"],
"@calcom/platform-libraries/repositories": ["../../../packages/platform/libraries/repositories.ts"]
},
"incremental": true,
"skipLibCheck": true,
@@ -5,10 +5,10 @@ import { z } from "zod";
import dayjs from "@calcom/dayjs";
import { ZGetRetellLLMSchema } from "@calcom/features/ee/cal-ai-phone/zod-utils";
import type { TGetRetellLLMSchema } from "@calcom/features/ee/cal-ai-phone/zod-utils";
import { getAvailableSlotsService } from "@calcom/lib/di/containers/available-slots";
import { fetcher } from "@calcom/lib/retellAIFetcher";
import { defaultHandler } from "@calcom/lib/server/defaultHandler";
import prisma from "@calcom/prisma";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
dayjs.extend(advancedFormat);
@@ -86,7 +86,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const startTime = now.startOf("month").toISOString();
const endTime = now.add(2, "month").endOf("month").toISOString();
const orgSlug = eventType?.team?.parent?.slug ?? null;
const availableSlotsService = new AvailableSlotsService();
const availableSlotsService = getAvailableSlotsService();
const availableSlots = await availableSlotsService.getAvailableSlots({
input: {
+2 -2
View File
@@ -16,8 +16,8 @@ import {
import { describe, vi, test } from "vitest";
import dayjs from "@calcom/dayjs";
import { getAvailableSlotsService } from "@calcom/lib/di/containers/available-slots";
import { SchedulingType, type BookingStatus } from "@calcom/prisma/enums";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expect, expectedSlotsForSchedule } from "./getSchedule/expects";
import { setupAndTeardown } from "./getSchedule/setupAndTeardown";
@@ -31,7 +31,7 @@ vi.mock("@calcom/lib/constants", () => ({
}));
describe("getSchedule", () => {
const availableSlotsService = new AvailableSlotsService();
const availableSlotsService = getAvailableSlotsService();
setupAndTeardown();
// TODO: Move these inside describe('Team Event')
@@ -9,13 +9,13 @@ import {
import { describe, test } from "vitest";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { getAvailableSlotsService } from "@calcom/lib/di/containers/available-slots";
import { expect, expectedSlotsForSchedule } from "./expects";
import { setupAndTeardown } from "./setupAndTeardown";
describe("getSchedule", () => {
const availableSlotsService = new AvailableSlotsService();
const availableSlotsService = getAvailableSlotsService();
setupAndTeardown();
describe("Calendar event", () => {
test("correctly identifies unavailable slots from selected calendars at user level", async () => {
@@ -12,13 +12,14 @@ import { expectNoAttemptToGetAvailability } from "../../utils/bookingScenario/ex
import { describe, test } from "vitest";
import { getAvailableSlotsService } from "@calcom/lib/di/containers/available-slots";
import { MembershipRole } from "@calcom/prisma/enums";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expect, expectedSlotsForSchedule } from "./expects";
import { setupAndTeardown } from "./setupAndTeardown";
describe("getSchedule", () => {
const availableSlotsService = getAvailableSlotsService();
setupAndTeardown();
describe("Delegation Credential", () => {
@@ -90,7 +91,6 @@ describe("getSchedule", () => {
};
await createBookingScenario(scenarioData);
const availableSlotsService = new AvailableSlotsService();
const scheduleForDayWithAGoogleCalendarBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
@@ -182,7 +182,6 @@ describe("getSchedule", () => {
};
await createBookingScenario(scenarioData);
const availableSlotsService = new AvailableSlotsService();
const scheduleForDayWithAGoogleCalendarBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
@@ -8,8 +8,8 @@ import type { ScenarioData } from "../../utils/bookingScenario/bookingScenario";
import { describe, expect, vi, test } from "vitest";
import { getAvailableSlotsService } from "@calcom/lib/di/containers/available-slots";
import { PeriodType } from "@calcom/prisma/enums";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expectedSlotsForSchedule } from "./expects";
import { setupAndTeardown } from "./setupAndTeardown";
@@ -70,7 +70,7 @@ vi.mock("@calcom/lib/constants", () => ({
}));
describe("getSchedule", () => {
const availableSlotsService = new AvailableSlotsService();
const availableSlotsService = getAvailableSlotsService();
setupAndTeardown();
describe("Future Limits", () => {
describe("PeriodType=ROLLING", () => {
@@ -10,8 +10,8 @@ import {
import { describe, test, vi } from "vitest";
import type { z } from "zod";
import { getAvailableSlotsService } from "@calcom/lib/di/containers/available-slots";
import type { getScheduleSchema } from "@calcom/trpc/server/routers/viewer/slots/types";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expect } from "./expects";
import { setupAndTeardown } from "./setupAndTeardown";
@@ -89,7 +89,7 @@ async function setupTeamAndFeatures() {
}
describe("getSchedule", () => {
const availableSlotsService = new AvailableSlotsService();
const availableSlotsService = getAvailableSlotsService();
setupAndTeardown();
describe("Restriction Schedule", () => {
@@ -10,9 +10,9 @@ import type { IncomingMessage } from "http";
import { describe, test, beforeEach, vi } from "vitest";
import type { z } from "zod";
import { getAvailableSlotsService } from "@calcom/lib/di/containers/available-slots";
import { prisma } from "@calcom/prisma";
import type { getScheduleSchema, GetScheduleOptions } from "@calcom/trpc/server/routers/viewer/slots/types";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expect } from "./expects";
import { setupAndTeardown } from "./setupAndTeardown";
@@ -62,7 +62,7 @@ const getBaseScenarioData = (): ScheduleScenario => ({
});
describe("getSchedule", () => {
const availableSlotsService = new AvailableSlotsService();
const availableSlotsService = getAvailableSlotsService();
setupAndTeardown();
describe("Reserved Slots", () => {
@@ -0,0 +1,19 @@
import { createContainer } from "@evyweb/ioctopus";
import { DI_TOKENS } from "@calcom/lib/di/tokens";
import { prismaModule } from "@calcom/prisma/prisma.module";
import type { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { availableSlotsModule } from "../modules/available-slots";
import { oooRepositoryModule } from "../modules/ooo";
import { scheduleRepositoryModule } from "../modules/schedule";
const container = createContainer();
container.load(DI_TOKENS.PRISMA_MODULE, prismaModule);
container.load(DI_TOKENS.OOO_REPOSITORY_MODULE, oooRepositoryModule);
container.load(DI_TOKENS.SCHEDULE_REPOSITORY_MODULE, scheduleRepositoryModule);
container.load(DI_TOKENS.AVAILABLE_SLOTS_SERVICE_MODULE, availableSlotsModule);
export function getAvailableSlotsService() {
return container.get<AvailableSlotsService>(DI_TOKENS.AVAILABLE_SLOTS_SERVICE);
}
@@ -0,0 +1,12 @@
import { createModule } from "@evyweb/ioctopus";
import type { IAvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { DI_TOKENS } from "../tokens";
export const availableSlotsModule = createModule();
availableSlotsModule.bind(DI_TOKENS.AVAILABLE_SLOTS_SERVICE).toClass(AvailableSlotsService, {
oooRepo: DI_TOKENS.OOO_REPOSITORY,
scheduleRepo: DI_TOKENS.SCHEDULE_REPOSITORY,
} satisfies Record<keyof IAvailableSlotsService, symbol>);
+7
View File
@@ -0,0 +1,7 @@
import { createModule } from "@evyweb/ioctopus";
import { DI_TOKENS } from "@calcom/lib/di/tokens";
import { PrismaOOORepository } from "@calcom/lib/server/repository/ooo";
export const oooRepositoryModule = createModule();
oooRepositoryModule.bind(DI_TOKENS.OOO_REPOSITORY).toClass(PrismaOOORepository, [DI_TOKENS.PRISMA_CLIENT]);
+9
View File
@@ -0,0 +1,9 @@
import { createModule } from "@evyweb/ioctopus";
import { DI_TOKENS } from "@calcom/lib/di/tokens";
import { ScheduleRepository } from "@calcom/lib/server/repository/schedule";
export const scheduleRepositoryModule = createModule();
scheduleRepositoryModule
.bind(DI_TOKENS.SCHEDULE_REPOSITORY)
.toClass(ScheduleRepository, [DI_TOKENS.PRISMA_CLIENT]); // Maps 'prismaClient' param to PRISMA_CLIENT token
+11
View File
@@ -0,0 +1,11 @@
export const DI_TOKENS = {
PRISMA_CLIENT: Symbol("PrismaClient"),
READ_ONLY_PRISMA_CLIENT: Symbol("ReadOnlyPrismaClient"),
PRISMA_MODULE: Symbol("PrismaModule"),
OOO_REPOSITORY: Symbol("OOORepository"),
OOO_REPOSITORY_MODULE: Symbol("OOORepositoryModule"),
SCHEDULE_REPOSITORY: Symbol("ScheduleRepository"),
SCHEDULE_REPOSITORY_MODULE: Symbol("ScheduleRepositoryModule"),
AVAILABLE_SLOTS_SERVICE: Symbol("AvailableSlotsService"),
AVAILABLE_SLOTS_SERVICE_MODULE: Symbol("AvailableSlotsModule"),
};
+8
View File
@@ -68,6 +68,11 @@
"import": "./dist/conferencing.js",
"require": "./dist/conferencing.cjs",
"types": "./dist/conferencing.d.ts"
},
"./repositories": {
"import": "./dist/repositories.js",
"require": "./dist/repositories.cjs",
"types": "./dist/repositories.d.ts"
}
},
"typesVersions": {
@@ -92,6 +97,9 @@
],
"conferencing": [
"dist/conferencing.d.ts"
],
"repositories": [
"dist/repositories.d.ts"
]
}
}
@@ -0,0 +1,2 @@
export { PrismaOOORepository } from "@calcom/lib/server/repository/ooo";
export { ScheduleRepository as PrismaScheduleRepository } from "@calcom/lib/server/repository/schedule";
@@ -25,6 +25,7 @@ export default defineConfig({
workflows: resolve(__dirname, "./workflows.ts"),
slots: resolve(__dirname, "./slots.ts"),
conferencing: resolve(__dirname, "./conferencing.ts"),
repositories: resolve(__dirname, "./repositories.ts"),
},
name: "calcom-lib",
fileName: "calcom-lib",
+11
View File
@@ -0,0 +1,11 @@
import { createModule } from "@evyweb/ioctopus";
import { DI_TOKENS } from "@calcom/lib/di/tokens";
import { prisma, readonlyPrisma } from "./index";
export const prismaModule = createModule();
prismaModule.bind(DI_TOKENS.PRISMA_CLIENT).toFactory(() => prisma, "singleton");
prismaModule.bind(DI_TOKENS.READ_ONLY_PRISMA_CLIENT).toFactory(() => readonlyPrisma, "singleton");
@@ -1,6 +1,7 @@
import type { IncomingMessage } from "http";
import { AvailableSlotsService } from "../slots/util";
import { getAvailableSlotsService } from "@calcom/lib/di/containers/available-slots";
import type { TGetTeamScheduleInputSchema } from "./getTeamSchedule.schema";
export type GetTeamScheduleOptions = {
@@ -13,6 +14,6 @@ interface ContextForGetSchedule extends Record<string, unknown> {
}
export const getTeamScheduleHandler = async ({ ctx, input }: GetTeamScheduleOptions) => {
const availableSlotsService = new AvailableSlotsService();
const availableSlotsService = getAvailableSlotsService();
return await availableSlotsService.getAvailableSlots({ ctx, input });
};
@@ -1,7 +1,8 @@
import { getAvailableSlotsService } from "@calcom/lib/di/containers/available-slots";
import type { GetScheduleOptions } from "./types";
import { AvailableSlotsService } from "./util";
export const getScheduleHandler = async ({ ctx, input }: GetScheduleOptions) => {
const availableSlotsService = new AvailableSlotsService();
const availableSlotsService = getAvailableSlotsService();
return await availableSlotsService.getAvailableSlots({ ctx, input });
};
@@ -44,13 +44,12 @@ import { getTotalBookingDuration } from "@calcom/lib/server/queries/booking";
import { BookingRepository as BookingRepo } from "@calcom/lib/server/repository/booking";
import { EventTypeRepository } from "@calcom/lib/server/repository/eventType";
import { RoutingFormResponseRepository } from "@calcom/lib/server/repository/formResponse";
import { PrismaOOORepository } from "@calcom/lib/server/repository/ooo";
import { ScheduleRepository } from "@calcom/lib/server/repository/schedule";
import type { PrismaOOORepository } from "@calcom/lib/server/repository/ooo";
import type { ScheduleRepository } from "@calcom/lib/server/repository/schedule";
import { SelectedSlotsRepository } from "@calcom/lib/server/repository/selectedSlots";
import { TeamRepository } from "@calcom/lib/server/repository/team";
import { UserRepository, withSelectedCalendars } from "@calcom/lib/server/repository/user";
import getSlots from "@calcom/lib/slots";
import prisma from "@calcom/prisma";
import { PeriodType } from "@calcom/prisma/client";
import { SchedulingType } from "@calcom/prisma/enums";
import type { EventBusyDate, EventBusyDetails } from "@calcom/types/Calendar";
@@ -89,7 +88,14 @@ export type GetAvailableSlotsResponse = Awaited<
ReturnType<(typeof AvailableSlotsService)["prototype"]["_getAvailableSlots"]>
>;
export interface IAvailableSlotsService {
oooRepo: PrismaOOORepository;
scheduleRepo: ScheduleRepository;
}
export class AvailableSlotsService {
constructor(private readonly dependencies: IAvailableSlotsService) {}
private async _getReservedSlotsAndCleanupExpired({
bookerClientUid,
usersWithCredentials,
@@ -626,8 +632,7 @@ export class AvailableSlotsService {
);
private async _getOOODates(startTimeDate: Date, endTimeDate: Date, allUserIds: number[]) {
const oooRepo = new PrismaOOORepository(prisma);
return oooRepo.findManyOOO({ startTimeDate, endTimeDate, allUserIds });
return this.dependencies.oooRepo.findManyOOO({ startTimeDate, endTimeDate, allUserIds });
}
private getOOODates = withReporting(this._getOOODates.bind(this), "getOOODates");
@@ -1054,8 +1059,7 @@ export class AvailableSlotsService {
// TODO: DI isRestrictionScheduleEnabled
const isRestrictionScheduleFeatureEnabled = await isRestrictionScheduleEnabled(eventType.team?.id);
if (eventType.restrictionScheduleId && isRestrictionScheduleFeatureEnabled) {
const scheduleRepo = new ScheduleRepository(prisma);
const restrictionSchedule = await scheduleRepo.findScheduleByIdForBuildDateRanges({
const restrictionSchedule = await this.dependencies.scheduleRepo.findScheduleByIdForBuildDateRanges({
scheduleId: eventType.restrictionScheduleId,
});
if (restrictionSchedule) {
+5 -5
View File
@@ -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.243"
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.249"
"@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.243":
version: 0.0.243
resolution: "@calcom/platform-libraries@npm:0.0.243"
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.249":
version: 0.0.249
resolution: "@calcom/platform-libraries@npm:0.0.249"
dependencies:
"@calcom/features": "*"
"@calcom/lib": "*"
checksum: ce0a4778857a62a6df46b1c0b419fbaad1d874d7b0da92d43589348f6e07a7de912703692c9fbc1e21fb2e0bf4d323bcd7eae96b5198376216216c872374cc09
checksum: 5ca9eec4c30ffa78b817979202dc33fa96f701b97f54ed946311b0f6a35d1a3c6f37947229cef3b3133438134bf82bbea15dfe47b32156f0da6b1f59c9ed9763
languageName: node
linkType: hard