pulse-rn
v1.0.1
Published
Powerful offline-first sync engine for React Native. Compatible with Django Pulse and future Node.js pulse-core.
Maintainers
Readme
pulse-rn
A lightweight offline-first synchronization engine for React Native/Expo applications. Provides real-time data synchronization between local SQLite database and remote server through WebSocket connections with conflict resolution and delta sync capabilities. It needs a backend server with the django-pulse library to work with. If this is library is well received, I will add more features to it and others backends support.
Features
- Offline-first architecture: Local SQLite database with automatic sync when online
- Real-time synchronization: WebSocket-based bidirectional sync
- Conflict resolution: Version-based conflict handling with server authority
- Delta sync: Only sync changes since last sync to minimize bandwidth
- Batch operations: Efficient batching of local changes
- TypeScript support: Full TypeScript implementation with type safety
- React Query integration: Seamless integration with TanStack Query
Installation
npm install pulse-rn expo-sqlite expo-crypto @tanstack/react-queryConfiguration
PulseProvider Setup
import { PulseProvider } from 'pulse-rn';
function App() {
return (
<PulseProvider
config={{
baseUrl: 'localhost:8000',
userId: 1,
tablesConfig: {
items: ['id', 'name', 'description', 'version', 'is_deleted'],
users: ['id', 'name', 'email', 'version', 'is_deleted']
}
}}
>
{/* Your app components */}
</PulseProvider>
);
}Configuration Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| baseUrl | string | WebSocket server base URL |
| userId | number | Current user identifier |
| tablesConfig | Record<string, string[]> | Table schema definitions |
API Reference
Hooks
useSyncTable
React hook for querying synchronized table data.
import { useSyncTable } from 'pulse-rn';
function ItemsList() {
const { data: items, isLoading, error } = useSyncTable('items');
if (isLoading) return <Text>Loading...</Text>;
if (error) return <Text>Error: {error.message}</Text>;
return (
<FlatList
data={items}
renderItem={({ item }) => <Text>{item.name}</Text>}
/>
);
}| Parameter | Type | Description |
|-----------|------|-------------|
| tableName | string | Name of the table to query |
Returns: Query object with data, isLoading, error properties filtered by is_deleted = 0
Functions
createItem
Creates a new record with automatic sync ID generation.
import { createItem } from 'pulse-rn';
import { useQueryClient } from '@tanstack/react-query';
function CreateItemForm() {
const queryClient = useQueryClient();
const handleCreate = () => {
createItem('items', {
name: 'New Item',
description: 'Item description'
}, queryClient);
};
return <Button title="Create Item" onPress={handleCreate} />;
}| Parameter | Type | Description |
|-----------|------|-------------|
| tableName | string | Target table name |
| data | object | Record data to insert |
| queryClient | QueryClient | TanStack Query client instance |
Behavior: Generates UUID sync_id, sets version = 0, marks is_local_only = 1
updateItem
Updates an existing record and queues for synchronization.
import { updateItem } from 'pulse-rn';
function UpdateItem({ item }) {
const queryClient = useQueryClient();
const handleUpdate = () => {
updateItem('items', item.sync_id, {
name: 'Updated Name',
description: 'Updated description'
}, queryClient);
};
return <Button title="Update" onPress={handleUpdate} />;
}| Parameter | Type | Description |
|-----------|------|-------------|
| tableName | string | Target table name |
| sync_id | string | Record synchronization identifier |
| data | object | Fields to update |
| queryClient | QueryClient | TanStack Query client instance |
Behavior: Updates specific fields, marks is_local_only = 1, resets sync_error
deleteItem
Performs logical deletion of a record.
import { deleteItem } from 'pulse-rn';
function DeleteItem({ item }) {
const queryClient = useQueryClient();
const handleDelete = () => {
deleteItem('items', item.sync_id, queryClient);
};
return <Button title="Delete" onPress={handleDelete} />;
}| Parameter | Type | Description |
|-----------|------|-------------|
| tableName | string | Target table name |
| sync_id | string | Record synchronization identifier |
| queryClient | QueryClient | TanStack Query client instance |
Behavior: Sets is_deleted = 1 (logical deletion)
Synchronization Logic
Batching System
Local changes are batched and sent to the server every 2 seconds to optimize network usage:
- Accumulates create/update/delete operations
- Sends batches of up to 50 records per request
- Automatic retry on connection failure
Delta Sync
When connecting to the server, pulse-rn requests only changes since the last synchronization:
{
type: 'SYNC_REQUEST_DELTA',
table: 'items',
last_version: 42
}- Tracks maximum local version per table
- Only requests records with version > max_local_version
- Minimizes bandwidth usage
Conflict Resolution
Version-based conflict resolution with server authority:
- Client operations increment version numbers
- Server validates and applies changes with final authority
- Conflicts resolved by server version precedence
- Failed operations marked with
sync_errorfield
Connection Management
- Automatic reconnection with 3-second backoff
- WebSocket connection state management
- Graceful handling of network interruptions
WebSocket Protocol
Message Types
| Type | Description |
|-------|-------------|
| SYNC_BATCH_UPLOAD | Batch of local changes |
| SYNC_REQUEST_DELTA | Request changes since version |
| BATCH_ACK | Batch processing acknowledgment |
| SYNC_ACK_INDIVIDUAL | Individual operation result |
| SYNC_UPDATE | Real-time data updates |
Error Handling
- Network errors trigger automatic reconnection
- Failed operations stored with error messages
- Sync queue preserved across app restarts
- Graceful degradation when offline
