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.3

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.