@geekmidas/cli 0.0.26 → 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 (121) hide show
  1. package/FUNCTION_CRON_SUPPORT.md +266 -0
  2. package/README.md +84 -17
  3. package/dist/CronGenerator-1PflEYe2.cjs +60 -0
  4. package/dist/CronGenerator-1PflEYe2.cjs.map +1 -0
  5. package/dist/CronGenerator-DXRfHQcV.mjs +54 -0
  6. package/dist/CronGenerator-DXRfHQcV.mjs.map +1 -0
  7. package/dist/EndpointGenerator-BbGrDiCP.cjs +264 -0
  8. package/dist/EndpointGenerator-BbGrDiCP.cjs.map +1 -0
  9. package/dist/EndpointGenerator-BmZ9BxbO.mjs +258 -0
  10. package/dist/EndpointGenerator-BmZ9BxbO.mjs.map +1 -0
  11. package/dist/FunctionGenerator-Clw64SwQ.cjs +59 -0
  12. package/dist/FunctionGenerator-Clw64SwQ.cjs.map +1 -0
  13. package/dist/FunctionGenerator-DOEB_yPh.mjs +53 -0
  14. package/dist/FunctionGenerator-DOEB_yPh.mjs.map +1 -0
  15. package/dist/Generator-CDoEXCDg.cjs +47 -0
  16. package/dist/Generator-CDoEXCDg.cjs.map +1 -0
  17. package/dist/Generator-UanJW0_V.mjs +41 -0
  18. package/dist/Generator-UanJW0_V.mjs.map +1 -0
  19. package/dist/SubscriberGenerator-BfMZCVNy.cjs +204 -0
  20. package/dist/SubscriberGenerator-BfMZCVNy.cjs.map +1 -0
  21. package/dist/SubscriberGenerator-D2u00NI3.mjs +198 -0
  22. package/dist/SubscriberGenerator-D2u00NI3.mjs.map +1 -0
  23. package/dist/build/index.cjs +12 -0
  24. package/dist/build/index.mjs +12 -0
  25. package/dist/build/manifests.cjs +3 -0
  26. package/dist/build/manifests.mjs +3 -0
  27. package/dist/build/providerResolver.cjs +5 -0
  28. package/dist/build/providerResolver.mjs +3 -0
  29. package/dist/build/types.cjs +0 -0
  30. package/dist/build/types.mjs +0 -0
  31. package/dist/build-BBhlEjf5.cjs +89 -0
  32. package/dist/build-BBhlEjf5.cjs.map +1 -0
  33. package/dist/build-kY-lG30Q.mjs +83 -0
  34. package/dist/build-kY-lG30Q.mjs.map +1 -0
  35. package/dist/config-D1EpSGk6.cjs +36 -0
  36. package/dist/config-D1EpSGk6.cjs.map +1 -0
  37. package/dist/config-U-mdW-7Y.mjs +30 -0
  38. package/dist/config-U-mdW-7Y.mjs.map +1 -0
  39. package/dist/config.cjs +1 -1
  40. package/dist/config.mjs +1 -1
  41. package/dist/generators/CronGenerator.cjs +4 -0
  42. package/dist/generators/CronGenerator.mjs +4 -0
  43. package/dist/generators/EndpointGenerator.cjs +4 -0
  44. package/dist/generators/EndpointGenerator.mjs +4 -0
  45. package/dist/generators/FunctionGenerator.cjs +4 -0
  46. package/dist/generators/FunctionGenerator.mjs +4 -0
  47. package/dist/generators/Generator.cjs +3 -0
  48. package/dist/generators/Generator.mjs +3 -0
  49. package/dist/generators/SubscriberGenerator.cjs +4 -0
  50. package/dist/generators/SubscriberGenerator.mjs +4 -0
  51. package/dist/generators/index.cjs +12 -0
  52. package/dist/generators/index.mjs +8 -0
  53. package/dist/generators-CEKtVh81.cjs +0 -0
  54. package/dist/generators-CsLujGXs.mjs +0 -0
  55. package/dist/index.cjs +71 -25
  56. package/dist/index.cjs.map +1 -0
  57. package/dist/index.mjs +71 -25
  58. package/dist/index.mjs.map +1 -0
  59. package/dist/manifests-BrJXpHrf.mjs +21 -0
  60. package/dist/manifests-BrJXpHrf.mjs.map +1 -0
  61. package/dist/manifests-D0saShvH.cjs +27 -0
  62. package/dist/manifests-D0saShvH.cjs.map +1 -0
  63. package/dist/{openapi-CksVdkh2.mjs → openapi-BQx3_JbM.mjs} +8 -6
  64. package/dist/openapi-BQx3_JbM.mjs.map +1 -0
  65. package/dist/{openapi-D4QQJUPY.cjs → openapi-CMLr04cz.cjs} +9 -7
  66. package/dist/openapi-CMLr04cz.cjs.map +1 -0
  67. package/dist/{openapi-react-query-DpT3XHFC.mjs → openapi-react-query-DbrWwQzb.mjs} +5 -3
  68. package/dist/openapi-react-query-DbrWwQzb.mjs.map +1 -0
  69. package/dist/{openapi-react-query-C1JLYUOs.cjs → openapi-react-query-Dvjqx_Eo.cjs} +5 -3
  70. package/dist/openapi-react-query-Dvjqx_Eo.cjs.map +1 -0
  71. package/dist/openapi-react-query.cjs +1 -1
  72. package/dist/openapi-react-query.mjs +1 -1
  73. package/dist/openapi.cjs +4 -3
  74. package/dist/openapi.mjs +4 -3
  75. package/dist/providerResolver-B_TjNF0_.mjs +96 -0
  76. package/dist/providerResolver-B_TjNF0_.mjs.map +1 -0
  77. package/dist/providerResolver-DgvzNfP4.cjs +114 -0
  78. package/dist/providerResolver-DgvzNfP4.cjs.map +1 -0
  79. package/examples/cron-example.ts +45 -0
  80. package/examples/function-example.ts +40 -0
  81. package/examples/gkm.config.json +22 -0
  82. package/examples/gkm.minimal.config.json +7 -0
  83. package/examples/gkm.production.config.json +27 -0
  84. package/examples/logger.ts +1 -1
  85. package/package.json +38 -14
  86. package/src/__tests__/config.spec.ts +110 -0
  87. package/src/__tests__/openapi-react-query.spec.ts +506 -0
  88. package/src/__tests__/openapi.spec.ts +362 -0
  89. package/src/__tests__/test-helpers.ts +180 -0
  90. package/src/build/__tests__/index-new.spec.ts +577 -0
  91. package/src/build/index.ts +197 -0
  92. package/src/build/manifests.ts +35 -0
  93. package/src/build/providerResolver.ts +184 -0
  94. package/src/build/types.ts +37 -0
  95. package/src/config.ts +14 -6
  96. package/src/generators/CronGenerator.ts +98 -0
  97. package/src/generators/EndpointGenerator.ts +389 -0
  98. package/src/generators/FunctionGenerator.ts +97 -0
  99. package/src/generators/Generator.ts +95 -0
  100. package/src/generators/SubscriberGenerator.ts +271 -0
  101. package/src/generators/__tests__/CronGenerator.spec.ts +445 -0
  102. package/src/generators/__tests__/EndpointGenerator.spec.ts +394 -0
  103. package/src/generators/__tests__/FunctionGenerator.spec.ts +256 -0
  104. package/src/generators/__tests__/SubscriberGenerator.spec.ts +341 -0
  105. package/src/generators/index.ts +9 -0
  106. package/src/index.ts +57 -22
  107. package/src/openapi-react-query.ts +2 -1
  108. package/src/openapi.ts +5 -4
  109. package/src/types.ts +91 -2
  110. package/dist/build-BTggTCYL.cjs +0 -176
  111. package/dist/build-Ca4P6_lY.mjs +0 -170
  112. package/dist/build.cjs +0 -5
  113. package/dist/build.mjs +0 -5
  114. package/dist/config-BNqUMsvc.cjs +0 -24
  115. package/dist/config-BciAdY6_.mjs +0 -18
  116. package/dist/loadEndpoints-BBIavB9h.cjs +0 -37
  117. package/dist/loadEndpoints-DAZ53Og2.mjs +0 -31
  118. package/dist/loadEndpoints.cjs +0 -3
  119. package/dist/loadEndpoints.mjs +0 -3
  120. package/src/build.ts +0 -305
  121. 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
@@ -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
  );
@@ -316,16 +366,16 @@ The CLI generates files in the `.gkm/<provider>` directory:
316
366
  ├── aws-apigatewayv1/
317
367
  │ ├── getUsers.ts # Individual Lambda handler
318
368
  │ ├── createUser.ts # Individual Lambda handler
319
- │ └── routes.json # Routes manifest
369
+ │ └── manifest.json # Build manifest
320
370
  ├── server/
321
371
  │ ├── app.ts # Server application
322
- │ └── routes.json # Routes manifest
372
+ │ └── manifest.json # Build manifest
323
373
  └── openapi.json # OpenAPI specification
324
374
  ```
325
375
 
326
- ### Routes Manifest
376
+ ### Build Manifest
327
377
 
328
- Each provider generates a `routes.json` file with routing information:
378
+ Each provider generates a `manifest.json` file with build information:
329
379
 
330
380
  ```json
331
381
  {
@@ -340,6 +390,23 @@ Each provider generates a `routes.json` file with routing information:
340
390
  "method": "POST",
341
391
  "handler": ".gkm/aws-apigatewayv1/createUser.handler"
342
392
  }
393
+ ],
394
+ "functions": [
395
+ {
396
+ "name": "processData",
397
+ "handler": ".gkm/aws-lambda/functions/processData.handler",
398
+ "timeout": 60,
399
+ "memorySize": 256
400
+ }
401
+ ],
402
+ "crons": [
403
+ {
404
+ "name": "dailyCleanup",
405
+ "handler": ".gkm/aws-lambda/crons/dailyCleanup.handler",
406
+ "schedule": "rate(1 day)",
407
+ "timeout": 300,
408
+ "memorySize": 512
409
+ }
343
410
  ]
344
411
  }
345
412
  ```
@@ -495,7 +562,7 @@ Set up structured logging with different levels:
495
562
 
496
563
  ```typescript
497
564
  // src/logger.ts
498
- import { ConsoleLogger } from '@geekmidas/api/logger';
565
+ import { ConsoleLogger } from '@geekmidas/logger/console';
499
566
 
500
567
  export const logger = new ConsoleLogger({
501
568
  level: process.env.LOG_LEVEL || 'info',
@@ -0,0 +1,60 @@
1
+ const require_chunk = require('./chunk-CUT6urMc.cjs');
2
+ const require_Generator = require('./Generator-CDoEXCDg.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_constructs_crons = require_chunk.__toESM(require("@geekmidas/constructs/crons"));
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
+ environment: await construct.getEnvironment()
24
+ });
25
+ logger.log(`Generated cron handler: ${key}`);
26
+ }
27
+ return cronInfos;
28
+ }
29
+ isConstruct(value) {
30
+ return __geekmidas_constructs_crons.Cron.isCron(value);
31
+ }
32
+ async generateCronHandler(outputDir, sourceFile, exportName, context) {
33
+ const handlerFileName = `${exportName}.ts`;
34
+ const handlerPath = (0, node_path.join)(outputDir, handlerFileName);
35
+ const relativePath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), sourceFile);
36
+ const importPath = relativePath.replace(/\.ts$/, ".js");
37
+ const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), context.envParserPath);
38
+ const relativeLoggerPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), context.loggerPath);
39
+ const content = `import { AWSScheduledFunction } from '@geekmidas/constructs/crons';
40
+ import { ${exportName} } from '${importPath}';
41
+ import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
42
+ import ${context.loggerImportPattern} from '${relativeLoggerPath}';
43
+
44
+ const adapter = new AWSScheduledFunction(envParser, ${exportName});
45
+
46
+ export const handler = adapter.handler;
47
+ `;
48
+ await (0, node_fs_promises.writeFile)(handlerPath, content);
49
+ return handlerPath;
50
+ }
51
+ };
52
+
53
+ //#endregion
54
+ Object.defineProperty(exports, 'CronGenerator', {
55
+ enumerable: true,
56
+ get: function () {
57
+ return CronGenerator;
58
+ }
59
+ });
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"}
@@ -0,0 +1,54 @@
1
+ import { ConstructGenerator } from "./Generator-UanJW0_V.mjs";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import { dirname, join, relative } from "node:path";
4
+ import { Cron } from "@geekmidas/constructs/crons";
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
+ environment: await construct.getEnvironment()
23
+ });
24
+ logger.log(`Generated cron handler: ${key}`);
25
+ }
26
+ return cronInfos;
27
+ }
28
+ isConstruct(value) {
29
+ return Cron.isCron(value);
30
+ }
31
+ async generateCronHandler(outputDir, sourceFile, exportName, context) {
32
+ const handlerFileName = `${exportName}.ts`;
33
+ const handlerPath = join(outputDir, handlerFileName);
34
+ const relativePath = relative(dirname(handlerPath), sourceFile);
35
+ const importPath = relativePath.replace(/\.ts$/, ".js");
36
+ const relativeEnvParserPath = relative(dirname(handlerPath), context.envParserPath);
37
+ const relativeLoggerPath = relative(dirname(handlerPath), context.loggerPath);
38
+ const content = `import { AWSScheduledFunction } from '@geekmidas/constructs/crons';
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 writeFile(handlerPath, content);
48
+ return handlerPath;
49
+ }
50
+ };
51
+
52
+ //#endregion
53
+ export { CronGenerator };
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"}