@areumtecnologia/mysql-db-handler 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/README.md ADDED
@@ -0,0 +1,218 @@
1
+ # mysql-db-handler
2
+
3
+ A powerful MySQL wrapper with connection pooling, singleton support, and advanced query handling for Node.js.
4
+
5
+ ## Features
6
+
7
+ * **Connection Pooling:** Efficiently manages database connections.
8
+ * **Promise-based:** Fully supports `async/await` for clean code.
9
+ * **Table Handler:** An abstraction layer to perform CRUD operations easily.
10
+ * **Datatables Integration:** Built-in helper to parse and query data specifically for jQuery Datatables server-side processing.
11
+ * **Singleton Support:** Includes a singleton pattern setup for easy global access.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install mysql-db-handler
17
+ ```
18
+
19
+ ## Basic Usage
20
+
21
+ ### 1. Initialize Connection
22
+ You can create a new instance of the database class directly.
23
+
24
+ ```javascript
25
+ const { DataBase } = require('mysql-db-handler');
26
+
27
+ const db = new DataBase({
28
+ host: 'localhost',
29
+ user: 'root',
30
+ password: 'password',
31
+ database: 'my_app_db',
32
+ port: 3306,
33
+ connectionLimit: 10
34
+ });
35
+ ```
36
+
37
+ ### 2. Executing Raw SQL
38
+ Use the `query` method to execute standard SQL.
39
+
40
+ ```javascript
41
+ try {
42
+ const rows = await db.query('SELECT * FROM users WHERE active = ?', [1]);
43
+ console.log(rows);
44
+ } catch (error) {
45
+ console.error(error);
46
+ }
47
+ ```
48
+
49
+ ### 3. Using the DataBaseHandler
50
+ The `DataBaseHandler` simplifies interactions with specific tables.
51
+
52
+ ```javascript
53
+ const { DataBaseHandler } = require('mysql-db-handler');
54
+
55
+ // Initialize handler for 'customers' table
56
+ const customers = new DataBaseHandler(db, 'customers');
57
+
58
+ // Select all
59
+ const allCustomers = await customers.select();
60
+
61
+ // Select with conditions
62
+ const activeCustomers = await customers.selectBy({ status: 1 });
63
+ ```
64
+
65
+ ---
66
+
67
+ ## Advanced Usage & Examples
68
+
69
+ ### Flexible Selection (`select`)
70
+
71
+ The `select` method allows you to build complex queries using an array of parameters and a clauses object.
72
+
73
+ **Parameters:**
74
+ * `params` (Array): An array where each element is either a condition object or a logical string ('AND', 'OR').
75
+ * Simple condition: `{ column: value }` (defaults to `=`)
76
+ * Condition with operator: `{ column: value, operator: '>' }`
77
+ * `clauses` (Object): Optional keys like `ORDER BY`, `LIMIT`, `OFFSET`, `GROUP BY`, `HAVING`.
78
+
79
+ **Example:**
80
+
81
+ ```javascript
82
+ const products = new DataBaseHandler(db, 'products');
83
+
84
+ const results = await products.select(
85
+ // 1. Params: Conditions
86
+ [
87
+ { category: 'electronics' }, // WHERE `category` = 'electronics'
88
+ 'AND',
89
+ { price: 1000, operator: '>' } // AND `price` > 1000
90
+ ],
91
+ // 2. Clauses: SQL Modifiers
92
+ {
93
+ 'ORDER BY': 'price DESC',
94
+ 'LIMIT': 10,
95
+ 'OFFSET': 0
96
+ }
97
+ );
98
+ ```
99
+
100
+ ### Updating Records (`update`)
101
+
102
+ The `update` method separates the values to change from the conditions.
103
+
104
+ **Parameters:**
105
+ * `params` (Object): Contains:
106
+ * `set`: Key-value pairs of columns to update.
107
+ * `where`: Key-value pairs for the WHERE clause (uses `AND` implicitly between keys).
108
+ * `options` (Object): Optional settings, e.g., `{ useRegex: true }` to use REGEXP instead of =.
109
+
110
+ **Example:**
111
+
112
+ ```javascript
113
+ const users = new DataBaseHandler(db, 'users');
114
+
115
+ const result = await users.update({
116
+ set: {
117
+ status: 'inactive',
118
+ last_seen: new Date()
119
+ },
120
+ where: {
121
+ id: 123,
122
+ role: 'guest'
123
+ }
124
+ });
125
+ // Executes: UPDATE users SET `status` = ?, `last_seen` = ? WHERE `id` = ? AND `role` = ?
126
+ ```
127
+
128
+ ### Deleting Records (`delete`)
129
+
130
+ The `delete` method removes rows matching the provided conditions.
131
+
132
+ **Parameters:**
133
+ * `conditions` (Object): Key-value pairs to match rows to delete (uses `AND` implicitly).
134
+
135
+ **Example:**
136
+
137
+ ```javascript
138
+ const sessions = new DataBaseHandler(db, 'user_sessions');
139
+
140
+ const result = await sessions.delete({
141
+ user_id: 55,
142
+ is_expired: 1
143
+ });
144
+ // Executes: DELETE FROM user_sessions WHERE `user_id` = ? AND `is_expired` = ?
145
+ ```
146
+
147
+ ---
148
+
149
+ ## API Documentation
150
+
151
+ ### Class: `DataBase`
152
+
153
+ #### `constructor(config)`
154
+ Creates a database instance with a connection pool.
155
+ * **config**: Object. MySQL2 connection configuration (host, user, password, database, port, connectionLimit, etc).
156
+
157
+ #### `async query(sql, params)`
158
+ Executes a SQL query using a pooled connection.
159
+ * **sql**: String. The SQL query to execute.
160
+ * **params**: Array. Parameters for the prepared statement.
161
+ * **Returns**: `Promise<Array|Object>`. Returns rows on success, or an error object if failed.
162
+
163
+ #### `async close()`
164
+ Closes the connection pool completely.
165
+ * **Returns**: `Promise<void>`.
166
+
167
+ ---
168
+
169
+ ### Class: `DataBaseHandler`
170
+
171
+ #### `constructor(database, table, expression)`
172
+ * **database**: Instance of `DataBase`.
173
+ * **table**: String. The name of the table.
174
+ * **expression**: String (Optional). Additional SQL expression (e.g., extra columns or joins).
175
+
176
+ #### `async select(params, clauses)`
177
+ See "Flexible Selection" above.
178
+ * **Returns**: `Promise<Array>`.
179
+
180
+ #### `async selectBy(params)`
181
+ Quickly select rows matching a specific object condition.
182
+ * **params**: Object. Key-value pairs for WHERE clause (e.g., `{ id: 5 }`).
183
+ * **Returns**: `Promise<Array>`.
184
+
185
+ #### `async insert(params)`
186
+ Inserts a new row.
187
+ * **params**: Object. Key-value pairs representing column names and values.
188
+ * **Returns**: `Promise<OkPacket>` (contains insertId, affectedRows, etc).
189
+
190
+ #### `async update(params, options)`
191
+ See "Updating Records" above.
192
+ * **Returns**: `Promise<OkPacket>`.
193
+
194
+ #### `async delete(conditions)`
195
+ See "Deleting Records" above.
196
+ * **Returns**: `Promise<OkPacket>`.
197
+
198
+ #### `async selectToDatatable(rawDtQuery, strictCondition)`
199
+ Helper for server-side Datatables.net processing.
200
+ * **rawDtQuery**: Object. The request object sent by Datatables.
201
+ * **strictCondition**: Array. Additional strict WHERE clauses not controlled by the frontend.
202
+ * **Returns**: Object. Format expected by Datatables `{ draw, recordsTotal, recordsFiltered, data }`.
203
+
204
+ ---
205
+
206
+ ## Contributing
207
+
208
+ Contributions are welcome! Please open an issue or submit a pull request.
209
+
210
+ 1. Fork the repository
211
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
212
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
213
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
214
+ 5. Open a Pull Request
215
+
216
+ ## License
217
+
218
+ MIT
package/index.js ADDED
@@ -0,0 +1,10 @@
1
+ // Áreum Tecnologia - Renan Moreira - renan.moreira@areum.com.br
2
+ const DataBase = require('./lib/database');
3
+ const DataBaseHandler = require('./lib/databaseHandler');
4
+ // We do not export the singleton by default in a library usually,
5
+ // but we export the classes so the user can instantiate them.
6
+
7
+ module.exports = {
8
+ DataBase,
9
+ DataBaseHandler
10
+ };
@@ -0,0 +1,77 @@
1
+ // Áreum Tecnologia - Renan Moreira - renan.moreira@areum.com.br
2
+ const mysql = require('mysql2/promise');
3
+ const NodeCache = require('node-cache');
4
+
5
+ class DataBase {
6
+ constructor(config = {}) {
7
+ this.config = config;
8
+ this.pool = mysql.createPool(this.config); // The pool is created once when the instance is created.
9
+ this.cache = new NodeCache({ stdTTL: 100, checkperiod: 120 }); // Cache instance with a default TTL and check period.
10
+ }
11
+
12
+ // The createPool method is preserved for compatibility but is not necessary as the pool is already created in the constructor.
13
+ createPool() {
14
+ if (!this.pool) {
15
+ this.pool = mysql.createPool(this.config);
16
+ }
17
+ return this.pool;
18
+ }
19
+
20
+ async getConnection() {
21
+ if (!this.pool) {
22
+ throw new Error('Pool de conexões não criado.');
23
+ }
24
+ return this.pool.getConnection();
25
+ }
26
+
27
+ async query(sql, params) {
28
+ const key = `query_${sql}_${JSON.stringify(params)}`;
29
+ const cachedResult = this.cache.get(key);
30
+
31
+ if (cachedResult) {
32
+ return cachedResult;
33
+ }
34
+
35
+ const connection = await this.getConnection();
36
+ try {
37
+ const [rows] = await connection.query(sql, params);
38
+ this.cache.set(key, rows); // Save the result in the cache.
39
+ return rows;
40
+ } catch (error) {
41
+ return { error };
42
+ } finally {
43
+ connection.release();
44
+ }
45
+ }
46
+
47
+ // This method now uses placeholders to prevent SQL injection.
48
+ async getTableSchema(table) {
49
+ const key = `schema_${table}`;
50
+ const cachedResult = this.cache.get(key);
51
+
52
+ if (cachedResult) {
53
+ return cachedResult;
54
+ }
55
+
56
+ const sql = `SELECT column_name FROM information_schema.columns WHERE table_schema = ? AND table_name = ?`;
57
+ const params = [this.config.database, table];
58
+
59
+ const connection = await this.getConnection();
60
+ try {
61
+ const [rows] = await connection.execute(sql, params); // Use execute with placeholders
62
+ this.cache.set(key, rows); // Save the result in the cache.
63
+ return rows;
64
+ } catch (error) {
65
+ return { error };
66
+ } finally {
67
+ connection.release();
68
+ }
69
+ }
70
+
71
+ // Optional: A method to clear the cache if needed.
72
+ clearCache() {
73
+ this.cache.flushAll();
74
+ }
75
+ }
76
+
77
+ module.exports = DataBase;
@@ -0,0 +1,19 @@
1
+ // Áreum Tecnologia - Renan Moreira - renan.moreira@areum.com.br
2
+ // src/database/database-singleton.js
3
+ // Exemplo Singleton para a conexão com o banco de dados
4
+ const { DB_HOST, DB_USER, DB_PASS } = require('../constants');
5
+ const DataBase = require("./database");
6
+
7
+ const dbi = new DataBase({
8
+ host: DB_HOST,
9
+ user: DB_USER,
10
+ password: DB_PASS,
11
+ database: '',
12
+ charset: "utf8mb4",
13
+ timezone: "-03:00",
14
+ connectionLimit: 1, // Ajustado para um limite de conexão mais comum
15
+ waitForConnections: true,
16
+ queueLimit: 0
17
+ });
18
+ // console.log("DATABASE SINGLETON CREATED", dbi.id);
19
+ module.exports = dbi;
@@ -0,0 +1,81 @@
1
+ const mysql = require('mysql2/promise');
2
+
3
+ class DataBase {
4
+ /**
5
+ * Creates a database instance with a connection pool.
6
+ * @param {Object} [config] - Configuration object for the database connection.
7
+ */
8
+ constructor(config) {
9
+ this.id = Date.now();
10
+ this.config = config;
11
+ this.pool = mysql.createPool(config);
12
+ }
13
+
14
+ /**
15
+ * Retrieves the connection pool.
16
+ * @returns {Promise<mysql.Pool>} The connection pool.
17
+ */
18
+ getPool() {
19
+ return this.pool;
20
+ }
21
+
22
+ /**
23
+ * Gets a connection from the pool.
24
+ * @returns {Promise<mysql.PoolConnection>} A database connection.
25
+ */
26
+ async getConnection() {
27
+ return this.pool.getConnection();
28
+ }
29
+
30
+ /**
31
+ * Executes a SQL query using a pooled connection.
32
+ * @param {string} sql - The SQL query to execute.
33
+ * @param {Array} [params] - The parameters for the SQL query.
34
+ * @returns {Promise<Array>} The result set from the query.
35
+ * @throws {Error} Throws an error if the query fails.
36
+ */
37
+ async query(sql, params) {
38
+ let connection; // Mova a declaração da conexão para fora do bloco try
39
+ try {
40
+ // Passo 1: Obter uma conexão do pool
41
+ connection = await this.getConnection();
42
+
43
+ // Passo 2: Executar a query
44
+ const [rows] = await connection.query(sql, params);
45
+ return rows;
46
+ } catch (error) {
47
+ // Passo 3: Se a query falhar, logar e retornar o erro no formato desejado
48
+ console.error('Erro na execução da query:', error);
49
+ return { error }; // Mantém o retorno do erro como um objeto
50
+ } finally {
51
+ // Passo 4: Este bloco SEMPRE será executado, independentemente de sucesso ou falha no 'try'
52
+ if (connection) {
53
+ connection.release(); // Garante que a conexão seja devolvida ao pool
54
+ }
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Retrieves the schema of a given table using prepared statements to prevent SQL injection.
60
+ * @param {string} table - The name of the table.
61
+ * @returns {Promise<Array>} The schema of the table.
62
+ * @throws {Error} Throws an error if the query fails.
63
+ */
64
+ async getTableSchema(table) {
65
+ const sql = `SELECT column_name
66
+ FROM information_schema.columns
67
+ WHERE table_schema = ? AND table_name = ?`;
68
+ return await this.query(sql, [this.config.database, table]);
69
+ }
70
+
71
+ /**
72
+ * Closes the connection pool.
73
+ */
74
+ async close() {
75
+ if (this.pool) {
76
+ await this.pool.end();
77
+ console.log(new Date().toLocaleString('pt-br'), 'POOL', 'Database connection pool closed.');
78
+ }
79
+ }
80
+ }
81
+ module.exports = DataBase;
@@ -0,0 +1,249 @@
1
+ class DatabaseHandler {
2
+ constructor(database, table, expression = '') {
3
+ this.db = database;
4
+ this.table = table;
5
+ this.debug = false;
6
+ this.expression = expression;
7
+ this.debug = false;
8
+ this.onError;
9
+ }
10
+
11
+ async executeQuery(sql, params) {
12
+ // const connection = await this.db;
13
+ // const rows = await connection.query(sql, params);
14
+ const rows = await this.db.query(sql, params);
15
+ return rows;
16
+ }
17
+
18
+ async getSchema() {
19
+ return await this.db.getTableSchema(this.table)
20
+ }
21
+
22
+ /**
23
+ * @private
24
+ * Converte um objeto "achatado" (form-urlencoded) em um objeto aninhado (JSON).
25
+ * Ex: { 'columns[0][data]': 'id' } => { columns: [{ data: 'id' }] }
26
+ */
27
+ _hydrateObject(flatObject) {
28
+ const result = {};
29
+ for (const key in flatObject) {
30
+ const keys = key.match(/[^[\]']+/g); // Extrai chaves como ['columns', '0', 'data']
31
+ if (!keys) continue;
32
+
33
+ let current = result;
34
+ while (keys.length > 1) {
35
+ const k = keys.shift();
36
+ current[k] = current[k] || (isNaN(keys[0]) ? {} : []);
37
+ current = current[k];
38
+ }
39
+ current[keys[0]] = flatObject[key];
40
+ }
41
+ return result;
42
+ }
43
+
44
+ _parseStrictCondition(strictCondition) {
45
+ if (!strictCondition || !Array.isArray(strictCondition) || strictCondition.length === 0) {
46
+ return { sql: '', bindings: [] };
47
+ }
48
+ const clauses = [];
49
+ const bindings = [];
50
+ for (const item of strictCondition) {
51
+ if (typeof item === 'string') {
52
+ clauses.push(item.toUpperCase());
53
+ } else if (typeof item === 'object' && item !== null) {
54
+ const key = Object.keys(item).find(k => k !== 'operator');
55
+ if (!key) continue;
56
+ const value = item[key];
57
+ const operator = item.operator || '=';
58
+ clauses.push(`\`${key}\` ${operator} ?`);
59
+ bindings.push(value);
60
+ }
61
+ }
62
+ return { sql: `(${clauses.join(' ')})`, bindings };
63
+ }
64
+
65
+ async selectToDatatable(rawDtQuery, strictCondition = []) {
66
+ // NOVO: Hidrata o objeto da requisição para o formato aninhado correto.
67
+ const dtQuery = this._hydrateObject(rawDtQuery);
68
+ const { draw, start, length, search, order, columns } = dtQuery;
69
+
70
+ try {
71
+ const baseWhere = this._parseStrictCondition(strictCondition);
72
+ const finalBindings = [...baseWhere.bindings];
73
+ const finalWhereClauses = baseWhere.sql ? [baseWhere.sql] : [];
74
+
75
+ const dtSearchClauses = [];
76
+ if (columns) {
77
+ if (search && search.value !== '') {
78
+ const globalSearch = columns
79
+ .filter(c => c.data && c.searchable === 'true')
80
+ .map(c => `\`${c.data}\` LIKE ?`);
81
+
82
+ if (globalSearch.length > 0) {
83
+ const regexSearch = search.regex === 'true' ? `${search.value}` : `%${search.value}%`;
84
+ const operator = search.regex === 'true' ? 'REGEXP' : 'LIKE';
85
+ const clauses = globalSearch.map(c => c.replace('LIKE ?', `${operator} ?`));
86
+
87
+ dtSearchClauses.push(`(${clauses.join(' OR ')})`);
88
+ for (let i = 0; i < globalSearch.length; i++) {
89
+ finalBindings.push(regexSearch);
90
+ }
91
+ }
92
+ }
93
+ for (const col of columns) {
94
+ if (col.data && col.searchable === 'true' && col.search && col.search.value !== '') {
95
+ const regexSearch = col.search.regex === 'true' ? `${col.search.value}` : `%${col.search.value}%`;
96
+ const operator = col.search.regex === 'true' ? 'REGEXP' : 'LIKE';
97
+ dtSearchClauses.push(`\`${col.data}\` ${operator} ?`);
98
+ finalBindings.push(regexSearch);
99
+ }
100
+ }
101
+ }
102
+
103
+ if (dtSearchClauses.length > 0) {
104
+ finalWhereClauses.push(dtSearchClauses.join(' AND '));
105
+ }
106
+
107
+ const whereSql = finalWhereClauses.length > 0 ? `WHERE ${finalWhereClauses.join(' AND ')}` : '';
108
+
109
+ let orderSql = '';
110
+ if (order && order.length > 0 && columns) {
111
+ const orderColumnIndex = order[0].column;
112
+ if (columns[orderColumnIndex] && columns[orderColumnIndex].orderable === 'true' && columns[orderColumnIndex].data) {
113
+ const orderColumnName = columns[orderColumnIndex].data;
114
+ const orderDir = order[0].dir.toUpperCase() === 'ASC' ? 'ASC' : 'DESC';
115
+ orderSql = `ORDER BY \`${orderColumnName}\` ${orderDir}`;
116
+ }
117
+ }
118
+
119
+ const limitSql = (length && length != '-1') ? `LIMIT ${parseInt(start, 10)}, ${parseInt(length, 10)}` : '';
120
+
121
+ // --- Queries ---
122
+ const baseWhereSql = baseWhere.sql ? `WHERE ${baseWhere.sql}` : '';
123
+ const totalCountSql = `SELECT COUNT(*) as total FROM ${this.table} ${baseWhereSql}`;
124
+ const [totalResult] = await this.executeQuery(totalCountSql, baseWhere.bindings);
125
+ const recordsTotal = totalResult.total;
126
+
127
+ const filteredCountSql = `SELECT COUNT(*) as total FROM ${this.table} ${whereSql}`;
128
+ const [filteredResult] = await this.executeQuery(filteredCountSql, finalBindings);
129
+ const recordsFiltered = filteredResult.total;
130
+
131
+ // CORREÇÃO: Construção segura da cláusula SELECT para evitar vírgulas duplas.
132
+ const selectFields = ['*'];
133
+ if (this.expression && this.expression.trim() !== '') {
134
+ // Remove vírgula do início da expressão, se houver, para evitar duplicação
135
+ selectFields.push(this.expression.trim().replace(/^,/, '').trim());
136
+ }
137
+ const dataSql = `SELECT ${selectFields.join(', ')} FROM ${this.table} ${whereSql} ${orderSql} ${limitSql}`;
138
+ const data = await this.executeQuery(dataSql, finalBindings);
139
+
140
+ return {
141
+ draw: parseInt(draw || 0),
142
+ recordsTotal: parseInt(recordsTotal),
143
+ recordsFiltered: parseInt(recordsFiltered),
144
+ data: data,
145
+ };
146
+
147
+ } catch (e) {
148
+ console.error("Erro em selectToDatatable:", e);
149
+ if (this.onError) this.onError(e);
150
+ return {
151
+ draw: parseInt(dtQuery.draw || 0),
152
+ recordsTotal: 0,
153
+ recordsFiltered: 0,
154
+ data: [],
155
+ error: e.message
156
+ };
157
+ }
158
+ }
159
+
160
+ async selectBy(params) {
161
+ if (params) {
162
+ const sql = `SELECT *${this.expression ? this.expression : ''} FROM ${this.table} WHERE ?`;
163
+ const rows = await this.executeQuery(sql, params);
164
+ return rows;//retorna um array, mesmo que vazio
165
+ }
166
+ else {
167
+ const sql = `SELECT *${this.expression ? this.expression : ''} FROM ${this.table}`;
168
+ return this.executeQuery(sql);
169
+ }
170
+ }
171
+
172
+ async select(params, clauses = {}) {
173
+ if (params != null && !Array.isArray(params)) {
174
+ return new Error('O parâmetro "params" deve ser um array');
175
+ }
176
+
177
+ const conditions = [];
178
+ const values = [];
179
+
180
+ if (params && params.length) {
181
+ params.map((param) => {
182
+ if (typeof param === 'object' && !Array.isArray(param)) {
183
+ const entries = Object.entries(param);
184
+ const [key, value] = entries[0];
185
+ const [operator, opValue] = entries[1] || [];
186
+
187
+ const condition = `\`${key}\` ${opValue ?? '='} ?`;
188
+ conditions.push(condition);
189
+ values.push(value);
190
+ } else if (typeof param === 'string') {
191
+ conditions.push(param.toUpperCase());
192
+ }
193
+ });
194
+ }
195
+
196
+ const whereClause = conditions.length > 0 ? ` WHERE ${conditions.join(' ')}` : '';
197
+
198
+ // Cláusulas adicionais
199
+ const groupByClause = clauses['GROUPBY'] ? ` GROUP BY ${clauses['GROUP BY']}` : '';
200
+ const havingClause = clauses['HAVING'] ? ` HAVING ${clauses['HAVING']}` : '';
201
+ const orderClause = clauses['ORDERBY'] ? ` ORDER BY ${clauses['ORDER BY']}` : '';
202
+ const limitClause = clauses['LIMIT'] ? ` LIMIT ${clauses['LIMIT']}` : '';
203
+ const offsetClause = clauses['OFFSET'] ? ` OFFSET ${clauses['OFFSET']}` : '';
204
+
205
+ const sql = `SELECT *${this.expression ?? ''} FROM ${this.table}${whereClause}${groupByClause}${havingClause}${orderClause}${limitClause}${offsetClause}`;
206
+
207
+ const rows = await this.executeQuery(sql, values);
208
+ return rows;
209
+ }
210
+
211
+ async insert(params) {
212
+ const sql = `INSERT INTO ${this.table} SET ?`;
213
+ const result = await this.executeQuery(sql, params);
214
+ return result;
215
+ }
216
+
217
+ async update(params, options = {}) {
218
+ // Inicializa a string SQL para a cláusula SET
219
+ const operator = options.useRegex ? 'REGEXP' : '=';
220
+ let setClause = Object.keys(params.set).map(key => `\`${key}\` = ?`).join(', ');
221
+ // Inicializa a string SQL para a cláusula WHERE
222
+ let whereClause = Object.keys(params.where).map(key => `\`${key}\` ${operator} ?`).join(' AND ');
223
+ // Constrói a consulta SQL completa
224
+ const sql = `UPDATE ${this.table} SET ${setClause} WHERE ${whereClause}`;
225
+ // Combina os valores SET e WHERE em um único array
226
+ const values = [...Object.values(params.set), ...Object.values(params.where)];
227
+ // Executa a consulta
228
+ const result = await this.executeQuery(sql, values);
229
+
230
+ return result;
231
+ }
232
+
233
+ async delete(conditions) {
234
+ const conditionKeys = Object.keys(conditions);
235
+ if (conditionKeys.length === 0) {
236
+ // Se o objeto conditions estiver vazio, não faz nada
237
+ return;
238
+ }
239
+
240
+ const whereConditions = conditionKeys.map((key) => `${key} = ?`).join(' AND ');
241
+ const sql = `DELETE FROM ${this.table} WHERE ${whereConditions}`;
242
+ const params = conditionKeys.map((key) => conditions[key]);
243
+ const result = await this.executeQuery(sql, params);
244
+ return result;
245
+ }
246
+
247
+ }
248
+
249
+ module.exports = DatabaseHandler;
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "@areumtecnologia/mysql-db-handler",
3
+ "version": "1.0.0",
4
+ "description": "A powerful MySQL wrapper with connection pooling, singleton support, and advanced query handling for Node.js.",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "author": "Renan Moreira / Áreum Tecnologia",
10
+ "license": "MIT",
11
+ "dependencies": {
12
+ "mysql2": "^3.0.0"
13
+ }
14
+ }