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,76 @@
1
+ const { ControllerBase } = require('../../../index');
2
+
3
+ class UserController extends ControllerBase {
4
+ constructor(options = {}) {
5
+ super(options);
6
+ }
7
+
8
+ list(req, res) {
9
+ const users = [
10
+ { id: 1, name: 'Ana García', email: 'ana@example.com', registered: '2026-01-01', active: true },
11
+ { id: 2, name: 'Carlos López', email: 'carlos@example.com', registered: '2026-01-02', active: false },
12
+ { id: 3, name: 'Laura Martínez', email: 'laura@example.com', registered: '2026-01-03', active: true },
13
+ { id: 4, name: 'Pedro Rodríguez', email: 'pedro@example.com', registered: '2026-01-04', active: true },
14
+ { id: 5, name: 'María Sánchez', email: 'maria@example.com', registered: '2026-01-05', active: false }
15
+ ];
16
+
17
+ this.set('title', 'Lista de Usuarios');
18
+ this.set('users', users);
19
+
20
+ this.render(res, 'user/list', {
21
+ totalUsers: users.length
22
+ });
23
+ }
24
+
25
+ profile(req, res) {
26
+ const userIdParam = this.input('id', '1');
27
+
28
+ // Validar que el ID sea un número entero positivo
29
+ if (!/^\d+$/.test(userIdParam) || parseInt(userIdParam) <= 0) {
30
+ this.set('title', 'ID de usuario inválido');
31
+ this.render(res, 'user/invalid', {
32
+ userId: userIdParam
33
+ });
34
+ return;
35
+ }
36
+
37
+ const userId = parseInt(userIdParam);
38
+
39
+ const users = [
40
+ { id: 1, name: 'Ana García', email: 'ana@example.com', registered: '2026-01-01', active: true },
41
+ { id: 2, name: 'Carlos López', email: 'carlos@example.com', registered: '2026-01-02', active: false },
42
+ { id: 3, name: 'Laura Martínez', email: 'laura@example.com', registered: '2026-01-03', active: true },
43
+ { id: 4, name: 'Pedro Rodríguez', email: 'pedro@example.com', registered: '2026-01-04', active: true },
44
+ { id: 5, name: 'María Sánchez', email: 'maria@example.com', registered: '2026-01-05', active: false }
45
+ ];
46
+
47
+ const user = users.find(u => u.id === userId);
48
+
49
+ if (!user) {
50
+ this.set('title', 'Usuario no encontrado');
51
+ this.render(res, 'user/notfound', {
52
+ userId: userId
53
+ });
54
+ return;
55
+ }
56
+
57
+ this.set('title', `Perfil de ${user.name}`);
58
+ this.set('user', user);
59
+
60
+ this.render(res, 'user/profile');
61
+ }
62
+ }
63
+
64
+ // Exportar métodos directamente para que el RouteLoader pueda acceder a ellos
65
+ const controllerInstance = new UserController({ viewsPath: './examples/mvc_routes_example/views' });
66
+
67
+ module.exports = {
68
+ list: (req, res) => {
69
+ controllerInstance.setRequestResponse(req, res);
70
+ controllerInstance.list(req, res);
71
+ },
72
+ profile: (req, res) => {
73
+ controllerInstance.setRequestResponse(req, res);
74
+ controllerInstance.profile(req, res);
75
+ }
76
+ };
@@ -0,0 +1,30 @@
1
+ [
2
+ {
3
+ "method": "GET",
4
+ "path": "/",
5
+ "controller": "./examples/mvc_routes_example/controllers/mainController.js",
6
+ "handler": "index",
7
+ "auth": "none"
8
+ },
9
+ {
10
+ "method": "GET",
11
+ "path": "/users",
12
+ "controller": "./examples/mvc_routes_example/controllers/userController.js",
13
+ "handler": "list",
14
+ "auth": "none"
15
+ },
16
+ {
17
+ "method": "GET",
18
+ "path": "/profile",
19
+ "controller": "./examples/mvc_routes_example/controllers/userController.js",
20
+ "handler": "profile",
21
+ "auth": "none"
22
+ },
23
+ {
24
+ "method": "GET",
25
+ "path": "/products",
26
+ "controller": "./examples/mvc_routes_example/controllers/productController.js",
27
+ "handler": "catalog",
28
+ "auth": "none"
29
+ }
30
+ ]
@@ -0,0 +1,31 @@
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
+ nav { margin: 20px 0; }
12
+ nav a { margin-right: 15px; text-decoration: none; color: #007bff; }
13
+ nav a:hover { text-decoration: underline; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <div class="container">
18
+ <h1>{{title}}</h1>
19
+ <p>{{message}}</p>
20
+
21
+ <nav>
22
+ <a href="/">Inicio</a>
23
+ <a href="/users">Usuarios</a>
24
+ <a href="/products">Productos</a>
25
+ </nav>
26
+
27
+ <p>Versión: {{version}}</p>
28
+ <p>Hora actual: {{currentTime}}</p>
29
+ </div>
30
+ </body>
31
+ </html>
@@ -0,0 +1,11 @@
1
+ <h1>{{title}}</h1>
2
+ <p>{{message}}</p>
3
+
4
+ <nav>
5
+ <a href="/">Inicio</a>
6
+ <a href="/users">Usuarios</a>
7
+ <a href="/products">Productos</a>
8
+ </nav>
9
+
10
+ <p>Versión: {{version}}</p>
11
+ <p>Hora actual: {{currentTime}}</p>
@@ -0,0 +1,24 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ {{if products}}
4
+ <div class="product-grid">
5
+ {{foreach:products}}
6
+ <div class="product-card">
7
+ <h3>{{item.name}}</h3>
8
+ <p>Categoría: {{item.category}}</p>
9
+ <p>Precio original: {{formatCurrency(item.price)}}</p>
10
+ <p>Descuento: {{item.discount}}%</p>
11
+ {{if item.discount > 0}}
12
+ <p>Precio con descuento: {{formatCurrency(calculateDiscount(item.price, item.discount))}}</p>
13
+ <p class="onsale">¡En oferta!</p>
14
+ {{else}}
15
+ <p class="regular">Precio regular</p>
16
+ {{endif}}
17
+ </div>
18
+ {{endforeach}}
19
+ </div>
20
+ {{else}}
21
+ <p>No hay productos disponibles.</p>
22
+ {{endif}}
23
+
24
+ <a href="/">Volver al inicio</a>
@@ -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,40 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ {{if users}}
4
+ <p>Total de usuarios: {{totalUsers}}</p>
5
+
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <th>ID</th>
10
+ <th>Nombre</th>
11
+ <th>Email</th>
12
+ <th>Registrado</th>
13
+ <th>Estado</th>
14
+ <th>Acciones</th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ {{foreach:users}}
19
+ <tr>
20
+ <td>{{item.id}}</td>
21
+ <td>{{item.name}}</td>
22
+ <td>{{item.email}}</td>
23
+ <td>{{item.registered|date:'DD/MM/YYYY'}}</td>
24
+ <td>
25
+ {{if item.active}}
26
+ <span class="active">Activo</span>
27
+ {{else}}
28
+ <span class="inactive">Inactivo</span>
29
+ {{endif}}
30
+ </td>
31
+ <td><a href="/profile?id={{item.id}}">Ver Perfil</a></td>
32
+ </tr>
33
+ {{endforeach}}
34
+ </tbody>
35
+ </table>
36
+ {{else}}
37
+ <p>No hay usuarios registrados.</p>
38
+ {{endif}}
39
+
40
+ <a href="/">Volver al 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,18 @@
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|date:'DD/MM/YYYY'}}</p>
9
+ <p><strong>Estado:</strong>
10
+ {{if user.active}}
11
+ <span class="active">Activo</span>
12
+ {{else}}
13
+ <span class="inactive">Inactivo</span>
14
+ {{endif}}
15
+ </p>
16
+ </div>
17
+
18
+ <a href="/users">Volver a la lista de usuarios</a>
@@ -0,0 +1,34 @@
1
+ # Ejemplo de Página de Bienvenida con Motor MVC
2
+
3
+ Este ejemplo demuestra cómo usar el motor de plantillas MVC del framework JERK para crear una página de bienvenida atractiva y funcional.
4
+
5
+ ## Características
6
+
7
+ - **Sistema MVC**: Uso completo del sistema de vistas, controladores y modelos
8
+ - **Motor de Plantillas**: Uso del motor de plantillas con soporte para variables, condicionales y bucles
9
+ - **Vistas Dinámicas**: Renderizado de contenido dinámico desde el controlador
10
+ - **Estilos Modernos**: Diseño responsive y atractivo
11
+
12
+ ## Componentes
13
+
14
+ - `app.js`: Archivo principal que configura el servidor y las rutas
15
+ - `controllers/welcomeController.js`: Controlador que maneja la lógica del sitio
16
+ - `views/home/welcome.html`: Vista principal con el diseño de la página de bienvenida
17
+
18
+ ## Uso
19
+
20
+ 1. Inicia el servidor:
21
+ ```bash
22
+ node examples/mvc_welcome/app.js
23
+ ```
24
+
25
+ 2. Visita http://localhost:9002 para ver la página de bienvenida
26
+
27
+ ## Características del Framework
28
+
29
+ Este ejemplo muestra algunas de las características clave del framework JERK:
30
+
31
+ - Motor de plantillas MVC profesional
32
+ - Sistema de vistas con soporte para variables, condicionales y bucles
33
+ - Controladores MVC con acceso fácil a vistas
34
+ - Arquitectura modular y extensible
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Ejemplo de página de bienvenida usando el motor de plantillas MVC de JERK
3
+ * Demostración del sistema MVC con vistas y controladores
4
+ */
5
+
6
+ const { APIServer, Router, Logger } = require('../../index');
7
+ const WelcomeController = require('./controllers/welcomeController');
8
+
9
+ async function startServer() {
10
+ // Crear instancia del servidor
11
+ const server = new APIServer({
12
+ port: 9002,
13
+ host: 'localhost'
14
+ });
15
+
16
+ // Crear instancia del logger
17
+ const logger = new Logger({ level: 'info' });
18
+
19
+ // Crear instancia del controlador
20
+ const welcomeController = new WelcomeController({
21
+ viewsPath: './examples/mvc_welcome/views'
22
+ });
23
+
24
+ // Definir rutas
25
+ const router = new Router();
26
+
27
+ router
28
+ .get('/', (req, res) => {
29
+ welcomeController.setRequestResponse(req, res);
30
+ welcomeController.index(req, res);
31
+ });
32
+
33
+ // Agregar las rutas del router al servidor
34
+ const routes = router.getRoutes();
35
+ for (const route of routes) {
36
+ server.addRoute(route.method, route.path, route.handler);
37
+ }
38
+
39
+ // Iniciar el servidor
40
+ server.start(() => {
41
+ logger.info('Servidor de bienvenida MVC iniciado en http://localhost:9002');
42
+ logger.info('Ruta disponible:');
43
+ logger.info('- http://localhost:9002/ (Página de bienvenida)');
44
+ });
45
+ }
46
+
47
+ // Iniciar el servidor
48
+ startServer();
49
+
50
+ module.exports = { startServer };
@@ -0,0 +1,41 @@
1
+ const { ControllerBase } = require('../../../index');
2
+
3
+ class WelcomeController extends ControllerBase {
4
+ constructor(options = {}) {
5
+ super(options);
6
+ }
7
+
8
+ index(req, res) {
9
+ // Establecer variables para la vista
10
+ this.set('title', 'Bienvenido a JERK Framework');
11
+ this.set('message', 'El poderoso framework para construir aplicaciones web completas con Node.js');
12
+
13
+ // Datos de características del framework
14
+ this.set('features', [
15
+ {
16
+ name: 'Motor MVC',
17
+ description: 'Sistema completo de vistas, controladores y modelos'
18
+ },
19
+ {
20
+ name: 'Seguridad',
21
+ description: 'Firewall integrado y protección contra ataques'
22
+ },
23
+ {
24
+ name: 'Autenticación',
25
+ description: 'Soporte para JWT, OAuth, sesiones y más'
26
+ },
27
+ {
28
+ name: 'Flexibilidad',
29
+ description: 'Arquitectura modular y altamente configurable'
30
+ }
31
+ ]);
32
+
33
+ this.set('documentationUrl', 'https://jerk.page.gd/');
34
+ this.set('examplesUrl', 'https://gitlab.com/bytedogssyndicate1/jerk');
35
+
36
+ // Renderizar la vista
37
+ this.render(res, 'home/welcome');
38
+ }
39
+ }
40
+
41
+ module.exports = WelcomeController;
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "jerk-mvc-welcome-example",
3
+ "version": "1.0.0",
4
+ "description": "Ejemplo de página de bienvenida usando el motor de plantillas MVC del framework JERK",
5
+ "main": "app.js",
6
+ "scripts": {
7
+ "start": "node app.js",
8
+ "dev": "nodemon app.js"
9
+ },
10
+ "keywords": [
11
+ "jerk",
12
+ "mvc",
13
+ "template-engine",
14
+ "welcome-page",
15
+ "nodejs",
16
+ "framework"
17
+ ],
18
+ "author": "JERK Framework Team",
19
+ "license": "Apache-2.0",
20
+ "dependencies": {
21
+ "jerkjs": "^2.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "nodemon": "^3.0.0"
25
+ }
26
+ }
@@ -0,0 +1,82 @@
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 {
9
+ font-family: Arial, sans-serif;
10
+ margin: 0;
11
+ padding: 0;
12
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
13
+ min-height: 100vh;
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: center;
17
+ }
18
+ .container {
19
+ background: white;
20
+ padding: 2rem;
21
+ border-radius: 10px;
22
+ box-shadow: 0 10px 30px rgba(0,0,0,0.2);
23
+ text-align: center;
24
+ max-width: 600px;
25
+ width: 90%;
26
+ }
27
+ h1 {
28
+ color: #333;
29
+ margin-bottom: 1rem;
30
+ }
31
+ .message {
32
+ font-size: 1.2rem;
33
+ color: #666;
34
+ margin-bottom: 2rem;
35
+ }
36
+ .features {
37
+ display: grid;
38
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
39
+ gap: 1rem;
40
+ margin: 2rem 0;
41
+ }
42
+ .feature {
43
+ background: #f8f9fa;
44
+ padding: 1rem;
45
+ border-radius: 5px;
46
+ border-left: 4px solid #667eea;
47
+ }
48
+ .btn {
49
+ display: inline-block;
50
+ background: #667eea;
51
+ color: white;
52
+ padding: 0.75rem 1.5rem;
53
+ text-decoration: none;
54
+ border-radius: 5px;
55
+ margin-top: 1rem;
56
+ transition: background 0.3s;
57
+ }
58
+ .btn:hover {
59
+ background: #5a6fd8;
60
+ }
61
+ </style>
62
+ </head>
63
+ <body>
64
+ <div class="container">
65
+ <h1>{{title}}</h1>
66
+ <div class="message">{{message}}</div>
67
+
68
+ <div class="features">
69
+ {{foreach:features}}
70
+ <div class="feature">
71
+ <h3>{{item.name}}</h3>
72
+ <p>{{item.description}}</p>
73
+ </div>
74
+ {{endforeach}}
75
+ </div>
76
+
77
+ <p>¡Comienza a construir tu aplicación con JERK!</p>
78
+ <a href="{{documentationUrl}}" class="btn">Documentación</a>
79
+ <a href="{{examplesUrl}}" class="btn">Ejemplos</a>
80
+ </div>
81
+ </body>
82
+ </html>
@@ -0,0 +1,72 @@
1
+ # Ejemplo API con Autenticación SQLite
2
+
3
+ Este ejemplo demuestra cómo crear una API con autenticación basada en tokens almacenados en SQLite utilizando el Framework JERK.
4
+
5
+ ## Características
6
+
7
+ - Autenticación JWT con tokens almacenados en SQLite
8
+ - Rutas protegidas y públicas
9
+ - Sistema de login para obtener tokens
10
+ - Controladores organizados por funcionalidad
11
+
12
+ ## Configuración
13
+
14
+ 1. Asegúrate de tener instaladas las dependencias del framework JERK
15
+ 2. Instala sqlite3 si aún no está instalado: `npm install sqlite3`
16
+
17
+ ## Uso
18
+
19
+ 1. Inicia el servidor:
20
+ ```bash
21
+ node app.js
22
+ ```
23
+
24
+ 2. El servidor escuchará en `http://localhost:8088`
25
+
26
+ ## Endpoints
27
+
28
+ - `GET /` - Página de inicio (público)
29
+ - `POST /login` - Iniciar sesión y obtener token (público)
30
+ - `GET /protected` - Contenido protegido (requiere token)
31
+ - `GET /profile` - Perfil de usuario (requiere token)
32
+
33
+ ## Ejemplo de uso
34
+
35
+ 1. Iniciar sesión:
36
+ ```bash
37
+ curl -X POST http://localhost:8088/login \
38
+ -H "Content-Type: application/json" \
39
+ -d '{"username": "admin", "password": "password"}'
40
+ ```
41
+
42
+ 2. Acceder a contenido protegido:
43
+ ```bash
44
+ curl -X GET http://localhost:8088/protected \
45
+ -H "Authorization: Bearer TU_TOKEN_AQUI"
46
+ ```
47
+
48
+ 3. Ver perfil de usuario:
49
+ ```bash
50
+ curl -X GET http://localhost:8088/profile \
51
+ -H "Authorization: Bearer TU_TOKEN_AQUI"
52
+ ```
53
+
54
+ ## Estructura del proyecto
55
+
56
+ ```
57
+ examples/v2/
58
+ ├── app.js # Punto de entrada de la aplicación
59
+ ├── routes.json # Definición de rutas
60
+ ├── controllers/ # Controladores de las rutas
61
+ │ ├── mainController.js
62
+ │ ├── authController.js
63
+ │ ├── protectedController.js
64
+ │ └── userController.js
65
+ └── tokens_example.sqlite # Base de datos SQLite para tokens (generada automáticamente)
66
+ ```
67
+
68
+ ## Seguridad
69
+
70
+ - Los tokens se almacenan en una base de datos SQLite
71
+ - Los tokens expiran después de 1 hora
72
+ - Las rutas protegidas requieren un token válido en el header Authorization
@@ -0,0 +1,74 @@
1
+ const {
2
+ APIServer,
3
+ Authenticator,
4
+ RouteLoader,
5
+ Logger,
6
+ SQLiteTokenAdapter
7
+ } = require('../../index.js');
8
+
9
+ async function startServer() {
10
+ // Crear instancia del servidor
11
+ const server = new APIServer({
12
+ port: 8088,
13
+ host: 'localhost'
14
+ });
15
+
16
+ // Crear instancia del logger
17
+ const logger = new Logger({ level: 'info' });
18
+
19
+ try {
20
+ // Crear instancia del adaptador de tokens SQLite
21
+ const tokenAdapter = new SQLiteTokenAdapter({
22
+ dbPath: './tokens_example.sqlite',
23
+ tableName: 'example_tokens'
24
+ });
25
+
26
+ // Inicializar el adaptador de tokens
27
+ await tokenAdapter.initialize();
28
+ logger.info('SQLite Token Adapter inicializado correctamente');
29
+
30
+ // Crear instancia del autenticador
31
+ const authenticator = new Authenticator({ logger });
32
+
33
+ // Registrar estrategia de autenticación JWT que utiliza el adaptador SQLite
34
+ authenticator.use('jwt-sqlite', async (req, options = {}) => {
35
+ const authHeader = req.headers.authorization;
36
+ const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
37
+
38
+ if (!token) {
39
+ return false;
40
+ }
41
+
42
+ // Validar el token contra la base de datos SQLite
43
+ const tokenRecord = await tokenAdapter.validateToken(token);
44
+
45
+ if (tokenRecord) {
46
+ // Agregar información del usuario a la solicitud
47
+ req.user = { userId: tokenRecord.user_id, tokenType: tokenRecord.token_type };
48
+ return true;
49
+ }
50
+
51
+ return false;
52
+ });
53
+
54
+ // Agregar el autenticador al servidor para que pueda ser usado por el RouteLoader
55
+ server.authenticator = authenticator;
56
+
57
+ // Cargar rutas desde archivo JSON
58
+ const routeLoader = new RouteLoader();
59
+ await routeLoader.loadRoutes(server, './routes.json');
60
+
61
+ // Iniciar el servidor
62
+ server.start();
63
+
64
+ logger.info('Servidor iniciado en http://localhost:8088');
65
+ } catch (error) {
66
+ logger.error('Error iniciando el servidor:', error.message);
67
+ process.exit(1);
68
+ }
69
+ }
70
+
71
+ // Iniciar el servidor
72
+ startServer();
73
+
74
+ module.exports = { startServer };