@geekmidas/cli 0.7.0 → 0.9.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/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/index.cjs +64 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +64 -34
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-Mwy2_R4W.mjs → openapi--vOy9mo4.mjs} +23 -2
- package/dist/openapi--vOy9mo4.mjs.map +1 -0
- package/dist/{openapi-tAIbJJU_.cjs → openapi-CHhTPief.cjs} +23 -2
- package/dist/openapi-CHhTPief.cjs.map +1 -0
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +1 -1
- package/dist/{types-B3TXoj7v.d.mts → types-DXgiA1sF.d.mts} +38 -1
- package/dist/{types-C0hwnSjm.d.cts → types-b-vwGpqc.d.cts} +38 -1
- package/package.json +7 -7
- package/src/__tests__/EndpointGenerator.hooks.spec.ts +204 -0
- package/src/__tests__/normalizeHooksConfig.spec.ts +63 -0
- package/src/build/index.ts +8 -1
- package/src/build/types.ts +6 -0
- package/src/dev/index.ts +104 -35
- package/src/generators/EndpointGenerator.ts +27 -1
- package/src/index.ts +5 -12
- package/src/types.ts +38 -0
- package/dist/openapi-Mwy2_R4W.mjs.map +0 -1
- package/dist/openapi-tAIbJJU_.cjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
2
|
import { loadConfig, parseModuleConfig } from "./config-Bq72aj8e.mjs";
|
|
3
|
-
import { ConstructGenerator, EndpointGenerator, generateOpenApi, openapiCommand, resolveOpenApiConfig } from "./openapi
|
|
3
|
+
import { ConstructGenerator, EndpointGenerator, OPENAPI_OUTPUT_PATH, generateOpenApi, openapiCommand, resolveOpenApiConfig } from "./openapi--vOy9mo4.mjs";
|
|
4
4
|
import { generateReactQueryCommand } from "./openapi-react-query-CcciaVu5.mjs";
|
|
5
5
|
import { join, relative } from "path";
|
|
6
6
|
import { Command } from "commander";
|
|
@@ -19,7 +19,7 @@ import prompts from "prompts";
|
|
|
19
19
|
|
|
20
20
|
//#region package.json
|
|
21
21
|
var name = "@geekmidas/cli";
|
|
22
|
-
var version = "0.
|
|
22
|
+
var version = "0.9.0";
|
|
23
23
|
var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
|
|
24
24
|
var private$1 = false;
|
|
25
25
|
var type = "module";
|
|
@@ -571,6 +571,16 @@ function normalizeStudioConfig(config$1) {
|
|
|
571
571
|
schema: studioConfig.schema ?? "public"
|
|
572
572
|
};
|
|
573
573
|
}
|
|
574
|
+
/**
|
|
575
|
+
* Normalize hooks configuration
|
|
576
|
+
* @internal Exported for testing
|
|
577
|
+
*/
|
|
578
|
+
function normalizeHooksConfig(config$1) {
|
|
579
|
+
if (!config$1?.server) return void 0;
|
|
580
|
+
const serverPath = config$1.server.endsWith(".ts") ? config$1.server : `${config$1.server}.ts`;
|
|
581
|
+
const resolvedPath = resolve(process.cwd(), serverPath);
|
|
582
|
+
return { serverHooksPath: resolvedPath };
|
|
583
|
+
}
|
|
574
584
|
async function devCommand(options) {
|
|
575
585
|
const defaultEnv = loadEnvFiles(".env");
|
|
576
586
|
if (defaultEnv.loaded.length > 0) logger$2.log(`📦 Loaded env: ${defaultEnv.loaded.join(", ")}`);
|
|
@@ -593,31 +603,36 @@ async function devCommand(options) {
|
|
|
593
603
|
if (telescope) logger$2.log(`🔭 Telescope enabled at ${telescope.path}`);
|
|
594
604
|
const studio = normalizeStudioConfig(config$1.studio);
|
|
595
605
|
if (studio) logger$2.log(`🗄️ Studio enabled at ${studio.path}`);
|
|
606
|
+
const hooks = normalizeHooksConfig(config$1.hooks);
|
|
607
|
+
if (hooks) logger$2.log(`🪝 Server hooks enabled from ${config$1.hooks?.server}`);
|
|
596
608
|
const openApiConfig = resolveOpenApiConfig(config$1);
|
|
597
609
|
const enableOpenApi = openApiConfig.enabled || resolved.enableOpenApi;
|
|
598
|
-
if (enableOpenApi) logger$2.log(`📄 OpenAPI output: ${
|
|
610
|
+
if (enableOpenApi) logger$2.log(`📄 OpenAPI output: ${OPENAPI_OUTPUT_PATH}`);
|
|
599
611
|
const buildContext = {
|
|
600
612
|
envParserPath,
|
|
601
613
|
envParserImportPattern,
|
|
602
614
|
loggerPath,
|
|
603
615
|
loggerImportPattern,
|
|
604
616
|
telescope,
|
|
605
|
-
studio
|
|
617
|
+
studio,
|
|
618
|
+
hooks
|
|
606
619
|
};
|
|
607
620
|
await buildServer(config$1, buildContext, resolved.providers[0], enableOpenApi);
|
|
608
621
|
if (enableOpenApi) await generateOpenApi(config$1);
|
|
609
622
|
const runtime = config$1.runtime ?? "node";
|
|
610
|
-
const devServer = new DevServer(resolved.providers[0], options.port || 3e3, enableOpenApi, telescope, studio, runtime);
|
|
623
|
+
const devServer = new DevServer(resolved.providers[0], options.port || 3e3, options.portExplicit ?? false, enableOpenApi, telescope, studio, runtime);
|
|
611
624
|
await devServer.start();
|
|
612
625
|
const envParserFile = config$1.envParser.split("#")[0];
|
|
613
626
|
const loggerFile = config$1.logger.split("#")[0];
|
|
627
|
+
const hooksFile = config$1.hooks?.server?.split("#")[0];
|
|
614
628
|
const watchPatterns = [
|
|
615
629
|
config$1.routes,
|
|
616
630
|
...config$1.functions ? [config$1.functions] : [],
|
|
617
631
|
...config$1.crons ? [config$1.crons] : [],
|
|
618
632
|
...config$1.subscribers ? [config$1.subscribers] : [],
|
|
619
633
|
envParserFile.endsWith(".ts") ? envParserFile : `${envParserFile}.ts`,
|
|
620
|
-
loggerFile.endsWith(".ts") ? loggerFile : `${loggerFile}.ts
|
|
634
|
+
loggerFile.endsWith(".ts") ? loggerFile : `${loggerFile}.ts`,
|
|
635
|
+
...hooksFile ? [hooksFile.endsWith(".ts") ? hooksFile : `${hooksFile}.ts`] : []
|
|
621
636
|
].flat();
|
|
622
637
|
const normalizedPatterns = watchPatterns.map((p) => p.startsWith("./") ? p.slice(2) : p);
|
|
623
638
|
logger$2.log(`👀 Watching for changes in: ${normalizedPatterns.join(", ")}`);
|
|
@@ -656,11 +671,16 @@ async function devCommand(options) {
|
|
|
656
671
|
}
|
|
657
672
|
}, 300);
|
|
658
673
|
});
|
|
659
|
-
|
|
674
|
+
let isShuttingDown = false;
|
|
675
|
+
const shutdown = () => {
|
|
676
|
+
if (isShuttingDown) return;
|
|
677
|
+
isShuttingDown = true;
|
|
660
678
|
logger$2.log("\n🛑 Shutting down...");
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
679
|
+
Promise.all([watcher.close(), devServer.stop()]).catch((err) => {
|
|
680
|
+
logger$2.error("Error during shutdown:", err);
|
|
681
|
+
}).finally(() => {
|
|
682
|
+
process.exit(0);
|
|
683
|
+
});
|
|
664
684
|
};
|
|
665
685
|
process.on("SIGINT", shutdown);
|
|
666
686
|
process.on("SIGTERM", shutdown);
|
|
@@ -692,9 +712,10 @@ var DevServer = class {
|
|
|
692
712
|
serverProcess = null;
|
|
693
713
|
isRunning = false;
|
|
694
714
|
actualPort;
|
|
695
|
-
constructor(provider, requestedPort, enableOpenApi, telescope, studio, runtime = "node") {
|
|
715
|
+
constructor(provider, requestedPort, portExplicit, enableOpenApi, telescope, studio, runtime = "node") {
|
|
696
716
|
this.provider = provider;
|
|
697
717
|
this.requestedPort = requestedPort;
|
|
718
|
+
this.portExplicit = portExplicit;
|
|
698
719
|
this.enableOpenApi = enableOpenApi;
|
|
699
720
|
this.telescope = telescope;
|
|
700
721
|
this.studio = studio;
|
|
@@ -703,8 +724,14 @@ var DevServer = class {
|
|
|
703
724
|
}
|
|
704
725
|
async start() {
|
|
705
726
|
if (this.isRunning) await this.stop();
|
|
706
|
-
|
|
707
|
-
|
|
727
|
+
if (this.portExplicit) {
|
|
728
|
+
const available = await isPortAvailable(this.requestedPort);
|
|
729
|
+
if (!available) throw new Error(`Port ${this.requestedPort} is already in use. Either stop the process using that port or omit -p/--port to auto-select an available port.`);
|
|
730
|
+
this.actualPort = this.requestedPort;
|
|
731
|
+
} else {
|
|
732
|
+
this.actualPort = await findAvailablePort(this.requestedPort);
|
|
733
|
+
if (this.actualPort !== this.requestedPort) logger$2.log(`ℹ️ Port ${this.requestedPort} was in use, using port ${this.actualPort} instead`);
|
|
734
|
+
}
|
|
708
735
|
const serverEntryPath = join$1(process.cwd(), ".gkm", this.provider, "server.ts");
|
|
709
736
|
await this.createServerEntry();
|
|
710
737
|
logger$2.log(`\n✨ Starting server on port ${this.actualPort}...`);
|
|
@@ -738,26 +765,25 @@ var DevServer = class {
|
|
|
738
765
|
}
|
|
739
766
|
}
|
|
740
767
|
async stop() {
|
|
768
|
+
const port = this.actualPort;
|
|
741
769
|
if (this.serverProcess && this.isRunning) {
|
|
742
770
|
const pid = this.serverProcess.pid;
|
|
743
771
|
if (pid) try {
|
|
744
|
-
process.kill(-pid, "
|
|
745
|
-
} catch {
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
} catch {}
|
|
751
|
-
resolve$1();
|
|
752
|
-
}, 3e3);
|
|
753
|
-
this.serverProcess?.on("exit", () => {
|
|
754
|
-
clearTimeout(timeout);
|
|
755
|
-
resolve$1();
|
|
756
|
-
});
|
|
757
|
-
});
|
|
772
|
+
process.kill(-pid, "SIGKILL");
|
|
773
|
+
} catch {
|
|
774
|
+
try {
|
|
775
|
+
process.kill(pid, "SIGKILL");
|
|
776
|
+
} catch {}
|
|
777
|
+
}
|
|
758
778
|
this.serverProcess = null;
|
|
759
779
|
this.isRunning = false;
|
|
760
780
|
}
|
|
781
|
+
this.killProcessesOnPort(port);
|
|
782
|
+
}
|
|
783
|
+
killProcessesOnPort(port) {
|
|
784
|
+
try {
|
|
785
|
+
execSync(`lsof -ti tcp:${port} | xargs kill -9 2>/dev/null || true`, { stdio: "ignore" });
|
|
786
|
+
} catch {}
|
|
761
787
|
}
|
|
762
788
|
async restart() {
|
|
763
789
|
const portToReuse = this.actualPort;
|
|
@@ -898,12 +924,15 @@ async function buildCommand(options) {
|
|
|
898
924
|
const { path: loggerPath, importPattern: loggerImportPattern } = parseModuleConfig(config$1.logger, "logger");
|
|
899
925
|
const telescope = normalizeTelescopeConfig(config$1.telescope);
|
|
900
926
|
if (telescope) logger.log(`🔭 Telescope enabled at ${telescope.path}`);
|
|
927
|
+
const hooks = normalizeHooksConfig(config$1.hooks);
|
|
928
|
+
if (hooks) logger.log(`🪝 Server hooks enabled`);
|
|
901
929
|
const buildContext = {
|
|
902
930
|
envParserPath,
|
|
903
931
|
envParserImportPattern,
|
|
904
932
|
loggerPath,
|
|
905
933
|
loggerImportPattern,
|
|
906
|
-
telescope
|
|
934
|
+
telescope,
|
|
935
|
+
hooks
|
|
907
936
|
};
|
|
908
937
|
const endpointGenerator = new EndpointGenerator();
|
|
909
938
|
const functionGenerator = new FunctionGenerator();
|
|
@@ -2282,7 +2311,7 @@ export const telescope = new Telescope({
|
|
|
2282
2311
|
/**
|
|
2283
2312
|
* OpenAPI output path (fixed, not configurable)
|
|
2284
2313
|
*/
|
|
2285
|
-
const OPENAPI_OUTPUT_PATH = "./.gkm/openapi.ts";
|
|
2314
|
+
const OPENAPI_OUTPUT_PATH$1 = "./.gkm/openapi.ts";
|
|
2286
2315
|
/**
|
|
2287
2316
|
* All available templates
|
|
2288
2317
|
*/
|
|
@@ -2399,8 +2428,8 @@ function generatePackageJson(options, template) {
|
|
|
2399
2428
|
private: true,
|
|
2400
2429
|
type: "module",
|
|
2401
2430
|
exports: { "./client": {
|
|
2402
|
-
types: OPENAPI_OUTPUT_PATH,
|
|
2403
|
-
import: OPENAPI_OUTPUT_PATH
|
|
2431
|
+
types: OPENAPI_OUTPUT_PATH$1,
|
|
2432
|
+
import: OPENAPI_OUTPUT_PATH$1
|
|
2404
2433
|
} },
|
|
2405
2434
|
scripts: scripts$1,
|
|
2406
2435
|
dependencies: sortObject(dependencies$1),
|
|
@@ -2678,12 +2707,13 @@ program.command("build").description("Build handlers from endpoints, functions,
|
|
|
2678
2707
|
process.exit(1);
|
|
2679
2708
|
}
|
|
2680
2709
|
});
|
|
2681
|
-
program.command("dev").description("Start development server with automatic reload").option("--port <port>", "Port to run the development server on"
|
|
2710
|
+
program.command("dev").description("Start development server with automatic reload").option("-p, --port <port>", "Port to run the development server on").option("--enable-openapi", "Enable OpenAPI documentation for development server", true).action(async (options) => {
|
|
2682
2711
|
try {
|
|
2683
2712
|
const globalOptions = program.opts();
|
|
2684
2713
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
2685
2714
|
await devCommand({
|
|
2686
2715
|
port: options.port ? Number.parseInt(options.port) : 3e3,
|
|
2716
|
+
portExplicit: !!options.port,
|
|
2687
2717
|
enableOpenApi: options.enableOpenapi ?? true
|
|
2688
2718
|
});
|
|
2689
2719
|
} catch (error) {
|
|
@@ -2706,11 +2736,11 @@ program.command("api").description("Manage REST API endpoints").action(() => {
|
|
|
2706
2736
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
2707
2737
|
process.stdout.write("REST API management - coming soon\n");
|
|
2708
2738
|
});
|
|
2709
|
-
program.command("openapi").description("Generate OpenAPI specification from endpoints
|
|
2739
|
+
program.command("openapi").description("Generate OpenAPI specification from endpoints").action(async () => {
|
|
2710
2740
|
try {
|
|
2711
2741
|
const globalOptions = program.opts();
|
|
2712
2742
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
2713
|
-
await openapiCommand(
|
|
2743
|
+
await openapiCommand({});
|
|
2714
2744
|
} catch (error) {
|
|
2715
2745
|
console.error("OpenAPI generation failed:", error.message);
|
|
2716
2746
|
process.exit(1);
|