local-serverless-stack 0.8.0 → 0.10.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 +55 -0
- package/README.md +214 -624
- package/dist/client/namespaces/lambdas.d.ts +1 -0
- package/dist/client/namespaces/lambdas.d.ts.map +1 -1
- package/dist/client/namespaces/lambdas.js.map +1 -1
- package/dist/client/types.d.ts +4 -0
- package/dist/client/types.d.ts.map +1 -1
- package/dist/server/engine/aoss-sidecar.d.ts +13 -0
- package/dist/server/engine/aoss-sidecar.d.ts.map +1 -0
- package/dist/server/engine/aoss-sidecar.js +93 -0
- package/dist/server/engine/aoss-sidecar.js.map +1 -0
- package/dist/server/engine/backends/self-backend.d.ts.map +1 -1
- package/dist/server/engine/backends/self-backend.js +4 -2
- package/dist/server/engine/backends/self-backend.js.map +1 -1
- package/dist/server/engine/emulators/dynamodb/index.d.ts +8 -0
- package/dist/server/engine/emulators/dynamodb/index.d.ts.map +1 -1
- package/dist/server/engine/emulators/dynamodb/index.js +208 -7
- package/dist/server/engine/emulators/dynamodb/index.js.map +1 -1
- package/dist/server/engine/emulators/dynamodb/transactions.d.ts +35 -0
- package/dist/server/engine/emulators/dynamodb/transactions.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/transactions.js +153 -0
- package/dist/server/engine/emulators/dynamodb/transactions.js.map +1 -0
- package/dist/server/engine/emulators/events/index.js +3 -3
- package/dist/server/engine/emulators/events/index.js.map +1 -1
- package/dist/server/engine/emulators/lambda-ctl/index.js +5 -5
- package/dist/server/engine/emulators/lambda-ctl/index.js.map +1 -1
- package/dist/server/engine/emulators/opensearch/index.d.ts +67 -0
- package/dist/server/engine/emulators/opensearch/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/opensearch/index.js +812 -0
- package/dist/server/engine/emulators/opensearch/index.js.map +1 -0
- package/dist/server/engine/emulators/opensearch/search.d.ts +17 -0
- package/dist/server/engine/emulators/opensearch/search.d.ts.map +1 -0
- package/dist/server/engine/emulators/opensearch/search.js +434 -0
- package/dist/server/engine/emulators/opensearch/search.js.map +1 -0
- package/dist/server/engine/emulators/s3/index.js +5 -5
- package/dist/server/engine/emulators/s3/index.js.map +1 -1
- package/dist/server/engine/emulators/sns/index.js +2 -2
- package/dist/server/engine/emulators/sns/index.js.map +1 -1
- package/dist/server/engine/emulators/sqs/index.js +2 -2
- package/dist/server/engine/emulators/sqs/index.js.map +1 -1
- package/dist/server/engine/emulators/sts.js +2 -2
- package/dist/server/engine/emulators/sts.js.map +1 -1
- package/dist/server/engine/http/errors.d.ts +1 -0
- package/dist/server/engine/http/errors.d.ts.map +1 -1
- package/dist/server/engine/http/errors.js +12 -0
- package/dist/server/engine/http/errors.js.map +1 -1
- package/dist/server/engine/http/router.d.ts.map +1 -1
- package/dist/server/engine/http/router.js +11 -0
- package/dist/server/engine/http/router.js.map +1 -1
- package/dist/server/engine/types.d.ts +1 -1
- package/dist/server/engine/types.d.ts.map +1 -1
- package/dist/server/index.js +31 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes/config.d.ts.map +1 -1
- package/dist/server/routes/config.js +16 -0
- package/dist/server/routes/config.js.map +1 -1
- package/dist/server/routes/opensearch.d.ts +3 -0
- package/dist/server/routes/opensearch.d.ts.map +1 -0
- package/dist/server/routes/opensearch.js +69 -0
- package/dist/server/routes/opensearch.js.map +1 -0
- package/dist/server/routes/resources.d.ts.map +1 -1
- package/dist/server/routes/resources.js +4 -1
- package/dist/server/routes/resources.js.map +1 -1
- package/dist/server/routes/services.d.ts.map +1 -1
- package/dist/server/routes/services.js +1 -0
- package/dist/server/routes/services.js.map +1 -1
- package/dist/server/runtime/log-capture.d.ts +7 -0
- package/dist/server/runtime/log-capture.d.ts.map +1 -0
- package/dist/server/runtime/log-capture.js +206 -0
- package/dist/server/runtime/log-capture.js.map +1 -0
- package/dist/server/runtime/runtime-worker.js +23 -14
- package/dist/server/runtime/runtime-worker.js.map +1 -1
- package/dist/server/services/cache-manager.d.ts +2 -1
- package/dist/server/services/cache-manager.d.ts.map +1 -1
- package/dist/server/services/cache-manager.js +22 -2
- package/dist/server/services/cache-manager.js.map +1 -1
- package/dist/server/services/cloudformation-parser.d.ts +10 -1
- package/dist/server/services/cloudformation-parser.d.ts.map +1 -1
- package/dist/server/services/cloudformation-parser.js +28 -0
- package/dist/server/services/cloudformation-parser.js.map +1 -1
- package/dist/server/services/config-manager.d.ts +55 -0
- package/dist/server/services/config-manager.d.ts.map +1 -1
- package/dist/server/services/config-manager.js +84 -0
- package/dist/server/services/config-manager.js.map +1 -1
- package/dist/server/services/gateway-manager.d.ts +2 -0
- package/dist/server/services/gateway-manager.d.ts.map +1 -1
- package/dist/server/services/gateway-manager.js +44 -6
- package/dist/server/services/gateway-manager.js.map +1 -1
- package/dist/server/services/lambda-runtime-manager.d.ts +2 -0
- package/dist/server/services/lambda-runtime-manager.d.ts.map +1 -1
- package/dist/server/services/lambda-runtime-manager.js +19 -1
- package/dist/server/services/lambda-runtime-manager.js.map +1 -1
- package/dist/server/services/opensearch-explorer.d.ts +37 -0
- package/dist/server/services/opensearch-explorer.d.ts.map +1 -0
- package/dist/server/services/opensearch-explorer.js +124 -0
- package/dist/server/services/opensearch-explorer.js.map +1 -0
- package/dist/server/services/resource-provisioner.d.ts +7 -0
- package/dist/server/services/resource-provisioner.d.ts.map +1 -1
- package/dist/server/services/resource-provisioner.js +86 -4
- package/dist/server/services/resource-provisioner.js.map +1 -1
- package/dist/server/services/service-registrar.d.ts +1 -0
- package/dist/server/services/service-registrar.d.ts.map +1 -1
- package/dist/server/services/service-registrar.js +17 -2
- package/dist/server/services/service-registrar.js.map +1 -1
- package/dist/ui/assets/{ApisPage-a9i2qD0Z.js → ApisPage-DyjG-weG.js} +1 -1
- package/dist/ui/assets/{BucketDetailPage-Cz27N0KV.js → BucketDetailPage-Bvrk1L6q.js} +1 -1
- package/dist/ui/assets/{BucketsPage-CZ7wGmUN.js → BucketsPage-KgeLoK6e.js} +1 -1
- package/dist/ui/assets/{DynamoPage-BZMs1iW8.js → DynamoPage-C8rwaEIi.js} +1 -1
- package/dist/ui/assets/{DynamoTablePage-BQsGkhtO.js → DynamoTablePage-CN5P5f7S.js} +1 -1
- package/dist/ui/assets/{LambdaDetailPage-DJb7xqRB.js → LambdaDetailPage-BPhEkF44.js} +3 -3
- package/dist/ui/assets/{LambdasPage-Ctg1l-Lg.js → LambdasPage-Dz4wxjVd.js} +1 -1
- package/dist/ui/assets/OpenSearchCollectionPage-B3s964oC.js +1 -0
- package/dist/ui/assets/OpenSearchPage-0fTJJovd.js +1 -0
- package/dist/ui/assets/OverviewPage-B13l71G0.js +1 -0
- package/dist/ui/assets/OverviewPage-qEl0a-0B.css +1 -0
- package/dist/ui/assets/{QueueDetailPage-DRpSqost.js → QueueDetailPage-peLph1_v.js} +1 -1
- package/dist/ui/assets/{QueuesPage-CY0bDGwV.js → QueuesPage-CF9yiBkq.js} +1 -1
- package/dist/ui/assets/ServiceDetailPage-ZGLPswmY.js +2 -0
- package/dist/ui/assets/ServicesPage-DsoZBBxo.js +2 -0
- package/dist/ui/assets/index-BP9zQ9L-.js +37 -0
- package/dist/ui/assets/{index-C1KdKPDS.css → index-DH7RTkRh.css} +1 -1
- package/dist/ui/index.html +2 -2
- package/package.json +2 -1
- package/dist/ui/assets/OverviewPage-6jDXV1jr.css +0 -1
- package/dist/ui/assets/OverviewPage-DiijblCA.js +0 -1
- package/dist/ui/assets/ServiceDetailPage-CYTEdtts.js +0 -2
- package/dist/ui/assets/ServicesPage-OlV_rr-q.js +0 -2
- package/dist/ui/assets/index-DA_C1HOg.js +0 -36
package/README.md
CHANGED
|
@@ -4,18 +4,29 @@
|
|
|
4
4
|
|
|
5
5
|
**Local control plane for serverless development — with its own in-process AWS engine (no Docker) or LocalStack orchestration**
|
|
6
6
|
|
|
7
|
-
LSS provides a unified local development environment for serverless microservices: one orchestrator provisions and serves every AWS resource your services declare, eliminating the need to run separate LocalStack instances (or, with the **self engine**, any LocalStack at all).
|
|
7
|
+
LSS provides a unified local development environment for serverless microservices: one orchestrator provisions and serves every AWS resource your services declare, eliminating the need to run separate LocalStack instances (or, with the **self engine**, any LocalStack at all). It scales to monorepos with 15+ microservices sharing one stack.
|
|
8
|
+
|
|
9
|
+
```mermaid
|
|
10
|
+
flowchart LR
|
|
11
|
+
DEV[Developer] -->|npx lss start| CLI[CLI<br/>bin/cli.js]
|
|
12
|
+
CLI --> ORCH[Orchestrator<br/>Express API + dashboard :3100]
|
|
13
|
+
SVC[Your services<br/>serverless.yml + serverless-lss] -->|sls package → register| ORCH
|
|
14
|
+
ORCH -->|provision + events| ENGINE{Engine}
|
|
15
|
+
ENGINE -->|"engine: self"| SELF[Self engine<br/>in-process :14566]
|
|
16
|
+
ENGINE -->|"engine: localstack"| LS[LocalStack<br/>Docker :4566]
|
|
17
|
+
ORCH --> RT[Lambda runtime + API Gateway emulation<br/>your handlers, ports 30xx/130xx]
|
|
18
|
+
```
|
|
8
19
|
|
|
9
20
|
## Features
|
|
10
21
|
|
|
11
|
-
- **⚡ Self engine (the LSS differentiator)**: DynamoDB, SQS, S3, EventBridge, SNS and the Lambda control plane emulated **in-process** by the orchestrator — no Docker, no LocalStack, no auth token. Boots in milliseconds, stores data in local files, delivers events straight into your handlers. See [Self engine](#self-engine--no-docker-no-localstack-no-auth-token) below.
|
|
22
|
+
- **⚡ Self engine (the LSS differentiator)**: DynamoDB, SQS, S3, EventBridge, OpenSearch Serverless, SNS and the Lambda control plane emulated **in-process** by the orchestrator — no Docker, no LocalStack, no auth token. Boots in milliseconds, stores data in local files, delivers events straight into your handlers. See [Self engine](#self-engine--no-docker-no-localstack-no-auth-token) below.
|
|
12
23
|
- **Centralized provisioning**: Parses CloudFormation templates from `sls package` and provisions resources automatically — into the self engine or a single shared LocalStack, your choice per instance
|
|
13
24
|
- **Event source mappings**: Automatically connects SQS queues, streams, S3 notifications and EventBridge rules to Lambda handlers
|
|
14
25
|
- **Lambda runtime & API emulation**: LSS answers on the same API (30xx) and Lambda invoke (130xx) ports that serverless-offline used
|
|
15
|
-
- **Web UI**: Vue 3 dashboard to monitor services, resources, and event mappings
|
|
26
|
+
- **Web UI**: Vue 3 dashboard to monitor services, resources, and event mappings — [brandable with your company's colors and logo](docs/CONFIGURATION.md#configuration-properties)
|
|
16
27
|
- **Hot reload**: Watch for code changes and auto-rebuild/reprovision
|
|
17
|
-
- **
|
|
18
|
-
- **CLI
|
|
28
|
+
- **DynamoDB seeds**: fixtures auto-applied on table creation, re-applied via `lss seed` or the dashboard
|
|
29
|
+
- **CLI + programmatic client**: manage the orchestrator from the shell (`npx lss …`) or from code (`LssClient`)
|
|
19
30
|
|
|
20
31
|
See [docs/FEATURES.md](docs/FEATURES.md) for the complete feature inventory and how each capability is tested.
|
|
21
32
|
|
|
@@ -43,6 +54,12 @@ What you get:
|
|
|
43
54
|
- **SQS** with FIFO, visibility redelivery and live counters; **S3** with byte-exact
|
|
44
55
|
object round trips and notifications; **EventBridge** with buses, pattern-filtered
|
|
45
56
|
rules and `rate()`/cron schedules; minimal **SNS** and **STS**.
|
|
57
|
+
- **OpenSearch Serverless**: collections declared as
|
|
58
|
+
`AWS::OpenSearchServerless::Collection` are provisioned via the real `aoss`
|
|
59
|
+
control plane and served through the OpenSearch REST API — document CRUD,
|
|
60
|
+
`_bulk`, `_search` with the everyday query DSL (match/term/range/bool…),
|
|
61
|
+
sorting and `terms`/metric aggregations — at
|
|
62
|
+
`http://localhost:14566/_aoss/<collection>`.
|
|
46
63
|
- **Events delivered in-process**: SQS batches, DynamoDB streams, S3 notifications and
|
|
47
64
|
EventBridge targets go straight from the engine to the LSS Lambda runtime — no proxy
|
|
48
65
|
Lambdas, no polling containers.
|
|
@@ -51,16 +68,17 @@ What you get:
|
|
|
51
68
|
flowchart LR
|
|
52
69
|
APP[Your services<br/>AWS SDK → :14566] --> ENG
|
|
53
70
|
subgraph ORCH["One orchestrator process — no Docker"]
|
|
54
|
-
ENG[Self engine<br/>DynamoDB · SQS · S3<br/>
|
|
71
|
+
ENG[Self engine<br/>DynamoDB · SQS · S3 · EventBridge<br/>OpenSearch · SNS · STS]
|
|
55
72
|
ENG -->|in-process events| RT[LSS Lambda runtime<br/>your handlers, ports 30xx/130xx]
|
|
56
73
|
ENG --- FS[(local files<br/>~/.lss/engine)]
|
|
57
74
|
end
|
|
58
75
|
```
|
|
59
76
|
|
|
60
|
-
Measured on [examples/self-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
77
|
+
Measured on [examples/self-hosted](examples/self-hosted/) (orders → billing →
|
|
78
|
+
notifications pipeline; the example also carries an OpenSearch catalog service):
|
|
79
|
+
engine boot **~10 ms**; a full pipeline crossing DynamoDB + SQS + S3 + EventBridge
|
|
80
|
+
across the three pipeline services completes in **~170 ms** — with the whole stack
|
|
81
|
+
being the orchestrator process plus one small worker per service.
|
|
64
82
|
|
|
65
83
|
Migration is gradual: LocalStack mode remains the default and fully supported; a running
|
|
66
84
|
instance picks one engine. Anything the self engine doesn't implement yet answers with an
|
|
@@ -68,714 +86,286 @@ explicit error naming the operation — or is forwarded verbatim to a LocalStack
|
|
|
68
86
|
`selfEngine.fallbackEndpoint`. Coverage matrix and storage model:
|
|
69
87
|
[docs/SELF_ENGINE.md](docs/SELF_ENGINE.md) · design/PRD:
|
|
70
88
|
[docs/PRD_SELF_ENGINE.md](docs/PRD_SELF_ENGINE.md) · runnable demo:
|
|
71
|
-
[examples/self-
|
|
72
|
-
|
|
73
|
-
## Architecture
|
|
74
|
-
|
|
75
|
-
```
|
|
76
|
-
local-serverless-stack/
|
|
77
|
-
├── bin/ # CLI executable
|
|
78
|
-
│ └── cli.js # lss command entry point
|
|
79
|
-
├── src/ # Source code
|
|
80
|
-
│ ├── server/ # Express API + services
|
|
81
|
-
│ │ ├── routes/ # API endpoints
|
|
82
|
-
│ │ ├── services/ # Business logic
|
|
83
|
-
│ │ └── dev/ # Dev utilities
|
|
84
|
-
│ └── ui/ # Vue 3 dashboard
|
|
85
|
-
├── packages/
|
|
86
|
-
│ └── serverless-plugin/ # Serverless Framework plugin (published separately)
|
|
87
|
-
├── dist/ # Build output
|
|
88
|
-
│ ├── server/ # Compiled Express app
|
|
89
|
-
│ └── ui/ # Built Vue app
|
|
90
|
-
└── tests/ # Integration tests
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
**Components**:
|
|
94
|
-
- **CLI** (`bin/cli.js`): Background process management (start/stop/status/logs)
|
|
95
|
-
- **Server** (`src/server/`): Express API + engine orchestration
|
|
96
|
-
- **Engine** (`src/server/engine/`): the AWS provider behind everything — either the in-process **self engine** (port 14566, no Docker) or a managed/external **LocalStack** container (port 4566)
|
|
97
|
-
- **UI** (`src/ui/`): Vue 3 dashboard for monitoring
|
|
98
|
-
- **Plugin** (`packages/serverless-plugin/`): Auto-registration for Serverless Framework
|
|
89
|
+
[examples/self-hosted](examples/self-hosted/).
|
|
99
90
|
|
|
100
91
|
## Quick Start
|
|
101
92
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
- Node.js >= 20
|
|
105
|
-
- Serverless Framework 3.40.0
|
|
106
|
-
- Docker — **only for the LocalStack engine**; the self engine (`--self-engine`) needs none
|
|
107
|
-
|
|
108
|
-
### Installation
|
|
93
|
+
Prerequisites: Node.js >= 20 · [osls](https://github.com/oss-serverless/serverless) 4.x (open-source Serverless Framework fork; provides the `serverless`/`sls` CLI) · Docker (**only** for the LocalStack engine)
|
|
109
94
|
|
|
110
95
|
```bash
|
|
96
|
+
# 1. Install
|
|
111
97
|
npm install -g local-serverless-stack
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
Or install locally:
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
cd /path/to/local-serverless-stack
|
|
118
|
-
npm install
|
|
119
|
-
npm run build
|
|
120
|
-
npm link
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
The `npm link` command makes the `lss` CLI available globally via `npx`.
|
|
124
98
|
|
|
125
|
-
|
|
99
|
+
# 2. Start the orchestrator (self engine: no Docker needed)
|
|
100
|
+
npx lss start --self-engine # or plain `npx lss start` for LocalStack
|
|
126
101
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
```bash
|
|
102
|
+
# 3. In each microservice: install the plugin and add it to serverless.yml
|
|
130
103
|
npm install --save-dev serverless-lss
|
|
131
104
|
```
|
|
132
105
|
|
|
133
|
-
See the [plugin documentation](packages/serverless-plugin/README.md) for configuration details.
|
|
134
|
-
|
|
135
|
-
## CLI Commands
|
|
136
|
-
|
|
137
|
-
LSS provides a simple CLI to manage the orchestrator in background mode:
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
# Start the orchestrator in background (managed LocalStack)
|
|
141
|
-
npx lss start
|
|
142
|
-
|
|
143
|
-
# Start with the in-process self engine instead — no Docker
|
|
144
|
-
npx lss start --self-engine
|
|
145
|
-
|
|
146
|
-
# Check if orchestrator is running
|
|
147
|
-
npx lss status
|
|
148
|
-
|
|
149
|
-
# View recent logs
|
|
150
|
-
npx lss logs
|
|
151
|
-
|
|
152
|
-
# Stop the orchestrator
|
|
153
|
-
npx lss stop
|
|
154
|
-
|
|
155
|
-
# Show help
|
|
156
|
-
npx lss help
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
### CLI Output
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
$ npx lss start --self-engine
|
|
163
|
-
🚀 LSS Orchestrator started (PID: 12345)
|
|
164
|
-
📊 Server: http://localhost:3100
|
|
165
|
-
🔧 Self Engine: http://localhost:14566 (no Docker)
|
|
166
|
-
✅ Service is running
|
|
167
|
-
|
|
168
|
-
$ npx lss start
|
|
169
|
-
🚀 LSS Orchestrator started (PID: 12345)
|
|
170
|
-
📊 Dashboard: http://localhost:3100
|
|
171
|
-
🔧 LocalStack: http://localhost:4566
|
|
172
|
-
📝 Logs: /tmp/lss-orchestrator.log
|
|
173
|
-
✅ Service is running
|
|
174
|
-
|
|
175
|
-
$ npx lss status
|
|
176
|
-
🟢 LSS Orchestrator: RUNNING (PID: 12345)
|
|
177
|
-
📊 Dashboard: http://localhost:3100
|
|
178
|
-
🔧 LocalStack: http://localhost:4566
|
|
179
|
-
📝 Logs: /tmp/lss-orchestrator.log
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
## Development Mode
|
|
183
|
-
|
|
184
|
-
For active development with hot reload:
|
|
185
|
-
|
|
186
|
-
```bash
|
|
187
|
-
npm run orchestrator:dev
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
This starts:
|
|
191
|
-
- Orchestrator API on http://localhost:3100
|
|
192
|
-
- LocalStack on http://localhost:4566
|
|
193
|
-
- Web UI at http://localhost:3100
|
|
194
|
-
- Auto-reload on code changes
|
|
195
|
-
|
|
196
|
-
## Integration with Projects
|
|
197
|
-
|
|
198
|
-
### 1. Link LSS to Your Project
|
|
199
|
-
|
|
200
|
-
In your project root:
|
|
201
|
-
|
|
202
|
-
```bash
|
|
203
|
-
npm link local-serverless-stack
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### 2. Install Plugin in Microservices
|
|
207
|
-
|
|
208
|
-
In each microservice directory:
|
|
209
|
-
|
|
210
|
-
```bash
|
|
211
|
-
npm link serverless-lss
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### 3. Configure serverless.yml
|
|
215
|
-
|
|
216
|
-
Add the plugin to your `serverless.yml`:
|
|
217
|
-
|
|
218
106
|
```yaml
|
|
107
|
+
# serverless.yml
|
|
219
108
|
plugins:
|
|
220
|
-
- serverless-
|
|
221
|
-
- serverless-esbuild
|
|
222
|
-
- serverless-offline
|
|
223
|
-
- serverless-localstack
|
|
224
|
-
- serverless-lss # Add this line
|
|
109
|
+
- serverless-lss
|
|
225
110
|
|
|
226
111
|
custom:
|
|
227
112
|
orchestrator:
|
|
228
|
-
|
|
113
|
+
enabled: true
|
|
114
|
+
orchestratorUrl: http://localhost:3100 # must match serverPort
|
|
115
|
+
lss:
|
|
116
|
+
apiPort: 3000 # HTTP API (API Gateway emulation)
|
|
117
|
+
invokePort: 3001 # direct Lambda invocations
|
|
229
118
|
```
|
|
230
119
|
|
|
231
|
-
### 4. Workflow
|
|
232
|
-
|
|
233
120
|
```bash
|
|
234
|
-
#
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
# 2. Package your microservice (auto-registers with LSS)
|
|
238
|
-
cd your-microservice
|
|
121
|
+
# 4. Package the service — the plugin auto-registers it with LSS
|
|
122
|
+
# (registration also fires on `sls offline` startup)
|
|
239
123
|
npx sls package
|
|
240
124
|
|
|
241
|
-
#
|
|
125
|
+
# 5. Watch everything in the dashboard
|
|
242
126
|
open http://localhost:3100
|
|
243
127
|
```
|
|
244
128
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
2. Invoke the Lambda proxy in LocalStack
|
|
248
|
-
3. Proxy calls LSS's Lambda invoke listener on the service invoke port
|
|
249
|
-
4. Your handler executes
|
|
129
|
+
A minimal template lives at [docs/serverless.yml.example](docs/serverless.yml.example);
|
|
130
|
+
complete runnable projects live in [examples/](examples/) — one per engine flavor:
|
|
250
131
|
|
|
251
|
-
|
|
252
|
-
|
|
132
|
+
| Example | Shows |
|
|
133
|
+
| --- | --- |
|
|
134
|
+
| [localstack-free](examples/localstack-free/) | LocalStack community 4.0 (Docker, no token): 3 services + a shared EventBridge bus — authorizers, SQS, schedules, DynamoDB stream → SNS, S3 notifications, seeds |
|
|
135
|
+
| [localstack-ultimate](examples/localstack-ultimate/) | LocalStack Pro image (Ultimate plan, auth token) with the serverless-offline path preserved |
|
|
136
|
+
| [self-hosted](examples/self-hosted/) | The no-Docker self engine end to end: orders → billing → notifications pipeline + an OpenSearch Serverless catalog |
|
|
253
137
|
|
|
254
|
-
|
|
138
|
+
Each example ships an `index.html` validation console and its own dashboard
|
|
139
|
+
branding — see [examples/README.md](examples/README.md) for the full port map and
|
|
140
|
+
shared conventions.
|
|
255
141
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
142
|
+
## CLI
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npx lss start # start the orchestrator in background (managed LocalStack)
|
|
146
|
+
npx lss start --self-engine # …with the in-process self engine (no Docker)
|
|
147
|
+
npx lss start --external # …connecting to a LocalStack you already run
|
|
148
|
+
npx lss start --pro # …with the LocalStack Pro image (needs auth token)
|
|
149
|
+
npx lss start --pro --localstack-token ls-xxx # …passing the auth token inline
|
|
150
|
+
npx lss start --enable-dynamo-proxy # …with the DynamoDB proxy on :8000
|
|
151
|
+
npx lss start --config ./e2e/lss.config.json # explicit config file (any command)
|
|
152
|
+
npx lss status # is it running? which ports?
|
|
153
|
+
npx lss logs # tail the orchestrator log
|
|
154
|
+
npx lss seed [table] # apply DynamoDB seed files (all tables or one)
|
|
155
|
+
npx lss seed:clear [table] -y # empty seeded tables (prompts unless --yes)
|
|
156
|
+
npx lss stop # stop the orchestrator (and managed LocalStack)
|
|
157
|
+
npx lss help # all commands, flags and a config template
|
|
270
158
|
```
|
|
271
159
|
|
|
272
|
-
|
|
160
|
+
```bash
|
|
161
|
+
$ npx lss start --self-engine
|
|
162
|
+
🚀 LSS Orchestrator started (PID: 12345)
|
|
163
|
+
📊 Server: http://localhost:3100
|
|
164
|
+
🔧 Self Engine: http://localhost:14566 (no Docker)
|
|
165
|
+
✅ Service is running
|
|
166
|
+
```
|
|
273
167
|
|
|
274
|
-
|
|
168
|
+
The CLI runs the orchestrator detached, storing the PID in
|
|
169
|
+
`$TMPDIR/lss-orchestrator-{serverPort}.pid` and logs in
|
|
170
|
+
`$TMPDIR/lss-orchestrator-{serverPort}.log` (no suffix for the default port 3100;
|
|
171
|
+
under `stateDir` both move into that directory). The port-scoped paths let multiple
|
|
172
|
+
LSS instances coexist — one per project — without trampling each other.
|
|
275
173
|
|
|
276
|
-
|
|
277
|
-
- `LSS_ENGINE`: AWS engine — `localstack` (default) or `self` (in-process, no Docker)
|
|
278
|
-
- `LSS_ENGINE_PORT`: Self engine port (default: 14566)
|
|
279
|
-
- `ENABLE_DYNAMO_PROXY`: Enable DynamoDB proxy on port 8000 (default: false)
|
|
280
|
-
- `DYNAMO_PROXY_PORT`: DynamoDB proxy port (default: 8000)
|
|
174
|
+
## Configuration
|
|
281
175
|
|
|
282
|
-
|
|
176
|
+
Create an `lss.config.json` in the directory where you run `lss start` (all keys
|
|
177
|
+
optional — [full reference](docs/CONFIGURATION.md)):
|
|
283
178
|
|
|
284
179
|
```jsonc
|
|
285
|
-
// lss.config.json
|
|
286
180
|
{
|
|
287
|
-
"
|
|
288
|
-
"
|
|
181
|
+
"serverPort": 3100, // dashboard + API
|
|
182
|
+
"engine": "localstack", // "localstack" (default) | "self" (no Docker)
|
|
183
|
+
"selfEngine": { "port": 14566 }, // engine "self" settings — docs/SELF_ENGINE.md
|
|
184
|
+
"localstackPort": 4566,
|
|
185
|
+
"services": ["dynamodb", "sqs", "sns", "s3", "lambda", "events"],
|
|
186
|
+
"seedsDir": "./seeds", // DynamoDB fixtures ({tableName}.json)
|
|
187
|
+
"autoPackage": false, // run `sls package` on register when template is missing
|
|
188
|
+
"lambdaRuntime": { "enabled": true, "execution": "auto" },
|
|
189
|
+
"branding": { // dashboard look & feel (optional)
|
|
190
|
+
"title": "Acme Cloud",
|
|
191
|
+
"logo": "./assets/acme.svg",
|
|
192
|
+
"colors": { "brand-primary": "#e63946" }
|
|
193
|
+
}
|
|
289
194
|
}
|
|
290
195
|
```
|
|
291
196
|
|
|
197
|
+
The most common environment overrides (env always wins over the file):
|
|
198
|
+
`LSS_DASHBOARD_PORT`, `LSS_ENGINE` (`localstack`/`self`), `LOCALSTACK_AUTH_TOKEN`,
|
|
199
|
+
`LSS_ENABLE_DYNAMO_PROXY`. Complete list: [docs/CONFIGURATION.md](docs/CONFIGURATION.md#environment-variables).
|
|
200
|
+
|
|
292
201
|
The self engine's default port sits **outside 4566–4599** on purpose: a real LocalStack
|
|
293
202
|
install intercepts that whole range on some hosts (Docker Desktop/WSL2). `--self-engine`
|
|
294
203
|
cannot be combined with the LocalStack-only flags (`--external`, `--pro`,
|
|
295
204
|
`--localstack-token`).
|
|
296
205
|
|
|
297
|
-
### LocalStack
|
|
298
|
-
|
|
299
|
-
LocalStack is configured with:
|
|
300
|
-
- Services: `dynamodb,sqs,sns,s3,lambda,events`
|
|
301
|
-
- Persistence: Enabled (volume: `lss-localstack-data`)
|
|
302
|
-
- Lambda executor: `local` (no Docker-in-Docker required)
|
|
303
|
-
- Docker socket: Mounted from host
|
|
304
|
-
|
|
305
|
-
#### Managed vs external mode
|
|
306
|
-
|
|
307
|
-
By default LSS spins up its own LocalStack container. To point at an already-running instance (e.g. one you're sharing across projects) set `mode: "external"` in `lss.config.json` or pass `--external`:
|
|
308
|
-
|
|
309
|
-
```bash
|
|
310
|
-
npx lss start --external # connect to whatever is on localstackEndpoint
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
#### Edition and auth token
|
|
206
|
+
### LocalStack: managed, external, Pro
|
|
314
207
|
|
|
315
|
-
|
|
208
|
+
By default LSS spins up its own container (`lss-localstack-<port>`, services
|
|
209
|
+
`dynamodb,sqs,sns,s3,lambda,events`, persistence volume, local Lambda executor). To point
|
|
210
|
+
at an already-running instance set `mode: "external"` or pass `--external`. Recent
|
|
211
|
+
LocalStack images (`>= 2026.5` community, all `pro`) require an auth token:
|
|
316
212
|
|
|
317
213
|
```bash
|
|
318
214
|
export LOCALSTACK_AUTH_TOKEN=ls-xxxxxxxx
|
|
319
|
-
npx lss start
|
|
320
|
-
npx lss start --pro
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for the full reference (`mode`, `localstackEdition`, `localstackVersion`, `localstackImage`, `localstackAuthToken`).
|
|
324
|
-
|
|
325
|
-
## Development
|
|
326
|
-
|
|
327
|
-
### Build All Packages
|
|
328
|
-
|
|
329
|
-
```bash
|
|
330
|
-
npm run build
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### Build Individual Packages
|
|
334
|
-
|
|
335
|
-
```bash
|
|
336
|
-
# Build orchestrator only
|
|
337
|
-
npm run orchestrator:build
|
|
338
|
-
|
|
339
|
-
# Build plugin only
|
|
340
|
-
npm run plugin:build
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
### Watch Mode (Development)
|
|
344
|
-
|
|
345
|
-
```bash
|
|
346
|
-
# Orchestrator with hot reload
|
|
347
|
-
npm run orchestrator:dev
|
|
348
|
-
|
|
349
|
-
# Plugin with watch
|
|
350
|
-
cd packages/serverless-plugin
|
|
351
|
-
npm run dev
|
|
215
|
+
npx lss start # community image with token
|
|
216
|
+
npx lss start --pro # pro image (token required)
|
|
352
217
|
```
|
|
353
218
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
LSS includes comprehensive integration tests covering CLI, Orchestrator API, and Plugin functionality.
|
|
357
|
-
|
|
358
|
-
### Quick Start
|
|
359
|
-
|
|
360
|
-
```bash
|
|
361
|
-
# Run all tests
|
|
362
|
-
npm test
|
|
363
|
-
|
|
364
|
-
# Run with coverage
|
|
365
|
-
npm run test:coverage
|
|
366
|
-
|
|
367
|
-
# Run specific test suite
|
|
368
|
-
npm run test:cli
|
|
369
|
-
npm run test:orchestrator
|
|
370
|
-
npm run test:plugin
|
|
371
|
-
|
|
372
|
-
# Watch mode
|
|
373
|
-
npm run test:watch
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
### Using Test Runner Script
|
|
377
|
-
|
|
378
|
-
```bash
|
|
379
|
-
# Run all integration tests
|
|
380
|
-
./run-tests.sh
|
|
381
|
-
|
|
382
|
-
# Run specific suite
|
|
383
|
-
./run-tests.sh cli
|
|
384
|
-
./run-tests.sh orchestrator
|
|
385
|
-
./run-tests.sh plugin
|
|
386
|
-
|
|
387
|
-
# Run with coverage
|
|
388
|
-
./run-tests.sh coverage
|
|
389
|
-
|
|
390
|
-
# Watch mode
|
|
391
|
-
./run-tests.sh watch
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
### Test Coverage
|
|
395
|
-
|
|
396
|
-
The test suite validates:
|
|
397
|
-
|
|
398
|
-
✅ **CLI Commands**
|
|
399
|
-
- `npx lss start` - Orchestrator startup
|
|
400
|
-
- `npx lss stop` - Graceful shutdown
|
|
401
|
-
- `npx lss status` - Status reporting
|
|
402
|
-
- `npx lss logs` - Log viewing
|
|
403
|
-
- `npx lss help` - Help information
|
|
219
|
+
Details (`mode`, `localstackEdition`, `localstackVersion`, `localstackImage`):
|
|
220
|
+
[docs/CONFIGURATION.md](docs/CONFIGURATION.md).
|
|
404
221
|
|
|
405
|
-
|
|
406
|
-
- Service registration
|
|
407
|
-
- Resource provisioning (DynamoDB, SQS, SNS)
|
|
408
|
-
- Lambda proxy creation
|
|
409
|
-
- Event source mappings
|
|
410
|
-
- Error handling
|
|
222
|
+
## Dashboard
|
|
411
223
|
|
|
412
|
-
|
|
413
|
-
-
|
|
414
|
-
|
|
415
|
-
|
|
224
|
+
The Vue 3 dashboard at `http://localhost:3100` has seven tabs — **Overview** (health,
|
|
225
|
+
config snapshot), **Services** (status, start/stop, live logs, per-service resource
|
|
226
|
+
breakdown incl. EventBridge buses & rules), **Lambdas** (registry + invoke), **APIs**
|
|
227
|
+
(emulated HTTP routes), **Queues** (send/receive/purge, consumers), **S3** (objects,
|
|
228
|
+
upload/download), **DynamoDB** (items explorer, editor, TTL, seeds). A region selector
|
|
229
|
+
lets you inspect resources in any region.
|
|
416
230
|
|
|
417
|
-
|
|
231
|
+
It can carry your team's identity via the `branding` config key: navbar title/subtitle,
|
|
232
|
+
logo and favicon (URL or a file next to `lss.config.json`), default theme, and any
|
|
233
|
+
[TreeUI](https://www.npmjs.com/package/@treeui/vue) color token per theme:
|
|
418
234
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
235
|
+
```jsonc
|
|
236
|
+
"branding": {
|
|
237
|
+
"title": "Acme Cloud",
|
|
238
|
+
"subtitle": "Sandbox local",
|
|
239
|
+
"logo": "./assets/acme.svg",
|
|
240
|
+
"defaultTheme": "light",
|
|
241
|
+
"colors": { "brand-primary": "#e63946", "brand-hover": "#c1121f" },
|
|
242
|
+
"themeColors": { "dark": { "bg-primary": "#0d1b2a" } }
|
|
243
|
+
}
|
|
425
244
|
```
|
|
426
245
|
|
|
427
246
|
## How It Works
|
|
428
247
|
|
|
429
|
-
###
|
|
248
|
+
### Registration & provisioning
|
|
430
249
|
|
|
431
250
|
```mermaid
|
|
432
251
|
sequenceDiagram
|
|
433
252
|
participant Dev as Developer
|
|
434
|
-
participant
|
|
253
|
+
participant Plugin as serverless-lss<br/>(plugin)
|
|
435
254
|
participant Orch as Orchestrator
|
|
436
|
-
participant
|
|
437
|
-
|
|
438
|
-
participant SLS as Serverless Offline
|
|
439
|
-
|
|
440
|
-
Note over Dev,SLS: 1. Start LSS Environment
|
|
441
|
-
Dev->>CLI: npx lss start
|
|
442
|
-
CLI->>Orch: Start orchestrator (port 3100)
|
|
443
|
-
Orch->>LS: Start LocalStack container (port 4566)
|
|
444
|
-
LS-->>Orch: Ready
|
|
445
|
-
Orch-->>CLI: ✅ Running (PID saved)
|
|
446
|
-
CLI-->>Dev: Dashboard: http://localhost:3100
|
|
447
|
-
|
|
448
|
-
Note over Dev,SLS: 2. Register Microservice
|
|
255
|
+
participant Eng as Engine<br/>(self or LocalStack)
|
|
256
|
+
|
|
449
257
|
Dev->>Plugin: sls package
|
|
450
|
-
Plugin->>Plugin: Read CloudFormation template
|
|
451
258
|
Plugin->>Orch: POST /api/services/register
|
|
452
|
-
Note right of Plugin: Sends:
|
|
453
|
-
|
|
454
|
-
Orch->>
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
Orch->>LS: Create DynamoDB tables
|
|
459
|
-
LS-->>Orch: Tables created
|
|
460
|
-
Orch->>LS: Create SQS queues (+ DLQs)
|
|
461
|
-
LS-->>Orch: Queues created
|
|
462
|
-
Orch->>LS: Create SNS topics
|
|
463
|
-
LS-->>Orch: Topics created
|
|
464
|
-
|
|
465
|
-
Note over Orch,LS: 4. Create Lambda Proxies (on-demand)
|
|
466
|
-
loop For each Event Source Mapping
|
|
467
|
-
Orch->>Orch: Generate proxy Lambda code
|
|
468
|
-
Note right of Orch: Proxy points to<br/>Serverless Offline
|
|
469
|
-
Orch->>LS: Create Lambda proxy function
|
|
470
|
-
LS-->>Orch: Proxy created
|
|
471
|
-
Orch->>LS: Create Event Source Mapping
|
|
472
|
-
Note right of Orch: SQS/DynamoDB/SNS → Lambda
|
|
473
|
-
LS-->>Orch: Mapping active
|
|
474
|
-
end
|
|
475
|
-
|
|
476
|
-
Orch-->>Plugin: ✅ Service registered
|
|
477
|
-
Plugin-->>Dev: ✅ Provisioned resources
|
|
478
|
-
|
|
479
|
-
Note over Dev,SLS: 5. Start Application
|
|
480
|
-
Dev->>SLS: serverless offline start
|
|
481
|
-
Note right of SLS: Starts on port 3020<br/>Lambda invoke: 13020
|
|
482
|
-
SLS-->>Dev: ✅ Handlers ready
|
|
259
|
+
Note right of Plugin: Sends: servicePath,<br/>apiPort, invokePort, region
|
|
260
|
+
Orch->>Orch: Read + parse CloudFormation template<br/>from servicePath/.serverless/
|
|
261
|
+
Orch->>Eng: Create tables, queues, topics,<br/>buckets, buses, rules
|
|
262
|
+
Orch->>Eng: Wire event source mappings<br/>(SQS/streams/S3/EventBridge → Lambda)
|
|
263
|
+
Orch->>Orch: Start Lambda runtime worker<br/>+ API listener (30xx) + invoke listener (130xx)
|
|
264
|
+
Orch-->>Plugin: ✅ registered (N resources)
|
|
483
265
|
```
|
|
484
266
|
|
|
485
|
-
|
|
267
|
+
The plugin itself only reports *where* the service lives — the orchestrator reads
|
|
268
|
+
`.serverless/cloudformation-template-update-stack.json` from that path (running
|
|
269
|
+
`sls package` generates it; `autoPackage: true` lets the orchestrator regenerate it
|
|
270
|
+
on demand).
|
|
271
|
+
|
|
272
|
+
### Event flow
|
|
486
273
|
|
|
487
274
|
```mermaid
|
|
488
275
|
sequenceDiagram
|
|
489
276
|
participant App as Application
|
|
490
|
-
participant
|
|
491
|
-
participant
|
|
492
|
-
participant
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
Note over
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
SQS-->>LS: Return message(s)
|
|
505
|
-
|
|
506
|
-
LS->>Proxy: Invoke Lambda proxy
|
|
507
|
-
Note right of LS: Event with Records[]:<br/>- SQS message body<br/>- Attributes<br/>- Message ID
|
|
508
|
-
|
|
509
|
-
Note over Proxy,SLS: Proxy Forwards to Serverless Offline
|
|
510
|
-
Proxy->>Proxy: Transform event if needed
|
|
511
|
-
Note right of Proxy: Ensure Records[] format
|
|
512
|
-
|
|
513
|
-
Proxy->>SLS: HTTP POST /2015-03-31/functions/<br/>{functionName}/invocations
|
|
514
|
-
Note right of Proxy: Headers:<br/>- Content-Type: application/json<br/>- X-Amz-Invocation-Type
|
|
515
|
-
|
|
516
|
-
SLS->>Handler: Execute handler(event, context)
|
|
517
|
-
Note right of Handler: Real business logic<br/>runs here
|
|
518
|
-
|
|
519
|
-
alt Handler Success
|
|
520
|
-
Handler-->>SLS: Return response
|
|
521
|
-
SLS-->>Proxy: 200 OK + response body
|
|
522
|
-
Proxy-->>LS: Success
|
|
523
|
-
LS->>SQS: Delete message from queue
|
|
524
|
-
else Handler Error
|
|
525
|
-
Handler-->>SLS: Throw error
|
|
526
|
-
SLS-->>Proxy: 500 Error
|
|
527
|
-
Proxy-->>LS: Error
|
|
528
|
-
LS->>SQS: Return to queue or send to DLQ
|
|
529
|
-
Note right of SQS: Based on retry policy
|
|
277
|
+
participant Eng as Engine<br/>(SQS queue)
|
|
278
|
+
participant RT as LSS Lambda runtime
|
|
279
|
+
participant H as Your handler
|
|
280
|
+
|
|
281
|
+
App->>Eng: SendMessage (AWS SDK)
|
|
282
|
+
Eng->>RT: Event batch {Records: [...]}
|
|
283
|
+
Note over Eng,RT: self engine: in-process dispatch<br/>LocalStack: proxy Lambda → HTTP → invoke listener
|
|
284
|
+
RT->>H: handler(event, context)
|
|
285
|
+
alt success
|
|
286
|
+
H-->>RT: return
|
|
287
|
+
RT-->>Eng: ok → message deleted
|
|
288
|
+
else error
|
|
289
|
+
H-->>RT: throw
|
|
290
|
+
RT-->>Eng: fail → redelivery / DLQ
|
|
530
291
|
end
|
|
531
|
-
|
|
532
|
-
Note over App,Handler: Processing Complete
|
|
533
292
|
```
|
|
534
293
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
- Developer runs `sls package` in their microservice
|
|
539
|
-
- Plugin reads `.serverless/cloudformation-template-update-stack.json`
|
|
540
|
-
- Plugin POSTs to orchestrator `/api/services/register` with service metadata
|
|
541
|
-
|
|
542
|
-
2. **Resource Provisioning**:
|
|
543
|
-
- Orchestrator parses CloudFormation template
|
|
544
|
-
- Extracts DynamoDB tables, SQS queues, SNS topics
|
|
545
|
-
- Creates resources in LocalStack via AWS SDK
|
|
546
|
-
- **Only creates Lambda proxies when Event Source Mappings exist**
|
|
547
|
-
- Generates proxy code that forwards to serverless-offline invoke endpoint
|
|
548
|
-
- Creates event source mappings (SQS/DynamoDB/SNS → Lambda)
|
|
549
|
-
|
|
550
|
-
3. **Event Flow**:
|
|
551
|
-
- Message arrives in SQS queue
|
|
552
|
-
- LocalStack polls queue via event source mapping
|
|
553
|
-
- Lambda proxy is triggered automatically
|
|
554
|
-
- Proxy transforms event and makes HTTP POST to serverless-offline
|
|
555
|
-
- Real handler executes in serverless-offline process
|
|
556
|
-
- Response returned through proxy chain
|
|
557
|
-
- Message deleted from queue on success, or sent to DLQ on failure
|
|
558
|
-
|
|
559
|
-
> **Self-engine mode collapses this whole chain**: the engine's event source mapping
|
|
560
|
-
> delivers the SQS batch **in-process** to the LSS Lambda runtime — no LocalStack
|
|
561
|
-
> polling, no proxy Lambda, no HTTP hop:
|
|
562
|
-
>
|
|
563
|
-
> ```
|
|
564
|
-
> LocalStack mode: SQS → LocalStack ESM → proxy Lambda (container) → HTTP → handler
|
|
565
|
-
> Self engine: SQS (engine) → dispatcher → handler
|
|
566
|
-
> ```
|
|
567
|
-
>
|
|
568
|
-
> The same applies to DynamoDB streams, S3 notifications and EventBridge targets.
|
|
569
|
-
|
|
570
|
-
## CLI Implementation Details
|
|
571
|
-
|
|
572
|
-
The `npx lss` CLI is implemented in `/bin/cli.js` and provides:
|
|
573
|
-
|
|
574
|
-
- **Background Process Management**: Uses `spawn` with `detached: true` to run orchestrator independently
|
|
575
|
-
- **PID File**: Stores process ID in `/tmp/lss-orchestrator-{serverPort}.pid` (or `/tmp/lss-orchestrator.pid` when serverPort is the default 3100). The port-scoped path lets multiple LSS instances coexist — one per project — without trampling each other.
|
|
576
|
-
- **Log File**: Redirects stdout/stderr to `/tmp/lss-orchestrator-{serverPort}.log` (or `/tmp/lss-orchestrator.log` for the default port).
|
|
577
|
-
- **Process Monitoring**: Checks if process is alive before starting/stopping
|
|
578
|
-
- **Clean Shutdown**: Sends SIGTERM for graceful termination
|
|
579
|
-
|
|
580
|
-
### Files
|
|
581
|
-
|
|
582
|
-
- **PID File**: `/tmp/lss-orchestrator-{serverPort}.pid`
|
|
583
|
-
- **Log File**: `/tmp/lss-orchestrator-{serverPort}.log`
|
|
294
|
+
The same flow applies to DynamoDB streams, S3 notifications and EventBridge targets.
|
|
295
|
+
In LocalStack mode the hop goes through a generated proxy Lambda inside the container;
|
|
296
|
+
in self-engine mode the dispatcher calls the runtime directly — no proxy, no polling.
|
|
584
297
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
### Check Logs
|
|
298
|
+
If you still want serverless-offline to own the ports for a service, disable the
|
|
299
|
+
LSS runtime globally or per service with `lambdaRuntime.enabled`/`serviceRuntime`.
|
|
588
300
|
|
|
589
|
-
|
|
590
|
-
npx lss logs
|
|
301
|
+
## Architecture
|
|
591
302
|
|
|
592
|
-
# Or directly
|
|
593
|
-
tail -f /tmp/lss-orchestrator.log
|
|
594
303
|
```
|
|
304
|
+
local-serverless-stack/
|
|
305
|
+
├── bin/cli.js # CLI entry point (npx lss)
|
|
306
|
+
├── src/
|
|
307
|
+
│ ├── server/ # Express API + orchestration
|
|
308
|
+
│ │ ├── routes/ # HTTP endpoints (/api/services, /api/queues, …)
|
|
309
|
+
│ │ ├── services/ # provisioner, registrar, packager, seeds, …
|
|
310
|
+
│ │ ├── engine/ # self engine (in-process AWS emulation)
|
|
311
|
+
│ │ ├── runtime/ # Lambda runtime + API Gateway emulation
|
|
312
|
+
│ │ └── dev/ # dev utilities (DynamoDB proxy)
|
|
313
|
+
│ ├── client/ # programmatic client (LssClient) — package entry point
|
|
314
|
+
│ └── ui/ # Vue 3 dashboard (npm workspace, @treeui/vue)
|
|
315
|
+
├── packages/serverless-plugin/ # serverless-lss (published separately)
|
|
316
|
+
├── docs/ # reference docs
|
|
317
|
+
├── examples/ # runnable sample projects
|
|
318
|
+
└── tests/ # unit + integration suites
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
- **CLI** (`bin/cli.js`): background process management (start/stop/status/logs/seed)
|
|
322
|
+
- **Server** (`src/server/`): Express API + engine orchestration; serves the built UI
|
|
323
|
+
- **Engine** (`src/server/engine/`): the AWS provider behind everything — in-process **self engine** (:14566, no Docker) or managed/external **LocalStack** (:4566)
|
|
324
|
+
- **Client** (`src/client/`): `LssClient` — the same API surface as the dashboard, from code
|
|
325
|
+
- **Plugin** (`packages/serverless-plugin/`): auto-registration on `sls package`
|
|
595
326
|
|
|
596
|
-
|
|
327
|
+
## Development
|
|
597
328
|
|
|
598
329
|
```bash
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
#
|
|
603
|
-
|
|
604
|
-
ls -la /workspaces/local-serverless-stack/dist/ui/
|
|
605
|
-
|
|
606
|
-
# Rebuild if needed
|
|
607
|
-
npm run build
|
|
330
|
+
git clone https://github.com/viserion77/local-serverless-stack.git
|
|
331
|
+
cd local-serverless-stack
|
|
332
|
+
npm run setup # install root + UI workspace deps
|
|
333
|
+
npm run dev # server (tsx watch) + UI (vite) concurrently
|
|
334
|
+
npm run build # ui + server + client + plugin
|
|
608
335
|
```
|
|
609
336
|
|
|
610
|
-
|
|
337
|
+
Granular builds: `server:build`, `ui:build`, `client:build`, `plugin:build`.
|
|
611
338
|
|
|
612
|
-
|
|
339
|
+
### Testing
|
|
613
340
|
|
|
614
341
|
```bash
|
|
615
|
-
#
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
#
|
|
619
|
-
|
|
342
|
+
npm test # unit suite (jest)
|
|
343
|
+
npm run test:coverage # with coverage (CI gate)
|
|
344
|
+
npm run test:watch # watch mode
|
|
345
|
+
npm run test:integration # boots a real orchestrator (Docker/LocalStack required)
|
|
346
|
+
npm run lint # eslint
|
|
347
|
+
npx jest tests/unit/services/config-manager.test.ts # a single suite
|
|
620
348
|
```
|
|
621
349
|
|
|
622
|
-
##
|
|
623
|
-
|
|
624
|
-
### DynamoDB Proxy (Port 8000)
|
|
625
|
-
|
|
626
|
-
The orchestrator includes an optional reverse proxy on port 8000 that forwards to LocalStack (4566).
|
|
350
|
+
## Troubleshooting
|
|
627
351
|
|
|
628
|
-
Enable with:
|
|
629
352
|
```bash
|
|
630
|
-
|
|
353
|
+
npx lss status # running? which ports?
|
|
354
|
+
npx lss logs # orchestrator log (also: $TMPDIR/lss-orchestrator*.log)
|
|
355
|
+
ls dist/server dist/ui # built? if not: npm run build
|
|
356
|
+
lsof -i :3100 # who owns the port?
|
|
631
357
|
```
|
|
632
358
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
359
|
+
- **Plugin registers nothing** → is `orchestratorUrl` pointing at the right `serverPort`? Try `ORCHESTRATOR_URL=http://localhost:3100 npx sls package`.
|
|
360
|
+
- **Ports 4566–4599 behave strangely** → a real LocalStack install may intercept the whole range; the self engine defaults to 14566 for this reason.
|
|
361
|
+
- **DynamoDB on port 8000 expected by your tooling** → enable the proxy: `lss start --enable-dynamo-proxy` (or `enableDynamoProxy: true`); it forwards to the active engine.
|
|
636
362
|
|
|
637
|
-
|
|
363
|
+
## Contributing & Releasing
|
|
638
364
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
- ✅ CLI with start/stop/status/logs commands
|
|
644
|
-
- ✅ Background process management
|
|
645
|
-
- ✅ Serverless Framework plugin
|
|
646
|
-
- ✅ Auto-provisioning of AWS resources
|
|
647
|
-
- ✅ Event source mapping (SQS → Lambda)
|
|
648
|
-
- ✅ Web dashboard (Vue 3)
|
|
649
|
-
- ✅ npm link support for local development
|
|
650
|
-
|
|
651
|
-
## Use Case Example
|
|
652
|
-
|
|
653
|
-
LSS can be used in monorepo setups to manage 15+ microservices with a single LocalStack instance. This eliminates the complexity of running multiple LocalStack containers and provides a unified development experience.
|
|
654
|
-
|
|
655
|
-
Integration approach:
|
|
656
|
-
- Place LSS in a dedicated directory (e.g., `/workspaces/local-serverless-stack`)
|
|
657
|
-
- Use `npm link` for local development and seamless updates
|
|
658
|
-
- Install the plugin in each microservice that needs AWS resource orchestration
|
|
659
|
-
- Orchestrator managed via `npx lss start/stop` commands
|
|
660
|
-
|
|
661
|
-
## Contributing
|
|
662
|
-
|
|
663
|
-
Contributions welcome! This is an open-source project designed to simplify local serverless development.
|
|
365
|
+
Contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). Release process
|
|
366
|
+
(automated npm publish on version bump): [docs/RELEASE.md](docs/RELEASE.md).
|
|
367
|
+
Changelog: [CHANGELOG.md](CHANGELOG.md).
|
|
664
368
|
|
|
665
369
|
## License
|
|
666
370
|
|
|
667
371
|
MIT
|
|
668
|
-
|
|
669
|
-
## Publishing to npm
|
|
670
|
-
|
|
671
|
-
⚠️ **For maintainers only**
|
|
672
|
-
|
|
673
|
-
### Automatic Publishing (Recommended)
|
|
674
|
-
|
|
675
|
-
The project uses GitHub Actions for automatic publishing to NPM when you update the version:
|
|
676
|
-
|
|
677
|
-
**1. Update version in package.json**:
|
|
678
|
-
```bash
|
|
679
|
-
# For the root package (CLI + orchestrator)
|
|
680
|
-
npm version patch # 0.0.1 -> 0.0.2
|
|
681
|
-
npm version minor # 0.0.1 -> 0.1.0
|
|
682
|
-
npm version major # 0.0.1 -> 1.0.0
|
|
683
|
-
```
|
|
684
|
-
|
|
685
|
-
**2. Push to main branch**:
|
|
686
|
-
```bash
|
|
687
|
-
git add package.json CHANGELOG.md
|
|
688
|
-
git commit -m "chore: bump version to 0.0.2"
|
|
689
|
-
git push origin main
|
|
690
|
-
```
|
|
691
|
-
|
|
692
|
-
**3. GitHub Actions will automatically**:
|
|
693
|
-
- ✅ Detect version change
|
|
694
|
-
- ✅ Run full test suite
|
|
695
|
-
- ✅ Build the project
|
|
696
|
-
- ✅ Publish to NPM
|
|
697
|
-
- ✅ Create a git tag (e.g., `v0.0.2`)
|
|
698
|
-
|
|
699
|
-
### Plugin Package
|
|
700
|
-
|
|
701
|
-
To publish the serverless plugin separately:
|
|
702
|
-
|
|
703
|
-
```bash
|
|
704
|
-
cd packages/serverless-plugin
|
|
705
|
-
npm version patch
|
|
706
|
-
cd ../..
|
|
707
|
-
git add packages/serverless-plugin/package.json
|
|
708
|
-
git commit -m "chore(plugin): bump version to 0.0.2"
|
|
709
|
-
git push origin main
|
|
710
|
-
```
|
|
711
|
-
|
|
712
|
-
### Required Setup (One-time)
|
|
713
|
-
|
|
714
|
-
Before automatic publishing works:
|
|
715
|
-
|
|
716
|
-
1. **NPM Access Token**:
|
|
717
|
-
- Go to npmjs.com → Access Tokens → Generate New Token
|
|
718
|
-
- Select "Automation" type
|
|
719
|
-
- Copy the token
|
|
720
|
-
|
|
721
|
-
2. **GitHub Secret**:
|
|
722
|
-
- Go to your repo → Settings → Secrets and variables → Actions
|
|
723
|
-
- Add new repository secret: `NPM_TOKEN`
|
|
724
|
-
- Paste your NPM token
|
|
725
|
-
|
|
726
|
-
### Pre-publish Checklist
|
|
727
|
-
|
|
728
|
-
1. ✅ All tests passing
|
|
729
|
-
2. ✅ Build successful (`npm run build`)
|
|
730
|
-
3. ✅ Version updated in `package.json`
|
|
731
|
-
4. ✅ CHANGELOG.md updated
|
|
732
|
-
5. ✅ README.md updated
|
|
733
|
-
6. ✅ No breaking changes (or properly documented)
|
|
734
|
-
|
|
735
|
-
### Manual Publishing (Emergency Only)
|
|
736
|
-
|
|
737
|
-
If GitHub Actions fails, you can publish manually:
|
|
738
|
-
|
|
739
|
-
```bash
|
|
740
|
-
# 1. Ensure clean working directory
|
|
741
|
-
git status
|
|
742
|
-
|
|
743
|
-
# 2. Build all packages
|
|
744
|
-
npm run build
|
|
745
|
-
|
|
746
|
-
# 3. Test the package contents
|
|
747
|
-
npm pack
|
|
748
|
-
tar -tzf local-serverless-stack-*.tgz
|
|
749
|
-
|
|
750
|
-
# 4. Publish to npm (dry-run first)
|
|
751
|
-
npm publish --dry-run
|
|
752
|
-
|
|
753
|
-
# 5. Publish for real
|
|
754
|
-
npm publish --access public
|
|
755
|
-
|
|
756
|
-
# 6. Create git tag
|
|
757
|
-
git tag v0.0.1
|
|
758
|
-
git push origin v0.0.1
|
|
759
|
-
```
|
|
760
|
-
|
|
761
|
-
### What Gets Published
|
|
762
|
-
|
|
763
|
-
The `files` field in package.json controls what's published:
|
|
764
|
-
|
|
765
|
-
- `bin/` - CLI scripts
|
|
766
|
-
- `dist/` - Compiled server + UI
|
|
767
|
-
- `packages/serverless-plugin/dist/` - Compiled plugin
|
|
768
|
-
- `README.md`, `LICENSE`, `CHANGELOG.md`
|
|
769
|
-
|
|
770
|
-
Source files and development dependencies are **not** included.
|
|
771
|
-
|
|
772
|
-
### Post-publish
|
|
773
|
-
|
|
774
|
-
After publishing, users can install with:
|
|
775
|
-
|
|
776
|
-
```bash
|
|
777
|
-
npm install local-serverless-stack
|
|
778
|
-
npx lss start
|
|
779
|
-
```
|
|
780
|
-
|
|
781
|
-
No build step required for end users!
|