jerkjs 2.2.0 → 2.3.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.
@@ -0,0 +1,353 @@
1
+ # Frontend y Sesiones con API SDK JS
2
+
3
+ ## Introducción
4
+
5
+ API SDK JS no solo es un framework para crear APIs, sino que ahora también soporta la creación de aplicaciones web completas con frontend y sistema de sesiones. Esta funcionalidad permite a los desarrolladores crear aplicaciones web completas con autenticación basada en sesiones, almacenamiento de datos y mucho más.
6
+
7
+ ## Características del Frontend
8
+
9
+ ### Especificación de Content-Type en routes.json
10
+
11
+ Una de las nuevas características es la capacidad de especificar el content-type directamente en el archivo routes.json:
12
+
13
+ ```json
14
+ [
15
+ {
16
+ "path": "/",
17
+ "method": "GET",
18
+ "controller": "./controllers/pageController.js",
19
+ "handler": "homePage",
20
+ "auth": "none",
21
+ "contentType": "text/html"
22
+ },
23
+ {
24
+ "path": "/api/data",
25
+ "method": "GET",
26
+ "controller": "./controllers/apiController.js",
27
+ "handler": "getData",
28
+ "auth": "none",
29
+ "contentType": "application/json"
30
+ }
31
+ ]
32
+ ```
33
+
34
+ ### Soporte para diferentes tipos de contenido
35
+
36
+ El framework ahora puede servir diferentes tipos de contenido:
37
+ - HTML para páginas web
38
+ - CSS para estilos
39
+ - JavaScript para scripts
40
+ - JSON para APIs
41
+ - Y cualquier otro tipo de contenido
42
+
43
+ ## Sistema de Sesiones
44
+
45
+ ### Configuración
46
+
47
+ Para usar el sistema de sesiones, primero debes configurar el middleware en tu aplicación:
48
+
49
+ ```javascript
50
+ const { APIServer, SessionManager, Cors } = require('@apisdkjs/apisdkjs');
51
+
52
+ async function startServer() {
53
+ const server = new APIServer({
54
+ port: 3000,
55
+ host: 'localhost'
56
+ });
57
+
58
+ // Crear instancia del administrador de sesiones
59
+ const sessionManager = new SessionManager({
60
+ cookieName: 'myapp_session',
61
+ secret: 'my-super-secret-session-key',
62
+ timeout: 3600000 // 1 hora
63
+ });
64
+
65
+ // Aplicar middleware de sesión
66
+ server.use(sessionManager.middleware());
67
+
68
+ // Hacer que sessionManager esté disponible para el RouteLoader
69
+ server.sessionManager = sessionManager;
70
+
71
+ // Cargar rutas
72
+ const routeLoader = new RouteLoader();
73
+ await routeLoader.loadRoutes(server, './routes.json');
74
+
75
+ server.start();
76
+ }
77
+ ```
78
+
79
+ ### Protección de rutas
80
+
81
+ Puedes proteger rutas específicas usando `"auth": "session"` en tu archivo routes.json:
82
+
83
+ ```json
84
+ [
85
+ {
86
+ "path": "/dashboard",
87
+ "method": "GET",
88
+ "controller": "./controllers/dashboardController.js",
89
+ "handler": "showDashboard",
90
+ "auth": "session",
91
+ "contentType": "text/html"
92
+ }
93
+ ]
94
+ ```
95
+
96
+ ### Uso en controladores
97
+
98
+ En tus controladores, puedes acceder a la sesión a través de `req.session`:
99
+
100
+ ```javascript
101
+ const authController = {
102
+ // Controlador para iniciar sesión
103
+ processLogin: async (req, res) => {
104
+ const { username, password } = req.body;
105
+
106
+ // Validar credenciales (tu lógica aquí)
107
+ const user = await validateUser(username, password);
108
+
109
+ if (user) {
110
+ // Crear sesión de usuario autenticado
111
+ req.session.create({
112
+ authenticated: true,
113
+ userId: user.id,
114
+ username: user.username
115
+ });
116
+
117
+ res.writeHead(200, { 'Content-Type': 'application/json' });
118
+ res.end(JSON.stringify({
119
+ success: true,
120
+ message: 'Inicio de sesión exitoso'
121
+ }));
122
+ } else {
123
+ res.writeHead(401, { 'Content-Type': 'application/json' });
124
+ res.end(JSON.stringify({
125
+ success: false,
126
+ message: 'Credenciales inválidas'
127
+ }));
128
+ }
129
+ },
130
+
131
+ // Controlador para cerrar sesión
132
+ processLogout: (req, res) => {
133
+ if (req.session) {
134
+ req.session.destroy();
135
+ }
136
+
137
+ res.writeHead(200, { 'Content-Type': 'application/json' });
138
+ res.end(JSON.stringify({
139
+ success: true,
140
+ message: 'Sesión cerrada exitosamente'
141
+ }));
142
+ }
143
+ };
144
+ ```
145
+
146
+ ## Sistema de Hooks, Filters y Actions
147
+
148
+ El sistema de sesiones está completamente integrado con el sistema de hooks, filters y actions del framework, lo que permite extender y personalizar su comportamiento.
149
+
150
+ ### Hooks Disponibles
151
+
152
+ #### Sesion Creation Hooks
153
+ - `session_create_data`: Filtra los datos antes de crear una sesión
154
+ - `session_created`: Acción disparada después de crear una sesión
155
+ - `session_create_user_data`: Filtra los datos de usuario antes de crear la sesión
156
+
157
+ #### Sesion Retrieval Hooks
158
+ - `session_get_id`: Filtra el ID de sesión antes de buscarla
159
+ - `session_retrieved`: Acción disparada después de obtener una sesión
160
+ - `session_not_found`: Acción disparada cuando no se encuentra una sesión
161
+ - `session_expired`: Acción disparada cuando una sesión ha expirado
162
+
163
+ #### Sesion Update Hooks
164
+ - `session_update_data`: Filtra los nuevos datos antes de actualizar la sesión
165
+ - `session_updated`: Acción disparada después de actualizar una sesión
166
+ - `session_update_user_data`: Filtra los datos de usuario antes de actualizar
167
+
168
+ #### Sesion Destruction Hooks
169
+ - `session_destroy_before`: Acción disparada antes de destruir una sesión
170
+ - `session_destroyed`: Acción disparada después de destruir una sesión
171
+ - `session_destroy_failed`: Acción disparada cuando falla la destrucción
172
+
173
+ #### Middleware Hooks
174
+ - `session_middleware_before`: Acción disparada antes del middleware de sesión
175
+ - `session_middleware_after`: Acción disparada después del middleware de sesión
176
+
177
+ #### Authentication Hooks
178
+ - `session_auth_check_before`: Acción disparada antes de verificar autenticación
179
+ - `session_auth_success`: Acción disparada cuando la autenticación es exitosa
180
+ - `session_auth_failed`: Acción disparada cuando la autenticación falla
181
+ - `session_created_response`: Acción disparada después de crear sesión en respuesta
182
+ - `session_updated_response`: Acción disparada después de actualizar sesión en respuesta
183
+ - `session_destroyed_response`: Acción disparada después de destruir sesión en respuesta
184
+
185
+ ### Ejemplos de Uso de Hooks
186
+
187
+ #### Registrar actividad de sesión
188
+
189
+ ```javascript
190
+ const { hooks } = require('@apisdkjs/apisdkjs');
191
+
192
+ // Registrar cuando se crea una sesión
193
+ hooks.addAction('session_created', (sessionId, sessionData) => {
194
+ console.log(`Sesión creada: ${sessionId} para el usuario: ${sessionData.username}`);
195
+ });
196
+
197
+ // Registrar cuando se destruye una sesión
198
+ hooks.addAction('session_destroyed', (sessionId, sessionData) => {
199
+ console.log(`Sesión destruida: ${sessionId} para el usuario: ${sessionData.username}`);
200
+ });
201
+ ```
202
+
203
+ #### Modificar datos de sesión antes de crearla
204
+
205
+ ```javascript
206
+ const { hooks } = require('@apisdkjs/apisdkjs');
207
+
208
+ // Añadir información de IP y fecha a los datos de sesión
209
+ hooks.addFilter('session_create_data', (userData, req) => {
210
+ return {
211
+ ...userData,
212
+ ipAddress: req.headers['x-forwarded-for'] || req.connection.remoteAddress,
213
+ createdAt: new Date().toISOString()
214
+ };
215
+ });
216
+ ```
217
+
218
+ #### Personalizar el manejo de autenticación fallida
219
+
220
+ ```javascript
221
+ const { hooks } = require('@apisdkjs/apisdkjs');
222
+
223
+ // Registrar intentos de acceso no autorizado
224
+ hooks.addAction('session_auth_failed', (req, res, redirectTo) => {
225
+ console.log(`Intento de acceso no autorizado a: ${req.url} desde IP: ${req.connection.remoteAddress}`);
226
+
227
+ // Puedes personalizar la respuesta aquí
228
+ if (req.headers.accept && req.headers.accept.includes('application/json')) {
229
+ res.writeHead(401, { 'Content-Type': 'application/json' });
230
+ res.end(JSON.stringify({ error: 'No autorizado', code: 'AUTH_REQUIRED' }));
231
+ }
232
+ });
233
+ ```
234
+
235
+ #### Extender datos de sesión durante la actualización
236
+
237
+ ```javascript
238
+ const { hooks } = require('@apisdkjs/apisdkjs');
239
+
240
+ // Añadir marca de tiempo a cada actualización de sesión
241
+ hooks.addFilter('session_update_data', (newData, req, sessionId) => {
242
+ return {
243
+ ...newData,
244
+ lastUpdated: new Date().toISOString(),
245
+ lastActivity: new Date().toISOString()
246
+ };
247
+ });
248
+ ```
249
+
250
+ ## Ejemplo Completo
251
+
252
+ Aquí tienes un ejemplo completo de una aplicación que combina frontend y sesiones:
253
+
254
+ ### app.js
255
+ ```javascript
256
+ const {
257
+ APIServer,
258
+ RouteLoader,
259
+ Logger,
260
+ Cors,
261
+ SessionManager
262
+ } = require('@apisdkjs/apisdkjs');
263
+
264
+ async function startServer() {
265
+ const server = new APIServer({
266
+ port: 3000,
267
+ host: 'localhost'
268
+ });
269
+
270
+ const logger = new Logger({ level: 'info' });
271
+
272
+ try {
273
+ // Configurar sesiones
274
+ const sessionManager = new SessionManager({
275
+ cookieName: 'myapp_session',
276
+ secret: 'my-super-secret-session-key',
277
+ timeout: 3600000
278
+ });
279
+
280
+ server.use(sessionManager.middleware());
281
+ server.sessionManager = sessionManager;
282
+
283
+ // Configurar CORS
284
+ const cors = new Cors({
285
+ origin: '*',
286
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
287
+ allowedHeaders: ['Content-Type', 'Authorization']
288
+ });
289
+
290
+ server.use(cors.middleware());
291
+
292
+ // Cargar rutas
293
+ const routeLoader = new RouteLoader();
294
+ await routeLoader.loadRoutes(server, './routes.json');
295
+
296
+ server.start();
297
+ logger.info('Servidor iniciado en http://localhost:3000');
298
+ } catch (error) {
299
+ logger.error('Error iniciando el servidor:', error.message);
300
+ process.exit(1);
301
+ }
302
+ }
303
+
304
+ startServer();
305
+ ```
306
+
307
+ ### routes.json
308
+ ```json
309
+ [
310
+ {
311
+ "path": "/",
312
+ "method": "GET",
313
+ "controller": "./controllers/pageController.js",
314
+ "handler": "homePage",
315
+ "auth": "none",
316
+ "contentType": "text/html"
317
+ },
318
+ {
319
+ "path": "/login",
320
+ "method": "GET",
321
+ "controller": "./controllers/authController.js",
322
+ "handler": "showLoginPage",
323
+ "auth": "none",
324
+ "contentType": "text/html"
325
+ },
326
+ {
327
+ "path": "/dashboard",
328
+ "method": "GET",
329
+ "controller": "./controllers/dashboardController.js",
330
+ "handler": "showDashboard",
331
+ "auth": "session",
332
+ "contentType": "text/html"
333
+ },
334
+ {
335
+ "path": "/api/login",
336
+ "method": "POST",
337
+ "controller": "./controllers/authController.js",
338
+ "handler": "processLogin",
339
+ "auth": "none",
340
+ "contentType": "application/json"
341
+ },
342
+ {
343
+ "path": "/api/logout",
344
+ "method": "POST",
345
+ "controller": "./controllers/authController.js",
346
+ "handler": "processLogout",
347
+ "auth": "session",
348
+ "contentType": "application/json"
349
+ }
350
+ ]
351
+ ```
352
+
353
+ Este ejemplo demuestra cómo crear una aplicación web completa con autenticación basada en sesiones, protección de rutas y soporte para frontend HTML.
@@ -0,0 +1,113 @@
1
+ # Documentación de Aprendizajes con JERKJS
2
+
3
+ ## 1. Formato del archivo routes.json
4
+
5
+ **Formato correcto:**
6
+ ```json
7
+ [
8
+ {
9
+ "method": "GET",
10
+ "path": "/",
11
+ "controller": "./controllers/mainController.js",
12
+ "handler": "home",
13
+ "auth": "none"
14
+ }
15
+ ]
16
+ ```
17
+
18
+ **Características importantes:**
19
+ - Debe ser un array directo de rutas, **NO** un objeto con propiedad "routes"
20
+ - Campos requeridos: `method`, `path`, `controller`, `handler`, `auth`
21
+ - El campo `controller` debe especificar la ruta completa al archivo del controlador
22
+ - El campo `handler` debe especificar el nombre exacto del método en el controlador
23
+ - El campo `auth` puede ser "none", "required", etc.
24
+
25
+ ## 2. Estructura de controladores para usar con routes.json
26
+
27
+ **Formato correcto:**
28
+ ```javascript
29
+ const { ControllerBase } = require('jerkjs');
30
+
31
+ class MainController extends ControllerBase {
32
+ constructor(options = {}) {
33
+ super(options);
34
+ }
35
+
36
+ home(req, res) {
37
+ // Lógica del controlador
38
+ }
39
+ }
40
+
41
+ // Exportar métodos directamente para que el RouteLoader pueda acceder a ellos
42
+ const controllerInstance = new MainController({ viewsPath: './views' });
43
+
44
+ module.exports = {
45
+ home: (req, res) => {
46
+ controllerInstance.setRequestResponse(req, res);
47
+ controllerInstance.home(req, res);
48
+ }
49
+ };
50
+ ```
51
+
52
+ **Características importantes:**
53
+ - No se puede exportar directamente la instancia del controlador
54
+ - Debe exportar un objeto con funciones que encapsulan la llamada al método del controlador
55
+ - Se debe llamar a `setRequestResponse()` antes de ejecutar el método del controlador
56
+
57
+ ## 3. Uso del motor de plantillas de JERK
58
+
59
+ **Características del motor de plantillas:**
60
+ - Usa sintaxis `{{variable}}` para mostrar variables
61
+ - Soporta condicionales: `{{if variable}}contenido{{endif}}`
62
+ - Soporta bucles: `{{foreach:array}}contenido{{endforeach}}`
63
+ - Se accede a los elementos del bucle con `{{item.property}}`
64
+
65
+ ## 4. Sistema de hooks
66
+
67
+ **Tipos de hooks:**
68
+ - `addAction(nombre_hook, callback)` - Para acciones que se ejecutan en puntos específicos
69
+ - `addFilter(nombre_hook, callback)` - Para filtrar/modificar datos
70
+
71
+ **Hooks útiles:**
72
+ - `post_controller_load` - Se ejecuta después de cargar un controlador
73
+ - `pre_route_load` - Se ejecuta antes de cargar rutas
74
+ - `post_route_load` - Se ejecuta después de cargar rutas
75
+ - `request_received` - Se ejecuta cuando se recibe una solicitud
76
+ - `request_completed` - Se ejecuta cuando se completa una solicitud
77
+
78
+ ## 5. Puerto y configuración del servidor
79
+
80
+ **Configuración del servidor:**
81
+ ```javascript
82
+ const server = new APIServer({
83
+ port: 11000, // Puerto específico
84
+ host: 'localhost'
85
+ });
86
+ ```
87
+
88
+ ## 6. Controladores que extienden ControllerBase
89
+
90
+ **Características:**
91
+ - Deben extender `ControllerBase` del framework
92
+ - Usan `this.set()` para establecer variables de vista
93
+ - Usan `this.render()` para renderizar vistas
94
+ - Requieren que se llame a `setRequestResponse()` antes de usar métodos del controlador
95
+
96
+ ## 7. Errores comunes y soluciones
97
+
98
+ **Error común:** "this.set is not a function"
99
+ **Solución:** Asegurarse de que se llama a `controllerInstance.setRequestResponse(req, res)` antes de ejecutar métodos del controlador
100
+
101
+ **Error común:** "Error cargando rutas desde ./routes.json: El archivo de rutas debe contener un array de rutas"
102
+ **Solución:** Asegurarse de que routes.json sea un array directo, no un objeto con propiedad "routes"
103
+
104
+ **Error común:** "controllerLoader.loadControllers is not a function"
105
+ **Solución:** El RouteLoader se encarga de cargar tanto rutas como controladores, no usar ControllerLoader por separado
106
+
107
+ ## 8. Recursos útiles
108
+
109
+ - Directorio de ejemplos en `/node_modules/jerkjs/examples/`
110
+ - Archivos routes.json de ejemplo en los directorios de ejemplos
111
+ - Documentación en el README del paquete
112
+
113
+ Esta documentación servirá para futuros desarrollos con JERKJS y evitará caer en los mismos errores o confusiones.
Binary file
package/index.js CHANGED
@@ -48,6 +48,11 @@ const ModelControllerExample = require('./lib/mvc/ModelControllerExample');
48
48
  // Componentes de manejo de errores
49
49
  const { ErrorHandler, ValidationError, AuthenticationError, DatabaseError } = require('./lib/utils/errorHandler');
50
50
 
51
+ // Componentes del QueryBuilder (v2.3.0)
52
+ const QueryBuilder = require('./lib/query/queryBuilder');
53
+ const QueryBuilderMiddleware = require('./lib/query/queryBuilderMiddleware');
54
+ const { initializeQueryBuilderHooks, extendQueryBuilderWithHooks } = require('./lib/query/queryBuilderHooks');
55
+
51
56
  // Exportar todos los componentes del framework
52
57
  module.exports = {
53
58
  // Componentes fundamentales (v1.0)
@@ -105,7 +110,13 @@ module.exports = {
105
110
  ErrorHandler,
106
111
  ValidationError,
107
112
  AuthenticationError,
108
- DatabaseError
113
+ DatabaseError,
114
+
115
+ // Componentes del QueryBuilder (v2.3.0)
116
+ QueryBuilder,
117
+ QueryBuilderMiddleware,
118
+ initializeQueryBuilderHooks,
119
+ extendQueryBuilderWithHooks
109
120
  };
110
121
 
111
122
  // También exportar clases individuales por conveniencia
@@ -0,0 +1,71 @@
1
+ # Changelog
2
+
3
+ Todos los cambios importantes en este proyecto se documentarán en este archivo.
4
+
5
+ El formato está basado en [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ y este proyecto adhiere al [Versionado Semántico](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Versión 1.0.0] - 2026-01-21
9
+
10
+ ### Cambios Importantes
11
+
12
+ #### 🚀 Características Nuevas
13
+
14
+ - **QueryBuilder principal**
15
+ - Implementación completa del QueryBuilder con API fluida
16
+ - Métodos para SELECT, INSERT, UPDATE, DELETE
17
+ - Soporte para condiciones WHERE, JOINs, GROUP BY, ORDER BY
18
+ - Paginación con LIMIT y OFFSET
19
+ - Funciones de agregación (COUNT, MAX, MIN, SUM, AVG)
20
+
21
+ - **Método setAdapter()**
22
+ - Implementación del método `setAdapter(adapter)` para configurar dinámicamente cualquier adaptador
23
+ - Permite cambiar de base de datos en tiempo de ejecución
24
+ - Compatible con múltiples sistemas de base de datos
25
+
26
+ - **Adaptador MariaDB**
27
+ - Implementación del adaptador para MariaDB/MySQL
28
+ - Conexión mediante pool de conexiones
29
+ - Ejecución segura de consultas SQL
30
+
31
+ - **Adaptador de Consola**
32
+ - Adaptador de ejemplo para mostrar consultas SQL por consola
33
+ - Útil para pruebas y desarrollo
34
+ - Simula resultados de consultas
35
+
36
+ - **Middleware de Integración**
37
+ - Sistema completo para inyectar QueryBuilder en solicitudes HTTP
38
+ - Middleware para configurar adaptadores
39
+ - Middleware para registrar QueryBuilder con hooks
40
+ - Middleware para habilitar registro de consultas
41
+ - Middleware para aplicar reglas de seguridad
42
+
43
+ - **Sistema de Hooks**
44
+ - Integración completa con el sistema de hooks de JERK
45
+ - Acciones y filtros para eventos del QueryBuilder
46
+ - Sistema de auditoría de consultas
47
+ - Aplicación de reglas de seguridad
48
+
49
+ #### 🔧 Cambios Técnicos
50
+
51
+ - **Arquitectura modular**
52
+ - Estructura de archivos separados para cada componente
53
+ - Dependencias claras entre módulos
54
+ - Código organizado y mantenible
55
+
56
+ - **Seguridad mejorada**
57
+ - Prevención de inyección SQL mediante el uso de parámetros
58
+ - Sistema de validación de consultas
59
+ - Reglas de seguridad configurables
60
+
61
+ - **Documentación completa**
62
+ - README.md con descripción general
63
+ - HOWTO.md con instrucciones detalladas de uso
64
+ - Ejemplos prácticos de implementación
65
+
66
+ #### 📝 Otros Cambios
67
+
68
+ - **Ejemplos de uso**
69
+ - Aplicación de demostración completa
70
+ - Ejemplos de integración con JERK Framework
71
+ - Casos de uso prácticos con base de datos real