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
- Create an IntelliToggle account at app.intellitoggle.com
- Create a project in the IntelliToggle dashboard
- Create OAuth2 Client Credentials under Settings → Create OAuth2 Client
- Save your credentials in a
.envfile - 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
.envfiles 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.