nuxt-openapi-hyperfetch 0.1.5-alpha.1 → 0.1.7-alpha.1

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.
package/dist/cli/logo.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import gradient from 'gradient-string';
2
2
  const NUXT_LOGO = `███╗ ██╗██╗ ██╗██╗ ██╗████████╗
3
3
  ████╗ ██║██║ ██║╚██╗██╔╝╚══██╔══╝
4
- ██╔██╗ ██║██║ ██║ ╚███╔╝ ██║
5
- ██║╚██╗██║██║ ██║ ██╔██╗ ██║
6
- ██║ ╚████║╚██████╔╝██╔╝ ██╗ ██║
4
+ ██╔██╗ ██║██║ ██║ ╚███╔╝ ██║
5
+ ██║╚██╗██║██║ ██║ ██╔██╗ ██║
6
+ ██║ ╚████║╚██████╔╝██╔╝ ██╗ ██║
7
7
  ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝`;
8
- const SUBTITLE = ' Swagger OpenAPI Generator v1.0';
8
+ const SUBTITLE = 'Nuxt OpenAPI Generator - useFetch, useAsyncData & Nuxt server';
9
9
  /**
10
10
  * Display the Nuxt logo with gradient colors
11
11
  * - Green gradient for Nuxt logo (official Nuxt color #00DC82)
@@ -119,6 +119,23 @@ export interface ApiRequestOptions<T = any> {
119
119
  * pick: ['person.name', 'person.email', 'status']
120
120
  */
121
121
  pick?: ReadonlyArray<string>;
122
+ /**
123
+ * Custom cache key for useAsyncData. If provided, used as-is instead of the auto-generated key.
124
+ * Useful for manual cache control or sharing cache between components.
125
+ */
126
+ cacheKey?: string;
127
+ /** Base URL prepended to every request URL. Overrides runtimeConfig.public.apiBaseUrl. */
128
+ baseURL?: string;
129
+ /** HTTP method (GET, POST, PUT, PATCH, DELETE, etc.) */
130
+ method?: string;
131
+ /** Request body */
132
+ body?: any;
133
+ /** Request headers */
134
+ headers?: Record<string, string> | HeadersInit;
135
+ /** URL query parameters */
136
+ query?: Record<string, any>;
137
+ /** Alias for query */
138
+ params?: Record<string, any>;
122
139
  }
123
140
  /**
124
141
  * Helper function to apply request modifications from onRequest interceptor
@@ -1,31 +1,18 @@
1
+ import type { UseFetchOptions } from '#app';
1
2
  import { type ApiRequestOptions as BaseApiRequestOptions } from '../../shared/runtime/apiHelpers.js';
2
3
  /**
3
- * Extended options specific to useAsyncData
4
+ * Options for useAsyncData API requests with lifecycle callbacks.
5
+ * Extends all native Nuxt useFetch options plus our custom callbacks, transform, and pick.
6
+ * Native options like baseURL, method, body, headers, query, lazy, server, immediate, dedupe, etc. are all available.
7
+ * watch: boolean (true = auto-watch reactive params, false = disable auto-refresh)
4
8
  */
5
- export interface ApiAsyncDataOptions<T> extends BaseApiRequestOptions<T> {
9
+ export type ApiAsyncDataOptions<T> = BaseApiRequestOptions<T> & Omit<UseFetchOptions<T>, 'transform' | 'pick' | 'watch'> & {
6
10
  /**
7
- * Whether to fetch data immediately on mount (default: true)
8
- */
9
- immediate?: boolean;
10
- /**
11
- * Lazy mode: don't block navigation (default: false)
12
- */
13
- lazy?: boolean;
14
- /**
15
- * Server-side rendering mode (default: true)
16
- */
17
- server?: boolean;
18
- /**
19
- * Deduplicate requests with the same key (default: 'cancel')
20
- */
21
- dedupe?: 'cancel' | 'defer';
22
- /**
23
- * Disable automatic refresh when reactive params change.
24
- * Set to false to prevent re-fetching when params/url refs update.
25
- * @default true
11
+ * Enable automatic refresh when reactive params/url change (default: true).
12
+ * Set to false to disable auto-refresh entirely.
26
13
  */
27
14
  watch?: boolean;
28
- }
15
+ };
29
16
  /**
30
17
  * Generic wrapper for API calls using Nuxt's useAsyncData
31
18
  * Supports:
@@ -9,9 +9,9 @@ import { getGlobalHeaders, getGlobalBaseUrl, applyPick, mergeCallbacks, } from '
9
9
  * - Watch pattern for reactive parameters
10
10
  */
11
11
  export function useApiAsyncData(key, url, options) {
12
- const { method = 'GET', body, headers = {}, params, transform, pick, onRequest, onSuccess, onError, onFinish, skipGlobalCallbacks, immediate = true, lazy = false, server = true, dedupe = 'cancel', watch: watchOption = true, ...restOptions } = options || {};
12
+ const { method = 'GET', body, headers = {}, params, baseURL, cacheKey, transform, pick, onRequest, onSuccess, onError, onFinish, skipGlobalCallbacks, immediate = true, lazy = false, server = true, dedupe = 'cancel', watch: watchOption = true, ...restOptions } = options || {};
13
13
  // Resolve base URL once at setup time (not inside fetchFn to avoid warning on every request)
14
- const resolvedBaseURL = restOptions.baseURL || getGlobalBaseUrl();
14
+ const resolvedBaseURL = baseURL || getGlobalBaseUrl();
15
15
  if (!resolvedBaseURL) {
16
16
  console.warn('[nuxt-openapi-hyperfetch] No baseURL configured. Set runtimeConfig.public.apiBaseUrl in nuxt.config.ts or pass baseURL in options.');
17
17
  }
@@ -30,6 +30,18 @@ export function useApiAsyncData(key, url, options) {
30
30
  : []
31
31
  : []),
32
32
  ];
33
+ // Build a reactive cache key: composableName + resolved URL + serialized query params
34
+ // This ensures distinct params produce distinct keys — preventing cache collisions
35
+ const computedKey = () => {
36
+ if (cacheKey)
37
+ return cacheKey;
38
+ const resolvedUrl = typeof url === 'function' ? url() : url;
39
+ const resolvedParams = toValue(params);
40
+ const paramsSuffix = resolvedParams && typeof resolvedParams === 'object' && Object.keys(resolvedParams).length > 0
41
+ ? '-' + JSON.stringify(resolvedParams)
42
+ : '';
43
+ return `${key}-${resolvedUrl}${paramsSuffix}`;
44
+ };
33
45
  // Fetch function for useAsyncData
34
46
  const fetchFn = async () => {
35
47
  // Get URL value for merging callbacks
@@ -116,13 +128,13 @@ export function useApiAsyncData(key, url, options) {
116
128
  }
117
129
  }
118
130
  };
119
- // Use Nuxt's useAsyncData
120
- const result = useAsyncData(key, fetchFn, {
131
+ // Use Nuxt's useAsyncData with a computed key for proper cache isolation per params
132
+ const result = useAsyncData(computedKey, fetchFn, {
121
133
  immediate,
122
134
  lazy,
123
135
  server,
124
136
  dedupe,
125
- watch: watchSources.length > 0 ? watchSources : undefined,
137
+ watch: watchOption === false ? [] : watchSources,
126
138
  });
127
139
  return result;
128
140
  }
@@ -1,3 +1,4 @@
1
+ import type { UseFetchOptions } from '#app';
1
2
  import { type ApiRequestOptions as BaseApiRequestOptions } from '../../shared/runtime/apiHelpers.js';
2
3
  /**
3
4
  * Response structure for Raw version
@@ -10,11 +11,13 @@ export interface RawResponse<T> {
10
11
  statusText: string;
11
12
  }
12
13
  /**
13
- * Extended options specific to useAsyncData Raw version
14
+ * Options for useAsyncData Raw API requests.
15
+ * Extends all native Nuxt useFetch options plus our custom callbacks, transform, and pick.
16
+ * onSuccess receives data AND the full response (headers, status, statusText).
14
17
  */
15
- export interface ApiAsyncDataRawOptions<T> extends Omit<BaseApiRequestOptions<T>, 'onSuccess'> {
18
+ export type ApiAsyncDataRawOptions<T> = Omit<BaseApiRequestOptions<T>, 'onSuccess'> & Omit<UseFetchOptions<T>, 'transform' | 'pick' | 'onSuccess'> & {
16
19
  /**
17
- * Success callback that receives both data and full response
20
+ * Called when the request succeeds — receives both data and the full response object.
18
21
  */
19
22
  onSuccess?: (data: T, response: {
20
23
  headers: Headers;
@@ -22,23 +25,7 @@ export interface ApiAsyncDataRawOptions<T> extends Omit<BaseApiRequestOptions<T>
22
25
  statusText: string;
23
26
  url: string;
24
27
  }) => void | Promise<void>;
25
- /**
26
- * Whether to fetch data immediately on mount (default: true)
27
- */
28
- immediate?: boolean;
29
- /**
30
- * Lazy mode: don't block navigation (default: false)
31
- */
32
- lazy?: boolean;
33
- /**
34
- * Server-side rendering mode (default: true)
35
- */
36
- server?: boolean;
37
- /**
38
- * Deduplicate requests with the same key (default: 'cancel')
39
- */
40
- dedupe?: 'cancel' | 'defer';
41
- }
28
+ };
42
29
  /**
43
30
  * Generic wrapper for API calls using Nuxt's useAsyncData - RAW VERSION
44
31
  * Returns full response with headers and status information
@@ -12,9 +12,9 @@ import { getGlobalHeaders, getGlobalBaseUrl, applyPick, mergeCallbacks, } from '
12
12
  * - Watch pattern for reactive parameters
13
13
  */
14
14
  export function useApiAsyncDataRaw(key, url, options) {
15
- const { method = 'GET', body, headers = {}, params, transform, pick, onRequest, onSuccess, onError, onFinish, skipGlobalCallbacks, immediate = true, lazy = false, server = true, dedupe = 'cancel', ...restOptions } = options || {};
15
+ const { method = 'GET', body, headers = {}, params, baseURL, cacheKey, transform, pick, onRequest, onSuccess, onError, onFinish, skipGlobalCallbacks, immediate = true, lazy = false, server = true, dedupe = 'cancel', ...restOptions } = options || {};
16
16
  // Resolve base URL once at setup time (not inside fetchFn to avoid warning on every request)
17
- const resolvedBaseURL = restOptions.baseURL || getGlobalBaseUrl();
17
+ const resolvedBaseURL = baseURL || getGlobalBaseUrl();
18
18
  if (!resolvedBaseURL) {
19
19
  console.warn('[nuxt-openapi-hyperfetch] No baseURL configured. Set runtimeConfig.public.apiBaseUrl in nuxt.config.ts or pass baseURL in options.');
20
20
  }
@@ -24,6 +24,18 @@ export function useApiAsyncDataRaw(key, url, options) {
24
24
  ...(body && typeof body === 'object' ? [() => body] : []),
25
25
  ...(params && typeof params === 'object' ? [() => params] : []),
26
26
  ];
27
+ // Build a reactive cache key: composableName + resolved URL + serialized query params
28
+ // This ensures distinct params produce distinct keys — preventing cache collisions
29
+ const computedKey = () => {
30
+ if (cacheKey)
31
+ return cacheKey;
32
+ const resolvedUrl = typeof url === 'function' ? url() : url;
33
+ const resolvedParams = toValue(params);
34
+ const paramsSuffix = resolvedParams && typeof resolvedParams === 'object' && Object.keys(resolvedParams).length > 0
35
+ ? '-' + JSON.stringify(resolvedParams)
36
+ : '';
37
+ return `${key}-${resolvedUrl}${paramsSuffix}`;
38
+ };
27
39
  // Fetch function for useAsyncData
28
40
  const fetchFn = async () => {
29
41
  // Get URL value for merging callbacks
@@ -120,8 +132,8 @@ export function useApiAsyncDataRaw(key, url, options) {
120
132
  }
121
133
  }
122
134
  };
123
- // Use Nuxt's useAsyncData
124
- const result = useAsyncData(key, fetchFn, {
135
+ // Use Nuxt's useAsyncData with a computed key for proper cache isolation per params
136
+ const result = useAsyncData(computedKey, fetchFn, {
125
137
  immediate,
126
138
  lazy,
127
139
  server,
@@ -117,7 +117,13 @@ function generateFunctionBody(method, isRaw, generateOptions) {
117
117
  // Choose the correct wrapper function
118
118
  const wrapperFunction = isRaw ? 'useApiAsyncDataRaw' : 'useApiAsyncData';
119
119
  const pInit = hasParams ? `\n const p = shallowRef(params)` : '';
120
- return `${description}export const ${composableName} = (${args}) => {${pInit}
120
+ const argsExtraction = hasParams
121
+ ? ` const _hasKey = typeof args[0] === 'string'\n const params = _hasKey ? args[1] : args[0]\n const options = _hasKey ? { cacheKey: args[0], ...args[2] } : args[1]`
122
+ : ` const _hasKey = typeof args[0] === 'string'\n const options = _hasKey ? { cacheKey: args[0], ...args[1] } : args[0]`;
123
+ return `${description}export function ${composableName}(key: string, ${args})
124
+ export function ${composableName}(${args})
125
+ export function ${composableName}(...args: any[]) {
126
+ ${argsExtraction}${pInit}
121
127
  return ${wrapperFunction}${responseTypeGeneric}(${key}, ${url}, ${fetchOptions})
122
128
  }`;
123
129
  }
@@ -1,12 +1,11 @@
1
+ import type { UseFetchOptions } from '#app';
1
2
  import { type ApiRequestOptions as BaseApiRequestOptions } from '../../shared/runtime/apiHelpers.js';
2
3
  /**
3
- * Options for useFetch API requests with lifecycle callbacks
4
- * Extends base options with useFetch-specific options
4
+ * Options for useFetch API requests with lifecycle callbacks.
5
+ * Extends all native Nuxt useFetch options plus our custom callbacks, transform, and pick.
6
+ * Native options like baseURL, method, body, headers, query, lazy, server, immediate, etc. are all available.
5
7
  */
6
- export interface ApiRequestOptions<T = any> extends BaseApiRequestOptions<T> {
7
- /** All standard useFetch options */
8
- [key: string]: any;
9
- }
8
+ export type ApiRequestOptions<T = any> = BaseApiRequestOptions<T> & Omit<UseFetchOptions<T>, 'transform' | 'pick'>;
10
9
  /**
11
10
  * Enhanced useFetch wrapper with lifecycle callbacks and request interception
12
11
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-openapi-hyperfetch",
3
- "version": "0.1.5-alpha.1",
3
+ "version": "0.1.7-alpha.1",
4
4
  "description": "Nuxt useFetch, useAsyncData and Nuxt server OpenAPI generator",
5
5
  "type": "module",
6
6
  "author": "",
package/src/cli/logo.ts CHANGED
@@ -2,12 +2,12 @@ import gradient from 'gradient-string';
2
2
 
3
3
  const NUXT_LOGO = `███╗ ██╗██╗ ██╗██╗ ██╗████████╗
4
4
  ████╗ ██║██║ ██║╚██╗██╔╝╚══██╔══╝
5
- ██╔██╗ ██║██║ ██║ ╚███╔╝ ██║
6
- ██║╚██╗██║██║ ██║ ██╔██╗ ██║
7
- ██║ ╚████║╚██████╔╝██╔╝ ██╗ ██║
5
+ ██╔██╗ ██║██║ ██║ ╚███╔╝ ██║
6
+ ██║╚██╗██║██║ ██║ ██╔██╗ ██║
7
+ ██║ ╚████║╚██████╔╝██╔╝ ██╗ ██║
8
8
  ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝`;
9
9
 
10
- const SUBTITLE = ' Swagger OpenAPI Generator v1.0';
10
+ const SUBTITLE = 'Nuxt OpenAPI Generator - useFetch, useAsyncData & Nuxt server';
11
11
 
12
12
  /**
13
13
  * Display the Nuxt logo with gradient colors
@@ -148,6 +148,32 @@ export interface ApiRequestOptions<T = any> {
148
148
  * pick: ['person.name', 'person.email', 'status']
149
149
  */
150
150
  pick?: ReadonlyArray<string>;
151
+
152
+ /**
153
+ * Custom cache key for useAsyncData. If provided, used as-is instead of the auto-generated key.
154
+ * Useful for manual cache control or sharing cache between components.
155
+ */
156
+ cacheKey?: string;
157
+
158
+ // --- Common fetch options (available in all composables) ---
159
+
160
+ /** Base URL prepended to every request URL. Overrides runtimeConfig.public.apiBaseUrl. */
161
+ baseURL?: string;
162
+
163
+ /** HTTP method (GET, POST, PUT, PATCH, DELETE, etc.) */
164
+ method?: string;
165
+
166
+ /** Request body */
167
+ body?: any;
168
+
169
+ /** Request headers */
170
+ headers?: Record<string, string> | HeadersInit;
171
+
172
+ /** URL query parameters */
173
+ query?: Record<string, any>;
174
+
175
+ /** Alias for query */
176
+ params?: Record<string, any>;
151
177
  }
152
178
 
153
179
  /**
@@ -4,6 +4,7 @@
4
4
  * It requires Nuxt 3 to be installed in the target project
5
5
  */
6
6
  import { watch } from 'vue';
7
+ import type { UseFetchOptions } from '#app';
7
8
  import {
8
9
  getGlobalHeaders,
9
10
  getGlobalBaseUrl,
@@ -29,36 +30,19 @@ type MaybeTransformed<T, Options> = Options extends { transform: (...args: any)
29
30
  : T;
30
31
 
31
32
  /**
32
- * Extended options specific to useAsyncData
33
+ * Options for useAsyncData API requests with lifecycle callbacks.
34
+ * Extends all native Nuxt useFetch options plus our custom callbacks, transform, and pick.
35
+ * Native options like baseURL, method, body, headers, query, lazy, server, immediate, dedupe, etc. are all available.
36
+ * watch: boolean (true = auto-watch reactive params, false = disable auto-refresh)
33
37
  */
34
- export interface ApiAsyncDataOptions<T> extends BaseApiRequestOptions<T> {
35
- /**
36
- * Whether to fetch data immediately on mount (default: true)
37
- */
38
- immediate?: boolean;
39
-
40
- /**
41
- * Lazy mode: don't block navigation (default: false)
42
- */
43
- lazy?: boolean;
44
-
45
- /**
46
- * Server-side rendering mode (default: true)
47
- */
48
- server?: boolean;
49
-
50
- /**
51
- * Deduplicate requests with the same key (default: 'cancel')
52
- */
53
- dedupe?: 'cancel' | 'defer';
54
-
55
- /**
56
- * Disable automatic refresh when reactive params change.
57
- * Set to false to prevent re-fetching when params/url refs update.
58
- * @default true
59
- */
60
- watch?: boolean;
61
- }
38
+ export type ApiAsyncDataOptions<T> = BaseApiRequestOptions<T> &
39
+ Omit<UseFetchOptions<T>, 'transform' | 'pick' | 'watch'> & {
40
+ /**
41
+ * Enable automatic refresh when reactive params/url change (default: true).
42
+ * Set to false to disable auto-refresh entirely.
43
+ */
44
+ watch?: boolean;
45
+ };
62
46
 
63
47
  /**
64
48
  * Generic wrapper for API calls using Nuxt's useAsyncData
@@ -79,6 +63,8 @@ export function useApiAsyncData<T>(
79
63
  body,
80
64
  headers = {},
81
65
  params,
66
+ baseURL,
67
+ cacheKey,
82
68
  transform,
83
69
  pick,
84
70
  onRequest,
@@ -95,7 +81,7 @@ export function useApiAsyncData<T>(
95
81
  } = options || {};
96
82
 
97
83
  // Resolve base URL once at setup time (not inside fetchFn to avoid warning on every request)
98
- const resolvedBaseURL = restOptions.baseURL || getGlobalBaseUrl();
84
+ const resolvedBaseURL = baseURL || getGlobalBaseUrl();
99
85
  if (!resolvedBaseURL) {
100
86
  console.warn(
101
87
  '[nuxt-openapi-hyperfetch] No baseURL configured. Set runtimeConfig.public.apiBaseUrl in nuxt.config.ts or pass baseURL in options.'
@@ -119,6 +105,19 @@ export function useApiAsyncData<T>(
119
105
  : []),
120
106
  ];
121
107
 
108
+ // Build a reactive cache key: composableName + resolved URL + serialized query params
109
+ // This ensures distinct params produce distinct keys — preventing cache collisions
110
+ const computedKey = () => {
111
+ if (cacheKey) return cacheKey;
112
+ const resolvedUrl = typeof url === 'function' ? url() : url;
113
+ const resolvedParams = toValue(params);
114
+ const paramsSuffix =
115
+ resolvedParams && typeof resolvedParams === 'object' && Object.keys(resolvedParams).length > 0
116
+ ? '-' + JSON.stringify(resolvedParams)
117
+ : '';
118
+ return `${key}-${resolvedUrl}${paramsSuffix}`;
119
+ };
120
+
122
121
  // Fetch function for useAsyncData
123
122
  const fetchFn = async () => {
124
123
  // Get URL value for merging callbacks
@@ -217,13 +216,13 @@ export function useApiAsyncData<T>(
217
216
  }
218
217
  };
219
218
 
220
- // Use Nuxt's useAsyncData
221
- const result = useAsyncData<MaybeTransformed<T, ApiAsyncDataOptions<T>>>(key, fetchFn, {
219
+ // Use Nuxt's useAsyncData with a computed key for proper cache isolation per params
220
+ const result = useAsyncData<MaybeTransformed<T, ApiAsyncDataOptions<T>>>(computedKey, fetchFn, {
222
221
  immediate,
223
222
  lazy,
224
223
  server,
225
224
  dedupe,
226
- watch: watchSources.length > 0 ? watchSources : undefined,
225
+ watch: watchOption === false ? [] : watchSources,
227
226
  });
228
227
 
229
228
  return result;
@@ -6,6 +6,7 @@
6
6
  * RAW VERSION: Returns full response including headers, status, and statusText
7
7
  */
8
8
  import { watch } from 'vue';
9
+ import type { UseFetchOptions } from '#app';
9
10
  import {
10
11
  getGlobalHeaders,
11
12
  getGlobalBaseUrl,
@@ -40,37 +41,20 @@ type MaybeTransformedRaw<T, Options> = Options extends { transform: (...args: an
40
41
  : RawResponse<T>;
41
42
 
42
43
  /**
43
- * Extended options specific to useAsyncData Raw version
44
+ * Options for useAsyncData Raw API requests.
45
+ * Extends all native Nuxt useFetch options plus our custom callbacks, transform, and pick.
46
+ * onSuccess receives data AND the full response (headers, status, statusText).
44
47
  */
45
- export interface ApiAsyncDataRawOptions<T> extends Omit<BaseApiRequestOptions<T>, 'onSuccess'> {
46
- /**
47
- * Success callback that receives both data and full response
48
- */
49
- onSuccess?: (
50
- data: T,
51
- response: { headers: Headers; status: number; statusText: string; url: string }
52
- ) => void | Promise<void>;
53
-
54
- /**
55
- * Whether to fetch data immediately on mount (default: true)
56
- */
57
- immediate?: boolean;
58
-
59
- /**
60
- * Lazy mode: don't block navigation (default: false)
61
- */
62
- lazy?: boolean;
63
-
64
- /**
65
- * Server-side rendering mode (default: true)
66
- */
67
- server?: boolean;
68
-
69
- /**
70
- * Deduplicate requests with the same key (default: 'cancel')
71
- */
72
- dedupe?: 'cancel' | 'defer';
73
- }
48
+ export type ApiAsyncDataRawOptions<T> = Omit<BaseApiRequestOptions<T>, 'onSuccess'> &
49
+ Omit<UseFetchOptions<T>, 'transform' | 'pick' | 'onSuccess'> & {
50
+ /**
51
+ * Called when the request succeeds — receives both data and the full response object.
52
+ */
53
+ onSuccess?: (
54
+ data: T,
55
+ response: { headers: Headers; status: number; statusText: string; url: string }
56
+ ) => void | Promise<void>;
57
+ };
74
58
 
75
59
  /**
76
60
  * Generic wrapper for API calls using Nuxt's useAsyncData - RAW VERSION
@@ -94,6 +78,8 @@ export function useApiAsyncDataRaw<T>(
94
78
  body,
95
79
  headers = {},
96
80
  params,
81
+ baseURL,
82
+ cacheKey,
97
83
  transform,
98
84
  pick,
99
85
  onRequest,
@@ -109,7 +95,7 @@ export function useApiAsyncDataRaw<T>(
109
95
  } = options || {};
110
96
 
111
97
  // Resolve base URL once at setup time (not inside fetchFn to avoid warning on every request)
112
- const resolvedBaseURL = restOptions.baseURL || getGlobalBaseUrl();
98
+ const resolvedBaseURL = baseURL || getGlobalBaseUrl();
113
99
  if (!resolvedBaseURL) {
114
100
  console.warn(
115
101
  '[nuxt-openapi-hyperfetch] No baseURL configured. Set runtimeConfig.public.apiBaseUrl in nuxt.config.ts or pass baseURL in options.'
@@ -123,6 +109,19 @@ export function useApiAsyncDataRaw<T>(
123
109
  ...(params && typeof params === 'object' ? [() => params] : []),
124
110
  ];
125
111
 
112
+ // Build a reactive cache key: composableName + resolved URL + serialized query params
113
+ // This ensures distinct params produce distinct keys — preventing cache collisions
114
+ const computedKey = () => {
115
+ if (cacheKey) return cacheKey;
116
+ const resolvedUrl = typeof url === 'function' ? url() : url;
117
+ const resolvedParams = toValue(params);
118
+ const paramsSuffix =
119
+ resolvedParams && typeof resolvedParams === 'object' && Object.keys(resolvedParams).length > 0
120
+ ? '-' + JSON.stringify(resolvedParams)
121
+ : '';
122
+ return `${key}-${resolvedUrl}${paramsSuffix}`;
123
+ };
124
+
126
125
  // Fetch function for useAsyncData
127
126
  const fetchFn = async (): Promise<RawResponse<T>> => {
128
127
  // Get URL value for merging callbacks
@@ -233,8 +232,8 @@ export function useApiAsyncDataRaw<T>(
233
232
  }
234
233
  };
235
234
 
236
- // Use Nuxt's useAsyncData
237
- const result = useAsyncData<MaybeTransformedRaw<T, ApiAsyncDataRawOptions<T>>>(key, fetchFn, {
235
+ // Use Nuxt's useAsyncData with a computed key for proper cache isolation per params
236
+ const result = useAsyncData<MaybeTransformedRaw<T, ApiAsyncDataRawOptions<T>>>(computedKey, fetchFn, {
238
237
  immediate,
239
238
  lazy,
240
239
  server,
@@ -165,7 +165,14 @@ function generateFunctionBody(
165
165
 
166
166
  const pInit = hasParams ? `\n const p = shallowRef(params)` : '';
167
167
 
168
- return `${description}export const ${composableName} = (${args}) => {${pInit}
168
+ const argsExtraction = hasParams
169
+ ? ` const _hasKey = typeof args[0] === 'string'\n const params = _hasKey ? args[1] : args[0]\n const options = _hasKey ? { cacheKey: args[0], ...args[2] } : args[1]`
170
+ : ` const _hasKey = typeof args[0] === 'string'\n const options = _hasKey ? { cacheKey: args[0], ...args[1] } : args[0]`;
171
+
172
+ return `${description}export function ${composableName}(key: string, ${args})
173
+ export function ${composableName}(${args})
174
+ export function ${composableName}(...args: any[]) {
175
+ ${argsExtraction}${pInit}
169
176
  return ${wrapperFunction}${responseTypeGeneric}(${key}, ${url}, ${fetchOptions})
170
177
  }`;
171
178
  }
@@ -4,6 +4,7 @@
4
4
  * It requires Nuxt 3 to be installed in the target project
5
5
  */
6
6
  import { watch } from 'vue';
7
+ import type { UseFetchOptions } from '#app';
7
8
  import {
8
9
  getGlobalHeaders,
9
10
  getGlobalBaseUrl,
@@ -29,13 +30,11 @@ type MaybeTransformed<T, Options> = Options extends { transform: (...args: any)
29
30
  : T;
30
31
 
31
32
  /**
32
- * Options for useFetch API requests with lifecycle callbacks
33
- * Extends base options with useFetch-specific options
33
+ * Options for useFetch API requests with lifecycle callbacks.
34
+ * Extends all native Nuxt useFetch options plus our custom callbacks, transform, and pick.
35
+ * Native options like baseURL, method, body, headers, query, lazy, server, immediate, etc. are all available.
34
36
  */
35
- export interface ApiRequestOptions<T = any> extends BaseApiRequestOptions<T> {
36
- /** All standard useFetch options */
37
- [key: string]: any;
38
- }
37
+ export type ApiRequestOptions<T = any> = BaseApiRequestOptions<T> & Omit<UseFetchOptions<T>, 'transform' | 'pick'>;
39
38
 
40
39
  /**
41
40
  * Enhanced useFetch wrapper with lifecycle callbacks and request interception