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,23 @@
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{title}}</title>
7
+ <style>
8
+ body { font-family: Arial, sans-serif; margin: 40px; background-color: #f5f5f5; }
9
+ .container { max-width: 800px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
10
+ h1 { color: #333; }
11
+ table { width: 100%; border-collapse: collapse; margin-top: 20px; }
12
+ th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
13
+ th { background-color: #f2f2f2; }
14
+ .active { color: green; }
15
+ .inactive { color: red; }
16
+ </style>
17
+ </head>
18
+ <body>
19
+ <div class="container">
20
+ {{content}}
21
+ </div>
22
+ </body>
23
+ </html>
@@ -0,0 +1,3 @@
1
+ <h1>{{title}}</h1>
2
+ <p>{{message}}</p>
3
+ <p>Prueba de variable simple: {{currentTime}}</p>
@@ -0,0 +1,6 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <div>
4
+ <p>El ID proporcionado no es válido: {{userId}}</p>
5
+ <a href="/users">Volver a la lista de usuarios</a>
6
+ </div>
@@ -0,0 +1,36 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ {{if users}}
4
+ <table>
5
+ <thead>
6
+ <tr>
7
+ <th>ID</th>
8
+ <th>Nombre</th>
9
+ <th>Email</th>
10
+ <th>Estado</th>
11
+ <th>Acciones</th>
12
+ </tr>
13
+ </thead>
14
+ <tbody>
15
+ {{foreach:users}}
16
+ <tr>
17
+ <td>{{item.id}}</td>
18
+ <td>{{item.name}}</td>
19
+ <td>{{item.email}}</td>
20
+ <td>
21
+ {{if item.active}}
22
+ <span class="active">Activo</span>
23
+ {{else}}
24
+ <span class="inactive">Inactivo</span>
25
+ {{endif}}
26
+ </td>
27
+ <td><a href="/profile?id={{item.id}}">Ver Perfil</a></td>
28
+ </tr>
29
+ {{endforeach}}
30
+ </tbody>
31
+ </table>
32
+ {{else}}
33
+ <p>No hay usuarios registrados.</p>
34
+ {{endif}}
35
+
36
+ <a href="/">Volver a la página de inicio</a>
@@ -0,0 +1,6 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <div>
4
+ <p>No se encontró el usuario con ID: {{userId}}</p>
5
+ <a href="/users">Volver a la lista de usuarios</a>
6
+ </div>
@@ -0,0 +1,11 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <div>
4
+ <h2>Información del Usuario</h2>
5
+ <p><strong>ID:</strong> {{user.id}}</p>
6
+ <p><strong>Nombre:</strong> {{user.name}}</p>
7
+ <p><strong>Email:</strong> {{user.email}}</p>
8
+ <p><strong>Registrado:</strong> {{user.registered}}</p>
9
+ </div>
10
+
11
+ <a href="/users">Volver a la lista de usuarios</a>
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Ejemplo de uso del sistema MVC con definición de rutas desde archivo JSON
3
+ * Demostración de vistas, helpers y filtros
4
+ */
5
+
6
+ const { APIServer, RouteLoader, ControllerLoader, ViewEngine } = require('../../index');
7
+
8
+ // Crear instancia del servidor
9
+ const server = new APIServer({
10
+ port: 9001,
11
+ host: 'localhost'
12
+ });
13
+
14
+ // Crear instancia del cargador de rutas
15
+ const routeLoader = new RouteLoader();
16
+
17
+ // Cargar las rutas desde el archivo JSON
18
+ routeLoader.loadRoutes(server, './examples/mvc_routes_example/routes.json')
19
+ .then(routes => {
20
+ console.log(`${routes.length} rutas cargadas exitosamente`);
21
+ console.log('Rutas disponibles:');
22
+ console.log('- http://localhost:9001/ (Página de inicio)');
23
+ console.log('- http://localhost:9001/users (Lista de usuarios)');
24
+ console.log('- http://localhost:9001/profile?id=1 (Perfil de usuario)');
25
+ console.log('- http://localhost:9001/products (Catálogo de productos)');
26
+
27
+ // Iniciar el servidor
28
+ server.start(() => {
29
+ console.log('Servidor MVC con rutas JSON iniciado en http://localhost:9001');
30
+ });
31
+ })
32
+ .catch(error => {
33
+ console.error('Error al cargar las rutas:', error);
34
+ });
@@ -0,0 +1,27 @@
1
+ const { ControllerBase } = require('../../../index');
2
+
3
+ class MainController extends ControllerBase {
4
+ constructor(options = {}) {
5
+ super(options);
6
+ }
7
+
8
+ index(req, res) {
9
+ this.set('title', 'Inicio - Ejemplo MVC con Routes');
10
+ this.set('message', '¡Bienvenido al ejemplo de MVC con definición de rutas!');
11
+
12
+ this.render(res, 'main/index', {
13
+ currentTime: new Date().toISOString(),
14
+ version: '2.3.1'
15
+ });
16
+ }
17
+ }
18
+
19
+ // Exportar métodos directamente para que el RouteLoader pueda acceder a ellos
20
+ const controllerInstance = new MainController({ viewsPath: './examples/mvc_routes_example/views' });
21
+
22
+ module.exports = {
23
+ index: (req, res) => {
24
+ controllerInstance.setRequestResponse(req, res);
25
+ controllerInstance.index(req, res);
26
+ }
27
+ };
@@ -0,0 +1,47 @@
1
+ const { ControllerBase } = require('../../../index');
2
+
3
+ class ProductController extends ControllerBase {
4
+ constructor(options = {}) {
5
+ super(options);
6
+
7
+ // Registrar helpers personalizados para este controlador
8
+ this.getViewEngine().addHelper('calculateDiscount', (price, discountPercent) => {
9
+ return price - (price * discountPercent / 100);
10
+ });
11
+
12
+ this.getViewEngine().addHelper('formatCurrency', (value, symbol = '$') => {
13
+ return `${symbol}${Number(value).toFixed(2)}`;
14
+ });
15
+
16
+ this.getViewEngine().addHelper('isOnSale', (product) => {
17
+ return product.discount > 0;
18
+ });
19
+ }
20
+
21
+ catalog(req, res) {
22
+ const products = [
23
+ { id: 1, name: 'Laptop Pro', price: 1200, discount: 10, category: 'Electronics' },
24
+ { id: 2, name: 'Mouse Inalámbrico', price: 25, discount: 15, category: 'Accessories' },
25
+ { id: 3, name: 'Teclado Mecánico', price: 80, discount: 0, category: 'Accessories' },
26
+ { id: 4, name: 'Monitor 4K', price: 400, discount: 20, category: 'Electronics' },
27
+ { id: 5, name: 'Auriculares', price: 150, discount: 5, category: 'Audio' }
28
+ ];
29
+
30
+ this.set('title', 'Catálogo de Productos');
31
+ this.set('products', products);
32
+
33
+ this.render(res, 'product/catalog', {
34
+ currencySymbol: 'USD'
35
+ });
36
+ }
37
+ }
38
+
39
+ // Exportar métodos directamente para que el RouteLoader pueda acceder a ellos
40
+ const controllerInstance = new ProductController({ viewsPath: './examples/mvc_routes_example/views' });
41
+
42
+ module.exports = {
43
+ catalog: (req, res) => {
44
+ controllerInstance.setRequestResponse(req, res);
45
+ controllerInstance.catalog(req, res);
46
+ }
47
+ };
@@ -0,0 +1,76 @@
1
+ const { ControllerBase } = require('../../../index');
2
+
3
+ class UserController extends ControllerBase {
4
+ constructor(options = {}) {
5
+ super(options);
6
+ }
7
+
8
+ list(req, res) {
9
+ const users = [
10
+ { id: 1, name: 'Ana García', email: 'ana@example.com', registered: '2026-01-01', active: true },
11
+ { id: 2, name: 'Carlos López', email: 'carlos@example.com', registered: '2026-01-02', active: false },
12
+ { id: 3, name: 'Laura Martínez', email: 'laura@example.com', registered: '2026-01-03', active: true },
13
+ { id: 4, name: 'Pedro Rodríguez', email: 'pedro@example.com', registered: '2026-01-04', active: true },
14
+ { id: 5, name: 'María Sánchez', email: 'maria@example.com', registered: '2026-01-05', active: false }
15
+ ];
16
+
17
+ this.set('title', 'Lista de Usuarios');
18
+ this.set('users', users);
19
+
20
+ this.render(res, 'user/list', {
21
+ totalUsers: users.length
22
+ });
23
+ }
24
+
25
+ profile(req, res) {
26
+ const userIdParam = this.input('id', '1');
27
+
28
+ // Validar que el ID sea un número entero positivo
29
+ if (!/^\d+$/.test(userIdParam) || parseInt(userIdParam) <= 0) {
30
+ this.set('title', 'ID de usuario inválido');
31
+ this.render(res, 'user/invalid', {
32
+ userId: userIdParam
33
+ });
34
+ return;
35
+ }
36
+
37
+ const userId = parseInt(userIdParam);
38
+
39
+ const users = [
40
+ { id: 1, name: 'Ana García', email: 'ana@example.com', registered: '2026-01-01', active: true },
41
+ { id: 2, name: 'Carlos López', email: 'carlos@example.com', registered: '2026-01-02', active: false },
42
+ { id: 3, name: 'Laura Martínez', email: 'laura@example.com', registered: '2026-01-03', active: true },
43
+ { id: 4, name: 'Pedro Rodríguez', email: 'pedro@example.com', registered: '2026-01-04', active: true },
44
+ { id: 5, name: 'María Sánchez', email: 'maria@example.com', registered: '2026-01-05', active: false }
45
+ ];
46
+
47
+ const user = users.find(u => u.id === userId);
48
+
49
+ if (!user) {
50
+ this.set('title', 'Usuario no encontrado');
51
+ this.render(res, 'user/notfound', {
52
+ userId: userId
53
+ });
54
+ return;
55
+ }
56
+
57
+ this.set('title', `Perfil de ${user.name}`);
58
+ this.set('user', user);
59
+
60
+ this.render(res, 'user/profile');
61
+ }
62
+ }
63
+
64
+ // Exportar métodos directamente para que el RouteLoader pueda acceder a ellos
65
+ const controllerInstance = new UserController({ viewsPath: './examples/mvc_routes_example/views' });
66
+
67
+ module.exports = {
68
+ list: (req, res) => {
69
+ controllerInstance.setRequestResponse(req, res);
70
+ controllerInstance.list(req, res);
71
+ },
72
+ profile: (req, res) => {
73
+ controllerInstance.setRequestResponse(req, res);
74
+ controllerInstance.profile(req, res);
75
+ }
76
+ };
@@ -0,0 +1,30 @@
1
+ [
2
+ {
3
+ "method": "GET",
4
+ "path": "/",
5
+ "controller": "./examples/mvc_routes_example/controllers/mainController.js",
6
+ "handler": "index",
7
+ "auth": "none"
8
+ },
9
+ {
10
+ "method": "GET",
11
+ "path": "/users",
12
+ "controller": "./examples/mvc_routes_example/controllers/userController.js",
13
+ "handler": "list",
14
+ "auth": "none"
15
+ },
16
+ {
17
+ "method": "GET",
18
+ "path": "/profile",
19
+ "controller": "./examples/mvc_routes_example/controllers/userController.js",
20
+ "handler": "profile",
21
+ "auth": "none"
22
+ },
23
+ {
24
+ "method": "GET",
25
+ "path": "/products",
26
+ "controller": "./examples/mvc_routes_example/controllers/productController.js",
27
+ "handler": "catalog",
28
+ "auth": "none"
29
+ }
30
+ ]
@@ -0,0 +1,31 @@
1
+ <!DOCTYPE html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>{{title}}</title>
7
+ <style>
8
+ body { font-family: Arial, sans-serif; margin: 40px; background-color: #f5f5f5; }
9
+ .container { max-width: 800px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
10
+ h1 { color: #333; }
11
+ nav { margin: 20px 0; }
12
+ nav a { margin-right: 15px; text-decoration: none; color: #007bff; }
13
+ nav a:hover { text-decoration: underline; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <div class="container">
18
+ <h1>{{title}}</h1>
19
+ <p>{{message}}</p>
20
+
21
+ <nav>
22
+ <a href="/">Inicio</a>
23
+ <a href="/users">Usuarios</a>
24
+ <a href="/products">Productos</a>
25
+ </nav>
26
+
27
+ <p>Versión: {{version}}</p>
28
+ <p>Hora actual: {{currentTime}}</p>
29
+ </div>
30
+ </body>
31
+ </html>
@@ -0,0 +1,11 @@
1
+ <h1>{{title}}</h1>
2
+ <p>{{message}}</p>
3
+
4
+ <nav>
5
+ <a href="/">Inicio</a>
6
+ <a href="/users">Usuarios</a>
7
+ <a href="/products">Productos</a>
8
+ </nav>
9
+
10
+ <p>Versión: {{version}}</p>
11
+ <p>Hora actual: {{currentTime}}</p>
@@ -0,0 +1,24 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ {{if products}}
4
+ <div class="product-grid">
5
+ {{foreach:products}}
6
+ <div class="product-card">
7
+ <h3>{{item.name}}</h3>
8
+ <p>Categoría: {{item.category}}</p>
9
+ <p>Precio original: {{formatCurrency(item.price)}}</p>
10
+ <p>Descuento: {{item.discount}}%</p>
11
+ {{if item.discount > 0}}
12
+ <p>Precio con descuento: {{formatCurrency(calculateDiscount(item.price, item.discount))}}</p>
13
+ <p class="onsale">¡En oferta!</p>
14
+ {{else}}
15
+ <p class="regular">Precio regular</p>
16
+ {{endif}}
17
+ </div>
18
+ {{endforeach}}
19
+ </div>
20
+ {{else}}
21
+ <p>No hay productos disponibles.</p>
22
+ {{endif}}
23
+
24
+ <a href="/">Volver al inicio</a>
@@ -0,0 +1,6 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <div>
4
+ <p>El ID proporcionado no es válido: {{userId}}</p>
5
+ <a href="/users">Volver a la lista de usuarios</a>
6
+ </div>
@@ -0,0 +1,40 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ {{if users}}
4
+ <p>Total de usuarios: {{totalUsers}}</p>
5
+
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <th>ID</th>
10
+ <th>Nombre</th>
11
+ <th>Email</th>
12
+ <th>Registrado</th>
13
+ <th>Estado</th>
14
+ <th>Acciones</th>
15
+ </tr>
16
+ </thead>
17
+ <tbody>
18
+ {{foreach:users}}
19
+ <tr>
20
+ <td>{{item.id}}</td>
21
+ <td>{{item.name}}</td>
22
+ <td>{{item.email}}</td>
23
+ <td>{{item.registered|date:'DD/MM/YYYY'}}</td>
24
+ <td>
25
+ {{if item.active}}
26
+ <span class="active">Activo</span>
27
+ {{else}}
28
+ <span class="inactive">Inactivo</span>
29
+ {{endif}}
30
+ </td>
31
+ <td><a href="/profile?id={{item.id}}">Ver Perfil</a></td>
32
+ </tr>
33
+ {{endforeach}}
34
+ </tbody>
35
+ </table>
36
+ {{else}}
37
+ <p>No hay usuarios registrados.</p>
38
+ {{endif}}
39
+
40
+ <a href="/">Volver al inicio</a>
@@ -0,0 +1,6 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <div>
4
+ <p>No se encontró el usuario con ID: {{userId}}</p>
5
+ <a href="/users">Volver a la lista de usuarios</a>
6
+ </div>
@@ -0,0 +1,18 @@
1
+ <h1>{{title}}</h1>
2
+
3
+ <div>
4
+ <h2>Información del Usuario</h2>
5
+ <p><strong>ID:</strong> {{user.id}}</p>
6
+ <p><strong>Nombre:</strong> {{user.name}}</p>
7
+ <p><strong>Email:</strong> {{user.email}}</p>
8
+ <p><strong>Registrado:</strong> {{user.registered|date:'DD/MM/YYYY'}}</p>
9
+ <p><strong>Estado:</strong>
10
+ {{if user.active}}
11
+ <span class="active">Activo</span>
12
+ {{else}}
13
+ <span class="inactive">Inactivo</span>
14
+ {{endif}}
15
+ </p>
16
+ </div>
17
+
18
+ <a href="/users">Volver a la lista de usuarios</a>
@@ -0,0 +1,92 @@
1
+ # API Pública de Ejemplo
2
+
3
+ Este ejemplo demuestra cómo crear una API pública usando el Framework API SDK JS. La API incluye endpoints para gestionar usuarios y está protegida con CORS y rate limiting.
4
+
5
+ ## Características
6
+
7
+ - API REST pública sin autenticación requerida
8
+ - Endpoints para gestión de usuarios (CRUD completo)
9
+ - Protección con CORS para permitir solicitudes desde cualquier origen
10
+ - Rate limiting para prevenir abusos
11
+ - Endpoints de salud del sistema
12
+ - Controladores organizados por funcionalidad
13
+
14
+ ## Configuración
15
+
16
+ 1. Asegúrate de tener instaladas las dependencias del framework API SDK
17
+ 2. No se requiere configuración adicional para esta API pública
18
+
19
+ ## Uso
20
+
21
+ 1. Inicia el servidor:
22
+ ```bash
23
+ node app.js
24
+ ```
25
+
26
+ 2. El servidor escuchará en `http://localhost:8081`
27
+
28
+ ## Endpoints
29
+
30
+ - `GET /` - Información general de la API (público)
31
+ - `GET /users` - Lista todos los usuarios (público)
32
+ - `GET /users/:id` - Obtiene un usuario específico (público)
33
+ - `POST /users` - Crea un nuevo usuario (público)
34
+ - `PUT /users/:id` - Actualiza un usuario existente (público)
35
+ - `DELETE /users/:id` - Elimina un usuario (público)
36
+ - `GET /health` - Verifica el estado del servicio (público)
37
+
38
+ ## Ejemplos de uso
39
+
40
+ 1. Obtener todos los usuarios:
41
+ ```bash
42
+ curl -X GET http://localhost:8081/users
43
+ ```
44
+
45
+ 2. Obtener un usuario específico:
46
+ ```bash
47
+ curl -X GET http://localhost:8081/users/1
48
+ ```
49
+
50
+ 3. Crear un nuevo usuario:
51
+ ```bash
52
+ curl -X POST http://localhost:8081/users \
53
+ -H "Content-Type: application/json" \
54
+ -d '{"name": "Nuevo Usuario", "email": "nuevo@ejemplo.com", "age": 28}'
55
+ ```
56
+
57
+ 4. Actualizar un usuario:
58
+ ```bash
59
+ curl -X PUT http://localhost:8081/users/1 \
60
+ -H "Content-Type: application/json" \
61
+ -d '{"name": "Usuario Actualizado", "email": "actualizado@ejemplo.com"}'
62
+ ```
63
+
64
+ 5. Eliminar un usuario:
65
+ ```bash
66
+ curl -X DELETE http://localhost:8081/users/1
67
+ ```
68
+
69
+ 6. Verificar estado del servicio:
70
+ ```bash
71
+ curl -X GET http://localhost:8081/health
72
+ ```
73
+
74
+ ## Estructura del proyecto
75
+
76
+ ```
77
+ examples/public/
78
+ ├── app.js # Punto de entrada de la aplicación
79
+ ├── routes.json # Definición de rutas
80
+ ├── controllers/ # Controladores de las rutas
81
+ │ ├── mainController.js
82
+ │ ├── userController.js
83
+ │ └── healthController.js
84
+ └── README.md
85
+ ```
86
+
87
+ ## Seguridad
88
+
89
+ - CORS configurado para permitir solicitudes desde cualquier origen
90
+ - Rate limiting configurado para prevenir abusos (100 solicitudes por 15 minutos)
91
+ - No se requiere autenticación para acceder a los endpoints
92
+ - Validación de entrada en endpoints de creación/actualización
@@ -0,0 +1,72 @@
1
+ const {
2
+ APIServer,
3
+ Router,
4
+ RouteLoader,
5
+ Logger,
6
+ Cors,
7
+ RateLimiter
8
+ } = require('../../index.js');
9
+
10
+ async function startServer() {
11
+ // Crear instancia del servidor
12
+ const server = new APIServer({
13
+ port: 8081,
14
+ host: 'localhost',
15
+ requestTimeout: 30000, // 30 segundos
16
+ connectionTimeout: 30000 // 30 segundos
17
+ });
18
+
19
+ // Crear instancia del logger
20
+ const logger = new Logger({ level: 'info' });
21
+
22
+ try {
23
+ // Configurar CORS para permitir solicitudes desde cualquier origen
24
+ const cors = new Cors({
25
+ origin: '*',
26
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
27
+ allowedHeaders: [
28
+ 'Content-Type',
29
+ 'Authorization',
30
+ 'X-Requested-With',
31
+ 'Accept',
32
+ 'Origin'
33
+ ]
34
+ });
35
+
36
+ // Aplicar middleware de CORS
37
+ server.use(cors.middleware());
38
+
39
+ // Configurar Rate Limiter para prevenir abusos
40
+ const rateLimiter = new RateLimiter({
41
+ windowMs: 15 * 60 * 1000, // 15 minutos
42
+ maxRequests: 100 // Límite de 100 solicitudes por ventana
43
+ });
44
+
45
+ // Aplicar middleware de rate limiting
46
+ server.use(rateLimiter.middleware());
47
+
48
+ // Cargar rutas desde archivo JSON
49
+ const routeLoader = new RouteLoader();
50
+ await routeLoader.loadRoutes(server, './routes.json');
51
+
52
+ // Iniciar el servidor
53
+ server.start();
54
+
55
+ logger.info('Servidor público iniciado en http://localhost:8081');
56
+ logger.info('Endpoints disponibles:');
57
+ logger.info('- GET / (Información del API)');
58
+ logger.info('- GET /users (Lista de usuarios)');
59
+ logger.info('- GET /users/:id (Obtener usuario específico)');
60
+ logger.info('- POST /users (Crear nuevo usuario)');
61
+ logger.info('- PUT /users/:id (Actualizar usuario)');
62
+ logger.info('- DELETE /users/:id (Eliminar usuario)');
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 };
@@ -0,0 +1,20 @@
1
+ const healthController = {
2
+ checkHealth: (req, res) => {
3
+ const healthStatus = {
4
+ status: 'healthy',
5
+ timestamp: new Date().toISOString(),
6
+ uptime: process.uptime(),
7
+ message: 'API Pública de Ejemplo está operando correctamente',
8
+ version: '1.0.0',
9
+ endpoints: {
10
+ total: 7,
11
+ active: true
12
+ }
13
+ };
14
+
15
+ res.writeHead(200, { 'Content-Type': 'application/json' });
16
+ res.end(JSON.stringify(healthStatus));
17
+ }
18
+ };
19
+
20
+ module.exports = healthController;
@@ -0,0 +1,22 @@
1
+ const mainController = {
2
+ home: (req, res) => {
3
+ res.writeHead(200, { 'Content-Type': 'application/json' });
4
+ res.end(JSON.stringify({
5
+ message: 'Bienvenido a la API Pública de Ejemplo',
6
+ version: '1.0.0',
7
+ description: 'Esta es una API pública de ejemplo creada con el Framework API SDK JS',
8
+ endpoints: {
9
+ 'GET /': 'Este mensaje',
10
+ 'GET /users': 'Obtener lista de usuarios',
11
+ 'GET /users/:id': 'Obtener usuario específico',
12
+ 'POST /users': 'Crear nuevo usuario',
13
+ 'PUT /users/:id': 'Actualizar usuario',
14
+ 'DELETE /users/:id': 'Eliminar usuario',
15
+ 'GET /health': 'Verificar estado del servicio'
16
+ },
17
+ documentation: 'Visita el README para más información sobre cómo usar esta API'
18
+ }));
19
+ }
20
+ };
21
+
22
+ module.exports = mainController;