babel-plugin-xplicit v1.0.0
Javascript Assertions with xplicit
Assert javascript code
class Sphere {
constructor (r) {
assert: r > 0;
this._radius = r;
}
setRadius (r) {
assert: this._radius > 0, {filter: 'jrambo'};
assert: r > 0;
this._radius = r;
}
}
This repository
Xplicit is a babel plugin that enables a simple assertion aproach for javascript. It was inspired by Charles Pick's use of javascript labeled statement in his babel-plugin-contracts.
Babel enables us to transform our assertion expressions, add some log information and probably the most important point, to strip code.
Asserting javascript code
Asserting is a simplified aproach to design by contract, but strong enough to enable programmers to write consistent code. With this plugin, it is possible to write pre and post conditions and invariants, but the responsibility of writing them at the right place is left to the programmer.
You may be interested in some tips for javascript assertion.
Installation
Just like other babel plugins:
npm install --save-dev babel-plugin-xplicit
Example of code assertions:
class Sphere {
constructor (r) {
assert: r > 0;
this._radius = r;
}
setRadius (r) {
assert: this._radius > 0, {filter: 'jrambo'};
assert: r > 0, {filter: 'jfive'};
this._radius = r;
}
}
This can be transpiled, depending on the options, to:
class Sphere {
constructor (r) {
console.assert(r > 0);
this._radius = r;
}
setRadius (r) {
console.assert(r > 0);
this._radius = r;
}
}
How to use
Just as other babel plugins, you can use your .babelrc to configure the plugin:
{
"presets": {...},
"env": {
"development": {
"plugins": [
["xplicit", {
"verbs": {
"assert": "myAssert"
},
"conditional": "_is_assert_active"
}]
]
},
"production": {
"plugins": [
["xplicit", {
"strip": true
}]
]
}
}
}
Then you can set the environment, for example, in you package.json:
{
"build": "babel ./src -d ./lib",
"dev": "BABEL_ENV=development npm run build",
"pub": "BABEL_ENV=production npm run build",
}
Option: strip assertions
Probably one of the most important options is simply to strip all assertions in production environments.
{
"strip": true
}
Option: verbs
This is the way you can customize the actual assertion function. It also allows you to specify the labels that you are going to use to assert. So you could use something like this:
{
"verbs": {
"assert": "console.assert",
"assert_log": "myAssertFunction"
}
}
Then you can use these labels to assert:
setRadius (r) {
assert: r > 0;
this._radius = r;
assert_log: this._radius > 0;
}
This would transpile to this:
setRadius (r) {
console.assert(r > 0);
this._radius = r;
myAssertFunction(this._radius > 0);
}
Option: filters
When assertions of one programmer affect other programmer (because they are continuously failing), we can filter them. This option strips all assertions except the ones we mark with an alias.
{
"filter": [
"jrambo"
]
}
Then, only asserts with 'jrambo' filter will survive:
setRadius (r) {
assert: r > 0;
this._radius = r;
assert: this._radius > 0, {filter: 'jrambo'};
}
This would transpile to this:
setRadius (r) {
this._radius = r;
console.assert(this._radius > 0);
}
Option: conditional
It is also possible to activate assertions in runtime (if the strip option is not used) using a global activation variable:
{
"conditional": "_dbg_assert"
}
Then in the transpiled code, assertions will be checked only if the variable is evaluated as true:
setRadius (r) {
this._radius = r;
_dbg_assert && console.assert(this._radius > 0);
}
You should define and assign a value to it.
Option: position
This option adds information about where the assert is located, adding an object indicating line and column of the assertion call:
{
"position": true
}
Once transpiled:
setRadius (r) {
this._radius = r;
console.assert(this._radius > 0, {line: 19, column: 4});
}
LICENSE
Licensed under the MIT license.
7 years ago