
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@flagdeck/js
Advanced tools
The official JavaScript/TypeScript SDK for Flagdeck, a modern feature flag and feature management system.
npm install @flagdeck/js
# or
yarn add @flagdeck/js
import { Flagdeck } from '@flagdeck/js';
// Initialize the client
const flagdeck = new Flagdeck({
apiKey: 'your-api-key'
});
// Check if a feature flag is enabled
async function checkFeature() {
const isEnabled = await flagdeck.isEnabled('new-feature', {
userId: 'user-123',
attributes: {
country: 'US',
plan: 'premium'
}
});
if (isEnabled) {
// Feature is enabled for this user
enableNewFeature();
} else {
// Feature is disabled
useDefaultFeature();
}
}
The SDK automatically detects your environment (browser or Node.js) and uses the appropriate implementation. If you want to explicitly import a specific version:
import { Flagdeck } from '@flagdeck/js/browser';
const flagdeck = new Flagdeck({
apiKey: 'your-api-key'
});
import { Flagdeck } from '@flagdeck/js/node';
const flagdeck = new Flagdeck({
apiKey: 'your-api-key'
});
Flagdeck supports multiple value types for feature flags:
// Check if a feature is enabled
const isEnabled = await flagdeck.isEnabled('new-feature');
if (isEnabled) {
showNewFeature();
}
// Get a string variant value with default
const variant = await flagdeck.getValue<string>('experiment-variant', context, 'control');
if (variant === 'A') {
// Show variant A
} else if (variant === 'B') {
// Show variant B
}
// Get a numeric configuration value with default
const limit = await flagdeck.getValue<number>('rate-limit', context, 100);
applyRateLimit(limit);
// Get complex configuration with TypeScript type
const config = await flagdeck.getValue<{
url: string;
timeout: number;
retries: number;
}>('api-config', context, { url: 'default.com', timeout: 5000, retries: 3 });
When you need additional metadata about an evaluation:
// Get the full evaluation result
const result = await flagdeck.evaluateFlag('new-feature', context);
console.log(`Feature is ${result.value ? 'enabled' : 'disabled'}`);
console.log(`Source: ${result.source}`); // 'api', 'cache', etc.
console.log(`Reason: ${result.reason}`);
console.log(`Evaluated at: ${new Date(result.timestamp)}`);
// Get multiple flag values in a single request
const values = await flagdeck.getValues([
'feature-a',
'rate-limit',
'experiment'
], context);
console.log(values['feature-a']); // boolean
console.log(values['rate-limit']); // number
console.log(values['experiment']); // string
Flagdeck supports real-time flag updates, allowing your application to instantly react to flag changes made in the Flagdeck dashboard without requiring page refreshes or API polling.
Real-time updates are enabled by default in browser environments and disabled by default in server environments. You can explicitly control this behavior during initialization:
const flagdeck = new Flagdeck({
apiKey: 'your-api-key',
realTimeUpdates: true // Enable real-time updates
});
// Listen for changes to a specific flag
flagdeck.onFlagChange('welcome-message', (newValue, oldValue) => {
console.log(`Flag value changed from ${oldValue} to ${newValue}`);
// Update your UI based on the new value
if (newValue === true) {
showWelcomeMessage();
} else {
hideWelcomeMessage();
}
});
// Listen for a flag being enabled
flagdeck.on('enabled:feature-name', (value) => {
console.log('Feature was enabled!');
showFeature();
});
// Listen for a flag being disabled
flagdeck.on('disabled:feature-name', (value) => {
console.log('Feature was disabled!');
hideFeature();
});
// Listen for all flag changes
flagdeck.on('change', (changes) => {
console.log('Multiple flags changed:', changes);
// { flagKey1: { newValue, oldValue }, flagKey2: { newValue, oldValue } }
});
// Listen for connection events
flagdeck.on('connected', () => {
console.log('Connected to real-time updates');
});
flagdeck.on('disconnected', (error) => {
console.log('Disconnected from real-time updates', error);
});
flagdeck.on('error', (error) => {
console.error('Real-time updates error', error);
});
You can enable or disable real-time updates at runtime:
// Enable real-time updates with options
flagdeck.enableRealTimeUpdates({
autoUpdate: true, // Automatically update cached values when flags change
onFlagUpdate: (flagKey, newValue) => {
console.log(`Flag ${flagKey} updated to:`, newValue);
},
onConnect: () => {
console.log('Connected to real-time updates');
},
onDisconnect: (error) => {
console.log('Disconnected from real-time updates', error);
}
});
// Disable real-time updates
flagdeck.disableRealTimeUpdates();
// Check if real-time updates are enabled
const enabled = flagdeck.areRealTimeUpdatesEnabled();
console.log('Real-time updates enabled:', enabled);
// Reset circuit breaker if connections are failing
flagdeck.resetSseCircuitBreaker();
In server environments, you can optimize performance by subscribing only to specific flags:
// In Node.js, subscribe to specific flags with options
flagdeck.subscribeToFlags(['payment-gateway', 'auth-method'], {
priority: 'high', // 'high', 'normal', or 'low'
ttl: 3600000 // Subscription time-to-live in ms (1 hour)
});
Most evaluation methods accept a context parameter that defines the user and environment details for targeting rules. Here's how to structure the context:
// Basic context with user ID
const context = {
userId: 'user-123'
};
// Full context with attributes
const detailedContext = {
userId: 'user-456',
sessionId: 'session-789', // Optional session identifier
attributes: {
// User attributes for targeting
email: 'user@example.com',
plan: 'premium',
country: 'US',
isAdmin: true,
// Custom business attributes
purchaseCount: 5,
lastLoginDate: '2023-04-15',
// Device/environment attributes
device: 'mobile',
browser: 'chrome',
version: '1.2.3'
}
};
The following options can be provided when initializing the Flagdeck SDK:
| Option | Type | Default | Description |
|---|---|---|---|
| apiKey | string | required | Your Flagdeck API key |
| enableCache | boolean | true | Cache flag evaluations in memory |
| cacheTimeout | number | 30000 | Cache timeout in milliseconds |
| timeout | number | 5000 | Network request timeout in milliseconds |
| retryConfig | object | { attempts: 3, delay: 1000, maxDelay: 5000 } | Retry configuration for network errors |
| debug | boolean | false | Enable detailed logging |
| enableOfflineMode | boolean | false | Enable offline fallback mode |
| enableAnalytics | boolean | true | Track evaluation metrics |
| realTimeUpdates | boolean | auto (true for browser, false for Node.js) | Enable real-time flag updates |
| onError | function | undefined | Global error handler |
| defaultFlagValue | any | false | Default value when evaluation fails |
| sdkPlatform | string | auto-detected | Override detected platform ('web', 'mobile', 'server') |
// Global error handler
const flagdeck = new Flagdeck({
apiKey: 'your-api-key',
onError: (error, flagKey) => {
console.error(`Error evaluating flag ${flagKey}:`, error);
// Log to your error tracking system
errorTracker.captureException(error);
},
defaultFlagValue: false // Value to use if evaluation fails
});
// Try/catch for specific evaluations
try {
const result = await flagdeck.evaluateFlag('new-feature');
// Use result
} catch (error) {
// Handle error
console.error('Failed to evaluate flag:', error);
}
Add custom behavior to the flag evaluation process with middleware:
flagdeck.use({
name: 'LoggingMiddleware',
beforeEvaluation: (flagKey, context) => {
console.log(`Evaluating flag: ${flagKey}`, context);
},
afterEvaluation: (flagKey, result, context) => {
console.log(`Flag ${flagKey} evaluated to:`, result.value);
return result;
},
onError: (error, flagKey) => {
console.error(`Error evaluating flag ${flagKey}:`, error);
}
});
Enable offline support to maintain functionality when connectivity is lost. Offline mode is essential for applications that need to maintain consistent feature flag evaluation during network outages, mobile usage with intermittent connectivity, or to reduce server load.
const flagdeck = new Flagdeck({
apiKey: 'your-api-key',
enableOfflineMode: true
});
// Save current flags for offline use
await flagdeck.saveForOffline('feature-a', true);
// Save multiple flags at once
await flagdeck.saveMultipleForOffline({
'feature-a': true,
'feature-b': false,
'limit': 100
});
// Clear offline storage
await flagdeck.clearOfflineStorage();
// When offline, the SDK will automatically use stored flag values
// No additional code needed for fallback behavior
The SDK implements an efficient storage system with the following optimizations:
localStorage with memory fallback and handles quota errors~/.flagdeck) with temp directory fallbackenableOfflineMode: true in your configuration optionssaveForOffline() or saveMultipleForOffline() when your app has connectivity// Ensure flags are properly saved before app-boot closes
window.addEventListener('beforeunload', async () => {
// Save important flags one last time
await flagdeck.saveMultipleForOffline({
'critical-feature': await flagdeck.getValue('critical-feature'),
'user-settings': await flagdeck.getValue('user-settings')
});
// Also flush analytics
await flagdeck.flushAnalytics();
});
// Example: Refresh critical flags every hour during active use
setInterval(async () => {
if (navigator.onLine) { // Check connectivity (browser only)
try {
const criticalFlags = await flagdeck.getValues([
'payment-gateway',
'auth-method',
'pricing-tiers'
]);
await flagdeck.saveMultipleForOffline(criticalFlags);
console.log('Refreshed offline flags successfully');
} catch (error) {
console.error('Failed to refresh offline flags:', error);
}
}
}, 60 * 60 * 1000); // 1 hour
The SDK automatically caches flag evaluations to improve performance. You can manage the cache manually:
// Clear the cache
flagdeck.clearCache();
The SDK collects anonymous usage statistics by default. You can flush these analytics manually before the app closes:
// Flush analytics events
await flagdeck.flushAnalytics();
When you're done with the Flagdeck client, you should clean up resources:
// Clean up resources when done
await flagdeck.destroy();
This SDK works across platforms:
The SDK includes complete TypeScript definitions:
import { Flagdeck, EvaluationContext } from '@flagdeck/js';
const flagdeck = new Flagdeck({
apiKey: 'your-api-key'
});
const context: Partial<EvaluationContext> = {
userId: 'user-123',
attributes: {
plan: 'premium',
region: 'eu-west',
isAdmin: true
}
};
const result = await flagdeck.evaluateFlag('new-feature', context);
While both versions share the same API, there are some internal differences:
Storage Mechanisms:
localStorage for offline storage when availableNetwork Implementation:
fetch APInode-fetch when the native fetch isn't available (Node.js < 18)Environment Detection:
Real-Time Updates:
These differences are handled internally, allowing you to use the same API regardless of environment.
The main class for interacting with Flagdeck.
isEnabled(flagKey: string, context?: EvaluationContext, defaultValue?: boolean): Promise<boolean> - Checks if a flag is enabledgetValue<T>(flagKey: string, context?: EvaluationContext, defaultValue?: T): Promise<T> - Gets just the flag valuegetValues<T>(flagKeys: string[], context?: EvaluationContext, defaultValue?: T): Promise<Record<string, T>> - Gets multiple flag values at onceevaluateFlag(flagKey: string, context?: EvaluationContext): Promise<EvaluationResult> - Evaluates a flag with full detailsevaluate(flagKey: string, context?: EvaluationContext): Promise<EvaluationResult> - Legacy alias for evaluateFlag (deprecated)evaluateBulk(flagKeys: string[], context?: EvaluationContext): Promise<BulkEvaluationResponse> - Evaluates multiple flagsuse(middleware: EvaluationMiddleware): Flagdeck - Adds an evaluation middlewareclearCache(): void - Clears the evaluation cachesaveForOffline(flagKey: string, value: any): Promise<void> - Saves a flag for offline usesaveMultipleForOffline(flags: Record<string, any>): Promise<void> - Saves multiple flags for offline useclearOfflineStorage(): Promise<void> - Clears stored offline flagsflushAnalytics(): Promise<void> - Manually sends any pending analytics eventson(event: string, listener: Function): Flagdeck - Subscribe to events (including real-time updates)off(event: string, listener: Function): Flagdeck - Unsubscribe from eventsonFlagChange(flagKey: string, listener: (newValue: any, oldValue: any) => void): Flagdeck - Subscribe to changes for a specific flagenableRealTimeUpdates(options?: object): void - Enable real-time flag updatesdisableRealTimeUpdates(): void - Disable real-time flag updatesareRealTimeUpdatesEnabled(): boolean - Check if real-time updates are currently enabledresetSseCircuitBreaker(): void - Reset the circuit breaker if connections are failingsubscribeToFlags(flagKeys: string[], options?: object): void - Subscribe to specific flags (Node.js)destroy(): Promise<void> - Cleans up resourcesMIT
For issues, feature requests, or questions, please visit our GitHub repository or contact support@flagdeck.com.
FAQs
JavaScript SDK for Flagdeck feature flags
The npm package @flagdeck/js receives a total of 3 weekly downloads. As such, @flagdeck/js popularity was classified as not popular.
We found that @flagdeck/js demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.