@minervajs/helmet 1.0.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/LICENSE +24 -0
- package/README.md +231 -0
- package/example/settings.js +53 -0
- package/js/db_mariadb.js +69 -0
- package/js/db_mongodb.js +49 -0
- package/js/db_mysql.js +162 -0
- package/js/db_oracle.js +76 -0
- package/js/db_postgres.js +60 -0
- package/package.json +33 -0
- package/src/db.js +246 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
BSD 2-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024, 2025, Alexander Enrique Escobar O.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
16
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
17
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
19
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
20
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
21
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
22
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
23
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
24
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# MinervaJS-Helmet
|
|
2
|
+
|
|
3
|
+
## 🛡️ Descripción
|
|
4
|
+
|
|
5
|
+
**MinervaJS-Helmet** es el módulo encargado de la **gestión unificada de conexiones y operaciones de base de datos** dentro del ecosistema **MinervaJS**.
|
|
6
|
+
|
|
7
|
+
Su función principal es abstraer el motor de base de datos (MySQL, PostgreSQL, Oracle, etc.) y exponer una **API homogénea**, permitiendo que el resto del sistema funcione de forma **JSON-driven**, desacoplada y extensible.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 🎯 Objetivos
|
|
12
|
+
|
|
13
|
+
* Centralizar la gestión de conexiones a bases de datos
|
|
14
|
+
* Soportar múltiples motores de forma transparente
|
|
15
|
+
* Proveer una API común para:
|
|
16
|
+
|
|
17
|
+
* Consultas de lectura (SELECT)
|
|
18
|
+
* Operaciones de escritura (INSERT / UPDATE / DELETE / DDL)
|
|
19
|
+
* Procedimientos almacenados
|
|
20
|
+
* Facilitar la construcción de backends genéricos y dinámicos
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🧱 Arquitectura
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
MinervaJS
|
|
28
|
+
└── Helmet
|
|
29
|
+
├── db_mysql.js
|
|
30
|
+
├── db_postgres.js
|
|
31
|
+
├── db_oracle.js
|
|
32
|
+
└── connections (cache interno)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Helmet actúa como un **dispatcher**, delegando la ejecución a proveedores específicos que implementan un contrato estándar.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## 🔌 Contrato estándar de proveedores
|
|
40
|
+
|
|
41
|
+
Cada proveedor de base de datos debe implementar las siguientes funciones:
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
connect(config)
|
|
45
|
+
query(connection, sql, params = [])
|
|
46
|
+
execute(connection, sql, params = [])
|
|
47
|
+
call(connection, procedureName, params = {})
|
|
48
|
+
close(connection)
|
|
49
|
+
closeAll(config)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Este contrato garantiza que Helmet pueda operar sin conocer los detalles del motor subyacente.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 📦 Instalación
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install @minervajs/helmet
|
|
60
|
+
```
|
|
61
|
+
⚠️ Previous name: minervajs-helmet (deprecated)
|
|
62
|
+
> *(o incluir el módulo directamente dentro del proyecto MinervaJS)*
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## ⚙️ Configuración de base de datos
|
|
67
|
+
|
|
68
|
+
Ejemplo de archivo `database.json`:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mysqlMain": {
|
|
73
|
+
"type": "mysql",
|
|
74
|
+
"host": "localhost",
|
|
75
|
+
"port": 3306,
|
|
76
|
+
"user": "user",
|
|
77
|
+
"password": "password",
|
|
78
|
+
"database": "minerva"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
En la instalacion, puedes hacer uso del archivo muestra que esta en *\node_modules\minervajs-helmet\example\settings.js*
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 🚀 Uso básico
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
const helmet = require('./helmet');
|
|
91
|
+
const config = require('./database.json');
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
### 🔍 Consultas de lectura (SELECT)
|
|
97
|
+
|
|
98
|
+
```js
|
|
99
|
+
const rows = await helmet.query(
|
|
100
|
+
'mysqlMain',
|
|
101
|
+
'SELECT * FROM pais WHERE iso3 = ?',
|
|
102
|
+
['SLV'],
|
|
103
|
+
config
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### ✏️ Operaciones de escritura
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
const result = await helmet.execute(
|
|
113
|
+
'mysqlMain',
|
|
114
|
+
'UPDATE pais SET nombre = ? WHERE iso3 = ?',
|
|
115
|
+
['El Salvador', 'SLV'],
|
|
116
|
+
config
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
console.log(result.rowsAffected);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### 🧠 Procedimientos almacenados
|
|
125
|
+
|
|
126
|
+
```js
|
|
127
|
+
const result = await helmet.call(
|
|
128
|
+
'mysqlMain',
|
|
129
|
+
'sp_pais_insert',
|
|
130
|
+
{
|
|
131
|
+
p_iso3: 'SLV',
|
|
132
|
+
p_nombre: 'El Salvador',
|
|
133
|
+
p_leyenda: 'Centroamérica',
|
|
134
|
+
p_iso2: 'SV',
|
|
135
|
+
p_existe: { out: true }
|
|
136
|
+
},
|
|
137
|
+
config
|
|
138
|
+
);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Resultado estándar:**
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
{
|
|
145
|
+
resultSets: [...],
|
|
146
|
+
out: {
|
|
147
|
+
p_existe: 0
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 🔐 Gestión de conexiones
|
|
155
|
+
|
|
156
|
+
* Una conexión por perfil de base de datos
|
|
157
|
+
* Reutilización automática
|
|
158
|
+
* Cache interno
|
|
159
|
+
* Cierre explícito
|
|
160
|
+
|
|
161
|
+
```js
|
|
162
|
+
await helmet.close('mysqlMain', config);
|
|
163
|
+
await helmet.closeAll(config);
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## ⚠️ Manejo de errores
|
|
169
|
+
|
|
170
|
+
Helmet agrega contexto a los errores:
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
[Helmet][mysql][execute] Duplicate entry
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Esto facilita el logging y el diagnóstico.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 🧩 Integración JSON-driven (MinervaJS)
|
|
181
|
+
|
|
182
|
+
Helmet está diseñado para ejecutarse a partir de manifiestos JSON:
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"database": "mysqlMain",
|
|
187
|
+
"procedure": "sp_pais_insert",
|
|
188
|
+
"params": {
|
|
189
|
+
"p_iso3": "$body.iso3",
|
|
190
|
+
"p_nombre": "$body.nombre",
|
|
191
|
+
"p_existe": { "out": true }
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
La API ejecuta la operación sin conocer SQL ni lógica de negocio.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## ✅ Buenas prácticas
|
|
201
|
+
|
|
202
|
+
* Usar `query()` exclusivamente para SELECT
|
|
203
|
+
* Usar `execute()` para DML / DDL
|
|
204
|
+
* Encapsular lógica compleja en Stored Procedures
|
|
205
|
+
* Cerrar conexiones en shutdown de la aplicación
|
|
206
|
+
* Mantener la configuración desacoplada
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 🔮 Evolución futura
|
|
212
|
+
|
|
213
|
+
* Pooling de conexiones
|
|
214
|
+
* Transacciones (`begin / commit / rollback`)
|
|
215
|
+
* Multi-tenant
|
|
216
|
+
* Logging estructurado
|
|
217
|
+
* Métricas
|
|
218
|
+
* Soporte para nuevos motores
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 📌 Conclusión
|
|
223
|
+
|
|
224
|
+
**MinervaJS-Helmet** es el pilar de acceso a datos de MinervaJS.
|
|
225
|
+
|
|
226
|
+
Su diseño modular, homogéneo y desacoplado permite construir aplicaciones dinámicas, escalables y mantenibles, donde la lógica de negocio puede definirse de forma declarativa y evolucionar sin reescribir el backend.
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module
|
|
3
|
+
* @name settings
|
|
4
|
+
* @description Modulo gestor de la coneccion a la base de datos
|
|
5
|
+
* Configuracion de la Base de Datos
|
|
6
|
+
*
|
|
7
|
+
* Se incluye un ejemplo de uso, segun el tipo de base de datos
|
|
8
|
+
*/
|
|
9
|
+
exports.httpMsgFormat = 'HTML';
|
|
10
|
+
exports.Title = "MinervaJS - Helmet";
|
|
11
|
+
exports.Rights_Reserved = "2023-2025 © A&C Consultoría Informática";
|
|
12
|
+
|
|
13
|
+
module.exports = {
|
|
14
|
+
/*
|
|
15
|
+
* 'mi_postgres':
|
|
16
|
+
* {
|
|
17
|
+
* type: 'postgres',
|
|
18
|
+
* host: 'localhost o IP',
|
|
19
|
+
* port: 5432,
|
|
20
|
+
* user: 'usuario',
|
|
21
|
+
* password: 'contraseña',
|
|
22
|
+
* database: 'nombre_db'
|
|
23
|
+
* },
|
|
24
|
+
*/
|
|
25
|
+
'my_mysql':
|
|
26
|
+
{
|
|
27
|
+
type: 'mysql',
|
|
28
|
+
host: 'sql3.freesqldatabase.com', // 'localhost',
|
|
29
|
+
port: 3306, // 'puerto',
|
|
30
|
+
user: 'sql3772729', // 'usuario',
|
|
31
|
+
password: 'esUA3qpGKD', // 'contraseña',
|
|
32
|
+
database: 'sql3772729' // 'nombre_db'
|
|
33
|
+
},
|
|
34
|
+
/* 'my_oracle': {
|
|
35
|
+
* type: 'oracle',
|
|
36
|
+
* user: 'usuario',
|
|
37
|
+
* password: 'contraseña',
|
|
38
|
+
* connectString : '(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=namehostoip)(PORT=port))(CONNECT_DATA=(SERVICE_NAME=servicename)))'
|
|
39
|
+
* },
|
|
40
|
+
* 'mi_mongodb': {
|
|
41
|
+
* type: 'mongodb',
|
|
42
|
+
* url: 'mongodb://localhost:27017/nombre_db'
|
|
43
|
+
* },
|
|
44
|
+
* 'mi_mariadb': {
|
|
45
|
+
* type: 'mariadb',
|
|
46
|
+
* host: 'localhost',
|
|
47
|
+
* port: 3306,
|
|
48
|
+
* user: 'mi_usuario',
|
|
49
|
+
* password: 'mi_contraseña',
|
|
50
|
+
* database: 'nombre_db'
|
|
51
|
+
* }
|
|
52
|
+
*/
|
|
53
|
+
};
|
package/js/db_mariadb.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module lib/mariadb
|
|
3
|
+
* @description Módulo para la conexión y operaciones de MariaDB.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @constant
|
|
8
|
+
* @type {string}
|
|
9
|
+
* @default
|
|
10
|
+
*/
|
|
11
|
+
const mariadb = require('mariadb/promise');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Establece una conexión a la base de datos MariaDB.
|
|
15
|
+
*
|
|
16
|
+
* @async
|
|
17
|
+
* @function connect
|
|
18
|
+
* @param {object} config - Configuración de la conexión.
|
|
19
|
+
* @returns {Promise<mariadb.Connection>} Objeto de conexión de MariaDB.
|
|
20
|
+
*/
|
|
21
|
+
async function connect(config) {
|
|
22
|
+
try {
|
|
23
|
+
const connection = await mariadb.createConnection(config);
|
|
24
|
+
return connection;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error('Error al conectar a MariaDB:', error);
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Ejecuta una consulta SQL en la base de datos MariaDB.
|
|
33
|
+
*
|
|
34
|
+
* @async
|
|
35
|
+
* @function query
|
|
36
|
+
* @param {mariadb.Connection} connection - Objeto de conexión de MariaDB.
|
|
37
|
+
* @param {string} sql - Consulta SQL.
|
|
38
|
+
* @param {Array} [values] - Parámetros para la consulta.
|
|
39
|
+
* @returns {Promise<Array>} Filas resultantes de la consulta.
|
|
40
|
+
*/
|
|
41
|
+
async function query(connection, sql, values = []) {
|
|
42
|
+
try {
|
|
43
|
+
const rows = await connection.query(sql, values);
|
|
44
|
+
return rows;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error('Error al ejecutar la consulta MariaDB:', error);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Cierra la conexión a la base de datos MariaDB.
|
|
53
|
+
*
|
|
54
|
+
* @async
|
|
55
|
+
* @function close
|
|
56
|
+
* @param {mariadb.Connection} connection - Objeto de conexión de MariaDB.
|
|
57
|
+
* @returns {Promise<void>}
|
|
58
|
+
*/
|
|
59
|
+
async function close(connection) {
|
|
60
|
+
try {
|
|
61
|
+
await connection.end();
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('Error al cerrar la conexión MariaDB:', error);
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = { connect, query, close };
|
|
69
|
+
|
package/js/db_mongodb.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const { MongoClient } = require('mongodb');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @module lib/mongodb
|
|
5
|
+
* @description Módulo para la conexión y operaciones de MongoDB. Comando: npm install mongodb
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Establece una conexión a la base de datos MongoDB.
|
|
10
|
+
*
|
|
11
|
+
* @async
|
|
12
|
+
* @function connect
|
|
13
|
+
* @param {object} config - Configuración de la conexión.
|
|
14
|
+
* @returns {Promise<MongoClient>} Objeto de cliente de MongoDB.
|
|
15
|
+
*/
|
|
16
|
+
async function connect(config) {
|
|
17
|
+
try {
|
|
18
|
+
const client = new MongoClient(config.url);
|
|
19
|
+
await client.connect();
|
|
20
|
+
return client;
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('Error al conectar a MongoDB:', error);
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
// query
|
|
29
|
+
// logica
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Cierra la conexión a la base de datos MongoDB.
|
|
34
|
+
*
|
|
35
|
+
* @async
|
|
36
|
+
* @function close
|
|
37
|
+
* @param {MongoClient} client - Objeto de cliente de MongoDB.
|
|
38
|
+
* @returns {Promise<void>}
|
|
39
|
+
*/
|
|
40
|
+
async function close(client) {
|
|
41
|
+
try {
|
|
42
|
+
await client.close();
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error('Error al cerrar la conexión MongoDB:', error);
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = { connect, close };
|
package/js/db_mysql.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module js/mysql
|
|
3
|
+
* @name Provider DB js/mysql
|
|
4
|
+
* @description Módulo proveedor MySQL para MinervaJS-Helmet.
|
|
5
|
+
* Implementa operaciones estándar: query, execute y call.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @constant
|
|
11
|
+
* @type {string}
|
|
12
|
+
* @default
|
|
13
|
+
*/
|
|
14
|
+
const mysql = require('mysql2/promise'); // Usamos mysql2/promise para async/await
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Establece una conexión a la base de datos MySQL.
|
|
18
|
+
*
|
|
19
|
+
* @async
|
|
20
|
+
* @function connect
|
|
21
|
+
* @param {object} config - Configuración de la conexión.
|
|
22
|
+
* @returns {Promise<mysql.Connection>} Objeto de conexión de MySQL.
|
|
23
|
+
*/
|
|
24
|
+
async function connect(config)
|
|
25
|
+
{
|
|
26
|
+
try
|
|
27
|
+
{
|
|
28
|
+
const connection = await mysql.createConnection({
|
|
29
|
+
host: config.host,
|
|
30
|
+
port: config.port,
|
|
31
|
+
user: config.user,
|
|
32
|
+
password: config.password,
|
|
33
|
+
database: config.database,
|
|
34
|
+
});
|
|
35
|
+
return connection;
|
|
36
|
+
}
|
|
37
|
+
catch (error)
|
|
38
|
+
{
|
|
39
|
+
console.error('[MySQL][connect]', error.message);
|
|
40
|
+
throw error; // Re-lanzamos el error para que sea manejado por el llamador
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Ejecuta una consulta SQL en la base de datos MySQL.
|
|
46
|
+
*
|
|
47
|
+
* @async
|
|
48
|
+
* @function query
|
|
49
|
+
* @param {mysql.Connection} connection - Objeto de conexión de MySQL.
|
|
50
|
+
* @param {string} sql - Consulta SQL.
|
|
51
|
+
* @param {Array} [params] - Parámetros para la consulta.
|
|
52
|
+
* @returns {Promise<Array>} Filas resultantes de la consulta.
|
|
53
|
+
*/
|
|
54
|
+
async function query(connection, sql, params = [])
|
|
55
|
+
{
|
|
56
|
+
try
|
|
57
|
+
{
|
|
58
|
+
const [rows, fields] = await connection.execute(sql, params);
|
|
59
|
+
return rows;
|
|
60
|
+
}
|
|
61
|
+
catch (error)
|
|
62
|
+
{
|
|
63
|
+
console.error('[MySQL][query]', error.message);
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Ejecuta una sentencia de escritura (INSERT, UPDATE, DELETE, DDL).
|
|
72
|
+
*/
|
|
73
|
+
async function execute(connection, sql, params = [])
|
|
74
|
+
{
|
|
75
|
+
try {
|
|
76
|
+
const [result] = await connection.execute(sql, params);
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
rowsAffected: result.affectedRows,
|
|
80
|
+
insertId: result.insertId || null
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error)
|
|
84
|
+
{
|
|
85
|
+
console.error('[MySQL][execute]', error.message);
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Ejecuta un procedimiento almacenado.
|
|
93
|
+
*
|
|
94
|
+
* Nota:
|
|
95
|
+
* MySQL maneja OUT params mediante variables de sesión (@var).
|
|
96
|
+
*/
|
|
97
|
+
async function call(connection, procedureName, params = {}) {
|
|
98
|
+
try {
|
|
99
|
+
const keys = Object.keys(params);
|
|
100
|
+
const values = [];
|
|
101
|
+
|
|
102
|
+
const placeholders = keys.map(key => {
|
|
103
|
+
if (params[key]?.out) {
|
|
104
|
+
return `@${key}`;
|
|
105
|
+
}
|
|
106
|
+
values.push(params[key]);
|
|
107
|
+
return '?';
|
|
108
|
+
}).join(',');
|
|
109
|
+
|
|
110
|
+
// 1️ - Ejecutar CALL
|
|
111
|
+
const callSQL = `CALL ${procedureName}(${placeholders})`;
|
|
112
|
+
const [resultSets] = await connection.query(callSQL, values);
|
|
113
|
+
|
|
114
|
+
// 2️ - Recuperar OUT params
|
|
115
|
+
const outParams = keys.filter(k => params[k]?.out);
|
|
116
|
+
let out = {};
|
|
117
|
+
|
|
118
|
+
if (outParams.length > 0) {
|
|
119
|
+
const selectOut = `SELECT ${outParams.map(k => `@${k} AS ${k}`).join(',')}`;
|
|
120
|
+
const [rows] = await connection.query(selectOut);
|
|
121
|
+
out = rows[0];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
resultSets,
|
|
126
|
+
out
|
|
127
|
+
};
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error('[MySQL][call]', error.message);
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Cierra la conexión a la base de datos MySQL.
|
|
138
|
+
*
|
|
139
|
+
* @async
|
|
140
|
+
* @function close
|
|
141
|
+
* @param {mysql.Connection} connection - Objeto de conexión de MySQL.
|
|
142
|
+
* @returns {Promise<void>}
|
|
143
|
+
*/
|
|
144
|
+
async function close(connection)
|
|
145
|
+
{
|
|
146
|
+
try
|
|
147
|
+
{ await connection.end(); }
|
|
148
|
+
catch (error)
|
|
149
|
+
{
|
|
150
|
+
console.error('[MySQL][close]', error.message);
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
module.exports =
|
|
156
|
+
{
|
|
157
|
+
connect,
|
|
158
|
+
query,
|
|
159
|
+
execute,
|
|
160
|
+
call,
|
|
161
|
+
close
|
|
162
|
+
};
|
package/js/db_oracle.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module js/oracle
|
|
3
|
+
* @name Provider DB js/oracle
|
|
4
|
+
* @description Módulo para la conexión y operaciones de Oracle.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @constant
|
|
9
|
+
* @type {string}
|
|
10
|
+
* @default
|
|
11
|
+
*/
|
|
12
|
+
const oracledb = require('oracledb');
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Establece una conexión a la base de datos Oracle.
|
|
17
|
+
*
|
|
18
|
+
* @async
|
|
19
|
+
* @function connect
|
|
20
|
+
* @param {object} config - Configuración de la conexión.
|
|
21
|
+
* @returns {Promise<oracledb.Connection>} Objeto de conexión de Oracle.
|
|
22
|
+
*/
|
|
23
|
+
async function connect(config) {
|
|
24
|
+
try {
|
|
25
|
+
oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT; // Para obtener resultados como objetos
|
|
26
|
+
|
|
27
|
+
const connection = await oracledb.getConnection({
|
|
28
|
+
user: config.user,
|
|
29
|
+
password: config.password,
|
|
30
|
+
connectString: config.connectString, // Ejemplo: 'localhost/XE' o una cadena de conexión TNS
|
|
31
|
+
});
|
|
32
|
+
return connection;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error('Error al conectar a Oracle:', error);
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Ejecuta una consulta SQL en la base de datos Oracle.
|
|
41
|
+
*
|
|
42
|
+
* @async
|
|
43
|
+
* @function query
|
|
44
|
+
* @param {oracledb.Connection} connection - Objeto de conexión de Oracle.
|
|
45
|
+
* @param {string} sql - Consulta SQL.
|
|
46
|
+
* @param {Array} [binds] - Parámetros para la consulta (bind variables).
|
|
47
|
+
* @returns {Promise<Array>} Filas resultantes de la consulta.
|
|
48
|
+
*/
|
|
49
|
+
async function query(connection, sql, binds = []) {
|
|
50
|
+
try {
|
|
51
|
+
const result = await connection.execute(sql, binds);
|
|
52
|
+
return result.rows;
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error('Error al ejecutar la consulta Oracle:', error);
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Cierra la conexión a la base de datos Oracle.
|
|
61
|
+
*
|
|
62
|
+
* @async
|
|
63
|
+
* @function close
|
|
64
|
+
* @param {oracledb.Connection} connection - Objeto de conexión de Oracle.
|
|
65
|
+
* @returns {Promise<void>}
|
|
66
|
+
*/
|
|
67
|
+
async function close(connection) {
|
|
68
|
+
try {
|
|
69
|
+
await connection.close();
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error('Error al cerrar la conexión Oracle:', error);
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = { connect, query, close };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module js/postgres
|
|
3
|
+
* @name Provider DB js/postgres
|
|
4
|
+
* @description Módulo para la conexión y operaciones del Proveedor PostgreSQL.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @constant
|
|
9
|
+
* @type {string}
|
|
10
|
+
* @default
|
|
11
|
+
*/
|
|
12
|
+
const { Client } = require('pg');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Establece una conexión a la base de datos PostgreSQL.
|
|
16
|
+
*
|
|
17
|
+
* @async
|
|
18
|
+
* @function connect
|
|
19
|
+
* @name connect
|
|
20
|
+
* @param {object} config - Configuración de la conexión.
|
|
21
|
+
* @returns {Promise<Client>} Objeto de cliente de PostgreSQL.
|
|
22
|
+
*/
|
|
23
|
+
async function connect(config)
|
|
24
|
+
{
|
|
25
|
+
const client = new Client(config);
|
|
26
|
+
await client.connect();
|
|
27
|
+
return client;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Ejecuta una consulta SQL en la base de datos PostgreSQL.
|
|
32
|
+
*
|
|
33
|
+
* @async
|
|
34
|
+
* @function query
|
|
35
|
+
* @name query
|
|
36
|
+
* @param {Client} client - Objeto de cliente de PostgreSQL.
|
|
37
|
+
* @param {string} sql - Consulta SQL.
|
|
38
|
+
* @returns {Promise<Array>} Filas resultantes de la consulta.
|
|
39
|
+
*/
|
|
40
|
+
async function query(client, sql)
|
|
41
|
+
{
|
|
42
|
+
const result = await client.query(sql);
|
|
43
|
+
return result.rows;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Cierra la conexión a la base de datos PostgreSQL.
|
|
48
|
+
*
|
|
49
|
+
* @async
|
|
50
|
+
* @function close
|
|
51
|
+
* @name close
|
|
52
|
+
* @param {Client} client - Objeto de cliente de PostgreSQL.
|
|
53
|
+
* @returns {Promise<void>}
|
|
54
|
+
*/
|
|
55
|
+
async function close(client)
|
|
56
|
+
{
|
|
57
|
+
await client.end();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = { connect, query, close };
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@minervajs/helmet",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "src/db.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"DB",
|
|
10
|
+
"Multi DataBase",
|
|
11
|
+
"connect",
|
|
12
|
+
"MySQL",
|
|
13
|
+
"Oracle Client",
|
|
14
|
+
"PostGres",
|
|
15
|
+
"MinervaJS"
|
|
16
|
+
],
|
|
17
|
+
"author": "alexander.enrique.escobar@gmail.com",
|
|
18
|
+
"license": "BSD-2-Clause",
|
|
19
|
+
"description": "Modulo para la gestion de coneccion a la base de datos, de diferentes tipos mediante el uso de sobre Carga y Herencia de clases",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"mysql2": "^3.14.0",
|
|
22
|
+
"oracledb": "^6.6.0",
|
|
23
|
+
"pg": "^8.14.1"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/Alexander-Escobar/MinervaJS.Helmet.git"
|
|
28
|
+
},
|
|
29
|
+
"bug": {
|
|
30
|
+
"url": "https://github.com/Alexander-Escobar/MinervaJS.Helmet.git/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/Alexander-Escobar/MinervaJS.Helmet.git#readme"
|
|
33
|
+
}
|
package/src/db.js
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* @name MinervaJS-Helmet
|
|
4
|
+
* @module MinervaJS-Helmet
|
|
5
|
+
* @description Gestor unificado de conexiones y ejecución de operaciones en múltiples motores de bases de datos.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const postgres = require('../js/db_postgres');
|
|
9
|
+
const mysql = require('../js/db_mysql');
|
|
10
|
+
const oracle = require('../js/db_oracle');
|
|
11
|
+
// const mongodb = require('./lib/mongodb');
|
|
12
|
+
// const mariadb = require('./lib/mariadb');
|
|
13
|
+
|
|
14
|
+
const connections = {};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Establece una conexión a la base de datos especificada.
|
|
18
|
+
*
|
|
19
|
+
* @async
|
|
20
|
+
* @function connect
|
|
21
|
+
* @name connect
|
|
22
|
+
* @param {string} databaseName - Perfil de la base de datos (clave de configuración)
|
|
23
|
+
* @returns {Promise<object>} Objeto de conexión.
|
|
24
|
+
* @throws {Error} Si la configuración no se encuentra o el tipo de base de datos no es soportado.
|
|
25
|
+
* @description Toma la configuracion y Establece una conexión a la base de datos especificada
|
|
26
|
+
*/
|
|
27
|
+
async function connect(databaseName, config)
|
|
28
|
+
{
|
|
29
|
+
const dbConfig = config[databaseName];
|
|
30
|
+
|
|
31
|
+
if (!dbConfig)
|
|
32
|
+
{ throw new Error(`Configuración de base de datos '${databaseName}' no encontrada.`); }
|
|
33
|
+
|
|
34
|
+
// Ya existe una conexión
|
|
35
|
+
if (connections[databaseName])
|
|
36
|
+
{ return connections[databaseName]; }
|
|
37
|
+
|
|
38
|
+
switch (dbConfig.type)
|
|
39
|
+
{
|
|
40
|
+
case 'postgres':
|
|
41
|
+
connections[databaseName] = await postgres.connect(dbConfig);
|
|
42
|
+
break;
|
|
43
|
+
case 'mysql':
|
|
44
|
+
connections[databaseName] = await mysql.connect(dbConfig);
|
|
45
|
+
break;
|
|
46
|
+
// case 'mariadb':
|
|
47
|
+
// connections[databaseName] = await mariadb.connect(dbConfig);
|
|
48
|
+
// break;
|
|
49
|
+
case 'oracle':
|
|
50
|
+
connections[databaseName] = await oracle.connect(dbConfig);
|
|
51
|
+
break;
|
|
52
|
+
// case 'mongodb':
|
|
53
|
+
// connections[databaseName] = await mongodb.connect(dbConfig);
|
|
54
|
+
// break;
|
|
55
|
+
default:
|
|
56
|
+
throw new Error(`Tipo de base de datos '${dbConfig.type}' no soportado.`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return connections[databaseName];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Dispatcher interno para query / execute / call
|
|
65
|
+
*/
|
|
66
|
+
async function run(databaseName, target, params, config, mode)
|
|
67
|
+
{
|
|
68
|
+
const connection = await connect(databaseName, config);
|
|
69
|
+
const dbConfig = config[databaseName];
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
switch (dbConfig.type) {
|
|
73
|
+
case 'postgres':
|
|
74
|
+
return await postgres[mode](connection, target, params);
|
|
75
|
+
|
|
76
|
+
case 'mysql':
|
|
77
|
+
return await mysql[mode](connection, target, params);
|
|
78
|
+
|
|
79
|
+
case 'oracle':
|
|
80
|
+
return await oracle[mode](connection, target, params);
|
|
81
|
+
|
|
82
|
+
default:
|
|
83
|
+
throw new Error(`Tipo de base de datos '${dbConfig.type}' no soportado.`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err)
|
|
87
|
+
{
|
|
88
|
+
throw new Error(`[Helmet][${dbConfig.type}][${mode}] ${err.message}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Ejecuta una consulta en la base de datos especificada.
|
|
96
|
+
*
|
|
97
|
+
* @async
|
|
98
|
+
* @function query
|
|
99
|
+
* @name query
|
|
100
|
+
* @param {string} databaseName - Perfil de la base de datos (clave de configuración)
|
|
101
|
+
* @param {string} sql - Consulta SQL, Sentencia SQL a ejecutar
|
|
102
|
+
* @param {Array} [binds] - Parámetros para la consulta (bind variables).
|
|
103
|
+
* @returns {Promise<Array>} Filas resultantes de la consulta.
|
|
104
|
+
* @throws {Error} Si el tipo de base de datos no es soportado para la operación 'query'.
|
|
105
|
+
* @description Ejecuta una sentencia SQL en la base de datos especificada y devuelve un objeto en un set de datos
|
|
106
|
+
*/
|
|
107
|
+
// async function query(databaseName, sql, values = [], config)
|
|
108
|
+
// {
|
|
109
|
+
// const connection = await connect(databaseName, config);
|
|
110
|
+
// const dbConfig = config[databaseName];
|
|
111
|
+
|
|
112
|
+
// switch (dbConfig.type)
|
|
113
|
+
// {
|
|
114
|
+
// case 'postgres':
|
|
115
|
+
// return postgres.query(connection, sql);
|
|
116
|
+
// case 'mysql':
|
|
117
|
+
// return mysql.query(connection, sql, values);
|
|
118
|
+
// // case 'mariadb': // agregamos el caso MariaDB
|
|
119
|
+
// // return mariadb.query(connection, sql, binds);
|
|
120
|
+
// // break;
|
|
121
|
+
// case 'oracle':
|
|
122
|
+
// return oracle.query(connection, sql);
|
|
123
|
+
// // case 'mongodb':
|
|
124
|
+
// // // Adaptar la consulta SQL a la sintaxis de MongoDB
|
|
125
|
+
// // console.warn("La función 'query' no es directamente aplicable a MongoDB con sintaxis SQL.");
|
|
126
|
+
// // return null; // O lanzar un error
|
|
127
|
+
// default:
|
|
128
|
+
// throw new Error(`Tipo de base de datos '${dbConfig.type}' no soportado para la operación 'query'.`);
|
|
129
|
+
// }
|
|
130
|
+
// }
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Ejecuta consultas de lectura (SELECT).
|
|
134
|
+
*/
|
|
135
|
+
async function query(databaseName, sql, params = [], config)
|
|
136
|
+
{
|
|
137
|
+
return run(databaseName, sql, params, config, 'query');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Ejecuta sentencias de escritura (INSERT, UPDATE, DELETE, DDL).
|
|
142
|
+
*/
|
|
143
|
+
async function execute(databaseName, sql, params = [], config)
|
|
144
|
+
{
|
|
145
|
+
return run(databaseName, sql, params, config, 'execute');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Ejecuta procedimientos almacenados o funciones.
|
|
151
|
+
*/
|
|
152
|
+
async function call(databaseName, procedureName, params = {}, config)
|
|
153
|
+
{
|
|
154
|
+
return run(databaseName, procedureName, params, config, 'call');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Cierra la conexión a la base de datos especificada.
|
|
159
|
+
*
|
|
160
|
+
* @async
|
|
161
|
+
* @function close
|
|
162
|
+
* @name close
|
|
163
|
+
* @param {string} databaseName - Perfil de la base de datos (clave de configuración).
|
|
164
|
+
* @returns {Promise<void>}
|
|
165
|
+
* @description Cierra la conexion del Perfil de la base de datos especificada.
|
|
166
|
+
*/
|
|
167
|
+
async function close(databaseName, config)
|
|
168
|
+
{
|
|
169
|
+
if (!connections[databaseName]) return;
|
|
170
|
+
|
|
171
|
+
const dbConfig = config[databaseName];
|
|
172
|
+
switch (dbConfig.type) {
|
|
173
|
+
case 'postgres':
|
|
174
|
+
await postgres.close(connections[databaseName]);
|
|
175
|
+
break;
|
|
176
|
+
case 'mysql':
|
|
177
|
+
await mysql.close(connections[databaseName]);
|
|
178
|
+
break;
|
|
179
|
+
// case 'mariadb': // agregamos el caso MariaDB
|
|
180
|
+
// await mariadb.close(connections[databaseName]);
|
|
181
|
+
// break;
|
|
182
|
+
case 'oracle':
|
|
183
|
+
await oracle.close(connections[databaseName]);
|
|
184
|
+
break;
|
|
185
|
+
// case 'mongodb':
|
|
186
|
+
// await mongodb.close(connections[databaseName]);
|
|
187
|
+
// break;
|
|
188
|
+
}
|
|
189
|
+
delete connections[databaseName];
|
|
190
|
+
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @function
|
|
197
|
+
* @name execute
|
|
198
|
+
* @param {string} sql - Sentencia SQL a ejecutar
|
|
199
|
+
* @param {Promise<callback>} callback - objeto, para retornar la promesa
|
|
200
|
+
* @returns {result} result/err - Devuelve un objeto con el set de datos o un objeto err con la respuesta del error
|
|
201
|
+
* @description Ejecuta una sentencia SQL y devuelve un objeto en un set de datos
|
|
202
|
+
*/
|
|
203
|
+
// async function execute(databaseName, sql, values = [], config)
|
|
204
|
+
// {
|
|
205
|
+
// const connection = await connect(databaseName, config);
|
|
206
|
+
// const dbConfig = config[databaseName];
|
|
207
|
+
|
|
208
|
+
// switch (dbConfig.type)
|
|
209
|
+
// {
|
|
210
|
+
// case 'postgres':
|
|
211
|
+
// return postgres.query(connection, sql);
|
|
212
|
+
// case 'mysql':
|
|
213
|
+
// return mysql.query(connection, sql, values);
|
|
214
|
+
// // case 'mariadb': // agregamos el caso MariaDB
|
|
215
|
+
// // return mariadb.query(connection, sql, binds);
|
|
216
|
+
// // break;
|
|
217
|
+
// case 'oracle':
|
|
218
|
+
// return oracle.query(connection, sql);
|
|
219
|
+
// // case 'mongodb':
|
|
220
|
+
// // // Adaptar la consulta SQL a la sintaxis de MongoDB
|
|
221
|
+
// // console.warn("La función 'query' no es directamente aplicable a MongoDB con sintaxis SQL.");
|
|
222
|
+
// // return null; // O lanzar un error
|
|
223
|
+
// default:
|
|
224
|
+
// throw new Error(`Tipo de base de datos '${dbConfig.type}' no soportado para la operación 'query'.`);
|
|
225
|
+
// }
|
|
226
|
+
// }
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Cierra todas las conexiones activas.
|
|
230
|
+
*/
|
|
231
|
+
async function closeAll(config)
|
|
232
|
+
{
|
|
233
|
+
for (const dbName of Object.keys(connections))
|
|
234
|
+
{ await close(dbName, config); }
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
module.exports =
|
|
238
|
+
{
|
|
239
|
+
connect,
|
|
240
|
+
query,
|
|
241
|
+
execute,
|
|
242
|
+
call,
|
|
243
|
+
close,
|
|
244
|
+
closeAll
|
|
245
|
+
// ... otras funciones comunes
|
|
246
|
+
};
|