nuxt-openapi-hyperfetch 0.1.8-alpha.1 → 0.2.8-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 (60) hide show
  1. package/.editorconfig +26 -26
  2. package/.prettierignore +17 -17
  3. package/CONTRIBUTING.md +291 -291
  4. package/INSTRUCTIONS.md +327 -327
  5. package/LICENSE +202 -202
  6. package/README.md +231 -231
  7. package/dist/cli/config.d.ts +9 -2
  8. package/dist/cli/config.js +1 -1
  9. package/dist/cli/logo.js +5 -5
  10. package/dist/cli/messages.d.ts +1 -0
  11. package/dist/cli/messages.js +2 -0
  12. package/dist/cli/prompts.d.ts +5 -0
  13. package/dist/cli/prompts.js +12 -0
  14. package/dist/cli/types.d.ts +1 -1
  15. package/dist/generators/components/connector-generator/templates.js +12 -12
  16. package/dist/generators/use-async-data/templates.js +17 -17
  17. package/dist/generators/use-fetch/templates.js +14 -14
  18. package/dist/index.js +39 -27
  19. package/dist/module/index.js +19 -0
  20. package/dist/module/types.d.ts +7 -0
  21. package/docs/API-REFERENCE.md +886 -886
  22. package/docs/generated-components.md +615 -0
  23. package/docs/headless-composables-ui.md +569 -0
  24. package/eslint.config.js +85 -85
  25. package/package.json +8 -2
  26. package/src/cli/config.ts +147 -140
  27. package/src/cli/logger.ts +124 -124
  28. package/src/cli/logo.ts +25 -25
  29. package/src/cli/messages.ts +4 -0
  30. package/src/cli/prompts.ts +14 -1
  31. package/src/cli/types.ts +50 -50
  32. package/src/generators/components/connector-generator/generator.ts +138 -0
  33. package/src/generators/components/connector-generator/templates.ts +254 -0
  34. package/src/generators/components/connector-generator/types.ts +34 -0
  35. package/src/generators/components/schema-analyzer/index.ts +44 -0
  36. package/src/generators/components/schema-analyzer/intent-detector.ts +187 -0
  37. package/src/generators/components/schema-analyzer/openapi-reader.ts +96 -0
  38. package/src/generators/components/schema-analyzer/resource-grouper.ts +166 -0
  39. package/src/generators/components/schema-analyzer/schema-field-mapper.ts +268 -0
  40. package/src/generators/components/schema-analyzer/types.ts +177 -0
  41. package/src/generators/nuxt-server/generator.ts +272 -272
  42. package/src/generators/shared/runtime/apiHelpers.ts +535 -507
  43. package/src/generators/shared/runtime/pagination.ts +323 -0
  44. package/src/generators/shared/runtime/useDeleteConnector.ts +109 -0
  45. package/src/generators/shared/runtime/useDetailConnector.ts +64 -0
  46. package/src/generators/shared/runtime/useFormConnector.ts +139 -0
  47. package/src/generators/shared/runtime/useListConnector.ts +148 -0
  48. package/src/generators/shared/runtime/zod-error-merger.ts +119 -0
  49. package/src/generators/shared/templates/api-callbacks-plugin.ts +399 -352
  50. package/src/generators/shared/templates/api-pagination-plugin.ts +158 -0
  51. package/src/generators/use-async-data/generator.ts +205 -205
  52. package/src/generators/use-async-data/runtime/useApiAsyncData.ts +329 -229
  53. package/src/generators/use-async-data/runtime/useApiAsyncDataRaw.ts +324 -245
  54. package/src/generators/use-async-data/templates.ts +257 -257
  55. package/src/generators/use-fetch/generator.ts +170 -170
  56. package/src/generators/use-fetch/runtime/useApiRequest.ts +354 -234
  57. package/src/generators/use-fetch/templates.ts +214 -214
  58. package/src/index.ts +305 -265
  59. package/src/module/index.ts +158 -133
  60. package/src/module/types.ts +39 -31
@@ -2,18 +2,18 @@
2
2
  * Generate file header with auto-generation warning
3
3
  */
4
4
  function generateFileHeader() {
5
- return `/**
6
- * ⚠️ AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
7
- *
8
- * This file was automatically generated by nuxt-openapi-generator.
9
- * Any manual changes will be overwritten on the next generation.
10
- *
11
- * @generated by nuxt-openapi-generator
12
- * @see https://github.com/dmartindiaz/nuxt-openapi-hyperfetch
13
- */
14
-
15
- /* eslint-disable */
16
- // @ts-nocheck
5
+ return `/**
6
+ * ⚠️ AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
7
+ *
8
+ * This file was automatically generated by nuxt-openapi-generator.
9
+ * Any manual changes will be overwritten on the next generation.
10
+ *
11
+ * @generated by nuxt-openapi-generator
12
+ * @see https://github.com/dmartindiaz/nuxt-openapi-hyperfetch
13
+ */
14
+
15
+ /* eslint-disable */
16
+ // @ts-nocheck
17
17
  `;
18
18
  }
19
19
  /**
@@ -95,8 +95,8 @@ function generateFunctionBody(method, options) {
95
95
  const fetchOptions = generateFetchOptions(method, options);
96
96
  const description = method.description ? `/**\n * ${method.description}\n */\n` : '';
97
97
  const pInit = hasParams ? `\n const p = shallowRef(params)` : '';
98
- return `${description}export const ${method.composableName} = (${args}) => {${pInit}
99
- return useApiRequest${responseTypeGeneric}(${url}, ${fetchOptions})
98
+ return `${description}export const ${method.composableName} = (${args}) => {${pInit}
99
+ return useApiRequest${responseTypeGeneric}(${url}, ${fetchOptions})
100
100
  }`;
101
101
  }
102
102
  /**
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import { generateUseFetchComposables } from './generators/use-fetch/generator.js
6
6
  import { generateUseAsyncDataComposables } from './generators/use-async-data/generator.js';
7
7
  import { generateNuxtServerRoutes } from './generators/nuxt-server/generator.js';
8
8
  import { generateConnectors } from './generators/components/connector-generator/generator.js';
9
- import { promptInitialInputs, promptInputPath, promptComposablesSelection, promptServerRoutePath, promptBffConfig, promptGeneratorBackend, } from './cli/prompts.js';
9
+ import { promptInitialInputs, promptInputPath, promptComposablesSelection, promptServerRoutePath, promptBffConfig, promptGeneratorBackend, promptConnectors, } from './cli/prompts.js';
10
10
  import { MESSAGES } from './cli/messages.js';
11
11
  import { displayLogo } from './cli/logo.js';
12
12
  import { loadConfig, mergeConfig, parseTags, parseGenerators } from './cli/config.js';
@@ -26,6 +26,7 @@ program
26
26
  .option('-v, --verbose', 'Enable verbose logging', false)
27
27
  .option('--watch', 'Watch mode - regenerate on file changes', false)
28
28
  .option('--generators <types>', 'Generators to use: useFetch,useAsyncData,nuxtServer')
29
+ .option('--connectors', 'Generate headless UI connectors on top of useAsyncData', false)
29
30
  .option('--server-route-path <path>', 'Server route path (for nuxtServer mode)')
30
31
  .option('--enable-bff', 'Enable BFF pattern (for nuxtServer mode)', false)
31
32
  .option('--backend <type>', 'Generator backend: official (Java) or heyapi (Node.js)')
@@ -54,6 +55,7 @@ program
54
55
  backend: options.backend === 'official' || options.backend === 'heyapi'
55
56
  ? options.backend
56
57
  : undefined,
58
+ createUseAsyncDataConnectors: options.connectors,
57
59
  });
58
60
  if (config.verbose) {
59
61
  console.log('Configuration:', config);
@@ -85,7 +87,8 @@ program
85
87
  // 1. Determine composables to generate FIRST
86
88
  let composables;
87
89
  if (config.generators) {
88
- composables = config.generators;
90
+ // filter out 'connectors' — handled separately below
91
+ composables = config.generators.filter((g) => g !== 'connectors');
89
92
  if (config.verbose) {
90
93
  console.log(`Using generators from config: ${composables.join(', ')}`);
91
94
  }
@@ -114,7 +117,17 @@ program
114
117
  inputPath = await promptInputPath(config.input);
115
118
  outputPath = config.output ?? './swagger';
116
119
  }
117
- // 3. Ask for server route path if nuxtServer is selected
120
+ // 3. Ask whether to generate headless connectors (only if useAsyncData selected)
121
+ let generateConnectorsFlag = false;
122
+ if (composables.includes('useAsyncData')) {
123
+ if (config.createUseAsyncDataConnectors !== undefined) {
124
+ generateConnectorsFlag = config.createUseAsyncDataConnectors;
125
+ }
126
+ else {
127
+ generateConnectorsFlag = await promptConnectors();
128
+ }
129
+ }
130
+ // 4. Ask for server route path if nuxtServer is selected
118
131
  let serverRoutePath = config.serverRoutePath || '';
119
132
  let enableBff = config.enableBff || false;
120
133
  if (needsNuxtServer && !config.serverRoutePath) {
@@ -181,6 +194,29 @@ program
181
194
  throw error;
182
195
  }
183
196
  }
197
+ // Generate headless connectors if requested (requires useAsyncData)
198
+ if (generateConnectorsFlag) {
199
+ const spinner = p.spinner();
200
+ spinner.start('Generating headless UI connectors...');
201
+ try {
202
+ if (!config.dryRun) {
203
+ await generateConnectors({
204
+ inputSpec: inputPath,
205
+ outputDir: `${composablesOutputDir}/connectors`,
206
+ composablesRelDir: '../use-async-data',
207
+ runtimeRelDir: '../../runtime',
208
+ });
209
+ spinner.stop('✓ Generated headless UI connectors');
210
+ }
211
+ else {
212
+ spinner.stop('Would generate headless UI connectors (dry-run)');
213
+ }
214
+ }
215
+ catch (error) {
216
+ spinner.stop('✗ Failed to generate connectors');
217
+ throw error;
218
+ }
219
+ }
184
220
  if (config.dryRun) {
185
221
  p.outro('🔍 Dry run complete - no files were modified');
186
222
  }
@@ -211,28 +247,4 @@ program
211
247
  process.exit(1);
212
248
  }
213
249
  });
214
- program
215
- .command('connectors')
216
- .description('Generate headless connector composables from an OpenAPI spec')
217
- .requiredOption('-i, --input <path>', 'Path to OpenAPI YAML or JSON spec')
218
- .requiredOption('-o, --output <path>', 'Output directory for connector composables')
219
- .option('--composables-dir <relPath>', 'Relative path from output dir to useAsyncData composables (default: ../use-async-data)')
220
- .option('--runtime-dir <relPath>', 'Relative path from output dir where runtime helpers are copied (default: ../runtime)')
221
- .action(async (options) => {
222
- try {
223
- displayLogo();
224
- p.intro('Generating connector composables…');
225
- await generateConnectors({
226
- inputSpec: options.input,
227
- outputDir: options.output,
228
- composablesRelDir: options.composablesDir,
229
- runtimeRelDir: options.runtimeDir,
230
- });
231
- p.outro('Done!');
232
- }
233
- catch (error) {
234
- p.log.error(`Error: ${String(error)}`);
235
- process.exit(1);
236
- }
237
- });
238
250
  program.parse();
@@ -5,6 +5,7 @@ import { checkJavaInstalled } from '../generate.js';
5
5
  import { generateUseFetchComposables } from '../generators/use-fetch/generator.js';
6
6
  import { generateUseAsyncDataComposables } from '../generators/use-async-data/generator.js';
7
7
  import { generateNuxtServerRoutes } from '../generators/nuxt-server/generator.js';
8
+ import { generateConnectors } from '../generators/components/connector-generator/generator.js';
8
9
  import { createConsoleLogger } from '../cli/logger.js';
9
10
  export default defineNuxtModule({
10
11
  meta: {
@@ -19,6 +20,7 @@ export default defineNuxtModule({
19
20
  enableProductionBuild: true,
20
21
  enableAutoGeneration: false,
21
22
  enableAutoImport: true,
23
+ createUseAsyncDataConnectors: false,
22
24
  },
23
25
  setup(options, nuxt) {
24
26
  // --- Guard: input is required ---
@@ -64,6 +66,20 @@ export default defineNuxtModule({
64
66
  const serverRoutePath = path.resolve(nuxt.options.rootDir, options.serverRoutePath ?? 'server/routes/api');
65
67
  await generateNuxtServerRoutes(resolvedOutput, serverRoutePath, { enableBff: options.enableBff, backend }, logger);
66
68
  }
69
+ // 3. Generate headless connectors if requested (requires useAsyncData)
70
+ if (options.createUseAsyncDataConnectors &&
71
+ selectedGenerators.includes('useAsyncData')) {
72
+ const connectorsOutputDir = path.join(composablesOutputDir, 'connectors');
73
+ const runtimeDir = path.join(resolvedOutput, 'runtime');
74
+ await generateConnectors({
75
+ inputSpec: resolvedInput,
76
+ outputDir: connectorsOutputDir,
77
+ composablesRelDir: '../use-async-data',
78
+ runtimeRelDir: '../../runtime',
79
+ }, logger);
80
+ // Register #nxh alias so generated connector imports resolve
81
+ nuxt.options.alias['#nxh'] = runtimeDir;
82
+ }
67
83
  };
68
84
  // --- Hooks: dev build / production build ---
69
85
  const isDev = nuxt.options.dev;
@@ -88,6 +104,9 @@ export default defineNuxtModule({
88
104
  if (selectedGenerators.includes('useAsyncData')) {
89
105
  addImportsDir(path.join(composablesOutputDir, 'use-async-data', 'composables'));
90
106
  }
107
+ if (options.createUseAsyncDataConnectors && selectedGenerators.includes('useAsyncData')) {
108
+ addImportsDir(path.join(composablesOutputDir, 'connectors'));
109
+ }
91
110
  }
92
111
  },
93
112
  });
@@ -24,4 +24,11 @@ export interface ModuleOptions extends GeneratorConfig {
24
24
  * @default true
25
25
  */
26
26
  enableAutoImport?: boolean;
27
+ /**
28
+ * Generate headless UI connector composables on top of useAsyncData.
29
+ * Connectors provide ready-made logic for tables, pagination, forms and delete actions.
30
+ * Requires useAsyncData to also be in generators.
31
+ * @default false
32
+ */
33
+ createUseAsyncDataConnectors?: boolean;
27
34
  }