@geekmidas/cli 0.2.4 → 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.
Files changed (82) hide show
  1. package/README.md +488 -71
  2. package/dist/{EndpointGenerator-C73wNoih.cjs → EndpointGenerator-BxNCkus4.cjs} +60 -6
  3. package/dist/EndpointGenerator-BxNCkus4.cjs.map +1 -0
  4. package/dist/{EndpointGenerator-CWh18d92.mjs → EndpointGenerator-CzDhG7Or.mjs} +60 -6
  5. package/dist/EndpointGenerator-CzDhG7Or.mjs.map +1 -0
  6. package/dist/OpenApiTsGenerator-NBNEoaeO.cjs +501 -0
  7. package/dist/OpenApiTsGenerator-NBNEoaeO.cjs.map +1 -0
  8. package/dist/OpenApiTsGenerator-q3aWNkuM.mjs +495 -0
  9. package/dist/OpenApiTsGenerator-q3aWNkuM.mjs.map +1 -0
  10. package/dist/build/index.cjs +4 -4
  11. package/dist/build/index.mjs +4 -4
  12. package/dist/build/manifests.cjs +3 -2
  13. package/dist/build/manifests.mjs +2 -2
  14. package/dist/{build-BVng9MQX.cjs → build-CWtHnJMQ.cjs} +19 -17
  15. package/dist/build-CWtHnJMQ.cjs.map +1 -0
  16. package/dist/{build-BqexeI-W.mjs → build-DyDgu_D1.mjs} +20 -18
  17. package/dist/build-DyDgu_D1.mjs.map +1 -0
  18. package/dist/{config-U-mdW-7Y.mjs → config-AFmFKmU0.mjs} +3 -3
  19. package/dist/config-AFmFKmU0.mjs.map +1 -0
  20. package/dist/{config-D1EpSGk6.cjs → config-BVIJpAsa.cjs} +3 -3
  21. package/dist/config-BVIJpAsa.cjs.map +1 -0
  22. package/dist/config.cjs +1 -1
  23. package/dist/config.mjs +1 -1
  24. package/dist/dev/index.cjs +5 -4
  25. package/dist/dev/index.mjs +4 -4
  26. package/dist/{dev-DbtyToc7.cjs → dev-CgDYC4o8.cjs} +95 -31
  27. package/dist/dev-CgDYC4o8.cjs.map +1 -0
  28. package/dist/{dev-DnGYXuMn.mjs → dev-CpA8AQPX.mjs} +90 -32
  29. package/dist/dev-CpA8AQPX.mjs.map +1 -0
  30. package/dist/generators/EndpointGenerator.cjs +1 -1
  31. package/dist/generators/EndpointGenerator.mjs +1 -1
  32. package/dist/generators/OpenApiTsGenerator.cjs +3 -0
  33. package/dist/generators/OpenApiTsGenerator.mjs +3 -0
  34. package/dist/generators/index.cjs +1 -1
  35. package/dist/generators/index.mjs +1 -1
  36. package/dist/index.cjs +16 -10
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.mjs +16 -10
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/manifests-C2eMoMUm.mjs +68 -0
  41. package/dist/manifests-C2eMoMUm.mjs.map +1 -0
  42. package/dist/manifests-CK1VV_pM.cjs +80 -0
  43. package/dist/manifests-CK1VV_pM.cjs.map +1 -0
  44. package/dist/openapi-DRTRGhTt.mjs +50 -0
  45. package/dist/openapi-DRTRGhTt.mjs.map +1 -0
  46. package/dist/openapi-DhK4b0lB.cjs +56 -0
  47. package/dist/openapi-DhK4b0lB.cjs.map +1 -0
  48. package/dist/openapi.cjs +4 -3
  49. package/dist/openapi.mjs +4 -3
  50. package/docs/OPENAPI_TYPESCRIPT_DESIGN.md +408 -0
  51. package/docs/manifest-refactor-design.md +287 -0
  52. package/package.json +10 -3
  53. package/src/__tests__/openapi.spec.ts +78 -63
  54. package/src/build/__tests__/index-new.spec.ts +43 -72
  55. package/src/build/__tests__/manifests.spec.ts +346 -0
  56. package/src/build/index.ts +59 -62
  57. package/src/build/manifests.ts +85 -13
  58. package/src/build/types.ts +13 -2
  59. package/src/config.ts +4 -2
  60. package/src/dev/__tests__/index.spec.ts +98 -1
  61. package/src/dev/index.ts +152 -25
  62. package/src/generators/EndpointGenerator.ts +69 -5
  63. package/src/generators/OpenApiTsGenerator.ts +798 -0
  64. package/src/index.ts +6 -3
  65. package/src/openapi.ts +36 -15
  66. package/src/types.ts +23 -7
  67. package/dist/EndpointGenerator-C73wNoih.cjs.map +0 -1
  68. package/dist/EndpointGenerator-CWh18d92.mjs.map +0 -1
  69. package/dist/build-BVng9MQX.cjs.map +0 -1
  70. package/dist/build-BqexeI-W.mjs.map +0 -1
  71. package/dist/config-D1EpSGk6.cjs.map +0 -1
  72. package/dist/config-U-mdW-7Y.mjs.map +0 -1
  73. package/dist/dev-DbtyToc7.cjs.map +0 -1
  74. package/dist/dev-DnGYXuMn.mjs.map +0 -1
  75. package/dist/manifests-BrJXpHrf.mjs +0 -21
  76. package/dist/manifests-BrJXpHrf.mjs.map +0 -1
  77. package/dist/manifests-D0saShvH.cjs +0 -27
  78. package/dist/manifests-D0saShvH.cjs.map +0 -1
  79. package/dist/openapi-BTHbPrxS.mjs +0 -36
  80. package/dist/openapi-BTHbPrxS.mjs.map +0 -1
  81. package/dist/openapi-CewcfoRH.cjs +0 -42
  82. package/dist/openapi-CewcfoRH.cjs.map +0 -1
@@ -1,10 +1,10 @@
1
1
  const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const require_config = require('./config-D1EpSGk6.cjs');
2
+ const require_config = require('./config-BVIJpAsa.cjs');
3
3
  const require_CronGenerator = require('./CronGenerator-C6MF8rlG.cjs');
4
- const require_EndpointGenerator = require('./EndpointGenerator-C73wNoih.cjs');
4
+ const require_EndpointGenerator = require('./EndpointGenerator-BxNCkus4.cjs');
5
5
  const require_FunctionGenerator = require('./FunctionGenerator-FgZUTd8L.cjs');
6
6
  const require_SubscriberGenerator = require('./SubscriberGenerator-Bd-a7aiw.cjs');
7
- const require_manifests = require('./manifests-D0saShvH.cjs');
7
+ const require_manifests = require('./manifests-CK1VV_pM.cjs');
8
8
  const require_providerResolver = require('./providerResolver-DgvzNfP4.cjs');
9
9
  const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
10
10
  const node_path = require_chunk.__toESM(require("node:path"));
@@ -50,14 +50,9 @@ async function buildCommand(options) {
50
50
  }
51
51
  const rootOutputDir = (0, node_path.join)(process.cwd(), ".gkm");
52
52
  await (0, node_fs_promises.mkdir)(rootOutputDir, { recursive: true });
53
- const allBuildResults = await Promise.all(resolved.providers.map((provider) => buildForProvider(provider, buildContext, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, allEndpoints, allFunctions, allCrons, allSubscribers, resolved.enableOpenApi)));
54
- const aggregatedRoutes = allBuildResults.flatMap((result) => result.routes);
55
- const aggregatedFunctions = allBuildResults.flatMap((result) => result.functions);
56
- const aggregatedCrons = allBuildResults.flatMap((result) => result.crons);
57
- const aggregatedSubscribers = allBuildResults.flatMap((result) => result.subscribers);
58
- await require_manifests.generateManifests(rootOutputDir, aggregatedRoutes, aggregatedFunctions, aggregatedCrons, aggregatedSubscribers);
53
+ for (const provider of resolved.providers) await buildForProvider(provider, buildContext, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, allEndpoints, allFunctions, allCrons, allSubscribers, resolved.enableOpenApi);
59
54
  }
60
- async function buildForProvider(provider, context, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, endpoints, functions, crons, subscribers, enableOpenApi) {
55
+ async function buildForProvider(provider, context, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, endpoints, functions, crons, subscribers, enableOpenApi) {
61
56
  const outputDir = (0, node_path.join)(process.cwd(), ".gkm", provider);
62
57
  await (0, node_fs_promises.mkdir)(outputDir, { recursive: true });
63
58
  logger.log(`\nGenerating handlers for provider: ${provider}`);
@@ -71,12 +66,19 @@ async function buildForProvider(provider, context, endpointGenerator, functionGe
71
66
  subscriberGenerator.build(context, subscribers, outputDir, { provider })
72
67
  ]);
73
68
  logger.log(`Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`);
74
- return {
75
- routes,
76
- functions: functionInfos,
77
- crons: cronInfos,
78
- subscribers: subscriberInfos
79
- };
69
+ if (provider === "server") {
70
+ const routeMetadata = await Promise.all(endpoints.map(async ({ construct }) => ({
71
+ path: construct._path,
72
+ method: construct.method,
73
+ handler: "",
74
+ authorizer: construct.authorizer?.name ?? "none"
75
+ })));
76
+ const appInfo = {
77
+ handler: (0, node_path.relative)(process.cwd(), (0, node_path.join)(outputDir, "app.ts")),
78
+ endpoints: (0, node_path.relative)(process.cwd(), (0, node_path.join)(outputDir, "endpoints.ts"))
79
+ };
80
+ await require_manifests.generateServerManifest(rootOutputDir, appInfo, routeMetadata, subscriberInfos);
81
+ } else await require_manifests.generateAwsManifest(rootOutputDir, routes, functionInfos, cronInfos, subscriberInfos);
80
82
  }
81
83
 
82
84
  //#endregion
@@ -86,4 +88,4 @@ Object.defineProperty(exports, 'buildCommand', {
86
88
  return buildCommand;
87
89
  }
88
90
  });
89
- //# sourceMappingURL=build-BVng9MQX.cjs.map
91
+ //# sourceMappingURL=build-CWtHnJMQ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-CWtHnJMQ.cjs","names":["options: BuildOptions","buildContext: BuildContext","EndpointGenerator","FunctionGenerator","CronGenerator","SubscriberGenerator","provider: LegacyProvider","context: BuildContext","rootOutputDir: string","endpointGenerator: EndpointGenerator","functionGenerator: FunctionGenerator","cronGenerator: CronGenerator","subscriberGenerator: SubscriberGenerator","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","functions: GeneratedConstruct<Function<any, any, any, any>>[]","crons: GeneratedConstruct<Cron<any, any, any, any>>[]","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","enableOpenApi: boolean","routeMetadata: RouteInfo[]","appInfo: ServerAppInfo"],"sources":["../src/build/index.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { Cron } from '@geekmidas/constructs/crons';\nimport type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { Function } from '@geekmidas/constructs/functions';\nimport type { Subscriber } from '@geekmidas/constructs/subscribers';\nimport { loadConfig } from '../config';\nimport {\n CronGenerator,\n EndpointGenerator,\n FunctionGenerator,\n type GeneratedConstruct,\n SubscriberGenerator,\n} from '../generators';\nimport type { BuildOptions, LegacyProvider, RouteInfo } from '../types';\nimport {\n type ServerAppInfo,\n generateAwsManifest,\n generateServerManifest,\n} from './manifests';\nimport { resolveProviders } from './providerResolver';\nimport type { BuildContext } from './types';\n\nconst logger = console;\n\nexport async function buildCommand(options: BuildOptions): Promise<void> {\n const config = await loadConfig();\n\n // Resolve providers from new config format\n const resolved = resolveProviders(config, options);\n\n logger.log(`Building with providers: ${resolved.providers.join(', ')}`);\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 const buildContext: BuildContext = {\n envParserPath,\n envParserImportPattern,\n loggerPath,\n loggerImportPattern,\n };\n\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 in parallel\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 logger.log(`Found ${allEndpoints.length} endpoints`);\n logger.log(`Found ${allFunctions.length} functions`);\n logger.log(`Found ${allCrons.length} crons`);\n logger.log(`Found ${allSubscribers.length} subscribers`);\n\n if (\n allEndpoints.length === 0 &&\n allFunctions.length === 0 &&\n allCrons.length === 0 &&\n allSubscribers.length === 0\n ) {\n logger.log(\n 'No endpoints, functions, crons, or subscribers found to process',\n );\n return;\n }\n\n // Ensure .gkm directory exists\n const rootOutputDir = join(process.cwd(), '.gkm');\n await mkdir(rootOutputDir, { recursive: true });\n\n // Build for each provider and generate per-provider manifests\n for (const provider of resolved.providers) {\n await buildForProvider(\n provider,\n buildContext,\n rootOutputDir,\n endpointGenerator,\n functionGenerator,\n cronGenerator,\n subscriberGenerator,\n allEndpoints,\n allFunctions,\n allCrons,\n allSubscribers,\n resolved.enableOpenApi,\n );\n }\n}\n\nasync function buildForProvider(\n provider: LegacyProvider,\n context: BuildContext,\n rootOutputDir: string,\n endpointGenerator: EndpointGenerator,\n functionGenerator: FunctionGenerator,\n cronGenerator: CronGenerator,\n subscriberGenerator: SubscriberGenerator,\n endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n functions: GeneratedConstruct<Function<any, any, any, any>>[],\n crons: GeneratedConstruct<Cron<any, any, any, any>>[],\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n enableOpenApi: boolean,\n): Promise<void> {\n const outputDir = join(process.cwd(), '.gkm', provider);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n logger.log(`\\nGenerating handlers for provider: ${provider}`);\n\n // Build all constructs in parallel\n const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all(\n [\n endpointGenerator.build(context, endpoints, outputDir, {\n provider,\n enableOpenApi,\n }),\n functionGenerator.build(context, functions, outputDir, { provider }),\n cronGenerator.build(context, crons, outputDir, { provider }),\n subscriberGenerator.build(context, subscribers, outputDir, { provider }),\n ],\n );\n\n logger.log(\n `Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,\n );\n\n // Generate provider-specific manifest\n if (provider === 'server') {\n // For server, collect actual route metadata from endpoint constructs\n const routeMetadata: RouteInfo[] = await Promise.all(\n endpoints.map(async ({ construct }) => ({\n path: construct._path,\n method: construct.method,\n handler: '', // Not needed for server manifest\n authorizer: construct.authorizer?.name ?? 'none',\n })),\n );\n\n const appInfo: ServerAppInfo = {\n handler: relative(process.cwd(), join(outputDir, 'app.ts')),\n endpoints: relative(process.cwd(), join(outputDir, 'endpoints.ts')),\n };\n\n await generateServerManifest(\n rootOutputDir,\n appInfo,\n routeMetadata,\n subscriberInfos,\n );\n } else {\n // For AWS providers, generate AWS manifest\n await generateAwsManifest(\n rootOutputDir,\n routes,\n functionInfos,\n cronInfos,\n subscriberInfos,\n );\n }\n}\n"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
- import { loadConfig } from "./config-U-mdW-7Y.mjs";
1
+ import { loadConfig } from "./config-AFmFKmU0.mjs";
2
2
  import { CronGenerator } from "./CronGenerator-Bh26MaNA.mjs";
3
- import { EndpointGenerator } from "./EndpointGenerator-CWh18d92.mjs";
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
- import { generateManifests } from "./manifests-BrJXpHrf.mjs";
6
+ import { generateAwsManifest, generateServerManifest } from "./manifests-C2eMoMUm.mjs";
7
7
  import { resolveProviders } from "./providerResolver-B_TjNF0_.mjs";
8
8
  import { mkdir } from "node:fs/promises";
9
- import { join } from "node:path";
9
+ import { join, relative } from "node:path";
10
10
 
11
11
  //#region src/build/index.ts
12
12
  const logger = console;
@@ -49,14 +49,9 @@ async function buildCommand(options) {
49
49
  }
50
50
  const rootOutputDir = join(process.cwd(), ".gkm");
51
51
  await mkdir(rootOutputDir, { recursive: true });
52
- const allBuildResults = await Promise.all(resolved.providers.map((provider) => buildForProvider(provider, buildContext, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, allEndpoints, allFunctions, allCrons, allSubscribers, resolved.enableOpenApi)));
53
- const aggregatedRoutes = allBuildResults.flatMap((result) => result.routes);
54
- const aggregatedFunctions = allBuildResults.flatMap((result) => result.functions);
55
- const aggregatedCrons = allBuildResults.flatMap((result) => result.crons);
56
- const aggregatedSubscribers = allBuildResults.flatMap((result) => result.subscribers);
57
- await generateManifests(rootOutputDir, aggregatedRoutes, aggregatedFunctions, aggregatedCrons, aggregatedSubscribers);
52
+ for (const provider of resolved.providers) await buildForProvider(provider, buildContext, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, allEndpoints, allFunctions, allCrons, allSubscribers, resolved.enableOpenApi);
58
53
  }
59
- async function buildForProvider(provider, context, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, endpoints, functions, crons, subscribers, enableOpenApi) {
54
+ async function buildForProvider(provider, context, rootOutputDir, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, endpoints, functions, crons, subscribers, enableOpenApi) {
60
55
  const outputDir = join(process.cwd(), ".gkm", provider);
61
56
  await mkdir(outputDir, { recursive: true });
62
57
  logger.log(`\nGenerating handlers for provider: ${provider}`);
@@ -70,14 +65,21 @@ async function buildForProvider(provider, context, endpointGenerator, functionGe
70
65
  subscriberGenerator.build(context, subscribers, outputDir, { provider })
71
66
  ]);
72
67
  logger.log(`Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`);
73
- return {
74
- routes,
75
- functions: functionInfos,
76
- crons: cronInfos,
77
- subscribers: subscriberInfos
78
- };
68
+ if (provider === "server") {
69
+ const routeMetadata = await Promise.all(endpoints.map(async ({ construct }) => ({
70
+ path: construct._path,
71
+ method: construct.method,
72
+ handler: "",
73
+ authorizer: construct.authorizer?.name ?? "none"
74
+ })));
75
+ const appInfo = {
76
+ handler: relative(process.cwd(), join(outputDir, "app.ts")),
77
+ endpoints: relative(process.cwd(), join(outputDir, "endpoints.ts"))
78
+ };
79
+ await generateServerManifest(rootOutputDir, appInfo, routeMetadata, subscriberInfos);
80
+ } else await generateAwsManifest(rootOutputDir, routes, functionInfos, cronInfos, subscriberInfos);
79
81
  }
80
82
 
81
83
  //#endregion
82
84
  export { buildCommand };
83
- //# sourceMappingURL=build-BqexeI-W.mjs.map
85
+ //# sourceMappingURL=build-DyDgu_D1.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-DyDgu_D1.mjs","names":["options: BuildOptions","buildContext: BuildContext","provider: LegacyProvider","context: BuildContext","rootOutputDir: string","endpointGenerator: EndpointGenerator","functionGenerator: FunctionGenerator","cronGenerator: CronGenerator","subscriberGenerator: SubscriberGenerator","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","functions: GeneratedConstruct<Function<any, any, any, any>>[]","crons: GeneratedConstruct<Cron<any, any, any, any>>[]","subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[]","enableOpenApi: boolean","routeMetadata: RouteInfo[]","appInfo: ServerAppInfo"],"sources":["../src/build/index.ts"],"sourcesContent":["import { mkdir } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { Cron } from '@geekmidas/constructs/crons';\nimport type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { Function } from '@geekmidas/constructs/functions';\nimport type { Subscriber } from '@geekmidas/constructs/subscribers';\nimport { loadConfig } from '../config';\nimport {\n CronGenerator,\n EndpointGenerator,\n FunctionGenerator,\n type GeneratedConstruct,\n SubscriberGenerator,\n} from '../generators';\nimport type { BuildOptions, LegacyProvider, RouteInfo } from '../types';\nimport {\n type ServerAppInfo,\n generateAwsManifest,\n generateServerManifest,\n} from './manifests';\nimport { resolveProviders } from './providerResolver';\nimport type { BuildContext } from './types';\n\nconst logger = console;\n\nexport async function buildCommand(options: BuildOptions): Promise<void> {\n const config = await loadConfig();\n\n // Resolve providers from new config format\n const resolved = resolveProviders(config, options);\n\n logger.log(`Building with providers: ${resolved.providers.join(', ')}`);\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 const buildContext: BuildContext = {\n envParserPath,\n envParserImportPattern,\n loggerPath,\n loggerImportPattern,\n };\n\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 in parallel\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 logger.log(`Found ${allEndpoints.length} endpoints`);\n logger.log(`Found ${allFunctions.length} functions`);\n logger.log(`Found ${allCrons.length} crons`);\n logger.log(`Found ${allSubscribers.length} subscribers`);\n\n if (\n allEndpoints.length === 0 &&\n allFunctions.length === 0 &&\n allCrons.length === 0 &&\n allSubscribers.length === 0\n ) {\n logger.log(\n 'No endpoints, functions, crons, or subscribers found to process',\n );\n return;\n }\n\n // Ensure .gkm directory exists\n const rootOutputDir = join(process.cwd(), '.gkm');\n await mkdir(rootOutputDir, { recursive: true });\n\n // Build for each provider and generate per-provider manifests\n for (const provider of resolved.providers) {\n await buildForProvider(\n provider,\n buildContext,\n rootOutputDir,\n endpointGenerator,\n functionGenerator,\n cronGenerator,\n subscriberGenerator,\n allEndpoints,\n allFunctions,\n allCrons,\n allSubscribers,\n resolved.enableOpenApi,\n );\n }\n}\n\nasync function buildForProvider(\n provider: LegacyProvider,\n context: BuildContext,\n rootOutputDir: string,\n endpointGenerator: EndpointGenerator,\n functionGenerator: FunctionGenerator,\n cronGenerator: CronGenerator,\n subscriberGenerator: SubscriberGenerator,\n endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n functions: GeneratedConstruct<Function<any, any, any, any>>[],\n crons: GeneratedConstruct<Cron<any, any, any, any>>[],\n subscribers: GeneratedConstruct<Subscriber<any, any, any, any, any, any>>[],\n enableOpenApi: boolean,\n): Promise<void> {\n const outputDir = join(process.cwd(), '.gkm', provider);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n logger.log(`\\nGenerating handlers for provider: ${provider}`);\n\n // Build all constructs in parallel\n const [routes, functionInfos, cronInfos, subscriberInfos] = await Promise.all(\n [\n endpointGenerator.build(context, endpoints, outputDir, {\n provider,\n enableOpenApi,\n }),\n functionGenerator.build(context, functions, outputDir, { provider }),\n cronGenerator.build(context, crons, outputDir, { provider }),\n subscriberGenerator.build(context, subscribers, outputDir, { provider }),\n ],\n );\n\n logger.log(\n `Generated ${routes.length} routes, ${functionInfos.length} functions, ${cronInfos.length} crons, ${subscriberInfos.length} subscribers for ${provider}`,\n );\n\n // Generate provider-specific manifest\n if (provider === 'server') {\n // For server, collect actual route metadata from endpoint constructs\n const routeMetadata: RouteInfo[] = await Promise.all(\n endpoints.map(async ({ construct }) => ({\n path: construct._path,\n method: construct.method,\n handler: '', // Not needed for server manifest\n authorizer: construct.authorizer?.name ?? 'none',\n })),\n );\n\n const appInfo: ServerAppInfo = {\n handler: relative(process.cwd(), join(outputDir, 'app.ts')),\n endpoints: relative(process.cwd(), join(outputDir, 'endpoints.ts')),\n };\n\n await generateServerManifest(\n rootOutputDir,\n appInfo,\n routeMetadata,\n subscriberInfos,\n );\n } else {\n // For AWS providers, generate AWS manifest\n await generateAwsManifest(\n rootOutputDir,\n routes,\n functionInfos,\n cronInfos,\n subscriberInfos,\n );\n }\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { existsSync } from "fs";
2
2
  import { join } from "path";
3
3
 
4
4
  //#region src/config.ts
5
- async function loadConfig() {
5
+ async function loadConfig(cwd = process.cwd()) {
6
6
  const files = [
7
7
  "gkm.config.json",
8
8
  "gkm.config.ts",
@@ -10,7 +10,7 @@ async function loadConfig() {
10
10
  ];
11
11
  let configPath = "";
12
12
  for (const file of files) {
13
- const path = join(process.cwd(), file);
13
+ const path = join(cwd, file);
14
14
  if (existsSync(path)) {
15
15
  configPath = path;
16
16
  break;
@@ -27,4 +27,4 @@ async function loadConfig() {
27
27
 
28
28
  //#endregion
29
29
  export { loadConfig };
30
- //# sourceMappingURL=config-U-mdW-7Y.mjs.map
30
+ //# sourceMappingURL=config-AFmFKmU0.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-AFmFKmU0.mjs","names":["cwd: string"],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync } from 'fs';\nimport { join } from 'path';\nimport type { GkmConfig } from './types.ts';\n\nexport async function loadConfig(\n cwd: string = process.cwd(),\n): Promise<GkmConfig> {\n const files = ['gkm.config.json', 'gkm.config.ts', 'gkm.config.js'];\n let configPath = '';\n\n for (const file of files) {\n const path = join(cwd, file);\n if (existsSync(path)) {\n configPath = path;\n break;\n }\n }\n\n if (!configPath) {\n throw new Error(\n 'Configuration file not found. Please create gkm.config.json, gkm.config.ts, or gkm.config.js in the project root.',\n );\n }\n\n try {\n const config = await import(configPath);\n return config.default;\n } catch (error) {\n throw new Error(\n `Failed to load gkm.config.json: ${(error as Error).message}`,\n );\n }\n}\n"],"mappings":";;;;AAIA,eAAsB,WACpBA,MAAc,QAAQ,KAAK,EACP;CACpB,MAAM,QAAQ;EAAC;EAAmB;EAAiB;CAAgB;CACnE,IAAI,aAAa;AAEjB,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,OAAO,KAAK,KAAK,KAAK;AAC5B,MAAI,WAAW,KAAK,EAAE;AACpB,gBAAa;AACb;EACD;CACF;AAED,MAAK,WACH,OAAM,IAAI,MACR;AAIJ,KAAI;EACF,MAAM,SAAS,MAAM,OAAO;AAC5B,SAAO,OAAO;CACf,SAAQ,OAAO;AACd,QAAM,IAAI,OACP,kCAAmC,MAAgB,QAAQ;CAE/D;AACF"}
@@ -3,7 +3,7 @@ const fs = require_chunk.__toESM(require("fs"));
3
3
  const path = require_chunk.__toESM(require("path"));
4
4
 
5
5
  //#region src/config.ts
6
- async function loadConfig() {
6
+ async function loadConfig(cwd = process.cwd()) {
7
7
  const files = [
8
8
  "gkm.config.json",
9
9
  "gkm.config.ts",
@@ -11,7 +11,7 @@ async function loadConfig() {
11
11
  ];
12
12
  let configPath = "";
13
13
  for (const file of files) {
14
- const path$1 = (0, path.join)(process.cwd(), file);
14
+ const path$1 = (0, path.join)(cwd, file);
15
15
  if ((0, fs.existsSync)(path$1)) {
16
16
  configPath = path$1;
17
17
  break;
@@ -33,4 +33,4 @@ Object.defineProperty(exports, 'loadConfig', {
33
33
  return loadConfig;
34
34
  }
35
35
  });
36
- //# sourceMappingURL=config-D1EpSGk6.cjs.map
36
+ //# sourceMappingURL=config-BVIJpAsa.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-BVIJpAsa.cjs","names":["cwd: string","path"],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync } from 'fs';\nimport { join } from 'path';\nimport type { GkmConfig } from './types.ts';\n\nexport async function loadConfig(\n cwd: string = process.cwd(),\n): Promise<GkmConfig> {\n const files = ['gkm.config.json', 'gkm.config.ts', 'gkm.config.js'];\n let configPath = '';\n\n for (const file of files) {\n const path = join(cwd, file);\n if (existsSync(path)) {\n configPath = path;\n break;\n }\n }\n\n if (!configPath) {\n throw new Error(\n 'Configuration file not found. Please create gkm.config.json, gkm.config.ts, or gkm.config.js in the project root.',\n );\n }\n\n try {\n const config = await import(configPath);\n return config.default;\n } catch (error) {\n throw new Error(\n `Failed to load gkm.config.json: ${(error as Error).message}`,\n );\n }\n}\n"],"mappings":";;;;;AAIA,eAAsB,WACpBA,MAAc,QAAQ,KAAK,EACP;CACpB,MAAM,QAAQ;EAAC;EAAmB;EAAiB;CAAgB;CACnE,IAAI,aAAa;AAEjB,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAMC,SAAO,eAAK,KAAK,KAAK;AAC5B,MAAI,mBAAWA,OAAK,EAAE;AACpB,gBAAaA;AACb;EACD;CACF;AAED,MAAK,WACH,OAAM,IAAI,MACR;AAIJ,KAAI;EACF,MAAM,SAAS,MAAM,OAAO;AAC5B,SAAO,OAAO;CACf,SAAQ,OAAO;AACd,QAAM,IAAI,OACP,kCAAmC,MAAgB,QAAQ;CAE/D;AACF"}
package/dist/config.cjs CHANGED
@@ -1,3 +1,3 @@
1
- const require_config = require('./config-D1EpSGk6.cjs');
1
+ const require_config = require('./config-BVIJpAsa.cjs');
2
2
 
3
3
  exports.loadConfig = require_config.loadConfig;
package/dist/config.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { loadConfig } from "./config-U-mdW-7Y.mjs";
1
+ import { loadConfig } from "./config-AFmFKmU0.mjs";
2
2
 
3
3
  export { loadConfig };
@@ -1,13 +1,14 @@
1
- require('../config-D1EpSGk6.cjs');
1
+ require('../config-BVIJpAsa.cjs');
2
2
  require('../Generator-CDoEXCDg.cjs');
3
3
  require('../CronGenerator-C6MF8rlG.cjs');
4
- require('../EndpointGenerator-C73wNoih.cjs');
4
+ require('../EndpointGenerator-BxNCkus4.cjs');
5
5
  require('../FunctionGenerator-FgZUTd8L.cjs');
6
6
  require('../SubscriberGenerator-Bd-a7aiw.cjs');
7
7
  require('../generators-CEKtVh81.cjs');
8
8
  require('../providerResolver-DgvzNfP4.cjs');
9
- const require_dev = require('../dev-DbtyToc7.cjs');
9
+ const require_dev = require('../dev-CgDYC4o8.cjs');
10
10
 
11
11
  exports.devCommand = require_dev.devCommand;
12
12
  exports.findAvailablePort = require_dev.findAvailablePort;
13
- exports.isPortAvailable = require_dev.isPortAvailable;
13
+ exports.isPortAvailable = require_dev.isPortAvailable;
14
+ exports.normalizeTelescopeConfig = require_dev.normalizeTelescopeConfig;
@@ -1,11 +1,11 @@
1
- import "../config-U-mdW-7Y.mjs";
1
+ import "../config-AFmFKmU0.mjs";
2
2
  import "../Generator-UanJW0_V.mjs";
3
3
  import "../CronGenerator-Bh26MaNA.mjs";
4
- import "../EndpointGenerator-CWh18d92.mjs";
4
+ import "../EndpointGenerator-CzDhG7Or.mjs";
5
5
  import "../FunctionGenerator-BNE_GC7N.mjs";
6
6
  import "../SubscriberGenerator-Dnlj_1FK.mjs";
7
7
  import "../generators-CsLujGXs.mjs";
8
8
  import "../providerResolver-B_TjNF0_.mjs";
9
- import { devCommand, findAvailablePort, isPortAvailable } from "../dev-DnGYXuMn.mjs";
9
+ import { devCommand, findAvailablePort, isPortAvailable, normalizeTelescopeConfig } from "../dev-CpA8AQPX.mjs";
10
10
 
11
- export { devCommand, findAvailablePort, isPortAvailable };
11
+ export { devCommand, findAvailablePort, isPortAvailable, normalizeTelescopeConfig };
@@ -1,12 +1,13 @@
1
1
  const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const require_config = require('./config-D1EpSGk6.cjs');
2
+ const require_config = require('./config-BVIJpAsa.cjs');
3
3
  const require_CronGenerator = require('./CronGenerator-C6MF8rlG.cjs');
4
- const require_EndpointGenerator = require('./EndpointGenerator-C73wNoih.cjs');
4
+ const require_EndpointGenerator = require('./EndpointGenerator-BxNCkus4.cjs');
5
5
  const require_FunctionGenerator = require('./FunctionGenerator-FgZUTd8L.cjs');
6
6
  const require_SubscriberGenerator = require('./SubscriberGenerator-Bd-a7aiw.cjs');
7
7
  const require_providerResolver = require('./providerResolver-DgvzNfP4.cjs');
8
8
  const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
9
9
  const node_path = require_chunk.__toESM(require("node:path"));
10
+ const fast_glob = require_chunk.__toESM(require("fast-glob"));
10
11
  const node_child_process = require_chunk.__toESM(require("node:child_process"));
11
12
  const node_net = require_chunk.__toESM(require("node:net"));
12
13
  const chokidar = require_chunk.__toESM(require("chokidar"));
@@ -43,6 +44,24 @@ async function findAvailablePort(preferredPort, maxAttempts = 10) {
43
44
  }
44
45
  throw new Error(`Could not find an available port after trying ${maxAttempts} ports starting from ${preferredPort}`);
45
46
  }
47
+ /**
48
+ * Normalize telescope configuration
49
+ * @internal Exported for testing
50
+ */
51
+ function normalizeTelescopeConfig(config) {
52
+ if (config === false) return void 0;
53
+ const isEnabled = config === true || config === void 0 || config.enabled !== false;
54
+ if (!isEnabled) return void 0;
55
+ const telescopeConfig = typeof config === "object" ? config : {};
56
+ return {
57
+ enabled: true,
58
+ path: telescopeConfig.path ?? "/__telescope",
59
+ ignore: telescopeConfig.ignore ?? [],
60
+ recordBody: telescopeConfig.recordBody ?? true,
61
+ maxEntries: telescopeConfig.maxEntries ?? 1e3,
62
+ websocket: telescopeConfig.websocket ?? true
63
+ };
64
+ }
46
65
  async function devCommand(options) {
47
66
  const config = await require_config.loadConfig();
48
67
  const resolved = require_providerResolver.resolveProviders(config, { provider: "server" });
@@ -56,28 +75,49 @@ async function devCommand(options) {
56
75
  const envParserImportPattern = !envParserName ? "envParser" : envParserName === "envParser" ? "{ envParser }" : `{ ${envParserName} as envParser }`;
57
76
  const [loggerPath, loggerName] = config.logger.split("#");
58
77
  const loggerImportPattern = !loggerName ? "logger" : loggerName === "logger" ? "{ logger }" : `{ ${loggerName} as logger }`;
78
+ const telescope = normalizeTelescopeConfig(config.telescope);
79
+ if (telescope) logger.log(`🔭 Telescope enabled at ${telescope.path}`);
59
80
  const buildContext = {
60
81
  envParserPath,
61
82
  envParserImportPattern,
62
83
  loggerPath,
63
- loggerImportPattern
84
+ loggerImportPattern,
85
+ telescope
64
86
  };
65
87
  await buildServer(config, buildContext, resolved.providers[0], resolved.enableOpenApi);
66
- const devServer = new DevServer(resolved.providers[0], options.port || 3e3, resolved.enableOpenApi);
88
+ const runtime = config.runtime ?? "node";
89
+ const devServer = new DevServer(resolved.providers[0], options.port || 3e3, resolved.enableOpenApi, telescope, runtime);
67
90
  await devServer.start();
91
+ const envParserFile = config.envParser.split("#")[0];
92
+ const loggerFile = config.logger.split("#")[0];
68
93
  const watchPatterns = [
69
94
  config.routes,
70
95
  ...config.functions ? [config.functions] : [],
71
96
  ...config.crons ? [config.crons] : [],
72
97
  ...config.subscribers ? [config.subscribers] : [],
73
- config.envParser.split("#")[0],
74
- config.logger.split("#")[0]
98
+ envParserFile.endsWith(".ts") ? envParserFile : `${envParserFile}.ts`,
99
+ loggerFile.endsWith(".ts") ? loggerFile : `${loggerFile}.ts`
75
100
  ].flat();
76
- logger.log(`👀 Watching for changes in: ${watchPatterns.join(", ")}`);
77
- const watcher = chokidar.default.watch(watchPatterns, {
101
+ const normalizedPatterns = watchPatterns.map((p) => p.startsWith("./") ? p.slice(2) : p);
102
+ logger.log(`👀 Watching for changes in: ${normalizedPatterns.join(", ")}`);
103
+ const resolvedFiles = await (0, fast_glob.default)(normalizedPatterns, {
104
+ cwd: process.cwd(),
105
+ absolute: false,
106
+ onlyFiles: true
107
+ });
108
+ const dirsToWatch = [...new Set(resolvedFiles.map((f) => f.split("/").slice(0, -1).join("/")))];
109
+ logger.log(`📁 Found ${resolvedFiles.length} files in ${dirsToWatch.length} directories`);
110
+ const watcher = chokidar.default.watch([...resolvedFiles, ...dirsToWatch], {
78
111
  ignored: /(^|[\/\\])\../,
79
112
  persistent: true,
80
- ignoreInitial: true
113
+ ignoreInitial: true,
114
+ cwd: process.cwd()
115
+ });
116
+ watcher.on("ready", () => {
117
+ logger.log("🔍 File watcher ready");
118
+ });
119
+ watcher.on("error", (error) => {
120
+ logger.error("❌ Watcher error:", error);
81
121
  });
82
122
  let rebuildTimeout = null;
83
123
  watcher.on("change", async (path) => {
@@ -130,10 +170,12 @@ var DevServer = class {
130
170
  serverProcess = null;
131
171
  isRunning = false;
132
172
  actualPort;
133
- constructor(provider, requestedPort, enableOpenApi) {
173
+ constructor(provider, requestedPort, enableOpenApi, telescope, runtime = "node") {
134
174
  this.provider = provider;
135
175
  this.requestedPort = requestedPort;
136
176
  this.enableOpenApi = enableOpenApi;
177
+ this.telescope = telescope;
178
+ this.runtime = runtime;
137
179
  this.actualPort = requestedPort;
138
180
  }
139
181
  async start() {
@@ -153,7 +195,8 @@ var DevServer = class {
153
195
  env: {
154
196
  ...process.env,
155
197
  NODE_ENV: "development"
156
- }
198
+ },
199
+ detached: true
157
200
  });
158
201
  this.isRunning = true;
159
202
  this.serverProcess.on("error", (error) => {
@@ -167,16 +210,22 @@ var DevServer = class {
167
210
  if (this.isRunning) {
168
211
  logger.log(`\n🎉 Server running at http://localhost:${this.actualPort}`);
169
212
  if (this.enableOpenApi) logger.log(`📚 API Docs available at http://localhost:${this.actualPort}/docs`);
213
+ if (this.telescope) logger.log(`🔭 Telescope available at http://localhost:${this.actualPort}${this.telescope.path}`);
170
214
  }
171
215
  }
172
216
  async stop() {
173
217
  if (this.serverProcess && this.isRunning) {
174
- this.serverProcess.kill("SIGTERM");
218
+ const pid = this.serverProcess.pid;
219
+ if (pid) try {
220
+ process.kill(-pid, "SIGTERM");
221
+ } catch {}
175
222
  await new Promise((resolve) => {
176
223
  const timeout = setTimeout(() => {
177
- this.serverProcess?.kill("SIGKILL");
224
+ if (pid) try {
225
+ process.kill(-pid, "SIGKILL");
226
+ } catch {}
178
227
  resolve();
179
- }, 5e3);
228
+ }, 3e3);
180
229
  this.serverProcess?.on("exit", () => {
181
230
  clearTimeout(timeout);
182
231
  resolve();
@@ -187,7 +236,15 @@ var DevServer = class {
187
236
  }
188
237
  }
189
238
  async restart() {
239
+ const portToReuse = this.actualPort;
190
240
  await this.stop();
241
+ let attempts = 0;
242
+ while (attempts < 30) {
243
+ if (await isPortAvailable(portToReuse)) break;
244
+ await new Promise((resolve) => setTimeout(resolve, 100));
245
+ attempts++;
246
+ }
247
+ this.requestedPort = portToReuse;
191
248
  await this.start();
192
249
  }
193
250
  async createServerEntry() {
@@ -195,6 +252,20 @@ var DevServer = class {
195
252
  const { relative, dirname } = await import("node:path");
196
253
  const serverPath = (0, node_path.join)(process.cwd(), ".gkm", this.provider, "server.ts");
197
254
  const relativeAppPath = relative(dirname(serverPath), (0, node_path.join)(dirname(serverPath), "app.js"));
255
+ const serveCode = this.runtime === "bun" ? `Bun.serve({
256
+ port,
257
+ fetch: app.fetch,
258
+ });` : `const { serve } = await import('@hono/node-server');
259
+ const server = serve({
260
+ fetch: app.fetch,
261
+ port,
262
+ });
263
+ // Inject WebSocket support if available
264
+ const injectWs = (app as any).__injectWebSocket;
265
+ if (injectWs) {
266
+ injectWs(server);
267
+ console.log('🔌 Telescope real-time updates enabled');
268
+ }`;
198
269
  const content = `#!/usr/bin/env node
199
270
  /**
200
271
  * Development server entry point
@@ -206,27 +277,14 @@ const port = process.argv.includes('--port')
206
277
  ? Number.parseInt(process.argv[process.argv.indexOf('--port') + 1])
207
278
  : 3000;
208
279
 
209
- const { app, start } = createApp(undefined, ${this.enableOpenApi});
280
+ // createApp is async to support optional WebSocket setup
281
+ const { app, start } = await createApp(undefined, ${this.enableOpenApi});
210
282
 
211
283
  // Start the server
212
284
  start({
213
285
  port,
214
286
  serve: async (app, port) => {
215
- // Detect runtime and use appropriate server
216
- if (typeof Bun !== 'undefined') {
217
- // Bun runtime
218
- Bun.serve({
219
- port,
220
- fetch: app.fetch,
221
- });
222
- } else {
223
- // Node.js runtime with @hono/node-server
224
- const { serve } = await import('@hono/node-server');
225
- serve({
226
- fetch: app.fetch,
227
- port,
228
- });
229
- }
287
+ ${serveCode}
230
288
  },
231
289
  }).catch((error) => {
232
290
  console.error('Failed to start server:', error);
@@ -256,4 +314,10 @@ Object.defineProperty(exports, 'isPortAvailable', {
256
314
  return isPortAvailable;
257
315
  }
258
316
  });
259
- //# sourceMappingURL=dev-DbtyToc7.cjs.map
317
+ Object.defineProperty(exports, 'normalizeTelescopeConfig', {
318
+ enumerable: true,
319
+ get: function () {
320
+ return normalizeTelescopeConfig;
321
+ }
322
+ });
323
+ //# sourceMappingURL=dev-CgDYC4o8.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-CgDYC4o8.cjs","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","EndpointGenerator","FunctionGenerator","CronGenerator","SubscriberGenerator","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":"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"}