Services
composeService is a utility function for creating service layers in GamanJS.
Services contain application business logic that is separated from controllers/handlers.
Creating a Service
Section titled “Creating a Service”import { composeService } from "@gaman/core";
export const AppService = composeService((userId: number) => ({ Welcome() { return `Welcome user ${userId}!`; },
async GetProfile() { return await db.user.findUnique({ where: { id: userId } }); }}));
export type AppServiceType = ReturnType<typeof AppService>;Service Parameters
Section titled “Service Parameters”Parameters in composeService can be customized as needed:
// Single parametercomposeService((id: number) => ({ /* ... */ }))
// Multiple parameterscomposeService((id: number, token: string) => ({ /* ... */ }))
// Object parametercomposeService((config: { userId: number; secret: string }) => ({ /* ... */ }))
// Without parametercomposeService(() => ({ /* ... */ }))How to Use Service
Section titled “How to Use Service”1. In Controller (Static Service)
Section titled “1. In Controller (Static Service)”Inject service directly into controller with fixed parameters:
import { composeController } from "@gaman/core";import { AppService, type AppServiceType } from "./AppService";
export default composeController((service: AppServiceType = AppService(1)) => ({ CreateUser: async (ctx) => { const profile = await service.GetProfile(); return Res.json({ message: "user created!", profile }); },
UpdateUser: (ctx) => { return Res.json({ message: "user updated!" }); },
DeleteUser: (ctx) => { return Res.json({ message: "user deleted!" }); }}));Note: If the service has parameters, pass the value when injecting: AppService(userId)
2. In Controller (Dynamic Service)
Section titled “2. In Controller (Dynamic Service)”Create a new service instance with dynamic parameters from the request:
import { composeController } from "@gaman/core";import { AppService, type AppServiceType } from "./AppService";
export default composeController((service: AppServiceType = AppService(1)) => ({ CreateUser: async (ctx) => { const profile = await service.GetProfile(); return Res.json({ message: "user created!", profile }); },
UpdateUser: (ctx) => { // Dynamic service based on request parameters const dynamicService = AppService(ctx.param("userId")); const profile = await dynamicService.GetProfile(); return Res.json({ message: "user updated!", profile }); },
DeleteUser: (ctx) => { return Res.json({ message: "user deleted!" }); }}));3. Directly in Route
Section titled “3. Directly in Route”import { AppService } from "./AppService";
route.get("/profile/:id", async (ctx) => { const userId = parseInt(ctx.params.id); const service = AppService(userId);
const profile = await service.GetProfile(); return Res.json(profile);});
route.get("/welcome", (ctx) => { const service = AppService(ctx.user.id); return Res.json({ message: service.Welcome() });});Complete Example
Section titled “Complete Example”export const UserService = composeService((userId: number, token: string) => ({ async GetUser() { return await db.user.findUnique({ where: { id: userId } }); },
async UpdateUser(data: any) { // Verify token if (!this.verifyToken(token)) { throw new Error("Invalid token"); }
return await db.user.update({ where: { id: userId }, data }); },
verifyToken(token: string) { // Token verification logic return true; }}));
export type UserServiceType = ReturnType<typeof UserService>;Usage:
// In Controllerexport default composeController( (service: UserServiceType = UserService(1, "secret-token")) => ({ GetProfile: async (ctx) => { const user = await service.GetUser(); return Res.json(user); } }));
// Or directly in Routeroute.get("/user/:id", async (ctx) => { const service = UserService( parseInt(ctx.params.id), ctx.headers.authorization );
const user = await service.GetUser(); return Res.json(user);});