DartStream IntelliToggle Feature Flag Provider

Archive validation on Dart 3.13.4 checks the provider's direct HTTP dependency independently of other workspace packages.

A DartStream provider for IntelliToggle, a Dart-native feature flag service. This package integrates IntelliToggle's OpenFeature-compliant SDK into the DartStream framework, allowing you to manage feature flags with minimal setup.

Features

  • Complete DSFeatureFlagProvider Implementation - Full feature parity with other DartStream feature flag providers
  • OpenFeature Compliant - Built on the OpenFeature standard via openfeature_provider_intellitoggle
  • OAuth2 Authentication - Secure machine-to-machine authentication
  • Flag Evaluation - Boolean, string, number, and JSON flag support
  • Targeting & Context - User-specific flag evaluation with targeting rules
  • Environment Presets - Production and development configurations out of the box
  • Event Handling - Provider lifecycle event subscriptions
  • Error Handling - Comprehensive error mapping for IntelliToggle API errors

Installation

Add the IntelliToggle provider to your pubspec.yaml:

dependencies:
  ds_feature_flags_base: ^0.0.1-pre+1
  ds_intellitoggle_provider: ^0.0.1-pre+1

Prerequisites

  1. Create an IntelliToggle account at app.intellitoggle.com
  2. Create a project in the IntelliToggle dashboard
  3. Create OAuth2 Client Credentials under Settings → Create OAuth2 Client
  4. Save your credentials in a .env file - never commit them to version control

Environment Setup

# Linux/macOS
export INTELLITOGGLE_CLIENT_ID="your-client-id"
export INTELLITOGGLE_CLIENT_SECRET="your-client-secret"
export INTELLITOGGLE_TENANT_ID="your-tenant-id"
export INTELLITOGGLE_ENVIRONMENT="production"

# Windows
set INTELLITOGGLE_CLIENT_ID="your-client-id"
set INTELLITOGGLE_CLIENT_SECRET="your-client-secret"
set INTELLITOGGLE_TENANT_ID="your-tenant-id"
set INTELLITOGGLE_ENVIRONMENT="production"

Quick Start

Entry-point registration (recommended)

import 'dart:io';
import 'package:ds_intellitoggle_provider/ds_intellitoggle_export.dart';

Future<void> main() async {
  await registerIntelliToggleProvider({
    'clientId': Platform.environment['INTELLITOGGLE_CLIENT_ID']!,
    'clientSecret': Platform.environment['INTELLITOGGLE_CLIENT_SECRET']!,
    'tenantId': Platform.environment['INTELLITOGGLE_TENANT_ID']!,
    'environment': 'production',
  });
}

Basic Flag Evaluation

import 'dart:io';
import 'package:ds_intellitoggle_provider/ds_intellitoggle_export.dart';

Future<void> main() async {
  final provider = DSIntelliToggleProvider(
    clientId: Platform.environment['INTELLITOGGLE_CLIENT_ID']!,
    clientSecret: Platform.environment['INTELLITOGGLE_CLIENT_SECRET']!,
    tenantId: Platform.environment['INTELLITOGGLE_TENANT_ID']!,
  );

  await provider.initialize();

  // Evaluate a boolean flag
  final isEnabled = await provider.getBooleanFlag(
    'new-dashboard',
    defaultValue: false,
    context: {
      'targetingKey': 'user-123',
      'role': 'admin',
      'plan': 'enterprise',
    },
  );

  print('new-dashboard: $isEnabled');

  await provider.shutdown();
}

Configuration

Production (default)

final provider = DSIntelliToggleProvider(
  clientId: clientId,
  clientSecret: clientSecret,
  tenantId: tenantId,
  config: DSIntelliToggleConfig.production(),
);

Development

final provider = DSIntelliToggleProvider(
  clientId: clientId,
  clientSecret: clientSecret,
  tenantId: tenantId,
  config: DSIntelliToggleConfig.development(),
);

Custom Configuration

final provider = DSIntelliToggleProvider(
  clientId: clientId,
  clientSecret: clientSecret,
  tenantId: tenantId,
  config: DSIntelliToggleConfig(
    timeout: Duration(seconds: 15),
    enablePolling: true,
    pollingInterval: Duration(minutes: 2),
    enableStreaming: true,
    maxRetries: 5,
    enableLogging: true,
  ),
);

API Reference

DSIntelliToggleProvider

Constructor

DSIntelliToggleProvider({
  required String clientId,
  required String clientSecret,
  required String tenantId,
  DSIntelliToggleConfig? config,
})

Methods

// Initialize the provider (must be called first)
Future<void> initialize();

// Shutdown and cleanup
Future<void> shutdown();

// Flag evaluation
Future<bool> getBooleanFlag(String flagKey, {bool defaultValue, Map<String, dynamic>? context});
Future<String> getStringFlag(String flagKey, {String defaultValue, Map<String, dynamic>? context});
Future<num> getNumberFlag(String flagKey, {num defaultValue, Map<String, dynamic>? context});
Future<Map<String, dynamic>> getJsonFlag(String flagKey, {Map<String, dynamic> defaultValue, Map<String, dynamic>? context});
Future<DSFeatureFlagEvaluationResult> evaluateFlag(String flagKey, {Map<String, dynamic>? context});

DSIntelliToggleConfig Options

Option Description Default
baseUri API endpoint https://api.intellitoggle.com
timeout Request timeout 10 seconds
enablePolling Poll for updates true
pollingInterval Polling frequency 5 minutes
enableStreaming Real-time updates false
maxRetries Retry attempts 3
enableLogging Debug logging false

Error Handling

try {
  final result = await provider.getBooleanFlag('my-flag');
} on DSIntelliToggleException catch (e) {
  switch (e.code) {
    case 'unauthorized':
      print('Invalid OAuth2 credentials');
      break;
    case 'flag_not_found':
      print('Flag does not exist');
      break;
    case 'rate_limit_exceeded':
      print('Too many requests');
      break;
    case 'timeout':
      print('Request timed out');
      break;
    default:
      print('Error: ${e.message}');
  }
}

Testing

# Run all tests
dart test

# Run with coverage
dart test --coverage

# Run integration test (requires INTELLITOGGLE_* env vars)
dart test test/ds_intellitoggle_integration_test.dart

Publish Validation

dart pub publish --dry-run

Security Best Practices

  • Never hardcode credentials in source code
  • Use environment variables for all sensitive values
  • Rotate OAuth2 credentials regularly
  • Use least privilege scopes when creating OAuth2 clients
  • Never commit .env files to version control

IntelliToggle Resources

License

This package is part of the DartStream project and is licensed under the BSD-3 License.

Support

For issues with the DartStream integration, visit the DartStream repository.

For issues with IntelliToggle itself, visit the IntelliToggle project.

Dart 3.13.4 analysis uses the hooks API exported by the IntelliToggle provider.