Skip to main content

split_openfeature_provider_dart_client 0.1.0 copy "split_openfeature_provider_dart_client: ^0.1.0" to clipboard
split_openfeature_provider_dart_client: ^0.1.0 copied to clipboard

Split OpenFeature provider for Dart (client-side / static-context) — adapts splitio_client_side to the OpenFeature FeatureProvider contract.

Split OpenFeature Provider for Dart #

Adapts the Split Dart client SDK (splitio_client_side) to the OpenFeature FeatureProvider contract defined by openfeature_dart_client_sdk.

Overview #

This provider lets you evaluate Split feature flags through OpenFeature's standard client-side (static-context) API.

Getting started #

Add the dependency #

Both openfeature_dart_client_sdk and splitio_client_side are peer packages and must be declared alongside this provider.

dependencies:
  split_openfeature_provider_dart_client: ^0.1.0
  openfeature_dart_client_sdk: ^0.0.1-beta.1
  splitio_client_side: ^1.1.0

Register the Split provider with OpenFeature #

Construct a SplitFactory, pass it to OpenFeatureSplitProvider, and register the provider with the OpenFeature API. The provider never constructs its own factory — the SDK key, config, and initial matching key are the caller's responsibility.

import 'package:openfeature_dart_client_sdk/openfeature_dart_client_sdk.dart';
import 'package:split_openfeature_provider_dart_client/split_openfeature_provider_dart_client.dart';
import 'package:splitio_client_side/splitio_client_side.dart'
    show SplitFactory, SplitClientConfig;

Future<void> main() async {
  final splitFactory = SplitFactory.create(
    'CLIENT_SIDE_SDK_KEY',
    SplitClientConfig(),
    'TARGETING_KEY',
  );

  final provider = OpenFeatureSplitProvider(splitFactory);

  // Waits for the Split SDK to become ready or errors on timeout.
  await OpenFeatureAPI.instance.setProviderAndWait(provider);

  final client = OpenFeatureAPI.instance.getClient();
}

Evaluating flags #

After registration you use OpenFeature's evaluation API as documented on openfeature.dev.

The provider uses one field on every EvaluationContext used for evaluation:

  • targetingKey — identifies the subject of evaluation.

trafficType is optional on the evaluation context for flag lookups (Split's client-side evaluation ignores it). It is required only when calling track.

await OpenFeatureAPI.instance.setEvaluationContextAndWait(
  EvaluationContext(
    targetingKey: 'TARGETING_KEY',
  ),
);

final showBanner = client.getBooleanValue('show_banner', false);

Evaluate with details #

Use the get*Details variants to retrieve the value alongside variant, reason, error code, and flag metadata. This provider exposes the raw Split treatment config JSON string under flagMetadata['config'].

final details = client.getBooleanDetails('bool_flag', false);
final config = details.flagMetadata['config']; // raw JSON string, or ''

Evaluate with attributes #

Attributes on the EvaluationContext (other than trafficType) are forwarded to Split as evaluation attributes.

await OpenFeatureAPI.instance.setEvaluationContextAndWait(
  EvaluationContext(
    targetingKey: 'TARGETING_KEY',
    attributes: {
      'plan': 'premium',
      'coupon': 'WELCOME10',
    },
  ),
);

final details = client.getBooleanDetails('bool_flag', false);

Treatment parsing #

The provider maps Split's string treatments to typed OpenFeature values:

OpenFeature method Accepted treatments
getBooleanValue / Details 'on', 'true' → true; 'off', 'false' → false
getStringValue / Details Any Split treatment string
getIntegerValue / Details Any string parseable by int.tryParse
getDoubleValue / Details Any string parseable by double.tryParse (NaN rejected)
getStructureValue / Details Any JSON object literal (arrays, scalars, null rejected)

Boolean matching is case-insensitive. Numeric parsing accepts 'Infinity' and '-Infinity' but rejects 'NaN'. Any treatment that fails to parse surfaces as an OpenFeature evaluation error with ErrorCode.parseError. A Split 'control' treatment surfaces as ErrorCode.flagNotFound.

Provider events #

The provider emits OpenFeature ProviderEvents driven by the Split SDK lifecycle:

  • SDK_READY → ProviderEventType.ready.
  • Split flag/segment updates → ProviderEventType.configurationChanged with the changed flag names in flagsChanged.
final client = OpenFeatureAPI.instance.getClient();
client.addHandler(ProviderEventType.configurationChanged, (details) {
  print('Flags changed: ${details.flagsChanged}');
});

Tracking #

track forwards to Split's event tracker. The event name must be non-empty and the current EvaluationContext MUST carry a non-empty String trafficType attribute — call setEvaluationContext with a valid trafficType before invoking track().

await OpenFeatureAPI.instance.setEvaluationContextAndWait(
  EvaluationContext(
    targetingKey: 'user-123',
    // trafficType is REQUIRED for track(); must be a non-empty String.
    attributes: {'trafficType': 'account'},
  ),
);

client.track(
  'checkout.completed',
  details: TrackingEventDetails(
    value: 19.99,
    attributes: {'plan': 'pro', 'coupon': 'WELCOME10'},
  ),
);

TrackingEventDetails.value is a num?; integer values are forwarded to Split as doubles. attributes on the details is forwarded as Split event properties.

If trafficType is missing when track() is called, the provider throws OpenFeatureException(ErrorCode.invalidContext, ...). Note that the OpenFeature client's track() is fire-and-forget per spec, so it swallows the exception; the provider also emits a print diagnostic tagged [split_openfeature_provider] so the refusal is observable in the console.

Reconciling context changes #

Calling OpenFeatureAPI.instance.setEvaluationContextAndWait(newContext) with a different targetingKey triggers the provider's onContextChanged. The provider rebinds to a new Split client for the new key, cancels the previous flag update subscription, waits for the new client to become ready, and emits ProviderEventType.configurationChanged.

If the new client times out before becoming ready, the future returned by setEvaluationContextAndWait completes with an OpenFeatureException (ErrorCode.general, 'Split SDK ready timed out').

Shutting down #

Call shutdown when you're done with the provider (typically only in tests or in short-lived programs). It cancels the flag update subscription, destroys the Split factory, and closes the event stream.

await provider.shutdown();

Behavior notes #

  1. trafficType is required at track() time, not evaluation time. Split's client-side evaluation ignores trafficType, so it is optional on the EvaluationContext for resolve*Value calls. Calling track() without a trafficType throws OpenFeatureException(ErrorCode.invalidContext, ...) rather than silently defaulting, which would misattribute tracking events across traffic types. Present-but-invalid values (non-String, empty String, whitespace-only String) are rejected at context transform time.
  2. No ready-from-cache / no update type metadata. The Split Dart client SDK does not currently expose an SDK_READY_FROM_CACHE equivalent or an update-type field on flag-change events, so the provider never emits ProviderEventType.stale and the configurationChanged event carries only flagsChanged (no metadata['type']).

Platform support #

Pure Dart. Runs everywhere splitio_client_side runs: Dart VM (server, CLI), Flutter (Android, iOS, Web, Desktop), and browser-compiled Dart. The provider package contains no dart:html, dart:io, or dart:ffi imports.

OpenFeature specification compliance #

This provider targets the OpenFeature specification v0.9.0. Section 2 (Provider) conformance:

Clause Status Notes
2.1.1 metadata name Yes metadata.name returns "split".
2.2 flag resolution (all types) Yes Boolean / string / integer / double / structure supported.
2.2.5 reason Yes Populated as "TARGETING_MATCH" for successful evaluations.
2.2.9 flag metadata Yes Raw Split treatment config JSON exposed under flagMetadata['config'].
2.3.1 provider hooks mechanism Yes Empty hook list; no provider-managed hooks.
2.4.1 initialize with domain Yes Signature accepts domain; provider is not domain-scoped.
2.5.1–2.5.3 shutdown Yes Idempotent; provider rejects initialize after shutdown.
2.6.1 onContextChanged Yes Reconciles by rebinding to a new Split client for the new targeting key.
2.7.1 tracking Yes track forwards to Split, requires a trafficType attribute.
2.8.1–2.8.4 provider events Yes Emits PROVIDER_READY, PROVIDER_ERROR, PROVIDER_CONFIGURATION_CHANGED, and PROVIDER_CONTEXT_CHANGED.
PROVIDER_STALE Not emitted The Split Dart client SDK does not expose a SDK_READY_FROM_CACHE signal today.

License #

Licensed under the Apache License, Version 2.0. See Apache License.

0
likes
135
points
228
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Split OpenFeature provider for Dart (client-side / static-context) — adapts splitio_client_side to the OpenFeature FeatureProvider contract.

Repository (GitHub)
View/report issues

Topics

#openfeature #feature-flags #split #feature-management

License

unknown (license)

Dependencies

openfeature_dart_client_sdk, splitio_client_side

More

Packages that depend on split_openfeature_provider_dart_client