nuxt-openapi-hyperfetch 0.1.6-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.js +17 -5
- package/dist/generators/use-async-data/runtime/useApiAsyncDataRaw.js +16 -4
- package/dist/generators/use-async-data/templates.js +7 -1
- 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 +19 -4
- package/src/generators/use-async-data/runtime/useApiAsyncDataRaw.ts +18 -3
- package/src/generators/use-async-data/templates.ts +8 -1
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
|
|
@@ -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
|
}
|
|
@@ -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
|
}
|
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
|
/**
|
|
@@ -63,6 +63,8 @@ export function useApiAsyncData<T>(
|
|
|
63
63
|
body,
|
|
64
64
|
headers = {},
|
|
65
65
|
params,
|
|
66
|
+
baseURL,
|
|
67
|
+
cacheKey,
|
|
66
68
|
transform,
|
|
67
69
|
pick,
|
|
68
70
|
onRequest,
|
|
@@ -79,7 +81,7 @@ export function useApiAsyncData<T>(
|
|
|
79
81
|
} = options || {};
|
|
80
82
|
|
|
81
83
|
// Resolve base URL once at setup time (not inside fetchFn to avoid warning on every request)
|
|
82
|
-
const resolvedBaseURL =
|
|
84
|
+
const resolvedBaseURL = baseURL || getGlobalBaseUrl();
|
|
83
85
|
if (!resolvedBaseURL) {
|
|
84
86
|
console.warn(
|
|
85
87
|
'[nuxt-openapi-hyperfetch] No baseURL configured. Set runtimeConfig.public.apiBaseUrl in nuxt.config.ts or pass baseURL in options.'
|
|
@@ -103,6 +105,19 @@ export function useApiAsyncData<T>(
|
|
|
103
105
|
: []),
|
|
104
106
|
];
|
|
105
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
|
+
|
|
106
121
|
// Fetch function for useAsyncData
|
|
107
122
|
const fetchFn = async () => {
|
|
108
123
|
// Get URL value for merging callbacks
|
|
@@ -201,13 +216,13 @@ export function useApiAsyncData<T>(
|
|
|
201
216
|
}
|
|
202
217
|
};
|
|
203
218
|
|
|
204
|
-
// Use Nuxt's useAsyncData
|
|
205
|
-
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, {
|
|
206
221
|
immediate,
|
|
207
222
|
lazy,
|
|
208
223
|
server,
|
|
209
224
|
dedupe,
|
|
210
|
-
watch:
|
|
225
|
+
watch: watchOption === false ? [] : watchSources,
|
|
211
226
|
});
|
|
212
227
|
|
|
213
228
|
return result;
|
|
@@ -78,6 +78,8 @@ export function useApiAsyncDataRaw<T>(
|
|
|
78
78
|
body,
|
|
79
79
|
headers = {},
|
|
80
80
|
params,
|
|
81
|
+
baseURL,
|
|
82
|
+
cacheKey,
|
|
81
83
|
transform,
|
|
82
84
|
pick,
|
|
83
85
|
onRequest,
|
|
@@ -93,7 +95,7 @@ export function useApiAsyncDataRaw<T>(
|
|
|
93
95
|
} = options || {};
|
|
94
96
|
|
|
95
97
|
// Resolve base URL once at setup time (not inside fetchFn to avoid warning on every request)
|
|
96
|
-
const resolvedBaseURL =
|
|
98
|
+
const resolvedBaseURL = baseURL || getGlobalBaseUrl();
|
|
97
99
|
if (!resolvedBaseURL) {
|
|
98
100
|
console.warn(
|
|
99
101
|
'[nuxt-openapi-hyperfetch] No baseURL configured. Set runtimeConfig.public.apiBaseUrl in nuxt.config.ts or pass baseURL in options.'
|
|
@@ -107,6 +109,19 @@ export function useApiAsyncDataRaw<T>(
|
|
|
107
109
|
...(params && typeof params === 'object' ? [() => params] : []),
|
|
108
110
|
];
|
|
109
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
|
+
|
|
110
125
|
// Fetch function for useAsyncData
|
|
111
126
|
const fetchFn = async (): Promise<RawResponse<T>> => {
|
|
112
127
|
// Get URL value for merging callbacks
|
|
@@ -217,8 +232,8 @@ export function useApiAsyncDataRaw<T>(
|
|
|
217
232
|
}
|
|
218
233
|
};
|
|
219
234
|
|
|
220
|
-
// Use Nuxt's useAsyncData
|
|
221
|
-
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, {
|
|
222
237
|
immediate,
|
|
223
238
|
lazy,
|
|
224
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
|
}
|