jerkjs 2.0.1 → 2.0.2

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.
Files changed (131) hide show
  1. package/README.md +4 -6
  2. package/docs/EXTENSION_MANUAL.md +955 -0
  3. package/docs/FIREWALL_MANUAL.md +416 -0
  4. package/docs/HOOKS_REFERENCE_IMPROVED.md +596 -0
  5. package/docs/MANUAL_API_SDK.md +536 -0
  6. package/docs/MARIADB_TOKENS_IMPLEMENTATION.md +110 -0
  7. package/docs/MIDDLEWARE_MANUAL.md +518 -0
  8. package/docs/OAUTH2_GOOGLE_MANUAL.md +405 -0
  9. package/docs/frontend-and-sessions.md +6 -6
  10. package/examples/advanced/controllers/productController.js +64 -0
  11. package/examples/advanced/controllers/userController.js +85 -0
  12. package/examples/advanced/routes.json +51 -0
  13. package/examples/advanced_example.js +93 -0
  14. package/examples/basic/controllers/userController.js +85 -0
  15. package/examples/basic_example.js +72 -0
  16. package/examples/mvc_example/app.js +138 -0
  17. package/examples/mvc_example/views/home/index.html +26 -0
  18. package/examples/mvc_example/views/home/simple.html +3 -0
  19. package/examples/mvc_example/views/layout.html +23 -0
  20. package/examples/mvc_example/views/test.html +3 -0
  21. package/examples/mvc_example/views/user/invalid.html +6 -0
  22. package/examples/mvc_example/views/user/list.html +36 -0
  23. package/examples/mvc_example/views/user/notfound.html +6 -0
  24. package/examples/mvc_example/views/user/profile.html +11 -0
  25. package/examples/mvc_routes_example/app.js +34 -0
  26. package/examples/mvc_routes_example/controllers/mainController.js +27 -0
  27. package/examples/mvc_routes_example/controllers/productController.js +47 -0
  28. package/examples/mvc_routes_example/controllers/userController.js +76 -0
  29. package/examples/mvc_routes_example/routes.json +30 -0
  30. package/examples/mvc_routes_example/views/layout.html +31 -0
  31. package/examples/mvc_routes_example/views/main/index.html +11 -0
  32. package/examples/mvc_routes_example/views/product/catalog.html +24 -0
  33. package/examples/mvc_routes_example/views/user/invalid.html +6 -0
  34. package/examples/mvc_routes_example/views/user/list.html +40 -0
  35. package/examples/mvc_routes_example/views/user/notfound.html +6 -0
  36. package/examples/mvc_routes_example/views/user/profile.html +18 -0
  37. package/examples/mvc_welcome/README.md +34 -0
  38. package/examples/mvc_welcome/app.js +50 -0
  39. package/examples/mvc_welcome/controllers/welcomeController.js +41 -0
  40. package/examples/mvc_welcome/package.json +26 -0
  41. package/examples/mvc_welcome/views/home/welcome.html +82 -0
  42. package/examples/v2/README.md +72 -0
  43. package/examples/v2/app.js +74 -0
  44. package/examples/v2/app_fixed.js +74 -0
  45. package/examples/v2/controllers/authController.js +64 -0
  46. package/examples/v2/controllers/mainController.js +24 -0
  47. package/examples/v2/controllers/protectedController.js +12 -0
  48. package/examples/v2/controllers/userController.js +16 -0
  49. package/examples/v2/package.json +27 -0
  50. package/examples/v2/routes.json +30 -0
  51. package/examples/v2/test_api.sh +47 -0
  52. package/examples/v2/tokens_example.sqlite +0 -0
  53. package/examples/v2.1_firewall_demo/README.md +113 -0
  54. package/examples/v2.1_firewall_demo/app.js +182 -0
  55. package/examples/v2.1_firewall_demo/package.json +27 -0
  56. package/examples/v2.1_hooks_demo/README.md +85 -0
  57. package/examples/v2.1_hooks_demo/app.js +101 -0
  58. package/examples/v2.1_hooks_demo/controllers/hooksController.js +29 -0
  59. package/examples/v2.1_hooks_demo/controllers/mainController.js +18 -0
  60. package/examples/v2.1_hooks_demo/package.json +27 -0
  61. package/examples/v2.1_hooks_demo/routes.json +16 -0
  62. package/examples/v2.1_openapi_demo/README.md +82 -0
  63. package/examples/v2.1_openapi_demo/app.js +296 -0
  64. package/examples/v2.1_openapi_demo/package.json +26 -0
  65. package/examples/v2_cors/README.md +82 -0
  66. package/examples/v2_cors/app.js +108 -0
  67. package/examples/v2_cors/package.json +23 -0
  68. package/examples/v2_json_auth/README.md +83 -0
  69. package/examples/v2_json_auth/app.js +72 -0
  70. package/examples/v2_json_auth/controllers/authController.js +67 -0
  71. package/examples/v2_json_auth/controllers/mainController.js +16 -0
  72. package/examples/v2_json_auth/controllers/protectedController.js +12 -0
  73. package/examples/v2_json_auth/controllers/tokenController.js +28 -0
  74. package/examples/v2_json_auth/controllers/userController.js +15 -0
  75. package/examples/v2_json_auth/package.json +26 -0
  76. package/examples/v2_json_auth/routes.json +37 -0
  77. package/examples/v2_json_auth/tokens.json +20 -0
  78. package/examples/v2_mariadb_auth/README.md +94 -0
  79. package/examples/v2_mariadb_auth/app.js +81 -0
  80. package/examples/v2_mariadb_auth/controllers/authController.js +95 -0
  81. package/examples/v2_mariadb_auth/controllers/mainController.js +31 -0
  82. package/examples/v2_mariadb_auth/controllers/protectedController.js +12 -0
  83. package/examples/v2_mariadb_auth/controllers/userController.js +17 -0
  84. package/examples/v2_mariadb_auth/package.json +27 -0
  85. package/examples/v2_mariadb_auth/routes.json +37 -0
  86. package/examples/v2_no_auth/README.md +75 -0
  87. package/examples/v2_no_auth/app.js +72 -0
  88. package/examples/v2_no_auth/controllers/healthController.js +14 -0
  89. package/examples/v2_no_auth/controllers/mainController.js +19 -0
  90. package/examples/v2_no_auth/controllers/productController.js +31 -0
  91. package/examples/v2_no_auth/controllers/publicController.js +16 -0
  92. package/examples/v2_no_auth/package.json +22 -0
  93. package/examples/v2_no_auth/routes.json +37 -0
  94. package/examples/v2_oauth/README.md +70 -0
  95. package/examples/v2_oauth/app.js +90 -0
  96. package/examples/v2_oauth/controllers/mainController.js +45 -0
  97. package/examples/v2_oauth/controllers/oauthController.js +247 -0
  98. package/examples/v2_oauth/controllers/protectedController.js +13 -0
  99. package/examples/v2_oauth/controllers/userController.js +17 -0
  100. package/examples/v2_oauth/package.json +26 -0
  101. package/examples/v2_oauth/routes.json +44 -0
  102. package/examples/v2_openapi/README.md +77 -0
  103. package/examples/v2_openapi/app.js +222 -0
  104. package/examples/v2_openapi/controllers/authController.js +52 -0
  105. package/examples/v2_openapi/controllers/mainController.js +26 -0
  106. package/examples/v2_openapi/controllers/productController.js +17 -0
  107. package/examples/v2_openapi/controllers/userController.js +27 -0
  108. package/examples/v2_openapi/package.json +26 -0
  109. package/examples/v2_openapi/routes.json +37 -0
  110. package/index.js +11 -3
  111. package/lib/core/handler.js +1 -1
  112. package/lib/core/hooks.js +1 -1
  113. package/lib/core/router.js +1 -1
  114. package/lib/core/server.js +1 -1
  115. package/lib/loader/controllerLoader.js +1 -1
  116. package/lib/loader/routeLoader.js +1 -1
  117. package/lib/middleware/auditLogger.js +1 -1
  118. package/lib/middleware/authenticator.js +1 -1
  119. package/lib/middleware/compressor.js +1 -1
  120. package/lib/middleware/cors.js +1 -1
  121. package/lib/middleware/firewall.js +1 -1
  122. package/lib/middleware/rateLimiter.js +1 -1
  123. package/lib/middleware/session.js +1 -1
  124. package/lib/middleware/validator.js +1 -1
  125. package/lib/mvc/controllerBase.js +207 -0
  126. package/lib/mvc/viewEngine.js +752 -0
  127. package/lib/utils/configParser.js +1 -1
  128. package/lib/utils/logger.js +1 -1
  129. package/lib/utils/openapiGenerator.js +1 -1
  130. package/lib/utils/tokenManager.js +1 -1
  131. package/package.json +1 -1
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Ejemplo real de uso del framework JERK
3
+ * Este script demuestra cómo cargar rutas desde un archivo JSON
4
+ * y usar los controladores definidos en el archivo de rutas
5
+ */
6
+
7
+ const path = require('path');
8
+ const { JERK, RouteLoader, Authenticator, Logger } = require('../index');
9
+
10
+ // Crear instancia del logger
11
+ const logger = new Logger({ level: 'info', timestamp: true });
12
+
13
+ logger.info('Iniciando ejemplo real de carga de rutas desde JSON');
14
+
15
+ // Crear instancia del servidor
16
+ const server = new JERK({
17
+ port: 6000,
18
+ host: 'localhost'
19
+ });
20
+
21
+ // Crear instancia del autenticador
22
+ const authenticator = new Authenticator();
23
+
24
+ // Registrar estrategias de autenticación que se usan en routes.json
25
+ authenticator.use('apiKey', authenticator.apiKeyStrategy('X-API-Key', ['secret-key-123']));
26
+ authenticator.use('jwt', authenticator.jwtStrategy('secret-jwt-key'));
27
+
28
+ // Cargar rutas desde el archivo JSON
29
+ const routeLoader = new RouteLoader();
30
+
31
+ // Middleware de logging
32
+ server.use((req, res, next) => {
33
+ logger.info(`${req.method} ${req.url} - IP: ${req.connection.remoteAddress}`);
34
+ next();
35
+ });
36
+
37
+ logger.info('Cargando rutas desde advanced/routes.json...');
38
+
39
+ // Cargar las rutas desde el archivo JSON
40
+ // Cambiamos temporalmente el directorio de trabajo para que las rutas relativas funcionen correctamente
41
+ const originalCwd = process.cwd();
42
+ process.chdir(__dirname); // Cambiar al directorio actual (examples)
43
+
44
+ routeLoader.loadRoutes(server, './advanced/routes.json')
45
+ .then(routes => {
46
+ process.chdir(originalCwd); // Restaurar directorio original
47
+
48
+ logger.info(`Cargadas ${routes.length} rutas desde el archivo JSON:`);
49
+ routes.forEach((route, index) => {
50
+ logger.info(` ${index + 1}. ${route.method} ${route.path} -> ${route.controller}#${route.handler}`);
51
+ });
52
+
53
+ logger.info('\nIniciando servidor en http://localhost:6000');
54
+
55
+ // Iniciar el servidor
56
+ const httpServer = server.start();
57
+
58
+ logger.info('\nENDPOINTS DISPONIBLES (cargados desde routes.json):');
59
+ logger.info('GET /api/users - Obtener todos los usuarios (JWT req)');
60
+ logger.info('GET /api/users/:id - Obtener usuario por ID (JWT req)');
61
+ logger.info('POST /api/users - Crear usuario (API Key req)');
62
+ logger.info('GET /api/products - Obtener productos (sin auth)');
63
+ logger.info('PUT /api/products/:id - Actualizar producto (API Key req)');
64
+
65
+ logger.info('\nEJEMPLOS DE USO:');
66
+ logger.info('# Obtener productos (sin autenticación):');
67
+ logger.info('curl -X GET http://localhost:6000/api/products');
68
+
69
+ logger.info('\nEl servidor se detendrá automáticamente en 120 segundos...');
70
+
71
+ // Programar apagado automático para la demostración
72
+ setTimeout(() => {
73
+ logger.info('Finalizando ejemplo...');
74
+ httpServer.close(() => {
75
+ logger.info('Servidor detenido. Ejemplo completado.');
76
+ console.log('\nEjemplo real completado exitosamente!');
77
+ console.log('El framework JERK ha demostrado su capacidad para:');
78
+ console.log(' - Cargar rutas dinámicamente desde archivos JSON');
79
+ console.log(' - Usar controladores definidos externamente');
80
+ console.log(' - Aplicar diferentes tipos de autenticación');
81
+ process.exit(0);
82
+ });
83
+ }, 120000);
84
+
85
+ })
86
+ .catch(error => {
87
+ process.chdir(originalCwd); // Asegurarse de restaurar el directorio en caso de error
88
+ logger.error('Error cargando rutas:', error.message);
89
+ process.exit(1);
90
+ });
91
+
92
+ // Mantener el proceso activo
93
+ process.stdin.resume();
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Controlador de ejemplo para usuarios
3
+ * Archivo: examples/basic/controllers/userController.js
4
+ */
5
+
6
+ // Simulación de base de datos
7
+ let users = [
8
+ { id: 1, name: 'John Doe', email: 'john@example.com' },
9
+ { id: 2, name: 'Jane Smith', email: 'jane@example.com' }
10
+ ];
11
+
12
+ // Obtener todos los usuarios
13
+ function getUsers(req, res) {
14
+ res.writeHead(200, { 'Content-Type': 'application/json' });
15
+ res.end(JSON.stringify({
16
+ success: true,
17
+ data: users
18
+ }));
19
+ }
20
+
21
+ // Obtener un usuario por ID
22
+ function getUserById(req, res) {
23
+ const userId = parseInt(req.params.id);
24
+ const user = users.find(u => u.id === userId);
25
+
26
+ if (!user) {
27
+ res.writeHead(404, { 'Content-Type': 'application/json' });
28
+ res.end(JSON.stringify({
29
+ success: false,
30
+ message: 'Usuario no encontrado'
31
+ }));
32
+ return;
33
+ }
34
+
35
+ res.writeHead(200, { 'Content-Type': 'application/json' });
36
+ res.end(JSON.stringify({
37
+ success: true,
38
+ data: user
39
+ }));
40
+ }
41
+
42
+ // Crear un nuevo usuario
43
+ function createUser(req, res) {
44
+ try {
45
+ const { name, email } = req.body;
46
+
47
+ // Validar datos
48
+ if (!name || !email) {
49
+ res.writeHead(400, { 'Content-Type': 'application/json' });
50
+ res.end(JSON.stringify({
51
+ success: false,
52
+ message: 'Nombre y correo electrónico son requeridos'
53
+ }));
54
+ return;
55
+ }
56
+
57
+ // Crear nuevo usuario
58
+ const newUser = {
59
+ id: users.length + 1,
60
+ name,
61
+ email
62
+ };
63
+
64
+ users.push(newUser);
65
+
66
+ res.writeHead(201, { 'Content-Type': 'application/json' });
67
+ res.end(JSON.stringify({
68
+ success: true,
69
+ data: newUser
70
+ }));
71
+ } catch (error) {
72
+ res.writeHead(500, { 'Content-Type': 'application/json' });
73
+ res.end(JSON.stringify({
74
+ success: false,
75
+ message: 'Error al crear usuario'
76
+ }));
77
+ }
78
+ }
79
+
80
+ // Exportar handlers
81
+ module.exports = {
82
+ getUsers,
83
+ getUserById,
84
+ createUser
85
+ };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Ejemplo basico de uso del framework JERK
3
+ * Este script demuestra cómo usar directamente los controladores
4
+ */
5
+
6
+ const { JERK, Logger } = require('../index');
7
+ const userController = require('./basic/controllers/userController');
8
+
9
+ // Crear instancia del logger
10
+ const logger = new Logger({ level: 'info', timestamp: true });
11
+
12
+ logger.info('Iniciando ejemplo basico con controladores');
13
+
14
+ // Crear instancia del servidor
15
+ const server = new JERK({
16
+ port: 6001,
17
+ host: 'localhost'
18
+ });
19
+
20
+ // Middleware de logging
21
+ server.use((req, res, next) => {
22
+ logger.info(`${req.method} ${req.url}`);
23
+ next();
24
+ });
25
+
26
+ // Usar los handlers directamente desde el controlador
27
+ server.addRoute('GET', '/api/users', userController.getUsers);
28
+ server.addRoute('GET', '/api/users/:id', userController.getUserById);
29
+ server.addRoute('POST', '/api/users', userController.createUser);
30
+
31
+ logger.info('Agregando rutas usando handlers del controlador userController');
32
+
33
+ logger.info('\nIniciando servidor en http://localhost:6001');
34
+
35
+ // Iniciar el servidor
36
+ const httpServer = server.start();
37
+
38
+ logger.info('\nENDPOINTS DISPONIBLES:');
39
+ logger.info('GET /api/users - Obtener todos los usuarios');
40
+ logger.info('GET /api/users/:id - Obtener usuario por ID');
41
+ logger.info('POST /api/users - Crear nuevo usuario');
42
+
43
+ logger.info('\nEJEMPLOS DE USO:');
44
+ logger.info('# Obtener todos los usuarios:');
45
+ logger.info('curl -X GET http://localhost:6001/api/users');
46
+ logger.info('');
47
+ logger.info('# Obtener usuario por ID:');
48
+ logger.info('curl -X GET http://localhost:6001/api/users/1');
49
+ logger.info('');
50
+ logger.info('# Crear nuevo usuario:');
51
+ logger.info('curl -X POST -H "Content-Type: application/json" \\');
52
+ logger.info(' -d \'{"name":"Juan Perez", "email":"juan@example.com"}\' \\');
53
+ logger.info(' http://localhost:6001/api/users');
54
+
55
+ logger.info('\nEl servidor se detendrá automáticamente en 60 segundos...');
56
+
57
+ // Programar apagado automático para la demostración
58
+ setTimeout(() => {
59
+ logger.info('Finalizando ejemplo basico...');
60
+ httpServer.close(() => {
61
+ logger.info('Servidor detenido. Ejemplo basico completado.');
62
+ console.log('\nEjemplo basico completado exitosamente!');
63
+ console.log('El framework JERK ha demostrado su capacidad para:');
64
+ console.log(' - Usar controladores directamente');
65
+ console.log(' - Manejar rutas parametrizadas');
66
+ console.log(' - Procesar solicitudes POST con cuerpo JSON');
67
+ process.exit(0);
68
+ });
69
+ }, 60000);
70
+
71
+ // Mantener el proceso activo
72
+ process.stdin.resume();
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Ejemplo de uso del sistema MVC para el framework JERK
3
+ * Demostración de vistas y controladores MVC
4
+ */
5
+
6
+ const { APIServer, Router, ControllerBase } = require('../../index');
7
+
8
+ // Crear un controlador personalizado que extienda ControllerBase
9
+ class HomeController extends ControllerBase {
10
+ constructor(options = {}) {
11
+ super(options);
12
+ }
13
+
14
+ // Acción para mostrar la página de inicio
15
+ index(req, res) {
16
+ // Establecer variables para la vista
17
+ this.set('title', 'Página de Inicio');
18
+ this.set('message', '¡Bienvenido al framework JERK!');
19
+ this.set('users', [
20
+ { name: 'Juan', email: 'juan@example.com' },
21
+ { name: 'María', email: 'maria@example.com' },
22
+ { name: 'Pedro', email: 'pedro@example.com' }
23
+ ]);
24
+
25
+ // Renderizar la vista
26
+ this.render(res, 'home/index', {
27
+ currentTime: new Date().toISOString()
28
+ });
29
+ }
30
+
31
+ // Acción para mostrar el perfil de un usuario
32
+ profile(req, res) {
33
+ // Obtener el ID del usuario de los parámetros
34
+ const userIdParam = this.input('id', '1');
35
+
36
+ // Validar que el ID sea un número entero positivo (no solo que empiece con un número)
37
+ if (!/^\d+$/.test(userIdParam) || parseInt(userIdParam) <= 0) {
38
+ // Si no es un ID válido, mostrar error
39
+ this.set('title', 'ID de usuario inválido');
40
+ this.render(res, 'user/invalid', {
41
+ userId: userIdParam
42
+ });
43
+ return;
44
+ }
45
+
46
+ const userId = parseInt(userIdParam);
47
+
48
+ // Array real de usuarios
49
+ const users = [
50
+ { id: 1, name: 'Ana García', email: 'ana@example.com', registered: '2026-01-01T10:00:00Z', active: true },
51
+ { id: 2, name: 'Carlos López', email: 'carlos@example.com', registered: '2026-01-02T11:30:00Z', active: false },
52
+ { id: 3, name: 'Laura Martínez', email: 'laura@example.com', registered: '2026-01-03T14:20:00Z', active: true },
53
+ { id: 4, name: 'Pedro Rodríguez', email: 'pedro@example.com', registered: '2026-01-04T09:15:00Z', active: true },
54
+ { id: 5, name: 'María Sánchez', email: 'maria@example.com', registered: '2026-01-05T16:45:00Z', active: false }
55
+ ];
56
+
57
+ // Buscar el usuario por ID
58
+ const user = users.find(u => u.id === userId);
59
+
60
+ if (!user) {
61
+ // Si no se encuentra el usuario, mostrar error
62
+ this.set('title', 'Usuario no encontrado');
63
+ this.render(res, 'user/notfound', {
64
+ userId: userId
65
+ });
66
+ return;
67
+ }
68
+
69
+ // Establecer variables para la vista
70
+ this.set('title', `Perfil de ${user.name}`);
71
+ this.set('user', user);
72
+
73
+ // Renderizar la vista de perfil
74
+ this.render(res, 'user/profile');
75
+ }
76
+
77
+ // Acción para mostrar la lista de usuarios
78
+ users(req, res) {
79
+ // Array real de usuarios (el mismo que en profile para consistencia)
80
+ const users = [
81
+ { id: 1, name: 'Ana García', email: 'ana@example.com', registered: '2026-01-01T10:00:00Z', active: true },
82
+ { id: 2, name: 'Carlos López', email: 'carlos@example.com', registered: '2026-01-02T11:30:00Z', active: false },
83
+ { id: 3, name: 'Laura Martínez', email: 'laura@example.com', registered: '2026-01-03T14:20:00Z', active: true },
84
+ { id: 4, name: 'Pedro Rodríguez', email: 'pedro@example.com', registered: '2026-01-04T09:15:00Z', active: true },
85
+ { id: 5, name: 'María Sánchez', email: 'maria@example.com', registered: '2026-01-05T16:45:00Z', active: false }
86
+ ];
87
+
88
+ // Establecer variables para la vista
89
+ this.set('title', 'Lista de Usuarios');
90
+ this.set('users', users);
91
+
92
+ // Renderizar la vista de usuarios
93
+ this.render(res, 'user/list');
94
+ }
95
+ }
96
+
97
+ // Crear instancia del servidor
98
+ const server = new APIServer({
99
+ port: 9000,
100
+ host: 'localhost'
101
+ });
102
+
103
+ // Crear instancia del router
104
+ const router = new Router();
105
+
106
+ // Crear instancia del controlador
107
+ const homeController = new HomeController({ viewsPath: './examples/mvc_example/views' });
108
+
109
+ // Definir rutas
110
+ router
111
+ .get('/', (req, res) => {
112
+ // Establecer la solicitud y respuesta en el controlador
113
+ homeController.setRequestResponse(req, res);
114
+ homeController.index(req, res);
115
+ })
116
+ .get('/profile', (req, res) => {
117
+ homeController.setRequestResponse(req, res);
118
+ homeController.profile(req, res);
119
+ })
120
+ .get('/users', (req, res) => {
121
+ homeController.setRequestResponse(req, res);
122
+ homeController.users(req, res);
123
+ });
124
+
125
+ // Agregar las rutas del router al servidor
126
+ const routes = router.getRoutes();
127
+ for (const route of routes) {
128
+ server.addRoute(route.method, route.path, route.handler);
129
+ }
130
+
131
+ // Iniciar el servidor
132
+ server.start(() => {
133
+ console.log('Servidor MVC iniciado en http://localhost:9000');
134
+ console.log('Rutas disponibles:');
135
+ console.log('- http://localhost:9000/ (Página de inicio)');
136
+ console.log('- http://localhost:9000/profile?id=1 (Perfil de usuario)');
137
+ console.log('- http://localhost:9000/users (Lista de usuarios)');
138
+ });
@@ -0,0 +1,26 @@
1
+ <h1>{{title}}</h1>
2
+ <p>{{message}}</p>
3
+
4
+ <h2>Usuarios Registrados</h2>
5
+ {{if users}}
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <th>Nombre</th>
10
+ <th>Email</th>
11
+ </tr>
12
+ </thead>
13
+ <tbody>
14
+ {{foreach:users}}
15
+ <tr>
16
+ <td>{{item.name}}</td>
17
+ <td>{{item.email}}</td>
18
+ </tr>
19
+ {{endforeach}}
20
+ </tbody>
21
+ </table>
22
+ {{else}}
23
+ <p>No hay usuarios registrados.</p>
24
+ {{endif}}
25
+
26
+ <p>Hora actual: {{currentTime}}</p>
@@ -0,0 +1,3 @@
1
+ <h1>{{title}}</h1>
2
+ <p>{{message}}</p>
3
+ <p>Hora actual: {{currentTime}}</p>
@@ -0,0 +1,23 @@
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{title}}</title>
7
+ <style>
8
+ body { font-family: Arial, sans-serif; margin: 40px; background-color: #f5f5f5; }
9
+ .container { max-width: 800px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
10
+ h1 { color: #333; }
11
+ table { width: 100%; border-collapse: collapse; margin-top: 20px; }
12
+ th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
13
+ th { background-color: #f2f2f2; }
14
+ .active { color: green; }
15
+ .inactive { color: red; }
16
+ </style>
17
+ </head>
18
+ <body>
19
+ <div class="container">
20
+ {{content}}
21
+ </div>
22
+ </body>
23
+ </html>
@@ -0,0 +1,3 @@
1
+ <h1>{{title}}</h1>
2
+ <p>{{message}}</p>
3
+ <p>Prueba de variable simple: {{currentTime}}</p>
@@ -0,0 +1,6 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <div>
4
+ <p>El ID proporcionado no es válido: {{userId}}</p>
5
+ <a href="/users">Volver a la lista de usuarios</a>
6
+ </div>
@@ -0,0 +1,36 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ {{if users}}
4
+ <table>
5
+ <thead>
6
+ <tr>
7
+ <th>ID</th>
8
+ <th>Nombre</th>
9
+ <th>Email</th>
10
+ <th>Estado</th>
11
+ <th>Acciones</th>
12
+ </tr>
13
+ </thead>
14
+ <tbody>
15
+ {{foreach:users}}
16
+ <tr>
17
+ <td>{{item.id}}</td>
18
+ <td>{{item.name}}</td>
19
+ <td>{{item.email}}</td>
20
+ <td>
21
+ {{if item.active}}
22
+ <span class="active">Activo</span>
23
+ {{else}}
24
+ <span class="inactive">Inactivo</span>
25
+ {{endif}}
26
+ </td>
27
+ <td><a href="/profile?id={{item.id}}">Ver Perfil</a></td>
28
+ </tr>
29
+ {{endforeach}}
30
+ </tbody>
31
+ </table>
32
+ {{else}}
33
+ <p>No hay usuarios registrados.</p>
34
+ {{endif}}
35
+
36
+ <a href="/">Volver a la página de inicio</a>
@@ -0,0 +1,6 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <div>
4
+ <p>No se encontró el usuario con ID: {{userId}}</p>
5
+ <a href="/users">Volver a la lista de usuarios</a>
6
+ </div>
@@ -0,0 +1,11 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <div>
4
+ <h2>Información del Usuario</h2>
5
+ <p><strong>ID:</strong> {{user.id}}</p>
6
+ <p><strong>Nombre:</strong> {{user.name}}</p>
7
+ <p><strong>Email:</strong> {{user.email}}</p>
8
+ <p><strong>Registrado:</strong> {{user.registered}}</p>
9
+ </div>
10
+
11
+ <a href="/users">Volver a la lista de usuarios</a>
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Ejemplo de uso del sistema MVC con definición de rutas desde archivo JSON
3
+ * Demostración de vistas, helpers y filtros
4
+ */
5
+
6
+ const { APIServer, RouteLoader, ControllerLoader, ViewEngine } = require('../../index');
7
+
8
+ // Crear instancia del servidor
9
+ const server = new APIServer({
10
+ port: 9001,
11
+ host: 'localhost'
12
+ });
13
+
14
+ // Crear instancia del cargador de rutas
15
+ const routeLoader = new RouteLoader();
16
+
17
+ // Cargar las rutas desde el archivo JSON
18
+ routeLoader.loadRoutes(server, './examples/mvc_routes_example/routes.json')
19
+ .then(routes => {
20
+ console.log(`${routes.length} rutas cargadas exitosamente`);
21
+ console.log('Rutas disponibles:');
22
+ console.log('- http://localhost:9001/ (Página de inicio)');
23
+ console.log('- http://localhost:9001/users (Lista de usuarios)');
24
+ console.log('- http://localhost:9001/profile?id=1 (Perfil de usuario)');
25
+ console.log('- http://localhost:9001/products (Catálogo de productos)');
26
+
27
+ // Iniciar el servidor
28
+ server.start(() => {
29
+ console.log('Servidor MVC con rutas JSON iniciado en http://localhost:9001');
30
+ });
31
+ })
32
+ .catch(error => {
33
+ console.error('Error al cargar las rutas:', error);
34
+ });
@@ -0,0 +1,27 @@
1
+ const { ControllerBase } = require('../../../index');
2
+
3
+ class MainController extends ControllerBase {
4
+ constructor(options = {}) {
5
+ super(options);
6
+ }
7
+
8
+ index(req, res) {
9
+ this.set('title', 'Inicio - Ejemplo MVC con Routes');
10
+ this.set('message', '¡Bienvenido al ejemplo de MVC con definición de rutas!');
11
+
12
+ this.render(res, 'main/index', {
13
+ currentTime: new Date().toISOString(),
14
+ version: '2.3.1'
15
+ });
16
+ }
17
+ }
18
+
19
+ // Exportar métodos directamente para que el RouteLoader pueda acceder a ellos
20
+ const controllerInstance = new MainController({ viewsPath: './examples/mvc_routes_example/views' });
21
+
22
+ module.exports = {
23
+ index: (req, res) => {
24
+ controllerInstance.setRequestResponse(req, res);
25
+ controllerInstance.index(req, res);
26
+ }
27
+ };
@@ -0,0 +1,47 @@
1
+ const { ControllerBase } = require('../../../index');
2
+
3
+ class ProductController extends ControllerBase {
4
+ constructor(options = {}) {
5
+ super(options);
6
+
7
+ // Registrar helpers personalizados para este controlador
8
+ this.getViewEngine().addHelper('calculateDiscount', (price, discountPercent) => {
9
+ return price - (price * discountPercent / 100);
10
+ });
11
+
12
+ this.getViewEngine().addHelper('formatCurrency', (value, symbol = '$') => {
13
+ return `${symbol}${Number(value).toFixed(2)}`;
14
+ });
15
+
16
+ this.getViewEngine().addHelper('isOnSale', (product) => {
17
+ return product.discount > 0;
18
+ });
19
+ }
20
+
21
+ catalog(req, res) {
22
+ const products = [
23
+ { id: 1, name: 'Laptop Pro', price: 1200, discount: 10, category: 'Electronics' },
24
+ { id: 2, name: 'Mouse Inalámbrico', price: 25, discount: 15, category: 'Accessories' },
25
+ { id: 3, name: 'Teclado Mecánico', price: 80, discount: 0, category: 'Accessories' },
26
+ { id: 4, name: 'Monitor 4K', price: 400, discount: 20, category: 'Electronics' },
27
+ { id: 5, name: 'Auriculares', price: 150, discount: 5, category: 'Audio' }
28
+ ];
29
+
30
+ this.set('title', 'Catálogo de Productos');
31
+ this.set('products', products);
32
+
33
+ this.render(res, 'product/catalog', {
34
+ currencySymbol: 'USD'
35
+ });
36
+ }
37
+ }
38
+
39
+ // Exportar métodos directamente para que el RouteLoader pueda acceder a ellos
40
+ const controllerInstance = new ProductController({ viewsPath: './examples/mvc_routes_example/views' });
41
+
42
+ module.exports = {
43
+ catalog: (req, res) => {
44
+ controllerInstance.setRequestResponse(req, res);
45
+ controllerInstance.catalog(req, res);
46
+ }
47
+ };