nats_for_dart 0.2.0
nats_for_dart: ^0.2.0 copied to clipboard
Dart FFI bindings for the NATS C client — core pub/sub, JetStream, and KeyValue store.
nats_for_dart #
Idiomatic Dart bindings for NATS — pub/sub, JetStream, and KeyValue built on nats.c v3.12.0, with no system OpenSSL required.
⚡ Features #
- Pub/sub — synchronous and asynchronous subscriptions, wildcard subjects (
foo.*,foo.>) - Request-reply — single-call request/response pattern
- Message headers — HTTP-style
name: valuemetadata on publish/request/respond and JetStream publish, with multi-value Add semantics; enables distributed tracing,Nats-Msg-Iddeduplication, andNats-Expected-Last-Sequenceoptimistic publish - JetStream — durable streams, consumers, publish with ack, and pull subscribe
- KeyValue store — get, put, delete, watch, history, and optimistic concurrency with revision checks
- Connection lifecycle — disconnect, reconnect, close, and async error event streams
- TLS / mTLS
- Server-cert verification — hostname checks against the cert's SAN/CN, auto-derived from the URL, or overridden via
NatsOptions.expectedHostnamefor IP-dialled or SNI-proxied connections - CA trust anchor — from a file path (
NatsOptions.caCertPath) or a concatenated PEM string (NatsOptions.caCertPem) for secrets-manager workflows - Client cert/key (mutual TLS) — from file paths (
NatsOptions.clientCertPath+NatsOptions.clientKeyPath) or PEM strings (NatsOptions.clientCertPem+NatsOptions.clientKeyPem) for secrets-manager workflows - Cipher allow-list — TLS ≤ 1.2 cipher selection via
NatsOptions.tlsCiphers(OpenSSL syntax) - TLS handshake-first — initiate the TLS handshake immediately on TCP connect (no plaintext exchange) via
NatsOptions.tlsHandshakeFirst, for downgrade-attack-resistant deployments paired with ahandshake_first: trueserver
- Server-cert verification — hostname checks against the cert's SAN/CN, auto-derived from the URL, or overridden via
📱 Supported platforms #
| Platform | Supported |
|---|---|
| Desktop | ✅ |
| Mobile | ❌ |
| Web | ❌ |
📦 Installation #
Add the package to your pubspec.yaml:
dependencies:
nats_for_dart: ^0.2.0
Then run:
dart pub get
The native
libnatsshared library is compiled on first build. This may take some time depending on your machine while LibreSSL and nats.c are compiled from source.
🚀 Quick Start #
import 'package:nats_for_dart/nats_for_dart.dart';
void main() {
// 1. Initialise the library once per process.
NatsLibrary.init();
final client = NatsClient.connect('nats://localhost:4222');
// 2. Subscribe synchronously on a subject.
final sub = client.subscribeSync('greet.hello');
// 3. Publish a message.
client.publish('greet.hello', 'Hello, NATS!');
// 4. Receive the next message (blocks up to 2 seconds).
final msg = sub.nextMessage(timeout: const Duration(seconds: 2));
print('${msg.subject}: ${msg.dataAsString}');
// → greet.hello: Hello, NATS!
// 5. Clean up.
sub.close();
client.close();
NatsLibrary.close(timeoutMs: 5000);
}
For async (Stream-based) subscriptions, see example/async_subscriber.dart. For JetStream and KeyValue examples, see Examples below.
💡 Examples #
| Example | Description | Run |
|---|---|---|
pubsub_sync.dart |
Synchronous pub/sub — publish and receive in one process | dart run example/pubsub_sync.dart |
async_subscriber.dart |
Async subscription via Dart Stream with wildcard subject |
dart run example/async_subscriber.dart |
lifecycle_demo.dart |
Connection lifecycle events — stop/restart the server while running to observe | dart run example/lifecycle_demo.dart |
jetstream_pub_sub.dart |
JetStream stream creation, publish with ack, and pull subscribe | dart run example/jetstream_pub_sub.dart |
headers_demo.dart |
Message headers — tracing header round-trip, then JetStream Nats-Msg-Id dedup |
dart run example/headers_demo.dart |
kv_demo.dart |
KeyValue CRUD, optimistic update, watch, history, delete, and purge | dart run example/kv_demo.dart |
mtls_demo.dart |
Mutual TLS pub/sub against an mTLS-enabled server | dart run example/mtls_demo.dart |
Server prerequisites by example:
pubsub_sync.dart,async_subscriber.dart,lifecycle_demo.dart— plainnats-server.jetstream_pub_sub.dart,headers_demo.dart,kv_demo.dart—nats-server -js(JetStream enabled).mtls_demo.dart— an mTLS-enabled server on port 4224. Start one withnats-server -c test/support/nats-mtls-native.conf, or run the bundled config in Docker (see the example's doc-comment for the full command). The integration-test fixture's container is torn down at the end ofdart testand isn't reusable for ad-hoc runs.
🤖 A note on AI assistance #
This package was developed with heavy use of AI tooling (Claude Code). The implementation has been
reviewed carefully, but given the early stage (v0.1.0) and the nature of AI-assisted development, you
should feel comfortable scrutinising any part of the code. If something looks wrong, surprising, or
suboptimal — it very well might be. Issues and PRs are welcome. 🙏
🗺️ Roadmap #
nats_for_dart v0.1.0 covers the core use cases. The following tracks progress toward production readiness and full parity with the NATS C client.
✨ Coming Next #
These additions complete the JetStream management API and round out connection options.
| Feature | Why it matters |
|---|---|
| Consumer Update | FFI binding already exists — only the Dart wrapper is missing |
| Stream Listing | Discover and manage all streams programmatically |
| Consumer Listing | Enumerate consumers per stream for monitoring and tooling |
| Reconnect Jitter | Prevents thundering-herd reconnects in large deployments |
| No Echo | Suppress delivery of your own published messages to your own subscribers |
| Direct NKey Auth | Alternative to credentials files — sign challenges directly with an NKey seed |
Priority 3 and 4 — Future Additions
Valuable Additions #
| Feature | Why it matters |
|---|---|
| Object Store | Large object (file/blob) storage over NATS via JetStream |
| Dynamic Server Discovery | Auto-discover new cluster members without restarting |
| Lame Duck Mode Callback | Graceful shutdown notification from departing servers |
| Allow/Disable Reconnect | Explicit control over whether reconnection is attempted |
| Custom Reconnect Delay | Callback-driven exponential backoff or custom logic |
| Fail Requests on Disconnect | Fail-fast behavior instead of buffering requests |
| Ordered Consumers | Simplified exactly-once-delivery consumer configuration |
Nice to Have #
| Feature | Why it matters |
|---|---|
| Token Refresh Handler | Dynamic token generation on each reconnect |
| Custom Credentials Callback | Generate credentials programmatically |
| Send As Soon As Possible | TCP_NODELAY for latency-sensitive workloads |
| Retry on Failed Connect | Auto-retry the initial connection attempt |
| Max Pending Msgs/Bytes | Per-subscription flow control |
| Micro Service API | Built-in NATS microservice framework (micro_AddService, etc.) |
| WebSocket Transport | Browser-compatible NATS connections |
🧑💻 Contributing #
Contributions are welcome. See CONTRIBUTING.md for development setup, pre-commit hooks, and instructions for upgrading the vendored nats.c and LibreSSL libraries.
⚖️ License #
This package is licensed under the Apache License, Version 2.0.
Third-Party Notices #
This package vendors the following C libraries, compiled into the native libnats
shared library:
LibreSSL includes code derived from OpenSSL and SSLeay. In compliance with those licenses:
This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit (http://www.openssl.org/)
This product includes cryptographic software written by Eric Young (eay@cryptsoft.com).
See NOTICE for full third-party attribution notices.