Giter Site home page Giter Site logo

5to6 / 5to6-codemod Goto Github PK

View Code? Open in Web Editor NEW
301.0 301.0 40.0 606 KB

A collection of codemods that allow you to transform your js code from ES5 to ES6.

Home Page: https://medium.com/@cpojer/effective-javascript-codemods-5a6686bb46fb

JavaScript 100.00%

5to6-codemod's Introduction

5to6-codemod's People

Contributors

akloboucnik avatar amilajack avatar ewnd9 avatar frodosamoa avatar gmathieu avatar jamischarles avatar jsnmoon avatar nmn avatar nolanlawson avatar rmacklin avatar xjamundx avatar xzyfer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

5to6-codemod's Issues

Named exports generation enhancement

I would like to suggest a new transformation for adding named exports corresponding to the properties in a CommonJS default object export. The following example is common for a codebase transitioning from CommonJS to ES6 modules:

module.before.js:

module.exports = {
  value1: 1,
  value2: 2,
};

module.after.js:

export default {
  value1: 1,
  value2: 2,
};

code.before.js:

var module = require('module.before.js');
var value1 = module.value1, 
  value2 = module.value2;

code.ideal.js:

import { value1, value2 } from 'module.after.js';

Unfortunately, code.ideal.js will not work since modules are not destructurable objects. However, we can add a compatibility shim to make code.ideal.js valid by adding named exports to module.after.js:

module.fixed.js

const exported = {
  value1: 1,
  value2: 2,
};
export default exported;
export const {
  value1,
  value,
} = exported;

Basically, this transformation allows better compatibility between CommonJS and ES2015 module notations; some people are opting to use a Babel 6 plugin to facilitate this behavior.

The downside to this transform is that it can cause declaration collisions since it creates new const declaration for each exported object's properties. Also, this transform can be unintuitive without the above example; it'll require proper documentation in the README for people to grasp its usefulness.

I'll push out a PR for this in a day or two.

Complete Exports Rule

  • Comments Missing
  • exports.thing() and module.exports.thing() and module.exports() not properly covered

[CJS] Support Multiple Requires in an Object with the Same Key

This tool is awesome! We've run into one minor issue on our end and actually have a monkeypatch to fix it.

Given this example:

var fetch = require('fetch');

var Routes = {
    route1: {
        component: require('Foo')
    },
    route2: {
        component: require('Bar')
    },
    route3: {
        component: require('Baz')
    },
    route4: {
        component: require('Foo')
    },
};

module.exports = Routes;

jscodeshift -t $GLOBAL_NODE_MODULES/5to6-codemod/transforms/cjs.js codeModExample.js --extensions=js

will return:

import fetch from 'fetch';
import component from 'Foo';
import component from 'Bar';
import component from 'Baz';
import component from 'Foo';

var Routes = {
    route1: {
        component
    },
    route2: {
        component
    },
    route3: {
        component
    },
    route4: {
        component
    }
};

module.exports = Routes;

Ideally, we would prefer if this resulted in this output:

import fetch from 'fetch';
import Foo from 'Foo';
import Bar from 'Bar';
import Baz from 'Baz';

var Routes = {
    route1: {
        component: Foo
    },
    route2: {
        component: Bar
    },
    route3: {
        component: Baz
    },
    route4: {
        component: Foo
    }
};

module.exports = Routes;

the "fix"

diff --git a/transforms/cjs.js b/transforms/cjs.js
index ab9e41d..406ad3d 100644
--- a/transforms/cjs.js
+++ b/transforms/cjs.js
@@ -73,6 +73,7 @@ module.exports = function transformer(file, api, options) {
 		}).forEach(replaceDeclarator.bind(undefined, j));
 	});

+	var moduleNames = {};
 	// var x = { x: require('...'), y: require('...'), ... }
 	root.find(j.VariableDeclaration, { declarations: [{ init: { type: 'ObjectExpression' }}] })
 		.forEach(function (variableDeclaration) {
@@ -83,13 +84,21 @@ module.exports = function transformer(file, api, options) {
 				.find(j.Property, { value: { callee: { name: 'require' }}})
 				.forEach(function (property) {
 					// generate import statement
-					var variableName = property.get('key', 'name').value
+					// var variableName = property.get('key', 'name').value
 					var moduleName = property.get('value', 'arguments', 0, 'value').value
+					var variableName = moduleName.slice(moduleName.lastIndexOf('/')+1, moduleName.length);
 					var importStatement = util.createImportStatement(moduleName, variableName, undefined, property.node.comments)
-
 					// modify property
 					var newProp = api.jscodeshift.property(property.node.kind, property.node.key, property.node.key)
-					newProp.shorthand = true
+					newProp.value = variableName;
+
+					if (moduleNames[variableName]) {
+						j(property).replaceWith(newProp);
+						return
+					} else {
+						moduleNames[variableName] = true;
+					}

 					j(variableDeclaration).insertBefore(importStatement)
 					j(property).replaceWith(newProp)

I would love to get opinions on this, and can open a PR if it's useful to others.

I don't think my monkey-patch should go down as is, it needs cleanup (I'm looking at you, return in the if).

There will be an issue if there's duplication of Module names in subdirectories, such as app/components/Header and app/components/redesign/Header. This change already stores moduleName and attempts to de-dupe, so the concept could be expanded upon to recursively add the subdirectory name to the moduleName if a module already exists.

We could actually go deeper, and do (only in case of namespace conflicts):

import Header from 'app/components/Header';
import RedesignHeader from 'app/components/redesign/Header';

Unexpected token export

jscodeshift -t node_modules/5to6-codemod/transforms/amd.js src

Result:

    export default _;
    ^^^^^^

SyntaxError: Unexpected token export
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:616:28)
    at Module._extensions..js (module.js:663:10)
    at Object.require.extensions.(anonymous function) [as .js] (C:\Users\Matt\AppData\Local\Yarn\config\global\node_modules\babel-regist
er\lib\node.js:152:7)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
All done.
Results:
0 errors
0 unmodified
0 skipped
0 ok
Time elapsed: 1.729seconds

Node v8.11

5to6-codemod/transforms/exports.js can't handle variable exports case

var exports = module.exports = {
    'testkey': 'testvalue'
};

// 导出错误类型码
Object.keys(constants).forEach(function (key) {
    if (key.indexOf('ERR_') === 0) {
        exports[key] = constants[key]; // this line will be converted wrong
    }
});

will be converted to

   export const key = ...

Add tests

ideally, this project would have some mocha test to ensure coverage. That's pretty necessary for a project like this, which can have unexpected side effects.

Error when running simple-arrow transformation

This is the stacktrace:

 ERR test.js Transformation error (Cannot read property 'map' of undefined)
TypeError: Cannot read property 'map' of undefined
    at Lines.Lp.join (/Users/dlj/.config/yarn/global/node_modules/recast/lib/lines.js:867:12)
    at printFunctionParams (/Users/dlj/.config/yarn/global/node_modules/recast/lib/printer.js:2669:35)
    at printMethod (/Users/dlj/.config/yarn/global/node_modules/recast/lib/printer.js:2595:13)
    at genericPrintNoParens (/Users/dlj/.config/yarn/global/node_modules/recast/lib/printer.js:389:16)
    at genericPrint (/Users/dlj/.config/yarn/global/node_modules/recast/lib/printer.js:173:9)
    at print (/Users/dlj/.config/yarn/global/node_modules/recast/lib/printer.js:99:15)
    at /Users/dlj/.config/yarn/global/node_modules/recast/lib/patcher.js:193:22
    at Array.forEach (<anonymous>)
    at /Users/dlj/.config/yarn/global/node_modules/recast/lib/patcher.js:176:14
    at print (/Users/dlj/.config/yarn/global/node_modules/recast/lib/printer.js:98:15)

And here's a simple file that demonstrates the issue:

import A from 'A';
  
class B extends A {
    load() {
        return super.load(['Stuff']);
    }
}

export default new B();

npm audit returning several vulnerabilities

The vulnerabilities reported are all in relation to an outdated version of babel and micromatch being used. The version of jscodeshift needs to be updated to ^0.6.0, and that should resolve the problem. While I understand that these aren't actual problems, as these are run-time vulnerabilities, this is causing massive headache for anyone who has npm audit as part of their CI pipeline.

┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Moderate      │ Prototype Pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ lodash                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=4.17.11                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ 5to6-codemod                                                 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ 5to6-codemod > jscodeshift > babel-core >                    │
│               │ babel-plugin-proto-to-assign > lodash                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/782                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Moderate      │ Prototype Pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ lodash                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=4.17.11                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ 5to6-codemod                                                 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ 5to6-codemod > jscodeshift > babel-core > lodash             │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/782                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low           │ Prototype Pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ lodash                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=4.17.5                                                     │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ 5to6-codemod                                                 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ 5to6-codemod > jscodeshift > babel-core >                    │
│               │ babel-plugin-proto-to-assign > lodash                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/577                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low           │ Prototype Pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ lodash                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=4.17.5                                                     │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ 5to6-codemod                                                 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ 5to6-codemod > jscodeshift > babel-core > lodash             │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/577                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High          │ Regular Expression Denial of Service                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ minimatch                                                    │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=3.0.2                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ 5to6-codemod                                                 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ 5to6-codemod > jscodeshift > babel-core > minimatch          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/118                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low           │ Regular Expression Denial of Service                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ braces                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=2.3.1                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ 5to6-codemod                                                 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ 5to6-codemod > jscodeshift > micromatch > braces             │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/786                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
found 6 vulnerabilities (3 low, 2 moderate, 1 high) in 5308 scanned packages
  6 vulnerabilities require manual review. See the full report for details.

Error when running exports transformation with shadowed variable

This the stacktrace:

 ERR test.js Transformation error (Identifier 'ids' has already been declared (3:12))
SyntaxError: Identifier 'ids' has already been declared (3:12)
    at Object.raise (/Users/dlj/.config/yarn/global/node_modules/@babel/parser/lib/index.js:6322:17)
    at ScopeHandler.checkRedeclarationInScope (/Users/dlj/.config/yarn/global/node_modules/@babel/parser/lib/index.js:3754:12)
    at ScopeHandler.declareName (/Users/dlj/.config/yarn/global/node_modules/@babel/parser/lib/index.js:3720:12)
    at Object.checkLVal (/Users/dlj/.config/yarn/global/node_modules/@babel/parser/lib/index.js:8006:22)
    at Object.checkLVal (/Users/dlj/.config/yarn/global/node_modules/@babel/parser/lib/index.js:373:15)
    at Object.parseVarId (/Users/dlj/.config/yarn/global/node_modules/@babel/parser/lib/index.js:10441:10)
    at Object.parseVar (/Users/dlj/.config/yarn/global/node_modules/@babel/parser/lib/index.js:10412:12)
    at Object.parseVarStatement (/Users/dlj/.config/yarn/global/node_modules/@babel/parser/lib/index.js:10234:10)
    at Object.parseStatementContent (/Users/dlj/.config/yarn/global/node_modules/@babel/parser/lib/index.js:9830:21)
    at Object.parseStatement (/Users/dlj/.config/yarn/global/node_modules/@babel/parser/lib/index.js:9763:17)

And here's a simple file that demonstrates the issue:

class Repeated {
    doSomething(ids) { 
        let ids = { ids: ids.toString() };
        return ids;
    }
}

Travis

Sorry! This issue is a dupe.

named-export-generation does not handle string literals as keys

Thanks for your work on this set of codemods, it's saved me at least a day of work already.

I noticed a weird behavior when using the named-export-generation transform on some code that has exports like;

module.exports = {
  'one': 1,
  'two': 2,
};

It looks like the transform is only accounting for keys that are of type Identifier and should be updated to handle keys of type Literal as well.

Handling cjs inline requires

Converting our legacy code, I found these weird cases which cause a few exceptions. I would consider all except var Foo = require('Foo') to be inline requires which es modules isn't meant to support.

Given that modules should only be imported at the the top level, should we assume any requires past the top level are inline? Or is that too simplistic an approach?

describe('foo', function () {
    var Foo = require('Foo')
    beforeEach(function () {
        this.foo = require('foo')
        var test = new fn(require('foo'))
    })
})
var LOOKUP = {
  	foo: require('foo'),
	get bar () { return require('bar') },
}

I'm happy to open a PR, just wanted to get some direction first.

Thanks for this tool, it's really helpful.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.