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

@codemodsquad/asyncify

v2.2.2

Published

transforms promise chains into async/await

Downloads

119

Readme

@codemodsquad/asyncify

CircleCI Coverage Status semantic-release Commitizen friendly npm version

Transforms promise chains into async/await. I wrote this to refactor the 5000+ .then/.catch/.finally calls in the sequelize codebase. This is slightly inspired by async-await-codemod, but written from scratch to guarantee that it doesn't change the behavior of the transformed code, and keeps the code reasonably tidy.

Usage

npx @codemodsquad/asyncify path/to/your/project/**/*.js

This command just forwards to jscodeshift, you can pass other jscodeshift CLI options.

Support table

| | asyncify | | ------------------------------------------------------------------ | ---------- | | Converts .then | ✅ | | Converts .catch | ✅ | | Converts .finally | ✅ | | Renames identifiers in handlers that would conflict | ✅ | | Converts promise chains that aren't returned/awaited into IIAAFs | ✅ | | Converts return Promise.resolve()/return Promise.reject() | ✅ | | Removes unnecessary Promise.resolve() wrappers | ✅ | | Warns when the original function could return/throw a non-promise | Planned | | Refactoring/inlining handlers that contain conditional returns | | | All but one if/else/switch branch return | ✅ | | All branches return, even nested ones | ✅ | | All but one nested if/else/switch branch return | 🚫 | | More than one if/else/switch branch doesn't return | 🚫 | | Return inside loop | 🚫 |

Warnings

Comments can sometimes get deleted due to an impedance mismatch between @babel and recast ASTs. If you use the --commentWorkarounds=true option it will try to prevent more comments from getting deleted but it sometimes causes an assertion to fail in recast.

There are a few edge cases where asyncify produces funky output. It's intended to not break any existing behavior (I know of no cases where it does, and I have fixed several such issues) but sometimes the output will be be semantically wrong even if it behaves correctly. For example, I've seen a case where doing an async operation several times in a row:

it('test', () => {
  const doSomething = () => {
    // ...
  }

  return doSomething()
    .then(doSomething)
    .then(doSomething)
})

Gets converted to:

it('test', async () => {
  const doSomething = () => {
    // ...
  }
  await doSomething(await doSomething(await doSomething()))
})

This works even though it initially seems like it wouldn't and is obviously not what you want:

it('test', async () => {
  const doSomething = () => {
    // ...
  }
  await doSomething()
  await doSomething()
  await doSomething()
})

Although I could possibly fix this for cases where it's easy to determine that the function has no parameters, there could be cases where it's impossible to determine whether the identifier doSomething is even a function or whether it has parameters.

Disabling recast workaround

At the time I wrote asyncify, there were some show-stopping bugs in old version of recast that jscodeshift depended on. To avoid this problem, asyncify parses with a newer version of recast in its own dependencies, instead of parsing with the jscodeshift API. The author of putout has asked to be able to parse with the injected jscodeshift API for performance, so you can access that version of the jscodeshift transform as:

import transform from '@codemodsquad/asyncify/noRecastWorkaround'

Or there are two ways you can do it when running via jscodeshift:

jscodeshift -t path/to/asyncify/noRecastWorkaround.js
jscodeshift -t path/to/asyncify/index.js --noRecastWorkaround=true