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,96 @@
1
+ const sqlite3 = require('sqlite3').verbose();
2
+ const path = require('path');
3
+
4
+ class MessageController {
5
+ constructor() {
6
+ // Usar una base de datos SQLite en memoria para este ejemplo
7
+ // En una aplicación real, usarías una ruta a un archivo
8
+ this.db = new sqlite3.Database(':memory:');
9
+ this.initDatabase();
10
+ }
11
+
12
+ initDatabase() {
13
+ // Crear tabla de mensajes
14
+ this.db.serialize(() => {
15
+ this.db.run(`
16
+ CREATE TABLE messages (
17
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
18
+ name TEXT NOT NULL,
19
+ email TEXT NOT NULL,
20
+ message TEXT NOT NULL,
21
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
22
+ )
23
+ `);
24
+
25
+ // Crear tabla de usuarios para login
26
+ this.db.run(`
27
+ CREATE TABLE users (
28
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
29
+ username TEXT UNIQUE NOT NULL,
30
+ password TEXT NOT NULL,
31
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
32
+ )
33
+ `);
34
+
35
+ // Insertar un usuario de ejemplo para pruebas
36
+ this.db.run("INSERT OR IGNORE INTO users (username, password) VALUES (?, ?)", ['admin', 'password123']);
37
+ });
38
+ }
39
+
40
+ // Guardar un mensaje en la base de datos
41
+ saveMessage(name, email, message) {
42
+ return new Promise((resolve, reject) => {
43
+ const stmt = this.db.prepare("INSERT INTO messages (name, email, message) VALUES (?, ?, ?)");
44
+ stmt.run([name, email, message], function(err) {
45
+ if (err) {
46
+ console.error('Error guardando mensaje:', err);
47
+ reject(err);
48
+ } else {
49
+ console.log(`Mensaje guardado con ID: ${this.lastID}`);
50
+ resolve(this.lastID);
51
+ }
52
+ });
53
+ stmt.finalize();
54
+ });
55
+ }
56
+
57
+ // Obtener todos los mensajes
58
+ getMessages() {
59
+ return new Promise((resolve, reject) => {
60
+ this.db.all("SELECT * FROM messages ORDER BY created_at DESC", [], (err, rows) => {
61
+ if (err) {
62
+ console.error('Error obteniendo mensajes:', err);
63
+ reject(err);
64
+ } else {
65
+ resolve(rows);
66
+ }
67
+ });
68
+ });
69
+ }
70
+
71
+ // Validar credenciales de usuario
72
+ validateUser(username, password) {
73
+ return new Promise((resolve, reject) => {
74
+ this.db.get("SELECT * FROM users WHERE username = ?", [username], (err, row) => {
75
+ if (err) {
76
+ console.error('Error validando usuario:', err);
77
+ reject(err);
78
+ } else if (row && row.password === password) {
79
+ resolve(row);
80
+ } else {
81
+ resolve(null);
82
+ }
83
+ });
84
+ });
85
+ }
86
+
87
+ // Cerrar la base de datos
88
+ close() {
89
+ this.db.close();
90
+ }
91
+ }
92
+
93
+ // Instancia global para compartir la base de datos
94
+ const messageController = new MessageController();
95
+
96
+ module.exports = messageController;
@@ -0,0 +1,178 @@
1
+ const messageController = require('./messageController');
2
+
3
+ const pageController = {
4
+ homePage: (req, res) => {
5
+ const html = `
6
+ <!DOCTYPE html>
7
+ <html lang="es">
8
+ <head>
9
+ <meta charset="UTF-8">
10
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
11
+ <title>Inicio - API Frontend Demo</title>
12
+ <link rel="stylesheet" href="/styles.css">
13
+ </head>
14
+ <body>
15
+ <div class="container">
16
+ <header>
17
+ <h1>Bienvenido a la API Frontend Demo</h1>
18
+ <nav>
19
+ <ul>
20
+ <li><a href="/">Inicio</a></li>
21
+ <li><a href="/about">Acerca de</a></li>
22
+ <li><a href="/contact">Contacto</a></li>
23
+ <li><a href="/login">Login</a></li>
24
+ <li><a href="/api/users">Usuarios (API)</a></li>
25
+ </ul>
26
+ </nav>
27
+ </header>
28
+
29
+ <main>
30
+ <section class="hero">
31
+ <h2>Framework API SDK JS</h2>
32
+ <p>Esta es una demostración de cómo el framework puede servir tanto APIs como contenido HTML para frontends.</p>
33
+ <p>El content-type de esta página se establece desde el archivo routes.json.</p>
34
+ </section>
35
+
36
+ <section class="features">
37
+ <h3>Características</h3>
38
+ <ul>
39
+ <li>Soporte para múltiples content-types</li>
40
+ <li>Rutas parametrizadas</li>
41
+ <li>Middleware de seguridad</li>
42
+ <li>CORS configurado</li>
43
+ </ul>
44
+ </section>
45
+ </main>
46
+
47
+ <footer>
48
+ <p>&copy; 2026 API SDK JS Framework</p>
49
+ </footer>
50
+ </div>
51
+ <script src="/script.js"></script>
52
+ </body>
53
+ </html>`;
54
+
55
+ res.writeHead(200);
56
+ res.end(html);
57
+ },
58
+
59
+ aboutPage: (req, res) => {
60
+ const html = `
61
+ <!DOCTYPE html>
62
+ <html lang="es">
63
+ <head>
64
+ <meta charset="UTF-8">
65
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
66
+ <title>Acerca de - API Frontend Demo</title>
67
+ <link rel="stylesheet" href="/styles.css">
68
+ </head>
69
+ <body>
70
+ <div class="container">
71
+ <header>
72
+ <h1>Acerca de API Frontend Demo</h1>
73
+ <nav>
74
+ <ul>
75
+ <li><a href="/">Inicio</a></li>
76
+ <li><a href="/about">Acerca de</a></li>
77
+ <li><a href="/contact">Contacto</a></li>
78
+ <li><a href="/login">Login</a></li>
79
+ <li><a href="/api/users">Usuarios (API)</a></li>
80
+ </ul>
81
+ </nav>
82
+ </header>
83
+
84
+ <main>
85
+ <section>
86
+ <h2>Nuestro Framework</h2>
87
+ <p>El Framework API SDK JS es una solución completa para construir APIs seguras y escalables.</p>
88
+
89
+ <h3>Capacidades Extendidas</h3>
90
+ <p>Ahora también puede servir contenido HTML y otros tipos de contenido gracias a la nueva funcionalidad de especificación de content-type en routes.json.</p>
91
+
92
+ <h3>Características Técnicas</h3>
93
+ <ul>
94
+ <li>Arquitectura modular</li>
95
+ <li>Sistema de hooks y filtros</li>
96
+ <li>Seguridad avanzada (WAF)</li>
97
+ <li>Soporte para múltiples métodos de autenticación</li>
98
+ <li>Almacenamiento de tokens flexible</li>
99
+ </ul>
100
+ </section>
101
+ </main>
102
+
103
+ <footer>
104
+ <p>&copy; 2026 API SDK JS Framework</p>
105
+ </footer>
106
+ </div>
107
+ <script src="/script.js"></script>
108
+ </body>
109
+ </html>`;
110
+
111
+ res.writeHead(200);
112
+ res.end(html);
113
+ },
114
+
115
+ contactPage: (req, res) => {
116
+ const html = `
117
+ <!DOCTYPE html>
118
+ <html lang="es">
119
+ <head>
120
+ <meta charset="UTF-8">
121
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
122
+ <title>Contacto - API Frontend Demo</title>
123
+ <link rel="stylesheet" href="/styles.css">
124
+ </head>
125
+ <body>
126
+ <div class="container">
127
+ <header>
128
+ <h1>Formulario de Contacto</h1>
129
+ <nav>
130
+ <ul>
131
+ <li><a href="/">Inicio</a></li>
132
+ <li><a href="/about">Acerca de</a></li>
133
+ <li><a href="/contact">Contacto</a></li>
134
+ <li><a href="/login">Login</a></li>
135
+ <li><a href="/api/users">Usuarios (API)</a></li>
136
+ </ul>
137
+ </nav>
138
+ </header>
139
+
140
+ <main>
141
+ <section>
142
+ <form id="contactForm">
143
+ <div class="form-group">
144
+ <label for="name">Nombre:</label>
145
+ <input type="text" id="name" name="name" required>
146
+ </div>
147
+
148
+ <div class="form-group">
149
+ <label for="email">Email:</label>
150
+ <input type="email" id="email" name="email" required>
151
+ </div>
152
+
153
+ <div class="form-group">
154
+ <label for="message">Mensaje:</label>
155
+ <textarea id="message" name="message" rows="5" required></textarea>
156
+ </div>
157
+
158
+ <button type="submit">Enviar</button>
159
+ </form>
160
+
161
+ <div id="response"></div>
162
+ </section>
163
+ </main>
164
+
165
+ <footer>
166
+ <p>&copy; 2026 API SDK JS Framework</p>
167
+ </footer>
168
+ </div>
169
+ <script src="/script.js"></script>
170
+ </body>
171
+ </html>`;
172
+
173
+ res.writeHead(200);
174
+ res.end(html);
175
+ }
176
+ };
177
+
178
+ module.exports = pageController;
@@ -0,0 +1,167 @@
1
+ const staticController = {
2
+ getCSS: (req, res) => {
3
+ const css = `
4
+ body {
5
+ font-family: Arial, sans-serif;
6
+ margin: 0;
7
+ padding: 0;
8
+ background-color: #f5f5f5;
9
+ }
10
+
11
+ .container {
12
+ max-width: 1200px;
13
+ margin: 0 auto;
14
+ padding: 20px;
15
+ }
16
+
17
+ header {
18
+ background-color: #333;
19
+ color: white;
20
+ padding: 1rem;
21
+ border-radius: 5px;
22
+ }
23
+
24
+ header h1 {
25
+ margin: 0;
26
+ }
27
+
28
+ nav ul {
29
+ list-style-type: none;
30
+ padding: 0;
31
+ margin: 10px 0 0 0;
32
+ }
33
+
34
+ nav ul li {
35
+ display: inline;
36
+ margin-right: 20px;
37
+ }
38
+
39
+ nav ul li a {
40
+ color: white;
41
+ text-decoration: none;
42
+ padding: 5px 10px;
43
+ border-radius: 3px;
44
+ transition: background-color 0.3s;
45
+ }
46
+
47
+ nav ul li a:hover {
48
+ background-color: #555;
49
+ }
50
+
51
+ main {
52
+ margin-top: 20px;
53
+ }
54
+
55
+ .hero {
56
+ background-color: white;
57
+ padding: 2rem;
58
+ border-radius: 5px;
59
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
60
+ }
61
+
62
+ .features {
63
+ background-color: white;
64
+ padding: 2rem;
65
+ margin-top: 20px;
66
+ border-radius: 5px;
67
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
68
+ }
69
+
70
+ .form-group {
71
+ margin-bottom: 15px;
72
+ }
73
+
74
+ .form-group label {
75
+ display: block;
76
+ margin-bottom: 5px;
77
+ font-weight: bold;
78
+ }
79
+
80
+ .form-group input,
81
+ .form-group textarea {
82
+ width: 100%;
83
+ padding: 8px;
84
+ border: 1px solid #ccc;
85
+ border-radius: 4px;
86
+ box-sizing: border-box;
87
+ }
88
+
89
+ button {
90
+ background-color: #007bff;
91
+ color: white;
92
+ padding: 10px 20px;
93
+ border: none;
94
+ border-radius: 4px;
95
+ cursor: pointer;
96
+ font-size: 16px;
97
+ }
98
+
99
+ button:hover {
100
+ background-color: #0056b3;
101
+ }
102
+
103
+ footer {
104
+ margin-top: 30px;
105
+ text-align: center;
106
+ padding: 20px;
107
+ color: #666;
108
+ border-top: 1px solid #ddd;
109
+ }`;
110
+
111
+ res.writeHead(200);
112
+ res.end(css);
113
+ },
114
+
115
+ getJS: (req, res) => {
116
+ const js = `
117
+ document.addEventListener('DOMContentLoaded', function() {
118
+ const contactForm = document.getElementById('contactForm');
119
+
120
+ if (contactForm) {
121
+ contactForm.addEventListener('submit', function(e) {
122
+ e.preventDefault();
123
+
124
+ const formData = new FormData(contactForm);
125
+ const data = Object.fromEntries(formData);
126
+
127
+ // Enviar datos al servidor
128
+ fetch('/api/contact', {
129
+ method: 'POST',
130
+ headers: {
131
+ 'Content-Type': 'application/json'
132
+ },
133
+ body: JSON.stringify(data)
134
+ })
135
+ .then(response => response.json())
136
+ .then(result => {
137
+ const responseDiv = document.getElementById('response');
138
+
139
+ if (result.success) {
140
+ responseDiv.innerHTML = '<p style="color: green;">' + result.message + '</p>';
141
+ contactForm.reset();
142
+ } else {
143
+ responseDiv.innerHTML = '<p style="color: red;">Error: ' + result.message + '</p>';
144
+ }
145
+
146
+ // Ocultar mensaje después de 5 segundos
147
+ setTimeout(() => {
148
+ responseDiv.innerHTML = '';
149
+ }, 5000);
150
+ })
151
+ .catch(error => {
152
+ console.error('Error:', error);
153
+ const responseDiv = document.getElementById('response');
154
+ responseDiv.innerHTML = '<p style="color: red;">Error de conexión</p>';
155
+ });
156
+ });
157
+ }
158
+
159
+ console.log('API Frontend Demo cargado correctamente');
160
+ });`;
161
+
162
+ res.writeHead(200);
163
+ res.end(js);
164
+ }
165
+ };
166
+
167
+ module.exports = staticController;
@@ -0,0 +1,90 @@
1
+ [
2
+ {
3
+ "path": "/",
4
+ "method": "GET",
5
+ "controller": "./controllers/pageController.js",
6
+ "handler": "homePage",
7
+ "auth": "none",
8
+ "contentType": "text/html"
9
+ },
10
+ {
11
+ "path": "/about",
12
+ "method": "GET",
13
+ "controller": "./controllers/pageController.js",
14
+ "handler": "aboutPage",
15
+ "auth": "none",
16
+ "contentType": "text/html"
17
+ },
18
+ {
19
+ "path": "/contact",
20
+ "method": "GET",
21
+ "controller": "./controllers/pageController.js",
22
+ "handler": "contactPage",
23
+ "auth": "none",
24
+ "contentType": "text/html"
25
+ },
26
+ {
27
+ "path": "/login",
28
+ "method": "GET",
29
+ "controller": "./controllers/authController.js",
30
+ "handler": "showLoginPage",
31
+ "auth": "none",
32
+ "contentType": "text/html"
33
+ },
34
+ {
35
+ "path": "/messages",
36
+ "method": "GET",
37
+ "controller": "./controllers/authController.js",
38
+ "handler": "showMessages",
39
+ "auth": "session",
40
+ "contentType": "text/html"
41
+ },
42
+ {
43
+ "path": "/api/login",
44
+ "method": "POST",
45
+ "controller": "./controllers/authController.js",
46
+ "handler": "processLogin",
47
+ "auth": "none",
48
+ "contentType": "application/json"
49
+ },
50
+ {
51
+ "path": "/api/contact",
52
+ "method": "POST",
53
+ "controller": "./controllers/formController.js",
54
+ "handler": "processContactForm",
55
+ "auth": "none",
56
+ "contentType": "application/json"
57
+ },
58
+ {
59
+ "path": "/api/users",
60
+ "method": "GET",
61
+ "controller": "./controllers/apiController.js",
62
+ "handler": "getUsers",
63
+ "auth": "none",
64
+ "contentType": "application/json"
65
+ },
66
+ {
67
+ "path": "/api/users/:id",
68
+ "method": "GET",
69
+ "controller": "./controllers/apiController.js",
70
+ "handler": "getUserById",
71
+ "auth": "none",
72
+ "contentType": "application/json"
73
+ },
74
+ {
75
+ "path": "/styles.css",
76
+ "method": "GET",
77
+ "controller": "./controllers/staticController.js",
78
+ "handler": "getCSS",
79
+ "auth": "none",
80
+ "contentType": "text/css"
81
+ },
82
+ {
83
+ "path": "/script.js",
84
+ "method": "GET",
85
+ "controller": "./controllers/staticController.js",
86
+ "handler": "getJS",
87
+ "auth": "none",
88
+ "contentType": "application/javascript"
89
+ }
90
+ ]
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Ejemplo de uso del sistema MVC para el framework API SDK
3
+ * Demostración de vistas y controladores MVC
4
+ */
5
+
6
+ const { APIServer, Router, ControllerBase } = require('../../index');
7
+
8
+ // Crear un controlador personalizado que extienda ControllerBase
9
+ class HomeController extends ControllerBase {
10
+ constructor(options = {}) {
11
+ super(options);
12
+ }
13
+
14
+ // Acción para mostrar la página de inicio
15
+ index(req, res) {
16
+ // Establecer variables para la vista
17
+ this.set('title', 'Página de Inicio');
18
+ this.set('message', '¡Bienvenido al framework API SDK!');
19
+ this.set('users', [
20
+ { name: 'Juan', email: 'juan@example.com' },
21
+ { name: 'María', email: 'maria@example.com' },
22
+ { name: 'Pedro', email: 'pedro@example.com' }
23
+ ]);
24
+
25
+ // Renderizar la vista
26
+ this.render(res, 'home/index', {
27
+ currentTime: new Date().toISOString()
28
+ });
29
+ }
30
+
31
+ // Acción para mostrar el perfil de un usuario
32
+ profile(req, res) {
33
+ // Obtener el ID del usuario de los parámetros
34
+ const userIdParam = this.input('id', '1');
35
+
36
+ // Validar que el ID sea un número entero positivo (no solo que empiece con un número)
37
+ if (!/^\d+$/.test(userIdParam) || parseInt(userIdParam) <= 0) {
38
+ // Si no es un ID válido, mostrar error
39
+ this.set('title', 'ID de usuario inválido');
40
+ this.render(res, 'user/invalid', {
41
+ userId: userIdParam
42
+ });
43
+ return;
44
+ }
45
+
46
+ const userId = parseInt(userIdParam);
47
+
48
+ // Array real de usuarios
49
+ const users = [
50
+ { id: 1, name: 'Ana García', email: 'ana@example.com', registered: '2026-01-01T10:00:00Z', active: true },
51
+ { id: 2, name: 'Carlos López', email: 'carlos@example.com', registered: '2026-01-02T11:30:00Z', active: false },
52
+ { id: 3, name: 'Laura Martínez', email: 'laura@example.com', registered: '2026-01-03T14:20:00Z', active: true },
53
+ { id: 4, name: 'Pedro Rodríguez', email: 'pedro@example.com', registered: '2026-01-04T09:15:00Z', active: true },
54
+ { id: 5, name: 'María Sánchez', email: 'maria@example.com', registered: '2026-01-05T16:45:00Z', active: false }
55
+ ];
56
+
57
+ // Buscar el usuario por ID
58
+ const user = users.find(u => u.id === userId);
59
+
60
+ if (!user) {
61
+ // Si no se encuentra el usuario, mostrar error
62
+ this.set('title', 'Usuario no encontrado');
63
+ this.render(res, 'user/notfound', {
64
+ userId: userId
65
+ });
66
+ return;
67
+ }
68
+
69
+ // Establecer variables para la vista
70
+ this.set('title', `Perfil de ${user.name}`);
71
+ this.set('user', user);
72
+
73
+ // Renderizar la vista de perfil
74
+ this.render(res, 'user/profile');
75
+ }
76
+
77
+ // Acción para mostrar la lista de usuarios
78
+ users(req, res) {
79
+ // Array real de usuarios (el mismo que en profile para consistencia)
80
+ const users = [
81
+ { id: 1, name: 'Ana García', email: 'ana@example.com', registered: '2026-01-01T10:00:00Z', active: true },
82
+ { id: 2, name: 'Carlos López', email: 'carlos@example.com', registered: '2026-01-02T11:30:00Z', active: false },
83
+ { id: 3, name: 'Laura Martínez', email: 'laura@example.com', registered: '2026-01-03T14:20:00Z', active: true },
84
+ { id: 4, name: 'Pedro Rodríguez', email: 'pedro@example.com', registered: '2026-01-04T09:15:00Z', active: true },
85
+ { id: 5, name: 'María Sánchez', email: 'maria@example.com', registered: '2026-01-05T16:45:00Z', active: false }
86
+ ];
87
+
88
+ // Establecer variables para la vista
89
+ this.set('title', 'Lista de Usuarios');
90
+ this.set('users', users);
91
+
92
+ // Renderizar la vista de usuarios
93
+ this.render(res, 'user/list');
94
+ }
95
+ }
96
+
97
+ // Crear instancia del servidor
98
+ const server = new APIServer({
99
+ port: 9000,
100
+ host: 'localhost'
101
+ });
102
+
103
+ // Crear instancia del router
104
+ const router = new Router();
105
+
106
+ // Crear instancia del controlador
107
+ const homeController = new HomeController({ viewsPath: './examples/mvc_example/views' });
108
+
109
+ // Definir rutas
110
+ router
111
+ .get('/', (req, res) => {
112
+ // Establecer la solicitud y respuesta en el controlador
113
+ homeController.setRequestResponse(req, res);
114
+ homeController.index(req, res);
115
+ })
116
+ .get('/profile', (req, res) => {
117
+ homeController.setRequestResponse(req, res);
118
+ homeController.profile(req, res);
119
+ })
120
+ .get('/users', (req, res) => {
121
+ homeController.setRequestResponse(req, res);
122
+ homeController.users(req, res);
123
+ });
124
+
125
+ // Agregar las rutas del router al servidor
126
+ const routes = router.getRoutes();
127
+ for (const route of routes) {
128
+ server.addRoute(route.method, route.path, route.handler);
129
+ }
130
+
131
+ // Iniciar el servidor
132
+ server.start(() => {
133
+ console.log('Servidor MVC iniciado en http://localhost:9000');
134
+ console.log('Rutas disponibles:');
135
+ console.log('- http://localhost:9000/ (Página de inicio)');
136
+ console.log('- http://localhost:9000/profile?id=1 (Perfil de usuario)');
137
+ console.log('- http://localhost:9000/users (Lista de usuarios)');
138
+ });
@@ -0,0 +1,26 @@
1
+ <h1>{{title}}</h1>
2
+ <p>{{message}}</p>
3
+
4
+ <h2>Usuarios Registrados</h2>
5
+ {{if users}}
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <th>Nombre</th>
10
+ <th>Email</th>
11
+ </tr>
12
+ </thead>
13
+ <tbody>
14
+ {{foreach:users}}
15
+ <tr>
16
+ <td>{{item.name}}</td>
17
+ <td>{{item.email}}</td>
18
+ </tr>
19
+ {{endforeach}}
20
+ </tbody>
21
+ </table>
22
+ {{else}}
23
+ <p>No hay usuarios registrados.</p>
24
+ {{endif}}
25
+
26
+ <p>Hora actual: {{currentTime}}</p>
@@ -0,0 +1,3 @@
1
+ <h1>{{title}}</h1>
2
+ <p>{{message}}</p>
3
+ <p>Hora actual: {{currentTime}}</p>