@velox/store Stable
Persistent reactive state backed by SQLite. In-memory reads are instant; writes survive app restarts.
Requires capability: "db"
Install
npm install @velox/storeSetup
Call initStore() once at app startup before any components render:
// src/main.ts
import { createApp } from 'veloxkit'
import { initStore } from '@velox/store'
import App from './App'
async function start() {
await initStore()
createApp({ component: App })
}
start()Define a store
// src/stores/settings.ts
import { createStore } from '@velox/store'
export const useSettings = createStore('settings', {
theme: 'dark',
fontSize: 14,
notifications: true,
})createStore(namespace, defaults) returns a React hook. The namespace is the SQLite partition key — use a unique string per store. The defaults object also determines which keys are valid.
Use in components
import { useSettings } from '../stores/settings'
import { Switch, Text, View } from 'veloxkit'
function SettingsScreen() {
const { state, set, hydrated } = useSettings()
if (!hydrated) return null // waiting for SQLite read on first mount
return (
<View style={{ padding: 24, gap: 16 }}>
<Switch
value={state.notifications}
onValueChange={(v) => set('notifications', v)}
label="Push notifications"
/>
<Text>Font size: {state.fontSize}</Text>
</View>
)
}API
initStore()
await initStore()Creates the velox_store SQLite table if it doesn't exist. Idempotent — safe to call multiple times.
createStore(namespace, defaults)
const useMyStore = createStore('my-namespace', { key: defaultValue, ... })Returns a React hook. Multiple calls with the same namespace return the same hook instance (singleton).
Hook return value
const { state, set, setMany, reset, hydrated } = useMyStore()| Field | Type | Description |
|---|---|---|
state | typeof defaults | Current state (in-memory, instant) |
set(key, value) | void | Update a single key synchronously; persists async |
setMany(patch) | void | Update multiple keys at once |
reset() | Promise<void> | Restore defaults and delete all persisted values |
hydrated | boolean | false until first SQLite read completes |
set updates in-memory state synchronously, triggering an immediate re-render. The SQLite write is async and fire-and-forget.
TypeScript
const useSettings = createStore('settings', {
theme: 'dark' as 'dark' | 'light',
fontSize: 14,
})
// typeof state inferred from defaults:
// { theme: 'dark' | 'light', fontSize: number }Multiple stores
export const useSettings = createStore('settings', { theme: 'dark', fontSize: 14 })
export const useEditor = createStore('editor', { wordWrap: true, tabSize: 2 })
export const useSync = createStore('sync', { lastSync: 0, enabled: false })Each namespace is independent — they share the same SQLite table but different partition keys.