OpenFeature
Shipeasy ships OpenFeature providers (CNCF OpenFeature parity) so apps standardized on the OpenFeature API can plug Shipeasy in as the backing provider. The…
/docs/ — also served raw at https://shipeasy-ai.github.io/sdk-ts/pages/openfeature.md.Shipeasy ships OpenFeature providers (CNCF OpenFeature parity) so apps standardized on the OpenFeature API can plug Shipeasy in as the backing provider. The provider is a pure adapter over the SDK's local evaluation — no change to how flags resolve.
They live in their own package, so @shipeasy/sdk itself stays peer-free:
npm install @shipeasy/openfeature| Entrypoint | Pair with | Peers |
|---|---|---|
@shipeasy/openfeature/server | @openfeature/server-sdk | @openfeature/server-sdk, @shipeasy/sdk |
@shipeasy/openfeature/web | @openfeature/web-sdk | @openfeature/web-sdk, @shipeasy/sdk |
@shipeasy/sdk is a peer, not a dependency: the provider wraps the engine your
configure() call already built, so it must resolve to the same installed copy.
The provider class is named ShipeasyProvider.
Server provider
Construct new ShipeasyProvider() with no argument — the global form
resolves the engine that configure({ apiKey }) already built. Always
configure() first:
import { OpenFeature } from "@openfeature/server-sdk";
import { configure } from "@shipeasy/sdk/server";
import { ShipeasyProvider } from "@shipeasy/openfeature/server";
// 1. Configure the SDK once at app boot (server key).
configure({ apiKey: process.env.SHIPEASY_SERVER_KEY! });
// 2. Register the provider — no-arg form resolves the configured engine.
await OpenFeature.setProviderAndWait(new ShipeasyProvider());
// 3. Read through the OpenFeature client.
const ofClient = OpenFeature.getClient();
const on = await ofClient.getBooleanValue("new_checkout", false, { targetingKey: "u1" });The provider's initialize() runs the SDK's one-shot rules fetch (the SDK fires
Ready when the blob resolves) and onClose() tears the configuration down.
Type / reason mapping
getBooleanValue→getFlagDetail— the gate'sFlagReasonmaps to an OpenFeature reason (RULE_MATCH→TARGETING_MATCH,DEFAULT→DEFAULT,FLAG_NOT_FOUND→ERROR/FLAG_NOT_FOUND,CLIENT_NOT_READY→PROVIDER_NOT_READY).getStringValue/getNumberValue/getObjectValue→getConfig, with aTYPE_MISMATCHerror code when the stored config value doesn't match the requested type.
The EvaluationContext.targetingKey becomes the bucketing user_id.
Tracking
The provider's OpenFeature track() forwards to the SDK's track() (no-op
without a targetingKey), so conversions for experiment analysis flow through
the same pipeline.
Testing
For unit tests, swap the live configure() for configureForTesting() — a drop-in sibling with no network, ever (no SDK key required). It replaces the active…
Advanced
LaunchDarkly / Statsig parity features. All are set as options on configure() (or on shipeasy() for SSR), or read through the bound Client.