@nuxt/docs-nightly 5.0.0-29841017.b1cd49dc → 5.0.0-29841042.d5a56a2a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: 'createUseAsyncData'
3
3
  description: A factory function to create a custom useAsyncData composable with pre-defined default options.
4
- minimalVersion: "4.2"
4
+ minimalVersion: "4.4"
5
5
  links:
6
6
  - label: Source
7
7
  icon: i-simple-icons-github
@@ -40,7 +40,7 @@ The resulting composable has the same signature and return type as [`useAsyncDat
40
40
 
41
41
  ```ts [Signature]
42
42
  function createUseAsyncData (
43
- options?: Partial<AsyncDataOptions>,
43
+ options?: Partial<AsyncDataOptions> & { addons?: UseAsyncDataAddon[] },
44
44
  ): typeof useAsyncData
45
45
 
46
46
  function createUseAsyncData (
@@ -48,6 +48,8 @@ function createUseAsyncData (
48
48
  ): typeof useAsyncData
49
49
  ```
50
50
 
51
+ The returned composable's signature includes any custom options and return-value extensions contributed by the [addons](#addons).
52
+
51
53
  ## Options
52
54
 
53
55
  `createUseAsyncData` accepts all the same options as [`useAsyncData`](/docs/api/composables/use-async-data#parameters), including `server`, `lazy`, `immediate`, `default`, `transform`, `pick`, `getCachedData`, `deep`, `dedupe`, `timeout`, and `watch`.
@@ -86,6 +88,47 @@ export const useStrictData = createUseAsyncData(callerOptions => ({
86
88
  }))
87
89
  ```
88
90
 
91
+ ## Addons
92
+
93
+ In addition to `useAsyncData` options, `createUseAsyncData` accepts an `addons` array. Addons are reusable units of behavior defined with [`defineUseAsyncDataAddon`](/docs/api/utils/define-use-async-data-addon). They can declare custom call-site options, run middleware around the handler, extend the returned object, and attach custom logic to the composable.
94
+
95
+ For example, an addon that refreshes the data whenever the window regains focus, gated behind a custom `refreshOnFocus` option, so callers opt in per call:
96
+
97
+ ```ts [app/composables/useCustomAsyncData.ts]
98
+ const refreshOnFocus = defineUseAsyncDataAddon({
99
+ // augment the call-site options for the custom useAsyncData instance 👇
100
+ setup: (options: UseAsyncDataAddonOptions<{ refreshOnFocus?: boolean }>) => {
101
+ // 👈 run code *before* creating the `useAsyncData` instance
102
+ if (import.meta.server || !options.refreshOnFocus) { return }
103
+
104
+ return (asyncData) => {
105
+ // 👈 run code *after* creating the `useAsyncData` instance
106
+ const focused = useWindowFocus()
107
+ watch(focused, (focused) => {
108
+ if (focused) { asyncData.refresh() }
109
+ })
110
+
111
+ return { focused } // 👈 extend the returned object with a new property
112
+ }
113
+ },
114
+ })
115
+
116
+ export const useCustomAsyncData = createUseAsyncData({ addons: [refreshOnFocus] })
117
+ ```
118
+
119
+ ```vue [app/pages/index.vue]
120
+ <script setup lang="ts">
121
+ // `refreshOnFocus` is typed on the created composable
122
+ const { data } = await useCustomAsyncData(
123
+ 'mountains',
124
+ () => $fetch('https://api.nuxtjs.dev/mountains'),
125
+ { refreshOnFocus: true },
126
+ )
127
+ </script>
128
+ ```
129
+
130
+ :read-more{to="/docs/api/utils/define-use-async-data-addon"}
131
+
89
132
  :read-more{to="/docs/guide/recipes/custom-usefetch"}
90
133
 
91
134
  :read-more{to="/docs/api/composables/use-async-data"}
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: 'createUseFetch'
3
3
  description: A factory function to create a custom useFetch composable with pre-defined default options.
4
- minimalVersion: "4.2"
4
+ minimalVersion: "4.4"
5
5
  links:
6
6
  - label: Source
7
7
  icon: i-simple-icons-github
@@ -35,7 +35,7 @@ The resulting `useAPI` composable has the same signature and return type as [`us
35
35
 
36
36
  ```ts [Signature]
37
37
  function createUseFetch (
38
- options?: Partial<UseFetchOptions>,
38
+ options?: Partial<UseFetchOptions> & { addons?: UseFetchAddon[] },
39
39
  ): typeof useFetch
40
40
 
41
41
  function createUseFetch (
@@ -44,10 +44,12 @@ function createUseFetch (
44
44
 
45
45
  // where the client declares the routes it serves
46
46
  function createUseFetch<Routes> (
47
- options: Partial<UseFetchOptions> & { routes: Routes },
47
+ options: Partial<UseFetchOptions> & { routes: Routes, addons?: UseFetchAddon[] },
48
48
  ): DeclaredUseFetch<Routes>
49
49
  ```
50
50
 
51
+ The returned composable's signature includes any custom options and return-value extensions contributed by the [addons](#addons).
52
+
51
53
  ## Options
52
54
 
53
55
  `createUseFetch` accepts all the same options as [`useFetch`](/docs/api/composables/use-fetch#parameters), including `baseURL`, `headers`, `query`, `onRequest`, `onResponse`, `server`, `lazy`, `transform`, `getCachedData`, and more.
@@ -164,6 +166,46 @@ export const useAPI = createUseFetch(callerOptions => ({
164
166
  The **function signature** (override mode) is required here so that [`useNuxtApp()`](/docs/api/composables/use-nuxt-app) is called in the setup context (at the composable call site) rather than in the module scope, where no Nuxt instance is available.
165
167
  ::
166
168
 
169
+ ## Addons
170
+
171
+ In addition to `useFetch` options, `createUseFetch` accepts an `addons` array. Addons are reusable units of behavior defined with [`defineUseFetchAddon`](/docs/api/utils/define-use-fetch-addon). They can declare custom call-site options, run middleware around the handler, extend the returned object, and attach custom logic to the composable.
172
+
173
+ For example, an addon that refreshes the data whenever the window regains focus, gated behind a custom `refreshOnFocus` option, so callers opt in per call:
174
+
175
+ ```ts [app/composables/useCustomFetch.ts]
176
+ const refreshOnFocus = defineUseFetchAddon({
177
+ // augment the call-site options for the custom useFetch instance 👇
178
+ setup: (options: UseFetchAddonOptions<{ refreshOnFocus?: boolean }>) => {
179
+ // 👈 run code *before* calling `useAsyncData` in `useFetch`
180
+ if (import.meta.server || !options.refreshOnFocus) { return }
181
+
182
+ return (asyncData) => {
183
+ // 👈 run code *after* calling `useAsyncData` in `useFetch`
184
+ const focused = useWindowFocus()
185
+ watch(focused, (focused) => {
186
+ if (focused) { asyncData.refresh() }
187
+ })
188
+
189
+ return { focused } // 👈 extend the returned object with a new property
190
+ }
191
+ },
192
+ })
193
+
194
+ export const useCustomFetch = createUseFetch({ addons: [refreshOnFocus] })
195
+ ```
196
+
197
+ ```vue [app/pages/index.vue]
198
+ <script setup lang="ts">
199
+ // `refreshOnFocus` is typed on the created composable
200
+ const { data } = await useCustomFetch(
201
+ 'https://api.nuxtjs.dev/mountains',
202
+ { refreshOnFocus: true },
203
+ )
204
+ </script>
205
+ ```
206
+
207
+ :read-more{to="/docs/api/utils/define-use-fetch-addon"}
208
+
167
209
  :read-more{to="/docs/guide/recipes/custom-usefetch"}
168
210
 
169
211
  :read-more{to="/docs/api/composables/use-fetch"}
@@ -168,8 +168,11 @@ type AsyncDataOptions<ResT, DataT = ResT> = {
168
168
  timeout?: number
169
169
  enabled?: MaybeRefOrGetter<boolean>
170
170
  serialize?: boolean
171
+ middleware?: AsyncDataMiddleware<ResT>[]
171
172
  }
172
173
 
174
+ type AsyncDataMiddleware<ResT> = (next: () => Promise<ResT>, ctx: { signal: AbortSignal }) => Promise<ResT>
175
+
173
176
  type AsyncDataRequestContext = {
174
177
  /** The reason for this data request */
175
178
  cause: 'initial' | 'refresh:manual' | 'refresh:hook' | 'watch'
@@ -220,6 +223,7 @@ The `handler` function should be **side-effect free** to ensure predictable beha
220
223
  | `dedupe` :badge[v3.9]{color="info" size="xs" class="align-middle"} | `'cancel' \| 'defer'` | `'cancel'` | Policy when triggering an execution more than once at a time. |
221
224
  | `enabled` :badge[v4.5]{color="info" size="xs" class="align-middle"} | `boolean` | `true` | Barrier that gates whether the `handler` may run. While `false`, every execution is blocked (initial fetch, `execute`/`refresh`, and watch triggers), and switching `true` → `false` cancels any in-flight request without clearing `data`. Re-enabling does not refetch on its own. |
222
225
  | `serialize` :badge[v4.6]{color="info" size="xs" class="align-middle"} | `boolean` | `true` | Whether to store resolved data in the Nuxt payload (`__NUXT_DATA__`). When `false`, server-fetched data is kept out of the payload and the client will refetch after hydration if a component renders it. Pair with [lazy hydration](/docs/guide/best-practices/performance#lazy-hydration) to avoid hydration mismatches and unnecessary client fetches. |
226
+ | `middleware` :badge[v4.6]{color="info" size="xs" class="align-middle"} | `AsyncDataMiddleware[]` | - | Functions wrapping the execution of the `handler`. Each receives `next`, which runs the rest of the chain and resolves to the data, and the handler context (`{ signal }`). The first entry is the outermost wrapper. Call `next()` to continue or throw to abort. |
223
227
 
224
228
  ::note
225
229
  All options can be given a `computed` or `ref` value. These will be watched and new requests made automatically with any new values if they are updated.
@@ -255,6 +259,7 @@ The following options **must be consistent** across all calls with the same key:
255
259
  - `pick` array
256
260
  - `getCachedData` function
257
261
  - `default` value
262
+ - `middleware` array
258
263
 
259
264
  The following options **can differ** without triggering warnings:
260
265
  - `server`
@@ -177,6 +177,7 @@ type UseFetchOptions<ResT, DataT = ResT> = {
177
177
  timeout?: number
178
178
  enabled?: MaybeRefOrGetter<boolean>
179
179
  serialize?: boolean
180
+ middleware?: AsyncDataMiddleware<ResT>[]
180
181
  default?: () => DataT | Ref<DataT>
181
182
  transform?: (input: ResT) => DataT | Promise<DataT>
182
183
  pick?: string[]
@@ -236,6 +237,7 @@ type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
236
237
  | `dedupe` :badge[v3.9]{color="info" size="xs" class="align-middle"} | `'cancel' \| 'defer'` | `'cancel'` | Avoid fetching same key more than once at a time. |
237
238
  | `enabled` :badge[v4.5]{color="info" size="xs" class="align-middle"} | `boolean` | `true` | Barrier that gates whether the request may run. While `false`, every execution is blocked (initial fetch, `execute`/`refresh`, and watch triggers), and switching `true` → `false` cancels any in-flight request without clearing `data`. Re-enabling does not refetch on its own. |
238
239
  | `serialize` :badge[v4.6]{color="info" size="xs" class="align-middle"} | `boolean` | `true` | Whether to store resolved data in the Nuxt payload (`__NUXT_DATA__`). When `false`, server-fetched data is kept out of the payload and the client will refetch after hydration if a component renders it. Pair with [lazy hydration](/docs/guide/best-practices/performance#lazy-hydration) to avoid hydration mismatches and unnecessary client fetches. |
240
+ | `middleware` :badge[v4.6]{color="info" size="xs" class="align-middle"} | `AsyncDataMiddleware[]` | - | Functions wrapping the execution of the request. Each receives `next`, which runs the rest of the chain and resolves to the data, and the handler context (`{ signal }`). The first entry is the outermost wrapper. Call `next()` to continue or throw to abort. |
239
241
  | `$fetch` :badge[v3.2]{color="info" size="xs" class="align-middle"} | `typeof globalThis.$fetch` | - | Custom $fetch implementation. See [Custom useFetch in Nuxt](/docs/guide/recipes/custom-usefetch) |
240
242
 
241
243
  ::note
@@ -0,0 +1,57 @@
1
+ ---
2
+ title: 'defineUseAsyncDataAddon'
3
+ description: Define a reusable addon that extends composables created with createUseAsyncData.
4
+ minimalVersion: "4.6"
5
+ links:
6
+ - label: Source
7
+ icon: i-simple-icons-github
8
+ to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/addons.ts
9
+ size: xs
10
+ ---
11
+
12
+ `defineUseAsyncDataAddon` defines a reusable extension for `useAsyncData` composables created with [`createUseAsyncData`](/docs/api/composables/create-use-async-data).
13
+
14
+ An addon can declare custom call-site options, wrap the handler with middleware, attach custom reactive logic or extend the returned object.
15
+
16
+ :read-more{to="/docs/api/utils/define-use-fetch-addon" title="defineUseFetchAddon: Addons for useAsyncData work the same way as useFetch addons"}
17
+
18
+ ## Usage
19
+
20
+ For example, an addon adding a `pollEvery` option that refreshes the data on an interval:
21
+
22
+ ```ts [app/composables/usePolledAsyncData.ts]
23
+ const polling = defineUseAsyncDataAddon({
24
+ setup: (options: UseAsyncDataAddonOptions<{ pollEvery?: number }>) => {
25
+ if (import.meta.server || !options.pollEvery) { return }
26
+ return (asyncData) => {
27
+ const interval = setInterval(() => asyncData.refresh(), options.pollEvery)
28
+ onScopeDispose(() => clearInterval(interval))
29
+ }
30
+ },
31
+ })
32
+
33
+ export const usePolledAsyncData = createUseAsyncData({ addons: [polling] })
34
+ ```
35
+
36
+ ```vue [app/pages/index.vue]
37
+ <script setup lang="ts">
38
+ // refreshes the data every 30 seconds
39
+ const { data } = await usePolledAsyncData(
40
+ 'mountains',
41
+ () => $fetch('https://api.nuxtjs.dev/mountains'),
42
+ { pollEvery: 30_000 },
43
+ )
44
+ </script>
45
+ ```
46
+
47
+ ::note
48
+ Addons run in the order of the `addons` array, with middleware from the first addon as the outermost wrapper. Listing the same addon object more than once runs it only once.
49
+ ::
50
+
51
+ ## Type
52
+
53
+ ```ts [Signature]
54
+ function defineUseAsyncDataAddon<Opts extends Record<string, any> = {}, Ext = {}> (addon: {
55
+ setup: (options: UseAsyncDataAddonOptions<Opts>) => ((asyncData: AsyncDataAddonInstance) => Ext | void) | void
56
+ }): UseAsyncDataAddon<Opts, Ext>
57
+ ```
@@ -0,0 +1,168 @@
1
+ ---
2
+ title: 'defineUseFetchAddon'
3
+ description: Define a reusable addon that extends composables created with createUseFetch.
4
+ minimalVersion: "4.6"
5
+ links:
6
+ - label: Source
7
+ icon: i-simple-icons-github
8
+ to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/addons.ts
9
+ size: xs
10
+ ---
11
+
12
+ `defineUseFetchAddon` defines a reusable extension for `useFetch` composables created with [`createUseFetch`](/docs/api/composables/create-use-fetch).
13
+
14
+ An addon can declare custom call-site options, wrap the handler with middleware, attach custom reactive logic or extend the returned object.
15
+
16
+ ## Usage
17
+
18
+ Pass addons to `createUseFetch` via the `addons` array.
19
+
20
+ This addon attaches custom logic: a watcher that refreshes the data whenever the window regains focus and gates it behind a custom `refreshOnFocus` option:
21
+
22
+ ```ts [app/composables/useCustomFetch.ts]
23
+ const refreshOnFocus = defineUseFetchAddon({
24
+ // augment the call-site options for the custom useFetch instance 👇
25
+ setup: (options: UseFetchAddonOptions<{ refreshOnFocus?: boolean }>) => {
26
+ // 👈 run code *before* calling `useAsyncData` in `useFetch`
27
+ if (import.meta.server || !options.refreshOnFocus) { return }
28
+
29
+ return (asyncData) => {
30
+ // 👈 run code *after* calling `useAsyncData` in `useFetch`
31
+ const focused = useWindowFocus()
32
+ watch(focused, (focused) => {
33
+ if (focused) { asyncData.refresh() }
34
+ })
35
+
36
+ return { focused } // 👈 extend the returned object with a new property
37
+ }
38
+ },
39
+ })
40
+
41
+ export const useCustomFetch = createUseFetch({ addons: [refreshOnFocus] })
42
+ ```
43
+
44
+ ```vue [app/pages/index.vue]
45
+ <script setup lang="ts">
46
+ const { data } = await useCustomFetch('/some-endpoint', { refreshOnFocus: true })
47
+ </script>
48
+ ```
49
+
50
+ The addon's `setup` function runs on every call of the composable, and receives the merged options (factory defaults plus caller options).
51
+
52
+ ::note
53
+ Addons run in the order of the `addons` array, with middleware from the first addon as the outermost wrapper. Listing the same addon object more than once runs it only once.
54
+ ::
55
+
56
+ ## Custom Options
57
+
58
+ Declare custom options by annotating the `setup` `options` parameter with `UseFetchAddonOptions<{ ... }>`. The options become part of the created composable's signature, fully typed for callers:
59
+
60
+ ```ts [app/composables/useCustomFetch.ts]
61
+ const auth = defineUseFetchAddon({
62
+ setup: (options: UseFetchAddonOptions<{ auth?: MaybeRefOrGetter<boolean> }>) => {
63
+ const { token } = useTokenStore()
64
+ options.auth ??= true
65
+ options.onRequest.push(({ options: fetchOptions }) => {
66
+ if (!toValue(options.auth)) { return }
67
+ fetchOptions.headers.set('Authorization', `Bearer ${token.value}`)
68
+ })
69
+ },
70
+ })
71
+
72
+ export const useCustomFetch = createUseFetch({ addons: [auth] })
73
+ ```
74
+
75
+ ```vue [app/pages/index.vue]
76
+ <script setup lang="ts">
77
+ // `auth` is typed
78
+ const { data } = await useCustomFetch('/public-endpoint', { auth: false })
79
+ </script>
80
+ ```
81
+
82
+ Custom options stay in the merged options object, so they are also passed to `$fetch` along with the request options, which ignores keys it does not recognise.
83
+
84
+ ## Extending the Return Value
85
+
86
+ If `setup` returns a function, that function is called with the async data instance. Any object it returns is merged into the composable's return value:
87
+
88
+ ```ts
89
+ const timestamps = defineUseFetchAddon({
90
+ setup: () => {
91
+ const refreshedAt = ref<Date>()
92
+
93
+ return (asyncData) => {
94
+ watch(asyncData.status, (status) => {
95
+ if (status === 'success') { refreshedAt.value = new Date() }
96
+ }, { immediate: true })
97
+
98
+ return { refreshedAt: readonly(refreshedAt) }
99
+ }
100
+ },
101
+ })
102
+
103
+ export const useCustomFetch = createUseFetch({ addons: [timestamps] })
104
+ ```
105
+
106
+ ```vue [app/pages/index.vue]
107
+ <script setup lang="ts">
108
+ // `refreshedAt` is typed
109
+ const { data, refreshedAt } = await useCustomFetch('/modules')
110
+ </script>
111
+ ```
112
+
113
+ ## Middleware
114
+
115
+ Middleware wraps the execution of the request handler. Call `next()` to continue the chain (and get the resolved data), or throw to abort. Middleware from the first addon is the outermost wrapper:
116
+
117
+ ```ts
118
+ const minDuration = defineUseFetchAddon({
119
+ setup: (options: UseFetchAddonOptions<{ minDuration?: number }>) => {
120
+ options.middleware.push(async (next) => {
121
+ const [result] = await Promise.all([
122
+ next(),
123
+ new Promise(resolve => setTimeout(resolve, toValue(options.minDuration) ?? 300)),
124
+ ])
125
+ return result
126
+ })
127
+ },
128
+ })
129
+ ```
130
+
131
+ ## Contributing to the Auto-Generated Key
132
+
133
+ Custom options are **not** part of the auto-generated key by default. If a custom option affects the response, provide a `key` resolver so calls with different values do not share a cached entry. Return a serializable value, or `undefined` to contribute nothing:
134
+
135
+ ```ts
136
+ const scoped = defineUseFetchAddon({
137
+ setup: (options: UseFetchAddonOptions<{ scope?: string }>) => {
138
+ options.scope ??= 'default'
139
+ // ...
140
+ },
141
+ key: options => toValue(options.scope),
142
+ })
143
+ ```
144
+
145
+ ::warning
146
+ Declare `setup` before `key`. TypeScript infers the custom options from the `setup` parameter annotation, and a `key` resolver written before a `setup` that returns an extension function is checked first and typed with empty options.
147
+ ::
148
+
149
+ ## Wrapping `then`, `catch` and `finally`
150
+
151
+ As an advanced escape hatch, the extension object may include `then`, `catch` or `finally` functions. These are not merged into the instance. Instead they wrap the corresponding method of the awaitable promise, receiving the original method as their first argument.
152
+
153
+ ::note
154
+ When several addons wrap the same method, the wrappers are composed in the order of the `addons` array: the first addon's wrapper wraps all the following ones, just as its middleware would.
155
+ ::
156
+
157
+ ## Type
158
+
159
+ ```ts [Signature]
160
+ function defineUseFetchAddon<Opts extends Record<string, any> = {}, Ext = {}> (addon: {
161
+ setup: (options: UseFetchAddonOptions<Opts>) => ((asyncData: AsyncDataAddonInstance) => Ext | void) | void
162
+ key?: (options: UseFetchAddonOptions<Opts>) => SerializableValue
163
+ }): UseFetchAddon<Opts, Ext>
164
+ ```
165
+
166
+ ::note
167
+ `middleware`, `onRequest`, `onRequestError`, `onResponse` and `onResponseError` are always normalized to arrays, so interceptors from the caller and from other addons are preserved.
168
+ ::
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/docs-nightly",
3
- "version": "5.0.0-29841017.b1cd49dc",
3
+ "version": "5.0.0-29841042.d5a56a2a",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/nuxt.git",