nuxt-openapi-hyperfetch 0.2.7-alpha.1 → 0.3.0-beta

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 (68) 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 +309 -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 +68 -19
  16. package/dist/generators/shared/runtime/useFormConnector.js +8 -1
  17. package/dist/generators/shared/runtime/useListConnector.js +13 -6
  18. package/dist/generators/use-async-data/generator.js +4 -0
  19. package/dist/generators/use-async-data/runtime/useApiAsyncData.js +4 -4
  20. package/dist/generators/use-async-data/runtime/useApiAsyncDataRaw.js +4 -4
  21. package/dist/generators/use-async-data/templates.js +17 -17
  22. package/dist/generators/use-fetch/generator.js +4 -0
  23. package/dist/generators/use-fetch/templates.js +14 -14
  24. package/dist/index.js +40 -27
  25. package/dist/module/index.js +19 -0
  26. package/dist/module/types.d.ts +7 -0
  27. package/docs/API-REFERENCE.md +886 -886
  28. package/docs/generated-components.md +615 -615
  29. package/docs/headless-composables-ui.md +569 -569
  30. package/eslint.config.js +85 -85
  31. package/package.json +1 -1
  32. package/src/cli/config.ts +147 -140
  33. package/src/cli/logger.ts +124 -124
  34. package/src/cli/logo.ts +25 -25
  35. package/src/cli/messages.ts +4 -0
  36. package/src/cli/prompts.ts +14 -1
  37. package/src/cli/types.ts +50 -50
  38. package/src/generators/components/connector-generator/generator.ts +138 -138
  39. package/src/generators/components/connector-generator/templates.ts +307 -254
  40. package/src/generators/components/connector-generator/types.ts +34 -34
  41. package/src/generators/components/schema-analyzer/index.ts +44 -44
  42. package/src/generators/components/schema-analyzer/intent-detector.ts +187 -187
  43. package/src/generators/components/schema-analyzer/openapi-reader.ts +96 -96
  44. package/src/generators/components/schema-analyzer/resource-grouper.ts +166 -166
  45. package/src/generators/components/schema-analyzer/schema-field-mapper.ts +268 -268
  46. package/src/generators/components/schema-analyzer/types.ts +177 -177
  47. package/src/generators/nuxt-server/generator.ts +272 -272
  48. package/src/generators/shared/runtime/apiHelpers.ts +535 -535
  49. package/src/generators/shared/runtime/pagination.ts +323 -323
  50. package/src/generators/shared/runtime/useDeleteConnector.ts +109 -109
  51. package/src/generators/shared/runtime/useDetailConnector.ts +64 -64
  52. package/src/generators/shared/runtime/useFormConnector.ts +147 -139
  53. package/src/generators/shared/runtime/useListConnector.ts +158 -148
  54. package/src/generators/shared/runtime/zod-error-merger.ts +119 -119
  55. package/src/generators/shared/templates/api-callbacks-plugin.ts +399 -399
  56. package/src/generators/shared/templates/api-pagination-plugin.ts +158 -158
  57. package/src/generators/use-async-data/generator.ts +213 -205
  58. package/src/generators/use-async-data/runtime/useApiAsyncData.ts +329 -329
  59. package/src/generators/use-async-data/runtime/useApiAsyncDataRaw.ts +324 -324
  60. package/src/generators/use-async-data/templates.ts +257 -257
  61. package/src/generators/use-fetch/generator.ts +178 -170
  62. package/src/generators/use-fetch/runtime/useApiRequest.ts +354 -354
  63. package/src/generators/use-fetch/templates.ts +214 -214
  64. package/src/index.ts +306 -303
  65. package/src/module/index.ts +158 -133
  66. package/src/module/types.ts +39 -31
  67. package/dist/generators/tanstack-query/generator.d.ts +0 -5
  68. package/dist/generators/tanstack-query/generator.js +0 -11
package/eslint.config.js CHANGED
@@ -1,85 +1,85 @@
1
- // @ts-check
2
- import eslint from '@eslint/js';
3
- import tseslint from 'typescript-eslint';
4
- import prettierConfig from 'eslint-config-prettier';
5
- import prettierPlugin from 'eslint-plugin-prettier';
6
-
7
- export default tseslint.config(
8
- eslint.configs.recommended,
9
- ...tseslint.configs.recommendedTypeChecked,
10
- prettierConfig,
11
- {
12
- plugins: {
13
- prettier: prettierPlugin,
14
- },
15
- languageOptions: {
16
- parserOptions: {
17
- project: './tsconfig.json',
18
- tsconfigRootDir: import.meta.dirname,
19
- },
20
- },
21
- rules: {
22
- 'prettier/prettier': 'error',
23
- '@typescript-eslint/no-explicit-any': 'warn',
24
- '@typescript-eslint/explicit-function-return-type': 'off',
25
- '@typescript-eslint/explicit-module-boundary-types': 'off',
26
- '@typescript-eslint/no-unused-vars': [
27
- 'error',
28
- {
29
- argsIgnorePattern: '^_',
30
- varsIgnorePattern: '^_',
31
- },
32
- ],
33
- '@typescript-eslint/no-floating-promises': 'error',
34
- '@typescript-eslint/no-misused-promises': 'error',
35
- '@typescript-eslint/no-unsafe-assignment': 'warn',
36
- '@typescript-eslint/no-unsafe-member-access': 'warn',
37
- '@typescript-eslint/no-unsafe-call': 'warn',
38
- '@typescript-eslint/no-unsafe-return': 'warn',
39
- '@typescript-eslint/no-unsafe-argument': 'warn',
40
- '@typescript-eslint/restrict-template-expressions': 'warn',
41
- '@typescript-eslint/ban-ts-comment': [
42
- 'error',
43
- {
44
- 'ts-nocheck': 'allow-with-description',
45
- minimumDescriptionLength: 10,
46
- },
47
- ],
48
- 'no-console': 'off',
49
- 'prefer-const': 'error',
50
- 'no-var': 'error',
51
- 'no-useless-escape': 'warn',
52
- eqeqeq: ['error', 'always'],
53
- curly: ['error', 'all'],
54
- },
55
- },
56
- {
57
- // src/module/** uses @nuxt/kit types that only resolve fully inside a real
58
- // Nuxt project. Disable the unsafe-* rules here to avoid false positives
59
- // while keeping all other rules active.
60
- files: ['src/module/**/*.ts'],
61
- rules: {
62
- '@typescript-eslint/no-unsafe-assignment': 'off',
63
- '@typescript-eslint/no-unsafe-member-access': 'off',
64
- '@typescript-eslint/no-unsafe-call': 'off',
65
- '@typescript-eslint/no-unsafe-argument': 'off',
66
- '@typescript-eslint/no-unsafe-return': 'off',
67
- },
68
- },
69
- {
70
- ignores: [
71
- 'dist/**',
72
- 'node_modules/**',
73
- 'swagger/**',
74
- 'test-*/**',
75
- 'index.ts',
76
- // Ignore runtime files - they run in user's project with different rules
77
- 'src/generators/*/runtime/**',
78
- 'src/generators/shared/runtime/**',
79
- 'src/generators/shared/templates/**',
80
- '*.js',
81
- '*.mjs',
82
- '*.cjs',
83
- ],
84
- }
85
- );
1
+ // @ts-check
2
+ import eslint from '@eslint/js';
3
+ import tseslint from 'typescript-eslint';
4
+ import prettierConfig from 'eslint-config-prettier';
5
+ import prettierPlugin from 'eslint-plugin-prettier';
6
+
7
+ export default tseslint.config(
8
+ eslint.configs.recommended,
9
+ ...tseslint.configs.recommendedTypeChecked,
10
+ prettierConfig,
11
+ {
12
+ plugins: {
13
+ prettier: prettierPlugin,
14
+ },
15
+ languageOptions: {
16
+ parserOptions: {
17
+ project: './tsconfig.json',
18
+ tsconfigRootDir: import.meta.dirname,
19
+ },
20
+ },
21
+ rules: {
22
+ 'prettier/prettier': 'error',
23
+ '@typescript-eslint/no-explicit-any': 'warn',
24
+ '@typescript-eslint/explicit-function-return-type': 'off',
25
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
26
+ '@typescript-eslint/no-unused-vars': [
27
+ 'error',
28
+ {
29
+ argsIgnorePattern: '^_',
30
+ varsIgnorePattern: '^_',
31
+ },
32
+ ],
33
+ '@typescript-eslint/no-floating-promises': 'error',
34
+ '@typescript-eslint/no-misused-promises': 'error',
35
+ '@typescript-eslint/no-unsafe-assignment': 'warn',
36
+ '@typescript-eslint/no-unsafe-member-access': 'warn',
37
+ '@typescript-eslint/no-unsafe-call': 'warn',
38
+ '@typescript-eslint/no-unsafe-return': 'warn',
39
+ '@typescript-eslint/no-unsafe-argument': 'warn',
40
+ '@typescript-eslint/restrict-template-expressions': 'warn',
41
+ '@typescript-eslint/ban-ts-comment': [
42
+ 'error',
43
+ {
44
+ 'ts-nocheck': 'allow-with-description',
45
+ minimumDescriptionLength: 10,
46
+ },
47
+ ],
48
+ 'no-console': 'off',
49
+ 'prefer-const': 'error',
50
+ 'no-var': 'error',
51
+ 'no-useless-escape': 'warn',
52
+ eqeqeq: ['error', 'always'],
53
+ curly: ['error', 'all'],
54
+ },
55
+ },
56
+ {
57
+ // src/module/** uses @nuxt/kit types that only resolve fully inside a real
58
+ // Nuxt project. Disable the unsafe-* rules here to avoid false positives
59
+ // while keeping all other rules active.
60
+ files: ['src/module/**/*.ts'],
61
+ rules: {
62
+ '@typescript-eslint/no-unsafe-assignment': 'off',
63
+ '@typescript-eslint/no-unsafe-member-access': 'off',
64
+ '@typescript-eslint/no-unsafe-call': 'off',
65
+ '@typescript-eslint/no-unsafe-argument': 'off',
66
+ '@typescript-eslint/no-unsafe-return': 'off',
67
+ },
68
+ },
69
+ {
70
+ ignores: [
71
+ 'dist/**',
72
+ 'node_modules/**',
73
+ 'swagger/**',
74
+ 'test-*/**',
75
+ 'index.ts',
76
+ // Ignore runtime files - they run in user's project with different rules
77
+ 'src/generators/*/runtime/**',
78
+ 'src/generators/shared/runtime/**',
79
+ 'src/generators/shared/templates/**',
80
+ '*.js',
81
+ '*.mjs',
82
+ '*.cjs',
83
+ ],
84
+ }
85
+ );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-openapi-hyperfetch",
3
- "version": "0.2.7-alpha.1",
3
+ "version": "0.3.0-beta",
4
4
  "description": "Nuxt useFetch, useAsyncData and Nuxt server OpenAPI generator",
5
5
  "type": "module",
6
6
  "author": "",
package/src/cli/config.ts CHANGED
@@ -1,140 +1,147 @@
1
- import fs from 'fs-extra';
2
- import { join } from 'path';
3
- import * as p from '@clack/prompts';
4
- import type { GeneratorBackend, ConfigGenerator } from './types.js';
5
-
6
- const { existsSync } = fs;
7
-
8
- /**
9
- * Configuration options for the generator
10
- */
11
- export interface GeneratorConfig {
12
- /** Path or URL to OpenAPI specification */
13
- input?: string;
14
- /** Output directory for generated files */
15
- output?: string;
16
- /** Base URL for API requests */
17
- baseUrl?: string;
18
- /** Generation mode: client or server */
19
- mode?: 'client' | 'server';
20
- /** Generate only specific tags */
21
- tags?: string[];
22
- /** Exclude specific tags */
23
- excludeTags?: string[];
24
- /** Overwrite existing files without prompting */
25
- overwrite?: boolean;
26
- /** Preview changes without writing files */
27
- dryRun?: boolean;
28
- /** Enable verbose logging */
29
- verbose?: boolean;
30
- /** Watch mode - regenerate on file changes */
31
- watch?: boolean;
32
- /** Generator types to use */
33
- generators?: ('useFetch' | 'useAsyncData' | 'nuxtServer')[];
34
- /** Server route path (for nuxtServer mode) */
35
- serverRoutePath?: string;
36
- /** Enable BFF pattern (for nuxtServer mode) */
37
- enableBff?: boolean;
38
- /** Generator backend: official (Java) or heyapi (Node.js) */
39
- backend?: GeneratorBackend;
40
- /**
41
- * Generation engine to use.
42
- * - 'openapi': @openapitools/openapi-generator-cli (requires Java 11+)
43
- * - 'heyapi': @hey-api/openapi-ts (Node.js native, no Java required)
44
- * When set, the CLI will not ask which engine to use.
45
- */
46
- generator?: ConfigGenerator;
47
- }
48
-
49
- /**
50
- * Load configuration from nxh.config.js, nuxt-openapi-generator.config.js, or package.json
51
- */
52
- export async function loadConfig(cwd: string = process.cwd()): Promise<GeneratorConfig | null> {
53
- // Try different config file names
54
- const configFiles = [
55
- 'nxh.config.js',
56
- 'nxh.config.mjs',
57
- 'nuxt-openapi-hyperfetch.js',
58
- 'nuxt-openapi-hyperfetch.mjs',
59
- ];
60
-
61
- for (const configFile of configFiles) {
62
- const configPath = join(cwd, configFile);
63
- if (existsSync(configPath)) {
64
- try {
65
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
66
- const config = await import(`file://${configPath}`);
67
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
68
- const exportedConfig = config.default || config;
69
- return exportedConfig as GeneratorConfig;
70
- } catch (error) {
71
- p.log.warn(`Failed to load config from ${configFile}: ${String(error)}`);
72
- }
73
- }
74
- }
75
-
76
- // Try package.json
77
- const packageJsonPath = join(cwd, 'package.json');
78
- if (existsSync(packageJsonPath)) {
79
- try {
80
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
81
- const packageJson = await import(`file://${packageJsonPath}`, {
82
- assert: { type: 'json' },
83
- });
84
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
85
- if (packageJson.default?.['nuxt-openapi-hyperfetch']) {
86
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
87
- return packageJson.default['nuxt-openapi-hyperfetch'] as GeneratorConfig;
88
- }
89
- } catch {
90
- // Silently ignore package.json errors
91
- }
92
- }
93
-
94
- return null;
95
- }
96
-
97
- /**
98
- * Merge CLI options with config file, CLI takes precedence
99
- */
100
- export function mergeConfig(
101
- fileConfig: GeneratorConfig | null,
102
- cliOptions: Partial<GeneratorConfig>
103
- ): GeneratorConfig {
104
- return {
105
- ...fileConfig,
106
- ...cliOptions,
107
- // Handle arrays specially - CLI should override completely
108
- tags: cliOptions.tags || fileConfig?.tags,
109
- excludeTags: cliOptions.excludeTags || fileConfig?.excludeTags,
110
- generators: cliOptions.generators || fileConfig?.generators,
111
- };
112
- }
113
-
114
- /**
115
- * Parse comma-separated tags string into array
116
- */
117
- export function parseTags(tagsString?: string): string[] | undefined {
118
- if (!tagsString) {
119
- return undefined;
120
- }
121
- return tagsString
122
- .split(',')
123
- .map((t) => t.trim())
124
- .filter(Boolean);
125
- }
126
-
127
- /**
128
- * Parse generators string into array
129
- */
130
- export function parseGenerators(
131
- generatorsString?: string
132
- ): ('useFetch' | 'useAsyncData' | 'nuxtServer')[] | undefined {
133
- if (!generatorsString) {
134
- return undefined;
135
- }
136
- const parts = generatorsString.split(',').map((g) => g.trim());
137
- return parts.filter((g): g is 'useFetch' | 'useAsyncData' | 'nuxtServer' =>
138
- ['useFetch', 'useAsyncData', 'nuxtServer'].includes(g)
139
- );
140
- }
1
+ import fs from 'fs-extra';
2
+ import { join } from 'path';
3
+ import * as p from '@clack/prompts';
4
+ import type { GeneratorBackend, ConfigGenerator } from './types.js';
5
+
6
+ const { existsSync } = fs;
7
+
8
+ /**
9
+ * Configuration options for the generator
10
+ */
11
+ export interface GeneratorConfig {
12
+ /** Path or URL to OpenAPI specification */
13
+ input?: string;
14
+ /** Output directory for generated files */
15
+ output?: string;
16
+ /** Base URL for API requests */
17
+ baseUrl?: string;
18
+ /** Generation mode: client or server */
19
+ mode?: 'client' | 'server';
20
+ /** Generate only specific tags */
21
+ tags?: string[];
22
+ /** Exclude specific tags */
23
+ excludeTags?: string[];
24
+ /** Overwrite existing files without prompting */
25
+ overwrite?: boolean;
26
+ /** Preview changes without writing files */
27
+ dryRun?: boolean;
28
+ /** Enable verbose logging */
29
+ verbose?: boolean;
30
+ /** Watch mode - regenerate on file changes */
31
+ watch?: boolean;
32
+ /** Generator types to use */
33
+ generators?: ('useFetch' | 'useAsyncData' | 'nuxtServer' | 'connectors')[];
34
+ /** Server route path (for nuxtServer mode) */
35
+ serverRoutePath?: string;
36
+ /** Enable BFF pattern (for nuxtServer mode) */
37
+ enableBff?: boolean;
38
+ /** Generator backend: official (Java) or heyapi (Node.js) */
39
+ backend?: GeneratorBackend;
40
+ /**
41
+ * Generation engine to use.
42
+ * - 'openapi': @openapitools/openapi-generator-cli (requires Java 11+)
43
+ * - 'heyapi': @hey-api/openapi-ts (Node.js native, no Java required)
44
+ * When set, the CLI will not ask which engine to use.
45
+ */
46
+ generator?: ConfigGenerator;
47
+ /**
48
+ * Generate headless UI connector composables on top of useAsyncData.
49
+ * Connectors provide ready-made logic for tables, pagination, forms and delete actions.
50
+ * Requires useAsyncData to also be generated.
51
+ * @default false
52
+ */
53
+ createUseAsyncDataConnectors?: boolean;
54
+ }
55
+
56
+ /**
57
+ * Load configuration from nxh.config.js, nuxt-openapi-generator.config.js, or package.json
58
+ */
59
+ export async function loadConfig(cwd: string = process.cwd()): Promise<GeneratorConfig | null> {
60
+ // Try different config file names
61
+ const configFiles = [
62
+ 'nxh.config.js',
63
+ 'nxh.config.mjs',
64
+ 'nuxt-openapi-hyperfetch.js',
65
+ 'nuxt-openapi-hyperfetch.mjs',
66
+ ];
67
+
68
+ for (const configFile of configFiles) {
69
+ const configPath = join(cwd, configFile);
70
+ if (existsSync(configPath)) {
71
+ try {
72
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
73
+ const config = await import(`file://${configPath}`);
74
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
75
+ const exportedConfig = config.default || config;
76
+ return exportedConfig as GeneratorConfig;
77
+ } catch (error) {
78
+ p.log.warn(`Failed to load config from ${configFile}: ${String(error)}`);
79
+ }
80
+ }
81
+ }
82
+
83
+ // Try package.json
84
+ const packageJsonPath = join(cwd, 'package.json');
85
+ if (existsSync(packageJsonPath)) {
86
+ try {
87
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
88
+ const packageJson = await import(`file://${packageJsonPath}`, {
89
+ assert: { type: 'json' },
90
+ });
91
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
92
+ if (packageJson.default?.['nuxt-openapi-hyperfetch']) {
93
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
94
+ return packageJson.default['nuxt-openapi-hyperfetch'] as GeneratorConfig;
95
+ }
96
+ } catch {
97
+ // Silently ignore package.json errors
98
+ }
99
+ }
100
+
101
+ return null;
102
+ }
103
+
104
+ /**
105
+ * Merge CLI options with config file, CLI takes precedence
106
+ */
107
+ export function mergeConfig(
108
+ fileConfig: GeneratorConfig | null,
109
+ cliOptions: Partial<GeneratorConfig>
110
+ ): GeneratorConfig {
111
+ return {
112
+ ...fileConfig,
113
+ ...cliOptions,
114
+ // Handle arrays specially - CLI should override completely
115
+ tags: cliOptions.tags || fileConfig?.tags,
116
+ excludeTags: cliOptions.excludeTags || fileConfig?.excludeTags,
117
+ generators: cliOptions.generators || fileConfig?.generators,
118
+ };
119
+ }
120
+
121
+ /**
122
+ * Parse comma-separated tags string into array
123
+ */
124
+ export function parseTags(tagsString?: string): string[] | undefined {
125
+ if (!tagsString) {
126
+ return undefined;
127
+ }
128
+ return tagsString
129
+ .split(',')
130
+ .map((t) => t.trim())
131
+ .filter(Boolean);
132
+ }
133
+
134
+ /**
135
+ * Parse generators string into array
136
+ */
137
+ export function parseGenerators(
138
+ generatorsString?: string
139
+ ): ('useFetch' | 'useAsyncData' | 'nuxtServer' | 'connectors')[] | undefined {
140
+ if (!generatorsString) {
141
+ return undefined;
142
+ }
143
+ const parts = generatorsString.split(',').map((g) => g.trim());
144
+ return parts.filter((g): g is 'useFetch' | 'useAsyncData' | 'nuxtServer' | 'connectors' =>
145
+ ['useFetch', 'useAsyncData', 'nuxtServer', 'connectors'].includes(g)
146
+ );
147
+ }