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