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,247 @@
1
+ const jwt = require('jsonwebtoken');
2
+ const { Authenticator, TokenManager } = require('../../../index.js');
3
+
4
+ // TokenManager para este controlador
5
+ const tokenManager = new TokenManager({
6
+ storage: 'memory'
7
+ });
8
+
9
+ const oauthController = {
10
+ initiateGoogleAuth: (req, res) => {
11
+ // Obtener las credenciales de OAuth
12
+ const clientId = process.env.OAUTH_CLIENT_ID;
13
+ const clientSecret = process.env.OAUTH_CLIENT_SECRET;
14
+
15
+ // Verificar si las credenciales están configuradas
16
+ if (!clientId || clientId === 'tu-client-id-aqui' || !clientSecret || clientSecret === 'tu-client-secret-aqui') {
17
+ res.writeHead(200, { 'Content-Type': 'text/html' });
18
+ res.end(`
19
+ <!DOCTYPE html>
20
+ <html>
21
+ <head>
22
+ <title>Configurar OAuth con Google</title>
23
+ <style>
24
+ body { font-family: Arial, sans-serif; margin: 40px; text-align: center; }
25
+ .container { max-width: 800px; margin: 0 auto; }
26
+ .setup-instructions {
27
+ margin: 20px 0;
28
+ padding: 20px;
29
+ background-color: #fff3cd;
30
+ border: 1px solid #ffeaa7;
31
+ border-radius: 4px;
32
+ text-align: left;
33
+ }
34
+ .credentials-form {
35
+ margin: 20px 0;
36
+ padding: 20px;
37
+ background-color: #f8f9fa;
38
+ border: 1px solid #dee2e6;
39
+ border-radius: 4px;
40
+ }
41
+ input[type="text"], input[type="password"] {
42
+ width: 100%;
43
+ padding: 8px;
44
+ margin: 5px 0;
45
+ box-sizing: border-box;
46
+ }
47
+ button {
48
+ background-color: #007bff;
49
+ color: white;
50
+ border: none;
51
+ padding: 10px 20px;
52
+ cursor: pointer;
53
+ margin: 10px 5px;
54
+ }
55
+ button:hover {
56
+ background-color: #0056b3;
57
+ }
58
+ </style>
59
+ </head>
60
+ <body>
61
+ <div class="container">
62
+ <h1>Configurar OAuth con Google</h1>
63
+
64
+ <div class="setup-instructions">
65
+ <h3>Para usar la autenticación OAuth real:</h3>
66
+ <ol>
67
+ <li>Registra tu aplicación en <a href="https://console.cloud.google.com/" target="_blank">Google Cloud Console</a></li>
68
+ <li>Ve a "APIs & Services" > "Credentials"</li>
69
+ <li>Crea un "OAuth 2.0 Client IDs"</li>
70
+ <li>Configura "Authorized redirect URIs" con: <code>http://localhost:8093/auth/callback</code></li>
71
+ <li>Copia tu Client ID y Client Secret</li>
72
+ </ol>
73
+ </div>
74
+
75
+ <div class="credentials-form">
76
+ <h3>Ingresa tus credenciales OAuth</h3>
77
+ <form id="credentialsForm">
78
+ <label for="clientId">Client ID:</label>
79
+ <input type="text" id="clientId" name="clientId" placeholder="Ingresa tu Client ID">
80
+
81
+ <label for="clientSecret">Client Secret:</label>
82
+ <input type="password" id="clientSecret" name="clientSecret" placeholder="Ingresa tu Client Secret">
83
+
84
+ <div style="margin-top: 15px;">
85
+ <button type="submit">Guardar Credenciales</button>
86
+ <button type="button" onclick="location.href='/'">Volver al inicio</button>
87
+ </div>
88
+ </form>
89
+
90
+ <div id="statusMessage" style="margin-top: 15px; display: none;"></div>
91
+ </div>
92
+
93
+ <script>
94
+ document.getElementById('credentialsForm').addEventListener('submit', function(e) {
95
+ e.preventDefault();
96
+
97
+ const clientId = document.getElementById('clientId').value;
98
+ const clientSecret = document.getElementById('clientSecret').value;
99
+
100
+ // Enviar credenciales al servidor
101
+ fetch('/auth/setup', {
102
+ method: 'POST',
103
+ headers: {
104
+ 'Content-Type': 'application/json'
105
+ },
106
+ body: JSON.stringify({ clientId, clientSecret })
107
+ })
108
+ .then(response => response.json())
109
+ .then(data => {
110
+ const statusDiv = document.getElementById('statusMessage');
111
+ statusDiv.style.display = 'block';
112
+
113
+ if (data.success) {
114
+ statusDiv.innerHTML = '<p style="color: green;">Credenciales guardadas exitosamente. <a href="/auth/google">Haz clic aquí para iniciar OAuth</a></p>';
115
+ document.getElementById('credentialsForm').reset();
116
+ } else {
117
+ statusDiv.innerHTML = '<p style="color: red;">Error: ' + data.message + '</p>';
118
+ }
119
+ })
120
+ .catch(error => {
121
+ console.error('Error:', error);
122
+ document.getElementById('statusMessage').innerHTML = '<p style="color: red;">Error al guardar credenciales</p>';
123
+ document.getElementById('statusMessage').style.display = 'block';
124
+ });
125
+ });
126
+ </script>
127
+ </div>
128
+ </body>
129
+ </html>
130
+ `);
131
+ return;
132
+ }
133
+
134
+ // Si las credenciales están configuradas, crear la URL de autorización OAuth
135
+ const redirectUri = encodeURIComponent('http://localhost:8093/auth/callback');
136
+ const scope = encodeURIComponent('email profile');
137
+ const authUrl = `https://accounts.google.com/o/oauth2/v2/auth?` +
138
+ `client_id=${clientId}&` +
139
+ `redirect_uri=${redirectUri}&` +
140
+ `response_type=code&` +
141
+ `scope=${scope}&` +
142
+ `access_type=offline&` +
143
+ `prompt=consent`;
144
+
145
+ // Redirigir al usuario a la URL de autorización de Google
146
+ res.writeHead(302, { 'Location': authUrl });
147
+ res.end();
148
+ },
149
+
150
+ handleCallback: async (req, res) => {
151
+ const { code } = req.query;
152
+
153
+ if (!code) {
154
+ res.writeHead(400, { 'Content-Type': 'application/json' });
155
+ res.end(JSON.stringify({ error: 'No authorization code received' }));
156
+ return;
157
+ }
158
+
159
+ try {
160
+ // En una implementación real, intercambiaríamos el código por tokens de acceso
161
+ const clientId = process.env.OAUTH_CLIENT_ID;
162
+ const clientSecret = process.env.OAUTH_CLIENT_SECRET;
163
+ const redirectUri = 'http://localhost:8093/auth/callback';
164
+
165
+ // Simular la obtención de tokens (en una implementación real, haríamos una solicitud HTTP real)
166
+ // Aquí es donde el framework realmente haría el trabajo pesado
167
+
168
+ // Simular la obtención de información del usuario desde Google
169
+ // En una implementación real, usaríamos el access token para llamar a la API de Google
170
+ const userInfo = {
171
+ id: 'demo_user_id',
172
+ email: 'demo@example.com',
173
+ name: 'Demo User',
174
+ picture: 'https://via.placeholder.com/150'
175
+ };
176
+
177
+ // Generar un token JWT para el usuario autenticado
178
+ const secret = 'super-secret-key-for-oauth-example';
179
+ const tokenPayload = {
180
+ userId: userInfo.id,
181
+ email: userInfo.email,
182
+ name: userInfo.name,
183
+ provider: 'google',
184
+ iat: Math.floor(Date.now() / 1000),
185
+ exp: Math.floor(Date.now() / 1000) + (60 * 60) // Expira en 1 hora
186
+ };
187
+
188
+ const token = jwt.sign(tokenPayload, secret);
189
+
190
+ // Enviar respuesta con el token
191
+ res.writeHead(200, { 'Content-Type': 'text/html' });
192
+ res.end(`
193
+ <h2>¡Autenticación OAuth exitosa!</h2>
194
+ <p>Usuario autenticado: <strong>${userInfo.name}</strong></p>
195
+ <p>Email: <strong>${userInfo.email}</strong></p>
196
+ <p>Proveedor: <strong>Google</strong></p>
197
+
198
+ <div style="margin: 20px 0; padding: 15px; background-color: #d4edda; border: 1px solid #c3e6cb; border-radius: 4px;">
199
+ <p><strong>Token JWT generado:</strong></p>
200
+ <textarea readonly style="width: 100%; height: 80px; font-family: monospace;">${token}</textarea>
201
+ <p>Este token puede usarse en el header <code>Authorization: Bearer &lt;token&gt;</code> para acceder a endpoints protegidos</p>
202
+ </div>
203
+
204
+ <p><a href="/profile">Ir al perfil del usuario</a> | <a href="/">Volver a la página principal</a></p>
205
+ `);
206
+ } catch (error) {
207
+ console.error('Error en el callback OAuth:', error);
208
+ res.writeHead(500, { 'Content-Type': 'text/html' });
209
+ res.end(`
210
+ <h2>Error en el proceso de autenticación</h2>
211
+ <p>${error.message}</p>
212
+ <p><a href="/auth/google">Intentar de nuevo</a></p>
213
+ `);
214
+ }
215
+ },
216
+
217
+ setupCredentials: (req, res) => {
218
+ // Este endpoint es para fines de demostración
219
+ // En una implementación real, las credenciales se configurarían en variables de entorno
220
+ let body = '';
221
+ req.on('data', chunk => {
222
+ body += chunk.toString();
223
+ });
224
+ req.on('end', () => {
225
+ try {
226
+ const data = JSON.parse(body);
227
+
228
+ // En una implementación real, esto se haría de forma segura
229
+ // Aquí solo simulamos el proceso para fines de demostración
230
+
231
+ res.writeHead(200, { 'Content-Type': 'application/json' });
232
+ res.end(JSON.stringify({
233
+ success: true,
234
+ message: 'Credenciales recibidas. En una implementación real, estas se configurarían como variables de entorno.'
235
+ }));
236
+ } catch (error) {
237
+ res.writeHead(400, { 'Content-Type': 'application/json' });
238
+ res.end(JSON.stringify({
239
+ success: false,
240
+ message: 'Error al procesar las credenciales'
241
+ }));
242
+ }
243
+ });
244
+ }
245
+ };
246
+
247
+ module.exports = oauthController;
@@ -0,0 +1,13 @@
1
+ const protectedController = {
2
+ getProtectedData: (req, res) => {
3
+ res.writeHead(200, { 'Content-Type': 'application/json' });
4
+ res.end(JSON.stringify({
5
+ message: 'Datos protegidos accesados exitosamente',
6
+ user: req.user,
7
+ timestamp: new Date().toISOString(),
8
+ provider: 'Este contenido fue protegido usando autenticación JWT generada tras OAuth'
9
+ }));
10
+ }
11
+ };
12
+
13
+ module.exports = protectedController;
@@ -0,0 +1,17 @@
1
+ const userController = {
2
+ getProfile: (req, res) => {
3
+ res.writeHead(200, { 'Content-Type': 'application/json' });
4
+ res.end(JSON.stringify({
5
+ profile: {
6
+ id: req.user.userId,
7
+ email: req.user.email,
8
+ name: req.user.name,
9
+ provider: req.user.provider,
10
+ authenticatedAt: new Date().toISOString()
11
+ },
12
+ message: 'Perfil de usuario obtenido exitosamente'
13
+ }));
14
+ }
15
+ };
16
+
17
+ module.exports = userController;
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "api-sdk-oauth-example",
3
+ "version": "1.0.0",
4
+ "description": "Ejemplo de API con funcionalidad OAuth 2.0 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
+ "oauth",
14
+ "oauth2",
15
+ "authentication",
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,44 @@
1
+ [
2
+ {
3
+ "path": "/",
4
+ "method": "GET",
5
+ "controller": "./controllers/mainController.js",
6
+ "handler": "home",
7
+ "auth": "none"
8
+ },
9
+ {
10
+ "path": "/auth/google",
11
+ "method": "GET",
12
+ "controller": "./controllers/oauthController.js",
13
+ "handler": "initiateGoogleAuth",
14
+ "auth": "none"
15
+ },
16
+ {
17
+ "path": "/auth/callback",
18
+ "method": "GET",
19
+ "controller": "./controllers/oauthController.js",
20
+ "handler": "handleCallback",
21
+ "auth": "none"
22
+ },
23
+ {
24
+ "path": "/auth/setup",
25
+ "method": "POST",
26
+ "controller": "./controllers/oauthController.js",
27
+ "handler": "setupCredentials",
28
+ "auth": "none"
29
+ },
30
+ {
31
+ "path": "/profile",
32
+ "method": "GET",
33
+ "controller": "./controllers/userController.js",
34
+ "handler": "getProfile",
35
+ "auth": "jwt-oauth"
36
+ },
37
+ {
38
+ "path": "/protected",
39
+ "method": "GET",
40
+ "controller": "./controllers/protectedController.js",
41
+ "handler": "getProtectedData",
42
+ "auth": "jwt-oauth"
43
+ }
44
+ ]
@@ -0,0 +1,77 @@
1
+ # Ejemplo API con Funcionalidad OpenAPI
2
+
3
+ Este ejemplo demuestra cómo crear una API con funcionalidad OpenAPI integrada utilizando el Framework API SDK.
4
+
5
+ ## Características
6
+
7
+ - API con autenticación JWT
8
+ - Documentación OpenAPI 3.0 generada automáticamente
9
+ - Interfaz Swagger UI para explorar y probar la API
10
+ - Rutas protegidas y públicas
11
+ - Controladores organizados por funcionalidad
12
+ - Esquemas OpenAPI definidos para modelos de datos
13
+
14
+ ## Configuración
15
+
16
+ No se requieren dependencias adicionales más allá del Framework API SDK.
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:8092`
26
+
27
+ ## Endpoints
28
+
29
+ - `GET /` - Página de inicio
30
+ - `POST /login` - Iniciar sesión y obtener token
31
+ - `GET /users` - Lista de usuarios (requiere token)
32
+ - `GET /products` - Lista de productos (requiere token)
33
+ - `GET /profile` - Perfil de usuario (requiere token)
34
+ - `GET /docs` - Documentación interactiva OpenAPI/Swagger
35
+ - `GET /openapi.json` - Especificación OpenAPI
36
+
37
+ ## Ejemplo de uso
38
+
39
+ 1. Iniciar sesión:
40
+ ```bash
41
+ curl -X POST http://localhost:8092/login \
42
+ -H "Content-Type: application/json" \
43
+ -d '{"username": "admin", "password": "password"}'
44
+ ```
45
+
46
+ 2. Acceder a usuarios con el token:
47
+ ```bash
48
+ curl -X GET http://localhost:8092/users \
49
+ -H "Authorization: Bearer TU_TOKEN_AQUI"
50
+ ```
51
+
52
+ 3. Ver documentación interactiva:
53
+ Visita `http://localhost:8092/docs` en tu navegador
54
+
55
+ ## Estructura del proyecto
56
+
57
+ ```
58
+ examples/v2_openapi/
59
+ ├── app.js # Punto de entrada de la aplicación
60
+ ├── routes.json # Definición de rutas
61
+ ├── controllers/ # Controladores de las rutas
62
+ │ ├── mainController.js
63
+ │ ├── authController.js
64
+ │ ├── userController.js
65
+ │ └── productController.js
66
+ └── README.md
67
+ ```
68
+
69
+ ## Documentación OpenAPI
70
+
71
+ El framework genera automáticamente:
72
+ - Una especificación OpenAPI 3.0 en `/openapi.json`
73
+ - Una interfaz Swagger UI interactiva en `/docs`
74
+ - Esquemas de datos definidos para reutilización
75
+ - Documentación detallada de endpoints, parámetros y respuestas
76
+ - Soporte para diferentes códigos de respuesta HTTP
77
+ - Definición de esquemas de seguridad
@@ -0,0 +1,222 @@
1
+ const {
2
+ APIServer,
3
+ Authenticator,
4
+ RouteLoader,
5
+ Logger,
6
+ OpenApiGenerator,
7
+ TokenManager
8
+ } = require('../../index.js');
9
+
10
+ async function startServer() {
11
+ // Crear instancia del servidor
12
+ const server = new APIServer({
13
+ port: 8092,
14
+ host: 'localhost'
15
+ });
16
+
17
+ // Crear instancia del logger
18
+ const logger = new Logger({ level: 'info' });
19
+
20
+ try {
21
+ // Crear instancia del TokenManager con almacenamiento en memoria
22
+ const tokenManager = new TokenManager({
23
+ storage: 'memory'
24
+ });
25
+
26
+ // Crear instancia del autenticador
27
+ const authenticator = new Authenticator({ logger });
28
+
29
+ // Registrar estrategia de autenticación JWT
30
+ authenticator.use('jwt-openapi', 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 un secreto fijo para este ejemplo
39
+ const secret = 'super-secret-key-for-openapi-example';
40
+ const decoded = tokenManager.validateToken(token, secret);
41
+
42
+ if (decoded) {
43
+ req.user = decoded;
44
+ return true;
45
+ }
46
+
47
+ return false;
48
+ });
49
+
50
+ // Agregar el autenticador al servidor para que pueda ser usado por el RouteLoader
51
+ server.authenticator = authenticator;
52
+
53
+ // Cargar rutas desde archivo JSON
54
+ const routeLoader = new RouteLoader();
55
+ await routeLoader.loadRoutes(server, './routes.json');
56
+
57
+ // Crear instancia del generador de OpenAPI
58
+ const openApiGenerator = new OpenApiGenerator({
59
+ title: 'API de Ejemplo con OpenAPI',
60
+ description: 'Una API de ejemplo que demuestra la funcionalidad OpenAPI del Framework API SDK',
61
+ version: '1.0.0',
62
+ servers: [
63
+ { url: 'http://localhost:8092', description: 'Servidor de desarrollo' }
64
+ ]
65
+ });
66
+
67
+ // Agregar esquemas a la documentación
68
+ openApiGenerator.addSchema('User', {
69
+ type: 'object',
70
+ properties: {
71
+ id: { type: 'integer', example: 1 },
72
+ name: { type: 'string', example: 'John Doe' },
73
+ email: { type: 'string', example: 'john@example.com' },
74
+ role: { type: 'string', example: 'user' }
75
+ }
76
+ });
77
+
78
+ openApiGenerator.addSchema('Product', {
79
+ type: 'object',
80
+ properties: {
81
+ id: { type: 'integer', example: 1 },
82
+ name: { type: 'string', example: 'Laptop' },
83
+ price: { type: 'number', example: 999.99 },
84
+ category: { type: 'string', example: 'Electronics' }
85
+ }
86
+ });
87
+
88
+ openApiGenerator.addSchema('ApiResponse', {
89
+ type: 'object',
90
+ properties: {
91
+ success: { type: 'boolean', example: true },
92
+ message: { type: 'string', example: 'Operación exitosa' },
93
+ data: { type: 'object', description: 'Datos de la respuesta' }
94
+ }
95
+ });
96
+
97
+ // Agregar esquema de seguridad
98
+ openApiGenerator.addSecurityScheme('bearerAuth', {
99
+ type: 'http',
100
+ scheme: 'bearer',
101
+ bearerFormat: 'JWT',
102
+ description: 'Autenticación por token JWT'
103
+ });
104
+
105
+ // Agregar rutas a la documentación OpenAPI
106
+ openApiGenerator.addRoute({
107
+ path: '/users',
108
+ method: 'GET',
109
+ config: {
110
+ summary: 'Obtener todos los usuarios',
111
+ description: 'Devuelve una lista de todos los usuarios registrados',
112
+ security: [{ bearerAuth: [] }],
113
+ responses: {
114
+ '200': {
115
+ description: 'Lista de usuarios',
116
+ content: {
117
+ 'application/json': {
118
+ schema: {
119
+ type: 'array',
120
+ items: {
121
+ $ref: '#/components/schemas/User'
122
+ }
123
+ }
124
+ }
125
+ }
126
+ },
127
+ '401': {
128
+ description: 'No autorizado - Token inválido o ausente'
129
+ }
130
+ }
131
+ }
132
+ });
133
+
134
+ openApiGenerator.addRoute({
135
+ path: '/products',
136
+ method: 'GET',
137
+ config: {
138
+ summary: 'Obtener todos los productos',
139
+ description: 'Devuelve una lista de todos los productos disponibles',
140
+ security: [{ bearerAuth: [] }],
141
+ responses: {
142
+ '200': {
143
+ description: 'Lista de productos',
144
+ content: {
145
+ 'application/json': {
146
+ schema: {
147
+ type: 'array',
148
+ items: {
149
+ $ref: '#/components/schemas/Product'
150
+ }
151
+ }
152
+ }
153
+ }
154
+ },
155
+ '401': {
156
+ description: 'No autorizado - Token inválido o ausente'
157
+ }
158
+ }
159
+ }
160
+ });
161
+
162
+ openApiGenerator.addRoute({
163
+ path: '/login',
164
+ method: 'POST',
165
+ config: {
166
+ summary: 'Iniciar sesión',
167
+ description: 'Autenticación de usuario y obtención de token JWT',
168
+ requestBody: {
169
+ content: {
170
+ 'application/json': {
171
+ schema: {
172
+ type: 'object',
173
+ properties: {
174
+ username: { type: 'string', example: 'admin' },
175
+ password: { type: 'string', example: 'password' }
176
+ },
177
+ required: ['username', 'password']
178
+ }
179
+ }
180
+ }
181
+ },
182
+ responses: {
183
+ '200': {
184
+ description: 'Inicio de sesión exitoso',
185
+ content: {
186
+ 'application/json': {
187
+ schema: {
188
+ type: 'object',
189
+ properties: {
190
+ message: { type: 'string', example: 'Inicio de sesión exitoso' },
191
+ token: { type: 'string', example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' },
192
+ user: { $ref: '#/components/schemas/User' }
193
+ }
194
+ }
195
+ }
196
+ }
197
+ },
198
+ '401': {
199
+ description: 'Credenciales inválidas'
200
+ }
201
+ }
202
+ }
203
+ });
204
+
205
+ // Agregar ruta de documentación al servidor
206
+ openApiGenerator.addDocumentationRoute(server);
207
+
208
+ // Iniciar el servidor
209
+ server.start();
210
+
211
+ logger.info('Servidor iniciado en http://localhost:8092');
212
+ logger.info('Documentación OpenAPI disponible en http://localhost:8092/docs');
213
+ } catch (error) {
214
+ logger.error('Error iniciando el servidor:', error.message);
215
+ process.exit(1);
216
+ }
217
+ }
218
+
219
+ // Iniciar el servidor
220
+ startServer();
221
+
222
+ module.exports = { startServer };