{"id":47647,"library":"fetch-run","title":"fetch-run","description":"A lightweight middleware library for the Fetch API, version 2.8.3, released monthly with active maintenance. It provides a composable middleware pipeline for fetch requests and responses, similar to koa or express middleware. Key differentiators: minimal (1.2KB gzipped), zero dependencies, supports both browser and Node.js (undici-based fetch), and TypeScript-first with full type inference. Unlike heavier solutions like axios or ky, fetch-run focuses solely on middleware chaining without bundling a fetch polyfill.","status":"active","version":"2.8.3","language":"javascript","source_language":"en","source_url":null,"tags":["javascript","fetch","fetch-run","http","api","middleware","stack"],"install":[{"cmd":"npm install fetch-run","lang":"bash","label":"npm"},{"cmd":"yarn add fetch-run","lang":"bash","label":"yarn"},{"cmd":"pnpm add fetch-run","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Named export, not default. ESM-only; no CommonJS support.","wrong":"import createFetch from 'fetch-run'","symbol":"createFetch","correct":"import { createFetch } from 'fetch-run'"},{"note":"Named export; require() works in CJS but TypeScript strict mode may require esModuleInterop.","wrong":"const { compose } = require('fetch-run')","symbol":"compose","correct":"import { compose } from 'fetch-run'"},{"note":"camelCase, not PascalCase. Used for direct middleware application without createFetch.","wrong":"import { FetchRun } from 'fetch-run'","symbol":"fetchRun","correct":"import { fetchRun } from 'fetch-run'"},{"note":"Type import for middleware type definitions. Not a runtime value.","wrong":"import { Middleware } from 'fetch-run'","symbol":"Middleware","correct":"import type { Middleware } from 'fetch-run'"}],"quickstart":{"code":"import { createFetch } from 'fetch-run';\n\n// Logging middleware\nconst logger = (next) => async (url, init) => {\n  console.log('Request:', url);\n  const response = await next(url, init);\n  console.log('Response status:', response.status);\n  return response;\n};\n\n// Authorization middleware\nconst auth = (token) => (next) => async (url, init) => {\n  const headers = new Headers(init?.headers);\n  headers.set('Authorization', `Bearer ${token}`);\n  return next(url, { ...init, headers });\n};\n\nconst fetch = createFetch(\n  logger,\n  auth(process.env.API_TOKEN ?? '')\n);\n\nasync function main() {\n  const res = await fetch('https://api.example.com/data');\n  const data = await res.json();\n  console.log(data);\n}\n\nmain().catch(console.error);","lang":"typescript","description":"Creates a fetch instance with middleware stack including logging and Bearer token authentication."},"warnings":[{"fix":"Upgrade to Node 18+ or use a fetch polyfill like 'undici' with a custom adapter.","message":"Version 2.0 dropped support for Node < 18 (fetch not polyfilled).","severity":"breaking","affected_versions":"<2.0.0"},{"fix":"Wrap middleware definitions in a higher-order function: `(next) => async (url, init) => { ... }`","message":"Middleware signature changed from async function to sync function returning an async function in v2.0.","severity":"breaking","affected_versions":"<2.0.0"},{"fix":"Replace `compose(logger, auth)` with `createFetch(logger, auth)`.","message":"`compose` is deprecated in v2.5+ in favor of direct `createFetch` for cleaner syntax.","severity":"deprecated","affected_versions":">=2.5.0"},{"fix":"Always clone and return a new Response: `const newRes = new Response(res.body, res); return newRes;`","message":"Middleware must return a Response object, not modify it in place. Mutations may cause undefined behavior.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Use `as const` for middleware arrays if needed: `const stack = [logger, auth] as const;`","message":"TypeScript users: `createFetch` expects tuple of middleware; order matters. Incorrect typings can cause inference failures.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Pass a custom fetch via `createFetch(middleware, { fetch: customFetch })`.","message":"Node.js 18 native fetch is used by default. If using a custom fetch (e.g., undici), it must be injected explicitly.","severity":"breaking","affected_versions":">=2.0.0"}],"env_vars":null,"search_vec":"'1.2':39 '2.8.3':13 'activ':17 'api':11,87 'axio':65 'base':51 'browser':46 'bundl':77 'chain':75 'compos':22 'depend':43 'differenti':37 'express':34 'fetch':2,10,26,52,69,79,82,84 'fetch-run':1,68,83 'first':56 'focus':71 'full':58 'gzip':41 'heavier':62 'http':86 'infer':60 'javascript':81 'kb':40 'key':36 'koa':32 'ky':67 'librari':7 'lightweight':5 'like':64 'mainten':18 'middlewar':6,23,35,74,88 'minim':38 'month':15 'node.js':48 'pipelin':24 'polyfil':80 'provid':20 'releas':14 'request':27 'respons':29 'run':3,70,85 'similar':30 'sole':72 'solut':63 'stack':89 'support':44 'type':59 'typescript':55 'typescript-first':54 'undici':50 'undici-bas':49 'unlik':61 'version':12 'without':76 'zero':42","created_at":"2026-06-07T16:52:34.624582+00:00","updated_at":"2026-06-07T16:52:34.624582+00:00","problems":[{"fix":"Ensure each middleware is a function returning a function of `(next) => async (url, init) => { ... }` not a direct async function.","cause":"Passed middleware incorrectly, e.g., forgot to call the higher-order function that returns middleware.","error":"TypeError: middleware is not a function"},{"fix":"Always clone response before mutation: `response = new Response(response.body, response)` and then modify headers.","cause":"Trying to modify response headers without cloning the response object.","error":"Cannot read properties of undefined (reading 'headers')"},{"fix":"Use `createFetch` instead of `compose` (removed since v2.8). If using older version, import `compose` from 'fetch-run/compose'.","cause":"Importing `compose` that was removed in v2.8.0 or using wrong import path/name.","error":"Module '\"fetch-run\"' has no exported member 'compose'"},{"fix":"Always return `await next(url, init)` or a new Response at the end of middleware.","cause":"Middleware callback doesn't return a Response or Promise<Response> at end.","error":"Type 'void' is not assignable to type 'Response | Promise<Response>'"}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":null,"cli_version":null,"type":"library","homepage":null,"github":null,"docs":null,"changelog":null,"pypi":null,"npm":"fetch-run","openapi_spec":null,"status_page":null,"smithery":null,"categories":["testing","devops"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-07","next_check":"2026-09-05","install_tag":null}}