@gugananuvem/aws-local-simulator 1.0.33 → 1.0.34
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 +834 -834
- package/aws-config +153 -153
- package/bin/aws-local-simulator.js +63 -63
- package/package.json +3 -2
- package/src/config/config-loader.js +114 -114
- package/src/config/default-config.js +79 -79
- package/src/config/env-loader.js +68 -68
- package/src/index.js +146 -146
- package/src/index.mjs +123 -123
- package/src/server.js +463 -463
- package/src/services/apigateway/index.js +75 -75
- package/src/services/apigateway/server.js +607 -607
- package/src/services/apigateway/simulator.js +1405 -1405
- package/src/services/athena/index.js +75 -75
- package/src/services/athena/server.js +101 -101
- package/src/services/athena/simulador.js +998 -998
- package/src/services/athena/simulator.js +346 -346
- package/src/services/cloudformation/index.js +106 -106
- package/src/services/cloudformation/server.js +417 -417
- package/src/services/cloudformation/simulador.js +1020 -1020
- package/src/services/cloudtrail/index.js +84 -84
- package/src/services/cloudtrail/server.js +235 -235
- package/src/services/cloudtrail/simulador.js +719 -719
- package/src/services/cloudwatch/index.js +84 -84
- package/src/services/cloudwatch/server.js +366 -366
- package/src/services/cloudwatch/simulador.js +1173 -1173
- package/src/services/cognito/index.js +79 -79
- package/src/services/cognito/server.js +297 -297
- package/src/services/cognito/simulator.js +1992 -1761
- package/src/services/config/index.js +96 -96
- package/src/services/config/server.js +215 -215
- package/src/services/config/simulador.js +1260 -1260
- package/src/services/dynamodb/index.js +74 -74
- package/src/services/dynamodb/server.js +139 -139
- package/src/services/dynamodb/simulator.js +1005 -994
- package/src/services/dynamodb/sqlite-store.js +722 -0
- package/src/services/ecs/index.js +65 -65
- package/src/services/ecs/server.js +235 -235
- package/src/services/ecs/simulator.js +844 -844
- package/src/services/eventbridge/index.js +89 -89
- package/src/services/eventbridge/server.js +209 -209
- package/src/services/eventbridge/simulator.js +684 -684
- package/src/services/index.js +45 -45
- package/src/services/kms/index.js +75 -75
- package/src/services/kms/server.js +81 -81
- package/src/services/kms/simulator.js +344 -344
- package/src/services/lambda/handler-loader.js +183 -183
- package/src/services/lambda/index.js +81 -81
- package/src/services/lambda/route-registry.js +274 -274
- package/src/services/lambda/server.js +191 -191
- package/src/services/lambda/simulator.js +364 -364
- package/src/services/parameter-store/index.js +80 -80
- package/src/services/parameter-store/server.js +50 -50
- package/src/services/parameter-store/simulator.js +201 -201
- package/src/services/s3/index.js +73 -73
- package/src/services/s3/server.js +350 -350
- package/src/services/s3/simulator.js +568 -568
- package/src/services/secret-manager/index.js +80 -80
- package/src/services/secret-manager/server.js +51 -51
- package/src/services/secret-manager/simulator.js +182 -182
- package/src/services/sns/index.js +89 -89
- package/src/services/sns/server.js +607 -607
- package/src/services/sns/simulator.js +1482 -1482
- package/src/services/sqs/index.js +98 -98
- package/src/services/sqs/server.js +360 -360
- package/src/services/sqs/simulator.js +509 -509
- package/src/services/sts/index.js +37 -37
- package/src/services/sts/server.js +144 -144
- package/src/services/sts/simulator.js +69 -69
- package/src/services/xray/index.js +83 -83
- package/src/services/xray/server.js +308 -308
- package/src/services/xray/simulador.js +994 -994
- 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 -129
- package/src/utils/local-store.js +83 -83
- package/src/utils/logger.js +59 -59
package/src/server.js
CHANGED
|
@@ -1,463 +1,463 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Servidor Principal - Orquestra todos os serviços
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const path = require("path");
|
|
6
|
-
const fs = require("fs");
|
|
7
|
-
const mkdirp = require("mkdirp");
|
|
8
|
-
const express = require("express");
|
|
9
|
-
const cors = require("cors");
|
|
10
|
-
const logger = require("./utils/logger");
|
|
11
|
-
|
|
12
|
-
// Importa serviços
|
|
13
|
-
const DynamoDBService = require("./services/dynamodb");
|
|
14
|
-
const S3Service = require("./services/s3");
|
|
15
|
-
const SQSService = require("./services/sqs");
|
|
16
|
-
const LambdaService = require("./services/lambda");
|
|
17
|
-
const { SNSService } = require("./services/sns");
|
|
18
|
-
const { EventBridgeService } = require("./services/eventbridge");
|
|
19
|
-
const CognitoService = require("./services/cognito");
|
|
20
|
-
const APIGatewayService = require("./services/apigateway");
|
|
21
|
-
const ECSService = require("./services/ecs");
|
|
22
|
-
const STSService = require("./services/sts");
|
|
23
|
-
const { CloudWatchService } = require("./services/cloudwatch");
|
|
24
|
-
const CloudTrailService = require("./services/cloudtrail");
|
|
25
|
-
const { KMSService } = require("./services/kms");
|
|
26
|
-
const CloudFormationService = require("./services/cloudformation");
|
|
27
|
-
const { XRayService } = require("./services/xray");
|
|
28
|
-
const { SecretManagerService } = require("./services/secret-manager");
|
|
29
|
-
const { ParameterStoreService } = require("./services/parameter-store");
|
|
30
|
-
const { ConfigService } = require("./services/config");
|
|
31
|
-
const { AthenaService } = require("./services/athena");
|
|
32
|
-
|
|
33
|
-
class Server {
|
|
34
|
-
constructor(config) {
|
|
35
|
-
this.config = config;
|
|
36
|
-
this.services = [];
|
|
37
|
-
this.servicesMap = new Map();
|
|
38
|
-
this.running = false;
|
|
39
|
-
this.managementApp = express();
|
|
40
|
-
this.managementApp.use(cors());
|
|
41
|
-
this.managementApp.use(express.json());
|
|
42
|
-
this.managementServer = null;
|
|
43
|
-
this.setupDataDir();
|
|
44
|
-
this.setupLogLevel();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
setupDataDir() {
|
|
48
|
-
const dataDir = path.resolve(process.cwd(), this.config.dataDir);
|
|
49
|
-
if (!fs.existsSync(dataDir)) {
|
|
50
|
-
mkdirp.sync(dataDir);
|
|
51
|
-
logger.debug(`📁 Diretório de dados criado: ${dataDir}`);
|
|
52
|
-
}
|
|
53
|
-
process.env.AWS_LOCAL_SIMULATOR_DATA_DIR = dataDir;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
setupLogLevel() {
|
|
57
|
-
logger.setLevel(this.config.logLevel);
|
|
58
|
-
logger.info(`📝 Nível de log: ${this.config.logLevel}`);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async start() {
|
|
62
|
-
if (this.running) {
|
|
63
|
-
logger.warn("Servidor já está rodando");
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
logger.info("\n🚀 Iniciando AWS Local Simulator...\n");
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
await this.initializeServices();
|
|
71
|
-
await this.startServices();
|
|
72
|
-
this.setupManagementRoutes();
|
|
73
|
-
await this.startManagementServer();
|
|
74
|
-
|
|
75
|
-
this.running = true;
|
|
76
|
-
this.printStatus();
|
|
77
|
-
} catch (error) {
|
|
78
|
-
logger.error("❌ Erro ao iniciar servidor:", error);
|
|
79
|
-
throw error;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
setupManagementRoutes() {
|
|
84
|
-
const app = this.managementApp;
|
|
85
|
-
|
|
86
|
-
// GET /__admin/services — returns all services status
|
|
87
|
-
app.get("/__admin/services", (req, res) => {
|
|
88
|
-
const registry = this.buildServiceRegistry();
|
|
89
|
-
const services = registry.map((def) => {
|
|
90
|
-
const svc = this.servicesMap.get(def.name);
|
|
91
|
-
if (svc) {
|
|
92
|
-
const status = typeof svc.getStatus === "function"
|
|
93
|
-
? svc.getStatus()
|
|
94
|
-
: { name: def.name, running: true, port: svc.port };
|
|
95
|
-
// Compute canDisable: no running service should depend on this one
|
|
96
|
-
const canDisable = !registry.some(
|
|
97
|
-
(other) =>
|
|
98
|
-
other.depends.includes(def.name) &&
|
|
99
|
-
this.servicesMap.has(other.name)
|
|
100
|
-
);
|
|
101
|
-
return {
|
|
102
|
-
name: def.name,
|
|
103
|
-
running: true,
|
|
104
|
-
enabled: true,
|
|
105
|
-
port: status.port || this.config.ports?.[def.name],
|
|
106
|
-
endpoint: status.endpoint || `http://localhost:${status.port || this.config.ports?.[def.name]}`,
|
|
107
|
-
dependencies: def.depends,
|
|
108
|
-
category: def.category,
|
|
109
|
-
canDisable,
|
|
110
|
-
...status,
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
return {
|
|
114
|
-
name: def.name,
|
|
115
|
-
running: false,
|
|
116
|
-
enabled: false,
|
|
117
|
-
port: this.config.ports?.[def.name],
|
|
118
|
-
endpoint: `http://localhost:${this.config.ports?.[def.name]}`,
|
|
119
|
-
dependencies: def.depends,
|
|
120
|
-
canDisable: true,
|
|
121
|
-
};
|
|
122
|
-
});
|
|
123
|
-
res.json({ services });
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// GET /__admin/services/:name — returns single service status
|
|
127
|
-
app.get("/__admin/services/:name", (req, res) => {
|
|
128
|
-
const { name } = req.params;
|
|
129
|
-
const registry = this.buildServiceRegistry();
|
|
130
|
-
const def = registry.find((d) => d.name === name);
|
|
131
|
-
if (!def) {
|
|
132
|
-
return res.status(404).json({ error: `Unknown service: ${name}` });
|
|
133
|
-
}
|
|
134
|
-
const svc = this.servicesMap.get(name);
|
|
135
|
-
const canDisable = !registry.some(
|
|
136
|
-
(other) =>
|
|
137
|
-
other.depends.includes(name) &&
|
|
138
|
-
this.servicesMap.has(other.name)
|
|
139
|
-
);
|
|
140
|
-
if (svc) {
|
|
141
|
-
const status = typeof svc.getStatus === "function"
|
|
142
|
-
? svc.getStatus()
|
|
143
|
-
: { name, running: true, port: svc.port };
|
|
144
|
-
return res.json({
|
|
145
|
-
name,
|
|
146
|
-
running: true,
|
|
147
|
-
enabled: true,
|
|
148
|
-
port: status.port || this.config.ports?.[name],
|
|
149
|
-
endpoint: status.endpoint || `http://localhost:${status.port || this.config.ports?.[name]}`,
|
|
150
|
-
dependencies: def.depends,
|
|
151
|
-
canDisable,
|
|
152
|
-
...status,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
return res.json({
|
|
156
|
-
name,
|
|
157
|
-
running: false,
|
|
158
|
-
enabled: false,
|
|
159
|
-
port: this.config.ports?.[name],
|
|
160
|
-
endpoint: `http://localhost:${this.config.ports?.[name]}`,
|
|
161
|
-
dependencies: def.depends,
|
|
162
|
-
canDisable: true,
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// POST /__admin/services/:name/enable — enables a service
|
|
167
|
-
app.post("/__admin/services/:name/enable", async (req, res) => {
|
|
168
|
-
const result = await this.enableService(req.params.name);
|
|
169
|
-
res.status(result.success ? 200 : 400).json(result);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// POST /__admin/services/:name/disable — disables a service
|
|
173
|
-
app.post("/__admin/services/:name/disable", async (req, res) => {
|
|
174
|
-
const result = await this.disableService(req.params.name);
|
|
175
|
-
res.status(result.success ? 200 : 400).json(result);
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
startManagementServer() {
|
|
180
|
-
return new Promise((resolve, reject) => {
|
|
181
|
-
const port = this.config.adminPort || 9999;
|
|
182
|
-
this.managementServer = this.managementApp.listen(port, () => {
|
|
183
|
-
logger.info(`🔧 Management API rodando em http://localhost:${port}`);
|
|
184
|
-
resolve();
|
|
185
|
-
});
|
|
186
|
-
this.managementServer.on("error", reject);
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
buildServiceRegistry() {
|
|
191
|
-
return [
|
|
192
|
-
//Armazenamento & BD
|
|
193
|
-
{ name: "dynamodb", class: DynamoDBService, depends: [], category: 'Armazenamento & Banco de Dados' },
|
|
194
|
-
{ name: "s3", class: S3Service, depends: [], category: 'Armazenamento & Banco de Dados' },
|
|
195
|
-
{ name: "athena", class: AthenaService, depends: [], category: 'Armazenamento & Banco de Dados' },
|
|
196
|
-
|
|
197
|
-
//Computação
|
|
198
|
-
{ name: "lambda", class: LambdaService, depends: [], category: 'Computação' },
|
|
199
|
-
/* { name: "ecs", class: ECSService, depends: [] , category:'Computação'},*/
|
|
200
|
-
|
|
201
|
-
{ name: "cognito", class: CognitoService, depends: ["lambda"], category: 'Segurança & Identidade' },
|
|
202
|
-
{ name: "sts", class: STSService, depends: [], category: 'Segurança & Identidade' },
|
|
203
|
-
{ name: "kms", class: KMSService, depends: [], category: 'Segurança & Identidade' },
|
|
204
|
-
{ name: "secret-manager", class: SecretManagerService, depends: [], category: 'Segurança & Identidade' },
|
|
205
|
-
{ name: "parameter-store", class: ParameterStoreService, depends: [], category: 'Segurança & Identidade' },
|
|
206
|
-
|
|
207
|
-
//Mensageria
|
|
208
|
-
{ name: "sqs", class: SQSService, depends: ["lambda"], category: 'Mensageria & Integração' },
|
|
209
|
-
{ name: "sns", class: SNSService, depends: [], category: 'Mensageria & Integração' },
|
|
210
|
-
{ name: "eventbridge", class: EventBridgeService, depends: [], category: 'Mensageria & Integração' },
|
|
211
|
-
|
|
212
|
-
//Networking
|
|
213
|
-
{ name: "apigateway", class: APIGatewayService, depends: ["lambda", "cognito"], category: 'Networking' },
|
|
214
|
-
|
|
215
|
-
//Observabilidade & Conformidade
|
|
216
|
-
{ name: "cloudwatch", class: CloudWatchService, depends: [], category: 'Observabilidade & Conformidade' },
|
|
217
|
-
{ name: "cloudtrail", class: CloudTrailService, depends: [], category: 'Observabilidade & Conformidade' },
|
|
218
|
-
{ name: "xray", class: XRayService, depends: [], category: 'Observabilidade & Conformidade' },
|
|
219
|
-
{ name: "config", class: ConfigService, depends: [], category: 'Observabilidade & Conformidade' },
|
|
220
|
-
{ name: "cloudformation", class: CloudFormationService, depends: [], category: 'Observabilidade & Conformidade' },
|
|
221
|
-
|
|
222
|
-
];
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
async initializeServices() {
|
|
226
|
-
const serviceOrder = this.buildServiceRegistry();
|
|
227
|
-
|
|
228
|
-
for (const serviceDef of serviceOrder) {
|
|
229
|
-
if (this.config.services[serviceDef.name]) {
|
|
230
|
-
try {
|
|
231
|
-
const dependencies = {};
|
|
232
|
-
for (const dep of serviceDef.depends) {
|
|
233
|
-
dependencies[dep] = this.servicesMap.get(dep);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const service = new serviceDef.class(this.config, dependencies);
|
|
237
|
-
await service.initialize();
|
|
238
|
-
|
|
239
|
-
this.services.push(service);
|
|
240
|
-
this.servicesMap.set(serviceDef.name, service);
|
|
241
|
-
|
|
242
|
-
logger.success(`✅ ${serviceDef.name.toUpperCase()} Service inicializado`);
|
|
243
|
-
} catch (error) {
|
|
244
|
-
logger.error(`❌ Erro ao inicializar ${serviceDef.name}:`, error);
|
|
245
|
-
if (serviceDef.name === "lambda") throw error;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Injeta dependências cross-service nos serviços que suportam
|
|
251
|
-
for (const service of this.services) {
|
|
252
|
-
if (typeof service.injectDependencies === "function") {
|
|
253
|
-
service.injectDependencies(this);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
async startServices() {
|
|
259
|
-
const startPromises = this.services.map((service) => service.start());
|
|
260
|
-
await Promise.all(startPromises);
|
|
261
|
-
logger.success("\n🎉 Todos os serviços foram iniciados com sucesso!");
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
async stop() {
|
|
265
|
-
if (!this.running) {
|
|
266
|
-
logger.warn("Servidor não está rodando");
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
logger.info("\n🛑 Parando AWS Local Simulator...\n");
|
|
271
|
-
|
|
272
|
-
try {
|
|
273
|
-
const stopPromises = [...this.services].reverse().map((service) => service.stop());
|
|
274
|
-
await Promise.all(stopPromises);
|
|
275
|
-
|
|
276
|
-
if (this.managementServer) {
|
|
277
|
-
await new Promise((resolve) => this.managementServer.close(resolve));
|
|
278
|
-
this.managementServer = null;
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
this.running = false;
|
|
282
|
-
logger.success("✅ Todos os serviços foram parados");
|
|
283
|
-
} catch (error) {
|
|
284
|
-
logger.error("❌ Erro ao parar servidor:", error);
|
|
285
|
-
throw error;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
async reset() {
|
|
290
|
-
logger.info("\n🗑️ Resetando todos os dados...\n");
|
|
291
|
-
|
|
292
|
-
const resetPromises = this.services.map((service) => service.reset());
|
|
293
|
-
await Promise.all(resetPromises);
|
|
294
|
-
|
|
295
|
-
logger.success("✅ Todos os dados foram resetados");
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
getStatus() {
|
|
299
|
-
const status = {
|
|
300
|
-
running: this.running,
|
|
301
|
-
services: {},
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
for (const service of this.services) {
|
|
305
|
-
status.services[service.name] = service.getStatus();
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
return status;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
getService(name) {
|
|
312
|
-
return this.servicesMap.get(name);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
async enableService(name) {
|
|
316
|
-
// Check if already running
|
|
317
|
-
if (this.servicesMap.has(name)) {
|
|
318
|
-
return { success: false, error: "Service already running" };
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// Look up in registry
|
|
322
|
-
const registry = this.buildServiceRegistry();
|
|
323
|
-
const serviceDef = registry.find((s) => s.name === name);
|
|
324
|
-
if (!serviceDef) {
|
|
325
|
-
return { success: false, error: "Unknown service" };
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// Validate all dependencies are running
|
|
329
|
-
for (const dep of serviceDef.depends) {
|
|
330
|
-
if (!this.servicesMap.has(dep)) {
|
|
331
|
-
return { success: false, error: `Dependency not running: ${dep}` };
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
try {
|
|
336
|
-
const service = new serviceDef.class(this.config);
|
|
337
|
-
await service.initialize();
|
|
338
|
-
await service.start();
|
|
339
|
-
|
|
340
|
-
this.services.push(service);
|
|
341
|
-
this.servicesMap.set(name, service);
|
|
342
|
-
|
|
343
|
-
if (typeof service.injectDependencies === "function") {
|
|
344
|
-
service.injectDependencies(this);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Build ServiceStatus for the response
|
|
348
|
-
const canDisable = !registry.some(
|
|
349
|
-
(other) =>
|
|
350
|
-
other.depends.includes(name) && this.servicesMap.has(other.name)
|
|
351
|
-
);
|
|
352
|
-
const rawStatus =
|
|
353
|
-
typeof service.getStatus === "function"
|
|
354
|
-
? service.getStatus()
|
|
355
|
-
: { name, running: true, port: service.port };
|
|
356
|
-
|
|
357
|
-
const serviceStatus = {
|
|
358
|
-
name,
|
|
359
|
-
running: true,
|
|
360
|
-
enabled: true,
|
|
361
|
-
port: rawStatus.port || this.config.ports?.[name],
|
|
362
|
-
endpoint:
|
|
363
|
-
rawStatus.endpoint ||
|
|
364
|
-
`http://localhost:${rawStatus.port || this.config.ports?.[name]}`,
|
|
365
|
-
dependencies: serviceDef.depends,
|
|
366
|
-
canDisable,
|
|
367
|
-
...rawStatus,
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
return { success: true, service: serviceStatus };
|
|
371
|
-
} catch (error) {
|
|
372
|
-
return { success: false, error: error.message };
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
async disableService(name) {
|
|
377
|
-
// Check if running
|
|
378
|
-
const service = this.servicesMap.get(name);
|
|
379
|
-
if (!service) {
|
|
380
|
-
return { success: false, error: "Service not running" };
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Check reverse dependencies
|
|
384
|
-
const registry = this.buildServiceRegistry();
|
|
385
|
-
for (const other of registry) {
|
|
386
|
-
if (other.depends.includes(name) && this.servicesMap.has(other.name)) {
|
|
387
|
-
return {
|
|
388
|
-
success: false,
|
|
389
|
-
error: `Cannot disable: ${other.name} depends on it`,
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
try {
|
|
395
|
-
await service.stop();
|
|
396
|
-
this.services = this.services.filter((s) => s !== service);
|
|
397
|
-
this.servicesMap.delete(name);
|
|
398
|
-
|
|
399
|
-
return {
|
|
400
|
-
success: true,
|
|
401
|
-
service: {
|
|
402
|
-
name,
|
|
403
|
-
running: false,
|
|
404
|
-
enabled: false,
|
|
405
|
-
port: this.config.ports?.[name],
|
|
406
|
-
endpoint: `http://localhost:${this.config.ports?.[name]}`,
|
|
407
|
-
dependencies: registry.find((d) => d.name === name)?.depends || [],
|
|
408
|
-
canDisable: true,
|
|
409
|
-
},
|
|
410
|
-
};
|
|
411
|
-
} catch (error) {
|
|
412
|
-
return { success: false, error: error.message };
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
printStatus() {
|
|
417
|
-
logger.info("\n" + "=".repeat(60));
|
|
418
|
-
logger.info("📊 Status dos Serviços:");
|
|
419
|
-
logger.info("=".repeat(60));
|
|
420
|
-
|
|
421
|
-
for (const service of this.services) {
|
|
422
|
-
const status = service.getStatus();
|
|
423
|
-
logger.info(`\n${service.name.toUpperCase()}:`);
|
|
424
|
-
logger.info(` Status: ${status.running ? "✅ Rodando" : "❌ Parado"}`);
|
|
425
|
-
logger.info(` Porta: ${status.port}`);
|
|
426
|
-
logger.info(` Endpoint: ${status.endpoint}`);
|
|
427
|
-
|
|
428
|
-
if (status.tablesCount !== undefined) {
|
|
429
|
-
logger.info(` Tabelas: ${status.tablesCount}`);
|
|
430
|
-
}
|
|
431
|
-
if (status.bucketsCount !== undefined) {
|
|
432
|
-
logger.info(` Buckets: ${status.bucketsCount}`);
|
|
433
|
-
}
|
|
434
|
-
if (status.queuesCount !== undefined) {
|
|
435
|
-
logger.info(` Filas: ${status.queuesCount}`);
|
|
436
|
-
}
|
|
437
|
-
if (status.lambdasCount !== undefined) {
|
|
438
|
-
logger.info(` Lambdas: ${status.lambdasCount}`);
|
|
439
|
-
}
|
|
440
|
-
if (status.objectsCount !== undefined) {
|
|
441
|
-
logger.info(` Objetos: ${status.objectsCount}`);
|
|
442
|
-
}
|
|
443
|
-
if (status.messagesCount !== undefined) {
|
|
444
|
-
logger.info(` Mensagens: ${status.messagesCount}`);
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
logger.info("\n" + "=".repeat(60));
|
|
449
|
-
logger.info("\n📝 Comandos úteis:");
|
|
450
|
-
logger.info(" AWS CLI:");
|
|
451
|
-
logger.info(" aws dynamodb list-tables --endpoint-url http://localhost:8000");
|
|
452
|
-
logger.info(" aws s3 ls --endpoint-url http://localhost:4566");
|
|
453
|
-
logger.info(" aws sqs list-queues --endpoint-url http://localhost:9324");
|
|
454
|
-
logger.info("\n Testar APIs:");
|
|
455
|
-
logger.info(" curl http://localhost:3001/health");
|
|
456
|
-
logger.info(" curl http://localhost:8000/__admin/tables");
|
|
457
|
-
logger.info(" curl http://localhost:4566/__admin/buckets");
|
|
458
|
-
logger.info(" curl http://localhost:9324/__admin/queues");
|
|
459
|
-
logger.info("=".repeat(60) + "\n");
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
module.exports = Server;
|
|
1
|
+
/**
|
|
2
|
+
* Servidor Principal - Orquestra todos os serviços
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const fs = require("fs");
|
|
7
|
+
const mkdirp = require("mkdirp");
|
|
8
|
+
const express = require("express");
|
|
9
|
+
const cors = require("cors");
|
|
10
|
+
const logger = require("./utils/logger");
|
|
11
|
+
|
|
12
|
+
// Importa serviços
|
|
13
|
+
const DynamoDBService = require("./services/dynamodb");
|
|
14
|
+
const S3Service = require("./services/s3");
|
|
15
|
+
const SQSService = require("./services/sqs");
|
|
16
|
+
const LambdaService = require("./services/lambda");
|
|
17
|
+
const { SNSService } = require("./services/sns");
|
|
18
|
+
const { EventBridgeService } = require("./services/eventbridge");
|
|
19
|
+
const CognitoService = require("./services/cognito");
|
|
20
|
+
const APIGatewayService = require("./services/apigateway");
|
|
21
|
+
const ECSService = require("./services/ecs");
|
|
22
|
+
const STSService = require("./services/sts");
|
|
23
|
+
const { CloudWatchService } = require("./services/cloudwatch");
|
|
24
|
+
const CloudTrailService = require("./services/cloudtrail");
|
|
25
|
+
const { KMSService } = require("./services/kms");
|
|
26
|
+
const CloudFormationService = require("./services/cloudformation");
|
|
27
|
+
const { XRayService } = require("./services/xray");
|
|
28
|
+
const { SecretManagerService } = require("./services/secret-manager");
|
|
29
|
+
const { ParameterStoreService } = require("./services/parameter-store");
|
|
30
|
+
const { ConfigService } = require("./services/config");
|
|
31
|
+
const { AthenaService } = require("./services/athena");
|
|
32
|
+
|
|
33
|
+
class Server {
|
|
34
|
+
constructor(config) {
|
|
35
|
+
this.config = config;
|
|
36
|
+
this.services = [];
|
|
37
|
+
this.servicesMap = new Map();
|
|
38
|
+
this.running = false;
|
|
39
|
+
this.managementApp = express();
|
|
40
|
+
this.managementApp.use(cors());
|
|
41
|
+
this.managementApp.use(express.json());
|
|
42
|
+
this.managementServer = null;
|
|
43
|
+
this.setupDataDir();
|
|
44
|
+
this.setupLogLevel();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setupDataDir() {
|
|
48
|
+
const dataDir = path.resolve(process.cwd(), this.config.dataDir);
|
|
49
|
+
if (!fs.existsSync(dataDir)) {
|
|
50
|
+
mkdirp.sync(dataDir);
|
|
51
|
+
logger.debug(`📁 Diretório de dados criado: ${dataDir}`);
|
|
52
|
+
}
|
|
53
|
+
process.env.AWS_LOCAL_SIMULATOR_DATA_DIR = dataDir;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
setupLogLevel() {
|
|
57
|
+
logger.setLevel(this.config.logLevel);
|
|
58
|
+
logger.info(`📝 Nível de log: ${this.config.logLevel}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async start() {
|
|
62
|
+
if (this.running) {
|
|
63
|
+
logger.warn("Servidor já está rodando");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
logger.info("\n🚀 Iniciando AWS Local Simulator...\n");
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
await this.initializeServices();
|
|
71
|
+
await this.startServices();
|
|
72
|
+
this.setupManagementRoutes();
|
|
73
|
+
await this.startManagementServer();
|
|
74
|
+
|
|
75
|
+
this.running = true;
|
|
76
|
+
this.printStatus();
|
|
77
|
+
} catch (error) {
|
|
78
|
+
logger.error("❌ Erro ao iniciar servidor:", error);
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
setupManagementRoutes() {
|
|
84
|
+
const app = this.managementApp;
|
|
85
|
+
|
|
86
|
+
// GET /__admin/services — returns all services status
|
|
87
|
+
app.get("/__admin/services", (req, res) => {
|
|
88
|
+
const registry = this.buildServiceRegistry();
|
|
89
|
+
const services = registry.map((def) => {
|
|
90
|
+
const svc = this.servicesMap.get(def.name);
|
|
91
|
+
if (svc) {
|
|
92
|
+
const status = typeof svc.getStatus === "function"
|
|
93
|
+
? svc.getStatus()
|
|
94
|
+
: { name: def.name, running: true, port: svc.port };
|
|
95
|
+
// Compute canDisable: no running service should depend on this one
|
|
96
|
+
const canDisable = !registry.some(
|
|
97
|
+
(other) =>
|
|
98
|
+
other.depends.includes(def.name) &&
|
|
99
|
+
this.servicesMap.has(other.name)
|
|
100
|
+
);
|
|
101
|
+
return {
|
|
102
|
+
name: def.name,
|
|
103
|
+
running: true,
|
|
104
|
+
enabled: true,
|
|
105
|
+
port: status.port || this.config.ports?.[def.name],
|
|
106
|
+
endpoint: status.endpoint || `http://localhost:${status.port || this.config.ports?.[def.name]}`,
|
|
107
|
+
dependencies: def.depends,
|
|
108
|
+
category: def.category,
|
|
109
|
+
canDisable,
|
|
110
|
+
...status,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
name: def.name,
|
|
115
|
+
running: false,
|
|
116
|
+
enabled: false,
|
|
117
|
+
port: this.config.ports?.[def.name],
|
|
118
|
+
endpoint: `http://localhost:${this.config.ports?.[def.name]}`,
|
|
119
|
+
dependencies: def.depends,
|
|
120
|
+
canDisable: true,
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
res.json({ services });
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// GET /__admin/services/:name — returns single service status
|
|
127
|
+
app.get("/__admin/services/:name", (req, res) => {
|
|
128
|
+
const { name } = req.params;
|
|
129
|
+
const registry = this.buildServiceRegistry();
|
|
130
|
+
const def = registry.find((d) => d.name === name);
|
|
131
|
+
if (!def) {
|
|
132
|
+
return res.status(404).json({ error: `Unknown service: ${name}` });
|
|
133
|
+
}
|
|
134
|
+
const svc = this.servicesMap.get(name);
|
|
135
|
+
const canDisable = !registry.some(
|
|
136
|
+
(other) =>
|
|
137
|
+
other.depends.includes(name) &&
|
|
138
|
+
this.servicesMap.has(other.name)
|
|
139
|
+
);
|
|
140
|
+
if (svc) {
|
|
141
|
+
const status = typeof svc.getStatus === "function"
|
|
142
|
+
? svc.getStatus()
|
|
143
|
+
: { name, running: true, port: svc.port };
|
|
144
|
+
return res.json({
|
|
145
|
+
name,
|
|
146
|
+
running: true,
|
|
147
|
+
enabled: true,
|
|
148
|
+
port: status.port || this.config.ports?.[name],
|
|
149
|
+
endpoint: status.endpoint || `http://localhost:${status.port || this.config.ports?.[name]}`,
|
|
150
|
+
dependencies: def.depends,
|
|
151
|
+
canDisable,
|
|
152
|
+
...status,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return res.json({
|
|
156
|
+
name,
|
|
157
|
+
running: false,
|
|
158
|
+
enabled: false,
|
|
159
|
+
port: this.config.ports?.[name],
|
|
160
|
+
endpoint: `http://localhost:${this.config.ports?.[name]}`,
|
|
161
|
+
dependencies: def.depends,
|
|
162
|
+
canDisable: true,
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// POST /__admin/services/:name/enable — enables a service
|
|
167
|
+
app.post("/__admin/services/:name/enable", async (req, res) => {
|
|
168
|
+
const result = await this.enableService(req.params.name);
|
|
169
|
+
res.status(result.success ? 200 : 400).json(result);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// POST /__admin/services/:name/disable — disables a service
|
|
173
|
+
app.post("/__admin/services/:name/disable", async (req, res) => {
|
|
174
|
+
const result = await this.disableService(req.params.name);
|
|
175
|
+
res.status(result.success ? 200 : 400).json(result);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
startManagementServer() {
|
|
180
|
+
return new Promise((resolve, reject) => {
|
|
181
|
+
const port = this.config.adminPort || 9999;
|
|
182
|
+
this.managementServer = this.managementApp.listen(port, () => {
|
|
183
|
+
logger.info(`🔧 Management API rodando em http://localhost:${port}`);
|
|
184
|
+
resolve();
|
|
185
|
+
});
|
|
186
|
+
this.managementServer.on("error", reject);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
buildServiceRegistry() {
|
|
191
|
+
return [
|
|
192
|
+
//Armazenamento & BD
|
|
193
|
+
{ name: "dynamodb", class: DynamoDBService, depends: [], category: 'Armazenamento & Banco de Dados' },
|
|
194
|
+
{ name: "s3", class: S3Service, depends: [], category: 'Armazenamento & Banco de Dados' },
|
|
195
|
+
{ name: "athena", class: AthenaService, depends: [], category: 'Armazenamento & Banco de Dados' },
|
|
196
|
+
|
|
197
|
+
//Computação
|
|
198
|
+
{ name: "lambda", class: LambdaService, depends: [], category: 'Computação' },
|
|
199
|
+
/* { name: "ecs", class: ECSService, depends: [] , category:'Computação'},*/
|
|
200
|
+
|
|
201
|
+
{ name: "cognito", class: CognitoService, depends: ["lambda"], category: 'Segurança & Identidade' },
|
|
202
|
+
{ name: "sts", class: STSService, depends: [], category: 'Segurança & Identidade' },
|
|
203
|
+
{ name: "kms", class: KMSService, depends: [], category: 'Segurança & Identidade' },
|
|
204
|
+
{ name: "secret-manager", class: SecretManagerService, depends: [], category: 'Segurança & Identidade' },
|
|
205
|
+
{ name: "parameter-store", class: ParameterStoreService, depends: [], category: 'Segurança & Identidade' },
|
|
206
|
+
|
|
207
|
+
//Mensageria
|
|
208
|
+
{ name: "sqs", class: SQSService, depends: ["lambda"], category: 'Mensageria & Integração' },
|
|
209
|
+
{ name: "sns", class: SNSService, depends: [], category: 'Mensageria & Integração' },
|
|
210
|
+
{ name: "eventbridge", class: EventBridgeService, depends: [], category: 'Mensageria & Integração' },
|
|
211
|
+
|
|
212
|
+
//Networking
|
|
213
|
+
{ name: "apigateway", class: APIGatewayService, depends: ["lambda", "cognito"], category: 'Networking' },
|
|
214
|
+
|
|
215
|
+
//Observabilidade & Conformidade
|
|
216
|
+
{ name: "cloudwatch", class: CloudWatchService, depends: [], category: 'Observabilidade & Conformidade' },
|
|
217
|
+
{ name: "cloudtrail", class: CloudTrailService, depends: [], category: 'Observabilidade & Conformidade' },
|
|
218
|
+
{ name: "xray", class: XRayService, depends: [], category: 'Observabilidade & Conformidade' },
|
|
219
|
+
{ name: "config", class: ConfigService, depends: [], category: 'Observabilidade & Conformidade' },
|
|
220
|
+
{ name: "cloudformation", class: CloudFormationService, depends: [], category: 'Observabilidade & Conformidade' },
|
|
221
|
+
|
|
222
|
+
];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async initializeServices() {
|
|
226
|
+
const serviceOrder = this.buildServiceRegistry();
|
|
227
|
+
|
|
228
|
+
for (const serviceDef of serviceOrder) {
|
|
229
|
+
if (this.config.services[serviceDef.name]) {
|
|
230
|
+
try {
|
|
231
|
+
const dependencies = {};
|
|
232
|
+
for (const dep of serviceDef.depends) {
|
|
233
|
+
dependencies[dep] = this.servicesMap.get(dep);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const service = new serviceDef.class(this.config, dependencies);
|
|
237
|
+
await service.initialize();
|
|
238
|
+
|
|
239
|
+
this.services.push(service);
|
|
240
|
+
this.servicesMap.set(serviceDef.name, service);
|
|
241
|
+
|
|
242
|
+
logger.success(`✅ ${serviceDef.name.toUpperCase()} Service inicializado`);
|
|
243
|
+
} catch (error) {
|
|
244
|
+
logger.error(`❌ Erro ao inicializar ${serviceDef.name}:`, error);
|
|
245
|
+
if (serviceDef.name === "lambda") throw error;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Injeta dependências cross-service nos serviços que suportam
|
|
251
|
+
for (const service of this.services) {
|
|
252
|
+
if (typeof service.injectDependencies === "function") {
|
|
253
|
+
service.injectDependencies(this);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async startServices() {
|
|
259
|
+
const startPromises = this.services.map((service) => service.start());
|
|
260
|
+
await Promise.all(startPromises);
|
|
261
|
+
logger.success("\n🎉 Todos os serviços foram iniciados com sucesso!");
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async stop() {
|
|
265
|
+
if (!this.running) {
|
|
266
|
+
logger.warn("Servidor não está rodando");
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
logger.info("\n🛑 Parando AWS Local Simulator...\n");
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
const stopPromises = [...this.services].reverse().map((service) => service.stop());
|
|
274
|
+
await Promise.all(stopPromises);
|
|
275
|
+
|
|
276
|
+
if (this.managementServer) {
|
|
277
|
+
await new Promise((resolve) => this.managementServer.close(resolve));
|
|
278
|
+
this.managementServer = null;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
this.running = false;
|
|
282
|
+
logger.success("✅ Todos os serviços foram parados");
|
|
283
|
+
} catch (error) {
|
|
284
|
+
logger.error("❌ Erro ao parar servidor:", error);
|
|
285
|
+
throw error;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
async reset() {
|
|
290
|
+
logger.info("\n🗑️ Resetando todos os dados...\n");
|
|
291
|
+
|
|
292
|
+
const resetPromises = this.services.map((service) => service.reset());
|
|
293
|
+
await Promise.all(resetPromises);
|
|
294
|
+
|
|
295
|
+
logger.success("✅ Todos os dados foram resetados");
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
getStatus() {
|
|
299
|
+
const status = {
|
|
300
|
+
running: this.running,
|
|
301
|
+
services: {},
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
for (const service of this.services) {
|
|
305
|
+
status.services[service.name] = service.getStatus();
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return status;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
getService(name) {
|
|
312
|
+
return this.servicesMap.get(name);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async enableService(name) {
|
|
316
|
+
// Check if already running
|
|
317
|
+
if (this.servicesMap.has(name)) {
|
|
318
|
+
return { success: false, error: "Service already running" };
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Look up in registry
|
|
322
|
+
const registry = this.buildServiceRegistry();
|
|
323
|
+
const serviceDef = registry.find((s) => s.name === name);
|
|
324
|
+
if (!serviceDef) {
|
|
325
|
+
return { success: false, error: "Unknown service" };
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Validate all dependencies are running
|
|
329
|
+
for (const dep of serviceDef.depends) {
|
|
330
|
+
if (!this.servicesMap.has(dep)) {
|
|
331
|
+
return { success: false, error: `Dependency not running: ${dep}` };
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
try {
|
|
336
|
+
const service = new serviceDef.class(this.config);
|
|
337
|
+
await service.initialize();
|
|
338
|
+
await service.start();
|
|
339
|
+
|
|
340
|
+
this.services.push(service);
|
|
341
|
+
this.servicesMap.set(name, service);
|
|
342
|
+
|
|
343
|
+
if (typeof service.injectDependencies === "function") {
|
|
344
|
+
service.injectDependencies(this);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Build ServiceStatus for the response
|
|
348
|
+
const canDisable = !registry.some(
|
|
349
|
+
(other) =>
|
|
350
|
+
other.depends.includes(name) && this.servicesMap.has(other.name)
|
|
351
|
+
);
|
|
352
|
+
const rawStatus =
|
|
353
|
+
typeof service.getStatus === "function"
|
|
354
|
+
? service.getStatus()
|
|
355
|
+
: { name, running: true, port: service.port };
|
|
356
|
+
|
|
357
|
+
const serviceStatus = {
|
|
358
|
+
name,
|
|
359
|
+
running: true,
|
|
360
|
+
enabled: true,
|
|
361
|
+
port: rawStatus.port || this.config.ports?.[name],
|
|
362
|
+
endpoint:
|
|
363
|
+
rawStatus.endpoint ||
|
|
364
|
+
`http://localhost:${rawStatus.port || this.config.ports?.[name]}`,
|
|
365
|
+
dependencies: serviceDef.depends,
|
|
366
|
+
canDisable,
|
|
367
|
+
...rawStatus,
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
return { success: true, service: serviceStatus };
|
|
371
|
+
} catch (error) {
|
|
372
|
+
return { success: false, error: error.message };
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
async disableService(name) {
|
|
377
|
+
// Check if running
|
|
378
|
+
const service = this.servicesMap.get(name);
|
|
379
|
+
if (!service) {
|
|
380
|
+
return { success: false, error: "Service not running" };
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Check reverse dependencies
|
|
384
|
+
const registry = this.buildServiceRegistry();
|
|
385
|
+
for (const other of registry) {
|
|
386
|
+
if (other.depends.includes(name) && this.servicesMap.has(other.name)) {
|
|
387
|
+
return {
|
|
388
|
+
success: false,
|
|
389
|
+
error: `Cannot disable: ${other.name} depends on it`,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
try {
|
|
395
|
+
await service.stop();
|
|
396
|
+
this.services = this.services.filter((s) => s !== service);
|
|
397
|
+
this.servicesMap.delete(name);
|
|
398
|
+
|
|
399
|
+
return {
|
|
400
|
+
success: true,
|
|
401
|
+
service: {
|
|
402
|
+
name,
|
|
403
|
+
running: false,
|
|
404
|
+
enabled: false,
|
|
405
|
+
port: this.config.ports?.[name],
|
|
406
|
+
endpoint: `http://localhost:${this.config.ports?.[name]}`,
|
|
407
|
+
dependencies: registry.find((d) => d.name === name)?.depends || [],
|
|
408
|
+
canDisable: true,
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
} catch (error) {
|
|
412
|
+
return { success: false, error: error.message };
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
printStatus() {
|
|
417
|
+
logger.info("\n" + "=".repeat(60));
|
|
418
|
+
logger.info("📊 Status dos Serviços:");
|
|
419
|
+
logger.info("=".repeat(60));
|
|
420
|
+
|
|
421
|
+
for (const service of this.services) {
|
|
422
|
+
const status = service.getStatus();
|
|
423
|
+
logger.info(`\n${service.name.toUpperCase()}:`);
|
|
424
|
+
logger.info(` Status: ${status.running ? "✅ Rodando" : "❌ Parado"}`);
|
|
425
|
+
logger.info(` Porta: ${status.port}`);
|
|
426
|
+
logger.info(` Endpoint: ${status.endpoint}`);
|
|
427
|
+
|
|
428
|
+
if (status.tablesCount !== undefined) {
|
|
429
|
+
logger.info(` Tabelas: ${status.tablesCount}`);
|
|
430
|
+
}
|
|
431
|
+
if (status.bucketsCount !== undefined) {
|
|
432
|
+
logger.info(` Buckets: ${status.bucketsCount}`);
|
|
433
|
+
}
|
|
434
|
+
if (status.queuesCount !== undefined) {
|
|
435
|
+
logger.info(` Filas: ${status.queuesCount}`);
|
|
436
|
+
}
|
|
437
|
+
if (status.lambdasCount !== undefined) {
|
|
438
|
+
logger.info(` Lambdas: ${status.lambdasCount}`);
|
|
439
|
+
}
|
|
440
|
+
if (status.objectsCount !== undefined) {
|
|
441
|
+
logger.info(` Objetos: ${status.objectsCount}`);
|
|
442
|
+
}
|
|
443
|
+
if (status.messagesCount !== undefined) {
|
|
444
|
+
logger.info(` Mensagens: ${status.messagesCount}`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
logger.info("\n" + "=".repeat(60));
|
|
449
|
+
logger.info("\n📝 Comandos úteis:");
|
|
450
|
+
logger.info(" AWS CLI:");
|
|
451
|
+
logger.info(" aws dynamodb list-tables --endpoint-url http://localhost:8000");
|
|
452
|
+
logger.info(" aws s3 ls --endpoint-url http://localhost:4566");
|
|
453
|
+
logger.info(" aws sqs list-queues --endpoint-url http://localhost:9324");
|
|
454
|
+
logger.info("\n Testar APIs:");
|
|
455
|
+
logger.info(" curl http://localhost:3001/health");
|
|
456
|
+
logger.info(" curl http://localhost:8000/__admin/tables");
|
|
457
|
+
logger.info(" curl http://localhost:4566/__admin/buckets");
|
|
458
|
+
logger.info(" curl http://localhost:9324/__admin/queues");
|
|
459
|
+
logger.info("=".repeat(60) + "\n");
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
module.exports = Server;
|