{"id":26925234,"url":"https://github.com/smbcheeky/error-object","last_synced_at":"2025-07-28T21:08:54.344Z","repository":{"id":277372555,"uuid":"932214272","full_name":"SMBCheeky/error-object","owner":"SMBCheeky","description":"Create errors that can be both thrown and returned. Make error handling easier for both JavaScript and TypeScript.","archived":false,"fork":false,"pushed_at":"2025-04-21T13:16:47.000Z","size":90,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-25T22:42:03.313Z","etag":null,"topics":["catch","caught","debug","error","error-handling","errors","exception","exceptions","instanceof","neverthrow","ok","result","try"],"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/SMBCheeky.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}},"created_at":"2025-02-13T14:58:37.000Z","updated_at":"2025-05-15T02:26:59.000Z","dependencies_parsed_at":"2025-02-13T16:29:08.870Z","dependency_job_id":"dbf31aa0-7719-4181-bc09-34173a3e9746","html_url":"https://github.com/SMBCheeky/error-object","commit_stats":null,"previous_names":["smbcheeky/error-object"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/SMBCheeky/error-object","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SMBCheeky%2Ferror-object","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SMBCheeky%2Ferror-object/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SMBCheeky%2Ferror-object/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SMBCheeky%2Ferror-object/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SMBCheeky","download_url":"https://codeload.github.com/SMBCheeky/error-object/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SMBCheeky%2Ferror-object/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267585783,"owners_count":24111577,"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","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["catch","caught","debug","error","error-handling","errors","exception","exceptions","instanceof","neverthrow","ok","result","try"],"created_at":"2025-04-02T02:33:45.253Z","updated_at":"2025-07-28T21:08:54.332Z","avatar_url":"https://github.com/SMBCheeky.png","language":"TypeScript","readme":"[![License](https://img.shields.io/npm/l/@smbcheeky/error-object)](LICENSE_FILE)\n[![deno.bundlejs.com](https://deno.bundlejs.com/badge?q=@smbcheeky/error-object\u0026treeshake=[*])](https://deno.bundlejs.com/?q=@smbcheeky/error-object\u0026treeshake=[*])\n[![npm downloads](https://img.shields.io/npm/dm/@smbcheeky/error-object)](https://www.npmjs.com/package/@smbcheeky/error-object)\n[![GitHub last commit](https://img.shields.io/github/last-commit/smbcheeky/error-object)](https://github.com/smbcheeky/error-object)\n[![GitHub stars](https://img.shields.io/github/stars/smbcheeky/error-object)](https://img.shields.io/github/stars/smbcheeky/error-object)\n\n## TL;DR\n\n- Install the package `npm install @smbcheeky/error-object`\n- Write `ErrorObject.from(\u003cpick an api response with an error\u003e).force.verboseLog('LOG')` and use the info provided to\n  map your error\n- Switch the .force with .error, and now you have an error object\n- :tada:\n- oh... and check the [playground](https://github.com/SMBCheeky/error-object/blob/main/playground/index.ts) file\n\n## Installation\n\n`npm install @smbcheeky/error-object`\n\n`yarn add @smbcheeky/error-object`\n\n## Description\n\nThe ErrorObject class is made to extend `Error` enabling checks like `errorObject instanceof Error` or\n`errorObject instanceof ErrorObject`. The `ErrorObject` class is backwards compatible with `Error` and introduces a few\nnew features:\n\n- It can be thrown or returned, you choose.\n- It can be valid only if it contains a `code` and a `message` values\n- It can have a numberCode, not just a string code\n- set default values for the generic and fallback error objects via `ErrorObject.DEFAULT_GENERIC_CODE` and\n  `ErrorObject.DEFAULT_GENERIC_MESSAGE`\n- set a default domain for all errors via `ErrorObject.DEFAULT_DOMAIN`\n- Use `ErrorObject.generic()` or `ErrorObject.withTag('TAG')` to create an error from thin air\n- Use `.isGeneric()`, `.isFallback()` and `.hasTag()` to check if the error is a generic error, a fallback error or\n  has a specific tag\n- Chain call setters like `.setCode()`, `.setNumberCode()`, `.setMessage()`, `.setDetails()`, `.setDomain()`,\n  `.setTag()` to modify the error\n  object at any moment\n- Setters can receive a value or a transform function, facilitating access to the current value while you modify the\n  property\n- Chain logs like `.log(tag)`, `.debugLog(tag)`, `.verboseLog(tag)` to log information about the error object\n  inline\n- Use `.description()` or `.toString()` to get a human-readable description of the error\n- Use `details`, `domain` and `tag` to customize the error object and help easily distinguish between different\n  errors\n\n## ErrorObject.from\n\nUse `ErrorObject.from(\u003canything\u003e)` to create errors from any input:\n\n- you can pass an object or a caught error to it, and it will try its best to create an error from it\n- `ErrorObject.from(\u003canything\u003e)` returns an object with two properties: `.error` and `.force`\n- `.error` represents the error, if it can be created, otherwise it is `undefined`\n- `.force` represents the error, if it can be created, otherwise it is going to return a `ErrorObject.fallback()`\n  error\n\nThe processing of the ErrorObject is done in a few steps, based on the `ErrorObjectBuildOptions`:\n\n- first the initial object is checked via the options `checkInputObjectForValues` and `checkInputObjectForTypes` and\n  `checkInputObjectForKeys`\n- then the objects checks for an object array at `pathToErrors`, which could be an array of errors\n- if an error array is found, the process will consider all other paths relative to the objects in the error array found\n- if an error array is not found, the process will consider all other paths absolute to the initial objectpassed to\n  `ErrorObject.from()`\n- the `pathToCode`, `pathToNumberCode`, `pathToMessage`, `pathToDetails` and `pathToDomain` options are used to map\n  values to their associated field, if found\n- for all fields other than `numberCode`, if a value is found and is a string, it is saved as is, but if it is an array\n  or an object it will be JSON.stringify'ed and saved as a string\n- for `numberCode`, if a value is found and it is a number different than `NaN`, it is saved\n- the `transform` function is used to transform the found values by the parsing process into the error object\n- the transform function has access to all pre-transformation values and also the initial object (object inside the\n  errors array or initial object)\n- everything gets processed into a list of `ErrorSummary | ErrorObjectErrorResult` array\n- it contains everything, from error strings custom-made to be as distinct and easy to read as possible, to self\n  documenting summaries of what values are found, at which path, if an errors object was found, etc.\n- the count of the list is meant to be an indication of how many input objects were found and processed, as each of them\n  should become an error object\n- in the last step of the process, the list is filtered down and a single error object is created, with everything baked\n  in\n- think detailed `processingErrors` which includes the summaries and the errors that were triggered during the process,\n  the `raw` object that was used as in input for the ErrorObject.from() call and the `nextErrors` array which allows for\n  all errors to be saved on one single error object for later use\n\n## Usage \u0026 Examples\n\nFor a guide on how to use the library, please check the first detailed example in\nthe [playground](https://github.com/SMBCheeky/error-object/blob/main/playground/index.ts) file.\n\n```typescript\nnew ErrorObject({ code: '', message: 'Something went wrong.', domain: 'auth' }).debugLog('LOG');\n\nErrorObject.from({ code: '', message: 'Something went wrong', domain: 'auth' })?.force?.debugLog('LOG');\n\n// Example 12 output:\n// \n// [LOG] Something went wrong. [auth]\n// {\n//   \"code\": \"\",\n//   \"message\": \"Something went wrong.\",\n//   \"domain\": \"auth\"\n// }\n// \n// [LOG] Something went wrong [auth]\n// {\n//   \"code\": \"\",\n//   \"message\": \"Something went wrong\",\n//   \"domain\": \"auth\"\n// }\n```\n\n```typescript\nconst response = {\n  statusCode: 400,\n  headers: {\n    'Content-Type': 'application/json',\n  },\n  body: '{\"error\":\"Invalid input data\",\"code\":400}',\n};\n\nErrorObject.from(JSON.parse(response?.body), {\n  pathToNumberCode: ['code'],\n  pathToMessage: ['error'],\n}).force?.debugLog('LOG');\n\n// Example 6 output:\n//\n// [LOG] Invalid input data [400]\n// {\n//   \"code\": \"400\",\n//   \"numberCode\": 400,\n//   \"message\": \"Invalid input data\"\n// }\n```\n\n```typescript\n/* \n * You could have a file called `errors.ts` in each of your modules/folders and \n * define a function like `createAuthError2()` that returns an error object with \n * the correct message and domain.\n */\nconst AuthMessageResolver = (\n  beforeTransform: ErrorObjectTransformState): ErrorObjectTransformState =\u003e {\n  // Quick tip: Make all messages slightly different, to make it easy\n  // to find the right one when debugging, even in production\n  let message: string | undefined;\n  switch (beforeTransform.code) {\n    case 'generic':\n      message = 'Something went wrong';\n      break;\n    case 'generic-again':\n      message = 'Something went wrong. Please try again.';\n      break;\n    case 'generic-network':\n      message = 'Something went wrong. Please check your internet connection and try again.';\n      break;\n    default:\n      message = 'Something went wrong.';\n  }\n  return { ...beforeTransform, message };\n};\n\nconst createAuthError2 = (code: string) =\u003e {\n  return ErrorObject.from({ code, domain: 'auth', }, { transform: AuthMessageResolver, });\n};\n\n\ncreateAuthError2('generic')?.error?.log('1');\ncreateAuthError2('generic-again')?.error?.log('2');\ncreateAuthError2('generic-network')?.error?.log('3');\ncreateAuthError2('invalid-code')?.error?.log('4');\n\n// Example 2 output:\n//\n// [1] Something went wrong [auth/generic]\n// [2] Something went wrong. Please try again. [auth/generic-again]\n// [3] Something went wrong. Please check your internet connection and try again. [auth/generic-network]\n// [4] Something went wrong. [auth/invalid-code]\n```\n\n## FAQ\n\n### How do I use paths? Are they absolute?\n\nTo support inputs containing arrays of errors as well as single errors, all paths are treated initially as absolute (\nfrom the\ninput root), but if an array of errors is detected, it will consider each element found the new root input object. Devs\nhave a\nchoice: set the \"pathToErrors\" option as empty, and then map only the first error (highly not recommended), or adjust\nthe paths to be relative to the objects inside the detected errors array.\n\n### How do I use paths? I sometimes get the error code in an `error` object, and sometimes in the root object...\n\nYou can use `pathToCode: addPrefixPathVariants('error', ['code']),` or `pathToCode: ['error.code']`\n\n### How do I use paths? Can I get the raw contents of a path and process it later?\n\nYes, you can. You can use paths like `error.details.0` to get a raw value, and then process it later using the\n`transform` option.\nIf the value is not a string, it will be converted to a string using `JSON.stringify` to ensure everything works as\nintended.\nRemember, for an ErrorObject to be created, it needs at least a code and a message, and both are required to be string\nvalues.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmbcheeky%2Ferror-object","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmbcheeky%2Ferror-object","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmbcheeky%2Ferror-object/lists"}