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 +4 -4
- package/dist/generators/shared/runtime/apiHelpers.d.ts +17 -0
- package/dist/generators/use-async-data/runtime/useApiAsyncData.d.ts +9 -22
- package/dist/generators/use-async-data/runtime/useApiAsyncData.js +17 -5
- package/dist/generators/use-async-data/runtime/useApiAsyncDataRaw.d.ts +7 -20
- package/dist/generators/use-async-data/runtime/useApiAsyncDataRaw.js +16 -4
- package/dist/generators/use-async-data/templates.js +7 -1
- package/dist/generators/use-fetch/runtime/useApiRequest.d.ts +5 -6
- package/package.json +1 -1
- package/src/cli/logo.ts +4 -4
- package/src/generators/shared/runtime/apiHelpers.ts +26 -0
- package/src/generators/use-async-data/runtime/useApiAsyncData.ts +32 -33
- package/src/generators/use-async-data/runtime/useApiAsyncDataRaw.ts +32 -33
- package/src/generators/use-async-data/templates.ts +8 -1
- package/src/generators/use-fetch/runtime/useApiRequest.ts +5 -6
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 = '
|
|
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
|
-
*
|
|
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
|
|
9
|
+
export type ApiAsyncDataOptions<T> = BaseApiRequestOptions<T> & Omit<UseFetchOptions<T>, 'transform' | 'pick' | 'watch'> & {
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
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 =
|
|
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(
|
|
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:
|
|
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
|
-
*
|
|
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
|
|
18
|
+
export type ApiAsyncDataRawOptions<T> = Omit<BaseApiRequestOptions<T>, 'onSuccess'> & Omit<UseFetchOptions<T>, 'transform' | 'pick' | 'onSuccess'> & {
|
|
16
19
|
/**
|
|
17
|
-
*
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
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
|
|
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
|
|
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
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 = '
|
|
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
|
-
*
|
|
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
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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 =
|
|
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>>>(
|
|
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:
|
|
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
|
-
*
|
|
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
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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 =
|
|
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>>>(
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|