babel-plugin-feature-flags
Advanced tools
Comparing version
71
index.js
@@ -1,35 +0,40 @@ | ||
module.exports = function(options) { | ||
options = options || {}; | ||
options.features = options.features || {}; | ||
options.import = options.import || {}; | ||
options.import.name = options.import.name || 'default'; | ||
module.exports = function(babel) { | ||
var t = babel.types; | ||
if (typeof options.import.module !== 'string') { | ||
throw new Error("options.import.module must be the name of a module, e.g. 'my-app/features'"); | ||
} | ||
return { | ||
visitor: { | ||
Program: function(path, state) { | ||
var options = state.opts; | ||
Object.keys(options.features).forEach(function(feature) { | ||
var value = options.features[feature]; | ||
options.features = options.features || {}; | ||
options.import = options.import || {}; | ||
options.import.name = options.import.name || 'default'; | ||
if (typeof value === 'string') { | ||
if (value === 'enabled') { | ||
options.features[feature] = true; | ||
} else if (value === 'disabled') { | ||
options.features[feature] = false; | ||
} else if (value === 'dynamic') { | ||
options.features[feature] = null; | ||
} else { | ||
throw new Error("An unknown feature state '" + value + "' was detected for '" + feature + "'. Valid values are 'enabled', 'disabled' and 'dynamic'"); | ||
} | ||
} | ||
}); | ||
if (typeof options.import.module !== 'string') { | ||
throw new Error("options.import.module must be the name of a module, e.g. 'my-app/features'"); | ||
} | ||
return function(babel) { | ||
var t = babel.types; | ||
Object.keys(options.features).forEach(function(feature) { | ||
var value = options.features[feature]; | ||
return new babel.Transformer('babel-plugin-feature-flags', { | ||
CallExpression: function(node, parent, scope, file) { | ||
var callee = this.get('callee'); | ||
if (typeof value === 'string') { | ||
if (value === 'enabled') { | ||
options.features[feature] = true; | ||
} else if (value === 'disabled') { | ||
options.features[feature] = false; | ||
} else if (value === 'dynamic') { | ||
options.features[feature] = null; | ||
} else { | ||
throw new Error("An unknown feature state '" + value + "' was detected for '" + feature + "'. Valid values are 'enabled', 'disabled' and 'dynamic'"); | ||
} | ||
} | ||
}); | ||
}, | ||
CallExpression: function(path, state) { | ||
var options = state.opts; | ||
var callee = path.get('callee'); | ||
if (callee.referencesImport(options.import.module, options.import.name)) { | ||
var featureName = getFeatureName(node); | ||
var featureName = getFeatureName(path.node); | ||
if (featureName in options.features) { | ||
@@ -39,10 +44,10 @@ var value = options.features[featureName]; | ||
if (typeof value === 'boolean') { | ||
this.replaceWith(t.literal(value)); | ||
path.replaceWith(t.booleanLiteral(value)); | ||
} | ||
} else { | ||
file.log.error("An unknown feature '" + featureName + "'' was encountered"); | ||
throw new Error("An unknown feature '" + featureName + "' was encountered"); | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
}; | ||
@@ -54,4 +59,4 @@ }; | ||
if (callExpression.arguments.length !== 1 || argument.type !== 'Literal' || typeof argument.value !== 'string') { | ||
file.log.error("Feature flag function should be called with a single string literal argument"); | ||
if (callExpression.arguments.length !== 1 || argument.type !== 'StringLiteral') { | ||
throw new Error("Feature flag function should be called with a single string literal argument"); | ||
} | ||
@@ -58,0 +63,0 @@ |
{ | ||
"name": "babel-plugin-feature-flags", | ||
"version": "0.2.1", | ||
"version": "0.3.0", | ||
"description": "A babel transform for managing feature flags", | ||
@@ -24,5 +24,5 @@ "main": "index.js", | ||
"devDependencies": { | ||
"babel-core": "^5.5.3", | ||
"babel-core": "^6.9.1", | ||
"mocha": "^2.2.5" | ||
} | ||
} |
@@ -1,9 +0,3 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (false) { | ||
@@ -13,2 +7,2 @@ 'enabled'; | ||
'disabled'; | ||
} | ||
} |
@@ -1,13 +0,7 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if ((0, _features2['default'])('dynamic')) { | ||
if (isEnabled('dynamic')) { | ||
'enabled'; | ||
} else { | ||
'disabled'; | ||
} | ||
} |
@@ -1,9 +0,3 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (true) { | ||
@@ -13,2 +7,2 @@ 'enabled'; | ||
'disabled'; | ||
} | ||
} |
@@ -1,11 +0,5 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (false) { | ||
'enabled'; | ||
} | ||
} |
@@ -1,11 +0,5 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if ((0, _features2['default'])('dynamic')) { | ||
if (isEnabled('dynamic')) { | ||
'enabled'; | ||
} | ||
} |
@@ -1,11 +0,5 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (true) { | ||
'enabled'; | ||
} | ||
} |
@@ -1,9 +0,3 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (false) { | ||
@@ -15,2 +9,2 @@ 'a'; | ||
'c'; | ||
} | ||
} |
@@ -1,15 +0,9 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (false) { | ||
'a'; | ||
if ((0, _features2['default'])('dynamic')) { | ||
if (isEnabled('dynamic')) { | ||
'b'; | ||
} | ||
'c'; | ||
} | ||
} |
@@ -1,9 +0,3 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (false) { | ||
@@ -15,2 +9,2 @@ 'a'; | ||
'c'; | ||
} | ||
} |
@@ -1,10 +0,4 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if ((0, _features2['default'])('dynamic')) { | ||
if (isEnabled('dynamic')) { | ||
'a'; | ||
@@ -15,2 +9,2 @@ if (false) { | ||
'c'; | ||
} | ||
} |
@@ -1,15 +0,9 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if ((0, _features2['default'])('dynamic')) { | ||
if (isEnabled('dynamic')) { | ||
'a'; | ||
if ((0, _features2['default'])('dynamic')) { | ||
if (isEnabled('dynamic')) { | ||
'b'; | ||
} | ||
'c'; | ||
} | ||
} |
@@ -1,10 +0,4 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if ((0, _features2['default'])('dynamic')) { | ||
if (isEnabled('dynamic')) { | ||
'a'; | ||
@@ -15,2 +9,2 @@ if (true) { | ||
'c'; | ||
} | ||
} |
@@ -1,9 +0,3 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (true) { | ||
@@ -15,2 +9,2 @@ 'a'; | ||
'c'; | ||
} | ||
} |
@@ -1,15 +0,9 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (true) { | ||
'a'; | ||
if ((0, _features2['default'])('dynamic')) { | ||
if (isEnabled('dynamic')) { | ||
'b'; | ||
} | ||
'c'; | ||
} | ||
} |
@@ -1,9 +0,3 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (true) { | ||
@@ -15,2 +9,2 @@ 'a'; | ||
'c'; | ||
} | ||
} |
@@ -1,11 +0,5 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (!false) { | ||
'disabled'; | ||
} | ||
} |
@@ -1,11 +0,5 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (!(0, _features2['default'])('dynamic')) { | ||
if (!isEnabled('dynamic')) { | ||
'disabled'; | ||
} | ||
} |
@@ -1,11 +0,5 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
if (!true) { | ||
'disabled'; | ||
} | ||
} |
@@ -1,13 +0,3 @@ | ||
'use strict'; | ||
import isEnabled, { FEATURES } from 'features'; | ||
function _interopRequireDefault2(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault2(_features); | ||
function _interopRequireDefault(obj) { | ||
return obj && obj.__esModule ? obj : { 'default': obj }; | ||
} | ||
if (true) { | ||
@@ -17,2 +7,2 @@ 'enabled'; | ||
_features.FEATURES; | ||
FEATURES; |
import isEnabled, { FEATURES } from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
if (isEnabled('enabled')) { | ||
@@ -6,0 +4,0 @@ 'enabled'; |
@@ -1,9 +0,3 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
var x = false ? 'enabled' : 'disabled'; | ||
var x = false ? 'enabled' : 'disabled'; |
@@ -1,9 +0,3 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
var x = (0, _features2['default'])('dynamic') ? 'enabled' : 'disabled'; | ||
var x = isEnabled('dynamic') ? 'enabled' : 'disabled'; |
@@ -1,9 +0,3 @@ | ||
'use strict'; | ||
import isEnabled from 'features'; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
var _features = require('features'); | ||
var _features2 = _interopRequireDefault(_features); | ||
var x = true ? 'enabled' : 'disabled'; | ||
var x = true ? 'enabled' : 'disabled'; |
103
test/test.js
@@ -7,3 +7,3 @@ var assert = require('assert'); | ||
function testFixture(name, options) { | ||
function testFixture(name, plugins) { | ||
it(name, function () { | ||
@@ -14,7 +14,5 @@ var fixturePath = path.resolve(__dirname, 'fixtures', name, 'fixture.js'); | ||
var expected = fs.readFileSync(expectedPath).toString(); | ||
var result = babel.transformFileSync(fixturePath, { | ||
plugins: [ applyFeatureFlags(options) ] | ||
}); | ||
var result = babel.transformFileSync(fixturePath, { plugins: plugins }); | ||
assert.strictEqual(result.code, expected); | ||
assert.strictEqual(result.code + '\n', expected); | ||
}); | ||
@@ -24,35 +22,66 @@ } | ||
describe('babel-plugin-feature-flags', function() { | ||
var options = { | ||
import: { | ||
module: 'features' | ||
}, | ||
features: { | ||
enabled: 'enabled', | ||
disabled: 'disabled', | ||
dynamic: 'dynamic' | ||
} | ||
} | ||
describe('basic', function() { | ||
var plugins = [ | ||
[applyFeatureFlags, { | ||
import: { | ||
module: 'features' | ||
}, | ||
features: { | ||
enabled: 'enabled', | ||
disabled: 'disabled', | ||
dynamic: 'dynamic' | ||
} | ||
}] | ||
]; | ||
testFixture('if/enabled', options); | ||
testFixture('if/disabled', options); | ||
testFixture('if/dynamic', options); | ||
testFixture('else/enabled', options); | ||
testFixture('else/disabled', options); | ||
testFixture('else/dynamic', options); | ||
testFixture('not-if/enabled', options); | ||
testFixture('not-if/disabled', options); | ||
testFixture('not-if/dynamic', options); | ||
testFixture('ternary/enabled', options); | ||
testFixture('ternary/disabled', options); | ||
testFixture('ternary/dynamic', options); | ||
testFixture('nested/enabled-enabled', options); | ||
testFixture('nested/enabled-disabled', options); | ||
testFixture('nested/enabled-dynamic', options); | ||
testFixture('nested/disabled-enabled', options); | ||
testFixture('nested/disabled-disabled', options); | ||
testFixture('nested/disabled-dynamic', options); | ||
testFixture('nested/dynamic-enabled', options); | ||
testFixture('nested/dynamic-disabled', options); | ||
testFixture('nested/dynamic-dynamic', options); | ||
testFixture('preserves-other-imports', options); | ||
testFixture('if/enabled', plugins); | ||
testFixture('if/disabled', plugins); | ||
testFixture('if/dynamic', plugins); | ||
testFixture('else/enabled', plugins); | ||
testFixture('else/disabled', plugins); | ||
testFixture('else/dynamic', plugins); | ||
testFixture('not-if/enabled', plugins); | ||
testFixture('not-if/disabled', plugins); | ||
testFixture('not-if/dynamic', plugins); | ||
testFixture('ternary/enabled', plugins); | ||
testFixture('ternary/disabled', plugins); | ||
testFixture('ternary/dynamic', plugins); | ||
testFixture('nested/enabled-enabled', plugins); | ||
testFixture('nested/enabled-disabled', plugins); | ||
testFixture('nested/enabled-dynamic', plugins); | ||
testFixture('nested/disabled-enabled', plugins); | ||
testFixture('nested/disabled-disabled', plugins); | ||
testFixture('nested/disabled-dynamic', plugins); | ||
testFixture('nested/dynamic-enabled', plugins); | ||
testFixture('nested/dynamic-disabled', plugins); | ||
testFixture('nested/dynamic-dynamic', plugins); | ||
testFixture('preserves-other-imports', plugins); | ||
}); | ||
describe('multiple instances', function() { | ||
var plugins = [ | ||
[applyFeatureFlags, { | ||
import: { | ||
module: 'features-one' | ||
}, | ||
features: { | ||
enabledOne: 'enabled', | ||
disabledOne: 'disabled', | ||
dynamicOne: 'dynamic' | ||
} | ||
}], | ||
[applyFeatureFlags, { | ||
import: { | ||
module: 'features-two' | ||
}, | ||
features: { | ||
enabledTwo: 'enabled', | ||
disabledTwo: 'disabled', | ||
dynamicTwo: 'dynamic' | ||
} | ||
}] | ||
]; | ||
testFixture('multiple-instances', plugins); | ||
}); | ||
}); |
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
53
6%0
-100%55
Infinity%12231
-7.36%395
-0.5%