Move modules to moduleLoader format (#23740)

This commit is contained in:
Hariom Balhara
2025-09-16 10:58:23 +00:00
committed by GitHub
parent 7fe80dd3dd
commit badc857bcd
7 changed files with 180 additions and 43 deletions
+3 -16
View File
@@ -1,24 +1,11 @@
import { DI_TOKENS } from "@calcom/lib/di/tokens";
import type { LuckyUserService } from "@calcom/lib/server/getLuckyUser";
import { prismaModule } from "@calcom/prisma/prisma.module";
import { createContainer } from "../di";
import { attributeRepositoryModule } from "../modules/Attribute";
import { bookingRepositoryModule } from "../modules/Booking";
import { hostRepositoryModule } from "../modules/Host";
import { luckyUserServiceModule } from "../modules/LuckyUser";
import { oooRepositoryModule } from "../modules/Ooo";
import { userRepositoryModule } from "../modules/User";
import { moduleLoader as luckyUserServiceModuleLoader } from "../modules/LuckyUser";
const container = createContainer();
container.load(DI_TOKENS.PRISMA_MODULE, prismaModule);
container.load(DI_TOKENS.BOOKING_REPOSITORY_MODULE, bookingRepositoryModule);
container.load(DI_TOKENS.HOST_REPOSITORY_MODULE, hostRepositoryModule);
container.load(DI_TOKENS.OOO_REPOSITORY_MODULE, oooRepositoryModule);
container.load(DI_TOKENS.USER_REPOSITORY_MODULE, userRepositoryModule);
container.load(DI_TOKENS.ATTRIBUTE_REPOSITORY_MODULE, attributeRepositoryModule);
container.load(DI_TOKENS.LUCKY_USER_SERVICE_MODULE, luckyUserServiceModule);
export function getLuckyUserService() {
return container.get<LuckyUserService>(DI_TOKENS.LUCKY_USER_SERVICE);
luckyUserServiceModuleLoader.loadModule(container);
return container.get<LuckyUserService>(luckyUserServiceModuleLoader.token);
}
+85 -9
View File
@@ -1,14 +1,16 @@
import type { Container, Module } from "@evyweb/ioctopus";
import { createContainer, createModule } from "@evyweb/ioctopus";
export type ModuleLoader = { token: string | symbol; loadModule: (container: Container) => void };
/**
* A type-safe alternative to module.bind(token).toClass(classs, deps) that automatically ensures that all dependencies required by the Class are provided.
* It assumes that dependencies are stored under the `deps` property of the Class, which is a good convention to follow anyway
* It assumes that dependencies are passed to the constructor as an object map(e.g. new MyService(deps))
*
* @returns A function that can be used to load the dependencies into the container automatically.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function bindModuleToClassOnToken<TClass extends new (...args: any[]) => any>({
export function bindModuleToClassOnToken<TClass extends new (deps: any) => any>({
module,
token,
classs,
@@ -20,18 +22,92 @@ export function bindModuleToClassOnToken<TClass extends new (...args: any[]) =>
token: string | symbol;
classs: TClass;
depsMap: Record<
keyof InstanceType<TClass>["deps"],
{ token: string | symbol; loadModule: (container: Container) => void }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
keyof (TClass extends new (deps: infer TDeps) => any ? TDeps : never),
ModuleLoader
>;
}): (container: Container) => void;
/**
* A type-safe alternative to module.bind(token).toClass(classs, deps) that automatically ensures that all dependencies required by the Class are provided.
* It assumes that there is a single dependency, passed as argument to the constructor
*
* @returns A function that can be used to load the dependencies into the container automatically.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function bindModuleToClassOnToken<TClass extends new (deps: any) => any>({
module,
token,
classs,
dep,
moduleToken,
}: {
module: Module;
moduleToken: string | symbol;
token: string | symbol;
classs: TClass;
dep: ModuleLoader;
}): (container: Container) => void;
/**
* A type-safe alternative to module.bind(token).toClass(classs, deps) that automatically ensures that all dependencies required by the Class are provided.
* @returns A function that can be used to load the dependencies into the container automatically.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function bindModuleToClassOnToken<TClass extends new (deps: any) => any>({
module,
token,
classs,
depsMap,
dep,
moduleToken,
}: {
module: Module;
moduleToken: string | symbol;
token: string | symbol;
classs: TClass;
/**
* When the constructor of the class accept deps as the argument which is a Record of many dependencies
*/
depsMap?: Record<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
keyof (TClass extends new (deps: infer TDeps) => any ? TDeps : never),
ModuleLoader
>;
/**
* When the constructor of the class accept a single dependency and is the only argument to constructor.
*/
dep?: ModuleLoader;
}) {
const depsObject = Object.fromEntries(Object.entries(depsMap).map(([key, value]) => [key, value.token]));
module.bind(token).toClass(classs, depsObject);
if (dep && depsMap) {
throw new Error(
"Cannot provide both 'dep' and 'depsMap'. Use 'dep' for single dependency or 'depsMap' for multiple dependencies."
);
}
if (!dep && !depsMap) {
throw new Error(
"Must provide either 'dep' for single dependency or 'depsMap' for multiple dependencies."
);
}
if (dep) {
module.bind(token).toClass(classs, [dep.token]);
} else if (depsMap) {
const depsObject = Object.fromEntries(Object.entries(depsMap).map(([key, value]) => [key, value.token]));
module.bind(token).toClass(classs, depsObject);
}
return function loadModule(container: Container) {
container.load(moduleToken, module);
for (const key in depsMap) {
const loadModule = depsMap[key as keyof typeof depsMap].loadModule;
loadModule(container);
if (dep) {
dep.loadModule(container);
} else if (depsMap) {
for (const key in depsMap) {
const loadModule = depsMap[key as keyof typeof depsMap].loadModule;
loadModule(container);
}
}
};
}
+16 -4
View File
@@ -1,9 +1,21 @@
import { DI_TOKENS } from "@calcom/lib/di/tokens";
import { PrismaAttributeRepository } from "@calcom/lib/server/repository/PrismaAttributeRepository";
import { moduleLoader as prismaModuleLoader } from "@calcom/prisma/prisma.module";
import { createModule } from "../di";
import { createModule, bindModuleToClassOnToken, type ModuleLoader } from "../di";
export const attributeRepositoryModule = createModule();
attributeRepositoryModule
.bind(DI_TOKENS.ATTRIBUTE_REPOSITORY)
.toClass(PrismaAttributeRepository, [DI_TOKENS.PRISMA_CLIENT]);
const token = DI_TOKENS.ATTRIBUTE_REPOSITORY;
const moduleToken = DI_TOKENS.ATTRIBUTE_REPOSITORY_MODULE;
const loadModule = bindModuleToClassOnToken({
module: attributeRepositoryModule,
moduleToken,
token,
classs: PrismaAttributeRepository,
dep: prismaModuleLoader,
});
export const moduleLoader: ModuleLoader = {
token,
loadModule,
};
+16 -2
View File
@@ -1,7 +1,21 @@
import { DI_TOKENS } from "@calcom/lib/di/tokens";
import { HostRepository } from "@calcom/lib/server/repository/host";
import { moduleLoader as prismaModuleLoader } from "@calcom/prisma/prisma.module";
import { createModule } from "../di";
import { createModule, bindModuleToClassOnToken, type ModuleLoader } from "../di";
export const hostRepositoryModule = createModule();
hostRepositoryModule.bind(DI_TOKENS.HOST_REPOSITORY).toClass(HostRepository, [DI_TOKENS.PRISMA_CLIENT]);
const token = DI_TOKENS.HOST_REPOSITORY;
const moduleToken = DI_TOKENS.HOST_REPOSITORY_MODULE;
const loadModule = bindModuleToClassOnToken({
module: hostRepositoryModule,
moduleToken,
token,
classs: HostRepository,
dep: prismaModuleLoader,
});
export const moduleLoader: ModuleLoader = {
token,
loadModule,
};
+28 -8
View File
@@ -1,13 +1,33 @@
import { DI_TOKENS } from "@calcom/lib/di/tokens";
import { LuckyUserService } from "@calcom/lib/server/getLuckyUser";
import { createModule } from "../di";
import { bindModuleToClassOnToken, createModule, type ModuleLoader } from "../di";
import { moduleLoader as attributeRepositoryModuleLoader } from "./Attribute";
import { moduleLoader as bookingRepositoryModuleLoader } from "./Booking";
import { moduleLoader as hostRepositoryModuleLoader } from "./Host";
import { moduleLoader as oooRepositoryModuleLoader } from "./Ooo";
import { moduleLoader as userRepositoryModuleLoader } from "./User";
export 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,
const thisModule = createModule();
const token = DI_TOKENS.LUCKY_USER_SERVICE;
const moduleToken = DI_TOKENS.LUCKY_USER_SERVICE_MODULE;
const loadModule = bindModuleToClassOnToken({
module: thisModule,
moduleToken,
token,
classs: LuckyUserService,
depsMap: {
bookingRepository: bookingRepositoryModuleLoader,
hostRepository: hostRepositoryModuleLoader,
oooRepository: oooRepositoryModuleLoader,
userRepository: userRepositoryModuleLoader,
attributeRepository: attributeRepositoryModuleLoader,
},
});
export const moduleLoader: ModuleLoader = {
token,
loadModule,
};
export type { LuckyUserService };
+16 -2
View File
@@ -1,7 +1,21 @@
import { DI_TOKENS } from "@calcom/lib/di/tokens";
import { PrismaOOORepository } from "@calcom/lib/server/repository/ooo";
import { moduleLoader as prismaModuleLoader } from "@calcom/prisma/prisma.module";
import { createModule } from "../di";
import { createModule, bindModuleToClassOnToken, type ModuleLoader } from "../di";
export const oooRepositoryModule = createModule();
oooRepositoryModule.bind(DI_TOKENS.OOO_REPOSITORY).toClass(PrismaOOORepository, [DI_TOKENS.PRISMA_CLIENT]);
const token = DI_TOKENS.OOO_REPOSITORY;
const moduleToken = DI_TOKENS.OOO_REPOSITORY_MODULE;
const loadModule = bindModuleToClassOnToken({
module: oooRepositoryModule,
moduleToken,
token,
classs: PrismaOOORepository,
dep: prismaModuleLoader,
});
export const moduleLoader: ModuleLoader = {
token,
loadModule,
};
+16 -2
View File
@@ -1,7 +1,21 @@
import { DI_TOKENS } from "@calcom/lib/di/tokens";
import { UserRepository } from "@calcom/lib/server/repository/user";
import { moduleLoader as prismaModuleLoader } from "@calcom/prisma/prisma.module";
import { createModule } from "../di";
import { createModule, bindModuleToClassOnToken, type ModuleLoader } from "../di";
export const userRepositoryModule = createModule();
userRepositoryModule.bind(DI_TOKENS.USER_REPOSITORY).toClass(UserRepository, [DI_TOKENS.PRISMA_CLIENT]);
const token = DI_TOKENS.USER_REPOSITORY;
const moduleToken = DI_TOKENS.USER_REPOSITORY_MODULE;
const loadModule = bindModuleToClassOnToken({
module: userRepositoryModule,
moduleToken,
token,
classs: UserRepository,
dep: prismaModuleLoader,
});
export const moduleLoader: ModuleLoader = {
token,
loadModule,
};