Skip to main content
Official Angular SDK for Westyx Nexus - configuration and feature flags, delivered to the browser and kept current.

Latest release

v0.17.0

What’s new in v0.17.0

  • Breaking: getSecret() removed, along with NexusPublicKeyError and NexusSecretNotFoundError. 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, since appConfig is built once and every request bootstraps from it - and each injector gets its own client, its own NEXUS_CLIENT_READY promise 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.warn if 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 by getStreamConnectedSignal() 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. rxjs is an optional peer dependency. Breaking
  • 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() and getQuarantinedUntilSignal(), and two typed errors: NexusNotInitializedError and NexusDuplicateRegistrationError.
  • 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_INTEGER as its exact decimal string - at any depth, in objects and arrays alike, so the resolved value survives JSON.stringify. Ordinary numbers are untouched, and the scalar number resolution still answers TYPE_MISMATCH for 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. subscribe also 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 targetingKey selects a per-user boolean evaluation through the Nexus AB Testing add-on, so rollout percentages and cohort rules apply. The request happens on setContext, not on evaluation, so reading a flag stays synchronous; one round trip covers every flag in the snapshot. See OpenFeature.
  • The provider takes options: logger and addonSuppressionMs, validated at construction.
  • The provider’s resolutions were corrected: an unknown flag reports FLAG_NOT_FOUND rather than a static default, a number resolution no longer converts a boolean or a string into a number, and a JSON null is reported as a missing value rather than as 0.
  • hasFlag(key) and getFlagKeys() on the client - whether the service defines a flag at all, and every flag key in the snapshot.

Breaking changes

  • evaluateAB() and evaluateABStream() 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 that getFlag() performs.
  • getConfigSignal(), getStreamStateSignal(), getBillingOverdueSignal() and getSyncedAtSignal() join getFlagSignal().
  • The stream reaches its fallback. Three consecutive failures hand over to polling and the backoff advances.
  • provideAppInitializer() replaces APP_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 bigint rather 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 the Observable form and aborts on unsubscribe. evaluateABPromise() is gone.
  • NexusLogger takes structured fields: (message, fields?), with a warn level added.
  • ttlMs: 0 and an empty sseReconnectCooldown array are rejected rather than coerced into a zero delay.

Where to start

How it works

One bulk GET /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.