jerkjs 2.1.7 → 2.2.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.
- package/CHANGELOG.md +30 -0
- package/README.md +201 -4
- package/index.js +29 -4
- package/lib/core/server.js +328 -27
- package/lib/loader/routeLoader.js +148 -117
- package/lib/mvc/GenericAdapter.js +136 -0
- package/lib/mvc/MariaDBAdapter.js +315 -0
- package/lib/mvc/MemoryAdapter.js +269 -0
- package/lib/mvc/ModelControllerExample.js +285 -0
- package/lib/mvc/controllerBase.js +60 -0
- package/lib/mvc/modelBase.js +383 -0
- package/lib/mvc/modelManager.js +284 -0
- package/lib/mvc/userModel.js +265 -0
- package/lib/mvc/viewEngine.js +32 -1
- package/lib/utils/mimeType.js +62 -0
- package/package.json +5 -3
- package/BUG_REPORTE_COMPRESION.txt +0 -72
- package/JERK_FRAMEWORK_DIAGRAM.txt +0 -492
- package/JERK_FRAMEWORK_DIAGRAM_MERMAID.mmd +0 -124
- package/JERK_FRAMEWORK_DOCUMENTATION.md +0 -527
- package/LICENSE +0 -201
- package/README_EN.md +0 -230
- package/README_PT.md +0 -230
- package/docs/ARQUITECTURA_ROUTES.md +0 -140
- package/docs/EXTENSION_MANUAL.md +0 -955
- package/docs/FIREWALL_MANUAL.md +0 -416
- package/docs/HOOK-2.0.md +0 -512
- package/docs/HOOKS_REFERENCE_IMPROVED.md +0 -596
- package/docs/MANUAL_API_SDK.md +0 -536
- package/docs/MARIADB_TOKENS_IMPLEMENTATION.md +0 -110
- package/docs/MIDDLEWARE_MANUAL.md +0 -518
- package/docs/OAUTH2_GOOGLE_MANUAL.md +0 -405
- package/docs/ROUTING_WITHOUT_JSON_GUIDE.md +0 -454
- package/docs/frontend-and-sessions.md +0 -353
- package/docs/guia_inicio_rapido_jerkjs.md +0 -113
- package/examples/examples.arj +0 -0
- package/standard/CompressionTestController.js +0 -56
- package/standard/HealthController.js +0 -16
- package/standard/HomeController.js +0 -12
- package/standard/ProductController.js +0 -18
- package/standard/README.md +0 -47
- package/standard/UserController.js +0 -23
- package/standard/package.json +0 -22
- package/standard/routes.json +0 -65
- package/standard/server.js +0 -140
- package/standardA/controllers/AuthController.js +0 -82
- package/standardA/controllers/HomeController.js +0 -19
- package/standardA/controllers/UserController.js +0 -41
- package/standardA/server.js +0 -311
- package/standardA/views/auth/dashboard.html +0 -51
- package/standardA/views/auth/login.html +0 -47
- package/standardA/views/index.html +0 -32
- package/standardA/views/users/detail.html +0 -28
- package/standardA/views/users/list.html +0 -36
package/docs/MANUAL_API_SDK.md
DELETED
|
@@ -1,536 +0,0 @@
|
|
|
1
|
-
# Manual para Construir APIs con el Framework API SDK
|
|
2
|
-
|
|
3
|
-
## Índice
|
|
4
|
-
1. [Introducción](#introducción)
|
|
5
|
-
2. [Instalación y Configuración](#instalación-y-configuración)
|
|
6
|
-
3. [Conceptos Fundamentales](#conceptos-fundamentales)
|
|
7
|
-
4. [Creación de tu Primera API](#creación-de-tu-primera-api)
|
|
8
|
-
5. [Enrutamiento Avanzado](#enrutamiento-avanzado)
|
|
9
|
-
6. [Middleware y Seguridad](#middleware-y-seguridad)
|
|
10
|
-
7. [Gestión de Tokens](#gestión-de-tokens)
|
|
11
|
-
8. [Documentación Automática](#documentación-automática)
|
|
12
|
-
9. [Carga de Controladores y Rutas](#carga-de-controladores-y-rutas)
|
|
13
|
-
10. [Mejores Prácticas](#mejores-prácticas)
|
|
14
|
-
|
|
15
|
-
## Introducción
|
|
16
|
-
|
|
17
|
-
El Framework API SDK es una solución completa para construir APIs RESTful con características avanzadas de seguridad, rendimiento y mantenibilidad. Proporciona una arquitectura modular que facilita la creación de servicios web robustos y escalables.
|
|
18
|
-
|
|
19
|
-
## Instalación y Configuración
|
|
20
|
-
|
|
21
|
-
Para comenzar a usar el framework, primero debes instalarlo como dependencia:
|
|
22
|
-
|
|
23
|
-
```javascript
|
|
24
|
-
const {
|
|
25
|
-
APIServer,
|
|
26
|
-
Router,
|
|
27
|
-
Authenticator,
|
|
28
|
-
Validator,
|
|
29
|
-
Cors,
|
|
30
|
-
RateLimiter,
|
|
31
|
-
Logger,
|
|
32
|
-
TokenManager,
|
|
33
|
-
OpenApiGenerator
|
|
34
|
-
} = require('@apisdkjs');
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Conceptos Fundamentales
|
|
38
|
-
|
|
39
|
-
### Componentes Principales
|
|
40
|
-
|
|
41
|
-
- **APIServer**: El servidor HTTP central que maneja todas las solicitudes
|
|
42
|
-
- **Router**: Sistema de enrutamiento para definir endpoints
|
|
43
|
-
- **Authenticator**: Sistema de autenticación con múltiples estrategias
|
|
44
|
-
- **Validator**: Validación de datos de entrada
|
|
45
|
-
- **Middleware**: Componentes que procesan solicitudes/responses
|
|
46
|
-
|
|
47
|
-
### Flujo de Trabajo Básico
|
|
48
|
-
|
|
49
|
-
1. Crear una instancia del servidor
|
|
50
|
-
2. Definir rutas y handlers
|
|
51
|
-
3. Aplicar middleware según sea necesario
|
|
52
|
-
4. Iniciar el servidor
|
|
53
|
-
|
|
54
|
-
## Creación de tu Primera API
|
|
55
|
-
|
|
56
|
-
### Servidor Básico
|
|
57
|
-
|
|
58
|
-
```javascript
|
|
59
|
-
const { APIServer, Router, Logger } = require('@apisdkjs');
|
|
60
|
-
|
|
61
|
-
// Crear instancia del servidor
|
|
62
|
-
const server = new APIServer({
|
|
63
|
-
port: 3000,
|
|
64
|
-
host: 'localhost'
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// Crear instancia del router
|
|
68
|
-
const router = new Router();
|
|
69
|
-
|
|
70
|
-
// Definir rutas
|
|
71
|
-
router.get('/', (req, res) => {
|
|
72
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
73
|
-
res.end(JSON.stringify({ message: '¡Hola Mundo!' }));
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
router.get('/users/:id', (req, res) => {
|
|
77
|
-
const userId = req.params.id;
|
|
78
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
79
|
-
res.end(JSON.stringify({ id: userId, name: 'Usuario Ejemplo' }));
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// Agregar rutas al servidor
|
|
83
|
-
for (const route of router.getRoutes()) {
|
|
84
|
-
server.addRoute(route.method, route.path, route.handler);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Iniciar el servidor
|
|
88
|
-
server.start();
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
### Controladores
|
|
92
|
-
|
|
93
|
-
Los controladores son funciones que manejan la lógica de negocio para cada endpoint:
|
|
94
|
-
|
|
95
|
-
```javascript
|
|
96
|
-
// controllers/userController.js
|
|
97
|
-
const userController = {
|
|
98
|
-
// GET /users
|
|
99
|
-
getAllUsers: (req, res) => {
|
|
100
|
-
const users = [
|
|
101
|
-
{ id: 1, name: 'Juan', email: 'juan@example.com' },
|
|
102
|
-
{ id: 2, name: 'María', email: 'maria@example.com' }
|
|
103
|
-
];
|
|
104
|
-
|
|
105
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
106
|
-
res.end(JSON.stringify(users));
|
|
107
|
-
},
|
|
108
|
-
|
|
109
|
-
// GET /users/:id
|
|
110
|
-
getUserById: (req, res) => {
|
|
111
|
-
const userId = parseInt(req.params.id);
|
|
112
|
-
const user = { id: userId, name: 'Usuario Ejemplo', email: 'user@example.com' };
|
|
113
|
-
|
|
114
|
-
if (!user) {
|
|
115
|
-
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
116
|
-
res.end(JSON.stringify({ error: 'Usuario no encontrado' }));
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
121
|
-
res.end(JSON.stringify(user));
|
|
122
|
-
},
|
|
123
|
-
|
|
124
|
-
// POST /users
|
|
125
|
-
createUser: (req, res) => {
|
|
126
|
-
const userData = req.body;
|
|
127
|
-
const newUser = {
|
|
128
|
-
id: Date.now(),
|
|
129
|
-
...userData
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
res.writeHead(201, { 'Content-Type': 'application/json' });
|
|
133
|
-
res.end(JSON.stringify(newUser));
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
module.exports = userController;
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Enrutamiento Avanzado
|
|
141
|
-
|
|
142
|
-
### Rutas Parametrizadas
|
|
143
|
-
|
|
144
|
-
El framework soporta rutas con parámetros:
|
|
145
|
-
|
|
146
|
-
```javascript
|
|
147
|
-
const router = new Router();
|
|
148
|
-
|
|
149
|
-
// Ruta con un parámetro
|
|
150
|
-
router.get('/users/:id', (req, res) => {
|
|
151
|
-
const userId = req.params.id;
|
|
152
|
-
// Procesar solicitud
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
// Ruta con múltiples parámetros
|
|
156
|
-
router.get('/users/:userId/posts/:postId', (req, res) => {
|
|
157
|
-
const { userId, postId } = req.params;
|
|
158
|
-
// Procesar solicitud
|
|
159
|
-
});
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### Rutas Anidadas
|
|
163
|
-
|
|
164
|
-
Puedes combinar routers para organizar mejor tu API:
|
|
165
|
-
|
|
166
|
-
```javascript
|
|
167
|
-
const mainRouter = new Router();
|
|
168
|
-
const userRouter = new Router({ prefix: '/users' });
|
|
169
|
-
const postRouter = new Router({ prefix: '/posts' });
|
|
170
|
-
|
|
171
|
-
// Definir rutas para usuarios
|
|
172
|
-
userRouter.get('/', (req, res) => {
|
|
173
|
-
// Obtener todos los usuarios
|
|
174
|
-
});
|
|
175
|
-
userRouter.get('/:id', (req, res) => {
|
|
176
|
-
// Obtener usuario por ID
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// Definir rutas para posts
|
|
180
|
-
postRouter.get('/', (req, res) => {
|
|
181
|
-
// Obtener todos los posts
|
|
182
|
-
});
|
|
183
|
-
postRouter.get('/:id', (req, res) => {
|
|
184
|
-
// Obtener post por ID
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
// Agregar routers anidados al router principal
|
|
188
|
-
mainRouter.addNestedRouter('/api/v1', userRouter);
|
|
189
|
-
mainRouter.addNestedRouter('/api/v1', postRouter);
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
## Middleware y Seguridad
|
|
193
|
-
|
|
194
|
-
### CORS
|
|
195
|
-
|
|
196
|
-
Configura CORS para permitir solicitudes cross-origin:
|
|
197
|
-
|
|
198
|
-
```javascript
|
|
199
|
-
const cors = new Cors({
|
|
200
|
-
origin: ['http://localhost:3000', 'https://myapp.com'],
|
|
201
|
-
methods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
202
|
-
allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key']
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
server.use(cors.middleware());
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
### Rate Limiting
|
|
209
|
-
|
|
210
|
-
Protege tu API contra abusos con limitación de tasa:
|
|
211
|
-
|
|
212
|
-
```javascript
|
|
213
|
-
const rateLimiter = new RateLimiter({
|
|
214
|
-
windowMs: 15 * 60 * 1000, // 15 minutos
|
|
215
|
-
maxRequests: 100 // Límite de 100 solicitudes por ventana
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
// Aplicar a todo el servidor
|
|
219
|
-
server.use(rateLimiter.middleware());
|
|
220
|
-
|
|
221
|
-
// O aplicar a rutas específicas
|
|
222
|
-
router.post('/login', rateLimiter.middleware(), (req, res) => {
|
|
223
|
-
// Lógica de login
|
|
224
|
-
});
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### Autenticación
|
|
228
|
-
|
|
229
|
-
El framework soporta múltiples estrategias de autenticación:
|
|
230
|
-
|
|
231
|
-
```javascript
|
|
232
|
-
const authenticator = new Authenticator();
|
|
233
|
-
|
|
234
|
-
// Estrategia JWT
|
|
235
|
-
const jwtStrategy = authenticator.jwtStrategy('tu_secreto_jwt');
|
|
236
|
-
authenticator.use('jwt', jwtStrategy);
|
|
237
|
-
|
|
238
|
-
// Estrategia API Key
|
|
239
|
-
const apiKeyStrategy = authenticator.apiKeyStrategy('X-API-Key', ['clave1', 'clave2']);
|
|
240
|
-
authenticator.use('apiKey', apiKeyStrategy);
|
|
241
|
-
|
|
242
|
-
// Aplicar autenticación a rutas
|
|
243
|
-
router.get('/protected', authenticator.authenticate('jwt'), (req, res) => {
|
|
244
|
-
// Ruta protegida - req.user contendrá la información del usuario
|
|
245
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
246
|
-
res.end(JSON.stringify({ message: 'Contenido protegido', user: req.user }));
|
|
247
|
-
});
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
### Validación
|
|
251
|
-
|
|
252
|
-
Valida los datos de entrada de tus endpoints:
|
|
253
|
-
|
|
254
|
-
```javascript
|
|
255
|
-
const validator = new Validator();
|
|
256
|
-
|
|
257
|
-
const userValidationSchema = {
|
|
258
|
-
body: {
|
|
259
|
-
name: ['required', 'string', 'minLength:2'],
|
|
260
|
-
email: ['required', 'email'],
|
|
261
|
-
age: ['required', 'number', 'min:18', 'max:120']
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
router.post('/users',
|
|
266
|
-
validator.validate(userValidationSchema),
|
|
267
|
-
(req, res) => {
|
|
268
|
-
// Si llega aquí, la validación pasó
|
|
269
|
-
const userData = req.body;
|
|
270
|
-
// Procesar solicitud
|
|
271
|
-
}
|
|
272
|
-
);
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
## Gestión de Tokens
|
|
276
|
-
|
|
277
|
-
### TokenManager
|
|
278
|
-
|
|
279
|
-
El framework incluye un sistema completo de gestión de tokens:
|
|
280
|
-
|
|
281
|
-
```javascript
|
|
282
|
-
const tokenManager = new TokenManager({
|
|
283
|
-
storage: 'memory' // Opciones: 'memory', 'json', 'database'
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
// Generar un token
|
|
287
|
-
const payload = { userId: 123, role: 'admin' };
|
|
288
|
-
const token = tokenManager.generateToken(payload, 'tu_secreto', '1h');
|
|
289
|
-
|
|
290
|
-
// Validar un token
|
|
291
|
-
const decoded = tokenManager.validateToken(token, 'tu_secreto');
|
|
292
|
-
if (decoded) {
|
|
293
|
-
console.log('Token válido:', decoded);
|
|
294
|
-
} else {
|
|
295
|
-
console.log('Token inválido');
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Generar par de tokens (access y refresh)
|
|
299
|
-
const tokenPair = tokenManager.generateTokenPair(
|
|
300
|
-
{ userId: 123, role: 'admin' },
|
|
301
|
-
{
|
|
302
|
-
jwtSecret: 'access_secret',
|
|
303
|
-
refreshSecret: 'refresh_secret',
|
|
304
|
-
accessExpiresIn: '15m',
|
|
305
|
-
refreshExpiresIn: '7d'
|
|
306
|
-
}
|
|
307
|
-
);
|
|
308
|
-
```
|
|
309
|
-
|
|
310
|
-
### Adaptadores de Base de Datos
|
|
311
|
-
|
|
312
|
-
Para almacenamiento persistente de tokens, puedes usar adaptadores:
|
|
313
|
-
|
|
314
|
-
```javascript
|
|
315
|
-
const MariaDBTokenAdapter = require('@apisdkjs/lib/utils/mariadbTokenAdapter');
|
|
316
|
-
const SQLiteTokenAdapter = require('@apisdkjs/lib/utils/sqliteTokenAdapter');
|
|
317
|
-
|
|
318
|
-
// Usar MariaDB
|
|
319
|
-
const dbAdapter = new MariaDBTokenAdapter({
|
|
320
|
-
host: 'localhost',
|
|
321
|
-
user: 'usuario',
|
|
322
|
-
password: 'contraseña',
|
|
323
|
-
database: 'mi_bd'
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
await dbAdapter.initialize();
|
|
327
|
-
|
|
328
|
-
// Guardar token en base de datos
|
|
329
|
-
await dbAdapter.saveToken(token, { userId: 123 }, 'access', new Date(Date.now() + 3600000));
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
## Documentación Automática
|
|
333
|
-
|
|
334
|
-
### OpenAPI Generator
|
|
335
|
-
|
|
336
|
-
Genera documentación OpenAPI automáticamente:
|
|
337
|
-
|
|
338
|
-
```javascript
|
|
339
|
-
const openApiGenerator = new OpenApiGenerator({
|
|
340
|
-
title: 'Mi API',
|
|
341
|
-
description: 'Documentación para Mi API',
|
|
342
|
-
version: '1.0.0'
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
// Agregar rutas a la documentación
|
|
346
|
-
openApiGenerator.addRoute({
|
|
347
|
-
path: '/users',
|
|
348
|
-
method: 'GET',
|
|
349
|
-
config: {
|
|
350
|
-
summary: 'Obtener todos los usuarios',
|
|
351
|
-
description: 'Devuelve una lista de todos los usuarios registrados',
|
|
352
|
-
responses: {
|
|
353
|
-
'200': {
|
|
354
|
-
description: 'Lista de usuarios',
|
|
355
|
-
content: {
|
|
356
|
-
'application/json': {
|
|
357
|
-
schema: {
|
|
358
|
-
type: 'array',
|
|
359
|
-
items: {
|
|
360
|
-
type: 'object',
|
|
361
|
-
properties: {
|
|
362
|
-
id: { type: 'integer' },
|
|
363
|
-
name: { type: 'string' },
|
|
364
|
-
email: { type: 'string' }
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
// Agregar ruta de documentación al servidor
|
|
376
|
-
openApiGenerator.addDocumentationRoute(server);
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
## Carga de Controladores y Rutas
|
|
380
|
-
|
|
381
|
-
### Carga Dinámica de Controladores
|
|
382
|
-
|
|
383
|
-
Carga controladores desde archivos:
|
|
384
|
-
|
|
385
|
-
```javascript
|
|
386
|
-
const { ControllerLoader } = require('@apisdkjs');
|
|
387
|
-
|
|
388
|
-
const controllerLoader = new ControllerLoader();
|
|
389
|
-
|
|
390
|
-
// Cargar un controlador específico
|
|
391
|
-
const userController = controllerLoader.loadController('./controllers/userController.js');
|
|
392
|
-
|
|
393
|
-
// Cargar todos los controladores de un directorio
|
|
394
|
-
const controllers = controllerLoader.loadControllersFromDirectory('./controllers');
|
|
395
|
-
|
|
396
|
-
// Obtener un handler específico de un controlador
|
|
397
|
-
const getUserHandler = controllerLoader.getHandlerFromController(
|
|
398
|
-
'./controllers/userController.js',
|
|
399
|
-
'getUserById'
|
|
400
|
-
);
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
### Carga de Rutas desde JSON
|
|
404
|
-
|
|
405
|
-
Define rutas en archivos JSON y cárgalas dinámicamente:
|
|
406
|
-
|
|
407
|
-
```javascript
|
|
408
|
-
// routes.json
|
|
409
|
-
[
|
|
410
|
-
{
|
|
411
|
-
"path": "/users",
|
|
412
|
-
"method": "GET",
|
|
413
|
-
"controller": "./controllers/userController.js",
|
|
414
|
-
"handler": "getAllUsers",
|
|
415
|
-
"auth": "jwt"
|
|
416
|
-
},
|
|
417
|
-
{
|
|
418
|
-
"path": "/users/:id",
|
|
419
|
-
"method": "GET",
|
|
420
|
-
"controller": "./controllers/userController.js",
|
|
421
|
-
"handler": "getUserById",
|
|
422
|
-
"auth": "jwt"
|
|
423
|
-
},
|
|
424
|
-
{
|
|
425
|
-
"path": "/users",
|
|
426
|
-
"method": "POST",
|
|
427
|
-
"controller": "./controllers/userController.js",
|
|
428
|
-
"handler": "createUser",
|
|
429
|
-
"auth": "apiKey"
|
|
430
|
-
}
|
|
431
|
-
]
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
```javascript
|
|
435
|
-
const { RouteLoader } = require('@apisdkjs');
|
|
436
|
-
|
|
437
|
-
const routeLoader = new RouteLoader();
|
|
438
|
-
const server = new APIServer({ port: 3000 });
|
|
439
|
-
|
|
440
|
-
// Cargar rutas desde archivo JSON
|
|
441
|
-
await routeLoader.loadRoutes(server, './routes.json');
|
|
442
|
-
```
|
|
443
|
-
|
|
444
|
-
## Mejores Prácticas
|
|
445
|
-
|
|
446
|
-
### Organización del Código
|
|
447
|
-
|
|
448
|
-
```
|
|
449
|
-
proyecto/
|
|
450
|
-
├── controllers/
|
|
451
|
-
│ ├── userController.js
|
|
452
|
-
│ └── postController.js
|
|
453
|
-
├── middleware/
|
|
454
|
-
│ └── customMiddleware.js
|
|
455
|
-
├── routes/
|
|
456
|
-
│ └── routes.json
|
|
457
|
-
├── utils/
|
|
458
|
-
│ └── helpers.js
|
|
459
|
-
├── config/
|
|
460
|
-
│ └── config.json
|
|
461
|
-
└── app.js
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
### Manejo de Errores
|
|
465
|
-
|
|
466
|
-
Implementa un middleware de manejo de errores global:
|
|
467
|
-
|
|
468
|
-
```javascript
|
|
469
|
-
const errorHandler = (err, req, res, next) => {
|
|
470
|
-
console.error('Error:', err);
|
|
471
|
-
|
|
472
|
-
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
473
|
-
res.end(JSON.stringify({
|
|
474
|
-
error: 'Error interno del servidor',
|
|
475
|
-
message: process.env.NODE_ENV === 'development' ? err.message : undefined
|
|
476
|
-
}));
|
|
477
|
-
};
|
|
478
|
-
|
|
479
|
-
server.use(errorHandler);
|
|
480
|
-
```
|
|
481
|
-
|
|
482
|
-
### Logging
|
|
483
|
-
|
|
484
|
-
Utiliza el sistema de logging del framework:
|
|
485
|
-
|
|
486
|
-
```javascript
|
|
487
|
-
const logger = new Logger({ level: 'info' });
|
|
488
|
-
|
|
489
|
-
// En tus handlers
|
|
490
|
-
router.get('/users/:id', (req, res) => {
|
|
491
|
-
logger.info(`Solicitud recibida para usuario ID: ${req.params.id}`);
|
|
492
|
-
|
|
493
|
-
// Lógica del handler
|
|
494
|
-
logger.info(`Usuario ${req.params.id} recuperado exitosamente`);
|
|
495
|
-
});
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
### Configuración
|
|
499
|
-
|
|
500
|
-
Usa el ConfigParser para manejar configuraciones:
|
|
501
|
-
|
|
502
|
-
```javascript
|
|
503
|
-
const { ConfigParser } = require('@apisdkjs');
|
|
504
|
-
|
|
505
|
-
const configParser = new ConfigParser();
|
|
506
|
-
|
|
507
|
-
// Cargar desde archivo
|
|
508
|
-
configParser.loadFromFile('./config.json');
|
|
509
|
-
|
|
510
|
-
// Cargar desde variables de entorno
|
|
511
|
-
configParser.loadFromEnv(process.env, {
|
|
512
|
-
'dbHost': 'DB_HOST',
|
|
513
|
-
'dbPort': 'DB_PORT',
|
|
514
|
-
'jwtSecret': 'JWT_SECRET'
|
|
515
|
-
});
|
|
516
|
-
|
|
517
|
-
// Obtener valores de configuración
|
|
518
|
-
const dbHost = configParser.get('dbHost', 'localhost');
|
|
519
|
-
const jwtSecret = configParser.get('jwtSecret');
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
### Seguridad Adicional
|
|
523
|
-
|
|
524
|
-
Considera implementar auditoría de seguridad:
|
|
525
|
-
|
|
526
|
-
```javascript
|
|
527
|
-
const auditLogger = new AuditLogger({
|
|
528
|
-
logFile: './security-audit.log',
|
|
529
|
-
events: ['request', 'response', 'error'],
|
|
530
|
-
includeHeaders: true
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
server.use(auditLogger.middleware());
|
|
534
|
-
```
|
|
535
|
-
|
|
536
|
-
Este manual proporciona una guía completa para construir APIs robustas y seguras con el Framework API SDK. Recuerda siempre seguir las mejores prácticas de seguridad y mantener tu código actualizado.
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# Implementación Completa: API SDK Framework v2.0 con Tokens en MariaDB
|
|
2
|
-
|
|
3
|
-
## Resumen Ejecutivo
|
|
4
|
-
|
|
5
|
-
Hemos implementado exitosamente una solución completa de gestión de tokens con MariaDB para el API SDK Framework v2.0, demostrando:
|
|
6
|
-
|
|
7
|
-
✅ **Conexión funcional a MariaDB**
|
|
8
|
-
✅ **Almacenamiento seguro de tokens JWT**
|
|
9
|
-
✅ **Validación en tiempo real contra base de datos**
|
|
10
|
-
✅ **Revocación de tokens**
|
|
11
|
-
✅ **Soporte para tokens de acceso y refresh**
|
|
12
|
-
✅ **Gestión de expiración automática**
|
|
13
|
-
|
|
14
|
-
## Componentes Implementados
|
|
15
|
-
|
|
16
|
-
### 1. Adaptador de Tokens para MariaDB (`lib/utils/mariadbTokenAdapter.js`)
|
|
17
|
-
- Conexión robusta a MariaDB usando pooling
|
|
18
|
-
- Almacenamiento seguro de tokens con índices
|
|
19
|
-
- Validación en tiempo real
|
|
20
|
-
- Revocación de tokens
|
|
21
|
-
- Gestión de expiración
|
|
22
|
-
|
|
23
|
-
### 2. Base de Datos
|
|
24
|
-
- Base de datos `token_api_db` creada
|
|
25
|
-
- Tabla `tokens` con estructura optimizada:
|
|
26
|
-
- `id`: Identificador único
|
|
27
|
-
- `token`: Token JWT almacenado
|
|
28
|
-
- `user_id`: ID del usuario propietario
|
|
29
|
-
- `token_type`: Tipo (access/refresh)
|
|
30
|
-
- `expires_at`: Fecha de expiración
|
|
31
|
-
- `revoked`: Indicador de revocación
|
|
32
|
-
|
|
33
|
-
### 3. Funcionalidades Clave
|
|
34
|
-
|
|
35
|
-
#### Almacenamiento Seguro
|
|
36
|
-
```sql
|
|
37
|
-
-- Tokens almacenados encriptados en base de datos
|
|
38
|
-
INSERT INTO tokens (token, user_id, token_type, expires_at) VALUES (?, ?, ?, ?);
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
#### Validación en Tiempo Real
|
|
42
|
-
```javascript
|
|
43
|
-
// Validación instantánea contra la base de datos
|
|
44
|
-
const tokenRecord = await tokenAdapter.validateToken(token);
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
#### Revocación Inmediata
|
|
48
|
-
```javascript
|
|
49
|
-
// Revocación que se refleja inmediatamente
|
|
50
|
-
await tokenAdapter.revokeToken(token);
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
#### Expiración Automática
|
|
54
|
-
```sql
|
|
55
|
-
-- Consultas que consideran tokens expirados
|
|
56
|
-
WHERE expires_at > NOW() AND revoked = FALSE
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Pruebas Realizadas
|
|
60
|
-
|
|
61
|
-
### 1. Prueba de Conexión
|
|
62
|
-
- ✅ Conexión estable a MariaDB
|
|
63
|
-
- ✅ Creación automática de base de datos y tablas
|
|
64
|
-
|
|
65
|
-
### 2. Prueba de Almacenamiento
|
|
66
|
-
- ✅ Almacenamiento de tokens JWT
|
|
67
|
-
- ✅ Diferenciación entre access y refresh tokens
|
|
68
|
-
|
|
69
|
-
### 3. Prueba de Validación
|
|
70
|
-
- ✅ Validación correcta de tokens válidos
|
|
71
|
-
- ✅ Rechazo de tokens inexistentes
|
|
72
|
-
|
|
73
|
-
### 4. Prueba de Expiración
|
|
74
|
-
- ✅ Detección de tokens expirados
|
|
75
|
-
- ✅ No validez de tokens fuera de tiempo
|
|
76
|
-
|
|
77
|
-
### 5. Prueba de Revocación
|
|
78
|
-
- ✅ Revocación efectiva de tokens
|
|
79
|
-
- ✅ No validez posterior a la revocación
|
|
80
|
-
|
|
81
|
-
## Beneficios de la Solución
|
|
82
|
-
|
|
83
|
-
### Seguridad
|
|
84
|
-
- Tokens almacenados en base de datos en lugar de memoria
|
|
85
|
-
- Posibilidad de revocación inmediata
|
|
86
|
-
- Validación en tiempo real
|
|
87
|
-
|
|
88
|
-
### Escalabilidad
|
|
89
|
-
- Uso de connection pooling
|
|
90
|
-
- Índices para búsquedas rápidas
|
|
91
|
-
- Gestión eficiente de recursos
|
|
92
|
-
|
|
93
|
-
### Control
|
|
94
|
-
- Visibilidad completa de tokens activos
|
|
95
|
-
- Auditoría de tokens por usuario
|
|
96
|
-
- Gestión centralizada
|
|
97
|
-
|
|
98
|
-
## Uso en Aplicaciones Reales
|
|
99
|
-
|
|
100
|
-
La implementación permite:
|
|
101
|
-
|
|
102
|
-
1. **Login seguro** con generación de tokens almacenados en MariaDB
|
|
103
|
-
2. **Acceso protegido** con validación contra base de datos
|
|
104
|
-
3. **Renovación automática** de tokens expirados
|
|
105
|
-
4. **Revocación inmediata** de tokens comprometidos
|
|
106
|
-
5. **Auditoría completa** de tokens por usuario
|
|
107
|
-
|
|
108
|
-
## Conclusión
|
|
109
|
-
|
|
110
|
-
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.
|