nuxt-openapi-hyperfetch 0.1.0-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/.editorconfig +26 -0
- package/.prettierignore +17 -0
- package/.prettierrc.json +12 -0
- package/CONTRIBUTING.md +292 -0
- package/INSTRUCTIONS.md +327 -0
- package/LICENSE +202 -0
- package/README.md +202 -0
- package/dist/cli/config.d.ts +57 -0
- package/dist/cli/config.js +85 -0
- package/dist/cli/logger.d.ts +44 -0
- package/dist/cli/logger.js +58 -0
- package/dist/cli/logo.d.ts +6 -0
- package/dist/cli/logo.js +21 -0
- package/dist/cli/messages.d.ts +65 -0
- package/dist/cli/messages.js +86 -0
- package/dist/cli/prompts.d.ts +30 -0
- package/dist/cli/prompts.js +118 -0
- package/dist/cli/types.d.ts +43 -0
- package/dist/cli/types.js +4 -0
- package/dist/cli/utils.d.ts +26 -0
- package/dist/cli/utils.js +45 -0
- package/dist/generate.d.ts +6 -0
- package/dist/generate.js +48 -0
- package/dist/generators/nuxt-server/bff-templates.d.ts +25 -0
- package/dist/generators/nuxt-server/bff-templates.js +737 -0
- package/dist/generators/nuxt-server/generator.d.ts +7 -0
- package/dist/generators/nuxt-server/generator.js +206 -0
- package/dist/generators/nuxt-server/parser.d.ts +5 -0
- package/dist/generators/nuxt-server/parser.js +5 -0
- package/dist/generators/nuxt-server/templates.d.ts +35 -0
- package/dist/generators/nuxt-server/templates.js +412 -0
- package/dist/generators/nuxt-server/types.d.ts +5 -0
- package/dist/generators/nuxt-server/types.js +5 -0
- package/dist/generators/shared/parsers/heyapi-parser.d.ts +11 -0
- package/dist/generators/shared/parsers/heyapi-parser.js +248 -0
- package/dist/generators/shared/parsers/official-parser.d.ts +5 -0
- package/dist/generators/shared/parsers/official-parser.js +5 -0
- package/dist/generators/shared/runtime/apiHelpers.d.ts +183 -0
- package/dist/generators/shared/runtime/apiHelpers.js +268 -0
- package/dist/generators/shared/templates/api-callbacks-plugin.d.ts +178 -0
- package/dist/generators/shared/templates/api-callbacks-plugin.js +338 -0
- package/dist/generators/shared/types.d.ts +25 -0
- package/dist/generators/shared/types.js +4 -0
- package/dist/generators/tanstack-query/generator.d.ts +5 -0
- package/dist/generators/tanstack-query/generator.js +11 -0
- package/dist/generators/use-async-data/generator.d.ts +5 -0
- package/dist/generators/use-async-data/generator.js +156 -0
- package/dist/generators/use-async-data/parser.d.ts +5 -0
- package/dist/generators/use-async-data/parser.js +5 -0
- package/dist/generators/use-async-data/runtime/useApiAsyncData.d.ts +38 -0
- package/dist/generators/use-async-data/runtime/useApiAsyncData.js +122 -0
- package/dist/generators/use-async-data/runtime/useApiAsyncDataRaw.d.ts +54 -0
- package/dist/generators/use-async-data/runtime/useApiAsyncDataRaw.js +126 -0
- package/dist/generators/use-async-data/templates.d.ts +20 -0
- package/dist/generators/use-async-data/templates.js +191 -0
- package/dist/generators/use-async-data/types.d.ts +4 -0
- package/dist/generators/use-async-data/types.js +4 -0
- package/dist/generators/use-fetch/generator.d.ts +5 -0
- package/dist/generators/use-fetch/generator.js +131 -0
- package/dist/generators/use-fetch/parser.d.ts +9 -0
- package/dist/generators/use-fetch/parser.js +282 -0
- package/dist/generators/use-fetch/runtime/useApiRequest.d.ts +46 -0
- package/dist/generators/use-fetch/runtime/useApiRequest.js +158 -0
- package/dist/generators/use-fetch/templates.d.ts +16 -0
- package/dist/generators/use-fetch/templates.js +169 -0
- package/dist/generators/use-fetch/types.d.ts +5 -0
- package/dist/generators/use-fetch/types.js +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +213 -0
- package/docs/API-REFERENCE.md +887 -0
- package/docs/ARCHITECTURE.md +649 -0
- package/docs/DEVELOPMENT.md +918 -0
- package/docs/QUICK-START.md +323 -0
- package/docs/README.md +155 -0
- package/docs/TROUBLESHOOTING.md +881 -0
- package/eslint.config.js +72 -0
- package/package.json +65 -0
- package/src/cli/config.ts +140 -0
- package/src/cli/logger.ts +66 -0
- package/src/cli/logo.ts +25 -0
- package/src/cli/messages.ts +97 -0
- package/src/cli/prompts.ts +143 -0
- package/src/cli/types.ts +50 -0
- package/src/cli/utils.ts +49 -0
- package/src/generate.ts +57 -0
- package/src/generators/nuxt-server/bff-templates.ts +754 -0
- package/src/generators/nuxt-server/generator.ts +270 -0
- package/src/generators/nuxt-server/parser.ts +5 -0
- package/src/generators/nuxt-server/templates.ts +483 -0
- package/src/generators/nuxt-server/types.ts +5 -0
- package/src/generators/shared/parsers/heyapi-parser.ts +307 -0
- package/src/generators/shared/parsers/official-parser.ts +5 -0
- package/src/generators/shared/runtime/apiHelpers.ts +466 -0
- package/src/generators/shared/templates/api-callbacks-plugin.ts +352 -0
- package/src/generators/shared/types.ts +27 -0
- package/src/generators/tanstack-query/generator.ts +11 -0
- package/src/generators/use-async-data/generator.ts +204 -0
- package/src/generators/use-async-data/parser.ts +5 -0
- package/src/generators/use-async-data/runtime/useApiAsyncData.ts +220 -0
- package/src/generators/use-async-data/runtime/useApiAsyncDataRaw.ts +236 -0
- package/src/generators/use-async-data/templates.ts +250 -0
- package/src/generators/use-async-data/types.ts +4 -0
- package/src/generators/use-fetch/generator.ts +169 -0
- package/src/generators/use-fetch/parser.ts +341 -0
- package/src/generators/use-fetch/runtime/useApiRequest.ts +223 -0
- package/src/generators/use-fetch/templates.ts +214 -0
- package/src/generators/use-fetch/types.ts +5 -0
- package/src/index.ts +265 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ApiClassInfo } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Get Hey API generated files from the output directory.
|
|
4
|
+
* Returns the sdk.gen.ts path — the single entry point for all operations.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getApiFiles(inputDir: string): string[];
|
|
7
|
+
/**
|
|
8
|
+
* Parse Hey API generated files and return all operations as ApiClassInfo.
|
|
9
|
+
* Reads both sdk.gen.ts (for HTTP method + description) and types.gen.ts (for param/response types).
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseApiFile(sdkFilePath: string): ApiClassInfo;
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { Project, SyntaxKind } from 'ts-morph';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { pascalCase } from 'change-case';
|
|
5
|
+
import { p } from '../../../cli/logger.js';
|
|
6
|
+
/**
|
|
7
|
+
* Get Hey API generated files from the output directory.
|
|
8
|
+
* Returns the sdk.gen.ts path — the single entry point for all operations.
|
|
9
|
+
*/
|
|
10
|
+
export function getApiFiles(inputDir) {
|
|
11
|
+
const sdkFile = path.join(inputDir, 'sdk.gen.ts');
|
|
12
|
+
if (!existsSync(sdkFile)) {
|
|
13
|
+
throw new Error(`Hey API output not found: ${sdkFile}\nMake sure to run @hey-api/openapi-ts before generating composables.`);
|
|
14
|
+
}
|
|
15
|
+
return [sdkFile];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse Hey API generated files and return all operations as ApiClassInfo.
|
|
19
|
+
* Reads both sdk.gen.ts (for HTTP method + description) and types.gen.ts (for param/response types).
|
|
20
|
+
*/
|
|
21
|
+
export function parseApiFile(sdkFilePath) {
|
|
22
|
+
const inputDir = path.dirname(sdkFilePath);
|
|
23
|
+
const typesFilePath = path.join(inputDir, 'types.gen.ts');
|
|
24
|
+
if (!existsSync(typesFilePath)) {
|
|
25
|
+
throw new Error(`types.gen.ts not found in ${inputDir}`);
|
|
26
|
+
}
|
|
27
|
+
// Parse types.gen.ts with ts-morph to read type declarations
|
|
28
|
+
const project = new Project({ skipAddingFilesFromTsConfig: true });
|
|
29
|
+
const typesFile = project.addSourceFileAtPath(typesFilePath);
|
|
30
|
+
// Build operation info map from sdk.gen.ts using text parsing
|
|
31
|
+
const sdkText = readFileSync(sdkFilePath, 'utf-8');
|
|
32
|
+
const opMap = buildOperationMap(sdkText);
|
|
33
|
+
const methodInfos = [];
|
|
34
|
+
// Iterate over all *Data type aliases — each represents one API operation
|
|
35
|
+
for (const typeAlias of typesFile.getTypeAliases()) {
|
|
36
|
+
const name = typeAlias.getName();
|
|
37
|
+
// Skip non-operation types (ClientOptions, etc.)
|
|
38
|
+
if (!name.endsWith('Data') || name === 'ClientOptions') {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const baseName = name.slice(0, -4); // 'AddPetData' → 'AddPet'
|
|
42
|
+
const opName = baseName.charAt(0).toLowerCase() + baseName.slice(1); // 'addPet'
|
|
43
|
+
try {
|
|
44
|
+
const methodInfo = extractMethodInfo(typeAlias, typesFile, baseName, opName, opMap);
|
|
45
|
+
if (methodInfo) {
|
|
46
|
+
methodInfos.push(methodInfo);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
p.log.warn(`Could not parse Hey API operation "${opName}": ${String(error)}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return { className: 'Api', methods: methodInfos };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build a map of operation name → SdkOpInfo by text-parsing sdk.gen.ts.
|
|
57
|
+
* Extracts HTTP method, JSDoc description, and Content-Type header.
|
|
58
|
+
*/
|
|
59
|
+
function buildOperationMap(sdkText) {
|
|
60
|
+
const map = new Map();
|
|
61
|
+
const lines = sdkText.split('\n');
|
|
62
|
+
let jsDocLines = [];
|
|
63
|
+
let inJsDoc = false;
|
|
64
|
+
let pendingDescription;
|
|
65
|
+
for (let i = 0; i < lines.length; i++) {
|
|
66
|
+
const line = lines[i];
|
|
67
|
+
const trimmed = line.trim();
|
|
68
|
+
if (trimmed === '/**') {
|
|
69
|
+
inJsDoc = true;
|
|
70
|
+
jsDocLines = [line];
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (inJsDoc) {
|
|
74
|
+
jsDocLines.push(line);
|
|
75
|
+
if (trimmed === '*/') {
|
|
76
|
+
inJsDoc = false;
|
|
77
|
+
pendingDescription = parseJsDocDescription(jsDocLines.join('\n'));
|
|
78
|
+
}
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
// Match: export const funcName =
|
|
82
|
+
const funcMatch = line.match(/^export const (\w+) =/);
|
|
83
|
+
if (funcMatch) {
|
|
84
|
+
const funcName = funcMatch[1];
|
|
85
|
+
// Scan ahead a few lines to find the HTTP method call
|
|
86
|
+
const snippet = lines.slice(i, Math.min(i + 8, lines.length)).join('\n');
|
|
87
|
+
const methodMatch = snippet.match(/\.(post|get|put|delete|patch)</i);
|
|
88
|
+
const httpMethod = methodMatch ? methodMatch[1].toUpperCase() : 'GET';
|
|
89
|
+
// Detect Content-Type header
|
|
90
|
+
const headers = {};
|
|
91
|
+
if (snippet.includes("'Content-Type': 'application/json'")) {
|
|
92
|
+
headers['Content-Type'] = 'application/json';
|
|
93
|
+
}
|
|
94
|
+
else if (snippet.includes("'Content-Type': 'application/octet-stream'")) {
|
|
95
|
+
headers['Content-Type'] = 'application/octet-stream';
|
|
96
|
+
}
|
|
97
|
+
map.set(funcName, { httpMethod, description: pendingDescription, headers });
|
|
98
|
+
pendingDescription = undefined;
|
|
99
|
+
jsDocLines = [];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return map;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Extract the first meaningful line from a JSDoc comment block.
|
|
106
|
+
*/
|
|
107
|
+
function parseJsDocDescription(jsDoc) {
|
|
108
|
+
for (const line of jsDoc.split('\n')) {
|
|
109
|
+
const cleaned = line.replace(/^\s*[/*]+\s?/, '').trim();
|
|
110
|
+
if (cleaned && !cleaned.startsWith('@')) {
|
|
111
|
+
return cleaned;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return undefined;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Convert a *Data TypeAliasDeclaration into a MethodInfo object.
|
|
118
|
+
*/
|
|
119
|
+
function extractMethodInfo(typeAlias, typesFile, baseName, opName, opMap) {
|
|
120
|
+
const dataTypeName = typeAlias.getName(); // e.g. 'AddPetData'
|
|
121
|
+
const opInfo = opMap.get(opName);
|
|
122
|
+
if (!opInfo) {
|
|
123
|
+
p.log.warn(`Operation "${opName}" not found in sdk.gen.ts — skipping`);
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const typeNode = typeAlias.getTypeNode();
|
|
127
|
+
if (!typeNode || typeNode.getKind() !== SyntaxKind.TypeLiteral) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
const typeLiteral = typeNode.asKind(SyntaxKind.TypeLiteral);
|
|
131
|
+
if (!typeLiteral) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
let urlPath = '';
|
|
135
|
+
let hasBody = false;
|
|
136
|
+
let pathParams = [];
|
|
137
|
+
let queryParams = [];
|
|
138
|
+
let hasQueryParams = false;
|
|
139
|
+
for (const member of typeLiteral.getMembers()) {
|
|
140
|
+
if (member.getKind() !== SyntaxKind.PropertySignature) {
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const propSig = member.asKind(SyntaxKind.PropertySignature);
|
|
144
|
+
if (!propSig) {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const propName = propSig.getName();
|
|
148
|
+
const typeNodeText = propSig.getTypeNode()?.getText() ?? '';
|
|
149
|
+
switch (propName) {
|
|
150
|
+
case 'url':
|
|
151
|
+
// String literal type: "'/pet'" → strip quotes → '/pet'
|
|
152
|
+
urlPath = typeNodeText.replace(/^['"`]|['"`]$/g, '');
|
|
153
|
+
break;
|
|
154
|
+
case 'body':
|
|
155
|
+
if (typeNodeText !== 'never') {
|
|
156
|
+
hasBody = true;
|
|
157
|
+
}
|
|
158
|
+
break;
|
|
159
|
+
case 'path': {
|
|
160
|
+
if (typeNodeText !== 'never') {
|
|
161
|
+
const pathTypeNode = propSig.getTypeNode();
|
|
162
|
+
if (pathTypeNode && pathTypeNode.getKind() === SyntaxKind.TypeLiteral) {
|
|
163
|
+
const innerLiteral = pathTypeNode.asKind(SyntaxKind.TypeLiteral);
|
|
164
|
+
if (innerLiteral) {
|
|
165
|
+
pathParams = innerLiteral
|
|
166
|
+
.getMembers()
|
|
167
|
+
.filter((m) => m.getKind() === SyntaxKind.PropertySignature)
|
|
168
|
+
.map((m) => m.asKind(SyntaxKind.PropertySignature).getName());
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
case 'query': {
|
|
175
|
+
if (typeNodeText !== 'never') {
|
|
176
|
+
const queryTypeNode = propSig.getTypeNode();
|
|
177
|
+
if (queryTypeNode && queryTypeNode.getKind() === SyntaxKind.TypeLiteral) {
|
|
178
|
+
const innerLiteral = queryTypeNode.asKind(SyntaxKind.TypeLiteral);
|
|
179
|
+
if (innerLiteral) {
|
|
180
|
+
queryParams = innerLiteral
|
|
181
|
+
.getMembers()
|
|
182
|
+
.filter((m) => m.getKind() === SyntaxKind.PropertySignature)
|
|
183
|
+
.map((m) => m.asKind(SyntaxKind.PropertySignature).getName());
|
|
184
|
+
hasQueryParams = queryParams.length > 0;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (!urlPath) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
// Extract response type from the matching *Responses type alias
|
|
196
|
+
const responsesAlias = typesFile.getTypeAlias(`${baseName}Responses`);
|
|
197
|
+
const responseType = responsesAlias ? extractResponseType(responsesAlias) : 'void';
|
|
198
|
+
// Only set requestType if the operation actually requires input params
|
|
199
|
+
const hasParams = hasBody || pathParams.length > 0 || hasQueryParams;
|
|
200
|
+
const requestType = hasParams ? dataTypeName : undefined;
|
|
201
|
+
return {
|
|
202
|
+
name: opName,
|
|
203
|
+
composableName: `useFetch${pascalCase(opName)}`,
|
|
204
|
+
requestType,
|
|
205
|
+
responseType,
|
|
206
|
+
httpMethod: opInfo.httpMethod,
|
|
207
|
+
path: urlPath,
|
|
208
|
+
hasBody,
|
|
209
|
+
bodyField: hasBody ? 'body' : undefined,
|
|
210
|
+
hasQueryParams,
|
|
211
|
+
queryParams,
|
|
212
|
+
pathParams,
|
|
213
|
+
headers: opInfo.headers,
|
|
214
|
+
description: opInfo.description,
|
|
215
|
+
hasRawMethod: false,
|
|
216
|
+
rawMethodName: undefined,
|
|
217
|
+
paramsShape: 'nested',
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Extract the success (2xx) response type from a *Responses type alias.
|
|
222
|
+
* Maps `unknown` to `void` for operations with no meaningful response body.
|
|
223
|
+
*/
|
|
224
|
+
function extractResponseType(responsesAlias) {
|
|
225
|
+
const typeNode = responsesAlias.getTypeNode();
|
|
226
|
+
if (!typeNode || typeNode.getKind() !== SyntaxKind.TypeLiteral) {
|
|
227
|
+
return 'void';
|
|
228
|
+
}
|
|
229
|
+
const typeLiteral = typeNode.asKind(SyntaxKind.TypeLiteral);
|
|
230
|
+
if (!typeLiteral) {
|
|
231
|
+
return 'void';
|
|
232
|
+
}
|
|
233
|
+
for (const member of typeLiteral.getMembers()) {
|
|
234
|
+
if (member.getKind() !== SyntaxKind.PropertySignature) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
const propSig = member.asKind(SyntaxKind.PropertySignature);
|
|
238
|
+
if (!propSig) {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const memberName = propSig.getName();
|
|
242
|
+
if (memberName === '200' || memberName === '201' || memberName === '202') {
|
|
243
|
+
const typeText = propSig.getTypeNode()?.getText() ?? '';
|
|
244
|
+
return typeText === 'unknown' || typeText === '' ? 'void' : typeText;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return 'void';
|
|
248
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared API Helpers - Used by both useFetch and useAsyncData wrappers
|
|
3
|
+
* This file contains common logic for callbacks, transforms, and global configuration
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Context provided to onRequest interceptor
|
|
7
|
+
*/
|
|
8
|
+
export interface RequestContext {
|
|
9
|
+
/** Request URL */
|
|
10
|
+
url: string;
|
|
11
|
+
/** HTTP method */
|
|
12
|
+
method: string;
|
|
13
|
+
/** Request body (if any) */
|
|
14
|
+
body?: any;
|
|
15
|
+
/** Request headers */
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
/** Query parameters */
|
|
18
|
+
query?: Record<string, any>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Modified context that can be returned from onRequest
|
|
22
|
+
*/
|
|
23
|
+
export interface ModifiedRequestContext {
|
|
24
|
+
/** Modified request body */
|
|
25
|
+
body?: any;
|
|
26
|
+
/** Modified request headers */
|
|
27
|
+
headers?: Record<string, string>;
|
|
28
|
+
/** Modified query parameters */
|
|
29
|
+
query?: Record<string, any>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Result context provided to onFinish callback
|
|
33
|
+
*/
|
|
34
|
+
export interface FinishContext<T> {
|
|
35
|
+
/** Response data (if successful) */
|
|
36
|
+
data?: T;
|
|
37
|
+
/** Error (if failed) */
|
|
38
|
+
error?: any;
|
|
39
|
+
/** Whether the request was successful */
|
|
40
|
+
success: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Global callbacks configuration
|
|
44
|
+
* Can be provided via Nuxt plugin: $getGlobalApiCallbacks
|
|
45
|
+
*/
|
|
46
|
+
export interface GlobalCallbacksConfig {
|
|
47
|
+
/**
|
|
48
|
+
* Optional URL patterns to match (Opción 3)
|
|
49
|
+
* Only apply global callbacks to URLs matching these patterns
|
|
50
|
+
* Supports wildcards: '/api/**', '/api/public/*', etc.
|
|
51
|
+
* If omitted, callbacks apply to all requests
|
|
52
|
+
*/
|
|
53
|
+
patterns?: string[];
|
|
54
|
+
/**
|
|
55
|
+
* Called before every request matching patterns
|
|
56
|
+
* Return false to prevent local callback execution (Opción 2)
|
|
57
|
+
* Return modified context to change request
|
|
58
|
+
*/
|
|
59
|
+
onRequest?: (context: RequestContext) => void | Promise<void> | ModifiedRequestContext | Promise<ModifiedRequestContext> | boolean | Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* Called when request succeeds
|
|
62
|
+
* Return false to prevent local callback execution (Opción 2)
|
|
63
|
+
*/
|
|
64
|
+
onSuccess?: (data: any, context?: any) => void | Promise<void> | boolean | Promise<boolean>;
|
|
65
|
+
/**
|
|
66
|
+
* Called when request fails
|
|
67
|
+
* Return false to prevent local callback execution (Opción 2)
|
|
68
|
+
*/
|
|
69
|
+
onError?: (error: any, context?: any) => void | Promise<void> | boolean | Promise<boolean>;
|
|
70
|
+
/**
|
|
71
|
+
* Called when request finishes (success or error)
|
|
72
|
+
* Return false to prevent local callback execution (Opción 2)
|
|
73
|
+
*/
|
|
74
|
+
onFinish?: (context: FinishContext<any>) => void | Promise<void> | boolean | Promise<boolean>;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Type for skipGlobalCallbacks option (Opción 1)
|
|
78
|
+
* - true: skip all global callbacks
|
|
79
|
+
* - array: skip specific callbacks by name
|
|
80
|
+
*/
|
|
81
|
+
export type SkipGlobalCallbacks = boolean | Array<'onRequest' | 'onSuccess' | 'onError' | 'onFinish'>;
|
|
82
|
+
/**
|
|
83
|
+
* Base options for API requests with lifecycle callbacks
|
|
84
|
+
* This is extended by specific wrapper options (useFetch, useAsyncData)
|
|
85
|
+
*/
|
|
86
|
+
export interface ApiRequestOptions<T = any> {
|
|
87
|
+
/**
|
|
88
|
+
* Called before the request is sent - can be used as an interceptor
|
|
89
|
+
* Return modified body/headers to transform the request
|
|
90
|
+
*/
|
|
91
|
+
onRequest?: (context: RequestContext) => void | Promise<void> | ModifiedRequestContext | Promise<ModifiedRequestContext>;
|
|
92
|
+
/** Called when the request succeeds with data (after transform/pick if provided) */
|
|
93
|
+
onSuccess?: (data: any) => void | Promise<void>;
|
|
94
|
+
/** Called when the request fails with an error */
|
|
95
|
+
onError?: (error: any) => void | Promise<void>;
|
|
96
|
+
/** Called when the request finishes (success or error) with result context */
|
|
97
|
+
onFinish?: (context: FinishContext<any>) => void | Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Skip global callbacks for this specific request (Opción 1)
|
|
100
|
+
* - true: skip all global callbacks
|
|
101
|
+
* - ['onSuccess', 'onError']: skip specific callbacks
|
|
102
|
+
* - false/undefined: use global callbacks (default)
|
|
103
|
+
* @example
|
|
104
|
+
* skipGlobalCallbacks: true // Skip all global callbacks
|
|
105
|
+
* skipGlobalCallbacks: ['onSuccess'] // Skip only global onSuccess
|
|
106
|
+
*/
|
|
107
|
+
skipGlobalCallbacks?: SkipGlobalCallbacks;
|
|
108
|
+
/**
|
|
109
|
+
* Transform the response data
|
|
110
|
+
* @example
|
|
111
|
+
* transform: (pet) => ({ displayName: pet.name, isAvailable: pet.status === 'available' })
|
|
112
|
+
*/
|
|
113
|
+
transform?: (data: T) => any;
|
|
114
|
+
/**
|
|
115
|
+
* Pick specific keys from the response (applied before transform)
|
|
116
|
+
* Supports dot notation for nested paths
|
|
117
|
+
* @example
|
|
118
|
+
* pick: ['id', 'name'] as const
|
|
119
|
+
* pick: ['person.name', 'person.email', 'status']
|
|
120
|
+
*/
|
|
121
|
+
pick?: ReadonlyArray<string>;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Helper function to apply request modifications from onRequest interceptor
|
|
125
|
+
*/
|
|
126
|
+
export declare function applyRequestModifications(options: Record<string, any>, modifications: ModifiedRequestContext): void;
|
|
127
|
+
/**
|
|
128
|
+
* Helper function to pick specific keys from an object
|
|
129
|
+
* Supports dot notation for nested paths (e.g., 'person.name')
|
|
130
|
+
*/
|
|
131
|
+
export declare function applyPick<T>(data: T, paths: ReadonlyArray<string>): any;
|
|
132
|
+
/**
|
|
133
|
+
* Helper function to get global headers from user configuration
|
|
134
|
+
* Supports two methods:
|
|
135
|
+
* 1. Auto-imported composable: composables/useApiHeaders.ts
|
|
136
|
+
* 2. Nuxt plugin provide: plugins/api-config.ts with $getApiHeaders
|
|
137
|
+
*/
|
|
138
|
+
export declare function getGlobalHeaders(): Record<string, string>;
|
|
139
|
+
/**
|
|
140
|
+
* Helper function to get global callbacks from user configuration
|
|
141
|
+
* Uses Nuxt plugin provide: plugins/api-callbacks.ts with $getGlobalApiCallbacks
|
|
142
|
+
*/
|
|
143
|
+
export declare function getGlobalCallbacks(): GlobalCallbacksConfig;
|
|
144
|
+
/**
|
|
145
|
+
* Check if a global callback should be applied to a specific request
|
|
146
|
+
* Implements Opción 1 (skipGlobalCallbacks) and Opción 3 (pattern matching)
|
|
147
|
+
*/
|
|
148
|
+
export declare function shouldApplyGlobalCallback(url: string, callbackName: 'onRequest' | 'onSuccess' | 'onError' | 'onFinish', patterns?: string[], skipConfig?: SkipGlobalCallbacks): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Merge local and global callbacks with proper execution order
|
|
151
|
+
* Implements all 3 options:
|
|
152
|
+
* - Opción 1: skipGlobalCallbacks to disable global callbacks
|
|
153
|
+
* - Opción 2: global callbacks can return false to prevent local execution
|
|
154
|
+
* - Opción 3: pattern matching to apply callbacks only to matching URLs
|
|
155
|
+
*/
|
|
156
|
+
export declare function mergeCallbacks(url: string, localCallbacks: {
|
|
157
|
+
onRequest?: Function;
|
|
158
|
+
onSuccess?: Function;
|
|
159
|
+
onError?: Function;
|
|
160
|
+
onFinish?: Function;
|
|
161
|
+
}, skipConfig?: SkipGlobalCallbacks): {
|
|
162
|
+
/**
|
|
163
|
+
* Merged onRequest callback
|
|
164
|
+
* Executes global first, then local
|
|
165
|
+
* Global can return modifications or false to cancel local
|
|
166
|
+
*/
|
|
167
|
+
onRequest: (ctx: RequestContext) => Promise<any>;
|
|
168
|
+
/**
|
|
169
|
+
* Merged onSuccess callback
|
|
170
|
+
* Executes global first, then local (if global doesn't return false)
|
|
171
|
+
*/
|
|
172
|
+
onSuccess: (data: any, context?: any) => Promise<void>;
|
|
173
|
+
/**
|
|
174
|
+
* Merged onError callback
|
|
175
|
+
* Executes global first, then local (if global doesn't return false)
|
|
176
|
+
*/
|
|
177
|
+
onError: (error: any, context?: any) => Promise<void>;
|
|
178
|
+
/**
|
|
179
|
+
* Merged onFinish callback
|
|
180
|
+
* Executes global first, then local (if global doesn't return false)
|
|
181
|
+
*/
|
|
182
|
+
onFinish: (context: any) => Promise<void>;
|
|
183
|
+
};
|