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

@subflag/openfeature-web-provider

v0.2.0

Published

OpenFeature web provider for Subflag feature flags

Readme

@subflag/openfeature-web-provider

OpenFeature web provider for Subflag feature flags.

How it works: This provider pre-fetches all flags during initialization and serves them synchronously from an in-memory cache. Flags are fetched once when the provider is set, making flag evaluations instant with zero network latency.

Installation

npm install @subflag/openfeature-web-provider @openfeature/web-sdk

or with pnpm:

pnpm add @subflag/openfeature-web-provider @openfeature/web-sdk

Quick Start

import { OpenFeature } from '@openfeature/web-sdk';
import { SubflagWebProvider } from '@subflag/openfeature-web-provider';

// Initialize the provider
const provider = new SubflagWebProvider({
  apiUrl: 'http://localhost:8080',
  apiKey: 'sdk-production-my-app-your-key-here',
});

// Set provider and wait for it to be ready
await OpenFeature.setProviderAndWait(provider);

// Get a client
const client = OpenFeature.getClient();

// Evaluate flags - synchronous, no network call!
const isEnabled = client.getBooleanValue('new-feature', false);
const bannerText = client.getStringValue('banner-text', 'Welcome!');
const maxItems = client.getNumberValue('max-items', 10);
const config = client.getObjectValue('ui-config', { theme: 'light' });

Configuration

SubflagProviderConfig

| Option | Type | Required | Description | |--------|------|----------|-------------| | apiUrl | string | Yes | The Subflag API URL (e.g., "http://localhost:8080") | | apiKey | string | Yes | Your SDK API key (format: sdk-{env}-{random}) | | timeout | number | No | Request timeout in milliseconds (default: 5000) |

Getting an API Key

See Team Management → API Keys in the docs for instructions on creating API keys.

How It Works: Flag Caching

The web provider uses a pre-fetch and cache strategy:

  1. Initialization: When setProviderAndWait() is called, the provider fetches ALL flags from the server using /sdk/evaluate-all
  2. Caching: All flags are stored in an in-memory Map by flag key
  3. Synchronous Evaluation: Flag lookups are instant - no network calls during evaluation
  4. Refresh: Call await provider.initialize() again to refresh the cache

This approach provides:

  • Zero-latency flag evaluations (synchronous, no await needed)
  • Reduced server load (one bulk request vs N individual requests)
  • Offline capability (flags work even if server becomes unreachable)
  • ⚠️ Eventual consistency (flags may be stale until next refresh)

Usage with React

import { useEffect, useState } from 'react';
import { OpenFeature } from '@openfeature/web-sdk';
import { SubflagWebProvider } from '@subflag/openfeature-web-provider';

function App() {
  const [client, setClient] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function initializeProvider() {
      try {
        const provider = new SubflagWebProvider({
          apiUrl: import.meta.env.VITE_SUBFLAG_API_URL,
          apiKey: import.meta.env.VITE_SUBFLAG_API_KEY,
        });

        // This pre-fetches all flags from the server
        await OpenFeature.setProviderAndWait(provider);
        setClient(OpenFeature.getClient());
      } catch (error) {
        console.error('Failed to initialize provider:', error);
      } finally {
        setLoading(false);
      }
    }

    initializeProvider();
  }, []);

  if (loading) return <div>Loading flags...</div>;
  if (!client) return <div>Error loading flags</div>;

  return <FeatureGatedComponent client={client} />;
}

function FeatureGatedComponent({ client }) {
  // Flags are evaluated synchronously from cache - no await needed!
  const enabled = client.getBooleanValue('new-feature', false);

  return enabled ? <NewFeature /> : <OldFeature />;
}

Refreshing Flags

To update flags without reloading the page:

import { OpenFeature } from '@openfeature/web-sdk';

// Get the current provider
const provider = OpenFeature.getProviderForClient();

// Re-fetch all flags from the server
await provider.initialize();

// Flags are now updated in the cache

Supported Flag Types

The provider supports all OpenFeature value types:

  • Boolean: getBooleanValue(flagKey, defaultValue)
  • String: getStringValue(flagKey, defaultValue)
  • Number: getNumberValue(flagKey, defaultValue)
  • Object: getObjectValue(flagKey, defaultValue)

Error Handling

The provider handles errors gracefully and returns default values when:

  • The flag doesn't exist (404)
  • The API key is invalid (401/403)
  • Network errors occur
  • The flag value type doesn't match the requested type
const client = OpenFeature.getClient();

// If 'missing-flag' doesn't exist, returns false
const value = client.getBooleanValue('missing-flag', false);

// You can also get detailed evaluation information
const details = client.getBooleanDetails('my-flag', false);
console.log(details.reason); // 'STATIC', 'DEFAULT', or 'ERROR'
console.log(details.variant); // Variant name (e.g., 'control', 'treatment')
console.log(details.errorCode); // Error code if reason is 'ERROR'

Development

# Install dependencies
pnpm install

# Build the provider
pnpm build

# Run tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Type check
pnpm typecheck

License

MIT