Skip to content

Make your contracts explicit with javascript assertions powered by babel.

License

Notifications You must be signed in to change notification settings

edgarweto/babel-plugin-xplicit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

Build Status License

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.

About

Make your contracts explicit with javascript assertions powered by babel.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published