JavaScript SDK
Flipswitch providers for JavaScript/TypeScript — web and server — with real-time SSE support
The Flipswitch JavaScript providers are OpenFeature-compatible with automatic cache invalidation via Server-Sent Events (SSE). Use @flipswitch-io/web-provider for browser apps and @flipswitch-io/server-provider for Node.js.
GitHub: github.com/flipswitch-io/js-sdk
Installation
The SDK is split into two packages depending on your runtime environment:
Web (Browser)
npm install @flipswitch-io/web-provider @openfeature/web-sdkyarn add @flipswitch-io/web-provider @openfeature/web-sdkpnpm add @flipswitch-io/web-provider @openfeature/web-sdkServer (Node.js)
npm install @flipswitch-io/server-provider @openfeature/server-sdkyarn add @flipswitch-io/server-provider @openfeature/server-sdkpnpm add @flipswitch-io/server-provider @openfeature/server-sdkQuick Start
Browser (React, Vue, etc.)
import { FlipswitchWebProvider } from '@flipswitch-io/web-provider';
import { OpenFeature } from '@openfeature/web-sdk';
// Only API key is required
const provider = new FlipswitchWebProvider({
apiKey: 'YOUR_API_KEY'
});
// Register with OpenFeature
await OpenFeature.setProviderAndWait(provider);
// Get a client and evaluate flags
const client = OpenFeature.getClient();
const darkMode = await client.getBooleanValue('dark-mode', false);
const welcomeMessage = await client.getStringValue('welcome-message', 'Hello!');Node.js (Server)
import { FlipswitchServerProvider } from '@flipswitch-io/server-provider';
import { OpenFeature } from '@openfeature/server-sdk';
const provider = new FlipswitchServerProvider({
apiKey: 'YOUR_API_KEY'
});
await OpenFeature.setProviderAndWait(provider);
const client = OpenFeature.getClient();
// Evaluate with context
const context = {
targetingKey: 'user-123',
email: 'user@example.com',
plan: 'premium',
};
const showFeature = await client.getBooleanValue('new-feature', false, context);Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | required | Environment API key from dashboard |
baseUrl | string | https://api.flipswitch.io | Your Flipswitch server URL |
enableRealtime | boolean | true | Enable SSE for real-time flag updates |
fetchImplementation | typeof fetch | fetch | Custom fetch function |
persistCache | boolean | true (browser) | Persist flag values to localStorage |
offlineMode | boolean | true (browser) | Enable offline support with cached values |
enableVisibilityHandling | boolean | true (browser) | Pause SSE when tab is hidden |
enablePollingFallback | boolean | true | Fall back to polling when SSE fails |
pollingInterval | number | 30000 | Polling interval in ms (fallback mode) |
maxSseRetries | number | 5 | Max SSE retries before polling fallback |
// Web provider example (FlipswitchServerProvider accepts the same core options)
const provider = new FlipswitchWebProvider({
apiKey: 'YOUR_API_KEY',
baseUrl: 'https://api.flipswitch.io',
enableRealtime: true,
enablePollingFallback: true,
pollingInterval: 30000,
maxSseRetries: 5,
// Browser-specific options (web provider only)
persistCache: true,
offlineMode: true,
enableVisibilityHandling: true,
});Real-Time Updates
When enableRealtime is enabled (default), the SDK maintains an SSE connection to receive instant flag changes:
- The SSE client receives a
flag-updatedorconfig-updatedevent - The local cache is immediately invalidated
- Next flag evaluation fetches the fresh value
- OpenFeature emits a
PROVIDER_CONFIGURATION_CHANGEDevent
Event Handlers
// Works with both FlipswitchWebProvider and FlipswitchServerProvider
const provider = new FlipswitchWebProvider(
{ apiKey: 'YOUR_API_KEY' },
{
onFlagChange: (event) => {
console.log(`Flag changed: ${event.flagKey ?? 'all flags'}`);
// event.flagKey is null for bulk invalidation
},
onConnectionStatusChange: (status) => {
console.log(`SSE status: ${status}`);
// 'connecting' | 'connected' | 'disconnected' | 'error'
},
}
);Connection Status
// Check current SSE status
const status = provider.getSseStatus();
// 'connecting' | 'connected' | 'disconnected' | 'error'
// Force reconnect
provider.reconnectSse();React Integration
import { OpenFeature, OpenFeatureProvider, useFlag } from '@openfeature/react-sdk';
import { FlipswitchWebProvider } from '@flipswitch-io/web-provider';
// Initialize provider (do this once at app startup)
const provider = new FlipswitchWebProvider({
apiKey: 'YOUR_API_KEY',
});
await OpenFeature.setProviderAndWait(provider);
function App() {
return (
<OpenFeatureProvider>
<MyComponent />
</OpenFeatureProvider>
);
}
function MyComponent() {
const { value: darkMode } = useFlag('dark-mode', false);
return (
<div className={darkMode ? 'dark' : 'light'}>
Dark mode is {darkMode ? 'enabled' : 'disabled'}
</div>
);
}The useFlag hook automatically re-renders when flags change via SSE.
Evaluation Context
Pass user attributes for targeting:
const context = {
targetingKey: 'user-123', // Required: unique user identifier
email: 'user@example.com',
plan: 'premium',
country: 'SE',
version: '2.1.0',
};
const showFeature = await client.getBooleanValue('feature', false, context);Bulk Flag Evaluation
Evaluate all flags at once or get detailed evaluation results:
// Evaluate all flags
const flags = await provider.evaluateAllFlags(context);
for (const flag of flags) {
console.log(`${flag.key} (${flag.valueType}): ${flag.value}`);
}
// Evaluate a single flag with full details
const flag = await provider.evaluateFlag('dark-mode', context);
if (flag) {
console.log(`Value: ${flag.value}, Reason: ${flag.reason}, Variant: ${flag.variant}`);
}Browser Features
Offline Support
When offline mode is enabled, the SDK serves cached values when offline:
const provider = new FlipswitchWebProvider({
apiKey: 'YOUR_API_KEY',
offlineMode: true, // Enable offline support
persistCache: true, // Persist to localStorage
});
// Check online status
if (provider.isOnline()) {
console.log('Online - flags are fresh');
} else {
console.log('Offline - serving cached values');
}Visibility API Integration
The SDK automatically pauses SSE when the browser tab is hidden to save resources:
const provider = new FlipswitchWebProvider({
apiKey: 'YOUR_API_KEY',
enableVisibilityHandling: true, // default: true in browsers
});
// Connection is paused when tab is hidden, resumes when visiblePolling Fallback
When SSE connection fails repeatedly, the SDK falls back to polling:
const provider = new FlipswitchWebProvider({
apiKey: 'YOUR_API_KEY',
enablePollingFallback: true, // default: true
pollingInterval: 30000, // Poll every 30 seconds
maxSseRetries: 5, // Fall back after 5 failed SSE attempts
});
// Check if polling is active
if (provider.isPollingActive()) {
console.log('Polling fallback is active');
}Reconnection Strategy
The SSE client automatically reconnects with exponential backoff:
- Initial delay: 1 second
- Maximum delay: 30 seconds
- Backoff multiplier: 2x
When reconnected, the provider status changes from STALE back to READY.
TypeScript Support
The SDK is written in TypeScript and provides full type definitions:
import type { FlipswitchWebProvider, FlipswitchConfig, SseStatus } from '@flipswitch-io/web-provider';
import type { FlipswitchServerProvider } from '@flipswitch-io/server-provider';Troubleshooting
SSE connection keeps disconnecting
Check if your server or proxy supports long-lived connections. Some proxies timeout after 30-60 seconds.
Flags not updating in real-time
Verify that enableRealtime is true (default) and check the SSE status:
console.log(provider.getSseStatus());CORS errors
Ensure your Flipswitch server has CORS configured to allow requests from your domain.