Socket
Socket
Sign inDemoInstall

@r/flags

Package Overview
Dependencies
0
Maintainers
4
Versions
4
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    @r/flags

config goes in, feature-enabled goes out


Version published
Weekly downloads
7
increased by40%
Maintainers
4
Install size
25.6 kB
Created
Weekly downloads
 

Readme

Source

flags

A simple feature flagging library.

100 lines of code, no dependencies. Written in ES6+.

Build Status

flags lets you quickly switch features on or off based on a context. This is useful to test features for specific users (such as flagging on new functionality in a web application by reading the response context), dark-launching code, and a/b testing.

// Import it!
import Flags from '@r/flags';

// Set up your experiment config!
const config = {
  loggedoutSearch: { loggedin: false },
  oldDesign: false,
  newListingStyle: { users: ['ajacksified'] },
};

const feature = new Flags(config);

// Add rules!
feature.addRule('loggedin', function(val) { return this.loggedin === val; });
feature.addRule('users', function(names) { return names.includes(this.username); });

// Get whatever blob of data you'll use to determine your experiment truthiness
const userData = {
  loggedin: true,
  username: 'ajacksified',
};

// For ease of use, build a context-bound flags instance. (Alternatively, you
// could call `feature.on(rule, context)` instead.)
const featureContext = feature.withContext(userData);

// Build your UI with a Flags context bound to userdata!

// false (loggedin is true, but the config wants false)
if (featureContext.enabled('loggedoutSearch')) {
  searchControl = <LoggedOutSearch />;
  console.log('show the logged out search');
}

// false (the config says it's always false)
if (featureContext.enabled('oldDesign')) {
  layout = <OldLayout />;
}

// true (the username is in the users array)
if (featureContext.enabled('newListingStyle')) {
  listing = <Listing2 />;
}

// Get the list of enabled featues:
const enabled = featureContext.allEnabled();
// => ['newListingStyle'];


// Or disabled:
const disabled = featureContext.allDisabled();
// => ['loggedoutSearch', 'oldDesign'];

Rules and Configuration

flags configuration and rules are very simple:

  • Define a name for your features; such as 'loggedoutSearch' or 'oldDesign' as above. These will be the basis if your config and your feature flags for later on.
  • Define the rules upon which your feature will be on or off. Above, we implement a boolean check (shoes) and an array check (username).
  • Check the flag - either by sending it in (feature.enabled('feature', { data } )) or by hanging on to a context-bound instance ( featureContext = feature.withContext({ data }); featureContext.enabled('feature'))

Of note: if a rule is defined in configuration but it is not implemented, it is assumed to be false.

Three special "pseudo-rules" implement boolean operators: and, or, and not, so that rules may stay simple and general and be combined in useful ways. For example:

const config = {
  friend: {
    and: [
      { or: [ { type: 'cyborg' }, { type: 'human' } ] },
      { not: { role: 'supervillain' } }
    ]
  }
};

You can also parse large objects to handle things such as environment variables. To do so, you should have configuration in the format feature_name. feature_ will be stripped from the key and lowercased:

import Flags from flags;

const config = Flags.parseConfig({
  something: 'wut',
  feature_flippers: { names: ['bob', 'jane'] }
});

// => { flippers: { names: ['bob', 'jane'] } };

You can supply your own function, too, and customize both key and value. In this example, we'll expect things to start with f_ instead of feature_.

import Flags from flags;

const config = Flags.parseConfig({
  something: 'wut',
  f_flippers: { names: ['bob', 'jane'] }
}, function(key, val) {
  if (key.indexOf('f_') === -1) { return; }
  return { key: key.slice(2), val: val };
});

// => { flippers: { names: ['bob', 'jane'] } };

You can also retrieve a list of all currently enabled or disabled rules for a given context by calling feature.allEnabled or feature.allDisabled. These can be called with a context passed in, or else will use a bound context.

Sometimes, for testing, it's nice to clone an instance that doesn't use the original rules and configuration by reference. You can call flagsinstance.clone() to return a new flags instance with shallow copies of the config, rules, and context.

Development

flags is an ES6 library. Take a look at the .babelrc file to see what presets we're using. To import it in ES5, use var Flags = require ('@r/flags').default;.

To get started:

  • With node installed,
  • Fork flags
  • Clone your fork to your machine
  • Run npm install to install dev dependencies (there are no regular dependencies; dependencies are for testing and running.)
  • Write features, and run npm test and npm run lint. Feature changes should have tests! For ease of use, install eslint for your favorite editor.
  • Check out CONTRIBUTING.md for more detailed info.

flags is MIT licensed. copyright 2016 reddit. See LICENSE for more info.

Keywords

FAQs

Last updated on 20 Jun 2016

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc