Flagdeck Flutter SDK
A Flutter SDK for integrating with Flagdeck - a feature flag and remote configuration service that helps you control feature rollouts, run A/B tests, and manage configurations across environments.
Features
- 🚀 Simple flag evaluation with boolean, string, number, and JSON value support
- 🔄 Batch flag evaluation for efficient API usage
- 💾 Offline mode with persistent cache
- 📊 Analytics tracking for flag usage
- 🔔 Real-time flag updates via Server-Sent Events (SSE)
- 🛡️ Type-safe API with Dart/Flutter integration
- 📱 Mobile-optimized performance
Installation
dependencies:
flagdeck: ^0.0.4
Run flutter pub get
to install the package.
Quick Start
Initialize the SDK
import 'package:flagdeck/flagdeck.dart';
import 'package:flagdeck/model/eval_payload/context.dart';
import 'package:eventflux/models/reconnect.dart';
// Create an instance of the SDK
final flagdeck = FlagDeckSdk(
apiKey: 'your-api-key',
enableCache: true, // Optional, defaults to true
enableAnalytics: true, // Optional, defaults to true
// SSE Configuration
onSseEvent: (flagKey, event, data) {
print("Flag update event: $flagKey ${event.event} ${data.timestamp}");
},
onSseConnect: (event) {
print("SSE connected: ${event.flag?.key} ${event.timestamp}");
},
handleSseConnectionError: (error) {
print("SSE connection error: ${error.message}");
},
handleSseDisconnect: () {
print("SSE disconnected");
},
sseReconnectConfig: ReconnectConfig(
mode: ReconnectMode.linear,
interval: Duration(seconds: 10),
),
);
Evaluate a Flag
// Evaluate a flag with user context
final result = await flagdeck.evaluateOrFind(
FlagdeckRequestData(
flagKey: 'my-feature-flag',
context: EvaluationContext(
userId: 'user-123',
attributes: {
'country': 'US',
'plan': 'premium',
},
),
),
);
// Check if the flag is enabled
if (result?.isEnabled == true) {
// The flag is enabled
print('Feature flag value: ${result?.value}');
} else {
// The flag is disabled or an error occurred
print('Feature disabled or error: ${result?.error?.message}');
}
Batch Evaluation
// Evaluate multiple flags at once
final batchResults = await flagdeck.evaluateBatch(
FlagdeckBatchRequestData(
flagKeys: ['feature-a', 'feature-b', 'feature-c'],
context: EvaluationContext(userId: 'user-123'),
),
);
// Access individual flag results
final featureAValue = batchResults?['feature-a']?.value;
final featureBValue = batchResults?['feature-b']?.value;
Advanced Usage
Using Event Callbacks
final result = await flagdeck.evaluateOrFind(
FlagdeckRequestData(
flagKey: 'my-feature-flag',
context: EvaluationContext(userId: 'user-123'),
onBeforeRequest: () {
// Called before the network request is made
showLoadingIndicator();
},
onSuccess: (response) {
// Called when the network request succeeds
hideLoadingIndicator();
logSuccess();
},
onError: (error, data) {
// Called when an error occurs
hideLoadingIndicator();
showErrorMessage(error.message);
},
),
);
Cache Control
// Force a network request even if the flag is cached
final result = await flagdeck.evaluateOrFind(
FlagdeckRequestData(
flagKey: 'my-feature-flag',
context: EvaluationContext(userId: 'user-123'),
invalidateCache: true, // Force refresh from network
),
);
// Clear the entire cache
await flagdeck.clearCachedFlags();
Offline Mode
// Use locally cached flags when offline
final result = await flagdeck.evaluateOrFind(
FlagdeckRequestData(
flagKey: 'my-feature-flag',
context: EvaluationContext(userId: 'user-123'),
enableOfflineMode: true, // Use cached values when available
),
);
Real-time Flag Updates
The SDK supports real-time flag updates via Server-Sent Events (SSE). When a flag is updated on the Flagdeck dashboard, your app will receive a notification:
// Check the SSE connection status
bool isConnected = flagdeck.serverSentEvents.connected;
// Manually close the SSE connection
flagdeck.serverSentEvents.close();
// SSE events are handled through callbacks provided during initialization
final flagdeck = FlagDeckSdk(
apiKey: 'your-api-key',
onSseEvent: (flagKey, event, data) {
// This is called when any flag event is received
if (event.event == 'flag.updated') {
// Handle flag update
refreshUI();
}
},
);
Analytics
Analytics events are automatically tracked when flag evaluations occur. To manually send tracked events to the server:
// Send accumulated analytics events to the server
await flagdeck.sendLocalEventsToServer();
API Reference
FlagDeckSdk
The main class for interacting with the Flagdeck service.
Constructor
FlagDeckSdk({
this.apiKey, // Required: Your Flagdeck API key
this.enableCache = true, // Optional: Enable caching of flag values
this.enableAnalytics = true, // Optional: Enable usage analytics
this.timeout, // Optional: Request timeout duration
this.baseUrl, // Optional: Custom API base URL
this.retryConfig, // Optional: Network retry configuration
this.maxLogCount = 10, // Optional: Maximum analytics events before auto-sending
this.onSseEvent, // Optional: Callback for SSE events
this.onSseConnect, // Optional: Callback when SSE connects
this.handleSseConnectionError, // Optional: Callback for SSE connection errors
this.handleSseDisconnect, // Optional: Callback when SSE disconnects
this.sseReconnectConfig, // Optional: Configuration for SSE reconnection
})
Methods
Method | Description |
---|---|
Future<EvaluationResult?> evaluateOrFind(FlagdeckRequestData data) |
Evaluates a single flag with the given context |
Future<Map<String, EvaluationResult>?> evaluateBatch(FlagdeckBatchRequestData data) |
Evaluates multiple flags in a single API call |
sendLocalEventsToServer() |
Sends accumulated analytics events to the server |
clearCachedFlags() |
Clears all cached flag values |
ReconnectConfig
Configuration for SSE reconnection strategy.
ReconnectConfig({
required this.mode, // ReconnectMode (linear, exponential, fixed)
required this.interval, // Base interval between reconnection attempts
})
EvaluationContext
Describes the context in which a flag is being evaluated (user, session, attributes).
EvaluationContext({
this.userId, // Optional: User identifier
this.sessionId, // Optional: Session identifier
this.attributes, // Optional: Additional user attributes
})
EvaluationResult
Contains the result of a flag evaluation.
Properties
Property | Type | Description |
---|---|---|
flagKey |
String? |
The key of the evaluated flag |
value |
dynamic |
The value of the flag |
source |
String? |
Source of the flag value (e.g., targeting rule, default) |
reason |
String? |
Reason for the resulting value |
timestamp |
int? |
Timestamp when the evaluation occurred |
error |
EvaluationError? |
Error details if the evaluation failed |
variant |
VariantInfo? |
Information about the variant if applicable |
isEnabled |
bool |
Helper property that returns true if no error occurred |
FlagdeckRequestData
Configuration for a single flag evaluation request.
FlagdeckRequestData({
required this.flagKey, // The key of the flag to evaluate
this.apiKey, // Optional: Override the SDK API key
this.context, // Optional: Evaluation context
this.enableOfflineMode, // Optional: Use offline values if available
this.invalidateCache = false, // Optional: Ignore cached values
this.onBeforeRequest, // Optional: Callback before the request
this.onSuccess, // Optional: Callback on success
this.onError, // Optional: Callback on error
})
FlagdeckBatchRequestData
Configuration for a batch evaluation request.
FlagdeckBatchRequestData({
required this.flagKeys, // List of flag keys to evaluate
this.apiKey, // Optional: Override the SDK API key
this.context, // Optional: Evaluation context
this.enableOfflineMode, // Optional: Use offline values if available
this.invalidateCache = false, // Optional: Ignore cached values
this.onBeforeRequest, // Optional: Callback before the request
this.onSuccess, // Optional: Callback on success
this.onError, // Optional: Callback on error
})
Error Handling
The SDK provides detailed error information through the EvaluationError
class:
class EvaluationError {
String? code; // Error code
String? message; // Human-readable error message
}
Example of handling errors:
final result = await flagdeck.evaluateOrFind(
FlagdeckRequestData(
flagKey: 'my-feature-flag',
context: EvaluationContext(userId: 'user-123'),
),
);
if (result?.error != null) {
print('Error code: ${result?.error?.code}');
print('Error message: ${result?.error?.message}');
}
Troubleshooting
Common Issues
- API Key Invalid: Ensure your API key is correctly configured
- Network Errors: Check your device's internet connection
- Flag Not Found: Verify the flag key exists in your Flagdeck dashboard
- SSE Connection Issues: Check your network connectivity and firewall settings
Enabling Debug Logs
To troubleshoot SDK issues, you can use Dart's logging functionality:
import 'dart:developer' as developer;
// Later in your code
developer.log('Flag evaluation result', name: 'FlagdeckSDK', error: result?.error);
Migration Guide
From v0.0.1 to v0.0.2
- Added support for real-time flag updates via Server-Sent Events (SSE)
- Added SSE connection management with automatic reconnection
- Added SSE event callbacks for connection status and flag updates
From v0.0.0 to v0.0.1
- Initial release, no migration necessary
Contributing
We welcome contributions! Please see our contributing guidelines for details.
License
This project is licensed under the MIT License - see the LICENSE file for details.