Lewati ke konten

Routing

GamanJS menggunakan composeRouter untuk mendefinisikan semua route aplikasi secara deklaratif. Router mendukung semua HTTP method, route grouping, middleware per-route, dan exception handler per-route.

src/modules/app/AppRoutes.ts
import { composeRouter } from 'gaman/compose';
import AppController from './controllers/AppController';
export default composeRouter((r) => {
r.get('/', [AppController, 'HelloWorld']);
r.post('/users', [AppController, 'CreateUser']);
});

Semua HTTP method standar tersedia:

export default composeRouter((r) => {
r.get('/resource', handler);
r.post('/resource', handler);
r.put('/resource/:id', handler);
r.patch('/resource/:id', handler);
r.delete('/resource/:id', handler);
r.head('/resource', handler);
r.options('/resource', handler);
r.all('/resource', handler); // GET, POST, PUT, DELETE, PATCH
});
r.match(['GET', 'POST'], '/custom', handler);

Handler bisa berupa function langsung atau tuple Controller:

r.get('/ping', (ctx) => {
return ctx.send('pong').ok();
});
import UserController from './controllers/UserController';
r.get('/users', [UserController, 'GetAll']);
r.get('/users/:id', [UserController, 'GetById']);
r.post('/users', [UserController, 'Create']);

Format: [ControllerFactory, 'NamaMethod']

Gunakan :nama untuk parameter dinamis:

r.get('/users/:id', [UserController, 'GetById']);
r.get('/posts/:postId/comments/:commentId', [PostController, 'GetComment']);

Akses di handler via ctx.param('id') atau ctx.params.

Grupkan route dengan prefix yang sama:

export default composeRouter((r) => {
r.group('/api/v1', (api) => {
api.get('/users', [UserController, 'GetAll']);
api.post('/users', [UserController, 'Create']);
api.group('/admin', (admin) => {
admin.get('/dashboard', [AdminController, 'Dashboard']);
});
});
});

Route yang dihasilkan:

  • GET /api/v1/users
  • POST /api/v1/users
  • GET /api/v1/admin/dashboard

Tambahkan middleware per-route menggunakan chaining .middleware():

import AuthMiddleware from './middlewares/AuthMiddleware';
export default composeRouter((r) => {
// Route tanpa middleware
r.get('/public', [AppController, 'Public']);
// Route dengan middleware
r.get('/protected', [AppController, 'Protected'])
.middleware(AuthMiddleware());
// Multiple middleware
r.post('/admin/action', [AdminController, 'DoAction'])
.middleware(AuthMiddleware())
.middleware(RateLimitMiddleware());
});

Otomatis berlaku ke semua route dalam group:

r.group('/admin', (admin) => {
admin.get('/dashboard', [AdminController, 'Dashboard']);
admin.get('/users', [AdminController, 'Users']);
}).middleware(AuthMiddleware());

Override error handling per-route:

import { composeException } from 'gaman/compose';
const CustomErrorHandler = composeException((error, ctx) => {
return ctx.send({ detail: error.message }).error();
});
r.get('/risky', [AppController, 'Risky'])
.exception(CustomErrorHandler);

Kamu bisa mendaftarkan middleware atau exception handler global khusus untuk satu router:

export default composeRouter((r) => {
r.mountMiddleware(LogMiddleware());
r.mountException(CustomErrorHandler);
r.get('/', [AppController, 'render']);
});
import UserRouter from '../user/UserRouter';
export default composeRouter((r) => {
r.mountRouter('/users', UserRouter);
});

Router yang dibuat dengan composeRouter dapat dipanggil dengan prefix string saat melakukan mount di defineBootstrap:

import UserRouter from './modules/user/UserRouter';
defineBootstrap(async (app) => {
app.mount(UserRouter('/user'));
});

Kamu bisa menyuntikkan (inject) service ke dalam controller menggunakan r.mountService(). Service ini akan diteruskan ke factory function controller.

import { composeRouter } from 'gaman/compose';
import { AppService } from './services/AppService';
import AppController from './controllers/AppController';
export default composeRouter((r) => {
// Inject service
r.mountService({
appService: AppService(),
});
r.get('/', [AppController, 'render']);
});

Semua method route mengembalikan RouteDefinition yang mendukung chaining:

r.post('/users', [UserController, 'Create'])
.middleware(AuthMiddleware())
.middleware(ValidateMiddleware())
.exception(CustomErrorHandler)
.name('users.create');