jerkjs 2.3.0 → 2.4.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.
@@ -1,325 +0,0 @@
1
- # Cómo usar el QueryBuilder
2
-
3
- ## Introducción
4
-
5
- El QueryBuilder es una herramienta poderosa para construir consultas SQL de manera segura y eficiente. Este documento explica cómo utilizarlo en diferentes escenarios, incluyendo su integración con middlewares y el sistema de hooks de JERK.
6
-
7
- ## Instalación y configuración
8
-
9
- ### 1. Importar el QueryBuilder
10
-
11
- ```javascript
12
- const QueryBuilder = require('./path/to/queryBuilder');
13
- const MariaDBAdapter = require('./path/to/MariaDBAdapter');
14
- ```
15
-
16
- ### 2. Crear un adaptador
17
-
18
- ```javascript
19
- // Adaptador para MariaDB
20
- const adapter = new MariaDBAdapter({
21
- host: 'localhost',
22
- user: 'root',
23
- password: '',
24
- database: 'my_database'
25
- });
26
- ```
27
-
28
- ## Uso básico
29
-
30
- ### 1. Crear una instancia del QueryBuilder
31
-
32
- ```javascript
33
- // Opción 1: Sin adaptador (solo para construir consultas)
34
- const qb = new QueryBuilder();
35
-
36
- // Opción 2: Con adaptador (para ejecutar consultas)
37
- const qb = new QueryBuilder(adapter);
38
-
39
- // Opción 3: Configurar adaptador después (método setAdapter())
40
- const qb = new QueryBuilder();
41
- qb.setAdapter(adapter);
42
- ```
43
-
44
- ### 2. Construir una consulta SELECT simple
45
-
46
- ```javascript
47
- const result = await qb
48
- .table('users')
49
- .select('id', 'name', 'email')
50
- .where('age', '>', 18)
51
- .orderBy('name', 'ASC')
52
- .limit(10)
53
- .get();
54
- ```
55
-
56
- ### 3. Usar SELECT *
57
-
58
- ```javascript
59
- // Para seleccionar todos los campos
60
- const result = await qb
61
- .table('users')
62
- .select('*') // Esto funciona correctamente
63
- .where('status', 'active')
64
- .get();
65
- ```
66
-
67
- ## Operaciones CRUD
68
-
69
- ### SELECT
70
-
71
- ```javascript
72
- // Consulta básica
73
- const users = await qb
74
- .table('users')
75
- .select('id', 'name', 'email')
76
- .where('active', true)
77
- .get();
78
-
79
- // Obtener un solo registro
80
- const user = await qb
81
- .table('users')
82
- .select('*')
83
- .where('id', 1)
84
- .first();
85
-
86
- // Consulta con JOIN
87
- const result = await qb
88
- .table('users')
89
- .select('users.name', 'profiles.bio')
90
- .join('profiles', 'users.id', '=', 'profiles.user_id')
91
- .where('users.active', true)
92
- .get();
93
-
94
- // Consulta con múltiples condiciones
95
- const result = await qb
96
- .table('orders')
97
- .select('*')
98
- .where('status', 'completed')
99
- .where('amount', '>', 100)
100
- .whereBetween('created_at', '2023-01-01', '2023-12-31')
101
- .get();
102
- ```
103
-
104
- ### INSERT
105
-
106
- ```javascript
107
- const result = await qb
108
- .table('users')
109
- .insert({
110
- name: 'John Doe',
111
- email: 'john@example.com',
112
- age: 30
113
- });
114
- ```
115
-
116
- ### UPDATE
117
-
118
- ```javascript
119
- const affectedRows = await qb
120
- .table('users')
121
- .where('id', 1)
122
- .update({
123
- name: 'Jane Doe',
124
- email: 'jane@example.com'
125
- });
126
- ```
127
-
128
- ### DELETE
129
-
130
- ```javascript
131
- const affectedRows = await qb
132
- .table('users')
133
- .where('status', 'inactive')
134
- .delete();
135
- ```
136
-
137
- ## Condiciones WHERE
138
-
139
- ### WHERE simple
140
- ```javascript
141
- qb.where('column', 'value')
142
- qb.where('column', '=', 'value')
143
- qb.where('column', '>', 18)
144
- ```
145
-
146
- ### WHERE con operadores
147
- ```javascript
148
- qb.where('age', '>=', 18)
149
- qb.where('status', '!=', 'inactive')
150
- qb.where('name', 'LIKE', '%john%')
151
- ```
152
-
153
- ### WHERE IN
154
- ```javascript
155
- qb.whereIn('id', [1, 2, 3, 4])
156
- qb.whereNotIn('category', ['deleted', 'spam'])
157
- ```
158
-
159
- ### WHERE BETWEEN
160
- ```javascript
161
- qb.whereBetween('age', 18, 65)
162
- qb.whereNotBetween('amount', 100, 1000)
163
- ```
164
-
165
- ### Condiciones complejas
166
- ```javascript
167
- qb.where(function(qb) {
168
- qb.where('status', 'active')
169
- .orWhere('premium', true);
170
- });
171
- ```
172
-
173
- ## Otras operaciones
174
-
175
- ### Agrupamiento y ordenamiento
176
- ```javascript
177
- qb.groupBy('category')
178
- qb.orderBy('created_at', 'DESC')
179
- qb.orderBy('name', 'ASC')
180
- ```
181
-
182
- ### Paginación
183
- ```javascript
184
- qb.offset(10)
185
- qb.limit(20)
186
- ```
187
-
188
- ### Funciones de agregación
189
- ```javascript
190
- // Contar registros
191
- const count = await qb.table('users').count();
192
-
193
- // Máximo valor
194
- const maxAge = await qb.table('users').max('age');
195
-
196
- // Mínimo valor
197
- const minAge = await qb.table('users').min('age');
198
-
199
- // Suma
200
- const totalAmount = await qb.table('orders').sum('amount');
201
-
202
- // Promedio
203
- const avgScore = await qb.table('students').avg('score');
204
- ```
205
-
206
- ## Uso con diferentes adaptadores
207
-
208
- ### 1. Adaptador de MariaDB/MySQL
209
- ```javascript
210
- const MariaDBAdapter = require('./MariaDBAdapter');
211
-
212
- const adapter = new MariaDBAdapter({
213
- host: 'localhost',
214
- user: 'root',
215
- password: 'password',
216
- database: 'myapp'
217
- });
218
-
219
- const qb = new QueryBuilder(adapter);
220
- ```
221
-
222
- ### 2. Adaptador de consola (para pruebas)
223
- ```javascript
224
- const ConsoleAdapter = require('./ConsoleAdapter');
225
-
226
- const adapter = new ConsoleAdapter();
227
- const qb = new QueryBuilder(adapter);
228
- ```
229
-
230
- ### 3. Cambiar adaptador dinámicamente
231
- ```javascript
232
- const qb = new QueryBuilder();
233
-
234
- // Más tarde en el código
235
- qb.setAdapter(mariaDBAdapter);
236
- // Ahora puede ejecutar consultas en la base de datos
237
- ```
238
-
239
- ## Integración con Middleware
240
-
241
- El QueryBuilder incluye un middleware para inyectar instancias del QueryBuilder en las solicitudes HTTP:
242
-
243
- ```javascript
244
- const { APIServer } = require('jerkjs');
245
- const { QueryBuilderMiddleware } = require('./queryBuilderMiddleware');
246
- const MariaDBAdapter = require('./MariaDBAdapter');
247
-
248
- const server = new APIServer({ port: 3000 });
249
-
250
- // Crear middleware
251
- const qbMiddleware = new QueryBuilderMiddleware();
252
- const dbAdapter = new MariaDBAdapter(config);
253
-
254
- // Agregar middleware para inyectar QueryBuilder
255
- server.use(qbMiddleware.configureWithAdapter(dbAdapter));
256
- server.use(qbMiddleware.injectQueryBuilder.bind(qbMiddleware));
257
-
258
- // En un controlador
259
- app.addRoute('GET', '/users', async (req, res) => {
260
- const users = await req.queryBuilder('users')
261
- .select('*')
262
- .where('active', true)
263
- .get();
264
-
265
- res.json(users);
266
- });
267
- ```
268
-
269
- ## Integración con el sistema de Hooks de JERK
270
-
271
- Cuando se usa con el framework JERK, el QueryBuilder se puede integrar con el sistema de hooks:
272
-
273
- ```javascript
274
- const { hooks } = require('jerkjs');
275
- const { initializeQueryBuilderHooks, extendQueryBuilderWithHooks } = require('./queryBuilderHooks');
276
-
277
- // Inicializar hooks
278
- initializeQueryBuilderHooks(hooks);
279
- extendQueryBuilderWithHooks(QueryBuilder, hooks);
280
- ```
281
-
282
- ## Ejemplo completo
283
-
284
- ```javascript
285
- const QueryBuilder = require('./queryBuilder');
286
- const MariaDBAdapter = require('./MariaDBAdapter');
287
-
288
- // Crear adaptador
289
- const dbAdapter = new MariaDBAdapter({
290
- host: 'localhost',
291
- user: 'root',
292
- password: '',
293
- database: 'otrack_db'
294
- });
295
-
296
- // Crear QueryBuilder
297
- const qb = new QueryBuilder(dbAdapter);
298
-
299
- // Ejemplo de uso: obtener usuarios activos con ciertos criterios
300
- try {
301
- const users = await qb
302
- .table('users')
303
- .select('id', 'name', 'email', 'created_at')
304
- .where('status', 'active')
305
- .where('created_at', '>', '2023-01-01')
306
- .whereIn('role', ['admin', 'editor'])
307
- .orderBy('created_at', 'DESC')
308
- .limit(50)
309
- .get();
310
-
311
- console.log(`Encontrados ${users.length} usuarios`);
312
- } catch (error) {
313
- console.error('Error en la consulta:', error.message);
314
- }
315
- ```
316
-
317
- ## Consejos de seguridad
318
-
319
- 1. **Siempre use parámetros**: El QueryBuilder utiliza placeholders (`?`) para prevenir inyección SQL
320
- 2. **Valide entradas**: Aunque el QueryBuilder ayuda con la seguridad, siempre valide y sane las entradas del usuario
321
- 3. **Use setAdapter() cuidadosamente**: Asegúrese de que los adaptadores provengan de fuentes confiables
322
-
323
- ## Resumen
324
-
325
- El QueryBuilder proporciona una forma segura y fluida de construir consultas SQL. Con su método `setAdapter()`, puede trabajar con cualquier base de datos, y su API intuitiva facilita la creación de consultas complejas. Además, incluye middleware para integración fácil con frameworks web y soporte para el sistema de hooks de JERK.
@@ -1,52 +0,0 @@
1
- # QueryBuilder para JERK Framework
2
-
3
- ## Descripción
4
-
5
- QueryBuilder es una biblioteca independiente para construir consultas SQL de manera fluida y segura. Está diseñada para trabajar con el framework JERK pero puede utilizarse de forma independiente con cualquier sistema Node.js.
6
-
7
- ## Características
8
-
9
- - **API fluida**: Construcción intuitiva de consultas SQL
10
- - **Seguridad**: Prevención de inyección SQL mediante el uso de parámetros
11
- - **Flexibilidad**: Compatible con múltiples adaptadores de base de datos
12
- - **Método setAdapter()**: Permite configurar dinámicamente cualquier adaptador
13
- - **Soporte para múltiples bases de datos**: MariaDB, MySQL, PostgreSQL, SQLite, etc.
14
- - **Middleware de integración**: Sistema completo para inyectar QueryBuilder en solicitudes HTTP
15
- - **Integración con hooks**: Compatible con el sistema de hooks y filters de JERK
16
-
17
- ## Componentes
18
-
19
- - `queryBuilder.js`: El QueryBuilder principal con todos sus métodos
20
- - `MariaDBAdapter.js`: Adaptador para conexión con bases de datos MariaDB/MySQL
21
- - `ConsoleAdapter.js`: Adaptador de ejemplo para mostrar consultas por consola
22
- - `queryBuilderHooks.js`: Sistema de integración con los hooks y filters de JERK
23
- - `queryBuilderMiddleware.js`: Middleware para integrar el QueryBuilder con el framework
24
-
25
- ## Instalación
26
-
27
- Simplemente copie los archivos del QueryBuilder a su proyecto y utilice los módulos según sus necesidades.
28
-
29
- ## Uso básico
30
-
31
- ```javascript
32
- const QueryBuilder = require('./queryBuilder');
33
- const MariaDBAdapter = require('./MariaDBAdapter');
34
-
35
- // Crear adaptador
36
- const adapter = new MariaDBAdapter({
37
- host: 'localhost',
38
- user: 'root',
39
- password: '',
40
- database: 'my_database'
41
- });
42
-
43
- // Crear QueryBuilder con adaptador
44
- const qb = new QueryBuilder(adapter);
45
-
46
- // Usar el QueryBuilder
47
- const results = await qb
48
- .table('users')
49
- .select('id', 'name', 'email')
50
- .where('active', true)
51
- .get();
52
- ```
package/jerk.jpg DELETED
Binary file
@@ -1,78 +0,0 @@
1
- /**
2
- * Adaptador de MariaDB para el QueryBuilder
3
- * MariaDBAdapter.js
4
- *
5
- * Este adaptador simplemente ejecuta las consultas SQL construidas por el QueryBuilder
6
- */
7
-
8
- const mariadb = require('mariadb');
9
-
10
- class MariaDBAdapter {
11
- /**
12
- * Constructor del adaptador MariaDB
13
- * @param {Object} options - Opciones de configuración
14
- */
15
- constructor(options = {}) {
16
- // Configuración de la conexión a la base de datos
17
- this.dbConfig = {
18
- host: options.host || 'localhost',
19
- user: options.user || 'root',
20
- password: options.password || '',
21
- database: options.database || 'otrack_db',
22
- waitForConnections: options.waitForConnections !== false,
23
- connectionLimit: options.connectionLimit || 10,
24
- queueLimit: options.queueLimit || 0,
25
- acquireTimeout: options.acquireTimeout || 60000,
26
- timeout: options.timeout || 60000,
27
- ...options
28
- };
29
-
30
- // Crear pool de conexiones
31
- this.pool = mariadb.createPool(this.dbConfig);
32
- }
33
-
34
- /**
35
- * Método para ejecutar una consulta SQL
36
- * @param {string} sql - Consulta SQL construida por el QueryBuilder
37
- * @param {Array} params - Parámetros de la consulta
38
- * @returns {Promise<Object>} - Resultado de la consulta
39
- */
40
- async query(sql, params = []) {
41
- const connection = await this.pool.getConnection();
42
- try {
43
- return await connection.query(sql, params);
44
- } catch (error) {
45
- throw error;
46
- } finally {
47
- connection.release();
48
- }
49
- }
50
-
51
- /**
52
- * Método para cerrar la conexión
53
- */
54
- async close() {
55
- try {
56
- await this.pool.end();
57
- console.log('Conexión a MariaDB cerrada correctamente');
58
- } catch (error) {
59
- console.error('Error al cerrar la conexión a MariaDB:', error.message);
60
- }
61
- }
62
-
63
- /**
64
- * Método para verificar si el adaptador está conectado
65
- * @returns {Promise<boolean>} - Verdadero si está conectado
66
- */
67
- async isConnected() {
68
- try {
69
- const connection = await this.pool.getConnection();
70
- connection.release();
71
- return true;
72
- } catch (error) {
73
- return false;
74
- }
75
- }
76
- }
77
-
78
- module.exports = MariaDBAdapter;
@@ -1,184 +0,0 @@
1
- /**
2
- * Adaptador de ejemplo para mostrar consultas SQL por consola
3
- * ConsoleAdapter.js
4
- */
5
-
6
- class ConsoleAdapter {
7
- constructor(options = {}) {
8
- this.options = options;
9
- this.queriesExecuted = 0;
10
- }
11
-
12
- /**
13
- * Método para ejecutar una consulta
14
- * @param {string} sql - Consulta SQL
15
- * @param {Array} params - Parámetros de la consulta
16
- * @returns {Promise<Object>} - Resultado simulado
17
- */
18
- async query(sql, params = []) {
19
- this.queriesExecuted++;
20
-
21
- console.log(`\n--- CONSULTA #${this.queriesExecuted} ---`);
22
- console.log(`SQL: ${sql}`);
23
- console.log(`Parámetros:`, params);
24
- console.log('--- FIN CONSULTA ---\n');
25
-
26
- // Simular un resultado dependiendo del tipo de consulta
27
- if (sql.trim().toUpperCase().startsWith('SELECT')) {
28
- // Para consultas SELECT, devolver un array vacío o con datos simulados
29
- return [];
30
- } else if (sql.trim().toUpperCase().startsWith('INSERT')) {
31
- // Para INSERT, simular un ID insertado
32
- return { insertId: Math.floor(Math.random() * 10000), affectedRows: 1 };
33
- } else if (sql.trim().toUpperCase().startsWith('UPDATE') || sql.trim().toUpperCase().startsWith('DELETE')) {
34
- // Para UPDATE/DELETE, simular filas afectadas
35
- return { affectedRows: Math.floor(Math.random() * 5) + 1 };
36
- } else {
37
- // Para otros tipos de consulta, devolver un objeto vacío
38
- return {};
39
- }
40
- }
41
-
42
- /**
43
- * Método para crear un registro
44
- * @param {string} tableName - Nombre de la tabla
45
- * @param {Object} data - Datos a insertar
46
- * @returns {Promise<Object>} - Resultado simulado
47
- */
48
- async create(tableName, data) {
49
- const columns = Object.keys(data).join(', ');
50
- const placeholders = Object.keys(data).map(() => '?').join(', ');
51
- const sql = `INSERT INTO \`${tableName}\` (${columns}) VALUES (${placeholders})`;
52
- const params = Object.values(data);
53
-
54
- return await this.query(sql, params);
55
- }
56
-
57
- /**
58
- * Método para encontrar registros
59
- * @param {string} tableName - Nombre de la tabla
60
- * @param {Object} conditions - Condiciones de búsqueda
61
- * @param {Object} options - Opciones adicionales
62
- * @returns {Promise<Array>} - Resultados simulados
63
- */
64
- async find(tableName, conditions, options = {}) {
65
- let sql = `SELECT * FROM \`${tableName}\``;
66
- const params = [];
67
-
68
- if (conditions && Object.keys(conditions).length > 0) {
69
- const conditionsList = [];
70
- for (const [key, value] of Object.entries(conditions)) {
71
- if (value !== undefined && value !== null) {
72
- conditionsList.push(`${key} = ?`);
73
- params.push(value);
74
- }
75
- }
76
- if (conditionsList.length > 0) {
77
- sql += ' WHERE ' + conditionsList.join(' AND ');
78
- }
79
- }
80
-
81
- return await this.query(sql, params);
82
- }
83
-
84
- /**
85
- * Método para encontrar un solo registro
86
- * @param {string} tableName - Nombre de la tabla
87
- * @param {Object} conditions - Condiciones de búsqueda
88
- * @param {Object} options - Opciones adicionales
89
- * @returns {Promise<Object|null>} - Resultado simulado o null
90
- */
91
- async findOne(tableName, conditions, options = {}) {
92
- const results = await this.find(tableName, conditions, { ...options, limit: 1 });
93
- return results.length > 0 ? results[0] : null;
94
- }
95
-
96
- /**
97
- * Método para actualizar registros
98
- * @param {string} tableName - Nombre de la tabla
99
- * @param {Object} conditions - Condiciones para seleccionar registros
100
- * @param {Object} data - Datos a actualizar
101
- * @returns {Promise<number>} - Número de filas afectadas simuladas
102
- */
103
- async update(tableName, conditions, data) {
104
- const dataEntries = Object.entries(data);
105
- if (dataEntries.length === 0) {
106
- return 0;
107
- }
108
-
109
- const setClause = dataEntries.map(([key]) => `${key} = ?`).join(', ');
110
- const params = dataEntries.map(([, value]) => value);
111
-
112
- const whereClause = [];
113
- for (const [key, value] of Object.entries(conditions)) {
114
- if (value !== undefined && value !== null) {
115
- whereClause.push(`${key} = ?`);
116
- params.push(value);
117
- }
118
- }
119
-
120
- let sql = `UPDATE \`${tableName}\` SET ${setClause}`;
121
- if (whereClause.length > 0) {
122
- sql += ' WHERE ' + whereClause.join(' AND ');
123
- }
124
-
125
- const result = await this.query(sql, params);
126
- return result.affectedRows || 0;
127
- }
128
-
129
- /**
130
- * Método para eliminar registros
131
- * @param {string} tableName - Nombre de la tabla
132
- * @param {Object} conditions - Condiciones para seleccionar registros
133
- * @returns {Promise<number>} - Número de filas afectadas simuladas
134
- */
135
- async delete(tableName, conditions) {
136
- let sql = `DELETE FROM \`${tableName}\``;
137
- const params = [];
138
-
139
- if (conditions && Object.keys(conditions).length > 0) {
140
- const conditionsList = [];
141
- for (const [key, value] of Object.entries(conditions)) {
142
- if (value !== undefined && value !== null) {
143
- conditionsList.push(`${key} = ?`);
144
- params.push(value);
145
- }
146
- }
147
- if (conditionsList.length > 0) {
148
- sql += ' WHERE ' + conditionsList.join(' AND ');
149
- }
150
- }
151
-
152
- const result = await this.query(sql, params);
153
- return result.affectedRows || 0;
154
- }
155
-
156
- /**
157
- * Método para contar registros
158
- * @param {string} tableName - Nombre de la tabla
159
- * @param {Object} conditions - Condiciones de conteo
160
- * @returns {Promise<number>} - Número simulado de registros
161
- */
162
- async count(tableName, conditions) {
163
- let sql = `SELECT COUNT(*) as total FROM \`${tableName}\``;
164
- const params = [];
165
-
166
- if (conditions && Object.keys(conditions).length > 0) {
167
- const conditionsList = [];
168
- for (const [key, value] of Object.entries(conditions)) {
169
- if (value !== undefined && value !== null) {
170
- conditionsList.push(`${key} = ?`);
171
- params.push(value);
172
- }
173
- }
174
- if (conditionsList.length > 0) {
175
- sql += ' WHERE ' + conditionsList.join(' AND ');
176
- }
177
- }
178
-
179
- const result = await this.query(sql, params);
180
- return result[0] ? result[0].total : 0;
181
- }
182
- }
183
-
184
- module.exports = ConsoleAdapter;