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