Offline-First Data Sync Library
A robust, TypeScript-based library for managing offline-first data synchronization in web applications. This library provides seamless data persistence and synchronization capabilities, ensuring your application works flawlessly regardless of network connectivity.

🚀 Features
📋 Prerequisites
Node.js >= 14.0.0
npm >= 6.0.0
🔧 Installation
npm install offline-data-sync
🚦 Quick Start
import { SyncManager } from "offline-data-sync";
class TodoApiAdapter implements ApiAdapter {
constructor(private baseUrl: string) {
this.apiUrl = baseUrl.replace(/\/$/, "");
}
async create(record: SyncRecord): Promise<Response> {
return fetch(`${this.apiUrl}/${record.id}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"If-Match": record.version?.toString() || "*",
},
body: JSON.stringify(record.data),
});
}
}
const syncManager = new SyncManager({
storeName: "todos",
apiAdapter: new TodoApiAdapter("http://localhost:3001/api/todos"),
conflictResolution: "server-wins",
batchSize: 50,
});
await syncManager.create({
title: "New Todo",
completed: false,
});
await syncManager.update("todo-id", {
title: "Updated Todo",
completed: true,
});
await syncManager.delete("todo-id");
const records = await syncManager.getProcessedRecords();
syncManager.onSyncStatusChange((status) => {
console.log("Sync status:", status);
});
⚙️ Configuration
interface SyncConfig {
storeName: string;
primaryKey?: string;
syncEndpoint?: string;
apiAdapter?: ApiAdapter;
conflictResolution?:
| "client-wins"
| "server-wins"
| "manual"
| "last-write-wins"
| "merge";
batchSize?: number;
maxRetries?: number;
retryDelay?: number;
mergeStrategy?: (clientData: any, serverData: any) => any;
}
interface ApiAdapter {
create(record: SyncRecord): Promise<Response>;
update(record: SyncRecord): Promise<Response>;
delete(record: SyncRecord): Promise<Response>;
handleResponse(response: Response): Promise<Record<string, unknown> | null>;
}
🔄 Conflict Resolution
Server Wins (Default)
const syncManager = new SyncManager({
conflictResolution: "server-wins",
});
Client Wins
const syncManager = new SyncManager({
conflictResolution: "client-wins",
});
Manual Resolution
const syncManager = new SyncManager({
conflictResolution: "manual",
});
await syncManager.resolveConflict(
"record-id",
"accept-server",
customData
);
🔌 Offline Behavior
- Records are immediately updated in IndexedDB
- UI reflects changes instantly
- Changes are queued for sync when online
- Deletions are handled gracefully
- Conflicts are detected and resolved on sync
🛠 Development
npm install
npm run build
cd example/ods-sample-app
npm install
npm run dev
cd example/test-server
npm install
npm run dev
📚 API Reference
SyncManager Methods
class SyncManager {
async create(data: any): Promise<void>;
async update(id: string, data: any): Promise<void>;
async delete(id: string): Promise<void>;
async get(id: string): Promise<SyncRecord>;
async getAll(): Promise<SyncRecord[]>;
async getProcessedRecords(): Promise<any[]>;
async resolveConflict(
id: string,
resolution: string,
customData?: any
): Promise<void>;
onSyncStatusChange(callback: (status: SyncStatus) => void): () => void;
}
🔒 Security
- Secure local data storage using IndexedDB
- Version control with ETags
- Data integrity validation
- Protected sync operations
- Conflict detection and resolution
📈 Performance
- Efficient batch processing
- Optimized IndexedDB operations
- Minimal memory footprint
- Smart conflict resolution
- Background sync operations