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

@togglebox/sdk

v0.1.0

Published

JavaScript SDK for remote config service

Readme

@togglebox/sdk

JavaScript/TypeScript SDK for ToggleBox - Remote configuration, feature flags, and A/B experiments.

Installation

npm install @togglebox/sdk
# or
yarn add @togglebox/sdk
# or
pnpm add @togglebox/sdk

Quick Start

Open Source Self-Hosted

import { ToggleBoxClient } from "@togglebox/sdk";

const client = new ToggleBoxClient({
  platform: "web",
  environment: "production",
  apiUrl: "https://your-domain.com",
  // apiKey: process.env.TOGGLEBOX_API_KEY, // Optional: only if auth is enabled
});

// Get configuration
const config = await client.getConfig();

// Check feature flag
const showNewUI = await client.isFlagEnabled("new-dashboard", {
  userId: "user-123",
});

Cloud Multi-Tenant

import { ToggleBoxClient } from "@togglebox/sdk";

const client = new ToggleBoxClient({
  platform: "web",
  environment: "production",
  tenantSubdomain: "acme", // Connects to https://acme.togglebox.io
  apiKey: process.env.TOGGLEBOX_API_KEY, // Required for cloud
});

Connection Health Check

Verify API connectivity before using the SDK:

const health = await client.checkConnection();
if (health.success) {
  console.log(`API is healthy, uptime: ${health.uptime}s`);
}

Three-Tier Architecture

ToggleBox provides three complementary systems for controlling your application:

| Tier | System | Use Case | Values | | ---- | -------------- | ---------------------------------- | ----------------- | | 1 | Remote Configs | Static settings, same for everyone | Any JSON | | 2 | Feature Flags | On/off switches with targeting | A or B | | 3 | Experiments | Multi-variant A/B testing | Multiple variants |


Tier 1: Remote Configs

Configs are versioned, immutable snapshots of application settings. Use them for:

  • API endpoints and service URLs
  • UI themes and branding
  • Default values and limits
  • Environment-specific settings

Get All Configuration

const config = await client.getConfig();

// Access your settings
const apiBaseUrl = config.apiBaseUrl; // 'https://api.example.com'
const theme = config.theme; // { primaryColor: '#007AFF', ... }
const maxUploadSize = config.limits.maxUploadSize; // 10485760

Get Specific Config Value

// Type-safe config access with defaults
const apiUrl = await client.getConfigValue<string>(
  "api_url",
  "https://default.api.com",
);
const maxRetries = await client.getConfigValue<number>("max_retries", 3);
const features = await client.getConfigValue<string[]>("enabled_features", [
  "basic",
]);

// Complex objects
const theme = await client.getConfigValue<{
  primary: string;
  secondary: string;
}>("theme", { primary: "#000", secondary: "#fff" });

Get All Configs

// Fetch all active config parameters as key-value object
const config = await client.getConfig();

// Access values directly
const apiUrl = config["api.url"];
const maxRetries = config["app.maxRetries"];

Tier 2: Feature Flags

Feature flags are 2-value switches (A or B) with targeting rules. Use them for:

  • Gradual rollouts (1% → 10% → 50% → 100%)
  • Country/language targeting
  • User-specific features (beta users, premium plans)
  • Kill switches for quick rollbacks

Check Flag Enabled

// Simple check (returns true if value A is served)
const showNewDashboard = await client.isFlagEnabled("new-dashboard", {
  userId: "user-123",
});

// With full targeting context
const hasPremiumFeatures = await client.isFlagEnabled("premium-features", {
  userId: "user-123",
  country: "US",
  language: "en",
});

Get Flag Evaluation Result

// Get detailed evaluation result
const result = await client.getFlag("ui-version", {
  userId: "user-123",
  country: "US",
});

console.log(result);
// {
//   servedValue: 'A',         // 'A' or 'B'
//   valueA: 'new-ui',         // Value when A is served
//   valueB: 'legacy-ui',      // Value when B is served
//   reason: 'percentage_rollout' // Why this value was chosen
// }

Get All Flags

const allFlags = await client.getFlags();
// Returns array of Flag objects

Get Flag Info

Get a specific flag's metadata without evaluation:

const flagInfo = await client.getFlagInfo("new-dashboard");

if (flagInfo) {
  console.log(`Flag: ${flagInfo.flagKey}`);
  console.log(`Enabled: ${flagInfo.enabled}`);
  console.log(`Rollout: ${flagInfo.rolloutPercentage}%`);
  console.log(`Target Countries: ${flagInfo.targetCountries?.join(", ")}`);
}

Tier 3: Experiments

Experiments enable multi-variant A/B testing with statistical tracking. Use them for:

  • Testing multiple UI variations
  • Measuring conversion impact
  • Data-driven product decisions

Get Experiment Variant

const assignment = await client.getVariant("checkout-experiment", {
  userId: "user-123",
});

if (assignment) {
  console.log(`Assigned to: ${assignment.variationKey}`);
  // 'control', 'variant-a', 'variant-b', etc.

  // Apply the variant
  switch (assignment.variationKey) {
    case "control":
      renderOriginalCheckout();
      break;
    case "variant-a":
      renderSimplifiedCheckout();
      break;
    case "variant-b":
      renderOneClickCheckout();
      break;
  }
}

Track Conversions

Track user conversions to measure experiment effectiveness:

// Track a simple conversion
await client.trackConversion(
  "checkout-experiment",
  { userId: "user-123" },
  { metricName: "purchase" },
);

// Track with a value (e.g., revenue)
await client.trackConversion(
  "checkout-experiment",
  { userId: "user-123" },
  {
    metricName: "purchase",
    value: 99.99, // Revenue amount
  },
);

Get All Experiments

const experiments = await client.getExperiments();
// Returns array of Experiment objects

Get Experiment Info

Get a specific experiment's metadata without assignment:

const expInfo = await client.getExperimentInfo("checkout-test");

if (expInfo) {
  console.log(`Experiment: ${expInfo.experimentKey}`);
  console.log(`Status: ${expInfo.status}`);
  console.log(`Variations: ${expInfo.variations.length}`);
  expInfo.variations.forEach((v) => {
    console.log(`  - ${v.variationKey}: ${v.weight}%`);
  });
}

User Context

Context is used for targeting rules in flags and experiments. Set it globally or per-evaluation.

Global Context

// Set global context (applied to all evaluations)
client.setContext({
  userId: "user-123",
  userEmail: "[email protected]",
  country: "US",
  language: "en",
  plan: "premium",
  betaTester: true,
  companyId: "company-456",
});

// All subsequent calls use global context
const showNewUI = await client.isFlagEnabled("new-ui", {});

Per-Evaluation Context

// Override global context for specific evaluation
const showNewUI = await client.isFlagEnabled("new-ui", {
  userId: "user-456", // Overrides global userId
  country: "GB", // Overrides global country
});

// Get current global context
const currentContext = client.getContext();

Context Properties

| Property | Type | Description | | ----------- | ------ | -------------------------------------------------------- | | userId | string | Unique user identifier (required for consistent hashing) | | userEmail | string | User email for targeting | | country | string | ISO country code (e.g., 'US', 'GB') | | language | string | Language code (e.g., 'en', 'fr') | | plan | string | Subscription plan for targeting | | * | any | Custom attributes for targeting rules |


API Key Authentication

Use API keys when your ToggleBox API has authentication enabled.

Self-Hosted with Authentication Enabled

When you enable authentication on your self-hosted instance (ENABLE_AUTHENTICATION=true):

const client = new ToggleBoxClient({
  platform: "web",
  environment: "production",
  apiUrl: "https://your-api.example.com",
  apiKey: process.env.TOGGLEBOX_API_KEY, // Your API key from admin dashboard
});

Cloud Multi-Tenant (Always Required)

Cloud deployments always require authentication:

const client = new ToggleBoxClient({
  platform: "web",
  environment: "production",
  tenantSubdomain: "acme", // Your tenant subdomain
  apiKey: process.env.TOGGLEBOX_API_KEY, // Required for cloud
});

The API key is sent with every request as the X-API-Key header.

Note: If you're using an open-source self-hosted instance without authentication enabled, you don't need to provide an API key.


Stats & Analytics

The SDK automatically tracks flag evaluations, experiment exposures, and conversions. Configure the stats reporter:

const client = new ToggleBoxClient({
  platform: "web",
  environment: "production",
  apiUrl: "https://api.example.com",
  stats: {
    enabled: true, // Enable stats collection (default: true)
    batchSize: 20, // Events to batch before sending (default: 20)
    flushIntervalMs: 10000, // Flush interval in ms (default: 10000)
    maxRetries: 3, // Retry attempts for failed sends (default: 3)
  },
});

// Listen for stats flush events
client.on("statsFlush", ({ eventCount }) => {
  console.log(`Flushed ${eventCount} stats events`);
});

// Manually flush pending events
await client.flushStats();

What Gets Tracked

  • Config fetches: When getConfigValue() is called
  • Flag evaluations: When getFlag() or isFlagEnabled() is called
  • Experiment exposures: When getVariant() is called
  • Conversions: When trackConversion() is called

Caching

Enable in-memory caching to reduce API calls:

const client = new ToggleBoxClient({
  platform: "web",
  environment: "production",
  apiUrl: "https://api.example.com",
  cache: {
    enabled: true,
    ttl: 300000, // 5 minutes in milliseconds
  },
});

Auto-Refresh Polling

Automatically poll for configuration updates:

const client = new ToggleBoxClient({
  platform: "web",
  environment: "production",
  apiUrl: "https://api.example.com",
  pollingInterval: 60000, // Poll every minute
});

// Listen for updates
client.on("update", ({ config, flags, experiments }) => {
  console.log("Configuration updated:", config);
  console.log("Flags updated:", flags);
  console.log("Experiments updated:", experiments);
});

client.on("error", (error) => {
  console.error("Polling error:", error);
});

// Stop polling
client.stopPolling();

Configuration Options

interface ClientOptions {
  /** Platform name (e.g., 'web', 'mobile') */
  platform: string;

  /** Environment name (e.g., 'production', 'staging') */
  environment: string;

  /**
   * API base URL (for open source self-hosted)
   * Use tenantSubdomain for cloud deployments
   */
  apiUrl?: string;

  /**
   * Tenant subdomain for cloud deployments
   * Automatically constructs apiUrl as https://{tenantSubdomain}.togglebox.io
   */
  tenantSubdomain?: string;

  /** API key for authentication (sent as X-API-Key header) */
  apiKey?: string;

  /**
   * Config version to fetch (default: 'stable')
   * - 'stable': Latest stable version
   * - 'latest': Latest version (may be unstable)
   * - '1.2.3': Specific version label
   */
  configVersion?: string;

  /** Cache configuration */
  cache?: {
    enabled: boolean;
    ttl: number; // milliseconds
  };

  /** Auto-refresh polling interval in milliseconds (0 to disable) */
  pollingInterval?: number;

  /** Stats configuration */
  stats?: {
    enabled?: boolean; // default: true
    batchSize?: number; // default: 20
    flushIntervalMs?: number; // default: 10000
    maxRetries?: number; // default: 3
  };

  /** Custom fetch implementation (defaults to global fetch) */
  fetchImpl?: typeof fetch;
}

Note: You must provide either apiUrl OR tenantSubdomain, not both.


API Methods

Connection & Health

| Method | Description | | ------------------- | --------------------------------------------- | | checkConnection() | Verify API connectivity and get health status |

Remote Configs (Tier 1) - Firebase-Style Parameters

| Method | Description | | -------------------------------------- | ---------------------------------------------------- | | getConfig() | Get all active config parameters as key-value object | | getConfigValue<T>(key, defaultValue) | Get a specific config value with type safety | | getAllConfigs() | Alias for getConfig() |

Feature Flags (Tier 2)

| Method | Description | | ------------------------------------------------ | ------------------------------------ | | getFlags() | Get all feature flags | | getFlag(flagKey, context) | Get detailed flag evaluation result | | isFlagEnabled(flagKey, context, defaultValue?) | Check if flag is enabled (A = true) | | getFlagInfo(flagKey) | Get flag metadata without evaluation |

Experiments (Tier 3)

| Method | Description | | ----------------------------------------------- | ------------------------------------------ | | getExperiments() | Get all experiments | | getVariant(experimentKey, context) | Get assigned variant for a user | | trackConversion(experimentKey, context, data) | Track a conversion event | | trackEvent(eventName, context, data?) | Track a custom event | | getExperimentInfo(experimentKey) | Get experiment metadata without assignment |

Context & Lifecycle

| Method | Description | | ---------------------- | --------------------------------------------------- | | setContext(context) | Set global evaluation context | | getContext() | Get current global context | | refresh() | Force refresh all cached data | | flushStats() | Flush pending stats events | | on(event, callback) | Listen for events ('update', 'error', 'statsFlush') | | off(event, callback) | Remove event listener | | stopPolling() | Stop auto-refresh polling | | destroy() | Stop polling and cleanup resources |


Real-World Examples

Feature Rollout with Percentage

// In ToggleBox dashboard, create flag 'new-checkout' with:
// - rolloutType: 'percentage'
// - rolloutPercentage: 25

const showNewCheckout = await client.isFlagEnabled("new-checkout", {
  userId: user.id, // Used for consistent hashing
});

if (showNewCheckout) {
  renderNewCheckout();
} else {
  renderLegacyCheckout();
}

Country-Targeted Feature

// Flag 'eu-privacy-banner' with targetCountries: ['DE', 'FR', 'IT', ...]
const showPrivacyBanner = await client.isFlagEnabled("eu-privacy-banner", {
  userId: user.id,
  country: user.country, // 'DE', 'US', etc.
});

A/B Test with Revenue Tracking

// Get variant assignment
const assignment = await client.getVariant("pricing-experiment", {
  userId: user.id,
});

// Render based on variant
if (assignment?.variationKey === "annual-first") {
  showAnnualPricingFirst();
} else {
  showMonthlyPricingFirst();
}

// Track purchase conversion with revenue
async function onPurchase(amount: number) {
  await client.trackConversion(
    "pricing-experiment",
    { userId: user.id },
    { metricName: "purchase", value: amount },
  );
}

Environment-Specific Configuration

// Different clients for different environments
const prodClient = new ToggleBoxClient({
  platform: "web",
  environment: "production",
  apiUrl: process.env.TOGGLEBOX_API_URL,
});

const stagingClient = new ToggleBoxClient({
  platform: "web",
  environment: "staging",
  apiUrl: process.env.TOGGLEBOX_API_URL,
});

// Each fetches environment-specific config and flags
const prodConfig = await prodClient.getConfig();
const stagingConfig = await stagingClient.getConfig();

TypeScript

This SDK is written in TypeScript and includes full type definitions.

import { ToggleBoxClient } from "@togglebox/sdk";
import type {
  ClientOptions,
  Config,
  Flag,
  FlagContext,
  FlagResult,
  Experiment,
  ExperimentContext,
  VariantAssignment,
  ConversionData,
  StatsOptions,
  HealthCheckResponse,
} from "@togglebox/sdk";

License

MIT