Services
Service di GamanJS adalah tempat untuk business logic aplikasi. Service dibuat dengan composeService dan tidak bergantung pada HTTP layer — murni logic.
Membuat Service
Section titled “Membuat Service”Pola yang direkomendasikan adalah meng-export instance service sebagai konstanta dan meng-export tipe kembaliannya (return type) untuk memudahkan dependency injection di controller.
import { composeService } from 'gaman/compose';import type { RT } from 'gaman/types';
export const AppService = composeService(() => { /** * Kamu bisa meletakkan logika private, state, atau koneksi database di sini */
return { WelcomeMessage() { return '❤️ Welcome to GamanJS'; }, };});
// Export tipe kembalian dari serviceexport type AppService = RT<typeof AppService>;Contoh: User Service
Section titled “Contoh: User Service”import { composeService } from 'gaman/compose';import type { RT } from 'gaman/types';
interface User { id: number; name: string; email: string;}
const users: User[] = [ { id: 1, name: 'Angga', email: 'angga@example.com' },];
export const UserService = composeService(() => { return { findAll(): User[] { return users; },
findById(id: number): User | undefined { return users.find((u) => u.id === id); },
create(data: Omit<User, 'id'>): User { const newUser = { ...data, id: users.length + 1 }; users.push(newUser); return newUser; }, };});
export type UserService = RT<typeof UserService>;Service dengan Dependency
Section titled “Service dengan Dependency”Service juga bisa menerima dependency dari service lain:
import { composeService } from 'gaman/compose';import type { RT } from 'gaman/types';import { EmailService } from './EmailService';
export const AuthService = composeService( (emailService: RT<typeof EmailService> = EmailService()) => { return { register(name: string, email: string) { // ... logika pendaftaran emailService.sendWelcome(email); return { name, email }; }, }; });
export type AuthService = RT<typeof AuthService>;Menggunakan di Controller
Section titled “Menggunakan di Controller”Saat menggunakan service di controller, gunakan pola destrukturisasi yang direkomendasikan dengan tipe Deps.
import { composeController } from 'gaman/compose';import { UserService } from '../services/UserService';
export type Deps = { userService: UserService;};
export default composeController(({ userService }: Deps) => ({ GetAll(ctx) { const users = userService.findAll(); return ctx.send(users).ok(); },}));- Service tidak memiliki akses ke
ctx— ini disengaja agar logic tidak bergantung pada HTTP. - Satu service bisa dipakai oleh banyak controller.
- Service bisa saling bergantung satu sama lain.
- Gunakan
export type Name = RT<typeof Name>agar DI menjadi bersih dan type-safe. - Pisahkan concern: Service = business logic, Controller = HTTP handling.