DataContainer — Changelog
v0.4.0 (2026-06-24)
TL;DR
Perubahan:
- 🔥 Breaking:
PageConfigrestrukturisasi —perPage,isFrontEndPreferCursor, danpaginationModedihapus, digantisetup: PageSetup | null(Breaking) - 🔥 Breaking:
PaginationIntent.preferCursordihapus (Breaking) - ✨ New:
declarePagination()— deklarasi intent pagination frontend secara eksplisit (Medium) - ✨ New:
submitSearch()— set search dan reset pagination ke halaman 1 dalam satu panggilan (Medium) - 🔧 Improved:
mapFromResponsetidak lagi override mode atauperPagejikapage.setupsudah di-set (Medium) - 🐛 Fixed: deteksi mode
'simple'salah terdeteksi sebagai'cursor'saat backend mengirimnext_cursor: null(Low)
Impact: 🔴 Breaking: 2 | ✨ New: 2 | 🟢 Medium: 2 | 🔵 Low: 1
Backward Compatible: ❌ Tidak
🔴 Breaking Changes
PageConfig: perPage, isFrontEndPreferCursor, dan paginationMode dihapus, setup ditambahkan
page.perPage, page.isFrontEndPreferCursor, dan page.paginationMode tidak lagi ada di PageConfig. Ketiganya digantikan oleh field baru page.setup: PageSetup | null yang menjadi satu-satunya sumber konfigurasi dan mode pagination. Mode dibaca via page.setup?.mode.
// Before (v0.3.x) - Tidak berlaku lagi
container.page.perPage = 15;
container.page.isFrontEndPreferCursor = true;
// After (v0.4.0)
container.declarePagination({ mode: 'cursor', perPage: 15 });
// atau lewat QueryIntent saat konstruksi
useDataContainer(filter, { pagination: { mode: 'cursor', perPage: 15 } });Fix:
- Ganti
page.paginationMode→page.setup?.mode - Ganti
page.perPage→page.setup?.perPageuntuk membaca,declarePagination()untuk menulis - Hapus semua akses ke
page.isFrontEndPreferCursor— gunakandeclarePagination({ mode: 'cursor' })sebagai gantinya - Update type annotation yang referensi
PageConfigsecara langsung
Affected: Semua code yang membaca atau menulis page.paginationMode, page.perPage, atau page.isFrontEndPreferCursor.
PaginationIntent.preferCursor dihapus
Field preferCursor pada PaginationIntent (QueryIntent) tidak lagi tersedia.
// Before (v0.3.x) - Tidak berlaku lagi
useDataContainer(filter, {
pagination: { mode: 'lengthAware', preferCursor: true }
});
// After (v0.4.0) - set mode secara eksplisit
useDataContainer(filter, {
pagination: { mode: 'cursor' }
});Fix: Hapus preferCursor dari semua QueryIntent, set mode: 'cursor' secara langsung.
✨ New
declarePagination()
Method baru declarePagination({ mode, perPage? }) untuk mendeklarasikan intent pagination frontend setelah konstruksi. Ini adalah satu-satunya cara yang diizinkan untuk menulis page.setup post-construct — page.setup bersifat convention-immutable dan tidak boleh diubah langsung atau lewat setPage().
Poin utama:
- Set
page.setupdanpage.paginationModesekaligus — efektif segera untuk URL generation - Harus dipanggil sebelum fetch pertama jika tidak menggunakan QueryIntent
perPageopsional — jika tidak di-set, perPage tidak dikirim ke backend (backend gunakan default-nya)
Lihat: declarePagination()
🟢 Medium Impact
Peningkatan:
mapFromResponseviaapplyResponsePaginationkini membacapage.setupsebelum memproses response. Jikasetupsudah di-set: mode tidak di-detect ulang dari response,perPagetidak ditimpa, hanya field state (cursor, page number, total, hasMore) yang diupdate. Jikasetupnull: perilaku lama (auto-detect dari response).
New:
submitSearch(value?)menggabungkan update nilai search dan reset pagination ke halaman 1 dalam satu panggilan. Sebelumnya, setcontainer.searchsecara langsung tidak mereset halaman, sehingga user yang sedang di halaman X bisa mendapat nol hasil saat search baru tidak mencapai halaman tersebut. Resetpage.numeric.currentke1danpage.cursor.directionke'next'secara otomatis. Settercontainer.searchtetap berfungsi untuk bindingv-model.
🔵 Low Impact
Bug Fixes:
- Fix deteksi pagination mode
'simple': sebelumnya salah terdeteksi sebagai'cursor'saat backend mengirimnext_cursor: nulldanprevious_cursor: nullsecara eksplisit (seperti pola laresponse). Deteksi kini mengecek nilai truthy, bukan hanya keberadaan key.
v0.3.1 (2026-04-22)
TL;DR
Perubahan:
- 🔥 Breaking:
sort.sortDirberubah dari'a'/'d'menjadi'asc'/'desc'(Breaking) — nilai yang tersimpan sekarang selalu longform - ✨ New:
setSortAsc()dansetSortDesc()(Medium) — Shorthand eksplisit untuk set sort direction - 🔧 Improved:
SortDirectiontype + normalisasisetSort()(Medium) — Input fleksibel, output konsisten - 🔵 Low:
'regular'alias untukPaginationIntent.mode(Low) — Alternatif dari'lengthAware'
Impact: 🔴 Breaking: 1 | ✨ New: 1 | 🟢 Medium: 1 | 🔵 Low: 1
Backward Compatible: ❌ Tidak
🔴 Breaking Changes
sort.sortDir: nilai berubah dari 'a'/'d' menjadi 'asc'/'desc'
sort.sortDir kini selalu disimpan dalam format panjang. Sebelumnya nilai yang tersimpan adalah shorthand 'a' atau 'd'. URL params tidak berubah — sortDir di URL sudah 'asc'/'desc' sejak sebelumnya.
// Before (v0.3.0) - Tidak berlaku lagi
container.sort.sortDir === 'a'
// After (v0.3.1) - Wajib longform
container.sort.sortDir === 'asc'Fix:
- Search & replace
sort.sortDir === 'a'→sort.sortDir === 'asc' - Search & replace
sort.sortDir === 'd'→sort.sortDir === 'desc' - Update pola toggle:
container.setSort(field, container.sort.sortDir === 'asc' ? 'desc' : 'asc')— atau gunakansetSortAsc/setSortDesc
Affected: Semua code yang membaca sort.sortDir untuk conditional logic atau toggle direction.
✨ New
setSortAsc() dan setSortDesc()
Dua shorthand baru untuk set sort direction secara eksplisit tanpa harus pass direction string ke setSort(). Keduanya menerima optional parameter sortBy — jika di-pass, field sort juga ikut berubah; jika tidak, hanya direction yang berubah.
Poin utama:
setSortAsc(field?)— set ascending, opsional ganti fieldsetSortDesc(field?)— set descending, opsional ganti fieldsetSort()tetap tersedia dan tidak berubah
Lihat: Sort Methods
🟢 Medium Impact
Peningkatan:
setSort()sekarang menerima 6 format input viaSortDirection:'a','asc',1,'d','desc',-1— auto-normalisasi ke'asc'/'desc'sebelum disimpan
🔵 Low Impact
Perubahan:
PaginationIntent.modekini menerima'regular'sebagai alias'lengthAware'— dinormalisasi sebelum disimpan,page.paginationModetetap selalu'lengthAware'
v0.3.0 (2026-04-22)
TL;DR
Perubahan:
- ✨ New:
modifyFilter()(High) — Update beberapa key filter sekaligus tanpasetFilter()berulang - ✨ New:
isUsingFilter()(High) — Cek apakah applied filter berbeda dari initial filter - 🔧 Improved:
resetFilterToInit()danresetFilterToApplied()(Medium) — Sekarang support partial reset via parameterpaths - 🐛 Fixed:
reset()mutasi snapshot_lastData(Low) — Sekarang menggunakanstructuredCloneuntuk isolasi yang benar
Impact: ✨ New: 2 | 🟡 High: 2 | 🟢 Medium: 1 | 🔵 Low: 1
Backward Compatible: ✅ Ya
✨ New
modifyFilter()
Method baru modifyFilter(partial) memungkinkan update beberapa key filter sekaligus dengan menerima object partial — sebagai alternatif ergonomis dari memanggil setFilter() berkali-kali. Key yang tidak ada di partial tidak akan disentuh, sehingga aman untuk pre-fill sebagian field dari query params atau preset tertentu.
Poin utama:
- Update banyak key dalam satu panggilan
- Hanya key yang disertakan yang berubah
- Tetap di lapisan draft — perlu
applyFilter()setelahnya
Lihat: modifyFilter()
isUsingFilter()
Method baru yang mengembalikan true jika applied filter saat ini berbeda dari initial filter. Berbeda dengan hasUnappliedFilterChanges() yang membandingkan draft vs applied — isUsingFilter() membandingkan applied vs initial, cocok untuk conditional rendering indikator "filter aktif" atau tombol "Hapus Filter".
Poin utama:
- Deteksi apakah ada filter aktif yang sudah di-apply
- Cocok untuk badge indikator atau tombol reset filter
- Perbandingan terhadap
initialFilter, bukan draft
Lihat: isUsingFilter()
🟢 Medium Impact
Peningkatan:
resetFilterToInit()danresetFilterToApplied()sekarang menerima optional parameterpaths(string atau string[]) untuk reset sebagian field filter saja, bukan seluruh filter
🔵 Low Impact
Bug Fixes:
- Fix
reset(): snapshot_lastDatadimutasi saat restore — sekarang menggunakanstructuredCloneuntuk isolasi yang benar
v0.2.0 (2026-04-09)
TL;DR
Perubahan:
- 🔥 Breaking:
dataLength()menjadigetDataLength()(Breaking) — rename untuk konsistensi penamaan getter - ✨ New:
navigatePage(),nextPage(),prevPage()(High) — Kontrol navigasi halaman tanpa override seluruh object pagination - 📝 Docs: Inline docs untuk semua method (Low)
Impact: 🔴 Breaking: 1 | ✨ New: 1 | 🟡 High: 1 | 🔵 Low: 1
Backward Compatible: ❌ Tidak
🔴 Breaking Changes
dataLength() diubah menjadi getDataLength()
Rename untuk menyelaraskan konvensi penamaan getter di seluruh API.
// Before (v0.1.x) - Tidak berlaku lagi
container.dataLength()
// After (v0.2.0)
container.getDataLength()Fix: Search & replace semua container.dataLength() → container.getDataLength().
✨ New
navigatePage(), nextPage(), prevPage()
Tiga method baru untuk navigasi halaman tanpa harus override seluruh object pagination via setPage(). navigatePage(target) menerima number atau string 'next'/'prev'; nextPage() dan prevPage() adalah shorthand-nya.
Poin utama:
- Navigasi halaman tanpa menyentuh konfigurasi pagination lainnya
- Support numerik dan cursor pagination
nextPage()/prevPage()sebagai shorthand umum
Lihat: Pagination Methods
🔵 Low Impact
Perubahan:
- Inline JSDoc ditambahkan untuk semua method
v0.1.1 (2025-12-26)
TL;DR
Perubahan:
- 🔥 Breaking:
loadStatusberubah dariRefmenjadi getter/setter (Breaking) — tidak perlu.valuedi script - ✨ New: Parameter
queryIntent(High) — Initialize state dari URL/router untuk deep linking dan SSR - 🎨 Refactor: File structure reorganization (Low) —
types.tsdipindah ketypes/index.ts - 📦 Dependencies: Build scripts + rimraf (Low)
Impact: 🔴 Breaking: 1 | ✨ New: 1 | 🟡 High: 1 | 🔵 Low: 2
Backward Compatible: ❌ Tidak
🔴 Breaking Changes
loadStatus: Ref → getter/setter
Property loadStatus tidak lagi berupa Ref. Access di <script> berubah; di <template> tetap sama.
// Before (v0.1.0) - Tidak berlaku lagi
container.loadStatus.value = 0;
if (container.loadStatus.value === 1) { }
// After (v0.1.1)
container.loadStatus = 0;
if (container.loadStatus === 1) { }Fix:
- Search & replace semua
container.loadStatus.value→container.loadStatusdi<script>sections - Template code tidak perlu diubah
Affected: Semua code yang mengakses loadStatus di script setup.
✨ New
Parameter queryIntent
useDataContainer() sekarang menerima optional second parameter untuk initialize pagination, sort, dan search state dari URL query params atau router state. Memungkinkan deep linking, shareable URLs, dan SSR hydration tanpa fetch dua kali.
Poin utama:
- Initialize page, sort, dan search dari URL dalam satu panggilan
- Support semua pagination modes di QueryIntent
- Backward compatible — parameter optional
Lihat: QueryIntent dan Example 6
🔵 Low Impact
Perubahan:
- File structure:
src/types.tsdipindah kesrc/types/index.ts - Build scripts: tambah
clean,build:watch,preview - Dependency: tambah
rimraf@^6.1.2untuk cross-platform clean script