local-serverless-stack 0.6.0 → 0.8.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 (215) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +99 -11
  3. package/bin/cli.js +31 -3
  4. package/dist/server/engine/backends/localstack-backend.d.ts +25 -0
  5. package/dist/server/engine/backends/localstack-backend.d.ts.map +1 -0
  6. package/dist/server/engine/backends/localstack-backend.js +199 -0
  7. package/dist/server/engine/backends/localstack-backend.js.map +1 -0
  8. package/dist/server/engine/backends/self-backend.d.ts +32 -0
  9. package/dist/server/engine/backends/self-backend.d.ts.map +1 -0
  10. package/dist/server/engine/backends/self-backend.js +205 -0
  11. package/dist/server/engine/backends/self-backend.js.map +1 -0
  12. package/dist/server/engine/bus.d.ts +10 -0
  13. package/dist/server/engine/bus.d.ts.map +1 -0
  14. package/dist/server/engine/bus.js +24 -0
  15. package/dist/server/engine/bus.js.map +1 -0
  16. package/dist/server/engine/dispatch/dispatcher.d.ts +46 -0
  17. package/dist/server/engine/dispatch/dispatcher.d.ts.map +1 -0
  18. package/dist/server/engine/dispatch/dispatcher.js +312 -0
  19. package/dist/server/engine/dispatch/dispatcher.js.map +1 -0
  20. package/dist/server/engine/dispatch/scheduler.d.ts +47 -0
  21. package/dist/server/engine/dispatch/scheduler.d.ts.map +1 -0
  22. package/dist/server/engine/dispatch/scheduler.js +328 -0
  23. package/dist/server/engine/dispatch/scheduler.js.map +1 -0
  24. package/dist/server/engine/dispatch/sqs-poller.d.ts +25 -0
  25. package/dist/server/engine/dispatch/sqs-poller.d.ts.map +1 -0
  26. package/dist/server/engine/dispatch/sqs-poller.js +242 -0
  27. package/dist/server/engine/dispatch/sqs-poller.js.map +1 -0
  28. package/dist/server/engine/dispatch/stream-tailer.d.ts +22 -0
  29. package/dist/server/engine/dispatch/stream-tailer.d.ts.map +1 -0
  30. package/dist/server/engine/dispatch/stream-tailer.js +205 -0
  31. package/dist/server/engine/dispatch/stream-tailer.js.map +1 -0
  32. package/dist/server/engine/emulators/dynamodb/expressions/decimal.d.ts +5 -0
  33. package/dist/server/engine/emulators/dynamodb/expressions/decimal.d.ts.map +1 -0
  34. package/dist/server/engine/emulators/dynamodb/expressions/decimal.js +91 -0
  35. package/dist/server/engine/emulators/dynamodb/expressions/decimal.js.map +1 -0
  36. package/dist/server/engine/emulators/dynamodb/expressions/evaluate.d.ts +24 -0
  37. package/dist/server/engine/emulators/dynamodb/expressions/evaluate.d.ts.map +1 -0
  38. package/dist/server/engine/emulators/dynamodb/expressions/evaluate.js +183 -0
  39. package/dist/server/engine/emulators/dynamodb/expressions/evaluate.js.map +1 -0
  40. package/dist/server/engine/emulators/dynamodb/expressions/expression-types.d.ts +29 -0
  41. package/dist/server/engine/emulators/dynamodb/expressions/expression-types.d.ts.map +1 -0
  42. package/dist/server/engine/emulators/dynamodb/expressions/expression-types.js +12 -0
  43. package/dist/server/engine/emulators/dynamodb/expressions/expression-types.js.map +1 -0
  44. package/dist/server/engine/emulators/dynamodb/expressions/index.d.ts +13 -0
  45. package/dist/server/engine/emulators/dynamodb/expressions/index.d.ts.map +1 -0
  46. package/dist/server/engine/emulators/dynamodb/expressions/index.js +244 -0
  47. package/dist/server/engine/emulators/dynamodb/expressions/index.js.map +1 -0
  48. package/dist/server/engine/emulators/dynamodb/expressions/lexer.d.ts +11 -0
  49. package/dist/server/engine/emulators/dynamodb/expressions/lexer.d.ts.map +1 -0
  50. package/dist/server/engine/emulators/dynamodb/expressions/lexer.js +109 -0
  51. package/dist/server/engine/emulators/dynamodb/expressions/lexer.js.map +1 -0
  52. package/dist/server/engine/emulators/dynamodb/expressions/parser.d.ts +23 -0
  53. package/dist/server/engine/emulators/dynamodb/expressions/parser.d.ts.map +1 -0
  54. package/dist/server/engine/emulators/dynamodb/expressions/parser.js +541 -0
  55. package/dist/server/engine/emulators/dynamodb/expressions/parser.js.map +1 -0
  56. package/dist/server/engine/emulators/dynamodb/index.d.ts +46 -0
  57. package/dist/server/engine/emulators/dynamodb/index.d.ts.map +1 -0
  58. package/dist/server/engine/emulators/dynamodb/index.js +572 -0
  59. package/dist/server/engine/emulators/dynamodb/index.js.map +1 -0
  60. package/dist/server/engine/emulators/dynamodb/query.d.ts +12 -0
  61. package/dist/server/engine/emulators/dynamodb/query.d.ts.map +1 -0
  62. package/dist/server/engine/emulators/dynamodb/query.js +237 -0
  63. package/dist/server/engine/emulators/dynamodb/query.js.map +1 -0
  64. package/dist/server/engine/emulators/dynamodb/schema.d.ts +58 -0
  65. package/dist/server/engine/emulators/dynamodb/schema.d.ts.map +1 -0
  66. package/dist/server/engine/emulators/dynamodb/schema.js +284 -0
  67. package/dist/server/engine/emulators/dynamodb/schema.js.map +1 -0
  68. package/dist/server/engine/emulators/dynamodb/streams.d.ts +28 -0
  69. package/dist/server/engine/emulators/dynamodb/streams.d.ts.map +1 -0
  70. package/dist/server/engine/emulators/dynamodb/streams.js +100 -0
  71. package/dist/server/engine/emulators/dynamodb/streams.js.map +1 -0
  72. package/dist/server/engine/emulators/events/index.d.ts +53 -0
  73. package/dist/server/engine/emulators/events/index.d.ts.map +1 -0
  74. package/dist/server/engine/emulators/events/index.js +417 -0
  75. package/dist/server/engine/emulators/events/index.js.map +1 -0
  76. package/dist/server/engine/emulators/events/pattern.d.ts +3 -0
  77. package/dist/server/engine/emulators/events/pattern.d.ts.map +1 -0
  78. package/dist/server/engine/emulators/events/pattern.js +125 -0
  79. package/dist/server/engine/emulators/events/pattern.js.map +1 -0
  80. package/dist/server/engine/emulators/lambda-ctl/index.d.ts +55 -0
  81. package/dist/server/engine/emulators/lambda-ctl/index.d.ts.map +1 -0
  82. package/dist/server/engine/emulators/lambda-ctl/index.js +461 -0
  83. package/dist/server/engine/emulators/lambda-ctl/index.js.map +1 -0
  84. package/dist/server/engine/emulators/s3/index.d.ts +45 -0
  85. package/dist/server/engine/emulators/s3/index.d.ts.map +1 -0
  86. package/dist/server/engine/emulators/s3/index.js +591 -0
  87. package/dist/server/engine/emulators/s3/index.js.map +1 -0
  88. package/dist/server/engine/emulators/sns/index.d.ts +22 -0
  89. package/dist/server/engine/emulators/sns/index.d.ts.map +1 -0
  90. package/dist/server/engine/emulators/sns/index.js +135 -0
  91. package/dist/server/engine/emulators/sns/index.js.map +1 -0
  92. package/dist/server/engine/emulators/sqs/index.d.ts +66 -0
  93. package/dist/server/engine/emulators/sqs/index.d.ts.map +1 -0
  94. package/dist/server/engine/emulators/sqs/index.js +552 -0
  95. package/dist/server/engine/emulators/sqs/index.js.map +1 -0
  96. package/dist/server/engine/emulators/sqs/md5.d.ts +8 -0
  97. package/dist/server/engine/emulators/sqs/md5.d.ts.map +1 -0
  98. package/dist/server/engine/emulators/sqs/md5.js +36 -0
  99. package/dist/server/engine/emulators/sqs/md5.js.map +1 -0
  100. package/dist/server/engine/emulators/sqs/queue.d.ts +105 -0
  101. package/dist/server/engine/emulators/sqs/queue.d.ts.map +1 -0
  102. package/dist/server/engine/emulators/sqs/queue.js +371 -0
  103. package/dist/server/engine/emulators/sqs/queue.js.map +1 -0
  104. package/dist/server/engine/emulators/sts.d.ts +8 -0
  105. package/dist/server/engine/emulators/sts.d.ts.map +1 -0
  106. package/dist/server/engine/emulators/sts.js +23 -0
  107. package/dist/server/engine/emulators/sts.js.map +1 -0
  108. package/dist/server/engine/engine-backend.d.ts +17 -0
  109. package/dist/server/engine/engine-backend.d.ts.map +1 -0
  110. package/dist/server/engine/engine-backend.js +7 -0
  111. package/dist/server/engine/engine-backend.js.map +1 -0
  112. package/dist/server/engine/engine-manager.d.ts +22 -0
  113. package/dist/server/engine/engine-manager.d.ts.map +1 -0
  114. package/dist/server/engine/engine-manager.js +74 -0
  115. package/dist/server/engine/engine-manager.js.map +1 -0
  116. package/dist/server/engine/http/aws-chunked.d.ts +3 -0
  117. package/dist/server/engine/http/aws-chunked.d.ts.map +1 -0
  118. package/dist/server/engine/http/aws-chunked.js +50 -0
  119. package/dist/server/engine/http/aws-chunked.js.map +1 -0
  120. package/dist/server/engine/http/errors.d.ts +20 -0
  121. package/dist/server/engine/http/errors.d.ts.map +1 -0
  122. package/dist/server/engine/http/errors.js +43 -0
  123. package/dist/server/engine/http/errors.js.map +1 -0
  124. package/dist/server/engine/http/protocols/aws-json.d.ts +8 -0
  125. package/dist/server/engine/http/protocols/aws-json.d.ts.map +1 -0
  126. package/dist/server/engine/http/protocols/aws-json.js +42 -0
  127. package/dist/server/engine/http/protocols/aws-json.js.map +1 -0
  128. package/dist/server/engine/http/protocols/query-xml.d.ts +7 -0
  129. package/dist/server/engine/http/protocols/query-xml.d.ts.map +1 -0
  130. package/dist/server/engine/http/protocols/query-xml.js +35 -0
  131. package/dist/server/engine/http/protocols/query-xml.js.map +1 -0
  132. package/dist/server/engine/http/router.d.ts +8 -0
  133. package/dist/server/engine/http/router.d.ts.map +1 -0
  134. package/dist/server/engine/http/router.js +391 -0
  135. package/dist/server/engine/http/router.js.map +1 -0
  136. package/dist/server/engine/http/sigv4.d.ts +9 -0
  137. package/dist/server/engine/http/sigv4.d.ts.map +1 -0
  138. package/dist/server/engine/http/sigv4.js +33 -0
  139. package/dist/server/engine/http/sigv4.js.map +1 -0
  140. package/dist/server/engine/http/xml.d.ts +16 -0
  141. package/dist/server/engine/http/xml.d.ts.map +1 -0
  142. package/dist/server/engine/http/xml.js +92 -0
  143. package/dist/server/engine/http/xml.js.map +1 -0
  144. package/dist/server/engine/store/atomic.d.ts +4 -0
  145. package/dist/server/engine/store/atomic.d.ts.map +1 -0
  146. package/dist/server/engine/store/atomic.js +35 -0
  147. package/dist/server/engine/store/atomic.js.map +1 -0
  148. package/dist/server/engine/store/engine-store.d.ts +9 -0
  149. package/dist/server/engine/store/engine-store.d.ts.map +1 -0
  150. package/dist/server/engine/store/engine-store.js +218 -0
  151. package/dist/server/engine/store/engine-store.js.map +1 -0
  152. package/dist/server/engine/store/store-types.d.ts +37 -0
  153. package/dist/server/engine/store/store-types.d.ts.map +1 -0
  154. package/dist/server/engine/store/store-types.js +17 -0
  155. package/dist/server/engine/store/store-types.js.map +1 -0
  156. package/dist/server/engine/store/wal.d.ts +49 -0
  157. package/dist/server/engine/store/wal.d.ts.map +1 -0
  158. package/dist/server/engine/store/wal.js +328 -0
  159. package/dist/server/engine/store/wal.js.map +1 -0
  160. package/dist/server/engine/types.d.ts +137 -0
  161. package/dist/server/engine/types.d.ts.map +1 -0
  162. package/dist/server/engine/types.js +8 -0
  163. package/dist/server/engine/types.js.map +1 -0
  164. package/dist/server/index.js +12 -9
  165. package/dist/server/index.js.map +1 -1
  166. package/dist/server/routes/services.d.ts.map +1 -1
  167. package/dist/server/routes/services.js +2 -0
  168. package/dist/server/routes/services.js.map +1 -1
  169. package/dist/server/services/cloudformation-parser.d.ts +26 -2
  170. package/dist/server/services/cloudformation-parser.d.ts.map +1 -1
  171. package/dist/server/services/cloudformation-parser.js +60 -3
  172. package/dist/server/services/cloudformation-parser.js.map +1 -1
  173. package/dist/server/services/config-manager.d.ts +27 -0
  174. package/dist/server/services/config-manager.d.ts.map +1 -1
  175. package/dist/server/services/config-manager.js +67 -7
  176. package/dist/server/services/config-manager.js.map +1 -1
  177. package/dist/server/services/localstack-manager.d.ts +0 -7
  178. package/dist/server/services/localstack-manager.d.ts.map +1 -1
  179. package/dist/server/services/localstack-manager.js +11 -173
  180. package/dist/server/services/localstack-manager.js.map +1 -1
  181. package/dist/server/services/resource-provisioner.d.ts +6 -0
  182. package/dist/server/services/resource-provisioner.d.ts.map +1 -1
  183. package/dist/server/services/resource-provisioner.js +171 -7
  184. package/dist/server/services/resource-provisioner.js.map +1 -1
  185. package/dist/server/services/service-registrar.js +2 -2
  186. package/dist/server/services/service-registrar.js.map +1 -1
  187. package/dist/ui/assets/ApisPage-a9i2qD0Z.js +1 -0
  188. package/dist/ui/assets/BucketDetailPage-Cz27N0KV.js +1 -0
  189. package/dist/ui/assets/BucketsPage-CZ7wGmUN.js +1 -0
  190. package/dist/ui/assets/{DynamoPage-B1__Rjr2.js → DynamoPage-BZMs1iW8.js} +1 -1
  191. package/dist/ui/assets/DynamoTablePage-BQsGkhtO.js +3 -0
  192. package/dist/ui/assets/LambdaDetailPage-DJb7xqRB.js +4 -0
  193. package/dist/ui/assets/LambdasPage-Ctg1l-Lg.js +1 -0
  194. package/dist/ui/assets/OverviewPage-DiijblCA.js +1 -0
  195. package/dist/ui/assets/QueueDetailPage-DRpSqost.js +1 -0
  196. package/dist/ui/assets/QueuesPage-CY0bDGwV.js +1 -0
  197. package/dist/ui/assets/ServiceDetailPage-CYTEdtts.js +2 -0
  198. package/dist/ui/assets/ServicesPage-OlV_rr-q.js +2 -0
  199. package/dist/ui/assets/index-C1KdKPDS.css +1 -0
  200. package/dist/ui/assets/index-DA_C1HOg.js +36 -0
  201. package/dist/ui/index.html +2 -2
  202. package/package.json +2 -1
  203. package/dist/ui/assets/ApisPage-DdgKjEdS.js +0 -1
  204. package/dist/ui/assets/BucketDetailPage-DZQGxm0y.js +0 -1
  205. package/dist/ui/assets/BucketsPage-xYXzxCvd.js +0 -1
  206. package/dist/ui/assets/DynamoTablePage-BCoxPdXW.js +0 -3
  207. package/dist/ui/assets/LambdaDetailPage-B85CA8tb.js +0 -4
  208. package/dist/ui/assets/LambdasPage-_TtxQMT_.js +0 -1
  209. package/dist/ui/assets/OverviewPage-CqTKTY64.js +0 -1
  210. package/dist/ui/assets/QueueDetailPage-BOr_sImA.js +0 -1
  211. package/dist/ui/assets/QueuesPage-DpByfcM5.js +0 -1
  212. package/dist/ui/assets/ServiceDetailPage-DsWgV-ad.js +0 -2
  213. package/dist/ui/assets/ServicesPage-CGlpsj98.js +0 -2
  214. package/dist/ui/assets/index-BWlB542w.js +0 -36
  215. package/dist/ui/assets/index-EYnsoJOq.css +0 -1
@@ -1,24 +1,11 @@
1
- import { spawn, exec } from 'child_process';
2
- import { promisify } from 'util';
3
- import { ConfigManager } from './config-manager.js';
4
- const execAsync = promisify(exec);
1
+ // Deprecated facade kept so the ~10 existing call sites (provisioner,
2
+ // explorers, seeds, dynamo-proxy, routes) stay untouched: they keep importing
3
+ // LocalStackManager, but the active provider may be the LocalStack container
4
+ // OR the in-process self engine — EngineManager decides from the config.
5
+ // New code should use EngineManager directly.
6
+ import { EngineManager } from '../engine/engine-manager.js';
5
7
  export class LocalStackManager {
6
8
  static instance;
7
- process = null;
8
- _isRunning = false;
9
- endpoint;
10
- // Container name is scoped to the LocalStack port so multiple LSS instances
11
- // (one per example/project) can launch their own container side by side.
12
- // Falls back to "lss-localstack" when the default 4566 is in use to preserve
13
- // existing teardown scripts that look for that name.
14
- containerName;
15
- configManager;
16
- constructor() {
17
- this.configManager = ConfigManager.getInstance();
18
- this.endpoint = this.configManager.getLocalStackEndpoint();
19
- const port = this.configManager.getLocalStackPort();
20
- this.containerName = port === 4566 ? 'lss-localstack' : `lss-localstack-${port}`;
21
- }
22
9
  static getInstance() {
23
10
  if (!LocalStackManager.instance) {
24
11
  LocalStackManager.instance = new LocalStackManager();
@@ -26,168 +13,19 @@ export class LocalStackManager {
26
13
  return LocalStackManager.instance;
27
14
  }
28
15
  async start() {
29
- if (this._isRunning) {
30
- console.log('⚠️ LocalStack already running');
31
- return;
32
- }
33
- if (this.configManager.isExternal()) {
34
- console.log(`🔗 Using external LocalStack at ${this.endpoint}`);
35
- await this.waitForReady(30);
36
- this._isRunning = true;
37
- console.log('✅ Connected to external LocalStack');
38
- return;
39
- }
40
- try {
41
- // Check if docker is available
42
- await execAsync('docker ps -q', { timeout: 5000 });
43
- }
44
- catch {
45
- throw new Error('Docker is not available or not running. Please start Docker first.');
46
- }
47
- const edition = this.configManager.getLocalStackEdition();
48
- const image = this.configManager.getLocalStackImage();
49
- const authToken = this.configManager.getLocalStackAuthToken();
50
- if (edition === 'pro' && !authToken) {
51
- throw new Error('LocalStack Pro requires LOCALSTACK_AUTH_TOKEN. Set the env var or "localstackAuthToken" in your config.');
52
- }
53
- if (edition === 'community' && !authToken) {
54
- console.warn('⚠️ LOCALSTACK_AUTH_TOKEN not set. Recent localstack/localstack images (>= 2026.5) require a token even for the community edition.');
55
- }
56
- return new Promise((resolve, reject) => {
57
- console.log(`🔄 Starting LocalStack (${image})...`);
58
- const port = this.configManager.getLocalStackPort();
59
- const services = this.configManager.getServices().join(',');
60
- const persistence = this.configManager.isPersistence() ? '1' : '0';
61
- const debug = this.configManager.isDebug() ? '1' : '0';
62
- // Persistence volume is scoped to the container so two LSS instances
63
- // don't share (and corrupt) the same on-disk state.
64
- const volumeName = this.containerName === 'lss-localstack'
65
- ? 'lss-localstack-data'
66
- : `${this.containerName}-data`;
67
- const dockerArgs = [
68
- 'run',
69
- '--rm',
70
- '-p',
71
- `${port}:4566`,
72
- '-v',
73
- `${volumeName}:/var/lib/localstack`,
74
- '-v',
75
- '/var/run/docker.sock:/var/run/docker.sock',
76
- // host.docker.internal resolves natively on Docker Desktop but not on
77
- // Linux; the generated Lambda proxies target it to reach the invoke
78
- // listeners on the host, so map it explicitly (no-op elsewhere).
79
- '--add-host',
80
- 'host.docker.internal:host-gateway',
81
- '--name',
82
- this.containerName,
83
- '-e',
84
- `SERVICES=${services}`,
85
- '-e',
86
- 'LAMBDA_EXECUTOR=local',
87
- // Lambda containers spawned BY LocalStack (which run the proxies) need
88
- // the same host mapping.
89
- '-e',
90
- 'LAMBDA_DOCKER_FLAGS=--add-host host.docker.internal:host-gateway',
91
- '-e',
92
- `PERSISTENCE=${persistence}`,
93
- '-e',
94
- `DEBUG=${debug}`,
95
- ];
96
- if (authToken) {
97
- dockerArgs.push('-e', `LOCALSTACK_AUTH_TOKEN=${authToken}`);
98
- }
99
- dockerArgs.push(image);
100
- this.process = spawn('docker', dockerArgs);
101
- let stderr = '';
102
- let stdout = '';
103
- this.process.stderr?.on('data', data => {
104
- stderr += data.toString();
105
- console.log(`[LocalStack stderr] ${data.toString().trim()}`);
106
- });
107
- this.process.stdout?.on('data', data => {
108
- stdout += data.toString();
109
- console.log(`[LocalStack stdout] ${data.toString().trim()}`);
110
- });
111
- this.process.on('error', error => {
112
- console.error('❌ Failed to start LocalStack process:', error);
113
- reject(error);
114
- });
115
- this.process.on('close', code => {
116
- if (code !== 0) {
117
- console.error(`Container exited with code ${code}`);
118
- console.error('stderr:', stderr);
119
- console.error('stdout:', stdout);
120
- }
121
- });
122
- // Wait for LocalStack to be ready
123
- this.waitForReady()
124
- .then(() => {
125
- this._isRunning = true;
126
- console.log('✅ LocalStack ready');
127
- resolve();
128
- })
129
- .catch(err => {
130
- console.error('LocalStack startup error:', err.message);
131
- this.process?.kill();
132
- reject(err);
133
- });
134
- });
16
+ return EngineManager.getInstance().start();
135
17
  }
136
18
  async stop() {
137
- if (!this._isRunning) {
138
- return;
139
- }
140
- if (this.configManager.isExternal()) {
141
- console.log('🔗 External LocalStack — leaving container untouched');
142
- this._isRunning = false;
143
- return;
144
- }
145
- console.log('🛑 Stopping LocalStack...');
146
- try {
147
- await execAsync(`docker stop ${this.containerName}`, { timeout: 10000 });
148
- this._isRunning = false;
149
- this.process = null;
150
- console.log('✅ LocalStack stopped');
151
- }
152
- catch (error) {
153
- console.error('⚠️ Error stopping LocalStack:', error instanceof Error ? error.message : 'Unknown error');
154
- this._isRunning = false;
155
- }
156
- }
157
- async waitForReady(maxAttempts = 120) {
158
- for (let i = 0; i < maxAttempts; i++) {
159
- try {
160
- const response = await fetch(`${this.endpoint}/_localstack/health`);
161
- if (response.ok) {
162
- console.log(`✓ LocalStack is responsive (attempt ${i + 1}/${maxAttempts})`);
163
- return;
164
- }
165
- }
166
- catch {
167
- // Ignore fetch errors during startup
168
- if (i % 20 === 0) {
169
- console.log(`⏳ Waiting for LocalStack... (attempt ${i + 1}/${maxAttempts})`);
170
- }
171
- }
172
- await new Promise(resolve => setTimeout(resolve, 1000));
173
- }
174
- throw new Error('LocalStack failed to start in time (120s timeout). Check Docker and container logs.');
19
+ return EngineManager.getInstance().stop();
175
20
  }
176
21
  isRunning() {
177
- return this._isRunning;
22
+ return EngineManager.getInstance().isRunning();
178
23
  }
179
24
  getEndpoint() {
180
- return this.endpoint;
25
+ return EngineManager.getInstance().getEndpoint();
181
26
  }
182
27
  getConfig() {
183
- return {
184
- endpoint: this.endpoint,
185
- region: this.configManager.getRegion(),
186
- credentials: {
187
- accessKeyId: process.env.LOCALSTACK_ACCESS_KEY_ID || 'test',
188
- secretAccessKey: process.env.LOCALSTACK_SECRET_ACCESS_KEY || 'test',
189
- },
190
- };
28
+ return EngineManager.getInstance().getConfig();
191
29
  }
192
30
  }
193
31
  //# sourceMappingURL=localstack-manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"localstack-manager.js","sourceRoot":"","sources":["../../../src/server/services/localstack-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"localstack-manager.js","sourceRoot":"","sources":["../../../src/server/services/localstack-manager.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,8EAA8E;AAC9E,6EAA6E;AAC7E,yEAAyE;AACzE,8CAA8C;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,OAAO,iBAAiB;IACpB,MAAM,CAAC,QAAQ,CAAoB;IAE3C,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;YAChC,iBAAiB,CAAC,QAAQ,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACvD,CAAC;QACD,OAAO,iBAAiB,CAAC,QAAQ,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,KAAK;QACT,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAC5C,CAAC;IAED,SAAS;QACP,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,SAAS,EAAE,CAAC;IACjD,CAAC;IAED,WAAW;QACT,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,CAAC;IACnD,CAAC;IAED,SAAS;QACP,OAAO,aAAa,CAAC,WAAW,EAAE,CAAC,SAAS,EAAE,CAAC;IACjD,CAAC;CACF"}
@@ -7,6 +7,7 @@ export declare class ResourceProvisioner {
7
7
  private snsClient;
8
8
  private s3Client;
9
9
  private lambdaClient;
10
+ private eventBridgeClient;
10
11
  private currentRegion;
11
12
  private resourcesByLogicalId;
12
13
  private constructor();
@@ -29,6 +30,9 @@ export declare class ResourceProvisioner {
29
30
  private resolveLambdaName;
30
31
  private generateProxyLambdaCode;
31
32
  private createEventSourceMapping;
33
+ private createEventBus;
34
+ private resolveEventBusName;
35
+ private createEventRule;
32
36
  private ensureLambdaProxyExists;
33
37
  private convertCamelCaseToKebab;
34
38
  private resolveEventSourceArn;
@@ -43,6 +47,8 @@ export declare class ResourceProvisioner {
43
47
  private listSNSTopics;
44
48
  private listS3Buckets;
45
49
  cleanupResources(serviceName: string, resources: Resource[]): Promise<void>;
50
+ private deleteEventRule;
51
+ private deleteEventBus;
46
52
  private deleteDynamoDBTable;
47
53
  private deleteSQSQueue;
48
54
  private deleteS3Bucket;
@@ -1 +1 @@
1
- {"version":3,"file":"resource-provisioner.d.ts","sourceRoot":"","sources":["../../../src/server/services/resource-provisioner.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,QAAQ,EAQT,MAAM,oBAAoB,CAAC;AAM5B,OAAO,KAAK,EACV,QAAQ,EAMT,MAAM,4BAA4B,CAAC;AAGpC,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAsB;IAC7C,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,aAAa,CAAuB;IAM5C,OAAO,CAAC,oBAAoB,CAA+B;IAE3D,OAAO;IAIP,MAAM,CAAC,WAAW,IAAI,mBAAmB;IAOzC,OAAO,CAAC,iBAAiB;IAezB,WAAW,IAAI,QAAQ;IAIvB,gBAAgB,IAAI,MAAM;IAIpB,kBAAkB,CACtB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,QAAQ,EAAE,EACrB,QAAQ,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACtE,OAAO,CAAC,IAAI,CAAC;YAuFF,mBAAmB;YA+DnB,eAAe;YAqBf,cAAc;YAiCd,cAAc;YAiBd,cAAc;YA4Bd,wBAAwB;IAiEtC,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,uBAAuB;YAoEjB,wBAAwB;YAsExB,uBAAuB;IAqErC,OAAO,CAAC,uBAAuB;YAOjB,qBAAqB;IAkH7B,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAC/C,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;YAoBY,kBAAkB;YASlB,aAAa;YASb,aAAa;YAYb,aAAa;IASrB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAyCnE,mBAAmB;YAYnB,cAAc;YAiBd,cAAc;YAsBd,cAAc;YAkBd,wBAAwB;CA6BvC"}
1
+ {"version":3,"file":"resource-provisioner.d.ts","sourceRoot":"","sources":["../../../src/server/services/resource-provisioner.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,QAAQ,EAQT,MAAM,oBAAoB,CAAC;AAe5B,OAAO,KAAK,EACV,QAAQ,EAQT,MAAM,4BAA4B,CAAC;AAGpC,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAsB;IAC7C,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,aAAa,CAAuB;IAM5C,OAAO,CAAC,oBAAoB,CAA+B;IAE3D,OAAO;IAIP,MAAM,CAAC,WAAW,IAAI,mBAAmB;IAOzC,OAAO,CAAC,iBAAiB;IAgBzB,WAAW,IAAI,QAAQ;IAIvB,gBAAgB,IAAI,MAAM;IAIpB,kBAAkB,CACtB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,QAAQ,EAAE,EACrB,QAAQ,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACtE,OAAO,CAAC,IAAI,CAAC;YAwGF,mBAAmB;YA+DnB,eAAe;YAqBf,cAAc;YAiCd,cAAc;YAiBd,cAAc;YA4Bd,wBAAwB;IAiEtC,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,uBAAuB;YAmEjB,wBAAwB;YAsExB,cAAc;IAgB5B,OAAO,CAAC,mBAAmB;YASb,eAAe;YAyEf,uBAAuB;IAqErC,OAAO,CAAC,uBAAuB;YAOjB,qBAAqB;IAkH7B,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAC/C,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;YAoBY,kBAAkB;YASlB,aAAa;YASb,aAAa;YAYb,aAAa;IASrB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAuEnE,eAAe;YAuBf,cAAc;YAWd,mBAAmB;YAYnB,cAAc;YAiBd,cAAc;YAsBd,cAAc;YAkBd,wBAAwB;CA6BvC"}
@@ -4,6 +4,7 @@ import { SNSClient, CreateTopicCommand, ListTopicsCommand, DeleteTopicCommand }
4
4
  import { S3Client, CreateBucketCommand, ListBucketsCommand, DeleteBucketCommand, PutBucketVersioningCommand, PutBucketNotificationConfigurationCommand, ListObjectsV2Command, DeleteObjectCommand, } from '@aws-sdk/client-s3';
5
5
  import { LambdaClient, CreateFunctionCommand, GetFunctionCommand, DeleteFunctionCommand, AddPermissionCommand, UpdateFunctionConfigurationCommand } from '@aws-sdk/client-lambda';
6
6
  import { CreateEventSourceMappingCommand, ListEventSourceMappingsCommand, DeleteEventSourceMappingCommand } from '@aws-sdk/client-lambda';
7
+ import { EventBridgeClient, CreateEventBusCommand, DeleteEventBusCommand, PutRuleCommand, PutTargetsCommand, RemoveTargetsCommand, DeleteRuleCommand, } from '@aws-sdk/client-eventbridge';
7
8
  import { LocalStackManager } from './localstack-manager.js';
8
9
  import { ConfigManager } from './config-manager.js';
9
10
  import { SeedManager } from './seed-manager.js';
@@ -15,6 +16,7 @@ export class ResourceProvisioner {
15
16
  snsClient;
16
17
  s3Client;
17
18
  lambdaClient;
19
+ eventBridgeClient;
18
20
  currentRegion = 'us-east-1';
19
21
  // CFN logical id → resource snapshot for the service currently being
20
22
  // provisioned. Lets resolveEventSourceArn map Fn::GetAtt references
@@ -44,6 +46,7 @@ export class ResourceProvisioner {
44
46
  // rather than as a virtual-host subdomain (which resolves to host.docker.internal).
45
47
  this.s3Client = new S3Client({ ...config, forcePathStyle: true });
46
48
  this.lambdaClient = new LambdaClient(config);
49
+ this.eventBridgeClient = new EventBridgeClient(config);
47
50
  }
48
51
  getS3Client() {
49
52
  return this.s3Client;
@@ -93,6 +96,10 @@ export class ResourceProvisioner {
93
96
  await this.createS3Bucket(resource);
94
97
  provisionedCount++;
95
98
  break;
99
+ case 'eventbus':
100
+ await this.createEventBus(resource);
101
+ provisionedCount++;
102
+ break;
96
103
  }
97
104
  }
98
105
  catch (error) {
@@ -117,6 +124,19 @@ export class ResourceProvisioner {
117
124
  }
118
125
  }
119
126
  }
127
+ // EventBridge rules ride the same proxy model as event source mappings:
128
+ // rule + pattern on the bus → Lambda proxy in LocalStack → LSS invoke API.
129
+ const eventRules = resources.filter(r => r.type === 'event-rule');
130
+ for (const rule of eventRules) {
131
+ try {
132
+ await this.createEventRule(serviceName, rule, invokeUrl);
133
+ provisionedCount++;
134
+ }
135
+ catch (error) {
136
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
137
+ console.error(`Failed to provision event-rule ${rule.name}:`, errorMessage);
138
+ }
139
+ }
120
140
  // Third pass: Wire S3 bucket notifications to Lambda proxies.
121
141
  // Done after event-source pass so proxies created there are available; the
122
142
  // wiring also creates a proxy on demand when only S3 (no SQS/Dynamo) triggers it.
@@ -374,14 +394,13 @@ export const handler = async (event, context) => {
374
394
  const invokeUrl = process.env.INVOKE_URL || '${invokeUrl}';
375
395
  const parsedUrl = url.parse(invokeUrl);
376
396
 
377
- // Transform event based on source
378
- // LocalStack sends events through different sources (SQS, DynamoDB, SNS, etc.)
379
- // We need to pass them correctly to the Serverless Offline handler
397
+ // SQS/DynamoDB/SNS deliver batches under Records; EventBridge delivers the
398
+ // event object itself (source / detail-type / detail) with no wrapper — real
399
+ // AWS Lambda targets read event.detail directly, so wrapping it would break
400
+ // handlers written for production. Wrap only non-EventBridge-shaped events.
380
401
  let transformedEvent = event;
381
-
382
- // If the event already has Records (SQS/DynamoDB/SNS event), use it as is
383
- // Otherwise wrap it in a Records array
384
- if (!event.Records) {
402
+ const isEventBridgeEvent = Boolean(event && event['detail-type'] !== undefined && event.source !== undefined);
403
+ if (!event.Records && !isEventBridgeEvent) {
385
404
  transformedEvent = {
386
405
  Records: [event]
387
406
  };
@@ -493,6 +512,92 @@ export const handler = async (event, context) => {
493
512
  }
494
513
  }
495
514
  }
515
+ async createEventBus(resource) {
516
+ try {
517
+ await this.eventBridgeClient.send(new CreateEventBusCommand({ Name: resource.name }));
518
+ console.log(` ✓ Created EventBridge bus: ${resource.name}`);
519
+ }
520
+ catch (error) {
521
+ if (error?.name === 'ResourceAlreadyExistsException') {
522
+ console.log(` ⚠ EventBridge bus already exists: ${resource.name}`);
523
+ }
524
+ else {
525
+ throw error;
526
+ }
527
+ }
528
+ }
529
+ // Resolve a rule's EventBusName: a logical id from the same template maps to
530
+ // the provisioned bus name; anything else is a literal name/ARN, both of
531
+ // which PutRule/PutTargets accept. Undefined targets the default bus.
532
+ resolveEventBusName(busRef) {
533
+ if (!busRef)
534
+ return undefined;
535
+ const direct = this.resourcesByLogicalId.get(busRef);
536
+ if (direct && direct.type === 'eventbus') {
537
+ return direct.name;
538
+ }
539
+ return busRef;
540
+ }
541
+ async createEventRule(serviceName, rule, invokeUrl) {
542
+ if (rule.eventBusUnresolved) {
543
+ // Binding it to the default bus instead would "work" but never match the
544
+ // producers' events — skipping with a warning is the honest failure.
545
+ console.warn(` ⚠ Skipped EventBridge rule ${rule.name}: EventBusName could not be resolved from the template (e.g. Fn::ImportValue).`);
546
+ return;
547
+ }
548
+ const eventBusName = this.resolveEventBusName(rule.eventBusRef);
549
+ // PutRule/PutTargets are upserts, so re-registration is naturally idempotent.
550
+ await this.eventBridgeClient.send(new PutRuleCommand({
551
+ Name: rule.name,
552
+ EventBusName: eventBusName,
553
+ EventPattern: rule.eventPattern ? JSON.stringify(rule.eventPattern) : undefined,
554
+ ScheduleExpression: rule.scheduleExpression,
555
+ State: rule.enabled ? 'ENABLED' : 'DISABLED',
556
+ }));
557
+ console.log(` ✓ Put EventBridge rule: ${rule.name}${eventBusName ? ` (bus: ${eventBusName})` : ''}`);
558
+ const targets = [];
559
+ for (const target of rule.targets) {
560
+ // Targets arrive as logical ids (Fn::GetAtt) or literal Lambda ARNs.
561
+ const actualFunctionName = target.functionRef.startsWith('arn:aws:')
562
+ ? target.functionRef.split(':function:')[1]?.split(':')[0]
563
+ : this.resolveLambdaName(serviceName, target.functionRef);
564
+ if (!actualFunctionName) {
565
+ console.warn(` ⚠ Skipped EventBridge target ${target.id} on rule ${rule.name}: unsupported target ${target.functionRef}`);
566
+ continue;
567
+ }
568
+ await this.ensureLambdaProxyExists(serviceName, actualFunctionName, actualFunctionName, invokeUrl);
569
+ const ruleArn = `arn:aws:events:${this.currentRegion}:000000000000:rule/${eventBusName ? `${eventBusName}/` : ''}${rule.name}`;
570
+ try {
571
+ await this.lambdaClient.send(new AddPermissionCommand({
572
+ FunctionName: actualFunctionName,
573
+ StatementId: `events-invoke-${rule.name}`,
574
+ Action: 'lambda:InvokeFunction',
575
+ Principal: 'events.amazonaws.com',
576
+ SourceArn: ruleArn,
577
+ }));
578
+ }
579
+ catch (error) {
580
+ // ResourceConflictException = statement already exists, which is fine.
581
+ if (error?.name !== 'ResourceConflictException') {
582
+ console.warn(` ⚠ Could not add EventBridge invoke permission for ${actualFunctionName}: ${error?.message || error}`);
583
+ }
584
+ }
585
+ targets.push({
586
+ Id: target.id,
587
+ Arn: `arn:aws:lambda:${this.currentRegion}:000000000000:function:${actualFunctionName}`,
588
+ Input: target.input,
589
+ InputPath: target.inputPath,
590
+ });
591
+ }
592
+ if (targets.length === 0)
593
+ return;
594
+ await this.eventBridgeClient.send(new PutTargetsCommand({
595
+ Rule: rule.name,
596
+ EventBusName: eventBusName,
597
+ Targets: targets,
598
+ }));
599
+ console.log(` ✓ Wired ${targets.length} target(s) on EventBridge rule: ${rule.name}`);
600
+ }
496
601
  async ensureLambdaProxyExists(serviceName, proxyName, invokeName, invokeUrl) {
497
602
  try {
498
603
  // Check if function already exists
@@ -715,7 +820,19 @@ export const handler = async (event, context) => {
715
820
  console.log(`No resources to clean up for ${serviceName}`);
716
821
  return;
717
822
  }
823
+ // Rebuild the logical id map so event-rule cleanup can resolve which bus
824
+ // each rule lives on (same lookup provisioning uses).
825
+ this.resourcesByLogicalId.clear();
826
+ for (const r of resources) {
827
+ if ('logicalId' in r && r.logicalId) {
828
+ this.resourcesByLogicalId.set(r.logicalId, r);
829
+ }
830
+ }
718
831
  let cleaned = 0;
832
+ // Buses are deleted after the main loop: EventBridge refuses to delete a
833
+ // bus that still has rules, and template order doesn't guarantee the rules
834
+ // come first.
835
+ const eventBuses = [];
719
836
  for (const resource of resources) {
720
837
  try {
721
838
  switch (resource.type) {
@@ -735,6 +852,13 @@ export const handler = async (event, context) => {
735
852
  await this.deleteS3Bucket(resource.name);
736
853
  cleaned++;
737
854
  break;
855
+ case 'eventbus':
856
+ eventBuses.push(resource);
857
+ break;
858
+ case 'event-rule':
859
+ await this.deleteEventRule(resource);
860
+ cleaned++;
861
+ break;
738
862
  case 'event-source':
739
863
  await this.deleteEventSourceMapping(serviceName, resource.functionName);
740
864
  cleaned++;
@@ -747,8 +871,48 @@ export const handler = async (event, context) => {
747
871
  console.error(`Failed to cleanup ${resource.type}:${resourceName}:`, errorMessage);
748
872
  }
749
873
  }
874
+ for (const bus of eventBuses) {
875
+ try {
876
+ await this.deleteEventBus(bus.name);
877
+ cleaned++;
878
+ }
879
+ catch (error) {
880
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
881
+ console.error(`Failed to cleanup eventbus:${bus.name}:`, errorMessage);
882
+ }
883
+ }
750
884
  console.log(`✅ Cleaned up ${cleaned} resources for ${serviceName}`);
751
885
  }
886
+ async deleteEventRule(rule) {
887
+ const eventBusName = this.resolveEventBusName(rule.eventBusRef);
888
+ try {
889
+ if (rule.targets.length > 0) {
890
+ await this.eventBridgeClient.send(new RemoveTargetsCommand({
891
+ Rule: rule.name,
892
+ EventBusName: eventBusName,
893
+ Ids: rule.targets.map(t => t.id),
894
+ }));
895
+ }
896
+ await this.eventBridgeClient.send(new DeleteRuleCommand({ Name: rule.name, EventBusName: eventBusName }));
897
+ console.log(`Deleted EventBridge rule: ${rule.name}`);
898
+ }
899
+ catch (error) {
900
+ if (error?.name !== 'ResourceNotFoundException') {
901
+ throw error;
902
+ }
903
+ }
904
+ }
905
+ async deleteEventBus(busName) {
906
+ try {
907
+ await this.eventBridgeClient.send(new DeleteEventBusCommand({ Name: busName }));
908
+ console.log(`Deleted EventBridge bus: ${busName}`);
909
+ }
910
+ catch (error) {
911
+ if (error?.name !== 'ResourceNotFoundException') {
912
+ throw error;
913
+ }
914
+ }
915
+ }
752
916
  async deleteDynamoDBTable(tableName) {
753
917
  try {
754
918
  await this.dynamoClient.send(new DeleteTableCommand({ TableName: tableName }));