@westyx-nexus/openfeature-provider-angular sub-package provides an OpenFeature Provider that wraps an existing NexusClient from @westyx-nexus/sdk-angular.
No second connection is opened and no second cache is kept. The bridge subscribes to the same NexusClient that the rest of your application uses. Whenever the client replaces its in-memory snapshot (TTL poll or stream push), the provider emits ProviderEvents.ConfigurationChanged so the OpenFeature SDK re-evaluates.
Installation
The bridge is a separate npm package:@westyx-nexus/sdk-angular package is the peer dependency - you already have it.
npm registry
Both packages are on the GitLab npm Package Registry. Add to your.npmrc:
Usage
Wiring up in app.config.ts
setProviderAndWait has completed before the first evaluation.
Reading flags
Using@openfeature/angular-sdk:
NgModule-based apps
Per-user targeting
When the evaluation context carries atargetingKey, a boolean evaluation is resolved for that user through the Nexus AB Testing add-on: the flag’s rollout percentage and cohort rules are applied to that identity, and the resolution reports TARGETING_MATCH.
Where the request happens
resolveBooleanEvaluation is synchronous in the OpenFeature Web SDK - there is no promise for it to await - and the Web SDK’s paradigm is a static evaluation context. So the provider asks the service when the context changes, not when a flag is read:
One round trip covers every flag in the snapshot, so a page reading twenty flags costs one request, and concurrent triggers for the same identity coalesce into one. A snapshot with more than 200 flags is split into successive calls, which is the endpoint’s documented cap.
Attributes are strings
The service’s cohort matcher compares strings witheq / neq / in, so only string context fields are sent. A non-string field is left out and reported at debug level rather than converted - a coerced value that matches no rule is harder to diagnose than an absent one. Format at the call site (String(age), not age) and you know exactly what the rule is matched against.
targetingKey is sent as the identity, never also as an attribute.
Reasons you will see
If the add-on is not active
Projects without the AB Testing add-on get a403 from the endpoint. The provider serves the snapshot with a STATIC reason and stops asking for five minutes at a time (addonSuppressionMs), so an inactive add-on costs one request per window rather than one per context change. It is a throttle, not a latch: buying the add-on starts producing targeted results within the window, with nothing to restart, and any success clears it immediately.
Provider options
There is deliberately no cache-lifetime option, unlike the server-side bridges. The targeted values are replaced on a context change and on a configuration change - both events rather than deadlines - so a time-to-live would have nothing to govern.
Flag resolution
Boolean flags come from feature flags; string, number and object evaluations come from config values. Config values are never targeted -
evaluate-ab is a flag concept, so there is no such thing as a targeted config value.
Inside a resolved object or array, an integer beyond Number.MAX_SAFE_INTEGER is carried as its exact decimal string, at any depth - OpenFeature’s JsonValue has no numeric slot that holds it exactly, and the decimal string is the lossless one, so the resolved value survives JSON.stringify. Ordinary numbers are untouched; parse the string with BigInt(value) where the magnitude matters.
A TYPE_MISMATCH message names the type that arrived, so it is actionable without opening the configuration.
Live updates
The provider callsclient.subscribe(listener) in initialize() and stores the returned unsubscribe function. When the NexusClient replaces its snapshot the listener fires, the provider emits ProviderEvents.ConfigurationChanged, and the OpenFeature SDK re-evaluates - so any UI using @openfeature/angular-sdk re-renders. The client’s listener also fires for a stream state transition, for a 304 and for the billing and quarantine flags, none of which changed a flag; the provider compares client.snapshotRevision and acts only on a real configuration change, so a reconnect costs no request and triggers no re-render.
The same listener re-asks for the targeted values. That refresh emits a second ConfigurationChanged only when the values actually moved: announcing an unchanged refresh would re-render every component bound to a flag on every sync.
onClose() unsubscribes the listener and drops the stored identity.
NexusClientLike interface
The provider’s constructor accepts a NexusClientLike interface rather than the concrete NexusClient class, so the package needs no build-time dependency on @westyx-nexus/sdk-angular - an Angular library’s typings live in its build output. Any object satisfying it works:
NexusClient inherits every member from the shared browser core.
Version
Latest release: v0.17.0. The bridge requires @westyx-nexus/sdk-angular v0.17.0 or newer - it is declared as a peer dependency, so npm will tell you if the two are out of step. The floor follows the release, so a consumer never resolves an SDK older than the bridge that wraps it.@openfeature/core is a direct dependency of the bridge. @openfeature/web-sdk declares it as a peer and imports it at runtime, so it must be present; it is resolved for you.