Skip to content

sumukhbarve/flagleap

Repository files navigation

FlagLeap

Table Of Contents

Introduction

  • FlagLeap is a simple & flexible solution for managing realtime feature flags.
  • It is meant to be deployed as a standalone service, and can be consumed via a REST API.
  • SDKs for JavaScript (browser and node), TypeScript, and React (web) are included.
  • FlagLeap supports rule-based, user-specific flag evaluations (with multiple rule types).
  • It has 2 modes: live and test. (Rules in test mode don't affect live mode.)

Screenshots

List of Flags Flag-Specific Rules
FlagLeap: List of Flags FlagLeap: Flag-Specific Rules

Not Ready for Production

  • FlagLeap is not yet ready for production use.
  • External & internal APIs are both likely change.
  • However, it is ready for POCs and non-critical internal apps.

Quickstart

  1. Please complete the Server Setup steps.
  2. And use any (one or more) of the following to interact with the server:

Server Setup

1. Clone the repo and start the server:

  • git clone https://github.com/sumukhbarve/flagleap.git
  • cd flagleap
  • npm install
  • npm run build
  • npm start

2. Set up your account and create your first flag:

  • Visit http://localhost:3333 and complete account setup.
  • Click 'Create Flag' and enter the an ID (eg. enableFoo) for the flag.

Set Environment Variables if deploying to the web:

  • PORT (defaults to 3333)
  • DATABASE_URL (defaults to repo/local-sqlite.db)
  • SECRET_KEY (defaults to not-really-a-secret--just-the-fallback)

Flag Shape

A flag, as returned by the REST API (and SDKs) has the following shape:

interface Flag {
  id: string
  enabled: boolean
  value: string
}

FlagMap

A FlagMap is a mapping from flag IDs to corresponding flag objects.

type FlagMap = Record<string, Flag>

.enabled vs .value

  • .enabled is a boolean, indicating whether the flag is turned on.
  • .value is the string obtained by evaluating the rules of the flag.
    • If a flag is disabled, the .value will always be '' (empty string).
    • If a flag is enabled, the .value will be the result value of the first satisfied rule.
    • If a flag has no rules, or if no rule is satisfied, the .value will be '' (empty string).

Rest API

Only POST requests of type application/json are expected.

1. Evaluating all flags

Endpoint: /exapi/evalFlags

Request Data:

  • mode: "test" or "live"
  • traits: A plain object describing the user, with only string or number values.
    • Eg: {"userId": "00c13408a...", "plan": "premium", "projectCount": 10}

Successful Response Shape:

  • {status: "success", data: FlagMap} (See FlagMap shape above)

CURL snippet:

curl --request POST \
  --url http://localhost:3333/exapi/evalFlags \
  --header 'content-type: application/json' \
  --data '{"mode": "test", "traits": {}}'

2. Evaluating a single flag

Endpoint: /exapi/evalFlag

Request Data:

  • flag_id: string
  • mode: "test" or "live"
  • traits: A plain object describing the user, with only string or number values.
    • Eg: {"userId": "00c13408a...", "plan": "premium", "projectCount": 10}

Successful Response Shape:

  • {status: "success", data: Flag} (See Flag shape above)

3. Socket.IO API

  • To subscribe to realtime updates, you can point a Socket.IO client to your FlagLeap server (instanceUrl).

  • Whenever a flag (potentially) changes, the server emits a 'flagNotifFromServer' event.

  • The associated data has two properties:

    • flag_id: string ID of the flag
    • mode: either 'test' or 'live'
  • Upon receiving a flagNotifFromServer, you should use the /exapi/evalFlag endpoint to re-evaluate that flag.

  • If you're using one of the SDKs, then there's you needn't do this manually. The SDK will handle this for you.

JS/TS/Node SDK

npm install flagleap in your app, and then:

import { flagleapSdk } from 'flagleap'

// Create a flagleap client:
const flagleap = flagleapSdk.flagleapClient({
  instanceUrl: "http://localhost:3333",
  mode: "test",
})

// Optionally set user-traits for user-specific flag evaluations.
// This may be done right away, or as/when a user logs in.
flagleap.setTraits({
  userId: 'user_1234',
  plan: 'premium',
  // ... etc ...
})

// Initialize the client and call `.getFlag()` for getting flags!
flagleap.init().then(function () {
  const isFooEnabled = flagleap.getFlag('enableFoo').enabled
})

// When the user logs out, you may want to:
flagleap.setTraits({})

Isomorphic fetch() on Node.js:

  • To use the JS/TS SDK on Node, npm install node-fetch (or another isomorphic fetch function).
  • And supply it (dependency injection) to flagleap via flagleapSdk.injectIsomorphicFetch(fetch).

Realtime Behavior:

  • To subscribe to realtime notifications regarding (potential) flag updates, use .subscribe():
flagleap.subscribe(() => {
  // This will be called whenever a flag changes.
})

React SDK

npm install flagleap in your app, and then:

flag-store.ts

import { React } from 'react'
import { flagleapSdk } from 'flagleap'

// Create a flagleap client:
const flagleap = flagleapSdk.flagleapClient({
  instanceUrl: "http://localhost:3333",
  mode: "test",
})

// Pass your version of React (>= 16.8) to generate a hook.
const useFlag = flagleapSdk.makeUseFlag(flagleap, React)

export { flagleap, useFlag }

And call useFlag in your components:

Counter.tsx

import { React } from 'react'
import { useFlag } from './flag-store'

export const Counter: React.VFC = () => {
  const [count, setCount] = React.useState(0)
  const addTwoEnabled = useFlag('enableAddTwo').enabled
  return (
    <div>
      Count: {count}
      <button onClick={() => setCount(count + 1)}>Add 1</button>
      {addTwoEnabled && (
        <button onClick={() => setCount(count + 2)}>Add 2</button>
      )}
    </div>
  )
}

Use the FlagLeap UI to (create and) enable the enableAddTwo flag. Toggling the flag will toggle the Add 2 button in your app.

About

Feature flag management software with support for dynamic rules. Focused on simplicity.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages