{"id":15442197,"url":"https://github.com/arthurfiorette/tuple-it","last_synced_at":"2025-04-07T07:13:37.324Z","repository":{"id":238607655,"uuid":"796965683","full_name":"arthurfiorette/tuple-it","owner":"arthurfiorette","description":"🦋 A simple Promise to [error, data] catcher.","archived":false,"fork":false,"pushed_at":"2024-10-28T21:00:03.000Z","size":177,"stargazers_count":45,"open_issues_count":6,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-31T06:08:20.788Z","etag":null,"topics":["async","await","error","it","js","promise","to","tuple","typescript"],"latest_commit_sha":null,"homepage":"https://npm.im/tuple-it","language":"JavaScript","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/arthurfiorette.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"arthurfiorette"}},"created_at":"2024-05-07T00:27:54.000Z","updated_at":"2025-03-05T21:45:31.000Z","dependencies_parsed_at":"2024-07-30T02:47:19.455Z","dependency_job_id":"daf9e2e3-5ca6-4ac8-a890-b9cb32f72500","html_url":"https://github.com/arthurfiorette/tuple-it","commit_stats":{"total_commits":45,"total_committers":4,"mean_commits":11.25,"dds":0.1333333333333333,"last_synced_commit":"32dc86108ae76e5c118bedf320c574c6ac8d6e41"},"previous_names":["arthurfiorette/tupleit"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurfiorette%2Ftuple-it","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurfiorette%2Ftuple-it/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurfiorette%2Ftuple-it/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurfiorette%2Ftuple-it/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arthurfiorette","download_url":"https://codeload.github.com/arthurfiorette/tuple-it/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247608153,"owners_count":20965952,"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","error","it","js","promise","to","tuple","typescript"],"created_at":"2024-10-01T19:25:42.090Z","updated_at":"2025-04-07T07:13:37.299Z","avatar_url":"https://github.com/arthurfiorette.png","language":"JavaScript","readme":"\u003cdiv align=\"center\"\u003e\n  \u003ca title=\"MIT license\" target=\"_blank\" href=\"https://github.com/arthurfiorette/tuple-it/blob/master/LICENSE\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/github/license/arthurfiorette/tuple-it\"\u003e\u003c/a\u003e\n  \u003ca title=\"Bundle size\" target=\"_blank\" href=\"https://bundlephobia.com/package/tuple-it\"\u003e\u003cimg alt=\"Bundlephobia\" src=\"https://img.shields.io/bundlephobia/minzip/tuple-it/latest\"\u003e\u003c/a\u003e\n  \u003ca title=\"Codecov\" target=\"_blank\" href=\"https://app.codecov.io/gh/arthurfiorette/tuple-it\"\u003e\u003cimg alt=\"Codecov\" src=\"https://img.shields.io/codecov/c/github/arthurfiorette/tuple-it?token=ML0KGCU0VM\"\u003e\u003c/a\u003e\n  \u003ca title=\"NPM Package\" target=\"_blank\" href=\"https://www.npmjs.com/package/tuple-it\"\u003e\u003cimg alt=\"Downloads\" src=\"https://img.shields.io/npm/dw/tuple-it?style=flat\"\u003e\u003c/a\u003e\n  \u003ca title=\"Install size\" target=\"_blank\" href=\"https://packagephobia.com/result?p=tuple-it\"\u003e\u003cimg alt=\"Bundlephobia\" src=\"https://packagephobia.com/badge?p=tuple-it\"\u003e\u003c/a\u003e\n  \u003ca title=\"Last Commit\" target=\"_blank\" href=\"https://github.com/arthurfiorette/tuple-it/commits/master\"\u003e\u003cimg alt=\"Last commit\" src=\"https://img.shields.io/github/last-commit/arthurfiorette/tuple-it\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/arthurfiorette/tuple-it/stargazers\"\u003e\u003cimg src=\"https://img.shields.io/github/stars/arthurfiorette/tuple-it?logo=github\u0026label=Stars\" alt=\"Stars\"\u003e\u003c/a\u003e\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n\u003cimg align=\"center\" src=\"./assets/cover.png\" /\u003e\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n\u003ch1 align=\"center\"\u003e\n  Tuple it!\n\u003c/h1\u003e\n\n\u003ch3 align=\"center\"\u003e\n  A simple \u003ccode\u003ePromise\u003c/code\u003e to \u003ccode\u003e[error, data]\u003c/code\u003e catcher.\n\u003c/h3\u003e\n\n\u003cbr /\u003e\n\u003cbr /\u003e\n\n- [Introduction](#introduction)\n- [How to Use](#how-to-use)\n- [Avoiding Global Scope Pollution](#avoiding-global-scope-pollution)\n- [The `TupleItError` Class](#the-tupleiterror-class)\n- [Promisable Objects](#promisable-objects)\n- [Typescript Support](#typescript-support)\n- [License](#license)\n- [Credits](#credits)\n\n\u003cbr /\u003e\n\n## Introduction\n\n**TupleIt** is a handy utility designed to simplify error handling with `async`/`await` operations in JavaScript.\n\nIt wraps the `await` statement in a `[error, data]` tuple, allowing you to easily discern whether a promise was rejected or resolved without resorting to nested `try`/`catch` blocks.\n\nThis not only enhances code readability but also mitigates one of the most common mistakes in JavaScript development - mishandling promise rejections.\n\n\u003cbr /\u003e\n\n## How to Use\n\n\u003e [!CAUTION]\n\u003e Extending the `Promise` prototype in a library is considered a horrible practice.\n\n**TupleIt** provides an import `tuple-it/register` to extend the `Promise` prototype:\n\n```typescript\nimport 'tuple-it/register'\n```\n\nNow, you can use the `.tuple()` method on any `Promise` object:\n\n```typescript\nasync function work(promise: Promise\u003cWorkData\u003e) {\n  const [error, data] = await promise.tuple()\n\n  if (error) {\n    console.log('Operation failed!')\n    return false\n  }\n\n  console.log('Operation succeeded!')\n  return true\n}\n```\n\n\u003cbr /\u003e\n\n## Avoiding Global Scope Pollution\n\nIf you're developing a library, it's advised not to pollute the global scope. Instead, you can import the `t` function directly (an alias for `tuple`):\n\n```typescript\nimport { t } from 'tuple-it'\n\nconst [error, data] = await t(someAsyncFunction())\n```\n\n\u003cbr /\u003e\n\n## The `TupleItError` Class\n\nOccasionally, promises might reject with non-error objects, which is a poor practice but still happens. **TupleIt** will wrap any non-`Error` object into a `TupleItError` object if it's not an instance of `Error`:\n\n```typescript\nimport { TupleItError } from 'tuple-it'\n\nasync function someAsyncFunction() {\n  throw 'Please avoid throwing strings!'\n}\n\nconst [error, data] = await someAsyncFunction().tuple()\n\nif (error instanceof TupleItError) {\n  console.error(error.error) // Logs the original object that was thrown.\n}\n```\n\n\u003cbr /\u003e\n\n## Promisable Objects\n\nIn some cases, functions may return either values or promises for performance optimization. **TupleIt** handles this scenario seamlessly:\n\n```typescript\nimport { t } from 'tuple-it'\n\nfunction someFunction() {\n  if (Math.random() \u003e 0.5) {\n    return 'Hello, World!'\n  } else {\n    return Promise.resolve('Hello, World!')\n  }\n}\n\n// Works the same way!\nconst [error, data] = await t(someFunction())\n```\n\n\u003cbr /\u003e\n\n## Typescript Support\n\nTypescript is fully supported:\n\n```ts\nimport 'tuple-it/register'\nimport { t } from 'tuple-it'\n\n// Custom error type (Defaults to Error)\nconst [customError, data] = await promise.then\u003cCustomError\u003e()\n\n// Custom data type\nconst [error, customData] = await t\u003cCustomData\u003e(promise)\n\n// Custom data and error types\nconst [customError, customData] = await t\u003cCustomError, CustomData\u003e(promise)\n```\n\n\u003cbr /\u003e\n\n## License\n\nThis project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.\n\n\u003cbr /\u003e\n\n## Credits\n\n**TupleIt** draws heavy inspiration from [`await-to-js`](https://github.com/scopsy/await-to-js).\n\n\u003cbr /\u003e\n","funding_links":["https://github.com/sponsors/arthurfiorette"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farthurfiorette%2Ftuple-it","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farthurfiorette%2Ftuple-it","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farthurfiorette%2Ftuple-it/lists"}