@geekmidas/cli 0.3.0 → 0.4.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.
- package/README.md +488 -71
- package/dist/{EndpointGenerator-C73wNoih.cjs → EndpointGenerator-BxNCkus4.cjs} +60 -6
- package/dist/EndpointGenerator-BxNCkus4.cjs.map +1 -0
- package/dist/{EndpointGenerator-CWh18d92.mjs → EndpointGenerator-CzDhG7Or.mjs} +60 -6
- package/dist/EndpointGenerator-CzDhG7Or.mjs.map +1 -0
- package/dist/OpenApiTsGenerator-NBNEoaeO.cjs +501 -0
- package/dist/OpenApiTsGenerator-NBNEoaeO.cjs.map +1 -0
- package/dist/OpenApiTsGenerator-q3aWNkuM.mjs +495 -0
- package/dist/OpenApiTsGenerator-q3aWNkuM.mjs.map +1 -0
- package/dist/build/index.cjs +3 -3
- package/dist/build/index.mjs +3 -3
- package/dist/{build-CBYBPZpC.cjs → build-CWtHnJMQ.cjs} +3 -3
- package/dist/{build-CBYBPZpC.cjs.map → build-CWtHnJMQ.cjs.map} +1 -1
- package/dist/{build-C6uEGRj8.mjs → build-DyDgu_D1.mjs} +3 -3
- package/dist/{build-C6uEGRj8.mjs.map → build-DyDgu_D1.mjs.map} +1 -1
- package/dist/{config-U-mdW-7Y.mjs → config-AFmFKmU0.mjs} +3 -3
- package/dist/config-AFmFKmU0.mjs.map +1 -0
- package/dist/{config-D1EpSGk6.cjs → config-BVIJpAsa.cjs} +3 -3
- package/dist/config-BVIJpAsa.cjs.map +1 -0
- package/dist/config.cjs +1 -1
- package/dist/config.mjs +1 -1
- package/dist/dev/index.cjs +5 -4
- package/dist/dev/index.mjs +4 -4
- package/dist/{dev-DbtyToc7.cjs → dev-CgDYC4o8.cjs} +95 -31
- package/dist/dev-CgDYC4o8.cjs.map +1 -0
- package/dist/{dev-DnGYXuMn.mjs → dev-CpA8AQPX.mjs} +90 -32
- package/dist/dev-CpA8AQPX.mjs.map +1 -0
- package/dist/generators/EndpointGenerator.cjs +1 -1
- package/dist/generators/EndpointGenerator.mjs +1 -1
- package/dist/generators/OpenApiTsGenerator.cjs +3 -0
- package/dist/generators/OpenApiTsGenerator.mjs +3 -0
- package/dist/generators/index.cjs +1 -1
- package/dist/generators/index.mjs +1 -1
- package/dist/index.cjs +15 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +15 -9
- package/dist/index.mjs.map +1 -1
- package/dist/openapi-DRTRGhTt.mjs +50 -0
- package/dist/openapi-DRTRGhTt.mjs.map +1 -0
- package/dist/openapi-DhK4b0lB.cjs +56 -0
- package/dist/openapi-DhK4b0lB.cjs.map +1 -0
- package/dist/openapi.cjs +4 -3
- package/dist/openapi.mjs +4 -3
- package/docs/OPENAPI_TYPESCRIPT_DESIGN.md +408 -0
- package/package.json +10 -3
- package/src/__tests__/openapi.spec.ts +78 -63
- package/src/build/types.ts +13 -2
- package/src/config.ts +4 -2
- package/src/dev/__tests__/index.spec.ts +98 -1
- package/src/dev/index.ts +152 -25
- package/src/generators/EndpointGenerator.ts +69 -5
- package/src/generators/OpenApiTsGenerator.ts +798 -0
- package/src/index.ts +6 -3
- package/src/openapi.ts +36 -15
- package/src/types.ts +23 -0
- package/dist/EndpointGenerator-C73wNoih.cjs.map +0 -1
- package/dist/EndpointGenerator-CWh18d92.mjs.map +0 -1
- package/dist/config-D1EpSGk6.cjs.map +0 -1
- package/dist/config-U-mdW-7Y.mjs.map +0 -1
- package/dist/dev-DbtyToc7.cjs.map +0 -1
- package/dist/dev-DnGYXuMn.mjs.map +0 -1
- package/dist/openapi-BTHbPrxS.mjs +0 -36
- package/dist/openapi-BTHbPrxS.mjs.map +0 -1
- package/dist/openapi-CewcfoRH.cjs +0 -42
- package/dist/openapi-CewcfoRH.cjs.map +0 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { loadConfig } from "./config-
|
|
1
|
+
import { loadConfig } from "./config-AFmFKmU0.mjs";
|
|
2
2
|
import { CronGenerator } from "./CronGenerator-Bh26MaNA.mjs";
|
|
3
|
-
import { EndpointGenerator } from "./EndpointGenerator-
|
|
3
|
+
import { EndpointGenerator } from "./EndpointGenerator-CzDhG7Or.mjs";
|
|
4
4
|
import { FunctionGenerator } from "./FunctionGenerator-BNE_GC7N.mjs";
|
|
5
5
|
import { SubscriberGenerator } from "./SubscriberGenerator-Dnlj_1FK.mjs";
|
|
6
6
|
import { resolveProviders } from "./providerResolver-B_TjNF0_.mjs";
|
|
7
7
|
import { mkdir } from "node:fs/promises";
|
|
8
8
|
import { join } from "node:path";
|
|
9
|
+
import fg from "fast-glob";
|
|
9
10
|
import { spawn } from "node:child_process";
|
|
10
11
|
import { createServer } from "node:net";
|
|
11
12
|
import chokidar from "chokidar";
|
|
@@ -42,6 +43,24 @@ async function findAvailablePort(preferredPort, maxAttempts = 10) {
|
|
|
42
43
|
}
|
|
43
44
|
throw new Error(`Could not find an available port after trying ${maxAttempts} ports starting from ${preferredPort}`);
|
|
44
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Normalize telescope configuration
|
|
48
|
+
* @internal Exported for testing
|
|
49
|
+
*/
|
|
50
|
+
function normalizeTelescopeConfig(config) {
|
|
51
|
+
if (config === false) return void 0;
|
|
52
|
+
const isEnabled = config === true || config === void 0 || config.enabled !== false;
|
|
53
|
+
if (!isEnabled) return void 0;
|
|
54
|
+
const telescopeConfig = typeof config === "object" ? config : {};
|
|
55
|
+
return {
|
|
56
|
+
enabled: true,
|
|
57
|
+
path: telescopeConfig.path ?? "/__telescope",
|
|
58
|
+
ignore: telescopeConfig.ignore ?? [],
|
|
59
|
+
recordBody: telescopeConfig.recordBody ?? true,
|
|
60
|
+
maxEntries: telescopeConfig.maxEntries ?? 1e3,
|
|
61
|
+
websocket: telescopeConfig.websocket ?? true
|
|
62
|
+
};
|
|
63
|
+
}
|
|
45
64
|
async function devCommand(options) {
|
|
46
65
|
const config = await loadConfig();
|
|
47
66
|
const resolved = resolveProviders(config, { provider: "server" });
|
|
@@ -55,28 +74,49 @@ async function devCommand(options) {
|
|
|
55
74
|
const envParserImportPattern = !envParserName ? "envParser" : envParserName === "envParser" ? "{ envParser }" : `{ ${envParserName} as envParser }`;
|
|
56
75
|
const [loggerPath, loggerName] = config.logger.split("#");
|
|
57
76
|
const loggerImportPattern = !loggerName ? "logger" : loggerName === "logger" ? "{ logger }" : `{ ${loggerName} as logger }`;
|
|
77
|
+
const telescope = normalizeTelescopeConfig(config.telescope);
|
|
78
|
+
if (telescope) logger.log(`🔭 Telescope enabled at ${telescope.path}`);
|
|
58
79
|
const buildContext = {
|
|
59
80
|
envParserPath,
|
|
60
81
|
envParserImportPattern,
|
|
61
82
|
loggerPath,
|
|
62
|
-
loggerImportPattern
|
|
83
|
+
loggerImportPattern,
|
|
84
|
+
telescope
|
|
63
85
|
};
|
|
64
86
|
await buildServer(config, buildContext, resolved.providers[0], resolved.enableOpenApi);
|
|
65
|
-
const
|
|
87
|
+
const runtime = config.runtime ?? "node";
|
|
88
|
+
const devServer = new DevServer(resolved.providers[0], options.port || 3e3, resolved.enableOpenApi, telescope, runtime);
|
|
66
89
|
await devServer.start();
|
|
90
|
+
const envParserFile = config.envParser.split("#")[0];
|
|
91
|
+
const loggerFile = config.logger.split("#")[0];
|
|
67
92
|
const watchPatterns = [
|
|
68
93
|
config.routes,
|
|
69
94
|
...config.functions ? [config.functions] : [],
|
|
70
95
|
...config.crons ? [config.crons] : [],
|
|
71
96
|
...config.subscribers ? [config.subscribers] : [],
|
|
72
|
-
|
|
73
|
-
|
|
97
|
+
envParserFile.endsWith(".ts") ? envParserFile : `${envParserFile}.ts`,
|
|
98
|
+
loggerFile.endsWith(".ts") ? loggerFile : `${loggerFile}.ts`
|
|
74
99
|
].flat();
|
|
75
|
-
|
|
76
|
-
|
|
100
|
+
const normalizedPatterns = watchPatterns.map((p) => p.startsWith("./") ? p.slice(2) : p);
|
|
101
|
+
logger.log(`👀 Watching for changes in: ${normalizedPatterns.join(", ")}`);
|
|
102
|
+
const resolvedFiles = await fg(normalizedPatterns, {
|
|
103
|
+
cwd: process.cwd(),
|
|
104
|
+
absolute: false,
|
|
105
|
+
onlyFiles: true
|
|
106
|
+
});
|
|
107
|
+
const dirsToWatch = [...new Set(resolvedFiles.map((f) => f.split("/").slice(0, -1).join("/")))];
|
|
108
|
+
logger.log(`📁 Found ${resolvedFiles.length} files in ${dirsToWatch.length} directories`);
|
|
109
|
+
const watcher = chokidar.watch([...resolvedFiles, ...dirsToWatch], {
|
|
77
110
|
ignored: /(^|[\/\\])\../,
|
|
78
111
|
persistent: true,
|
|
79
|
-
ignoreInitial: true
|
|
112
|
+
ignoreInitial: true,
|
|
113
|
+
cwd: process.cwd()
|
|
114
|
+
});
|
|
115
|
+
watcher.on("ready", () => {
|
|
116
|
+
logger.log("🔍 File watcher ready");
|
|
117
|
+
});
|
|
118
|
+
watcher.on("error", (error) => {
|
|
119
|
+
logger.error("❌ Watcher error:", error);
|
|
80
120
|
});
|
|
81
121
|
let rebuildTimeout = null;
|
|
82
122
|
watcher.on("change", async (path) => {
|
|
@@ -129,10 +169,12 @@ var DevServer = class {
|
|
|
129
169
|
serverProcess = null;
|
|
130
170
|
isRunning = false;
|
|
131
171
|
actualPort;
|
|
132
|
-
constructor(provider, requestedPort, enableOpenApi) {
|
|
172
|
+
constructor(provider, requestedPort, enableOpenApi, telescope, runtime = "node") {
|
|
133
173
|
this.provider = provider;
|
|
134
174
|
this.requestedPort = requestedPort;
|
|
135
175
|
this.enableOpenApi = enableOpenApi;
|
|
176
|
+
this.telescope = telescope;
|
|
177
|
+
this.runtime = runtime;
|
|
136
178
|
this.actualPort = requestedPort;
|
|
137
179
|
}
|
|
138
180
|
async start() {
|
|
@@ -152,7 +194,8 @@ var DevServer = class {
|
|
|
152
194
|
env: {
|
|
153
195
|
...process.env,
|
|
154
196
|
NODE_ENV: "development"
|
|
155
|
-
}
|
|
197
|
+
},
|
|
198
|
+
detached: true
|
|
156
199
|
});
|
|
157
200
|
this.isRunning = true;
|
|
158
201
|
this.serverProcess.on("error", (error) => {
|
|
@@ -166,16 +209,22 @@ var DevServer = class {
|
|
|
166
209
|
if (this.isRunning) {
|
|
167
210
|
logger.log(`\n🎉 Server running at http://localhost:${this.actualPort}`);
|
|
168
211
|
if (this.enableOpenApi) logger.log(`📚 API Docs available at http://localhost:${this.actualPort}/docs`);
|
|
212
|
+
if (this.telescope) logger.log(`🔭 Telescope available at http://localhost:${this.actualPort}${this.telescope.path}`);
|
|
169
213
|
}
|
|
170
214
|
}
|
|
171
215
|
async stop() {
|
|
172
216
|
if (this.serverProcess && this.isRunning) {
|
|
173
|
-
this.serverProcess.
|
|
217
|
+
const pid = this.serverProcess.pid;
|
|
218
|
+
if (pid) try {
|
|
219
|
+
process.kill(-pid, "SIGTERM");
|
|
220
|
+
} catch {}
|
|
174
221
|
await new Promise((resolve) => {
|
|
175
222
|
const timeout = setTimeout(() => {
|
|
176
|
-
|
|
223
|
+
if (pid) try {
|
|
224
|
+
process.kill(-pid, "SIGKILL");
|
|
225
|
+
} catch {}
|
|
177
226
|
resolve();
|
|
178
|
-
},
|
|
227
|
+
}, 3e3);
|
|
179
228
|
this.serverProcess?.on("exit", () => {
|
|
180
229
|
clearTimeout(timeout);
|
|
181
230
|
resolve();
|
|
@@ -186,7 +235,15 @@ var DevServer = class {
|
|
|
186
235
|
}
|
|
187
236
|
}
|
|
188
237
|
async restart() {
|
|
238
|
+
const portToReuse = this.actualPort;
|
|
189
239
|
await this.stop();
|
|
240
|
+
let attempts = 0;
|
|
241
|
+
while (attempts < 30) {
|
|
242
|
+
if (await isPortAvailable(portToReuse)) break;
|
|
243
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
244
|
+
attempts++;
|
|
245
|
+
}
|
|
246
|
+
this.requestedPort = portToReuse;
|
|
190
247
|
await this.start();
|
|
191
248
|
}
|
|
192
249
|
async createServerEntry() {
|
|
@@ -194,6 +251,20 @@ var DevServer = class {
|
|
|
194
251
|
const { relative: relative$1, dirname: dirname$1 } = await import("node:path");
|
|
195
252
|
const serverPath = join(process.cwd(), ".gkm", this.provider, "server.ts");
|
|
196
253
|
const relativeAppPath = relative$1(dirname$1(serverPath), join(dirname$1(serverPath), "app.js"));
|
|
254
|
+
const serveCode = this.runtime === "bun" ? `Bun.serve({
|
|
255
|
+
port,
|
|
256
|
+
fetch: app.fetch,
|
|
257
|
+
});` : `const { serve } = await import('@hono/node-server');
|
|
258
|
+
const server = serve({
|
|
259
|
+
fetch: app.fetch,
|
|
260
|
+
port,
|
|
261
|
+
});
|
|
262
|
+
// Inject WebSocket support if available
|
|
263
|
+
const injectWs = (app as any).__injectWebSocket;
|
|
264
|
+
if (injectWs) {
|
|
265
|
+
injectWs(server);
|
|
266
|
+
console.log('🔌 Telescope real-time updates enabled');
|
|
267
|
+
}`;
|
|
197
268
|
const content = `#!/usr/bin/env node
|
|
198
269
|
/**
|
|
199
270
|
* Development server entry point
|
|
@@ -205,27 +276,14 @@ const port = process.argv.includes('--port')
|
|
|
205
276
|
? Number.parseInt(process.argv[process.argv.indexOf('--port') + 1])
|
|
206
277
|
: 3000;
|
|
207
278
|
|
|
208
|
-
|
|
279
|
+
// createApp is async to support optional WebSocket setup
|
|
280
|
+
const { app, start } = await createApp(undefined, ${this.enableOpenApi});
|
|
209
281
|
|
|
210
282
|
// Start the server
|
|
211
283
|
start({
|
|
212
284
|
port,
|
|
213
285
|
serve: async (app, port) => {
|
|
214
|
-
|
|
215
|
-
if (typeof Bun !== 'undefined') {
|
|
216
|
-
// Bun runtime
|
|
217
|
-
Bun.serve({
|
|
218
|
-
port,
|
|
219
|
-
fetch: app.fetch,
|
|
220
|
-
});
|
|
221
|
-
} else {
|
|
222
|
-
// Node.js runtime with @hono/node-server
|
|
223
|
-
const { serve } = await import('@hono/node-server');
|
|
224
|
-
serve({
|
|
225
|
-
fetch: app.fetch,
|
|
226
|
-
port,
|
|
227
|
-
});
|
|
228
|
-
}
|
|
286
|
+
${serveCode}
|
|
229
287
|
},
|
|
230
288
|
}).catch((error) => {
|
|
231
289
|
console.error('Failed to start server:', error);
|
|
@@ -237,5 +295,5 @@ start({
|
|
|
237
295
|
};
|
|
238
296
|
|
|
239
297
|
//#endregion
|
|
240
|
-
export { devCommand, findAvailablePort, isPortAvailable };
|
|
241
|
-
//# sourceMappingURL=dev-
|
|
298
|
+
export { devCommand, findAvailablePort, isPortAvailable, normalizeTelescopeConfig };
|
|
299
|
+
//# sourceMappingURL=dev-CpA8AQPX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev-CpA8AQPX.mjs","names":["port: number","err: NodeJS.ErrnoException","preferredPort: number","config: GkmConfig['telescope']","telescopeConfig: TelescopeConfig","options: DevOptions","buildContext: BuildContext","runtime: Runtime","rebuildTimeout: NodeJS.Timeout | null","config: any","context: BuildContext","provider: LegacyProvider","enableOpenApi: boolean","requestedPort: number","telescope?: NormalizedTelescopeConfig"],"sources":["../src/dev/index.ts"],"sourcesContent":["import { type ChildProcess, spawn } from 'node:child_process';\nimport { mkdir } from 'node:fs/promises';\nimport { createServer } from 'node:net';\nimport { join } from 'node:path';\nimport chokidar from 'chokidar';\nimport fg from 'fast-glob';\nimport { resolveProviders } from '../build/providerResolver';\nimport type { BuildContext, NormalizedTelescopeConfig } from '../build/types';\nimport { loadConfig } from '../config';\nimport {\n CronGenerator,\n EndpointGenerator,\n FunctionGenerator,\n SubscriberGenerator,\n} from '../generators';\nimport type {\n GkmConfig,\n LegacyProvider,\n Runtime,\n TelescopeConfig,\n} from '../types';\n\nconst logger = console;\n\n/**\n * Check if a port is available\n * @internal Exported for testing\n */\nexport async function isPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = createServer();\n\n server.once('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n resolve(false);\n } else {\n resolve(false);\n }\n });\n\n server.once('listening', () => {\n server.close();\n resolve(true);\n });\n\n server.listen(port);\n });\n}\n\n/**\n * Find an available port starting from the preferred port\n * @internal Exported for testing\n */\nexport async function findAvailablePort(\n preferredPort: number,\n maxAttempts = 10,\n): Promise<number> {\n for (let i = 0; i < maxAttempts; i++) {\n const port = preferredPort + i;\n if (await isPortAvailable(port)) {\n return port;\n }\n logger.log(`⚠️ Port ${port} is in use, trying ${port + 1}...`);\n }\n\n throw new Error(\n `Could not find an available port after trying ${maxAttempts} ports starting from ${preferredPort}`,\n );\n}\n\n/**\n * Normalize telescope configuration\n * @internal Exported for testing\n */\nexport function normalizeTelescopeConfig(\n config: GkmConfig['telescope'],\n): NormalizedTelescopeConfig | undefined {\n if (config === false) {\n return undefined;\n }\n\n // Default to enabled in development mode\n const isEnabled =\n config === true || config === undefined || config.enabled !== false;\n\n if (!isEnabled) {\n return undefined;\n }\n\n const telescopeConfig: TelescopeConfig =\n typeof config === 'object' ? config : {};\n\n return {\n enabled: true,\n path: telescopeConfig.path ?? '/__telescope',\n ignore: telescopeConfig.ignore ?? [],\n recordBody: telescopeConfig.recordBody ?? true,\n maxEntries: telescopeConfig.maxEntries ?? 1000,\n websocket: telescopeConfig.websocket ?? true,\n };\n}\n\nexport interface DevOptions {\n port?: number;\n enableOpenApi?: boolean;\n}\n\nexport async function devCommand(options: DevOptions): Promise<void> {\n const config = await loadConfig();\n\n // Force server provider for dev mode\n const resolved = resolveProviders(config, { provider: 'server' });\n\n logger.log('🚀 Starting development server...');\n logger.log(`Loading routes from: ${config.routes}`);\n if (config.functions) {\n logger.log(`Loading functions from: ${config.functions}`);\n }\n if (config.crons) {\n logger.log(`Loading crons from: ${config.crons}`);\n }\n if (config.subscribers) {\n logger.log(`Loading subscribers from: ${config.subscribers}`);\n }\n logger.log(`Using envParser: ${config.envParser}`);\n\n // Parse envParser configuration\n const [envParserPath, envParserName] = config.envParser.split('#');\n const envParserImportPattern = !envParserName\n ? 'envParser'\n : envParserName === 'envParser'\n ? '{ envParser }'\n : `{ ${envParserName} as envParser }`;\n\n // Parse logger configuration\n const [loggerPath, loggerName] = config.logger.split('#');\n const loggerImportPattern = !loggerName\n ? 'logger'\n : loggerName === 'logger'\n ? '{ logger }'\n : `{ ${loggerName} as logger }`;\n\n // Normalize telescope configuration\n const telescope = normalizeTelescopeConfig(config.telescope);\n if (telescope) {\n logger.log(`🔭 Telescope enabled at ${telescope.path}`);\n }\n\n const buildContext: BuildContext = {\n envParserPath,\n envParserImportPattern,\n loggerPath,\n loggerImportPattern,\n telescope,\n };\n\n // Build initial version\n await buildServer(\n config,\n buildContext,\n resolved.providers[0] as LegacyProvider,\n resolved.enableOpenApi,\n );\n\n // Determine runtime (default to node)\n const runtime: Runtime = config.runtime ?? 'node';\n\n // Start the dev server\n const devServer = new DevServer(\n resolved.providers[0] as LegacyProvider,\n options.port || 3000,\n resolved.enableOpenApi,\n telescope,\n runtime,\n );\n\n await devServer.start();\n\n // Watch for file changes\n const envParserFile = config.envParser.split('#')[0];\n const loggerFile = config.logger.split('#')[0];\n\n const watchPatterns = [\n config.routes,\n ...(config.functions ? [config.functions] : []),\n ...(config.crons ? [config.crons] : []),\n ...(config.subscribers ? [config.subscribers] : []),\n // Add .ts extension if not present for config files\n envParserFile.endsWith('.ts') ? envParserFile : `${envParserFile}.ts`,\n loggerFile.endsWith('.ts') ? loggerFile : `${loggerFile}.ts`,\n ].flat();\n\n // Normalize patterns - remove leading ./ when using cwd option\n const normalizedPatterns = watchPatterns.map((p) =>\n p.startsWith('./') ? p.slice(2) : p,\n );\n\n logger.log(`👀 Watching for changes in: ${normalizedPatterns.join(', ')}`);\n\n // Resolve glob patterns to actual files (chokidar 4.x doesn't support globs)\n const resolvedFiles = await fg(normalizedPatterns, {\n cwd: process.cwd(),\n absolute: false,\n onlyFiles: true,\n });\n\n // Also watch the directories for new files\n const dirsToWatch = [\n ...new Set(resolvedFiles.map((f) => f.split('/').slice(0, -1).join('/'))),\n ];\n\n logger.log(\n `📁 Found ${resolvedFiles.length} files in ${dirsToWatch.length} directories`,\n );\n\n const watcher = chokidar.watch([...resolvedFiles, ...dirsToWatch], {\n ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\n persistent: true,\n ignoreInitial: true,\n cwd: process.cwd(),\n });\n\n watcher.on('ready', () => {\n logger.log('🔍 File watcher ready');\n });\n\n watcher.on('error', (error) => {\n logger.error('❌ Watcher error:', error);\n });\n\n let rebuildTimeout: NodeJS.Timeout | null = null;\n\n watcher.on('change', async (path) => {\n logger.log(`📝 File changed: ${path}`);\n\n // Debounce rebuilds\n if (rebuildTimeout) {\n clearTimeout(rebuildTimeout);\n }\n\n rebuildTimeout = setTimeout(async () => {\n try {\n logger.log('🔄 Rebuilding...');\n await buildServer(\n config,\n buildContext,\n resolved.providers[0] as LegacyProvider,\n resolved.enableOpenApi,\n );\n logger.log('✅ Rebuild complete, restarting server...');\n await devServer.restart();\n } catch (error) {\n logger.error('❌ Rebuild failed:', (error as Error).message);\n }\n }, 300);\n });\n\n // Handle graceful shutdown\n const shutdown = async () => {\n logger.log('\\n🛑 Shutting down...');\n await watcher.close();\n await devServer.stop();\n process.exit(0);\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n}\n\nasync function buildServer(\n config: any,\n context: BuildContext,\n provider: LegacyProvider,\n enableOpenApi: boolean,\n): Promise<void> {\n // Initialize generators\n const endpointGenerator = new EndpointGenerator();\n const functionGenerator = new FunctionGenerator();\n const cronGenerator = new CronGenerator();\n const subscriberGenerator = new SubscriberGenerator();\n\n // Load all constructs\n const [allEndpoints, allFunctions, allCrons, allSubscribers] =\n await Promise.all([\n endpointGenerator.load(config.routes),\n config.functions ? functionGenerator.load(config.functions) : [],\n config.crons ? cronGenerator.load(config.crons) : [],\n config.subscribers ? subscriberGenerator.load(config.subscribers) : [],\n ]);\n\n // Ensure .gkm directory exists\n const outputDir = join(process.cwd(), '.gkm', provider);\n await mkdir(outputDir, { recursive: true });\n\n // Build for server provider\n await Promise.all([\n endpointGenerator.build(context, allEndpoints, outputDir, {\n provider,\n enableOpenApi,\n }),\n functionGenerator.build(context, allFunctions, outputDir, { provider }),\n cronGenerator.build(context, allCrons, outputDir, { provider }),\n subscriberGenerator.build(context, allSubscribers, outputDir, { provider }),\n ]);\n}\n\nclass DevServer {\n private serverProcess: ChildProcess | null = null;\n private isRunning = false;\n private actualPort: number;\n\n constructor(\n private provider: LegacyProvider,\n private requestedPort: number,\n private enableOpenApi: boolean,\n private telescope?: NormalizedTelescopeConfig,\n private runtime: Runtime = 'node',\n ) {\n this.actualPort = requestedPort;\n }\n\n async start(): Promise<void> {\n if (this.isRunning) {\n await this.stop();\n }\n\n // Find an available port\n this.actualPort = await findAvailablePort(this.requestedPort);\n\n if (this.actualPort !== this.requestedPort) {\n logger.log(\n `ℹ️ Port ${this.requestedPort} was in use, using port ${this.actualPort} instead`,\n );\n }\n\n const serverEntryPath = join(\n process.cwd(),\n '.gkm',\n this.provider,\n 'server.ts',\n );\n\n // Create server entry file\n await this.createServerEntry();\n\n logger.log(`\\n✨ Starting server on port ${this.actualPort}...`);\n\n // Start the server using tsx (TypeScript execution)\n // Use detached: true so we can kill the entire process tree\n this.serverProcess = spawn(\n 'npx',\n ['tsx', serverEntryPath, '--port', this.actualPort.toString()],\n {\n stdio: 'inherit',\n env: { ...process.env, NODE_ENV: 'development' },\n detached: true,\n },\n );\n\n this.isRunning = true;\n\n this.serverProcess.on('error', (error) => {\n logger.error('❌ Server error:', error);\n });\n\n this.serverProcess.on('exit', (code, signal) => {\n if (code !== null && code !== 0 && signal !== 'SIGTERM') {\n logger.error(`❌ Server exited with code ${code}`);\n }\n this.isRunning = false;\n });\n\n // Give the server a moment to start\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n if (this.isRunning) {\n logger.log(`\\n🎉 Server running at http://localhost:${this.actualPort}`);\n if (this.enableOpenApi) {\n logger.log(\n `📚 API Docs available at http://localhost:${this.actualPort}/docs`,\n );\n }\n if (this.telescope) {\n logger.log(\n `🔭 Telescope available at http://localhost:${this.actualPort}${this.telescope.path}`,\n );\n }\n }\n }\n\n async stop(): Promise<void> {\n if (this.serverProcess && this.isRunning) {\n const pid = this.serverProcess.pid;\n\n // Kill the entire process group (negative PID kills the group)\n if (pid) {\n try {\n process.kill(-pid, 'SIGTERM');\n } catch {\n // Process might already be dead\n }\n }\n\n // Wait for process to exit\n await new Promise<void>((resolve) => {\n const timeout = setTimeout(() => {\n if (pid) {\n try {\n process.kill(-pid, 'SIGKILL');\n } catch {\n // Process might already be dead\n }\n }\n resolve();\n }, 3000);\n\n this.serverProcess?.on('exit', () => {\n clearTimeout(timeout);\n resolve();\n });\n });\n\n this.serverProcess = null;\n this.isRunning = false;\n }\n }\n\n async restart(): Promise<void> {\n const portToReuse = this.actualPort;\n await this.stop();\n\n // Wait for port to be released (up to 3 seconds)\n let attempts = 0;\n while (attempts < 30) {\n if (await isPortAvailable(portToReuse)) {\n break;\n }\n await new Promise((resolve) => setTimeout(resolve, 100));\n attempts++;\n }\n\n // Force reuse the same port\n this.requestedPort = portToReuse;\n await this.start();\n }\n\n private async createServerEntry(): Promise<void> {\n const { writeFile } = await import('node:fs/promises');\n const { relative, dirname } = await import('node:path');\n\n const serverPath = join(process.cwd(), '.gkm', this.provider, 'server.ts');\n\n const relativeAppPath = relative(\n dirname(serverPath),\n join(dirname(serverPath), 'app.js'),\n );\n\n const serveCode =\n this.runtime === 'bun'\n ? `Bun.serve({\n port,\n fetch: app.fetch,\n });`\n : `const { serve } = await import('@hono/node-server');\n const server = serve({\n fetch: app.fetch,\n port,\n });\n // Inject WebSocket support if available\n const injectWs = (app as any).__injectWebSocket;\n if (injectWs) {\n injectWs(server);\n console.log('🔌 Telescope real-time updates enabled');\n }`;\n\n const content = `#!/usr/bin/env node\n/**\n * Development server entry point\n * This file is auto-generated by 'gkm dev'\n */\nimport { createApp } from './${relativeAppPath.startsWith('.') ? relativeAppPath : './' + relativeAppPath}';\n\nconst port = process.argv.includes('--port')\n ? Number.parseInt(process.argv[process.argv.indexOf('--port') + 1])\n : 3000;\n\n// createApp is async to support optional WebSocket setup\nconst { app, start } = await createApp(undefined, ${this.enableOpenApi});\n\n// Start the server\nstart({\n port,\n serve: async (app, port) => {\n ${serveCode}\n },\n}).catch((error) => {\n console.error('Failed to start server:', error);\n process.exit(1);\n});\n`;\n\n await writeFile(serverPath, content);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAsBA,MAAM,SAAS;;;;;AAMf,eAAsB,gBAAgBA,MAAgC;AACpE,QAAO,IAAI,QAAQ,CAAC,YAAY;EAC9B,MAAM,SAAS,cAAc;AAE7B,SAAO,KAAK,SAAS,CAACC,QAA+B;AACnD,OAAI,IAAI,SAAS,aACf,SAAQ,MAAM;OAEd,SAAQ,MAAM;EAEjB,EAAC;AAEF,SAAO,KAAK,aAAa,MAAM;AAC7B,UAAO,OAAO;AACd,WAAQ,KAAK;EACd,EAAC;AAEF,SAAO,OAAO,KAAK;CACpB;AACF;;;;;AAMD,eAAsB,kBACpBC,eACA,cAAc,IACG;AACjB,MAAK,IAAI,IAAI,GAAG,IAAI,aAAa,KAAK;EACpC,MAAM,OAAO,gBAAgB;AAC7B,MAAI,MAAM,gBAAgB,KAAK,CAC7B,QAAO;AAET,SAAO,KAAK,WAAW,KAAK,qBAAqB,OAAO,EAAE,KAAK;CAChE;AAED,OAAM,IAAI,OACP,gDAAgD,YAAY,uBAAuB,cAAc;AAErG;;;;;AAMD,SAAgB,yBACdC,QACuC;AACvC,KAAI,WAAW,MACb;CAIF,MAAM,YACJ,WAAW,QAAQ,qBAAwB,OAAO,YAAY;AAEhE,MAAK,UACH;CAGF,MAAMC,yBACG,WAAW,WAAW,SAAS,CAAE;AAE1C,QAAO;EACL,SAAS;EACT,MAAM,gBAAgB,QAAQ;EAC9B,QAAQ,gBAAgB,UAAU,CAAE;EACpC,YAAY,gBAAgB,cAAc;EAC1C,YAAY,gBAAgB,cAAc;EAC1C,WAAW,gBAAgB,aAAa;CACzC;AACF;AAOD,eAAsB,WAAWC,SAAoC;CACnE,MAAM,SAAS,MAAM,YAAY;CAGjC,MAAM,WAAW,iBAAiB,QAAQ,EAAE,UAAU,SAAU,EAAC;AAEjE,QAAO,IAAI,oCAAoC;AAC/C,QAAO,KAAK,uBAAuB,OAAO,OAAO,EAAE;AACnD,KAAI,OAAO,UACT,QAAO,KAAK,0BAA0B,OAAO,UAAU,EAAE;AAE3D,KAAI,OAAO,MACT,QAAO,KAAK,sBAAsB,OAAO,MAAM,EAAE;AAEnD,KAAI,OAAO,YACT,QAAO,KAAK,4BAA4B,OAAO,YAAY,EAAE;AAE/D,QAAO,KAAK,mBAAmB,OAAO,UAAU,EAAE;CAGlD,MAAM,CAAC,eAAe,cAAc,GAAG,OAAO,UAAU,MAAM,IAAI;CAClE,MAAM,0BAA0B,gBAC5B,cACA,kBAAkB,cAChB,mBACC,IAAI,cAAc;CAGzB,MAAM,CAAC,YAAY,WAAW,GAAG,OAAO,OAAO,MAAM,IAAI;CACzD,MAAM,uBAAuB,aACzB,WACA,eAAe,WACb,gBACC,IAAI,WAAW;CAGtB,MAAM,YAAY,yBAAyB,OAAO,UAAU;AAC5D,KAAI,UACF,QAAO,KAAK,0BAA0B,UAAU,KAAK,EAAE;CAGzD,MAAMC,eAA6B;EACjC;EACA;EACA;EACA;EACA;CACD;AAGD,OAAM,YACJ,QACA,cACA,SAAS,UAAU,IACnB,SAAS,cACV;CAGD,MAAMC,UAAmB,OAAO,WAAW;CAG3C,MAAM,YAAY,IAAI,UACpB,SAAS,UAAU,IACnB,QAAQ,QAAQ,KAChB,SAAS,eACT,WACA;AAGF,OAAM,UAAU,OAAO;CAGvB,MAAM,gBAAgB,OAAO,UAAU,MAAM,IAAI,CAAC;CAClD,MAAM,aAAa,OAAO,OAAO,MAAM,IAAI,CAAC;CAE5C,MAAM,gBAAgB;EACpB,OAAO;EACP,GAAI,OAAO,YAAY,CAAC,OAAO,SAAU,IAAG,CAAE;EAC9C,GAAI,OAAO,QAAQ,CAAC,OAAO,KAAM,IAAG,CAAE;EACtC,GAAI,OAAO,cAAc,CAAC,OAAO,WAAY,IAAG,CAAE;EAElD,cAAc,SAAS,MAAM,GAAG,iBAAiB,EAAE,cAAc;EACjE,WAAW,SAAS,MAAM,GAAG,cAAc,EAAE,WAAW;CACzD,EAAC,MAAM;CAGR,MAAM,qBAAqB,cAAc,IAAI,CAAC,MAC5C,EAAE,WAAW,KAAK,GAAG,EAAE,MAAM,EAAE,GAAG,EACnC;AAED,QAAO,KAAK,8BAA8B,mBAAmB,KAAK,KAAK,CAAC,EAAE;CAG1E,MAAM,gBAAgB,MAAM,GAAG,oBAAoB;EACjD,KAAK,QAAQ,KAAK;EAClB,UAAU;EACV,WAAW;CACZ,EAAC;CAGF,MAAM,cAAc,CAClB,GAAG,IAAI,IAAI,cAAc,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,IAAI,CAAC,CACzE;AAED,QAAO,KACJ,WAAW,cAAc,OAAO,YAAY,YAAY,OAAO,cACjE;CAED,MAAM,UAAU,SAAS,MAAM,CAAC,GAAG,eAAe,GAAG,WAAY,GAAE;EACjE,SAAS;EACT,YAAY;EACZ,eAAe;EACf,KAAK,QAAQ,KAAK;CACnB,EAAC;AAEF,SAAQ,GAAG,SAAS,MAAM;AACxB,SAAO,IAAI,wBAAwB;CACpC,EAAC;AAEF,SAAQ,GAAG,SAAS,CAAC,UAAU;AAC7B,SAAO,MAAM,oBAAoB,MAAM;CACxC,EAAC;CAEF,IAAIC,iBAAwC;AAE5C,SAAQ,GAAG,UAAU,OAAO,SAAS;AACnC,SAAO,KAAK,mBAAmB,KAAK,EAAE;AAGtC,MAAI,eACF,cAAa,eAAe;AAG9B,mBAAiB,WAAW,YAAY;AACtC,OAAI;AACF,WAAO,IAAI,mBAAmB;AAC9B,UAAM,YACJ,QACA,cACA,SAAS,UAAU,IACnB,SAAS,cACV;AACD,WAAO,IAAI,2CAA2C;AACtD,UAAM,UAAU,SAAS;GAC1B,SAAQ,OAAO;AACd,WAAO,MAAM,qBAAsB,MAAgB,QAAQ;GAC5D;EACF,GAAE,IAAI;CACR,EAAC;CAGF,MAAM,WAAW,YAAY;AAC3B,SAAO,IAAI,wBAAwB;AACnC,QAAM,QAAQ,OAAO;AACrB,QAAM,UAAU,MAAM;AACtB,UAAQ,KAAK,EAAE;CAChB;AAED,SAAQ,GAAG,UAAU,SAAS;AAC9B,SAAQ,GAAG,WAAW,SAAS;AAChC;AAED,eAAe,YACbC,QACAC,SACAC,UACAC,eACe;CAEf,MAAM,oBAAoB,IAAI;CAC9B,MAAM,oBAAoB,IAAI;CAC9B,MAAM,gBAAgB,IAAI;CAC1B,MAAM,sBAAsB,IAAI;CAGhC,MAAM,CAAC,cAAc,cAAc,UAAU,eAAe,GAC1D,MAAM,QAAQ,IAAI;EAChB,kBAAkB,KAAK,OAAO,OAAO;EACrC,OAAO,YAAY,kBAAkB,KAAK,OAAO,UAAU,GAAG,CAAE;EAChE,OAAO,QAAQ,cAAc,KAAK,OAAO,MAAM,GAAG,CAAE;EACpD,OAAO,cAAc,oBAAoB,KAAK,OAAO,YAAY,GAAG,CAAE;CACvE,EAAC;CAGJ,MAAM,YAAY,KAAK,QAAQ,KAAK,EAAE,QAAQ,SAAS;AACvD,OAAM,MAAM,WAAW,EAAE,WAAW,KAAM,EAAC;AAG3C,OAAM,QAAQ,IAAI;EAChB,kBAAkB,MAAM,SAAS,cAAc,WAAW;GACxD;GACA;EACD,EAAC;EACF,kBAAkB,MAAM,SAAS,cAAc,WAAW,EAAE,SAAU,EAAC;EACvE,cAAc,MAAM,SAAS,UAAU,WAAW,EAAE,SAAU,EAAC;EAC/D,oBAAoB,MAAM,SAAS,gBAAgB,WAAW,EAAE,SAAU,EAAC;CAC5E,EAAC;AACH;AAED,IAAM,YAAN,MAAgB;CACd,AAAQ,gBAAqC;CAC7C,AAAQ,YAAY;CACpB,AAAQ;CAER,YACUD,UACAE,eACAD,eACAE,WACAP,UAAmB,QAC3B;EALQ;EACA;EACA;EACA;EACA;AAER,OAAK,aAAa;CACnB;CAED,MAAM,QAAuB;AAC3B,MAAI,KAAK,UACP,OAAM,KAAK,MAAM;AAInB,OAAK,aAAa,MAAM,kBAAkB,KAAK,cAAc;AAE7D,MAAI,KAAK,eAAe,KAAK,cAC3B,QAAO,KACJ,WAAW,KAAK,cAAc,0BAA0B,KAAK,WAAW,UAC1E;EAGH,MAAM,kBAAkB,KACtB,QAAQ,KAAK,EACb,QACA,KAAK,UACL,YACD;AAGD,QAAM,KAAK,mBAAmB;AAE9B,SAAO,KAAK,8BAA8B,KAAK,WAAW,KAAK;AAI/D,OAAK,gBAAgB,MACnB,OACA;GAAC;GAAO;GAAiB;GAAU,KAAK,WAAW,UAAU;EAAC,GAC9D;GACE,OAAO;GACP,KAAK;IAAE,GAAG,QAAQ;IAAK,UAAU;GAAe;GAChD,UAAU;EACX,EACF;AAED,OAAK,YAAY;AAEjB,OAAK,cAAc,GAAG,SAAS,CAAC,UAAU;AACxC,UAAO,MAAM,mBAAmB,MAAM;EACvC,EAAC;AAEF,OAAK,cAAc,GAAG,QAAQ,CAAC,MAAM,WAAW;AAC9C,OAAI,SAAS,QAAQ,SAAS,KAAK,WAAW,UAC5C,QAAO,OAAO,4BAA4B,KAAK,EAAE;AAEnD,QAAK,YAAY;EAClB,EAAC;AAGF,QAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,IAAK;AAExD,MAAI,KAAK,WAAW;AAClB,UAAO,KAAK,0CAA0C,KAAK,WAAW,EAAE;AACxE,OAAI,KAAK,cACP,QAAO,KACJ,4CAA4C,KAAK,WAAW,OAC9D;AAEH,OAAI,KAAK,UACP,QAAO,KACJ,6CAA6C,KAAK,WAAW,EAAE,KAAK,UAAU,KAAK,EACrF;EAEJ;CACF;CAED,MAAM,OAAsB;AAC1B,MAAI,KAAK,iBAAiB,KAAK,WAAW;GACxC,MAAM,MAAM,KAAK,cAAc;AAG/B,OAAI,IACF,KAAI;AACF,YAAQ,MAAM,KAAK,UAAU;GAC9B,QAAO,CAEP;AAIH,SAAM,IAAI,QAAc,CAAC,YAAY;IACnC,MAAM,UAAU,WAAW,MAAM;AAC/B,SAAI,IACF,KAAI;AACF,cAAQ,MAAM,KAAK,UAAU;KAC9B,QAAO,CAEP;AAEH,cAAS;IACV,GAAE,IAAK;AAER,SAAK,eAAe,GAAG,QAAQ,MAAM;AACnC,kBAAa,QAAQ;AACrB,cAAS;IACV,EAAC;GACH;AAED,QAAK,gBAAgB;AACrB,QAAK,YAAY;EAClB;CACF;CAED,MAAM,UAAyB;EAC7B,MAAM,cAAc,KAAK;AACzB,QAAM,KAAK,MAAM;EAGjB,IAAI,WAAW;AACf,SAAO,WAAW,IAAI;AACpB,OAAI,MAAM,gBAAgB,YAAY,CACpC;AAEF,SAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,IAAI;AACvD;EACD;AAGD,OAAK,gBAAgB;AACrB,QAAM,KAAK,OAAO;CACnB;CAED,MAAc,oBAAmC;EAC/C,MAAM,EAAE,wBAAW,GAAG,MAAM,OAAO;EACnC,MAAM,EAAE,sBAAU,oBAAS,GAAG,MAAM,OAAO;EAE3C,MAAM,aAAa,KAAK,QAAQ,KAAK,EAAE,QAAQ,KAAK,UAAU,YAAY;EAE1E,MAAM,kBAAkB,WACtB,UAAQ,WAAW,EACnB,KAAK,UAAQ,WAAW,EAAE,SAAS,CACpC;EAED,MAAM,YACJ,KAAK,YAAY,SACZ;;;YAIA;;;;;;;;;;;EAYP,MAAM,WAAW;;;;;+BAKU,gBAAgB,WAAW,IAAI,GAAG,kBAAkB,OAAO,gBAAgB;;;;;;;oDAOtD,KAAK,cAAc;;;;;;MAMjE,UAAU;;;;;;;AAQZ,QAAM,YAAU,YAAY,QAAQ;CACrC;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
require('../Generator-CDoEXCDg.cjs');
|
|
2
|
-
const require_EndpointGenerator = require('../EndpointGenerator-
|
|
2
|
+
const require_EndpointGenerator = require('../EndpointGenerator-BxNCkus4.cjs');
|
|
3
3
|
|
|
4
4
|
exports.EndpointGenerator = require_EndpointGenerator.EndpointGenerator;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const require_Generator = require('../Generator-CDoEXCDg.cjs');
|
|
2
2
|
const require_CronGenerator = require('../CronGenerator-C6MF8rlG.cjs');
|
|
3
|
-
const require_EndpointGenerator = require('../EndpointGenerator-
|
|
3
|
+
const require_EndpointGenerator = require('../EndpointGenerator-BxNCkus4.cjs');
|
|
4
4
|
const require_FunctionGenerator = require('../FunctionGenerator-FgZUTd8L.cjs');
|
|
5
5
|
const require_SubscriberGenerator = require('../SubscriberGenerator-Bd-a7aiw.cjs');
|
|
6
6
|
require('../generators-CEKtVh81.cjs');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConstructGenerator } from "../Generator-UanJW0_V.mjs";
|
|
2
2
|
import { CronGenerator } from "../CronGenerator-Bh26MaNA.mjs";
|
|
3
|
-
import { EndpointGenerator } from "../EndpointGenerator-
|
|
3
|
+
import { EndpointGenerator } from "../EndpointGenerator-CzDhG7Or.mjs";
|
|
4
4
|
import { FunctionGenerator } from "../FunctionGenerator-BNE_GC7N.mjs";
|
|
5
5
|
import { SubscriberGenerator } from "../SubscriberGenerator-Dnlj_1FK.mjs";
|
|
6
6
|
import "../generators-CsLujGXs.mjs";
|
package/dist/index.cjs
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
2
|
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
|
3
|
-
require('./config-
|
|
3
|
+
require('./config-BVIJpAsa.cjs');
|
|
4
4
|
require('./Generator-CDoEXCDg.cjs');
|
|
5
5
|
require('./CronGenerator-C6MF8rlG.cjs');
|
|
6
|
-
require('./EndpointGenerator-
|
|
6
|
+
require('./EndpointGenerator-BxNCkus4.cjs');
|
|
7
7
|
require('./FunctionGenerator-FgZUTd8L.cjs');
|
|
8
8
|
require('./SubscriberGenerator-Bd-a7aiw.cjs');
|
|
9
9
|
require('./generators-CEKtVh81.cjs');
|
|
10
10
|
require('./manifests-CK1VV_pM.cjs');
|
|
11
11
|
require('./providerResolver-DgvzNfP4.cjs');
|
|
12
|
-
const require_build = require('./build-
|
|
13
|
-
const require_dev = require('./dev-
|
|
12
|
+
const require_build = require('./build-CWtHnJMQ.cjs');
|
|
13
|
+
const require_dev = require('./dev-CgDYC4o8.cjs');
|
|
14
14
|
const require_openapi_react_query = require('./openapi-react-query-D9Z7lh0p.cjs');
|
|
15
|
-
|
|
15
|
+
require('./OpenApiTsGenerator-NBNEoaeO.cjs');
|
|
16
|
+
const require_openapi = require('./openapi-DhK4b0lB.cjs');
|
|
16
17
|
const commander = require_chunk.__toESM(require("commander"));
|
|
17
18
|
|
|
18
19
|
//#region package.json
|
|
19
20
|
var name = "@geekmidas/cli";
|
|
20
|
-
var version = "0.
|
|
21
|
+
var version = "0.4.0";
|
|
22
|
+
var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
|
|
21
23
|
var private$1 = false;
|
|
22
24
|
var type = "module";
|
|
23
25
|
var exports$1 = {
|
|
@@ -68,11 +70,14 @@ var peerDependencies = {
|
|
|
68
70
|
"@geekmidas/constructs": "workspace:~",
|
|
69
71
|
"@geekmidas/envkit": "workspace:~",
|
|
70
72
|
"@geekmidas/logger": "workspace:~",
|
|
71
|
-
"@geekmidas/schema": "workspace:~"
|
|
73
|
+
"@geekmidas/schema": "workspace:~",
|
|
74
|
+
"@geekmidas/telescope": "workspace:~"
|
|
72
75
|
};
|
|
76
|
+
var peerDependenciesMeta = { "@geekmidas/telescope": { "optional": true } };
|
|
73
77
|
var package_default = {
|
|
74
78
|
name,
|
|
75
79
|
version,
|
|
80
|
+
description,
|
|
76
81
|
private: private$1,
|
|
77
82
|
type,
|
|
78
83
|
exports: exports$1,
|
|
@@ -81,7 +86,8 @@ var package_default = {
|
|
|
81
86
|
repository,
|
|
82
87
|
dependencies,
|
|
83
88
|
devDependencies,
|
|
84
|
-
peerDependencies
|
|
89
|
+
peerDependencies,
|
|
90
|
+
peerDependenciesMeta
|
|
85
91
|
};
|
|
86
92
|
|
|
87
93
|
//#endregion
|
|
@@ -142,7 +148,7 @@ program.command("api").description("Manage REST API endpoints").action(() => {
|
|
|
142
148
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
143
149
|
process.stdout.write("REST API management - coming soon\n");
|
|
144
150
|
});
|
|
145
|
-
program.command("openapi").description("Generate OpenAPI
|
|
151
|
+
program.command("openapi").description("Generate OpenAPI specification from endpoints (TypeScript by default)").option("--output <path>", "Output file path for the OpenAPI spec", "openapi.ts").option("--json", "Generate JSON instead of TypeScript (legacy)", false).action(async (options) => {
|
|
146
152
|
try {
|
|
147
153
|
const globalOptions = program.opts();
|
|
148
154
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["Command","pkg","options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }","options: { port?: string; enableOpenapi?: boolean }","options: { output?: string }","options: { input?: string; output?: string; name?: string }"],"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@geekmidas/cli\",\n \"version\": \"0.3.0\",\n \"private\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openapi\": {\n \"types\": \"./dist/openapi.d.ts\",\n \"import\": \"./dist/openapi.mjs\",\n \"require\": \"./dist/openapi.cjs\"\n },\n \"./openapi-react-query\": {\n \"types\": \"./dist/openapi-react-query.d.ts\",\n \"import\": \"./dist/openapi-react-query.mjs\",\n \"require\": \"./dist/openapi-react-query.cjs\"\n }\n },\n \"bin\": {\n \"gkm\": \"./dist/index.cjs\"\n },\n \"scripts\": {\n \"ts\": \"tsc --noEmit --skipLibCheck src/**/*.ts\",\n \"test\": \"vitest\",\n \"test:once\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/geekmidas/toolbox\"\n },\n \"dependencies\": {\n \"@apidevtools/swagger-parser\": \"^10.1.0\",\n \"chokidar\": \"~4.0.3\",\n \"commander\": \"^12.1.0\",\n \"fast-glob\": \"^3.3.2\",\n \"lodash.kebabcase\": \"^4.1.1\",\n \"openapi-typescript\": \"^7.4.2\"\n },\n \"devDependencies\": {\n \"@geekmidas/testkit\": \"workspace:*\",\n \"@types/lodash.kebabcase\": \"^4.1.9\",\n \"@types/node\": \"~24.9.1\",\n \"typescript\": \"^5.8.2\",\n \"vitest\": \"^3.2.4\",\n \"zod\": \"~4.1.13\"\n },\n \"peerDependencies\": {\n \"@geekmidas/constructs\": \"workspace:~\",\n \"@geekmidas/envkit\": \"workspace:~\",\n \"@geekmidas/logger\": \"workspace:~\",\n \"@geekmidas/schema\": \"workspace:~\"\n }\n}\n","#!/usr/bin/env -S npx tsx\n\nimport { Command } from 'commander';\nimport pkg from '../package.json' assert { type: 'json' };\nimport { buildCommand } from './build/index.ts';\nimport { devCommand } from './dev/index.ts';\nimport { generateReactQueryCommand } from './openapi-react-query.ts';\nimport { openapiCommand } from './openapi.ts';\nimport type { LegacyProvider, MainProvider } from './types.ts';\n\nconst program = new Command();\n\nprogram\n .name('gkm')\n .description('GeekMidas backend framework CLI')\n .version(pkg.version)\n .option('--cwd <path>', 'Change working directory');\n\nprogram\n .command('build')\n .description('Build handlers from endpoints, functions, and crons')\n .option(\n '--provider <provider>',\n 'Target provider for generated handlers (aws, server)',\n )\n .option(\n '--providers <providers>',\n '[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)',\n )\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation generation for server builds',\n )\n .action(\n async (options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n // Handle new single provider option\n if (options.provider) {\n if (!['aws', 'server'].includes(options.provider)) {\n console.error(\n `Invalid provider: ${options.provider}. Must be 'aws' or 'server'.`,\n );\n process.exit(1);\n }\n await buildCommand({\n provider: options.provider as MainProvider,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Handle legacy providers option\n else if (options.providers) {\n console.warn(\n '⚠️ --providers flag is deprecated. Use --provider instead.',\n );\n const providerList = [\n ...new Set(options.providers.split(',').map((p) => p.trim())),\n ] as LegacyProvider[];\n await buildCommand({\n providers: providerList,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Default to config-driven build\n else {\n await buildCommand({\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n } catch (error) {\n console.error('Build failed:', (error as Error).message);\n process.exit(1);\n }\n },\n );\n\nprogram\n .command('dev')\n .description('Start development server with automatic reload')\n .option('--port <port>', 'Port to run the development server on', '3000')\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation for development server',\n true,\n )\n .action(async (options: { port?: string; enableOpenapi?: boolean }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n await devCommand({\n port: options.port ? Number.parseInt(options.port) : 3000,\n enableOpenApi: options.enableOpenapi ?? true,\n });\n } catch (error) {\n console.error('Dev server failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('cron')\n .description('Manage cron jobs')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Cron management - coming soon\\n');\n });\n\nprogram\n .command('function')\n .description('Manage serverless functions')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Serverless function management - coming soon\\n');\n });\n\nprogram\n .command('api')\n .description('Manage REST API endpoints')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('REST API management - coming soon\\n');\n });\n\nprogram\n .command('openapi')\n .description('Generate OpenAPI 3.0 specification from endpoints')\n .option(\n '--output <path>',\n 'Output file path for the OpenAPI spec',\n 'openapi.json',\n )\n .action(async (options: { output?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await openapiCommand(options);\n } catch (error) {\n console.error('OpenAPI generation failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('generate:react-query')\n .description('Generate React Query hooks from OpenAPI specification')\n .option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')\n .option(\n '--output <path>',\n 'Output file path for generated hooks',\n 'src/api/hooks.ts',\n )\n .option('--name <name>', 'API name prefix for generated code', 'API')\n .action(\n async (options: { input?: string; output?: string; name?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await generateReactQueryCommand(options);\n } catch (error) {\n console.error(\n 'React Query generation failed:',\n (error as Error).message,\n );\n process.exit(1);\n }\n },\n );\n\nprogram.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["Command","pkg","options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }","options: { port?: string; enableOpenapi?: boolean }","options: { output?: string; json?: boolean }","options: { input?: string; output?: string; name?: string }"],"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@geekmidas/cli\",\n \"version\": \"0.4.0\",\n \"description\": \"CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs\",\n \"private\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openapi\": {\n \"types\": \"./dist/openapi.d.ts\",\n \"import\": \"./dist/openapi.mjs\",\n \"require\": \"./dist/openapi.cjs\"\n },\n \"./openapi-react-query\": {\n \"types\": \"./dist/openapi-react-query.d.ts\",\n \"import\": \"./dist/openapi-react-query.mjs\",\n \"require\": \"./dist/openapi-react-query.cjs\"\n }\n },\n \"bin\": {\n \"gkm\": \"./dist/index.cjs\"\n },\n \"scripts\": {\n \"ts\": \"tsc --noEmit --skipLibCheck src/**/*.ts\",\n \"test\": \"vitest\",\n \"test:once\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/geekmidas/toolbox\"\n },\n \"dependencies\": {\n \"@apidevtools/swagger-parser\": \"^10.1.0\",\n \"chokidar\": \"~4.0.3\",\n \"commander\": \"^12.1.0\",\n \"fast-glob\": \"^3.3.2\",\n \"lodash.kebabcase\": \"^4.1.1\",\n \"openapi-typescript\": \"^7.4.2\"\n },\n \"devDependencies\": {\n \"@geekmidas/testkit\": \"workspace:*\",\n \"@types/lodash.kebabcase\": \"^4.1.9\",\n \"@types/node\": \"~24.9.1\",\n \"typescript\": \"^5.8.2\",\n \"vitest\": \"^3.2.4\",\n \"zod\": \"~4.1.13\"\n },\n \"peerDependencies\": {\n \"@geekmidas/constructs\": \"workspace:~\",\n \"@geekmidas/envkit\": \"workspace:~\",\n \"@geekmidas/logger\": \"workspace:~\",\n \"@geekmidas/schema\": \"workspace:~\",\n \"@geekmidas/telescope\": \"workspace:~\"\n },\n \"peerDependenciesMeta\": {\n \"@geekmidas/telescope\": {\n \"optional\": true\n }\n }\n}\n","#!/usr/bin/env -S npx tsx\n\nimport { Command } from 'commander';\nimport pkg from '../package.json' assert { type: 'json' };\nimport { buildCommand } from './build/index.ts';\nimport { devCommand } from './dev/index.ts';\nimport { generateReactQueryCommand } from './openapi-react-query.ts';\nimport { openapiCommand } from './openapi.ts';\nimport type { LegacyProvider, MainProvider } from './types.ts';\n\nconst program = new Command();\n\nprogram\n .name('gkm')\n .description('GeekMidas backend framework CLI')\n .version(pkg.version)\n .option('--cwd <path>', 'Change working directory');\n\nprogram\n .command('build')\n .description('Build handlers from endpoints, functions, and crons')\n .option(\n '--provider <provider>',\n 'Target provider for generated handlers (aws, server)',\n )\n .option(\n '--providers <providers>',\n '[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)',\n )\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation generation for server builds',\n )\n .action(\n async (options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n // Handle new single provider option\n if (options.provider) {\n if (!['aws', 'server'].includes(options.provider)) {\n console.error(\n `Invalid provider: ${options.provider}. Must be 'aws' or 'server'.`,\n );\n process.exit(1);\n }\n await buildCommand({\n provider: options.provider as MainProvider,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Handle legacy providers option\n else if (options.providers) {\n console.warn(\n '⚠️ --providers flag is deprecated. Use --provider instead.',\n );\n const providerList = [\n ...new Set(options.providers.split(',').map((p) => p.trim())),\n ] as LegacyProvider[];\n await buildCommand({\n providers: providerList,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Default to config-driven build\n else {\n await buildCommand({\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n } catch (error) {\n console.error('Build failed:', (error as Error).message);\n process.exit(1);\n }\n },\n );\n\nprogram\n .command('dev')\n .description('Start development server with automatic reload')\n .option('--port <port>', 'Port to run the development server on', '3000')\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation for development server',\n true,\n )\n .action(async (options: { port?: string; enableOpenapi?: boolean }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n await devCommand({\n port: options.port ? Number.parseInt(options.port) : 3000,\n enableOpenApi: options.enableOpenapi ?? true,\n });\n } catch (error) {\n console.error('Dev server failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('cron')\n .description('Manage cron jobs')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Cron management - coming soon\\n');\n });\n\nprogram\n .command('function')\n .description('Manage serverless functions')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Serverless function management - coming soon\\n');\n });\n\nprogram\n .command('api')\n .description('Manage REST API endpoints')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('REST API management - coming soon\\n');\n });\n\nprogram\n .command('openapi')\n .description(\n 'Generate OpenAPI specification from endpoints (TypeScript by default)',\n )\n .option(\n '--output <path>',\n 'Output file path for the OpenAPI spec',\n 'openapi.ts',\n )\n .option('--json', 'Generate JSON instead of TypeScript (legacy)', false)\n .action(async (options: { output?: string; json?: boolean }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await openapiCommand(options);\n } catch (error) {\n console.error('OpenAPI generation failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('generate:react-query')\n .description('Generate React Query hooks from OpenAPI specification')\n .option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')\n .option(\n '--output <path>',\n 'Output file path for generated hooks',\n 'src/api/hooks.ts',\n )\n .option('--name <name>', 'API name prefix for generated code', 'API')\n .action(\n async (options: { input?: string; output?: string; name?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await generateReactQueryCommand(options);\n } catch (error) {\n console.error(\n 'React Query generation failed:',\n (error as Error).message,\n );\n process.exit(1);\n }\n },\n );\n\nprogram.parse();\n"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
|
-
import "./config-
|
|
2
|
+
import "./config-AFmFKmU0.mjs";
|
|
3
3
|
import "./Generator-UanJW0_V.mjs";
|
|
4
4
|
import "./CronGenerator-Bh26MaNA.mjs";
|
|
5
|
-
import "./EndpointGenerator-
|
|
5
|
+
import "./EndpointGenerator-CzDhG7Or.mjs";
|
|
6
6
|
import "./FunctionGenerator-BNE_GC7N.mjs";
|
|
7
7
|
import "./SubscriberGenerator-Dnlj_1FK.mjs";
|
|
8
8
|
import "./generators-CsLujGXs.mjs";
|
|
9
9
|
import "./manifests-C2eMoMUm.mjs";
|
|
10
10
|
import "./providerResolver-B_TjNF0_.mjs";
|
|
11
|
-
import { buildCommand } from "./build-
|
|
12
|
-
import { devCommand } from "./dev-
|
|
11
|
+
import { buildCommand } from "./build-DyDgu_D1.mjs";
|
|
12
|
+
import { devCommand } from "./dev-CpA8AQPX.mjs";
|
|
13
13
|
import { generateReactQueryCommand } from "./openapi-react-query-MEBlYIM1.mjs";
|
|
14
|
-
import
|
|
14
|
+
import "./OpenApiTsGenerator-q3aWNkuM.mjs";
|
|
15
|
+
import { openapiCommand } from "./openapi-DRTRGhTt.mjs";
|
|
15
16
|
import { Command } from "commander";
|
|
16
17
|
|
|
17
18
|
//#region package.json
|
|
18
19
|
var name = "@geekmidas/cli";
|
|
19
|
-
var version = "0.
|
|
20
|
+
var version = "0.4.0";
|
|
21
|
+
var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
|
|
20
22
|
var private$1 = false;
|
|
21
23
|
var type = "module";
|
|
22
24
|
var exports = {
|
|
@@ -67,11 +69,14 @@ var peerDependencies = {
|
|
|
67
69
|
"@geekmidas/constructs": "workspace:~",
|
|
68
70
|
"@geekmidas/envkit": "workspace:~",
|
|
69
71
|
"@geekmidas/logger": "workspace:~",
|
|
70
|
-
"@geekmidas/schema": "workspace:~"
|
|
72
|
+
"@geekmidas/schema": "workspace:~",
|
|
73
|
+
"@geekmidas/telescope": "workspace:~"
|
|
71
74
|
};
|
|
75
|
+
var peerDependenciesMeta = { "@geekmidas/telescope": { "optional": true } };
|
|
72
76
|
var package_default = {
|
|
73
77
|
name,
|
|
74
78
|
version,
|
|
79
|
+
description,
|
|
75
80
|
private: private$1,
|
|
76
81
|
type,
|
|
77
82
|
exports,
|
|
@@ -80,7 +85,8 @@ var package_default = {
|
|
|
80
85
|
repository,
|
|
81
86
|
dependencies,
|
|
82
87
|
devDependencies,
|
|
83
|
-
peerDependencies
|
|
88
|
+
peerDependencies,
|
|
89
|
+
peerDependenciesMeta
|
|
84
90
|
};
|
|
85
91
|
|
|
86
92
|
//#endregion
|
|
@@ -141,7 +147,7 @@ program.command("api").description("Manage REST API endpoints").action(() => {
|
|
|
141
147
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
142
148
|
process.stdout.write("REST API management - coming soon\n");
|
|
143
149
|
});
|
|
144
|
-
program.command("openapi").description("Generate OpenAPI
|
|
150
|
+
program.command("openapi").description("Generate OpenAPI specification from endpoints (TypeScript by default)").option("--output <path>", "Output file path for the OpenAPI spec", "openapi.ts").option("--json", "Generate JSON instead of TypeScript (legacy)", false).action(async (options) => {
|
|
145
151
|
try {
|
|
146
152
|
const globalOptions = program.opts();
|
|
147
153
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["pkg","options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }","options: { port?: string; enableOpenapi?: boolean }","options: { output?: string }","options: { input?: string; output?: string; name?: string }"],"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@geekmidas/cli\",\n \"version\": \"0.3.0\",\n \"private\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openapi\": {\n \"types\": \"./dist/openapi.d.ts\",\n \"import\": \"./dist/openapi.mjs\",\n \"require\": \"./dist/openapi.cjs\"\n },\n \"./openapi-react-query\": {\n \"types\": \"./dist/openapi-react-query.d.ts\",\n \"import\": \"./dist/openapi-react-query.mjs\",\n \"require\": \"./dist/openapi-react-query.cjs\"\n }\n },\n \"bin\": {\n \"gkm\": \"./dist/index.cjs\"\n },\n \"scripts\": {\n \"ts\": \"tsc --noEmit --skipLibCheck src/**/*.ts\",\n \"test\": \"vitest\",\n \"test:once\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/geekmidas/toolbox\"\n },\n \"dependencies\": {\n \"@apidevtools/swagger-parser\": \"^10.1.0\",\n \"chokidar\": \"~4.0.3\",\n \"commander\": \"^12.1.0\",\n \"fast-glob\": \"^3.3.2\",\n \"lodash.kebabcase\": \"^4.1.1\",\n \"openapi-typescript\": \"^7.4.2\"\n },\n \"devDependencies\": {\n \"@geekmidas/testkit\": \"workspace:*\",\n \"@types/lodash.kebabcase\": \"^4.1.9\",\n \"@types/node\": \"~24.9.1\",\n \"typescript\": \"^5.8.2\",\n \"vitest\": \"^3.2.4\",\n \"zod\": \"~4.1.13\"\n },\n \"peerDependencies\": {\n \"@geekmidas/constructs\": \"workspace:~\",\n \"@geekmidas/envkit\": \"workspace:~\",\n \"@geekmidas/logger\": \"workspace:~\",\n \"@geekmidas/schema\": \"workspace:~\"\n }\n}\n","#!/usr/bin/env -S npx tsx\n\nimport { Command } from 'commander';\nimport pkg from '../package.json' assert { type: 'json' };\nimport { buildCommand } from './build/index.ts';\nimport { devCommand } from './dev/index.ts';\nimport { generateReactQueryCommand } from './openapi-react-query.ts';\nimport { openapiCommand } from './openapi.ts';\nimport type { LegacyProvider, MainProvider } from './types.ts';\n\nconst program = new Command();\n\nprogram\n .name('gkm')\n .description('GeekMidas backend framework CLI')\n .version(pkg.version)\n .option('--cwd <path>', 'Change working directory');\n\nprogram\n .command('build')\n .description('Build handlers from endpoints, functions, and crons')\n .option(\n '--provider <provider>',\n 'Target provider for generated handlers (aws, server)',\n )\n .option(\n '--providers <providers>',\n '[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)',\n )\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation generation for server builds',\n )\n .action(\n async (options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n // Handle new single provider option\n if (options.provider) {\n if (!['aws', 'server'].includes(options.provider)) {\n console.error(\n `Invalid provider: ${options.provider}. Must be 'aws' or 'server'.`,\n );\n process.exit(1);\n }\n await buildCommand({\n provider: options.provider as MainProvider,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Handle legacy providers option\n else if (options.providers) {\n console.warn(\n '⚠️ --providers flag is deprecated. Use --provider instead.',\n );\n const providerList = [\n ...new Set(options.providers.split(',').map((p) => p.trim())),\n ] as LegacyProvider[];\n await buildCommand({\n providers: providerList,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Default to config-driven build\n else {\n await buildCommand({\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n } catch (error) {\n console.error('Build failed:', (error as Error).message);\n process.exit(1);\n }\n },\n );\n\nprogram\n .command('dev')\n .description('Start development server with automatic reload')\n .option('--port <port>', 'Port to run the development server on', '3000')\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation for development server',\n true,\n )\n .action(async (options: { port?: string; enableOpenapi?: boolean }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n await devCommand({\n port: options.port ? Number.parseInt(options.port) : 3000,\n enableOpenApi: options.enableOpenapi ?? true,\n });\n } catch (error) {\n console.error('Dev server failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('cron')\n .description('Manage cron jobs')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Cron management - coming soon\\n');\n });\n\nprogram\n .command('function')\n .description('Manage serverless functions')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Serverless function management - coming soon\\n');\n });\n\nprogram\n .command('api')\n .description('Manage REST API endpoints')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('REST API management - coming soon\\n');\n });\n\nprogram\n .command('openapi')\n .description('Generate OpenAPI 3.0 specification from endpoints')\n .option(\n '--output <path>',\n 'Output file path for the OpenAPI spec',\n 'openapi.json',\n )\n .action(async (options: { output?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await openapiCommand(options);\n } catch (error) {\n console.error('OpenAPI generation failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('generate:react-query')\n .description('Generate React Query hooks from OpenAPI specification')\n .option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')\n .option(\n '--output <path>',\n 'Output file path for generated hooks',\n 'src/api/hooks.ts',\n )\n .option('--name <name>', 'API name prefix for generated code', 'API')\n .action(\n async (options: { input?: string; output?: string; name?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await generateReactQueryCommand(options);\n } catch (error) {\n console.error(\n 'React Query generation failed:',\n (error as Error).message,\n );\n process.exit(1);\n }\n },\n );\n\nprogram.parse();\n"],"mappings":";;;;;;;;;;;;;;;;;WACU;cACG;gBACA;WACH;cACG;CACT,KAAK;EACH,SAAS;EACT,UAAU;EACV,WAAW;CACZ;CACD,aAAa;EACX,SAAS;EACT,UAAU;EACV,WAAW;CACZ;CACD,yBAAyB;EACvB,SAAS;EACT,UAAU;EACV,WAAW;CACZ;AACF;UACM,EACL,OAAO,mBACR;cACU;CACT,MAAM;CACN,QAAQ;CACR,aAAa;CACb,iBAAiB;AAClB;iBACa;CACZ,QAAQ;CACR,OAAO;AACR;mBACe;CACd,+BAA+B;CAC/B,YAAY;CACZ,aAAa;CACb,aAAa;CACb,oBAAoB;CACpB,sBAAsB;AACvB;sBACkB;CACjB,sBAAsB;CACtB,2BAA2B;CAC3B,eAAe;CACf,cAAc;CACd,UAAU;CACV,OAAO;AACR;uBACmB;CAClB,yBAAyB;CACzB,qBAAqB;CACrB,qBAAqB;CACrB,qBAAqB;AACtB;sBAxDH;;;;;;;;;;;;AAyDC;;;;AC/CD,MAAM,UAAU,IAAI;AAEpB,QACG,KAAK,MAAM,CACX,YAAY,kCAAkC,CAC9C,QAAQA,gBAAI,QAAQ,CACpB,OAAO,gBAAgB,2BAA2B;AAErD,QACG,QAAQ,QAAQ,CAChB,YAAY,sDAAsD,CAClE,OACC,yBACA,uDACD,CACA,OACC,2BACA,iGACD,CACA,OACC,oBACA,4DACD,CACA,OACC,OAAOC,YAID;AACJ,KAAI;EACF,MAAM,gBAAgB,QAAQ,MAAM;AACpC,MAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAIlC,MAAI,QAAQ,UAAU;AACpB,QAAK,CAAC,OAAO,QAAS,EAAC,SAAS,QAAQ,SAAS,EAAE;AACjD,YAAQ,OACL,oBAAoB,QAAQ,SAAS,8BACvC;AACD,YAAQ,KAAK,EAAE;GAChB;AACD,SAAM,aAAa;IACjB,UAAU,QAAQ;IAClB,eAAe,QAAQ,iBAAiB;GACzC,EAAC;EACH,WAEQ,QAAQ,WAAW;AAC1B,WAAQ,KACN,8DACD;GACD,MAAM,eAAe,CACnB,GAAG,IAAI,IAAI,QAAQ,UAAU,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAC7D;AACD,SAAM,aAAa;IACjB,WAAW;IACX,eAAe,QAAQ,iBAAiB;GACzC,EAAC;EACH,MAGC,OAAM,aAAa,EACjB,eAAe,QAAQ,iBAAiB,MACzC,EAAC;CAEL,SAAQ,OAAO;AACd,UAAQ,MAAM,iBAAkB,MAAgB,QAAQ;AACxD,UAAQ,KAAK,EAAE;CAChB;AACF,EACF;AAEH,QACG,QAAQ,MAAM,CACd,YAAY,iDAAiD,CAC7D,OAAO,iBAAiB,yCAAyC,OAAO,CACxE,OACC,oBACA,uDACA,KACD,CACA,OAAO,OAAOC,YAAwD;AACrE,KAAI;EACF,MAAM,gBAAgB,QAAQ,MAAM;AACpC,MAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAGlC,QAAM,WAAW;GACf,MAAM,QAAQ,OAAO,OAAO,SAAS,QAAQ,KAAK,GAAG;GACrD,eAAe,QAAQ,iBAAiB;EACzC,EAAC;CACH,SAAQ,OAAO;AACd,UAAQ,MAAM,sBAAuB,MAAgB,QAAQ;AAC7D,UAAQ,KAAK,EAAE;CAChB;AACF,EAAC;AAEJ,QACG,QAAQ,OAAO,CACf,YAAY,mBAAmB,CAC/B,OAAO,MAAM;CACZ,MAAM,gBAAgB,QAAQ,MAAM;AACpC,KAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAElC,SAAQ,OAAO,MAAM,kCAAkC;AACxD,EAAC;AAEJ,QACG,QAAQ,WAAW,CACnB,YAAY,8BAA8B,CAC1C,OAAO,MAAM;CACZ,MAAM,gBAAgB,QAAQ,MAAM;AACpC,KAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAElC,SAAQ,OAAO,MAAM,iDAAiD;AACvE,EAAC;AAEJ,QACG,QAAQ,MAAM,CACd,YAAY,4BAA4B,CACxC,OAAO,MAAM;CACZ,MAAM,gBAAgB,QAAQ,MAAM;AACpC,KAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAElC,SAAQ,OAAO,MAAM,sCAAsC;AAC5D,EAAC;AAEJ,QACG,QAAQ,UAAU,CAClB,YAAY,oDAAoD,CAChE,OACC,mBACA,yCACA,eACD,CACA,OAAO,OAAOC,YAAiC;AAC9C,KAAI;EACF,MAAM,gBAAgB,QAAQ,MAAM;AACpC,MAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAElC,QAAM,eAAe,QAAQ;CAC9B,SAAQ,OAAO;AACd,UAAQ,MAAM,8BAA+B,MAAgB,QAAQ;AACrE,UAAQ,KAAK,EAAE;CAChB;AACF,EAAC;AAEJ,QACG,QAAQ,uBAAuB,CAC/B,YAAY,wDAAwD,CACpE,OAAO,kBAAkB,gCAAgC,eAAe,CACxE,OACC,mBACA,wCACA,mBACD,CACA,OAAO,iBAAiB,sCAAsC,MAAM,CACpE,OACC,OAAOC,YAAgE;AACrE,KAAI;EACF,MAAM,gBAAgB,QAAQ,MAAM;AACpC,MAAI,cAAc,IAChB,SAAQ,MAAM,cAAc,IAAI;AAElC,QAAM,0BAA0B,QAAQ;CACzC,SAAQ,OAAO;AACd,UAAQ,MACN,kCACC,MAAgB,QAClB;AACD,UAAQ,KAAK,EAAE;CAChB;AACF,EACF;AAEH,QAAQ,OAAO"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["pkg","options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }","options: { port?: string; enableOpenapi?: boolean }","options: { output?: string; json?: boolean }","options: { input?: string; output?: string; name?: string }"],"sources":["../package.json","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@geekmidas/cli\",\n \"version\": \"0.4.0\",\n \"description\": \"CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs\",\n \"private\": false,\n \"type\": \"module\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.mjs\",\n \"require\": \"./dist/index.cjs\"\n },\n \"./openapi\": {\n \"types\": \"./dist/openapi.d.ts\",\n \"import\": \"./dist/openapi.mjs\",\n \"require\": \"./dist/openapi.cjs\"\n },\n \"./openapi-react-query\": {\n \"types\": \"./dist/openapi-react-query.d.ts\",\n \"import\": \"./dist/openapi-react-query.mjs\",\n \"require\": \"./dist/openapi-react-query.cjs\"\n }\n },\n \"bin\": {\n \"gkm\": \"./dist/index.cjs\"\n },\n \"scripts\": {\n \"ts\": \"tsc --noEmit --skipLibCheck src/**/*.ts\",\n \"test\": \"vitest\",\n \"test:once\": \"vitest run\",\n \"test:coverage\": \"vitest run --coverage\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/geekmidas/toolbox\"\n },\n \"dependencies\": {\n \"@apidevtools/swagger-parser\": \"^10.1.0\",\n \"chokidar\": \"~4.0.3\",\n \"commander\": \"^12.1.0\",\n \"fast-glob\": \"^3.3.2\",\n \"lodash.kebabcase\": \"^4.1.1\",\n \"openapi-typescript\": \"^7.4.2\"\n },\n \"devDependencies\": {\n \"@geekmidas/testkit\": \"workspace:*\",\n \"@types/lodash.kebabcase\": \"^4.1.9\",\n \"@types/node\": \"~24.9.1\",\n \"typescript\": \"^5.8.2\",\n \"vitest\": \"^3.2.4\",\n \"zod\": \"~4.1.13\"\n },\n \"peerDependencies\": {\n \"@geekmidas/constructs\": \"workspace:~\",\n \"@geekmidas/envkit\": \"workspace:~\",\n \"@geekmidas/logger\": \"workspace:~\",\n \"@geekmidas/schema\": \"workspace:~\",\n \"@geekmidas/telescope\": \"workspace:~\"\n },\n \"peerDependenciesMeta\": {\n \"@geekmidas/telescope\": {\n \"optional\": true\n }\n }\n}\n","#!/usr/bin/env -S npx tsx\n\nimport { Command } from 'commander';\nimport pkg from '../package.json' assert { type: 'json' };\nimport { buildCommand } from './build/index.ts';\nimport { devCommand } from './dev/index.ts';\nimport { generateReactQueryCommand } from './openapi-react-query.ts';\nimport { openapiCommand } from './openapi.ts';\nimport type { LegacyProvider, MainProvider } from './types.ts';\n\nconst program = new Command();\n\nprogram\n .name('gkm')\n .description('GeekMidas backend framework CLI')\n .version(pkg.version)\n .option('--cwd <path>', 'Change working directory');\n\nprogram\n .command('build')\n .description('Build handlers from endpoints, functions, and crons')\n .option(\n '--provider <provider>',\n 'Target provider for generated handlers (aws, server)',\n )\n .option(\n '--providers <providers>',\n '[DEPRECATED] Use --provider instead. Target providers for generated handlers (comma-separated)',\n )\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation generation for server builds',\n )\n .action(\n async (options: {\n provider?: string;\n providers?: string;\n enableOpenapi?: boolean;\n }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n // Handle new single provider option\n if (options.provider) {\n if (!['aws', 'server'].includes(options.provider)) {\n console.error(\n `Invalid provider: ${options.provider}. Must be 'aws' or 'server'.`,\n );\n process.exit(1);\n }\n await buildCommand({\n provider: options.provider as MainProvider,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Handle legacy providers option\n else if (options.providers) {\n console.warn(\n '⚠️ --providers flag is deprecated. Use --provider instead.',\n );\n const providerList = [\n ...new Set(options.providers.split(',').map((p) => p.trim())),\n ] as LegacyProvider[];\n await buildCommand({\n providers: providerList,\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n // Default to config-driven build\n else {\n await buildCommand({\n enableOpenApi: options.enableOpenapi || false,\n });\n }\n } catch (error) {\n console.error('Build failed:', (error as Error).message);\n process.exit(1);\n }\n },\n );\n\nprogram\n .command('dev')\n .description('Start development server with automatic reload')\n .option('--port <port>', 'Port to run the development server on', '3000')\n .option(\n '--enable-openapi',\n 'Enable OpenAPI documentation for development server',\n true,\n )\n .action(async (options: { port?: string; enableOpenapi?: boolean }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n\n await devCommand({\n port: options.port ? Number.parseInt(options.port) : 3000,\n enableOpenApi: options.enableOpenapi ?? true,\n });\n } catch (error) {\n console.error('Dev server failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('cron')\n .description('Manage cron jobs')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Cron management - coming soon\\n');\n });\n\nprogram\n .command('function')\n .description('Manage serverless functions')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('Serverless function management - coming soon\\n');\n });\n\nprogram\n .command('api')\n .description('Manage REST API endpoints')\n .action(() => {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n process.stdout.write('REST API management - coming soon\\n');\n });\n\nprogram\n .command('openapi')\n .description(\n 'Generate OpenAPI specification from endpoints (TypeScript by default)',\n )\n .option(\n '--output <path>',\n 'Output file path for the OpenAPI spec',\n 'openapi.ts',\n )\n .option('--json', 'Generate JSON instead of TypeScript (legacy)', false)\n .action(async (options: { output?: string; json?: boolean }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await openapiCommand(options);\n } catch (error) {\n console.error('OpenAPI generation failed:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('generate:react-query')\n .description('Generate React Query hooks from OpenAPI specification')\n .option('--input <path>', 'Input OpenAPI spec file path', 'openapi.json')\n .option(\n '--output <path>',\n 'Output file path for generated hooks',\n 'src/api/hooks.ts',\n )\n .option('--name <name>', 'API name prefix for generated code', 'API')\n .action(\n async (options: { input?: string; output?: string; name?: string }) => {\n try {\n const globalOptions = program.opts();\n if (globalOptions.cwd) {\n process.chdir(globalOptions.cwd);\n }\n await generateReactQueryCommand(options);\n } catch (error) {\n console.error(\n 'React Query generation failed:',\n (error as Error).message,\n );\n process.exit(1);\n }\n },\n );\n\nprogram.parse();\n"],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { loadConfig } from "./config-AFmFKmU0.mjs";
|
|
2
|
+
import { EndpointGenerator } from "./EndpointGenerator-CzDhG7Or.mjs";
|
|
3
|
+
import { OpenApiTsGenerator } from "./OpenApiTsGenerator-q3aWNkuM.mjs";
|
|
4
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { Endpoint } from "@geekmidas/constructs/endpoints";
|
|
7
|
+
|
|
8
|
+
//#region src/openapi.ts
|
|
9
|
+
async function openapiCommand(options = {}) {
|
|
10
|
+
const logger = console;
|
|
11
|
+
try {
|
|
12
|
+
const config = await loadConfig(options.cwd);
|
|
13
|
+
const endpointGenerator = new EndpointGenerator();
|
|
14
|
+
const loadedEndpoints = await endpointGenerator.load(config.routes);
|
|
15
|
+
if (loadedEndpoints.length === 0) {
|
|
16
|
+
logger.log("No valid endpoints found");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const endpoints = loadedEndpoints.map(({ construct }) => construct);
|
|
20
|
+
const isJson = options.json === true;
|
|
21
|
+
const defaultOutput = isJson ? "openapi.json" : "openapi.ts";
|
|
22
|
+
const outputPath = options.output || join(process.cwd(), defaultOutput);
|
|
23
|
+
await mkdir(dirname(outputPath), { recursive: true });
|
|
24
|
+
if (isJson) {
|
|
25
|
+
const spec = await Endpoint.buildOpenApiSchema(endpoints, {
|
|
26
|
+
title: "API Documentation",
|
|
27
|
+
version: "1.0.0",
|
|
28
|
+
description: "Auto-generated API documentation from endpoints"
|
|
29
|
+
});
|
|
30
|
+
await writeFile(outputPath, JSON.stringify(spec, null, 2));
|
|
31
|
+
logger.log(`OpenAPI JSON spec generated: ${outputPath}`);
|
|
32
|
+
} else {
|
|
33
|
+
const tsGenerator = new OpenApiTsGenerator();
|
|
34
|
+
const tsContent = await tsGenerator.generate(endpoints, {
|
|
35
|
+
title: "API Documentation",
|
|
36
|
+
version: "1.0.0",
|
|
37
|
+
description: "Auto-generated API documentation from endpoints"
|
|
38
|
+
});
|
|
39
|
+
await writeFile(outputPath, tsContent);
|
|
40
|
+
logger.log(`OpenAPI TypeScript module generated: ${outputPath}`);
|
|
41
|
+
}
|
|
42
|
+
logger.log(`Found ${endpoints.length} endpoints`);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
throw new Error(`OpenAPI generation failed: ${error.message}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
//#endregion
|
|
49
|
+
export { openapiCommand };
|
|
50
|
+
//# sourceMappingURL=openapi-DRTRGhTt.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi-DRTRGhTt.mjs","names":["options: OpenAPIOptions"],"sources":["../src/openapi.ts"],"sourcesContent":["#!/usr/bin/env -S npx tsx\n\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { Endpoint } from '@geekmidas/constructs/endpoints';\nimport { loadConfig } from './config.js';\nimport { EndpointGenerator } from './generators/EndpointGenerator.js';\nimport { OpenApiTsGenerator } from './generators/OpenApiTsGenerator.js';\n\ninterface OpenAPIOptions {\n output?: string;\n json?: boolean;\n cwd?: string;\n}\n\nexport async function openapiCommand(\n options: OpenAPIOptions = {},\n): Promise<void> {\n const logger = console;\n\n try {\n // Load config using existing function\n const config = await loadConfig(options.cwd);\n const endpointGenerator = new EndpointGenerator();\n\n // Load all endpoints using the refactored function\n const loadedEndpoints = await endpointGenerator.load(config.routes);\n\n if (loadedEndpoints.length === 0) {\n logger.log('No valid endpoints found');\n return;\n }\n\n // Extract just the endpoint instances for OpenAPI generation\n const endpoints = loadedEndpoints.map(({ construct }) => construct);\n\n // Determine output format (TypeScript is default)\n const isJson = options.json === true;\n const defaultOutput = isJson ? 'openapi.json' : 'openapi.ts';\n const outputPath = options.output || join(process.cwd(), defaultOutput);\n\n // Ensure output directory exists\n await mkdir(dirname(outputPath), { recursive: true });\n\n if (isJson) {\n // Generate JSON OpenAPI spec (legacy)\n const spec = await Endpoint.buildOpenApiSchema(endpoints, {\n title: 'API Documentation',\n version: '1.0.0',\n description: 'Auto-generated API documentation from endpoints',\n });\n\n await writeFile(outputPath, JSON.stringify(spec, null, 2));\n logger.log(`OpenAPI JSON spec generated: ${outputPath}`);\n } else {\n // Generate TypeScript OpenAPI module (default)\n const tsGenerator = new OpenApiTsGenerator();\n const tsContent = await tsGenerator.generate(endpoints, {\n title: 'API Documentation',\n version: '1.0.0',\n description: 'Auto-generated API documentation from endpoints',\n });\n\n await writeFile(outputPath, tsContent);\n logger.log(`OpenAPI TypeScript module generated: ${outputPath}`);\n }\n\n logger.log(`Found ${endpoints.length} endpoints`);\n } catch (error) {\n throw new Error(`OpenAPI generation failed: ${(error as Error).message}`);\n }\n}\n"],"mappings":";;;;;;;;AAeA,eAAsB,eACpBA,UAA0B,CAAE,GACb;CACf,MAAM,SAAS;AAEf,KAAI;EAEF,MAAM,SAAS,MAAM,WAAW,QAAQ,IAAI;EAC5C,MAAM,oBAAoB,IAAI;EAG9B,MAAM,kBAAkB,MAAM,kBAAkB,KAAK,OAAO,OAAO;AAEnE,MAAI,gBAAgB,WAAW,GAAG;AAChC,UAAO,IAAI,2BAA2B;AACtC;EACD;EAGD,MAAM,YAAY,gBAAgB,IAAI,CAAC,EAAE,WAAW,KAAK,UAAU;EAGnE,MAAM,SAAS,QAAQ,SAAS;EAChC,MAAM,gBAAgB,SAAS,iBAAiB;EAChD,MAAM,aAAa,QAAQ,UAAU,KAAK,QAAQ,KAAK,EAAE,cAAc;AAGvE,QAAM,MAAM,QAAQ,WAAW,EAAE,EAAE,WAAW,KAAM,EAAC;AAErD,MAAI,QAAQ;GAEV,MAAM,OAAO,MAAM,SAAS,mBAAmB,WAAW;IACxD,OAAO;IACP,SAAS;IACT,aAAa;GACd,EAAC;AAEF,SAAM,UAAU,YAAY,KAAK,UAAU,MAAM,MAAM,EAAE,CAAC;AAC1D,UAAO,KAAK,+BAA+B,WAAW,EAAE;EACzD,OAAM;GAEL,MAAM,cAAc,IAAI;GACxB,MAAM,YAAY,MAAM,YAAY,SAAS,WAAW;IACtD,OAAO;IACP,SAAS;IACT,aAAa;GACd,EAAC;AAEF,SAAM,UAAU,YAAY,UAAU;AACtC,UAAO,KAAK,uCAAuC,WAAW,EAAE;EACjE;AAED,SAAO,KAAK,QAAQ,UAAU,OAAO,YAAY;CAClD,SAAQ,OAAO;AACd,QAAM,IAAI,OAAO,6BAA8B,MAAgB,QAAQ;CACxE;AACF"}
|