feat_sdk 0.1.0
feat_sdk: ^0.1.0 copied to clipboard
Dart and Flutter client for the feat feature-flag platform: sync flag getters, change listeners, live SSE streaming, anonymous contexts, and offline snapshots.
example/lib/main.dart
// A minimal Flutter app demonstrating feat_sdk: initialize, read a boolean
// flag, listen for changes, and swap the context. It wires up the optional
// Flutter glue (shared_preferences storage + lifecycle observer) from
// feat_flutter.dart.
import 'dart:async';
import 'package:feat_sdk/feat_sdk.dart';
import 'package:flutter/material.dart';
import 'feat_flutter.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final storage = await SharedPreferencesFeatStorage.create();
final client = await FeatClient.initialize(FeatClientConfig(
// Use a client-side id key (prefix feat_cs_) or a mobile key. Both are
// non-secret client keys and safe to ship in an app.
apiKey: 'feat_cs_your_key_here',
anonymous: true, // mint a stable per-install anonymous context
storage: storage, // persist the anonymous key + offline snapshots
// Streaming follows the change subscription by default; polling is the
// safety net.
));
runApp(ExampleApp(client: client));
}
class ExampleApp extends StatefulWidget {
final FeatClient client;
const ExampleApp({super.key, required this.client});
@override
State<ExampleApp> createState() => _ExampleAppState();
}
class _ExampleAppState extends State<ExampleApp> {
late final FeatLifecycleObserver _observer;
StreamSubscription<FlagChange>? _changes;
@override
void initState() {
super.initState();
// Pause/resume live updates with the app lifecycle.
_observer = FeatLifecycleObserver(widget.client)..attach();
// Re-render whenever a flag value flips. Subscribing also opens the live
// stream under the default streaming policy.
_changes = widget.client.changes.listen((change) {
if (mounted) setState(() {});
});
}
@override
void dispose() {
_observer.detach();
_changes?.cancel();
unawaited(widget.client.close());
super.dispose();
}
@override
Widget build(BuildContext context) {
final enabled = widget.client.getBool('checkout-v2', false);
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('feat_sdk example')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('checkout-v2 is ${enabled ? 'ON' : 'OFF'}'),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => widget.client.setContext(
EvalContext.user('user-123', attributes: {'plan': 'pro'}),
),
child: const Text('Identify as user-123 (pro)'),
),
],
),
),
),
);
}
}