@geekmidas/cli 0.0.13 → 0.0.15

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/dist/cli.cjs CHANGED
@@ -1,7 +1,95 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env -S npx tsx
2
+ const require_chunk = require('./chunk-CUT6urMc.cjs');
2
3
  require('./config-D8AyiwBU.cjs');
3
4
  require('./loadEndpoints-Dh-dSqZX.cjs');
4
- require('./build-CTKUZTHx.cjs');
5
- require('./cli-CNAOwWIn.cjs');
6
- require('./openapi-DrPYAlJ_.cjs');
7
- require('./openapi-react-query-BWpdwBix.cjs');
5
+ const require_build = require('./build-CTKUZTHx.cjs');
6
+ const require_openapi_react_query = require('./openapi-react-query-C1JLYUOs.cjs');
7
+ const require_openapi = require('./openapi-DrPYAlJ_.cjs');
8
+ const commander = require_chunk.__toESM(require("commander"));
9
+
10
+ //#region package.json
11
+ var name = "@geekmidas/cli";
12
+ var version = "0.0.14";
13
+ var private$1 = false;
14
+ var type = "commonjs";
15
+ var bin = { "gkm": "./dist/cli.cjs" };
16
+ var publishConfig = {
17
+ "registry": "https://registry.npmjs.org/",
18
+ "access": "public"
19
+ };
20
+ var dependencies = {
21
+ "commander": "~14.0.0",
22
+ "lodash.get": "~4.4.2",
23
+ "lodash.set": "~4.3.2",
24
+ "zod": "~3.25.67",
25
+ "fast-glob": "~3.3.3",
26
+ "@geekmidas/api": "workspace:*"
27
+ };
28
+ var devDependencies = {
29
+ "@types/lodash.get": "~4.4.9",
30
+ "@types/lodash.set": "~4.3.9"
31
+ };
32
+ var package_default = {
33
+ name,
34
+ version,
35
+ private: private$1,
36
+ type,
37
+ bin,
38
+ publishConfig,
39
+ dependencies,
40
+ devDependencies
41
+ };
42
+
43
+ //#endregion
44
+ //#region src/cli.ts
45
+ const program = new commander.Command();
46
+ program.name("gkm").description("GeekMidas backend framework CLI").version(package_default.version).option("--cwd <path>", "Change working directory");
47
+ program.command("build").description("Build API handlers from endpoints").option("--providers <providers>", "Target providers for generated handlers (comma-separated)", "aws-apigatewayv1").action(async (options) => {
48
+ try {
49
+ const globalOptions = program.opts();
50
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
51
+ const providerList = [...new Set(options.providers.split(",").map((p) => p.trim()))];
52
+ await require_build.buildCommand({ providers: providerList });
53
+ } catch (error) {
54
+ console.error("Build failed:", error.message);
55
+ process.exit(1);
56
+ }
57
+ });
58
+ program.command("cron").description("Manage cron jobs").action(() => {
59
+ const globalOptions = program.opts();
60
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
61
+ process.stdout.write("Cron management - coming soon\n");
62
+ });
63
+ program.command("function").description("Manage serverless functions").action(() => {
64
+ const globalOptions = program.opts();
65
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
66
+ process.stdout.write("Serverless function management - coming soon\n");
67
+ });
68
+ program.command("api").description("Manage REST API endpoints").action(() => {
69
+ const globalOptions = program.opts();
70
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
71
+ process.stdout.write("REST API management - coming soon\n");
72
+ });
73
+ program.command("openapi").description("Generate OpenAPI 3.0 specification from endpoints").option("--output <path>", "Output file path for the OpenAPI spec", "openapi.json").action(async (options) => {
74
+ try {
75
+ const globalOptions = program.opts();
76
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
77
+ await require_openapi.openapiCommand(options);
78
+ } catch (error) {
79
+ console.error("OpenAPI generation failed:", error.message);
80
+ process.exit(1);
81
+ }
82
+ });
83
+ program.command("generate:react-query").description("Generate React Query hooks from OpenAPI specification").option("--input <path>", "Input OpenAPI spec file path", "openapi.json").option("--output <path>", "Output file path for generated hooks", "src/api/hooks.ts").option("--name <name>", "API name prefix for generated code", "API").action(async (options) => {
84
+ try {
85
+ const globalOptions = program.opts();
86
+ if (globalOptions.cwd) process.chdir(globalOptions.cwd);
87
+ await require_openapi_react_query.generateReactQueryCommand(options);
88
+ } catch (error) {
89
+ console.error("React Query generation failed:", error.message);
90
+ process.exit(1);
91
+ }
92
+ });
93
+ program.parse();
94
+
95
+ //#endregion
@@ -1,8 +1,8 @@
1
1
  const require_chunk = require('./chunk-CUT6urMc.cjs');
2
2
  const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
3
- const node_path = require_chunk.__toESM(require("node:path"));
4
- const node_fs = require_chunk.__toESM(require("node:fs"));
5
3
  const node_child_process = require_chunk.__toESM(require("node:child_process"));
4
+ const node_fs = require_chunk.__toESM(require("node:fs"));
5
+ const node_path = require_chunk.__toESM(require("node:path"));
6
6
  const node_util = require_chunk.__toESM(require("node:util"));
7
7
 
8
8
  //#region src/openapi-react-query.ts
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env -S npx tsx
2
- const require_openapi_react_query = require('./openapi-react-query-BWpdwBix.cjs');
2
+ const require_openapi_react_query = require('./openapi-react-query-C1JLYUOs.cjs');
3
3
 
4
4
  exports.generateReactQueryCommand = require_openapi_react_query.generateReactQueryCommand;
package/package.json CHANGED
@@ -1,17 +1,10 @@
1
1
  {
2
2
  "name": "@geekmidas/cli",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "private": false,
5
- "type": "module",
5
+ "type": "commonjs",
6
6
  "bin": {
7
- "gkm": "./src/index.ts"
8
- },
9
- "exports": {
10
- ".": {
11
- "import": "./dist/index.mjs",
12
- "require": "./dist/index.cjs",
13
- "types": "./src/index.ts"
14
- }
7
+ "gkm": "./dist/cli.cjs"
15
8
  },
16
9
  "publishConfig": {
17
10
  "registry": "https://registry.npmjs.org/",
@@ -23,7 +16,7 @@
23
16
  "lodash.set": "~4.3.2",
24
17
  "zod": "~3.25.67",
25
18
  "fast-glob": "~3.3.3",
26
- "@geekmidas/api": "0.0.26"
19
+ "@geekmidas/api": "0.0.31"
27
20
  },
28
21
  "devDependencies": {
29
22
  "@types/lodash.get": "~4.4.9",
package/src/cli.ts CHANGED
@@ -1,11 +1,11 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env -S npx tsx
2
2
 
3
3
  import { Command } from 'commander';
4
4
  import pkg from '../package.json' assert { type: 'json' };
5
- import { buildCommand } from './build.js';
6
- import { openapiCommand } from './openapi.js';
7
- import { generateReactQueryCommand } from './openapi-react-query.js';
8
- import type { Provider } from './types.js';
5
+ import { buildCommand } from './build.ts';
6
+ import { generateReactQueryCommand } from './openapi-react-query.ts';
7
+ import { openapiCommand } from './openapi.ts';
8
+ import type { Provider } from './types.ts';
9
9
 
10
10
  const program = new Command();
11
11
 
@@ -96,32 +96,29 @@ program
96
96
  program
97
97
  .command('generate:react-query')
98
98
  .description('Generate React Query hooks from OpenAPI specification')
99
- .option(
100
- '--input <path>',
101
- 'Input OpenAPI spec file path',
102
- 'openapi.json',
103
- )
99
+ .option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')
104
100
  .option(
105
101
  '--output <path>',
106
102
  'Output file path for generated hooks',
107
103
  'src/api/hooks.ts',
108
104
  )
109
- .option(
110
- '--name <name>',
111
- 'API name prefix for generated code',
112
- 'API',
113
- )
114
- .action(async (options: { input?: string; output?: string; name?: string }) => {
115
- try {
116
- const globalOptions = program.opts();
117
- if (globalOptions.cwd) {
118
- process.chdir(globalOptions.cwd);
105
+ .option('--name <name>', 'API name prefix for generated code', 'API')
106
+ .action(
107
+ async (options: { input?: string; output?: string; name?: string }) => {
108
+ try {
109
+ const globalOptions = program.opts();
110
+ if (globalOptions.cwd) {
111
+ process.chdir(globalOptions.cwd);
112
+ }
113
+ await generateReactQueryCommand(options);
114
+ } catch (error) {
115
+ console.error(
116
+ 'React Query generation failed:',
117
+ (error as Error).message,
118
+ );
119
+ process.exit(1);
119
120
  }
120
- await generateReactQueryCommand(options);
121
- } catch (error) {
122
- console.error('React Query generation failed:', (error as Error).message);
123
- process.exit(1);
124
- }
125
- });
121
+ },
122
+ );
126
123
 
127
124
  program.parse();
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env -S npx tsx
2
2
 
3
- import { readFile, writeFile, mkdir } from 'node:fs/promises';
4
- import { join, dirname } from 'node:path';
5
- import { existsSync } from 'node:fs';
6
3
  import { exec } from 'node:child_process';
4
+ import { existsSync } from 'node:fs';
5
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
6
+ import { dirname, join } from 'node:path';
7
7
  import { promisify } from 'node:util';
8
8
 
9
9
  const execAsync = promisify(exec);
@@ -31,33 +31,41 @@ export async function generateReactQueryCommand(
31
31
  try {
32
32
  // Read OpenAPI spec
33
33
  const inputPath = options.input || join(process.cwd(), 'openapi.json');
34
-
34
+
35
35
  if (!existsSync(inputPath)) {
36
- throw new Error(`OpenAPI spec not found at ${inputPath}. Run 'npx @geekmidas/cli openapi' first.`);
36
+ throw new Error(
37
+ `OpenAPI spec not found at ${inputPath}. Run 'npx @geekmidas/cli openapi' first.`,
38
+ );
37
39
  }
38
40
 
39
41
  const specContent = await readFile(inputPath, 'utf-8');
40
42
  const spec: OpenAPISpec = JSON.parse(specContent);
41
43
 
42
44
  // Generate TypeScript types from OpenAPI spec
43
- const outputDir = dirname(options.output || join(process.cwd(), 'src', 'api', 'hooks.ts'));
45
+ const outputDir = dirname(
46
+ options.output || join(process.cwd(), 'src', 'api', 'hooks.ts'),
47
+ );
44
48
  const typesPath = join(outputDir, 'openapi-types.d.ts');
45
-
49
+
46
50
  logger.log('Generating TypeScript types from OpenAPI spec...');
47
-
51
+
48
52
  try {
49
53
  // Use npx to run openapi-typescript
50
54
  await execAsync(
51
55
  `npx openapi-typescript "${inputPath}" -o "${typesPath}"`,
52
- { cwd: process.cwd() }
56
+ { cwd: process.cwd() },
53
57
  );
54
58
  logger.log(`TypeScript types generated: ${typesPath}`);
55
59
  } catch (error) {
56
- logger.warn('Could not generate types with openapi-typescript. Install it for better type inference.');
60
+ logger.warn(
61
+ 'Could not generate types with openapi-typescript. Install it for better type inference.',
62
+ );
57
63
  logger.warn('Run: npm install -D openapi-typescript');
58
-
64
+
59
65
  // Generate basic types file
60
- await writeFile(typesPath, `// Auto-generated placeholder types
66
+ await writeFile(
67
+ typesPath,
68
+ `// Auto-generated placeholder types
61
69
  export interface paths {
62
70
  [path: string]: {
63
71
  [method: string]: {
@@ -68,24 +76,32 @@ export interface paths {
68
76
  };
69
77
  };
70
78
  }
71
- `);
79
+ `,
80
+ );
72
81
  }
73
82
 
74
83
  // Extract operation info
75
84
  const operations = extractOperations(spec);
76
-
85
+
77
86
  // Generate TypeScript code
78
- const code = generateReactQueryCode(spec, operations, options.name || 'API');
87
+ const code = generateReactQueryCode(
88
+ spec,
89
+ operations,
90
+ options.name || 'API',
91
+ );
79
92
 
80
93
  // Write output
81
- const outputPath = options.output || join(process.cwd(), 'src', 'api', 'hooks.ts');
94
+ const outputPath =
95
+ options.output || join(process.cwd(), 'src', 'api', 'hooks.ts');
82
96
  await mkdir(dirname(outputPath), { recursive: true });
83
97
  await writeFile(outputPath, code);
84
98
 
85
99
  logger.log(`React Query hooks generated: ${outputPath}`);
86
100
  logger.log(`Generated ${operations.length} hooks`);
87
101
  } catch (error) {
88
- throw new Error(`React Query generation failed: ${(error as Error).message}`);
102
+ throw new Error(
103
+ `React Query generation failed: ${(error as Error).message}`,
104
+ );
89
105
  }
90
106
  }
91
107
 
@@ -137,7 +153,7 @@ function extractResponseType(operation: any): string {
137
153
 
138
154
  function schemaToTypeString(schema: any): string {
139
155
  if (!schema) return 'unknown';
140
-
156
+
141
157
  switch (schema.type) {
142
158
  case 'string':
143
159
  return 'string';
@@ -151,7 +167,10 @@ function schemaToTypeString(schema: any): string {
151
167
  case 'object':
152
168
  if (schema.properties) {
153
169
  const props = Object.entries(schema.properties)
154
- .map(([key, value]: [string, any]) => `${key}: ${schemaToTypeString(value)}`)
170
+ .map(
171
+ ([key, value]: [string, any]) =>
172
+ `${key}: ${schemaToTypeString(value)}`,
173
+ )
155
174
  .join('; ');
156
175
  return `{ ${props} }`;
157
176
  }
@@ -178,13 +197,13 @@ export const ${apiName.toLowerCase()} = createTypedQueryClient<paths>({
178
197
  `;
179
198
 
180
199
  const queryHooks = operations
181
- .filter(op => op.method === 'GET')
182
- .map(op => generateQueryHook(op, apiName))
200
+ .filter((op) => op.method === 'GET')
201
+ .map((op) => generateQueryHook(op, apiName))
183
202
  .join('\n\n');
184
203
 
185
204
  const mutationHooks = operations
186
- .filter(op => op.method !== 'GET')
187
- .map(op => generateMutationHook(op, apiName))
205
+ .filter((op) => op.method !== 'GET')
206
+ .map((op) => generateMutationHook(op, apiName))
188
207
  .join('\n\n');
189
208
 
190
209
  const typeExports = generateTypeExports(operations);
@@ -207,18 +226,21 @@ export { ${apiName.toLowerCase()} };
207
226
  function generateQueryHook(op: OperationInfo, apiName: string): string {
208
227
  const hookName = `use${capitalize(op.operationId)}`;
209
228
  const endpoint = op.endpoint;
210
- const hasParams = op.parameters?.some(p => p.in === 'path');
211
- const hasQuery = op.parameters?.some(p => p.in === 'query');
212
-
229
+ const hasParams = op.parameters?.some((p) => p.in === 'path');
230
+ const hasQuery = op.parameters?.some((p) => p.in === 'query');
231
+
213
232
  // Generate properly typed hook
214
233
  let params = '';
215
234
  let args = '';
216
-
235
+
217
236
  if (hasParams || hasQuery) {
218
237
  const paramParts: string[] = [];
219
238
  if (hasParams) {
220
- const pathParams = op.parameters?.filter(p => p.in === 'path').map(p => p.name) || [];
221
- paramParts.push(`params: { ${pathParams.map(p => `${p}: string`).join('; ')} }`);
239
+ const pathParams =
240
+ op.parameters?.filter((p) => p.in === 'path').map((p) => p.name) || [];
241
+ paramParts.push(
242
+ `params: { ${pathParams.map((p) => `${p}: string`).join('; ')} }`,
243
+ );
222
244
  }
223
245
  if (hasQuery) {
224
246
  paramParts.push(`query?: Record<string, any>`);
@@ -226,7 +248,7 @@ function generateQueryHook(op: OperationInfo, apiName: string): string {
226
248
  params = `config: { ${paramParts.join('; ')} }, `;
227
249
  args = ', config';
228
250
  }
229
-
251
+
230
252
  return `export const ${hookName} = (
231
253
  ${params}options?: Parameters<typeof ${apiName.toLowerCase()}.useQuery>[2]
232
254
  ) => {
@@ -237,7 +259,7 @@ function generateQueryHook(op: OperationInfo, apiName: string): string {
237
259
  function generateMutationHook(op: OperationInfo, apiName: string): string {
238
260
  const hookName = `use${capitalize(op.operationId)}`;
239
261
  const endpoint = op.endpoint;
240
-
262
+
241
263
  return `export const ${hookName} = (
242
264
  options?: Parameters<typeof ${apiName.toLowerCase()}.useMutation>[1]
243
265
  ) => {
@@ -246,10 +268,10 @@ function generateMutationHook(op: OperationInfo, apiName: string): string {
246
268
  }
247
269
 
248
270
  function generateTypeExports(operations: OperationInfo[]): string {
249
- const exports = operations.map(op => {
271
+ const exports = operations.map((op) => {
250
272
  const typeName = capitalize(op.operationId);
251
273
  const isQuery = op.method === 'GET';
252
-
274
+
253
275
  if (isQuery) {
254
276
  return `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['data']>>;`;
255
277
  } else {
@@ -262,4 +284,4 @@ function generateTypeExports(operations: OperationInfo[]): string {
262
284
 
263
285
  function capitalize(str: string): string {
264
286
  return str.charAt(0).toUpperCase() + str.slice(1);
265
- }
287
+ }
package/tsdown.config.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  import { defineConfig } from 'tsdown';
2
2
 
3
- export default defineConfig({});
3
+ export default defineConfig({
4
+ dts: false,
5
+ format: 'cjs',
6
+ });
@@ -1,160 +0,0 @@
1
- import { loadConfig } from "./config-DV1Lwdkx.mjs";
2
- import { loadEndpoints } from "./loadEndpoints-DKaw6Eqm.mjs";
3
- import { mkdir, writeFile } from "node:fs/promises";
4
- import { dirname, join, relative } from "path";
5
-
6
- //#region src/build.ts
7
- const logger = console;
8
- async function buildCommand(options) {
9
- logger.log(`Building with providers: ${options.providers.join(", ")}`);
10
- const config = await loadConfig();
11
- logger.log(`Loading routes from: ${config.routes}`);
12
- logger.log(`Using envParser: ${config.envParser}`);
13
- const [envParserPath, envParserName] = config.envParser.split("#");
14
- const envParserImportPattern = !envParserName ? "envParser" : envParserName === "envParser" ? "{ envParser }" : `{ ${envParserName} as envParser }`;
15
- const [loggerPath, loggerName] = config.logger.split("#");
16
- const loggerImportPattern = !loggerName ? "logger" : loggerName === "logger" ? "{ logger }" : `{ ${loggerName} as logger }`;
17
- const loadedEndpoints = await loadEndpoints(config.routes);
18
- if (loadedEndpoints.length === 0) {
19
- logger.log("No endpoints found to process");
20
- return;
21
- }
22
- const allEndpoints = loadedEndpoints.map(({ name, endpoint, file }) => {
23
- const routeInfo = {
24
- path: endpoint._path,
25
- method: endpoint.method,
26
- handler: ""
27
- };
28
- logger.log(`Found endpoint: ${name} - ${routeInfo.method} ${routeInfo.path}`);
29
- return {
30
- file: relative(process.cwd(), file),
31
- exportName: name,
32
- endpoint,
33
- routeInfo
34
- };
35
- });
36
- for (const provider of options.providers) {
37
- const routes = [];
38
- const outputDir = join(process.cwd(), ".gkm", provider);
39
- await mkdir(outputDir, { recursive: true });
40
- logger.log(`\nGenerating handlers for provider: ${provider}`);
41
- if (provider === "server") {
42
- const serverFile = await generateServerFile(outputDir, allEndpoints, envParserPath, envParserImportPattern, loggerPath, loggerImportPattern);
43
- routes.push({
44
- path: "*",
45
- method: "ALL",
46
- handler: relative(process.cwd(), serverFile)
47
- });
48
- logger.log(`Generated server app with ${allEndpoints.length} endpoints`);
49
- } else for (const { file, exportName, routeInfo } of allEndpoints) {
50
- const handlerFile = await generateHandlerFile(outputDir, file, exportName, provider, routeInfo, envParserPath, envParserImportPattern);
51
- routes.push({
52
- ...routeInfo,
53
- handler: relative(process.cwd(), handlerFile).replace(/\.ts$/, ".handler")
54
- });
55
- logger.log(`Generated handler for ${routeInfo.method} ${routeInfo.path}`);
56
- }
57
- const manifest = { routes };
58
- const manifestPath = join(outputDir, "routes.json");
59
- await writeFile(manifestPath, JSON.stringify(manifest, null, 2));
60
- logger.log(`Generated ${routes.length} handlers in ${relative(process.cwd(), outputDir)}`);
61
- logger.log(`Routes manifest: ${relative(process.cwd(), manifestPath)}`);
62
- }
63
- }
64
- async function generateServerFile(outputDir, endpoints, envParserPath, envParserImportPattern, loggerPath, loggerImportPattern) {
65
- const serverFileName = "app.ts";
66
- const serverPath = join(outputDir, serverFileName);
67
- const importsByFile = /* @__PURE__ */ new Map();
68
- for (const { file, exportName } of endpoints) {
69
- const relativePath = relative(dirname(serverPath), file);
70
- const importPath = relativePath.replace(/\.ts$/, ".js");
71
- if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
72
- importsByFile.get(importPath).push(exportName);
73
- }
74
- const relativeEnvParserPath = relative(dirname(serverPath), envParserPath);
75
- const relativeLoggerPath = relative(dirname(serverPath), loggerPath);
76
- const imports = Array.from(importsByFile.entries()).map(([importPath, exports]) => `import { ${exports.join(", ")} } from '${importPath}';`).join("\n");
77
- const allExportNames = endpoints.map(({ exportName }) => exportName);
78
- const content = `import { HonoEndpoint } from '@geekmidas/api/hono';
79
- import { Endpoint } from '@geekmidas/api/server';
80
- import { ServiceDiscovery } from '@geekmidas/api/services';
81
- import { Hono } from 'hono';
82
- import ${envParserImportPattern} from '${relativeEnvParserPath}';
83
- import ${loggerImportPattern} from '${relativeLoggerPath}';
84
- ${imports}
85
-
86
- export function createApp(app?: Hono): Hono {
87
- const honoApp = app || new Hono();
88
-
89
- const endpoints: Endpoint<any, any, any, any, any, any>[] = [
90
- ${allExportNames.join(",\n ")}
91
- ];
92
-
93
- const serviceDiscovery = ServiceDiscovery.getInstance(
94
- logger,
95
- envParser
96
- );
97
-
98
- HonoEndpoint.addRoutes(endpoints, serviceDiscovery, honoApp);
99
-
100
- return honoApp;
101
- }
102
-
103
- // Default export for convenience
104
- export default createApp;
105
- `;
106
- await writeFile(serverPath, content);
107
- return serverPath;
108
- }
109
- async function generateHandlerFile(outputDir, sourceFile, exportName, provider, _routeInfo, envParserPath, envParserImportPattern) {
110
- const handlerFileName = `${exportName}.ts`;
111
- const handlerPath = join(outputDir, handlerFileName);
112
- const relativePath = relative(dirname(handlerPath), sourceFile);
113
- const importPath = relativePath.replace(/\.ts$/, ".js");
114
- const relativeEnvParserPath = relative(dirname(handlerPath), envParserPath);
115
- let content;
116
- switch (provider) {
117
- case "aws-apigatewayv1":
118
- content = generateAWSApiGatewayV1Handler(importPath, exportName, relativeEnvParserPath, envParserImportPattern);
119
- break;
120
- case "aws-apigatewayv2":
121
- content = generateAWSApiGatewayV2Handler(importPath, exportName, relativeEnvParserPath, envParserImportPattern);
122
- break;
123
- case "server":
124
- content = generateServerHandler(importPath, exportName);
125
- break;
126
- default: throw new Error(`Unsupported provider: ${provider}`);
127
- }
128
- await writeFile(handlerPath, content);
129
- return handlerPath;
130
- }
131
- function generateAWSApiGatewayV1Handler(importPath, exportName, envParserPath, envParserImportPattern) {
132
- return `import { AmazonApiGatewayV1Endpoint } from '@geekmidas/api/aws-apigateway';
133
- import { ${exportName} } from '${importPath}';
134
- import ${envParserImportPattern} from '${envParserPath}';
135
-
136
- const adapter = new AmazonApiGatewayV1Endpoint(envParser, ${exportName});
137
-
138
- export const handler = adapter.handler;
139
- `;
140
- }
141
- function generateAWSApiGatewayV2Handler(importPath, exportName, envParserPath, envParserImportPattern) {
142
- return `import { AmazonApiGatewayV2Endpoint } from '@geekmidas/api/aws-apigateway';
143
- import { ${exportName} } from '${importPath}';
144
- import ${envParserImportPattern} from '${envParserPath}';
145
-
146
- const adapter = new AmazonApiGatewayV2Endpoint(envParser, ${exportName});
147
-
148
- export const handler = adapter.handler;
149
- `;
150
- }
151
- function generateServerHandler(importPath, exportName) {
152
- return `import { ${exportName} } from '${importPath}';
153
-
154
- // Server handler - implement based on your server framework
155
- export const handler = ${exportName};
156
- `;
157
- }
158
-
159
- //#endregion
160
- export { buildCommand };
package/dist/build.mjs DELETED
@@ -1,5 +0,0 @@
1
- import "./config-DV1Lwdkx.mjs";
2
- import "./loadEndpoints-DKaw6Eqm.mjs";
3
- import { buildCommand } from "./build-DgeiXkH-.mjs";
4
-
5
- export { buildCommand };
@@ -1,98 +0,0 @@
1
- const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const require_build = require('./build-CTKUZTHx.cjs');
3
- const require_openapi = require('./openapi-DrPYAlJ_.cjs');
4
- const require_openapi_react_query = require('./openapi-react-query-BWpdwBix.cjs');
5
- const commander = require_chunk.__toESM(require("commander"));
6
-
7
- //#region package.json
8
- var name = "@geekmidas/cli";
9
- var version = "0.0.13";
10
- var private$1 = false;
11
- var type = "module";
12
- var bin = { "gkm": "./src/index.ts" };
13
- var exports$1 = { ".": {
14
- "import": "./dist/index.mjs",
15
- "require": "./dist/index.cjs",
16
- "types": "./src/index.ts"
17
- } };
18
- var publishConfig = {
19
- "registry": "https://registry.npmjs.org/",
20
- "access": "public"
21
- };
22
- var dependencies = {
23
- "commander": "~14.0.0",
24
- "lodash.get": "~4.4.2",
25
- "lodash.set": "~4.3.2",
26
- "zod": "~3.25.67",
27
- "fast-glob": "~3.3.3",
28
- "@geekmidas/api": "workspace:*"
29
- };
30
- var devDependencies = {
31
- "@types/lodash.get": "~4.4.9",
32
- "@types/lodash.set": "~4.3.9"
33
- };
34
- var package_default = {
35
- name,
36
- version,
37
- private: private$1,
38
- type,
39
- bin,
40
- exports: exports$1,
41
- publishConfig,
42
- dependencies,
43
- devDependencies
44
- };
45
-
46
- //#endregion
47
- //#region src/cli.ts
48
- const program = new commander.Command();
49
- program.name("gkm").description("GeekMidas backend framework CLI").version(package_default.version).option("--cwd <path>", "Change working directory");
50
- program.command("build").description("Build API handlers from endpoints").option("--providers <providers>", "Target providers for generated handlers (comma-separated)", "aws-apigatewayv1").action(async (options) => {
51
- try {
52
- const globalOptions = program.opts();
53
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
54
- const providerList = [...new Set(options.providers.split(",").map((p) => p.trim()))];
55
- await require_build.buildCommand({ providers: providerList });
56
- } catch (error) {
57
- console.error("Build failed:", error.message);
58
- process.exit(1);
59
- }
60
- });
61
- program.command("cron").description("Manage cron jobs").action(() => {
62
- const globalOptions = program.opts();
63
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
64
- process.stdout.write("Cron management - coming soon\n");
65
- });
66
- program.command("function").description("Manage serverless functions").action(() => {
67
- const globalOptions = program.opts();
68
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
69
- process.stdout.write("Serverless function management - coming soon\n");
70
- });
71
- program.command("api").description("Manage REST API endpoints").action(() => {
72
- const globalOptions = program.opts();
73
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
74
- process.stdout.write("REST API management - coming soon\n");
75
- });
76
- program.command("openapi").description("Generate OpenAPI 3.0 specification from endpoints").option("--output <path>", "Output file path for the OpenAPI spec", "openapi.json").action(async (options) => {
77
- try {
78
- const globalOptions = program.opts();
79
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
80
- await require_openapi.openapiCommand(options);
81
- } catch (error) {
82
- console.error("OpenAPI generation failed:", error.message);
83
- process.exit(1);
84
- }
85
- });
86
- program.command("generate:react-query").description("Generate React Query hooks from OpenAPI specification").option("--input <path>", "Input OpenAPI spec file path", "openapi.json").option("--output <path>", "Output file path for generated hooks", "src/api/hooks.ts").option("--name <name>", "API name prefix for generated code", "API").action(async (options) => {
87
- try {
88
- const globalOptions = program.opts();
89
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
90
- await require_openapi_react_query.generateReactQueryCommand(options);
91
- } catch (error) {
92
- console.error("React Query generation failed:", error.message);
93
- process.exit(1);
94
- }
95
- });
96
- program.parse();
97
-
98
- //#endregion
@@ -1,97 +0,0 @@
1
- import { buildCommand } from "./build-DgeiXkH-.mjs";
2
- import { openapiCommand } from "./openapi-DgLItZw-.mjs";
3
- import { generateReactQueryCommand } from "./openapi-react-query-DuNQ8DwF.mjs";
4
- import { Command } from "commander";
5
-
6
- //#region package.json
7
- var name = "@geekmidas/cli";
8
- var version = "0.0.13";
9
- var private$1 = false;
10
- var type = "module";
11
- var bin = { "gkm": "./src/index.ts" };
12
- var exports = { ".": {
13
- "import": "./dist/index.mjs",
14
- "require": "./dist/index.cjs",
15
- "types": "./src/index.ts"
16
- } };
17
- var publishConfig = {
18
- "registry": "https://registry.npmjs.org/",
19
- "access": "public"
20
- };
21
- var dependencies = {
22
- "commander": "~14.0.0",
23
- "lodash.get": "~4.4.2",
24
- "lodash.set": "~4.3.2",
25
- "zod": "~3.25.67",
26
- "fast-glob": "~3.3.3",
27
- "@geekmidas/api": "workspace:*"
28
- };
29
- var devDependencies = {
30
- "@types/lodash.get": "~4.4.9",
31
- "@types/lodash.set": "~4.3.9"
32
- };
33
- var package_default = {
34
- name,
35
- version,
36
- private: private$1,
37
- type,
38
- bin,
39
- exports,
40
- publishConfig,
41
- dependencies,
42
- devDependencies
43
- };
44
-
45
- //#endregion
46
- //#region src/cli.ts
47
- const program = new Command();
48
- program.name("gkm").description("GeekMidas backend framework CLI").version(package_default.version).option("--cwd <path>", "Change working directory");
49
- program.command("build").description("Build API handlers from endpoints").option("--providers <providers>", "Target providers for generated handlers (comma-separated)", "aws-apigatewayv1").action(async (options) => {
50
- try {
51
- const globalOptions = program.opts();
52
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
53
- const providerList = [...new Set(options.providers.split(",").map((p) => p.trim()))];
54
- await buildCommand({ providers: providerList });
55
- } catch (error) {
56
- console.error("Build failed:", error.message);
57
- process.exit(1);
58
- }
59
- });
60
- program.command("cron").description("Manage cron jobs").action(() => {
61
- const globalOptions = program.opts();
62
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
63
- process.stdout.write("Cron management - coming soon\n");
64
- });
65
- program.command("function").description("Manage serverless functions").action(() => {
66
- const globalOptions = program.opts();
67
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
68
- process.stdout.write("Serverless function management - coming soon\n");
69
- });
70
- program.command("api").description("Manage REST API endpoints").action(() => {
71
- const globalOptions = program.opts();
72
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
73
- process.stdout.write("REST API management - coming soon\n");
74
- });
75
- program.command("openapi").description("Generate OpenAPI 3.0 specification from endpoints").option("--output <path>", "Output file path for the OpenAPI spec", "openapi.json").action(async (options) => {
76
- try {
77
- const globalOptions = program.opts();
78
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
79
- await openapiCommand(options);
80
- } catch (error) {
81
- console.error("OpenAPI generation failed:", error.message);
82
- process.exit(1);
83
- }
84
- });
85
- program.command("generate:react-query").description("Generate React Query hooks from OpenAPI specification").option("--input <path>", "Input OpenAPI spec file path", "openapi.json").option("--output <path>", "Output file path for generated hooks", "src/api/hooks.ts").option("--name <name>", "API name prefix for generated code", "API").action(async (options) => {
86
- try {
87
- const globalOptions = program.opts();
88
- if (globalOptions.cwd) process.chdir(globalOptions.cwd);
89
- await generateReactQueryCommand(options);
90
- } catch (error) {
91
- console.error("React Query generation failed:", error.message);
92
- process.exit(1);
93
- }
94
- });
95
- program.parse();
96
-
97
- //#endregion
package/dist/cli.mjs DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./config-DV1Lwdkx.mjs";
3
- import "./loadEndpoints-DKaw6Eqm.mjs";
4
- import "./build-DgeiXkH-.mjs";
5
- import "./cli-jxBvJiFq.mjs";
6
- import "./openapi-DgLItZw-.mjs";
7
- import "./openapi-react-query-DuNQ8DwF.mjs";
@@ -1,17 +0,0 @@
1
- import { join } from "path";
2
- import { existsSync } from "fs";
3
-
4
- //#region src/config.ts
5
- async function loadConfig() {
6
- const configPath = join(process.cwd(), "gkm.config.json");
7
- if (!existsSync(configPath)) throw new Error("gkm.config.json not found. Please create a configuration file.");
8
- try {
9
- const config = await import(configPath);
10
- return config.default || config;
11
- } catch (error) {
12
- throw new Error(`Failed to load gkm.config.ts: ${error.message}`);
13
- }
14
- }
15
-
16
- //#endregion
17
- export { loadConfig };
package/dist/config.mjs DELETED
@@ -1,3 +0,0 @@
1
- import { loadConfig } from "./config-DV1Lwdkx.mjs";
2
-
3
- export { loadConfig };
package/dist/index.cjs DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env -S npx tsx
2
- require('./config-D8AyiwBU.cjs');
3
- require('./loadEndpoints-Dh-dSqZX.cjs');
4
- require('./build-CTKUZTHx.cjs');
5
- require('./cli-CNAOwWIn.cjs');
6
- require('./openapi-DrPYAlJ_.cjs');
7
- require('./openapi-react-query-BWpdwBix.cjs');
package/dist/index.mjs DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env -S npx tsx
2
- import "./config-DV1Lwdkx.mjs";
3
- import "./loadEndpoints-DKaw6Eqm.mjs";
4
- import "./build-DgeiXkH-.mjs";
5
- import "./cli-jxBvJiFq.mjs";
6
- import "./openapi-DgLItZw-.mjs";
7
- import "./openapi-react-query-DuNQ8DwF.mjs";
@@ -1,30 +0,0 @@
1
- import { Endpoint } from "@geekmidas/api/server";
2
- import fg from "fast-glob";
3
-
4
- //#region src/loadEndpoints.ts
5
- async function loadEndpoints(routes) {
6
- const logger = console;
7
- const files = await fg.stream(routes, {
8
- cwd: process.cwd(),
9
- absolute: true
10
- });
11
- const endpoints = [];
12
- for await (const f of files) try {
13
- const file = f.toString();
14
- const module = await import(file);
15
- for (const [exportName, exportValue] of Object.entries(module)) if (Endpoint.isEndpoint(exportValue)) {
16
- exportValue.operationId = exportName;
17
- endpoints.push({
18
- name: exportName,
19
- endpoint: exportValue,
20
- file
21
- });
22
- }
23
- } catch (error) {
24
- logger.warn(`Failed to load ${f}:`, error.message);
25
- }
26
- return endpoints;
27
- }
28
-
29
- //#endregion
30
- export { loadEndpoints };
@@ -1,3 +0,0 @@
1
- import { loadEndpoints } from "./loadEndpoints-DKaw6Eqm.mjs";
2
-
3
- export { loadEndpoints };
@@ -1,34 +0,0 @@
1
- import { loadConfig } from "./config-DV1Lwdkx.mjs";
2
- import { loadEndpoints } from "./loadEndpoints-DKaw6Eqm.mjs";
3
- import { mkdir, writeFile } from "node:fs/promises";
4
- import { Endpoint } from "@geekmidas/api/server";
5
- import { join } from "node:path";
6
-
7
- //#region src/openapi.ts
8
- async function openapiCommand(options = {}) {
9
- const logger = console;
10
- try {
11
- const config = await loadConfig();
12
- const loadedEndpoints = await loadEndpoints(config.routes);
13
- if (loadedEndpoints.length === 0) {
14
- logger.log("No valid endpoints found");
15
- return;
16
- }
17
- const endpoints = loadedEndpoints.map(({ endpoint }) => endpoint);
18
- const spec = await Endpoint.buildOpenApiSchema(endpoints, {
19
- title: "API Documentation",
20
- version: "1.0.0",
21
- description: "Auto-generated API documentation from endpoints"
22
- });
23
- const outputPath = options.output || join(process.cwd(), "openapi.json");
24
- await mkdir(join(outputPath, ".."), { recursive: true });
25
- await writeFile(outputPath, JSON.stringify(spec, null, 2));
26
- logger.log(`OpenAPI spec generated: ${outputPath}`);
27
- logger.log(`Found ${endpoints.length} endpoints`);
28
- } catch (error) {
29
- throw new Error(`OpenAPI generation failed: ${error.message}`);
30
- }
31
- }
32
-
33
- //#endregion
34
- export { openapiCommand };
@@ -1,165 +0,0 @@
1
- import { mkdir, readFile, writeFile } from "node:fs/promises";
2
- import { dirname, join } from "node:path";
3
- import { existsSync } from "node:fs";
4
- import { exec } from "node:child_process";
5
- import { promisify } from "node:util";
6
-
7
- //#region src/openapi-react-query.ts
8
- const execAsync = promisify(exec);
9
- async function generateReactQueryCommand(options = {}) {
10
- const logger = console;
11
- try {
12
- const inputPath = options.input || join(process.cwd(), "openapi.json");
13
- if (!existsSync(inputPath)) throw new Error(`OpenAPI spec not found at ${inputPath}. Run 'npx @geekmidas/cli openapi' first.`);
14
- const specContent = await readFile(inputPath, "utf-8");
15
- const spec = JSON.parse(specContent);
16
- const outputDir = dirname(options.output || join(process.cwd(), "src", "api", "hooks.ts"));
17
- const typesPath = join(outputDir, "openapi-types.d.ts");
18
- logger.log("Generating TypeScript types from OpenAPI spec...");
19
- try {
20
- await execAsync(`npx openapi-typescript "${inputPath}" -o "${typesPath}"`, { cwd: process.cwd() });
21
- logger.log(`TypeScript types generated: ${typesPath}`);
22
- } catch (error) {
23
- logger.warn("Could not generate types with openapi-typescript. Install it for better type inference.");
24
- logger.warn("Run: npm install -D openapi-typescript");
25
- await writeFile(typesPath, `// Auto-generated placeholder types
26
- export interface paths {
27
- [path: string]: {
28
- [method: string]: {
29
- operationId?: string;
30
- parameters?: any;
31
- requestBody?: any;
32
- responses?: any;
33
- };
34
- };
35
- }
36
- `);
37
- }
38
- const operations = extractOperations(spec);
39
- const code = generateReactQueryCode(spec, operations, options.name || "API");
40
- const outputPath = options.output || join(process.cwd(), "src", "api", "hooks.ts");
41
- await mkdir(dirname(outputPath), { recursive: true });
42
- await writeFile(outputPath, code);
43
- logger.log(`React Query hooks generated: ${outputPath}`);
44
- logger.log(`Generated ${operations.length} hooks`);
45
- } catch (error) {
46
- throw new Error(`React Query generation failed: ${error.message}`);
47
- }
48
- }
49
- function extractOperations(spec) {
50
- const operations = [];
51
- Object.entries(spec.paths).forEach(([path, methods]) => {
52
- Object.entries(methods).forEach(([method, operation]) => {
53
- if (operation.operationId) operations.push({
54
- operationId: operation.operationId,
55
- path,
56
- method: method.toUpperCase(),
57
- endpoint: `${method.toUpperCase()} ${path}`,
58
- parameters: operation.parameters,
59
- requestBody: !!operation.requestBody,
60
- responseType: extractResponseType(operation)
61
- });
62
- });
63
- });
64
- return operations;
65
- }
66
- function extractResponseType(operation) {
67
- const responses = operation.responses;
68
- if (!responses) return "unknown";
69
- const successResponse = responses["200"] || responses["201"];
70
- if (!successResponse?.content?.["application/json"]?.schema) return "unknown";
71
- const schema = successResponse.content["application/json"].schema;
72
- return schemaToTypeString(schema);
73
- }
74
- function schemaToTypeString(schema) {
75
- if (!schema) return "unknown";
76
- switch (schema.type) {
77
- case "string": return "string";
78
- case "number":
79
- case "integer": return "number";
80
- case "boolean": return "boolean";
81
- case "array": return `Array<${schemaToTypeString(schema.items)}>`;
82
- case "object":
83
- if (schema.properties) {
84
- const props = Object.entries(schema.properties).map(([key, value]) => `${key}: ${schemaToTypeString(value)}`).join("; ");
85
- return `{ ${props} }`;
86
- }
87
- return "Record<string, unknown>";
88
- default: return "unknown";
89
- }
90
- }
91
- function generateReactQueryCode(spec, operations, apiName) {
92
- const imports = `import { createTypedQueryClient } from '@geekmidas/api/client';
93
- import type { paths } from './openapi-types';
94
-
95
- // Create typed query client
96
- export const ${apiName.toLowerCase()} = createTypedQueryClient<paths>({
97
- baseURL: process.env.NEXT_PUBLIC_API_URL || '/api',
98
- });
99
-
100
- // Export individual hooks for better DX
101
- `;
102
- const queryHooks = operations.filter((op) => op.method === "GET").map((op) => generateQueryHook(op, apiName)).join("\n\n");
103
- const mutationHooks = operations.filter((op) => op.method !== "GET").map((op) => generateMutationHook(op, apiName)).join("\n\n");
104
- const typeExports = generateTypeExports(operations);
105
- return `${imports}
106
- // Query Hooks
107
- ${queryHooks}
108
-
109
- // Mutation Hooks
110
- ${mutationHooks}
111
-
112
- // Type exports for convenience
113
- ${typeExports}
114
-
115
- // Re-export the api for advanced usage
116
- export { ${apiName.toLowerCase()} };
117
- `;
118
- }
119
- function generateQueryHook(op, apiName) {
120
- const hookName = `use${capitalize(op.operationId)}`;
121
- const endpoint = op.endpoint;
122
- const hasParams = op.parameters?.some((p) => p.in === "path");
123
- const hasQuery = op.parameters?.some((p) => p.in === "query");
124
- let params = "";
125
- let args = "";
126
- if (hasParams || hasQuery) {
127
- const paramParts = [];
128
- if (hasParams) {
129
- const pathParams = op.parameters?.filter((p) => p.in === "path").map((p) => p.name) || [];
130
- paramParts.push(`params: { ${pathParams.map((p) => `${p}: string`).join("; ")} }`);
131
- }
132
- if (hasQuery) paramParts.push(`query?: Record<string, any>`);
133
- params = `config: { ${paramParts.join("; ")} }, `;
134
- args = ", config";
135
- }
136
- return `export const ${hookName} = (
137
- ${params}options?: Parameters<typeof ${apiName.toLowerCase()}.useQuery>[2]
138
- ) => {
139
- return ${apiName.toLowerCase()}.useQuery('${endpoint}' as any${args}, options);
140
- };`;
141
- }
142
- function generateMutationHook(op, apiName) {
143
- const hookName = `use${capitalize(op.operationId)}`;
144
- const endpoint = op.endpoint;
145
- return `export const ${hookName} = (
146
- options?: Parameters<typeof ${apiName.toLowerCase()}.useMutation>[1]
147
- ) => {
148
- return ${apiName.toLowerCase()}.useMutation('${endpoint}' as any, options);
149
- };`;
150
- }
151
- function generateTypeExports(operations) {
152
- const exports = operations.map((op) => {
153
- const typeName = capitalize(op.operationId);
154
- const isQuery = op.method === "GET";
155
- if (isQuery) return `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['data']>>;`;
156
- else return `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['mutateAsync']>>;`;
157
- });
158
- return exports.join("\n");
159
- }
160
- function capitalize(str) {
161
- return str.charAt(0).toUpperCase() + str.slice(1);
162
- }
163
-
164
- //#endregion
165
- export { generateReactQueryCommand };
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env -S npx tsx
2
- import { generateReactQueryCommand } from "./openapi-react-query-DuNQ8DwF.mjs";
3
-
4
- export { generateReactQueryCommand };
package/dist/openapi.mjs DELETED
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env -S npx tsx
2
- import "./config-DV1Lwdkx.mjs";
3
- import "./loadEndpoints-DKaw6Eqm.mjs";
4
- import { openapiCommand } from "./openapi-DgLItZw-.mjs";
5
-
6
- export { openapiCommand };
package/dist/types.mjs DELETED
File without changes
package/src/index.ts DELETED
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env -S npx tsx
2
-
3
- import './cli.ts';
4
-
5
- // Export types for user configuration
6
- export type { GkmConfig, Provider, BuildOptions } from './types.ts';