Skip to content
NanoFlags
Start free

SDKs

OpenFeature

An OpenFeature provider for the JavaScript server SDK (@openfeature/server-sdk) and web SDK (@openfeature/web-sdk). It wraps a NanoFlags client: evaluation stays local and synchronous inside the provider, and the NanoFlags client keeps doing the loading, live updates and polling.

Install

sh
npm install @nanoflags/openfeature-provider @nanoflags/sdk @openfeature/server-sdk   # or @openfeature/web-sdk

Server

ts
import { OpenFeature } from "@openfeature/server-sdk";
import { createClient } from "@nanoflags/sdk";
import { NanoFlagsProvider } from "@nanoflags/openfeature-provider/server";

const nanoflags = createClient({ sdkKey: process.env.NANOFLAGS_SDK_KEY!, baseUrl: "https://edge.nanoflags.io", service: "checkout-api" });
await OpenFeature.setProviderAndWait(new NanoFlagsProvider({ client: nanoflags }));

const client = OpenFeature.getClient();
const enabled = await client.getBooleanValue("checkout-v2", false, { targetingKey: user.id, signedIn: true, region: "US" });

Web

ts
import { OpenFeature } from "@openfeature/web-sdk";
import { createClient } from "@nanoflags/sdk";
import { NanoFlagsWebProvider } from "@nanoflags/openfeature-provider/web";

const nanoflags = createClient({ sdkKey: "nf_pub_…", baseUrl: "https://edge.nanoflags.io" });
await OpenFeature.setContext({ targetingKey: user.id, plan: user.plan });
await OpenFeature.setProviderAndWait(new NanoFlagsWebProvider({ client: nanoflags }));

const ranking = OpenFeature.getClient().getStringValue("search-ranking", "relevance-v2");

Options

OptionDefaultDescription
clientrequiredA @nanoflags/sdk client.
closeClientfalseClose the NanoFlags client when the provider shuts down.
evaluatorthe clientFunction returning an object with evaluate; redirects evaluations, for example to the current request's test session.
ts
import { flagsFor } from "@nanoflags/sdk/node";
new NanoFlagsProvider({ client: nanoflags, evaluator: () => flagsFor(nanoflags) });

What is supported

OpenFeatureNanoFlags
resolveBoolean/String/Number/ObjectEvaluationboolean, string, number, json flags. Object resolution accepts any JSON value (a json flag may hold a string or a number).
targetingKeyContext attribute key, the identity used for rollout bucketing. It overrides an attribute named key.
Other context attributesPassed through. Date values become ISO strings. Non-finite numbers and undefined are dropped.
reasonTARGETING_MATCH (a fixed-value rule matched) · SPLIT (a rollout rule matched, in or out of the allocation) · DEFAULT (no rule matched) · DISABLED (flag off, off value served) · ERROR.
variantThe id of the matching rule, when a rule matched. Otherwise absent.
flagMetadata{ revision }: the revision the value came from.
Errors (default value returned, reason ERROR)FLAG_NOT_FOUND (unknown, archived, or not client-exposed with a client key) · TYPE_MISMATCH · GENERAL (malformed configuration) · PROVIDER_NOT_READY (nothing loaded yet).
Provider status and eventsREADY when a current bundle is in use · STALE when the bundle is not known to be current (evaluations continue) · ERROR when initialization ends without any configuration (READY follows once one arrives) · CONFIGURATION_CHANGED for every new revision, with metadata.revision.
Web SDK context changesEvaluation is local, so a new context applies to the next evaluation without a network round trip.
Hooks, domains, context merging, evaluation detailsProvided by the OpenFeature SDK and unaffected.

What is not supported

  • Named variants. Rules serve values, not named variants; variant carries the rule id and is absent for DEFAULT and DISABLED.
  • flagsChanged on CONFIGURATION_CHANGED: the event says that a new revision is in use, not which flags differ.
  • Tracking (track) is not implemented. NanoFlags' own sampled telemetry is configured on the SDK client.
  • Provider hooks, PROVIDER_FATAL and RECONCILING are not emitted. A revoked or wrong key surfaces as ERROR (no configuration) or STALE (a configuration was already loaded).
  • Reasons STATIC, CACHED and TARGETING_KEY_MISSING are not used. A rollout evaluated without a targeting key is treated as outside the allocation and reported as SPLIT.
  • Other languages: this page covers the JavaScript/TypeScript provider. Python and Go have their own providers (Python, Go); every other language can use an OFREP provider.
  • STALE and ERROR describe the client's configuration, not individual flags; a flag evaluated while STALE reports its normal reason.
The provider is tested through the real OpenFeature SDKs for the surface listed above. This is not a claim of conformance beyond that surface.