@geekmidas/cli 0.10.0 → 0.13.0

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 (146) hide show
  1. package/README.md +525 -0
  2. package/dist/bundler-B1qy9b-j.cjs +112 -0
  3. package/dist/bundler-B1qy9b-j.cjs.map +1 -0
  4. package/dist/bundler-DskIqW2t.mjs +111 -0
  5. package/dist/bundler-DskIqW2t.mjs.map +1 -0
  6. package/dist/{config-C9aXOHBe.cjs → config-AmInkU7k.cjs} +8 -8
  7. package/dist/config-AmInkU7k.cjs.map +1 -0
  8. package/dist/{config-BrkUalUh.mjs → config-DYULeEv8.mjs} +3 -3
  9. package/dist/config-DYULeEv8.mjs.map +1 -0
  10. package/dist/config.cjs +1 -1
  11. package/dist/config.d.cts +1 -1
  12. package/dist/config.d.mts +1 -1
  13. package/dist/config.mjs +1 -1
  14. package/dist/encryption-C8H-38Yy.mjs +42 -0
  15. package/dist/encryption-C8H-38Yy.mjs.map +1 -0
  16. package/dist/encryption-Dyf_r1h-.cjs +44 -0
  17. package/dist/encryption-Dyf_r1h-.cjs.map +1 -0
  18. package/dist/index.cjs +2123 -179
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.mjs +2141 -192
  21. package/dist/index.mjs.map +1 -1
  22. package/dist/{openapi-CZLI4QTr.mjs → openapi-BfFlOBCG.mjs} +801 -38
  23. package/dist/openapi-BfFlOBCG.mjs.map +1 -0
  24. package/dist/{openapi-BeHLKcwP.cjs → openapi-Bt_1FDpT.cjs} +794 -31
  25. package/dist/openapi-Bt_1FDpT.cjs.map +1 -0
  26. package/dist/{openapi-react-query-o5iMi8tz.cjs → openapi-react-query-B-sNWHFU.cjs} +5 -5
  27. package/dist/openapi-react-query-B-sNWHFU.cjs.map +1 -0
  28. package/dist/{openapi-react-query-CcciaVu5.mjs → openapi-react-query-B6XTeGqS.mjs} +5 -5
  29. package/dist/openapi-react-query-B6XTeGqS.mjs.map +1 -0
  30. package/dist/openapi-react-query.cjs +1 -1
  31. package/dist/openapi-react-query.d.cts.map +1 -1
  32. package/dist/openapi-react-query.d.mts.map +1 -1
  33. package/dist/openapi-react-query.mjs +1 -1
  34. package/dist/openapi.cjs +2 -2
  35. package/dist/openapi.d.cts +1 -1
  36. package/dist/openapi.d.cts.map +1 -1
  37. package/dist/openapi.d.mts +1 -1
  38. package/dist/openapi.d.mts.map +1 -1
  39. package/dist/openapi.mjs +2 -2
  40. package/dist/storage-BOOpAF8N.cjs +5 -0
  41. package/dist/storage-Bj1E26lU.cjs +187 -0
  42. package/dist/storage-Bj1E26lU.cjs.map +1 -0
  43. package/dist/storage-kSxTjkNb.mjs +133 -0
  44. package/dist/storage-kSxTjkNb.mjs.map +1 -0
  45. package/dist/storage-tgZSUnKl.mjs +3 -0
  46. package/dist/{types-b-vwGpqc.d.cts → types-BR0M2v_c.d.mts} +100 -1
  47. package/dist/types-BR0M2v_c.d.mts.map +1 -0
  48. package/dist/{types-DXgiA1sF.d.mts → types-BhkZc-vm.d.cts} +100 -1
  49. package/dist/types-BhkZc-vm.d.cts.map +1 -0
  50. package/examples/cron-example.ts +27 -27
  51. package/examples/env.ts +27 -27
  52. package/examples/function-example.ts +31 -31
  53. package/examples/gkm.config.json +20 -20
  54. package/examples/gkm.config.ts +8 -8
  55. package/examples/gkm.minimal.config.json +5 -5
  56. package/examples/gkm.production.config.json +25 -25
  57. package/examples/logger.ts +2 -2
  58. package/package.json +6 -6
  59. package/src/__tests__/EndpointGenerator.hooks.spec.ts +191 -191
  60. package/src/__tests__/config.spec.ts +55 -55
  61. package/src/__tests__/loadEnvFiles.spec.ts +93 -93
  62. package/src/__tests__/normalizeHooksConfig.spec.ts +58 -58
  63. package/src/__tests__/openapi-react-query.spec.ts +497 -497
  64. package/src/__tests__/openapi.spec.ts +428 -428
  65. package/src/__tests__/test-helpers.ts +76 -76
  66. package/src/auth/__tests__/credentials.spec.ts +204 -0
  67. package/src/auth/__tests__/index.spec.ts +168 -0
  68. package/src/auth/credentials.ts +187 -0
  69. package/src/auth/index.ts +226 -0
  70. package/src/build/__tests__/bundler.spec.ts +444 -0
  71. package/src/build/__tests__/index-new.spec.ts +474 -474
  72. package/src/build/__tests__/manifests.spec.ts +333 -333
  73. package/src/build/bundler.ts +210 -0
  74. package/src/build/endpoint-analyzer.ts +236 -0
  75. package/src/build/handler-templates.ts +1253 -0
  76. package/src/build/index.ts +260 -179
  77. package/src/build/manifests.ts +52 -52
  78. package/src/build/providerResolver.ts +145 -145
  79. package/src/build/types.ts +64 -43
  80. package/src/config.ts +39 -39
  81. package/src/deploy/__tests__/docker.spec.ts +111 -0
  82. package/src/deploy/__tests__/dokploy.spec.ts +245 -0
  83. package/src/deploy/__tests__/init.spec.ts +662 -0
  84. package/src/deploy/docker.ts +128 -0
  85. package/src/deploy/dokploy.ts +204 -0
  86. package/src/deploy/index.ts +136 -0
  87. package/src/deploy/init.ts +484 -0
  88. package/src/deploy/types.ts +48 -0
  89. package/src/dev/__tests__/index.spec.ts +266 -266
  90. package/src/dev/index.ts +647 -601
  91. package/src/docker/__tests__/compose.spec.ts +531 -0
  92. package/src/docker/__tests__/templates.spec.ts +280 -0
  93. package/src/docker/compose.ts +273 -0
  94. package/src/docker/index.ts +230 -0
  95. package/src/docker/templates.ts +446 -0
  96. package/src/generators/CronGenerator.ts +72 -72
  97. package/src/generators/EndpointGenerator.ts +699 -398
  98. package/src/generators/FunctionGenerator.ts +84 -84
  99. package/src/generators/Generator.ts +72 -72
  100. package/src/generators/OpenApiTsGenerator.ts +577 -577
  101. package/src/generators/SubscriberGenerator.ts +124 -124
  102. package/src/generators/__tests__/CronGenerator.spec.ts +433 -433
  103. package/src/generators/__tests__/EndpointGenerator.spec.ts +532 -382
  104. package/src/generators/__tests__/FunctionGenerator.spec.ts +244 -244
  105. package/src/generators/__tests__/SubscriberGenerator.spec.ts +397 -382
  106. package/src/generators/index.ts +4 -4
  107. package/src/index.ts +623 -201
  108. package/src/init/__tests__/generators.spec.ts +334 -334
  109. package/src/init/__tests__/init.spec.ts +332 -332
  110. package/src/init/__tests__/utils.spec.ts +89 -89
  111. package/src/init/generators/config.ts +175 -175
  112. package/src/init/generators/docker.ts +41 -41
  113. package/src/init/generators/env.ts +72 -72
  114. package/src/init/generators/index.ts +1 -1
  115. package/src/init/generators/models.ts +64 -64
  116. package/src/init/generators/monorepo.ts +161 -161
  117. package/src/init/generators/package.ts +71 -71
  118. package/src/init/generators/source.ts +6 -6
  119. package/src/init/index.ts +203 -208
  120. package/src/init/templates/api.ts +115 -115
  121. package/src/init/templates/index.ts +75 -75
  122. package/src/init/templates/minimal.ts +98 -98
  123. package/src/init/templates/serverless.ts +89 -89
  124. package/src/init/templates/worker.ts +98 -98
  125. package/src/init/utils.ts +54 -56
  126. package/src/openapi-react-query.ts +194 -194
  127. package/src/openapi.ts +63 -63
  128. package/src/secrets/__tests__/encryption.spec.ts +226 -0
  129. package/src/secrets/__tests__/generator.spec.ts +319 -0
  130. package/src/secrets/__tests__/index.spec.ts +91 -0
  131. package/src/secrets/__tests__/storage.spec.ts +611 -0
  132. package/src/secrets/encryption.ts +91 -0
  133. package/src/secrets/generator.ts +164 -0
  134. package/src/secrets/index.ts +383 -0
  135. package/src/secrets/storage.ts +192 -0
  136. package/src/secrets/types.ts +53 -0
  137. package/src/types.ts +295 -176
  138. package/tsdown.config.ts +11 -8
  139. package/dist/config-BrkUalUh.mjs.map +0 -1
  140. package/dist/config-C9aXOHBe.cjs.map +0 -1
  141. package/dist/openapi-BeHLKcwP.cjs.map +0 -1
  142. package/dist/openapi-CZLI4QTr.mjs.map +0 -1
  143. package/dist/openapi-react-query-CcciaVu5.mjs.map +0 -1
  144. package/dist/openapi-react-query-o5iMi8tz.cjs.map +0 -1
  145. package/dist/types-DXgiA1sF.d.mts.map +0 -1
  146. package/dist/types-b-vwGpqc.d.cts.map +0 -1
@@ -9,64 +9,64 @@ import { promisify } from 'node:util';
9
9
  const execAsync = promisify(exec);
10
10
 
11
11
  interface ReactQueryOptions {
12
- input?: string;
13
- output?: string;
14
- name?: string;
12
+ input?: string;
13
+ output?: string;
14
+ name?: string;
15
15
  }
16
16
 
17
17
  interface OpenAPISpec {
18
- openapi: string;
19
- info?: {
20
- title?: string;
21
- version?: string;
22
- };
23
- paths: Record<string, Record<string, any>>;
18
+ openapi: string;
19
+ info?: {
20
+ title?: string;
21
+ version?: string;
22
+ };
23
+ paths: Record<string, Record<string, any>>;
24
24
  }
25
25
 
26
26
  export async function generateReactQueryCommand(
27
- options: ReactQueryOptions = {},
27
+ options: ReactQueryOptions = {},
28
28
  ): Promise<void> {
29
- const logger = console;
30
-
31
- try {
32
- // Read OpenAPI spec
33
- const inputPath = options.input || join(process.cwd(), 'openapi.json');
34
-
35
- if (!existsSync(inputPath)) {
36
- throw new Error(
37
- `OpenAPI spec not found at ${inputPath}. Run 'npx @geekmidas/cli openapi' first.`,
38
- );
39
- }
40
-
41
- const specContent = await readFile(inputPath, 'utf-8');
42
- const spec: OpenAPISpec = JSON.parse(specContent);
43
-
44
- // Generate TypeScript types from OpenAPI spec
45
- const outputDir = dirname(
46
- options.output || join(process.cwd(), 'src', 'api', 'hooks.ts'),
47
- );
48
- const typesPath = join(outputDir, 'openapi-types.d.ts');
49
-
50
- logger.log('Generating TypeScript types from OpenAPI spec...');
51
-
52
- try {
53
- // Use npx to run openapi-typescript
54
- await execAsync(
55
- `npx openapi-typescript "${inputPath}" -o "${typesPath}"`,
56
- { cwd: process.cwd() },
57
- );
58
- logger.log(`TypeScript types generated: ${typesPath}`);
59
- } catch (error) {
60
- logger.warn(
61
- 'Could not generate types with openapi-typescript. Install it for better type inference.',
62
- );
63
- logger.warn('Run: npm install -D openapi-typescript');
64
-
65
- // Generate basic types file
66
- await mkdir(dirname(typesPath), { recursive: true });
67
- await writeFile(
68
- typesPath,
69
- `// Auto-generated placeholder types
29
+ const logger = console;
30
+
31
+ try {
32
+ // Read OpenAPI spec
33
+ const inputPath = options.input || join(process.cwd(), 'openapi.json');
34
+
35
+ if (!existsSync(inputPath)) {
36
+ throw new Error(
37
+ `OpenAPI spec not found at ${inputPath}. Run 'npx @geekmidas/cli openapi' first.`,
38
+ );
39
+ }
40
+
41
+ const specContent = await readFile(inputPath, 'utf-8');
42
+ const spec: OpenAPISpec = JSON.parse(specContent);
43
+
44
+ // Generate TypeScript types from OpenAPI spec
45
+ const outputDir = dirname(
46
+ options.output || join(process.cwd(), 'src', 'api', 'hooks.ts'),
47
+ );
48
+ const typesPath = join(outputDir, 'openapi-types.d.ts');
49
+
50
+ logger.log('Generating TypeScript types from OpenAPI spec...');
51
+
52
+ try {
53
+ // Use npx to run openapi-typescript
54
+ await execAsync(
55
+ `npx openapi-typescript "${inputPath}" -o "${typesPath}"`,
56
+ { cwd: process.cwd() },
57
+ );
58
+ logger.log(`TypeScript types generated: ${typesPath}`);
59
+ } catch (_error) {
60
+ logger.warn(
61
+ 'Could not generate types with openapi-typescript. Install it for better type inference.',
62
+ );
63
+ logger.warn('Run: npm install -D openapi-typescript');
64
+
65
+ // Generate basic types file
66
+ await mkdir(dirname(typesPath), { recursive: true });
67
+ await writeFile(
68
+ typesPath,
69
+ `// Auto-generated placeholder types
70
70
  export interface paths {
71
71
  [path: string]: {
72
72
  [method: string]: {
@@ -78,115 +78,115 @@ export interface paths {
78
78
  };
79
79
  }
80
80
  `,
81
- );
82
- }
83
-
84
- // Extract operation info
85
- const operations = extractOperations(spec);
86
-
87
- // Generate TypeScript code
88
- const code = generateReactQueryCode(
89
- spec,
90
- operations,
91
- options.name || 'API',
92
- );
93
-
94
- // Write output
95
- const outputPath =
96
- options.output || join(process.cwd(), 'src', 'api', 'hooks.ts');
97
- await mkdir(dirname(outputPath), { recursive: true });
98
- await writeFile(outputPath, code);
99
-
100
- logger.log(`React Query hooks generated: ${outputPath}`);
101
- logger.log(`Generated ${operations.length} hooks`);
102
- } catch (error) {
103
- throw new Error(
104
- `React Query generation failed: ${(error as Error).message}`,
105
- );
106
- }
81
+ );
82
+ }
83
+
84
+ // Extract operation info
85
+ const operations = extractOperations(spec);
86
+
87
+ // Generate TypeScript code
88
+ const code = generateReactQueryCode(
89
+ spec,
90
+ operations,
91
+ options.name || 'API',
92
+ );
93
+
94
+ // Write output
95
+ const outputPath =
96
+ options.output || join(process.cwd(), 'src', 'api', 'hooks.ts');
97
+ await mkdir(dirname(outputPath), { recursive: true });
98
+ await writeFile(outputPath, code);
99
+
100
+ logger.log(`React Query hooks generated: ${outputPath}`);
101
+ logger.log(`Generated ${operations.length} hooks`);
102
+ } catch (error) {
103
+ throw new Error(
104
+ `React Query generation failed: ${(error as Error).message}`,
105
+ );
106
+ }
107
107
  }
108
108
 
109
109
  interface OperationInfo {
110
- operationId: string;
111
- path: string;
112
- method: string;
113
- endpoint: string; // Full endpoint like 'GET /users/{id}'
114
- parameters?: Array<{ name: string; in: string; required?: boolean }>;
115
- requestBody?: boolean;
116
- responseType?: string;
110
+ operationId: string;
111
+ path: string;
112
+ method: string;
113
+ endpoint: string; // Full endpoint like 'GET /users/{id}'
114
+ parameters?: Array<{ name: string; in: string; required?: boolean }>;
115
+ requestBody?: boolean;
116
+ responseType?: string;
117
117
  }
118
118
 
119
119
  function extractOperations(spec: OpenAPISpec): OperationInfo[] {
120
- const operations: OperationInfo[] = [];
121
-
122
- Object.entries(spec.paths).forEach(([path, methods]) => {
123
- Object.entries(methods).forEach(([method, operation]) => {
124
- if (operation.operationId) {
125
- operations.push({
126
- operationId: operation.operationId,
127
- path,
128
- method: method.toUpperCase(),
129
- endpoint: `${method.toUpperCase()} ${path}`,
130
- parameters: operation.parameters,
131
- requestBody: !!operation.requestBody,
132
- responseType: extractResponseType(operation),
133
- });
134
- }
135
- });
136
- });
137
-
138
- return operations;
120
+ const operations: OperationInfo[] = [];
121
+
122
+ Object.entries(spec.paths).forEach(([path, methods]) => {
123
+ Object.entries(methods).forEach(([method, operation]) => {
124
+ if (operation.operationId) {
125
+ operations.push({
126
+ operationId: operation.operationId,
127
+ path,
128
+ method: method.toUpperCase(),
129
+ endpoint: `${method.toUpperCase()} ${path}`,
130
+ parameters: operation.parameters,
131
+ requestBody: !!operation.requestBody,
132
+ responseType: extractResponseType(operation),
133
+ });
134
+ }
135
+ });
136
+ });
137
+
138
+ return operations;
139
139
  }
140
140
 
141
141
  function extractResponseType(operation: any): string {
142
- const responses = operation.responses;
143
- if (!responses) return 'unknown';
142
+ const responses = operation.responses;
143
+ if (!responses) return 'unknown';
144
144
 
145
- const successResponse = responses['200'] || responses['201'];
146
- if (!successResponse?.content?.['application/json']?.schema) {
147
- return 'unknown';
148
- }
145
+ const successResponse = responses['200'] || responses['201'];
146
+ if (!successResponse?.content?.['application/json']?.schema) {
147
+ return 'unknown';
148
+ }
149
149
 
150
- // Basic type inference from schema
151
- const schema = successResponse.content['application/json'].schema;
152
- return schemaToTypeString(schema);
150
+ // Basic type inference from schema
151
+ const schema = successResponse.content['application/json'].schema;
152
+ return schemaToTypeString(schema);
153
153
  }
154
154
 
155
155
  function schemaToTypeString(schema: any): string {
156
- if (!schema) return 'unknown';
157
-
158
- switch (schema.type) {
159
- case 'string':
160
- return 'string';
161
- case 'number':
162
- case 'integer':
163
- return 'number';
164
- case 'boolean':
165
- return 'boolean';
166
- case 'array':
167
- return `Array<${schemaToTypeString(schema.items)}>`;
168
- case 'object':
169
- if (schema.properties) {
170
- const props = Object.entries(schema.properties)
171
- .map(
172
- ([key, value]: [string, any]) =>
173
- `${key}: ${schemaToTypeString(value)}`,
174
- )
175
- .join('; ');
176
- return `{ ${props} }`;
177
- }
178
- return 'Record<string, unknown>';
179
- default:
180
- return 'unknown';
181
- }
156
+ if (!schema) return 'unknown';
157
+
158
+ switch (schema.type) {
159
+ case 'string':
160
+ return 'string';
161
+ case 'number':
162
+ case 'integer':
163
+ return 'number';
164
+ case 'boolean':
165
+ return 'boolean';
166
+ case 'array':
167
+ return `Array<${schemaToTypeString(schema.items)}>`;
168
+ case 'object':
169
+ if (schema.properties) {
170
+ const props = Object.entries(schema.properties)
171
+ .map(
172
+ ([key, value]: [string, any]) =>
173
+ `${key}: ${schemaToTypeString(value)}`,
174
+ )
175
+ .join('; ');
176
+ return `{ ${props} }`;
177
+ }
178
+ return 'Record<string, unknown>';
179
+ default:
180
+ return 'unknown';
181
+ }
182
182
  }
183
183
 
184
184
  function generateReactQueryCode(
185
- spec: OpenAPISpec,
186
- operations: OperationInfo[],
187
- apiName: string,
185
+ _spec: OpenAPISpec,
186
+ operations: OperationInfo[],
187
+ apiName: string,
188
188
  ): string {
189
- const imports = `import { createTypedQueryClient } from '@geekmidas/client';
189
+ const imports = `import { createTypedQueryClient } from '@geekmidas/client';
190
190
  import type { paths } from './openapi-types';
191
191
 
192
192
  // Create typed query client
@@ -197,19 +197,19 @@ export const ${apiName.toLowerCase()} = createTypedQueryClient<paths>({
197
197
  // Export individual hooks for better DX
198
198
  `;
199
199
 
200
- const queryHooks = operations
201
- .filter((op) => op.method === 'GET')
202
- .map((op) => generateQueryHook(op, apiName))
203
- .join('\n\n');
200
+ const queryHooks = operations
201
+ .filter((op) => op.method === 'GET')
202
+ .map((op) => generateQueryHook(op, apiName))
203
+ .join('\n\n');
204
204
 
205
- const mutationHooks = operations
206
- .filter((op) => op.method !== 'GET')
207
- .map((op) => generateMutationHook(op, apiName))
208
- .join('\n\n');
205
+ const mutationHooks = operations
206
+ .filter((op) => op.method !== 'GET')
207
+ .map((op) => generateMutationHook(op, apiName))
208
+ .join('\n\n');
209
209
 
210
- const typeExports = generateTypeExports(operations);
210
+ const typeExports = generateTypeExports(operations);
211
211
 
212
- return `${imports}
212
+ return `${imports}
213
213
  // Query Hooks
214
214
  ${queryHooks}
215
215
 
@@ -225,32 +225,32 @@ export { ${apiName.toLowerCase()} };
225
225
  }
226
226
 
227
227
  function generateQueryHook(op: OperationInfo, apiName: string): string {
228
- const hookName = `use${capitalize(op.operationId)}`;
229
- const endpoint = op.endpoint;
230
- const hasParams = op.parameters?.some((p) => p.in === 'path');
231
- const hasQuery = op.parameters?.some((p) => p.in === 'query');
232
-
233
- // Generate properly typed hook
234
- let params = '';
235
- let args = '';
236
-
237
- if (hasParams || hasQuery) {
238
- const paramParts: string[] = [];
239
- if (hasParams) {
240
- const pathParams =
241
- op.parameters?.filter((p) => p.in === 'path').map((p) => p.name) || [];
242
- paramParts.push(
243
- `params: { ${pathParams.map((p) => `${p}: string`).join('; ')} }`,
244
- );
245
- }
246
- if (hasQuery) {
247
- paramParts.push(`query?: Record<string, any>`);
248
- }
249
- params = `config: { ${paramParts.join('; ')} }, `;
250
- args = ', config';
251
- }
252
-
253
- return `export const ${hookName} = (
228
+ const hookName = `use${capitalize(op.operationId)}`;
229
+ const endpoint = op.endpoint;
230
+ const hasParams = op.parameters?.some((p) => p.in === 'path');
231
+ const hasQuery = op.parameters?.some((p) => p.in === 'query');
232
+
233
+ // Generate properly typed hook
234
+ let params = '';
235
+ let args = '';
236
+
237
+ if (hasParams || hasQuery) {
238
+ const paramParts: string[] = [];
239
+ if (hasParams) {
240
+ const pathParams =
241
+ op.parameters?.filter((p) => p.in === 'path').map((p) => p.name) || [];
242
+ paramParts.push(
243
+ `params: { ${pathParams.map((p) => `${p}: string`).join('; ')} }`,
244
+ );
245
+ }
246
+ if (hasQuery) {
247
+ paramParts.push(`query?: Record<string, any>`);
248
+ }
249
+ params = `config: { ${paramParts.join('; ')} }, `;
250
+ args = ', config';
251
+ }
252
+
253
+ return `export const ${hookName} = (
254
254
  ${params}options?: Parameters<typeof ${apiName.toLowerCase()}.useQuery>[2]
255
255
  ) => {
256
256
  return ${apiName.toLowerCase()}.useQuery('${endpoint}' as any${args}, options);
@@ -258,10 +258,10 @@ function generateQueryHook(op: OperationInfo, apiName: string): string {
258
258
  }
259
259
 
260
260
  function generateMutationHook(op: OperationInfo, apiName: string): string {
261
- const hookName = `use${capitalize(op.operationId)}`;
262
- const endpoint = op.endpoint;
261
+ const hookName = `use${capitalize(op.operationId)}`;
262
+ const endpoint = op.endpoint;
263
263
 
264
- return `export const ${hookName} = (
264
+ return `export const ${hookName} = (
265
265
  options?: Parameters<typeof ${apiName.toLowerCase()}.useMutation>[1]
266
266
  ) => {
267
267
  return ${apiName.toLowerCase()}.useMutation('${endpoint}' as any, options);
@@ -269,20 +269,20 @@ function generateMutationHook(op: OperationInfo, apiName: string): string {
269
269
  }
270
270
 
271
271
  function generateTypeExports(operations: OperationInfo[]): string {
272
- const exports = operations.map((op) => {
273
- const typeName = capitalize(op.operationId);
274
- const isQuery = op.method === 'GET';
275
-
276
- if (isQuery) {
277
- return `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['data']>>;`;
278
- } else {
279
- return `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['mutateAsync']>>;`;
280
- }
281
- });
282
-
283
- return exports.join('\n');
272
+ const exports = operations.map((op) => {
273
+ const typeName = capitalize(op.operationId);
274
+ const isQuery = op.method === 'GET';
275
+
276
+ if (isQuery) {
277
+ return `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['data']>>;`;
278
+ } else {
279
+ return `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['mutateAsync']>>;`;
280
+ }
281
+ });
282
+
283
+ return exports.join('\n');
284
284
  }
285
285
 
286
286
  function capitalize(str: string): string {
287
- return str.charAt(0).toUpperCase() + str.slice(1);
287
+ return str.charAt(0).toUpperCase() + str.slice(1);
288
288
  }
package/src/openapi.ts CHANGED
@@ -8,7 +8,7 @@ import { OpenApiTsGenerator } from './generators/OpenApiTsGenerator.js';
8
8
  import type { GkmConfig, OpenApiConfig } from './types.js';
9
9
 
10
10
  interface OpenAPIOptions {
11
- cwd?: string;
11
+ cwd?: string;
12
12
  }
13
13
 
14
14
  /**
@@ -20,29 +20,29 @@ export const OPENAPI_OUTPUT_PATH = './.gkm/openapi.ts';
20
20
  * Resolve OpenAPI config from GkmConfig
21
21
  */
22
22
  export function resolveOpenApiConfig(
23
- config: GkmConfig,
23
+ config: GkmConfig,
24
24
  ): OpenApiConfig & { enabled: boolean } {
25
- if (config.openapi === false) {
26
- return { enabled: false };
27
- }
28
-
29
- if (config.openapi === true || config.openapi === undefined) {
30
- return {
31
- enabled: config.openapi === true,
32
- title: 'API Documentation',
33
- version: '1.0.0',
34
- description: 'Auto-generated API documentation from endpoints',
35
- };
36
- }
37
-
38
- return {
39
- enabled: config.openapi.enabled !== false,
40
- title: config.openapi.title || 'API Documentation',
41
- version: config.openapi.version || '1.0.0',
42
- description:
43
- config.openapi.description ||
44
- 'Auto-generated API documentation from endpoints',
45
- };
25
+ if (config.openapi === false) {
26
+ return { enabled: false };
27
+ }
28
+
29
+ if (config.openapi === true || config.openapi === undefined) {
30
+ return {
31
+ enabled: config.openapi === true,
32
+ title: 'API Documentation',
33
+ version: '1.0.0',
34
+ description: 'Auto-generated API documentation from endpoints',
35
+ };
36
+ }
37
+
38
+ return {
39
+ enabled: config.openapi.enabled !== false,
40
+ title: config.openapi.title || 'API Documentation',
41
+ version: config.openapi.version || '1.0.0',
42
+ description:
43
+ config.openapi.description ||
44
+ 'Auto-generated API documentation from endpoints',
45
+ };
46
46
  }
47
47
 
48
48
  /**
@@ -50,61 +50,61 @@ export function resolveOpenApiConfig(
50
50
  * @returns Object with output path and endpoint count, or null if disabled
51
51
  */
52
52
  export async function generateOpenApi(
53
- config: GkmConfig,
54
- options: { silent?: boolean } = {},
53
+ config: GkmConfig,
54
+ options: { silent?: boolean } = {},
55
55
  ): Promise<{ outputPath: string; endpointCount: number } | null> {
56
- const logger = options.silent ? { log: () => {} } : console;
57
- const openApiConfig = resolveOpenApiConfig(config);
56
+ const logger = options.silent ? { log: () => {} } : console;
57
+ const openApiConfig = resolveOpenApiConfig(config);
58
58
 
59
- if (!openApiConfig.enabled) {
60
- return null;
61
- }
59
+ if (!openApiConfig.enabled) {
60
+ return null;
61
+ }
62
62
 
63
- const endpointGenerator = new EndpointGenerator();
64
- const loadedEndpoints = await endpointGenerator.load(config.routes);
63
+ const endpointGenerator = new EndpointGenerator();
64
+ const loadedEndpoints = await endpointGenerator.load(config.routes);
65
65
 
66
- if (loadedEndpoints.length === 0) {
67
- logger.log('No valid endpoints found for OpenAPI generation');
68
- return null;
69
- }
66
+ if (loadedEndpoints.length === 0) {
67
+ logger.log('No valid endpoints found for OpenAPI generation');
68
+ return null;
69
+ }
70
70
 
71
- const endpoints = loadedEndpoints.map(({ construct }) => construct);
72
- const outputPath = join(process.cwd(), OPENAPI_OUTPUT_PATH);
71
+ const endpoints = loadedEndpoints.map(({ construct }) => construct);
72
+ const outputPath = join(process.cwd(), OPENAPI_OUTPUT_PATH);
73
73
 
74
- await mkdir(dirname(outputPath), { recursive: true });
74
+ await mkdir(dirname(outputPath), { recursive: true });
75
75
 
76
- const tsGenerator = new OpenApiTsGenerator();
77
- const tsContent = await tsGenerator.generate(endpoints, {
78
- title: openApiConfig.title!,
79
- version: openApiConfig.version!,
80
- description: openApiConfig.description!,
81
- });
76
+ const tsGenerator = new OpenApiTsGenerator();
77
+ const tsContent = await tsGenerator.generate(endpoints, {
78
+ title: openApiConfig.title!,
79
+ version: openApiConfig.version!,
80
+ description: openApiConfig.description!,
81
+ });
82
82
 
83
- await writeFile(outputPath, tsContent);
84
- logger.log(`📄 OpenAPI client generated: ${OPENAPI_OUTPUT_PATH}`);
83
+ await writeFile(outputPath, tsContent);
84
+ logger.log(`📄 OpenAPI client generated: ${OPENAPI_OUTPUT_PATH}`);
85
85
 
86
- return { outputPath, endpointCount: loadedEndpoints.length };
86
+ return { outputPath, endpointCount: loadedEndpoints.length };
87
87
  }
88
88
 
89
89
  export async function openapiCommand(
90
- options: OpenAPIOptions = {},
90
+ options: OpenAPIOptions = {},
91
91
  ): Promise<void> {
92
- const logger = console;
92
+ const logger = console;
93
93
 
94
- try {
95
- const config = await loadConfig(options.cwd);
94
+ try {
95
+ const config = await loadConfig(options.cwd);
96
96
 
97
- // Enable openapi if not configured
98
- if (!config.openapi) {
99
- config.openapi = { enabled: true };
100
- }
97
+ // Enable openapi if not configured
98
+ if (!config.openapi) {
99
+ config.openapi = { enabled: true };
100
+ }
101
101
 
102
- const result = await generateOpenApi(config);
102
+ const result = await generateOpenApi(config);
103
103
 
104
- if (result) {
105
- logger.log(`Found ${result.endpointCount} endpoints`);
106
- }
107
- } catch (error) {
108
- throw new Error(`OpenAPI generation failed: ${(error as Error).message}`);
109
- }
104
+ if (result) {
105
+ logger.log(`Found ${result.endpointCount} endpoints`);
106
+ }
107
+ } catch (error) {
108
+ throw new Error(`OpenAPI generation failed: ${(error as Error).message}`);
109
+ }
110
110
  }