From 4f8c21e122e339c806f81df279b30db04164368c Mon Sep 17 00:00:00 2001 From: Johann Schopplich Date: Wed, 17 Apr 2024 19:15:41 +0200 Subject: [PATCH] docs: add interceptors guide (closes #69) --- README.md | 4 +- docs/.vitepress/config.ts | 19 ++++---- docs/.vitepress/meta.ts | 1 + docs/api/index.md | 8 ++-- docs/api/my-api.md | 2 +- docs/api/use-my-api-data.md | 2 +- docs/config/index.md | 2 +- docs/guide/error-handling.md | 2 +- docs/guide/getting-started.md | 6 +-- docs/guide/interceptors.md | 84 +++++++++++++++++++++++++++++++++++ docs/guide/openapi-types.md | 8 ++-- docs/index.md | 22 ++++----- 12 files changed, 124 insertions(+), 36 deletions(-) create mode 100644 docs/guide/interceptors.md diff --git a/README.md b/README.md index 8ff8771..7503231 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![nuxt-api-party](./docs/public/og.jpg)](https://nuxt-api-party.byjohann.dev) -# nuxt-api-party +# Nuxt API Party [![npm version](https://img.shields.io/npm/v/nuxt-api-party?color=a1b858&label=)](https://www.npmjs.com/package/nuxt-api-party) @@ -33,7 +33,7 @@ npx nuxi@latest module add api-party > [!TIP] > [📖 Read the documentation](https://nuxt-api-party.byjohann.dev) -Add this module `nuxt-api-party` to your Nuxt config and prepare your first API connection by setting an endpoint object with the following properties for the `apiParty` module option: +Add the Nuxt API Party to your Nuxt config and prepare your first API connection by setting an endpoint object with the following properties for the `apiParty` module option: ```ts // `nuxt.config.ts` diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index bf80faa..d012701 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,8 +1,9 @@ import { defineConfig } from 'vitepress' import type { DefaultTheme } from 'vitepress' -import { description, name, version } from '../../package.json' +import { description, version } from '../../package.json' import { github, + name, ogImage, ogUrl, releases, @@ -13,7 +14,7 @@ const url = new URL(ogUrl) export default defineConfig({ lang: 'en-US', title: name, - description: 'Connect to any API securely', + description: 'Server proxy and generated API composables', head: [ ['link', { rel: 'icon', href: '/logo.svg', type: 'image/svg+xml' }], ['meta', { name: 'author', content: 'Johann Schopplich' }], @@ -82,10 +83,11 @@ function nav(): DefaultTheme.NavItem[] { { text: 'Advanced', items: [ - { text: 'Hydration', link: '/guide/hydration' }, { text: 'Caching', link: '/guide/caching' }, + { text: 'Interceptors', link: '/guide/interceptors' }, { text: 'Cookies', link: '/guide/cookies' }, { text: 'Retries', link: '/guide/retries' }, + { text: 'Hydration', link: '/guide/hydration' }, { text: 'Dynamic Backend URL', link: '/guide/dynamic-backend-url' }, ], }, @@ -106,8 +108,8 @@ function nav(): DefaultTheme.NavItem[] { { text: 'Composables', items: [ - { text: 'useMyApiData', link: '/api/use-my-api-data' }, - { text: '$myApi', link: '/api/my-api' }, + { text: 'useFetch Substitute', link: '/api/use-my-api-data' }, + { text: '$fetch Substitute', link: '/api/my-api' }, ], }, ], @@ -144,10 +146,11 @@ function sidebarGuide(): DefaultTheme.SidebarItem[] { { text: 'Advanced', items: [ - { text: 'Hydration', link: '/guide/hydration' }, { text: 'Caching', link: '/guide/caching' }, + { text: 'Interceptors', link: '/guide/interceptors' }, { text: 'Cookies', link: '/guide/cookies' }, { text: 'Retries', link: '/guide/retries' }, + { text: 'Hydration', link: '/guide/hydration' }, { text: 'Dynamic Backend URL', link: '/guide/dynamic-backend-url' }, ], }, @@ -166,8 +169,8 @@ function sidebarApi(): DefaultTheme.SidebarItem[] { { text: 'Composables', items: [ - { text: 'useMyApiData', link: '/api/use-my-api-data' }, - { text: '$myApi', link: '/api/my-api' }, + { text: 'useFetch Substitute', link: '/api/use-my-api-data' }, + { text: '$fetch Substitute', link: '/api/my-api' }, ], }, ] diff --git a/docs/.vitepress/meta.ts b/docs/.vitepress/meta.ts index a1c5bff..68f1199 100644 --- a/docs/.vitepress/meta.ts +++ b/docs/.vitepress/meta.ts @@ -1,4 +1,5 @@ /* VitePress head */ +export const name = 'Nuxt API Party' export const ogUrl = 'https://nuxt-api-party.byjohann.dev/' export const ogImage = `${ogUrl}og.jpg` diff --git a/docs/api/index.md b/docs/api/index.md index fdef1c1..823848b 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -2,16 +2,16 @@ ## Composables -`nuxt-api-party` offers two distinct composable types to return data from your APIs. All composables are [auto-imported](https://nuxt.com/docs/guide/concepts/auto-imports) and globally available inside your components: +Nuxt API Party offers two distinct composable types to return data from your APIs. All composables are [auto-imported](https://nuxt.com/docs/guide/concepts/auto-imports) and globally available inside your components: -- [`useMyApiData`](/api/use-my-api-data) – Returns multiple values similar to [`useFetch`](https://nuxt.com/docs/api/composables/use-fetch) -- [`$myApi`](/api/my-api) – Returns the response data, similar to [`$fetch`](https://nuxt.com/docs/api/utils/dollarfetch#fetch) +- [Substitute for Nuxt `useFetch`](/api/use-my-api-data) – Returns multiple values similar to [`useFetch`](https://nuxt.com/docs/api/composables/use-fetch) +- [Substitute for Nuxt `$fetch`](/api/my-api) – Returns the response data, similar to [`$fetch`](https://nuxt.com/docs/api/utils/dollarfetch#fetch) ::: info `$myApi` and `useMyApiData` are placeholders. They are used as examples in the documentation. The actual composables are generated based on your API endpoint ID. ::: -## Dynamic Composables +## Generated Composables The composables are generated based on your API endpoint ID. For example, if you were to call your API `jsonPlaceholder`, the generated composables are: diff --git a/docs/api/my-api.md b/docs/api/my-api.md index 2e5506a..3c6b470 100644 --- a/docs/api/my-api.md +++ b/docs/api/my-api.md @@ -1,4 +1,4 @@ -# `$myApi` +# Nuxt `$fetch` Substitute ::: info `$myApi` is a placeholder used as an example in the documentation. The composable is generated based on your API endpoint ID. For example, if you were to call an endpoint `jsonPlaceholder`, the composable will be called `$jsonPlaceholder`. diff --git a/docs/api/use-my-api-data.md b/docs/api/use-my-api-data.md index cf409a7..b93541b 100644 --- a/docs/api/use-my-api-data.md +++ b/docs/api/use-my-api-data.md @@ -1,4 +1,4 @@ -# `useMyApiData` +# Nuxt `useFetch` Substitute ::: info `useMyApiData` is a placeholder used as an example in the documentation. The composable is generated based on your API endpoint ID. For example, if you were to call an endpoint `jsonPlaceholder`, the composable will be called `useJsonPlaceholderData`. diff --git a/docs/config/index.md b/docs/config/index.md index c445c58..0810826 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -1,6 +1,6 @@ # Module Configuration -Adapt `nuxt-api-party` to your needs with the following options in your `nuxt.config.ts` file: +Adapt Nuxt API Party to your needs with the following options in your `nuxt.config.ts` file: ```ts // `nuxt.config.ts` diff --git a/docs/guide/error-handling.md b/docs/guide/error-handling.md index c441cb2..23f89e3 100644 --- a/docs/guide/error-handling.md +++ b/docs/guide/error-handling.md @@ -1,6 +1,6 @@ # Error Handling -While the idea of this Nuxt module is to mask your real API (and credentials) within the server proxy, `nuxt-api-party` will minimize the hassle of handling errors by passing through the following properties to the response on the client: +While the idea of this Nuxt module is to mask your real API (and credentials) within the server proxy, Nuxt API Party will minimize the hassle of handling errors by passing through the following properties to the response on the client: - Response body - HTTP status code diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index 1da6dab..ca22403 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -1,14 +1,14 @@ # Getting Started -This guide will walk you through the steps to get started with `nuxt-api-party`. +This guide will walk you through the steps to get started with Nuxt API Party. -## Step 1: Install `nuxt-api-party` +## Step 1: Install Nuxt API Party ```bash npx nuxi@latest module add api-party ``` -## Step 2: Use `nuxt-api-party` +## Step 2: Use the `nuxt-api-party` module Add `nuxt-api-party` to your Nuxt configuration: diff --git a/docs/guide/interceptors.md b/docs/guide/interceptors.md new file mode 100644 index 0000000..d36d714 --- /dev/null +++ b/docs/guide/interceptors.md @@ -0,0 +1,84 @@ +# Interceptors + +A common question when working with APIs is how to handle the HTTP status code. This is where interceptors come in. Interceptors are functions that are called before and after the fetch request is made. They can be used to modify the request, response, or options. Nuxt uses [`ofetch`](https://github.com/unjs/ofetch) for its fetch implementation, which provides a way to [intercept requests and responses](https://github.com/unjs/ofetch?tab=readme-ov-file#%EF%B8%8F-interceptors). + +**tl;dr**: To use interceptors, pass an object with the following properties to the composables: + +- `onRequest({ request, options })` +- `onRequestError({ request, options, error })` +- `onResponse({ request, options, response })` +- `onResponseError({ request, options, response })` + +Getting the HTTP status code is as simple as logging the response status from the `response` object in the `onResponse` interceptor. + +```ts +const { data } = await useApiData('path', { + onResponse(ctx) { + const status = ctx.response.status + console.log('The status code is:', status) + }, +}) +``` + +::: tip +The examples below work with both the `$fetch` and `useFetch` composable substitutes, `$myApi` and `useMyApiData` respectively. +::: + +## `onRequest({ request, options })` + +`onRequest` is called as soon as the given composable is called, allowing you to modify options or log the request. + +```ts +const { data } = await useApiData('path', { + async onRequest({ request, options }) { + // Log the request + console.log(request, options) + + // Add a timestamp to the search parameters + options.query ||= {} + options.query.t = Date.now() + }, +}) +``` + +## `onRequestError({ request, options, error })` + +`onRequestError` will be called when the fetch request fails before it is made, allowing you to log the error. + +```ts +const { data } = await useApiData('path', { + async onRequestError({ request, options, error }) { + // Log the error + console.error(error) + }, +}) +``` + +## `onResponse({ request, options, response })` + +`onResponse` will be called after the fetch request is made, allowing you to log the response or modify the data. + +```ts +const { data } = await useApiData('path', { + async onResponse({ request, response, options }) { + // Log the response status code and body + console.log(response.status, response.body) + }, +}) +``` + +## `onResponseError({ request, options, response })` + +`onResponseError` is the same as `onResponse` but will be called when the fetch request fails and `response.ok` is `false`. + +```ts +const { data } = await useApiData('path', { + async onResponseError({ request, response, options }) { + // Log the response status code and body + console.error( + response.status, + response.body + ) + }, +}) +``` diff --git a/docs/guide/openapi-types.md b/docs/guide/openapi-types.md index 4afff61..2d964e1 100644 --- a/docs/guide/openapi-types.md +++ b/docs/guide/openapi-types.md @@ -1,9 +1,9 @@ # OpenAPI Types -If your API has an [OpenAPI](https://swagger.io/resources/open-api/) schema, `nuxt-api-party` can use it to generate types for you. These include path names, supported HTTP methods, request body, response body, query parameters, and headers. +If your API has an [OpenAPI](https://swagger.io/resources/open-api/) schema, Nuxt API Party can use it to generate types for you. These include path names, supported HTTP methods, request body, response body, query parameters, and headers. ::: info -Usage of this feature requires [`openapi-typescript`](https://www.npmjs.com/package/openapi-typescript) to generate TypeScript definitions from your OpenAPI schema file. It is installed alongside `nuxt-api-party`. +Usage of this feature requires [`openapi-typescript`](https://www.npmjs.com/package/openapi-typescript) to generate TypeScript definitions from your OpenAPI schema file. It is installed alongside Nuxt API Party. ::: ## Schema Generation @@ -98,7 +98,7 @@ export default defineNuxtConfig({ ## Using the Types -For most usages, no further intervention is needed. `nuxt-api-party` will use the types generated from this config to infer the correct types automatically when `$myApi` and `useMyApiData` is used. +For most usages, no further intervention is needed. Nuxt API Party will use the types generated from this config to infer the correct types automatically when `$myApi` and `useMyApiData` is used. However, there may be a few things you may want to do now that you have type information. @@ -142,7 +142,7 @@ const data = await $myApi('/foo/{id}', { ``` ::: warning -Issues will **NOT** be reported at runtime by `nuxt-api-party` if the wrong parameters are used. The **incomplete** path will be sent to the backend **as-is**. +Issues will **NOT** be reported at runtime by Nuxt API Party if the wrong parameters are used. The **incomplete** path will be sent to the backend **as-is**. ::: ### Route Method Overloading diff --git a/docs/index.md b/docs/index.md index fd00665..cb70067 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,13 +1,13 @@ --- layout: home -titleTemplate: Connect to any API securely +titleTemplate: Server Proxy and Generated API Composables hero: - name: nuxt-api-party - text: Connect to any API securely - tagline: Server proxy and dynamic composables + name: Nuxt API Party + text: Server Proxy and Generated API Composables + tagline: Connect to all your APIs securely image: src: /logo-shadow.svg - alt: nuxt-api-party + alt: Nuxt API Party Logo actions: - theme: brand text: Get Started @@ -20,24 +20,24 @@ hero: link: https://github.com/johannschopplich/nuxt-api-party features: - - title: Dynamic composable names + - title: Dynamic composables icon: details: Auto-generated composables for each API endpoint. link: /api/ linkText: API Reference - - title: Protected API credentials + - title: Protected API Credentials icon: details: A Nuxt server route proxies your requests. No CORS issues! link: /guide/how-it-works linkText: How It Works - title: Familiar Data Handling icon: - details: Handle requests just like useFetch or $fetch. + details: Handle requests just like Nuxt `useFetch` and `$fetch`. link: /api/use-my-api-data - linkText: useMyApiData - - title: Connect multiple APIs + linkText: Async Data Composable + - title: Connect Multiple APIs icon: - details: Use multiple APIs in your app with one module. + details: Configure all your APIs once and use them throughout your app. link: /guide/getting-started.html#step-3-set-up-api-endpoints linkText: Set Up API Endpoints ---