Skip to content

groupon/esfixup

Repository files navigation

nlm-github nlm-node nlm-version

esfixup

CLI to transform/port/upgrade/improve your existing JavaScript (or convert Coffee to JS)

Usage

npx esfixup --help
npx esfixup --transforms=decaf *.coffee lib
npx esfixup --transforms=js,testium-wd modules

Options

--no-lint-fix

Don't run eslint --fix (using your lint settings) on any JS files when complete. (Default JS output is pretty ugly, you probably don't want this).

--node-version

Explicitly specify a compatible version of JS that should be generated - by default this is inferred from the engines.node section of your package.json

--transforms or -t

Comma-separated list of which transforms you want to apply; order given in option is ignored; transforms know which order they should be applied in.

Available transforms include:

assert

Converts uses of assertive to modern builtin NodeJS assert.

File type: *.js

Assertive was great in its day, but mostly NodeJS assert has caught up, and is much more standard.

Example:

const { equal } = require('assertive');
equal('expected', 'actual');
$ npx esfixup --transforms=assert foo.js
[assert] ✏️  foo.js
const assert = require('assert');
assert.strictEqual('actual', 'expected');

decaf

Decaffeinate single files or entire folders - tries to convert to idiomatic JavaScript where possible, which means it may not always be a 100% faithful conversion.

File type: *.coffee

Example:

# foo.coffee
x = 20
y = 10
y = 30
$ npx esfixup --transforms=decaf foo.coffee
[decaf] ✏️  foo.coffee → foo.js
// foo.js
'use strict';

const x = 20;
let y = 10;
y = 30;

js

Upgrades JS/ES Syntax to maximum features available for your NodeJS version

File type: *.js

Included features:

  • Object.assign({}, a, b) replaced with object-spread: { ...a, ...b }
  • Uses of bluebird.coroutine and co.wrap replaced with async/await
  • Uses object & array destructuring in function and assignments where possible
  • Replaces .indexOf(x) !== -1 with .includes()
  • Removes unnecessary const { URL } = require('url');
  • Removes unused catch clause parameter
  • Replaces [].concat.apply() construct with .flat()
  • Replaces a && a.b && a.b.c sort of stuff with optional chaining: a?.b?.c
  • Removes __guard__ constructs introduced by --transforms=decaf

nodash

Replace some uses of lodash with ES6+ code

File type: *.js

Notes:

  • After applying, rigorously test your code
  • Some transforms are very complex. If possible, try to avoid lodash usage in the first place.
  • Transforms currently happen in place. Refactor your code afterwards to not replicate code.

This will replace some uses of:

  • assign
  • compact
  • concat
  • difference
  • drop
  • fill
  • head
  • first
  • initial
  • intersection
  • join
  • keys
  • last
  • take
  • takeRight
  • toPairs
  • without
  • uniq
  • union
  • unzip
  • values
  • zip
  • zipObject

phy

Converts boring h() or jsx calls to phy h() calls

File type: *.jsx, *.js

Example:

// foo.jsx
const { h } = require('preact');

function SomeComp() {
  return <div class="a"><b>stuff</b></div>;
}
function OtherComp() {
  return h('div', { className: 'a' }, [h('b', {}, ['stuff'])]);
}
$ npx esfixup --transforms=phy foo.jsx
[phy] ✏️  foo.jsx → foo.js
// foo.js
const h = require('phy');

function SomeComp() {
  return h('.a', h('b', 'stuff'));
}

function OtherComp() {
  return h('.a', [h('b', ['stuff'])]);
}

testium-wd

Converts testium-driver-sync tests to testium-driver-wd

File type: *.js

const injectBrowser = require('testium/mocha');

describe('x', () => {
  before(injectBrowser({ driver: 'sync' }));
  it('y', function () {
    this.browser.navigateTo('/');
    return this.browser.waitForElementVisible('#a');
  });
  it('checks', () => {
    browser.assert.httpStatus(204);
  });
  it('z', () => {
    browser.navigateTo('/z');
    assert.equal(200, browser.getStatusCode());
    browser.assert.elementIsVisible('#a');
    assert.expect(true);
    browser.setCookie({ domain: 'd' });
  });
});
$ npx esfixup --transforms=testium-wd some.test.js
[testium-wd] ✏️  some.test.js
const { browser } = require("testium-mocha");

describe('x', () => {
  before(browser.beforeHook({ driver: 'wd' }));
  it('y', () =>
    browser
      .loadPage('/', { expectedStatusCode: 204 })
      .waitForElementDisplayed('#a')
  );

  it('z', async () => {
    await browser
      .loadPage('/z')
      .assertElementIsDisplayed('#a');
    assert.expect(true);
    await browser.setCookie({ domain: 'd' });
  });
});

ts

File type: *.js

Transforms JavaScript with optional TS-compatible JSDoc comments into idiomatic TypeScript. Sadly most other transforms currently only operate on JavaScript, so this transform will run last.

Example:

// foo.js
/**
 * @param {string} a
 * @param {import('./foo').Foo} [b]
 * @return {number}
 */
function fn(a, b) {
  return a + (b ? b.toNum() : 42);
}
$ npx esfixup --transforms=ts foo.js
[ts] ✏️  foo.js → foo.ts
// foo.ts
import { Foo } from './foo';

function fn(a: string, b?: Foo): number {
  return a + (b ? b.toNum() : 42);
}

Development

For work on this library, see DEVELOPMENT.md