{"id":13760287,"url":"https://github.com/D-Marc1/far-fetch","last_synced_at":"2025-05-10T10:32:13.258Z","repository":{"id":89895676,"uuid":"263215860","full_name":"D-Marc1/far-fetch","owner":"D-Marc1","description":"Modern Fetch API wrapper for simplicity.","archived":false,"fork":false,"pushed_at":"2022-11-28T03:04:55.000Z","size":97,"stargazers_count":58,"open_issues_count":2,"forks_count":6,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-08-08T19:57:16.381Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://farfetch.js.org","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/D-Marc1.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2020-05-12T02:50:06.000Z","updated_at":"2023-12-13T22:18:38.000Z","dependencies_parsed_at":null,"dependency_job_id":"fdb1b40d-272e-4374-af90-73714698c374","html_url":"https://github.com/D-Marc1/far-fetch","commit_stats":null,"previous_names":["d-marc1/far-fetch","websitebeaver/far-fetch"],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/D-Marc1%2Ffar-fetch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/D-Marc1%2Ffar-fetch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/D-Marc1%2Ffar-fetch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/D-Marc1%2Ffar-fetch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/D-Marc1","download_url":"https://codeload.github.com/D-Marc1/far-fetch/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224949761,"owners_count":17397230,"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":[],"created_at":"2024-08-03T13:01:06.899Z","updated_at":"2024-11-16T17:30:56.021Z","avatar_url":"https://github.com/D-Marc1.png","language":"JavaScript","funding_links":[],"categories":["API"],"sub_categories":["Runner"],"readme":"# FarFetch Class\n\nModern Fetch API wrapper for simplicity.\n\n## Install\n\n```\nnpm i @websitebeaver/far-fetch\n```\n\nThen include it in the files you want to use it in like so:\n\n```js\nimport FarFetch from '@websitebeaver/far-fetch';\n\n// If you need to manually handle errors\nimport FarFetch, { FarFetchError } from '@websitebeaver/far-fetch';\n```\n\n## Instantiating Class\n\n```js\nconst ff = new FarFetch();\n```\n\nThis is how you'd create a class in its simplest form in `FarFetch`. You can\ncheck out [all the options you can use here](#new-farfetchoptions).\n\nIt is recommended to then import the initialized class on every page used.\n\n## Why Use FarFetch?\n\nWhile JavaScript's native `Fetch API` was an amazing feature added, it\nintroduced a myriad of inconsistencies, which cause you to have to copy and\npaste StackOverflow questions for simple boilerplate code often times. This is\nespecially the case with uploading files and I find it hard to believe anyone\njust straight memorizes how to do it. There's so many things to think about. It\nwould have been so much better in a unified experience.\n\nThe core philosophy of `FarFetch` to is keep things as similar as possible to\nnative JavaScript fetch, and merely improve upon it. This way, you're not really\nlearning a completely new API. Instead, the aim of this class is almost to pitch\nwhich features I think are missing in `Fetch API`. The aim of this class isn't\nto recreate the wheel, but rather, to improve upon `Fetch API`, with a super\nthin wrapper. The main advantages over vanilla `Fetch` are as follows:\n\n1. Ability to call syntactic sugar methods like `ff.get()`, `ff.post()`,\n   `ff.put`, etc., rather than `fetch(url, { method: 'GET' })`. `FarFetch`\n   allows both ways.\n2. Ability to [\"automatically\" throw and handle errors](#error-handling) for\n   every call in a unified manner with a global error handler.\n3. Ability to use default [request init options](#passing-in-fetch-api-init-options)\n   on every call.\n4. Ability to do actions before every request\n   with [`beforeSend()` and `afterSend(response)` hooks](#beforeafter-send-hook).\n5. Ability to [pass data to each call in a consistent manner](#passing-in-data-to-request).\n6. Ability to [upload files](#uploading-files) in a consistent manner.\n\n- [FarFetch Class](#farfetch-class)\n  - [Install](#install)\n  - [Instantiating Class](#instantiating-class)\n  - [Why Use FarFetch?](#why-use-farfetch)\n  - [Passing in Data to Request](#passing-in-data-to-request)\n    - [GET Request](#get-request)\n    - [POST Request](#post-request)\n    - [application/x-www-form-urlencoded Request](#applicationx-www-form-urlencoded-request)\n    - [Array or Object as Value for Key for GET Request](#array-or-object-as-value-for-key-for-get-request)\n    - [Passing in URLParams to Request](#passing-in-urlparams-to-request)\n  - [Uploading Files](#uploading-files)\n    - [Uploading One File](#uploading-one-file)\n    - [Uploading Multiple Files](#uploading-multiple-files)\n    - [Uploading Multiple Files with Distinct File Names](#uploading-multiple-files-with-distinct-file-names)\n  - [Passing in Fetch API init options](#passing-in-fetch-api-init-options)\n    - [Set Options for Single Request](#set-options-for-single-request)\n    - [Set Global Options for Every Request](#set-global-options-for-every-request)\n    - [Set Dynamic Options for Every Request](#set-dynamic-options-for-every-request)\n  - [Getting Response](#getting-response)\n    - [Retrieving Response Data](#retrieving-response-data)\n  - [Set Base URL](#set-base-url)\n  - [Before/After Send Hook](#beforeafter-send-hook)\n    - [Turn off Before/After Send Hook on Single Request](#turn-off-beforeafter-send-hook-on-single-request)\n  - [Error Handling](#error-handling)\n    - [Modifying the Default Error Message Template](#modifying-the-default-error-message-template)\n    - [Overriding Default Error Message for Single Request](#overriding-default-error-message-for-single-request)\n    - [Catching Exceptions Manually](#catching-exceptions-manually)\n    - [Empty Try/Catch](#empty-trycatch)\n- [API](#api)\n  - [FarFetch](#farfetch)\n    - [new FarFetch([options])](#new-farfetchoptions)\n    - [farFetch.fetch(url, options) ⇒ \u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#farfetchfetchurl-options--promiseresponseplus)\n    - [farFetch.get(url, [...options]) ⇒ \u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#farfetchgeturl-options--promiseresponseplus)\n    - [farFetch.post(url, [...options]) ⇒ \u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#farfetchposturl-options--promiseresponseplus)\n    - [farFetch.put(url, [...options]) ⇒ \u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#farfetchputurl-options--promiseresponseplus)\n    - [farFetch.patch(url, [...options]) ⇒ \u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#farfetchpatchurl-options--promiseresponseplus)\n    - [farFetch.delete(url, [...options]) ⇒ \u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#farfetchdeleteurl-options--promiseresponseplus)\n    - [farFetch.head(url, [...options]) ⇒ \u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#farfetchheadurl-options--promiseresponseplus)\n  - [FarFetchError ⇐ \u003ccode\u003eError\u003c/code\u003e](#farfetcherror--error)\n    - [new FarFetchError(message)](#new-farfetcherrormessage)\n  - [RequestException : \u003ccode\u003eObject\u003c/code\u003e](#requestexception--object)\n  - [ResponsePlus : \u003ccode\u003eObject\u003c/code\u003e](#responseplus--object)\n  - [RequestOptionsNoInit : \u003ccode\u003eObject\u003c/code\u003e](#requestoptionsnoinit--object)\n  - [RequestOptions : \u003ccode\u003eObject\u003c/code\u003e](#requestoptions--object)\n  - [dynamicOptionsCallback ⇒ \u003ccode\u003eRequestInit\u003c/code\u003e](#dynamicoptionscallback--requestinit)\n  - [beforeSendCallback : \u003ccode\u003efunction\u003c/code\u003e](#beforesendcallback--function)\n\n## Passing in Data to Request\n\nPassing in data in `Fetch API` is exceedingly inconsistent. In this regard, it\nreally took a step backwards from how jQuery implemented passing in data, in my\nopinion, at least from a usability standpoint. Of course `Fetch API`'s `body`\noptions offers more versatility, which is why `FarFetch` supports using `body`.\nHowever, it really shouldn't be necessary in the majority of use cases. Adding\ndata to a `GET` and `POST` request is done in two separate ways in `Fetch API`.\n`GET` requests must use appended URL query parameters, while `POST` requests\ngenerally use a stringified object used as the `body` property.\n\n### GET Request\n\n**Fetch API**\n\n```js\nasync getPerson() {\n  const data = { name: 'Bobby Big Boy', gender: 'Male', age: 5 };\n\n  const queryString = `?${new URLSearchParams(data)}`;\n\n  const response = await fetch(`https://example.com/people${queryString}`, {\n    method: 'GET',\n  });\n\n  if(!response.ok) throw new Error('Server error.');\n\n  return response.json();\n}\n```\n\n**FarFetch**\n\n```js\nasync getPerson() {\n  const { responseJSON } = await ff.get('https://example.com/people', {\n    data: { name: 'Bobby Big Boy', gender: 'Male', age: 5 },\n  });\n\n  return responseJSON;\n}\n```\n\n### POST Request\n\n**Fetch API**\n\n```js\nasync addPerson() {\n  const data = { name: 'Bobby Big Boy', gender: 'Male', age: 5 };\n\n  const response = await fetch(`https://example.com/people`, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify(data),\n  });\n\n  if(!response.ok) throw new Error('Server error.');\n\n  return response.json();\n}\n```\n\n**FarFetch**\n\n```js\nasync addPerson() {\n  const { responseJSON } = await ff.post('https://example.com/people', {\n    data: { name: 'Bobby Big Boy', gender: 'Male', age: 5 },\n  });\n\n  return responseJSON;\n}\n```\n\n### application/x-www-form-urlencoded Request\n\n**Fetch API**\n\n```js\nasync addPerson() {\n  const data = { name: 'Bobby Big Boy', gender: 'Male', age: 5 };\n\n  const response = await fetch(`https://example.com/people`, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n    body: new URLSearchParams(data),\n  });\n\n  if(!response.ok) throw new Error('Server error.');\n\n  return response.json();\n}\n```\n\n**FarFetch**\n\n```js\nasync addPerson() {\n  const { responseJSON } = await ff.post('https://example.com/people', {\n    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n    data: { name: 'Bobby Big Boy', gender: 'Male', age: 5 },\n  });\n\n  return responseJSON;\n}\n```\n\n### Array or Object as Value for Key for GET Request\n\n**Fetch API**\n\n```js\nasync getPerson() {\n  const queryString = `?${new URLSearchParams({\n    name: 'Bobby Big Boy', \n    hobbies: JSON.stringify(['collecting stamps', 'sports']),\n    location: JSON.stringify({ city: 'Miami', state: 'Florida' }),\n  })}`;\n\n  const response = await fetch(`https://example.com/people${queryString}`, {\n    method: 'GET',\n  });\n\n  if(!response.ok) throw new Error('Server error.');\n\n  return response.json();\n}\n```\n\nThis can be a bit cumbersome to have to have to `JSON.stringify()` each value\nthat's an array or object. `FarFetch` automatically takes care of this.\n\n**FarFetch**\n\n```js\nasync getPerson() {\n  const { responseJSON } = await ff.get(`https://example.com/people`, {\n    data: {\n      name: 'Bobby Big Boy', \n      hobbies: ['collecting stamps', 'sports'],\n      location: { city: 'Miami', state: 'Florida' },\n    },\n  });\n\n  return responseJSON;\n}\n```\n\nNotice how each request is completely predictable in `FarFetch` and doesn't\nrequire you to throw an exception if it's not a status code in the `200-299`\nrange (`response.ok`). Sure, using the native javascript `Fetch API` isn't\nhorrible anymore in regular Javascript, thanks to features like\n`URLSearchParams`, but it's so much easier to not have to\nthink much when you program. `FarFetch`'s consistent API makes it a breeze to\nmake any sort of request.\n\n*Note: The content type header for a `POST`, `PUT` and `PATCH` request will\nalways be `application/json`, unless `application/x-www-form-urlencoded` is\nspecified or if it's a file upload*.\n\n### Passing in URLParams to Request\n\nThis is specifically for converting to a `URL query string`, which differs from\n`data`, which *detects* the default type (`body` or `query string`).\n\nIt's recommended to strictly use the `URLParams` option in cases where `POST`,\n`POST` and `PATCH` are used, as the default behavior for passing in `data` in\nthis case will result in passing in the object to `body`. You can still pass in\n`URLParams` on `GET`, `HEAD` and `DELETE`, but you can't combine it with `data`.\nThis is for consistency purposes, as it would be confusing as to why you'd be\nusing `data` and `URLParams` in the latter ones, as they would achieve the same\nresult in this case. In fact, `FarFetch` even throws an exception in this\nsenario.  \n\n```js\nasync addPerson() {\n  const { responseJSON } = await ff.post('https://example.com/people', {\n    URLParams: { weight: 75 },\n    data: { name: 'Bobby Big Boy', gender: 'Male', age: 5 },\n  });\n\n  return responseJSON;\n}\n```\n\nConverted to `Fetch API`, the following will result in:\n\n```js\nconst response = await fetch(`https://example.com/people?weight=75`, {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ name: 'Bobby Big Boy', gender: 'Male', age: 5 }),\n});\n```\n\n## Uploading Files\n\n### Uploading One File\n\n**Fetch API**\n\n```js\nasync uploadFile() {\n  const [file] = document.querySelector('#my-file').files;\n\n  const data = { name: 'Bobby Big Boy', gender: 'Male', age: 5 };\n\n  const formData = new FormData();\n\n  formData.append('file', file);\n\n  Object.keys(data).forEach((key) =\u003e {\n    formData.append(key, data[key]); // Add server data to formData\n  });\n\n  const response = await fetch('https://example.com/people', {\n    method: 'POST',\n    body: formData,\n  });\n\n  if(!response.ok) throw new Error('Server error.');\n}\n```\n\n**FarFetch**\n\n```js\nasync uploadFile() {\n  const [file] = document.querySelector('#my-file').files;\n\n  await ff.post('https://example.com/people', {\n    data: { name: 'Bobby Big Boy', gender: 'Male', age: 5 },\n    files: file,\n  });\n}\n```\n\n### Uploading Multiple Files\n\n**Fetch API**\n\n```js\nasync uploadFiles() {\n  const files = document.querySelector('#my-files').files;\n\n  const data = { name: 'Bobby Big Boy', gender: 'Male', age: 5 };\n\n  const formData = new FormData();\n\n  Object.keys(data).forEach((key) =\u003e {\n    formData.append(key, data[key]); // Add server data to formData\n  });\n\n  files.forEach((file) =\u003e {\n    formData.append('files[]', file); // Add files array to formData\n  });\n\n  await fetch('https://example.com/people', {\n    method: 'POST',\n    body: formData,\n  });\n\n  if(!response.ok) throw new Error('Server error.');\n}\n```\n\n**FarFetch**\n\n```js\nasync uploadFiles() {\n  const files = document.querySelector('#my-files').files;\n\n  await ff.post('https://example.com/people', {\n    data: { name: 'Bobby Big Boy', gender: 'Male', age: 5 },\n    files,\n  });\n}\n```\n\n### Uploading Multiple Files with Distinct File Names\n\n**Fetch API**\n\n```js\nasync uploadFiles() {\n  const photos = document.querySelector('#photos').files;\n  const videos = document.querySelector('#videos').files;\n  const documents = document.querySelector('#documents').files;\n\n  const data = { name: 'Bobby Big Boy', gender: 'Male', age: 5 };\n\n  const formData = new FormData();\n\n  Object.keys(data).forEach((key) =\u003e {\n    formData.append(key, data[key]); // Add server data to formData\n  });\n\n  photos.forEach((photo) =\u003e {\n    formData.append('photos[]', photo); // Add files array to formData\n  });\n\n  videos.forEach((video) =\u003e {\n    formData.append('videos[]', video); // Add files array to formData\n  });\n\n  documents.forEach((document) =\u003e {\n    formData.append('documents[]', document); // Add files array to formData\n  });\n\n  await fetch('https://example.com/people', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: formData,\n  });\n\n  if(!response.ok) throw new Error('Server error.');\n}\n```\n\n**FarFetch**\n\n```js\nasync uploadFiles() {\n  const photos = document.querySelector('#photos').files;\n  const videos = document.querySelector('#videos').files;\n  const documents = document.querySelector('#documents').files;\n\n  await ff.post('https://example.com/people', {\n    data: { name: 'Bobby Big Boy', gender: 'Male', age: 22 },\n    files: { photos, videos, documents },\n  });\n}\n```\n\nLook at how much more comprehensible the code becomes with `FarFetch`. This is\npractically even readable by a non-programmer, as this reads as: *Let's add a 22\nyear old man named Bobby and upload his following files: photos, videos and\ndocuments*.\n\n## Passing in Fetch API init options\n\n`FarFetch` accepts all [Fetch API init\noptions](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters).\nIt's even possible to pass in the native fetch `body`, though its use is\ndiscouraged in most cases, in favor of, `FarFetch`'s `data` parameter.\n\n### Set Options for Single Request\n\n```js\nawait ff.get('https://example.com', {\n  headers: { 'Content-Type': 'application/json' },\n  cache: 'reload',\n})\n```\n\n### Set Global Options for Every Request\n\nThis is really handy for when you know for a fact you will be using the same\noptions on either every request or nearly all. You can accomplish this by\ndeclaring these options when you instantiate `FarFetch`.\n\n```js\nconst ff = new FarFetch({\n  headers: { 'Content-Type': 'application/json' },\n  cache: 'reload',\n});\n```\n\n### Set Dynamic Options for Every Request\n\nSometimes you might not want to set a particular option when FarFetch is\ncreated. Let's say you're using a login system. You don't want to have the `JWT`\nbe evaluated when you instantiate the class, since it won't work properly if a\nuser accesses the page logged out. The header would never reevaluate. This is\nwhy `FarFetch` has allows you to return options you want to use on specific\nconditions on the global `dynamicOptions()` function. These options will then\nget deep merged, with the `dynamicOptions()` return taking precedence.\nObviously passing options into a specific request will take the highest\nprecedence of them all, however.\n\n```js\nconst ff = new FarFetch({\n  headers: { 'Content-Type': 'application/json' },\n  cache: 'reload',\n  dynamicOptions() {\n    // Use authorization header if token set in localStorage\n    if (localStorage.getItem('token')) {\n      return {\n        headers: {\n          Authorization: `Bearer ${localStorage.getItem('token')}`,\n        },\n      };\n    }\n  },\n});\n```\n\nSo if you're logged in, your request would have the following options.\n\n```js\n{\n  headers: {\n    'Content-Type': 'application/json',\n    Authorization: `Bearer ${localStorage.getItem('token')}`,\n  },\n  cache: reload,\n}\n```\n\nNotice how the `Content-Type` is set to `text/plain`, rather than\n`application/json`. As stated before, this is because the return on\n`beforeSend()` takes precedence on the deep merge.\n\n## Getting Response\n\n### Retrieving Response Data\n\n`FarFetch` returns a [Response\nobject](https://developer.mozilla.org/en-US/docs/Web/API/Response), so you can\nuse [the `Body`\nmethods](https:/developer.mozilla.org/en-US/docs/Web/API/Body#Methods):\n`arrayBuffer()`, `blob()`, `formData()`, `json()` and `text()`. This is exactly\nhow you'd be doing it in native `Fetch` as well.\n\n`FarFetch` supports the vanilla `Fetch` way of retrieving data, by awaiting for\nthe the `Response` `Body` and transforming it to your type.\n\n```js\nconst response = await ff.get('https://example.com/people');\n\nconst responseJSON = await response.json();\n\nreturn responseJSON;\n```\n\nYou can also use `FarFetch`'s handy `responseJSON` and `responseText`\nproperties for your convenience, instead of having to await for either `response.json()` or\n`response.text()`, if the response header type is either `application/json` or\n`text/plain`, respectively. These are properties that were simply added to the\n`Response` object. What's also nice about this is that it ensures that getting\nthe JSON won't result in an error, due to a mismatch in header, as `FarFetch`\nchecks for this already, internally.\n\n```js\nconst { responseJSON } = await ff.get('https://example.com/people');\n\nreturn responseJSON;\n```\n\n```js\nconst { responseText } = await ff.get('https://example.com/people');\n\nreturn responseText;\n```\n\n## Set Base URL\n\nMost applications will likely use the same domain for most or even all requests.\n`FarFetch` has a `baseURL` option you can use when you instantiate the class.\n\n```js\nconst ff = new FarFetch({\n  baseURL: 'https://example.com',\n});\n```\n\nNow request like the following will work.\n\n```js\nawait ff.get('/people');\n```\n\nBut what if you want to use a different base URL for just a few requests in your\napplication? `FarFetch` automatically detects if an absolute path is used, and\nwill override the `baseURL`.\n\n```js\nawait ff.get('https://notexample.com/posts');\n```\n\n## Before/After Send Hook\n\nYou can use the built-in `beforeSend()` hook to do something before every\nrequest and the `afterSend(response)` one to do something after every request.\n\n```js\nconst ff = new FarFetch({\n  beforeSend({\n    url,\n    fetchAPIOptions,\n    data,\n    URLParams,\n    files,\n    errorMsg,\n    errorMsgNoun,\n    globalBeforeSend,\n    globalAfterSend,\n    defaultOptionsUsed,\n  }) {\n    console.log('do this before every request');\n  },\n  afterSend(response) {\n    console.log('do this after every request');\n  },\n});\n```\n\n### Turn off Before/After Send Hook on Single Request\n\nYou might want to use the `beforeSend()` or `afterSend(response)` hook on nearly\nall requests, but turn it off certain ones.\n\n```js\nawait ff.get('http://example.com/', {\n  globalBeforeSend: false,\n  globalAfterSend: false,\n});\n```\n\n## Error Handling\n\nAnother annoyance of `Fetch API` is that it doesn't automatically throw an error\non a failed request, and forces you to throw your own.\n\n**Fetch API**\n\n```js\nconst data = { name: 'Bobby Big Boy', gender: 'Male', age: 5 };\n\ntry {\n  const response = await fetch('https://example.com/people', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify(data),\n  });\n\n  if(!response.ok) throw new Error('Server error.');\n} catch {\n  alert('Error adding person');\n}\n```\n\nThankfully you don't need to worry about this with `FarFetch`. With `FarFetch`,\nyou can just append the noun to `errorMsgNoun` and it'll append to a\ndefault template, dependent on the CRUD type.\n\n**FarFetch**\n\n```js\ntry {\n  await ff.post('https://example.com/person', {\n    data: { name: 'Bobby Big Boy', gender: 'Male', age: 5 },\n    errorMsgNoun: 'person'\n  });\n} catch {}\n```\n\nYour global handler would then handle it as such:\n\n```js\nconst ff = new FarFetch({\n  errorHandler({ error, userMessage, response }) {\n    if(response.status === 401) { // Unauthorized\n      router.push('/login'); // Go to login page if logged out\n    }\n\n    // Error message will be presented to the user in an alert\n    alert(userMessage);\n  },\n});\n```\n\nIf an error occurs, this will result in an alert with the following message:\n\n\u003e Error adding person.\n\nYou might be wondering how this works behind the scenes.\nHere's the basic template of what going into the `userMessage` parameter\nproperty.\n\n```js\nlet action = '';\n\nif (method === 'GET' || method === 'HEAD') {\n  action = 'fetching';\n} else if (method === 'POST') {\n  action = 'adding';\n} else if (method === 'PUT' || method === 'PATCH') {\n  action = 'updating';\n} else if (method === 'DELETE') {\n  action = 'deleting';\n}\n\nconst userMessage = `Error ${action} ${errorMsgNoun}`;\n```\n\n### Modifying the Default Error Message Template\n\nYou can even override this default template with the `errorMsgTemplate`\nproperty, which accepts function.\n\n```js\nconst ff = new FarFetch({\n  errorMsgTemplate: ({ method, errorMsgNoun }) =\u003e {\n    let action = '';\n\n    if (method === 'GET' || method === 'HEAD') {\n      action = 'retrieving';\n    } else if (method === 'POST') {\n      action = 'posting';\n    } else if (method === 'PUT' || method === 'PATCH') {\n      action = 'changing';\n    } else if (method === 'DELETE') {\n      action = 'removing';\n    }\n\n    return `Error ${action} ${errorMsgNoun}.`;\n  },\n});\n```\n\nIn case you couldn't tell by this contrived example, I merely used synonyms of\nthe default template. However, this allows flexibility to tailor to\ncustom requirements.\n\n### Overriding Default Error Message for Single Request\n\nSometimes you might just want to change the message for a unique request. You\ncan accomplish this via the `errorMsg` property.\n\n```js\nawait ff.get('https://example.com/users', {\n  errorMsg: 'Oh no! We are having trouble retrieving your friends!',\n});\n```\n\n### Catching Exceptions Manually\n\nUsing the global `errorHandler()`, along with `errorMsgNoun` or `errorMsg`\nshould work fine in most cases, but sometimes you might need to handle multiple\ncases. You can easily achieve this by simply omitting both `errorMsgNoun` and\n`errorMsg`. `FarFetch` will then know not to run the global error handler. You\ncan then can the errors in a `try/catch`. Take a register account example for\ninstance.\n\n```js\nasync register(type) {\n  try {\n    const response = await ff.post(`http://127.0.0.1:3333/${type}`, {\n      data: {\n        email: this.email,\n        password: this.password,\n      },\n    });\n\n    const responseData = await response.json();\n\n    localStorage.setItem('token', responseData.token);\n\n    this.$router.push('/');\n  } catch (e) {\n    if (e instanceof FarFetchError) {\n      let userMessage = '';\n\n      const { response, error } = e;\n\n      if (response.status === 409) { // Conflict\n        userMessage = 'Email is already in system';\n      } else if (response.status === 400) { // Validation failed\n        const { field, validationMsg } = response.responseJSON;\n\n        userMessage = `${field} is ${validationMsg}`;\n      }\n      \n      ff.errorHandler({ error, response, userMessage });\n    } else {\n      userMessage = e.message;\n\n      ff.errorHandler({ error, userMessage });\n    }\n  }\n}\n```\n\nEach case his handled individually. You can then add the string to the global\nerror handler you created on instantiation, with\n`ff.errorHandler({ error, response, userMessage })`.\n\n### Empty Try/Catch\n\nIt is **required** to use a `try/catch` on every request in `FarFetch`, in order\nto stop execution on an error. This isn't because there's anything\nunique about how this library does anything; the same recommendation would apply\nto any async request in JavaScript that relies on sequential steps occurring on\nsuccess. `FarFetch` specifically throws an error to stop the further execution\nof code. Perhaps an example would help illustrate my point better.\n\nConsider how a simple register account might work, like in the previous example.\nYou make a request and if there aren't any issues, like email already taken or\nvalidation issues, you set the `localStorage` to the `JWT` and then route to the\nlogged in page. The problem is that if you an exception isn't thrown, there's\nnothing to stop the script's execution, and it'll *always* set `localStorage`\nand try to route to the logged in route, even if the request failed.\n\n# API\n\n## Classes\n\n\u003cdl\u003e\n\u003cdt\u003e\u003ca href=\"#FarFetch\"\u003eFarFetch\u003c/a\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eCRUD class to simplify fetch API and uploading.\u003c/p\u003e\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#FarFetchError\"\u003eFarFetchError\u003c/a\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eFarFetch Error class.\u003c/p\u003e\u003c/dd\u003e\n\u003c/dl\u003e\n\n## Typedefs\n\n\u003cdl\u003e\n\u003cdt\u003e\u003ca href=\"#RequestException\"\u003eRequestException\u003c/a\u003e : \u003ccode\u003eObject\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eThe Request exception object.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#ResponsePlus\"\u003eResponsePlus\u003c/a\u003e : \u003ccode\u003eObject\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eRequest object plus responseJSON and responseText properties if correct header type.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#RequestOptionsNoInit\"\u003eRequestOptionsNoInit\u003c/a\u003e : \u003ccode\u003eObject\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eThe request object options without Fetch API options.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#RequestOptions\"\u003eRequestOptions\u003c/a\u003e : \u003ccode\u003eObject\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eThe request object options.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#dynamicOptionsCallback\"\u003edynamicOptionsCallback\u003c/a\u003e ⇒ \u003ccode\u003eRequestInit\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eCallback for global dynamic options. Allows a dynamic option to be set, like a token stored in\nlocalStorage.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#beforeSendCallback\"\u003ebeforeSendCallback\u003c/a\u003e : \u003ccode\u003efunction\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eCallback for global before send hook.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#afterSendCallback\"\u003eafterSendCallback\u003c/a\u003e : \u003ccode\u003efunction\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eCallback for global after send hook.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#errorHandlerCallback\"\u003eerrorHandlerCallback\u003c/a\u003e : \u003ccode\u003efunction\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eCallback for global error handler.\u003c/p\u003e\n\u003c/dd\u003e\n\u003cdt\u003e\u003ca href=\"#errorMsgTemplateCallback\"\u003eerrorMsgTemplateCallback\u003c/a\u003e ⇒ \u003ccode\u003estring\u003c/code\u003e\u003c/dt\u003e\n\u003cdd\u003e\u003cp\u003eCallback for overriding default error message template.\u003c/p\u003e\n\u003c/dd\u003e\n\u003c/dl\u003e\n\n\u003ca name=\"FarFetch\"\u003e\u003c/a\u003e\n\n## FarFetch\nCRUD class to simplify fetch API and uploading.\n\n**Kind**: global class  \n\n* [FarFetch](#FarFetch)\n    * [new FarFetch([options])](#new_FarFetch_new)\n    * [.fetch(url, options)](#FarFetch+fetch) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\n    * [.get(url, [...options])](#FarFetch+get) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\n    * [.post(url, [...options])](#FarFetch+post) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\n    * [.put(url, [...options])](#FarFetch+put) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\n    * [.patch(url, [...options])](#FarFetch+patch) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\n    * [.delete(url, [...options])](#FarFetch+delete) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\n    * [.head(url, [...options])](#FarFetch+head) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\n\n\u003ca name=\"new_FarFetch_new\"\u003e\u003c/a\u003e\n\n### new FarFetch([options])\nCreate FarFetch object.\n\n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [options] | \u003ccode\u003eObject\u003c/code\u003e | \u003ccode\u003e{}\u003c/code\u003e | Set options. |\n| [options.baseURL] | \u003ccode\u003estring\u003c/code\u003e | \u003ccode\u003e\u0026#x27;\u0026#x27;\u003c/code\u003e | Base URL for each request. |\n| [options.dynamicOptions] | [\u003ccode\u003edynamicOptionsCallback\u003c/code\u003e](#dynamicOptionsCallback) |  | Function that allows a dynamic option to be set, like a token stored in localStorage. |\n| [options.beforeSend] | [\u003ccode\u003ebeforeSendCallback\u003c/code\u003e](#beforeSendCallback) |  | Function to do something before each fetch request. Can return object with RequestOptions to add or override options. |\n| [options.afterSend] | [\u003ccode\u003eafterSendCallback\u003c/code\u003e](#afterSendCallback) |  | Function to do something after each fetch request. |\n| [options.errorHandler] | [\u003ccode\u003eerrorHandlerCallback\u003c/code\u003e](#errorHandlerCallback) |  | Global error handler. |\n| [options.errorMsgTemplate] | [\u003ccode\u003eerrorMsgTemplateCallback\u003c/code\u003e](#errorMsgTemplateCallback) |  | Function to modify the default error message template for `errorMsgNoun`. |\n| [...options.defaultOptions] | \u003ccode\u003eRequestInit\u003c/code\u003e | \u003ccode\u003e{}\u003c/code\u003e | [Init options](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) from Fetch API. |\n\n**Example**  \n```js\nconst ff = new FarFetch({\n  baseURL: 'https://my-url.com',\n  dynamicOptions() {\n    // Use authorization header if token set in localStorage\n    if (localStorage.getItem('token')) {\n      return {\n        headers: {\n          Authorization: `Bearer ${localStorage.getItem('token')}`,\n        },\n      }\n    }\n  },\n  beforeSend() {\n    console.log('Doing something before every request');\n  },\n  afterSend(response) {\n    console.log('Doing after before every request');\n  },\n  errorHandler({ error, userMessage, response }) {\n    if(response.status === 401) { // Unauthorized\n      router.push('/login');\n    }\n\n    alert(userMessage); // Error message from either errorMsg or errorMsgNoun will be used\n  },\n  headers: { 'Content-Type': 'application/json' },\n});\n```\n\u003ca name=\"FarFetch+fetch\"\u003e\u003c/a\u003e\n\n### farFetch.fetch(url, options) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\nRequest function called on every CRUD function.\n\n**Kind**: instance method of [\u003ccode\u003eFarFetch\u003c/code\u003e](#FarFetch)  \n**Throws**:\n\n- [\u003ccode\u003eRequestException\u003c/code\u003e](#RequestException) \n\n\n| Param | Type | Description |\n| --- | --- | --- |\n| url | \u003ccode\u003estring\u003c/code\u003e | The URL. |\n| options | \u003ccode\u003eObject\u003c/code\u003e |  |\n| options.method | \u003ccode\u003e\u0026#x27;GET\u0026#x27;\u003c/code\u003e \\| \u003ccode\u003e\u0026#x27;POST\u0026#x27;\u003c/code\u003e \\| \u003ccode\u003e\u0026#x27;PUT\u0026#x27;\u003c/code\u003e \\| \u003ccode\u003e\u0026#x27;PATCH\u0026#x27;\u003c/code\u003e \\| \u003ccode\u003e\u0026#x27;DELETE\u0026#x27;\u003c/code\u003e \\| \u003ccode\u003e\u0026#x27;HEAD\u0026#x27;\u003c/code\u003e | The CRUD method. |\n| [...options.RequestOptions] | [\u003ccode\u003eRequestOptions\u003c/code\u003e](#RequestOptions) |  |\n\n**Example**  \n```js\nawait ff.fetch('https://my-website.com/users', {\n method: 'GET',\n data: { id: 23 },\n errorMsgNoun: 'users',\n});\n```\n\u003ca name=\"FarFetch+get\"\u003e\u003c/a\u003e\n\n### farFetch.get(url, [...options]) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\nGET fetch request.\n\n**Kind**: instance method of [\u003ccode\u003eFarFetch\u003c/code\u003e](#FarFetch)  \n**Throws**:\n\n- [\u003ccode\u003eRequestException\u003c/code\u003e](#RequestException) \n\n\n| Param | Type | Description |\n| --- | --- | --- |\n| url | \u003ccode\u003estring\u003c/code\u003e | The URL. |\n| [...options] | [\u003ccode\u003eRequestOptions\u003c/code\u003e](#RequestOptions) |  |\n\n**Example**  \n```js\nawait ff.get('https://my-website.com/users', {\n data: { id: 23 },\n errorMsgNoun: 'users',\n});\n```\n\u003ca name=\"FarFetch+post\"\u003e\u003c/a\u003e\n\n### farFetch.post(url, [...options]) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\nPOST fetch request. Will default to `'Content-Type': 'application/json'` for the request header\nif `FarFetch` data option is provided.\n\n**Kind**: instance method of [\u003ccode\u003eFarFetch\u003c/code\u003e](#FarFetch)  \n**Throws**:\n\n- [\u003ccode\u003eRequestException\u003c/code\u003e](#RequestException) \n\n\n| Param | Type | Description |\n| --- | --- | --- |\n| url | \u003ccode\u003estring\u003c/code\u003e | The URL. |\n| [...options] | [\u003ccode\u003eRequestOptions\u003c/code\u003e](#RequestOptions) |  |\n\n**Example**  \n```js\nawait ff.post('https://my-website.com/user/23', {\n data: { gender: 'male', age: 39 },\n errorMsgNoun: 'user',\n});\n```\n\u003ca name=\"FarFetch+put\"\u003e\u003c/a\u003e\n\n### farFetch.put(url, [...options]) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\nPUT fetch request. Will default to `'Content-Type': 'application/json'` for the request header\nif `FarFetch` data option is provided.\n\n**Kind**: instance method of [\u003ccode\u003eFarFetch\u003c/code\u003e](#FarFetch)  \n**Throws**:\n\n- [\u003ccode\u003eRequestException\u003c/code\u003e](#RequestException) \n\n\n| Param | Type | Description |\n| --- | --- | --- |\n| url | \u003ccode\u003estring\u003c/code\u003e | The URL. |\n| [...options] | [\u003ccode\u003eRequestOptions\u003c/code\u003e](#RequestOptions) |  |\n\n**Example**  \n```js\nawait ff.put('https://my-website.com/user/47', {\n data: { gender: 'female', age: 22 },\n errorMsgNoun: 'user',\n});\n```\n\u003ca name=\"FarFetch+patch\"\u003e\u003c/a\u003e\n\n### farFetch.patch(url, [...options]) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\nPATCH fetch request. Will default to `'Content-Type': 'application/json'` for the request\nheader if `FarFetch` data option is provided.\n\n**Kind**: instance method of [\u003ccode\u003eFarFetch\u003c/code\u003e](#FarFetch)  \n**Throws**:\n\n- [\u003ccode\u003eRequestException\u003c/code\u003e](#RequestException) \n\n\n| Param | Type | Description |\n| --- | --- | --- |\n| url | \u003ccode\u003estring\u003c/code\u003e | The URL. |\n| [...options] | [\u003ccode\u003eRequestOptions\u003c/code\u003e](#RequestOptions) |  |\n\n**Example**  \n```js\nawait ff.patch('https://my-website.com/user/91', {\n data: { age: 18 },\n errorMsgNoun: 'user',\n});\n```\n\u003ca name=\"FarFetch+delete\"\u003e\u003c/a\u003e\n\n### farFetch.delete(url, [...options]) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\nDELETE fetch request.\n\n**Kind**: instance method of [\u003ccode\u003eFarFetch\u003c/code\u003e](#FarFetch)  \n**Throws**:\n\n- [\u003ccode\u003eRequestException\u003c/code\u003e](#RequestException) \n\n\n| Param | Type | Description |\n| --- | --- | --- |\n| url | \u003ccode\u003estring\u003c/code\u003e | The URL. |\n| [...options] | [\u003ccode\u003eRequestOptions\u003c/code\u003e](#RequestOptions) |  |\n\n**Example**  \n```js\nawait ff.delete('https://my-website.com/user/107', {\n errorMsgNoun: 'user',\n});\n```\n\u003ca name=\"FarFetch+head\"\u003e\u003c/a\u003e\n\n### farFetch.head(url, [...options]) ⇒ [\u003ccode\u003ePromise.\u0026lt;ResponsePlus\u0026gt;\u003c/code\u003e](#ResponsePlus)\nHEAD fetch request.\n\n**Kind**: instance method of [\u003ccode\u003eFarFetch\u003c/code\u003e](#FarFetch)  \n**Throws**:\n\n- [\u003ccode\u003eRequestException\u003c/code\u003e](#RequestException) \n\n\n| Param | Type | Description |\n| --- | --- | --- |\n| url | \u003ccode\u003estring\u003c/code\u003e | The URL. |\n| [...options] | [\u003ccode\u003eRequestOptions\u003c/code\u003e](#RequestOptions) |  |\n\n**Example**  \n```js\nawait ff.head('https://my-website.com/user/107');\n```\n\n\u003ca name=\"FarFetchError\"\u003e\u003c/a\u003e\n\n## FarFetchError ⇐ \u003ccode\u003eError\u003c/code\u003e\nFarFetch Error class.\n\n**Kind**: global class  \n**Extends**: \u003ccode\u003eError\u003c/code\u003e  \n\u003ca name=\"new_FarFetchError_new\"\u003e\u003c/a\u003e\n\n### new FarFetchError(message)\n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | \u003ccode\u003estring\u003c/code\u003e \\| \u003ccode\u003eobject.\u0026lt;string, \\*\u0026gt;\u003c/code\u003e | Will be in the `message` property if a string or its own properties if object. |\n\n\u003ca name=\"RequestException\"\u003e\u003c/a\u003e\n\n## RequestException : \u003ccode\u003eObject\u003c/code\u003e\nThe Request exception object.\n\n**Kind**: global typedef  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| error | \u003ccode\u003eFarFetchError\u003c/code\u003e | FarFetch error. |\n| response | [\u003ccode\u003eResponsePlus\u003c/code\u003e](#ResponsePlus) | Fetch API response plus added properties for syntactic sugar. |\n\n\u003ca name=\"ResponsePlus\"\u003e\u003c/a\u003e\n\n## ResponsePlus : \u003ccode\u003eObject\u003c/code\u003e\nRequest object plus responseJSON and responseText properties if correct header type.\n\n**Kind**: global typedef  \n**Properties**\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| response | \u003ccode\u003eResponse\u003c/code\u003e |  | Fetch API response. [Response object](https://developer.mozilla.org/en-US/docs/Web/API/Response). |\n| [response.responseJSON] | \u003ccode\u003eObject\u003c/code\u003e | \u003ccode\u003e\u003c/code\u003e | FarFetch added property that transforms the body to JSON for syntactic sugar if the same response header type. |\n| [response.responseText] | \u003ccode\u003estring\u003c/code\u003e | \u003ccode\u003enull\u003c/code\u003e | FarFetch added property that transforms the body to text for syntactic sugar if the same response header type. |\n\n\u003ca name=\"RequestOptionsNoInit\"\u003e\u003c/a\u003e\n\n## RequestOptionsNoInit : \u003ccode\u003eObject\u003c/code\u003e\nThe request object options without Fetch API options.\n\n**Kind**: global typedef  \n**Properties**\n\n| Name | Type | Default | Description |\n| --- | --- | --- | --- |\n| [data] | \u003ccode\u003eObject.\u0026lt;string, (string\\|number\\|null\\|boolean\\|Array\\|Object)\u0026gt;\u003c/code\u003e | \u003ccode\u003e{}\u003c/code\u003e | Data sent to server on request. Will use `body` for: POST, PUT, PATCH and `URL query params string` for: GET, HEAD, DELETE. |\n| [URLParams] | \u003ccode\u003eObject.\u0026lt;string, (string\\|number\\|null\\|boolean\\|Array\\|Object)\u0026gt;\u003c/code\u003e | \u003ccode\u003e{}\u003c/code\u003e | URL query params string. Don't use both `data` and `URLParams` together with GET, HEAD or DELETE, as they're redundant in these cases. Pick one or the other, as they will both have the same effect. |\n| [files] | \u003ccode\u003eFile\u003c/code\u003e \\| \u003ccode\u003eArray.\u0026lt;File\u0026gt;\u003c/code\u003e \\| \u003ccode\u003eObject.\u0026lt;string, File\u0026gt;\u003c/code\u003e \\| \u003ccode\u003eObject.\u0026lt;string, Array.\u0026lt;File\u0026gt;\u0026gt;\u003c/code\u003e |  | Files to upload to server. Will use `file` as key if literal and `files[]` if array; if object, will use properties as keys. |\n| [errorMsgNoun] | \u003ccode\u003estring\u003c/code\u003e | \u003ccode\u003e\u0026#x27;\u0026#x27;\u003c/code\u003e | Appended error message noun to global error handler. |\n| [errorMsg] | \u003ccode\u003estring\u003c/code\u003e | \u003ccode\u003e\u0026#x27;\u0026#x27;\u003c/code\u003e | Error message used to global error handler. Overrides `errorMsgNoun`. |\n| [globalBeforeSend] | \u003ccode\u003eboolean\u003c/code\u003e | \u003ccode\u003etrue\u003c/code\u003e | Will this specific request use the beforeSend() hook? |\n| [globalAfterSend] | \u003ccode\u003eboolean\u003c/code\u003e | \u003ccode\u003etrue\u003c/code\u003e | Will this specific request use the afterSend() hook? |\n| [defaultOptionsUsed] | \u003ccode\u003eboolean\u003c/code\u003e | \u003ccode\u003etrue\u003c/code\u003e | Will this specific request use the default options specified on instantiation and the return value of `dynamicOptions()`? |\n\n\u003ca name=\"RequestOptions\"\u003e\u003c/a\u003e\n\n## RequestOptions : \u003ccode\u003eObject\u003c/code\u003e\nThe request object options.\n\n**Kind**: global typedef  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| [...requestOptionsNoInit] | [\u003ccode\u003eRequestOptionsNoInit\u003c/code\u003e](#RequestOptionsNoInit) |  |\n| [...rest] | \u003ccode\u003eRequestInit\u003c/code\u003e | [Init options](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) from Fetch API. |\n\n\u003ca name=\"dynamicOptionsCallback\"\u003e\u003c/a\u003e\n\n## dynamicOptionsCallback ⇒ \u003ccode\u003eRequestInit\u003c/code\u003e\nCallback for global dynamic options. Allows a dynamic option to be set, like a token stored in\nlocalStorage.\n\n**Kind**: global typedef  \n**Returns**: \u003ccode\u003eRequestInit\u003c/code\u003e - [Init options](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters)\nfrom Fetch API.  \n\u003ca name=\"beforeSendCallback\"\u003e\u003c/a\u003e\n\n## beforeSendCallback : \u003ccode\u003efunction\u003c/code\u003e\nCallback for global before send hook.\n\n**Kind**: global typedef  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [options] | \u003ccode\u003eObject\u003c/code\u003e |  |\n| [options.url] | \u003ccode\u003estring\u003c/code\u003e | The URL. |\n| [options.fetchAPIOptions] | \u003ccode\u003eRequestInit\u003c/code\u003e | [Init options](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) from Fetch API. |\n| [...options.requestOptions] | [\u003ccode\u003eRequestOptionsNoInit\u003c/code\u003e](#RequestOptionsNoInit) | The request object options without Fetch API options. |\n\n\u003ca name=\"afterSendCallback\"\u003e\u003c/a\u003e\n\n## afterSendCallback : \u003ccode\u003efunction\u003c/code\u003e\nCallback for global after send hook.\n\n**Kind**: global typedef  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| response | [\u003ccode\u003eResponsePlus\u003c/code\u003e](#ResponsePlus) | Request object plus responseJSON and responseText properties if correct header type. |\n\n\u003ca name=\"errorHandlerCallback\"\u003e\u003c/a\u003e\n\n## errorHandlerCallback : \u003ccode\u003efunction\u003c/code\u003e\nCallback for global error handler.\n\n**Kind**: global typedef  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [options] | \u003ccode\u003eObject\u003c/code\u003e |  |\n| [options.error] | \u003ccode\u003eFarFetchError\u003c/code\u003e \\| \u003ccode\u003eError\u003c/code\u003e | The FarFetchError option. Will throw regular error if needed. |\n| [options.response] | [\u003ccode\u003eResponsePlus\u003c/code\u003e](#ResponsePlus) | Request object plus responseJSON and responseText properties if correct header type. |\n| [options.userMessage] | \u003ccode\u003estring\u003c/code\u003e | The message given to the user. |\n\n\u003ca name=\"errorMsgTemplateCallback\"\u003e\u003c/a\u003e\n\n## errorMsgTemplateCallback ⇒ \u003ccode\u003estring\u003c/code\u003e\nCallback for overriding default error message template.\n\n**Kind**: global typedef  \n**Returns**: \u003ccode\u003estring\u003c/code\u003e - Full error message string.  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [options] | \u003ccode\u003eObject\u003c/code\u003e |  |\n| [options.method] | \u003ccode\u003e\u0026#x27;GET\u0026#x27;\u003c/code\u003e \\| \u003ccode\u003e\u0026#x27;POST\u0026#x27;\u003c/code\u003e \\| \u003ccode\u003e\u0026#x27;PUT\u0026#x27;\u003c/code\u003e \\| \u003ccode\u003e\u0026#x27;PATCH\u0026#x27;\u003c/code\u003e \\| \u003ccode\u003e\u0026#x27;DELETE\u0026#x27;\u003c/code\u003e \\| \u003ccode\u003e\u0026#x27;HEAD\u0026#x27;\u003c/code\u003e | The CRUD method. |\n| [options.errorMsgNoun] | \u003ccode\u003estring\u003c/code\u003e | The error message noun. |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FD-Marc1%2Ffar-fetch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FD-Marc1%2Ffar-fetch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FD-Marc1%2Ffar-fetch/lists"}