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.
- package/CHANGELOG.md +54 -0
- package/README.md +99 -11
- package/bin/cli.js +31 -3
- package/dist/server/engine/backends/localstack-backend.d.ts +25 -0
- package/dist/server/engine/backends/localstack-backend.d.ts.map +1 -0
- package/dist/server/engine/backends/localstack-backend.js +199 -0
- package/dist/server/engine/backends/localstack-backend.js.map +1 -0
- package/dist/server/engine/backends/self-backend.d.ts +32 -0
- package/dist/server/engine/backends/self-backend.d.ts.map +1 -0
- package/dist/server/engine/backends/self-backend.js +205 -0
- package/dist/server/engine/backends/self-backend.js.map +1 -0
- package/dist/server/engine/bus.d.ts +10 -0
- package/dist/server/engine/bus.d.ts.map +1 -0
- package/dist/server/engine/bus.js +24 -0
- package/dist/server/engine/bus.js.map +1 -0
- package/dist/server/engine/dispatch/dispatcher.d.ts +46 -0
- package/dist/server/engine/dispatch/dispatcher.d.ts.map +1 -0
- package/dist/server/engine/dispatch/dispatcher.js +312 -0
- package/dist/server/engine/dispatch/dispatcher.js.map +1 -0
- package/dist/server/engine/dispatch/scheduler.d.ts +47 -0
- package/dist/server/engine/dispatch/scheduler.d.ts.map +1 -0
- package/dist/server/engine/dispatch/scheduler.js +328 -0
- package/dist/server/engine/dispatch/scheduler.js.map +1 -0
- package/dist/server/engine/dispatch/sqs-poller.d.ts +25 -0
- package/dist/server/engine/dispatch/sqs-poller.d.ts.map +1 -0
- package/dist/server/engine/dispatch/sqs-poller.js +242 -0
- package/dist/server/engine/dispatch/sqs-poller.js.map +1 -0
- package/dist/server/engine/dispatch/stream-tailer.d.ts +22 -0
- package/dist/server/engine/dispatch/stream-tailer.d.ts.map +1 -0
- package/dist/server/engine/dispatch/stream-tailer.js +205 -0
- package/dist/server/engine/dispatch/stream-tailer.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/decimal.d.ts +5 -0
- package/dist/server/engine/emulators/dynamodb/expressions/decimal.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/decimal.js +91 -0
- package/dist/server/engine/emulators/dynamodb/expressions/decimal.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/evaluate.d.ts +24 -0
- package/dist/server/engine/emulators/dynamodb/expressions/evaluate.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/evaluate.js +183 -0
- package/dist/server/engine/emulators/dynamodb/expressions/evaluate.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/expression-types.d.ts +29 -0
- package/dist/server/engine/emulators/dynamodb/expressions/expression-types.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/expression-types.js +12 -0
- package/dist/server/engine/emulators/dynamodb/expressions/expression-types.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/index.d.ts +13 -0
- package/dist/server/engine/emulators/dynamodb/expressions/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/index.js +244 -0
- package/dist/server/engine/emulators/dynamodb/expressions/index.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/lexer.d.ts +11 -0
- package/dist/server/engine/emulators/dynamodb/expressions/lexer.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/lexer.js +109 -0
- package/dist/server/engine/emulators/dynamodb/expressions/lexer.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/parser.d.ts +23 -0
- package/dist/server/engine/emulators/dynamodb/expressions/parser.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/expressions/parser.js +541 -0
- package/dist/server/engine/emulators/dynamodb/expressions/parser.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/index.d.ts +46 -0
- package/dist/server/engine/emulators/dynamodb/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/index.js +572 -0
- package/dist/server/engine/emulators/dynamodb/index.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/query.d.ts +12 -0
- package/dist/server/engine/emulators/dynamodb/query.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/query.js +237 -0
- package/dist/server/engine/emulators/dynamodb/query.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/schema.d.ts +58 -0
- package/dist/server/engine/emulators/dynamodb/schema.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/schema.js +284 -0
- package/dist/server/engine/emulators/dynamodb/schema.js.map +1 -0
- package/dist/server/engine/emulators/dynamodb/streams.d.ts +28 -0
- package/dist/server/engine/emulators/dynamodb/streams.d.ts.map +1 -0
- package/dist/server/engine/emulators/dynamodb/streams.js +100 -0
- package/dist/server/engine/emulators/dynamodb/streams.js.map +1 -0
- package/dist/server/engine/emulators/events/index.d.ts +53 -0
- package/dist/server/engine/emulators/events/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/events/index.js +417 -0
- package/dist/server/engine/emulators/events/index.js.map +1 -0
- package/dist/server/engine/emulators/events/pattern.d.ts +3 -0
- package/dist/server/engine/emulators/events/pattern.d.ts.map +1 -0
- package/dist/server/engine/emulators/events/pattern.js +125 -0
- package/dist/server/engine/emulators/events/pattern.js.map +1 -0
- package/dist/server/engine/emulators/lambda-ctl/index.d.ts +55 -0
- package/dist/server/engine/emulators/lambda-ctl/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/lambda-ctl/index.js +461 -0
- package/dist/server/engine/emulators/lambda-ctl/index.js.map +1 -0
- package/dist/server/engine/emulators/s3/index.d.ts +45 -0
- package/dist/server/engine/emulators/s3/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/s3/index.js +591 -0
- package/dist/server/engine/emulators/s3/index.js.map +1 -0
- package/dist/server/engine/emulators/sns/index.d.ts +22 -0
- package/dist/server/engine/emulators/sns/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/sns/index.js +135 -0
- package/dist/server/engine/emulators/sns/index.js.map +1 -0
- package/dist/server/engine/emulators/sqs/index.d.ts +66 -0
- package/dist/server/engine/emulators/sqs/index.d.ts.map +1 -0
- package/dist/server/engine/emulators/sqs/index.js +552 -0
- package/dist/server/engine/emulators/sqs/index.js.map +1 -0
- package/dist/server/engine/emulators/sqs/md5.d.ts +8 -0
- package/dist/server/engine/emulators/sqs/md5.d.ts.map +1 -0
- package/dist/server/engine/emulators/sqs/md5.js +36 -0
- package/dist/server/engine/emulators/sqs/md5.js.map +1 -0
- package/dist/server/engine/emulators/sqs/queue.d.ts +105 -0
- package/dist/server/engine/emulators/sqs/queue.d.ts.map +1 -0
- package/dist/server/engine/emulators/sqs/queue.js +371 -0
- package/dist/server/engine/emulators/sqs/queue.js.map +1 -0
- package/dist/server/engine/emulators/sts.d.ts +8 -0
- package/dist/server/engine/emulators/sts.d.ts.map +1 -0
- package/dist/server/engine/emulators/sts.js +23 -0
- package/dist/server/engine/emulators/sts.js.map +1 -0
- package/dist/server/engine/engine-backend.d.ts +17 -0
- package/dist/server/engine/engine-backend.d.ts.map +1 -0
- package/dist/server/engine/engine-backend.js +7 -0
- package/dist/server/engine/engine-backend.js.map +1 -0
- package/dist/server/engine/engine-manager.d.ts +22 -0
- package/dist/server/engine/engine-manager.d.ts.map +1 -0
- package/dist/server/engine/engine-manager.js +74 -0
- package/dist/server/engine/engine-manager.js.map +1 -0
- package/dist/server/engine/http/aws-chunked.d.ts +3 -0
- package/dist/server/engine/http/aws-chunked.d.ts.map +1 -0
- package/dist/server/engine/http/aws-chunked.js +50 -0
- package/dist/server/engine/http/aws-chunked.js.map +1 -0
- package/dist/server/engine/http/errors.d.ts +20 -0
- package/dist/server/engine/http/errors.d.ts.map +1 -0
- package/dist/server/engine/http/errors.js +43 -0
- package/dist/server/engine/http/errors.js.map +1 -0
- package/dist/server/engine/http/protocols/aws-json.d.ts +8 -0
- package/dist/server/engine/http/protocols/aws-json.d.ts.map +1 -0
- package/dist/server/engine/http/protocols/aws-json.js +42 -0
- package/dist/server/engine/http/protocols/aws-json.js.map +1 -0
- package/dist/server/engine/http/protocols/query-xml.d.ts +7 -0
- package/dist/server/engine/http/protocols/query-xml.d.ts.map +1 -0
- package/dist/server/engine/http/protocols/query-xml.js +35 -0
- package/dist/server/engine/http/protocols/query-xml.js.map +1 -0
- package/dist/server/engine/http/router.d.ts +8 -0
- package/dist/server/engine/http/router.d.ts.map +1 -0
- package/dist/server/engine/http/router.js +391 -0
- package/dist/server/engine/http/router.js.map +1 -0
- package/dist/server/engine/http/sigv4.d.ts +9 -0
- package/dist/server/engine/http/sigv4.d.ts.map +1 -0
- package/dist/server/engine/http/sigv4.js +33 -0
- package/dist/server/engine/http/sigv4.js.map +1 -0
- package/dist/server/engine/http/xml.d.ts +16 -0
- package/dist/server/engine/http/xml.d.ts.map +1 -0
- package/dist/server/engine/http/xml.js +92 -0
- package/dist/server/engine/http/xml.js.map +1 -0
- package/dist/server/engine/store/atomic.d.ts +4 -0
- package/dist/server/engine/store/atomic.d.ts.map +1 -0
- package/dist/server/engine/store/atomic.js +35 -0
- package/dist/server/engine/store/atomic.js.map +1 -0
- package/dist/server/engine/store/engine-store.d.ts +9 -0
- package/dist/server/engine/store/engine-store.d.ts.map +1 -0
- package/dist/server/engine/store/engine-store.js +218 -0
- package/dist/server/engine/store/engine-store.js.map +1 -0
- package/dist/server/engine/store/store-types.d.ts +37 -0
- package/dist/server/engine/store/store-types.d.ts.map +1 -0
- package/dist/server/engine/store/store-types.js +17 -0
- package/dist/server/engine/store/store-types.js.map +1 -0
- package/dist/server/engine/store/wal.d.ts +49 -0
- package/dist/server/engine/store/wal.d.ts.map +1 -0
- package/dist/server/engine/store/wal.js +328 -0
- package/dist/server/engine/store/wal.js.map +1 -0
- package/dist/server/engine/types.d.ts +137 -0
- package/dist/server/engine/types.d.ts.map +1 -0
- package/dist/server/engine/types.js +8 -0
- package/dist/server/engine/types.js.map +1 -0
- package/dist/server/index.js +12 -9
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes/services.d.ts.map +1 -1
- package/dist/server/routes/services.js +2 -0
- package/dist/server/routes/services.js.map +1 -1
- package/dist/server/services/cloudformation-parser.d.ts +26 -2
- package/dist/server/services/cloudformation-parser.d.ts.map +1 -1
- package/dist/server/services/cloudformation-parser.js +60 -3
- package/dist/server/services/cloudformation-parser.js.map +1 -1
- package/dist/server/services/config-manager.d.ts +27 -0
- package/dist/server/services/config-manager.d.ts.map +1 -1
- package/dist/server/services/config-manager.js +67 -7
- package/dist/server/services/config-manager.js.map +1 -1
- package/dist/server/services/localstack-manager.d.ts +0 -7
- package/dist/server/services/localstack-manager.d.ts.map +1 -1
- package/dist/server/services/localstack-manager.js +11 -173
- package/dist/server/services/localstack-manager.js.map +1 -1
- package/dist/server/services/resource-provisioner.d.ts +6 -0
- package/dist/server/services/resource-provisioner.d.ts.map +1 -1
- package/dist/server/services/resource-provisioner.js +171 -7
- package/dist/server/services/resource-provisioner.js.map +1 -1
- package/dist/server/services/service-registrar.js +2 -2
- package/dist/server/services/service-registrar.js.map +1 -1
- package/dist/ui/assets/ApisPage-a9i2qD0Z.js +1 -0
- package/dist/ui/assets/BucketDetailPage-Cz27N0KV.js +1 -0
- package/dist/ui/assets/BucketsPage-CZ7wGmUN.js +1 -0
- package/dist/ui/assets/{DynamoPage-B1__Rjr2.js → DynamoPage-BZMs1iW8.js} +1 -1
- package/dist/ui/assets/DynamoTablePage-BQsGkhtO.js +3 -0
- package/dist/ui/assets/LambdaDetailPage-DJb7xqRB.js +4 -0
- package/dist/ui/assets/LambdasPage-Ctg1l-Lg.js +1 -0
- package/dist/ui/assets/OverviewPage-DiijblCA.js +1 -0
- package/dist/ui/assets/QueueDetailPage-DRpSqost.js +1 -0
- package/dist/ui/assets/QueuesPage-CY0bDGwV.js +1 -0
- package/dist/ui/assets/ServiceDetailPage-CYTEdtts.js +2 -0
- package/dist/ui/assets/ServicesPage-OlV_rr-q.js +2 -0
- package/dist/ui/assets/index-C1KdKPDS.css +1 -0
- package/dist/ui/assets/index-DA_C1HOg.js +36 -0
- package/dist/ui/index.html +2 -2
- package/package.json +2 -1
- package/dist/ui/assets/ApisPage-DdgKjEdS.js +0 -1
- package/dist/ui/assets/BucketDetailPage-DZQGxm0y.js +0 -1
- package/dist/ui/assets/BucketsPage-xYXzxCvd.js +0 -1
- package/dist/ui/assets/DynamoTablePage-BCoxPdXW.js +0 -3
- package/dist/ui/assets/LambdaDetailPage-B85CA8tb.js +0 -4
- package/dist/ui/assets/LambdasPage-_TtxQMT_.js +0 -1
- package/dist/ui/assets/OverviewPage-CqTKTY64.js +0 -1
- package/dist/ui/assets/QueueDetailPage-BOr_sImA.js +0 -1
- package/dist/ui/assets/QueuesPage-DpByfcM5.js +0 -1
- package/dist/ui/assets/ServiceDetailPage-DsWgV-ad.js +0 -2
- package/dist/ui/assets/ServicesPage-CGlpsj98.js +0 -2
- package/dist/ui/assets/index-BWlB542w.js +0 -36
- package/dist/ui/assets/index-EYnsoJOq.css +0 -1
|
@@ -1,24 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
22
|
+
return EngineManager.getInstance().isRunning();
|
|
178
23
|
}
|
|
179
24
|
getEndpoint() {
|
|
180
|
-
return
|
|
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":"AAAA,
|
|
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;
|
|
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
|
-
//
|
|
378
|
-
//
|
|
379
|
-
//
|
|
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
|
-
|
|
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 }));
|