bridra_flutter 0.6.1 copy "bridra_flutter: ^0.6.1" to clipboard
bridra_flutter: ^0.6.1 copied to clipboard

Reusable Flutter RPC and Go sidecar runtime for Bridra applications.

bridra_flutter #

Reusable Flutter transport package for Bridra applications.

This package is licensed under the MIT License, Copyright (c) 2026 Cluion. It is the Flutter-facing runtime package for the Bridra framework.

It provides:

  • the common RPC client contract and error types;
  • an HTTP RPC client for mobile, Web, and remote backends;
  • a managed Go sidecar client for Windows, macOS, and Linux;
  • verified out-of-band file uploads and resumable downloads for HTTP and Desktop Sidecars;
  • desktop single-instance ownership and activation forwarding;
  • a conditional default connector that selects the platform transport.

Desktop executable discovery checks BRIDRA_SIDECAR_PATH, the application libexec directory, build/sidecar, then backend/bin. Web builds select the HTTP connector through a conditional import and never import dart:io.

The desktop client automatically restarts an unexpectedly terminated Sidecar. Calls that were in flight fail and are never replayed automatically. Calls made during recovery wait for a replacement process to pass system.health, while their own timeout and cancellation remain active.

Application-specific methods and response models do not belong in this package. Define those in the consuming application's typed gateway.

Install #

flutter pub add bridra_flutter

Common transport #

import 'package:bridra_flutter/bridra_flutter.dart';

final client = await connectDefaultRpcClient();
final reply = await client.call('system.health');
await client.close();

Calls accept an optional cancellation token. Timeouts use the same transport cancellation path automatically.

final cancellationToken = RpcCancellationToken();
final reply = client.call(
  'report.build',
  cancellationToken: cancellationToken,
);
cancellationToken.cancel();

Server-streaming calls emit typed data and progress events. Generated APIs perform application-result decoding; the transport package owns framing:

await for (final event in api.buildReport(request)) {
  if (event is RpcStreamProgress<ReportPage>) {
    updateProgress(event.progress.fraction);
  } else {
    render((event as RpcStreamData<ReportPage>).value);
  }
}

The default stream timeout is five minutes. HTTP uses flushed NDJSON. Desktop Sidecars use a bounded credit window and acknowledge each event only after the listener consumes it.

Large results use a generated RpcFileReference instead of embedding bytes in JSON. The same API streams HTTP response chunks or reads a Sidecar-managed temporary file, then verifies the declared byte count and SHA-256 digest:

final export = await api.exportReport(request);
await for (final chunk in client.download(export.file)) {
  output.add(chunk);
}

HTTP downloads resume automatically from the verified byte offset, with three attempts by default, and capabilities are consumed only after a complete response. Desktop files are deleted after consumption. If integrity validation still fails, discard any partial output already written.

Upload a large input before passing its generated RpcFileReference to a typed request:

final source = File(path);
final digest = await sha256.bind(source.openRead()).first;
final upload = RpcFileUpload(
  name: 'archive.zip',
  mediaType: 'application/zip',
  size: await source.length(),
  sha256: digest.toString(),
  openRead: (offset) => source.openRead(offset),
);
final file = await client.upload(upload);
await api.importArchive(ImportArchiveRequest(file: file));

HTTP uploads recover from the server-reported offset. Desktop uploads use a bounded, verified staging file and the reserved rpc.file_upload Sidecar method; file bytes never enter the JSON RPC envelope.

Desktop single instance #

Acquire ownership once in the root isolate before runApp. A later process forwards its command-line arguments, including file paths or deep-link URIs, to the primary process and returns isPrimary == false.

Future<void> main([List<String> arguments = const []]) async {
  WidgetsFlutterBinding.ensureInitialized();
  final instance = await DesktopSingleInstance.acquire(
    applicationId: 'com.example.my_app',
    arguments: arguments,
  );
  if (!instance.isPrimary) return;

  instance.activations.listen((activation) {
    openFilesAndLinks(activation.arguments);
  });
  runApp(const MyApp());
}

The ownership lock is released by the operating system if the primary process crashes. Activation transport is bound to IPv4 loopback, uses an ephemeral port and a random token, limits frames to 1 MiB, and waits for an acknowledgement before the later process exits. Call acquire only once from the root isolate; desktop file locks are process-scoped on Linux and macOS.

Desktop sidecar #

Desktop-only code may import the explicit sidecar library:

import 'package:bridra_flutter/bridra_flutter_sidecar.dart';

final client = await SidecarClient.start(
  executablePath: executablePath,
  token: SidecarClient.createToken(),
  streamWindow: 16,
  restartPolicy: const SidecarRestartPolicy(
    maxAttempts: 3,
    initialDelay: Duration(milliseconds: 250),
    maxDelay: Duration(seconds: 2),
  ),
);

The default policy uses three restart attempts. Set SidecarRestartPolicy.disabled() only when the application owns recovery.

0
likes
140
points
328
downloads

Documentation

API reference

Publisher

verified publishercluion.com

Weekly Downloads

Reusable Flutter RPC and Go sidecar runtime for Bridra applications.

Repository (GitHub)
View/report issues
Contributing

Topics

#flutter #go #rpc #sidecar

License

MIT (license)

Dependencies

crypto, flutter, http

More

Packages that depend on bridra_flutter