jerkjs 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/LICENSE +200 -0
  2. package/README.md +171 -0
  3. package/doc/EXTENSION_MANUAL.md +958 -0
  4. package/doc/FIREWALL_MANUAL.md +419 -0
  5. package/doc/HOOKS_REFERENCE_IMPROVED.md +599 -0
  6. package/doc/MANUAL_API_SDK.md +539 -0
  7. package/doc/MANUAL_MVC.md +397 -0
  8. package/doc/MARIADB_TOKENS_IMPLEMENTATION.md +113 -0
  9. package/doc/MIDDLEWARE_MANUAL.md +521 -0
  10. package/doc/OAUTH2_GOOGLE_MANUAL.md +408 -0
  11. package/doc/frontend-and-sessions.md +356 -0
  12. package/examples/advanced/controllers/productController.js +64 -0
  13. package/examples/advanced/controllers/userController.js +85 -0
  14. package/examples/advanced/routes.json +51 -0
  15. package/examples/advanced_example.js +93 -0
  16. package/examples/basic/controllers/userController.js +85 -0
  17. package/examples/basic_example.js +72 -0
  18. package/examples/frontend/README.md +71 -0
  19. package/examples/frontend/app.js +71 -0
  20. package/examples/frontend/controllers/apiController.js +39 -0
  21. package/examples/frontend/controllers/authController.js +220 -0
  22. package/examples/frontend/controllers/formController.js +47 -0
  23. package/examples/frontend/controllers/messageController.js +96 -0
  24. package/examples/frontend/controllers/pageController.js +178 -0
  25. package/examples/frontend/controllers/staticController.js +167 -0
  26. package/examples/frontend/routes.json +90 -0
  27. package/examples/mvc_example/app.js +138 -0
  28. package/examples/mvc_example/views/home/index.html +26 -0
  29. package/examples/mvc_example/views/home/simple.html +3 -0
  30. package/examples/mvc_example/views/layout.html +23 -0
  31. package/examples/mvc_example/views/test.html +3 -0
  32. package/examples/mvc_example/views/user/invalid.html +6 -0
  33. package/examples/mvc_example/views/user/list.html +36 -0
  34. package/examples/mvc_example/views/user/notfound.html +6 -0
  35. package/examples/mvc_example/views/user/profile.html +11 -0
  36. package/examples/mvc_routes_example/app.js +34 -0
  37. package/examples/mvc_routes_example/controllers/mainController.js +27 -0
  38. package/examples/mvc_routes_example/controllers/productController.js +47 -0
  39. package/examples/mvc_routes_example/controllers/userController.js +76 -0
  40. package/examples/mvc_routes_example/routes.json +30 -0
  41. package/examples/mvc_routes_example/views/layout.html +31 -0
  42. package/examples/mvc_routes_example/views/main/index.html +11 -0
  43. package/examples/mvc_routes_example/views/product/catalog.html +24 -0
  44. package/examples/mvc_routes_example/views/user/invalid.html +6 -0
  45. package/examples/mvc_routes_example/views/user/list.html +40 -0
  46. package/examples/mvc_routes_example/views/user/notfound.html +6 -0
  47. package/examples/mvc_routes_example/views/user/profile.html +18 -0
  48. package/examples/public/README.md +92 -0
  49. package/examples/public/app.js +72 -0
  50. package/examples/public/controllers/healthController.js +20 -0
  51. package/examples/public/controllers/mainController.js +22 -0
  52. package/examples/public/controllers/userController.js +139 -0
  53. package/examples/public/routes.json +51 -0
  54. package/examples/v2/README.md +72 -0
  55. package/examples/v2/app.js +74 -0
  56. package/examples/v2/app_fixed.js +74 -0
  57. package/examples/v2/controllers/authController.js +64 -0
  58. package/examples/v2/controllers/mainController.js +24 -0
  59. package/examples/v2/controllers/protectedController.js +12 -0
  60. package/examples/v2/controllers/userController.js +16 -0
  61. package/examples/v2/package.json +27 -0
  62. package/examples/v2/routes.json +30 -0
  63. package/examples/v2/test_api.sh +47 -0
  64. package/examples/v2/tokens_example.sqlite +0 -0
  65. package/examples/v2.1_firewall_demo/README.md +113 -0
  66. package/examples/v2.1_firewall_demo/app.js +182 -0
  67. package/examples/v2.1_firewall_demo/package.json +27 -0
  68. package/examples/v2.1_hooks_demo/README.md +85 -0
  69. package/examples/v2.1_hooks_demo/app.js +101 -0
  70. package/examples/v2.1_hooks_demo/controllers/hooksController.js +29 -0
  71. package/examples/v2.1_hooks_demo/controllers/mainController.js +18 -0
  72. package/examples/v2.1_hooks_demo/package.json +27 -0
  73. package/examples/v2.1_hooks_demo/routes.json +16 -0
  74. package/examples/v2.1_openapi_demo/README.md +82 -0
  75. package/examples/v2.1_openapi_demo/app.js +296 -0
  76. package/examples/v2.1_openapi_demo/package.json +26 -0
  77. package/examples/v2_cors/README.md +82 -0
  78. package/examples/v2_cors/app.js +108 -0
  79. package/examples/v2_cors/package.json +23 -0
  80. package/examples/v2_json_auth/README.md +83 -0
  81. package/examples/v2_json_auth/app.js +72 -0
  82. package/examples/v2_json_auth/controllers/authController.js +67 -0
  83. package/examples/v2_json_auth/controllers/mainController.js +16 -0
  84. package/examples/v2_json_auth/controllers/protectedController.js +12 -0
  85. package/examples/v2_json_auth/controllers/tokenController.js +28 -0
  86. package/examples/v2_json_auth/controllers/userController.js +15 -0
  87. package/examples/v2_json_auth/package.json +26 -0
  88. package/examples/v2_json_auth/routes.json +37 -0
  89. package/examples/v2_json_auth/tokens.json +20 -0
  90. package/examples/v2_mariadb_auth/README.md +94 -0
  91. package/examples/v2_mariadb_auth/app.js +81 -0
  92. package/examples/v2_mariadb_auth/controllers/authController.js +95 -0
  93. package/examples/v2_mariadb_auth/controllers/mainController.js +31 -0
  94. package/examples/v2_mariadb_auth/controllers/protectedController.js +12 -0
  95. package/examples/v2_mariadb_auth/controllers/userController.js +17 -0
  96. package/examples/v2_mariadb_auth/package.json +27 -0
  97. package/examples/v2_mariadb_auth/routes.json +37 -0
  98. package/examples/v2_no_auth/README.md +75 -0
  99. package/examples/v2_no_auth/app.js +72 -0
  100. package/examples/v2_no_auth/controllers/healthController.js +14 -0
  101. package/examples/v2_no_auth/controllers/mainController.js +19 -0
  102. package/examples/v2_no_auth/controllers/productController.js +31 -0
  103. package/examples/v2_no_auth/controllers/publicController.js +16 -0
  104. package/examples/v2_no_auth/package.json +22 -0
  105. package/examples/v2_no_auth/routes.json +37 -0
  106. package/examples/v2_oauth/README.md +70 -0
  107. package/examples/v2_oauth/app.js +90 -0
  108. package/examples/v2_oauth/controllers/mainController.js +45 -0
  109. package/examples/v2_oauth/controllers/oauthController.js +247 -0
  110. package/examples/v2_oauth/controllers/protectedController.js +13 -0
  111. package/examples/v2_oauth/controllers/userController.js +17 -0
  112. package/examples/v2_oauth/package.json +26 -0
  113. package/examples/v2_oauth/routes.json +44 -0
  114. package/examples/v2_openapi/README.md +77 -0
  115. package/examples/v2_openapi/app.js +222 -0
  116. package/examples/v2_openapi/controllers/authController.js +52 -0
  117. package/examples/v2_openapi/controllers/mainController.js +26 -0
  118. package/examples/v2_openapi/controllers/productController.js +17 -0
  119. package/examples/v2_openapi/controllers/userController.js +27 -0
  120. package/examples/v2_openapi/package.json +26 -0
  121. package/examples/v2_openapi/routes.json +37 -0
  122. package/generate_token.js +10 -0
  123. package/index.js +85 -0
  124. package/jerk.jpg +0 -0
  125. package/lib/core/handler.js +86 -0
  126. package/lib/core/hooks.js +224 -0
  127. package/lib/core/router.js +204 -0
  128. package/lib/core/securityEnhancedServer.js +752 -0
  129. package/lib/core/server.js +369 -0
  130. package/lib/loader/controllerLoader.js +175 -0
  131. package/lib/loader/routeLoader.js +341 -0
  132. package/lib/middleware/auditLogger.js +208 -0
  133. package/lib/middleware/authenticator.js +565 -0
  134. package/lib/middleware/compressor.js +218 -0
  135. package/lib/middleware/cors.js +135 -0
  136. package/lib/middleware/firewall.js +443 -0
  137. package/lib/middleware/rateLimiter.js +210 -0
  138. package/lib/middleware/session.js +301 -0
  139. package/lib/middleware/validator.js +193 -0
  140. package/lib/mvc/controllerBase.js +207 -0
  141. package/lib/mvc/viewEngine.js +752 -0
  142. package/lib/utils/configParser.js +223 -0
  143. package/lib/utils/logger.js +145 -0
  144. package/lib/utils/mariadbTokenAdapter.js +226 -0
  145. package/lib/utils/openapiGenerator.js +140 -0
  146. package/lib/utils/sqliteTokenAdapter.js +224 -0
  147. package/lib/utils/tokenManager.js +254 -0
  148. package/package.json +47 -0
  149. package/v2examplle/v2_json_auth/README.md +83 -0
  150. package/v2examplle/v2_json_auth/app.js +72 -0
  151. package/v2examplle/v2_json_auth/controllers/authController.js +67 -0
  152. package/v2examplle/v2_json_auth/controllers/mainController.js +16 -0
  153. package/v2examplle/v2_json_auth/controllers/protectedController.js +12 -0
  154. package/v2examplle/v2_json_auth/controllers/tokenController.js +28 -0
  155. package/v2examplle/v2_json_auth/controllers/userController.js +15 -0
  156. package/v2examplle/v2_json_auth/package.json +26 -0
  157. package/v2examplle/v2_json_auth/routes.json +37 -0
  158. package/v2examplle/v2_json_auth/tokens.json +20 -0
  159. package/v2examplle/v2_mariadb_auth/README.md +94 -0
  160. package/v2examplle/v2_mariadb_auth/app.js +81 -0
  161. package/v2examplle/v2_mariadb_auth/controllers/authController.js +95 -0
  162. package/v2examplle/v2_mariadb_auth/controllers/mainController.js +31 -0
  163. package/v2examplle/v2_mariadb_auth/controllers/protectedController.js +12 -0
  164. package/v2examplle/v2_mariadb_auth/controllers/userController.js +17 -0
  165. package/v2examplle/v2_mariadb_auth/package.json +27 -0
  166. package/v2examplle/v2_mariadb_auth/routes.json +37 -0
  167. package/v2examplle/v2_sqlite_auth/README.md +72 -0
  168. package/v2examplle/v2_sqlite_auth/app.js +74 -0
  169. package/v2examplle/v2_sqlite_auth/app_fixed.js +74 -0
  170. package/v2examplle/v2_sqlite_auth/controllers/authController.js +64 -0
  171. package/v2examplle/v2_sqlite_auth/controllers/mainController.js +24 -0
  172. package/v2examplle/v2_sqlite_auth/controllers/protectedController.js +12 -0
  173. package/v2examplle/v2_sqlite_auth/controllers/userController.js +16 -0
  174. package/v2examplle/v2_sqlite_auth/package.json +27 -0
  175. package/v2examplle/v2_sqlite_auth/routes.json +30 -0
  176. package/v2examplle/v2_sqlite_auth/test_api.sh +47 -0
  177. package/v2examplle/v2_sqlite_auth/tokens_example.sqlite +0 -0
@@ -0,0 +1,397 @@
1
+ # Manual del Sistema MVC para API SDK Framework
2
+
3
+ Visita nuestra página web: https://jerk.page.gd/
4
+ Repositorio oficial: https://gitlab.com/bytedogssyndicate1/jerk/
5
+
6
+ ## Índice
7
+ 1. [Introducción](#introducción)
8
+ 2. [Arquitectura MVC](#arquitectura-mvc)
9
+ 3. [Componentes del Sistema MVC](#componentes-del-sistema-mvc)
10
+ 4. [Motor de Vistas (ViewEngine)](#motor-de-vistas-viewengine)
11
+ 5. [Controladores Base (ControllerBase)](#controladores-base-controllerbase)
12
+ 6. [Sintaxis de Plantillas](#sintaxis-de-plantillas)
13
+ 7. [Hooks, Filters y Actions](#hooks-filters-y-actions)
14
+ 8. [Ejemplos de Uso](#ejemplos-de-uso)
15
+ 9. [Mejores Prácticas](#mejores-prácticas)
16
+
17
+ ## Introducción
18
+
19
+ El sistema MVC (Modelo-Vista-Controlador) para el API SDK Framework proporciona una arquitectura organizada para desarrollar aplicaciones web. Este sistema permite separar la lógica de negocio, la presentación y el flujo de control de manera limpia y mantenible.
20
+
21
+ ## Arquitectura MVC
22
+
23
+ La arquitectura MVC se divide en tres componentes principales:
24
+
25
+ - **Modelo**: Representa los datos y la lógica de negocio (manejado por el desarrollador)
26
+ - **Vista**: Presenta la información al usuario (manejado por el ViewEngine)
27
+ - **Controlador**: Coordina la interacción entre Modelo y Vista (manejado por ControllerBase)
28
+
29
+ ## Componentes del Sistema MVC
30
+
31
+ ### ViewEngine
32
+ Motor de vistas robusto que procesa plantillas con soporte para:
33
+ - Variables simples y anidadas
34
+ - Condiciones y bucles
35
+ - Filtros personalizables
36
+ - Hooks para extensibilidad
37
+ - Inclusiones de vistas
38
+
39
+ ### ControllerBase
40
+ Clase base para controladores que proporciona:
41
+ - Métodos para pasar datos a vistas
42
+ - Renderizado de vistas
43
+ - Manejo de solicitudes y respuestas
44
+ - Acceso a parámetros de entrada
45
+
46
+ ## Motor de Vistas (ViewEngine)
47
+
48
+ ### Configuración
49
+ ```javascript
50
+ const viewEngine = new ViewEngine({
51
+ viewsPath: './views', // Ruta a las vistas
52
+ defaultExtension: '.html', // Extensión por defecto
53
+ cacheEnabled: true // Habilitar cache
54
+ });
55
+ ```
56
+
57
+ ### Renderizado de Vistas
58
+ ```javascript
59
+ // Renderizar una vista con datos
60
+ const html = viewEngine.render('home/index', {
61
+ title: 'Mi Aplicación',
62
+ users: [{name: 'Juan', email: 'juan@example.com'}]
63
+ });
64
+ ```
65
+
66
+ ## Controladores Base (ControllerBase)
67
+
68
+ ### Extender ControllerBase
69
+ ```javascript
70
+ const { ControllerBase } = require('@jerkjs');
71
+
72
+ class HomeController extends ControllerBase {
73
+ constructor(options = {}) {
74
+ super(options);
75
+ }
76
+
77
+ index(req, res) {
78
+ this.set('title', 'Página de Inicio');
79
+ this.set('message', '¡Bienvenido!');
80
+
81
+ this.render(res, 'home/index', {
82
+ currentTime: new Date()
83
+ });
84
+ }
85
+ }
86
+ ```
87
+
88
+ ### Métodos Disponibles
89
+ - `set(key, value)`: Establece variables para la vista
90
+ - `render(res, viewName, data)`: Renderiza y envía una vista como respuesta
91
+ - `view(viewName, data)`: Renderiza una vista y retorna el HTML
92
+ - `input(key, defaultValue)`: Obtiene valores de la solicitud
93
+ - `redirect(res, url)`: Redirecciona a otra URL
94
+ - `json(res, data)`: Envía una respuesta JSON
95
+
96
+ ## Sintaxis de Plantillas
97
+
98
+ ### Variables
99
+ ```html
100
+ <h1>{{title}}</h1>
101
+ <p>{{user.name}}</p>
102
+ <p>{{user.profile.email}}</p>
103
+ ```
104
+
105
+ ### Condiciones
106
+ ```html
107
+ {{if user.active}}
108
+ <span class="active">Activo</span>
109
+ {{else}}
110
+ <span class="inactive">Inactivo</span>
111
+ {{endif}}
112
+ ```
113
+
114
+ ### Bucles
115
+ ```html
116
+ {{foreach:users}}
117
+ <div>
118
+ <h3>{{item.name}}</h3>
119
+ <p>{{item.email}}</p>
120
+ </div>
121
+ {{endforeach}}
122
+ ```
123
+
124
+ ### Inclusiones
125
+ ```html
126
+ {{include:header}}
127
+ {{include:./partials/navigation}}
128
+ ```
129
+
130
+ ### Filtros
131
+ ```html
132
+ <p>{{user.name|upper}}</p>
133
+ <p>{{user.bio|escape}}</p>
134
+ <p>{{post.date|date:'DD/MM/YYYY'}}</p>
135
+ ```
136
+
137
+ ## Hooks, Filters y Actions
138
+
139
+ ### Filtros Disponibles
140
+ - `escape`: Escapa caracteres HTML
141
+ - `upper`: Convierte a mayúsculas
142
+ - `lower`: Convierte a minúsculas
143
+ - `capitalize`: Capitaliza texto
144
+ - `date`: Formatea fechas
145
+
146
+ ### Agregar Filtros Personalizados
147
+ ```javascript
148
+ viewEngine.addFilter('truncate', (value, length = 100) => {
149
+ if (typeof value !== 'string') return value;
150
+ return value.length > length ? value.substring(0, length) + '...' : value;
151
+ });
152
+ ```
153
+
154
+ ### Agregar Helpers Personalizados
155
+ ```javascript
156
+ // Registrar un helper para formatear fechas
157
+ viewEngine.addHelper('formatDate', (date, format = 'YYYY-MM-DD HH:mm:ss') => {
158
+ if (!date) return '';
159
+ const d = new Date(date);
160
+ if (isNaN(d.getTime())) return date;
161
+
162
+ const pad = (n) => n.toString().padStart(2, '0');
163
+ const padYear = (n) => n.toString().padStart(4, '0');
164
+
165
+ return format
166
+ .replace('YYYY', padYear(d.getFullYear()))
167
+ .replace('MM', pad(d.getMonth() + 1))
168
+ .replace('DD', pad(d.getDate()))
169
+ .replace('HH', pad(d.getHours()))
170
+ .replace('mm', pad(d.getMinutes()))
171
+ .replace('ss', pad(d.getSeconds()));
172
+ });
173
+
174
+ // Registrar un helper para verificar si un número es par
175
+ viewEngine.addHelper('isEven', (value) => {
176
+ return Number(value) % 2 === 0;
177
+ });
178
+
179
+ // Registrar un helper para contar elementos
180
+ viewEngine.addHelper('count', (array) => {
181
+ return Array.isArray(array) ? array.length : 0;
182
+ });
183
+ ```
184
+
185
+ ### Uso de Helpers en Plantillas
186
+ ```html
187
+ <!-- Usar helper para formatear fecha -->
188
+ <p>Fecha de registro: {{formatDate(user.registered, 'DD/MM/YYYY')}}</p>
189
+
190
+ <!-- Usar helper para verificar si un número es par -->
191
+ {{if isEven(user.id)}}
192
+ <span class="even-id">ID Par</span>
193
+ {{else}}
194
+ <span class="odd-id">ID Impar</span>
195
+ {{endif}}
196
+
197
+ <!-- Usar helper para contar elementos -->
198
+ <p>Total de usuarios: {{count(users)}}</p>
199
+ ```
200
+
201
+ ### Validación de Sintaxis de Plantillas
202
+ ```javascript
203
+ // Validar un template antes de renderizarlo
204
+ const template = `
205
+ <h1>{{title}}</h1>
206
+ {{if users}}
207
+ {{foreach:users}}
208
+ <div>{{item.name}}</div>
209
+ {{endforeach}}
210
+ {{endif}}
211
+ `;
212
+
213
+ const errors = ViewEngine.validateTemplate(template);
214
+ if (errors.length > 0) {
215
+ console.warn('Errores de sintaxis encontrados:', errors);
216
+ }
217
+ ```
218
+
219
+ ### Opciones de Renderizado
220
+ ```javascript
221
+ // Renderizar con opciones de validación y advertencias
222
+ const html = viewEngine.render('home/index', {
223
+ title: 'Mi Aplicación',
224
+ users: [{name: 'Juan', email: 'juan@example.com'}]
225
+ }, {
226
+ validateSyntax: true, // Validar sintaxis del template
227
+ showWarnings: true, // Mostrar advertencias sobre variables no definidas
228
+ preserveUndefined: false // Qué hacer con variables no definidas
229
+ });
230
+ ```
231
+
232
+ ## Ejemplos de Uso
233
+
234
+ ### Ejemplo Completo de Controlador
235
+ ```javascript
236
+ const { ControllerBase } = require('@jerkjs');
237
+
238
+ class UserController extends ControllerBase {
239
+ constructor(options = {}) {
240
+ super(options);
241
+ }
242
+
243
+ // Mostrar lista de usuarios
244
+ index(req, res) {
245
+ const users = [
246
+ { id: 1, name: 'Ana', email: 'ana@example.com', active: true },
247
+ { id: 2, name: 'Carlos', email: 'carlos@example.com', active: false }
248
+ ];
249
+
250
+ this.set('title', 'Lista de Usuarios');
251
+ this.set('users', users);
252
+
253
+ this.render(res, 'users/list');
254
+ }
255
+
256
+ // Mostrar perfil de usuario
257
+ profile(req, res) {
258
+ const userId = parseInt(this.input('id'));
259
+
260
+ if (!userId || userId <= 0) {
261
+ this.set('title', 'ID Inválido');
262
+ this.render(res, 'users/invalid', { userId: this.input('id') });
263
+ return;
264
+ }
265
+
266
+ const users = [
267
+ { id: 1, name: 'Ana', email: 'ana@example.com', registered: '2026-01-01' },
268
+ { id: 2, name: 'Carlos', email: 'carlos@example.com', registered: '2026-01-02' }
269
+ ];
270
+
271
+ const user = users.find(u => u.id === userId);
272
+
273
+ if (!user) {
274
+ this.set('title', 'Usuario No Encontrado');
275
+ this.render(res, 'users/notfound', { userId });
276
+ return;
277
+ }
278
+
279
+ this.set('title', `Perfil de ${user.name}`);
280
+ this.set('user', user);
281
+
282
+ this.render(res, 'users/profile');
283
+ }
284
+ }
285
+ ```
286
+
287
+ ### Ejemplo de Uso de Helpers y Filtros
288
+ ```javascript
289
+ class ProductController extends ControllerBase {
290
+ constructor(options = {}) {
291
+ super(options);
292
+
293
+ // Registrar helpers personalizados para este controlador
294
+ this.getViewEngine().addHelper('calculateDiscount', (price, discountPercent) => {
295
+ return price - (price * discountPercent / 100);
296
+ });
297
+
298
+ this.getViewEngine().addFilter('currency', (value, symbol = '$') => {
299
+ return `${symbol}${Number(value).toFixed(2)}`;
300
+ });
301
+ }
302
+
303
+ products(req, res) {
304
+ const products = [
305
+ { id: 1, name: 'Producto A', price: 100, discount: 10 },
306
+ { id: 2, name: 'Producto B', price: 200, discount: 15 }
307
+ ];
308
+
309
+ this.set('title', 'Catálogo de Productos');
310
+ this.set('products', products);
311
+
312
+ this.render(res, 'products/catalog');
313
+ }
314
+ }
315
+ ```
316
+
317
+ ### Vista con Helpers y Filtros (products/catalog.html)
318
+ ```html
319
+ <h1>{{title}}</h1>
320
+
321
+ {{if products}}
322
+ <div class="product-grid">
323
+ {{foreach:products}}
324
+ <div class="product-card">
325
+ <h3>{{item.name}}</h3>
326
+ <p>Precio original: {{item.price|currency}}</p>
327
+ <p>Descuento: {{item.discount}}%</p>
328
+ <p>Precio con descuento: {{calculateDiscount(item.price, item.discount)|currency}}</p>
329
+ </div>
330
+ {{endforeach}}
331
+ </div>
332
+ {{else}}
333
+ <p>No hay productos disponibles.</p>
334
+ {{endif}}
335
+ ```
336
+
337
+ ### Vista de Lista de Usuarios (users/list.html)
338
+ ```html
339
+ <h1>{{title}}</h1>
340
+
341
+ {{if users}}
342
+ <table>
343
+ <thead>
344
+ <tr>
345
+ <th>ID</th>
346
+ <th>Nombre</th>
347
+ <th>Email</th>
348
+ <th>Estado</th>
349
+ <th>Acciones</th>
350
+ </tr>
351
+ </thead>
352
+ <tbody>
353
+ {{foreach:users}}
354
+ <tr>
355
+ <td>{{item.id}}</td>
356
+ <td>{{item.name}}</td>
357
+ <td>{{item.email}}</td>
358
+ <td>
359
+ {{if item.active}}
360
+ <span class="active">Activo</span>
361
+ {{else}}
362
+ <span class="inactive">Inactivo</span>
363
+ {{endif}}
364
+ </td>
365
+ <td><a href="/profile?id={{item.id}}">Ver Perfil</a></td>
366
+ </tr>
367
+ {{endforeach}}
368
+ </tbody>
369
+ </table>
370
+ {{else}}
371
+ <p>No hay usuarios registrados.</p>
372
+ {{endif}}
373
+
374
+ <a href="/">Volver al inicio</a>
375
+ ```
376
+
377
+ ## Mejores Prácticas
378
+
379
+ 1. **Organización de Archivos**:
380
+ - Colocar vistas en `./views/nombre_modulo/nombre_vista.html`
381
+ - Nombrar controladores con sufijo `Controller`
382
+ - Usar convención de nombres en minúsculas con guiones bajos
383
+
384
+ 2. **Seguridad**:
385
+ - Siempre validar entradas de usuario
386
+ - Usar el filtro `|escape` para mostrar datos de usuario
387
+ - Validar IDs y parámetros antes de usarlos
388
+
389
+ 3. **Rendimiento**:
390
+ - Habilitar cache de vistas en producción
391
+ - Minimizar la lógica en vistas
392
+ - Usar datos eficientes en bucles
393
+
394
+ 4. **Mantenibilidad**:
395
+ - Separar lógica compleja en métodos del controlador
396
+ - Usar vistas parciales para componentes repetitivos
397
+ - Documentar controladores y vistas según sea necesario
@@ -0,0 +1,113 @@
1
+ # Implementación Completa: API SDK Framework v2.0 con Tokens en MariaDB
2
+
3
+ Visita nuestra página web: https://jerk.page.gd/
4
+ Repositorio oficial: https://gitlab.com/bytedogssyndicate1/jerk/
5
+
6
+ ## Resumen Ejecutivo
7
+
8
+ Hemos implementado exitosamente una solución completa de gestión de tokens con MariaDB para el API SDK Framework v2.0, demostrando:
9
+
10
+ ✅ **Conexión funcional a MariaDB**
11
+ ✅ **Almacenamiento seguro de tokens JWT**
12
+ ✅ **Validación en tiempo real contra base de datos**
13
+ ✅ **Revocación de tokens**
14
+ ✅ **Soporte para tokens de acceso y refresh**
15
+ ✅ **Gestión de expiración automática**
16
+
17
+ ## Componentes Implementados
18
+
19
+ ### 1. Adaptador de Tokens para MariaDB (`lib/utils/mariadbTokenAdapter.js`)
20
+ - Conexión robusta a MariaDB usando pooling
21
+ - Almacenamiento seguro de tokens con índices
22
+ - Validación en tiempo real
23
+ - Revocación de tokens
24
+ - Gestión de expiración
25
+
26
+ ### 2. Base de Datos
27
+ - Base de datos `token_api_db` creada
28
+ - Tabla `tokens` con estructura optimizada:
29
+ - `id`: Identificador único
30
+ - `token`: Token JWT almacenado
31
+ - `user_id`: ID del usuario propietario
32
+ - `token_type`: Tipo (access/refresh)
33
+ - `expires_at`: Fecha de expiración
34
+ - `revoked`: Indicador de revocación
35
+
36
+ ### 3. Funcionalidades Clave
37
+
38
+ #### Almacenamiento Seguro
39
+ ```sql
40
+ -- Tokens almacenados encriptados en base de datos
41
+ INSERT INTO tokens (token, user_id, token_type, expires_at) VALUES (?, ?, ?, ?);
42
+ ```
43
+
44
+ #### Validación en Tiempo Real
45
+ ```javascript
46
+ // Validación instantánea contra la base de datos
47
+ const tokenRecord = await tokenAdapter.validateToken(token);
48
+ ```
49
+
50
+ #### Revocación Inmediata
51
+ ```javascript
52
+ // Revocación que se refleja inmediatamente
53
+ await tokenAdapter.revokeToken(token);
54
+ ```
55
+
56
+ #### Expiración Automática
57
+ ```sql
58
+ -- Consultas que consideran tokens expirados
59
+ WHERE expires_at > NOW() AND revoked = FALSE
60
+ ```
61
+
62
+ ## Pruebas Realizadas
63
+
64
+ ### 1. Prueba de Conexión
65
+ - ✅ Conexión estable a MariaDB
66
+ - ✅ Creación automática de base de datos y tablas
67
+
68
+ ### 2. Prueba de Almacenamiento
69
+ - ✅ Almacenamiento de tokens JWT
70
+ - ✅ Diferenciación entre access y refresh tokens
71
+
72
+ ### 3. Prueba de Validación
73
+ - ✅ Validación correcta de tokens válidos
74
+ - ✅ Rechazo de tokens inexistentes
75
+
76
+ ### 4. Prueba de Expiración
77
+ - ✅ Detección de tokens expirados
78
+ - ✅ No validez de tokens fuera de tiempo
79
+
80
+ ### 5. Prueba de Revocación
81
+ - ✅ Revocación efectiva de tokens
82
+ - ✅ No validez posterior a la revocación
83
+
84
+ ## Beneficios de la Solución
85
+
86
+ ### Seguridad
87
+ - Tokens almacenados en base de datos en lugar de memoria
88
+ - Posibilidad de revocación inmediata
89
+ - Validación en tiempo real
90
+
91
+ ### Escalabilidad
92
+ - Uso de connection pooling
93
+ - Índices para búsquedas rápidas
94
+ - Gestión eficiente de recursos
95
+
96
+ ### Control
97
+ - Visibilidad completa de tokens activos
98
+ - Auditoría de tokens por usuario
99
+ - Gestión centralizada
100
+
101
+ ## Uso en Aplicaciones Reales
102
+
103
+ La implementación permite:
104
+
105
+ 1. **Login seguro** con generación de tokens almacenados en MariaDB
106
+ 2. **Acceso protegido** con validación contra base de datos
107
+ 3. **Renovación automática** de tokens expirados
108
+ 4. **Revocación inmediata** de tokens comprometidos
109
+ 5. **Auditoría completa** de tokens por usuario
110
+
111
+ ## Conclusión
112
+
113
+ La implementación de tokens en MariaDB para el API SDK Framework v2.0 está **completa, funcional y lista para producción**, ofreciendo un nivel superior de seguridad y control sobre la autenticación basada en tokens.