StoreOptions
Advanced configuration options for the Store.
Import
import type { StoreOptions } from '@gluonic/client'Type Definition
Complete interface from implementation:
export type StoreOptions = {
// Debugging
debug?: boolean
// Authentication
onUnauthenticated?: () => void | Promise<void>
// Transformation
transformByModel?: Record<string, (op: 'i'|'u'|'d', payload: Record<string, any>) => Record<string, any>>
// Sync adapters
downsync?: DownsyncAdapter
realtime?: RealtimeAdapter
// Instrumentation callbacks
logger?: {
debug?: (...a: any[]) => void
info?: (...a: any[]) => void
warn?: (...a: any[]) => void
error?: (...a: any[]) => void
}
onFrameApplied?: (info: { count: number, minSid?: number, maxSid?: number, ms: number }) => void
onReconnect?: (info: { attempt: number, backoffMs: number }) => void
onQueueResult?: (info: { id: string, result: 'ok'|'permanent'|'retry' }) => void
// Performance
applyChunkSize?: number
}Total: 10 configuration options. All are optional - Store works with defaults.
Options Reference
debug
debug?: booleanDefault: false
Description: Enable debug logging to console.
Example:
const client = SyncClient({
server,
storage,
models,
performance: {
debug: true // Logs all sync operations
}
})onUnauthenticated
onUnauthenticated?: () => void | Promise<void>Description: Callback when server returns 401/403 (unauthenticated).
Use case: Redirect to login, clear tokens, show auth dialog
Example:
const client = SyncClient({
server,
storage,
models,
auth: {
onUnauthenticated: () => {
// Clear token
localStorage.removeItem('token')
// Redirect to login
router.push('/login')
}
}
})transformByModel
transformByModel?: Record<string, (
op: 'i'|'u'|'d',
payload: Record<string, any>
) => Record<string, any>>Description: Transform data before storing in pool (per model type).
Use case: Data normalization, field mapping, computed fields
Example:
const client = SyncClient({
server,
storage,
models,
transformByModel: {
task: (op, payload) => {
// Add computed field
return {
...payload,
displayTitle: payload.title?.toUpperCase()
}
},
user: (op, payload) => {
// Normalize email
return {
...payload,
email: payload.email?.toLowerCase()
}
}
}
})downsync
downsync?: DownsyncAdapterDescription: Custom adapter for delta sync and bootstrap.
Default: HTTP adapter created from server URL
Example:
const client = SyncClient({
server,
storage,
models,
downsync: {
fetchDelta: async (since, token, onUnauthenticated) => {
// Custom delta sync implementation
},
fetchBootstrap: async (token, onUnauthenticated) => {
// Custom bootstrap implementation
}
}
})See: DownsyncAdapter
realtime
realtime?: RealtimeAdapterDescription: Custom adapter for WebSocket real-time updates.
Default: WebSocket adapter created from server URL
Example:
const client = SyncClient({
server,
storage,
models,
realtime: {
connect: (token, onFrames, onError, onClose) => {
// Custom WebSocket implementation
const ws = new WebSocket('wss://custom.com/ws')
// ...
return { close: () => ws.close() }
}
}
})See: RealtimeAdapter
logger
logger?: {
debug?: (...a: any[]) => void
info?: (...a: any[]) => void
warn?: (...a: any[]) => void
error?: (...a: any[]) => void
}Description: Custom logging functions for sync operations.
Default: No logging (silent)
Example:
import * as Sentry from '@sentry/react'
const client = SyncClient({
server,
storage,
models,
logger: {
debug: (...args) => console.debug('[Gluonic]', ...args),
info: (...args) => console.info('[Gluonic]', ...args),
warn: (...args) => console.warn('[Gluonic]', ...args),
error: (...args) => {
console.error('[Gluonic]', ...args)
Sentry.captureException(new Error(args.join(' ')))
}
}
})onFrameApplied
onFrameApplied?: (info: {
count: number
minSid?: number
maxSid?: number
ms: number
}) => voidDescription: Callback after applying sync frames (for monitoring).
Info object:
count- Number of frames appliedminSid- Lowest sync ID in batchmaxSid- Highest sync ID in batchms- Time taken to apply (milliseconds)
Example:
const client = SyncClient({
server,
storage,
models,
onFrameApplied: (info) => {
console.log(`Applied ${info.count} frames in ${info.ms}ms`)
// Track performance
analytics.track('sync_frames_applied', {
count: info.count,
duration_ms: info.ms,
sync_range: `${info.minSid}-${info.maxSid}`
})
}
})onReconnect
onReconnect?: (info: {
attempt: number
backoffMs: number
}) => voidDescription: Callback when WebSocket reconnects (for monitoring).
Info object:
attempt- Reconnect attempt number (1, 2, 3…)backoffMs- Backoff delay in milliseconds
Example:
const client = SyncClient({
server,
storage,
models,
onReconnect: (info) => {
console.log(`Reconnect attempt ${info.attempt}, waiting ${info.backoffMs}ms`)
if (info.attempt > 5) {
toast.error('Connection unstable, please check your network')
}
}
})onQueueResult
onQueueResult?: (info: {
id: string
result: 'ok'|'permanent'|'retry'
}) => voidDescription: Callback when transaction queue item is processed.
Info object:
id- Transaction IDresult- Processing result:'ok'- Successfully confirmed by server'permanent'- Permanent failure (won’t retry)'retry'- Temporary failure (will retry)
Example:
const client = SyncClient({
server,
storage,
models,
onQueueResult: (info) => {
if (info.result === 'permanent') {
console.error(`Transaction ${info.id} failed permanently`)
toast.error('Failed to sync changes')
} else if (info.result === 'retry') {
console.warn(`Transaction ${info.id} will retry`)
}
}
})applyChunkSize
applyChunkSize?: numberDefault: 100
Description: Number of frames to process in each chunk (for performance).
Use case:
- Large syncs with thousands of frames
- Prevents UI blocking
- Allows UI updates between chunks
Example:
const client = SyncClient({
server,
storage,
models,
performance: {
applyChunkSize: 500 // Process 500 frames at a time
}
})Performance:
- Lower value (50): More responsive UI, slower total sync
- Higher value (1000): Faster total sync, longer UI blocks
- Default (100): Good balance
Usage
In SyncClient
StoreOptions are passed through SyncClient config:
const client = SyncClient({
server: 'https://api.example.com/sync/v1',
storage: DrizzleAdapter({ db }),
models: [Task, User],
// StoreOptions
auth: {
onUnauthenticated: () => router.push('/login')
},
performance: {
debug: true,
applyChunkSize: 500
},
downsync: customDownsyncAdapter,
realtime: customRealtimeAdapter,
logger: customLogger,
onFrameApplied: (info) => trackPerformance(info),
onReconnect: (info) => handleReconnect(info),
onQueueResult: (info) => handleQueueResult(info)
})Complete Example
import { SyncClient } from '@gluonic/client'
import { DrizzleAdapter } from '@gluonic/client-drizzle'
import * as Sentry from '@sentry/react'
const client = SyncClient({
server: 'https://api.example.com/sync/v1',
storage: DrizzleAdapter({ db }),
models: [Task, User, Project],
// Authentication
auth: {
onUnauthenticated: () => {
localStorage.removeItem('token')
window.location.href = '/login'
}
},
// Performance
performance: {
debug: process.env.NODE_ENV === 'development',
applyChunkSize: 500
},
// Logging
logger: {
error: (...args) => {
console.error('[Gluonic]', ...args)
Sentry.captureException(new Error(args.join(' ')))
},
warn: (...args) => console.warn('[Gluonic]', ...args),
info: (...args) => console.info('[Gluonic]', ...args),
debug: (...args) => console.debug('[Gluonic]', ...args)
},
// Monitoring
onFrameApplied: (info) => {
analytics.track('sync_frames', {
count: info.count,
duration_ms: info.ms
})
},
onReconnect: (info) => {
if (info.attempt > 3) {
toast.warning('Connection unstable')
}
},
onQueueResult: (info) => {
if (info.result === 'permanent') {
Sentry.captureMessage(`Transaction failed: ${info.id}`)
}
}
})See Also
- SyncClient - Client factory
- DownsyncAdapter - Delta sync adapter
- RealtimeAdapter - WebSocket adapter
- Store - Store class