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 🙏

© 2026 – Pkg Stats / Ryan Hefner

flagwithme-sdk

v1.1.0

Published

Official Node.js SDK for FlagWithMe - A powerful feature flag management system with support for boolean, string, number, JSON, and multivariate flags

Readme

FlagWithMe SDK

Official Node.js SDK for FlagWithMe — a self-hosted feature flag management system.

npm version License: MIT Node.js Version

Features

  • 5 Flag Types: Boolean, String, Number, JSON, Multivariate (A/B/C testing)
  • Server-Side Evaluation: Rollout %, segment targeting, and rules evaluated on the backend
  • Per-User Targeting: Pass user context at evaluation time — no shared mutable state
  • Per-User Cache: Each unique user context cached independently with configurable TTL
  • TypeScript Support: Full type definitions included
  • Lightweight: Only 1 dependency (axios)

Installation

npm install flagwithme-sdk

Quick Start

1. Get your SDK key

In the FlagWithMe dashboard: Project → Environments → copy the SDK Key for your environment.

2. Initialize the client

const FlagWithMeClient = require('flagwithme-sdk');

// Only two fields required — the SDK key identifies the project and environment
const client = new FlagWithMeClient({
  apiUrl: 'http://localhost:4001/api/v1',
  sdkKey: 'fwm_sdk_xxxxxxxxxxxx',
});

3. Evaluate flags

// Global flag — on/off for everyone, no user context needed
const isMaintenance = await client.isEnabled('maintenance-mode');

// Per-user flag — pass user context at evaluation time
const user = { id: req.user.id, email: req.user.email };

const showNewUI     = await client.isEnabled('new-dashboard', false, user);
const apiEndpoint   = await client.getString('api-endpoint', 'https://default.com', user);
const uploadLimit   = await client.getNumber('max-upload-mb', 10, user);
const themeConfig   = await client.getJSON('theme-config', {}, user);
const buttonVariant = await client.getVariant('button-test', 'control', user);

Configuration

Constructor options

| Option | Type | Required | Description | |--------|------|----------|-------------| | apiUrl | string | ✅ Yes | Base URL of the FlagWithMe API | | sdkKey | string | ✅ Yes | Environment SDK key — identifies and authenticates the environment | | environment | string | No | Environment name — informational only (sdkKey already identifies it) | | cacheDuration | number | No | Cache TTL per user context in ms (default: 60000) | | logger | object | No | Custom logger with error/warn/debug methods. Set FLAGWITHME_DEBUG=true to use console. | | apiKey | string | No | Reserved for future use | | projectId | string | No | Reserved for future use |

Environment variables (recommended)

FLAG_API_URL=https://your-backend.com/api/v1
FLAG_SDK_KEY=fwm_sdk_xxxxxxxxxxxx
const client = new FlagWithMeClient({
  apiUrl: process.env.FLAG_API_URL,
  sdkKey: process.env.FLAG_SDK_KEY,
});

API Reference

isEnabled(flagKey, defaultValue?, user?)

Evaluate a boolean feature flag.

// Global
const isOn = await client.isEnabled('maintenance-mode');

// Per-user
const showBeta = await client.isEnabled('beta-feature', false, { id: 'user-123' });

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | flagKey | string | — | Flag key from the dashboard | | defaultValue | boolean | false | Returned when flag not found or an error occurs | | user | UserContext | — | User context for rollout and segment targeting |

Returns: Promise<boolean>


getString(flagKey, defaultValue?, user?)

Get a string flag value.

const message = await client.getString('welcome-message', 'Hello!', { id: 'user-123' });

Returns: Promise<string>


getNumber(flagKey, defaultValue?, user?)

Get a number flag value.

const timeout = await client.getNumber('api-timeout', 5000, { id: 'user-123' });

Returns: Promise<number>


getJSON(flagKey, defaultValue?, user?)

Get a JSON object flag value.

const config = await client.getJSON('app-config', { theme: 'light' }, { id: 'user-123' });

Returns: Promise<Object>


getVariant(flagKey, defaultVariant?, user?)

Get a multivariate flag variant. Variant selection and weight distribution is handled server-side.

const variant = await client.getVariant('checkout-flow', 'control', { id: 'user-123' });

switch (variant) {
  case 'one-page':    return renderOnePageCheckout();
  case 'multi-step':  return renderMultiStepCheckout();
  default:            return renderDefaultCheckout();
}

Returns: Promise<string>


getAllFlags(user?)

Get all flags with their resolved values for a given user context.

const flags = await client.getAllFlags({ id: 'user-123' });
// { 'new-dashboard': true, 'api-url': 'https://...', 'timeout': 5000 }

Returns: Promise<Object>


setUser(user)

Set a default user context used when no user is passed to evaluation methods. Useful for single-user environments (mobile apps, CLIs). For web servers, prefer passing user context per evaluation call.

client.setUser({ id: 'user-123', email: '[email protected]', plan: 'premium' });
// Now evaluation calls without a user param use this context
const isOn = await client.isEnabled('feature');

client.setUser(null); // clear default

clearCache()

Clear the entire flag cache. Forces a fresh evaluation on next call.

client.clearCache();

setEnvironment(environment, sdkKey?)

Switch to a different environment. Always clears the cache.

client.setEnvironment('staging', 'fwm_sdk_staging_xxxxxxxxxxxx');

login(email, password)

Authenticate against the admin API. Not required for flag evaluation — the SDK key handles that. Useful for admin operations.

const token = await client.login('[email protected]', 'password');

User Context

The user parameter tells the backend who is making this request so it can apply targeting rules configured in the dashboard.

// Minimum — enables rollout bucketing
{ id: 'user-123' }

// With email — enables email-based segment rules
{ id: 'user-123', email: '[email protected]' }

// With custom attributes — enables attribute-based segment rules
{ id: 'user-123', email: '[email protected]', plan: 'premium', country: 'US' }

Custom attributes are matched against segment rules you define in the dashboard (e.g. plan equals 'premium').

If no user context is provided, the backend evaluates the flag without targeting — the result applies to all users equally.

Usage Patterns

Express.js (recommended pattern)

const FlagWithMeClient = require('flagwithme-sdk');

// Initialize once at app startup
const flagClient = new FlagWithMeClient({
  apiUrl: process.env.FLAG_API_URL,
  sdkKey: process.env.FLAG_SDK_KEY,
});

// Per request — pass user context at evaluation time
app.get('/dashboard', async (req, res) => {
  const user = { id: req.user.id, email: req.user.email };

  const showNewUI = await flagClient.isEnabled('new-dashboard', false, user);
  const config    = await flagClient.getJSON('app-config', {}, user);

  res.render('dashboard', { showNewUI, config });
});

Webhook-triggered cache refresh

// When a flag changes in the dashboard, the backend can notify your server
app.post('/webhooks/flags', (req, res) => {
  flagClient.clearCache();
  res.sendStatus(200);
});

Kill switch

const isAvailable = await client.isEnabled('payment-service', true);
if (!isAvailable) {
  return res.status(503).json({ error: 'Service temporarily unavailable' });
}

Remote configuration

const limits = await client.getJSON('upload-limits', { maxSizeMb: 10, allowedTypes: ['jpg', 'png'] });
upload.limits = { fileSize: limits.maxSizeMb * 1024 * 1024 };

TypeScript Support

import FlagWithMeClient, { FlagWithMeConfig, UserContext } from 'flagwithme-sdk';

const config: FlagWithMeConfig = {
  apiUrl: 'http://localhost:4001/api/v1',
  sdkKey: 'fwm_sdk_xxxxxxxxxxxx',
};

const client = new FlagWithMeClient(config);

const user: UserContext = { id: 'user-123', email: '[email protected]' };

const enabled: boolean = await client.isEnabled('feature', false, user);
const message: string  = await client.getString('message', '', user);
const timeout: number  = await client.getNumber('timeout', 5000, user);

Caching

Flags are cached per user context with a configurable TTL (default: 60 seconds).

  • Each unique user context gets its own cache entry
  • Cache holds up to 500 user contexts — oldest entry is evicted when full
  • Cache is invalidated automatically when you call clearCache() or setEnvironment()
  • Stale cache is served as a fallback if the backend is temporarily unreachable
// Reduce TTL if you need near-real-time flag updates
const client = new FlagWithMeClient({
  apiUrl: process.env.FLAG_API_URL,
  sdkKey: process.env.FLAG_SDK_KEY,
  cacheDuration: 10000, // 10 seconds
});

Troubleshooting

Flags always return default values

  1. Check the flag is enabled in the environment (dashboard → Flags → toggle)
  2. Check rollout percentage is > 0%
  3. Verify sdkKey matches the environment you expect
  4. Enable debug logging: FLAGWITHME_DEBUG=true node app.js

Segment rules not matching

Check that the attributes you pass in user match the rule field names in the dashboard exactly (case-sensitive). For example, if the rule says plan equals premium, pass { plan: 'premium' }.

Backend unreachable

The SDK returns the stale cache if available, or the caller's defaultValue if the cache is empty. Set FLAGWITHME_DEBUG=true to see the error logged.

Requirements

  • Node.js 14.0.0 or higher
  • FlagWithMe backend running and accessible

License

MIT

Support


Version: 1.2.0 | Made with ❤️ by Thamizhmani C