Latest release
v0.17.0What’s new in v0.17.0
- Breaking:
getSecret()removed, along withNexusPublicKeyErrorandNexusSecretNotFoundError. This SDK only ever holds a public key, and the backend never sends a secret to one, so the method could only ever throw. No change needed unless your code called it.
What’s new in v0.16.0
- The client belongs to the injector that registered it. One
provideNexus()value can register any number of environment injectors - which is what a server-rendered application does, sinceappConfigis built once and every request bootstraps from it - and each injector gets its own client, its ownNEXUS_CLIENT_READYpromise and its own teardown. A request finishing releases only what it created. See API reference.
What’s new in v0.15.0
- A live stream that never connects is reported. When the client gives up before its first successful connection it says so once - through the logger you configured, or on
console.warnif you configured none. Reads keep succeeding on the TTL in that state, so without this a template looks healthy and its values simply stop changing. A connection lost after connecting is reported bygetStreamConnectedSignal()instead. See SSE live updates. - The stream request carries only the API key and
Accept. Both are all the server needs, which is one fewer name a deployment’s CORS configuration has to allow.
What’s new in v0.14.0
- A signal bound in a template stays current while the live stream is unavailable. The TTL drives the refresh in that state, and the registration invalidates the signals when the snapshot reaches it. The request is still made by a read: an application that binds no signal makes no requests.
- The RxJS-shaped AB evaluation lives in its own entry point,
@westyx-nexus/sdk-angular/rxjs- 6 366 bytes (2 147 gzipped) off the package for a consumer who does not use it.rxjsis an optional peer dependency. Breaking- see Installation.
NEXUS_CLIENT_READY- the client as a promise, for an application initializer that has to hold it during bootstrap. Angular starts every initializer before awaiting any of them, so this is what orders yours after the SDK’s.getStreamConnectedSignal()andgetQuarantinedUntilSignal(), and two typed errors:NexusNotInitializedErrorandNexusDuplicateRegistrationError.- An unchanged value no longer re-renders. An object-valued config signal and
getSyncedAtSignal()keep their value across a sync that changed nothing.
What’s new in v0.13.0
- A composite (object or array) resolution in the OpenFeature bridge carries an
integer beyond
Number.MAX_SAFE_INTEGERas its exact decimal string - at any depth, in objects and arrays alike, so the resolved value survivesJSON.stringify. Ordinary numbers are untouched, and the scalar number resolution still answersTYPE_MISMATCHfor the same value.
What’s new in v0.12.1
- The OpenFeature provider re-fetches targeted values only when the configuration
actually changed. The client reports every observable change, a stream state
transition included; the provider tells the two apart through
NexusClient.snapshotRevision, so a reconnect or a fall-back-to-polling costs no request and triggers no re-render. NexusClient.snapshotRevision- how many times the snapshot’s contents have been replaced.subscribealso fires for connection state and for the billing and quarantine flags, and this is what distinguishes a configuration change from those.- Closing the provider releases the identity it was holding, including from a refresh that had been requested but not yet sent.
- The bridge requires this SDK at
>=0.12.1, and its published type entry points resolve correctly from both ESM and CommonJS consumers.
What’s new in v0.12.0
- The OpenFeature provider resolves per user. An evaluation context carrying a
targetingKeyselects a per-user boolean evaluation through the Nexus AB Testing add-on, so rollout percentages and cohort rules apply. The request happens onsetContext, not on evaluation, so reading a flag stays synchronous; one round trip covers every flag in the snapshot. See OpenFeature. - The provider takes options:
loggerandaddonSuppressionMs, validated at construction. - The provider’s resolutions were corrected: an unknown flag reports
FLAG_NOT_FOUNDrather than a static default, a number resolution no longer converts a boolean or a string into a number, and a JSONnullis reported as a missing value rather than as0. hasFlag(key)andgetFlagKeys()on the client - whether the service defines a flag at all, and every flag key in the snapshot.
Breaking changes
evaluateAB()andevaluateABStream()take string attribute values (Record<string, string>). The endpoint’s request type is string-to-string and answers anything else with a 400, so a call passing a number or a boolean was already failing; it is a compile error now.
What’s new in v0.11.0
This release rebuilds the client on a core shared with the React and Vue SDKs, so the three behave identically.- Signals participate in the cache’s TTL. A component bound to
getFlagSignal()keeps its data current; reading through a signal previously bypassed the freshness check thatgetFlag()performs. getConfigSignal(),getStreamStateSignal(),getBillingOverdueSignal()andgetSyncedAtSignal()joingetFlagSignal().- The stream reaches its fallback. Three consecutive failures hand over to polling and the backoff advances.
provideAppInitializer()replacesAPP_INITIALIZER, deprecated in Angular 19.- Destroying the injector releases everything - including when it is destroyed while the initial sync is still running.
- Every request has a deadline, and the stream carries both a connect deadline and a liveness deadline that every received byte resets.
- A refresh is coalesced, and a slow response can never be applied over a newer one.
- Large integers survive the decode. An integer above 2^53 arrives as a
bigintrather than rounded. - Configuration is validated at construction, naming the option, the reason and the value.
- Tested on Angular 20 and 22.
Breaking changes
- The peer range is now
>=20.0.0. Angular 17, 18 and 19 have reached end of support upstream; the floor is the oldest release Angular itself still supports, and both ends are exercised in CI. - A public key (
wxp_) is now required; any other key is rejected at construction. evaluateAB()returns a promise;evaluateABStream()is theObservableform and aborts on unsubscribe.evaluateABPromise()is gone.NexusLoggertakes structured fields:(message, fields?), with awarnlevel added.ttlMs: 0and an emptysseReconnectCooldownarray are rejected rather than coerced into a zero delay.
Where to start
- Installation - the registry, the token, the key
- Quick start - a working provider and your first flag
- API reference - every member and option
- Caching behaviour - when it refreshes, and what happens when the server pushes back
How it works
One bulkGET /v1/sync fills an in-memory snapshot before the application
renders. A live event stream pushes changes as they happen; when it is
unavailable the TTL drives polling instead, and reads keep being served from the
last snapshot throughout. A read never blocks.
Public keys only
A browser SDK ships inside a bundle any visitor can read, so it accepts only a public key (wxp_). Public keys cannot read secrets, and the backend’s
Double-Gate check ties them to one service host. Secrets belong in a backend SDK.
