npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ticklepoke/codemods

v1.27.0

Published

JavaScript codemods using Facebook's jscodeshift

Downloads

25

Readme

codemods CI

JavaScript codemods using jscodeshift

Usage

The npm package is namespaced to my username (@ticklepoke) for now as it is intended to be a personal project. If this package gains enough traction, I will consider finding a more elegant package name.

via git

git clone https://github.com/facebook/jscodeshift.git

Install the codeshift runner globally. There is a known bug where the runner doesnt work with yarn: 424.

npm install -g jscodeshift

Alternatively, one can format jscodeshift's binaries on every install using a tool such as dos2unix:

dos2unix node_modules/jscodeshift/bin/*

Install dependencies and build transforms

yarn install && yarn build

List available transforms

yarn transform:ls

Execute a codemod:

jscodeshift -t dist/[TRANSFORM FILENAME.js] [YOUR INPUT FILE.js]

via npm

# npm
npm install @ticklepoke/codemods

# yarn
yarn add @ticklepoke/codemods

Install jscodeshift and format with dos2unix if we want to use jscodeshift within a package.json script

yarn add jscodeshift &&
dos2unix node_modules/jscodeshift/bin/*

Add a transform to your package.json

{
  "scripts": {
    "start": "jscodeshift -d -p -t node_modules/@ticklepoke/codemods/[DESIRED TRANSFORM].js [YOUR INPUT FILE].js",
    "list:transform": "node node_modules/@ticklepoke/codemods/index.js",
    "fix:deps": "dos2unix node_modules/jscodeshift/bin/*"
  },
}

Development

Creating a new transform

To create a new transform, run

yarn plop

This will generate the transform file and relevant test and fixture files.

Testing

Fill in the fixture files with the input and output code. Then, run

yarn test

Branch Naming

Branches follow this naming convention:

  • For new transforms feat/transfrom-[transform_name]

  • For bug fixes: fix/[bug_description]

  • For other chores chore/[chore_description]

Transforms

remove-debugger

Removes all debugger statements

// Input code
1+1;
debugger;

// Output code
1+1;

remove-console

Removes all console statements, include destructured console statements

// Input code
console.log();

const { log } = console;

log();

const copiedLog = log; // Also handles this stupid case

copiedLog();

// Output code
// empty

convert-template-literal

Converts template literals without any template elements to string literals

// Input code
const a = `abcde`;
const b = `1234${true}`;


// Output code
const a = 'abcde';
const b = `1234${true}`;

convert-object-destructure

Converts variable declarations to object destructure. Also combines object destructures of the same member expression

// Input code
const a = obj.a;
const b = obj.b;
const d = obj.c;

const c = newObj.c;

function bar() {
  const a = obj.a;
  const c = obj.c;
  const d = obj.c;
  const e = otherObj.a;
}

// Output code
const {
    a,
    b,
    c: d
} = obj;

const {
  c
} = newObj;

function bar() {
    const {
        a,
        c,
        c: d
    } = obj;
    const {
      a: e
    } = otherObj;
}

convert-object-shorthand

Convert object expressions and object patterns that have the same key and value to shorthand

// Input code
const { a: a } = obj;

bar({a: a});


// Output code
const { a } = obj;

bar({ a });

convert-concat-strings

Converts string concatenations to template literals. Unable to handle escaped characters

// Input code
let vars = "b"
"a" + vars + "c"

// Output code
let vars = "b"
`a${vars}c`

convert-let-const

Converts variable declarations that are not reassigned from let to const.

  • Supports shadowed variables

  • Supports UpdateExpressions (a++)

  • Supports object patterns const { a, b } = .... Entire object is changed to const only if all properties are not reassigned.

  • Supports array patterns let [a, b] = .... Entire array pattern is changed to const only if all properties are not reassigned.

// Input code
let a = 1;
let b = 1;
b = 2;
{
  let a = 2;
  let b = 3;
  a = 3;
}

// Output code
const a = 1;
let b = 1;
b = 2;
{
  let a = 2;
  const b = 3;
  a = 3;
}

convert-function-expression-arrow

Transfrom function expressions to arrow functions without violating lexical this. Only converts if this is not used in the function body:

  • Preserves async function signatures

  • Does not transform generator functions (arrow functions cannot be generators)

// Input code
const a = function() {};
const b = function() { this };

// Output code
const a = () => {};
const b = function() { this };

convert-bind-arrow-function

Transform function expression with .bind(this) to arrow functions.

  • Preserves async function signatures

  • Does not transform generator functions (arrow functions cannot be generators)

// Input code
const a = function() {}.bind(this);

// Output code
const a = () => {};

convert-then-async

Convert .then() promises to async / await with support for catch and finally blocks

  • Supports .then() chaining

  • Only supports promises in a return statement

  • Only supports single param callbacks .then(a => ...) or .then(({a, b}) => ...). Multi params .then((a, b) => ...) and .then(({a, b}, c) => ...) are not allowed

  • Supports .then().catch().finally(), then().finally()

Improvements: Support for .then().finally().then()

// Input code
function bar() {
  return myPromise.then((a) => a).catch(e => e).finally()
}

// Output code
async function bar() {
  try {
    const a = await myPromise;
  } catch (e) {
    return e
  } finally {

  }
}

convert-spread-assign

Converts object spread to Object.assign, preserving order of properties being written

// Input code
const a = {
  a: 1,
  b: 2,
  ...otherObj
}

const b = {
  a: 1,
  ...otherObj,
  b:2
}

// Output code
const a = Object.assign({}, {a:1, b:2}, otherObj)

const b = Object.assign({}, {a:1}, otherObj, {b:2})

convert-chained-declarations

Converts chained variable declarations to individual declarations

// Input code
let a = b = [];
let c = d = 1;

// Output code
let b = [], a = b;

let d = 1, c = d;

convert-react-pure

Converts a react class component with only a render() method into a React.memo functional component

// Input code
class Foo extends React.Component {
  render() {
    return (
      <div>
        {this.props.bar}
      </div>
    )
  }
}

// Output code
const Foo = React.memo(function (props) {
  return (
    <div>
      {props.bar}
    </div>
  )
})

Road Map

Future transforms in the works. Feel free to open an issue if you would like to suggest another transform.

  • [ ] no-params-reassignment: Convert function params reassignment to scoped variables
// from this
bar(baz) {
    baz = 1;
}

// to this
bar(baz) {
    _baz = 1;
}
  • [ ] convert-await-loop-promise-all: Converts await statements in a loop into Promise.all()
// from this
let data = []
for (let i ....) {
    data.push(await fn())
}
return data

// to this
let promises = [];
for (let i ...) {
    promises.push(fn())
}
return Promise.all(promises)

React Codemods

  • [ ] destructure-props: Destructures react props:
// from this:
this.props.bar;

// to this
const { bar } = this.props;
bar;