Simple, memory and JS based feature testing with express support.
Simple usage:
module.exports = {
'beta': function (user) {
return user.beta;
},
'10%': function (user) {
return user.id % 10 === 0;
}
}
'use strict';
var flags = require('./flags');
var features = require('./lib')(flags);
var user = { beta: true }; // usually from a database
if (features('beta', user)) {
// show beta features
}
The feature gateway can be used with express to block or grant access to particular routes:
module.exports = {
'beta': function (req) { // also recieves res & next
return req.session.user.beta; // content set from some other middleware
},
'10%': function (req) {
return req.session.user.id % 10 === 0;
}
}
'use strict';
var flags = require('./flags');
var features = require('./lib')(flags);
app.get('/home', features.route('beta'), function (req, res) {
// send the redesigned beta homepage
res.render('home-v2');
});
app.get('/home', function (req, res) {
// send the regular homepage
res.render('home');
});
You can attach a logger, and you'll get the data about the feature test:
var features = new Features(flags);
features.log = function (flag, response, args) {
console.log('Flag: ' + flag);
console.log('Response: ' + response);
console.log('Arguments to flag test: ' + JSON.stringify(args));
}
If you want the inverse of the flag, prefix the feature with a !
to invert the result:
if (features('!beta', user)) {
// this is for users who are NOT in the beta flag
}
This is an example of how we're using the features in our handlebar templates (as well as routes and general code):
'use strict';
var hbs = require('hbs'),
features = require('./features');
/**
* usage:
*
* {{#feature user 'alpha'}}
* <!-- here be the new stuff -->
* {{else}}
* <!--- unentitled users get this stuff -->
* {{/feature}}
*/
hbs.registerHelper('feature', function (user, flag, opts) {
// note that for this project, the convention is that the feature receives a request object
// that will contain a session property with the user, so I'm fleshing it out here.
return (features(flag, { session: { user: user }})) ? opts.fn(this) : opts.inverse(this);
});
module.exports = hbs;
The following is an example of how to use the feature gateway to give 50% of users (based on IP address) a feature:
function ipAsNum(req) {
// takes the last part of an IP (n.n.n.last-part) and returns as number
return (req.headers['x-real-ip'] || req.ip || '0.0').split('.').slice(-1) * 1;
}
function percentage(n, req) {
var ip = ipAsNum(req);
return (ip / 256) <= (n / 100);
}
var features = new Features({
fooFeature: function (request) {
// request is the express request object - passed in via our routing OR handlebars feature flags
// note that now 50% can easily be tweaked to 10% or even 100%
return percentage(50, request);
}
});
Now my code can use fooFeature
test and 50% of visitors will get the feature to allow me to perform real A/B testing.