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 🙏

© 2024 – Pkg Stats / Ryan Hefner

codetags

v0.1.2

Published

A simple feature toggle utility

Downloads

83

Readme

codetags

A simple feature toggle utility

What is codetags?

codetags is a simple feature toggle utility for javascript/nodejs. Developers could use this library to prepare new features and switch the features by using environment variables.

How does it work?

Architecture

Retrieving a codetags instance

A default codetags instance can be retrieved simply by a require call:

const codetags = require('codetags');

We can create multiple codetags's instance with newInstance or getInstance methods. Call to both will create a codetags instance, but the getInstance creates a new instance only if it has not existed before.

const codetags = require('codetags');

const space1 = codetags.getInstance('main', {
  namespace: 'maincode'
});
const space2 = codetags.newInstance('test', {
  namespace: 'testcode'
});

// ...

const space3 = codetags.getInstance('main', {
  namespace: 'maincode'
});
console.log(space3 === space1); // true
const space4 = codetags.newInstance('test', {
  namespace: 'testcode'
});
console.log(space4 === space2); // false

Initializing default tags

Default tags can be initialized by register() method:

codetags_instance.register(an_array_of_tag_descriptors);

For example:

codetags.register(['a-simple-tag']);

similar to:

codetags.register([
  {
    name: 'a-simple-tag',
    enabled: true
  }
]);

More complex example:

codetags.register([
  'foo',
  {
    name: 'bar'
  },
  {
    name: 'nil',
    enabled: false
  }
]);

Wrapping code in a tags filter expression

const codetags = require('codetags');

// ...

if (codetags.isActive('foo')) {
  // do something
}

if (tryit.isActive(['foo', 'bar'])) {
  // do other things
}

Enable/disable tags

Declare environment variables:

export CODETAGS_INCLUDED_TAGS=nil,foo
export CODETAGS_EXCLUDED_TAGS=bar

Start node program:

node index.js

Methods

.initialize(kwargs)

The kwargs composes of following fields:

  • namespace - a customized namespace.
  • INCLUDED_TAGS - a customized label for included tags environment variable name (default: INCLUDED_TAGS).
  • EXCLUDED_TAGS - a customized label for excluded tags environment variable name (default: EXCLUDED_TAGS).
  • version - the current package version.

This method returns the codetags instance itself.

.register(descriptors)

Method register() is used to define the default declaredTags collection.

The argument descriptors is an array of descriptor objects which of each describing a string label together with the range of versions that will be applied.

const descriptor1 = {
  name: 'tag-1',
  plan: {
    minBound: '0.1.3',
    enabled: true
  }
}

const descriptor2 = {
  name: 'tag-2',
  plan: {
    maxBound: '0.2.7',
    enabled: false
  }
}

const descriptor3 = {
  name: 'tag-3',
  plan: {
    minBound: '0.1.2',
    maxBound: '0.2.8',
    enabled: false
  }
}

const descriptors = [ descriptor1, descriptor2, descriptor3 ];

codetags.register(descriptors);

This method returns the codetags instance itself.

.isActive(tagexps)

Method isActive() evaluates tags filter expressions (named tagexp) based on three collections of tags (declaredTags, includedTags, excludedTags) to determine whether it is accepted or denied. An expression of tags is composed by string labels, arrays, hashmaps and conditional operators ($all, $any, $not).

tagexp is a single string

Syntax:

const tagexp = 'tagexp-is-a-string';
if (codetags.isActive(tagexp)) {
  // do something
}

Function call codetags.isActive(tagexp) returns true when:

  • excludedTags does not contain tagexp-is-a-string;
  • at least one of includedTags and declaredTags contains tagexp-is-a-string.

tagexp is an array of sub-tagexps

Syntax:

const tagexp = [subtagexp_1, subtagexp_2, subtagexp_3];
if (codetags.isActive(tagexp)) {
  // do something
}

Function call codetags.isActive(tagexp) returns true if all of sub-tagexp in the array must satisfy the function codetags.isActive (i.e. codetags.isActive(subtagexp_i)) return true for any i from 1 to 3).

tagexp is a conditional expression

Syntax:

const tagexp = {
  $all: [
    {
      $not: subtagexp_0,
      $any: [ subtagexp_1, subtagexp_2, subtagexp_3 ]
    },
    {
      $any: [ subtagexp_4, subtagexp_5 ]
    }
  ]
};
if (codetags.isActive(tagexp)) {
  // do something
}

Function call codetags.isActive(tagexp) returns true if the sub-tagexps are satisfied the following constraints:

  • codetags.isActive(subtagexp_0) returns false;
  • one of codetags.isActive(subtagexp_i) returns true (with i from 1 to 3);
  • one of codetags.isActive(subtagexp_j) returns true (with j is 4 or 5);

arguments is a sequence of tagexps

Syntax:

codetags.isActive(tagexp1, tagexp2, tagexp3);

The above function call will return true if there is at least one of tagexp arguments satisfies the function codetags.isActive. It is equivalent to the following expression:

codetags.isActive(tagexp1) || codetags.isActive(tagexp2) || codetags.isActive(tagexp3) 

.clearCache()

Method clearCache() clears the cached values of tags filtering result as well as the cached values of environment variables. This method returns the codetags instance itself.

.reset()

Method reset() invokes the method clearCache() as well as clears the values of declaredTags collection that has been defined by register() method. This method also returns the codetags instance itself.

.newInstance(name, opts)

Method newInstance() creates a new instance in each time it is called and assigns name to this instance. The name value is associated with the latest instance. If you want to retrieve the already created instance, using getInstance instead. The arguments can be:

  • name: a string as name (using in getInstance() to retrieve the instance);
  • opts: an option object that is similar to which in initialize();

This method returns the created instance.

.getInstance(name, opts)

Method getInstance() returns the instance associated to name or creates a new instance when it has not existed before. Its arguments are the same as the method newInstance().

Examples

Default codetags instance

Register feature tags:

// file: bootstrap.js
const codetags = require('codetags');

codetags.register([
  {
    name: 'replace-console-log-with-winston',
    enabled: false
  },
  {
    name: 'moving-from-mongodb-to-couchbase',
    enabled: true
  },
]);

Check the state of tags:

// file: index.js
require('./bootstrap.js');
const codetags = require('codetags');

// ...

if (codetags.isActive('replace-console-log-with-winston')) {
  // be disabled by default
  winston.log('debug', 'Hello world from winston');
} else {
  console.log('Hello world from console.log');
}

Change state of tags with environment variables:

export CODETAGS_INCLUDED_TAGS=replace-console-log-with-winston
export CODETAGS_EXCLUDED_TAGS=moving-from-mongodb-to-couchbase
node index.js

Multiple instances

Create multiple codetags instances:

// file: bootstrap.js
const codetags = require('codetags');

// features for trunk branch
const trunk = codetags.newInstance('trunk', {
  namespace: 'my_mission'
});

trunk.register([
  {
    name: 'replace-console-log-with-winston',
    enabled: false
  },
  {
    name: 'moving-from-mongodb-to-couchbase',
    enabled: true
  },
]);

// features for trial branch
const trial = codetags.newInstance('trial', {
  namespace: 'my_passion'
});

trial.register(['foo', 'bar']);

Make conditional flow:

// file: index.js
require('./bootstrap.js');
const codetags = require('codetags');
const trunk = codetags.getInstance('trunk');
const tryit = codetags.getInstance('trial');

// ...

if (trunk.isActive('replace-console-log-with-winston')) {
  // be disabled by default
  winston.log('debug', 'Hello world from winston');
} else {
  console.log('Hello world from console.log');
}

// ...

if (tryit.isActive('foo')) {
  // do something here
}

if (tryit.isActive(['foo', 'bar'])) {
  // and here
}

if (tryit.isActive('foo', 'bar')) {
  // and here
}

Change state of tags with environment variables:

export MY_MISSION_INCLUDED_TAGS=replace-console-log-with-winston
export MY_PASSION_EXCLUDED_TAGS=foo,bar
node index.js

License

MIT

See LICENSE to see the full text.