synclayer 0.1.0-alpha.3 copy "synclayer: ^0.1.0-alpha.3" to clipboard
synclayer: ^0.1.0-alpha.3 copied to clipboard

A local-first sync SDK for Flutter with offline support, automatic conflict resolution, and real-time synchronization.

SyncLayer #

pub package

Build offline-first Flutter apps in minutes — Production-grade sync engine with automatic background synchronization and conflict resolution.

⚠️ ALPHA VERSION - Early release. APIs may change. See known limitations.


Why SyncLayer? #

Your users expect apps to work offline. But building sync is hard:

❌ Manual queue management
❌ Conflict resolution logic
❌ Network retry handling
❌ Version tracking

SyncLayer handles all of this for you.

// That's it. Your app now works offline.
await SyncLayer.init(
  SyncConfig(
    baseUrl: 'https://api.example.com',
    collections: ['todos'],
  ),
);

// Save works instantly (local-first)
await SyncLayer.collection('todos').save({
  'text': 'Buy groceries',
  'done': false,
});

// Auto-syncs in background when online
// Handles conflicts automatically
// Retries on failure

What You Get #

🚀 Local-First - Writes happen instantly to local storage
🔄 Auto-Sync - Background sync every 5 minutes (configurable)
📡 Offline Queue - Operations sync automatically when online
⚔️ Conflict Resolution - Last-write-wins, server-wins, or client-wins
🔌 Backend Agnostic - Works with REST, Firebase, Supabase, or custom backends
📦 Batch Operations - Save/delete multiple documents efficiently
👀 Reactive - Watch collections for real-time UI updates


Quick Start #

1. Add dependency #

dependencies:
  synclayer: ^0.1.0-alpha.2

2. Initialize #

import 'package:synclayer/synclayer.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  await SyncLayer.init(
    SyncConfig(
      baseUrl: 'https://api.example.com',
      syncInterval: Duration(minutes: 5),
      collections: ['todos', 'users'], // Collections to sync
    ),
  );
  
  runApp(MyApp());
}

3. Use it #

// Save (works offline)
final id = await SyncLayer.collection('todos').save({
  'text': 'Buy milk',
  'done': false,
});

// Get
final todo = await SyncLayer.collection('todos').get(id);

// Update (same as save with id)
await SyncLayer.collection('todos').save({
  'text': 'Buy milk',
  'done': true,
}, id: id);

// Delete
await SyncLayer.collection('todos').delete(id);

// Watch for changes (reactive UI)
StreamBuilder(
  stream: SyncLayer.collection('todos').watch(),
  builder: (context, snapshot) {
    final todos = snapshot.data ?? [];
    return ListView.builder(
      itemCount: todos.length,
      itemBuilder: (context, i) => Text(todos[i]['text']),
    );
  },
);

How It Works #

┌─────────────┐
│  Your App   │
└──────┬──────┘
       │ save()
       ▼
┌─────────────┐     ┌──────────────┐
│   SyncLayer │────▶│ Local Storage│  (Instant)
│             │     │    (Isar)    │
└──────┬──────┘     └──────────────┘
       │
       │ (Background)
       ▼
┌─────────────┐     ┌──────────────┐
│ Sync Engine │────▶│   Backend    │  (Auto-sync)
│   + Queue   │     │     API      │
└─────────────┘     └──────────────┘

Architecture:

  • SyncLayer - Main API (what you use)
  • Collections - Data abstraction (like tables)
  • SyncEngine - Background processor (handles sync)
  • Queue Manager - Retry logic and ordering
  • Conflict Resolver - Handles conflicts automatically

Example App #

See the Todo App example for a complete working app with:

  • Offline editing
  • Auto-sync when online
  • Conflict resolution
  • Real-time UI updates

Backend Integration #

SyncLayer works with any backend. You need two endpoints:

// Push: Receive changes from client
POST /sync/{collection}
Body: { recordId, data, version, updatedAt }

// Pull: Send changes to client
GET /sync/{collection}?since={timestamp}
Response: [{ recordId, data, version, updatedAt }]

See backend example for a complete Node.js implementation.

Works With #

  • ✅ REST APIs (built-in adapter)
  • ✅ Firebase (custom adapter)
  • ✅ Supabase (custom adapter)
  • ✅ GraphQL (custom adapter)
  • ✅ Any backend (implement SyncBackendAdapter)

Advanced Features #

Batch Operations #

// Save multiple
await SyncLayer.collection('todos').saveAll([
  {'text': 'Task 1'},
  {'text': 'Task 2'},
  {'text': 'Task 3'},
]);

// Delete multiple
await SyncLayer.collection('todos').deleteAll([id1, id2, id3]);

Manual Sync #

// Trigger sync immediately (e.g., pull-to-refresh)
await SyncLayer.syncNow();

Conflict Resolution #

await SyncLayer.init(
  SyncConfig(
    baseUrl: 'https://api.example.com',
    conflictStrategy: ConflictStrategy.lastWriteWins, // Default
    // or: ConflictStrategy.serverWins
    // or: ConflictStrategy.clientWins
  ),
);

Event Monitoring #

SyncLayerCore.instance.syncEngine.events.listen((event) {
  switch (event.type) {
    case SyncEventType.syncStarted:
      print('Sync started');
      break;
    case SyncEventType.syncCompleted:
      print('Sync completed');
      break;
    case SyncEventType.conflictDetected:
      print('Conflict in ${event.collectionName}');
      break;
  }
});

Known Limitations #

This is an alpha release. Known issues:

  • ⚠️ Pull sync requires explicit collections configuration
  • ⚠️ Example backend uses in-memory storage (not production-ready)
  • ⚠️ Limited production testing (2 of 10 validation tests completed)
  • ⚠️ Basic error handling and retry logic
  • ⚠️ No built-in authentication or encryption

See CHANGELOG for details.


Roadmap #

  • ❌ Complete production validation tests
  • ❌ Persistent backend example
  • ❌ Custom conflict resolvers
  • ❌ Encryption support
  • ❌ WebSocket support for real-time sync
  • ❌ Firebase/Supabase adapters
  • ❌ Pagination for large datasets

vs Other Solutions #

Feature SyncLayer Drift Firebase Supabase
Offline-first
Backend agnostic
Auto-sync
Conflict resolution
Queue management
Custom backend

SyncLayer = Drift's offline-first + Firebase's auto-sync + Your own backend


Contributing #

Issues and PRs welcome! See CONTRIBUTING.md.


License #

MIT License - see LICENSE file.


Support #


Made with ❤️ by Hostspica

10
likes
0
points
354
downloads

Publisher

verified publisherhostspica.com

Weekly Downloads

A local-first sync SDK for Flutter with offline support, automatic conflict resolution, and real-time synchronization.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

connectivity_plus, dio, flutter, isar, isar_flutter_libs, path_provider, uuid

More

Packages that depend on synclayer