{"id":21186033,"url":"https://github.com/codemodsquad/asyncify","last_synced_at":"2025-07-10T01:30:52.880Z","repository":{"id":39964802,"uuid":"254710597","full_name":"codemodsquad/asyncify","owner":"codemodsquad","description":"Don't keep your promises 😉","archived":false,"fork":false,"pushed_at":"2023-01-07T04:38:15.000Z","size":1109,"stargazers_count":13,"open_issues_count":18,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-18T13:25:17.655Z","etag":null,"topics":["async","await","chain","codemod","promise","refactoring","then","thenable"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codemodsquad.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-04-10T18:46:16.000Z","updated_at":"2023-10-09T03:50:16.000Z","dependencies_parsed_at":"2023-02-06T12:01:14.240Z","dependency_job_id":null,"html_url":"https://github.com/codemodsquad/asyncify","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemodsquad%2Fasyncify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemodsquad%2Fasyncify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemodsquad%2Fasyncify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemodsquad%2Fasyncify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codemodsquad","download_url":"https://codeload.github.com/codemodsquad/asyncify/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225607480,"owners_count":17495737,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","await","chain","codemod","promise","refactoring","then","thenable"],"created_at":"2024-11-20T18:20:53.155Z","updated_at":"2024-11-20T18:20:53.597Z","avatar_url":"https://github.com/codemodsquad.png","language":"TypeScript","readme":"# @codemodsquad/asyncify\n\n[![CircleCI](https://circleci.com/gh/codemodsquad/asyncify.svg?style=svg)](https://circleci.com/gh/codemodsquad/asyncify)\n[![Coverage Status](https://codecov.io/gh/codemodsquad/asyncify/branch/master/graph/badge.svg)](https://codecov.io/gh/codemodsquad/asyncify)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)\n[![npm version](https://badge.fury.io/js/%40codemodsquad%2Fasyncify.svg)](https://badge.fury.io/js/%40codemodsquad%2Fasyncify)\n\nTransforms promise chains into `async`/`await`. I wrote this to refactor the 5000+ `.then`/`.catch`/`.finally` calls in the\n`sequelize` codebase. This is slightly inspired by [async-await-codemod](https://github.com/sgilroy/async-await-codemod),\nbut written from scratch to guarantee that it doesn't change the behavior of the transformed code, and keeps the code reasonably tidy.\n\n## Usage\n\n```\nnpx @codemodsquad/asyncify path/to/your/project/**/*.js\n```\n\nThis command just forwards to `jscodeshift`, you can pass other `jscodeshift` CLI options.\n\n## Support table\n\n|                                                                    | `asyncify` |\n| ------------------------------------------------------------------ | ---------- |\n| Converts `.then`                                                   | ✅         |\n| Converts `.catch`                                                  | ✅         |\n| Converts `.finally`                                                | ✅         |\n| Renames identifiers in handlers that would conflict                | ✅         |\n| Converts promise chains that aren't returned/awaited into IIAAFs   | ✅         |\n| Converts `return Promise.resolve()`/`return Promise.reject()`      | ✅         |\n| Removes unnecessary `Promise.resolve()` wrappers                   | ✅         |\n| Warns when the original function could return/throw a non-promise  | Planned    |\n| **Refactoring/inlining handlers that contain conditional returns** |            |\n| All but one if/else/switch branch return                           | ✅         |\n| All branches return, even nested ones                              | ✅         |\n| All but one nested if/else/switch branch return                    | 🚫         |\n| More than one if/else/switch branch doesn't return                 | 🚫         |\n| Return inside loop                                                 | 🚫         |\n\n## Warnings\n\nComments can sometimes get deleted due to an impedance mismatch between `@babel` and `recast`\nASTs. If you use the `--commentWorkarounds=true` option it will try to prevent more comments\nfrom getting deleted but it sometimes causes an assertion to fail in `recast`.\n\nThere are a few edge cases where `asyncify` produces funky output. It's intended to not break\nany existing behavior (I know of no cases where it does, and I have fixed several such issues)\nbut sometimes the output will be be semantically wrong even if it behaves\ncorrectly. For example, I've seen a case where doing an async operation several times in a row:\n\n```js\nit('test', () =\u003e {\n  const doSomething = () =\u003e {\n    // ...\n  }\n\n  return doSomething()\n    .then(doSomething)\n    .then(doSomething)\n})\n```\n\nGets converted to:\n\n```js\nit('test', async () =\u003e {\n  const doSomething = () =\u003e {\n    // ...\n  }\n  await doSomething(await doSomething(await doSomething()))\n})\n```\n\nThis works even though it initially seems like it wouldn't and is obviously not what you want:\n\n```js\nit('test', async () =\u003e {\n  const doSomething = () =\u003e {\n    // ...\n  }\n  await doSomething()\n  await doSomething()\n  await doSomething()\n})\n```\n\nAlthough I could possibly fix this for cases where it's easy to determine that the function has\nno parameters, there could be cases where it's impossible to determine whether the identifier\n`doSomething` is even a function or whether it has parameters.\n\n## Disabling `recast` workaround\n\nAt the time I wrote `asyncify`, there were some show-stopping bugs in old version of `recast` that\n`jscodeshift` depended on. To avoid this problem, `asyncify` parses with a newer version of `recast` in its\nown dependencies, instead of parsing with the `jscodeshift` API. The author of `putout` has asked to be able\nto parse with the injected `jscodeshift` API for performance, so you can access that version of the\n`jscodeshift` transform as:\n\n```js\nimport transform from '@codemodsquad/asyncify/noRecastWorkaround'\n```\n\nOr there are two ways you can do it when running via `jscodeshift`:\n\n```\njscodeshift -t path/to/asyncify/noRecastWorkaround.js\njscodeshift -t path/to/asyncify/index.js --noRecastWorkaround=true\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodemodsquad%2Fasyncify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodemodsquad%2Fasyncify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodemodsquad%2Fasyncify/lists"}