@gugananuvem/aws-local-simulator 1.0.22 → 1.0.25
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/aws-config +154 -0
- package/package.json +6 -5
- package/src/services/cognito/simulator.js +25 -0
- package/src/services/dynamodb/simulator.js +33 -0
package/aws-config
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// lambda/layer/utils/aws-config.js
|
|
2
|
+
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
|
|
3
|
+
const { DynamoDBDocumentClient } = require('@aws-sdk/lib-dynamodb');
|
|
4
|
+
const { S3Client } = require('@aws-sdk/client-s3');
|
|
5
|
+
const { SQSClient } = require('@aws-sdk/client-sqs');
|
|
6
|
+
const { LambdaClient } = require('@aws-sdk/client-lambda');
|
|
7
|
+
const { CognitoIdentityProviderClient } = require("@aws-sdk/client-cognito-identity-provider");
|
|
8
|
+
|
|
9
|
+
// Detecta ambiente local
|
|
10
|
+
const isLocal = process.env.IS_LOCAL === 'true' ||
|
|
11
|
+
process.env.NODE_ENV === 'development' ||
|
|
12
|
+
process.env.AWS_SAM_LOCAL === 'true';
|
|
13
|
+
|
|
14
|
+
const isLocalS3 = process.env.IS_LOCAL_S3 === 'true'
|
|
15
|
+
const isLocalSQS = process.env.IS_LOCAL_SQS === 'true'
|
|
16
|
+
const isLocalDynamoDB = process.env.IS_LOCAL_DYNAMODB === 'true'
|
|
17
|
+
const isLocalLambda = process.env.IS_LOCAL_LAMBDA === 'true'
|
|
18
|
+
const isLocalCognito = process.env.IS_LOCAL_COGNITO === 'true'
|
|
19
|
+
|
|
20
|
+
// Endpoints locais (configuráveis via variáveis de ambiente)
|
|
21
|
+
const localEndpoints = {
|
|
22
|
+
dynamodb: process.env.DYNAMODB_ENDPOINT || 'http://localhost:8000',
|
|
23
|
+
s3: process.env.S3_ENDPOINT || 'http://localhost:4566',
|
|
24
|
+
sqs: process.env.SQS_ENDPOINT || 'http://localhost:9324',
|
|
25
|
+
lambda: process.env.LAMBDA_ENDPOINT || 'http://localhost:3001',
|
|
26
|
+
cognito: process.env.LOCAL_COGNITO || 'http://localhost:9229'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Credenciais para ambiente local (não são validadas)
|
|
30
|
+
const localCredentials = {
|
|
31
|
+
accessKeyId: process.env.AWS_ACCESS_KEY_ID || 'local',
|
|
32
|
+
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || 'local',
|
|
33
|
+
sessionToken: process.env.AWS_SESSION_TOKEN || undefined
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Configuração base para todos os clients
|
|
37
|
+
const baseConfig = {
|
|
38
|
+
region: process.env.AWS_REGION || 'us-east-1',
|
|
39
|
+
credentials: isLocal ? localCredentials : undefined
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// ============ DynamoDB Client ============
|
|
43
|
+
const dynamoDBClient = new DynamoDBClient({
|
|
44
|
+
...baseConfig,
|
|
45
|
+
endpoint: isLocalDynamoDB ? localEndpoints.dynamodb : undefined,
|
|
46
|
+
region: process.env.AWS_REGION || "us-east-1"
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const dynamoDBDocClient = DynamoDBDocumentClient.from(dynamoDBClient, {
|
|
50
|
+
marshallOptions: {
|
|
51
|
+
removeUndefinedValues: true,
|
|
52
|
+
convertEmptyValues: false
|
|
53
|
+
},
|
|
54
|
+
unmarshallOptions: {
|
|
55
|
+
wrapNumbers: false
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const cognitoClient = new CognitoIdentityProviderClient({
|
|
60
|
+
...baseConfig,
|
|
61
|
+
endpoint: isLocalCognito ? localEndpoints.cognito : undefined,
|
|
62
|
+
region: process.env.AWS_REGION || 'us-east-1'
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// ============ S3 Client ============
|
|
66
|
+
const s3Client = new S3Client({
|
|
67
|
+
...baseConfig,
|
|
68
|
+
endpoint: isLocalS3 ? localEndpoints.s3 : undefined,
|
|
69
|
+
forcePathStyle: true, // Necessário para S3 local (LocalStack, MinIO, etc)
|
|
70
|
+
// Para S3 real, não usar forcePathStyle
|
|
71
|
+
...(isLocalS3 ? {} : { forcePathStyle: false })
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// ============ SQS Client ============
|
|
75
|
+
const sqsClient = new SQSClient({
|
|
76
|
+
...baseConfig,
|
|
77
|
+
endpoint: isLocalSQS ? localEndpoints.sqs : undefined
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// ============ Lambda Client ============
|
|
81
|
+
const lambdaClient = new LambdaClient({
|
|
82
|
+
...baseConfig,
|
|
83
|
+
endpoint: isLocalLambda ? localEndpoints.lambda : undefined
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Log de configuração (apenas em desenvolvimento)
|
|
87
|
+
if (isLocalDynamoDB || isLocalS3 || isLocalSQS || isLocalLambda) {
|
|
88
|
+
console.log('🔧 Ambiente LOCAL detectado:');
|
|
89
|
+
console.log(` DynamoDB: ${localEndpoints.dynamodb}`);
|
|
90
|
+
console.log(` S3: ${localEndpoints.s3} (forcePathStyle: true)`);
|
|
91
|
+
console.log(` SQS: ${localEndpoints.sqs}`);
|
|
92
|
+
console.log(` Lambda: ${localEndpoints.lambda}`);
|
|
93
|
+
console.log(` Region: ${baseConfig.region}`);
|
|
94
|
+
}
|
|
95
|
+
if (isLocalDynamoDB || isLocalS3 || isLocalSQS || isLocalLambda) {
|
|
96
|
+
console.log('🔧 Ambiente LOCAL detectado:');
|
|
97
|
+
console.log(` Region: ${baseConfig.region}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (isLocalDynamoDB) {
|
|
101
|
+
console.log(` DynamoDB: ${localEndpoints.dynamodb}`);
|
|
102
|
+
}
|
|
103
|
+
if (isLocalS3) {
|
|
104
|
+
console.log(` S3: ${localEndpoints.s3} (forcePathStyle: true)`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (isLocalSQS) {
|
|
108
|
+
console.log(` SQS: ${localEndpoints.sqs}`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (isLocalLambda) {
|
|
112
|
+
console.log(` Lambda: ${localEndpoints.lambda}`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (isLocalCognito){
|
|
116
|
+
console.log(` Cognito: ${localEndpoints.cognito}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
module.exports = {
|
|
120
|
+
// Clients
|
|
121
|
+
dynamoDB: dynamoDBDocClient,
|
|
122
|
+
cognitoClient,
|
|
123
|
+
dynamoDBClient,
|
|
124
|
+
s3: s3Client,
|
|
125
|
+
sqs: sqsClient,
|
|
126
|
+
lambda: lambdaClient,
|
|
127
|
+
|
|
128
|
+
// Utilitários
|
|
129
|
+
isLocal,
|
|
130
|
+
localEndpoints,
|
|
131
|
+
|
|
132
|
+
// Configuração
|
|
133
|
+
config: {
|
|
134
|
+
region: baseConfig.region,
|
|
135
|
+
isLocal,
|
|
136
|
+
endpoints: localEndpoints
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
// Função para criar clients customizados (útil para testes)
|
|
140
|
+
createS3Client: (customEndpoint) => {
|
|
141
|
+
return new S3Client({
|
|
142
|
+
...baseConfig,
|
|
143
|
+
endpoint: customEndpoint || localEndpoints.s3,
|
|
144
|
+
forcePathStyle: true
|
|
145
|
+
});
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
createDynamoDBClient: (customEndpoint) => {
|
|
149
|
+
return new DynamoDBClient({
|
|
150
|
+
...baseConfig,
|
|
151
|
+
endpoint: customEndpoint || localEndpoints.dynamodb
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gugananuvem/aws-local-simulator",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.25",
|
|
4
4
|
"description": "Simulador local completo para serviços AWS",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -75,7 +75,8 @@
|
|
|
75
75
|
"src/",
|
|
76
76
|
"bin/",
|
|
77
77
|
"README.md",
|
|
78
|
-
"LICENSE"
|
|
78
|
+
"LICENSE",
|
|
79
|
+
"aws-config"
|
|
79
80
|
],
|
|
80
81
|
"publishConfig": {
|
|
81
82
|
"directory": "dist"
|
|
@@ -84,11 +85,11 @@
|
|
|
84
85
|
"cors": "^2.8.5",
|
|
85
86
|
"dotenv": "^16.3.1",
|
|
86
87
|
"express": "^4.18.2",
|
|
87
|
-
"glob": "
|
|
88
|
+
"glob": "10.5.0",
|
|
88
89
|
"jsonwebtoken": "^9.0.2",
|
|
89
90
|
"mkdirp": "^3.0.1",
|
|
90
91
|
"urlpattern-polyfill": "^10.0.0",
|
|
91
|
-
"uuid": "
|
|
92
|
+
"uuid": "14.0.0"
|
|
92
93
|
},
|
|
93
94
|
"peerDependencies": {
|
|
94
95
|
"@aws-sdk/client-api-gateway": "^3.0.0",
|
|
@@ -120,6 +121,6 @@
|
|
|
120
121
|
"optional": true
|
|
121
122
|
}
|
|
122
123
|
},
|
|
123
|
-
"buildDate": "2026-04-
|
|
124
|
+
"buildDate": "2026-04-24T17:52:50.093Z",
|
|
124
125
|
"published": true
|
|
125
126
|
}
|
|
@@ -87,10 +87,35 @@ class CognitoSimulator {
|
|
|
87
87
|
this.loadIdentityPools();
|
|
88
88
|
this.loadUsers();
|
|
89
89
|
this.loadSessions();
|
|
90
|
+
this._watchUsersFile();
|
|
90
91
|
|
|
91
92
|
logger.debug(`✅ Cognito Simulator inicializado com ${this.userPools.size} user pools, ${this.identityPools.size} identity pools, ${this.users.size} usuários`);
|
|
92
93
|
}
|
|
93
94
|
|
|
95
|
+
_watchUsersFile() {
|
|
96
|
+
const fs = require("fs");
|
|
97
|
+
const usersFilePath = this.store.getFilePath("__users__");
|
|
98
|
+
if (!fs.existsSync(usersFilePath)) return;
|
|
99
|
+
|
|
100
|
+
let reloadTimeout = null;
|
|
101
|
+
fs.watch(usersFilePath, (eventType) => {
|
|
102
|
+
if (eventType !== "change") return;
|
|
103
|
+
// Debounce para evitar múltiplos reloads em edições rápidas
|
|
104
|
+
clearTimeout(reloadTimeout);
|
|
105
|
+
reloadTimeout = setTimeout(() => {
|
|
106
|
+
try {
|
|
107
|
+
this.users.clear();
|
|
108
|
+
this.loadUsers();
|
|
109
|
+
logger.info(`🔄 Cognito users recarregados do disco (${this.users.size} usuários)`);
|
|
110
|
+
} catch (err) {
|
|
111
|
+
logger.warn(`⚠️ Erro ao recarregar users: ${err.message}`);
|
|
112
|
+
}
|
|
113
|
+
}, 200);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
logger.debug(`👁️ Watching: ${usersFilePath}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
94
119
|
// ============ User Pool Operations ============
|
|
95
120
|
|
|
96
121
|
createUserPool(params) {
|
|
@@ -25,9 +25,38 @@ class DynamoDBSimulator {
|
|
|
25
25
|
async initialize() {
|
|
26
26
|
logger.debug("Inicializando DynamoDB Simulator...");
|
|
27
27
|
this.loadTables();
|
|
28
|
+
this._watchTablesFile();
|
|
28
29
|
logger.debug(`✅ DynamoDB Simulator inicializado com ${this.tables.size} tabelas`);
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
_watchTablesFile() {
|
|
33
|
+
const fs = require("fs");
|
|
34
|
+
const tablesFilePath = this.store.getFilePath("__tables__");
|
|
35
|
+
if (!fs.existsSync(tablesFilePath)) return;
|
|
36
|
+
|
|
37
|
+
let reloadTimeout = null;
|
|
38
|
+
fs.watch(tablesFilePath, (eventType) => {
|
|
39
|
+
if (eventType !== "change") return;
|
|
40
|
+
clearTimeout(reloadTimeout);
|
|
41
|
+
reloadTimeout = setTimeout(() => {
|
|
42
|
+
try {
|
|
43
|
+
this.tables.clear();
|
|
44
|
+
const savedTables = this.store.read("__tables__");
|
|
45
|
+
if (savedTables) {
|
|
46
|
+
for (const [name, definition] of Object.entries(savedTables)) {
|
|
47
|
+
this.tables.set(name, definition);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
logger.info(`🔄 DynamoDB schema recarregado (${this.tables.size} tabelas)`);
|
|
51
|
+
} catch (err) {
|
|
52
|
+
logger.warn(`⚠️ Erro ao recarregar schema: ${err.message}`);
|
|
53
|
+
}
|
|
54
|
+
}, 200);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
logger.debug(`👁️ Watching: ${tablesFilePath}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
31
60
|
loadTables() {
|
|
32
61
|
// Carrega tabelas existentes do disco PRIMEIRO para evitar sobrescrever definições persistidas
|
|
33
62
|
const savedTables = this.store.read("__tables__");
|
|
@@ -350,8 +379,12 @@ class DynamoDBSimulator {
|
|
|
350
379
|
response.Attributes = this.marshallItem(oldItem, table);
|
|
351
380
|
break;
|
|
352
381
|
case "ALL_NEW":
|
|
382
|
+
case "UPDATED_NEW":
|
|
353
383
|
response.Attributes = this.marshallItem(updatedItem, table);
|
|
354
384
|
break;
|
|
385
|
+
case "UPDATED_OLD":
|
|
386
|
+
response.Attributes = this.marshallItem(oldItem, table);
|
|
387
|
+
break;
|
|
355
388
|
default:
|
|
356
389
|
break;
|
|
357
390
|
}
|