@geekmidas/cli 0.0.26 → 0.1.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 (142) hide show
  1. package/FUNCTION_CRON_SUPPORT.md +266 -0
  2. package/README.md +21 -4
  3. package/dist/CronGenerator-ClbRcmz_.mjs +53 -0
  4. package/dist/CronGenerator-ClbRcmz_.mjs.map +1 -0
  5. package/dist/CronGenerator-Ctl4USy4.cjs +59 -0
  6. package/dist/CronGenerator-Ctl4USy4.cjs.map +1 -0
  7. package/dist/EndpointGenerator-Dj7AumHi.cjs +164 -0
  8. package/dist/EndpointGenerator-Dj7AumHi.cjs.map +1 -0
  9. package/dist/EndpointGenerator-uBA1ixUw.mjs +158 -0
  10. package/dist/EndpointGenerator-uBA1ixUw.mjs.map +1 -0
  11. package/dist/FunctionGenerator-DN681IUn.cjs +58 -0
  12. package/dist/FunctionGenerator-DN681IUn.cjs.map +1 -0
  13. package/dist/FunctionGenerator-crAa-JC7.mjs +52 -0
  14. package/dist/FunctionGenerator-crAa-JC7.mjs.map +1 -0
  15. package/dist/Generator-C3tYSTQY.cjs +47 -0
  16. package/dist/Generator-C3tYSTQY.cjs.map +1 -0
  17. package/dist/Generator-CDt4pB3W.mjs +41 -0
  18. package/dist/Generator-CDt4pB3W.mjs.map +1 -0
  19. package/dist/__tests__/config.spec.cjs +98 -0
  20. package/dist/__tests__/config.spec.cjs.map +1 -0
  21. package/dist/__tests__/config.spec.mjs +97 -0
  22. package/dist/__tests__/config.spec.mjs.map +1 -0
  23. package/dist/__tests__/test-helpers.cjs +14 -0
  24. package/dist/__tests__/test-helpers.mjs +4 -0
  25. package/dist/build/__tests__/index-new.spec.cjs +286 -0
  26. package/dist/build/__tests__/index-new.spec.cjs.map +1 -0
  27. package/dist/build/__tests__/index-new.spec.mjs +285 -0
  28. package/dist/build/__tests__/index-new.spec.mjs.map +1 -0
  29. package/dist/build/index.cjs +11 -0
  30. package/dist/build/index.mjs +11 -0
  31. package/dist/build/manifests.cjs +3 -0
  32. package/dist/build/manifests.mjs +3 -0
  33. package/dist/build/providerResolver.cjs +5 -0
  34. package/dist/build/providerResolver.mjs +3 -0
  35. package/dist/build/types.cjs +0 -0
  36. package/dist/build/types.mjs +0 -0
  37. package/dist/build-BZdwxCLW.mjs +64 -0
  38. package/dist/build-BZdwxCLW.mjs.map +1 -0
  39. package/dist/build-BfQFnU5-.cjs +70 -0
  40. package/dist/build-BfQFnU5-.cjs.map +1 -0
  41. package/dist/{chunk-CUT6urMc.cjs → chunk-CsX-DzYB.cjs} +12 -0
  42. package/dist/config-CXxYmz_o.mjs +30 -0
  43. package/dist/config-CXxYmz_o.mjs.map +1 -0
  44. package/dist/config-RcNESK0T.cjs +36 -0
  45. package/dist/config-RcNESK0T.cjs.map +1 -0
  46. package/dist/config.cjs +1 -1
  47. package/dist/config.mjs +1 -1
  48. package/dist/esm-9eeZntth.mjs +3777 -0
  49. package/dist/esm-9eeZntth.mjs.map +1 -0
  50. package/dist/esm-Crmo4h9t.cjs +4392 -0
  51. package/dist/esm-Crmo4h9t.cjs.map +1 -0
  52. package/dist/esm-CsJbr7gi.mjs +3 -0
  53. package/dist/esm-w09tAC4l.cjs +8 -0
  54. package/dist/generators/CronGenerator.cjs +4 -0
  55. package/dist/generators/CronGenerator.mjs +4 -0
  56. package/dist/generators/EndpointGenerator.cjs +4 -0
  57. package/dist/generators/EndpointGenerator.mjs +4 -0
  58. package/dist/generators/FunctionGenerator.cjs +4 -0
  59. package/dist/generators/FunctionGenerator.mjs +4 -0
  60. package/dist/generators/Generator.cjs +3 -0
  61. package/dist/generators/Generator.mjs +3 -0
  62. package/dist/generators/__tests__/CronGenerator.spec.cjs +216 -0
  63. package/dist/generators/__tests__/CronGenerator.spec.cjs.map +1 -0
  64. package/dist/generators/__tests__/CronGenerator.spec.mjs +215 -0
  65. package/dist/generators/__tests__/CronGenerator.spec.mjs.map +1 -0
  66. package/dist/generators/__tests__/EndpointGenerator.spec.cjs +182 -0
  67. package/dist/generators/__tests__/EndpointGenerator.spec.cjs.map +1 -0
  68. package/dist/generators/__tests__/EndpointGenerator.spec.mjs +181 -0
  69. package/dist/generators/__tests__/EndpointGenerator.spec.mjs.map +1 -0
  70. package/dist/generators/__tests__/FunctionGenerator.spec.cjs +152 -0
  71. package/dist/generators/__tests__/FunctionGenerator.spec.cjs.map +1 -0
  72. package/dist/generators/__tests__/FunctionGenerator.spec.mjs +151 -0
  73. package/dist/generators/__tests__/FunctionGenerator.spec.mjs.map +1 -0
  74. package/dist/generators/index.cjs +10 -0
  75. package/dist/generators/index.mjs +7 -0
  76. package/dist/generators-CsLujGXs.mjs +0 -0
  77. package/dist/generators-_pY7sHy1.cjs +0 -0
  78. package/dist/index.cjs +68 -26
  79. package/dist/index.cjs.map +1 -0
  80. package/dist/index.mjs +67 -25
  81. package/dist/index.mjs.map +1 -0
  82. package/dist/manifests-BTtfDMX8.cjs +26 -0
  83. package/dist/manifests-BTtfDMX8.cjs.map +1 -0
  84. package/dist/manifests-HX4z4kkz.mjs +20 -0
  85. package/dist/manifests-HX4z4kkz.mjs.map +1 -0
  86. package/dist/{openapi-CksVdkh2.mjs → openapi-BivnatiC.mjs} +8 -6
  87. package/dist/openapi-BivnatiC.mjs.map +1 -0
  88. package/dist/{openapi-D4QQJUPY.cjs → openapi-DW-qF3oW.cjs} +9 -7
  89. package/dist/openapi-DW-qF3oW.cjs.map +1 -0
  90. package/dist/{openapi-react-query-C1JLYUOs.cjs → openapi-react-query-J0BzBHhN.cjs} +4 -3
  91. package/dist/openapi-react-query-J0BzBHhN.cjs.map +1 -0
  92. package/dist/{openapi-react-query-DpT3XHFC.mjs → openapi-react-query-lgS7AVEz.mjs} +3 -2
  93. package/dist/openapi-react-query-lgS7AVEz.mjs.map +1 -0
  94. package/dist/openapi-react-query.cjs +1 -1
  95. package/dist/openapi-react-query.mjs +1 -1
  96. package/dist/openapi.cjs +4 -3
  97. package/dist/openapi.mjs +4 -3
  98. package/dist/providerResolver-B_TjNF0_.mjs +96 -0
  99. package/dist/providerResolver-B_TjNF0_.mjs.map +1 -0
  100. package/dist/providerResolver-Cs-0YCaP.cjs +114 -0
  101. package/dist/providerResolver-Cs-0YCaP.cjs.map +1 -0
  102. package/dist/test-helpers-ARd8GDgx.cjs +199 -0
  103. package/dist/test-helpers-ARd8GDgx.cjs.map +1 -0
  104. package/dist/test-helpers-DdVBk23F.mjs +133 -0
  105. package/dist/test-helpers-DdVBk23F.mjs.map +1 -0
  106. package/examples/cron-example.ts +45 -0
  107. package/examples/function-example.ts +40 -0
  108. package/examples/gkm.config.json +22 -0
  109. package/examples/gkm.minimal.config.json +7 -0
  110. package/examples/gkm.production.config.json +27 -0
  111. package/package.json +35 -14
  112. package/src/__tests__/config.spec.ts +110 -0
  113. package/src/__tests__/test-helpers.ts +178 -0
  114. package/src/build/__tests__/index-new.spec.ts +578 -0
  115. package/src/build/index.ts +136 -0
  116. package/src/build/manifests.ts +32 -0
  117. package/src/build/providerResolver.ts +184 -0
  118. package/src/build/types.ts +37 -0
  119. package/src/config.ts +14 -6
  120. package/src/generators/CronGenerator.ts +97 -0
  121. package/src/generators/EndpointGenerator.ts +290 -0
  122. package/src/generators/FunctionGenerator.ts +96 -0
  123. package/src/generators/Generator.ts +95 -0
  124. package/src/generators/__tests__/CronGenerator.spec.ts +445 -0
  125. package/src/generators/__tests__/EndpointGenerator.spec.ts +372 -0
  126. package/src/generators/__tests__/FunctionGenerator.spec.ts +257 -0
  127. package/src/generators/index.ts +8 -0
  128. package/src/index.ts +57 -22
  129. package/src/openapi.ts +4 -3
  130. package/src/types.ts +73 -2
  131. package/dist/build-BTggTCYL.cjs +0 -176
  132. package/dist/build-Ca4P6_lY.mjs +0 -170
  133. package/dist/build.cjs +0 -5
  134. package/dist/build.mjs +0 -5
  135. package/dist/config-BNqUMsvc.cjs +0 -24
  136. package/dist/config-BciAdY6_.mjs +0 -18
  137. package/dist/loadEndpoints-BBIavB9h.cjs +0 -37
  138. package/dist/loadEndpoints-DAZ53Og2.mjs +0 -31
  139. package/dist/loadEndpoints.cjs +0 -3
  140. package/dist/loadEndpoints.mjs +0 -3
  141. package/src/build.ts +0 -305
  142. package/src/loadEndpoints.ts +0 -48
@@ -0,0 +1,266 @@
1
+ # Function and Cron Support in @geekmidas/cli
2
+
3
+ ## Overview
4
+
5
+ The @geekmidas/cli now supports building AWS Lambda functions and scheduled crons in addition to HTTP endpoints. This enables you to create a complete serverless application with:
6
+
7
+ - **HTTP Endpoints**: RESTful APIs via API Gateway
8
+ - **Functions**: Event-driven Lambda functions
9
+ - **Crons**: Scheduled Lambda functions with cron or rate expressions
10
+
11
+ ## Configuration
12
+
13
+ ### Simple Configuration
14
+
15
+ For basic usage, just specify the paths:
16
+
17
+ ```json
18
+ {
19
+ "routes": "./src/endpoints/**/*.ts",
20
+ "functions": "./src/functions/**/*.ts",
21
+ "crons": "./src/crons/**/*.ts",
22
+ "envParser": "./src/env.ts#envParser",
23
+ "logger": "./src/logger.ts#logger"
24
+ }
25
+ ```
26
+
27
+ ### Advanced Configuration
28
+
29
+ For fine-grained control over providers:
30
+
31
+ ```json
32
+ {
33
+ "routes": "./src/endpoints/**/*.ts",
34
+ "functions": "./src/functions/**/*.ts",
35
+ "crons": "./src/crons/**/*.ts",
36
+ "envParser": "./src/env.ts#envParser",
37
+ "logger": "./src/logger.ts#logger",
38
+ "providers": {
39
+ "aws": {
40
+ "apiGateway": {
41
+ "v1": false,
42
+ "v2": true
43
+ },
44
+ "lambda": {
45
+ "functions": true,
46
+ "crons": true
47
+ }
48
+ },
49
+ "server": {
50
+ "enableOpenApi": true
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ ## Writing Functions
57
+
58
+ Functions are standalone Lambda handlers that can be triggered by various AWS services:
59
+
60
+ ```typescript
61
+ import { f } from '@geekmidas/api/function';
62
+ import { z } from 'zod';
63
+
64
+ export const processOrder = f
65
+ .input(
66
+ z.object({
67
+ orderId: z.string(),
68
+ items: z.array(z.object({
69
+ id: z.string(),
70
+ quantity: z.number()
71
+ }))
72
+ })
73
+ )
74
+ .output(
75
+ z.object({
76
+ orderId: z.string(),
77
+ status: z.enum(['processing', 'completed', 'failed'])
78
+ })
79
+ )
80
+ .timeout(300000) // 5 minutes
81
+ .handle(async ({ input, services, logger }) => {
82
+ logger.info(`Processing order ${input.orderId}`);
83
+
84
+ // Your business logic here
85
+
86
+ return {
87
+ orderId: input.orderId,
88
+ status: 'completed'
89
+ };
90
+ });
91
+ ```
92
+
93
+ ## Writing Crons
94
+
95
+ Crons are scheduled functions that run on a regular basis:
96
+
97
+ ```typescript
98
+ import { cron } from '@geekmidas/api/cron';
99
+
100
+ // Using cron expression (runs daily at 9 AM UTC)
101
+ export const dailyReport = cron
102
+ .schedule('cron(0 9 * * ? *)')
103
+ .timeout(600000) // 10 minutes
104
+ .handle(async ({ services, logger }) => {
105
+ logger.info('Generating daily report');
106
+
107
+ // Your scheduled logic here
108
+
109
+ return { success: true };
110
+ });
111
+
112
+ // Using rate expression (runs every hour)
113
+ export const hourlyCleanup = cron
114
+ .schedule('rate(1 hour)')
115
+ .handle(async ({ services, logger }) => {
116
+ logger.info('Running cleanup');
117
+
118
+ // Your cleanup logic here
119
+
120
+ return { itemsCleaned: 42 };
121
+ });
122
+ ```
123
+
124
+ ### Schedule Expressions
125
+
126
+ - **Cron expressions**: `cron(Minutes Hours Day Month Weekday Year)`
127
+ - Example: `cron(0 9 * * ? *)` - Daily at 9 AM UTC
128
+ - Example: `cron(*/5 * * * ? *)` - Every 5 minutes
129
+
130
+ - **Rate expressions**: `rate(Value Unit)`
131
+ - Example: `rate(5 minutes)`
132
+ - Example: `rate(1 hour)`
133
+ - Example: `rate(7 days)`
134
+
135
+ ## Building
136
+
137
+ ### New Simplified Commands
138
+
139
+ ```bash
140
+ # Build for AWS (uses config to determine what to build)
141
+ gkm build --provider aws
142
+
143
+ # Build for local server development
144
+ gkm build --provider server
145
+
146
+ # Build everything configured in gkm.config.json
147
+ gkm build
148
+ ```
149
+
150
+ ### Legacy Commands (Deprecated)
151
+
152
+ ```bash
153
+ # Still supported but deprecated
154
+ gkm build --providers aws-lambda,aws-apigatewayv2
155
+ ```
156
+
157
+ This generates:
158
+
159
+ ```
160
+ .gkm/
161
+ └── aws-lambda/
162
+ ├── routes/
163
+ │ └── [endpoint handlers]
164
+ ├── functions/
165
+ │ └── [function handlers]
166
+ ├── crons/
167
+ │ └── [cron handlers]
168
+ └── manifest.json
169
+ ```
170
+
171
+ ## Generated Manifest
172
+
173
+ ### manifest.json
174
+ ```json
175
+ {
176
+ "routes": [
177
+ {
178
+ "path": "/api/health",
179
+ "method": "GET",
180
+ "handler": ".gkm/aws-lambda/routes/health.handler"
181
+ }
182
+ ],
183
+ "functions": [
184
+ {
185
+ "name": "processOrder",
186
+ "handler": ".gkm/aws-lambda/functions/processOrder.handler",
187
+ "timeout": 300000,
188
+ "memorySize": 256
189
+ }
190
+ ],
191
+ "crons": [
192
+ {
193
+ "name": "dailyReport",
194
+ "handler": ".gkm/aws-lambda/crons/dailyReport.handler",
195
+ "schedule": "cron(0 9 * * ? *)",
196
+ "timeout": 600000,
197
+ "memorySize": 256
198
+ }
199
+ ]
200
+ }
201
+ ```
202
+
203
+ ## Infrastructure Integration
204
+
205
+ The generated manifests can be consumed by infrastructure tools like AWS CDK or Terraform to deploy your functions:
206
+
207
+ ```typescript
208
+ // AWS CDK Example
209
+ import { Function, Runtime, Code } from 'aws-cdk-lib/aws-lambda';
210
+ import { Rule, Schedule } from 'aws-cdk-lib/aws-events';
211
+ import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets';
212
+ import manifest from './.gkm/aws-lambda/manifest.json';
213
+
214
+ // Deploy functions
215
+ for (const fn of manifest.functions) {
216
+ new Function(stack, fn.name, {
217
+ runtime: Runtime.NODEJS_20_X,
218
+ handler: fn.handler,
219
+ code: Code.fromAsset('.'),
220
+ timeout: Duration.millis(fn.timeout || 30000),
221
+ memorySize: fn.memorySize || 256
222
+ });
223
+ }
224
+
225
+ // Deploy crons
226
+ for (const cron of manifest.crons) {
227
+ const fn = new Function(stack, cron.name, {
228
+ runtime: Runtime.NODEJS_20_X,
229
+ handler: cron.handler,
230
+ code: Code.fromAsset('.'),
231
+ timeout: Duration.millis(cron.timeout || 30000),
232
+ memorySize: cron.memorySize || 256
233
+ });
234
+
235
+ new Rule(stack, `${cron.name}Rule`, {
236
+ schedule: Schedule.expression(cron.schedule),
237
+ targets: [new LambdaFunction(fn)]
238
+ });
239
+ }
240
+ ```
241
+
242
+ ## Features
243
+
244
+ - **Type Safety**: Full TypeScript support with input/output validation
245
+ - **Service Injection**: Access configured services in your handlers
246
+ - **Structured Logging**: Built-in logger with request context
247
+ - **Error Handling**: Automatic error wrapping and reporting
248
+ - **Event Publishing**: Support for publishing events after execution
249
+ - **Timeout Control**: Configure function-specific timeouts
250
+
251
+ ## Migration from Lambda Functions
252
+
253
+ If you have existing Lambda functions, you can gradually migrate them:
254
+
255
+ 1. Create function wrappers using the `f` builder
256
+ 2. Move business logic into the handle method
257
+ 3. Add input/output schemas for validation
258
+ 4. Configure services and logging as needed
259
+
260
+ ## Best Practices
261
+
262
+ 1. **Input Validation**: Always define input schemas for functions
263
+ 2. **Error Handling**: Let the framework handle errors, throw meaningful exceptions
264
+ 3. **Logging**: Use the provided logger for structured logs
265
+ 4. **Timeouts**: Set appropriate timeouts based on expected execution time
266
+ 5. **Testing**: Test functions locally before deployment
package/README.md CHANGED
@@ -316,16 +316,16 @@ The CLI generates files in the `.gkm/<provider>` directory:
316
316
  ├── aws-apigatewayv1/
317
317
  │ ├── getUsers.ts # Individual Lambda handler
318
318
  │ ├── createUser.ts # Individual Lambda handler
319
- │ └── routes.json # Routes manifest
319
+ │ └── manifest.json # Build manifest
320
320
  ├── server/
321
321
  │ ├── app.ts # Server application
322
- │ └── routes.json # Routes manifest
322
+ │ └── manifest.json # Build manifest
323
323
  └── openapi.json # OpenAPI specification
324
324
  ```
325
325
 
326
- ### Routes Manifest
326
+ ### Build Manifest
327
327
 
328
- Each provider generates a `routes.json` file with routing information:
328
+ Each provider generates a `manifest.json` file with build information:
329
329
 
330
330
  ```json
331
331
  {
@@ -340,6 +340,23 @@ Each provider generates a `routes.json` file with routing information:
340
340
  "method": "POST",
341
341
  "handler": ".gkm/aws-apigatewayv1/createUser.handler"
342
342
  }
343
+ ],
344
+ "functions": [
345
+ {
346
+ "name": "processData",
347
+ "handler": ".gkm/aws-lambda/functions/processData.handler",
348
+ "timeout": 60,
349
+ "memorySize": 256
350
+ }
351
+ ],
352
+ "crons": [
353
+ {
354
+ "name": "dailyCleanup",
355
+ "handler": ".gkm/aws-lambda/crons/dailyCleanup.handler",
356
+ "schedule": "rate(1 day)",
357
+ "timeout": 300,
358
+ "memorySize": 512
359
+ }
343
360
  ]
344
361
  }
345
362
  ```
@@ -0,0 +1,53 @@
1
+ import { ConstructGenerator } from "./Generator-CDt4pB3W.mjs";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import { dirname, join, relative } from "node:path";
4
+ import { Cron } from "@geekmidas/api/constructs";
5
+
6
+ //#region src/generators/CronGenerator.ts
7
+ var CronGenerator = class extends ConstructGenerator {
8
+ async build(context, constructs, outputDir, options) {
9
+ const provider = options?.provider || "aws-lambda";
10
+ const logger = console;
11
+ const cronInfos = [];
12
+ if (constructs.length === 0 || provider !== "aws-lambda") return cronInfos;
13
+ const cronsDir = join(outputDir, "crons");
14
+ await mkdir(cronsDir, { recursive: true });
15
+ for (const { key, construct, path } of constructs) {
16
+ const handlerFile = await this.generateCronHandler(cronsDir, path.relative, key, context);
17
+ cronInfos.push({
18
+ name: key,
19
+ handler: relative(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
20
+ schedule: construct.schedule || "rate(1 hour)",
21
+ timeout: construct.timeout
22
+ });
23
+ logger.log(`Generated cron handler: ${key}`);
24
+ }
25
+ return cronInfos;
26
+ }
27
+ isConstruct(value) {
28
+ return Cron.isCron(value);
29
+ }
30
+ async generateCronHandler(outputDir, sourceFile, exportName, context) {
31
+ const handlerFileName = `${exportName}.ts`;
32
+ const handlerPath = join(outputDir, handlerFileName);
33
+ const relativePath = relative(dirname(handlerPath), sourceFile);
34
+ const importPath = relativePath.replace(/\.ts$/, ".js");
35
+ const relativeEnvParserPath = relative(dirname(handlerPath), context.envParserPath);
36
+ const relativeLoggerPath = relative(dirname(handlerPath), context.loggerPath);
37
+ const content = `import { AWSScheduledFunction } from '@geekmidas/api/aws-lambda';
38
+ import { ${exportName} } from '${importPath}';
39
+ import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
40
+ import ${context.loggerImportPattern} from '${relativeLoggerPath}';
41
+
42
+ const adapter = new AWSScheduledFunction(envParser, ${exportName});
43
+
44
+ export const handler = adapter.handler;
45
+ `;
46
+ await writeFile(handlerPath, content);
47
+ return handlerPath;
48
+ }
49
+ };
50
+
51
+ //#endregion
52
+ export { CronGenerator };
53
+ //# sourceMappingURL=CronGenerator-ClbRcmz_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CronGenerator-ClbRcmz_.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/api/constructs';\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 });\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/api/aws-lambda';\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;GACpB,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"}
@@ -0,0 +1,59 @@
1
+ const require_chunk = require('./chunk-CsX-DzYB.cjs');
2
+ const require_Generator = require('./Generator-C3tYSTQY.cjs');
3
+ const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
4
+ const node_path = require_chunk.__toESM(require("node:path"));
5
+ const __geekmidas_api_constructs = require_chunk.__toESM(require("@geekmidas/api/constructs"));
6
+
7
+ //#region src/generators/CronGenerator.ts
8
+ var CronGenerator = class extends require_Generator.ConstructGenerator {
9
+ async build(context, constructs, outputDir, options) {
10
+ const provider = options?.provider || "aws-lambda";
11
+ const logger = console;
12
+ const cronInfos = [];
13
+ if (constructs.length === 0 || provider !== "aws-lambda") return cronInfos;
14
+ const cronsDir = (0, node_path.join)(outputDir, "crons");
15
+ await (0, node_fs_promises.mkdir)(cronsDir, { recursive: true });
16
+ for (const { key, construct, path } of constructs) {
17
+ const handlerFile = await this.generateCronHandler(cronsDir, path.relative, key, context);
18
+ cronInfos.push({
19
+ name: key,
20
+ handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
21
+ schedule: construct.schedule || "rate(1 hour)",
22
+ timeout: construct.timeout
23
+ });
24
+ logger.log(`Generated cron handler: ${key}`);
25
+ }
26
+ return cronInfos;
27
+ }
28
+ isConstruct(value) {
29
+ return __geekmidas_api_constructs.Cron.isCron(value);
30
+ }
31
+ async generateCronHandler(outputDir, sourceFile, exportName, context) {
32
+ const handlerFileName = `${exportName}.ts`;
33
+ const handlerPath = (0, node_path.join)(outputDir, handlerFileName);
34
+ const relativePath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), sourceFile);
35
+ const importPath = relativePath.replace(/\.ts$/, ".js");
36
+ const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), context.envParserPath);
37
+ const relativeLoggerPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), context.loggerPath);
38
+ const content = `import { AWSScheduledFunction } from '@geekmidas/api/aws-lambda';
39
+ import { ${exportName} } from '${importPath}';
40
+ import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
41
+ import ${context.loggerImportPattern} from '${relativeLoggerPath}';
42
+
43
+ const adapter = new AWSScheduledFunction(envParser, ${exportName});
44
+
45
+ export const handler = adapter.handler;
46
+ `;
47
+ await (0, node_fs_promises.writeFile)(handlerPath, content);
48
+ return handlerPath;
49
+ }
50
+ };
51
+
52
+ //#endregion
53
+ Object.defineProperty(exports, 'CronGenerator', {
54
+ enumerable: true,
55
+ get: function () {
56
+ return CronGenerator;
57
+ }
58
+ });
59
+ //# sourceMappingURL=CronGenerator-Ctl4USy4.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CronGenerator-Ctl4USy4.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/api/constructs';\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 });\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/api/aws-lambda';\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;GACpB,EAAC;AAEF,UAAO,KAAK,0BAA0B,IAAI,EAAE;EAC7C;AAED,SAAO;CACR;CAED,YAAYC,OAA+C;AACzD,SAAO,gCAAK,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"}
@@ -0,0 +1,164 @@
1
+ const require_chunk = require('./chunk-CsX-DzYB.cjs');
2
+ const require_Generator = require('./Generator-C3tYSTQY.cjs');
3
+ const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
4
+ const node_path = require_chunk.__toESM(require("node:path"));
5
+ const __geekmidas_api_server = require_chunk.__toESM(require("@geekmidas/api/server"));
6
+
7
+ //#region src/generators/EndpointGenerator.ts
8
+ var EndpointGenerator = class extends require_Generator.ConstructGenerator {
9
+ isConstruct(value) {
10
+ return __geekmidas_api_server.Endpoint.isEndpoint(value);
11
+ }
12
+ async build(context, constructs, outputDir, options) {
13
+ const provider = options?.provider || "aws-apigatewayv2";
14
+ const enableOpenApi = options?.enableOpenApi || false;
15
+ const logger = console;
16
+ const routes = [];
17
+ if (constructs.length === 0) return routes;
18
+ if (provider === "server") {
19
+ const serverFile = await this.generateServerFile(outputDir, constructs, context, enableOpenApi);
20
+ routes.push({
21
+ path: "*",
22
+ method: "ALL",
23
+ handler: (0, node_path.relative)(process.cwd(), serverFile)
24
+ });
25
+ logger.log(`Generated server app with ${constructs.length} endpoints${enableOpenApi ? " (OpenAPI enabled)" : ""}`);
26
+ } else if (provider === "aws-lambda") {
27
+ const routesDir = (0, node_path.join)(outputDir, "routes");
28
+ await (0, node_fs_promises.mkdir)(routesDir, { recursive: true });
29
+ for (const { key, construct, path } of constructs) {
30
+ const handlerFile = await this.generateHandlerFile(routesDir, path.relative, key, "aws-apigatewayv2", construct, context);
31
+ const routeInfo = {
32
+ path: construct._path,
33
+ method: construct.method,
34
+ handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler")
35
+ };
36
+ routes.push(routeInfo);
37
+ logger.log(`Generated handler for ${routeInfo.method} ${routeInfo.path}`);
38
+ }
39
+ } else for (const { key, construct, path } of constructs) {
40
+ const handlerFile = await this.generateHandlerFile(outputDir, path.relative, key, provider, construct, context);
41
+ const routeInfo = {
42
+ path: construct._path,
43
+ method: construct.method,
44
+ handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler")
45
+ };
46
+ routes.push(routeInfo);
47
+ logger.log(`Generated handler for ${routeInfo.method} ${routeInfo.path}`);
48
+ }
49
+ return routes;
50
+ }
51
+ async generateHandlerFile(outputDir, sourceFile, exportName, provider, _endpoint, context) {
52
+ const handlerFileName = `${exportName}.ts`;
53
+ const handlerPath = (0, node_path.join)(outputDir, handlerFileName);
54
+ const relativePath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), sourceFile);
55
+ const importPath = relativePath.replace(/\.ts$/, ".js");
56
+ const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), context.envParserPath);
57
+ let content;
58
+ switch (provider) {
59
+ case "aws-apigatewayv1":
60
+ content = this.generateAWSApiGatewayV1Handler(importPath, exportName, relativeEnvParserPath, context.envParserImportPattern);
61
+ break;
62
+ case "aws-apigatewayv2":
63
+ content = this.generateAWSApiGatewayV2Handler(importPath, exportName, relativeEnvParserPath, context.envParserImportPattern);
64
+ break;
65
+ case "server":
66
+ content = this.generateServerHandler(importPath, exportName);
67
+ break;
68
+ default: throw new Error(`Unsupported provider: ${provider}`);
69
+ }
70
+ await (0, node_fs_promises.writeFile)(handlerPath, content);
71
+ return handlerPath;
72
+ }
73
+ async generateServerFile(outputDir, endpoints, context, enableOpenApi) {
74
+ const serverFileName = "app.ts";
75
+ const serverPath = (0, node_path.join)(outputDir, serverFileName);
76
+ const importsByFile = /* @__PURE__ */ new Map();
77
+ for (const { path, key } of endpoints) {
78
+ const relativePath = (0, node_path.relative)((0, node_path.dirname)(serverPath), path.relative);
79
+ const importPath = relativePath.replace(/\.ts$/, ".js");
80
+ if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
81
+ importsByFile.get(importPath).push(key);
82
+ }
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
+ const imports = Array.from(importsByFile.entries()).map(([importPath, exports$1]) => `import { ${exports$1.join(", ")} } from '${importPath}';`).join("\n");
86
+ 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}';
93
+ ${imports}
94
+
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
+ ];
101
+
102
+ const serviceDiscovery = ServiceDiscovery.getInstance(
103
+ logger,
104
+ envParser
105
+ );
106
+
107
+ // Configure OpenAPI options based on enableOpenApi flag
108
+ const openApiOptions: any = enableOpenApi ? {
109
+ docsPath: '/docs',
110
+ openApiOptions: {
111
+ title: 'API Documentation',
112
+ version: '1.0.0',
113
+ description: 'Generated API documentation'
114
+ }
115
+ } : { docsPath: false };
116
+
117
+ HonoEndpoint.addRoutes(endpoints, serviceDiscovery, honoApp, openApiOptions);
118
+
119
+ return honoApp;
120
+ }
121
+
122
+ // Default export for convenience
123
+ export default createApp;
124
+ `;
125
+ await (0, node_fs_promises.writeFile)(serverPath, content);
126
+ return serverPath;
127
+ }
128
+ generateAWSApiGatewayV1Handler(importPath, exportName, envParserPath, envParserImportPattern) {
129
+ return `import { AmazonApiGatewayV1Endpoint } from '@geekmidas/api/aws-apigateway';
130
+ import { ${exportName} } from '${importPath}';
131
+ import ${envParserImportPattern} from '${envParserPath}';
132
+
133
+ const adapter = new AmazonApiGatewayV1Endpoint(envParser, ${exportName});
134
+
135
+ export const handler = adapter.handler;
136
+ `;
137
+ }
138
+ generateAWSApiGatewayV2Handler(importPath, exportName, envParserPath, envParserImportPattern) {
139
+ return `import { AmazonApiGatewayV2Endpoint } from '@geekmidas/api/aws-apigateway';
140
+ import { ${exportName} } from '${importPath}';
141
+ import ${envParserImportPattern} from '${envParserPath}';
142
+
143
+ const adapter = new AmazonApiGatewayV2Endpoint(envParser, ${exportName});
144
+
145
+ export const handler = adapter.handler;
146
+ `;
147
+ }
148
+ generateServerHandler(importPath, exportName) {
149
+ return `import { ${exportName} } from '${importPath}';
150
+
151
+ // Server handler - implement based on your server framework
152
+ export const handler = ${exportName};
153
+ `;
154
+ }
155
+ };
156
+
157
+ //#endregion
158
+ Object.defineProperty(exports, 'EndpointGenerator', {
159
+ enumerable: true,
160
+ get: function () {
161
+ return EndpointGenerator;
162
+ }
163
+ });
164
+ //# sourceMappingURL=EndpointGenerator-Dj7AumHi.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EndpointGenerator-Dj7AumHi.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>>[]","enableOpenApi: boolean","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/api/server';\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 single server file with all endpoints\n const serverFile = await this.generateServerFile(\n outputDir,\n constructs,\n context,\n enableOpenApi,\n );\n\n routes.push({\n path: '*',\n method: 'ALL',\n handler: relative(process.cwd(), serverFile),\n });\n\n logger.log(\n `Generated server app 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 };\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 };\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 generateServerFile(\n outputDir: string,\n endpoints: GeneratedConstruct<Endpoint<any, any, any, any, any, any>>[],\n context: BuildContext,\n enableOpenApi: boolean,\n ): Promise<string> {\n const serverFileName = 'app.ts';\n const serverPath = join(outputDir, serverFileName);\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(serverPath), 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 const relativeEnvParserPath = relative(\n dirname(serverPath),\n context.envParserPath,\n );\n const relativeLoggerPath = relative(\n dirname(serverPath),\n context.loggerPath,\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 { HonoEndpoint } from '@geekmidas/api/hono';\nimport { Endpoint } from '@geekmidas/api/server';\nimport { ServiceDiscovery } from '@geekmidas/api/services';\nimport { Hono } from 'hono';\nimport ${context.envParserImportPattern} from '${relativeEnvParserPath}';\nimport ${context.loggerImportPattern} from '${relativeLoggerPath}';\n${imports}\n\nexport function createApp(app?: Hono, enableOpenApi: boolean = ${enableOpenApi}): Hono {\n const honoApp = app || new Hono();\n \n const endpoints: Endpoint<any, any, any, any, any, any, any>[] = [\n ${allExportNames.join(',\\n ')}\n ];\n\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, honoApp, openApiOptions);\n\n return honoApp;\n}\n\n// Default export for convenience\nexport default createApp;\n`;\n\n await writeFile(serverPath, content);\n\n return serverPath;\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/api/aws-apigateway';\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/api/aws-apigateway';\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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"}