Setup & Quick Start
Status: This SDK is in alpha and is subject to change between releases.
The Dart/Flutter SDK is kalam_link (pub package name: kalam_link). It is a thin Dart layer over a Rust core bridged via Flutter Rust Bridge.
If you need Topic consumers / ACK worker APIs, those are currently documented in the TypeScript SDK. The Dart SDK currently focuses on app-client query + subscription flows.
Install
Add to pubspec.yaml:
dependencies:
kalam_link: ^0.1.2Then fetch dependencies:
flutter pub get
# or
dart pub getSupported platforms (per plugin configuration): Android, iOS, macOS, Windows, Linux.
If you’re evaluating web builds: check the current package release notes first. Flutter FFI plugins may require additional setup for web/WASM targets.
Required initialization
You must call KalamClient.init() exactly once at app startup, before any other SDK call.
Flutter:
import 'package:flutter/widgets.dart';
import 'package:kalam_link/kalam_link.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await KalamClient.init();
// runApp(const MyApp());
}Pure Dart (non-Flutter):
import 'package:kalam_link/kalam_link.dart';
Future<void> main() async {
await KalamClient.init();
}Create a client
KalamClient.connect(...) constructs a client handle. Prefer authProvider for expiring tokens.
import 'package:kalam_link/kalam_link.dart';
final client = await KalamClient.connect(
url: 'http://localhost:8080',
authProvider: () async => Auth.jwt(await getJwtFromSecureStorage()),
);If you don’t have auth enabled (for example on a local server in bypass mode), you can omit auth entirely:
final client = await KalamClient.connect(url: 'http://localhost:8080');First query
final result = await client.query('SELECT CURRENT_USER()');
if (!result.success) {
throw StateError('Query failed: ${result.error}');
}
print(result.toMaps().first);QueryResponse also includes timing metadata (tookMs) and can contain multiple result sets when you send multiple statements.
First live subscription
subscribe(...) returns a Stream<ChangeEvent>.
final stream = client.subscribe('SELECT * FROM app.messages ORDER BY created_at DESC LIMIT 50');
final sub = stream.listen((event) {
switch (event) {
case AckEvent(:final subscriptionId):
print('Subscribed: $subscriptionId');
case InsertEvent(:final row):
print('New row: $row');
case SubscriptionError(:final code, :final message):
print('Error [$code]: $message');
default:
break;
}
});
// Later
await sub.cancel();Cleanup
await client.dispose();