# ADR 0002: Ekstraksi Shared Packages (@keluargamart/*) - **Status**: Diterima (Accepted) - **Tanggal**: 17 Oktober 2026 - **Penulis**: Principal Software Architect & Fullstack Lead --- ## Konteks & Masalah Sebelum migrasi, setiap frontend mengelola kontrak API, permission, dan fungsi utilitas secara terpisah: - `apps/erp`, `apps/pos`, dan `apps/b2b` masing-masing memiliki copy file `backendRoutes.txt`. - `apps/erp` memiliki file `backendPermissions.txt` yang sudah tertinggal 1 permission dibanding backend Go (`hr.leaves.store.any`). - Fungsi utilitas pemformatan Rupiah (`formatRupiah`, `formatIDR`, `parseMoney`) dan pembuatan token idempotency ditulis ulang di 3 tempat berbeda dengan sedikit variasi implementasi. - Wrapper Axios dikonfigurasi ulang secara independen di setiap project dengan penanganan error yang tidak seragam. --- ## Keputusan Kami memutuskan untuk mengekstrak kode-kode bersama tersebut ke dalam empat **Shared Packages** di direktori `packages/*`: 1. **`@keluargamart/contracts`**: - Berisi daftar 368 canonical API routes dari `openapi.yaml`. - Menyediakan `src/routes.js`, `src/routes.d.ts`, dan file teks `src/routes.txt`. - Menggantikan seluruh `backendRoutes.txt` di ERP, POS, dan B2B. 2. **`@keluargamart/permissions`**: - Berisi 198 permission RBAC yang diekstrak langsung dari `catalog.go` backend. - Menyediakan fungsi evaluasi otorisasi terstandarisasi: `can(permissions, requiredPermission, role)` dan `isSuperAdmin(role)`. - Menyediakan TypeScript definition (`index.d.ts`) untuk autocomplete IDE. 3. **`@keluargamart/utils`**: - Berisi fungsi utilitas bisnis teruji: `formatRupiah`, `formatIDR`, `formatNumber`, `parseMoney`, `formatDate`, dan `newIdempotencyKey`. 4. **`@keluargamart/api-client`**: - Mengemas Axios dengan kelas error kustom `ApiError` (`status`, `code`, `message`, `details`). - Menyediakan request dan response interceptors standar untuk inject token dan handling response unifikasi. ### Dukungan Polyglot Frontend (JS & TS) Shared packages dibangun menggunakan JavaScript murni (ESM) dengan file pendamping TypeScript Declaration (`.d.ts`). Keputusan ini memastikan: - Konsumer yang ditulis dengan JavaScript murni (seperti ERP dan POS) dapat mengonsumsi package tanpa perlu step kompilasi build bundler tambahan. - Konsumer yang ditulis dengan TypeScript (seperti B2B / Nuxt) mendapatkan static typechecking dan intellisense penuh. --- ## Konsekuensi ### Konsekuensi Positif - **Zero Drift**: Seluruh rute dan permission disinkronkan melalui automated CI drift guard (`scripts/check-drift.py`). - **DRY (Don't Repeat Yourself)**: Eliminasi lebih dari 1.200 baris kode duplikasi di frontend. - **Konsistensi UI**: Format mata uang, angka, dan tanggal di POS, ERP, dan B2B dijamin seragam. - **Standar Error Handling**: Semua frontend menangani error backend dengan struktur payload yang sama (`ApiError`). ### Konsekuensi Negatif - Perubahan pada shared package dapat memengaruhi seluruh aplikasi consumer. (Mitigasi: Turborepo menjalankan pengujian seluruh consumer saat package diubah).