{"id":17929180,"url":"https://github.com/skarab42/ts-pojo-error","last_synced_at":"2025-03-24T04:30:55.236Z","repository":{"id":57701388,"uuid":"477693898","full_name":"skarab42/ts-pojo-error","owner":"skarab42","description":"🔥 Type safe pojo error will help you to easily create typed and serializable error.","archived":false,"fork":false,"pushed_at":"2023-10-06T18:12:06.000Z","size":1430,"stargazers_count":14,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-19T02:45:30.669Z","etag":null,"topics":["error","error-handling","exception","json","pojo","serializable","type-safety","typed","typescript"],"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/skarab42.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"skarab42","custom":"http://paypal.me/skarab"}},"created_at":"2022-04-04T12:37:39.000Z","updated_at":"2024-10-06T20:51:36.000Z","dependencies_parsed_at":"2022-08-29T04:31:35.048Z","dependency_job_id":null,"html_url":"https://github.com/skarab42/ts-pojo-error","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skarab42%2Fts-pojo-error","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skarab42%2Fts-pojo-error/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skarab42%2Fts-pojo-error/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skarab42%2Fts-pojo-error/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skarab42","download_url":"https://codeload.github.com/skarab42/ts-pojo-error/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245210845,"owners_count":20578299,"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":["error","error-handling","exception","json","pojo","serializable","type-safety","typed","typescript"],"created_at":"2024-10-28T21:07:57.093Z","updated_at":"2025-03-24T04:30:54.931Z","avatar_url":"https://github.com/skarab42.png","language":"TypeScript","funding_links":["https://github.com/sponsors/skarab42","http://paypal.me/skarab"],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e🔥 Type safe pojo error will help you to easily create typed and serializable error.\u003c/h1\u003e\n\n\u003ctable align=\"center\"\u003e\n  \u003ctr\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://github.com/skarab42/ts-pojo-error/actions/workflows/CI.yaml\"\u003e\n        \u003cimg src=\"https://github.com/skarab42/ts-pojo-error/actions/workflows/CI.yaml/badge.svg\"\u003e\n      \u003c/a\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://codecov.io/gh/skarab42/ts-pojo-error\"\u003e\n        \u003cimg src=\"https://codecov.io/gh/skarab42/ts-pojo-error/branch/main/graph/badge.svg?token=4PSFJBVAFB\"\u003e\n      \u003c/a\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://img.shields.io/github/languages/code-size/skarab42/ts-pojo-error?color=success\u0026style=flat\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003cimg src=\"https://img.shields.io/github/license/skarab42/ts-pojo-error?color=success\"\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://github.com/sponsors/skarab42\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/sponsors/skarab42?color=ff69b4\u0026label=%E2%9D%A4%20sponsors%20\"\u003e\n      \u003c/a\u003e\n    \u003c/td\u003e\n    \u003ctd\u003e\n      \u003ca href=\"https://www.twitch.tv/skarab42\"\u003e\n        \u003cimg src=\"https://img.shields.io/twitch/status/skarab42?style=social\"\u003e\n      \u003c/a\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"images/ts-pojo-error.gif\"\u003e\n\u003c/p\u003e\n\n# Intro\n\n**The problem with exceptions is that once caught you don't know what type they are.** You can of course create a bunch of custom error classes and use `instanceof` to overcome this. The advantage of `ts-pojo-error` is that you have a single error type `PojoError` which can be easily typed and serialized.\n\n# Features\n\n- 🔥 Type safe \u0026 autocompletion\n- 👓 Serializable output\n- 🔗 [Stackable](https://github.com/tc39/proposal-error-cause) errors\n- 🌌 Node or Browser\n- 🌓 ESM or CJS\n- ✅ Well tested\n\n# Usage\n\n## Installation\n\n```bash\npnpm add @skarab/ts-pojo-error # yarn and npm also works\n```\n\n## Defining an error factory\n\n- **factory(** errors: `PojoErrorTypes` **)** : `PojoFactory`\n\nAn error factory is constructed from a `Record` where the key is the type of the error and the value is a `callback` that defines the `PojoError`.\nThe `callback` parameters define the parameters passed at the creation of the error and the return value defines the data of the error.\n\n```ts\n// errors.ts\n\nimport { factory } from \"@skarab/ts-pojo-error\";\n\nexport const errors = factory({\n  UNKNOWN: () =\u003e ({ message: \"Unknown error...\" }),\n  WARNING: (message: string) =\u003e ({ message, time: Date.now() }),\n  FATAL: (message?: string) =\u003e ({ message: message ?? \"Fatal error\" }),\n  EXIT: (message: string, code: number) =\u003e ({ message, code }),\n});\n```\n\n## Instantiating \u0026 Throwing errors\n\n- **new(** type: `infered`, ...args: `infered[]` **)** : `PojoError`\n- **throw(** type: `infered`, ...args: `infered[]` **)** : `never`\n\nThe first parameter is always the type of error, the following parameters are the ones you set in the factory.\n\n\u003e All parameters have support for autocompletion.\n\n```ts\n// action.ts\n\nimport { errors } from \"./errors\";\n\nexport function action() {\n  // Do your awsome stuff...\n\n  // ...something go wrong, throw an typed error\n  throw errors.new(\"FATAL\");\n\n  // or with a custom error message\n  throw errors.new(\"FATAL\", \"Oupsy!\");\n\n  // or by using the .throw helper\n  errors.throw(\"FATAL\");\n\n  // or by using the fake enum\n  errors.throw(errors.type.FATAL);\n}\n```\n\n## Catching \u0026 Typing errors\n\n- **is(** type: `infered`, error: `unknown` **)** : boolean\n- **has(** error: `unknown` **)** : boolean\n\nThis is where it gets really interesting, the problem with exceptions is that once caught you don't know what type they are. You can of course create a bunch of custom error classes and use `instanceof` to overcome this. The advantage of `ts-pojo-error` is that you have a single error type `PojoError` which can be easily typed and serialized.\n\nThe `is` method is a [type guard](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) that will narrow the error to the specific type if the original type is compatible.\n\n\u003e In the if block all properties are typed and have support for autocompletion.\n\n```ts\n// index.ts\n\nimport { action } from \"./action\";\nimport { errors } from \"./errors\";\n\ntry {\n  action();\n} catch (error) {\n  error; // \u003c- unknown type\n\n  if (errors.is(\"FATAL\", error)) {\n    error; // \u003c- PojoError instance with type \"FATAL\"\n\n    error.message; // \"Oupsy!\": string\n\n    error.type; // \"FATAL\": \"FATAL\"\n    error.args; // [\"Oupsy!\"] : [message?: string | undefined]\n    error.data; // { message: \"Oupsy!\" }: { message: string }\n\n    error.cause; // Error | undefined (see \"Stacking of errors\" below)\n\n    error.toObject(); // { type, args, data, stack?: string | undefined }\n    error.toJSON(); // string\n  }\n\n  if (errors.has(error)) {\n    error.type; // \"UNKNOWN\" | \"WARNING\" | \"FATAL\" | ...\n  }\n\n  if (error instanceof PojoError) {\n    error.type; // any (Bad!)\n  }\n}\n```\n\n## Stacking of errors\n\n- **newFrom(** cause: Error, type: `infered`, ...args: `infered[]` **)** : `PojoError`\n- **throwFrom(** cause: Error, type: `infered`, ...args: `infered[]` **)** : `never`\n\nBasically it adds a `.cause` property with the parent error to the newly created `PojoError`, see [Error Cause](https://github.com/tc39/proposal-error-cause) tc39 proposal for further information.\n\n```ts\ntry {\n  throw myErrors.new(\"UNKNOWN\");\n} catch (error) {\n  throw myErrors.newFrom(error, \"FATAL\");\n}\n```\n\nYou can stack any type of error.\n\n```ts\ntry {\n  throw new Error(\"Unknown error\");\n} catch (error) {\n  myErrors.throwFrom(error, \"FATAL\");\n}\n```\n\n### Usage with [voxpelli/pony-cause](https://github.com/voxpelli/pony-cause)\n\nThis library coded by [@voxpelli](https://twitter.com/voxpelli/status/1438476680537034756) includes a couple of helpers inspired by VError, supporting both standard causes and VError causes.\n\n```ts\nimport { stackWithCauses } from \"pony-cause\";\n\nconst error1 = myErrors.new(\"UNKNOWN\");\nconst erorr2 = myErrors.newFrom(error1, \"FATAL\");\nconst error3 = myErrors.newFrom(error2, \"WARNING\", \"Attention to danger !!!\");\nconst error4 = myErrors.newFrom(\n  erorr3,\n  \"PAGE_NOT_FOUND\",\n  \"http://www.prout.com\",\n);\n\nconsole.log(\"We had a mishap:\", stackWithCauses(error4));\n```\n\nTo make the example more readable I have replaced the full stack with `...` but the actual output contains it.\n\n```bash\nWe had a mishap: PojoError: Page Not Found: http://www.prout.com\n    at index.ts:191:31\n    at ...\ncaused by: PojoError: Attention to danger !!!\n    at index.ts:190:31\n    at ...\ncaused by: PojoError: Fatal error\n    at index.ts:189:31\n    at ...\ncaused by: PojoError: Unknown error...\n    at index.ts:188:34\n    at ...\n```\n\n# Contributing 💜\n\nSee [CONTRIBUTING.md](https://github.com/skarab42/ts-pojo-error/blob/main/CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskarab42%2Fts-pojo-error","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskarab42%2Fts-pojo-error","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskarab42%2Fts-pojo-error/lists"}