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

ft-flags

v0.1.2

Published

Feature flags for TypeScript with Cargo-style feature definitions, conditional compilation, and CLI tooling

Readme

ft-flags

JSR npm Version GitHub Issues License

Feature flags for TypeScript with Cargo-style feature definitions, conditional compilation, and CLI tooling.

Overview

ft-flags provides a robust feature flag system for TypeScript that follows the same conventions as Cargo features in Rust. Features can be:

  • Declared statically in your deno.json or package.json
  • Composed together into feature sets
  • Enabled by default or opt-in
  • Validated at build time via JSON schema
  • Queried via CLI for scripting and debugging

This package serves as the foundation for conditional compilation in the @hiisi/cfg-ts ecosystem.

npm package: This is the Node.js and Bun optimized version of ft-flags. For Deno, see @hiisi/ft-flags on JSR.

Supported Runtimes

This is the Node.js/Bun optimized package. The following runtimes and versions are tested in CI:

Node.js

| 18 | 20 | 22 | |:--:|:--:|:--:| | ✅ | ✅ | ✅ |

Bun

| 1.0 | latest | |:---:|:------:| | ⚠️ | ✅ |

Bun support is best-effort

For Deno support, use the JSR package.

Installation

# npm
npm install ft-flags

# yarn
yarn add ft-flags

# pnpm
pnpm add ft-flags

Feature Model

Declaring Features

Features are declared at the root level of your package.json. The format follows Cargo's conventions:

{
  "name": "@my/package",
  "version": "1.0.0",
  "features": {
    "default": ["std"],
    "std": ["fs", "env"],
    "full": ["std", "experimental"],
    "fs": [],
    "env": [],
    "args": [],
    "experimental": ["async-runtime"],
    "async-runtime": []
  }
}

Naming Conventions

Feature names follow Cargo conventions:

  • Kebab-case: Feature names use lowercase with hyphens: async-runtime, serde-support
  • : for dependency features: Enable features from dependencies: lodash:clone, @scope/pkg:feature
  • dep: for optional deps: Enable optional dependencies: dep:tokio

Note: We use : instead of / (which Cargo uses) to avoid ambiguity with scoped package names like @scope/pkg that are common in the JS/TS ecosystem.

Key Concepts

The default Feature

The default feature is special — it lists the features that are enabled when no explicit feature selection is made. This is equivalent to Cargo's default feature.

{
  "features": {
    "default": ["std", "logging"]
  }
}

To disable default features, use the --no-default-features CLI flag or set defaultFeatures: false in your config.

Feature Dependencies

Each feature maps to an array of features it activates. When you enable a feature, all features it lists are also enabled (transitively).

{
  "features": {
    "full": ["std", "experimental", "async-runtime"],
    "std": ["fs", "env"]
  }
}

Enabling full will enable: full, std, experimental, async-runtime, fs, env.

Dependency Features

Enable features from your dependencies using ::

{
  "features": {
    "serialization": ["serde:derive", "@myorg/utils:json"],
    "async": ["tokio:full"]
  }
}

Optional Dependencies

Similar to Cargo's dep: syntax, you can reference optional package dependencies:

{
  "features": {
    "async": ["dep:async-hooks"],
    "tracing": ["dep:opentelemetry"]
  }
}

Note: dep: integration with package managers is planned for a future release.

Feature Metadata

You can add metadata to features for documentation and tooling. Metadata uses the metadata.features namespace, following the convention used by Cargo's [package.metadata.X]:

{
  "name": "@my/package",
  "features": {
    "default": ["std"],
    "std": ["fs", "env"],
    "experimental": []
  },
  "metadata": {
    "features": {
      "std": {
        "description": "Standard library features for cross-runtime compatibility"
      },
      "experimental": {
        "description": "Unstable features that may change",
        "unstable": true
      },
      "legacy-api": {
        "description": "Use the new API instead",
        "deprecated": true,
        "deprecatedMessage": "Migrate to v2-api feature"
      }
    }
  }
}

Configuration

Full Configuration Schema

{
  "name": "@my/package",
  "features": {
    "default": ["..."],
    "feature-name": ["dependency1", "dependency2"]
  },
  "metadata": {
    "features": {
      "feature-name": {
        "description": "Human-readable description",
        "since": "1.0.0",
        "unstable": false,
        "deprecated": false,
        "deprecatedMessage": "..."
      }
    }
  }
}

Environment Variables

Override features at runtime via environment variables:

# Enable specific features
FT_FEATURES=experimental,async-runtime

# Disable default features
FT_NO_DEFAULT_FEATURES=true

# Enable all features
FT_ALL_FEATURES=true

CLI Arguments

Pass feature flags via command line:

my-app --features experimental,async-runtime
my-app --no-default-features
my-app --all-features

CLI Tool

ft-flags includes a CLI (ft) for querying and validating features.

Installation

# Run via npx
npx ft <command>

# Or install globally
npm install -g ft-flags
ft <command>

Commands

ft list

List all available features for the current package.

$ ft list
Available features:
  default       -> [std]
  std           -> [fs, env]
  fs            -> []
  env           -> []
  experimental  -> []

$ ft list --enabled
Enabled features (with default):
  [ok] default
  [ok] std
  [ok] fs
  [ok] env

ft check <feature>

Check if a specific feature is enabled.

$ ft check fs
[ok] fs is enabled (via: default -> std -> fs)

$ ft check experimental
[x] experimental is not enabled

$ ft check experimental --features experimental
[ok] experimental is enabled (explicit)

Exit codes: 0 if enabled, 1 if disabled.

ft resolve

Show the fully resolved set of enabled features.

$ ft resolve
Resolved features:
  default, std, fs, env

$ ft resolve --features full --no-default-features
Resolved features:
  full, std, experimental, async-runtime, fs, env

$ ft resolve --all-features
Resolved features:
  default, std, full, experimental, async-runtime, fs, env, args

ft tree [feature]

Display the feature dependency tree.

$ ft tree
Feature tree:
default
`-- std
    |-- fs
    `-- env
full
|-- std
|   |-- fs
|   `-- env
`-- experimental
    `-- async-runtime
args

$ ft tree full
full
|-- std
|   |-- fs
|   `-- env
`-- experimental
    `-- async-runtime

ft validate

Validate the feature configuration.

$ ft validate
[ok] Configuration is valid

$ ft validate
[x] Error: Circular dependency detected: full -> experimental -> full
[x] Error: Unknown feature referenced: "nonexistent" in feature "std"

Package-Specific Queries

Query features for a specific package in a workspace:

$ ft list --package @myorg/subpackage
$ ft check fs --package ./packages/my-lib

Programmatic API

Basic Usage

import {
  isFeatureEnabled,
  listAvailableFeatures,
  loadManifest,
  resolveFeatures,
} from "ft-flags";

// Load features from package.json
const manifest = await loadManifest();

// Resolve with default features
const resolved = resolveFeatures(manifest);

// Check if a feature is enabled
if (isFeatureEnabled("fs", resolved)) {
  // Use filesystem features
}

// List all available features
const available = listAvailableFeatures(manifest);
console.log(available); // ["default", "std", "fs", ...]

Custom Feature Selection

import { resolveFeatures } from "@hiisi/ft-flags";

// Enable specific features, no defaults
const resolved = resolveFeatures(manifest, {
  features: ["experimental", "fs"],
  noDefaultFeatures: true,
});

// Enable all features
const all = resolveFeatures(manifest, {
  allFeatures: true,
});

Using the Registry API

import { buildSchema, createRegistry, featureId, isEnabled } from "@hiisi/ft-flags";

// Define features with schema
const schema = buildSchema([
  { id: "fs", description: "File system access" },
  { id: "env", description: "Environment variable access" },
  { id: "async-runtime", description: "Async runtime support" },
]);

// Create registry with enabled features
const registry = createRegistry({
  schema,
  config: {
    enabled: ["fs", "env"],
  },
});

// Type-safe feature checks
if (isEnabled(registry, featureId("fs"))) {
  // ...
}

Schema Validation

import { validateManifest } from "@hiisi/ft-flags";

const result = validateManifest({
  features: {
    default: ["std"],
    std: ["unknown-feature"], // Error!
  },
});

if (!result.valid) {
  console.error(result.errors);
  // ["Unknown feature 'unknown-feature' referenced in 'std'"]
}

JSON Schema

A JSON schema is provided for editor validation and autocompletion.

VS Code / Editors

Add to your settings.json:

{
  "json.schemas": [
    {
      "fileMatch": ["deno.json", "package.json"],
      "url": "https://jsr.io/@hiisi/ft-flags/schema.json"
    }
  ]
}

Schema URL

https://jsr.io/@hiisi/ft-flags/schema.json

Integration with cfg-ts

ft-flags is designed to work with cfg-ts for conditional compilation:

import { cfg } from "cfg-ts";

// @cfg(feature("fs"))
export function readFile(path: string): string {
  // This function is only included when fs is enabled
}

// @cfg(not(feature("experimental")))
export function stableApi(): void {
  // Only included when experimental is NOT enabled
}

// @cfg(all(feature("std"), not(feature("legacy"))))
export function modernStdLib(): void {
  // Complex predicates
}

Comparison with Cargo

| Cargo | ft-flags | Notes | | ----------------------- | ----------------------- | ------------------------------------ | | [features] | "features": {} | Same concept | | default = ["std"] | "default": ["std"] | Same semantics | | foo = ["bar", "baz"] | "foo": ["bar", "baz"] | Feature enables others | | dep:optional-dep | "dep:pkg-name" | Optional dependency | | serde/derive | "serde:derive" | Dep feature ref (: instead of /) | | --features foo | --features foo | CLI flag | | --no-default-features | --no-default-features | Disable defaults | | --all-features | --all-features | Enable everything |

Related Packages

  • cfg-ts - Conditional compilation with @cfg() syntax
  • otso - Build framework that orchestrates feature-based builds
  • tgts - Target definitions (runtime, platform, arch)
  • onlywhen - Runtime feature detection

Support

Whether you use this project, have learned something from it, or just like it, please consider supporting it by buying me a coffee, so I can dedicate more time on open-source projects like this :)

License

You can check out the full license here

This project is licensed under the terms of the Mozilla Public License 2.0.

SPDX-License-Identifier: MPL-2.0