# Babel Debug Macros And Feature Flags

This provides debug macros and feature flagging.

## Setup

The plugin takes 5 types options: `envFlags`, `features`, `debugTools`, `externalizeHelpers` and `svelte`. The `importSpecifier` is used as a hint to this plugin as to where macros are being imported and completely configurable by the host. Like Babel you can supply your own helpers using the `externalizeHelpers` options.

```
{
  plugins: [
    ['babel-debug-macros', {
      // @required
      envFlags: {
        source: '@ember/env-flags',
        flags: { DEBUG: true }
      },
      // @required
      debugTools: {
        source: 'debug-tools',
        // @optional
        assertPredicateIndex: 0
      },
      // @optional
      features: {
        name: 'ember-source',
        source: '@ember/features',
        flags: { FEATURE_A: false, FEATURE_B: true, DEPRECATED_CONTROLLERS: "2.12.0" }
      },
      // @optional
      svelte: {
        'ember-source': "2.15.0"
      },
      // @optional
      externalizeHelpers: {
        module: true,
        // global: '__my_global_ns__'
      }
    }]
  ]
}
```

Flags and features are inlined into the consuming module so that something like UglifyJS will DCE them when they are unreachable.

## Simple environment and fetaure flags

```javascript
import { DEBUG } from '@ember/env-flags';
import { FEATURE_A, FEATURE_B } from '@ember/features';

if (DEBUG) {
  console.log('Hello from debug');
}

let woot;
if (FEATURE_A) {
  woot = () => 'woot';
} else if (FEATURE_B) {
  woot = () => 'toow';
}

woot();
```

Transforms to:

```javascript
if (true) {
  console.log('Hello from debug');
}

let woot;
if (false) {
  woot = () => 'woot';
} else if (true) {
  woot = () => 'toow';
}

woot();
```

## `warn` macro expansion

```javascript
import { warn } from 'debug-tools';

warn('this is a warning');
```

Expands into:

```javascript
(true && console.warn('this is a warning'));
```

## `assert` macro expansion

The `assert` macro can expand in a more intelligent way with the correct
configuration. When `babel-plugin-debug-macros` is provided with the
`assertPredicateIndex` the predicate is injected in front of the assertion
in order to avoid costly assertion message generation when not needed.

```javascript
import { assert } from 'debug-tools';

assert((() => {
  return 1 === 1;
})(), 'You bad!');
```

With the `debugTools: { assertPredicateIndex: 0 }` configuration the following expansion is done:

```js
(true && !((() => { return 1 === 1;})()) && console.assert(false, 'this is a warning'));
```

When `assertPredicateIndex` is not specified, the following expansion is done:

```javascript
(true && console.assert((() => { return 1 === 1;})(), 'this is a warning'));
```

## `deprecate` macro expansion

```javascript
import { deprecate } from 'debug-tools';

let foo = 2;

deprecate('This is deprecated.', foo % 2);
```

Expands into:

```javascript
let foo = 2;

(true && !(foo % 2) && console.warn('This is deprecated.'));
```

## Externalized Helpers

When you externalize helpers you must provide runtime implementations for the above macros. An expansion will still occur, however we will emit references to those runtime helpers.

A global expansion looks like the following:

```javascript
import { warn } from 'debug-tools';

warn('this is a warning');
```

Expands into:

```javascript
(true && Ember.warn('this is a warning'));
```

While externalizing the helpers to a module looks like the following:

```javascript
import { warn } from 'debug-tools';

warn('this is a warning');
```

Expands into:

```javascript
(true && warn('this is a warning'));
```

# Svelte

Svelte allows for consumers to opt into stripping deprecated code from your dependecies. By adding a package name and minimum version that contains no deprecations, that code will be compiled away.

For example, consider you are on `ember-source@2.10.0` and you have no deprecations. All deprecated code in `ember-source` that is `<=2.10.0` will be removed.

```
...
svelte: {
  "ember-source": "2.10.0"
}
...
```

Now if you bump to `ember-source@2.11.0` you may encounter new deprecations. The workflow would then be to clear out all deprecations and then bump the version in the `svelte` options.

```
svelte: {
  "ember-source": "2.11.0"
}
```

# Hygenic

As you may notice that we inject `DEBUG` into the code when we expand the macro. We guarantee that the binding is unique when injected and follow the local binding name if it is imported directly.
