@ezmodo/flags-sdk
v0.1.0
Published
Isomorphic client SDK for evaluating ezmodo feature flags with a publishable client key
Readme
@ezmodo/flags-sdk
Isomorphic JS/TS client for evaluating ezmodo feature
flags from untrusted code (browser, mobile, Node 18+) using a publishable
client key (ezm_ck_…, scope client:eval).
Evaluation is server-side: the SDK ships inputs to the public endpoint and returns the server's result. It never re-implements evaluation — targeting rules, rollout buckets, and other-environment config stay on the server, so it is safe to ship the key in a client.
Full guide: vanilla JS / React-Next / Node quickstart + complete API reference is at
docs/public/help/flags-sdk.md. A runnable React example is inexamples/react.
Install
npm install @ezmodo/flags-sdkGet a publishable key in ezmodo: Settings → API keys → Create → "Client key
(publishable)". It starts with ezm_ck_ and is safe to embed in client code
(it can only evaluate flags for the workspaces you select).
Usage
import { createClient } from '@ezmodo/flags-sdk'
const flags = createClient({
publishableKey: 'ezm_ck_…',
organizationId: 'org_123',
environment: 'production', // optional; omitted → the flag's scope default
})
// Boolean flag with a safe default (never throws)
if (await flags.boolVariation('new-checkout', false)) {
// …
}
// Multivariate / config value with a safe default (never throws)
const color = await flags.variation('theme-color', '#000000', {
subjectId: 'user-1',
attributes: { plan: 'pro' },
})
// Raw result (throws FlagsClientError on request failure)
const result = await flags.evaluate('new-checkout', { subjectId: 'user-1' })
// → { on, variantKey?, value?, reason }
// Batch — one round trip for the same subject
const results = await flags.evaluateAll(['a', 'b'], { subjectId: 'user-1' })evaluateAll, variation, and boolVariation never throw — failed reads fall
back to the last-known-good cached value or your default. evaluate returns a
cached fallback when available, otherwise throws
FlagsClientError.
Caching, batching & resilience
The client is efficient and flaky-network safe by default:
- Caching — results are cached by
(flagKey, subjectId, environment)for a TTL window (default 30s, aligned to the server flag-cache). Disable withcache: falseor tune withcache: { ttlMs }. - Batching — concurrent
evaluatecalls made in the same tick are coalesced into a single/evaluate/batchrequest, and identical in-flight requests are deduped. Disable withbatch: false. - Last-known-good — when a refresh fails, a cached value (even expired) is
returned before falling back to a caller default. Observe failures via
onError. - Prefetch —
await flags.prefetch(['a', 'b'])warms the cache on init.
const flags = createClient({
publishableKey: 'ezm_ck_…',
organizationId: 'org_123',
cache: { ttlMs: 60_000 },
onError: (err, { flagKeys }) => console.warn('flag eval failed', flagKeys, err),
})
await flags.prefetch(['new-checkout', 'theme-color'])Build & test
npm run build # dual-format ESM + CJS into dist/
npm run type-check
npm test