Skip to content

Controllers

Controllers in GamanJS handle HTTP requests. Use composeController to create structured controllers with simple dependency injection through destructuring.

src/modules/app/controllers/AppController.ts
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.

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();
},
};
});
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();
},
};
});

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.