Lewati ke konten

Controllers

Controller di GamanJS adalah tempat untuk menangani HTTP request. Gunakan composeController untuk membuat controller yang terstruktur dengan dependency injection sederhana melalui destrukturisasi.

src/modules/app/controllers/AppController.ts
import { composeController } from 'gaman/compose';
export default composeController(() => {
/**
* Kamu bisa menaruh logik privat di sini
*/
return {
HelloWorld(ctx) {
return ctx.send('Hello World!').ok();
},
About(ctx) {
return ctx.send({ name: 'GamanJS', version: '2.0' }).ok();
},
};
});

composeController menerima factory function yang mengembalikan object berisi method-method handler. Setiap method menerima ctx (Context) sebagai parameter.

Controller mendukung DI melalui destrukturisasi pada factory function. Direkomendasikan untuk mendefinisikan tipe Deps untuk service-service kamu.

import { composeController } from 'gaman/compose';
import { UserService } from '../services/UserService';
export type Deps = {
userService: UserService;
};
export default composeController(({ userService }: Deps) => {
/**
* TODO: taruh logik privat di sini
*/
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();
},
};
});

Controller didaftarkan dengan format tuple [ControllerFactory, 'NamaMethod'].

[!IMPORTANT] Untuk menyediakan dependensi (service) ke controller kamu, kamu wajib menggunakan r.mountService() di dalam 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. Sediakan dependensi
r.mountService({
userService: UserService(),
});
// 2. Daftarkan route
r.get('/users', [UserController, 'GetAll']);
r.get('/users/:id', [UserController, 'GetById']);
});

Untuk detail lebih lanjut tentang konfigurasi router, lihat Router.

  • Satu file controller bisa berisi banyak method — grupkan berdasarkan domain/resource.
  • Gunakan pola export type Deps = { ... } untuk DI yang bersih dan type-safe.
  • Destruktur service kamu dari parameter factory function.
  • Controller hanya berisi logic handling — business logic taruh di Service.