Skip to content

Services

composeService is a utility function for creating service layers in GamanJS.
Services contain application business logic that is separated from controllers/handlers.

AppService.ts
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>;

Parameters in composeService can be customized as needed:

// Single parameter
composeService((id: number) => ({ /* ... */ }))
// Multiple parameters
composeService((id: number, token: string) => ({ /* ... */ }))
// Object parameter
composeService((config: { userId: number; secret: string }) => ({ /* ... */ }))
// Without parameter
composeService(() => ({ /* ... */ }))

Inject service directly into controller with fixed parameters:

UserController.ts
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)

Create a new service instance with dynamic parameters from the request:

UserController.ts
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!" });
}
}));
AppRoutes.ts
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() });
});
UserService.ts
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 Controller
export default composeController(
(service: UserServiceType = UserService(1, "secret-token")) => ({
GetProfile: async (ctx) => {
const user = await service.GetUser();
return Res.json(user);
}
})
);
// Or directly in Route
route.get("/user/:id", async (ctx) => {
const service = UserService(
parseInt(ctx.params.id),
ctx.headers.authorization
);
const user = await service.GetUser();
return Res.json(user);
});