Nuxt API Party

repository·main·Indexed 43 days ago

https://github.com/johannschopplich/nuxt-api-party

A Nuxt module that provides auto-generated, fully typed composables for any API based on OpenAPI specifications. It utilizes a Nuxt proxy route to protect API credentials from client-side exposure and resolve CORS issues. Version 4.0.1 requires Nuxt 4 and openapi-typescript v7.

Tokens
23.8K
Snippets
76
Records
102
Agent score
50%

What's inside Nuxt API Party

  1. Understand authorization header behavior during cookie forwarding

    main

    When using cookie forwarding, the authorization header sent by the browser is never passed on to the upstream API, regardless of your proxyMode. The purpose of the authorization header in the incoming request is to authenticate the user against your Nuxt application, not to authenticate your application against the upstream API.

    To authenticate your application against the upstream service, use one of the following methods:

    1. Default Proxy Mode: Use the endpoint's token or headers configuration option, or provide a headers option directly in the API call.
    2. proxyMode: 'passthrough': Use a request hook to manually attach the required authentication headers.
  2. How caching works in Nuxt API Party

    main

    Nuxt API Party employs two independent caching layers:

    1. In-Memory (Payload) Caching: Fast, lives for the duration of the page session, and is stored in the Nuxt payload. It resolves repeated requests for the same resource without a network round trip. It works for all request methods (not just GET) and does not require specific server headers.
    2. Browser (HTTP) Caching: Survives page reloads by utilizing the browser's native HTTP cache. This only works for GET requests and requires the server to respond with appropriate cache headers (e.g., Cache-Control, ETag, or Last-Modified).

    These layers are controlled by separate options: payloadCache (boolean) and cache (string).

  3. Understand the core concept of Nuxt API Party

    main

    Nuxt API Party is a Nuxt module designed for interacting with external APIs that you do not control. It acts as a server-side proxy: you configure an endpoint once, and the module creates a dedicated Nuxt server route to handle requests.

    Key benefits include:

    • Security: Credentials (tokens, keys) are stored in the server configuration and never reach the browser or the network tab.
    • No CORS issues: Since the browser only communicates with your own Nuxt origin, you avoid Cross-Origin Resource Sharing restrictions.
    • Type Safety: If using an OpenAPI schema, request bodies, query parameters, path parameters, and responses are automatically inferred.
    • Nuxt Native Patterns: The generated tools behave exactly like Nuxt's built-in useFetch and $fetch regarding return values, options, and caching.
  4. How Nuxt API Party handles API requests

    main

    Nuxt API Party uses an internal server route to proxy requests between your Nuxt application and your external API.

    The Workflow:

    1. Generated composables send a POST request to /api/__api_party/{endpointId}.
    2. The request body contains the target API route, HTTP method, headers, and body as JSON.
    3. The Nuxt server receives this, makes the actual request to your API, and returns the response to the client.

    Key Benefits:

    • Security: API credentials remain on the server and are never exposed to the client.
    • CORS: Since requests originate from the server, you avoid browser-based Cross-Origin Resource Sharing issues.
    • SSR Optimization: During Server-Side Rendering, the module invokes the handler directly instead of making an HTTP round trip, improving performance.
  5. Compare `useMyApiData` and `$myApi` data fetching methods

    main

    Each endpoint generated by the module provides two distinct ways to interact with the API. Choosing the right one depends on whether you are fetching data for rendering or performing an action.

    useMyApiData (Reactive Data Fetching)

    • Best for: Page and component data fetching.
    • Returns: An AsyncData object (similar to Nuxt's useFetch).
    • Error Handling: Provides a reactive error value.
    • Caching: Enables payload caching and deduplication by default; hydrates automatically during SSR to prevent double-fetching on the client.

    $myApi (Direct API Calls)

    • Best for: Mutations (POST/PUT/DELETE), form submissions, and programmatic calls where you control the timing.
    • Returns: A Promise that resolves to the response data.
    • Error Handling: Throws an error on failure.
    • Caching: Payload caching is off by default.
    • SSR Note: You decide exactly where and when it runs.
    |                     | `useMyApiData`                                                                    | `$myApi`                          |
    | ------------------- | --------------------------------------------------------------------------------- | --------------------------------- |
    | **Returns**         | [`AsyncData`](https://nuxt.com/docs/api/composables/use-async-data#return-values)          | A promise of the response data    |
    | **On failure**      | A reactive `error` value                                                          | Throws                            |
    | **Caching**         | Payload cache on by default, with deduplication                                   | Payload cache off unless opted in |
    | **Server rendering**| Hydrates automatically                                                           | You decide where it runs          |
    | **Reach for it**    | Page and component data                                                           | Mutations and programmatic calls  |
  6. Handle Nuxt context loss when using `$myApi` inside `useAsyncData`

    main

    Calling $myApi multiple times sequentially inside useAsyncData can cause server-side errors because async operations break the Nuxt context chain.

    To resolve this, you have two options:

    Option 1: Use callWithNuxt

    Wrap subsequent calls with the callWithNuxt helper to restore the context.

    For reactive data fetching within components, use the useMyApiData composables instead. These are designed to handle the Nuxt context automatically and are preferred for standard data fetching.

    // Option 1: Using callWithNuxt
    import { callWithNuxt } from '#app'
    
    const { data } = await useAsyncData(async (nuxt) => {
      const firstResult = await $myApi('/path1')
    
      // Wrap the second call to restore context
      const secondResult = await callWithNuxt(nuxt!, async () =>
        await $myApi('/path2'))
    
      return { firstResult, secondResult }
    })
    
    // Option 2: Using useMyApiData (Preferred for reactive data)
    const { data: posts } = await useMyApiData('posts')
    const { data: comments } = await useMyApiData('comments')
  7. How hooks work in Nuxt API Party

    main

    Hooks allow you to intercept and modify API requests and responses across your entire application. They run inside Nuxt plugins or Nitro plugins and can be applied globally (generic hooks) or to specific endpoints (endpoint-specific hooks).

    Execution Order

    Generic and endpoint-specific hooks are merged and executed in a specific sequence:

    • Requests: The generic api-party:request hook executes first, followed by the endpoint-specific api-party:request:${endpointId} hook.
    • Responses: The endpoint-specific api-party:response:${endpointId} hook executes first, followed by the generic api-party:response hook.

    If you only need to change a single specific API call rather than behavior spanning multiple endpoints, use interceptors instead.

  8. Understand the Passthrough Proxy behavior

    main

    When server.proxyMode is set to 'passthrough', the request pattern changes. Instead of a JSON-wrapped POST to a single endpoint, requests are sent to /api/__api_party/{endpointId}/proxy/{path} using their original HTTP method.

    When to use Passthrough mode:

    • Debugging: When you want the browser's Network tab to mirror the actual upstream request.
    • Caching: When you need to utilize HTTP cache control. The default wrapped mode uses POST, which is never served from the browser's cache.

    Security & Headers in Passthrough mode:

    • Authorization: The proxy automatically withholds the browser's authorization header to prevent leaking app-level credentials to the upstream service.
    • Cookies: Cookies are only forwarded for endpoints where cookies: true is explicitly configured.
  9. What are interceptors and when to use them

    main

    Interceptors are ofetch callbacks (onRequest, onResponse, onRequestError, and onResponseError) that allow you to hook into the lifecycle of a single fetch call.

    Use interceptors for per-request concerns, such as:

    • Retrying a specific endpoint.
    • Adding a log line for a single query.
    • Injecting dynamic authentication for one specific call.

    Note: If you need to apply logic to every request made by the module (e.g., global authentication), use hooks instead of interceptors.

  10. Understand server-side API call behavior and limitations

    main

    Server-side calls via the generated $myApi functions behave differently than browser-side calls because they bypass the client-side proxy and cache.

    Key differences:

    • Direct Requests: Requests go straight to your API, bypassing the /api/__api_party/{endpointId} proxy hop.
    • No Automatic Caching: There is no payload cache. Every call results in a new request. Use Nitro's cachedEventHandler if you need caching.
    • No Nuxt App Hooks: The api-party:request and api-party:response hooks do not fire in server code.
    • No Client Options: Options like client, payloadCache, key, and $fetch are not supported and will result in TypeScript errors.

    Supported parameters: Path parameters, query, headers, body, and method work identically to how they work in the browser.

  11. Configure server.proxyMode for HTTP caching

    main

    To enable the cache option in nuxt-api-party, you must set the server.proxyMode configuration to 'passthrough'.

    By default, proxyMode is set to 'wrapped', which converts every API call into a POST request. Because POST requests are not served from the browser's HTTP cache, caching will not function in the default mode. Setting it to 'passthrough' ensures requests are sent from the client in a way that allows standard HTTP caching to work.

    // Example configuration in nuxt.config.ts
    export default defineNuxtConfig({
      modules: ['nuxt-api-party'],
      apiParty: {
        server: {
          proxyMode: 'passthrough'
        }
      }
    });