@gugananuvem/aws-local-simulator 1.0.12 → 1.0.15
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/README.md +594 -257
- package/bin/aws-local-simulator.js +63 -63
- package/package.json +21 -10
- package/src/config/config-loader.js +114 -114
- package/src/config/default-config.js +68 -67
- package/src/config/env-loader.js +68 -68
- package/src/index.js +146 -130
- package/src/index.mjs +123 -123
- package/src/server.js +227 -223
- package/src/services/apigateway/index.js +73 -68
- package/src/services/apigateway/server.js +507 -487
- package/src/services/apigateway/simulator.js +1261 -1251
- package/src/services/athena/index.js +75 -0
- package/src/services/athena/server.js +101 -0
- package/src/services/athena/simulador.js +998 -0
- package/src/services/athena/simulator.js +346 -0
- package/src/services/cloudformation/index.js +106 -0
- package/src/services/cloudformation/server.js +417 -0
- package/src/services/cloudformation/simulador.js +1045 -0
- package/src/services/cloudtrail/index.js +84 -0
- package/src/services/cloudtrail/server.js +235 -0
- package/src/services/cloudtrail/simulador.js +719 -0
- package/src/services/cloudwatch/index.js +84 -0
- package/src/services/cloudwatch/server.js +366 -0
- package/src/services/cloudwatch/simulador.js +1173 -0
- package/src/services/cognito/index.js +79 -65
- package/src/services/cognito/server.js +301 -279
- package/src/services/cognito/simulator.js +1655 -1115
- package/src/services/config/index.js +96 -0
- package/src/services/config/server.js +215 -0
- package/src/services/config/simulador.js +1260 -0
- package/src/services/dynamodb/index.js +74 -70
- package/src/services/dynamodb/server.js +125 -121
- package/src/services/dynamodb/simulator.js +630 -620
- package/src/services/ecs/index.js +65 -65
- package/src/services/ecs/server.js +235 -233
- package/src/services/ecs/simulator.js +844 -844
- package/src/services/eventbridge/index.js +89 -85
- package/src/services/eventbridge/server.js +209 -0
- package/src/services/eventbridge/simulator.js +684 -0
- package/src/services/index.js +45 -19
- package/src/services/kms/index.js +75 -0
- package/src/services/kms/server.js +67 -0
- package/src/services/kms/simulator.js +324 -0
- package/src/services/lambda/handler-loader.js +183 -183
- package/src/services/lambda/index.js +78 -73
- package/src/services/lambda/route-registry.js +274 -274
- package/src/services/lambda/server.js +145 -145
- package/src/services/lambda/simulator.js +199 -172
- package/src/services/parameter-store/index.js +80 -0
- package/src/services/parameter-store/server.js +50 -0
- package/src/services/parameter-store/simulator.js +201 -0
- package/src/services/s3/index.js +73 -69
- package/src/services/s3/server.js +329 -238
- package/src/services/s3/simulator.js +565 -740
- package/src/services/secret-manager/index.js +80 -0
- package/src/services/secret-manager/server.js +50 -0
- package/src/services/secret-manager/simulator.js +171 -0
- package/src/services/sns/index.js +89 -76
- package/src/services/sns/server.js +580 -0
- package/src/services/sns/simulator.js +1482 -0
- package/src/services/sqs/index.js +93 -95
- package/src/services/sqs/server.js +349 -345
- package/src/services/sqs/simulator.js +441 -441
- package/src/services/sts/index.js +37 -37
- package/src/services/sts/server.js +144 -142
- package/src/services/sts/simulator.js +69 -69
- package/src/services/xray/index.js +83 -0
- package/src/services/xray/server.js +308 -0
- package/src/services/xray/simulador.js +994 -0
- package/src/template/aws-config-template.js +87 -87
- package/src/template/aws-config-template.mjs +90 -90
- package/src/template/config-template.json +203 -203
- package/src/utils/aws-config.js +91 -91
- package/src/utils/cloudtrail-audit.js +129 -0
- package/src/utils/local-store.js +83 -67
- package/src/utils/logger.js +59 -59
|
@@ -1,85 +1,89 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
this.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
this.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview EventBridge Service — entry point
|
|
5
|
+
* Porta padrão: 4010
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const http = require('http');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { EventBridgeSimulator } = require('./simulator');
|
|
11
|
+
const { createEventBridgeServer } = require('./server');
|
|
12
|
+
const LocalStore = require('../../utils/local-store');
|
|
13
|
+
|
|
14
|
+
class EventBridgeService {
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.logger = require('../../utils/logger');
|
|
18
|
+
this.name = 'eventbridge';
|
|
19
|
+
this.port = config?.ports?.eventbridge || config?.services?.eventbridge?.port || 4010;
|
|
20
|
+
this.store = null;
|
|
21
|
+
this.simulator = null;
|
|
22
|
+
this.app = null;
|
|
23
|
+
this.server = null;
|
|
24
|
+
this.isRunning = false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async initialize() {
|
|
28
|
+
this.logger.debug(`Inicializando EventBridge Service na porta ${this.port}...`);
|
|
29
|
+
const dataDir = process.env.AWS_LOCAL_SIMULATOR_DATA_DIR;
|
|
30
|
+
this.store = new LocalStore(path.join(dataDir, 'eventbridge'));
|
|
31
|
+
this.simulator = new EventBridgeSimulator(this.config, this.store, this.logger);
|
|
32
|
+
this.app = createEventBridgeServer(this.simulator, this.config, this.logger);
|
|
33
|
+
this.logger.debug('EventBridge Service inicializado');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
injectDependencies(server) {
|
|
37
|
+
if (!server) return;
|
|
38
|
+
const lambda = server.getService('lambda');
|
|
39
|
+
if (lambda) this.simulator.setLambdaService(lambda);
|
|
40
|
+
const sqs = server.getService('sqs');
|
|
41
|
+
if (sqs) this.simulator.setSqsService(sqs);
|
|
42
|
+
const sns = server.getService('sns');
|
|
43
|
+
if (sns) this.simulator.setSnsService(sns);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async start() {
|
|
47
|
+
if (this.isRunning) return;
|
|
48
|
+
await this.store.ensureDir();
|
|
49
|
+
await this.simulator.load();
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
this.server = http.createServer(this.app);
|
|
52
|
+
this.server.on('error', reject);
|
|
53
|
+
this.server.listen(this.port, () => {
|
|
54
|
+
this.isRunning = true;
|
|
55
|
+
this.logger.debug(`EventBridge rodando na porta ${this.port}`);
|
|
56
|
+
resolve();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async stop() {
|
|
62
|
+
if (!this.isRunning || !this.server) return;
|
|
63
|
+
return new Promise((resolve, reject) => {
|
|
64
|
+
this.server.close((err) => {
|
|
65
|
+
if (err) return reject(err);
|
|
66
|
+
this.isRunning = false;
|
|
67
|
+
resolve();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async reset() {
|
|
73
|
+
await this.simulator.reset();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getStatus() {
|
|
77
|
+
return {
|
|
78
|
+
running: this.isRunning,
|
|
79
|
+
port: this.port,
|
|
80
|
+
endpoint: `http://localhost:${this.port}`,
|
|
81
|
+
buses: this.simulator?.buses.size || 0,
|
|
82
|
+
rules: this.simulator?.rules.size || 0,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getSimulator() { return this.simulator; }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = { EventBridgeService };
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview EventBridge HTTP Server
|
|
3
|
+
* Express server compatível com AWS EventBridge REST API (JSON)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const express = require('express');
|
|
9
|
+
const cors = require('cors');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create EventBridge Express application
|
|
13
|
+
* @param {Object} simulator - EventBridgeSimulator instance
|
|
14
|
+
* @param {Object} config - Service configuration
|
|
15
|
+
* @param {Object} logger - Logger instance
|
|
16
|
+
* @returns {express.Application}
|
|
17
|
+
*/
|
|
18
|
+
function createEventBridgeServer(simulator, config, logger) {
|
|
19
|
+
const app = express();
|
|
20
|
+
|
|
21
|
+
if (config.cors?.enabled !== false) {
|
|
22
|
+
app.use(cors({ origin: config.cors?.origin || '*' }));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
app.use(express.json({ limit: '10mb' }));
|
|
26
|
+
|
|
27
|
+
app.use((req, _res, next) => {
|
|
28
|
+
logger.debug('EventBridge', `${req.method} ${req.path}`);
|
|
29
|
+
next();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// ==================== Event Buses ====================
|
|
33
|
+
|
|
34
|
+
app.post('/event-buses', async (req, res) => {
|
|
35
|
+
try {
|
|
36
|
+
const result = await simulator.createEventBus(req.body);
|
|
37
|
+
res.status(201).json(result);
|
|
38
|
+
} catch (err) { sendError(res, err); }
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
app.delete('/event-buses/:name', async (req, res) => {
|
|
42
|
+
try {
|
|
43
|
+
await simulator.deleteEventBus({ Name: req.params.name });
|
|
44
|
+
res.status(200).json({});
|
|
45
|
+
} catch (err) { sendError(res, err); }
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
app.get('/event-buses', (_req, res) => {
|
|
49
|
+
try {
|
|
50
|
+
const result = simulator.listEventBuses();
|
|
51
|
+
res.json(result);
|
|
52
|
+
} catch (err) { sendError(res, err); }
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
app.get('/event-buses/:name', (req, res) => {
|
|
56
|
+
try {
|
|
57
|
+
const result = simulator.describeEventBus({ Name: req.params.name });
|
|
58
|
+
res.json(result);
|
|
59
|
+
} catch (err) { sendError(res, err); }
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// ==================== Rules ====================
|
|
63
|
+
|
|
64
|
+
app.put('/rules', async (req, res) => {
|
|
65
|
+
try {
|
|
66
|
+
const result = await simulator.putRule(req.body);
|
|
67
|
+
res.json(result);
|
|
68
|
+
} catch (err) { sendError(res, err); }
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
app.delete('/rules/:name', async (req, res) => {
|
|
72
|
+
try {
|
|
73
|
+
await simulator.deleteRule({ Name: req.params.name, EventBusName: req.query.eventBusName });
|
|
74
|
+
res.status(200).json({});
|
|
75
|
+
} catch (err) { sendError(res, err); }
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
app.get('/rules', (req, res) => {
|
|
79
|
+
try {
|
|
80
|
+
const result = simulator.listRules({
|
|
81
|
+
EventBusName: req.query.EventBusName || 'default',
|
|
82
|
+
NamePrefix: req.query.NamePrefix,
|
|
83
|
+
Limit: req.query.Limit ? parseInt(req.query.Limit) : undefined
|
|
84
|
+
});
|
|
85
|
+
res.json(result);
|
|
86
|
+
} catch (err) { sendError(res, err); }
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
app.get('/rules/:name', (req, res) => {
|
|
90
|
+
try {
|
|
91
|
+
const result = simulator.describeRule({
|
|
92
|
+
Name: req.params.name,
|
|
93
|
+
EventBusName: req.query.EventBusName || 'default'
|
|
94
|
+
});
|
|
95
|
+
res.json(result);
|
|
96
|
+
} catch (err) { sendError(res, err); }
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
app.patch('/rules/:name/enable', async (req, res) => {
|
|
100
|
+
try {
|
|
101
|
+
await simulator.enableRule({ Name: req.params.name, EventBusName: req.query.EventBusName || 'default' });
|
|
102
|
+
res.json({ message: 'Rule enabled' });
|
|
103
|
+
} catch (err) { sendError(res, err); }
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
app.patch('/rules/:name/disable', async (req, res) => {
|
|
107
|
+
try {
|
|
108
|
+
await simulator.disableRule({ Name: req.params.name, EventBusName: req.query.EventBusName || 'default' });
|
|
109
|
+
res.json({ message: 'Rule disabled' });
|
|
110
|
+
} catch (err) { sendError(res, err); }
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// ==================== Targets ====================
|
|
114
|
+
|
|
115
|
+
app.put('/rules/:name/targets', async (req, res) => {
|
|
116
|
+
try {
|
|
117
|
+
const result = await simulator.putTargets({
|
|
118
|
+
Rule: req.params.name,
|
|
119
|
+
EventBusName: req.body.EventBusName || 'default',
|
|
120
|
+
Targets: req.body.Targets
|
|
121
|
+
});
|
|
122
|
+
res.json(result);
|
|
123
|
+
} catch (err) { sendError(res, err); }
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
app.delete('/rules/:name/targets', async (req, res) => {
|
|
127
|
+
try {
|
|
128
|
+
const result = await simulator.removeTargets({
|
|
129
|
+
Rule: req.params.name,
|
|
130
|
+
EventBusName: req.query.EventBusName || 'default',
|
|
131
|
+
Ids: req.body.Ids || []
|
|
132
|
+
});
|
|
133
|
+
res.json(result);
|
|
134
|
+
} catch (err) { sendError(res, err); }
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
app.get('/rules/:name/targets', (req, res) => {
|
|
138
|
+
try {
|
|
139
|
+
const result = simulator.listTargetsByRule({
|
|
140
|
+
Rule: req.params.name,
|
|
141
|
+
EventBusName: req.query.EventBusName || 'default'
|
|
142
|
+
});
|
|
143
|
+
res.json(result);
|
|
144
|
+
} catch (err) { sendError(res, err); }
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ==================== PutEvents ====================
|
|
148
|
+
|
|
149
|
+
app.post('/events', async (req, res) => {
|
|
150
|
+
try {
|
|
151
|
+
const result = await simulator.putEvents(req.body);
|
|
152
|
+
res.json(result);
|
|
153
|
+
} catch (err) { sendError(res, err); }
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// ==================== Admin ====================
|
|
157
|
+
|
|
158
|
+
app.get('/__admin/health', (_req, res) => {
|
|
159
|
+
res.json({
|
|
160
|
+
status: 'healthy',
|
|
161
|
+
service: 'eventbridge',
|
|
162
|
+
buses: simulator.buses.size,
|
|
163
|
+
rules: simulator.rules.size,
|
|
164
|
+
recentEvents: simulator.eventArchive.length,
|
|
165
|
+
timestamp: new Date().toISOString()
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
app.get('/__admin/buses', (_req, res) => {
|
|
170
|
+
res.json({ buses: Array.from(simulator.buses.values()) });
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
app.get('/__admin/rules', (_req, res) => {
|
|
174
|
+
res.json({ rules: Array.from(simulator.rules.values()) });
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
app.get('/__admin/events', (req, res) => {
|
|
178
|
+
const limit = parseInt(req.query.limit) || 50;
|
|
179
|
+
const events = simulator.eventArchive.slice(-limit);
|
|
180
|
+
res.json({ events, total: simulator.eventArchive.length });
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
app.post('/__admin/reset', async (_req, res) => {
|
|
184
|
+
await simulator.reset();
|
|
185
|
+
res.json({ message: 'EventBridge data reset' });
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
app.use((_req, res) => res.status(404).json({ message: 'Not Found' }));
|
|
189
|
+
|
|
190
|
+
return app;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Send error response
|
|
195
|
+
* @param {express.Response} res
|
|
196
|
+
* @param {Error} err
|
|
197
|
+
*/
|
|
198
|
+
function sendError(res, err) {
|
|
199
|
+
const statusMap = {
|
|
200
|
+
ValidationException: 400,
|
|
201
|
+
ResourceNotFoundException: 404,
|
|
202
|
+
ResourceAlreadyExistsException: 409,
|
|
203
|
+
InvalidEventPatternException: 400
|
|
204
|
+
};
|
|
205
|
+
const status = statusMap[err.code] || statusMap[err.__type] || 500;
|
|
206
|
+
res.status(status).json({ message: err.message, __type: err.__type || err.code });
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
module.exports = { createEventBridgeServer };
|