Licence
MIT
Version
0.2.8
Deps
1
Size
197 kB
Vulns
0
Weekly
0
@flexstore/core
Framework-agnostic FlexStore sync engine for browsers.
Repository: github.com/flexstoresync/flexstore-core
Data flow
flowchart TB
subgraph App["Your UI"]
UI[React / Vue / Angular / vanilla]
end
subgraph Core["@flexstore/core"]
CLIENT[SyncClient]
SCHED[Scheduler]
TRANS[Transport]
CLIENT --> SCHED
SCHED --> TRANS
end
subgraph Local["Browser local store default"]
SQL[SQLite WASM]
IDB[(IndexedDB\ndatabase file)]
SQL --> IDB
end
subgraph Remote["flexstoresync server"]
API[Sync API]
LEDGER[(Ledger)]
API <--> LEDGER
end
UI <-->|create / query / subscribe| CLIENT
CLIENT <-->|upsert / pending / cursors| SQL
TRANS <-->|push / pull / check-deltas| API
Write path (offline-first):
sequenceDiagram
participant UI as App UI
participant SC as SyncClient
participant DB as SqliteStore
participant IDB as IndexedDB
participant API as Sync API
UI->>SC: create / update / remove
SC->>DB: upsert row + sync_status
DB->>IDB: persist SQLite pages
SC-->>UI: immediate local read
Note over SC,API: background when online
SC->>API: check-deltas → push → pull
API-->>SC: remote changes
SC->>DB: apply pulled rows
SC-->>UI: subscribe callback
npm install @flexstore/core @journeyapps/wa-sqlite@journeyapps/wa-sqlite is a direct dependency of core but must be resolvable by your bundler (Vite/Webpack) for the WASM module.
Vite
// vite.config.ts — allow WASM + wa-sqlite subpaths
export default defineConfig({
optimizeDeps: {
exclude: ['@journeyapps/wa-sqlite', '@flexstore/core'],
},
});Quick start
import { createSyncClient, defineResource, resourceRegistry } from '@flexstore/core';
const todos = defineResource({
name: 'todos',
attributes: { title: 'string', done: 'boolean' },
});
const client = createSyncClient({
baseUrl: 'http://localhost:8088',
apiKey: 'my-key',
tenantId: 'my-tenant',
resources: resourceRegistry(todos),
// store: default SqliteStore (SQLite WASM → IndexedDB)
});
await client.start();
await client.create('todos', { title: 'Buy milk', done: false });
const open = await client.query('todos', { done: false });Store adapters
| Adapter | Export | When |
|---|---|---|
| SQLite WASM (default) | SqliteStore |
Production — SQL surface, IDB-backed file |
| Legacy document store | IndexedDbStore |
Migration / debugging only |
import { createSyncClient, IndexedDbStore } from '@flexstore/core';
createSyncClient({
...config,
store: new IndexedDbStore(['todos'], 'flexstore-legacy'),
});Implement FlexStoreAdapter (see index.d.ts) for React Native, Node, etc.
Pub/sub + fallback polling
When pubsubUrl is set, the client subscribes to SSE sync hints for near-real-time pulls. A background check-deltas timer still runs as a safety net:
| Mode | Config | Default |
|---|---|---|
| Pub/sub connected | pubsubFallbackPollMs / pollIntervalConnectedMs |
60s |
| Pub/sub down / off | pollIntervalDisconnectedMs |
4s |
createSyncClient({
baseUrl: 'http://localhost:8088',
pubsubUrl: 'http://localhost:8090',
pubsubFallbackPollMs: 60_000, // or 0 for hints-only while connected
pollIntervalDisconnectedMs: 4_000,
// ...
});useSyncStatus() / client.status expose pollIntervalMs (active timer) and pubsubFallbackPollMs (configured fallback).
Framework wrappers
| Package | Repo |
|---|---|
@flexstore/react |
flexstore-react |
@flexstore/vue |
flexstore-vue (composables) |
| Angular | Use createSyncClient + inject a singleton service (see packages/angular in monorepo) |
Related
| Repo | Role |
|---|---|
| flexstore-self-host | Docker sync server |
| flexstore | Monorepo + design docs |
License
MIT — see LICENSE.