Controllers
Controllers in GamanJS handle HTTP requests. Use composeController to create structured controllers with simple dependency injection through destructuring.
Creating a Controller
Section titled “Creating a Controller”import { composeController } from 'gaman/compose';
export default composeController(() => { /** * You can put your private logic here */
return { HelloWorld(ctx) { return ctx.send('Hello World!').ok(); },
About(ctx) { return ctx.send({ name: 'GamanJS', version: '2.0' }).ok(); }, };});composeController takes a factory function that returns an object containing handler methods. Each method receives ctx (Context) as a parameter.
Dependency Injection
Section titled “Dependency Injection”Controllers support DI through destructuring in the factory function. It is recommended to define a Deps type for your services.
import { composeController } from 'gaman/compose';import { UserService } from '../services/UserService';
export type Deps = { userService: UserService;};
export default composeController(({ userService }: Deps) => { /** * TODO: your private logic in here */
return { GetAll(ctx) { const users = userService.findAll(); return ctx.send(users).ok(); },
GetById(ctx) { const id = ctx.param('id'); const user = userService.findById(id);
if (!user) { return ctx.send('User not found').notFound(); }
return ctx.send(user).ok(); },
async Create(ctx) { const body = await ctx.json(); const user = userService.create(body); return ctx.send(user).created(); }, };});Multiple Services
Section titled “Multiple Services”import { composeController } from 'gaman/compose';import { UserService } from '../services/UserService';import { EmailService } from '../services/EmailService';
export type Deps = { userService: UserService; emailService: EmailService;};
export default composeController(({ userService, emailService }: Deps) => { return { async Register(ctx) { const body = await ctx.json(); const user = userService.create(body); emailService.sendWelcome(user.email); return ctx.send(user).created(); }, };});Registering in the Router
Section titled “Registering in the Router”Controllers are registered using the tuple format [ControllerFactory, 'MethodName'].
[!IMPORTANT] To provide the dependencies (services) to your controller, you must use
r.mountService()in your router.
import { composeRouter } from 'gaman/compose';import UserController from './modules/app/controllers/UserController';import { UserService } from './modules/app/services/UserService';
export default composeRouter((r) => { // 1. Provide dependencies r.mountService({ userService: UserService(), });
// 2. Register routes r.get('/users', [UserController, 'GetAll']); r.get('/users/:id', [UserController, 'GetById']);});For more details on router configuration, see Router.
- A single controller file can contain many methods — group them by domain/resource.
- Use the
export type Deps = { ... }pattern for clean and type-safe DI. - Destructure your services from the factory function parameter.
- Controllers should only contain handling logic — put business logic in Services.