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,296 @@
1
+ /**
2
+ * Ejemplo de API con funcionalidades OpenAPI (v2.1.0)
3
+ * Demostrando la generación automática de documentación OpenAPI
4
+ */
5
+
6
+ const {
7
+ APIServer,
8
+ Authenticator,
9
+ Logger,
10
+ OpenApiGenerator
11
+ } = require('../../index.js');
12
+
13
+ async function startServer() {
14
+ // Crear instancia del servidor
15
+ const server = new APIServer({
16
+ port: 8096,
17
+ host: 'localhost'
18
+ });
19
+
20
+ // Crear instancia del logger
21
+ const logger = new Logger({ level: 'info' });
22
+
23
+ // Crear instancia del autenticador
24
+ const authenticator = new Authenticator({ logger });
25
+
26
+ // Registrar estrategia de autenticación JWT
27
+ authenticator.use('jwt-openapi', authenticator.jwtStrategy('super-secret-key-for-openapi-example'));
28
+
29
+ try {
30
+ // Crear instancia del generador de OpenAPI
31
+ const openApiGenerator = new OpenApiGenerator({
32
+ title: 'API de Ejemplo con OpenAPI',
33
+ description: 'API que demuestra la funcionalidad OpenAPI del Framework API SDK',
34
+ version: '2.1.0',
35
+ servers: [
36
+ { url: 'http://localhost:8096', description: 'Servidor de desarrollo' }
37
+ ]
38
+ });
39
+
40
+ // Definir esquemas para la documentación
41
+ openApiGenerator.addSchema('User', {
42
+ type: 'object',
43
+ properties: {
44
+ id: { type: 'integer', example: 1 },
45
+ name: { type: 'string', example: 'John Doe' },
46
+ email: { type: 'string', example: 'john@example.com' },
47
+ role: { type: 'string', example: 'user' }
48
+ },
49
+ required: ['id', 'name', 'email']
50
+ });
51
+
52
+ openApiGenerator.addSchema('Product', {
53
+ type: 'object',
54
+ properties: {
55
+ id: { type: 'integer', example: 1 },
56
+ name: { type: 'string', example: 'Laptop' },
57
+ price: { type: 'number', example: 999.99 },
58
+ category: { type: 'string', example: 'Electronics' }
59
+ },
60
+ required: ['id', 'name', 'price']
61
+ });
62
+
63
+ openApiGenerator.addSchema('LoginRequest', {
64
+ type: 'object',
65
+ properties: {
66
+ username: { type: 'string', example: 'admin' },
67
+ password: { type: 'string', example: 'password' }
68
+ },
69
+ required: ['username', 'password']
70
+ });
71
+
72
+ openApiGenerator.addSchema('LoginResponse', {
73
+ type: 'object',
74
+ properties: {
75
+ message: { type: 'string', example: 'Inicio de sesión exitoso' },
76
+ token: { type: 'string', example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' },
77
+ user: { $ref: '#/components/schemas/User' }
78
+ }
79
+ });
80
+
81
+ // Agregar rutas a la documentación OpenAPI
82
+ openApiGenerator.addRoute({
83
+ path: '/',
84
+ method: 'GET',
85
+ config: {
86
+ summary: 'Página de inicio',
87
+ description: 'Devuelve información básica sobre la API y sus funcionalidades OpenAPI',
88
+ responses: {
89
+ '200': {
90
+ description: 'Información de la API',
91
+ content: {
92
+ 'application/json': {
93
+ schema: {
94
+ type: 'object',
95
+ properties: {
96
+ message: { type: 'string' },
97
+ features: { type: 'array', items: { type: 'string' } },
98
+ timestamp: { type: 'string', format: 'date-time' }
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+ });
107
+
108
+ openApiGenerator.addRoute({
109
+ path: '/login',
110
+ method: 'POST',
111
+ config: {
112
+ summary: 'Iniciar sesión',
113
+ description: 'Autenticación de usuario y obtención de token JWT',
114
+ requestBody: {
115
+ content: {
116
+ 'application/json': {
117
+ schema: { $ref: '#/components/schemas/LoginRequest' }
118
+ }
119
+ }
120
+ },
121
+ responses: {
122
+ '200': {
123
+ description: 'Inicio de sesión exitoso',
124
+ content: {
125
+ 'application/json': {
126
+ schema: { $ref: '#/components/schemas/LoginResponse' }
127
+ }
128
+ }
129
+ },
130
+ '401': {
131
+ description: 'Credenciales inválidas'
132
+ }
133
+ }
134
+ }
135
+ });
136
+
137
+ openApiGenerator.addRoute({
138
+ path: '/users',
139
+ method: 'GET',
140
+ config: {
141
+ summary: 'Obtener usuarios',
142
+ description: 'Lista de usuarios registrados (requiere autenticación JWT)',
143
+ security: [{ bearerAuth: [] }],
144
+ responses: {
145
+ '200': {
146
+ description: 'Lista de usuarios',
147
+ content: {
148
+ 'application/json': {
149
+ schema: {
150
+ type: 'array',
151
+ items: { $ref: '#/components/schemas/User' }
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+ }
158
+ });
159
+
160
+ openApiGenerator.addRoute({
161
+ path: '/products',
162
+ method: 'GET',
163
+ config: {
164
+ summary: 'Obtener productos',
165
+ description: 'Lista de productos disponibles (requiere autenticación JWT)',
166
+ security: [{ bearerAuth: [] }],
167
+ responses: {
168
+ '200': {
169
+ description: 'Lista de productos',
170
+ content: {
171
+ 'application/json': {
172
+ schema: {
173
+ type: 'array',
174
+ items: { $ref: '#/components/schemas/Product' }
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+ }
181
+ });
182
+
183
+ // Agregar esquema de seguridad
184
+ openApiGenerator.addSecurityScheme('bearerAuth', {
185
+ type: 'http',
186
+ scheme: 'bearer',
187
+ bearerFormat: 'JWT',
188
+ description: 'Autenticación por token JWT'
189
+ });
190
+
191
+ // Agregar rutas de documentación al servidor
192
+ openApiGenerator.addDocumentationRoute(server);
193
+
194
+ // Ruta pública
195
+ server.addRoute('GET', '/', (req, res) => {
196
+ res.writeHead(200, { 'Content-Type': 'application/json' });
197
+ res.end(JSON.stringify({
198
+ message: 'API con funcionalidades OpenAPI (v2.1.0)',
199
+ features: [
200
+ 'Generación automática de documentación OpenAPI 3.0',
201
+ 'Interfaz Swagger UI interactiva',
202
+ 'Esquemas de datos definidos',
203
+ 'Documentación de seguridad',
204
+ 'Especificación de endpoints, parámetros y respuestas'
205
+ ],
206
+ timestamp: new Date().toISOString()
207
+ }));
208
+ });
209
+
210
+ // Ruta de login
211
+ server.addRoute('POST', '/login', (req, res) => {
212
+ let body = req.body;
213
+
214
+ // Si body es string, intentar parsear como JSON
215
+ if (typeof body === 'string') {
216
+ try {
217
+ body = JSON.parse(body);
218
+ } catch (parseError) {
219
+ res.writeHead(400, { 'Content-Type': 'application/json' });
220
+ res.end(JSON.stringify({ error: 'Formato de solicitud inválido' }));
221
+ return;
222
+ }
223
+ }
224
+
225
+ const { username, password } = body;
226
+
227
+ // Simulación de autenticación
228
+ if (username === 'admin' && password === 'password') {
229
+ // Generar token JWT
230
+ const jwt = require('jsonwebtoken');
231
+ const token = jwt.sign(
232
+ { userId: 1, username: username, role: 'admin' },
233
+ 'super-secret-key-for-openapi-example',
234
+ { expiresIn: '1h' }
235
+ );
236
+
237
+ res.writeHead(200, { 'Content-Type': 'application/json' });
238
+ res.end(JSON.stringify({
239
+ message: 'Inicio de sesión exitoso',
240
+ token: token,
241
+ user: { userId: 1, username: username, role: 'admin' }
242
+ }));
243
+ } else {
244
+ res.writeHead(401, { 'Content-Type': 'application/json' });
245
+ res.end(JSON.stringify({ error: 'Credenciales inválidas' }));
246
+ }
247
+ });
248
+
249
+ // Ruta protegida - Usuarios
250
+ server.addRoute('GET', '/users', (req, res) => {
251
+ authenticator.authenticate('jwt-openapi')(req, res, () => {
252
+ if (req.user) {
253
+ const users = [
254
+ { id: 1, name: 'John Doe', email: 'john@example.com', role: 'admin' },
255
+ { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'user' },
256
+ { id: 3, name: 'Robert Johnson', email: 'robert@example.com', role: 'user' }
257
+ ];
258
+
259
+ res.writeHead(200, { 'Content-Type': 'application/json' });
260
+ res.end(JSON.stringify(users));
261
+ }
262
+ });
263
+ });
264
+
265
+ // Ruta protegida - Productos
266
+ server.addRoute('GET', '/products', (req, res) => {
267
+ authenticator.authenticate('jwt-openapi')(req, res, () => {
268
+ if (req.user) {
269
+ const products = [
270
+ { id: 1, name: 'Laptop', price: 999.99, category: 'Electronics' },
271
+ { id: 2, name: 'Mouse', price: 29.99, category: 'Electronics' },
272
+ { id: 3, name: 'Keyboard', price: 79.99, category: 'Electronics' }
273
+ ];
274
+
275
+ res.writeHead(200, { 'Content-Type': 'application/json' });
276
+ res.end(JSON.stringify(products));
277
+ }
278
+ });
279
+ });
280
+
281
+ // Iniciar el servidor
282
+ server.start();
283
+
284
+ logger.info('Servidor OpenAPI iniciado en http://localhost:8096');
285
+ logger.info('Documentación OpenAPI disponible en http://localhost:8096/docs');
286
+ logger.info('Especificación OpenAPI disponible en http://localhost:8096/openapi.json');
287
+ } catch (error) {
288
+ logger.error('Error iniciando el servidor:', error.message);
289
+ process.exit(1);
290
+ }
291
+ }
292
+
293
+ // Iniciar el servidor
294
+ startServer();
295
+
296
+ module.exports = { startServer };
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "api-sdk-openapi-demo",
3
+ "version": "1.0.0",
4
+ "description": "Ejemplo de API con funcionalidades OpenAPI usando el Framework API SDK",
5
+ "main": "app.js",
6
+ "scripts": {
7
+ "start": "node app.js",
8
+ "dev": "nodemon app.js"
9
+ },
10
+ "keywords": [
11
+ "api",
12
+ "sdk",
13
+ "openapi",
14
+ "swagger",
15
+ "documentation",
16
+ "framework"
17
+ ],
18
+ "author": "API SDK Framework",
19
+ "license": "MIT",
20
+ "dependencies": {
21
+ "jsonwebtoken": "^9.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "nodemon": "^3.0.0"
25
+ }
26
+ }
@@ -0,0 +1,82 @@
1
+ # Ejemplo API con Funcionalidad CORS
2
+
3
+ Este ejemplo demuestra cómo usar la funcionalidad CORS (Cross-Origin Resource Sharing) del Framework API SDK.
4
+
5
+ ## Características
6
+
7
+ - Configuración de CORS con múltiples orígenes permitidos
8
+ - Configuración de métodos HTTP permitidos
9
+ - Configuración de encabezados permitidos y expuestos
10
+ - Soporte para credenciales
11
+ - Manejo de solicitudes preflight (OPTIONS)
12
+ - Ejemplos de endpoints para probar diferentes aspectos de CORS
13
+
14
+ ## Configuración de CORS
15
+
16
+ El ejemplo configura CORS con las siguientes opciones:
17
+
18
+ - **Orígenes permitidos**: `['http://localhost:3000', 'http://localhost:8080', 'https://miapp.com']`
19
+ - **Métodos permitidos**: `['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']`
20
+ - **Encabezados permitidos**: `['Content-Type', 'Authorization', 'X-Requested-With', 'Accept', 'X-Api-Key']`
21
+ - **Encabezados expuestos**: `['X-Total-Count', 'X-Request-ID']`
22
+ - **Credenciales**: `true` (permite el uso de cookies y encabezados de autenticación)
23
+ - **Max Age**: `86400` (24 horas para caché de preflight)
24
+
25
+ ## Uso
26
+
27
+ 1. Inicia el servidor:
28
+ ```bash
29
+ node app.js
30
+ ```
31
+
32
+ 2. El servidor escuchará en `http://localhost:8094`
33
+
34
+ ## Endpoints
35
+
36
+ - `GET /` - Página de inicio
37
+ - `GET /public` - Endpoint público con CORS habilitado
38
+ - `POST /data` - Endpoint para recibir datos con CORS
39
+ - `GET /test-cors` - Endpoint para probar diferentes encabezados CORS
40
+
41
+ ## Pruebas de CORS
42
+
43
+ Puedes probar la funcionalidad CORS desde una aplicación web alojada en uno de los orígenes permitidos:
44
+
45
+ ### Ejemplo de solicitud GET:
46
+ ```javascript
47
+ fetch('http://localhost:8094/public')
48
+ .then(response => response.json())
49
+ .then(data => console.log(data));
50
+ ```
51
+
52
+ ### Ejemplo de solicitud POST con encabezados personalizados:
53
+ ```javascript
54
+ fetch('http://localhost:8094/data', {
55
+ method: 'POST',
56
+ headers: {
57
+ 'Content-Type': 'application/json',
58
+ 'X-Api-Key': 'tu-api-key'
59
+ },
60
+ body: JSON.stringify({ dato: 'ejemplo' })
61
+ })
62
+ .then(response => response.json())
63
+ .then(data => console.log(data));
64
+ ```
65
+
66
+ ### Solicitudes complejas que disparan preflight:
67
+ Las solicitudes con encabezados personalizados o ciertos tipos de contenido dispararán una solicitud OPTIONS preflight, que será manejada automáticamente por el middleware CORS.
68
+
69
+ ## Estructura del proyecto
70
+
71
+ ```
72
+ examples/v2_cors/
73
+ ├── app.js # Punto de entrada de la aplicación
74
+ └── README.md
75
+ ```
76
+
77
+ ## Notas
78
+
79
+ - El middleware CORS maneja automáticamente las solicitudes preflight (OPTIONS)
80
+ - Los encabezados expuestos son accesibles desde el código JavaScript del cliente
81
+ - Las credenciales permiten el uso de cookies y encabezados de autenticación
82
+ - El encabezado `Access-Control-Max-Age` permite cachear la respuesta preflight
@@ -0,0 +1,108 @@
1
+ const {
2
+ APIServer,
3
+ Cors,
4
+ Logger
5
+ } = require('../../index.js');
6
+
7
+ async function startServer() {
8
+ // Crear instancia del servidor
9
+ const server = new APIServer({
10
+ port: 8094,
11
+ host: 'localhost'
12
+ });
13
+
14
+ // Crear instancia del logger
15
+ const logger = new Logger({ level: 'info' });
16
+
17
+ try {
18
+ // Crear instancia del middleware CORS
19
+ const cors = new Cors({
20
+ origin: ['http://localhost:3000', 'http://localhost:8080', 'https://miapp.com'],
21
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
22
+ allowedHeaders: [
23
+ 'Content-Type',
24
+ 'Authorization',
25
+ 'X-Requested-With',
26
+ 'Accept',
27
+ 'X-Api-Key'
28
+ ],
29
+ exposedHeaders: [
30
+ 'X-Total-Count',
31
+ 'X-Request-ID'
32
+ ],
33
+ credentials: true,
34
+ maxAge: 86400 // 24 horas
35
+ });
36
+
37
+ // Aplicar el middleware CORS al servidor
38
+ server.use(cors.middleware());
39
+
40
+ // Agregar algunas rutas de ejemplo
41
+ server.addRoute('GET', '/', (req, res) => {
42
+ res.writeHead(200, { 'Content-Type': 'application/json' });
43
+ res.end(JSON.stringify({
44
+ message: 'API con CORS configurado',
45
+ endpoints: {
46
+ 'GET /public': 'Endpoint público con CORS',
47
+ 'POST /data': 'Endpoint para recibir datos con CORS',
48
+ 'GET /test-cors': 'Endpoint para probar diferentes encabezados CORS'
49
+ }
50
+ }));
51
+ });
52
+
53
+ server.addRoute('GET', '/public', (req, res) => {
54
+ // Establecer encabezados personalizados que serán expuestos al cliente
55
+ res.setHeader('X-Request-ID', 'req-' + Date.now());
56
+ res.setHeader('X-Total-Count', '100');
57
+
58
+ res.writeHead(200, { 'Content-Type': 'application/json' });
59
+ res.end(JSON.stringify({
60
+ message: 'Este es un endpoint público con CORS habilitado',
61
+ timestamp: new Date().toISOString(),
62
+ origin: req.headers.origin || 'no origin'
63
+ }));
64
+ });
65
+
66
+ server.addRoute('POST', '/data', (req, res) => {
67
+ // Establecer encabezados personalizados
68
+ res.setHeader('X-Request-ID', 'req-' + Date.now());
69
+
70
+ res.writeHead(200, { 'Content-Type': 'application/json' });
71
+ res.end(JSON.stringify({
72
+ message: 'Datos recibidos exitosamente',
73
+ receivedData: req.body,
74
+ timestamp: new Date().toISOString()
75
+ }));
76
+ });
77
+
78
+ server.addRoute('GET', '/test-cors', (req, res) => {
79
+ // Endpoint para probar diferentes aspectos de CORS
80
+ res.setHeader('X-Request-ID', 'req-' + Date.now());
81
+ res.setHeader('X-Custom-Header', 'custom-value'); // Este encabezado no está en exposedHeaders
82
+
83
+ res.writeHead(200, { 'Content-Type': 'application/json' });
84
+ res.end(JSON.stringify({
85
+ message: 'Prueba de CORS completada',
86
+ headers: req.headers,
87
+ timestamp: new Date().toISOString()
88
+ }));
89
+ });
90
+
91
+ // Manejar solicitudes OPTIONS para todos los endpoints (preflight)
92
+ // No es necesario agregar una ruta específica para '*' ya que el middleware CORS lo maneja
93
+
94
+ // Iniciar el servidor
95
+ server.start();
96
+
97
+ logger.info('Servidor iniciado en http://localhost:8094');
98
+ logger.info('CORS configurado para orígenes: http://localhost:3000, http://localhost:8080, https://miapp.com');
99
+ } catch (error) {
100
+ logger.error('Error iniciando el servidor:', error.message);
101
+ process.exit(1);
102
+ }
103
+ }
104
+
105
+ // Iniciar el servidor
106
+ startServer();
107
+
108
+ module.exports = { startServer };
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "api-sdk-cors-example",
3
+ "version": "1.0.0",
4
+ "description": "Ejemplo de API con funcionalidad CORS usando el Framework API SDK",
5
+ "main": "app.js",
6
+ "scripts": {
7
+ "start": "node app.js",
8
+ "dev": "nodemon app.js"
9
+ },
10
+ "keywords": [
11
+ "api",
12
+ "sdk",
13
+ "cors",
14
+ "cross-origin",
15
+ "security",
16
+ "framework"
17
+ ],
18
+ "author": "API SDK Framework",
19
+ "license": "MIT",
20
+ "devDependencies": {
21
+ "nodemon": "^3.0.0"
22
+ }
23
+ }
@@ -0,0 +1,83 @@
1
+ # Ejemplo API con Autenticación JSON
2
+
3
+ Este ejemplo demuestra cómo crear una API con autenticación basada en tokens estáticos almacenados en un archivo JSON utilizando el Framework API SDK.
4
+
5
+ ## Características
6
+
7
+ - Autenticación JWT con tokens gestionados a través de almacenamiento JSON
8
+ - Rutas protegidas y públicas
9
+ - Sistema de login para obtener tokens
10
+ - Controladores organizados por funcionalidad
11
+ - Tokens almacenados en un archivo JSON local
12
+
13
+ ## Configuración
14
+
15
+ 1. Asegúrate de tener instaladas las dependencias del framework API SDK
16
+ 2. El archivo de tokens `tokens.json` se creará automáticamente al iniciar la aplicación
17
+
18
+ ## Uso
19
+
20
+ 1. Inicia el servidor:
21
+ ```bash
22
+ node app.js
23
+ ```
24
+
25
+ 2. El servidor escuchará en `http://localhost:8091`
26
+
27
+ ## Endpoints
28
+
29
+ - `GET /` - Página de inicio (público)
30
+ - `POST /login` - Iniciar sesión y obtener token (público)
31
+ - `GET /protected` - Contenido protegido (requiere token)
32
+ - `GET /profile` - Perfil de usuario (requiere token)
33
+ - `GET /tokens` - Ver tokens almacenados (requiere token)
34
+
35
+ ## Ejemplo de uso
36
+
37
+ 1. Iniciar sesión:
38
+ ```bash
39
+ curl -X POST http://localhost:8091/login \
40
+ -H "Content-Type: application/json" \
41
+ -d '{"username": "admin", "password": "password"}'
42
+ ```
43
+
44
+ 2. Acceder a contenido protegido:
45
+ ```bash
46
+ curl -X GET http://localhost:8091/protected \
47
+ -H "Authorization: Bearer TU_TOKEN_AQUI"
48
+ ```
49
+
50
+ 3. Ver perfil de usuario:
51
+ ```bash
52
+ curl -X GET http://localhost:8091/profile \
53
+ -H "Authorization: Bearer TU_TOKEN_AQUI"
54
+ ```
55
+
56
+ 4. Ver tokens almacenados:
57
+ ```bash
58
+ curl -X GET http://localhost:8091/tokens \
59
+ -H "Authorization: Bearer TU_TOKEN_AQUI"
60
+ ```
61
+
62
+ ## Estructura del proyecto
63
+
64
+ ```
65
+ examples/v2_json_auth/
66
+ ├── app.js # Punto de entrada de la aplicación
67
+ ├── routes.json # Definición de rutas
68
+ ├── controllers/ # Controladores de las rutas
69
+ │ ├── mainController.js
70
+ │ ├── authController.js
71
+ │ ├── protectedController.js
72
+ │ ├── userController.js
73
+ │ └── tokenController.js
74
+ ├── tokens.json # Archivo de almacenamiento de tokens (generado automáticamente)
75
+ └── README.md
76
+ ```
77
+
78
+ ## Seguridad
79
+
80
+ - Los tokens se gestionan a través del sistema de TokenManager del framework
81
+ - Los tokens expiran después de 1 hora
82
+ - Las rutas protegidas requieren un token válido en el header Authorization
83
+ - El archivo de tokens se almacena localmente en formato JSON
@@ -0,0 +1,72 @@
1
+ const {
2
+ APIServer,
3
+ Authenticator,
4
+ RouteLoader,
5
+ Logger,
6
+ TokenManager
7
+ } = require('../../index.js');
8
+
9
+ async function startServer() {
10
+ // Crear instancia del servidor
11
+ const server = new APIServer({
12
+ port: 8091,
13
+ host: 'localhost'
14
+ });
15
+
16
+ // Crear instancia del logger
17
+ const logger = new Logger({ level: 'info' });
18
+
19
+ try {
20
+ // Crear instancia del TokenManager con almacenamiento en JSON
21
+ const tokenManager = new TokenManager({
22
+ storage: 'json',
23
+ tokenFile: './tokens.json'
24
+ });
25
+
26
+ // Crear instancia del autenticador
27
+ const authenticator = new Authenticator({ logger });
28
+
29
+ // Registrar estrategia de autenticación JWT que utiliza el TokenManager con almacenamiento JSON
30
+ authenticator.use('jwt-json', async (req, options = {}) => {
31
+ const authHeader = req.headers.authorization;
32
+ const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN
33
+
34
+ if (!token) {
35
+ return false;
36
+ }
37
+
38
+ // Validar el token usando el TokenManager
39
+ const secret = 'super-secret-key-for-json-example';
40
+ const decoded = tokenManager.validateToken(token, secret);
41
+
42
+ if (decoded) {
43
+ // Verificar si el token está almacenado en el archivo JSON (opcional, dependiendo del enfoque)
44
+ // En este caso, simplemente verificamos que el token sea válido
45
+ req.user = decoded;
46
+ return true;
47
+ }
48
+
49
+ return false;
50
+ });
51
+
52
+ // Agregar el autenticador al servidor para que pueda ser usado por el RouteLoader
53
+ server.authenticator = authenticator;
54
+
55
+ // Cargar rutas desde archivo JSON
56
+ const routeLoader = new RouteLoader();
57
+ await routeLoader.loadRoutes(server, './routes.json');
58
+
59
+ // Iniciar el servidor
60
+ server.start();
61
+
62
+ logger.info('Servidor iniciado en http://localhost:8091');
63
+ } catch (error) {
64
+ logger.error('Error iniciando el servidor:', error.message);
65
+ process.exit(1);
66
+ }
67
+ }
68
+
69
+ // Iniciar el servidor
70
+ startServer();
71
+
72
+ module.exports = { startServer };