@hemia/db-connector 0.0.1
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 +101 -0
- package/dist/hemia-db-connector.esm.js +570 -0
- package/dist/hemia-db-connector.js +614 -0
- package/dist/types/Core/CoreSqlServerConnection.d.ts +0 -0
- package/dist/types/Core/MongoDBConnector.d.ts +30 -0
- package/dist/types/Core/SequalizeConnector.d.ts +28 -0
- package/dist/types/DBConnector.d.ts +18 -0
- package/dist/types/abstract/NoSQLConnector.d.ts +40 -0
- package/dist/types/abstract/SQLConnector.d.ts +22 -0
- package/dist/types/enums/CoreSqlTypes.d.ts +8 -0
- package/dist/types/enums/QueryType.d.ts +4 -0
- package/dist/types/errors/DBError.d.ts +11 -0
- package/dist/types/errors/MySQLConnectionError.d.ts +4 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/managers/NoSQLConnectionManager.d.ts +6 -0
- package/dist/types/managers/SQLConnectionManager.d.ts +6 -0
- package/dist/types/types/CredentialsConnection.d.ts +12 -0
- package/dist/types/types/DBNoSQLTypes.d.ts +4 -0
- package/dist/types/types/DBSQLTypes.d.ts +4 -0
- package/dist/types/types/NoSQLOptions.d.ts +7 -0
- package/dist/types/types/RecordSet.d.ts +6 -0
- package/package.json +77 -0
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# @hemia/db-connector
|
|
2
|
+
|
|
3
|
+
Conector unificado para bases de datos SQL (MySQL, MSSQL) y NoSQL (MongoDB), diseñado para facilitar operaciones comunes como conexión, transacciones, queries y manipulación de datos. Ideal para aplicaciones Node.js que requieren una interfaz abstracta para distintos motores de base de datos.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Instalación
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @hemia/db-connector
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Soporta:
|
|
16
|
+
|
|
17
|
+
* ✅ MongoDB (Mongoose)
|
|
18
|
+
* ✅ MySQL / MSSQL (Sequelize)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Uso rápido
|
|
23
|
+
|
|
24
|
+
### MongoDB
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { MongoDBConnector } from '@hemia/db-connector';
|
|
28
|
+
|
|
29
|
+
const mongo = new MongoDBConnector({
|
|
30
|
+
host: 'localhost',
|
|
31
|
+
user: 'admin',
|
|
32
|
+
password: '1234',
|
|
33
|
+
database: 'mydb',
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
await mongo.connect();
|
|
37
|
+
const docs = await mongo.find(MyModel, { status: 'active' });
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### SQL (MySQL/MSSQL)
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { SequelizeSqlConnector } from '@hemia/db-connector';
|
|
44
|
+
|
|
45
|
+
const sql = new SequelizeSqlConnector({
|
|
46
|
+
host: 'localhost',
|
|
47
|
+
user: 'root',
|
|
48
|
+
password: 'pass',
|
|
49
|
+
database: 'mydb',
|
|
50
|
+
dialect: 'mysql'
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
await sql.connect();
|
|
54
|
+
const rows = await sql.select('users', { where: { active: true } });
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Características destacadas
|
|
60
|
+
|
|
61
|
+
### MongoDBConnector
|
|
62
|
+
|
|
63
|
+
* Conexión y desconexión automáticas
|
|
64
|
+
* Transacciones con rollback (`withTransaction`)
|
|
65
|
+
* CRUD genérico (`create`, `find`, `findOne`, `update`, `delete`, etc.)
|
|
66
|
+
* `aggregate`, `findAllFromMultipleModels`
|
|
67
|
+
|
|
68
|
+
### SequelizeSqlConnector
|
|
69
|
+
|
|
70
|
+
* `select`, `insert`, `update`, `delete` por entidad (tabla)
|
|
71
|
+
* Transacciones (`withTransaction`)
|
|
72
|
+
* Query SQL libre (`query()`)
|
|
73
|
+
* Manejo de errores y mapeo de códigos SQLSTATE (`createDatabaseError`)
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Tipos esperados de configuración
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
interface CredentialsConnection {
|
|
81
|
+
host: string;
|
|
82
|
+
port?: number;
|
|
83
|
+
user?: string;
|
|
84
|
+
password?: string;
|
|
85
|
+
database: string;
|
|
86
|
+
dialect?: 'mysql' | 'mssql';
|
|
87
|
+
logging?: boolean;
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Licencia
|
|
94
|
+
|
|
95
|
+
MIT
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Autor
|
|
100
|
+
|
|
101
|
+
Hemia Technologies
|
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
export { Document, Model, Schema } from 'mongoose';
|
|
3
|
+
import { ValidationError, DatabaseError, AccessDeniedError, Sequelize } from 'sequelize';
|
|
4
|
+
export { DataTypes, Model as ModelSequelize, Op, QueryTypes, Sequelize, Transaction, fn } from 'sequelize';
|
|
5
|
+
|
|
6
|
+
var CoreSqlTypes;
|
|
7
|
+
(function (CoreSqlTypes) {
|
|
8
|
+
CoreSqlTypes["Number"] = "Number";
|
|
9
|
+
CoreSqlTypes["string"] = "string";
|
|
10
|
+
CoreSqlTypes["DateTime"] = "DateTime";
|
|
11
|
+
CoreSqlTypes["Decimal"] = "Decimal";
|
|
12
|
+
CoreSqlTypes["Boolean"] = "Boolean";
|
|
13
|
+
CoreSqlTypes["Float"] = "Float";
|
|
14
|
+
})(CoreSqlTypes || (CoreSqlTypes = {}));
|
|
15
|
+
|
|
16
|
+
/******************************************************************************
|
|
17
|
+
Copyright (c) Microsoft Corporation.
|
|
18
|
+
|
|
19
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
20
|
+
purpose with or without fee is hereby granted.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
23
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
24
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
25
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
26
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
27
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
28
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
29
|
+
***************************************************************************** */
|
|
30
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
34
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
35
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
36
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
37
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
38
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
39
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
44
|
+
var e = new Error(message);
|
|
45
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
class NoSQLConnector {
|
|
49
|
+
constructor() {
|
|
50
|
+
this.config = {};
|
|
51
|
+
this.provider = '';
|
|
52
|
+
this.connection = null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var DBNoSQLType;
|
|
57
|
+
(function (DBNoSQLType) {
|
|
58
|
+
DBNoSQLType["MongoDB"] = "MongoDB";
|
|
59
|
+
DBNoSQLType["Cassandra"] = "Cassandra";
|
|
60
|
+
})(DBNoSQLType || (DBNoSQLType = {}));
|
|
61
|
+
|
|
62
|
+
class MongoDBConnector extends NoSQLConnector {
|
|
63
|
+
constructor(param) {
|
|
64
|
+
super();
|
|
65
|
+
this.currentSession = null;
|
|
66
|
+
this.config = param;
|
|
67
|
+
this.provider = DBNoSQLType.MongoDB;
|
|
68
|
+
this.mongooseConnection = mongoose.connection;
|
|
69
|
+
}
|
|
70
|
+
connect() {
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
try {
|
|
73
|
+
if (this.mongooseConnection.readyState === 1) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
yield mongoose.connect(`mongodb://${this.config.host}:${this.config.port || 27017}`, {
|
|
77
|
+
user: this.config.user,
|
|
78
|
+
pass: this.config.password,
|
|
79
|
+
dbName: this.config.database,
|
|
80
|
+
});
|
|
81
|
+
this.mongooseConnection = mongoose.connection;
|
|
82
|
+
console.log('Connected to MongoDB');
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error('Error connecting to MongoDB:', error);
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
disconnect() {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
try {
|
|
93
|
+
console.log('Disconnected from MongoDB');
|
|
94
|
+
yield this.mongooseConnection.close();
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error('Error disconnecting from MongoDB:', error);
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
getConnection() {
|
|
103
|
+
return this.mongooseConnection;
|
|
104
|
+
}
|
|
105
|
+
isConnected() {
|
|
106
|
+
return this.mongooseConnection.readyState === 1;
|
|
107
|
+
}
|
|
108
|
+
state() {
|
|
109
|
+
return this.mongooseConnection.readyState;
|
|
110
|
+
}
|
|
111
|
+
getCredentials() {
|
|
112
|
+
return this.config;
|
|
113
|
+
}
|
|
114
|
+
getProvider() {
|
|
115
|
+
return this.provider;
|
|
116
|
+
}
|
|
117
|
+
startSession() {
|
|
118
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
119
|
+
if (!this.currentSession) {
|
|
120
|
+
this.currentSession = yield this.mongooseConnection.startSession();
|
|
121
|
+
this.currentSession.startTransaction();
|
|
122
|
+
}
|
|
123
|
+
return this.currentSession;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
commitTransaction() {
|
|
127
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
if (this.currentSession) {
|
|
129
|
+
yield this.currentSession.commitTransaction();
|
|
130
|
+
this.currentSession.endSession();
|
|
131
|
+
this.currentSession = null;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
abortTransaction() {
|
|
136
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
137
|
+
if (this.currentSession) {
|
|
138
|
+
yield this.currentSession.abortTransaction();
|
|
139
|
+
this.currentSession.endSession();
|
|
140
|
+
this.currentSession = null;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
withTransaction(transactionFn) {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
const session = yield this.startSession();
|
|
147
|
+
try {
|
|
148
|
+
const result = yield transactionFn(session);
|
|
149
|
+
yield this.commitTransaction();
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
yield this.abortTransaction();
|
|
154
|
+
console.error('Transaction aborted:', error);
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
create(model, data, session) {
|
|
160
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
161
|
+
try {
|
|
162
|
+
const doc = new model(data);
|
|
163
|
+
return yield doc.save({ session });
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
console.error('Error al crear documento:', error);
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
find(model, query, options) {
|
|
172
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
173
|
+
try {
|
|
174
|
+
let queryBuilder = model.find(query);
|
|
175
|
+
if (options === null || options === void 0 ? void 0 : options.limit)
|
|
176
|
+
queryBuilder = queryBuilder.limit(options.limit);
|
|
177
|
+
if (options === null || options === void 0 ? void 0 : options.skip)
|
|
178
|
+
queryBuilder = queryBuilder.skip(options.skip);
|
|
179
|
+
if (options === null || options === void 0 ? void 0 : options.sort)
|
|
180
|
+
queryBuilder = queryBuilder.sort(options.sort);
|
|
181
|
+
return yield queryBuilder;
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
console.error('Error al obtener documentos:', error);
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
findOne(model, query) {
|
|
190
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
191
|
+
try {
|
|
192
|
+
return yield model.findOne(query);
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
console.error('Error al obtener un documento:', error);
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
findById(model, id) {
|
|
201
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
202
|
+
try {
|
|
203
|
+
return yield model.findById(id);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
console.error('Error al obtener un documento:', error);
|
|
207
|
+
throw error;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
update(model, query, updateData, session) {
|
|
212
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
213
|
+
try {
|
|
214
|
+
return yield model.findOneAndUpdate(query, updateData, { new: true, runValidators: false, session });
|
|
215
|
+
}
|
|
216
|
+
catch (error) {
|
|
217
|
+
console.error('Error al actualizar documento:', error);
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
updateById(model, id, updateData, session) {
|
|
223
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
224
|
+
try {
|
|
225
|
+
return yield model.findOneAndUpdate({ _id: id }, updateData, { new: true, runValidators: false, session });
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
console.error('Error al actualizar documento:', error);
|
|
229
|
+
throw error;
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
delete(model, query, session) {
|
|
234
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
235
|
+
try {
|
|
236
|
+
yield model.findOneAndDelete(query, { session });
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
console.error('Error al eliminar documento:', error);
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
deleteById(model, id, session) {
|
|
246
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
247
|
+
try {
|
|
248
|
+
yield model.findByIdAndDelete(id, { session });
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
console.error('Error al eliminar documento:', error);
|
|
253
|
+
throw error;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
findAllFromMultipleModels(models, filter) {
|
|
258
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
259
|
+
try {
|
|
260
|
+
const results = yield Promise.all(models.map((model) => model.find(filter).exec()));
|
|
261
|
+
return results.flat();
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
console.error('Error al buscar documentos en múltiples colecciones:', error);
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
aggregate(model, pipeline, options) {
|
|
270
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
271
|
+
try {
|
|
272
|
+
return yield model.aggregate(pipeline, options);
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
console.error('Error al buscar documentos la coleccion:', error);
|
|
276
|
+
throw error;
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
class NoSQLConnectionManager {
|
|
283
|
+
static getInstance(type, credentials) {
|
|
284
|
+
switch (type) {
|
|
285
|
+
case DBNoSQLType.MongoDB:
|
|
286
|
+
return new MongoDBConnector(credentials);
|
|
287
|
+
case DBNoSQLType.Cassandra:
|
|
288
|
+
throw new Error(`Tipo de base de datos no soportado: ${type}`);
|
|
289
|
+
default:
|
|
290
|
+
throw new Error(`Tipo de base de datos no soportado: ${type}`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
class SqlConnector {
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
class DBError extends Error {
|
|
299
|
+
constructor(code, message, meta) {
|
|
300
|
+
super(message);
|
|
301
|
+
if (Error.captureStackTrace) {
|
|
302
|
+
Error.captureStackTrace(this, this.constructor);
|
|
303
|
+
}
|
|
304
|
+
this.name = 'DatabaseError';
|
|
305
|
+
this.code = code;
|
|
306
|
+
this.sqlState = meta === null || meta === void 0 ? void 0 : meta.sqlState;
|
|
307
|
+
this.errno = meta === null || meta === void 0 ? void 0 : meta.errno;
|
|
308
|
+
this.status = meta === null || meta === void 0 ? void 0 : meta.status;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
class MySQLConnectionError {
|
|
313
|
+
constructor() { }
|
|
314
|
+
static handleMysqlConnectionError(error) {
|
|
315
|
+
if (error instanceof ValidationError) {
|
|
316
|
+
throw new DBError('401', `Validation Error: [${error.message}]`);
|
|
317
|
+
}
|
|
318
|
+
else if (error instanceof DatabaseError) {
|
|
319
|
+
throw new DBError('401', `Database Error: [${error.message}]`);
|
|
320
|
+
}
|
|
321
|
+
else if (error instanceof AccessDeniedError) {
|
|
322
|
+
throw new DBError('403', `Forbidden: [${error.message}]`);
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
throw new DBError('400', `Unable to connect to the database, ${error}`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
class SequelizeSqlConnector extends SqlConnector {
|
|
331
|
+
constructor(creds) {
|
|
332
|
+
var _a, _b;
|
|
333
|
+
super();
|
|
334
|
+
this.creds = creds;
|
|
335
|
+
this.sequelize = new Sequelize(creds.database, creds.user || '', creds.password, {
|
|
336
|
+
host: creds.host,
|
|
337
|
+
port: creds.port,
|
|
338
|
+
dialect: (_a = creds.dialect) !== null && _a !== void 0 ? _a : 'mysql',
|
|
339
|
+
logging: (_b = creds.logging) !== null && _b !== void 0 ? _b : false,
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
connect() {
|
|
343
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
344
|
+
try {
|
|
345
|
+
yield this.sequelize.authenticate();
|
|
346
|
+
}
|
|
347
|
+
catch (error) {
|
|
348
|
+
MySQLConnectionError.handleMysqlConnectionError(error);
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
disconnect() {
|
|
353
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
354
|
+
yield this.sequelize.close();
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
isConnected() {
|
|
358
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
359
|
+
try {
|
|
360
|
+
yield this.sequelize.query('SELECT 1', { raw: true });
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
getSequelize() {
|
|
369
|
+
return this.sequelize;
|
|
370
|
+
}
|
|
371
|
+
getModel(name) {
|
|
372
|
+
if (!this.sequelize.isDefined(name)) {
|
|
373
|
+
throw new Error(`Modelo no definido: ${name}`);
|
|
374
|
+
}
|
|
375
|
+
return this.sequelize.model(name);
|
|
376
|
+
}
|
|
377
|
+
select(entity, options) {
|
|
378
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
379
|
+
try {
|
|
380
|
+
const model = this.getModel(entity);
|
|
381
|
+
const records = yield model.findAll(options);
|
|
382
|
+
return records;
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
console.error(error);
|
|
386
|
+
throw this.createDatabaseError(error);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
insert(entity, values, options) {
|
|
391
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
392
|
+
try {
|
|
393
|
+
const model = this.getModel(entity);
|
|
394
|
+
const instance = yield model.create(values, options);
|
|
395
|
+
return instance;
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
console.error(error);
|
|
399
|
+
throw this.createDatabaseError(error);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
update(entity, filter, data, options) {
|
|
404
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
405
|
+
try {
|
|
406
|
+
const model = this.getModel(entity);
|
|
407
|
+
const updateOpts = Object.assign(Object.assign({}, options), { where: filter });
|
|
408
|
+
const [count] = yield model.update(data, updateOpts);
|
|
409
|
+
return count;
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
console.error(error);
|
|
413
|
+
throw this.createDatabaseError(error);
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
delete(entity, filter, options) {
|
|
418
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
419
|
+
try {
|
|
420
|
+
const model = this.getModel(entity);
|
|
421
|
+
const destroyOpts = Object.assign({ where: filter }, options);
|
|
422
|
+
const deletedCount = yield model.destroy(destroyOpts);
|
|
423
|
+
return deletedCount;
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
console.error(error);
|
|
427
|
+
throw this.createDatabaseError(error);
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
query(sql, options) {
|
|
432
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
433
|
+
try {
|
|
434
|
+
const results = yield this.sequelize.query(sql, options);
|
|
435
|
+
return results;
|
|
436
|
+
}
|
|
437
|
+
catch (error) {
|
|
438
|
+
console.error(error);
|
|
439
|
+
throw this.createDatabaseError(error);
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
withTransaction(fn) {
|
|
444
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
445
|
+
const tx = yield this.sequelize.transaction();
|
|
446
|
+
try {
|
|
447
|
+
const result = yield fn(tx);
|
|
448
|
+
yield tx.commit();
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
451
|
+
catch (error) {
|
|
452
|
+
console.error(error);
|
|
453
|
+
yield tx.rollback();
|
|
454
|
+
throw this.createDatabaseError(error);
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
createDatabaseError(err) {
|
|
459
|
+
var _a, _b, _c;
|
|
460
|
+
const SQLSTATE_CODE_MAP = {
|
|
461
|
+
'42S02': 'DB_TABLE_NOT_FOUND',
|
|
462
|
+
'42S22': 'DB_COLUMN_NOT_FOUND',
|
|
463
|
+
'23000': 'DB_INTEGRITY_ERROR',
|
|
464
|
+
};
|
|
465
|
+
const source = (_a = err.original) !== null && _a !== void 0 ? _a : err;
|
|
466
|
+
const sqlState = source.sqlState;
|
|
467
|
+
const errno = source.errno;
|
|
468
|
+
const rawMsg = (_c = (_b = source.sqlMessage) !== null && _b !== void 0 ? _b : err.message) !== null && _c !== void 0 ? _c : String(err);
|
|
469
|
+
let code;
|
|
470
|
+
try {
|
|
471
|
+
const parsed = JSON.parse(rawMsg);
|
|
472
|
+
code = parsed.code || rawMsg;
|
|
473
|
+
}
|
|
474
|
+
catch (_d) {
|
|
475
|
+
code = sqlState && SQLSTATE_CODE_MAP[sqlState]
|
|
476
|
+
? SQLSTATE_CODE_MAP[sqlState]
|
|
477
|
+
: sqlState == '45000' ? rawMsg : 'DB_UNKNOWN_ERROR';
|
|
478
|
+
}
|
|
479
|
+
const message = `DatabaseError [${code}] (SQLSTATE=${sqlState}, errno=${errno}): ${rawMsg}`;
|
|
480
|
+
return new DBError(code, message, { sqlState, errno });
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
var DBSQLType;
|
|
485
|
+
(function (DBSQLType) {
|
|
486
|
+
DBSQLType["SQLServer"] = "SQLServer";
|
|
487
|
+
DBSQLType["MYSQL"] = "MYSQL";
|
|
488
|
+
})(DBSQLType || (DBSQLType = {}));
|
|
489
|
+
|
|
490
|
+
class SQLConnectionManager {
|
|
491
|
+
static getInstance(type, credentials) {
|
|
492
|
+
switch (type) {
|
|
493
|
+
case DBSQLType.MYSQL:
|
|
494
|
+
return new SequelizeSqlConnector(credentials);
|
|
495
|
+
default:
|
|
496
|
+
throw new Error(`Tipo de base de datos no soportado: ${type}`);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
class DBConnector {
|
|
502
|
+
constructor() {
|
|
503
|
+
this.connection = null;
|
|
504
|
+
this.sqlConnection = null;
|
|
505
|
+
this.credentials = null;
|
|
506
|
+
this.dbType = null;
|
|
507
|
+
}
|
|
508
|
+
static getInstance() {
|
|
509
|
+
if (!DBConnector.instance) {
|
|
510
|
+
DBConnector.instance = new DBConnector();
|
|
511
|
+
}
|
|
512
|
+
return DBConnector.instance;
|
|
513
|
+
}
|
|
514
|
+
createConnection(type, credentials) {
|
|
515
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
516
|
+
if (this.connection && this.dbType === type && JSON.stringify(this.credentials) === JSON.stringify(credentials)) {
|
|
517
|
+
return this.sqlConnection;
|
|
518
|
+
}
|
|
519
|
+
if (this.connection) {
|
|
520
|
+
yield this.closeConnection();
|
|
521
|
+
}
|
|
522
|
+
if (Object.values(DBNoSQLType).includes(type)) {
|
|
523
|
+
this.connection = NoSQLConnectionManager.getInstance(type, credentials);
|
|
524
|
+
}
|
|
525
|
+
else if (Object.values(DBSQLType).includes(type)) {
|
|
526
|
+
this.connection = SQLConnectionManager.getInstance(type, credentials);
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
throw new Error(`Unsupported database type: ${type}`);
|
|
530
|
+
}
|
|
531
|
+
yield this.connection.connect();
|
|
532
|
+
this.credentials = credentials;
|
|
533
|
+
this.dbType = type;
|
|
534
|
+
return this.connection;
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
getConnection() {
|
|
538
|
+
return this.connection;
|
|
539
|
+
}
|
|
540
|
+
closeConnection() {
|
|
541
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
542
|
+
if (this.connection) {
|
|
543
|
+
yield this.connection.disconnect();
|
|
544
|
+
this.connection = null;
|
|
545
|
+
this.credentials = null;
|
|
546
|
+
this.dbType = null;
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
getEngine(type, credentials) {
|
|
551
|
+
try {
|
|
552
|
+
if (Object.values(DBNoSQLType).includes(type)) {
|
|
553
|
+
this.connection = NoSQLConnectionManager.getInstance(type, credentials);
|
|
554
|
+
}
|
|
555
|
+
else if (Object.values(DBSQLType).includes(type)) {
|
|
556
|
+
this.connection = SQLConnectionManager.getInstance(type, credentials);
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
throw new Error(`Unsupported database type: ${type}`);
|
|
560
|
+
}
|
|
561
|
+
return this.connection;
|
|
562
|
+
}
|
|
563
|
+
catch (error) {
|
|
564
|
+
throw error;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
DBConnector.instance = null;
|
|
569
|
+
|
|
570
|
+
export { CoreSqlTypes, DBConnector, DBError, DBNoSQLType, DBSQLType, MySQLConnectionError, NoSQLConnector, SqlConnector };
|