@omniretail/omniflags-core
v1.0.25
Published
OmniFlags feature flag SDK — core evaluator, cache, and transport
Readme
@omniretail/omniflags-core
JavaScript/TypeScript SDK for OmniFlags.
Installation
npm install @omniretail/omniflags-coreQuick start
import { OmniFlagsClient } from "@omniretail/omniflags-core";
const client = new OmniFlagsClient({ sdkKey: "your-sdk-key" });
await client.waitForReady();
const enabled = client.isEnabled("store.dark-mode");
const theme = client.getString("store.theme", "light");Configuration
const client = new OmniFlagsClient({
sdkKey: "your-sdk-key", // required
hooks: [loggingHook], // optional evaluation hooks
});| Option | Type | Description |
|--------|------|-------------|
| sdkKey | string | Required. SDK key from the OmniFlags dashboard. |
| hooks | Hook[] | Lifecycle hooks called before/after each evaluation. |
Evaluation
Flag keys are namespaced by project: {projectKey}.{flagKey}.
// Boolean
client.isEnabled("store.show-banner");
client.isEnabled("store.show-banner", { customerId: "cust-123" }); // with context
// Typed value methods
client.getBoolean("store.dark-mode", false);
client.getString("store.theme", "light");
client.getNumber("store.max-items", 10);
// Generic — useful when the type is only known at runtime
client.getValue<{ color: string }>("store.config", defaultConfig);
// Full evaluation result (variant, reason, rule matched)
const result = client.getVariant("store.show-banner");
// result.value, result.variant, result.reason, result.ruleId, result.errorCodeContext
Pass context per evaluation call — customer, business, branch, country, etc. There is no persistent context state on the client.
const ctx = {
customerId: request.customerId,
agentId: request.agentId,
businessId: request.businessId,
businessBranchId: request.businessBranchId,
};
client.isEnabled("store.show-banner", ctx);
client.getString("store.theme", "light", ctx);Loading state
const state = client.loadingState;
// state.isFetching — a network request is in flight
// state.isLoading — no flags have been loaded yet (first fetch pending)
// state.origin — "NONE" | "CACHE" | "SERVER"
// state.error — last fetch error, or nullSubscribe to changes:
const unsub = client.on("PROVIDER_LOADING_STATE_CHANGED", () => {
console.log(client.loadingState);
});
unsub(); // remove the listenerStatus & lifecycle
client.status; // "not_ready" | "ready" | "stale" | "error"
await client.waitForReady(); // resolves after the first fetch or cache hit
await client.shutdown(); // stop polling and flush metricsThe SDK polls for flag updates automatically on a server-driven interval (default: 5 minutes).
Events
const unsub = client.on("PROVIDER_CONFIGURATION_CHANGED", () => {
// flags updated
});
unsub(); // remove the listener| Event | When |
|-------|------|
| PROVIDER_READY | First snapshot loaded |
| PROVIDER_STALE | Fetch failed but cached flags are available |
| PROVIDER_ERROR | Fetch failed and no cache |
| PROVIDER_CONFIGURATION_CHANGED | Flags updated by a background poll |
| PROVIDER_LOADING_STATE_CHANGED | Loading state changed |
Hooks
import type { Hook } from "@omniretail/omniflags-core";
const loggingHook: Hook = {
after(flagKey, result) {
console.log(`[flag] ${flagKey} → ${result.variant} (${result.reason})`);
},
};
const client = new OmniFlagsClient({ sdkKey: "your-sdk-key", hooks: [loggingHook] });
// Or add after construction
client.addHook(loggingHook);Metrics
Flag evaluations are tracked and flushed to OmniFlags automatically. The flush interval and batch size are driven by the server — no configuration needed.
