chore: [Booking flow refactor - DI Cleanup - 1] Make ioctopus flow more type-safe and runtime-safe#23541
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
WalkthroughThis PR migrates DI imports from the external "@evyweb/ioctopus" to local "../di" and introduces a new helper bindModuleToClassOnToken in packages/lib/di/di.ts. It refactors booking-related DI: moves booking tokens into packages/lib/di/bookings/tokens.ts and spreads them into DI_TOKENS, deletes legacy RegularBookingService DI files under packages/features/bookings, and adds new booking modules/containers under packages/lib/di/bookings (including RegularBookingService.module/container). Multiple modules now export moduleLoader wrappers and several repository modules switch to toClass bindings with Prisma client injection. Prisma’s module now exports a moduleLoader with token/readOnlyToken. Numerous containers update createContainer import paths. Possibly related PRs
Pre-merge checks (2 passed, 1 warning)❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Hey there and thank you for opening this pull request! 👋🏼 We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted. Details: |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (21)
packages/lib/di/modules/CheckBookingAndDurationLimits.ts (2)
15-19: Make the wrapper readonly to prevent accidental mutation.Add
as constto narrow types and freeze shape.-export const checkBookingAndDurationLimitsModuleWithToken = { +export const checkBookingAndDurationLimitsModuleWithToken = { token, moduleToken, module: checkBookingAndDurationLimitsModule, -}; +} as const;Nit: consider using the same DI_TOKENS import style used elsewhere (absolute alias) for consistency.
15-19: Centralize the wrapper shape.Define and reuse a shared
ModuleWithTokentype to standardize these objects across modules.Example (in a common DI file):
export type ModuleWithToken = Readonly<{ token: symbol; moduleToken: symbol; module: ReturnType<typeof createModule>; }>;Then annotate:
export const checkBookingAndDurationLimitsModuleWithToken: ModuleWithToken = { ... } as const;packages/lib/di/modules/Cache.ts (1)
15-19: Harden the wrapper by marking it readonly.-export const cacheModuleWithToken = { +export const cacheModuleWithToken = { token, moduleToken, module: cacheModule, -}; +} as const;packages/lib/di/modules/CheckBookingLimits.ts (2)
6-11: Add a minimal compile-time guard on dep keys.Mirror the pattern used in other modules by asserting the dep-map keys.
- .bind(token) - .toClass(CheckBookingLimitsService, { bookingRepo: DI_TOKENS.BOOKING_REPOSITORY }); + .bind(token) + .toClass( + CheckBookingLimitsService, + { bookingRepo: DI_TOKENS.BOOKING_REPOSITORY } as const satisfies Record<"bookingRepo", symbol>, + );
13-17: Mark the wrapperas constfor safety and consistency.-export const checkBookingLimitsModuleWithToken = { +export const checkBookingLimitsModuleWithToken = { token, moduleToken, module: checkBookingLimitsModule, -}; +} as const;packages/prisma/prisma.module.ts (2)
8-10: Use the localtokenalias in the binding for consistency.-const token = DI_TOKENS.PRISMA_CLIENT; +const token = DI_TOKENS.PRISMA_CLIENT; const moduleToken = DI_TOKENS.PRISMA_MODULE; -prismaModule.bind(DI_TOKENS.PRISMA_CLIENT).toFactory(() => prisma, "singleton"); +prismaModule.bind(token).toFactory(() => prisma, "singleton");
13-17: Applyas constto the wrapper.-export const prismaModuleWithToken = { +export const prismaModuleWithToken = { token, moduleToken, module: prismaModule, -}; +} as const;packages/lib/di/modules/Booking.ts (2)
9-9: Optional: prefer named deps over positional array (if supported).Positional arrays couple binding to constructor order. A named map is more resilient to constructor changes.
11-15: Freeze the wrapper withas const.-export const bookingRepositoryModuleWithToken = { +export const bookingRepositoryModuleWithToken = { token, moduleToken, module: bookingRepositoryModule, -}; +} as const;packages/lib/di/modules/Features.ts (2)
9-9: Prefer using the new type-safe binder + export aloadDepsto preload Prisma.Leverage
bindModuleToClassOnTokenfor compile-time validation and to auto-generate a deps loader. This keeps the module consistent with others (e.g., RegularBookingService). Adjust the deps key to matchFeaturesRepository['deps'].Example refactor:
import { DI_TOKENS } from "@calcom/lib/di/tokens"; +import { bindModuleToClassOnToken } from "@calcom/lib/di/ioctopus"; +import { prismaModuleWithToken } from "@calcom/prisma/prisma.module"; export const featuresRepositoryModule = createModule(); const token = DI_TOKENS.FEATURES_REPOSITORY; const moduleToken = DI_TOKENS.FEATURES_REPOSITORY_MODULE; -featuresRepositoryModule.bind(token).toClass(FeaturesRepository, [DI_TOKENS.PRISMA_CLIENT]); +export const loadDeps = bindModuleToClassOnToken({ + module: featuresRepositoryModule, + token, + classs: FeaturesRepository, + depsMap: { + // Replace 'prisma' key if FeaturesRepository.deps uses a different key name + prisma: prismaModuleWithToken, + }, +});
11-15: Add a shared type for the wrapper to enforce shape.Export and reuse a
ModuleWithTokentype (e.g., from@calcom/lib/di/ioctopus) to catch shape drift across modules.packages/lib/di/ioctopus.ts (4)
24-37: Dial down library-wide console noise; gate logs behind an option.Unconditional
console.login a shared lib is noisy and may leak internals. Make logging opt-in and switch toconsole.debug.Apply:
- return function loadDeps(container: Container) { - console.log("[DI DEBUG] Binding Class to token", token); - console.log("[DI DEBUG] Deps Object", depsObject); - console.log("[DI DEBUG] Bound Class to token", token); + return function loadDeps(container: Container, opts?: { debug?: boolean }) { + if (opts?.debug) console.debug("[DI DEBUG] Binding Class to token", token); + if (opts?.debug) console.debug("[DI DEBUG] Deps Object", depsObject); + if (opts?.debug) console.debug("[DI DEBUG] Bound Class to token", token); - for (const key in depsMap) { - const depToken = depsMap[key as keyof typeof depsMap].moduleToken; - const depModule = depsMap[key as keyof typeof depsMap].module; - console.log("[DI DEBUG] Loading dependency", depToken, depModule); - container.load(depToken, depModule); - console.log("[DI DEBUG] Successfully loaded dependency", depToken); - } - console.log("[DI DEBUG] All dependencies loaded for token", token); + for (const { moduleToken: depToken, module: depModule } of Object.values(depsMap)) { + if (opts?.debug) console.debug("[DI DEBUG] Loading dependency", depToken); + container.load(depToken, depModule); + if (opts?.debug) console.debug("[DI DEBUG] Successfully loaded dependency", depToken); + } + if (opts?.debug) console.debug("[DI DEBUG] All dependencies loaded for token", token); };
16-19: Introduce and reuse aModuleWithTokentype for stronger typing.This avoids repeating the shape and keeps modules consistent.
Apply:
import type { Container, Module } from "@evyweb/ioctopus"; +export type ModuleWithToken = { + token: string | symbol; + moduleToken: string | symbol; + module: Module; +}; + ... depsMap: Record< keyof InstanceType<TClass>["deps"], - { token: string | symbol; moduleToken: string | symbol; module: Module } + ModuleWithToken >;
7-20: Optional: tighten type constraint on classes expected to havedeps.If all participating classes expose
deps, constrainTClassto improve errors when misused. Keep as an overload to avoid breaking existing callers.Example overload:
type HasDeps = { deps: Record<string | number | symbol, unknown> }; export function bindModuleToClassOnToken<TClass extends new (...args: any[]) => any>(args: { module: Module; token: string | symbol; classs: TClass; depsMap: Record<keyof InstanceType<TClass>["deps"], ModuleWithToken>; }): (container: Container, opts?: { debug?: boolean }) => void; // Stricter version: export function bindModuleToClassOnToken<TClass extends new (...args: any[]) => HasDeps>(args: { module: Module; token: string | symbol; classs: TClass; depsMap: Record<keyof InstanceType<TClass>["deps"], ModuleWithToken>; }): (container: Container, opts?: { debug?: boolean }) => void;
29-35: Avoidfor..inon objects with unknown prototypes.Swapping to
Object.values(depsMap)prevents accidental iteration over inherited props.packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts (1)
17-17: Load dependencies once at module init, not on every call.Calling
loadDepsper invocation can repeatedly callcontainer.load, which may be non-idempotent and adds overhead.Apply:
-export function getRegularBookingService(): RegularBookingService { - loadRegularBookingServiceModuleDeps(regularBookingServiceContainer); +// Preload deps once +loadRegularBookingServiceModuleDeps(regularBookingServiceContainer); + +export function getRegularBookingService(): RegularBookingService {And remove the now-redundant call inside the function.
- loadRegularBookingServiceModuleDeps(regularBookingServiceContainer);packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts (5)
15-16: Narrow token types withas const(optional).Helps keep literal types and catch mismatches at compile time.
-const token = DI_TOKENS.REGULAR_BOOKING_SERVICE; -const moduleToken = DI_TOKENS.REGULAR_BOOKING_SERVICE_MODULE; +const token = DI_TOKENS.REGULAR_BOOKING_SERVICE as const; +const moduleToken = DI_TOKENS.REGULAR_BOOKING_SERVICE_MODULE as const;
20-20: "classs" reads like a typo—preferklassorctorfor clarity.If
bindModuleToClassOnTokenaccepts an alias, consider this rename to avoid confusion; otherwise, ignore.- classs: RegularBookingService, + klass: RegularBookingService,
21-28: Freeze depsMap literal for stronger inference.Adding
as constpreserves key literals and prevents accidental mutation.depsMap: { cacheService: cacheModuleWithToken, checkBookingAndDurationLimitsService: checkBookingAndDurationLimitsModuleWithToken, prismaClient: prismaModuleWithToken, bookingRepository: bookingRepositoryModuleWithToken, featuresRepository: featuresRepositoryModuleWithToken, checkBookingLimitsService: checkBookingLimitsModuleWithToken, - }, + } as const,
31-35: Type-guard the WithToken object.Lock it down with
as const(and optionallysatisfiesa common ModuleWithToken shape if available).-const regularBookingServiceModuleWithToken = { +const regularBookingServiceModuleWithToken = { token, moduleToken, module: regularBookingServiceModule, -}; +} as const;Optionally, if a helper type exists:
const regularBookingServiceModuleWithToken = { token, moduleToken, module: regularBookingServiceModule, } satisfies ModuleWithToken;
31-35: Inline-export the WithToken object to reduce export churn (optional).Keeps declaration and export together; minor readability win.
-const regularBookingServiceModuleWithToken = { +export const regularBookingServiceModuleWithToken = { token, moduleToken, module: regularBookingServiceModule, -}; +}; -export { loadDeps, regularBookingServiceModuleWithToken }; +export { loadDeps };Also applies to: 39-39
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (9)
packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts(1 hunks)packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts(1 hunks)packages/lib/di/ioctopus.ts(1 hunks)packages/lib/di/modules/Booking.ts(1 hunks)packages/lib/di/modules/Cache.ts(1 hunks)packages/lib/di/modules/CheckBookingAndDurationLimits.ts(1 hunks)packages/lib/di/modules/CheckBookingLimits.ts(1 hunks)packages/lib/di/modules/Features.ts(1 hunks)packages/prisma/prisma.module.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/lib/di/modules/Booking.tspackages/prisma/prisma.module.tspackages/lib/di/modules/Features.tspackages/lib/di/ioctopus.tspackages/lib/di/modules/CheckBookingLimits.tspackages/lib/di/modules/Cache.tspackages/features/bookings/lib/di/modules/RegularBookingServiceModule.tspackages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
packages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/lib/di/modules/Booking.tspackages/prisma/prisma.module.tspackages/lib/di/modules/Features.tspackages/lib/di/ioctopus.tspackages/lib/di/modules/CheckBookingLimits.tspackages/lib/di/modules/Cache.tspackages/features/bookings/lib/di/modules/RegularBookingServiceModule.tspackages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
packages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/lib/di/modules/Booking.tspackages/prisma/prisma.module.tspackages/lib/di/modules/Features.tspackages/lib/di/ioctopus.tspackages/lib/di/modules/CheckBookingLimits.tspackages/lib/di/modules/Cache.tspackages/features/bookings/lib/di/modules/RegularBookingServiceModule.tspackages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts
🧬 Code graph analysis (7)
packages/lib/di/modules/CheckBookingAndDurationLimits.ts (2)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
ICheckBookingAndDurationLimitsService(17-19)
packages/lib/di/modules/Booking.ts (2)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/lib/server/repository/booking.ts (1)
BookingRepository(117-948)
packages/prisma/prisma.module.ts (2)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/prisma/index.ts (1)
readonlyPrisma(71-75)
packages/lib/di/modules/Features.ts (1)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)
packages/lib/di/modules/CheckBookingLimits.ts (1)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)
packages/lib/di/modules/Cache.ts (2)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/features/calendar-cache/lib/getShouldServeCache.ts (1)
ICacheService(3-5)
packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts (1)
packages/features/bookings/lib/handleNewBooking.ts (1)
RegularBookingService(2477-2496)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Install dependencies / Yarn install & cache
- GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (8)
packages/lib/di/modules/CheckBookingAndDurationLimits.ts (1)
9-13: Good: token/moduleToken aliases and typed deps mapping.Local aliases + satisfies guard prevent mismatches and catch key drift at compile time.
packages/lib/di/modules/Cache.ts (1)
9-11: Good: local token/moduleToken aliases.This aligns with the new standard and avoids cross-file token drift.
packages/lib/di/modules/Features.ts (1)
11-15: Good move: standardized ModuleWithToken wrapper.This aligns with the new pattern and reduces token drift. Naming is consistent with other modules.
packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts (3)
11-14: LGTM: module and token loaded correctly.Using
moduleTokenwithmoduleis consistent with the new pattern.
19-21: LGTM: retrieval uses the module’s service token.This keeps the container API stable while switching to the wrapper.
17-17: Verifycontainer.loadidempotency
Ensure repeated calls tocontainer.loadwon’t trigger “module already loaded” errors. Ifloadisn’t inherently idempotent, wrap it in a guard (e.g. checkcontainer.has(token)or track loaded modules) before invoking.packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts (2)
3-8: LGTM: Consistent shift to WithToken imports.Imports align with the new token-wrapped module pattern and improve DI consistency.
Also applies to: 10-10
39-39: All legacy DI patterns removed
No occurrences ofloadModuleDepsor directREGULAR_BOOKING_SERVICE_MODULEimports in consumer code; all bindings useregularBookingServiceModuleWithTokenandloadDeps.
packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts
Outdated
Show resolved
Hide resolved
| function loadModuleDeps(container: Container) { | ||
| container.load(DI_TOKENS.CACHE_SERVICE_MODULE, cacheModule); | ||
| container.load( | ||
| DI_TOKENS.CHECK_BOOKING_AND_DURATION_LIMITS_SERVICE_MODULE, | ||
| checkBookingAndDurationLimitsModule | ||
| ); | ||
| container.load(DI_TOKENS.PRISMA_MODULE, prismaModule); | ||
| container.load(DI_TOKENS.BOOKING_REPOSITORY_MODULE, bookingRepositoryModule); | ||
| container.load(DI_TOKENS.FEATURES_REPOSITORY_MODULE, featuresRepositoryModule); | ||
| container.load(DI_TOKENS.CHECK_BOOKING_LIMITS_SERVICE_MODULE, checkBookingLimitsModule); | ||
| } |
There was a problem hiding this comment.
We don't need to maintain it separately. These are loaded automatically now through loadDeps fn.
| regularBookingServiceContainer.load( | ||
| regularBookingServiceModuleWithToken.moduleToken, | ||
| regularBookingServiceModuleWithToken.module | ||
| ); |
There was a problem hiding this comment.
Just realized, this too could be moved to loadDeps and then we could rename loadDeps to loadModule
5c34efe to
bbdfd82
Compare
|
Simplified the flow further and now we don't need to expose moduleToken. Also now, we export a moduleLoader object consistently. |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (9)
packages/lib/di/modules/Booking.ts (2)
8-11: Good move to localize tokens; consider using the new helper for type-safetyBindings look fine. To align with the PR’s goal of type-safe wiring, consider replacing manual bind/toClass with the new bindModuleToClassOnToken utility for compile-time checks on deps.
12-17: Export a single “WithToken” object (token, moduleToken, module, loadModule) for SSoTCurrent export exposes only token and loadModule. Including moduleToken and module prevents drift and matches the standardized shape.
Apply:
-export const moduleLoader = { - token, - loadModule: function (container: Container) { - container.load(moduleToken, bookingRepositoryModule); - }, -}; +export const bookingRepositoryModuleWithToken = { + token, + moduleToken, + module: bookingRepositoryModule, + loadModule(container: Container) { + container.load(moduleToken, bookingRepositoryModule); + }, +}; +// Back-compat alias if callers expect `moduleLoader` +export const moduleLoader = bookingRepositoryModuleWithToken;packages/lib/di/modules/CheckBookingLimits.ts (2)
11-12: Add a “satisfies” guard to lock deps map to the service’s contractMirror the pattern used in CheckBookingAndDurationLimits to avoid runtime key mismatches.
Apply (adjust interface name if different):
- .bind(token) - .toClass(CheckBookingLimitsService, { bookingRepo: DI_TOKENS.BOOKING_REPOSITORY }); + .bind(token) + .toClass( + CheckBookingLimitsService, + { bookingRepo: DI_TOKENS.BOOKING_REPOSITORY } + satisfies Record<keyof ICheckBookingLimitsService, symbol> + );If no interface exists, I can add a minimal
ICheckBookingLimitsServicetype and wire it up. Want me to push that?
14-19: Export the unified “WithToken” object (include moduleToken and module)Brings this module in line with the standardized export shape and prevents token/module divergence.
-export const moduleLoader = { - token, - loadModule: (container: Container) => { - container.load(moduleToken, checkBookingLimitsModule); - }, -}; +export const checkBookingLimitsModuleWithToken = { + token, + moduleToken, + module: checkBookingLimitsModule, + loadModule(container: Container) { + container.load(moduleToken, checkBookingLimitsModule); + }, +}; +export const moduleLoader = checkBookingLimitsModuleWithToken;packages/lib/di/modules/CheckBookingAndDurationLimits.ts (1)
16-21: Standardize on “WithToken” export shapeExpose moduleToken and module alongside token and loadModule for consistency and easier introspection.
-export const moduleLoader = { - token, - loadModule: (container: Container) => { - container.load(moduleToken, checkBookingAndDurationLimitsModule); - }, -}; +export const checkBookingAndDurationLimitsModuleWithToken = { + token, + moduleToken, + module: checkBookingAndDurationLimitsModule, + loadModule(container: Container) { + container.load(moduleToken, checkBookingAndDurationLimitsModule); + }, +}; +export const moduleLoader = checkBookingAndDurationLimitsModuleWithToken;packages/prisma/prisma.module.ts (1)
14-19: Expose read-only client via its own loader and include module/moduleToken for SSoTSome modules depend on READ_ONLY_PRISMA_CLIENT; giving it a loader keeps the API symmetric and prevents ad-hoc token references. Also export module and moduleToken.
-export const moduleLoader = { - token, - loadModule: (container: Container) => { - container.load(moduleToken, prismaModule); - }, -}; +export const prismaModuleWithToken = { + token, + moduleToken, + module: prismaModule, + loadModule(container: Container) { + container.load(moduleToken, prismaModule); + }, +}; +export const moduleLoader = prismaModuleWithToken; + +export const readOnlyPrismaModuleLoader = { + token: DI_TOKENS.READ_ONLY_PRISMA_CLIENT, + loadModule(container: Container) { + container.load(moduleToken, prismaModule); + }, +};If you prefer a single export, we can also expose
tokens: [DI_TOKENS.PRISMA_CLIENT, DI_TOKENS.READ_ONLY_PRISMA_CLIENT]on prismaModuleWithToken and keep one loader.packages/lib/di/modules/Features.ts (1)
12-17: Adopt the unified “WithToken” export (add moduleToken and module)Keeps exports consistent and future-proof.
-export const moduleLoader = { - token, - loadModule: (container: Container) => { - container.load(moduleToken, featuresRepositoryModule); - }, -}; +export const featuresRepositoryModuleWithToken = { + token, + moduleToken, + module: featuresRepositoryModule, + loadModule(container: Container) { + container.load(moduleToken, featuresRepositoryModule); + }, +}; +export const moduleLoader = featuresRepositoryModuleWithToken;packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts (2)
17-21: ConfirmbindModuleToClassOnTokenoption name:classsIs the option intentionally spelled
classsin the util’s signature? If the util expectsklass/classRef/Class, this will fail type-checking at call sites. Please verify the util’s param name and adjust here for consistency.
32-35: Export the standardized ModuleWithToken shape (token + moduleToken + module) and aliasmoduleLoaderOther modules expose a unified object with
token,moduleToken, andmodule, plus amoduleLoaderalias. This file currently omitsmoduleTokenandmodule, and only exportsregularBookingServiceModule. For cross-module consistency and single source of truth, export the full shape and an alias.Apply:
export const regularBookingServiceModule = { token, + moduleToken, + module: thisModule, loadModule, }; + +// For import consistency with other modules: +export const moduleLoader = regularBookingServiceModule;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (9)
packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts(1 hunks)packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts(1 hunks)packages/lib/di/ioctopus.ts(1 hunks)packages/lib/di/modules/Booking.ts(1 hunks)packages/lib/di/modules/Cache.ts(2 hunks)packages/lib/di/modules/CheckBookingAndDurationLimits.ts(2 hunks)packages/lib/di/modules/CheckBookingLimits.ts(1 hunks)packages/lib/di/modules/Features.ts(1 hunks)packages/prisma/prisma.module.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/lib/di/modules/Cache.ts
- packages/lib/di/ioctopus.ts
- packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/lib/di/modules/Booking.tspackages/lib/di/modules/Features.tspackages/lib/di/modules/CheckBookingLimits.tspackages/prisma/prisma.module.tspackages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
packages/lib/di/modules/Booking.tspackages/lib/di/modules/Features.tspackages/lib/di/modules/CheckBookingLimits.tspackages/prisma/prisma.module.tspackages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
packages/lib/di/modules/Booking.tspackages/lib/di/modules/Features.tspackages/lib/di/modules/CheckBookingLimits.tspackages/prisma/prisma.module.tspackages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.149Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-03T09:52:51.149Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.149Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Applied to files:
packages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts
🧬 Code graph analysis (4)
packages/lib/di/modules/Features.ts (2)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/lib/di/modules/Cache.ts (1)
moduleLoader(16-21)
packages/lib/di/modules/CheckBookingLimits.ts (3)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/lib/di/modules/Cache.ts (1)
moduleLoader(16-21)packages/prisma/prisma.module.ts (1)
moduleLoader(14-19)
packages/prisma/prisma.module.ts (6)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/prisma/index.ts (1)
readonlyPrisma(71-75)packages/lib/di/modules/Cache.ts (1)
moduleLoader(16-21)packages/lib/di/modules/CheckBookingAndDurationLimits.ts (1)
moduleLoader(16-21)packages/lib/di/modules/CheckBookingLimits.ts (1)
moduleLoader(14-19)packages/lib/di/modules/Features.ts (1)
moduleLoader(12-17)
packages/lib/di/modules/CheckBookingAndDurationLimits.ts (3)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
ICheckBookingAndDurationLimitsService(17-19)packages/lib/di/modules/CheckBookingLimits.ts (1)
moduleLoader(14-19)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (6)
packages/lib/di/modules/CheckBookingAndDurationLimits.ts (2)
10-15: Nice: typed deps map withsatisfiesThis ensures the map keys stay in sync with ICheckBookingAndDurationLimitsService.
7-7: Retain relative import for DI_TOKENS in library modules
The lib package’s tsconfig has no@calcom/libpath mapping, soimport { DI_TOKENS } from "../tokens"correctly resolves a single instance. Switching to an alias would break the library build.Likely an incorrect or invalid review comment.
packages/prisma/prisma.module.ts (1)
11-12: Bindings look correct and scoped singleton is appropriateBoth prisma and readonlyPrisma registrations LGTM.
packages/lib/di/modules/Features.ts (1)
10-10: OK: binding via localized token and PRISMA dependencyLooks consistent with the pattern.
packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts (2)
3-10: Imports look consistent with the new moduleLoader patternUsing named
moduleLoaderimports across dependencies aligns with the PR’s DI approach.
22-29: Deps map matches IBookingServiceDependenciesAll six deps align with the interface used by RegularBookingService. Good.
E2E results are ready! |
packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts
Outdated
Show resolved
Hide resolved
bbdfd82 to
7fd53d0
Compare
7fd53d0 to
ccda9ce
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
packages/lib/di/modules/Membership.ts (1)
6-10: Export amoduleLoaderto align with the new standard module shape.PR objective says modules should export
{ token, loadModule }. This file only exports the module; add the loader to keep consumers consistent.Apply:
export const membershipRepositoryModule = createModule(); membershipRepositoryModule .bind(DI_TOKENS.MEMBERSHIP_REPOSITORY) .toClass(MembershipRepository, [DI_TOKENS.PRISMA_CLIENT]); +export const membershipRepositoryModuleLoader = { + token: DI_TOKENS.MEMBERSHIP_REPOSITORY, + loadModule: () => membershipRepositoryModule, +};If there’s a shared helper (e.g.,
moduleLoader()in../di), prefer that for consistency.packages/lib/di/modules/QualifiedHosts.ts (1)
6-11: Export a moduleLoader to align with the new standard module shape.This module doesn’t expose moduleLoader yet. Add it so containers can load it consistently via container.load(moduleToken, module) behind a stable API.
Apply this diff:
@@ -import { createModule } from "../di"; +import type { Container } from "../di"; +import { createModule } from "../di"; @@ } satisfies Record<keyof IQualifiedHostsService, symbol>); + +const token = DI_TOKENS.QUALIFIED_HOSTS_SERVICE; +const moduleToken = DI_TOKENS.QUALIFIED_HOSTS_SERVICE_MODULE; +export const moduleLoader = { + token, + loadModule: (container: Container) => { + container.load(moduleToken, qualifiedHostsModule); + }, +};packages/lib/di/modules/GetUserAvailability.ts (1)
6-12: Expose moduleLoader for consistency and runtime-safe loading.Publish the standard { token, loadModule } so containers don’t have to import the raw module.
Apply this diff:
@@ -import { createModule } from "../di"; +import type { Container } from "../di"; +import { createModule } from "../di"; @@ } satisfies Record<keyof IUserAvailabilityService, symbol>); + +const token = DI_TOKENS.GET_USER_AVAILABILITY_SERVICE; +const moduleToken = DI_TOKENS.GET_USER_AVAILABILITY_SERVICE_MODULE; +export const moduleLoader = { + token, + loadModule: (container: Container) => { + container.load(moduleToken, getUserAvailabilityModule); + }, +};packages/lib/di/modules/RoutingFormResponse.ts (1)
6-9: Export moduleLoader to standardize loading.Add the { token, loadModule } wrapper so containers don’t import the raw module directly.
Apply this diff:
@@ -import { createModule } from "../di"; +import type { Container } from "../di"; +import { createModule } from "../di"; @@ .bind(DI_TOKENS.ROUTING_FORM_RESPONSE_REPOSITORY) .toClass(RoutingFormResponseRepository, [DI_TOKENS.PRISMA_CLIENT]); + +const token = DI_TOKENS.ROUTING_FORM_RESPONSE_REPOSITORY; +const moduleToken = DI_TOKENS.ROUTING_FORM_RESPONSE_REPOSITORY_MODULE; +export const moduleLoader = { + token, + loadModule: (container: Container) => { + container.load(moduleToken, routingFormResponseRepositoryModule); + }, +};packages/lib/di/modules/InsightsBooking.ts (1)
7-10: Expose moduleLoader for InsightsBooking.Publish the standard loader so containers can adopt the unified loading flow.
Apply this diff:
@@ -import { createModule } from "../di"; +import type { Container } from "../di"; +import { createModule } from "../di"; @@ } satisfies Record<keyof IInsightsBookingService, symbol>); + +const token = DI_TOKENS.INSIGHTS_BOOKING_SERVICE; +const moduleToken = DI_TOKENS.INSIGHTS_BOOKING_SERVICE_MODULE; +export const moduleLoader = { + token, + loadModule: (container: Container) => { + container.load(moduleToken, insightsBookingModule); + }, +};
🧹 Nitpick comments (5)
packages/lib/di/modules/EventType.ts (1)
6-9: Export a standardized moduleLoader to match the new convention.Per this PR’s objective, modules should export
{ token, loadModule }. This file currently exposes onlyeventTypeRepositoryModule. Recommend adding amoduleLoaderexport (keep the existing export for backwards compatibility).export const eventTypeRepositoryModule = createModule(); eventTypeRepositoryModule .bind(DI_TOKENS.EVENT_TYPE_REPOSITORY) .toClass(EventTypeRepository, [DI_TOKENS.PRISMA_CLIENT]); +// Standardized loader export to align with repo-wide convention +export const eventTypeRepositoryModuleLoader = { + token: DI_TOKENS.EVENT_TYPE_REPOSITORY, + loadModule: async () => eventTypeRepositoryModule, +};Please confirm downstream code expects
moduleLoaderhere as with other modules in this PR.packages/lib/di/modules/Team.ts (1)
6-7: AddmoduleLoaderexport to Team.ts for consistent DI pattern
Other modules underpackages/lib/di/modulesexpose bothtokenandloadModule;Team.tscurrently only exportsteamRepositoryModule. Retain the existing export for back-compat and append the loader wrapper:export const teamRepositoryModule = createModule(); teamRepositoryModule .bind(DI_TOKENS.TEAM_REPOSITORY) .toClass(TeamRepository, [DI_TOKENS.PRISMA_CLIENT]); +// New uniform entrypoint (non-breaking) +export const moduleLoader = { + token: DI_TOKENS.TEAM_REPOSITORY, + loadModule: async () => teamRepositoryModule, +};packages/lib/di/containers/BookingLimits.ts (2)
12-18: Use moduleLoader.token instead of DI_TOKENS to avoid duplicationLeverage the module’s single source of truth for its token; removes drift risk and matches the standardized moduleLoader shape.
- container.load(DI_TOKENS.PRISMA_MODULE, prismaModule); - container.load(DI_TOKENS.BOOKING_REPOSITORY_MODULE, bookingRepositoryModule); - container.load(DI_TOKENS.CHECK_BOOKING_LIMITS_SERVICE_MODULE, checkBookingLimitsModule); - container.load( - DI_TOKENS.CHECK_BOOKING_AND_DURATION_LIMITS_SERVICE_MODULE, - checkBookingAndDurationLimitsModule - ); + container.load(prismaModule.token, prismaModule); + container.load(bookingRepositoryModule.token, bookingRepositoryModule); + container.load(checkBookingLimitsModule.token, checkBookingLimitsModule); + container.load( + checkBookingAndDurationLimitsModule.token, + checkBookingAndDurationLimitsModule + );
20-28: Annotate return types on public gettersMakes the public surface explicit and resilient to inference regressions.
-export function getCheckBookingLimitsService() { +export function getCheckBookingLimitsService(): CheckBookingLimitsService { return container.get<CheckBookingLimitsService>(DI_TOKENS.CHECK_BOOKING_LIMITS_SERVICE); } -export function getCheckBookingAndDurationLimitsService() { +export function getCheckBookingAndDurationLimitsService(): CheckBookingAndDurationLimitsService { return container.get<CheckBookingAndDurationLimitsService>( DI_TOKENS.CHECK_BOOKING_AND_DURATION_LIMITS_SERVICE ); }packages/lib/di/modules/RoutingFormResponse.ts (1)
7-9: Prefer named DI map over positional injection for type-safety.If the repository supports named deps, switch to an object map with satisfies to catch mismatches at compile time. If not, keep as-is.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (46)
packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts(0 hunks)packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts(0 hunks)packages/features/redis/di/redisModule.ts(1 hunks)packages/lib/di/containers/AvailableSlots.ts(1 hunks)packages/lib/di/containers/BookingLimits.ts(1 hunks)packages/lib/di/containers/BusyTimes.ts(1 hunks)packages/lib/di/containers/Cache.ts(1 hunks)packages/lib/di/containers/FilterHosts.ts(1 hunks)packages/lib/di/containers/GetUserAvailability.ts(1 hunks)packages/lib/di/containers/InsightsBooking.ts(1 hunks)packages/lib/di/containers/InsightsRouting.ts(1 hunks)packages/lib/di/containers/LuckyUser.ts(1 hunks)packages/lib/di/containers/NoSlotsNotification.ts(1 hunks)packages/lib/di/containers/QualifiedHosts.ts(1 hunks)packages/lib/di/containers/bookings/InstantBookingCreateServiceContainer.ts(1 hunks)packages/lib/di/containers/bookings/RecurringBookingServiceContainer.ts(1 hunks)packages/lib/di/containers/bookings/RegularBookingServiceContainer.ts(1 hunks)packages/lib/di/di.ts(1 hunks)packages/lib/di/modules/Attribute.ts(1 hunks)packages/lib/di/modules/AvailableSlots.ts(1 hunks)packages/lib/di/modules/Booking.ts(1 hunks)packages/lib/di/modules/BusyTimes.ts(1 hunks)packages/lib/di/modules/Cache.ts(1 hunks)packages/lib/di/modules/CheckBookingAndDurationLimits.ts(1 hunks)packages/lib/di/modules/CheckBookingLimits.ts(1 hunks)packages/lib/di/modules/EventType.ts(1 hunks)packages/lib/di/modules/Features.ts(1 hunks)packages/lib/di/modules/FilterHosts.ts(1 hunks)packages/lib/di/modules/GetUserAvailability.ts(1 hunks)packages/lib/di/modules/Host.ts(1 hunks)packages/lib/di/modules/InsightsBooking.ts(1 hunks)packages/lib/di/modules/InsightsRouting.ts(1 hunks)packages/lib/di/modules/LuckyUser.ts(1 hunks)packages/lib/di/modules/Membership.ts(1 hunks)packages/lib/di/modules/NoSlotsNotification.ts(1 hunks)packages/lib/di/modules/Ooo.ts(1 hunks)packages/lib/di/modules/QualifiedHosts.ts(1 hunks)packages/lib/di/modules/RoutingFormResponse.ts(1 hunks)packages/lib/di/modules/Schedule.ts(1 hunks)packages/lib/di/modules/SelectedSlots.ts(1 hunks)packages/lib/di/modules/Team.ts(1 hunks)packages/lib/di/modules/User.ts(1 hunks)packages/lib/di/modules/bookings/InstantBookingCreateServiceModule.ts(1 hunks)packages/lib/di/modules/bookings/RecurringBookingServiceModule.ts(1 hunks)packages/lib/di/modules/bookings/RegularBookingServiceModule.ts(1 hunks)packages/prisma/prisma.module.ts(1 hunks)
💤 Files with no reviewable changes (2)
- packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts
- packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts
✅ Files skipped from review due to trivial changes (1)
- packages/features/redis/di/redisModule.ts
🚧 Files skipped from review as they are similar to previous changes (33)
- packages/lib/di/modules/NoSlotsNotification.ts
- packages/lib/di/containers/NoSlotsNotification.ts
- packages/lib/di/modules/bookings/RegularBookingServiceModule.ts
- packages/lib/di/containers/FilterHosts.ts
- packages/lib/di/containers/QualifiedHosts.ts
- packages/lib/di/modules/BusyTimes.ts
- packages/lib/di/containers/Cache.ts
- packages/lib/di/modules/AvailableSlots.ts
- packages/lib/di/containers/InsightsRouting.ts
- packages/lib/di/modules/InsightsRouting.ts
- packages/lib/di/modules/LuckyUser.ts
- packages/lib/di/containers/bookings/InstantBookingCreateServiceContainer.ts
- packages/lib/di/containers/AvailableSlots.ts
- packages/lib/di/modules/bookings/RecurringBookingServiceModule.ts
- packages/lib/di/modules/FilterHosts.ts
- packages/lib/di/modules/bookings/InstantBookingCreateServiceModule.ts
- packages/lib/di/modules/CheckBookingLimits.ts
- packages/lib/di/containers/LuckyUser.ts
- packages/lib/di/modules/Booking.ts
- packages/lib/di/containers/GetUserAvailability.ts
- packages/lib/di/modules/Host.ts
- packages/lib/di/containers/BusyTimes.ts
- packages/lib/di/modules/User.ts
- packages/lib/di/containers/bookings/RegularBookingServiceContainer.ts
- packages/lib/di/modules/SelectedSlots.ts
- packages/lib/di/di.ts
- packages/lib/di/modules/Ooo.ts
- packages/lib/di/modules/Attribute.ts
- packages/lib/di/modules/Cache.ts
- packages/lib/di/modules/CheckBookingAndDurationLimits.ts
- packages/lib/di/containers/bookings/RecurringBookingServiceContainer.ts
- packages/lib/di/modules/Features.ts
- packages/lib/di/modules/Schedule.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/lib/di/modules/InsightsBooking.tspackages/lib/di/containers/InsightsBooking.tspackages/lib/di/modules/Team.tspackages/lib/di/modules/GetUserAvailability.tspackages/lib/di/modules/RoutingFormResponse.tspackages/lib/di/modules/QualifiedHosts.tspackages/prisma/prisma.module.tspackages/lib/di/modules/EventType.tspackages/lib/di/modules/Membership.tspackages/lib/di/containers/BookingLimits.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
packages/lib/di/modules/InsightsBooking.tspackages/lib/di/containers/InsightsBooking.tspackages/lib/di/modules/Team.tspackages/lib/di/modules/GetUserAvailability.tspackages/lib/di/modules/RoutingFormResponse.tspackages/lib/di/modules/QualifiedHosts.tspackages/prisma/prisma.module.tspackages/lib/di/modules/EventType.tspackages/lib/di/modules/Membership.tspackages/lib/di/containers/BookingLimits.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
packages/lib/di/modules/InsightsBooking.tspackages/lib/di/containers/InsightsBooking.tspackages/lib/di/modules/Team.tspackages/lib/di/modules/GetUserAvailability.tspackages/lib/di/modules/RoutingFormResponse.tspackages/lib/di/modules/QualifiedHosts.tspackages/prisma/prisma.module.tspackages/lib/di/modules/EventType.tspackages/lib/di/modules/Membership.tspackages/lib/di/containers/BookingLimits.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Applied to files:
packages/lib/di/modules/InsightsBooking.tspackages/lib/di/containers/InsightsBooking.tspackages/lib/di/containers/BookingLimits.ts
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.
Applied to files:
packages/lib/di/modules/EventType.ts
🧬 Code graph analysis (1)
packages/prisma/prisma.module.ts (8)
packages/lib/di/di.ts (2)
createModule(38-38)Container(38-38)packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/prisma/index.ts (1)
readonlyPrisma(71-75)packages/lib/di/modules/Booking.ts (1)
moduleLoader(12-17)packages/lib/di/modules/Cache.ts (1)
moduleLoader(15-20)packages/lib/di/modules/CheckBookingAndDurationLimits.ts (1)
moduleLoader(15-20)packages/lib/di/modules/CheckBookingLimits.ts (1)
moduleLoader(14-19)packages/lib/di/modules/Features.ts (1)
moduleLoader(12-17)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Production builds / Build Web App
- GitHub Check: Production builds / Build API v1
🔇 Additional comments (8)
packages/lib/di/modules/EventType.ts (1)
4-5: Good swap to local DI entrypoint.Importing
createModulefrom the local DI consolidates dependencies and matches the PR direction.packages/lib/di/modules/Membership.ts (1)
4-5: Local DI import verification complete.createModuleis correctly re-exported in packages/lib/di/di.ts, and there are no remaining@evyweb/ioctopusimports.packages/lib/di/modules/Team.ts (1)
4-4: Good switch to local DI entrypoint.Importing
createModulefrom the local../dialigns with the PR direction and removes the external dependency.packages/lib/di/modules/QualifiedHosts.ts (1)
3-3: Local DI entrypoint import change looks good.packages/lib/di/modules/GetUserAvailability.ts (1)
3-3: Local DI entrypoint import change looks good.packages/lib/di/modules/RoutingFormResponse.ts (1)
4-4: Switch to local DI import looks good.packages/prisma/prisma.module.ts (1)
1-2: Local DI import and Container typing are correct.packages/lib/di/modules/InsightsBooking.ts (1)
4-4: Local DI import looks good.
ccda9ce to
fd8e133
Compare
fd8e133 to
8d57e82
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
packages/lib/di/modules/GetUserAvailability.ts (1)
6-12: Export a moduleLoader to match the new standardized pattern.Per PR objectives, modules should expose
{ token, loadModule }. Add amoduleLoaderhere so downstream code can uniformly consume it.import type { IUserAvailabilityService } from "../../getUserAvailability"; import { UserAvailabilityService } from "../../getUserAvailability"; import { createModule } from "../di"; import { DI_TOKENS } from "../tokens"; export const getUserAvailabilityModule = createModule(); getUserAvailabilityModule.bind(DI_TOKENS.GET_USER_AVAILABILITY_SERVICE).toClass(UserAvailabilityService, { oooRepo: DI_TOKENS.OOO_REPOSITORY, bookingRepo: DI_TOKENS.BOOKING_REPOSITORY, eventTypeRepo: DI_TOKENS.EVENT_TYPE_REPOSITORY, redisClient: DI_TOKENS.REDIS_CLIENT, } satisfies Record<keyof IUserAvailabilityService, symbol>); +// New standardized export for loader-based consumption +export const getUserAvailabilityModuleLoader = { + token: DI_TOKENS.GET_USER_AVAILABILITY_SERVICE, + async loadModule() { + const mod = createModule(); + mod.bind(DI_TOKENS.GET_USER_AVAILABILITY_SERVICE).toClass(UserAvailabilityService, { + oooRepo: DI_TOKENS.OOO_REPOSITORY, + bookingRepo: DI_TOKENS.BOOKING_REPOSITORY, + eventTypeRepo: DI_TOKENS.EVENT_TYPE_REPOSITORY, + redisClient: DI_TOKENS.REDIS_CLIENT, + } satisfies Record<keyof IUserAvailabilityService, symbol>); + return mod; + }, +};packages/lib/di/modules/NoSlotsNotification.ts (1)
4-12: Adopt moduleLoader + bindModuleToClassOnToken; stop using createModule.bind(...)This module still uses createModule and manual bind, which diverges from the PR’s standardized “export a moduleLoader { token, loadModule }” pattern and misses the runtime-safety guarantees from bindModuleToClassOnToken.
Apply:
-import { createModule } from "../di"; +import { bindModuleToClassOnToken } from "../di"; import { DI_TOKENS } from "../tokens"; -export const noSlotsNotificationModule = createModule(); -noSlotsNotificationModule.bind(DI_TOKENS.NO_SLOTS_NOTIFICATION_SERVICE).toClass(NoSlotsNotificationService, { - teamRepo: DI_TOKENS.TEAM_REPOSITORY, - membershipRepo: DI_TOKENS.MEMBERSHIP_REPOSITORY, - redisClient: DI_TOKENS.REDIS_CLIENT, -} satisfies Record<keyof INoSlotsNotificationService, symbol>); +export const noSlotsNotificationModuleWithToken = { + token: DI_TOKENS.NO_SLOTS_NOTIFICATION_SERVICE, + loadModule: () => + bindModuleToClassOnToken( + DI_TOKENS.NO_SLOTS_NOTIFICATION_SERVICE, + NoSlotsNotificationService, + { + teamRepo: DI_TOKENS.TEAM_REPOSITORY, + membershipRepo: DI_TOKENS.MEMBERSHIP_REPOSITORY, + redisClient: DI_TOKENS.REDIS_CLIENT, + } satisfies Record<keyof INoSlotsNotificationService, symbol> + ), +} as const;
- If other modules use “ModuleWithToken” naming, keep that for consistency; otherwise, rename to whatever convention this PR adopted globally.
packages/lib/di/modules/LuckyUser.ts (1)
6-13: Export standardizedmoduleLoader
In packages/lib/di/modules/LuckyUser.ts, add:import { type Container } from "../di"; export const moduleLoader = { token: DI_TOKENS.LUCKY_USER_SERVICE, loadModule(container: Container) { container.load(DI_TOKENS.LUCKY_USER_SERVICE_MODULE, luckyUserServiceModule); }, } as const;No existing code imports
moduleLoaderfrom this module.
🧹 Nitpick comments (9)
packages/lib/di/containers/FilterHosts.ts (3)
2-12: Align loads with the new moduleLoader pattern.Per PR objectives, modules now export a
{ token, loadModule }moduleLoader. Prefercontainer.load(moduleLoader)over(token, module)to keep consistency and leverage the standardized shape.Apply this refactor (adjust names if your modules re-export
moduleLoaderunder a different alias):-import { prismaModule } from "@calcom/prisma/prisma.module"; +import { moduleLoader as prismaModuleLoader } from "@calcom/prisma/prisma.module"; @@ -import { bookingRepositoryModule } from "../modules/Booking"; -import { filterHostsModule } from "../modules/FilterHosts"; +import { moduleLoader as bookingRepositoryModuleLoader } from "../modules/Booking"; +import { moduleLoader as filterHostsModuleLoader } from "../modules/FilterHosts"; @@ -const container = createContainer(); -container.load(DI_TOKENS.PRISMA_MODULE, prismaModule); -container.load(DI_TOKENS.BOOKING_REPOSITORY_MODULE, bookingRepositoryModule); -container.load(DI_TOKENS.FILTER_HOSTS_SERVICE_MODULE, filterHostsModule); +const container = createContainer(); +container.load(prismaModuleLoader); +container.load(bookingRepositoryModuleLoader); +container.load(filterHostsModuleLoader);
9-16: Optional: lazy-init the container for testability and to avoid side effects at import time.Defers wiring until needed and makes it easier to reset between tests.
-const container = createContainer(); -container.load(DI_TOKENS.PRISMA_MODULE, prismaModule); -container.load(DI_TOKENS.BOOKING_REPOSITORY_MODULE, bookingRepositoryModule); -container.load(DI_TOKENS.FILTER_HOSTS_SERVICE_MODULE, filterHostsModule); - -export function getFilterHostsService() { - return container.get<FilterHostsService>(DI_TOKENS.FILTER_HOSTS_SERVICE); -} +let _container: ReturnType<typeof createContainer> | null = null; + +export function getFilterHostsService() { + if (!_container) { + _container = createContainer(); + // Use moduleLoader-based loads if available + // _container.load(prismaModuleLoader); + // _container.load(bookingRepositoryModuleLoader); + // _container.load(filterHostsModuleLoader); + // If still on (token, module), keep the original three loads here. + } + return _container.get<FilterHostsService>(DI_TOKENS.FILTER_HOSTS_SERVICE); +}
1-16: Standardize module export/loading conventions across DI containers
- FilterHosts module doesn’t export a
moduleLoader(whereas Booking, Cache, etc. do); either add amoduleLoaderexport toFilterHosts.tsor remove the unusedmoduleLoaderexports from the other modules.- Decide on—and apply—one loading pattern repo-wide: use either the one-arg
container.load(moduleLoader)approach or the two-argcontainer.load(token, module)style (including forprismaModule).packages/lib/di/modules/Team.ts (1)
6-7: Export a standardized moduleLoader alongside the module to match PR’s unified pattern.Keeps current export while enabling the new loader-based flow everywhere.
Apply:
export const teamRepositoryModule = createModule(); teamRepositoryModule.bind(DI_TOKENS.TEAM_REPOSITORY).toClass(TeamRepository, [DI_TOKENS.PRISMA_CLIENT]); +// PR convention: every module exports a { token, loadModule } loader +export const moduleLoader = { + token: DI_TOKENS.TEAM_REPOSITORY, + loadModule: () => teamRepositoryModule, +};packages/lib/di/modules/GetUserAvailability.ts (1)
6-12: Optional: adopt bindModuleToClassOnToken for stronger type/runtime safety.To align with the new DI utility, consider wiring via
bindModuleToClassOnToken(...)from../diso the depsMap is generically validated andloadDepsis auto-generated. I can provide a patch once we confirm the exact helper signature exported by../di.packages/lib/di/containers/Cache.ts (2)
1-12: Adopt moduleLoader pattern to decouple from DI_TOKENS and standardize loadingUse each module’s moduleLoader.{loadModule, token} instead of loading by DI_TOKENS._MODULE and getting by DI_TOKENS.. This aligns with the PR’s “single source of truth” and avoids token drift.
-import { DI_TOKENS } from "@calcom/lib/di/tokens"; -import { prismaModule } from "@calcom/prisma/prisma.module"; +import { moduleLoader as prismaModuleWithToken } from "@calcom/prisma/prisma.module"; import type { CacheService } from "../../../features/calendar-cache/lib/getShouldServeCache"; import { createContainer } from "../di"; -import { cacheModule } from "../modules/Cache"; -import { featuresRepositoryModule } from "../modules/Features"; +import { moduleLoader as cacheModuleWithToken } from "../modules/Cache"; +import { moduleLoader as featuresRepositoryModuleWithToken } from "../modules/Features"; const container = createContainer(); -container.load(DI_TOKENS.PRISMA_MODULE, prismaModule); -container.load(DI_TOKENS.FEATURES_REPOSITORY_MODULE, featuresRepositoryModule); -container.load(DI_TOKENS.CACHE_SERVICE_MODULE, cacheModule); +prismaModuleWithToken.loadModule(container); +featuresRepositoryModuleWithToken.loadModule(container); +cacheModuleWithToken.loadModule(container);
14-16: Get by moduleLoader.token and annotate return typeMinor consistency and typing polish.
-export function getCacheService() { - return container.get<CacheService>(DI_TOKENS.CACHE_SERVICE); +export function getCacheService(): CacheService { + return container.get<CacheService>(cacheModuleWithToken.token); }packages/lib/di/modules/Features.ts (2)
11-16: Freeze moduleLoader for immutability and stronger inferenceTiny hardening: mark the loader object immutable.
export const moduleLoader = { token, loadModule: (container: Container) => { container.load(moduleToken, featuresRepositoryModule); }, -}; +} as const;
9-9: Use bindModuleToClassOnToken for type-checked dependenciesImport the helper from
"../di"and replace:featuresRepositoryModule.bind(token).toClass(FeaturesRepository, [DI_TOKENS.PRISMA_CLIENT]);with:
import { bindModuleToClassOnToken } from "../di"; const loadModule = bindModuleToClassOnToken({ module: featuresRepositoryModule, token, class: FeaturesRepository, deps: [DI_TOKENS.PRISMA_CLIENT], });This enforces compile-time validation of constructor deps and sets up auto-loading hooks.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (46)
packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts(0 hunks)packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts(0 hunks)packages/features/redis/di/redisModule.ts(1 hunks)packages/lib/di/containers/AvailableSlots.ts(1 hunks)packages/lib/di/containers/BookingLimits.ts(1 hunks)packages/lib/di/containers/BusyTimes.ts(1 hunks)packages/lib/di/containers/Cache.ts(1 hunks)packages/lib/di/containers/FilterHosts.ts(1 hunks)packages/lib/di/containers/GetUserAvailability.ts(1 hunks)packages/lib/di/containers/InsightsBooking.ts(1 hunks)packages/lib/di/containers/InsightsRouting.ts(1 hunks)packages/lib/di/containers/LuckyUser.ts(1 hunks)packages/lib/di/containers/NoSlotsNotification.ts(1 hunks)packages/lib/di/containers/QualifiedHosts.ts(1 hunks)packages/lib/di/containers/bookings/InstantBookingCreateServiceContainer.ts(1 hunks)packages/lib/di/containers/bookings/RecurringBookingServiceContainer.ts(1 hunks)packages/lib/di/containers/bookings/RegularBookingServiceContainer.ts(1 hunks)packages/lib/di/di.ts(1 hunks)packages/lib/di/modules/Attribute.ts(1 hunks)packages/lib/di/modules/AvailableSlots.ts(1 hunks)packages/lib/di/modules/Booking.ts(1 hunks)packages/lib/di/modules/BusyTimes.ts(1 hunks)packages/lib/di/modules/Cache.ts(1 hunks)packages/lib/di/modules/CheckBookingAndDurationLimits.ts(1 hunks)packages/lib/di/modules/CheckBookingLimits.ts(1 hunks)packages/lib/di/modules/EventType.ts(1 hunks)packages/lib/di/modules/Features.ts(1 hunks)packages/lib/di/modules/FilterHosts.ts(1 hunks)packages/lib/di/modules/GetUserAvailability.ts(1 hunks)packages/lib/di/modules/Host.ts(1 hunks)packages/lib/di/modules/InsightsBooking.ts(1 hunks)packages/lib/di/modules/InsightsRouting.ts(1 hunks)packages/lib/di/modules/LuckyUser.ts(1 hunks)packages/lib/di/modules/Membership.ts(1 hunks)packages/lib/di/modules/NoSlotsNotification.ts(1 hunks)packages/lib/di/modules/Ooo.ts(1 hunks)packages/lib/di/modules/QualifiedHosts.ts(1 hunks)packages/lib/di/modules/RoutingFormResponse.ts(1 hunks)packages/lib/di/modules/Schedule.ts(1 hunks)packages/lib/di/modules/SelectedSlots.ts(1 hunks)packages/lib/di/modules/Team.ts(1 hunks)packages/lib/di/modules/User.ts(1 hunks)packages/lib/di/modules/bookings/InstantBookingCreateServiceModule.ts(1 hunks)packages/lib/di/modules/bookings/RecurringBookingServiceModule.ts(1 hunks)packages/lib/di/modules/bookings/RegularBookingServiceModule.ts(1 hunks)packages/prisma/prisma.module.ts(1 hunks)
💤 Files with no reviewable changes (2)
- packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts
- packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts
🚧 Files skipped from review as they are similar to previous changes (36)
- packages/lib/di/containers/QualifiedHosts.ts
- packages/features/redis/di/redisModule.ts
- packages/lib/di/containers/AvailableSlots.ts
- packages/lib/di/modules/InsightsRouting.ts
- packages/lib/di/modules/Host.ts
- packages/lib/di/modules/SelectedSlots.ts
- packages/lib/di/containers/bookings/RegularBookingServiceContainer.ts
- packages/lib/di/modules/FilterHosts.ts
- packages/lib/di/containers/BusyTimes.ts
- packages/lib/di/containers/NoSlotsNotification.ts
- packages/lib/di/modules/User.ts
- packages/lib/di/containers/bookings/InstantBookingCreateServiceContainer.ts
- packages/lib/di/modules/Booking.ts
- packages/lib/di/modules/bookings/InstantBookingCreateServiceModule.ts
- packages/lib/di/modules/InsightsBooking.ts
- packages/lib/di/containers/bookings/RecurringBookingServiceContainer.ts
- packages/lib/di/modules/CheckBookingLimits.ts
- packages/lib/di/modules/Ooo.ts
- packages/lib/di/containers/LuckyUser.ts
- packages/lib/di/modules/Attribute.ts
- packages/lib/di/containers/InsightsRouting.ts
- packages/lib/di/containers/InsightsBooking.ts
- packages/lib/di/modules/bookings/RecurringBookingServiceModule.ts
- packages/lib/di/modules/RoutingFormResponse.ts
- packages/lib/di/modules/CheckBookingAndDurationLimits.ts
- packages/prisma/prisma.module.ts
- packages/lib/di/di.ts
- packages/lib/di/modules/Membership.ts
- packages/lib/di/modules/bookings/RegularBookingServiceModule.ts
- packages/lib/di/modules/AvailableSlots.ts
- packages/lib/di/containers/BookingLimits.ts
- packages/lib/di/modules/BusyTimes.ts
- packages/lib/di/containers/GetUserAvailability.ts
- packages/lib/di/modules/QualifiedHosts.ts
- packages/lib/di/modules/Cache.ts
- packages/lib/di/modules/Schedule.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/lib/di/modules/Team.tspackages/lib/di/containers/Cache.tspackages/lib/di/containers/FilterHosts.tspackages/lib/di/modules/GetUserAvailability.tspackages/lib/di/modules/Features.tspackages/lib/di/modules/NoSlotsNotification.tspackages/lib/di/modules/EventType.tspackages/lib/di/modules/LuckyUser.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
packages/lib/di/modules/Team.tspackages/lib/di/containers/Cache.tspackages/lib/di/containers/FilterHosts.tspackages/lib/di/modules/GetUserAvailability.tspackages/lib/di/modules/Features.tspackages/lib/di/modules/NoSlotsNotification.tspackages/lib/di/modules/EventType.tspackages/lib/di/modules/LuckyUser.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
packages/lib/di/modules/Team.tspackages/lib/di/containers/Cache.tspackages/lib/di/containers/FilterHosts.tspackages/lib/di/modules/GetUserAvailability.tspackages/lib/di/modules/Features.tspackages/lib/di/modules/NoSlotsNotification.tspackages/lib/di/modules/EventType.tspackages/lib/di/modules/LuckyUser.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-08-21T13:44:06.805Z
Learnt from: supalarry
PR: calcom/cal.com#23217
File: apps/api/v2/src/ee/event-types/event-types_2024_06_14/services/output-event-types.service.ts:93-94
Timestamp: 2025-08-21T13:44:06.805Z
Learning: In apps/api/v2/src/ee/event-types/event-types_2024_06_14/event-types.repository.ts, repository functions that use explicit Prisma select clauses (like getEventTypeWithSeats) are used for specific purposes and don't need to include all EventType fields like bookingRequiresAuthentication. These methods don't feed into the general OutputEventTypesService_2024_06_14 flow.
Applied to files:
packages/lib/di/modules/EventType.ts
🧬 Code graph analysis (1)
packages/lib/di/modules/Features.ts (3)
packages/lib/di/di.ts (2)
createModule(38-38)Container(38-38)packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/lib/di/modules/Booking.ts (1)
moduleLoader(11-16)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Production builds / Build Web App
- GitHub Check: Production builds / Build API v1
- GitHub Check: Production builds / Build Atoms
- GitHub Check: Tests / Unit
- GitHub Check: Type check / check-types
🔇 Additional comments (8)
packages/lib/di/containers/FilterHosts.ts (1)
5-5: Good switch to the local DI entrypoint.Aligns this container with the repo-wide DI consolidation and removes the external dependency on @evyweb/ioctopus.
packages/lib/di/modules/EventType.ts (1)
6-10: No changes needed: constructor matches binding
TheEventTypeRepositoryconstructor accepts a singlePrismaClient, which aligns with the.toClass(EventTypeRepository, [DI_TOKENS.PRISMA_CLIENT])binding.packages/lib/di/modules/Team.ts (1)
4-5: Approve code changespackages/lib/di/di.ts re-exports
createModule, and no direct imports from “@evyweb/ioctopus” remain outside this entrypoint.packages/lib/di/modules/GetUserAvailability.ts (2)
3-3: Switching to local DI entrypoint looks good.Importing
createModulefrom../dialigns with the repo-wide refactor.
12-12:IUserAvailabilityServicecorrectly defines the four DI dependencies, so usingsatisfies Record<keyof IUserAvailabilityService, symbol>is accurate.packages/lib/di/modules/NoSlotsNotification.ts (1)
12-12: No change needed: INoSlotsNotificationService correctly describes the constructor’s dependencies.packages/lib/di/modules/Features.ts (1)
4-16: Good move to local DI and moduleLoader; structure looks solidImports from ../di, local tokens, and moduleLoader wrapper are consistent with the new pattern.
packages/lib/di/modules/LuckyUser.ts (1)
4-4: Local DI import looks goodSwitching to the local DI entrypoint aligns with the PR’s consolidation effort.
| import { createModule } from "../di"; | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Switch to the standardized moduleLoader + bindModuleToClassOnToken pattern
This file still exports a createModule-based module, which diverges from the PR-wide standard “export a moduleLoader { token, loadModule }” and misses the compile-time dep checks/runtime auto-loading. Migrate to bindModuleToClassOnToken and export moduleLoader.
-import { createModule } from "../di";
+import { bindModuleToClassOnToken } from "../di";
+// Adjust path/name to match your Prisma module’s export:
+import { moduleLoader as prismaModuleLoader } from "../modules/Prisma";
@@
-export const eventTypeRepositoryModule = createModule();
-eventTypeRepositoryModule
- .bind(DI_TOKENS.EVENT_TYPE_REPOSITORY)
- .toClass(EventTypeRepository, [DI_TOKENS.PRISMA_CLIENT]);
+export const moduleLoader = bindModuleToClassOnToken({
+ token: DI_TOKENS.EVENT_TYPE_REPOSITORY,
+ Class: EventTypeRepository,
+ depsMap: {
+ prismaClient: prismaModuleLoader,
+ },
+});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { createModule } from "../di"; | |
| // packages/lib/di/modules/EventType.ts | |
| import { bindModuleToClassOnToken } from "../di"; | |
| // Adjust path/name to match your Prisma module’s export: | |
| import { moduleLoader as prismaModuleLoader } from "../modules/Prisma"; | |
| // … other existing imports (e.g. DI_TOKENS, EventTypeRepository) | |
| export const moduleLoader = bindModuleToClassOnToken({ | |
| token: DI_TOKENS.EVENT_TYPE_REPOSITORY, | |
| Class: EventTypeRepository, | |
| depsMap: { | |
| prismaClient: prismaModuleLoader, | |
| }, | |
| }); |
🤖 Prompt for AI Agents
In packages/lib/di/modules/EventType.ts around lines 4 to 5, replace the current
createModule export with the standardized moduleLoader pattern: define and
export a moduleLoader object with { token, loadModule } and use
bindModuleToClassOnToken to bind the EventType class to its DI token inside
loadModule; ensure the token is exported/used consistently, import
bindModuleToClassOnToken instead of createModule, and implement loadModule to
perform the class binding so compile-time dependency checks and runtime
auto-loading work as expected.
8d57e82 to
93f51c3
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/lib/di/containers/AvailableSlots.ts (1)
43-44: Duplicate load for BUSY_TIMES service module.
container.load(DI_TOKENS.BUSY_TIMES_SERVICE_MODULE, busyTimesModule);is called twice. Depending on the container’s behavior, this can error, override, or cause unintended side effects. Drop the duplicate.- container.load(DI_TOKENS.BUSY_TIMES_SERVICE_MODULE, busyTimesModule);packages/lib/di/modules/LuckyUser.ts (1)
6-14: Export standardized module loader for LuckyUser moduleexport const luckyUserServiceModule = createModule(); luckyUserServiceModule.bind(DI_TOKENS.LUCKY_USER_SERVICE).toClass(LuckyUserService, { bookingRepository: DI_TOKENS.BOOKING_REPOSITORY, hostRepository: DI_TOKENS.HOST_REPOSITORY, oooRepository: DI_TOKENS.OOO_REPOSITORY, userRepository: DI_TOKENS.USER_REPOSITORY, attributeRepository: DI_TOKENS.ATTRIBUTE_REPOSITORY, }); +// Standardized loader export for container consumption +export const moduleLoader = { + token: DI_TOKENS.LUCKY_USER_SERVICE_MODULE, + loadModule: () => luckyUserServiceModule, +};
♻️ Duplicate comments (1)
packages/lib/di/containers/BookingLimits.ts (1)
6-6: Internalize DI import: LGTMSwitching
createContainerto the local DI entrypoint aligns with the PR direction and keeps DI concerns in-repo.
🧹 Nitpick comments (6)
packages/lib/di/containers/BookingLimits.ts (2)
7-9: Consider adopting the new moduleLoader pattern here for consistency and type-safetyThis container still manually loads modules via DI_TOKENS. To match the PR’s standardized pattern ({ token, loadModule }) and gain type-safe wiring, load via the per-module loader objects.
Example refactor (assuming these modules export
...ModuleLoader):-import { bookingRepositoryModule } from "../modules/Booking"; -import { checkBookingAndDurationLimitsModule } from "../modules/CheckBookingAndDurationLimits"; -import { checkBookingLimitsModule } from "../modules/CheckBookingLimits"; +import { bookingRepositoryModuleLoader } from "../modules/Booking"; +import { checkBookingAndDurationLimitsModuleLoader } from "../modules/CheckBookingAndDurationLimits"; +import { checkBookingLimitsModuleLoader } from "../modules/CheckBookingLimits"; -const container = createContainer(); -container.load(DI_TOKENS.PRISMA_MODULE, prismaModule); -container.load(DI_TOKENS.BOOKING_REPOSITORY_MODULE, bookingRepositoryModule); -container.load(DI_TOKENS.CHECK_BOOKING_LIMITS_SERVICE_MODULE, checkBookingLimitsModule); -container.load( - DI_TOKENS.CHECK_BOOKING_AND_DURATION_LIMITS_SERVICE_MODULE, - checkBookingAndDurationLimitsModule -); +const container = createContainer(); +// If prisma also exposes a loader, prefer that for consistency: +// container.load(prismaModuleLoader.token, prismaModuleLoader.loadModule); +container.load(bookingRepositoryModuleLoader.token, bookingRepositoryModuleLoader.loadModule); +container.load(checkBookingLimitsModuleLoader.token, checkBookingLimitsModuleLoader.loadModule); +container.load( + checkBookingAndDurationLimitsModuleLoader.token, + checkBookingAndDurationLimitsModuleLoader.loadModule +);If you’ve generated loadDeps for a higher-level module/container, you can replace these manual loads entirely with that helper.
Also applies to: 11-18
20-28: Add explicit return types on exported gettersLocks the public API and protects against accidental type drift if internal implementations change.
-export function getCheckBookingLimitsService() { +export function getCheckBookingLimitsService(): CheckBookingLimitsService { return container.get<CheckBookingLimitsService>(DI_TOKENS.CHECK_BOOKING_LIMITS_SERVICE); } -export function getCheckBookingAndDurationLimitsService() { +export function getCheckBookingAndDurationLimitsService(): CheckBookingAndDurationLimitsService { return container.get<CheckBookingAndDurationLimitsService>( DI_TOKENS.CHECK_BOOKING_AND_DURATION_LIMITS_SERVICE ); }packages/lib/di/containers/AvailableSlots.ts (2)
27-47: Align with the new moduleLoader pattern to remove token duplication.Per PR objectives, modules export
{ token, loadModule }. Prefercontainer.load(moduleLoader)to avoid drift betweenDI_TOKENS.*and the module’s internal token and to gain type/runtime safety.- container.load(DI_TOKENS.REDIS_CLIENT, redisModule); - 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.SELECTED_SLOT_REPOSITORY_MODULE, selectedSlotsRepositoryModule); - container.load(DI_TOKENS.TEAM_REPOSITORY_MODULE, teamRepositoryModule); - container.load(DI_TOKENS.MEMBERSHIP_REPOSITORY_MODULE, membershipRepositoryModule); - container.load(DI_TOKENS.USER_REPOSITORY_MODULE, userRepositoryModule); - container.load(DI_TOKENS.BOOKING_REPOSITORY_MODULE, bookingRepositoryModule); - container.load(DI_TOKENS.EVENT_TYPE_REPOSITORY_MODULE, eventTypeRepositoryModule); - container.load(DI_TOKENS.ROUTING_FORM_RESPONSE_REPOSITORY_MODULE, routingFormResponseRepositoryModule); - container.load(DI_TOKENS.FEATURES_REPOSITORY_MODULE, featuresRepositoryModule); - container.load(DI_TOKENS.CACHE_SERVICE_MODULE, cacheModule); - container.load(DI_TOKENS.CHECK_BOOKING_LIMITS_SERVICE_MODULE, checkBookingLimitsModule); - container.load(DI_TOKENS.AVAILABLE_SLOTS_SERVICE_MODULE, availableSlotsModule); - container.load(DI_TOKENS.GET_USER_AVAILABILITY_SERVICE_MODULE, getUserAvailabilityModule); - container.load(DI_TOKENS.BUSY_TIMES_SERVICE_MODULE, busyTimesModule); - container.load(DI_TOKENS.FILTER_HOSTS_SERVICE_MODULE, filterHostsModule); - container.load(DI_TOKENS.QUALIFIED_HOSTS_SERVICE_MODULE, qualifiedHostsModule); - container.load(DI_TOKENS.NO_SLOTS_NOTIFICATION_SERVICE_MODULE, noSlotsNotificationModule); + container.load(redisModule); + container.load(prismaModule); + container.load(oooRepositoryModule); + container.load(scheduleRepositoryModule); + container.load(selectedSlotsRepositoryModule); + container.load(teamRepositoryModule); + container.load(membershipRepositoryModule); + container.load(userRepositoryModule); + container.load(bookingRepositoryModule); + container.load(eventTypeRepositoryModule); + container.load(routingFormResponseRepositoryModule); + container.load(featuresRepositoryModule); + container.load(cacheModule); + container.load(checkBookingLimitsModule); + container.load(availableSlotsModule); + container.load(getUserAvailabilityModule); + container.load(busyTimesModule); + container.load(filterHostsModule); + container.load(qualifiedHostsModule); + container.load(noSlotsNotificationModule);
49-51: Prefer moduleLoader.token for retrieval to keep token definitions single-sourced.This avoids mismatches between
DI_TOKENSand the module’s declared token.- return container.get<AvailableSlotsService>(DI_TOKENS.AVAILABLE_SLOTS_SERVICE); + return container.get<AvailableSlotsService>(availableSlotsModule.token);packages/lib/di/modules/CheckBookingAndDurationLimits.ts (2)
4-4: Adopt the new helper for stronger typing and consistency with the PR’s pattern.Prefer using bindModuleToClassOnToken from ../di rather than hand-rolling the toClass + satisfies check. It yields tighter compile-time guarantees and better aligns with the new moduleLoader flow.
Apply:
-import { type Container, createModule } from "../di"; +import { type Container, createModule, bindModuleToClassOnToken } from "../di";
14-19: Minor: freeze the loader object.Mark moduleLoader as const to prevent accidental mutation and keep its shape stable.
export const moduleLoader = { token, loadModule: (container: Container) => { container.load(moduleToken, checkBookingAndDurationLimitsModule); }, -}; +} as const;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (46)
packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts(0 hunks)packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts(0 hunks)packages/features/redis/di/redisModule.ts(1 hunks)packages/lib/di/containers/AvailableSlots.ts(1 hunks)packages/lib/di/containers/BookingLimits.ts(1 hunks)packages/lib/di/containers/BusyTimes.ts(1 hunks)packages/lib/di/containers/Cache.ts(1 hunks)packages/lib/di/containers/FilterHosts.ts(1 hunks)packages/lib/di/containers/GetUserAvailability.ts(1 hunks)packages/lib/di/containers/InsightsBooking.ts(1 hunks)packages/lib/di/containers/InsightsRouting.ts(1 hunks)packages/lib/di/containers/LuckyUser.ts(1 hunks)packages/lib/di/containers/NoSlotsNotification.ts(1 hunks)packages/lib/di/containers/QualifiedHosts.ts(1 hunks)packages/lib/di/containers/bookings/InstantBookingCreateServiceContainer.ts(1 hunks)packages/lib/di/containers/bookings/RecurringBookingServiceContainer.ts(1 hunks)packages/lib/di/containers/bookings/RegularBookingServiceContainer.ts(1 hunks)packages/lib/di/di.ts(1 hunks)packages/lib/di/modules/Attribute.ts(1 hunks)packages/lib/di/modules/AvailableSlots.ts(1 hunks)packages/lib/di/modules/Booking.ts(1 hunks)packages/lib/di/modules/BusyTimes.ts(1 hunks)packages/lib/di/modules/Cache.ts(1 hunks)packages/lib/di/modules/CheckBookingAndDurationLimits.ts(1 hunks)packages/lib/di/modules/CheckBookingLimits.ts(1 hunks)packages/lib/di/modules/EventType.ts(1 hunks)packages/lib/di/modules/Features.ts(1 hunks)packages/lib/di/modules/FilterHosts.ts(1 hunks)packages/lib/di/modules/GetUserAvailability.ts(1 hunks)packages/lib/di/modules/Host.ts(1 hunks)packages/lib/di/modules/InsightsBooking.ts(1 hunks)packages/lib/di/modules/InsightsRouting.ts(1 hunks)packages/lib/di/modules/LuckyUser.ts(1 hunks)packages/lib/di/modules/Membership.ts(1 hunks)packages/lib/di/modules/NoSlotsNotification.ts(1 hunks)packages/lib/di/modules/Ooo.ts(1 hunks)packages/lib/di/modules/QualifiedHosts.ts(1 hunks)packages/lib/di/modules/RoutingFormResponse.ts(1 hunks)packages/lib/di/modules/Schedule.ts(1 hunks)packages/lib/di/modules/SelectedSlots.ts(1 hunks)packages/lib/di/modules/Team.ts(1 hunks)packages/lib/di/modules/User.ts(1 hunks)packages/lib/di/modules/bookings/InstantBookingCreateServiceModule.ts(1 hunks)packages/lib/di/modules/bookings/RecurringBookingServiceModule.ts(1 hunks)packages/lib/di/modules/bookings/RegularBookingServiceModule.ts(1 hunks)packages/prisma/prisma.module.ts(1 hunks)
💤 Files with no reviewable changes (2)
- packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts
- packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts
🚧 Files skipped from review as they are similar to previous changes (40)
- packages/lib/di/containers/LuckyUser.ts
- packages/lib/di/modules/FilterHosts.ts
- packages/lib/di/containers/bookings/RegularBookingServiceContainer.ts
- packages/features/redis/di/redisModule.ts
- packages/lib/di/modules/bookings/RecurringBookingServiceModule.ts
- packages/lib/di/modules/EventType.ts
- packages/lib/di/modules/bookings/RegularBookingServiceModule.ts
- packages/lib/di/containers/Cache.ts
- packages/lib/di/modules/Host.ts
- packages/lib/di/modules/CheckBookingLimits.ts
- packages/lib/di/modules/Schedule.ts
- packages/lib/di/modules/User.ts
- packages/lib/di/containers/FilterHosts.ts
- packages/lib/di/containers/BusyTimes.ts
- packages/lib/di/containers/bookings/RecurringBookingServiceContainer.ts
- packages/lib/di/modules/GetUserAvailability.ts
- packages/lib/di/containers/GetUserAvailability.ts
- packages/lib/di/modules/NoSlotsNotification.ts
- packages/lib/di/modules/Ooo.ts
- packages/lib/di/modules/Membership.ts
- packages/lib/di/modules/InsightsRouting.ts
- packages/lib/di/modules/bookings/InstantBookingCreateServiceModule.ts
- packages/lib/di/containers/NoSlotsNotification.ts
- packages/lib/di/modules/AvailableSlots.ts
- packages/lib/di/modules/SelectedSlots.ts
- packages/lib/di/modules/Attribute.ts
- packages/prisma/prisma.module.ts
- packages/lib/di/modules/QualifiedHosts.ts
- packages/lib/di/containers/QualifiedHosts.ts
- packages/lib/di/modules/Team.ts
- packages/lib/di/modules/InsightsBooking.ts
- packages/lib/di/modules/Features.ts
- packages/lib/di/modules/Booking.ts
- packages/lib/di/containers/InsightsRouting.ts
- packages/lib/di/modules/BusyTimes.ts
- packages/lib/di/modules/Cache.ts
- packages/lib/di/containers/bookings/InstantBookingCreateServiceContainer.ts
- packages/lib/di/di.ts
- packages/lib/di/containers/InsightsBooking.ts
- packages/lib/di/modules/RoutingFormResponse.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/lib/di/containers/AvailableSlots.tspackages/lib/di/containers/BookingLimits.tspackages/lib/di/modules/LuckyUser.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
packages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/lib/di/containers/AvailableSlots.tspackages/lib/di/containers/BookingLimits.tspackages/lib/di/modules/LuckyUser.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
packages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/lib/di/containers/AvailableSlots.tspackages/lib/di/containers/BookingLimits.tspackages/lib/di/modules/LuckyUser.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Applied to files:
packages/lib/di/modules/CheckBookingAndDurationLimits.tspackages/lib/di/containers/BookingLimits.ts
🧬 Code graph analysis (1)
packages/lib/di/modules/CheckBookingAndDurationLimits.ts (5)
packages/lib/di/tokens.ts (1)
DI_TOKENS(1-60)packages/features/bookings/lib/handleNewBooking/checkBookingAndDurationLimits.ts (1)
ICheckBookingAndDurationLimitsService(17-19)packages/lib/di/modules/Booking.ts (1)
moduleLoader(11-16)packages/lib/di/modules/Cache.ts (1)
moduleLoader(14-19)packages/lib/di/modules/CheckBookingLimits.ts (1)
moduleLoader(13-18)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Production builds / Build Web App
- GitHub Check: Production builds / Build API v2
- GitHub Check: Production builds / Build Docs
- GitHub Check: Production builds / Build API v1
- GitHub Check: Type check / check-types
- GitHub Check: Tests / Unit
- GitHub Check: Linters / lint
- GitHub Check: Production builds / Build Atoms
🔇 Additional comments (4)
packages/lib/di/containers/AvailableSlots.ts (1)
6-6: Import source swap to internal DI looks good—confirm API parity.Ensure
../dire-exportscreateContaineras a named export (ESM/CJS) with the same semantics as before.packages/lib/di/modules/CheckBookingAndDurationLimits.ts (2)
8-9: Token wiring looks correct.CHECK_BOOKING_AND_DURATION_LIMITS_SERVICE and its MODULE token match tokens.ts and the new pattern.
10-12: Use bindModuleToClassOnToken instead of manual toClass binding- checkBookingAndDurationLimitsModule.bind(token).toClass(CheckBookingAndDurationLimitsService, { - checkBookingLimitsService: DI_TOKENS.CHECK_BOOKING_LIMITS_SERVICE, - } satisfies Record<keyof ICheckBookingAndDurationLimitsService, symbol>); + bindModuleToClassOnToken<ICheckBookingAndDurationLimitsService>( + checkBookingAndDurationLimitsModule, + token, + CheckBookingAndDurationLimitsService, + { checkBookingLimitsService: DI_TOKENS.CHECK_BOOKING_LIMITS_SERVICE }, + );Ensure that every file importing CheckBookingAndDurationLimitsService also imports CheckBookingLimits – the provided verification script failed to execute in this environment, so please manually confirm.
packages/lib/di/modules/LuckyUser.ts (1)
4-4: LGTM on DI import migrationSwitching to the local DI entrypoint aligns with the refactor direction.
d0d7baa to
fa2efbe
Compare
fa2efbe to
66952a8
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
packages/lib/di/bookings/modules/RecurringBookingService.module.ts (1)
1-12: Adopt the moduleLoader pattern for consistency (and future-proof containers).This module still exports a raw module via createModule and relies on DI_TOKENS.RECURRING_BOOKING_SERVICE_MODULE for container.load(...). Per PR objective, modules should expose a moduleLoader with token + loadModule. Propose:
-import { createModule } from "../../di"; +import { type Container, createModule } from "../../di"; export const recurringBookingServiceModule = createModule(); recurringBookingServiceModule.bind(DI_TOKENS.RECURRING_BOOKING_SERVICE).toClass(RecurringBookingService, { regularBookingService: DI_TOKENS.REGULAR_BOOKING_SERVICE, }); export type { RecurringBookingService }; + +const token = DI_TOKENS.RECURRING_BOOKING_SERVICE; +const moduleToken = DI_TOKENS.RECURRING_BOOKING_SERVICE_MODULE; +export const moduleLoader = { + token, + loadModule: (container: Container) => { + container.load(moduleToken, recurringBookingServiceModule); + }, +};Follow-up: migrate containers to use recurringBookingServiceModule.loadModule(...) and recurringBookingServiceModule.token, then (optionally) stop exporting the raw module to prevent regressions.
packages/lib/di/modules/Schedule.ts (1)
4-10: Export a moduleLoader to match the new standard.Schedule still exposes a raw module; export a loader with token + loadModule, mirroring Cache/Prisma.
-import { createModule } from "../di"; +import { type Container, createModule } from "../di"; export const scheduleRepositoryModule = createModule(); scheduleRepositoryModule .bind(DI_TOKENS.SCHEDULE_REPOSITORY) .toClass(ScheduleRepository, [DI_TOKENS.PRISMA_CLIENT]); // Maps 'prismaClient' param to PRISMA_CLIENT token + +const token = DI_TOKENS.SCHEDULE_REPOSITORY; +const moduleToken = DI_TOKENS.SCHEDULE_REPOSITORY_MODULE; +export const moduleLoader = { + token, + loadModule: (container: Container) => { + container.load(moduleToken, scheduleRepositoryModule); + }, +};packages/lib/di/bookings/containers/RecurringBookingService.container.ts (1)
15-29: Replace directcontainer.loadcalls with module loaders in booking containers
- RecurringBookingService.container.ts still uses
container.loadat lines 16–21 and 25; swap eachcontainer.load(DI_TOKENS…, …)with the corresponding*ModuleLoader.loadModule(container)and updategetRecurringBookingService()to userecurringBookingServiceModule.tokenper the suggested diff.- InstantBookingCreateService.container.ts (line 10) likewise needs its
container.load(DI_TOKENS.INSTANT_BOOKING_CREATE_SERVICE_MODULE, instantBookingCreateServiceModule)replaced withinstantBookingCreateServiceModuleLoader.loadModule(container)and resolution via itstoken.packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts (1)
4-12: Export a moduleLoader for InstantBookingCreateService.Mirror the standardized pattern:
-import { createModule } from "../../di"; +import { type Container, createModule } from "../../di"; export const instantBookingCreateServiceModule = createModule(); instantBookingCreateServiceModule .bind(DI_TOKENS.INSTANT_BOOKING_CREATE_SERVICE) .toClass(InstantBookingCreateService); export type { InstantBookingCreateService }; + +const token = DI_TOKENS.INSTANT_BOOKING_CREATE_SERVICE; +const moduleToken = DI_TOKENS.INSTANT_BOOKING_CREATE_SERVICE_MODULE; +export const moduleLoader = { + token, + loadModule: (container: Container) => { + container.load(moduleToken, instantBookingCreateServiceModule); + }, +};
♻️ Duplicate comments (1)
packages/prisma/prisma.module.ts (1)
13-19: Optional: dedicated loader for read-only token (repeat of earlier feedback).If you want first-class referencing symmetry, add a separate readOnlyModuleLoader; current readOnlyToken on moduleLoader is workable, so this is optional.
export const moduleLoader = { token, readOnlyToken, loadModule: (container: Container) => { container.load(moduleToken, prismaModule); }, }; + +export const readOnlyModuleLoader = { + token: readOnlyToken, + loadModule: (container: Container) => { + container.load(moduleToken, prismaModule); + }, +};
🧹 Nitpick comments (5)
packages/lib/di/bookings/tokens.ts (1)
1-8: Make token bag readonly to prevent accidental mutation.Tiny safety improvement:
-export const BOOKING_DI_TOKENS = { +export const BOOKING_DI_TOKENS = { REGULAR_BOOKING_SERVICE: Symbol("RegularBookingService"), REGULAR_BOOKING_SERVICE_MODULE: Symbol("RegularBookingServiceModule"), RECURRING_BOOKING_SERVICE: Symbol("RecurringBookingService"), RECURRING_BOOKING_SERVICE_MODULE: Symbol("RecurringBookingServiceModule"), INSTANT_BOOKING_CREATE_SERVICE: Symbol("InstantBookingCreateService"), INSTANT_BOOKING_CREATE_SERVICE_MODULE: Symbol("InstantBookingCreateServiceModule"), -}; +} as const;packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (2)
4-7: Align export naming with the standardizedmoduleLoader.If
InstantBookingCreateService.module.tsnow exportsmoduleLoader, prefer importing that for consistency across modules.Apply:
-import { - type InstantBookingCreateService, - instantBookingCreateServiceModule, -} from "../modules/InstantBookingCreateService.module"; +import { + type InstantBookingCreateService, + moduleLoader as instantBookingCreateServiceModule, +} from "../modules/InstantBookingCreateService.module";
9-14: Confirm container lifecycle is safe in your runtimes.Module-scoped singleton container persists across imports. Verify it’s safe under SSR/serverless concurrency and won’t retain request-scoped state.
packages/lib/di/bookings/modules/RegularBookingService.module.ts (2)
30-33: Standardize export name tomoduleLoader.The PR’s pattern says each module exports
{ token, loadModule }asmoduleLoader. Rename for consistency with other modules and imports (you’re already consuming others asmoduleLoader).Apply:
-export const regularBookingServiceModule = { - token, - loadModule, -}; +export const moduleLoader = { + token, + loadModule, +} as const;And update any consumers (e.g., RegularBookingService.container) to import
{ moduleLoader }or alias as needed.
10-18: Optional: add a type to the exported loader for stronger guarantees.If you have a
ModuleLoaderinterface/type, annotate the export or usesatisfiesto lock shape at compile time.Example:
export const moduleLoader = { token, loadModule } satisfies ModuleLoader;
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (48)
packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts(0 hunks)packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts(0 hunks)packages/features/redis/di/redisModule.ts(1 hunks)packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts(1 hunks)packages/lib/di/bookings/containers/RecurringBookingService.container.ts(1 hunks)packages/lib/di/bookings/containers/RegularBookingService.container.ts(1 hunks)packages/lib/di/bookings/modules/InstantBookingCreateService.module.ts(1 hunks)packages/lib/di/bookings/modules/RecurringBookingService.module.ts(1 hunks)packages/lib/di/bookings/modules/RegularBookingService.module.ts(1 hunks)packages/lib/di/bookings/tokens.ts(1 hunks)packages/lib/di/containers/AvailableSlots.ts(1 hunks)packages/lib/di/containers/BookingLimits.ts(1 hunks)packages/lib/di/containers/BusyTimes.ts(1 hunks)packages/lib/di/containers/Cache.ts(1 hunks)packages/lib/di/containers/FilterHosts.ts(1 hunks)packages/lib/di/containers/GetUserAvailability.ts(1 hunks)packages/lib/di/containers/InsightsBooking.ts(1 hunks)packages/lib/di/containers/InsightsRouting.ts(1 hunks)packages/lib/di/containers/LuckyUser.ts(1 hunks)packages/lib/di/containers/NoSlotsNotification.ts(1 hunks)packages/lib/di/containers/QualifiedHosts.ts(1 hunks)packages/lib/di/di.ts(1 hunks)packages/lib/di/modules/Attribute.ts(1 hunks)packages/lib/di/modules/AvailableSlots.ts(1 hunks)packages/lib/di/modules/Booking.ts(1 hunks)packages/lib/di/modules/BusyTimes.ts(1 hunks)packages/lib/di/modules/Cache.ts(1 hunks)packages/lib/di/modules/CheckBookingAndDurationLimits.ts(1 hunks)packages/lib/di/modules/CheckBookingLimits.ts(1 hunks)packages/lib/di/modules/EventType.ts(1 hunks)packages/lib/di/modules/Features.ts(1 hunks)packages/lib/di/modules/FilterHosts.ts(1 hunks)packages/lib/di/modules/GetUserAvailability.ts(1 hunks)packages/lib/di/modules/Host.ts(1 hunks)packages/lib/di/modules/InsightsBooking.ts(1 hunks)packages/lib/di/modules/InsightsRouting.ts(1 hunks)packages/lib/di/modules/LuckyUser.ts(1 hunks)packages/lib/di/modules/Membership.ts(1 hunks)packages/lib/di/modules/NoSlotsNotification.ts(1 hunks)packages/lib/di/modules/Ooo.ts(1 hunks)packages/lib/di/modules/QualifiedHosts.ts(1 hunks)packages/lib/di/modules/RoutingFormResponse.ts(1 hunks)packages/lib/di/modules/Schedule.ts(1 hunks)packages/lib/di/modules/SelectedSlots.ts(1 hunks)packages/lib/di/modules/Team.ts(1 hunks)packages/lib/di/modules/User.ts(1 hunks)packages/lib/di/tokens.ts(2 hunks)packages/prisma/prisma.module.ts(1 hunks)
💤 Files with no reviewable changes (2)
- packages/features/bookings/lib/di/containers/RegularBookingServiceContainer.ts
- packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts
🚧 Files skipped from review as they are similar to previous changes (36)
- packages/lib/di/containers/LuckyUser.ts
- packages/lib/di/containers/GetUserAvailability.ts
- packages/lib/di/modules/FilterHosts.ts
- packages/lib/di/containers/QualifiedHosts.ts
- packages/lib/di/containers/FilterHosts.ts
- packages/lib/di/modules/Team.ts
- packages/lib/di/modules/InsightsBooking.ts
- packages/lib/di/modules/Membership.ts
- packages/lib/di/modules/CheckBookingLimits.ts
- packages/features/redis/di/redisModule.ts
- packages/lib/di/modules/Features.ts
- packages/lib/di/modules/InsightsRouting.ts
- packages/lib/di/containers/BusyTimes.ts
- packages/lib/di/modules/SelectedSlots.ts
- packages/lib/di/modules/Ooo.ts
- packages/lib/di/modules/GetUserAvailability.ts
- packages/lib/di/modules/LuckyUser.ts
- packages/lib/di/modules/CheckBookingAndDurationLimits.ts
- packages/lib/di/containers/InsightsBooking.ts
- packages/lib/di/modules/BusyTimes.ts
- packages/lib/di/modules/QualifiedHosts.ts
- packages/lib/di/modules/EventType.ts
- packages/lib/di/containers/NoSlotsNotification.ts
- packages/lib/di/containers/AvailableSlots.ts
- packages/lib/di/modules/Cache.ts
- packages/lib/di/containers/Cache.ts
- packages/lib/di/containers/BookingLimits.ts
- packages/lib/di/modules/Host.ts
- packages/lib/di/modules/Booking.ts
- packages/lib/di/modules/AvailableSlots.ts
- packages/lib/di/modules/User.ts
- packages/lib/di/containers/InsightsRouting.ts
- packages/lib/di/modules/Attribute.ts
- packages/lib/di/di.ts
- packages/lib/di/modules/RoutingFormResponse.ts
- packages/lib/di/modules/NoSlotsNotification.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
**/*.ts: For Prisma queries, only select data you need; never useinclude, always useselect
Ensure thecredential.keyfield is never returned from tRPC endpoints or APIs
Files:
packages/lib/di/bookings/containers/RegularBookingService.container.tspackages/lib/di/bookings/modules/InstantBookingCreateService.module.tspackages/prisma/prisma.module.tspackages/lib/di/bookings/modules/RegularBookingService.module.tspackages/lib/di/bookings/tokens.tspackages/lib/di/bookings/modules/RecurringBookingService.module.tspackages/lib/di/bookings/containers/InstantBookingCreateService.container.tspackages/lib/di/modules/Schedule.tspackages/lib/di/tokens.tspackages/lib/di/bookings/containers/RecurringBookingService.container.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/review.mdc)
Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js
.utc()in hot paths like loops
Files:
packages/lib/di/bookings/containers/RegularBookingService.container.tspackages/lib/di/bookings/modules/InstantBookingCreateService.module.tspackages/prisma/prisma.module.tspackages/lib/di/bookings/modules/RegularBookingService.module.tspackages/lib/di/bookings/tokens.tspackages/lib/di/bookings/modules/RecurringBookingService.module.tspackages/lib/di/bookings/containers/InstantBookingCreateService.container.tspackages/lib/di/modules/Schedule.tspackages/lib/di/tokens.tspackages/lib/di/bookings/containers/RecurringBookingService.container.ts
**/*.{ts,tsx,js,jsx}
⚙️ CodeRabbit configuration file
Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.
Files:
packages/lib/di/bookings/containers/RegularBookingService.container.tspackages/lib/di/bookings/modules/InstantBookingCreateService.module.tspackages/prisma/prisma.module.tspackages/lib/di/bookings/modules/RegularBookingService.module.tspackages/lib/di/bookings/tokens.tspackages/lib/di/bookings/modules/RecurringBookingService.module.tspackages/lib/di/bookings/containers/InstantBookingCreateService.container.tspackages/lib/di/modules/Schedule.tspackages/lib/di/tokens.tspackages/lib/di/bookings/containers/RecurringBookingService.container.ts
🧠 Learnings (1)
📚 Learning: 2025-09-03T09:52:51.182Z
Learnt from: hariombalhara
PR: calcom/cal.com#23541
File: packages/features/bookings/lib/di/modules/RegularBookingServiceModule.ts:22-28
Timestamp: 2025-09-03T09:52:51.182Z
Learning: The IBookingServiceDependencies interface in packages/features/bookings/lib/handleNewBooking.ts contains 6 properties: cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, and checkBookingLimitsService. This interface is used by RegularBookingService and matches the depsMap structure in RegularBookingServiceModule.
Applied to files:
packages/lib/di/bookings/containers/RegularBookingService.container.tspackages/lib/di/bookings/modules/InstantBookingCreateService.module.tspackages/lib/di/bookings/modules/RegularBookingService.module.tspackages/lib/di/bookings/tokens.tspackages/lib/di/bookings/modules/RecurringBookingService.module.tspackages/lib/di/bookings/containers/RecurringBookingService.container.ts
🧬 Code graph analysis (4)
packages/lib/di/bookings/containers/RegularBookingService.container.ts (2)
packages/lib/di/di.ts (1)
createContainer(38-38)packages/lib/di/bookings/modules/RegularBookingService.module.ts (2)
RegularBookingService(35-35)regularBookingServiceModule(30-33)
packages/prisma/prisma.module.ts (3)
packages/lib/di/tokens.ts (1)
DI_TOKENS(3-58)packages/prisma/index.ts (1)
readonlyPrisma(67-71)packages/lib/di/modules/Cache.ts (1)
moduleLoader(14-19)
packages/lib/di/bookings/modules/RegularBookingService.module.ts (2)
packages/lib/di/di.ts (1)
bindModuleToClassOnToken(11-37)packages/lib/di/tokens.ts (1)
DI_TOKENS(3-58)
packages/lib/di/tokens.ts (1)
packages/lib/di/bookings/tokens.ts (1)
BOOKING_DI_TOKENS(1-8)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (5)
packages/lib/di/tokens.ts (1)
56-57: LGTM: booking tokens are now sourced from a single place.Spreading BOOKING_DI_TOKENS into DI_TOKENS aligns with the new structure and keeps symbols centralized.
packages/lib/di/bookings/containers/RegularBookingService.container.ts (1)
1-13: LGTM: conforms to the moduleLoader contract.Uses loadModule + resolve by module token; aligns with the new DI conventions.
packages/lib/di/bookings/containers/InstantBookingCreateService.container.ts (1)
3-7: LGTM: local DI import and module wiring look correct.Migration to the local DI
createContainerand the module import path is consistent with the new DI structure.packages/lib/di/bookings/modules/RegularBookingService.module.ts (2)
12-28: Binding and deps map look correct.Deps keys match the known
IBookingServiceDependencies(cacheService, checkBookingAndDurationLimitsService, prismaClient, bookingRepository, featuresRepository, checkBookingLimitsService).
1-1: Verified: RegularBookingService shape matches DI helper requirements.
| import { createContainer } from "../../di"; | ||
| import { | ||
| type RecurringBookingService, | ||
| recurringBookingServiceModule, | ||
| } from "../modules/RecurringBookingService.module"; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Switch imports to moduleLoader variants.
Update imports to use each module’s moduleLoader, including Prisma. Example:
-import { createContainer } from "../../di";
-import {
- type RecurringBookingService,
- recurringBookingServiceModule,
-} from "../modules/RecurringBookingService.module";
+import { createContainer } from "../../di";
+import { moduleLoader as prismaModuleLoader } from "@calcom/prisma/prisma.module";
+import { moduleLoader as bookingModuleLoader } from "@calcom/lib/di/modules/Booking";
+import { moduleLoader as cacheModuleLoader } from "@calcom/lib/di/modules/Cache";
+import { moduleLoader as checkBookingAndDurationLimitsModuleLoader } from "@calcom/lib/di/modules/CheckBookingAndDurationLimits";
+import { moduleLoader as checkBookingLimitsModuleLoader } from "@calcom/lib/di/modules/CheckBookingLimits";
+import { moduleLoader as featuresModuleLoader } from "@calcom/lib/di/modules/Features";
+import {
+ type RecurringBookingService,
+ moduleLoader as recurringBookingServiceModule,
+} from "../modules/RecurringBookingService.module";📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { createContainer } from "../../di"; | |
| import { | |
| type RecurringBookingService, | |
| recurringBookingServiceModule, | |
| } from "../modules/RecurringBookingService.module"; | |
| import { createContainer } from "../../di"; | |
| import { moduleLoader as prismaModuleLoader } from "@calcom/prisma/prisma.module"; | |
| import { moduleLoader as bookingModuleLoader } from "@calcom/lib/di/modules/Booking"; | |
| import { moduleLoader as cacheModuleLoader } from "@calcom/lib/di/modules/Cache"; | |
| import { moduleLoader as checkBookingAndDurationLimitsModuleLoader } from "@calcom/lib/di/modules/CheckBookingAndDurationLimits"; | |
| import { moduleLoader as checkBookingLimitsModuleLoader } from "@calcom/lib/di/modules/CheckBookingLimits"; | |
| import { moduleLoader as featuresModuleLoader } from "@calcom/lib/di/modules/Features"; | |
| import { | |
| type RecurringBookingService, | |
| moduleLoader as recurringBookingServiceModule, | |
| } from "../modules/RecurringBookingService.module"; |
🤖 Prompt for AI Agents
In packages/lib/di/bookings/containers/RecurringBookingService.container.ts
around lines 9 to 13, the file currently imports modules directly (e.g.,
recurringBookingServiceModule and Prisma) but the codebase expects the
moduleLoader variants; replace the direct module imports with their
corresponding moduleLoader exports (for example use
recurringBookingServiceModuleLoader and the prismaModuleLoader) and update the
import source paths to the modules' moduleLoader entry points so the DI
container wires the loaders instead of raw modules.
| export const prismaModule = createModule(); | ||
| const token = DI_TOKENS.PRISMA_CLIENT; | ||
| const readOnlyToken = DI_TOKENS.READ_ONLY_PRISMA_CLIENT; | ||
| const moduleToken = DI_TOKENS.PRISMA_MODULE; | ||
| prismaModule.bind(token).toFactory(() => prisma, "singleton"); | ||
| prismaModule.bind(readOnlyToken).toFactory(() => readonlyPrisma, "singleton"); |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Stop exporting the raw prismaModule to enforce the loader contract.
Keeping prismaModule exported encourages direct container.load(...), which this PR aims to remove. Make it internal:
-export const prismaModule = createModule();
+const prismaModule = createModule();Containers should import { moduleLoader as prismaModuleLoader } and call prismaModuleLoader.loadModule(container).
Run to find remaining direct usages to migrate:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Direct imports of raw prismaModule
rg -nP '\bfrom ["\']@calcom/prisma/prisma\.module["\']' -C2 | rg -nP '\bprismaModule\b' -n
# Any container.load(...) calls left in DI containers
rg -nP 'container\.load\(' packages/lib/di/containers -nLength of output: 68
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Direct imports of raw prismaModule
rg -nP "from ['\"]@calcom/prisma/prisma\.module['\"]" -C2 packages/ | rg -nP "\bprismaModule\b" -n || true
# Any container.load(...) calls left in DI containers
rg -nP "container\.load\(" packages/lib/di/containers -n || trueLength of output: 8670
Remove the exported prismaModule and migrate all containers to use prismaModuleLoader
All DI container files under packages/lib/di/containers (e.g. RecurringBookingService.container.ts, Cache.ts, QualifiedHosts.ts, etc.) still import and pass the raw prismaModule to container.load(...). Update each to:
- Import
{ moduleLoader as prismaModuleLoader }instead ofprismaModule - Replace
container.load(DI_TOKENS.PRISMA_MODULE, prismaModule)
with
prismaModuleLoader.loadModule(container)
This ensures the loader contract is enforced and removes direct use of the internal module.
🤖 Prompt for AI Agents
In packages/prisma/prisma.module.ts around lines 6 to 11, the file currently
exports prismaModule and binds tokens directly; the review asks to stop
exporting the raw prismaModule and migrate consumers to use prismaModuleLoader.
Remove the exported prismaModule from this file (keep internal creation and
bindings as needed) and export or re-export the moduleLoader instead (named
export moduleLoader or prismaModuleLoader per project convention). Then update
every DI container under packages/lib/di/containers to import { moduleLoader as
prismaModuleLoader } from the prisma module file and replace
container.load(DI_TOKENS.PRISMA_MODULE, prismaModule) with
prismaModuleLoader.loadModule(container) so the loader contract is used and
direct module passing is eliminated.

1. Standardized Module Structure
moduleLoader:2. Type-Safe Dependency Binding
bindModuleToClassOnTokenutility function in/packages/lib/di/ioctopus.tsdepsMapmatches the class's dependency requirements3. Enhanced Container Management
loadDepsfunctionsRegularBookingServiceModulenow uses type-safe dependency mapping: