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:
@@ -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) => {
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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>);
|
||||
@@ -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]);
|
||||
@@ -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
|
||||
@@ -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"),
|
||||
};
|
||||
@@ -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",
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user