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.
Files changed (109) hide show
  1. package/.editorconfig +26 -0
  2. package/.prettierignore +17 -0
  3. package/.prettierrc.json +12 -0
  4. package/CONTRIBUTING.md +292 -0
  5. package/INSTRUCTIONS.md +327 -0
  6. package/LICENSE +202 -0
  7. package/README.md +202 -0
  8. package/dist/cli/config.d.ts +57 -0
  9. package/dist/cli/config.js +85 -0
  10. package/dist/cli/logger.d.ts +44 -0
  11. package/dist/cli/logger.js +58 -0
  12. package/dist/cli/logo.d.ts +6 -0
  13. package/dist/cli/logo.js +21 -0
  14. package/dist/cli/messages.d.ts +65 -0
  15. package/dist/cli/messages.js +86 -0
  16. package/dist/cli/prompts.d.ts +30 -0
  17. package/dist/cli/prompts.js +118 -0
  18. package/dist/cli/types.d.ts +43 -0
  19. package/dist/cli/types.js +4 -0
  20. package/dist/cli/utils.d.ts +26 -0
  21. package/dist/cli/utils.js +45 -0
  22. package/dist/generate.d.ts +6 -0
  23. package/dist/generate.js +48 -0
  24. package/dist/generators/nuxt-server/bff-templates.d.ts +25 -0
  25. package/dist/generators/nuxt-server/bff-templates.js +737 -0
  26. package/dist/generators/nuxt-server/generator.d.ts +7 -0
  27. package/dist/generators/nuxt-server/generator.js +206 -0
  28. package/dist/generators/nuxt-server/parser.d.ts +5 -0
  29. package/dist/generators/nuxt-server/parser.js +5 -0
  30. package/dist/generators/nuxt-server/templates.d.ts +35 -0
  31. package/dist/generators/nuxt-server/templates.js +412 -0
  32. package/dist/generators/nuxt-server/types.d.ts +5 -0
  33. package/dist/generators/nuxt-server/types.js +5 -0
  34. package/dist/generators/shared/parsers/heyapi-parser.d.ts +11 -0
  35. package/dist/generators/shared/parsers/heyapi-parser.js +248 -0
  36. package/dist/generators/shared/parsers/official-parser.d.ts +5 -0
  37. package/dist/generators/shared/parsers/official-parser.js +5 -0
  38. package/dist/generators/shared/runtime/apiHelpers.d.ts +183 -0
  39. package/dist/generators/shared/runtime/apiHelpers.js +268 -0
  40. package/dist/generators/shared/templates/api-callbacks-plugin.d.ts +178 -0
  41. package/dist/generators/shared/templates/api-callbacks-plugin.js +338 -0
  42. package/dist/generators/shared/types.d.ts +25 -0
  43. package/dist/generators/shared/types.js +4 -0
  44. package/dist/generators/tanstack-query/generator.d.ts +5 -0
  45. package/dist/generators/tanstack-query/generator.js +11 -0
  46. package/dist/generators/use-async-data/generator.d.ts +5 -0
  47. package/dist/generators/use-async-data/generator.js +156 -0
  48. package/dist/generators/use-async-data/parser.d.ts +5 -0
  49. package/dist/generators/use-async-data/parser.js +5 -0
  50. package/dist/generators/use-async-data/runtime/useApiAsyncData.d.ts +38 -0
  51. package/dist/generators/use-async-data/runtime/useApiAsyncData.js +122 -0
  52. package/dist/generators/use-async-data/runtime/useApiAsyncDataRaw.d.ts +54 -0
  53. package/dist/generators/use-async-data/runtime/useApiAsyncDataRaw.js +126 -0
  54. package/dist/generators/use-async-data/templates.d.ts +20 -0
  55. package/dist/generators/use-async-data/templates.js +191 -0
  56. package/dist/generators/use-async-data/types.d.ts +4 -0
  57. package/dist/generators/use-async-data/types.js +4 -0
  58. package/dist/generators/use-fetch/generator.d.ts +5 -0
  59. package/dist/generators/use-fetch/generator.js +131 -0
  60. package/dist/generators/use-fetch/parser.d.ts +9 -0
  61. package/dist/generators/use-fetch/parser.js +282 -0
  62. package/dist/generators/use-fetch/runtime/useApiRequest.d.ts +46 -0
  63. package/dist/generators/use-fetch/runtime/useApiRequest.js +158 -0
  64. package/dist/generators/use-fetch/templates.d.ts +16 -0
  65. package/dist/generators/use-fetch/templates.js +169 -0
  66. package/dist/generators/use-fetch/types.d.ts +5 -0
  67. package/dist/generators/use-fetch/types.js +5 -0
  68. package/dist/index.d.ts +2 -0
  69. package/dist/index.js +213 -0
  70. package/docs/API-REFERENCE.md +887 -0
  71. package/docs/ARCHITECTURE.md +649 -0
  72. package/docs/DEVELOPMENT.md +918 -0
  73. package/docs/QUICK-START.md +323 -0
  74. package/docs/README.md +155 -0
  75. package/docs/TROUBLESHOOTING.md +881 -0
  76. package/eslint.config.js +72 -0
  77. package/package.json +65 -0
  78. package/src/cli/config.ts +140 -0
  79. package/src/cli/logger.ts +66 -0
  80. package/src/cli/logo.ts +25 -0
  81. package/src/cli/messages.ts +97 -0
  82. package/src/cli/prompts.ts +143 -0
  83. package/src/cli/types.ts +50 -0
  84. package/src/cli/utils.ts +49 -0
  85. package/src/generate.ts +57 -0
  86. package/src/generators/nuxt-server/bff-templates.ts +754 -0
  87. package/src/generators/nuxt-server/generator.ts +270 -0
  88. package/src/generators/nuxt-server/parser.ts +5 -0
  89. package/src/generators/nuxt-server/templates.ts +483 -0
  90. package/src/generators/nuxt-server/types.ts +5 -0
  91. package/src/generators/shared/parsers/heyapi-parser.ts +307 -0
  92. package/src/generators/shared/parsers/official-parser.ts +5 -0
  93. package/src/generators/shared/runtime/apiHelpers.ts +466 -0
  94. package/src/generators/shared/templates/api-callbacks-plugin.ts +352 -0
  95. package/src/generators/shared/types.ts +27 -0
  96. package/src/generators/tanstack-query/generator.ts +11 -0
  97. package/src/generators/use-async-data/generator.ts +204 -0
  98. package/src/generators/use-async-data/parser.ts +5 -0
  99. package/src/generators/use-async-data/runtime/useApiAsyncData.ts +220 -0
  100. package/src/generators/use-async-data/runtime/useApiAsyncDataRaw.ts +236 -0
  101. package/src/generators/use-async-data/templates.ts +250 -0
  102. package/src/generators/use-async-data/types.ts +4 -0
  103. package/src/generators/use-fetch/generator.ts +169 -0
  104. package/src/generators/use-fetch/parser.ts +341 -0
  105. package/src/generators/use-fetch/runtime/useApiRequest.ts +223 -0
  106. package/src/generators/use-fetch/templates.ts +214 -0
  107. package/src/generators/use-fetch/types.ts +5 -0
  108. package/src/index.ts +265 -0
  109. package/tsconfig.json +15 -0
@@ -0,0 +1,649 @@
1
+ # 🏗️ Architecture & Design Decisions
2
+
3
+ > **Purpose**: Understand WHY the codebase is structured this way and the trade-offs made.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Architectural Overview](#architectural-overview)
8
+ - [Core Patterns](#core-patterns)
9
+ - [Design Decisions (ADRs)](#design-decisions-adrs)
10
+ - [Component Map](#component-map)
11
+ - [Data Flow](#data-flow)
12
+ - [Extension Points](#extension-points)
13
+
14
+ ## Architectural Overview
15
+
16
+ ### High-Level Architecture
17
+
18
+ ```
19
+ ┌──────────────────────────────────────────────────────────────┐
20
+ │ CLI Tool │
21
+ │ (Runs on developer's machine during development) │
22
+ └────────────────────────┬─────────────────────────────────────┘
23
+
24
+
25
+ ┌──────────────────────────────────────────────────────────────┐
26
+ │ OpenAPI Generator (typescript-fetch) │
27
+ │ Generates: PetApi.ts, models/, runtime.ts │
28
+ └────────────────────────┬─────────────────────────────────────┘
29
+
30
+
31
+ ┌──────────────────────────────────────────────────────────────┐
32
+ │ Parser (ts-morph) │
33
+ │ Extracts: method names, params, paths, HTTP details │
34
+ └────────────────────────┬─────────────────────────────────────┘
35
+
36
+
37
+ ┌──────────────────────────────────────────────────────────────┐
38
+ │ Template Generator │
39
+ │ Creates: useFetchAddPet, useAsyncDataGetPet │
40
+ └────────────────────────┬─────────────────────────────────────┘
41
+
42
+
43
+ ┌──────────────────────────────────────────────────────────────┐
44
+ │ User's Nuxt Project │
45
+ │ Runtime: useApiRequest, apiHelpers, global callbacks │
46
+ │ Generated: Individual composables per endpoint │
47
+ └──────────────────────────────────────────────────────────────┘
48
+ ```
49
+
50
+ ### Two-Runtime Architecture
51
+
52
+ This project operates in **two separate runtime contexts**:
53
+
54
+ #### 1. **Build-time Runtime** (CLI Tool)
55
+
56
+ - Runs during development
57
+ - Uses Node.js, TypeScript, ts-morph
58
+ - Has access to file system
59
+ - Generates code as strings
60
+
61
+ #### 2. **User Runtime** (Nuxt Project)
62
+
63
+ - Runs in production (browser + server)
64
+ - Uses Vue 3, Nuxt 3 APIs
65
+ - No access to our CLI dependencies
66
+ - Executes generated composables
67
+
68
+ **Critical implication**: Runtime files can't be imported from our npm package - they must be **copied** to user's project.
69
+
70
+ ## Core Patterns
71
+
72
+ ### 1. Two-Stage Generation Pattern
73
+
74
+ **Problem**: OpenAPI specs are verbose XML/YAML. Nuxt needs composables.
75
+
76
+ **Solution**: Use an existing OpenAPI client generator for Stage 1, then parse and transform its output in Stage 2.
77
+
78
+ ```
79
+ OpenAPI Spec → [Stage 1: backend A or B] → TypeScript Client
80
+ TypeScript Client → [Stage 2: Our Parser + Templates] → Nuxt Composables
81
+ ```
82
+
83
+ **Two supported backends for Stage 1:**
84
+
85
+ | Backend | Package | Requires | Parser used in Stage 2 |
86
+ |---|---|---|---|
87
+ | `official` | `@openapitools/openapi-generator-cli` | Java 11+ | `official-parser.ts` (reads `apis/*.ts`) |
88
+ | `heyapi` | `@hey-api/openapi-ts` | Node.js only | `heyapi-parser.ts` (reads `sdk.gen.ts` + `types.gen.ts`) |
89
+
90
+ Both parsers (`src/generators/shared/parsers/`) produce identical `MethodInfo[]` output, so all downstream templates are shared and backend-agnostic.
91
+
92
+ **Benefits**:
93
+
94
+ - ✅ Leverage mature OpenAPI ecosystem
95
+ - ✅ Don't reinvent OpenAPI parsing
96
+ - ✅ No Java required when using heyapi backend
97
+ - ✅ Templates work identically regardless of backend
98
+
99
+ **Trade-offs**:
100
+
101
+ - ⚠️ official backend depends on openapi-generator-cli staying stable
102
+ - ⚠️ Must parse TypeScript (additional complexity)
103
+ - ⚠️ Two-step process (slower than direct)
104
+
105
+ ### 2. Wrapper Pattern
106
+
107
+ **Problem**: Want to add features (callbacks, auth) without modifying generated code.
108
+
109
+ **Solution**: Wrap native Nuxt composables with our enhanced version.
110
+
111
+ ```typescript
112
+ // Generated composable (auto-regenerated)
113
+ export const useFetchAddPet = (
114
+ params: MaybeRef<AddPetRequest>,
115
+ options?: ApiRequestOptions<Pet>
116
+ ) => {
117
+ const p = isRef(params) ? params : shallowRef(params);
118
+ return useApiRequest<Pet>(() => `/pet`, {
119
+ method: 'POST',
120
+ body: computed(() => p.value.pet),
121
+ ...options,
122
+ });
123
+ };
124
+
125
+ // Our wrapper (user-modifiable)
126
+ export function useApiRequest<T>(url: string | (() => string), options?: ApiRequestOptions<T>) {
127
+ const result = useFetch<T>(url, options);
128
+ // Add: callbacks, auth, transforms, etc.
129
+ return result;
130
+ }
131
+ ```
132
+
133
+ **Benefits**:
134
+
135
+ - ✅ Generated code stays simple
136
+ - ✅ Features in one place (DRY)
137
+ - ✅ Easy to extend without regeneration
138
+ - ✅ Users can customize wrappers
139
+
140
+ **Trade-offs**:
141
+
142
+ - ⚠️ Extra function call (negligible overhead)
143
+ - ⚠️ Wrapper logic applies to all endpoints
144
+
145
+ ### 3. Shared Code Architecture
146
+
147
+ **Problem**: Multiple generators (useFetch, useAsyncData, nuxt-server) duplicate logic.
148
+
149
+ **Solution**: Extract common code to `shared/` folder.
150
+
151
+ ```
152
+ generators/
153
+ shared/
154
+ types.ts # MethodInfo interface (all generators use)
155
+ runtime/
156
+ apiHelpers.ts # Callbacks, auth, transforms (all wrappers use)
157
+ use-fetch/
158
+ parser.ts # Re-exported from shared
159
+ templates.ts # Specific to useFetch
160
+ use-async-data/
161
+ parser.ts # Re-exported from shared
162
+ templates.ts # Specific to useAsyncData
163
+ ```
164
+
165
+ **Benefits**:
166
+
167
+ - ✅ Single source of truth
168
+ - ✅ Bug fixes apply everywhere
169
+ - ✅ Easier to add new generators
170
+
171
+ **Trade-offs**:
172
+
173
+ - ⚠️ Changes affect all generators
174
+ - ⚠️ Must maintain backward compatibility
175
+
176
+ ### 4. Template-Based Code Generation
177
+
178
+ **Problem**: Generating code programmatically is error-prone with string concatenation.
179
+
180
+ **Solution**: Use template functions that interpolate variables.
181
+
182
+ ```typescript
183
+ function generateFunctionBody(method: MethodInfo): string {
184
+ return `export const ${method.composableName} = (
185
+ params: MaybeRef<${method.requestType}>,
186
+ options?: ApiRequestOptions<${method.responseType}>
187
+ ) => {
188
+ const p = isRef(params) ? params : shallowRef(params)
189
+ return useApiRequest<${method.responseType}>(
190
+ () => \`${method.path}\`,
191
+ { method: '${method.method}', body: computed(() => p.value.${method.bodyField}), ...options }
192
+ )
193
+ }`;
194
+ }
195
+ ```
196
+
197
+ **Benefits**:
198
+
199
+ - ✅ Easier to read/maintain
200
+ - ✅ Clear what's generated
201
+ - ✅ Can format with Prettier
202
+
203
+ **Trade-offs**:
204
+
205
+ - ⚠️ Escaping can be tricky
206
+ - ⚠️ Template strings can get long
207
+
208
+ ### 5. Copy vs Import Pattern (Runtime Files)
209
+
210
+ **Problem**: How do users get runtime code (wrappers, helpers)?
211
+
212
+ **Option A**: Import from our npm package
213
+ **Option B**: Copy files to user's project
214
+
215
+ **Decision**: **Copy files** (Option B)
216
+
217
+ **Rationale**:
218
+
219
+ - ✅ Zero runtime dependencies
220
+ - ✅ Users can customize wrappers
221
+ - ✅ Works with any Nuxt setup
222
+ - ✅ No version conflicts
223
+ - ✅ Framework agnostic
224
+
225
+ **Trade-offs**:
226
+
227
+ - ⚠️ File duplication
228
+ - ⚠️ Updates require regeneration
229
+ - ⚠️ User modifications can break things
230
+
231
+ **Implementation**: Use `fs.copy()` to copy `runtime/` files to output.
232
+
233
+ ### 6. Global Callbacks System
234
+
235
+ **Problem**: Repeating same callbacks (auth, error handling) on every API call.
236
+
237
+ **Solution**: Plugin-based global callbacks with 3 control options.
238
+
239
+ ```typescript
240
+ // Define once in plugin
241
+ export default defineNuxtPlugin(() => ({
242
+ provide: {
243
+ getGlobalApiCallbacks: () => ({
244
+ onRequest: (ctx) => {
245
+ /* Add auth header to all requests */
246
+ },
247
+ onError: (error) => {
248
+ /* Handle 401/500 errors globally */
249
+ },
250
+ }),
251
+ },
252
+ }));
253
+
254
+ // Control per-call
255
+ useFetchGetPet({ petId: 123 }, {
256
+ skipGlobalCallbacks: true, // Option 1: Disable
257
+ });
258
+
259
+ // Or in global callback
260
+ onError: (error) => {
261
+ if (error.status >= 500) return false; // Option 2: Cancel local
262
+ };
263
+
264
+ // Or with patterns
265
+ {
266
+ patterns: ['/api/auth/**'], // Option 3: URL matching
267
+ }
268
+ ```
269
+
270
+ See [Global Callbacks Deep Dive](#global-callbacks-deep-dive) below.
271
+
272
+ ## Design Decisions (ADRs)
273
+
274
+ ### ADR-001: Use ts-morph Instead of Regex
275
+
276
+ **Context**: Need to parse generated TypeScript to extract API info.
277
+
278
+ **Decision**: Use ts-morph library for TypeScript AST parsing.
279
+
280
+ **Alternatives Considered**:
281
+
282
+ - ❌ Regex: Too fragile, can't handle complex syntax
283
+ - ❌ Babel: Wrong target (designed for JS, not TS)
284
+ - ❌ TypeScript Compiler API: Too low-level
285
+
286
+ **Rationale**:
287
+
288
+ - ✅ Type-aware parsing
289
+ - ✅ Handles complex TypeScript syntax
290
+ - ✅ Provides semantic information
291
+ - ✅ Less brittle than regex
292
+ - ✅ Good documentation
293
+
294
+ **Trade-offs**:
295
+
296
+ - ⚠️ Dependency on ts-morph (large library)
297
+ - ⚠️ AST navigation can be complex
298
+
299
+ **Status**: ✅ Accepted (v1.0)
300
+
301
+ **Date**: Initial design
302
+
303
+ ---
304
+
305
+ ### ADR-002: Copy Runtime Files Instead of NPM Package
306
+
307
+ **Context**: Users need runtime code (wrappers, helpers) in their Nuxt project.
308
+
309
+ **Decision**: Copy runtime files to user's project instead of npm import.
310
+
311
+ **Alternatives Considered**:
312
+
313
+ - ❌ Import from npm: `import { useApiRequest } from 'nuxt-generator/runtime'`
314
+ - ❌ Virtual modules: Nuxt module that provides runtime
315
+
316
+ **Rationale**:
317
+
318
+ - ✅ **Zero dependencies**: User doesn't need to install our package in production
319
+ - ✅ **Customizable**: Users can modify wrappers for their needs
320
+ - ✅ **Framework agnostic**: Works with any Nuxt setup
321
+ - ✅ **No version conflicts**: Each project has its own copy
322
+ - ✅ **Explicit**: Users see exactly what code runs
323
+
324
+ **Trade-offs**:
325
+
326
+ - ⚠️ File duplication across projects
327
+ - ⚠️ Updates require regeneration
328
+ - ⚠️ Users might break things with modifications
329
+
330
+ **Status**: ✅ Accepted (v1.0)
331
+
332
+ **Date**: Initial design
333
+
334
+ ---
335
+
336
+ ### ADR-003: @ts-nocheck in Runtime Files
337
+
338
+ **Context**: Runtime files are copied to user's Nuxt project with different TypeScript config.
339
+
340
+ **Decision**: Add `// @ts-nocheck` to all runtime files.
341
+
342
+ **Rationale**:
343
+
344
+ - ✅ Files run in user's project with different `tsconfig.json`
345
+ - ✅ May use different TS version
346
+ - ✅ Different strict mode settings
347
+ - ✅ CLI doesn't need to compile them
348
+
349
+ **Trade-offs**:
350
+
351
+ - ⚠️ No type checking in our development
352
+ - ⚠️ Potential bugs hidden
353
+
354
+ **Status**: ✅ Accepted (v1.2)
355
+
356
+ **Date**: After user reports of TS errors
357
+
358
+ ---
359
+
360
+ ### ADR-004: Dual Composables for useAsyncData (Normal + Raw)
361
+
362
+ **Context**: Some users need response headers/status, others just need data.
363
+
364
+ **Decision**: Generate both normal and raw versions when possible.
365
+
366
+ ```typescript
367
+ // Normal: Simple data access
368
+ const { data } = useAsyncDataGetPet({ petId: 123 });
369
+ // data: Ref<Pet>
370
+
371
+ // Raw: With headers/status
372
+ const { data } = useAsyncDataGetPetRaw({ petId: 123 });
373
+ // data: Ref<{ data: Pet, headers: Headers, status: number }>
374
+ ```
375
+
376
+ **Rationale**:
377
+
378
+ - ✅ Covers both use cases
379
+ - ✅ Clean API for simple cases
380
+ - ✅ Power when needed (auth, rate limiting, caching)
381
+
382
+ **Trade-offs**:
383
+
384
+ - ⚠️ 2x composables generated (double the code)
385
+ - ⚠️ Users might be confused which to use
386
+
387
+ **Status**: ✅ Accepted (v1.3)
388
+
389
+ **Date**: When Raw support added
390
+
391
+ ---
392
+
393
+ ### ADR-005: Plugin Template Never Regenerated
394
+
395
+ **Context**: Global callbacks plugin needs user customization.
396
+
397
+ **Decision**: Copy plugin template once, never overwrite.
398
+
399
+ **Implementation**:
400
+
401
+ ```typescript
402
+ if (await fs.pathExists(pluginPath)) {
403
+ return; // Already exists, don't overwrite
404
+ }
405
+ await fs.copy(templatePath, pluginPath);
406
+ ```
407
+
408
+ **Rationale**:
409
+
410
+ - ✅ Preserves user customizations
411
+ - ✅ Clear ownership (user's file)
412
+ - ✅ Safe regeneration
413
+
414
+ **Trade-offs**:
415
+
416
+ - ⚠️ Updates to template don't apply automatically
417
+ - ⚠️ Users might not know it exists
418
+
419
+ **Status**: ✅ Accepted (v1.4)
420
+
421
+ **Date**: Global callbacks feature
422
+
423
+ ---
424
+
425
+ ### ADR-006: ESLint Flat Config for Modern Standards
426
+
427
+ **Context**: Need linting for maintainability and PR contributions.
428
+
429
+ **Decision**: Use ESLint v9+ flat config format.
430
+
431
+ **Rationale**:
432
+
433
+ - ✅ Future-proof (ESLint's new standard)
434
+ - ✅ Better TypeScript integration
435
+ - ✅ Simpler configuration
436
+
437
+ **Trade-offs**:
438
+
439
+ - ⚠️ Requires ESLint 9+ (breaking for some users)
440
+
441
+ **Status**: ✅ Accepted (v1.5)
442
+
443
+ **Date**: 2026-03-21
444
+
445
+ ## Component Map
446
+
447
+ ### Dependency Graph
448
+
449
+ ```
450
+ ┌──────────────────────────────────────────────────────────────┐
451
+ │ CLI Entry (index.ts) │
452
+ │ Commands: generate, ... │
453
+ └────────────────────────┬─────────────────────────────────────┘
454
+
455
+ ├─► generate.ts (OpenAPI Generator wrapper)
456
+
457
+ └─► generators/
458
+
459
+ ├─► shared/
460
+ │ ├─ types.ts (MethodInfo, ApiClassInfo)
461
+ │ ├─ runtime/apiHelpers.ts (copied to output)
462
+ │ └─ templates/api-callbacks-plugin.ts (copied once)
463
+
464
+ ├─► use-fetch/
465
+ │ ├─ parser.ts → shared/types.ts
466
+ │ ├─ templates.ts → parser.ts
467
+ │ ├─ generator.ts → parser.ts + templates.ts
468
+ │ └─ runtime/useApiRequest.ts → shared/runtime/
469
+
470
+ ├─► use-async-data/
471
+ │ ├─ parser.ts (re-exports from use-fetch)
472
+ │ ├─ templates.ts → parser.ts
473
+ │ ├─ generator.ts → parser.ts + templates.ts
474
+ │ └─ runtime/
475
+ │ ├─ useApiAsyncData.ts → shared/runtime/
476
+ │ └─ useApiAsyncDataRaw.ts → shared/runtime/
477
+
478
+ └─► nuxt-server/
479
+ ├─ parser.ts (re-exports from use-fetch)
480
+ ├─ templates.ts
481
+ ├─ bff-templates.ts (auth + transformers)
482
+ └─ generator.ts → templates + bff-templates
483
+ ```
484
+
485
+ ### Information Flow
486
+
487
+ ```
488
+ swagger.yaml
489
+
490
+
491
+ [OpenAPI Generator]
492
+
493
+ ├─► apis/PetApi.ts
494
+ ├─► models/Pet.ts
495
+ └─► runtime.ts
496
+
497
+
498
+ [Parser]
499
+
500
+ ├─► MethodInfo {
501
+ │ name: 'addPet',
502
+ │ path: '/pet',
503
+ │ method: 'POST',
504
+ │ requestType: 'AddPetRequest',
505
+ │ responseType: 'Pet',
506
+ │ ...
507
+ │ }
508
+
509
+
510
+ [Template Generator]
511
+
512
+ ├─► useFetchAddPet.ts
513
+ ├─► useFetchUpdatePet.ts
514
+ ├─► ...
515
+
516
+
517
+ [User's Nuxt Project]
518
+
519
+ ├─► composables/use-fetch/ (composables)
520
+ ├─► composables/shared/runtime/ (helpers)
521
+ └─► plugins/api-callbacks.ts (global config)
522
+ ```
523
+
524
+ ## Global Callbacks Deep Dive
525
+
526
+ ### Architecture
527
+
528
+ ```
529
+ ┌────────────────────────────────────────────────────────────────┐
530
+ │ User's Nuxt Project │
531
+ ├────────────────────────────────────────────────────────────────┤
532
+ │ │
533
+ │ plugins/api-callbacks.ts (NEVER regenerated) │
534
+ │ ┌──────────────────────────────────────────────────┐ │
535
+ │ │ defineNuxtPlugin(() => ({ │ │
536
+ │ │ provide: { │ │
537
+ │ │ getGlobalApiCallbacks: () => ({ │ │
538
+ │ │ patterns: ['/api/auth/**'], │ │
539
+ │ │ onRequest: (ctx) => { ... }, │ │
540
+ │ │ onSuccess: (data) => { ... }, │ │
541
+ │ │ onError: (error) => { ... } │ │
542
+ │ │ }) │ │
543
+ │ │ } │ │
544
+ │ │ })) │ │
545
+ │ └──────────────────────────────────────────────────┘ │
546
+ │ ↓ provide │
547
+ │ ┌──────────────────────────────────────────────────┐ │
548
+ │ │ nuxtApp.$getGlobalApiCallbacks() │ │
549
+ │ └──────────────────────────────────────────────────┘ │
550
+ │ ↓ called by │
551
+ │ ┌──────────────────────────────────────────────────┐ │
552
+ │ │ composables/shared/runtime/apiHelpers.ts │ │
553
+ │ │ - getGlobalCallbacks() │ │
554
+ │ │ - shouldApplyGlobalCallback() │ │
555
+ │ │ - mergeCallbacks() │ │
556
+ │ └──────────────────────────────────────────────────┘ │
557
+ │ ↓ used by │
558
+ │ ┌──────────────────────────────────────────────────┐ │
559
+ │ │ composables/use-fetch/runtime/useApiRequest.ts │ │
560
+ │ │ - Calls mergeCallbacks() │ │
561
+ │ │ - Executes merged callbacks in watch() │ │
562
+ │ └──────────────────────────────────────────────────┘ │
563
+ │ ↓ called by │
564
+ │ ┌──────────────────────────────────────────────────┐ │
565
+ │ │ composables/use-fetch/useFetchAddPet.ts │ │
566
+ │ │ (Generated - CAN be regenerated safely) │ │
567
+ │ └──────────────────────────────────────────────────┘ │
568
+ │ │
569
+ └────────────────────────────────────────────────────────────────┘
570
+ ```
571
+
572
+ ### Execution Flow
573
+
574
+ ```
575
+ User calls: useFetchGetPet({ petId: 123 }, { onSuccess: localCallback })
576
+
577
+
578
+ useApiRequest(url, options)
579
+
580
+ ├─► Extract: skipGlobalCallbacks from options
581
+
582
+ ├─► Call: mergeCallbacks(url, localCallbacks, skipGlobalCallbacks)
583
+ │ │
584
+ │ ├─► getGlobalCallbacks() → reads nuxtApp.$getGlobalApiCallbacks()
585
+ │ │
586
+ │ ├─► For each callback type (onRequest, onSuccess, onError, onFinish):
587
+ │ │ │
588
+ │ │ ├─► shouldApplyGlobalCallback(name, skipConfig, url, patterns)
589
+ │ │ │ │
590
+ │ │ │ ├─► Check skipConfig: true / array?
591
+ │ │ │ ├─► Match URL against patterns
592
+ │ │ │ └─► Return: boolean
593
+ │ │ │
594
+ │ │ └─► Create merged function:
595
+ │ │ (args) => {
596
+ │ │ if (global && shouldApply) {
597
+ │ │ result = global(args);
598
+ │ │ if (result === false) return; // Cancel local
599
+ │ │ }
600
+ │ │ if (local) local(args);
601
+ │ │ }
602
+ │ │
603
+ │ └─► Return: { onRequest, onSuccess, onError, onFinish }
604
+
605
+ ├─► useFetch(url, options)
606
+
607
+ └─► watch(data/error/pending) → Execute merged callbacks
608
+ ```
609
+
610
+ ## Extension Points
611
+
612
+ ### Want to add a new callback?
613
+
614
+ **Files to modify**:
615
+
616
+ 1. `src/generators/shared/runtime/apiHelpers.ts`
617
+ - Add to `GlobalCallbacksConfig` interface
618
+ - Update `mergeCallbacks()` function
619
+ 2. `src/generators/use-fetch/runtime/useApiRequest.ts`
620
+ - Add callback execution in `watch()`
621
+ 3. `src/generators/use-async-data/runtime/useApiAsyncData.ts`
622
+ - Add callback execution in try/catch/finally
623
+ 4. `src/generators/shared/templates/api-callbacks-plugin.ts`
624
+ - Add examples and documentation
625
+ 5. `docs/API-REFERENCE.md`
626
+ - Document the new callback
627
+
628
+ ### Want to add a new generator?
629
+
630
+ **Steps**:
631
+
632
+ 1. Copy `src/generators/use-fetch/` → `src/generators/your-generator/`
633
+ 2. Modify `templates.ts` for your output format
634
+ 3. Create/modify `runtime/` wrapper for your needs
635
+ 4. Update `src/index.ts` to add CLI choice
636
+ 5. Test: `npm run build && node dist/index.js generate`
637
+
638
+ ### Want to add parser feature?
639
+
640
+ **Steps**:
641
+
642
+ 1. Edit `src/generators/shared/types.ts` - Add field to `MethodInfo`
643
+ 2. Edit `src/generators/use-fetch/parser.ts` - Extract from AST
644
+ 3. Edit `src/generators/*/templates.ts` - Use in generation
645
+ 4. Test with complex OpenAPI spec
646
+
647
+ ---
648
+
649
+ **Next**: [API Reference](./API-REFERENCE.md) | [Development Guide](./DEVELOPMENT.md)