crdt_grpc_sync 1.0.1 copy "crdt_grpc_sync: ^1.0.1" to clipboard
crdt_grpc_sync: ^1.0.1 copied to clipboard

A gRPC network sync layer for crdt, mirrors & inspired by crdt_sync, to get full P2P, local-first sync in any Dart app.

example/example.dart

import 'dart:convert';
import 'dart:io';

import 'package:crdt/map_crdt.dart';
import 'package:crdt_grpc_sync/crdt_grpc_sync.dart';
import 'package:uuid/uuid.dart';

/// Hub-and-spoke chat: one server relays messages to all clients.
///
/// Run without args to start the hub server:
///   dart run example/example.dart
///
/// Run with a gRPC URL to connect as a spoke:
///   dart run example/example.dart grpc://localhost:8080
Future<void> main(List<String> args) async {
  final crdt = MapCrdt(['chat']);

  print('Welcome to CRDT Chat (hub topology).');
  stdout.write('Your name: ');
  final author = stdin.readLineSync()?.trim() ?? 'anonymous';
  print('Hi $author. Type anything to send a message.');

  final verbose = args.contains('--verbose');
  final realUri = args.where((a) => a != '--verbose').toList();
  String? remoteAuthor;

  if (realUri.isEmpty) {
    // Run as server
    await listen(
      crdt,
      8080,
      config: CrdtSyncServiceConfig(
        handshakeDataBuilder: (peerId, peerData) => {'name': author},
        onClientConnected: (crdtSync, peerData) {
          final data = peerData as Map?;
          remoteAuthor = data?['name'] as String? ?? 'unknown';
          print('Client joined: $remoteAuthor');
        },
        onClientDisconnected: (peerId, code, reason) {
          final name = remoteAuthor;
          print('Client left: ${name ?? "unknown"}');
        },
        syncConfig: CrdtSyncConfig(verbose: verbose),
      ),
    );
    print('Server listening on port 8080');
    if (verbose) print('Verbose mode enabled');
  } else {
    // Run as client
    final uri = Uri.tryParse(realUri.first);
    if (uri == null || (uri.scheme != 'grpc' && uri.scheme != 'grpcs')) {
      print('Invalid URI: ${realUri.first}. Use grpc://host:port');
      exit(1);
    }

    CrdtSyncClient(
      crdt,
      uri,
      syncConfig: CrdtSyncConfig(verbose: verbose),
      handshakeDataBuilder: () => {'name': author},
      onConnecting: () => print('Connecting...'),
      onConnected: (nodeId, info) {
        final data = info as Map?;
        remoteAuthor = data?['name'] as String? ?? 'unknown';
        print('Connected to $remoteAuthor');
      },
      onDisconnected: (nodeId, code, reason) {
        final name = remoteAuthor;
        print('Disconnected: $name ($code $reason)');
      },
    ).connect();
  }

  // Listen for incoming chat messages
  crdt.onTablesChanged.listen((e) {
    final records = crdt.getChangeset(modifiedOn: e.hlc)['chat'] ?? [];
    for (final record in records) {
      final message = record['value'] as Map<String, dynamic>?;
      if (message != null) {
        print('[${message['author']}] ${message['line']}');
      }
    }
  });

  // Read stdin and broadcast as CRDT records
  stdin.transform(utf8.decoder).transform(const LineSplitter()).listen((line) {
    crdt.put('chat', const Uuid().v4(), {'author': author, 'line': line});
  });
}
1
likes
150
points
30
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A gRPC network sync layer for crdt, mirrors & inspired by crdt_sync, to get full P2P, local-first sync in any Dart app.

Repository (GitHub)
View/report issues

License

Apache-2.0 (license)

Dependencies

crdt, grpc, protobuf, uuid

More

Packages that depend on crdt_grpc_sync