Flagdeck Flutter SDK

pub package

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

  1. API Key Invalid: Ensure your API key is correctly configured
  2. Network Errors: Check your device's internet connection
  3. Flag Not Found: Verify the flag key exists in your Flagdeck dashboard
  4. 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.