aws-lambda-devkit 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 (183) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/LICENSE +21 -0
  3. package/README.md +214 -0
  4. package/dist/aws/batch-response.d.ts +8 -0
  5. package/dist/aws/batch-response.d.ts.map +1 -0
  6. package/dist/aws/batch-response.js +12 -0
  7. package/dist/aws/batch-response.js.map +1 -0
  8. package/dist/aws/clients.d.ts +6 -0
  9. package/dist/aws/clients.d.ts.map +1 -0
  10. package/dist/aws/clients.js +30 -0
  11. package/dist/aws/clients.js.map +1 -0
  12. package/dist/aws/sns-publish.d.ts +10 -0
  13. package/dist/aws/sns-publish.d.ts.map +1 -0
  14. package/dist/aws/sns-publish.js +17 -0
  15. package/dist/aws/sns-publish.js.map +1 -0
  16. package/dist/aws/sqs-listen.d.ts +17 -0
  17. package/dist/aws/sqs-listen.d.ts.map +1 -0
  18. package/dist/aws/sqs-listen.js +113 -0
  19. package/dist/aws/sqs-listen.js.map +1 -0
  20. package/dist/aws/sqs-process.d.ts +39 -0
  21. package/dist/aws/sqs-process.d.ts.map +1 -0
  22. package/dist/aws/sqs-process.js +95 -0
  23. package/dist/aws/sqs-process.js.map +1 -0
  24. package/dist/aws/sqs-send.d.ts +15 -0
  25. package/dist/aws/sqs-send.d.ts.map +1 -0
  26. package/dist/aws/sqs-send.js +27 -0
  27. package/dist/aws/sqs-send.js.map +1 -0
  28. package/dist/aws/sqs-visibility.d.ts +10 -0
  29. package/dist/aws/sqs-visibility.d.ts.map +1 -0
  30. package/dist/aws/sqs-visibility.js +29 -0
  31. package/dist/aws/sqs-visibility.js.map +1 -0
  32. package/dist/cli.d.ts +3 -0
  33. package/dist/cli.d.ts.map +1 -0
  34. package/dist/cli.js +187 -0
  35. package/dist/cli.js.map +1 -0
  36. package/dist/commands/config-cmd.d.ts +5 -0
  37. package/dist/commands/config-cmd.d.ts.map +1 -0
  38. package/dist/commands/config-cmd.js +8 -0
  39. package/dist/commands/config-cmd.js.map +1 -0
  40. package/dist/commands/config.d.ts +2 -0
  41. package/dist/commands/config.d.ts.map +1 -0
  42. package/dist/commands/config.js +24 -0
  43. package/dist/commands/config.js.map +1 -0
  44. package/dist/commands/init.d.ts +7 -0
  45. package/dist/commands/init.d.ts.map +1 -0
  46. package/dist/commands/init.js +59 -0
  47. package/dist/commands/init.js.map +1 -0
  48. package/dist/commands/list.d.ts +4 -0
  49. package/dist/commands/list.d.ts.map +1 -0
  50. package/dist/commands/list.js +23 -0
  51. package/dist/commands/list.js.map +1 -0
  52. package/dist/commands/listen.d.ts +20 -0
  53. package/dist/commands/listen.d.ts.map +1 -0
  54. package/dist/commands/listen.js +36 -0
  55. package/dist/commands/listen.js.map +1 -0
  56. package/dist/commands/send.d.ts +17 -0
  57. package/dist/commands/send.d.ts.map +1 -0
  58. package/dist/commands/send.js +51 -0
  59. package/dist/commands/send.js.map +1 -0
  60. package/dist/commands/test.d.ts +23 -0
  61. package/dist/commands/test.d.ts.map +1 -0
  62. package/dist/commands/test.js +123 -0
  63. package/dist/commands/test.js.map +1 -0
  64. package/dist/config/env.d.ts +8 -0
  65. package/dist/config/env.d.ts.map +1 -0
  66. package/dist/config/env.js +16 -0
  67. package/dist/config/env.js.map +1 -0
  68. package/dist/config/load.d.ts +9 -0
  69. package/dist/config/load.d.ts.map +1 -0
  70. package/dist/config/load.js +72 -0
  71. package/dist/config/load.js.map +1 -0
  72. package/dist/config/merge.d.ts +36 -0
  73. package/dist/config/merge.d.ts.map +1 -0
  74. package/dist/config/merge.js +89 -0
  75. package/dist/config/merge.js.map +1 -0
  76. package/dist/config/project-env.d.ts +34 -0
  77. package/dist/config/project-env.d.ts.map +1 -0
  78. package/dist/config/project-env.js +90 -0
  79. package/dist/config/project-env.js.map +1 -0
  80. package/dist/config/schema.d.ts +27 -0
  81. package/dist/config/schema.d.ts.map +1 -0
  82. package/dist/config/schema.js +123 -0
  83. package/dist/config/schema.js.map +1 -0
  84. package/dist/config/types.d.ts +167 -0
  85. package/dist/config/types.d.ts.map +1 -0
  86. package/dist/config/types.js +2 -0
  87. package/dist/config/types.js.map +1 -0
  88. package/dist/events/apigw.d.ts +41 -0
  89. package/dist/events/apigw.d.ts.map +1 -0
  90. package/dist/events/apigw.js +43 -0
  91. package/dist/events/apigw.js.map +1 -0
  92. package/dist/events/eventbridge.d.ts +16 -0
  93. package/dist/events/eventbridge.d.ts.map +1 -0
  94. package/dist/events/eventbridge.js +19 -0
  95. package/dist/events/eventbridge.js.map +1 -0
  96. package/dist/events/index.d.ts +17 -0
  97. package/dist/events/index.d.ts.map +1 -0
  98. package/dist/events/index.js +50 -0
  99. package/dist/events/index.js.map +1 -0
  100. package/dist/events/s3.d.ts +45 -0
  101. package/dist/events/s3.d.ts.map +1 -0
  102. package/dist/events/s3.js +44 -0
  103. package/dist/events/s3.js.map +1 -0
  104. package/dist/events/schedule.d.ts +12 -0
  105. package/dist/events/schedule.d.ts.map +1 -0
  106. package/dist/events/schedule.js +15 -0
  107. package/dist/events/schedule.js.map +1 -0
  108. package/dist/events/sns.d.ts +24 -0
  109. package/dist/events/sns.d.ts.map +1 -0
  110. package/dist/events/sns.js +31 -0
  111. package/dist/events/sns.js.map +1 -0
  112. package/dist/events/sqs-record.d.ts +44 -0
  113. package/dist/events/sqs-record.d.ts.map +1 -0
  114. package/dist/events/sqs-record.js +75 -0
  115. package/dist/events/sqs-record.js.map +1 -0
  116. package/dist/events/sqs.d.ts +21 -0
  117. package/dist/events/sqs.d.ts.map +1 -0
  118. package/dist/events/sqs.js +28 -0
  119. package/dist/events/sqs.js.map +1 -0
  120. package/dist/events/util.d.ts +2 -0
  121. package/dist/events/util.d.ts.map +1 -0
  122. package/dist/events/util.js +7 -0
  123. package/dist/events/util.js.map +1 -0
  124. package/dist/index.d.ts +15 -0
  125. package/dist/index.d.ts.map +1 -0
  126. package/dist/index.js +14 -0
  127. package/dist/index.js.map +1 -0
  128. package/dist/peer-resolve.d.ts +5 -0
  129. package/dist/peer-resolve.d.ts.map +1 -0
  130. package/dist/peer-resolve.js +44 -0
  131. package/dist/peer-resolve.js.map +1 -0
  132. package/dist/runtime/asset-links.d.ts +15 -0
  133. package/dist/runtime/asset-links.d.ts.map +1 -0
  134. package/dist/runtime/asset-links.js +42 -0
  135. package/dist/runtime/asset-links.js.map +1 -0
  136. package/dist/runtime/clear-caches.d.ts +5 -0
  137. package/dist/runtime/clear-caches.d.ts.map +1 -0
  138. package/dist/runtime/clear-caches.js +8 -0
  139. package/dist/runtime/clear-caches.js.map +1 -0
  140. package/dist/runtime/context.d.ts +10 -0
  141. package/dist/runtime/context.d.ts.map +1 -0
  142. package/dist/runtime/context.js +42 -0
  143. package/dist/runtime/context.js.map +1 -0
  144. package/dist/runtime/handler-cache.d.ts +6 -0
  145. package/dist/runtime/handler-cache.d.ts.map +1 -0
  146. package/dist/runtime/handler-cache.js +14 -0
  147. package/dist/runtime/handler-cache.js.map +1 -0
  148. package/dist/runtime/invoke.d.ts +32 -0
  149. package/dist/runtime/invoke.d.ts.map +1 -0
  150. package/dist/runtime/invoke.js +111 -0
  151. package/dist/runtime/invoke.js.map +1 -0
  152. package/dist/runtime/loader.d.ts +17 -0
  153. package/dist/runtime/loader.d.ts.map +1 -0
  154. package/dist/runtime/loader.js +76 -0
  155. package/dist/runtime/loader.js.map +1 -0
  156. package/dist/runtime/logs.d.ts +19 -0
  157. package/dist/runtime/logs.d.ts.map +1 -0
  158. package/dist/runtime/logs.js +125 -0
  159. package/dist/runtime/logs.js.map +1 -0
  160. package/dist/util/payload.d.ts +13 -0
  161. package/dist/util/payload.d.ts.map +1 -0
  162. package/dist/util/payload.js +40 -0
  163. package/dist/util/payload.js.map +1 -0
  164. package/dist/util/tsx-register.d.ts +4 -0
  165. package/dist/util/tsx-register.d.ts.map +1 -0
  166. package/dist/util/tsx-register.js +27 -0
  167. package/dist/util/tsx-register.js.map +1 -0
  168. package/dist/version.d.ts +2 -0
  169. package/dist/version.d.ts.map +1 -0
  170. package/dist/version.js +2 -0
  171. package/dist/version.js.map +1 -0
  172. package/docs/README.md +23 -0
  173. package/docs/commands.md +294 -0
  174. package/docs/configuration.md +652 -0
  175. package/docs/getting-started.md +400 -0
  176. package/docs/recipes.md +743 -0
  177. package/docs/troubleshooting.md +393 -0
  178. package/package.json +76 -0
  179. package/templates/.env.example +5 -0
  180. package/templates/.vscode/launch.json +14 -0
  181. package/templates/events/sample.json +4 -0
  182. package/templates/lamkit.config.js +38 -0
  183. package/templates/lamkit.config.ts +27 -0
@@ -0,0 +1,652 @@
1
+ # Configuration reference
2
+
3
+ Everything you can put in **`lamkit.config.js`** (or `.mjs`, `.cjs`, `.ts`). Lamkit reads this file on every command and validates it with clear error messages.
4
+
5
+ **Tip:** Run `lamkit config worker` after editing to see the merged result.
6
+
7
+ ---
8
+
9
+ ## Where the config file lives
10
+
11
+ Lamkit searches the current directory (or `--cwd`) for the first match:
12
+
13
+ 1. `lamkit.config.ts`
14
+ 2. `lamkit.config.js`
15
+ 3. `lamkit.config.mjs`
16
+ 4. `lamkit.config.cjs`
17
+
18
+ ```bash
19
+ # Run from the config directory
20
+ cd my-lambda-worker
21
+ npx lamkit test
22
+
23
+ # Or point at another folder
24
+ npx lamkit test --cwd ./packages/worker-service
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Config file formats
30
+
31
+ ### JavaScript (default)
32
+
33
+ **`lamkit.config.js`:**
34
+
35
+ ```js
36
+ export default {
37
+ functions: [
38
+ { name: 'worker', entry: './dist/handler.js', trigger: 'sqs' },
39
+ ],
40
+ };
41
+ ```
42
+
43
+ ### CommonJS
44
+
45
+ **`lamkit.config.cjs`:**
46
+
47
+ ```js
48
+ module.exports = {
49
+ functions: [
50
+ { name: 'worker', entry: './dist/handler.js', trigger: 'sqs' },
51
+ ],
52
+ };
53
+ ```
54
+
55
+ ### TypeScript
56
+
57
+ Requires optional peer `tsx`:
58
+
59
+ ```bash
60
+ npm install -D tsx
61
+ ```
62
+
63
+ **`lamkit.config.ts`:**
64
+
65
+ ```ts
66
+ import { defineConfig } from 'aws-lambda-devkit';
67
+
68
+ export default defineConfig({
69
+ defaults: {
70
+ aws: { region: 'us-east-1' },
71
+ },
72
+ functions: [
73
+ {
74
+ name: 'worker',
75
+ entry: './dist/handler.js',
76
+ trigger: 'sqs',
77
+ },
78
+ ],
79
+ });
80
+ ```
81
+
82
+ `defineConfig()` wraps your config with full TypeScript types. **Hover any key** (`entry`, `trigger`, `assetLinks`, …) in VS Code / Cursor for field descriptions, examples, and allowed values.
83
+
84
+ Types are also available without importing runtime code:
85
+
86
+ ```ts
87
+ import type { FunctionConfig, LamkitConfigInput } from 'aws-lambda-devkit/config';
88
+ ```
89
+
90
+ See also `templates/lamkit.config.ts` in the package (copy after `lamkit init`).
91
+
92
+ ---
93
+
94
+ ## Full config shape
95
+
96
+ ```js
97
+ export default {
98
+ // Shared defaults for all functions
99
+ defaults: {
100
+ runtime: 'nodejs20.x',
101
+ memorySize: 512,
102
+ timeout: 30,
103
+ logFormat: 'text',
104
+ tracing: false,
105
+ aws: {
106
+ region: 'us-east-1',
107
+ endpoint: undefined,
108
+ },
109
+ },
110
+
111
+ // Optional: symlink local asset folders before invoke
112
+ assetLinks: [
113
+ { path: 'contracts', target: 'src/contracts' },
114
+ ],
115
+
116
+ // One object per Lambda you want to test
117
+ functions: [
118
+ {
119
+ name: 'worker',
120
+ entry: './dist/handler.js',
121
+ trigger: 'sqs',
122
+ memorySize: 1024,
123
+ timeout: 120,
124
+ logFormat: 'json',
125
+ test: { data: { id: 'default' } },
126
+ aws: {
127
+ region: 'eu-west-1',
128
+ queueUrl: process.env.WORKER_QUEUE_URL,
129
+ topicArn: process.env.EVENTS_TOPIC_ARN,
130
+ endpoint: undefined,
131
+ },
132
+ },
133
+ ],
134
+ };
135
+ ```
136
+
137
+ ### Single-function shortcut
138
+
139
+ If you only have one Lambda, you can flatten the config:
140
+
141
+ ```js
142
+ export default {
143
+ name: 'worker',
144
+ entry: './src/handler.js',
145
+ trigger: 'sqs',
146
+ test: { data: { id: '1' } },
147
+ };
148
+ ```
149
+
150
+ Lamkit converts this internally to `functions: [{ name: 'worker', ... }]`. If you omit `name`, it becomes `default`.
151
+
152
+ ---
153
+
154
+ ## `defaults` — shared settings
155
+
156
+ Apply to every function unless the function overrides the same field.
157
+
158
+ ```js
159
+ export default {
160
+ defaults: {
161
+ runtime: 'nodejs20.x', // shown in logs
162
+ memorySize: 512, // MB — used in REPORT line
163
+ timeout: 30, // seconds — handler killed after this
164
+ logFormat: 'text', // 'text' | 'json'
165
+ tracing: false, // X-Ray fields in REPORT when true
166
+ aws: {
167
+ region: 'us-east-1', // event region + SDK default
168
+ endpoint: undefined, // optional custom endpoint for send/listen
169
+ },
170
+ },
171
+ functions: [/* ... */],
172
+ };
173
+ ```
174
+
175
+ **Example — JSON logs for all functions:**
176
+
177
+ ```js
178
+ export default {
179
+ defaults: { logFormat: 'json' },
180
+ functions: [
181
+ { name: 'worker', entry: './src/handler.js', trigger: 'sqs' },
182
+ ],
183
+ };
184
+ ```
185
+
186
+ **Example — one function overrides timeout:**
187
+
188
+ ```js
189
+ export default {
190
+ defaults: { timeout: 30 },
191
+ functions: [
192
+ {
193
+ name: 'slow-worker',
194
+ entry: './dist/slow.js',
195
+ trigger: 'sqs',
196
+ timeout: 300,
197
+ },
198
+ ],
199
+ };
200
+ ```
201
+
202
+ | Field | Default if omitted |
203
+ |-------|-------------------|
204
+ | `runtime` | `nodejs20.x` |
205
+ | `memorySize` | `512` |
206
+ | `timeout` | `30` |
207
+ | `logFormat` | `text` |
208
+ | `tracing` | `false` |
209
+ | `aws.region` | `process.env.AWS_REGION` → `us-east-1` |
210
+
211
+ ---
212
+
213
+ ## `functions[]` — one entry per Lambda
214
+
215
+ | Field | Required | Description |
216
+ |-------|----------|-------------|
217
+ | `name` | Yes | CLI name: `lamkit test worker` |
218
+ | `entry` | Yes | Path to module that exports `handler` |
219
+ | `trigger` | No | Event builder (`sqs` default) |
220
+ | `memorySize` | No | Overrides `defaults.memorySize` |
221
+ | `timeout` | No | Overrides `defaults.timeout` |
222
+ | `logFormat` | No | Overrides `defaults.logFormat` |
223
+ | `test.data` | No | Default `--data` when CLI omits it |
224
+ | `aws.*` | No | Queue/topic/region for send, listen, realistic ARNs |
225
+
226
+ ### `entry` — which file to load
227
+
228
+ | Your setup | Set `entry` to |
229
+ |------------|----------------|
230
+ | Plain JavaScript | `./src/handler.js` |
231
+ | Compiled TypeScript | `./dist/handler.js` (after `npm run build`) |
232
+ | TypeScript via tsx | `./src/handler.ts` (requires `tsx` peer) |
233
+
234
+ Handler module **must** export:
235
+
236
+ ```js
237
+ export const handler = async (event, context) => {
238
+ // ...
239
+ };
240
+ ```
241
+
242
+ ### `test.data` — default payload
243
+
244
+ ```js
245
+ {
246
+ name: 'worker',
247
+ entry: './src/handler.js',
248
+ trigger: 'sqs',
249
+ test: {
250
+ data: {
251
+ type: 'ORDER_CREATED',
252
+ orderId: 'ord_local_1',
253
+ },
254
+ },
255
+ }
256
+ ```
257
+
258
+ ```bash
259
+ npx lamkit test
260
+ # same payload as: npx lamkit test --data '{"type":"ORDER_CREATED",...}'
261
+ ```
262
+
263
+ CLI `--data` always wins over `test.data`.
264
+
265
+ ---
266
+
267
+ ## `trigger` — event types for `lamkit test`
268
+
269
+ The `trigger` field tells lamkit how to turn your `--data` JSON into a full AWS event.
270
+
271
+ ### `sqs` (default)
272
+
273
+ **Config:**
274
+
275
+ ```js
276
+ { name: 'worker', entry: './dist/handler.js', trigger: 'sqs' }
277
+ ```
278
+
279
+ **Handler pattern:**
280
+
281
+ ```js
282
+ export const handler = async (event) => {
283
+ for (const record of event.Records) {
284
+ const body = JSON.parse(record.body);
285
+ console.log(body);
286
+ }
287
+ };
288
+ ```
289
+
290
+ **CLI:**
291
+
292
+ ```bash
293
+ npx lamkit test --data '{"orderId":"1"}'
294
+ npx lamkit test --data '{"orderId":"1"}' --batch-size 3
295
+ npx lamkit test --data '[{"a":1},{"a":2}]'
296
+ ```
297
+
298
+ **`--data` meaning:** JSON object (or array) stored in `Records[].body` as a string.
299
+
300
+ If `aws.queueUrl` is set, lamkit also sets a realistic `eventSourceARN` on each record.
301
+
302
+ ---
303
+
304
+ ### `http` (API Gateway)
305
+
306
+ **Config:**
307
+
308
+ ```js
309
+ { name: 'api', entry: './dist/http.js', trigger: 'http' }
310
+ ```
311
+
312
+ **Handler pattern:**
313
+
314
+ ```js
315
+ export const handler = async (event) => {
316
+ console.log(event.httpMethod, event.path);
317
+ console.log('Body:', event.body);
318
+ return {
319
+ statusCode: 200,
320
+ headers: { 'Content-Type': 'application/json' },
321
+ body: JSON.stringify({ ok: true }),
322
+ };
323
+ };
324
+ ```
325
+
326
+ **CLI:**
327
+
328
+ ```bash
329
+ npx lamkit test api --data '{"username":"ada"}'
330
+ ```
331
+
332
+ **`--data` meaning:** HTTP request body (lamkit wraps it in an API Gateway proxy event).
333
+
334
+ ---
335
+
336
+ ### `sns`
337
+
338
+ **Config:**
339
+
340
+ ```js
341
+ { name: 'subscriber', entry: './dist/handler.js', trigger: 'sns' }
342
+ ```
343
+
344
+ **CLI:**
345
+
346
+ ```bash
347
+ npx lamkit test subscriber --data '{"alert":"cpu high"}'
348
+ ```
349
+
350
+ **`--data` meaning:** SNS `Message` string (object is JSON-stringified).
351
+
352
+ ---
353
+
354
+ ### `s3`, `eventbridge`, `schedule`
355
+
356
+ ```js
357
+ { name: 'on-upload', entry: './dist/handler.js', trigger: 's3' }
358
+ { name: 'on-bus', entry: './dist/handler.js', trigger: 'eventbridge' }
359
+ { name: 'cron', entry: './dist/handler.js', trigger: 'schedule' }
360
+ ```
361
+
362
+ ```bash
363
+ npx lamkit test on-upload --data '{"key":"uploads/file.pdf"}'
364
+ npx lamkit test on-bus --data '{"orderId":"1","status":"shipped"}'
365
+ npx lamkit test cron --data '{}'
366
+ ```
367
+
368
+ For full control, skip the builder and use a captured event:
369
+
370
+ ```bash
371
+ npx lamkit test worker --event events/captured-from-cloudwatch.json
372
+ ```
373
+
374
+ ---
375
+
376
+ ## `aws` block — real queues and topics
377
+
378
+ Only required for **`lamkit send`** and **`lamkit listen`**. Optional for `lamkit test` (improves SQS ARN realism).
379
+
380
+ ```js
381
+ export default {
382
+ defaults: {
383
+ aws: { region: 'us-east-1' },
384
+ },
385
+ functions: [
386
+ {
387
+ name: 'worker',
388
+ entry: './dist/handler.js',
389
+ trigger: 'sqs',
390
+ aws: {
391
+ queueUrl: process.env.WORKER_QUEUE_URL,
392
+ },
393
+ },
394
+ {
395
+ name: 'notifier',
396
+ entry: './dist/notify.js',
397
+ trigger: 'sns',
398
+ aws: {
399
+ topicArn: process.env.EVENTS_TOPIC_ARN,
400
+ },
401
+ },
402
+ ],
403
+ };
404
+ ```
405
+
406
+ **`.env` example:**
407
+
408
+ ```env
409
+ AWS_REGION=us-east-1
410
+ AWS_ACCESS_KEY_ID=AKIA...
411
+ AWS_SECRET_ACCESS_KEY=...
412
+ WORKER_QUEUE_URL=https://sqs.us-east-1.amazonaws.com/123456789012/dev-worker
413
+ EVENTS_TOPIC_ARN=arn:aws:sns:us-east-1:123456789012:dev-events
414
+ ```
415
+
416
+ **Custom endpoint** (private cloud / compatible API):
417
+
418
+ ```js
419
+ defaults: {
420
+ aws: {
421
+ region: 'us-east-1',
422
+ endpoint: process.env.AWS_ENDPOINT_URL,
423
+ },
424
+ },
425
+ ```
426
+
427
+ ---
428
+
429
+ ## `assetLinks` — local files your `dist/` code expects
430
+
431
+ ### The problem
432
+
433
+ Compiled code often loads files relative to its own path:
434
+
435
+ ```
436
+ dist/services/connector.js → require('../../contracts/abi.json')
437
+ resolves to ./contracts/abi.json
438
+ ```
439
+
440
+ In your Docker image, `contracts/` is copied next to `dist/`. In git, files may live under `src/contracts/` instead. Local invoke fails with `Cannot find module`.
441
+
442
+ ### The solution
443
+
444
+ ```js
445
+ export default {
446
+ assetLinks: [
447
+ { path: 'contracts', target: 'src/contracts' },
448
+ { path: 'email-templates', target: 'src/templates' },
449
+ ],
450
+ functions: [
451
+ { name: 'worker', entry: './dist/handler.js', trigger: 'sqs' },
452
+ ],
453
+ };
454
+ ```
455
+
456
+ Before `test` or `listen`, lamkit creates a symlink:
457
+
458
+ ```
459
+ contracts → src/contracts
460
+ ```
461
+
462
+ If `contracts/` already exists, lamkit leaves it alone.
463
+
464
+ | Field | Example | Meaning |
465
+ |-------|---------|---------|
466
+ | `path` | `contracts` | Where compiled code looks |
467
+ | `target` | `src/contracts` | Where files live in dev |
468
+
469
+ ---
470
+
471
+ ## Environment variables
472
+
473
+ ### Auto-loaded `.env`
474
+
475
+ By default lamkit loads **`.env`** from the project root (same directory as config).
476
+
477
+ ```env
478
+ # .env
479
+ AWS_REGION=us-east-1
480
+ DATABASE_URL=postgres://localhost:5432/app
481
+ WORKER_QUEUE_URL=https://sqs.us-east-1.amazonaws.com/123456789012/dev-worker
482
+ LOG_LEVEL=debug
483
+ ```
484
+
485
+ Rules:
486
+
487
+ - `KEY=value` per line
488
+ - `# comment`
489
+ - Quotes allowed: `KEY="value with spaces"`
490
+
491
+ **Never commit `.env`** — use `.env.example` with placeholder values.
492
+
493
+ ### `loadProjectEnv()` — monorepos and name mapping
494
+
495
+ When the Lambda package is in a subfolder and `.env` lives at the repo root:
496
+
497
+ **Layout:**
498
+
499
+ ```
500
+ repo/
501
+ ├── .env
502
+ └── services/
503
+ └── worker/
504
+ ├── lamkit.config.mjs
505
+ └── dist/handler.js
506
+ ```
507
+
508
+ **`services/worker/lamkit.config.mjs`:**
509
+
510
+ ```js
511
+ import { loadProjectEnv } from 'aws-lambda-devkit';
512
+
513
+ loadProjectEnv({
514
+ files: ['../../.env'],
515
+ skipDotenv: true,
516
+ aliases: {
517
+ APP_DATABASE_NAME: 'DB_NAME',
518
+ APP_DATABASE_PORT: 'DB_PORT',
519
+ APP_DATABASE_HOST: 'DB_HOST',
520
+ },
521
+ rules: [
522
+ { when: { USE_SSL: 'true' }, set: { DB_SSL: 'true' } },
523
+ { when: { NODE_ENV: 'development' }, set: { LOG_LEVEL: 'debug' } },
524
+ ],
525
+ });
526
+
527
+ const region = process.env.AWS_REGION ?? 'us-east-1';
528
+
529
+ export default {
530
+ defaults: { aws: { region } },
531
+ functions: [
532
+ {
533
+ name: 'worker',
534
+ entry: './dist/handler.js',
535
+ trigger: 'sqs',
536
+ aws: { queueUrl: process.env.WORKER_QUEUE_URL, region },
537
+ },
538
+ ],
539
+ };
540
+ ```
541
+
542
+ | Option | What it does |
543
+ |--------|----------------|
544
+ | `files` | Load these env files first (paths relative to config dir) |
545
+ | `skipDotenv: true` | Do not load `./.env` inside the worker package |
546
+ | `aliases` | If `APP_DATABASE_NAME` is set and `DB_NAME` is not, copy value |
547
+ | `rules` | When all `when` keys match, set `set` keys (if not already set) |
548
+ | `stripCustomEndpointForRealAws` | Default `true` — strips `AWS_ENDPOINT_URL*` when using real `AKIA*` keys |
549
+
550
+ Call `loadProjectEnv()` **before** `export default { ... }` so `process.env` is ready when the config object is built.
551
+
552
+ ---
553
+
554
+ ## Payload priority (`lamkit test`)
555
+
556
+ | Priority | Source |
557
+ |----------|--------|
558
+ | 1 (highest) | `--event file.json` |
559
+ | 2 | `--data` or `--data-file` |
560
+ | 3 | `functions[].test.data` |
561
+ | 4 | Builder default for trigger |
562
+
563
+ Example:
564
+
565
+ ```js
566
+ // config has test.data: { id: 'from-config' }
567
+ npx lamkit test --data '{"id":"from-cli"}' // uses from-cli
568
+ npx lamkit test // uses from-config
569
+ ```
570
+
571
+ ---
572
+
573
+ ## CLI flags (quick reference)
574
+
575
+ Full examples: [Commands reference](commands.md)
576
+
577
+ | Flag | Example |
578
+ |------|---------|
579
+ | `--cwd` | `lamkit test --cwd ./services/worker` |
580
+ | `--data` | `lamkit test --data '{"id":"1"}'` |
581
+ | `--data-file` | `lamkit test --data-file events/p.json` |
582
+ | `--event` | `lamkit test --event events/raw.json` |
583
+ | `--batch-size` | `lamkit test --batch-size 5` |
584
+ | `--env` | `lamkit test --env KEY=val` |
585
+ | `--dry-run` | `lamkit test --dry-run` |
586
+ | `--reload` | `lamkit test --reload` |
587
+ | `--strict-batch` | `lamkit test --strict-batch` |
588
+ | `--queue-url` | `lamkit listen --queue-url 'https://sqs...'` |
589
+
590
+ ---
591
+
592
+ ## Complete production-like example
593
+
594
+ ```js
595
+ import { defineConfig, loadProjectEnv } from 'aws-lambda-devkit';
596
+
597
+ loadProjectEnv({
598
+ files: ['../.env'],
599
+ skipDotenv: true,
600
+ aliases: { SHARED_DB_NAME: 'DB_NAME' },
601
+ });
602
+
603
+ const region = process.env.AWS_REGION ?? 'us-east-1';
604
+
605
+ export default defineConfig({
606
+ defaults: {
607
+ runtime: 'nodejs20.x',
608
+ memorySize: 512,
609
+ timeout: 30,
610
+ logFormat: 'text',
611
+ aws: { region },
612
+ },
613
+ assetLinks: [
614
+ { path: 'contracts', target: 'src/contracts' },
615
+ ],
616
+ functions: [
617
+ {
618
+ name: 'queue-worker',
619
+ entry: './dist/worker.js',
620
+ trigger: 'sqs',
621
+ timeout: 120,
622
+ memorySize: 1024,
623
+ aws: { queueUrl: process.env.WORKER_QUEUE_URL },
624
+ test: { data: { type: 'ORDER_CREATED', id: 'local-1' } },
625
+ },
626
+ {
627
+ name: 'http-api',
628
+ entry: './dist/api.js',
629
+ trigger: 'http',
630
+ test: { data: { action: 'health' } },
631
+ },
632
+ {
633
+ name: 'sns-handler',
634
+ entry: './dist/events.js',
635
+ trigger: 'sns',
636
+ aws: { topicArn: process.env.EVENTS_TOPIC_ARN },
637
+ test: { data: { event: 'USER_SIGNUP' } },
638
+ },
639
+ ],
640
+ });
641
+ ```
642
+
643
+ **Verify:**
644
+
645
+ ```bash
646
+ npx lamkit list
647
+ npx lamkit config queue-worker
648
+ npx lamkit test queue-worker
649
+ npx lamkit test --all
650
+ ```
651
+
652
+ More scenarios: [Recipes](recipes.md)