{"id":17374255,"url":"https://github.com/krutoo/fetch-tools","last_synced_at":"2025-04-15T06:28:48.285Z","repository":{"id":147211326,"uuid":"615284809","full_name":"krutoo/fetch-tools","owner":"krutoo","description":"Set of utilities for JS Fetch API","archived":false,"fork":false,"pushed_at":"2024-12-11T13:30:12.000Z","size":160,"stargazers_count":8,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-10T14:55:54.736Z","etag":null,"topics":["axios","bun","deno","fetch","fetch-tool","http","javascript","middleware","nodejs","typescript"],"latest_commit_sha":null,"homepage":"https://jsr.io/@krutoo/fetch-tools","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/krutoo.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}},"created_at":"2023-03-17T10:59:24.000Z","updated_at":"2025-02-24T06:39:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"9b46311a-5b64-4d83-8161-b5b79b8dfae1","html_url":"https://github.com/krutoo/fetch-tools","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krutoo%2Ffetch-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krutoo%2Ffetch-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krutoo%2Ffetch-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krutoo%2Ffetch-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krutoo","download_url":"https://codeload.github.com/krutoo/fetch-tools/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249020074,"owners_count":21199482,"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":["axios","bun","deno","fetch","fetch-tool","http","javascript","middleware","nodejs","typescript"],"created_at":"2024-10-16T03:04:42.480Z","updated_at":"2025-04-15T06:28:48.266Z","avatar_url":"https://github.com/krutoo.png","language":"TypeScript","readme":"# Fetch tools\n\nSet of utilities for JavaScript\n[Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch).\n\n## Goals\n\n- do not change `fetch` behavior, just add some features\n- ability to run in browser, Node.js, Deno, Bun, WinterJS (...any runtime that implements Fetch API)\n- zero dependencies\n\n## Installation\n\n```bash\n# in Node.js via NPM\nnpm add @krutoo/fetch-tools\n\n# in Deno via JSR\ndeno add @krutoo/fetch-tools\n\n# in Bun\nbun add @krutoo/fetch-tools\n```\n\n## Usage\n\nCreating fetch with some extra features.\n\n```ts\nimport { applyMiddleware, configureFetch } from '@krutoo/fetch-tools';\nimport { defaultHeaders, log, validateStatus } from '@krutoo/fetch-tools/middleware';\n\n// configure your own fetch...\nconst myFetch = configureFetch(\n  fetch,\n  applyMiddleware(\n    // validate status (like in axios)\n    validateStatus((status) =\u003e status \u003e= 200 \u0026\u0026 status \u003c 300),\n    // add default headers\n    defaultHeaders({\n      'user-agent': 'test',\n    }),\n    // log request stages (before request, after response, on catch)\n    log({\n      onCatch: ({ error }) =\u003e console.error(error),\n    }),\n  ),\n);\n\n// ...and using it like normal fetch\nmyFetch('posts/1')\n  .then((res) =\u003e res.json())\n  .then((data) =\u003e console.log(data));\n```\n\n## Middleware\n\nMiddleware are just functions and you can write your own.\n\n```ts\nasync function myMiddleware(request, next) {\n  try {\n    // [do something before request here]\n\n    const response = await next(request);\n\n    // [do something after response here]\n\n    return response;\n  } catch (error) {\n    // [do something on error here but don't forget throw error or return response]\n\n    throw error;\n  }\n}\n```\n\n## Builtin middleware\n\n### `validateStatus`\n\nReturns a middleware that will validate status.\n\n```ts\nimport { applyMiddleware, configureFetch } from '@krutoo/fetch-tools';\nimport { validateStatus } from '@krutoo/fetch-tools/middleware';\n\nconst myFetch = configureFetch(\n  fetch,\n  applyMiddleware(\n    // fetch promise will be rejected when status is not valid\n    validateStatus((status) =\u003e status \u003e= 200 \u0026\u0026 status \u003c 300),\n  ),\n);\n```\n\n### `defaultHeaders`\n\nReturns a middleware that will set default headers to request.\n\n```ts\nimport { applyMiddleware, configureFetch } from '@krutoo/fetch-tools';\nimport { defaultHeaders } from '@krutoo/fetch-tools/middleware';\n\nconst myFetch = configureFetch(\n  fetch,\n  applyMiddleware(\n    // all requests will contain declared headers\n    defaultHeaders({ 'user-agent': 'spy' }),\n  ),\n);\n```\n\n### `log`\n\nReturns a middleware that will log phases by handler.\n\n```ts\nimport { applyMiddleware, configureFetch } from '@krutoo/fetch-tools';\nimport { log } from '@krutoo/fetch-tools/middleware';\n\nconst myFetch = configureFetch(\n  fetch,\n  applyMiddleware(\n    // each phase of request will be logged\n    log({\n      onRequest({ request }) {\n        console.log(request);\n      },\n\n      onResponse({ request, response }) {\n        console.log(response);\n      },\n\n      onCatch({ request, error }) {\n        console.error(error);\n      },\n    }),\n  ),\n);\n```\n\n### `jwt`\n\nReturns simplest JWT middleware. This middleware will add `Authorization` header to each request\nthat matches the condition.\n\n```ts\nimport { applyMiddleware, configureFetch } from '@krutoo/fetch-tools';\nimport { jwt } from '@krutoo/fetch-tools/middleware';\n\nconst myFetch = configureFetch(\n  fetch,\n  applyMiddleware(\n    jwt({\n      // Access token\n      token: '...',\n\n      // Determines whether to add a header\n      filter: (req) =\u003e req.url.includes('/api/'),\n    }),\n    // ...or like this\n    jwt({\n      // \"token\" can be function that should return string or null or Promise\u003cstring | null\u003e\n      token: () =\u003e getJwtFromSomewhere(),\n    }),\n  ),\n);\n```\n\n### `retry`\n\nReturns a middleware that will retry the request until either:\n\n- or the retries count is exceeded;\n- or until a successful response is received.\n\n```ts\nimport { applyMiddleware, configureFetch } from '@krutoo/fetch-tools';\nimport { retry } from '@krutoo/fetch-tools/middleware';\n\nconst myFetch = configureFetch(\n  fetch,\n  applyMiddleware(\n    retry({\n      count: 5,\n      whenNotOk: true,\n      whenCatch: false,\n    }),\n  ),\n);\n```\n\n### `proxy`\n\nReturns simple proxy middleware. Useful for servers based on Fetch API.\n\n```ts\nimport { applyMiddleware } from '@krutoo/fetch-tools';\nimport { proxy } from '@krutoo/fetch-tools/middleware';\n\nconst enhance = applyMiddleware(\n  proxy({\n    // pathname(s) of incoming request URL which will be proxied\n    filter: ['/api/v2/', '/api/v3/'],\n\n    // define target URL\n    target: 'https://www.my-site.com/',\n  }),\n);\n\nDeno.serve(\n  enhance((req) =\u003e {\n    return new Response('\u003ch1\u003eMain page\u003c/h1\u003e');\n  }),\n);\n```\n\n## Server utilities\n\nYou can use utils for simply configure your HTTP server.\n\n### In Deno\n\n```ts\nimport { router } from '@krutoo/fetch-tools/server';\n\nconst handler = router\n  .builder()\n  .get('/', () =\u003e new Response('Home page'))\n  .put('/about', () =\u003e new Response('About page'))\n  .post('/news', () =\u003e new Response('News page'))\n  .all('/stats', () =\u003e new Response('Some stats'))\n  .build();\n\nawait Deno.serve({\n  port: 8080,\n  handler: handler,\n});\n```\n\n### In Bun\n\n```ts\nimport { router } from '@krutoo/fetch-tools/server';\n\nconst handler = router\n  .builder()\n  .get('/', () =\u003e new Response('Home page'))\n  .put('/about', () =\u003e new Response('About page'))\n  .post('/news', () =\u003e new Response('News page'))\n  .all('/stats', () =\u003e new Response('Some stats'))\n  .build();\n\nBun.serve({\n  port: 8080,\n  fetch: handler,\n});\n```\n\n### In Node.js (`node:http` or `express`)\n\nCurrently there is no builtin server implementation based on Fetch API in Node.js.\n\nIt is possible to use _adapter_ for `node:http` or `express` from\n[@whatwg-node/server](https://www.npmjs.com/package/@whatwg-node/server).\n\n```ts\nimport { router } from '@krutoo/fetch-tools';\nimport { createServer } from 'node:http';\nimport { createServerAdapter } from '@whatwg-node/server';\n\nconst handler = router\n  .builder()\n  .get('/', () =\u003e new Response('Home page'))\n  .put('/about', () =\u003e new Response('About page'))\n  .post('/news', () =\u003e new Response('News page'))\n  .all('/stats', () =\u003e new Response('Some stats'))\n  .build();\n\nconst server = createServer(createServerAdapter(handler));\n\nserver.listen(8080);\n```\n\n### Middleware for servers\n\nYou can use middleware for server handlers too:\n\n```ts\nimport { applyMiddleware } from '@krutoo/fetch-tools';\nimport { router } from '@krutoo/fetch-tools/server';\nimport { log } from '@krutoo/fetch-tools/middleware';\n\nconst enhance = applyMiddleware(\n  log({\n    onCatch: ({ error }) =\u003e console.error(error),\n  }),\n);\n\nconst handler = router\n  .builder()\n  .get('/', () =\u003e new Response('Home page'))\n  .put('/about', () =\u003e new Response('About page'))\n  .post('/news', () =\u003e new Response('News page'))\n  .all('/stats', () =\u003e new Response('Some stats'))\n  .build();\n\nBun.serve({\n  port: 8080,\n  fetch: enhance(handler), // just wrap handler to enhancer for apply middleware\n});\n```\n\n### Working with HTTP cookie on server\n\nCookies can be used in different ways on the server.\n\n### Browser like behavior\n\nIf you want to imitate browser behavior as much as possible in terms of working with cookies, you\ncan use `@krutoo/fetch-tools` together with `fetch-cookie`.\n\nTo use **fetch-cookie** as an middleware, follow\n[these](https://github.com/valeriangalliat/fetch-cookie/issues/79#issuecomment-1672188226)\ninstructions.\n\n### Microfrontends\n\nServer part of the microfrontend can make requests to some HTTP API on behalf of the user, sending\nhis cookies in requests.\n\nIn this case you can use just `defaultHeaders` middleware:\n\n```ts\nimport { applyMiddleware, configureFetch } from '@krutoo/fetch-tools';\nimport { defaultHeaders } from '@krutoo/fetch-tools/middleware';\n\n// example of server handler\nasync function handler(request: Request) {\n  const myFetch = configureFetch(\n    fetch,\n    applyMiddleware(\n      // forward cookie from incoming request to all outgoing requests\n      defaultHeaders({ cookie: request.headers.get('cookie') }),\n    ),\n  );\n\n  // this request will contain cookies from the incoming request\n  const orders = await myFetch('http://something.com/api/user/orders').then(\n    (res) =\u003e res.json(),\n  );\n\n  return new Response(JSON.stringify({ orders }), {\n    'content-type': 'application/json',\n  });\n}\n```\n\n## To do\n\n- ~~JWT middleware~~\n- ~~retry middleware~~\n- ~~ability to use with Bun's `Bun.serve` and Deno's `serve` from `std/http`~~\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrutoo%2Ffetch-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrutoo%2Ffetch-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrutoo%2Ffetch-tools/lists"}