Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions packages/react-native-openfeature/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,50 @@ precomputed-only `configurationFromString` helper.
`Error`. Loading a usable configuration after an error emits `Ready`, followed by
`ConfigurationChanged`.

### Fetching rules configuration

Use `fetchRulesConfiguration` from the `/rules-based` entry point to fetch client-distributed rules and decode them into a `FlagsConfiguration`. Like the browser helper, it accepts `clientToken`, `env`, an optional site domain, an optional `flagSelection`, an optional `fetch` implementation, and an optional `AbortSignal`. An optional `logger` receives selection diagnostics and defaults to `console`. The helper does not require native SDK initialization or `DdFlags.enable()`.

```tsx
import {
DatadogCoreProvider,
fetchRulesConfiguration
} from '@datadog/mobile-react-native-openfeature/rules-based';
import { OpenFeature } from '@openfeature/react-sdk';

const fetchOptions = {
clientToken: '<CLIENT_TOKEN>',
env: 'production',
site: 'datadoghq.com',
flagSelection: { tags: ['team:checkout'], keyPatterns: ['checkout-*'] }
};
const provider = new DatadogCoreProvider();
provider.setConfiguration(await fetchRulesConfiguration(fetchOptions));
await OpenFeature.setProviderAndWait('datadog-core', provider, {
targetingKey: 'user-123', country: 'US'
});
const client = OpenFeature.getClient('datadog-core');
const enabled = client.getBooleanValue('checkout-new-flow', false);

// Context changes evaluate the loaded rules locally, without another request.
await OpenFeature.setContext('datadog-core', {
targetingKey: 'user-456', country: 'CA'
});

// Refresh explicitly when the application needs new rules.
provider.setConfiguration(await fetchRulesConfiguration(fetchOptions));
```

The helper makes one request per call, with no automatic polling, retries, persistence, or tracking. It rejects on HTTP, network, cancellation, body-read, or decoding failures. Catch refresh errors before replacing the provider configuration to keep evaluating the last successfully loaded rules. Use a client token; the helper only requests client-distributed configuration, never server-distributed rules.

`flagSelection` requests flags matching any of the listed tags or key patterns (OR). Tags are exact, case-sensitive matches; key patterns are case-sensitive and match the whole key, with `*` matching any run of characters. Values are trimmed using Unicode whitespace, deduplicated, and sorted by UTF-8 bytes. Each list accepts at most 31 distinct nonempty values after normalization, and each value can contain at most 200 UTF-8 bytes. Empty selections are omitted quietly.

Selection is best-effort: a malformed or over-limit selection, or one that makes the encoded request URL exceed 8,192 bytes, is not sent. The helper logs an error and requests the full configuration instead. A nonempty `DD-Flag-Selection-Ignored` response header also produces an error diagnostic when a selection was sent. Supply `logger: { error(message) { /* route diagnostics */ } }` to customize reporting. Diagnostics do not initialize the native SDK or send telemetry, and a throwing logger does not prevent configuration loading.

When the backend applies selection, flags outside it are absent from the returned configuration. Evaluating them returns your default value with `FLAG_NOT_FOUND`, so select every flag the app evaluates. Selection is not an access-control boundary: the helper retains the full returned configuration if the server ignores selection and does not filter it locally.

`site` uses a domain such as `datadoghq.com` or `datadoghq.eu`, not the native SDK's `US1` or `EU1` identifiers. The default is `datadoghq.com`. Fetching and evaluation do not register tracking; use the hooks below when tracking is needed.

### Optional tracking with DatadogCoreProvider (Android only)

Register exposure, evaluation, and RUM hooks independently with the evaluation-only
Expand Down
5 changes: 3 additions & 2 deletions packages/react-native-openfeature/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,17 @@
"scripts": {
"test": "jest",
"lint": "eslint .",
"prepare": "rm -rf lib && yarn bob build"
"prepare": "genversion --es6 --semi src/version.ts && rm -rf lib && yarn bob build"
},
"dependencies": {
"@datadog/flagging-core": "3.1.1"
"@datadog/flagging-core": "3.3.0"
},
"devDependencies": {
"@datadog/mobile-react-native": "^3.11.0",
"@openfeature/core": "^1.9.2",
"@openfeature/web-sdk": "^1.8.0",
"@testing-library/react-native": "7.0.2",
"genversion": "3.0.2",
"react-native-builder-bob": "0.26.0",
"react-native-gesture-handler": "1.10.3"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Shared Flag Selection Vectors

`selection-vectors.json` is copied unchanged from [DataDog/ffe-system-test-data](https://github.com/DataDog/ffe-system-test-data/blob/caa6d1ac3e5fbda0ce57ef3ffff3772901f3f466/flag-selection/selection-vectors.json) at commit `caa6d1ac3e5fbda0ce57ef3ffff3772901f3f466`.

The fetch-helper tests consume all 38 `sdk` expectations. Raw-query percent-decoding and server-side `selectedKeys` expectations are not SDK transport behavior and are not exercised here. Test runs use this checked-in snapshot without network access. Update shared expectations upstream, then replace this file from a pinned commit and update this provenance and the SDK-case count assertion together.
Loading