@geekmidas/cli 0.1.0 → 0.2.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 (146) hide show
  1. package/README.md +63 -13
  2. package/dist/{CronGenerator-Ctl4USy4.cjs → CronGenerator-1PflEYe2.cjs} +8 -7
  3. package/dist/CronGenerator-1PflEYe2.cjs.map +1 -0
  4. package/dist/{CronGenerator-ClbRcmz_.mjs → CronGenerator-DXRfHQcV.mjs} +6 -5
  5. package/dist/CronGenerator-DXRfHQcV.mjs.map +1 -0
  6. package/dist/{EndpointGenerator-Dj7AumHi.cjs → EndpointGenerator-BbGrDiCP.cjs} +134 -34
  7. package/dist/EndpointGenerator-BbGrDiCP.cjs.map +1 -0
  8. package/dist/{EndpointGenerator-uBA1ixUw.mjs → EndpointGenerator-BmZ9BxbO.mjs} +132 -32
  9. package/dist/EndpointGenerator-BmZ9BxbO.mjs.map +1 -0
  10. package/dist/{FunctionGenerator-DN681IUn.cjs → FunctionGenerator-Clw64SwQ.cjs} +8 -7
  11. package/dist/FunctionGenerator-Clw64SwQ.cjs.map +1 -0
  12. package/dist/{FunctionGenerator-crAa-JC7.mjs → FunctionGenerator-DOEB_yPh.mjs} +6 -5
  13. package/dist/FunctionGenerator-DOEB_yPh.mjs.map +1 -0
  14. package/dist/{Generator-C3tYSTQY.cjs → Generator-CDoEXCDg.cjs} +2 -2
  15. package/dist/Generator-CDoEXCDg.cjs.map +1 -0
  16. package/dist/{Generator-CDt4pB3W.mjs → Generator-UanJW0_V.mjs} +1 -1
  17. package/dist/Generator-UanJW0_V.mjs.map +1 -0
  18. package/dist/SubscriberGenerator-BfMZCVNy.cjs +204 -0
  19. package/dist/SubscriberGenerator-BfMZCVNy.cjs.map +1 -0
  20. package/dist/SubscriberGenerator-D2u00NI3.mjs +198 -0
  21. package/dist/SubscriberGenerator-D2u00NI3.mjs.map +1 -0
  22. package/dist/build/index.cjs +10 -9
  23. package/dist/build/index.mjs +8 -7
  24. package/dist/build/manifests.cjs +1 -1
  25. package/dist/build/manifests.mjs +1 -1
  26. package/dist/build/providerResolver.cjs +1 -1
  27. package/dist/build-BBhlEjf5.cjs +89 -0
  28. package/dist/build-BBhlEjf5.cjs.map +1 -0
  29. package/dist/build-kY-lG30Q.mjs +83 -0
  30. package/dist/build-kY-lG30Q.mjs.map +1 -0
  31. package/dist/{chunk-CsX-DzYB.cjs → chunk-CUT6urMc.cjs} +0 -12
  32. package/dist/{config-RcNESK0T.cjs → config-D1EpSGk6.cjs} +2 -2
  33. package/dist/{config-RcNESK0T.cjs.map → config-D1EpSGk6.cjs.map} +1 -1
  34. package/dist/{config-CXxYmz_o.mjs → config-U-mdW-7Y.mjs} +1 -1
  35. package/dist/{config-CXxYmz_o.mjs.map → config-U-mdW-7Y.mjs.map} +1 -1
  36. package/dist/config.cjs +1 -1
  37. package/dist/config.mjs +1 -1
  38. package/dist/generators/CronGenerator.cjs +2 -2
  39. package/dist/generators/CronGenerator.mjs +2 -2
  40. package/dist/generators/EndpointGenerator.cjs +2 -2
  41. package/dist/generators/EndpointGenerator.mjs +2 -2
  42. package/dist/generators/FunctionGenerator.cjs +2 -2
  43. package/dist/generators/FunctionGenerator.mjs +2 -2
  44. package/dist/generators/Generator.cjs +1 -1
  45. package/dist/generators/Generator.mjs +1 -1
  46. package/dist/generators/SubscriberGenerator.cjs +4 -0
  47. package/dist/generators/SubscriberGenerator.mjs +4 -0
  48. package/dist/generators/index.cjs +8 -6
  49. package/dist/generators/index.mjs +6 -5
  50. package/dist/index.cjs +18 -14
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.mjs +15 -11
  53. package/dist/index.mjs.map +1 -1
  54. package/dist/{manifests-HX4z4kkz.mjs → manifests-BrJXpHrf.mjs} +5 -4
  55. package/dist/manifests-BrJXpHrf.mjs.map +1 -0
  56. package/dist/{manifests-BTtfDMX8.cjs → manifests-D0saShvH.cjs} +6 -5
  57. package/dist/manifests-D0saShvH.cjs.map +1 -0
  58. package/dist/{openapi-BivnatiC.mjs → openapi-BQx3_JbM.mjs} +4 -4
  59. package/dist/openapi-BQx3_JbM.mjs.map +1 -0
  60. package/dist/{openapi-DW-qF3oW.cjs → openapi-CMLr04cz.cjs} +6 -6
  61. package/dist/openapi-CMLr04cz.cjs.map +1 -0
  62. package/dist/{openapi-react-query-lgS7AVEz.mjs → openapi-react-query-DbrWwQzb.mjs} +3 -2
  63. package/dist/openapi-react-query-DbrWwQzb.mjs.map +1 -0
  64. package/dist/{openapi-react-query-J0BzBHhN.cjs → openapi-react-query-Dvjqx_Eo.cjs} +4 -3
  65. package/dist/openapi-react-query-Dvjqx_Eo.cjs.map +1 -0
  66. package/dist/openapi-react-query.cjs +1 -1
  67. package/dist/openapi-react-query.mjs +1 -1
  68. package/dist/openapi.cjs +4 -4
  69. package/dist/openapi.mjs +4 -4
  70. package/dist/{providerResolver-Cs-0YCaP.cjs → providerResolver-DgvzNfP4.cjs} +1 -1
  71. package/dist/{providerResolver-Cs-0YCaP.cjs.map → providerResolver-DgvzNfP4.cjs.map} +1 -1
  72. package/examples/cron-example.ts +1 -1
  73. package/examples/function-example.ts +1 -1
  74. package/examples/logger.ts +1 -1
  75. package/package.json +6 -3
  76. package/src/__tests__/openapi-react-query.spec.ts +506 -0
  77. package/src/__tests__/openapi.spec.ts +362 -0
  78. package/src/__tests__/test-helpers.ts +10 -8
  79. package/src/build/__tests__/index-new.spec.ts +41 -42
  80. package/src/build/index.ts +89 -28
  81. package/src/build/manifests.ts +4 -1
  82. package/src/build/types.ts +2 -2
  83. package/src/generators/CronGenerator.ts +3 -2
  84. package/src/generators/EndpointGenerator.ts +141 -42
  85. package/src/generators/FunctionGenerator.ts +3 -2
  86. package/src/generators/Generator.ts +1 -1
  87. package/src/generators/SubscriberGenerator.ts +271 -0
  88. package/src/generators/__tests__/CronGenerator.spec.ts +1 -1
  89. package/src/generators/__tests__/EndpointGenerator.spec.ts +33 -11
  90. package/src/generators/__tests__/FunctionGenerator.spec.ts +21 -22
  91. package/src/generators/__tests__/SubscriberGenerator.spec.ts +341 -0
  92. package/src/generators/index.ts +1 -0
  93. package/src/openapi-react-query.ts +2 -1
  94. package/src/openapi.ts +1 -1
  95. package/src/types.ts +18 -0
  96. package/dist/CronGenerator-ClbRcmz_.mjs.map +0 -1
  97. package/dist/CronGenerator-Ctl4USy4.cjs.map +0 -1
  98. package/dist/EndpointGenerator-Dj7AumHi.cjs.map +0 -1
  99. package/dist/EndpointGenerator-uBA1ixUw.mjs.map +0 -1
  100. package/dist/FunctionGenerator-DN681IUn.cjs.map +0 -1
  101. package/dist/FunctionGenerator-crAa-JC7.mjs.map +0 -1
  102. package/dist/Generator-C3tYSTQY.cjs.map +0 -1
  103. package/dist/Generator-CDt4pB3W.mjs.map +0 -1
  104. package/dist/__tests__/config.spec.cjs +0 -98
  105. package/dist/__tests__/config.spec.cjs.map +0 -1
  106. package/dist/__tests__/config.spec.mjs +0 -97
  107. package/dist/__tests__/config.spec.mjs.map +0 -1
  108. package/dist/__tests__/test-helpers.cjs +0 -14
  109. package/dist/__tests__/test-helpers.mjs +0 -4
  110. package/dist/build/__tests__/index-new.spec.cjs +0 -286
  111. package/dist/build/__tests__/index-new.spec.cjs.map +0 -1
  112. package/dist/build/__tests__/index-new.spec.mjs +0 -285
  113. package/dist/build/__tests__/index-new.spec.mjs.map +0 -1
  114. package/dist/build-BZdwxCLW.mjs +0 -64
  115. package/dist/build-BZdwxCLW.mjs.map +0 -1
  116. package/dist/build-BfQFnU5-.cjs +0 -70
  117. package/dist/build-BfQFnU5-.cjs.map +0 -1
  118. package/dist/esm-9eeZntth.mjs +0 -3777
  119. package/dist/esm-9eeZntth.mjs.map +0 -1
  120. package/dist/esm-Crmo4h9t.cjs +0 -4392
  121. package/dist/esm-Crmo4h9t.cjs.map +0 -1
  122. package/dist/esm-CsJbr7gi.mjs +0 -3
  123. package/dist/esm-w09tAC4l.cjs +0 -8
  124. package/dist/generators/__tests__/CronGenerator.spec.cjs +0 -216
  125. package/dist/generators/__tests__/CronGenerator.spec.cjs.map +0 -1
  126. package/dist/generators/__tests__/CronGenerator.spec.mjs +0 -215
  127. package/dist/generators/__tests__/CronGenerator.spec.mjs.map +0 -1
  128. package/dist/generators/__tests__/EndpointGenerator.spec.cjs +0 -182
  129. package/dist/generators/__tests__/EndpointGenerator.spec.cjs.map +0 -1
  130. package/dist/generators/__tests__/EndpointGenerator.spec.mjs +0 -181
  131. package/dist/generators/__tests__/EndpointGenerator.spec.mjs.map +0 -1
  132. package/dist/generators/__tests__/FunctionGenerator.spec.cjs +0 -152
  133. package/dist/generators/__tests__/FunctionGenerator.spec.cjs.map +0 -1
  134. package/dist/generators/__tests__/FunctionGenerator.spec.mjs +0 -151
  135. package/dist/generators/__tests__/FunctionGenerator.spec.mjs.map +0 -1
  136. package/dist/manifests-BTtfDMX8.cjs.map +0 -1
  137. package/dist/manifests-HX4z4kkz.mjs.map +0 -1
  138. package/dist/openapi-BivnatiC.mjs.map +0 -1
  139. package/dist/openapi-DW-qF3oW.cjs.map +0 -1
  140. package/dist/openapi-react-query-J0BzBHhN.cjs.map +0 -1
  141. package/dist/openapi-react-query-lgS7AVEz.mjs.map +0 -1
  142. package/dist/test-helpers-ARd8GDgx.cjs +0 -199
  143. package/dist/test-helpers-ARd8GDgx.cjs.map +0 -1
  144. package/dist/test-helpers-DdVBk23F.mjs +0 -133
  145. package/dist/test-helpers-DdVBk23F.mjs.map +0 -1
  146. /package/dist/{generators-_pY7sHy1.cjs → generators-CEKtVh81.cjs} +0 -0
package/README.md CHANGED
@@ -36,10 +36,19 @@ import type { GkmConfig } from '@geekmidas/cli';
36
36
  const config: GkmConfig = {
37
37
  // Glob pattern to find endpoint files
38
38
  routes: 'src/routes/**/*.ts',
39
-
39
+
40
+ // Optional: Functions
41
+ functions: 'src/functions/**/*.ts',
42
+
43
+ // Optional: Cron jobs
44
+ crons: 'src/crons/**/*.ts',
45
+
46
+ // Optional: Event subscribers
47
+ subscribers: 'src/subscribers/**/*.ts',
48
+
40
49
  // Environment parser configuration
41
50
  envParser: './src/env.ts#envParser',
42
-
51
+
43
52
  // Logger configuration
44
53
  logger: './src/logger.ts#logger',
45
54
  };
@@ -74,7 +83,7 @@ export const envParser = new EnvironmentParser(process.env)
74
83
  Create `src/logger.ts`:
75
84
 
76
85
  ```typescript
77
- import { ConsoleLogger } from '@geekmidas/api/logger';
86
+ import { ConsoleLogger } from '@geekmidas/logger/console';
78
87
 
79
88
  export const logger = new ConsoleLogger({
80
89
  level: process.env.LOG_LEVEL || 'info',
@@ -88,7 +97,7 @@ Create endpoint files in `src/routes/`:
88
97
 
89
98
  ```typescript
90
99
  // src/routes/users.ts
91
- import { e } from '@geekmidas/api/server';
100
+ import { e } from '@geekmidas/constructs/endpoints';
92
101
  import { z } from 'zod';
93
102
 
94
103
  export const getUsers = e
@@ -107,7 +116,48 @@ export const createUser = e
107
116
  });
108
117
  ```
109
118
 
110
- ### 5. Build Handlers
119
+ ### 5. Create Subscribers (Optional)
120
+
121
+ Create event subscribers in `src/subscribers/`:
122
+
123
+ ```typescript
124
+ // src/subscribers/userSubscriber.ts
125
+ import { SubscriberBuilder } from '@geekmidas/constructs/subscribers';
126
+ import type { Service } from '@geekmidas/services';
127
+ import type { EventPublisher, PublishableMessage } from '@geekmidas/events';
128
+ import type { EnvironmentParser } from '@geekmidas/envkit';
129
+
130
+ // Define event types
131
+ type UserEvents =
132
+ | PublishableMessage<'user.created', { userId: string; email: string }>
133
+ | PublishableMessage<'user.updated', { userId: string }>;
134
+
135
+ // Create event publisher service
136
+ const userEventPublisher = {
137
+ serviceName: 'userEventPublisher' as const,
138
+ async register(envParser: EnvironmentParser<{}>) {
139
+ const config = envParser.create((get) => ({
140
+ publisherUrl: get('EVENT_PUBLISHER_URL').string()
141
+ })).parse();
142
+
143
+ const { Publisher } = await import('@geekmidas/events');
144
+ return Publisher.fromConnectionString<UserEvents>(config.publisherUrl);
145
+ }
146
+ } satisfies Service<'userEventPublisher', EventPublisher<UserEvents>>;
147
+
148
+ // Create subscriber
149
+ export const userCreatedSubscriber = new SubscriberBuilder()
150
+ .publisher(userEventPublisher)
151
+ .subscribe(['user.created'])
152
+ .handle(async ({ events, logger }) => {
153
+ for (const event of events) {
154
+ logger.info({ userId: event.payload.userId }, 'Processing user.created event');
155
+ // Process event...
156
+ }
157
+ });
158
+ ```
159
+
160
+ ### 6. Build Handlers
111
161
 
112
162
  ```bash
113
163
  # Generate AWS Lambda handlers
@@ -244,7 +294,7 @@ gkm build --provider aws-apigatewayv1
244
294
 
245
295
  **Generated Handler:**
246
296
  ```typescript
247
- import { AmazonApiGatewayV1Endpoint } from '@geekmidas/api/aws-apigateway';
297
+ import { AmazonApiGatewayV1Endpoint } from '@geekmidas/constructs/aws';
248
298
  import { myEndpoint } from '../src/routes/example.js';
249
299
  import { envParser } from '../src/env.js';
250
300
 
@@ -263,7 +313,7 @@ gkm build --provider aws-apigatewayv2
263
313
 
264
314
  **Generated Handler:**
265
315
  ```typescript
266
- import { AmazonApiGatewayV2Endpoint } from '@geekmidas/api/aws-apigateway';
316
+ import { AmazonApiGatewayV2Endpoint } from '@geekmidas/constructs/aws';
267
317
  import { myEndpoint } from '../src/routes/example.js';
268
318
  import { envParser } from '../src/env.js';
269
319
 
@@ -282,8 +332,8 @@ gkm build --provider server
282
332
 
283
333
  **Generated Server:**
284
334
  ```typescript
285
- import { HonoEndpoint } from '@geekmidas/api/hono';
286
- import { HermodServiceDiscovery } from '@geekmidas/api/services';
335
+ import { HonoEndpoint } from '@geekmidas/constructs/endpoints';
336
+ import { ServiceDiscovery } from '@geekmidas/services';
287
337
  import { Hono } from 'hono';
288
338
  import { envParser } from '../src/env.js';
289
339
  import { logger } from '../src/logger.js';
@@ -291,10 +341,10 @@ import { getUsers, createUser } from '../src/routes/users.js';
291
341
 
292
342
  export function createApp(app?: Hono): Hono {
293
343
  const honoApp = app || new Hono();
294
-
344
+
295
345
  const endpoints = [getUsers, createUser];
296
-
297
- const serviceDiscovery = HermodServiceDiscovery.getInstance(
346
+
347
+ const serviceDiscovery = ServiceDiscovery.getInstance(
298
348
  logger,
299
349
  envParser
300
350
  );
@@ -512,7 +562,7 @@ Set up structured logging with different levels:
512
562
 
513
563
  ```typescript
514
564
  // src/logger.ts
515
- import { ConsoleLogger } from '@geekmidas/api/logger';
565
+ import { ConsoleLogger } from '@geekmidas/logger/console';
516
566
 
517
567
  export const logger = new ConsoleLogger({
518
568
  level: process.env.LOG_LEVEL || 'info',
@@ -1,8 +1,8 @@
1
- const require_chunk = require('./chunk-CsX-DzYB.cjs');
2
- const require_Generator = require('./Generator-C3tYSTQY.cjs');
1
+ const require_chunk = require('./chunk-CUT6urMc.cjs');
2
+ const require_Generator = require('./Generator-CDoEXCDg.cjs');
3
3
  const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
4
4
  const node_path = require_chunk.__toESM(require("node:path"));
5
- const __geekmidas_api_constructs = require_chunk.__toESM(require("@geekmidas/api/constructs"));
5
+ const __geekmidas_constructs_crons = require_chunk.__toESM(require("@geekmidas/constructs/crons"));
6
6
 
7
7
  //#region src/generators/CronGenerator.ts
8
8
  var CronGenerator = class extends require_Generator.ConstructGenerator {
@@ -19,14 +19,15 @@ var CronGenerator = class extends require_Generator.ConstructGenerator {
19
19
  name: key,
20
20
  handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
21
21
  schedule: construct.schedule || "rate(1 hour)",
22
- timeout: construct.timeout
22
+ timeout: construct.timeout,
23
+ environment: await construct.getEnvironment()
23
24
  });
24
25
  logger.log(`Generated cron handler: ${key}`);
25
26
  }
26
27
  return cronInfos;
27
28
  }
28
29
  isConstruct(value) {
29
- return __geekmidas_api_constructs.Cron.isCron(value);
30
+ return __geekmidas_constructs_crons.Cron.isCron(value);
30
31
  }
31
32
  async generateCronHandler(outputDir, sourceFile, exportName, context) {
32
33
  const handlerFileName = `${exportName}.ts`;
@@ -35,7 +36,7 @@ var CronGenerator = class extends require_Generator.ConstructGenerator {
35
36
  const importPath = relativePath.replace(/\.ts$/, ".js");
36
37
  const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), context.envParserPath);
37
38
  const relativeLoggerPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), context.loggerPath);
38
- const content = `import { AWSScheduledFunction } from '@geekmidas/api/aws-lambda';
39
+ const content = `import { AWSScheduledFunction } from '@geekmidas/constructs/crons';
39
40
  import { ${exportName} } from '${importPath}';
40
41
  import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
41
42
  import ${context.loggerImportPattern} from '${relativeLoggerPath}';
@@ -56,4 +57,4 @@ Object.defineProperty(exports, 'CronGenerator', {
56
57
  return CronGenerator;
57
58
  }
58
59
  });
59
- //# sourceMappingURL=CronGenerator-Ctl4USy4.cjs.map
60
+ //# sourceMappingURL=CronGenerator-1PflEYe2.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CronGenerator-1PflEYe2.cjs","names":["ConstructGenerator","context: BuildContext","constructs: GeneratedConstruct<Cron<any, any, any, any>>[]","outputDir: string","options?: GeneratorOptions","cronInfos: CronInfo[]","value: any","sourceFile: string","exportName: string"],"sources":["../src/generators/CronGenerator.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Cron } from '@geekmidas/constructs/crons';\nimport type { BuildContext } from '../build/types';\nimport type { CronInfo } from '../types';\nimport {\n ConstructGenerator,\n type GeneratedConstruct,\n type GeneratorOptions,\n} from './Generator';\n\nexport class CronGenerator extends ConstructGenerator<\n Cron<any, any, any, any>,\n CronInfo[]\n> {\n async build(\n context: BuildContext,\n constructs: GeneratedConstruct<Cron<any, any, any, any>>[],\n outputDir: string,\n options?: GeneratorOptions,\n ): Promise<CronInfo[]> {\n const provider = options?.provider || 'aws-lambda';\n const logger = console;\n const cronInfos: CronInfo[] = [];\n\n if (constructs.length === 0 || provider !== 'aws-lambda') {\n return cronInfos;\n }\n\n // Create crons subdirectory\n const cronsDir = join(outputDir, 'crons');\n await mkdir(cronsDir, { recursive: true });\n\n // Generate cron handlers\n for (const { key, construct, path } of constructs) {\n const handlerFile = await this.generateCronHandler(\n cronsDir,\n path.relative,\n key,\n context,\n );\n\n cronInfos.push({\n name: key,\n handler: relative(process.cwd(), handlerFile).replace(\n /\\.ts$/,\n '.handler',\n ),\n schedule: construct.schedule || 'rate(1 hour)',\n timeout: construct.timeout,\n environment: await construct.getEnvironment(),\n });\n\n logger.log(`Generated cron handler: ${key}`);\n }\n\n return cronInfos;\n }\n\n isConstruct(value: any): value is Cron<any, any, any, any> {\n return Cron.isCron(value);\n }\n\n private async generateCronHandler(\n outputDir: string,\n sourceFile: string,\n exportName: string,\n context: BuildContext,\n ): Promise<string> {\n const handlerFileName = `${exportName}.ts`;\n const handlerPath = join(outputDir, handlerFileName);\n\n const relativePath = relative(dirname(handlerPath), sourceFile);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n const relativeEnvParserPath = relative(\n dirname(handlerPath),\n context.envParserPath,\n );\n const relativeLoggerPath = relative(\n dirname(handlerPath),\n context.loggerPath,\n );\n\n const content = `import { AWSScheduledFunction } from '@geekmidas/constructs/crons';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\nimport ${context.loggerImportPattern} from '${relativeLoggerPath}';\n\nconst adapter = new AWSScheduledFunction(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n await writeFile(handlerPath, content);\n return handlerPath;\n }\n}\n"],"mappings":";;;;;;;AAWA,IAAa,gBAAb,cAAmCA,qCAGjC;CACA,MAAM,MACJC,SACAC,YACAC,WACAC,SACqB;EACrB,MAAM,WAAW,SAAS,YAAY;EACtC,MAAM,SAAS;EACf,MAAMC,YAAwB,CAAE;AAEhC,MAAI,WAAW,WAAW,KAAK,aAAa,aAC1C,QAAO;EAIT,MAAM,WAAW,oBAAK,WAAW,QAAQ;AACzC,QAAM,4BAAM,UAAU,EAAE,WAAW,KAAM,EAAC;AAG1C,OAAK,MAAM,EAAE,KAAK,WAAW,MAAM,IAAI,YAAY;GACjD,MAAM,cAAc,MAAM,KAAK,oBAC7B,UACA,KAAK,UACL,KACA,QACD;AAED,aAAU,KAAK;IACb,MAAM;IACN,SAAS,wBAAS,QAAQ,KAAK,EAAE,YAAY,CAAC,QAC5C,SACA,WACD;IACD,UAAU,UAAU,YAAY;IAChC,SAAS,UAAU;IACnB,aAAa,MAAM,UAAU,gBAAgB;GAC9C,EAAC;AAEF,UAAO,KAAK,0BAA0B,IAAI,EAAE;EAC7C;AAED,SAAO;CACR;CAED,YAAYC,OAA+C;AACzD,SAAO,kCAAK,OAAO,MAAM;CAC1B;CAED,MAAc,oBACZH,WACAI,YACAC,YACAP,SACiB;EACjB,MAAM,mBAAmB,EAAE,WAAW;EACtC,MAAM,cAAc,oBAAK,WAAW,gBAAgB;EAEpD,MAAM,eAAe,wBAAS,uBAAQ,YAAY,EAAE,WAAW;EAC/D,MAAM,aAAa,aAAa,QAAQ,SAAS,MAAM;EAEvD,MAAM,wBAAwB,wBAC5B,uBAAQ,YAAY,EACpB,QAAQ,cACT;EACD,MAAM,qBAAqB,wBACzB,uBAAQ,YAAY,EACpB,QAAQ,WACT;EAED,MAAM,WAAW;WACV,WAAW,WAAW,WAAW;SACnC,QAAQ,uBAAuB,SAAS,sBAAsB;SAC9D,QAAQ,oBAAoB,SAAS,mBAAmB;;sDAEX,WAAW;;;;AAK7D,QAAM,gCAAU,aAAa,QAAQ;AACrC,SAAO;CACR;AACF"}
@@ -1,7 +1,7 @@
1
- import { ConstructGenerator } from "./Generator-CDt4pB3W.mjs";
1
+ import { ConstructGenerator } from "./Generator-UanJW0_V.mjs";
2
2
  import { mkdir, writeFile } from "node:fs/promises";
3
3
  import { dirname, join, relative } from "node:path";
4
- import { Cron } from "@geekmidas/api/constructs";
4
+ import { Cron } from "@geekmidas/constructs/crons";
5
5
 
6
6
  //#region src/generators/CronGenerator.ts
7
7
  var CronGenerator = class extends ConstructGenerator {
@@ -18,7 +18,8 @@ var CronGenerator = class extends ConstructGenerator {
18
18
  name: key,
19
19
  handler: relative(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
20
20
  schedule: construct.schedule || "rate(1 hour)",
21
- timeout: construct.timeout
21
+ timeout: construct.timeout,
22
+ environment: await construct.getEnvironment()
22
23
  });
23
24
  logger.log(`Generated cron handler: ${key}`);
24
25
  }
@@ -34,7 +35,7 @@ var CronGenerator = class extends ConstructGenerator {
34
35
  const importPath = relativePath.replace(/\.ts$/, ".js");
35
36
  const relativeEnvParserPath = relative(dirname(handlerPath), context.envParserPath);
36
37
  const relativeLoggerPath = relative(dirname(handlerPath), context.loggerPath);
37
- const content = `import { AWSScheduledFunction } from '@geekmidas/api/aws-lambda';
38
+ const content = `import { AWSScheduledFunction } from '@geekmidas/constructs/crons';
38
39
  import { ${exportName} } from '${importPath}';
39
40
  import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
40
41
  import ${context.loggerImportPattern} from '${relativeLoggerPath}';
@@ -50,4 +51,4 @@ export const handler = adapter.handler;
50
51
 
51
52
  //#endregion
52
53
  export { CronGenerator };
53
- //# sourceMappingURL=CronGenerator-ClbRcmz_.mjs.map
54
+ //# sourceMappingURL=CronGenerator-DXRfHQcV.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CronGenerator-DXRfHQcV.mjs","names":["context: BuildContext","constructs: GeneratedConstruct<Cron<any, any, any, any>>[]","outputDir: string","options?: GeneratorOptions","cronInfos: CronInfo[]","value: any","sourceFile: string","exportName: string"],"sources":["../src/generators/CronGenerator.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Cron } from '@geekmidas/constructs/crons';\nimport type { BuildContext } from '../build/types';\nimport type { CronInfo } from '../types';\nimport {\n ConstructGenerator,\n type GeneratedConstruct,\n type GeneratorOptions,\n} from './Generator';\n\nexport class CronGenerator extends ConstructGenerator<\n Cron<any, any, any, any>,\n CronInfo[]\n> {\n async build(\n context: BuildContext,\n constructs: GeneratedConstruct<Cron<any, any, any, any>>[],\n outputDir: string,\n options?: GeneratorOptions,\n ): Promise<CronInfo[]> {\n const provider = options?.provider || 'aws-lambda';\n const logger = console;\n const cronInfos: CronInfo[] = [];\n\n if (constructs.length === 0 || provider !== 'aws-lambda') {\n return cronInfos;\n }\n\n // Create crons subdirectory\n const cronsDir = join(outputDir, 'crons');\n await mkdir(cronsDir, { recursive: true });\n\n // Generate cron handlers\n for (const { key, construct, path } of constructs) {\n const handlerFile = await this.generateCronHandler(\n cronsDir,\n path.relative,\n key,\n context,\n );\n\n cronInfos.push({\n name: key,\n handler: relative(process.cwd(), handlerFile).replace(\n /\\.ts$/,\n '.handler',\n ),\n schedule: construct.schedule || 'rate(1 hour)',\n timeout: construct.timeout,\n environment: await construct.getEnvironment(),\n });\n\n logger.log(`Generated cron handler: ${key}`);\n }\n\n return cronInfos;\n }\n\n isConstruct(value: any): value is Cron<any, any, any, any> {\n return Cron.isCron(value);\n }\n\n private async generateCronHandler(\n outputDir: string,\n sourceFile: string,\n exportName: string,\n context: BuildContext,\n ): Promise<string> {\n const handlerFileName = `${exportName}.ts`;\n const handlerPath = join(outputDir, handlerFileName);\n\n const relativePath = relative(dirname(handlerPath), sourceFile);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n const relativeEnvParserPath = relative(\n dirname(handlerPath),\n context.envParserPath,\n );\n const relativeLoggerPath = relative(\n dirname(handlerPath),\n context.loggerPath,\n );\n\n const content = `import { AWSScheduledFunction } from '@geekmidas/constructs/crons';\nimport { ${exportName} } from '${importPath}';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\nimport ${context.loggerImportPattern} from '${relativeLoggerPath}';\n\nconst adapter = new AWSScheduledFunction(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n\n await writeFile(handlerPath, content);\n return handlerPath;\n }\n}\n"],"mappings":";;;;;;AAWA,IAAa,gBAAb,cAAmC,mBAGjC;CACA,MAAM,MACJA,SACAC,YACAC,WACAC,SACqB;EACrB,MAAM,WAAW,SAAS,YAAY;EACtC,MAAM,SAAS;EACf,MAAMC,YAAwB,CAAE;AAEhC,MAAI,WAAW,WAAW,KAAK,aAAa,aAC1C,QAAO;EAIT,MAAM,WAAW,KAAK,WAAW,QAAQ;AACzC,QAAM,MAAM,UAAU,EAAE,WAAW,KAAM,EAAC;AAG1C,OAAK,MAAM,EAAE,KAAK,WAAW,MAAM,IAAI,YAAY;GACjD,MAAM,cAAc,MAAM,KAAK,oBAC7B,UACA,KAAK,UACL,KACA,QACD;AAED,aAAU,KAAK;IACb,MAAM;IACN,SAAS,SAAS,QAAQ,KAAK,EAAE,YAAY,CAAC,QAC5C,SACA,WACD;IACD,UAAU,UAAU,YAAY;IAChC,SAAS,UAAU;IACnB,aAAa,MAAM,UAAU,gBAAgB;GAC9C,EAAC;AAEF,UAAO,KAAK,0BAA0B,IAAI,EAAE;EAC7C;AAED,SAAO;CACR;CAED,YAAYC,OAA+C;AACzD,SAAO,KAAK,OAAO,MAAM;CAC1B;CAED,MAAc,oBACZH,WACAI,YACAC,YACAP,SACiB;EACjB,MAAM,mBAAmB,EAAE,WAAW;EACtC,MAAM,cAAc,KAAK,WAAW,gBAAgB;EAEpD,MAAM,eAAe,SAAS,QAAQ,YAAY,EAAE,WAAW;EAC/D,MAAM,aAAa,aAAa,QAAQ,SAAS,MAAM;EAEvD,MAAM,wBAAwB,SAC5B,QAAQ,YAAY,EACpB,QAAQ,cACT;EACD,MAAM,qBAAqB,SACzB,QAAQ,YAAY,EACpB,QAAQ,WACT;EAED,MAAM,WAAW;WACV,WAAW,WAAW,WAAW;SACnC,QAAQ,uBAAuB,SAAS,sBAAsB;SAC9D,QAAQ,oBAAoB,SAAS,mBAAmB;;sDAEX,WAAW;;;;AAK7D,QAAM,UAAU,aAAa,QAAQ;AACrC,SAAO;CACR;AACF"}
@@ -1,13 +1,13 @@
1
- const require_chunk = require('./chunk-CsX-DzYB.cjs');
2
- const require_Generator = require('./Generator-C3tYSTQY.cjs');
1
+ const require_chunk = require('./chunk-CUT6urMc.cjs');
2
+ const require_Generator = require('./Generator-CDoEXCDg.cjs');
3
3
  const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
4
4
  const node_path = require_chunk.__toESM(require("node:path"));
5
- const __geekmidas_api_server = require_chunk.__toESM(require("@geekmidas/api/server"));
5
+ const __geekmidas_constructs_endpoints = require_chunk.__toESM(require("@geekmidas/constructs/endpoints"));
6
6
 
7
7
  //#region src/generators/EndpointGenerator.ts
8
8
  var EndpointGenerator = class extends require_Generator.ConstructGenerator {
9
9
  isConstruct(value) {
10
- return __geekmidas_api_server.Endpoint.isEndpoint(value);
10
+ return __geekmidas_constructs_endpoints.Endpoint.isEndpoint(value);
11
11
  }
12
12
  async build(context, constructs, outputDir, options) {
13
13
  const provider = options?.provider || "aws-apigatewayv2";
@@ -16,13 +16,14 @@ var EndpointGenerator = class extends require_Generator.ConstructGenerator {
16
16
  const routes = [];
17
17
  if (constructs.length === 0) return routes;
18
18
  if (provider === "server") {
19
- const serverFile = await this.generateServerFile(outputDir, constructs, context, enableOpenApi);
19
+ await this.generateEndpointsFile(outputDir, constructs, context);
20
+ const appFile = await this.generateAppFile(outputDir, context);
20
21
  routes.push({
21
22
  path: "*",
22
23
  method: "ALL",
23
- handler: (0, node_path.relative)(process.cwd(), serverFile)
24
+ handler: (0, node_path.relative)(process.cwd(), appFile)
24
25
  });
25
- logger.log(`Generated server app with ${constructs.length} endpoints${enableOpenApi ? " (OpenAPI enabled)" : ""}`);
26
+ logger.log(`Generated server with ${constructs.length} endpoints${enableOpenApi ? " (OpenAPI enabled)" : ""}`);
26
27
  } else if (provider === "aws-lambda") {
27
28
  const routesDir = (0, node_path.join)(outputDir, "routes");
28
29
  await (0, node_fs_promises.mkdir)(routesDir, { recursive: true });
@@ -31,7 +32,8 @@ var EndpointGenerator = class extends require_Generator.ConstructGenerator {
31
32
  const routeInfo = {
32
33
  path: construct._path,
33
34
  method: construct.method,
34
- handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler")
35
+ handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
36
+ environment: await construct.getEnvironment()
35
37
  };
36
38
  routes.push(routeInfo);
37
39
  logger.log(`Generated handler for ${routeInfo.method} ${routeInfo.path}`);
@@ -41,7 +43,8 @@ var EndpointGenerator = class extends require_Generator.ConstructGenerator {
41
43
  const routeInfo = {
42
44
  path: construct._path,
43
45
  method: construct.method,
44
- handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler")
46
+ handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
47
+ environment: await construct.getEnvironment()
45
48
  };
46
49
  routes.push(routeInfo);
47
50
  logger.log(`Generated handler for ${routeInfo.method} ${routeInfo.path}`);
@@ -70,35 +73,36 @@ var EndpointGenerator = class extends require_Generator.ConstructGenerator {
70
73
  await (0, node_fs_promises.writeFile)(handlerPath, content);
71
74
  return handlerPath;
72
75
  }
73
- async generateServerFile(outputDir, endpoints, context, enableOpenApi) {
74
- const serverFileName = "app.ts";
75
- const serverPath = (0, node_path.join)(outputDir, serverFileName);
76
+ async generateEndpointsFile(outputDir, endpoints, context) {
77
+ const endpointsFileName = "endpoints.ts";
78
+ const endpointsPath = (0, node_path.join)(outputDir, endpointsFileName);
76
79
  const importsByFile = /* @__PURE__ */ new Map();
77
80
  for (const { path, key } of endpoints) {
78
- const relativePath = (0, node_path.relative)((0, node_path.dirname)(serverPath), path.relative);
81
+ const relativePath = (0, node_path.relative)((0, node_path.dirname)(endpointsPath), path.relative);
79
82
  const importPath = relativePath.replace(/\.ts$/, ".js");
80
83
  if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
81
84
  importsByFile.get(importPath).push(key);
82
85
  }
83
- const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(serverPath), context.envParserPath);
84
- const relativeLoggerPath = (0, node_path.relative)((0, node_path.dirname)(serverPath), context.loggerPath);
85
86
  const imports = Array.from(importsByFile.entries()).map(([importPath, exports$1]) => `import { ${exports$1.join(", ")} } from '${importPath}';`).join("\n");
86
87
  const allExportNames = endpoints.map(({ key }) => key);
87
- const content = `import { HonoEndpoint } from '@geekmidas/api/hono';
88
- import { Endpoint } from '@geekmidas/api/server';
89
- import { ServiceDiscovery } from '@geekmidas/api/services';
90
- import { Hono } from 'hono';
91
- import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
92
- import ${context.loggerImportPattern} from '${relativeLoggerPath}';
88
+ const content = `import type { EnvironmentParser } from '@geekmidas/envkit';
89
+ import type { Logger } from '@geekmidas/logger';
90
+ import { HonoEndpoint } from '@geekmidas/constructs/hono';
91
+ import { Endpoint } from '@geekmidas/constructs/endpoints';
92
+ import { ServiceDiscovery } from '@geekmidas/services';
93
+ import type { Hono } from 'hono';
93
94
  ${imports}
94
95
 
95
- export function createApp(app?: Hono, enableOpenApi: boolean = ${enableOpenApi}): Hono {
96
- const honoApp = app || new Hono();
97
-
98
- const endpoints: Endpoint<any, any, any, any, any, any, any>[] = [
99
- ${allExportNames.join(",\n ")}
100
- ];
96
+ const endpoints: Endpoint<any, any, any, any, any, any, any, any>[] = [
97
+ ${allExportNames.join(",\n ")}
98
+ ];
101
99
 
100
+ export function setupEndpoints(
101
+ app: Hono,
102
+ envParser: EnvironmentParser<any>,
103
+ logger: Logger,
104
+ enableOpenApi: boolean = true,
105
+ ): void {
102
106
  const serviceDiscovery = ServiceDiscovery.getInstance(
103
107
  logger,
104
108
  envParser
@@ -114,19 +118,115 @@ export function createApp(app?: Hono, enableOpenApi: boolean = ${enableOpenApi})
114
118
  }
115
119
  } : { docsPath: false };
116
120
 
117
- HonoEndpoint.addRoutes(endpoints, serviceDiscovery, honoApp, openApiOptions);
121
+ HonoEndpoint.addRoutes(endpoints, serviceDiscovery, app, openApiOptions);
122
+ }
123
+ `;
124
+ await (0, node_fs_promises.writeFile)(endpointsPath, content);
125
+ return endpointsPath;
126
+ }
127
+ async generateAppFile(outputDir, context) {
128
+ const appFileName = "app.ts";
129
+ const appPath = (0, node_path.join)(outputDir, appFileName);
130
+ const relativeLoggerPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.loggerPath);
131
+ const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.envParserPath);
132
+ const content = `/**
133
+ * Generated server application
134
+ *
135
+ * ⚠️ WARNING: This is for LOCAL DEVELOPMENT ONLY
136
+ * The subscriber polling mechanism is not production-ready.
137
+ * For production, use AWS Lambda with SQS/SNS event sources.
138
+ */
139
+ import { Hono } from 'hono';
140
+ import type { Hono as HonoType } from 'hono';
141
+ import { setupEndpoints } from './endpoints.js';
142
+ import { setupSubscribers } from './subscribers.js';
143
+ import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
144
+ import ${context.loggerImportPattern} from '${relativeLoggerPath}';
118
145
 
119
- return honoApp;
146
+ export interface ServerApp {
147
+ app: HonoType;
148
+ start: (options?: {
149
+ port?: number;
150
+ serve: (app: HonoType, port: number) => void | Promise<void>;
151
+ }) => Promise<void>;
152
+ }
153
+
154
+ /**
155
+ * Create and configure the Hono application
156
+ *
157
+ * @param app - Optional Hono app instance to configure (creates new one if not provided)
158
+ * @param enableOpenApi - Enable OpenAPI documentation (default: true)
159
+ * @returns Server app with configured Hono app and start function
160
+ *
161
+ * @example
162
+ * // With Bun
163
+ * import { createApp } from './.gkm/server/app.js';
164
+ *
165
+ * const { app, start } = createApp();
166
+ *
167
+ * await start({
168
+ * port: 3000,
169
+ * serve: (app, port) => {
170
+ * Bun.serve({ port, fetch: app.fetch });
171
+ * }
172
+ * });
173
+ *
174
+ * @example
175
+ * // With Node.js (using @hono/node-server)
176
+ * import { serve } from '@hono/node-server';
177
+ * import { createApp } from './.gkm/server/app.js';
178
+ *
179
+ * const { app, start } = createApp();
180
+ *
181
+ * await start({
182
+ * port: 3000,
183
+ * serve: (app, port) => {
184
+ * serve({ fetch: app.fetch, port });
185
+ * }
186
+ * });
187
+ */
188
+ export function createApp(app?: HonoType, enableOpenApi: boolean = true): ServerApp {
189
+ const honoApp = app || new Hono();
190
+
191
+ // Setup HTTP endpoints
192
+ setupEndpoints(honoApp, envParser, logger, enableOpenApi);
193
+
194
+ return {
195
+ app: honoApp,
196
+ async start(options) {
197
+ if (!options?.serve) {
198
+ throw new Error(
199
+ 'serve function is required. Pass a serve function for your runtime:\\n' +
200
+ ' - Bun: (app, port) => Bun.serve({ port, fetch: app.fetch })\\n' +
201
+ ' - Node: (app, port) => serve({ fetch: app.fetch, port })'
202
+ );
203
+ }
204
+
205
+ const port = options.port ?? 3000;
206
+
207
+ // Start subscribers in background (non-blocking, local development only)
208
+ await setupSubscribers(envParser, logger).catch((error) => {
209
+ logger.error({ error }, 'Failed to start subscribers');
210
+ });
211
+
212
+ logger.info({ port }, 'Starting server');
213
+
214
+ // Start HTTP server using provided serve function
215
+ await options.serve(honoApp, port);
216
+
217
+ logger.info({ port }, 'Server started');
218
+ }
219
+ };
120
220
  }
121
221
 
122
222
  // Default export for convenience
123
223
  export default createApp;
124
224
  `;
125
- await (0, node_fs_promises.writeFile)(serverPath, content);
126
- return serverPath;
225
+ await (0, node_fs_promises.writeFile)(appPath, content);
226
+ return appPath;
127
227
  }
128
228
  generateAWSApiGatewayV1Handler(importPath, exportName, envParserPath, envParserImportPattern) {
129
- return `import { AmazonApiGatewayV1Endpoint } from '@geekmidas/api/aws-apigateway';
229
+ return `import { AmazonApiGatewayV1Endpoint } from '@geekmidas/constructs/aws';
130
230
  import { ${exportName} } from '${importPath}';
131
231
  import ${envParserImportPattern} from '${envParserPath}';
132
232
 
@@ -136,7 +236,7 @@ export const handler = adapter.handler;
136
236
  `;
137
237
  }
138
238
  generateAWSApiGatewayV2Handler(importPath, exportName, envParserPath, envParserImportPattern) {
139
- return `import { AmazonApiGatewayV2Endpoint } from '@geekmidas/api/aws-apigateway';
239
+ return `import { AmazonApiGatewayV2Endpoint } from '@geekmidas/constructs/aws';
140
240
  import { ${exportName} } from '${importPath}';
141
241
  import ${envParserImportPattern} from '${envParserPath}';
142
242
 
@@ -161,4 +261,4 @@ Object.defineProperty(exports, 'EndpointGenerator', {
161
261
  return EndpointGenerator;
162
262
  }
163
263
  });
164
- //# sourceMappingURL=EndpointGenerator-Dj7AumHi.cjs.map
264
+ //# sourceMappingURL=EndpointGenerator-BbGrDiCP.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EndpointGenerator-BbGrDiCP.cjs","names":["ConstructGenerator","value: any","context: BuildContext","constructs: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","outputDir: string","options?: GeneratorOptions","routes: RouteInfo[]","routeInfo: RouteInfo","sourceFile: string","exportName: string","provider: LegacyProvider","_endpoint: Endpoint<any, any, any, any, any, any>","content: string","endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[]","exports","importPath: string","envParserPath: string","envParserImportPattern: string"],"sources":["../src/generators/EndpointGenerator.ts"],"sourcesContent":["import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative } from 'node:path';\nimport { Endpoint } from '@geekmidas/constructs/endpoints';\nimport type { BuildContext } from '../build/types';\nimport type { LegacyProvider, RouteInfo } from '../types';\nimport {\n ConstructGenerator,\n type GeneratedConstruct,\n type GeneratorOptions,\n} from './Generator';\n\nexport class EndpointGenerator extends ConstructGenerator<\n Endpoint<any, any, any, any, any, any>,\n RouteInfo[]\n> {\n isConstruct(value: any): value is Endpoint<any, any, any, any, any, any> {\n return Endpoint.isEndpoint(value);\n }\n\n async build(\n context: BuildContext,\n constructs: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n outputDir: string,\n options?: GeneratorOptions,\n ): Promise<RouteInfo[]> {\n const provider = options?.provider || 'aws-apigatewayv2';\n const enableOpenApi = options?.enableOpenApi || false;\n const logger = console;\n const routes: RouteInfo[] = [];\n\n if (constructs.length === 0) {\n return routes;\n }\n\n if (provider === 'server') {\n // Generate endpoints.ts and app.ts\n await this.generateEndpointsFile(outputDir, constructs, context);\n const appFile = await this.generateAppFile(outputDir, context);\n\n routes.push({\n path: '*',\n method: 'ALL',\n handler: relative(process.cwd(), appFile),\n });\n\n logger.log(\n `Generated server with ${constructs.length} endpoints${enableOpenApi ? ' (OpenAPI enabled)' : ''}`,\n );\n } else if (provider === 'aws-lambda') {\n // For aws-lambda, create routes subdirectory\n const routesDir = join(outputDir, 'routes');\n await mkdir(routesDir, { recursive: true });\n\n // Generate individual handlers for API Gateway routes\n for (const { key, construct, path } of constructs) {\n const handlerFile = await this.generateHandlerFile(\n routesDir,\n path.relative,\n key,\n 'aws-apigatewayv2',\n construct,\n context,\n );\n\n const routeInfo: RouteInfo = {\n path: construct._path,\n method: construct.method,\n handler: relative(process.cwd(), handlerFile).replace(\n /\\.ts$/,\n '.handler',\n ),\n environment: await construct.getEnvironment(),\n };\n\n routes.push(routeInfo);\n logger.log(\n `Generated handler for ${routeInfo.method} ${routeInfo.path}`,\n );\n }\n } else {\n // Generate individual handler files for AWS API Gateway providers\n for (const { key, construct, path } of constructs) {\n const handlerFile = await this.generateHandlerFile(\n outputDir,\n path.relative,\n key,\n provider,\n construct,\n context,\n );\n\n const routeInfo: RouteInfo = {\n path: construct._path,\n method: construct.method,\n handler: relative(process.cwd(), handlerFile).replace(\n /\\.ts$/,\n '.handler',\n ),\n environment: await construct.getEnvironment(),\n };\n\n routes.push(routeInfo);\n logger.log(\n `Generated handler for ${routeInfo.method} ${routeInfo.path}`,\n );\n }\n }\n\n return routes;\n }\n\n private async generateHandlerFile(\n outputDir: string,\n sourceFile: string,\n exportName: string,\n provider: LegacyProvider,\n _endpoint: Endpoint<any, any, any, any, any, any>,\n context: BuildContext,\n ): Promise<string> {\n const handlerFileName = `${exportName}.ts`;\n const handlerPath = join(outputDir, handlerFileName);\n\n const relativePath = relative(dirname(handlerPath), sourceFile);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n const relativeEnvParserPath = relative(\n dirname(handlerPath),\n context.envParserPath,\n );\n\n let content: string;\n\n switch (provider) {\n case 'aws-apigatewayv1':\n content = this.generateAWSApiGatewayV1Handler(\n importPath,\n exportName,\n relativeEnvParserPath,\n context.envParserImportPattern,\n );\n break;\n case 'aws-apigatewayv2':\n content = this.generateAWSApiGatewayV2Handler(\n importPath,\n exportName,\n relativeEnvParserPath,\n context.envParserImportPattern,\n );\n break;\n case 'server':\n content = this.generateServerHandler(importPath, exportName);\n break;\n default:\n throw new Error(`Unsupported provider: ${provider}`);\n }\n\n await writeFile(handlerPath, content);\n return handlerPath;\n }\n\n private async generateEndpointsFile(\n outputDir: string,\n endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n context: BuildContext,\n ): Promise<string> {\n const endpointsFileName = 'endpoints.ts';\n const endpointsPath = join(outputDir, endpointsFileName);\n\n // Group imports by file\n const importsByFile = new Map<string, string[]>();\n\n for (const { path, key } of endpoints) {\n const relativePath = relative(dirname(endpointsPath), path.relative);\n const importPath = relativePath.replace(/\\.ts$/, '.js');\n\n if (!importsByFile.has(importPath)) {\n importsByFile.set(importPath, []);\n }\n importsByFile.get(importPath)!.push(key);\n }\n\n // Generate import statements\n const imports = Array.from(importsByFile.entries())\n .map(\n ([importPath, exports]) =>\n `import { ${exports.join(', ')} } from '${importPath}';`,\n )\n .join('\\n');\n\n const allExportNames = endpoints.map(({ key }) => key);\n\n const content = `import type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { Logger } from '@geekmidas/logger';\nimport { HonoEndpoint } from '@geekmidas/constructs/hono';\nimport { Endpoint } from '@geekmidas/constructs/endpoints';\nimport { ServiceDiscovery } from '@geekmidas/services';\nimport type { Hono } from 'hono';\n${imports}\n\nconst endpoints: Endpoint<any, any, any, any, any, any, any, any>[] = [\n ${allExportNames.join(',\\n ')}\n];\n\nexport function setupEndpoints(\n app: Hono,\n envParser: EnvironmentParser<any>,\n logger: Logger,\n enableOpenApi: boolean = true,\n): void {\n const serviceDiscovery = ServiceDiscovery.getInstance(\n logger,\n envParser\n );\n\n // Configure OpenAPI options based on enableOpenApi flag\n const openApiOptions: any = enableOpenApi ? {\n docsPath: '/docs',\n openApiOptions: {\n title: 'API Documentation',\n version: '1.0.0',\n description: 'Generated API documentation'\n }\n } : { docsPath: false };\n\n HonoEndpoint.addRoutes(endpoints, serviceDiscovery, app, openApiOptions);\n}\n`;\n\n await writeFile(endpointsPath, content);\n\n return endpointsPath;\n }\n\n private async generateAppFile(\n outputDir: string,\n context: BuildContext,\n ): Promise<string> {\n const appFileName = 'app.ts';\n const appPath = join(outputDir, appFileName);\n\n const relativeLoggerPath = relative(dirname(appPath), context.loggerPath);\n\n const relativeEnvParserPath = relative(\n dirname(appPath),\n context.envParserPath,\n );\n\n const content = `/**\n * Generated server application\n *\n * ⚠️ WARNING: This is for LOCAL DEVELOPMENT ONLY\n * The subscriber polling mechanism is not production-ready.\n * For production, use AWS Lambda with SQS/SNS event sources.\n */\nimport { Hono } from 'hono';\nimport type { Hono as HonoType } from 'hono';\nimport { setupEndpoints } from './endpoints.js';\nimport { setupSubscribers } from './subscribers.js';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\nimport ${context.loggerImportPattern} from '${relativeLoggerPath}';\n\nexport interface ServerApp {\n app: HonoType;\n start: (options?: {\n port?: number;\n serve: (app: HonoType, port: number) => void | Promise<void>;\n }) => Promise<void>;\n}\n\n/**\n * Create and configure the Hono application\n *\n * @param app - Optional Hono app instance to configure (creates new one if not provided)\n * @param enableOpenApi - Enable OpenAPI documentation (default: true)\n * @returns Server app with configured Hono app and start function\n *\n * @example\n * // With Bun\n * import { createApp } from './.gkm/server/app.js';\n *\n * const { app, start } = createApp();\n *\n * await start({\n * port: 3000,\n * serve: (app, port) => {\n * Bun.serve({ port, fetch: app.fetch });\n * }\n * });\n *\n * @example\n * // With Node.js (using @hono/node-server)\n * import { serve } from '@hono/node-server';\n * import { createApp } from './.gkm/server/app.js';\n *\n * const { app, start } = createApp();\n *\n * await start({\n * port: 3000,\n * serve: (app, port) => {\n * serve({ fetch: app.fetch, port });\n * }\n * });\n */\nexport function createApp(app?: HonoType, enableOpenApi: boolean = true): ServerApp {\n const honoApp = app || new Hono();\n\n // Setup HTTP endpoints\n setupEndpoints(honoApp, envParser, logger, enableOpenApi);\n\n return {\n app: honoApp,\n async start(options) {\n if (!options?.serve) {\n throw new Error(\n 'serve function is required. Pass a serve function for your runtime:\\\\n' +\n ' - Bun: (app, port) => Bun.serve({ port, fetch: app.fetch })\\\\n' +\n ' - Node: (app, port) => serve({ fetch: app.fetch, port })'\n );\n }\n\n const port = options.port ?? 3000;\n\n // Start subscribers in background (non-blocking, local development only)\n await setupSubscribers(envParser, logger).catch((error) => {\n logger.error({ error }, 'Failed to start subscribers');\n });\n\n logger.info({ port }, 'Starting server');\n\n // Start HTTP server using provided serve function\n await options.serve(honoApp, port);\n\n logger.info({ port }, 'Server started');\n }\n };\n}\n\n// Default export for convenience\nexport default createApp;\n`;\n\n await writeFile(appPath, content);\n\n return appPath;\n }\n\n private generateAWSApiGatewayV1Handler(\n importPath: string,\n exportName: string,\n envParserPath: string,\n envParserImportPattern: string,\n ): string {\n return `import { AmazonApiGatewayV1Endpoint } from '@geekmidas/constructs/aws';\nimport { ${exportName} } from '${importPath}';\nimport ${envParserImportPattern} from '${envParserPath}';\n\nconst adapter = new AmazonApiGatewayV1Endpoint(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n }\n\n private generateAWSApiGatewayV2Handler(\n importPath: string,\n exportName: string,\n envParserPath: string,\n envParserImportPattern: string,\n ): string {\n return `import { AmazonApiGatewayV2Endpoint } from '@geekmidas/constructs/aws';\nimport { ${exportName} } from '${importPath}';\nimport ${envParserImportPattern} from '${envParserPath}';\n\nconst adapter = new AmazonApiGatewayV2Endpoint(envParser, ${exportName});\n\nexport const handler = adapter.handler;\n`;\n }\n\n private generateServerHandler(\n importPath: string,\n exportName: string,\n ): string {\n return `import { ${exportName} } from '${importPath}';\n\n// Server handler - implement based on your server framework\nexport const handler = ${exportName};\n`;\n }\n}\n"],"mappings":"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"}