npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@flagdeck/js

v0.0.34

Published

JavaScript SDK for Flagdeck feature flags

Downloads

61

Readme

Flagdeck JavaScript SDK

The official JavaScript/TypeScript SDK for Flagdeck, a modern feature flag and feature management system.

Installation

npm install @flagdeck/js
# or
yarn add @flagdeck/js

Quick Start

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();
   }
}

Environment-Specific Imports

The SDK automatically detects your environment (browser or Node.js) and uses the appropriate implementation. If you want to explicitly import a specific version:

Browser Import

import { Flagdeck } from '@flagdeck/js/browser';

const flagdeck = new Flagdeck({
   apiKey: 'your-api-key'
});

Node.js Import

import { Flagdeck } from '@flagdeck/js/node';

const flagdeck = new Flagdeck({
   apiKey: 'your-api-key'
});

Working with Different Value Types

Flagdeck supports multiple value types for feature flags:

Boolean Flags

// Check if a feature is enabled
const isEnabled = await flagdeck.isEnabled('new-feature');
if (isEnabled) {
   showNewFeature();
}

String Variants

// 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
}

Numeric Settings

// Get a numeric configuration value with default
const limit = await flagdeck.getValue<number>('rate-limit', context, 100);
applyRateLimit(limit);

JSON/Object Configuration

// 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 });

Advanced Usage: Full Evaluation Details

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)}`);

Multiple Flags at Once

// 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

Real-Time Updates

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.

Enabling Real-Time Updates

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
});

Listening for Flag Changes

// 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);
});

Managing Real-Time Updates

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();

Subscribing to Specific Flags

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)
});

Real-Time Updates Implementation Details

  • Browser: Uses the native EventSource API (Server-Sent Events) with automatic reconnection
  • Node.js: Uses the 'eventsource' package (must be installed separately)
  • Fault Tolerance: Includes circuit breaker pattern to prevent excessive reconnection attempts
  • Memory Management: Automatically cleans up unused flag subscriptions
  • Performance: Optimized to minimize bandwidth and CPU usage

Evaluation Context

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: '[email protected]',
    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'
  }
};

Configuration Options

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') |

Error Handling

// 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);
}

Middleware

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);
  }
});

Offline Mode

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

Offline Storage Details

The SDK implements an efficient storage system with the following optimizations:

  • Flag Expiration: Flags are stored with expiration times (default: 7 days)
  • Automatic Pruning: Oldest flags are automatically removed when storage limits are reached
  • Size Management: Storage size is monitored and optimized (100KB limit in browsers, 500KB in Node.js)
  • Periodic Maintenance: The SDK automatically cleans up expired flags
  • Efficient I/O: Batch operations minimize disk/localStorage writes

Environment-Specific Storage

  • Browser: Uses localStorage with memory fallback and handles quota errors
  • Node.js: Uses filesystem storage in the user's home directory (~/.flagdeck) with temp directory fallback

Important Considerations

  1. Offline Mode Must Be Enabled: Set enableOfflineMode: true in your configuration options
  2. Save Flags Proactively: Call saveForOffline() or saveMultipleForOffline() when your app has connectivity
  3. Storage Limits: Be mindful of storage limits, especially for mobile browsers with tight localStorage quotas
  4. Flag Expiration: Stored flags expire after 7 days by default; customize expiration by providing a TTL (coming soon)
  5. Flushing Before App Closure: For browser applications, consider flushing before app closure:
// 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();
});

Best Practices

  • Default Values: Always provide sensible default values as a final fallback
  • Periodic Refreshes: Refresh offline flags periodically during active use
  • Critical Flags: Identify and prioritize saving business-critical flags
  • Storage Monitoring: For sensitive applications, monitor offline storage usage
// 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

Cache Management

The SDK automatically caches flag evaluations to improve performance. You can manage the cache manually:

// Clear the cache
flagdeck.clearCache();

Analytics

The SDK collects anonymous usage statistics by default. You can flush these analytics manually before the app closes:

// Flush analytics events
await flagdeck.flushAnalytics();

Cleanup

When you're done with the Flagdeck client, you should clean up resources:

// Clean up resources when done
await flagdeck.destroy();

Platform Support

This SDK works across platforms:

  • Browsers: All modern browsers are supported
  • Node.js: Server-side environments
  • React Native: Mobile applications (via the JavaScript runtime)

TypeScript Support

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);

Differences Between Browser and Node.js Versions

While both versions share the same API, there are some internal differences:

  1. Storage Mechanisms:

    • Browser: Uses localStorage for offline storage when available
    • Node.js: Uses file system storage in the user's home directory
  2. Network Implementation:

    • Browser: Uses the native fetch API
    • Node.js: Uses node-fetch when the native fetch isn't available (Node.js < 18)
  3. Environment Detection:

    • Browser: Detects browser, screen, and web-specific properties
    • Node.js: Detects Node.js version, platform, and server-specific properties
  4. Real-Time Updates:

    • Browser: Enabled by default, uses native EventSource API
    • Node.js: Disabled by default, requires the 'eventsource' package

These differences are handled internally, allowing you to use the same API regardless of environment.

API Reference

Flagdeck

The main class for interacting with Flagdeck.

Methods

  • isEnabled(flagKey: string, context?: EvaluationContext, defaultValue?: boolean): Promise<boolean> - Checks if a flag is enabled
  • getValue<T>(flagKey: string, context?: EvaluationContext, defaultValue?: T): Promise<T> - Gets just the flag value
  • getValues<T>(flagKeys: string[], context?: EvaluationContext, defaultValue?: T): Promise<Record<string, T>> - Gets multiple flag values at once
  • evaluateFlag(flagKey: string, context?: EvaluationContext): Promise<EvaluationResult> - Evaluates a flag with full details
  • evaluate(flagKey: string, context?: EvaluationContext): Promise<EvaluationResult> - Legacy alias for evaluateFlag (deprecated)
  • evaluateBulk(flagKeys: string[], context?: EvaluationContext): Promise<BulkEvaluationResponse> - Evaluates multiple flags
  • use(middleware: EvaluationMiddleware): Flagdeck - Adds an evaluation middleware
  • clearCache(): void - Clears the evaluation cache
  • saveForOffline(flagKey: string, value: any): Promise<void> - Saves a flag for offline use
  • saveMultipleForOffline(flags: Record<string, any>): Promise<void> - Saves multiple flags for offline use
  • clearOfflineStorage(): Promise<void> - Clears stored offline flags
  • flushAnalytics(): Promise<void> - Manually sends any pending analytics events
  • on(event: string, listener: Function): Flagdeck - Subscribe to events (including real-time updates)
  • off(event: string, listener: Function): Flagdeck - Unsubscribe from events
  • onFlagChange(flagKey: string, listener: (newValue: any, oldValue: any) => void): Flagdeck - Subscribe to changes for a specific flag
  • enableRealTimeUpdates(options?: object): void - Enable real-time flag updates
  • disableRealTimeUpdates(): void - Disable real-time flag updates
  • areRealTimeUpdatesEnabled(): boolean - Check if real-time updates are currently enabled
  • resetSseCircuitBreaker(): void - Reset the circuit breaker if connections are failing
  • subscribeToFlags(flagKeys: string[], options?: object): void - Subscribe to specific flags (Node.js)
  • destroy(): Promise<void> - Cleans up resources

License

MIT

Support

For issues, feature requests, or questions, please visit our GitHub repository or contact [email protected].