nuxt-openapi-hyperfetch 1.0.3 → 1.0.4
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/README.md +105 -48
- package/dist/cli/config.d.ts +15 -49
- package/dist/cli/config.js +42 -6
- package/dist/config/connectors.d.ts +6 -0
- package/dist/config/connectors.js +26 -0
- package/dist/config/types.d.ts +62 -0
- package/dist/config/types.js +1 -0
- package/dist/generators/connectors/config-resolver.d.ts +3 -0
- package/dist/generators/connectors/config-resolver.js +207 -0
- package/dist/generators/connectors/generator.js +3 -1
- package/dist/generators/connectors/templates.js +6 -2
- package/dist/generators/connectors/types.d.ts +3 -0
- package/dist/index.js +27 -10
- package/dist/module/index.js +11 -3
- package/dist/module/types.d.ts +4 -4
- package/docs/QUICK-START.md +44 -4
- package/package.json +14 -8
- package/src/cli/config.ts +61 -57
- package/src/config/connectors.ts +48 -0
- package/src/config/types.ts +67 -0
- package/src/generators/connectors/config-resolver.ts +303 -0
- package/src/generators/connectors/generator.ts +3 -1
- package/src/generators/connectors/templates.ts +5 -2
- package/src/generators/connectors/types.ts +4 -0
- package/src/index.ts +41 -12
- package/src/module/index.ts +18 -3
- package/src/module/types.ts +4 -4
package/README.md
CHANGED
|
@@ -49,10 +49,10 @@ One composable per endpoint, for when you need direct control:
|
|
|
49
49
|
|
|
50
50
|
```ts
|
|
51
51
|
// useFetch — reactive, bound to template lifecycle
|
|
52
|
-
const { data: pet, pending, error } = useFetchGetPetById({ petId: 123 })
|
|
52
|
+
const { data: pet, pending, error } = useFetchGetPetById({ petId: 123 });
|
|
53
53
|
|
|
54
54
|
// useAsyncData — SSR-compatible, awaitable
|
|
55
|
-
const { data: pets } = await useAsyncDataFindPets({ status: 'available' })
|
|
55
|
+
const { data: pets } = await useAsyncDataFindPets({ status: 'available' });
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
With callbacks and request modification:
|
|
@@ -64,13 +64,13 @@ const { data } = useFetchFindPets(
|
|
|
64
64
|
{
|
|
65
65
|
onRequest: (ctx) => {
|
|
66
66
|
// ctx: { url, method, headers, query, body }
|
|
67
|
-
return { headers: { 'X-Source': 'pets-page' } }
|
|
67
|
+
return { headers: { 'X-Source': 'pets-page' } };
|
|
68
68
|
},
|
|
69
69
|
onSuccess: (pets) => console.log(`${pets.length} pets loaded`),
|
|
70
70
|
onError: (err) => console.error(err.message),
|
|
71
71
|
onFinish: ({ success }) => console.log('Done:', success),
|
|
72
72
|
}
|
|
73
|
-
)
|
|
73
|
+
);
|
|
74
74
|
|
|
75
75
|
// useAsyncData — onSuccess and onError receive a second context argument
|
|
76
76
|
const { data: pets } = await useAsyncDataFindPets(
|
|
@@ -80,7 +80,7 @@ const { data: pets } = await useAsyncDataFindPets(
|
|
|
80
80
|
onSuccess: (pets, ctx) => console.log(`${pets.length} from ${ctx.url}`),
|
|
81
81
|
onError: (err, ctx) => console.error(err.message, ctx.url),
|
|
82
82
|
}
|
|
83
|
-
)
|
|
83
|
+
);
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
---
|
|
@@ -95,7 +95,7 @@ Client → Nuxt Server Route (generated) → External API
|
|
|
95
95
|
|
|
96
96
|
```ts
|
|
97
97
|
// Works automatically after generation
|
|
98
|
-
const { data } = useFetch('/api/pet/123')
|
|
98
|
+
const { data } = useFetch('/api/pet/123');
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
---
|
|
@@ -105,19 +105,19 @@ const { data } = useFetch('/api/pet/123')
|
|
|
105
105
|
A connector exposes five sub-composables for one resource. For a `pet` tag in your spec:
|
|
106
106
|
|
|
107
107
|
```ts
|
|
108
|
-
const { getAll, get, create, update, del } = usePetsConnector()
|
|
108
|
+
const { getAll, get, create, update, del } = usePetsConnector();
|
|
109
109
|
```
|
|
110
110
|
|
|
111
111
|
### Full CRUD page in one component
|
|
112
112
|
|
|
113
113
|
```vue
|
|
114
114
|
<script setup lang="ts">
|
|
115
|
-
const { getAll, create, update, del } = usePetsConnector()
|
|
115
|
+
const { getAll, create, update, del } = usePetsConnector();
|
|
116
116
|
|
|
117
117
|
// Reload the list after every mutation
|
|
118
|
-
create.onSuccess(() => getAll.load())
|
|
119
|
-
update.onSuccess(() => getAll.load())
|
|
120
|
-
del.onSuccess(()
|
|
118
|
+
create.onSuccess(() => getAll.load());
|
|
119
|
+
update.onSuccess(() => getAll.load());
|
|
120
|
+
del.onSuccess(() => getAll.load());
|
|
121
121
|
</script>
|
|
122
122
|
|
|
123
123
|
<template>
|
|
@@ -141,8 +141,7 @@ del.onSuccess(() => getAll.load())
|
|
|
141
141
|
<UInput v-model="create.model.value.name" />
|
|
142
142
|
</UFormField>
|
|
143
143
|
<UFormField label="Status">
|
|
144
|
-
<USelect v-model="create.model.value.status"
|
|
145
|
-
:options="['available','pending','sold']" />
|
|
144
|
+
<USelect v-model="create.model.value.status" :options="['available', 'pending', 'sold']" />
|
|
146
145
|
</UFormField>
|
|
147
146
|
<template #footer>
|
|
148
147
|
<UButton :loading="create.loading.value" @click="create.execute()">Save</UButton>
|
|
@@ -155,8 +154,9 @@ del.onSuccess(() => getAll.load())
|
|
|
155
154
|
<UCard>
|
|
156
155
|
<UInput v-model="update.model.value.name" />
|
|
157
156
|
<template #footer>
|
|
158
|
-
<UButton :loading="update.loading.value"
|
|
159
|
-
|
|
157
|
+
<UButton :loading="update.loading.value" @click="update.execute(update.model.value.id)"
|
|
158
|
+
>Save changes</UButton
|
|
159
|
+
>
|
|
160
160
|
</template>
|
|
161
161
|
</UCard>
|
|
162
162
|
</UModal>
|
|
@@ -164,7 +164,10 @@ del.onSuccess(() => getAll.load())
|
|
|
164
164
|
<!-- Delete confirmation -->
|
|
165
165
|
<UModal v-model:open="del.ui.isOpen.value">
|
|
166
166
|
<UCard>
|
|
167
|
-
<p>
|
|
167
|
+
<p>
|
|
168
|
+
Delete <strong>{{ del.staged.value?.name }}</strong
|
|
169
|
+
>?
|
|
170
|
+
</p>
|
|
168
171
|
<template #footer>
|
|
169
172
|
<UButton color="red" :loading="del.loading.value" @click="del.execute()">Delete</UButton>
|
|
170
173
|
<UButton variant="outline" @click="del.ui.close()">Cancel</UButton>
|
|
@@ -176,21 +179,21 @@ del.onSuccess(() => getAll.load())
|
|
|
176
179
|
|
|
177
180
|
### What each sub-connector provides
|
|
178
181
|
|
|
179
|
-
| Key
|
|
180
|
-
|
|
182
|
+
| Key | Transport | What you get |
|
|
183
|
+
| -------- | -------------- | -------------------------------------------------------------------------- |
|
|
181
184
|
| `getAll` | `useAsyncData` | `items`, `columns`, `loading`, `error`, `pagination`, `selected`, `load()` |
|
|
182
|
-
| `get`
|
|
183
|
-
| `create` | `$fetch`
|
|
184
|
-
| `update` | `$fetch`
|
|
185
|
-
| `del`
|
|
185
|
+
| `get` | `$fetch` | `data`, `loading`, `error`, `load(id)`, `clear()` |
|
|
186
|
+
| `create` | `$fetch` | `model`, `errors`, `isValid`, `execute()`, `reset()`, `ui.open/close` |
|
|
187
|
+
| `update` | `$fetch` | Same as create + `load(id)`, `ui.open(row)`, `targetId` |
|
|
188
|
+
| `del` | `$fetch` | `staged`, `hasStaged`, `execute()`, `ui.open(item)/close` |
|
|
186
189
|
|
|
187
190
|
### Reactive list parameters
|
|
188
191
|
|
|
189
192
|
```ts
|
|
190
|
-
const status = ref('available')
|
|
193
|
+
const status = ref('available');
|
|
191
194
|
|
|
192
195
|
// Re-fetches automatically when status changes
|
|
193
|
-
const { getAll } = usePetsConnector(() => ({ status: status.value }))
|
|
196
|
+
const { getAll } = usePetsConnector(() => ({ status: status.value }));
|
|
194
197
|
```
|
|
195
198
|
|
|
196
199
|
### Zod validation, out of the box
|
|
@@ -199,11 +202,15 @@ Schemas are generated from your OpenAPI `requestBody`. `create.execute()` valida
|
|
|
199
202
|
|
|
200
203
|
```ts
|
|
201
204
|
// Extend the generated schema for extra rules
|
|
202
|
-
const { create } = usePetsConnector(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
205
|
+
const { create } = usePetsConnector(
|
|
206
|
+
{},
|
|
207
|
+
{
|
|
208
|
+
createSchema: (base) =>
|
|
209
|
+
base.extend({
|
|
210
|
+
name: z.string().min(2, 'At least 2 characters'),
|
|
211
|
+
}),
|
|
212
|
+
}
|
|
213
|
+
);
|
|
207
214
|
```
|
|
208
215
|
|
|
209
216
|
### Global callbacks
|
|
@@ -215,11 +222,11 @@ Register once, applies to every API call in the app:
|
|
|
215
222
|
defineGlobalApiCallbacks([
|
|
216
223
|
{
|
|
217
224
|
onRequest: (ctx) => ({
|
|
218
|
-
headers: { Authorization: `Bearer ${useAuthStore().token}` }
|
|
225
|
+
headers: { Authorization: `Bearer ${useAuthStore().token}` },
|
|
219
226
|
}),
|
|
220
227
|
onError: (err) => useToast().add({ title: err.message, color: 'red' }),
|
|
221
|
-
}
|
|
222
|
-
])
|
|
228
|
+
},
|
|
229
|
+
]);
|
|
223
230
|
```
|
|
224
231
|
|
|
225
232
|
Connector-level and per-operation callbacks are also available — see [Callbacks docs](./docs/connectors/callbacks.md).
|
|
@@ -242,6 +249,55 @@ nxh generate -i ./swagger.yaml -o ./composables/api
|
|
|
242
249
|
|
|
243
250
|
The CLI asks for your spec path, output folder, engine (`heyapi` or `official`), and which generators to run.
|
|
244
251
|
|
|
252
|
+
### Generators semantics (CLI + config)
|
|
253
|
+
|
|
254
|
+
`generators` now supports `connectors` as a declarative option.
|
|
255
|
+
|
|
256
|
+
- `['connectors']` → generates `useAsyncData` + `connectors`
|
|
257
|
+
- `['useAsyncData']` → generates only `useAsyncData`
|
|
258
|
+
- `['useAsyncData', 'connectors']` → generates both
|
|
259
|
+
|
|
260
|
+
`createUseAsyncDataConnectors` is still supported for backward compatibility, but `generators: ['connectors']` is the recommended setup.
|
|
261
|
+
|
|
262
|
+
### Typed `nxh.config.ts`
|
|
263
|
+
|
|
264
|
+
The CLI now supports `nxh.config.ts` (besides `.js`/`.mjs`).
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
// nxh.config.ts
|
|
268
|
+
import type { GeneratorConfig } from 'nuxt-openapi-hyperfetch';
|
|
269
|
+
|
|
270
|
+
const config: GeneratorConfig = {
|
|
271
|
+
input: './swagger.yaml',
|
|
272
|
+
output: './composables/api',
|
|
273
|
+
generators: ['useAsyncData', 'connectors'],
|
|
274
|
+
connectors: {
|
|
275
|
+
strategy: 'hybrid',
|
|
276
|
+
resources: {
|
|
277
|
+
pets: {
|
|
278
|
+
operations: {
|
|
279
|
+
getAll: { operationId: 'findPetsByStatus' },
|
|
280
|
+
get: { path: '/pet/{petId}' },
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
featuredPets: {
|
|
284
|
+
operations: {
|
|
285
|
+
getAll: { operationId: 'findPetsByTags' },
|
|
286
|
+
get: { operationId: 'getPetById' },
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
export default config;
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
`connectors.strategy` supports:
|
|
297
|
+
|
|
298
|
+
- `manual`: generate only resources defined by the user
|
|
299
|
+
- `hybrid`: start from inferred resources and apply user overrides/custom resources
|
|
300
|
+
|
|
245
301
|
### Nuxt module
|
|
246
302
|
|
|
247
303
|
```ts
|
|
@@ -252,11 +308,11 @@ export default defineNuxtConfig({
|
|
|
252
308
|
openApiHyperFetch: {
|
|
253
309
|
input: './swagger.yaml',
|
|
254
310
|
output: './composables/api',
|
|
255
|
-
generators: ['useFetch', '
|
|
311
|
+
generators: ['useFetch', 'connectors', 'nuxtServer'],
|
|
256
312
|
backend: 'heyapi',
|
|
257
313
|
enableAutoImport: true,
|
|
258
314
|
},
|
|
259
|
-
})
|
|
315
|
+
});
|
|
260
316
|
```
|
|
261
317
|
|
|
262
318
|
### Configure the base URL
|
|
@@ -264,7 +320,9 @@ export default defineNuxtConfig({
|
|
|
264
320
|
```ts
|
|
265
321
|
// nuxt.config.ts
|
|
266
322
|
runtimeConfig: {
|
|
267
|
-
public: {
|
|
323
|
+
public: {
|
|
324
|
+
apiBaseUrl: process.env.NUXT_PUBLIC_API_BASE_URL || 'https://api.example.com';
|
|
325
|
+
}
|
|
268
326
|
}
|
|
269
327
|
```
|
|
270
328
|
|
|
@@ -274,28 +332,28 @@ All generated composables and connectors pick up `apiBaseUrl` automatically.
|
|
|
274
332
|
|
|
275
333
|
## Two generation engines
|
|
276
334
|
|
|
277
|
-
| Engine
|
|
278
|
-
|
|
279
|
-
| `heyapi`
|
|
280
|
-
| `official` | Java 11+
|
|
335
|
+
| Engine | Requires | Best for |
|
|
336
|
+
| ---------- | --------- | -------------------------- |
|
|
337
|
+
| `heyapi` | Node only | Quick setup, CI/CD |
|
|
338
|
+
| `official` | Java 11+ | Maximum spec compatibility |
|
|
281
339
|
|
|
282
340
|
Pre-select in `nxh.config.js` to skip the prompt:
|
|
283
341
|
|
|
284
342
|
```js
|
|
285
|
-
export default { generator: 'heyapi', input: './swagger.yaml', output: './api' }
|
|
343
|
+
export default { generator: 'heyapi', input: './swagger.yaml', output: './api' };
|
|
286
344
|
```
|
|
287
345
|
|
|
288
346
|
---
|
|
289
347
|
|
|
290
348
|
## Documentation
|
|
291
349
|
|
|
292
|
-
|
|
|
293
|
-
|
|
294
|
-
| [Connectors](./docs/connectors/index.md)
|
|
295
|
-
| [Quick Start](./docs/QUICK-START.md)
|
|
296
|
-
| [API Reference](./docs/API-REFERENCE.md)
|
|
297
|
-
| [Architecture](./docs/ARCHITECTURE.md)
|
|
298
|
-
| [Troubleshooting](./docs/TROUBLESHOOTING.md) | Common errors and solutions
|
|
350
|
+
| | |
|
|
351
|
+
| -------------------------------------------- | --------------------------------------------- |
|
|
352
|
+
| [Connectors](./docs/connectors/index.md) | Full connector API reference and examples |
|
|
353
|
+
| [Quick Start](./docs/QUICK-START.md) | From zero to working composables in 5 minutes |
|
|
354
|
+
| [API Reference](./docs/API-REFERENCE.md) | All options and TypeScript types |
|
|
355
|
+
| [Architecture](./docs/ARCHITECTURE.md) | How the generator works internally |
|
|
356
|
+
| [Troubleshooting](./docs/TROUBLESHOOTING.md) | Common errors and solutions |
|
|
299
357
|
|
|
300
358
|
---
|
|
301
359
|
|
|
@@ -309,7 +367,6 @@ npm run validate # lint + type check
|
|
|
309
367
|
|
|
310
368
|
See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
311
369
|
|
|
312
|
-
|
|
313
370
|
---
|
|
314
371
|
|
|
315
372
|
## License
|
package/dist/cli/config.d.ts
CHANGED
|
@@ -1,53 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/** Path or URL to OpenAPI specification */
|
|
7
|
-
input?: string;
|
|
8
|
-
/** Output directory for generated files */
|
|
9
|
-
output?: string;
|
|
10
|
-
/** Base URL for API requests */
|
|
11
|
-
baseUrl?: string;
|
|
12
|
-
/** Generation mode: client or server */
|
|
13
|
-
mode?: 'client' | 'server';
|
|
14
|
-
/** Generate only specific tags */
|
|
15
|
-
tags?: string[];
|
|
16
|
-
/** Exclude specific tags */
|
|
17
|
-
excludeTags?: string[];
|
|
18
|
-
/** Overwrite existing files without prompting */
|
|
19
|
-
overwrite?: boolean;
|
|
20
|
-
/** Preview changes without writing files */
|
|
21
|
-
dryRun?: boolean;
|
|
22
|
-
/** Enable verbose logging */
|
|
23
|
-
verbose?: boolean;
|
|
24
|
-
/** Watch mode - regenerate on file changes */
|
|
25
|
-
watch?: boolean;
|
|
26
|
-
/** Generator types to use */
|
|
27
|
-
generators?: ('useFetch' | 'useAsyncData' | 'nuxtServer' | 'connectors')[];
|
|
28
|
-
/** Server route path (for nuxtServer mode) */
|
|
29
|
-
serverRoutePath?: string;
|
|
30
|
-
/** Enable BFF pattern (for nuxtServer mode) */
|
|
31
|
-
enableBff?: boolean;
|
|
32
|
-
/** Generator backend: official (Java) or heyapi (Node.js) */
|
|
33
|
-
backend?: GeneratorBackend;
|
|
34
|
-
/**
|
|
35
|
-
* Generation engine to use.
|
|
36
|
-
* - 'openapi': @openapitools/openapi-generator-cli (requires Java 11+)
|
|
37
|
-
* - 'heyapi': @hey-api/openapi-ts (Node.js native, no Java required)
|
|
38
|
-
* When set, the CLI will not ask which engine to use.
|
|
39
|
-
*/
|
|
40
|
-
generator?: ConfigGenerator;
|
|
41
|
-
/**
|
|
42
|
-
* Generate headless UI connector composables on top of useAsyncData.
|
|
43
|
-
* Connectors provide ready-made logic for tables, pagination, forms and delete actions.
|
|
44
|
-
* Requires useAsyncData to also be generated.
|
|
45
|
-
* @default false
|
|
46
|
-
*/
|
|
47
|
-
createUseAsyncDataConnectors?: boolean;
|
|
1
|
+
import type { GeneratorConfig, GeneratorType } from '../config/types.js';
|
|
2
|
+
export type ComposableGeneratorType = 'useFetch' | 'useAsyncData' | 'nuxtServer';
|
|
3
|
+
export interface NormalizedGenerators {
|
|
4
|
+
composables: ComposableGeneratorType[];
|
|
5
|
+
generateConnectors: boolean;
|
|
48
6
|
}
|
|
49
7
|
/**
|
|
50
|
-
* Load configuration from nxh.config.js, nuxt-openapi-
|
|
8
|
+
* Load configuration from nxh.config.{ts,js,mjs}, nuxt-openapi-hyperfetch.{ts,js,mjs}, or package.json
|
|
51
9
|
*/
|
|
52
10
|
export declare function loadConfig(cwd?: string): Promise<GeneratorConfig | null>;
|
|
53
11
|
/**
|
|
@@ -61,4 +19,12 @@ export declare function parseTags(tagsString?: string): string[] | undefined;
|
|
|
61
19
|
/**
|
|
62
20
|
* Parse generators string into array
|
|
63
21
|
*/
|
|
64
|
-
export declare function parseGenerators(generatorsString?: string):
|
|
22
|
+
export declare function parseGenerators(generatorsString?: string): GeneratorType[] | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Normalize generator selection so connectors can be requested declaratively.
|
|
25
|
+
* Rules:
|
|
26
|
+
* - If `connectors` is selected, `useAsyncData` is added automatically.
|
|
27
|
+
* - If `createUseAsyncDataConnectors` is true, connectors are enabled and
|
|
28
|
+
* `useAsyncData` is added automatically.
|
|
29
|
+
*/
|
|
30
|
+
export declare function normalizeGenerators(generators?: GeneratorType[], createUseAsyncDataConnectors?: boolean): NormalizedGenerators;
|
package/dist/cli/config.js
CHANGED
|
@@ -1,15 +1,38 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import { join } from 'path';
|
|
3
|
+
import { pathToFileURL } from 'url';
|
|
3
4
|
import * as p from '@clack/prompts';
|
|
4
5
|
const { existsSync } = fs;
|
|
6
|
+
const COMPOSABLE_GENERATOR_ORDER = [
|
|
7
|
+
'useFetch',
|
|
8
|
+
'useAsyncData',
|
|
9
|
+
'nuxtServer',
|
|
10
|
+
];
|
|
11
|
+
async function importConfigModule(configPath) {
|
|
12
|
+
try {
|
|
13
|
+
const module = await import(pathToFileURL(configPath).href);
|
|
14
|
+
return module.default || module;
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
if (!configPath.endsWith('.ts')) {
|
|
18
|
+
throw error;
|
|
19
|
+
}
|
|
20
|
+
const { createJiti } = await import('jiti');
|
|
21
|
+
const jiti = createJiti(import.meta.url, { interopDefault: true });
|
|
22
|
+
const module = jiti(configPath);
|
|
23
|
+
return module?.default || module;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
5
26
|
/**
|
|
6
|
-
* Load configuration from nxh.config.js, nuxt-openapi-
|
|
27
|
+
* Load configuration from nxh.config.{ts,js,mjs}, nuxt-openapi-hyperfetch.{ts,js,mjs}, or package.json
|
|
7
28
|
*/
|
|
8
29
|
export async function loadConfig(cwd = process.cwd()) {
|
|
9
30
|
// Try different config file names
|
|
10
31
|
const configFiles = [
|
|
32
|
+
'nxh.config.ts',
|
|
11
33
|
'nxh.config.js',
|
|
12
34
|
'nxh.config.mjs',
|
|
35
|
+
'nuxt-openapi-hyperfetch.ts',
|
|
13
36
|
'nuxt-openapi-hyperfetch.js',
|
|
14
37
|
'nuxt-openapi-hyperfetch.mjs',
|
|
15
38
|
];
|
|
@@ -17,11 +40,8 @@ export async function loadConfig(cwd = process.cwd()) {
|
|
|
17
40
|
const configPath = join(cwd, configFile);
|
|
18
41
|
if (existsSync(configPath)) {
|
|
19
42
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
|
|
23
|
-
const exportedConfig = config.default || config;
|
|
24
|
-
return exportedConfig;
|
|
43
|
+
const config = await importConfigModule(configPath);
|
|
44
|
+
return config;
|
|
25
45
|
}
|
|
26
46
|
catch (error) {
|
|
27
47
|
p.log.warn(`Failed to load config from ${configFile}: ${String(error)}`);
|
|
@@ -83,3 +103,19 @@ export function parseGenerators(generatorsString) {
|
|
|
83
103
|
const parts = generatorsString.split(',').map((g) => g.trim());
|
|
84
104
|
return parts.filter((g) => ['useFetch', 'useAsyncData', 'nuxtServer', 'connectors'].includes(g));
|
|
85
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Normalize generator selection so connectors can be requested declaratively.
|
|
108
|
+
* Rules:
|
|
109
|
+
* - If `connectors` is selected, `useAsyncData` is added automatically.
|
|
110
|
+
* - If `createUseAsyncDataConnectors` is true, connectors are enabled and
|
|
111
|
+
* `useAsyncData` is added automatically.
|
|
112
|
+
*/
|
|
113
|
+
export function normalizeGenerators(generators, createUseAsyncDataConnectors) {
|
|
114
|
+
const requested = new Set(generators ?? []);
|
|
115
|
+
const generateConnectors = requested.has('connectors') || createUseAsyncDataConnectors === true;
|
|
116
|
+
const composables = COMPOSABLE_GENERATOR_ORDER.filter((generator) => requested.has(generator));
|
|
117
|
+
if (generateConnectors && !composables.includes('useAsyncData')) {
|
|
118
|
+
composables.push('useAsyncData');
|
|
119
|
+
}
|
|
120
|
+
return { composables, generateConnectors };
|
|
121
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ConnectorsConfig, GeneratorConfig, GeneratorType } from './types.js';
|
|
2
|
+
export type RuntimeComposableGenerator = 'useFetch' | 'useAsyncData' | 'nuxtServer';
|
|
3
|
+
export declare function hasConnectorsConfig(connectors?: ConnectorsConfig): boolean;
|
|
4
|
+
export declare function isConnectorsRequested(config: Pick<GeneratorConfig, 'generators' | 'createUseAsyncDataConnectors' | 'connectors'>): boolean;
|
|
5
|
+
export declare function toRuntimeComposableGenerators(generators?: GeneratorType[]): RuntimeComposableGenerator[];
|
|
6
|
+
export declare function ensureUseAsyncDataForConnectors(composables: RuntimeComposableGenerator[], connectorsRequested: boolean): RuntimeComposableGenerator[];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function hasConnectorsConfig(connectors) {
|
|
2
|
+
if (!connectors) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
if (connectors.enabled === true) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
if (connectors.strategy !== undefined) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
return Object.keys(connectors.resources ?? {}).length > 0;
|
|
12
|
+
}
|
|
13
|
+
export function isConnectorsRequested(config) {
|
|
14
|
+
return (config.createUseAsyncDataConnectors === true ||
|
|
15
|
+
(config.generators ?? []).includes('connectors') ||
|
|
16
|
+
hasConnectorsConfig(config.connectors));
|
|
17
|
+
}
|
|
18
|
+
export function toRuntimeComposableGenerators(generators) {
|
|
19
|
+
return (generators ?? []).filter((g) => g === 'useFetch' || g === 'useAsyncData' || g === 'nuxtServer');
|
|
20
|
+
}
|
|
21
|
+
export function ensureUseAsyncDataForConnectors(composables, connectorsRequested) {
|
|
22
|
+
if (!connectorsRequested || composables.includes('useAsyncData')) {
|
|
23
|
+
return composables;
|
|
24
|
+
}
|
|
25
|
+
return [...composables, 'useAsyncData'];
|
|
26
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { GeneratorBackend, ConfigGenerator } from '../cli/types.js';
|
|
2
|
+
export type GeneratorType = 'useFetch' | 'useAsyncData' | 'nuxtServer' | 'connectors';
|
|
3
|
+
export type ConnectorStrategy = 'manual' | 'hybrid';
|
|
4
|
+
export type ConnectorOperationName = 'getAll' | 'get' | 'create' | 'update' | 'delete';
|
|
5
|
+
export interface ConnectorOperationConfig {
|
|
6
|
+
operationId?: string;
|
|
7
|
+
path?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ConnectorResourceConfig {
|
|
10
|
+
operations?: Partial<Record<ConnectorOperationName, ConnectorOperationConfig>>;
|
|
11
|
+
}
|
|
12
|
+
export interface ConnectorsConfig {
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
strategy?: ConnectorStrategy;
|
|
15
|
+
resources?: Record<string, ConnectorResourceConfig>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Shared configuration contract used by both CLI (nxh.config.*) and Nuxt module (nuxt.config.ts).
|
|
19
|
+
*/
|
|
20
|
+
export interface GeneratorConfig {
|
|
21
|
+
/** Path or URL to OpenAPI specification */
|
|
22
|
+
input?: string;
|
|
23
|
+
/** Output directory for generated files */
|
|
24
|
+
output?: string;
|
|
25
|
+
/** Base URL for API requests */
|
|
26
|
+
baseUrl?: string;
|
|
27
|
+
/** Generation mode: client or server */
|
|
28
|
+
mode?: 'client' | 'server';
|
|
29
|
+
/** Generate only specific tags */
|
|
30
|
+
tags?: string[];
|
|
31
|
+
/** Exclude specific tags */
|
|
32
|
+
excludeTags?: string[];
|
|
33
|
+
/** Overwrite existing files without prompting */
|
|
34
|
+
overwrite?: boolean;
|
|
35
|
+
/** Preview changes without writing files */
|
|
36
|
+
dryRun?: boolean;
|
|
37
|
+
/** Enable verbose logging */
|
|
38
|
+
verbose?: boolean;
|
|
39
|
+
/** Watch mode - regenerate on file changes */
|
|
40
|
+
watch?: boolean;
|
|
41
|
+
/** Generator types to use */
|
|
42
|
+
generators?: GeneratorType[];
|
|
43
|
+
/** Server route path (for nuxtServer mode) */
|
|
44
|
+
serverRoutePath?: string;
|
|
45
|
+
/** Enable BFF pattern (for nuxtServer mode) */
|
|
46
|
+
enableBff?: boolean;
|
|
47
|
+
/** Generator backend: official (Java) or heyapi (Node.js) */
|
|
48
|
+
backend?: GeneratorBackend;
|
|
49
|
+
/**
|
|
50
|
+
* Generation engine to use.
|
|
51
|
+
* - 'openapi': @openapitools/openapi-generator-cli (requires Java 11+)
|
|
52
|
+
* - 'heyapi': @hey-api/openapi-ts (Node.js native, no Java required)
|
|
53
|
+
*/
|
|
54
|
+
generator?: ConfigGenerator;
|
|
55
|
+
/**
|
|
56
|
+
* Generate headless UI connector composables on top of useAsyncData.
|
|
57
|
+
* Requires useAsyncData to also be generated.
|
|
58
|
+
*/
|
|
59
|
+
createUseAsyncDataConnectors?: boolean;
|
|
60
|
+
/** Advanced connectors generation contract (manual/hybrid, custom resources, overloads). */
|
|
61
|
+
connectors?: ConnectorsConfig;
|
|
62
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|