{"id":16995038,"url":"https://github.com/jalik/js-fetch-client","last_synced_at":"2026-04-21T19:34:32.149Z","repository":{"id":161291099,"uuid":"636026876","full_name":"jalik/js-fetch-client","owner":"jalik","description":"Instanciable and customizable fetch client for Browser and NodeJS","archived":false,"fork":false,"pushed_at":"2026-02-02T23:31:19.000Z","size":2131,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-03T12:36:06.187Z","etag":null,"topics":["fetch","http"],"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/jalik.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-05-04T01:19:38.000Z","updated_at":"2026-02-02T23:31:22.000Z","dependencies_parsed_at":"2024-02-26T20:51:21.098Z","dependency_job_id":"56d97ce6-1a7c-448f-b641-f3d10618ddc3","html_url":"https://github.com/jalik/js-fetch-client","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/jalik/js-fetch-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jalik%2Fjs-fetch-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jalik%2Fjs-fetch-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jalik%2Fjs-fetch-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jalik%2Fjs-fetch-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jalik","download_url":"https://codeload.github.com/jalik/js-fetch-client/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jalik%2Fjs-fetch-client/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32106732,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-21T11:25:29.218Z","status":"ssl_error","status_checked_at":"2026-04-21T11:25:28.499Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["fetch","http"],"created_at":"2024-10-14T03:47:24.307Z","updated_at":"2026-04-21T19:34:32.128Z","avatar_url":"https://github.com/jalik.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @jalik/fetch-client\n\n![GitHub package.json version](https://img.shields.io/github/package-json/v/jalik/js-fetch-client.svg)\n![Build Status](https://github.com/jalik/js-fetch-client/actions/workflows/node.js.yml/badge.svg)\n![Last commit](https://img.shields.io/github/last-commit/jalik/js-fetch-client.svg)\n[![GitHub issues](https://img.shields.io/github/issues/jalik/js-fetch-client.svg)](https://github.com/jalik/js-fetch-client/issues)\n![GitHub](https://img.shields.io/github/license/jalik/js-fetch-client.svg)\n![npm](https://img.shields.io/npm/dt/@jalik/fetch-client.svg)\n\nHTTP client based on Fetch API with error handling and other DX improvements.\n\n## Features\n\n* Based on Fetch API (RequestInit + Response), with extra options\n* Works in the browser (use fetch polyfill for old browsers)\n* Works in NodeJS (since version 18)\n* Shortcut methods (DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT)\n* Global configuration for all requests (headers, options and base URL)\n* Conversion of response body using a type (json, blob, text, arrayBuffer...)\n* Transform request options and headers before sending\n* Transform response body before return\n* Transform response error before return\n* TypeScript declarations ♥\n\n## Sandbox\n\nPlay with the lib here:\nhttps://codesandbox.io/s/jalik-fetch-client-demo-8rolt2?file=/src/index.js\n\n## Installing\n\n```shell\nnpm i -P @jalik/fetch-client\n```\n```shell\nyarn add @jalik/fetch-client\n```\n\n## Creating a client\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient()\n```\n\n## Executing a request\n\nThe method `.fetch(url, options)` is a generic method to execute a request.  \nIt's like calling `fetch()` directly, but with all the benefits of using `FetchClient` (error handling, body transformations...).  \nUsually, you would prefer to use a shortcut method (described after) like `.get()` or `.post()` instead of `.fetch()`.\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient()\n\nclient.fetch('https://jsonplaceholder.typicode.com/todos/1', {\n  method: 'GET',\n  responseType: 'json'\n})\n  .then((resp) =\u003e {\n    console.log(resp.body)\n  })\n```\n\n### Request options\n\nThe request options are the same as Fetch options with extra options.\n\n```ts\ntype FetchOptions = RequestInit \u0026 {\n  /**\n   * The type of response to expect.\n   * Pass undefined to ignore response body.\n   */\n  responseType?: ResponseType\n}\n```\n\n### Response object\n\nThe response object returned by all request methods follows the declaration below.\n\n```ts\ntype FetchClientResponse\u003cT = any\u003e = {\n  /**\n   * Response body.\n   */\n  body: T\n  /**\n   * Response headers.\n   */\n  headers: Record\u003cstring, string\u003e\n  /**\n   * The original Fetch Response.\n   */\n  original: Response\n  /**\n   * Tells if the request has been redirected.\n   */\n  redirected: boolean\n  /**\n   * Response status code (ex: 200).\n   */\n  status: number\n  /**\n   * Response status text (ex: \"OK\").\n   */\n  statusText: string\n  /**\n   * Contains the response type.\n   */\n  type: ResponseType\n}\n```\n\n### Executing a DELETE request\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient()\n\nclient.delete('https://jsonplaceholder.typicode.com/posts/1')\n```\n\n### Executing a GET request\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient()\n\nclient.get('https://jsonplaceholder.typicode.com/todos/1', {\n  // Convert response body to JSON.\n  // It can be done per request, or for all requests when passed to FetchClient options.\n  responseType: 'json'\n})\n  .then((resp) =\u003e {\n    console.log(resp.body)\n  })\n```\n\n### Executing a HEAD request\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient()\n\nclient.head('https://jsonplaceholder.typicode.com/todos/1')\n  .then((resp) =\u003e {\n    // Access response headers\n    console.log(resp.headers)\n  })\n```\n\n### Executing an OPTIONS request\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient()\n\nclient.options('https://jsonplaceholder.typicode.com/todos')\n  .then((resp) =\u003e {\n    // Access response headers\n    console.log(resp.headers)\n  })\n```\n\n### Executing a PATCH request\n\nWhen `body` is an object and `Content-Type` is not defined in headers:\n\n* `body` is serialized to JSON\n* `Content-Type: application/json` is added to headers\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient()\n\nclient.patch(\n  'https://jsonplaceholder.typicode.com/todos/1',\n  { completed: true },\n  { responseType: 'json' }\n)\n  .then((resp) =\u003e {\n    console.log(resp.body)\n  })\n```\n\n### Executing a POST request\n\nWhen `body` is an object and `Content-Type` is not defined in headers:\n\n* `body` is serialized to JSON\n* `Content-Type: application/json` is added to headers\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient()\n\nclient.post(\n  'https://jsonplaceholder.typicode.com/todos',\n  { title: 'test' },\n  { responseType: 'json' }\n)\n  .then((resp) =\u003e {\n    console.log(resp.body)\n  })\n```\n\n### Executing a PUT request\n\nWhen `body` is an object and `Content-Type` is not defined in headers:\n\n* `body` is serialized to JSON\n* `Content-Type: application/json` is added to headers\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient()\n\nclient.put(\n  'https://jsonplaceholder.typicode.com/todos/1',\n  { title: 'test' },\n  { responseType: 'json' }\n)\n  .then((resp) =\u003e {\n    console.log(resp.body)\n  })\n```\n\n## Handling errors\n\nWhen the server returns an error code (4xx, 5xx...), the client throws an error.  \nIf the server returned a body (containing error details), it can be found in `error.response.body`.  \nHowever be aware that the body is only available when `responseType` is defined in `FetchClient` options or in request options.\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient()\n\nconst invalidObject = {}\n\nclient.post('https://jsonplaceholder.typicode.com/todos', invalidObject, {\n  // Setting the responseType is important to convert error response body.\n  responseType: 'json',\n})\n  .catch((error: FetchResponseError) =\u003e {\n    console.error(\n      // the status error\n      error.message,\n      // the server response\n      error.response.body\n    )\n  })\n```\n\nBy default, the error contains a basic message (status text like \"Bad Request\").\nYou can use the error returned by the server like below (this will be applied to all client responses).\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient({\n  transformError: (error: FetchResponseError, response: FetchClientResponse) =\u003e {\n    // Return custom server error.\n    if (error.response.body?.message) {\n      return new FetchResponseError(error.response.body.message, response)\n    }\n    return error\n  },\n})\n\nclient.post('https://jsonplaceholder.typicode.com/todos', invalidObject, {\n  // Setting the responseType is important to convert error response body.\n  responseType: 'json',\n})\n  .catch((error: FetchResponseError) =\u003e {\n    // the error message has the same value as \"error.response.body.error\"\n    console.error(error.message)\n  })\n```\n\n## Configuring the client\n\n```js\nimport { FetchClient } from '@jalik/fetch-client'\n\nconst client = new FetchClient({\n  // Do something async after each successful request (200 \u003e= code \u003c 400).\n  afterEach: async (url, resp) =\u003e {\n    return resp\n  },\n  // Prefix all relative URL with the base URL (does nothing on absolute URL).\n  baseUrl: 'http://localhost',\n  // Do something async before each request.\n  beforeEach: async (url, options) =\u003e {\n    return options\n  },\n  // Set default headers for all requests (empty by default).\n  headers: {\n    'authorization': '...',\n    'x-xsrf-token': '...',\n  },\n  // Set default Fetch options for all requests.\n  options: {\n    mode: 'cors',\n  },\n  // Enable conversion of body response.\n  // Use one of \"arrayBuffer\", \"blob\", \"formData\", \"json\", \"stream\", \"text\", or\n  // undefined to ignore response body.\n  responseType: 'json',\n  // Transform response error before returning.\n  transformError: (error: FetchResponseError, response: FetchClientResponse) =\u003e {\n    // Return custom server error.\n    if (error.response.body?.message) {\n      return new FetchResponseError(error.response.body.message, response)\n    }\n    return error\n  },\n  // Transform request options and headers before sending.\n  // Several functions can be passed (all executed sequentially).\n  transformRequest: [\n    (url, options) =\u003e ({\n      ...options,\n      headers: {\n        ...options.headers,\n        // Add request date to each request\n        'x-request-date': Date.now().toString(),\n      },\n    }),\n  ],\n  // Transform response Body before returning.\n  // Several functions can be passed (all executed sequentially).\n  transformResponse: [\n    (body, response) =\u003e ({\n      ...body,\n      // Add response date to each response\n      receivedAt: Date.now(),\n    }),\n  ],\n})\n```\n\n## Changelog\n\nHistory of releases is in the [changelog](./CHANGELOG.md) on GitHub.\n\n## License\n\nThe code is released under the [MIT License](http://www.opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjalik%2Fjs-fetch-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjalik%2Fjs-fetch-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjalik%2Fjs-fetch-client/lists"}