Data & Sync
Local-first IndexedDB store with CRUD, live queries, and Background Sync.
Local-First Store
IDB-backed collection with CRUD, reactive queries, and automatic Background Sync queuing.
No items
import { effect, enhance } from 'weblisk'; import { collection } from 'weblisk/data/store.js'; enhance('#demo-store', (el, { $ }) => { const todos = collection('demo-todos'); const live = todos.live(); let itemNum = 0; effect(() => { const items = live(); if (items.length === 0) { $('#output-store').textContent = 'No items'; } else { $('#output-store').textContent = items .map(i => `• ${i.text}`) .join('\n'); } }); $('#btn-store-add').addEventListener('click', async () => { itemNum++; await todos.put({ text: `Task #${itemNum} — ${new Date().toLocaleTimeString()}` }); }); $('#btn-store-clear').addEventListener('click', async () => { const all = await todos.getAll(); for (const item of all) await todos.delete(item.id); }); });
Sync Status
Reactive sync status, pending mutation count, and manual sync trigger.
Checking...
import { effect, enhance } from 'weblisk'; import { syncStatus, pendingCount, countPending, triggerSync } from 'weblisk/pwa/offline.js'; enhance('#demo-sync-status', (el, { $ }) => { effect(() => { const status = syncStatus(); const pending = pendingCount(); $('#output-sync-status').textContent = `Sync Status: ${status}\nPending: ${pending} mutation(s)\n` + '\nMutations queue via Background Sync.\n' + 'SW replays them when connectivity returns.'; }); $('#btn-sync-trigger').addEventListener('click', async () => { await triggerSync(); }); $('#btn-sync-count').addEventListener('click', async () => { const count = await countPending(); $('#output-sync-status').textContent = `Pending mutations: ${count}`; }); });