wretch

repository·master·Indexed 26 days ago

https://github.com/elbywan/wretch

A tiny (~1.8KB g-zipped) isomorphic wrapper around the Fetch API designed to simplify network requests, response handling, and error management. It features an intuitive, immutable, and type-safe API with a two-stage chaining pattern (Request Chain and Response Chain), supporting environments including modern browsers, Node.js >= 22, Deno, and Bun.

Tokens
23.1K
Snippets
70
Records
92
Agent score
88%

What's inside wretch

  1. Add multiple addons to a wretch instance

    master

    Addons are separate pieces of code that can be imported and plugged into wretch to add new features. You can add multiple addons by passing an array to the .addon() method.

    import FormDataAddon from "wretch/addons/formData"
    import QueryStringAddon from "wretch/addons/queryString"
    
    // Add both addons
    const w = wretch().addon([FormDataAddon, QueryStringAddon])
    
    // Additional features are now available
    w.formData({ hello: "world" }).query({ check: true })
  2. Migrate from Wretch v1 to v2: Addons System

    master

    In Wretch v2, several features previously included in the core are now modular addons. You must explicitly import and register them using the .addon() method to use them.

    Available Addons:

    • QueryString: wretch/addons/queryString
    • FormData: wretch/addons/formData
    • FormUrl: wretch/addons/formUrl
    • BasicAuth: wretch/addons/basicAuth
    • Abort: wretch/addons/abort
    • Progress: wretch/addons/progress
    • Performance: wretch/addons/perfs
    import FormDataAddon from "wretch/addons/formData"
    import QueryStringAddon from "wretch/addons/queryString"
    import wretch from "wretch"
    
    // Register addons
    const w = wretch().addon(FormDataAddon).addon(QueryStringAddon)
    
    // Now the features are available
    w.formData({ hello: "world" }).query({ check: true })
  3. Understand the wretch request and response chaining pattern

    master

    Wretch uses a two-stage chaining pattern: a Request Chain followed by a Response Chain.

    1. Request Chain

    Starts with wretch(url). You can chain helper methods (like .headers(), .auth(), .query()), body type methods (like .json() or .formData()), and finally an HTTP method (like .get(), .post(), .put(), .delete()). The HTTP method call triggers the actual fetch().

    2. Response Chain

    Once fetch() is called, the response chain begins. You can chain catchers (like .notFound(), .unauthorized(), .error()) to handle specific status codes, and finally a response type handler (like .json(), .text(), .blob(), or .res()) to parse the data. The response type handler returns a standard Promise.

    Example Chain:

    await wretch("https://api.example.com")        // Base URL
      .headers({ "X-Api-Key": "secret" })          // Helper method
      .query({ limit: 10 })                        // Helper method
      .json({ name: "Alice", role: "admin" })     // Body type
      .post("/users")                              // HTTP method (starts request)
      .badRequest(err => console.log("Invalid"))   // Catcher
      .unauthorized(err => console.log("No auth")) // Catcher
      .json(user => console.log(user))             // Response type
  4. Migrate from Wretch v2 to v3

    master

    Upgrading to Wretch v3 requires several breaking changes and configuration updates.

    Migration Checklist:

    • Update Node.js: Ensure you are using Node.js 22 or higher.
    • Remove Polyfills: Delete dependencies like node-fetch or form-data. Use native Web APIs.
    • Replace .polyfills(): Use .fetchPolyfill(customFetch) for custom fetch implementations.
    • Replace Global Config: Remove wretch.polyfills() and wretch.options() static calls. Use per-instance configuration instead.
    • Replace .errorType(): Use .customError() for typed error parsing.
    • Update Addon Parameters: Convert positional optional parameters to options objects for .query(), .formData(), and .setTimeout().
    • Review Retry Behavior: Note that retry middleware now skips 4xx errors by default.
  5. Migrate from Wretch v1 to v2: HTTP Method Arguments

    master

    In Wretch v1, you could pass fetch options directly as an argument to HTTP methods. In v2, passing an argument to an HTTP method (like .get(), .post(), etc.) will append a URL segment instead.

    To set fetch options in v2, use the .options() method before calling the HTTP method.

    // v2 way to set options
    wretch("...")
      .options({ my: "option" })
      .get()
    
    // v2 way to append a URL segment
    wretch("https://base.com").get("/resource/1")
  6. Refresh authentication tokens on 401 Unauthorized

    master

    To automatically handle expired tokens, use .unauthorized() within a .resolve() block. Inside the handler, perform the token refresh logic, clear the unauthorized catcher to prevent infinite loops using .resolve(chain => chain, true), and then replay the original request using .fetch().

    import wretch from 'wretch';
    import basicAuth from 'wretch/addons/basicAuth';
    
    let authToken = null;
    let refreshCount = 0;
    
    const refreshToken = async () => {
      refreshCount++;
      authToken = `token-${refreshCount}`;
      return authToken;
    };
    
    const api = wretch('https://httpbingo.org')
      .addon(basicAuth)
      // add the auth header to every request
      .defer((w) => authToken ? w.basicAuth("user", authToken) : w)
      .resolve(chain =>
        chain.unauthorized(async (error, request) => {
          authToken = await refreshToken();
          return request
             // clear unauthorized catcher to avoid infinite loop
            .resolve(chain => chain, true)
            // replay the original request
            .fetch().json();
        })
      );
    
    await api.get('/basic-auth/user/token-1').json();
  7. Quick Start with Wretch

    master

    Wretch is a tiny (~1.8KB g-zipped) wrapper around fetch that simplifies network requests, response handling, and error management. It is immutable, meaning every call creates a cloned instance that can be reused safely.

    Basic Usage Example

    import wretch from "wretch"
    
    // 1. Create a reusable API client with a base URL and options
    const api = wretch("https://jsonplaceholder.typicode.com")
      .options({ mode: "cors" })
    
    // 2. GET request with automatic JSON parsing
    const post = await api.get("/posts/1").json()
    console.log(post.title)
    
    // 3. POST request with automatic JSON serialization
    const created = await api
      .post({ title: "New Post", body: "Content", userId: 1 }, "/posts")
      .json()
    
    // 4. Handle specific error codes (e.g., 404)
    await api
      .get("/posts/999")
      .notFound(() => console.log("Post not found!"))
      .json()
    
    // 5. Access different response types
    const text = await api.get("/posts/1").text()      // Raw text
    const response = await api.get("/posts/1").res()   // Raw Response object
    const blob = await api.get("/photos/1").blob()     // Binary data
    import wretch from "wretch"
    
    const api = wretch("https://jsonplaceholder.typicode.com")
      .options({ mode: "cors" })
    
    const post = await api.get("/posts/1").json()
    
    const created = await api
      .post({ title: "New Post", body: "Content", userId: 1 }, "/posts")
      .json()
    
    await api
      .get("/posts/999")
      .notFound(() => console.log("Post not found!"))
      .json()
    
    const text = await api.get("/posts/1").text()
    const response = await api.get("/posts/1").res()
    const blob = await api.get("/photos/1").blob()
  8. Send multipart FormData with files

    master

    Use the FormDataAddon to send files alongside structured data in a single multipart request. Pass an object to .formData() containing both primitive values and File objects.

    import wretch from 'wretch';
    import FormDataAddon from 'wretch/addons/formData';
    
    const api = wretch('https://httpbingo.org/anything').addon(FormDataAddon);
    
    await api
      .url('/users/profile')
      .formData({
        userId: '123',
        metadata: { role: 'admin', verified: true },
        avatar: file,
      })
      .post()
      .json();
  9. Compatibility and Environment Requirements for Wretch v2

    master

    Wretch v2 is transpiled to es2018. To use it, ensure your environment meets the following requirements:

    • Node.js: Version 14 or higher.
    • Browsers: Any modern browser.

    If you require compatibility with older environments (ES5 or Node.js < 14), you must either:

    1. Use polyfills.
    2. Configure @babel to transpile wretch.
    3. Stay on Wretch v1 (npm install wretch@^1).
  10. Track upload progress with FormData

    master

    To track upload progress, use the FormDataAddon and ProgressAddon. Use the .onUpload((loaded, total) => ...) method to receive updates on the number of bytes loaded versus the total size.

    Note: Upload progress requires HTTP/2 (HTTPS) in browsers and is not supported in Firefox due to streaming limitations.

    import wretch from 'wretch';
    import FormDataAddon from 'wretch/addons/formData';
    import ProgressAddon from 'wretch/addons/progress';
    
    async function uploadFile(file: File) {
      return wretch('https://api.example.com/upload')
        .addon([FormDataAddon, ProgressAddon()])
        .formData({ file })
        .onUpload((loaded, total) => {
          const percent = Math.round((loaded / total) * 100);
          console.log(`Uploading: ${percent}%`);
        })
        .post()
        .json();
    }
  11. Install Wretch

    master

    You can install Wretch using your preferred package manager or via a <script> tag for browser environments.

    Package Managers

    npm i wretch

    (Also supports yarn and pnpm)

    Deno

    deno add npm:wretch

    Bun

    bun add wretch

    <script> tag (Browser)

    For UMD usage, use a CDN like unpkg:

    <script src="https://unpkg.com/wretch"></script>

    For modern ESM imports, use Skypack:

    <script type="module">
      import wretch from 'https://cdn.skypack.dev/wretch/dist/bundle/wretch.all.min.mjs'
    </script>
  12. Use the AbortAddon to manage request cancellation

    master

    To enable request cancellation and timeout capabilities in wretch, you must first add the AbortAddon. This addon provides methods for associating custom AbortController instances, setting timeouts, and handling abort events.

    import AbortAddon from "wretch/addons/abort"
    
    const [c, w] = wretch("...")
      .addon(AbortAddon())
      .get()
      .onAbort((_) => console.log("Aborted !"))
      .controller();
    
    w.text((_) => console.log("should never be called"));
    c.abort();
    import AbortAddon from "wretch/addons/abort"
    
    const [c, w] = wretch("...")
      .addon(AbortAddon())
      .get()
      .onAbort((_) => console.log("Aborted !"))
      .controller();
    
    w.text((_) => console.log("should never be called"));
    c.abort();