flagnetic_flutter library

Flutter bindings for Flagnetic: a scope holding the client, a builder widget rebuilding when a flag changes, listenables for a flag and for the fallback chain's stage, the lifecycle observer moving the client between foreground and background, the default store and the Dev Tools helper and screen for local overrides.

The client, the fallback chain and offline mode live in package:flagnetic/flagnetic.dart, which this package re-exports: one import is enough in an app.

final store = FlutterStore();
final client = Flagnetic.client(
  'fn_cli_…',
  baseUrl: Uri.parse('https://flags.example.com'),
  context: FlagneticContext(units: {'anonymous': await anonymousUnitId(store, 'anonymous')}),
  options: ClientOptions(store: store, platform: 'android'),
);
runApp(FlagneticScope(client: client, child: const MyApp()));

Classes

ClientOptions
How a client behaves. Every duration is configurable so that a test can run a whole scenario in milliseconds.
Detail
A served value and why it was served.
Experiment
The experiment block of a served value: everything an exposure reports, so an analyst can recompute both buckets.
FallbackCodes
Why a Detail has reason fallback, by wire name. The error codes of the server's evaluator (inconsistent_ruleset, prerequisite_cycle, …) are passed through as they arrived.
FlagBuilder<T>
Builds from the value of one flag and rebuilds whenever it changes.
FlagListenable<T>
The value of one flag as a ValueListenable, so a widget follows it without plumbing: it notifies whenever the client's values change or the fallback chain moves to another stage.
Flagnetic
The entry point of the Flagnetic SDK: client builds a client-mode client.
FlagneticClient
A client-mode client: values from remote evaluation, cached on device as last good, served through the fallback chain. Every public member is total: an internal failure is logged and never escapes.
FlagneticContext
Who a flag is evaluated for: units identify the subjects experiments bucket by, attributes feed targeting.
FlagneticDevTools
The Dev Tools helper for local overrides: gates every mutation behind the build mode — a no-op, override_refused, in a release build, however FlagneticClient.overrides was constructed, because the pure Dart client has no notion of a Flutter build mode — persists overrides in FlagneticStore under their own key so QA's flips survive a restart, and exposes hasOverrides for a badge.
FlagneticDevToolsScreen
Lists every flag the client currently holds — key, value, reason and stage — and lets QA edit or clear local overrides.
FlagneticLifecycleObserver
Drives a client's foreground and background triggers from the application's lifecycle. The app resuming reopens the ruleset stream and evaluates again, unless the last attempt is less than ClientOptions.minimumRefetchGap old; the app paused, hidden or detached closes the stream, stops the interval and flushes queued events best effort, because an app in the background must hold no connection.
FlagneticScope
Holds the client for the widgets below it and, unless observeLifecycle is off, attaches a FlagneticLifecycleObserver, so values follow the platform without any plumbing in the app.
FlagneticStore
Where a client keeps what must survive a restart: the last good values of each recent unit set, its event queue and its local overrides. Keys and values are strings; an implementation may answer synchronously or with a future. Shared preferences, secure storage or an app database all fit.
FlagSummary
One flag's current state, for a Dev Tools screen listing every flag: not an evaluation of it, so reading FlagneticClient.allFlags records nothing in the evaluation summary. Empty at stage built_in.
FlutterStore
The default FlagneticStore of a Flutter app: shared preferences for the small entries (the index of unit sets, anonymous unit IDs) and one file under the application support directory for each unit set's last good values, which are a whole evaluate response and do not belong in a preference.
InMemoryStore
A FlagneticStore in memory: nothing survives the process. The default store, and the one tests use.
LocalOverrides
Local overrides: substitutions of flag values inside this process that never reach the platform. An overridden flag reads reason local_override, with no experiment block and the stage unchanged, so exposure is a no-op for it. They exist only with the allowOverrides option and are refused in a protected environment. Obtain this through the client's overrides.
LogEvents
Stable log event names: alert on them.
OfflineMode
The test helpers of an offline client: no network at all, stage fresh, events recorded in memory.
OfflineSource
A document to serve instead of the network: a values document, exactly what remote evaluation returns. A document saved from the platform works as is.
Reasons
Evaluation reasons by wire name. A client key learns only that targeting decided a value, never which rule, rollout or prerequisite did, so the server answers it targetingMatch where it would answer a server key with a finer reason. The SDK produces localOverride and fallback. A reason the SDK does not know is passed through as it arrived.
StageListenable
The stage of a client's fallback chain as a ValueListenable: built_in until values arrive, fresh while the last attempt succeeded and last_good while it did not. A badge showing that a build is serving cached values reads this.
Status
The stage of a client and how long its values have been stale.
StoreKeys
The keys one SDK key writes. An app that talks to two environments, or to two installations, shares one store between them, and neither may serve the other's values or send the other's events under its own key. The SDK key, which is what names an environment of an installation, names every key; the unit set names only the values. The base URL takes no part: the same key behind a proxy, a renamed host or another port is the same environment.

Enums

LogLevel
The severity of a log event.
Stage
The step of the fallback chain a client serves from.

Functions

anonymousUnitId(FlagneticStore store, String unitType, {Logger? logger}) → Future<String>
The unit ID this device (this origin in a browser) uses for the anonymous unit type unitType, generating and persisting a random one the first time.
anonymousUnitIdKey(String unitType) → String
The store key holding the anonymous unit ID of unitType.
isLastGoodValuesKey(String key) → bool
True when key holds one unit set's last good values: a whole evaluate response, which a store may want to keep somewhere other than its small entries. The index of unit sets and an anonymous unit ID are not.

Typedefs

ChangeListener = void Function(List<String> changedKeys)
A listener of changed flag keys.
Logger = void Function(LogLevel level, String event, Map<String, Object?> fields)
Receives every log event: its level, a stable name from LogEvents and structured fields. Called synchronously; an exception it throws is swallowed.
StageListener = void Function(Stage stage)
A listener of stage transitions.
SummaryRow = ({int count, String flag, String reason, String? variation})
One row of an evaluation summary: one flag, one variation, one evaluation reason and how often it was served. No unit ID, attribute or flag value is in it, by construction.