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.
- package/CHANGELOG.md +72 -0
- package/LICENSE +21 -0
- package/README.md +214 -0
- package/dist/aws/batch-response.d.ts +8 -0
- package/dist/aws/batch-response.d.ts.map +1 -0
- package/dist/aws/batch-response.js +12 -0
- package/dist/aws/batch-response.js.map +1 -0
- package/dist/aws/clients.d.ts +6 -0
- package/dist/aws/clients.d.ts.map +1 -0
- package/dist/aws/clients.js +30 -0
- package/dist/aws/clients.js.map +1 -0
- package/dist/aws/sns-publish.d.ts +10 -0
- package/dist/aws/sns-publish.d.ts.map +1 -0
- package/dist/aws/sns-publish.js +17 -0
- package/dist/aws/sns-publish.js.map +1 -0
- package/dist/aws/sqs-listen.d.ts +17 -0
- package/dist/aws/sqs-listen.d.ts.map +1 -0
- package/dist/aws/sqs-listen.js +113 -0
- package/dist/aws/sqs-listen.js.map +1 -0
- package/dist/aws/sqs-process.d.ts +39 -0
- package/dist/aws/sqs-process.d.ts.map +1 -0
- package/dist/aws/sqs-process.js +95 -0
- package/dist/aws/sqs-process.js.map +1 -0
- package/dist/aws/sqs-send.d.ts +15 -0
- package/dist/aws/sqs-send.d.ts.map +1 -0
- package/dist/aws/sqs-send.js +27 -0
- package/dist/aws/sqs-send.js.map +1 -0
- package/dist/aws/sqs-visibility.d.ts +10 -0
- package/dist/aws/sqs-visibility.d.ts.map +1 -0
- package/dist/aws/sqs-visibility.js +29 -0
- package/dist/aws/sqs-visibility.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +187 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config-cmd.d.ts +5 -0
- package/dist/commands/config-cmd.d.ts.map +1 -0
- package/dist/commands/config-cmd.js +8 -0
- package/dist/commands/config-cmd.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +24 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +59 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +4 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +23 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/listen.d.ts +20 -0
- package/dist/commands/listen.d.ts.map +1 -0
- package/dist/commands/listen.js +36 -0
- package/dist/commands/listen.js.map +1 -0
- package/dist/commands/send.d.ts +17 -0
- package/dist/commands/send.d.ts.map +1 -0
- package/dist/commands/send.js +51 -0
- package/dist/commands/send.js.map +1 -0
- package/dist/commands/test.d.ts +23 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +123 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/config/env.d.ts +8 -0
- package/dist/config/env.d.ts.map +1 -0
- package/dist/config/env.js +16 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/load.d.ts +9 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +72 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/merge.d.ts +36 -0
- package/dist/config/merge.d.ts.map +1 -0
- package/dist/config/merge.js +89 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/config/project-env.d.ts +34 -0
- package/dist/config/project-env.d.ts.map +1 -0
- package/dist/config/project-env.js +90 -0
- package/dist/config/project-env.js.map +1 -0
- package/dist/config/schema.d.ts +27 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +123 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/types.d.ts +167 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/events/apigw.d.ts +41 -0
- package/dist/events/apigw.d.ts.map +1 -0
- package/dist/events/apigw.js +43 -0
- package/dist/events/apigw.js.map +1 -0
- package/dist/events/eventbridge.d.ts +16 -0
- package/dist/events/eventbridge.d.ts.map +1 -0
- package/dist/events/eventbridge.js +19 -0
- package/dist/events/eventbridge.js.map +1 -0
- package/dist/events/index.d.ts +17 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +50 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/s3.d.ts +45 -0
- package/dist/events/s3.d.ts.map +1 -0
- package/dist/events/s3.js +44 -0
- package/dist/events/s3.js.map +1 -0
- package/dist/events/schedule.d.ts +12 -0
- package/dist/events/schedule.d.ts.map +1 -0
- package/dist/events/schedule.js +15 -0
- package/dist/events/schedule.js.map +1 -0
- package/dist/events/sns.d.ts +24 -0
- package/dist/events/sns.d.ts.map +1 -0
- package/dist/events/sns.js +31 -0
- package/dist/events/sns.js.map +1 -0
- package/dist/events/sqs-record.d.ts +44 -0
- package/dist/events/sqs-record.d.ts.map +1 -0
- package/dist/events/sqs-record.js +75 -0
- package/dist/events/sqs-record.js.map +1 -0
- package/dist/events/sqs.d.ts +21 -0
- package/dist/events/sqs.d.ts.map +1 -0
- package/dist/events/sqs.js +28 -0
- package/dist/events/sqs.js.map +1 -0
- package/dist/events/util.d.ts +2 -0
- package/dist/events/util.d.ts.map +1 -0
- package/dist/events/util.js +7 -0
- package/dist/events/util.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/peer-resolve.d.ts +5 -0
- package/dist/peer-resolve.d.ts.map +1 -0
- package/dist/peer-resolve.js +44 -0
- package/dist/peer-resolve.js.map +1 -0
- package/dist/runtime/asset-links.d.ts +15 -0
- package/dist/runtime/asset-links.d.ts.map +1 -0
- package/dist/runtime/asset-links.js +42 -0
- package/dist/runtime/asset-links.js.map +1 -0
- package/dist/runtime/clear-caches.d.ts +5 -0
- package/dist/runtime/clear-caches.d.ts.map +1 -0
- package/dist/runtime/clear-caches.js +8 -0
- package/dist/runtime/clear-caches.js.map +1 -0
- package/dist/runtime/context.d.ts +10 -0
- package/dist/runtime/context.d.ts.map +1 -0
- package/dist/runtime/context.js +42 -0
- package/dist/runtime/context.js.map +1 -0
- package/dist/runtime/handler-cache.d.ts +6 -0
- package/dist/runtime/handler-cache.d.ts.map +1 -0
- package/dist/runtime/handler-cache.js +14 -0
- package/dist/runtime/handler-cache.js.map +1 -0
- package/dist/runtime/invoke.d.ts +32 -0
- package/dist/runtime/invoke.d.ts.map +1 -0
- package/dist/runtime/invoke.js +111 -0
- package/dist/runtime/invoke.js.map +1 -0
- package/dist/runtime/loader.d.ts +17 -0
- package/dist/runtime/loader.d.ts.map +1 -0
- package/dist/runtime/loader.js +76 -0
- package/dist/runtime/loader.js.map +1 -0
- package/dist/runtime/logs.d.ts +19 -0
- package/dist/runtime/logs.d.ts.map +1 -0
- package/dist/runtime/logs.js +125 -0
- package/dist/runtime/logs.js.map +1 -0
- package/dist/util/payload.d.ts +13 -0
- package/dist/util/payload.d.ts.map +1 -0
- package/dist/util/payload.js +40 -0
- package/dist/util/payload.js.map +1 -0
- package/dist/util/tsx-register.d.ts +4 -0
- package/dist/util/tsx-register.d.ts.map +1 -0
- package/dist/util/tsx-register.js +27 -0
- package/dist/util/tsx-register.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/docs/README.md +23 -0
- package/docs/commands.md +294 -0
- package/docs/configuration.md +652 -0
- package/docs/getting-started.md +400 -0
- package/docs/recipes.md +743 -0
- package/docs/troubleshooting.md +393 -0
- package/package.json +76 -0
- package/templates/.env.example +5 -0
- package/templates/.vscode/launch.json +14 -0
- package/templates/events/sample.json +4 -0
- package/templates/lamkit.config.js +38 -0
- package/templates/lamkit.config.ts +27 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to **aws-lambda-devkit** are documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-06-23
|
|
6
|
+
|
|
7
|
+
**Initial public release** of `aws-lambda-devkit` — a local development toolkit for Node.js AWS Lambda handlers.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
#### CLI (`lamkit`)
|
|
12
|
+
|
|
13
|
+
- `init` — scaffold `lamkit.config.js`, `.env.example`, sample event, VS Code launch config
|
|
14
|
+
- `test` — invoke handlers locally with AWS-shaped events (no deploy required)
|
|
15
|
+
- `list` — show registered functions from config
|
|
16
|
+
- `config` — print resolved config (secrets redacted)
|
|
17
|
+
- `send sqs` / `send sns` — publish to real dev queues/topics (optional AWS SDK peers)
|
|
18
|
+
- `listen` — poll a real SQS queue and run the handler locally
|
|
19
|
+
|
|
20
|
+
#### Local invoke & events
|
|
21
|
+
|
|
22
|
+
- Simulated invokes for triggers: `sqs`, `http`, `sns`, `s3`, `eventbridge`, `schedule`
|
|
23
|
+
- Plain Node.js handler loading — entry must export `handler` (or default export)
|
|
24
|
+
- CloudWatch-style `START` / `END` / `REPORT` log output
|
|
25
|
+
- Structured logging via `logFormat: 'json'` (global or per-function)
|
|
26
|
+
- Handler module cache with `clearHandlerCache()` / `clearAllHandlerCaches()`
|
|
27
|
+
- `lamkit test` flags: `--data`, `--data-file`, `@file`, `--event`, `--batch-size`, `--reload`, `--cold`, `--dry-run`, `--inspect-brk`, `--strict-batch`, `--env`, `--cwd`
|
|
28
|
+
- `lamkit listen` flags: `--once`, `--expect-messages`, `--batch-invoke` (default), `--no-batch-invoke`, visibility timeout extension
|
|
29
|
+
|
|
30
|
+
#### Configuration
|
|
31
|
+
|
|
32
|
+
- Config loader for `lamkit.config.{js,mjs,cjs,ts}`
|
|
33
|
+
- Zod validation with readable errors via `formatZodError()`
|
|
34
|
+
- `defineConfig()` helper for TypeScript projects
|
|
35
|
+
- `defaults` block — shared runtime, memory, timeout, region, log format
|
|
36
|
+
- `functions[]` — multiple Lambdas in one config; single-function shorthand at root
|
|
37
|
+
- `test.data` — default payload when CLI flags are omitted
|
|
38
|
+
- `aws` block per function — `queueUrl`, `topicArn`, `region`, `endpoint`
|
|
39
|
+
- **`loadProjectEnv()`** — load parent/shared `.env` files, env aliases, conditional rules, and safe endpoint stripping for real IAM keys
|
|
40
|
+
- **`assetLinks`** — symlink dev asset folders (e.g. `contracts` → `src/contracts`) before handler load
|
|
41
|
+
|
|
42
|
+
#### TypeScript & programmatic API
|
|
43
|
+
|
|
44
|
+
- Documented public interfaces with JSDoc (`FunctionConfig`, `LamkitConfigInput`, `AssetLink`, `Trigger`, …)
|
|
45
|
+
- Hover docs in editors when using `defineConfig()` in `lamkit.config.ts`
|
|
46
|
+
- Type-only import path: `aws-lambda-devkit/config`
|
|
47
|
+
- Exports: `buildSqsEvent`, `invokeHandler`, `ensureAssetLinks`, `parseConfig`, `loadProjectEnv`, and related helpers
|
|
48
|
+
|
|
49
|
+
#### AWS (optional)
|
|
50
|
+
|
|
51
|
+
- SQS send and long-poll listen via `@aws-sdk/client-sqs` peer
|
|
52
|
+
- SNS publish via `@aws-sdk/client-sns` peer
|
|
53
|
+
- FIFO queue support (`MessageGroupId`, `MessageDeduplicationId`)
|
|
54
|
+
- Custom endpoint via `aws.endpoint` (LocalStack, private gateways)
|
|
55
|
+
- SQS `MessageAttributes` preserved when building events from polled messages
|
|
56
|
+
|
|
57
|
+
#### Documentation & templates
|
|
58
|
+
|
|
59
|
+
- User guides in `docs/`: getting started, commands, configuration, recipes (22 scenarios), troubleshooting
|
|
60
|
+
- `templates/lamkit.config.js` and `templates/lamkit.config.ts`
|
|
61
|
+
- `templates/events/sample.json`, `.env.example`, `.vscode/launch.json`
|
|
62
|
+
|
|
63
|
+
#### Quality
|
|
64
|
+
|
|
65
|
+
- Unit tests for event builders, invoke pipeline, config loading, asset links, and SQS helpers
|
|
66
|
+
|
|
67
|
+
### Notes
|
|
68
|
+
|
|
69
|
+
- Complements SAM, CDK, and SST — does **not** deploy Lambdas or create AWS resources
|
|
70
|
+
- Default install: 4 runtime dependencies (`zod`, `commander`, `picocolors`, `@types/aws-lambda`)
|
|
71
|
+
- Optional peers: `@aws-sdk/client-sqs`, `@aws-sdk/client-sns`, `tsx`
|
|
72
|
+
- Requires Node.js 20+
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lambda DevKit contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Lambda DevKit
|
|
2
|
+
|
|
3
|
+
**Test AWS Lambda handlers on your laptop** — same `handler` export, realistic events, CloudWatch-style logs. Optional real SQS/SNS against a dev account.
|
|
4
|
+
|
|
5
|
+
| | Name |
|
|
6
|
+
|---|------|
|
|
7
|
+
| **npm package** | [`aws-lambda-devkit`](https://www.npmjs.com/package/aws-lambda-devkit) |
|
|
8
|
+
| **CLI command** | `lamkit` |
|
|
9
|
+
| **Config file** | `lamkit.config.js` (also `.mjs`, `.cjs`, `.ts`) |
|
|
10
|
+
|
|
11
|
+
Install as a dev dependency. Complements SAM, CDK, and SST; does not deploy infrastructure.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Documentation
|
|
16
|
+
|
|
17
|
+
**New here?** Start with the guides below. They use plain language and generic examples only.
|
|
18
|
+
|
|
19
|
+
| Guide | Description |
|
|
20
|
+
|-------|-------------|
|
|
21
|
+
| **[Getting started](docs/getting-started.md)** | Install → first successful `lamkit test` (~15 min walkthrough with sample output) |
|
|
22
|
+
| **[Commands reference](docs/commands.md)** | Every CLI command and flag with copy-paste examples |
|
|
23
|
+
| **[Configuration reference](docs/configuration.md)** | Every config field, `loadProjectEnv`, `assetLinks`, full examples |
|
|
24
|
+
| **[Recipes](docs/recipes.md)** | 22 end-to-end setups with layouts, handlers, commands, and expected results |
|
|
25
|
+
| **[Troubleshooting](docs/troubleshooting.md)** | Symptom → cause → fix for common errors |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## What this package does
|
|
30
|
+
|
|
31
|
+
| Feature | Command | Needs AWS? |
|
|
32
|
+
|---------|---------|------------|
|
|
33
|
+
| Simulate invoke | `lamkit test` | No |
|
|
34
|
+
| List / inspect config | `lamkit list`, `lamkit config` | No |
|
|
35
|
+
| Send message to SQS | `lamkit send sqs` | Yes |
|
|
36
|
+
| Poll SQS → local handler | `lamkit listen` | Yes |
|
|
37
|
+
| Publish to SNS | `lamkit send sns` | Yes |
|
|
38
|
+
| Scaffold project files | `lamkit init` | No |
|
|
39
|
+
|
|
40
|
+
## What it does not do
|
|
41
|
+
|
|
42
|
+
- Deploy Lambdas or create queues/topics
|
|
43
|
+
- Replace SAM Docker emulation or full IaC workflows
|
|
44
|
+
- Require changes inside your production handler code
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Five-minute quick start
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm install -D aws-lambda-devkit
|
|
52
|
+
npx lamkit init
|
|
53
|
+
cp .env.example .env
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Create `src/lambda/handler.js`:
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
export const handler = async (event) => {
|
|
60
|
+
console.log(event);
|
|
61
|
+
return { ok: true };
|
|
62
|
+
};
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`lamkit.config.js` (created by init):
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
export default {
|
|
69
|
+
functions: [
|
|
70
|
+
{
|
|
71
|
+
name: 'worker',
|
|
72
|
+
entry: './src/lambda/handler.js',
|
|
73
|
+
trigger: 'sqs',
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Run:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npx lamkit test --data '{"id":"1"}'
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
You should see `START`, your logs, `END`, and `REPORT` lines.
|
|
86
|
+
|
|
87
|
+
**Next:** [Getting started](docs/getting-started.md) · [Recipes](docs/recipes.md)
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Config at a glance
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
export default {
|
|
95
|
+
defaults: {
|
|
96
|
+
runtime: 'nodejs20.x',
|
|
97
|
+
memorySize: 512,
|
|
98
|
+
timeout: 30,
|
|
99
|
+
logFormat: 'text',
|
|
100
|
+
aws: { region: 'us-east-1' },
|
|
101
|
+
},
|
|
102
|
+
assetLinks: [
|
|
103
|
+
{ path: 'contracts', target: 'src/contracts' },
|
|
104
|
+
],
|
|
105
|
+
functions: [
|
|
106
|
+
{
|
|
107
|
+
name: 'worker',
|
|
108
|
+
entry: './dist/handler.js',
|
|
109
|
+
trigger: 'sqs',
|
|
110
|
+
aws: { queueUrl: process.env.WORKER_QUEUE_URL },
|
|
111
|
+
test: { data: { id: '1' } },
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
};
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
| Block | Purpose |
|
|
118
|
+
|-------|---------|
|
|
119
|
+
| `defaults` | Shared memory, timeout, region, log format |
|
|
120
|
+
| `assetLinks` | Symlink local asset folders before invoke (see [docs](docs/configuration.md#assetlinks)) |
|
|
121
|
+
| `functions` | One entry per Lambda; `entry` must export `handler` |
|
|
122
|
+
|
|
123
|
+
**Monorepo / shared `.env`:** call `loadProjectEnv()` at the top of your config — [example in recipes](docs/recipes.md#recipe-10--monorepo-with-shared-root-env).
|
|
124
|
+
|
|
125
|
+
Config file names: `lamkit.config.{js,mjs,cjs,ts}` (`.ts` needs optional `tsx` peer).
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Commands
|
|
130
|
+
|
|
131
|
+
### Daily development
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
lamkit test [name] --data '{"key":"value"}'
|
|
135
|
+
lamkit test --data-file events/payload.json
|
|
136
|
+
lamkit test --event events/captured-sqs.json
|
|
137
|
+
lamkit test --all
|
|
138
|
+
lamkit test --inspect-brk
|
|
139
|
+
lamkit list
|
|
140
|
+
lamkit config [name]
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Real AWS (dev account only)
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npm install -D @aws-sdk/client-sqs # for send/listen
|
|
147
|
+
lamkit send sqs worker --data '{"id":"1"}'
|
|
148
|
+
lamkit listen worker --once
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Use a **dev queue** — do not run `listen` against production while deployed Lambdas consume the same queue.
|
|
152
|
+
|
|
153
|
+
Full command reference: [Commands](docs/commands.md)
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Optional peers
|
|
158
|
+
|
|
159
|
+
| Install when… | Package |
|
|
160
|
+
|---------------|---------|
|
|
161
|
+
| TypeScript handler or `lamkit.config.ts` | `tsx` |
|
|
162
|
+
| `lamkit send sqs` / `lamkit listen` | `@aws-sdk/client-sqs` |
|
|
163
|
+
| `lamkit send sns` | `@aws-sdk/client-sns` |
|
|
164
|
+
|
|
165
|
+
Default install is **4 small dependencies** (~5 MB): `zod`, `commander`, `picocolors`, `@types/aws-lambda`.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Triggers (simulated `lamkit test`)
|
|
170
|
+
|
|
171
|
+
| `trigger` | Event type |
|
|
172
|
+
|-----------|------------|
|
|
173
|
+
| `sqs` | SQS (default) |
|
|
174
|
+
| `http` | API Gateway HTTP |
|
|
175
|
+
| `sns` | SNS notification |
|
|
176
|
+
| `s3` | S3 object event |
|
|
177
|
+
| `eventbridge` | EventBridge |
|
|
178
|
+
| `schedule` | Scheduled / cron |
|
|
179
|
+
|
|
180
|
+
Examples per trigger: [Recipes](docs/recipes.md)
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## vs SAM / SST
|
|
185
|
+
|
|
186
|
+
| Tool | Best for |
|
|
187
|
+
|------|----------|
|
|
188
|
+
| **Lambda DevKit** | Fast edit-test loop on Node handlers; optional real SQS poll |
|
|
189
|
+
| **SAM** | Docker parity, deploy, broader AWS emulation |
|
|
190
|
+
| **SST `dev`** | Live AWS proxy tied to SST stacks |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Programmatic API
|
|
195
|
+
|
|
196
|
+
```ts
|
|
197
|
+
import {
|
|
198
|
+
defineConfig,
|
|
199
|
+
loadProjectEnv,
|
|
200
|
+
buildSqsEvent,
|
|
201
|
+
ensureAssetLinks,
|
|
202
|
+
} from 'aws-lambda-devkit';
|
|
203
|
+
|
|
204
|
+
// Types only (no runtime import):
|
|
205
|
+
import type { FunctionConfig, LamkitConfigInput } from 'aws-lambda-devkit/config';
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Use `defineConfig()` in `lamkit.config.ts` so every config field shows docs on hover. Most users only need the CLI and `lamkit.config.*`.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
MIT
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type BatchItemFailure = {
|
|
2
|
+
itemIdentifier: string;
|
|
3
|
+
};
|
|
4
|
+
export declare function isBatchItemFailures(value: unknown): value is {
|
|
5
|
+
batchItemFailures: BatchItemFailure[];
|
|
6
|
+
};
|
|
7
|
+
export declare function countBatchItemFailures(result: unknown): number;
|
|
8
|
+
//# sourceMappingURL=batch-response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-response.d.ts","sourceRoot":"","sources":["../../src/aws/batch-response.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI;IAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAMpD;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAM9D"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function isBatchItemFailures(value) {
|
|
2
|
+
return (!!value &&
|
|
3
|
+
typeof value === 'object' &&
|
|
4
|
+
Array.isArray(value.batchItemFailures));
|
|
5
|
+
}
|
|
6
|
+
export function countBatchItemFailures(result) {
|
|
7
|
+
if (!isBatchItemFailures(result)) {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
return result.batchItemFailures.length;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=batch-response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch-response.js","sourceRoot":"","sources":["../../src/aws/batch-response.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,mBAAmB,CACjC,KAAc;IAEd,OAAO,CACL,CAAC,CAAC,KAAK;QACP,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,CAAC,OAAO,CAAE,KAAyC,CAAC,iBAAiB,CAAC,CAC5E,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAe;IACpD,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { MissingPeerError } from '../peer-resolve.js';
|
|
2
|
+
export declare function importSqsSdk(cwd?: string): Promise<Record<string, unknown>>;
|
|
3
|
+
export declare function importSnsSdk(cwd?: string): Promise<Record<string, unknown>>;
|
|
4
|
+
export declare function loadSqsClient(region: string, cwd?: string, endpoint?: string): Promise<unknown>;
|
|
5
|
+
export declare function loadSnsClient(region: string, cwd?: string, endpoint?: string): Promise<unknown>;
|
|
6
|
+
//# sourceMappingURL=clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../src/aws/clients.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,wBAAsB,YAAY,CAAC,GAAG,GAAE,MAAsB,oCAE7D;AAED,wBAAsB,YAAY,CAAC,GAAG,GAAE,MAAsB,oCAE7D;AAMD,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,EAAE,QAAQ,CAAC,EAAE,MAAM,oBAQjG;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,EAAE,QAAQ,CAAC,EAAE,MAAM,oBAQjG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { importPeerFromConsumer } from '../peer-resolve.js';
|
|
2
|
+
export { MissingPeerError } from '../peer-resolve.js';
|
|
3
|
+
export async function importSqsSdk(cwd = process.cwd()) {
|
|
4
|
+
return importPeerFromConsumer(cwd, '@aws-sdk/client-sqs', 'lamkit send sqs / lamkit listen');
|
|
5
|
+
}
|
|
6
|
+
export async function importSnsSdk(cwd = process.cwd()) {
|
|
7
|
+
return importPeerFromConsumer(cwd, '@aws-sdk/client-sns', 'lamkit send sns');
|
|
8
|
+
}
|
|
9
|
+
function resolveEndpoint(explicit) {
|
|
10
|
+
return explicit ?? process.env.AWS_ENDPOINT_URL;
|
|
11
|
+
}
|
|
12
|
+
export async function loadSqsClient(region, cwd = process.cwd(), endpoint) {
|
|
13
|
+
const { SQSClient } = await importSqsSdk(cwd);
|
|
14
|
+
const clientConfig = { region };
|
|
15
|
+
const resolvedEndpoint = resolveEndpoint(endpoint);
|
|
16
|
+
if (resolvedEndpoint) {
|
|
17
|
+
clientConfig.endpoint = resolvedEndpoint;
|
|
18
|
+
}
|
|
19
|
+
return new SQSClient(clientConfig);
|
|
20
|
+
}
|
|
21
|
+
export async function loadSnsClient(region, cwd = process.cwd(), endpoint) {
|
|
22
|
+
const { SNSClient } = await importSnsSdk(cwd);
|
|
23
|
+
const clientConfig = { region };
|
|
24
|
+
const resolvedEndpoint = resolveEndpoint(endpoint);
|
|
25
|
+
if (resolvedEndpoint) {
|
|
26
|
+
clientConfig.endpoint = resolvedEndpoint;
|
|
27
|
+
}
|
|
28
|
+
return new SNSClient(clientConfig);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=clients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.js","sourceRoot":"","sources":["../../src/aws/clients.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC5D,OAAO,sBAAsB,CAAC,GAAG,EAAE,qBAAqB,EAAE,iCAAiC,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC5D,OAAO,sBAAsB,CAAC,GAAG,EAAE,qBAAqB,EAAE,iBAAiB,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,eAAe,CAAC,QAAiB;IACxC,OAAO,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE,EAAE,QAAiB;IAChG,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,YAAY,GAA0C,EAAE,MAAM,EAAE,CAAC;IACvE,MAAM,gBAAgB,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,gBAAgB,EAAE,CAAC;QACrB,YAAY,CAAC,QAAQ,GAAG,gBAAgB,CAAC;IAC3C,CAAC;IACD,OAAO,IAAK,SAA8C,CAAC,YAAY,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAc,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE,EAAE,QAAiB;IAChG,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,YAAY,GAA0C,EAAE,MAAM,EAAE,CAAC;IACvE,MAAM,gBAAgB,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,gBAAgB,EAAE,CAAC;QACrB,YAAY,CAAC,QAAQ,GAAG,gBAAgB,CAAC;IAC3C,CAAC;IACD,OAAO,IAAK,SAA8C,CAAC,YAAY,CAAC,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type PublishSnsOptions = {
|
|
2
|
+
topicArn: string;
|
|
3
|
+
region: string;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
endpoint?: string;
|
|
6
|
+
data?: unknown;
|
|
7
|
+
message?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function publishSnsMessage(options: PublishSnsOptions): Promise<string>;
|
|
10
|
+
//# sourceMappingURL=sns-publish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sns-publish.d.ts","sourceRoot":"","sources":["../../src/aws/sns-publish.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuBnF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { importSnsSdk, loadSnsClient } from './clients.js';
|
|
2
|
+
import { serializePayload } from '../events/util.js';
|
|
3
|
+
export async function publishSnsMessage(options) {
|
|
4
|
+
const cwd = options.cwd ?? process.cwd();
|
|
5
|
+
const { PublishCommand } = (await importSnsSdk(cwd));
|
|
6
|
+
const client = (await loadSnsClient(options.region, cwd, options.endpoint));
|
|
7
|
+
const message = options.message ?? serializePayload(options.data ?? { message: 'hello from lamkit' });
|
|
8
|
+
const response = (await client.send(new PublishCommand({
|
|
9
|
+
TopicArn: options.topicArn,
|
|
10
|
+
Message: message,
|
|
11
|
+
})));
|
|
12
|
+
if (!response.MessageId) {
|
|
13
|
+
throw new Error('Publish succeeded but no MessageId returned');
|
|
14
|
+
}
|
|
15
|
+
return response.MessageId;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=sns-publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sns-publish.js","sourceRoot":"","sources":["../../src/aws/sns-publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAWrD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAA0B;IAChE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,CAElD,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,MAAM,aAAa,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,CAEzE,CAAC;IACF,MAAM,OAAO,GACX,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAExF,MAAM,QAAQ,GAAG,CAAC,MAAM,MAAM,CAAC,IAAI,CACjC,IAAI,cAAc,CAAC;QACjB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,OAAO,EAAE,OAAO;KACjB,CAAC,CACH,CAA2B,CAAC;IAE7B,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,QAAQ,CAAC,SAAS,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { MergedFunctionConfig } from '../config/merge.js';
|
|
2
|
+
import { type ListenResult } from './sqs-process.js';
|
|
3
|
+
export type { ListenResult, SqsMessage } from './sqs-process.js';
|
|
4
|
+
export { buildSqsEventFromMessage, buildSqsEventFromMessages, countBatchItemFailures, isMessageFailed, processSqsMessages, queueArnFromUrl, } from './sqs-process.js';
|
|
5
|
+
export type ListenOptions = {
|
|
6
|
+
fn: MergedFunctionConfig;
|
|
7
|
+
cwd?: string;
|
|
8
|
+
batchSize?: number;
|
|
9
|
+
batchInvoke?: boolean;
|
|
10
|
+
deleteOnSuccess?: boolean;
|
|
11
|
+
once?: boolean;
|
|
12
|
+
reload?: boolean;
|
|
13
|
+
extendVisibility?: boolean;
|
|
14
|
+
onMessage?: (messageId: string, status: 'success' | 'failure') => void;
|
|
15
|
+
};
|
|
16
|
+
export declare function listenSqsQueue(options: ListenOptions): Promise<ListenResult>;
|
|
17
|
+
//# sourceMappingURL=sqs-listen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqs-listen.d.ts","sourceRoot":"","sources":["../../src/aws/sqs-listen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAQ/D,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,sBAAsB,EACtB,eAAe,EACf,kBAAkB,EAClB,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,oBAAoB,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,SAAS,KAAK,IAAI,CAAC;CACxE,CAAC;AAEF,wBAAsB,cAAc,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAyJlF"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { loadHandler } from '../runtime/loader.js';
|
|
2
|
+
import { clearAllHandlerCaches } from '../runtime/clear-caches.js';
|
|
3
|
+
import { createVisibilityHeartbeat, resolveVisibilityExtensionSeconds, } from './sqs-visibility.js';
|
|
4
|
+
import { importSqsSdk, loadSqsClient } from './clients.js';
|
|
5
|
+
import { processSqsMessages, queueArnFromUrl, } from './sqs-process.js';
|
|
6
|
+
export { buildSqsEventFromMessage, buildSqsEventFromMessages, countBatchItemFailures, isMessageFailed, processSqsMessages, queueArnFromUrl, } from './sqs-process.js';
|
|
7
|
+
export async function listenSqsQueue(options) {
|
|
8
|
+
const cwd = options.cwd ?? process.cwd();
|
|
9
|
+
if (options.reload) {
|
|
10
|
+
clearAllHandlerCaches();
|
|
11
|
+
}
|
|
12
|
+
const { ReceiveMessageCommand, DeleteMessageCommand, ChangeMessageVisibilityCommand, GetQueueAttributesCommand } = (await importSqsSdk(cwd));
|
|
13
|
+
const client = (await loadSqsClient(options.fn.region, cwd, options.fn.aws.endpoint));
|
|
14
|
+
const queueUrl = options.fn.aws.queueUrl;
|
|
15
|
+
if (!queueUrl) {
|
|
16
|
+
throw new Error('queueUrl is required. Set functions[].aws.queueUrl in lamkit.config.js or pass --queue-url');
|
|
17
|
+
}
|
|
18
|
+
const batchSize = options.batchSize ?? 10;
|
|
19
|
+
const deleteOnSuccess = options.deleteOnSuccess ?? true;
|
|
20
|
+
const batchInvoke = options.batchInvoke ?? true;
|
|
21
|
+
const extendVisibility = options.extendVisibility ?? true;
|
|
22
|
+
const handler = await loadHandler(options.fn, cwd, { reload: options.reload });
|
|
23
|
+
const queueArn = queueArnFromUrl(queueUrl, options.fn.region);
|
|
24
|
+
let queueVisibilitySeconds = 30;
|
|
25
|
+
if (extendVisibility) {
|
|
26
|
+
try {
|
|
27
|
+
const attrs = (await client.send(new GetQueueAttributesCommand({
|
|
28
|
+
QueueUrl: queueUrl,
|
|
29
|
+
AttributeNames: ['VisibilityTimeout'],
|
|
30
|
+
})));
|
|
31
|
+
queueVisibilitySeconds = Number(attrs.Attributes?.VisibilityTimeout ?? 30);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
queueVisibilitySeconds = 30;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const visibilitySeconds = resolveVisibilityExtensionSeconds(options.fn.timeout, queueVisibilitySeconds);
|
|
38
|
+
const visibilityHeartbeat = extendVisibility
|
|
39
|
+
? createVisibilityHeartbeat({
|
|
40
|
+
visibilitySeconds,
|
|
41
|
+
extendVisibility: async (receiptHandles, seconds) => {
|
|
42
|
+
await Promise.all(receiptHandles.map((receiptHandle) => client.send(new ChangeMessageVisibilityCommand({
|
|
43
|
+
QueueUrl: queueUrl,
|
|
44
|
+
ReceiptHandle: receiptHandle,
|
|
45
|
+
VisibilityTimeout: seconds,
|
|
46
|
+
}))));
|
|
47
|
+
},
|
|
48
|
+
})
|
|
49
|
+
: undefined;
|
|
50
|
+
let running = true;
|
|
51
|
+
const stop = () => {
|
|
52
|
+
running = false;
|
|
53
|
+
};
|
|
54
|
+
let processed = 0;
|
|
55
|
+
let failures = 0;
|
|
56
|
+
let messagesReceived = 0;
|
|
57
|
+
process.once('SIGINT', stop);
|
|
58
|
+
process.once('SIGTERM', stop);
|
|
59
|
+
try {
|
|
60
|
+
while (running) {
|
|
61
|
+
const response = (await client.send(new ReceiveMessageCommand({
|
|
62
|
+
QueueUrl: queueUrl,
|
|
63
|
+
MaxNumberOfMessages: batchSize,
|
|
64
|
+
WaitTimeSeconds: 20,
|
|
65
|
+
MessageAttributeNames: ['All'],
|
|
66
|
+
AttributeNames: ['All'],
|
|
67
|
+
})));
|
|
68
|
+
const messages = response.Messages ?? [];
|
|
69
|
+
if (messages.length === 0) {
|
|
70
|
+
if (options.once) {
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const batchResult = await processSqsMessages({
|
|
76
|
+
messages,
|
|
77
|
+
handler,
|
|
78
|
+
fn: options.fn,
|
|
79
|
+
queueArn,
|
|
80
|
+
region: options.fn.region,
|
|
81
|
+
batchInvoke,
|
|
82
|
+
deleteOnSuccess,
|
|
83
|
+
deleteMessage: async (receiptHandle) => {
|
|
84
|
+
await client.send(new DeleteMessageCommand({
|
|
85
|
+
QueueUrl: queueUrl,
|
|
86
|
+
ReceiptHandle: receiptHandle,
|
|
87
|
+
}));
|
|
88
|
+
},
|
|
89
|
+
onMessage: options.onMessage,
|
|
90
|
+
visibilityHeartbeat,
|
|
91
|
+
});
|
|
92
|
+
processed += batchResult.processed;
|
|
93
|
+
failures += batchResult.failures;
|
|
94
|
+
messagesReceived += batchResult.messagesReceived;
|
|
95
|
+
for (const line of batchResult.logs) {
|
|
96
|
+
console.log(line);
|
|
97
|
+
}
|
|
98
|
+
if (!running) {
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
if (options.once) {
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
process.off('SIGINT', stop);
|
|
108
|
+
process.off('SIGTERM', stop);
|
|
109
|
+
visibilityHeartbeat?.stop();
|
|
110
|
+
}
|
|
111
|
+
return { processed, failures, messagesReceived };
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=sqs-listen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqs-listen.js","sourceRoot":"","sources":["../../src/aws/sqs-listen.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { MergedFunctionConfig } from '../config/merge.js';
|
|
2
|
+
import { queueArnFromUrl, type AwsSqsMessage } from '../events/sqs-record.js';
|
|
3
|
+
import type { VisibilityHeartbeat } from '../aws/sqs-visibility.js';
|
|
4
|
+
import type { Handler } from '../runtime/invoke.js';
|
|
5
|
+
export type SqsMessage = AwsSqsMessage;
|
|
6
|
+
export type ListenResult = {
|
|
7
|
+
processed: number;
|
|
8
|
+
failures: number;
|
|
9
|
+
messagesReceived: number;
|
|
10
|
+
};
|
|
11
|
+
export { isBatchItemFailures, countBatchItemFailures } from '../aws/batch-response.js';
|
|
12
|
+
export declare function buildSqsRecordFromMessage(message: SqsMessage, queueArn: string, region: string): import("../events/sqs-record.js").SqsRecord;
|
|
13
|
+
export declare function buildSqsEventFromMessage(message: SqsMessage, queueArn: string, region: string): {
|
|
14
|
+
Records: import("../events/sqs-record.js").SqsRecord[];
|
|
15
|
+
};
|
|
16
|
+
export declare function buildSqsEventFromMessages(messages: SqsMessage[], queueArn: string, region: string): {
|
|
17
|
+
Records: import("../events/sqs-record.js").SqsRecord[];
|
|
18
|
+
};
|
|
19
|
+
export declare function isMessageFailed(result: {
|
|
20
|
+
success: boolean;
|
|
21
|
+
result?: unknown;
|
|
22
|
+
}, messageId: string): boolean;
|
|
23
|
+
export type ProcessSqsMessagesOptions = {
|
|
24
|
+
messages: SqsMessage[];
|
|
25
|
+
handler: Handler;
|
|
26
|
+
fn: MergedFunctionConfig;
|
|
27
|
+
queueArn: string;
|
|
28
|
+
region: string;
|
|
29
|
+
batchInvoke?: boolean;
|
|
30
|
+
deleteOnSuccess?: boolean;
|
|
31
|
+
deleteMessage?: (receiptHandle: string) => Promise<void>;
|
|
32
|
+
onMessage?: (messageId: string, status: 'success' | 'failure') => void;
|
|
33
|
+
visibilityHeartbeat?: VisibilityHeartbeat;
|
|
34
|
+
};
|
|
35
|
+
export declare function processSqsMessages(options: ProcessSqsMessagesOptions): Promise<ListenResult & {
|
|
36
|
+
logs: string[];
|
|
37
|
+
}>;
|
|
38
|
+
export { queueArnFromUrl };
|
|
39
|
+
//# sourceMappingURL=sqs-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqs-process.d.ts","sourceRoot":"","sources":["../../src/aws/sqs-process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAEL,eAAe,EACf,KAAK,aAAa,EACnB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGpD,MAAM,MAAM,UAAU,GAAG,aAAa,CAAC;AAEvC,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvF,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,+CAGf;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM;;EAKf;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,UAAU,EAAE,EACtB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM;;EAKf;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAU1G;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,EAAE,oBAAoB,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,SAAS,KAAK,IAAI,CAAC;IACvE,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;CAC3C,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,YAAY,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA6E5C;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
|