blackcoffee2 2.1.0 → 2.1.2

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 (89) hide show
  1. package/.env.example +67 -0
  2. package/CHANGELOG.md +167 -0
  3. package/README.md +1 -3
  4. package/config/database.json +11 -0
  5. package/controllers/admin/AuthController.js +2 -1
  6. package/core/ViewHelper.js +75 -0
  7. package/core/hotReload.js +1 -1
  8. package/data/blackcoffee_admin.db-shm +0 -0
  9. package/data/blackcoffee_admin.db-wal +0 -0
  10. package/includes/adminAuth.js +5 -3
  11. package/includes/sessions.js +1 -1
  12. package/otrack.tar.gz +0 -0
  13. package/package.json +4 -2
  14. package/programatically/initFlow.js +2 -2
  15. package/test-aplicacion.con-logisession/BlackCoffee.js +0 -226
  16. package/test-aplicacion.con-logisession/SSL_SETUP.md +0 -53
  17. package/test-aplicacion.con-logisession/certs/ca-certificate.pem +0 -32
  18. package/test-aplicacion.con-logisession/certs/ca-private-key.pem +0 -52
  19. package/test-aplicacion.con-logisession/certs/certificate-2048.pem +0 -22
  20. package/test-aplicacion.con-logisession/certs/certificate.pem +0 -32
  21. package/test-aplicacion.con-logisession/certs/private-key-2048.pem +0 -28
  22. package/test-aplicacion.con-logisession/certs/private-key.pem +0 -52
  23. package/test-aplicacion.con-logisession/config/iaQueueSetup.js +0 -84
  24. package/test-aplicacion.con-logisession/config/qwen-rules.json +0 -39
  25. package/test-aplicacion.con-logisession/controllers/analyticsController.js +0 -117
  26. package/test-aplicacion.con-logisession/controllers/auth/AdminAuthController.js +0 -142
  27. package/test-aplicacion.con-logisession/controllers/auth/AuthController.js +0 -439
  28. package/test-aplicacion.con-logisession/controllers/auth/AuthViewController.js +0 -223
  29. package/test-aplicacion.con-logisession/controllers/endpointController.js +0 -66
  30. package/test-aplicacion.con-logisession/controllers/example.js +0 -183
  31. package/test-aplicacion.con-logisession/controllers/iaQueueController.js +0 -367
  32. package/test-aplicacion.con-logisession/controllers/queueController.js +0 -206
  33. package/test-aplicacion.con-logisession/controllers/qwenQueueController.js +0 -197
  34. package/test-aplicacion.con-logisession/controllers/test.js +0 -0
  35. package/test-aplicacion.con-logisession/controllers/tracking/EventsNoFinishController.js +0 -78
  36. package/test-aplicacion.con-logisession/controllers/tracking/TrackingController.js +0 -412
  37. package/test-aplicacion.con-logisession/controllers/tracking/TrackingControllerWithLoadModel.js +0 -437
  38. package/test-aplicacion.con-logisession/hooks/admin-hooks.js +0 -20
  39. package/test-aplicacion.con-logisession/hooks/general-hooks.js +0 -97
  40. package/test-aplicacion.con-logisession/hooks/queue-hooks.js +0 -64
  41. package/test-aplicacion.con-logisession/hooks/route-directory-hooks.js +0 -38
  42. package/test-aplicacion.con-logisession/hooks/security-hooks.js +0 -24
  43. package/test-aplicacion.con-logisession/insitu-admin-client/README.md +0 -69
  44. package/test-aplicacion.con-logisession/insitu-admin-client/package.json +0 -23
  45. package/test-aplicacion.con-logisession/insitu-admin-client.js +0 -257
  46. package/test-aplicacion.con-logisession/models/ExampleModel.js +0 -88
  47. package/test-aplicacion.con-logisession/models/QueueJobModel.js +0 -263
  48. package/test-aplicacion.con-logisession/models/TokenModel.js +0 -207
  49. package/test-aplicacion.con-logisession/models/auth/AuthModel.js +0 -66
  50. package/test-aplicacion.con-logisession/models/auth/UserModel.js +0 -189
  51. package/test-aplicacion.con-logisession/models/tracking/CompletedCartModel.js +0 -213
  52. package/test-aplicacion.con-logisession/models/tracking/EventModel.js +0 -366
  53. package/test-aplicacion.con-logisession/models/tracking/EventsNoFinishModel.js +0 -131
  54. package/test-aplicacion.con-logisession/models/tracking/SessionModel.js +0 -360
  55. package/test-aplicacion.con-logisession/models/tracking/SiteFlowModel.js +0 -286
  56. package/test-aplicacion.con-logisession/models/tracking/TokenModel.js +0 -207
  57. package/test-aplicacion.con-logisession/package-lock.json +0 -3313
  58. package/test-aplicacion.con-logisession/package.json +0 -32
  59. package/test-aplicacion.con-logisession/public/blackcoffee-welcome/index.html +0 -1339
  60. package/test-aplicacion.con-logisession/public/css/style.css +0 -64
  61. package/test-aplicacion.con-logisession/public/ejemplo-estatica/index.html +0 -18
  62. package/test-aplicacion.con-logisession/public/ejemplo-estatica/script.js +0 -16
  63. package/test-aplicacion.con-logisession/public/ejemplo-estatica/styles.css +0 -43
  64. package/test-aplicacion.con-logisession/public/images/logo.svg +0 -7
  65. package/test-aplicacion.con-logisession/public/js/main.js +0 -67
  66. package/test-aplicacion.con-logisession/routes/analytics-routes.json +0 -8
  67. package/test-aplicacion.con-logisession/routes/auth-routes.json +0 -98
  68. package/test-aplicacion.con-logisession/routes/blackcoffee-welcome-routes.json +0 -20
  69. package/test-aplicacion.con-logisession/routes/duplicate-test-routes.json.disabled +0 -16
  70. package/test-aplicacion.con-logisession/routes/ejemplo-estatica-routes.json +0 -11
  71. package/test-aplicacion.con-logisession/routes/endpoints-routes.json +0 -8
  72. package/test-aplicacion.con-logisession/routes/ia-queue-routes.json +0 -26
  73. package/test-aplicacion.con-logisession/routes/product-routes.json.disabled +0 -20
  74. package/test-aplicacion.con-logisession/routes/queue-routes.json +0 -32
  75. package/test-aplicacion.con-logisession/routes/qwen-routes.json +0 -14
  76. package/test-aplicacion.con-logisession/routes/static-routes.json +0 -29
  77. package/test-aplicacion.con-logisession/routes/tracking-routes.json +0 -58
  78. package/test-aplicacion.con-logisession/routes/tracking-with-loadmodel-routes.json +0 -51
  79. package/test-aplicacion.con-logisession/utils/dbAdapter.js +0 -88
  80. package/test-aplicacion.con-logisession/utils/qbWrapper.js +0 -4
  81. package/test-aplicacion.con-logisession/utils/queueProcessor.js +0 -305
  82. package/test-aplicacion.con-logisession/utils/qwenRulesService.js +0 -131
  83. package/test-aplicacion.con-logisession/utils/tokenHelper.js +0 -22
  84. package/test-aplicacion.con-logisession/views/auth/dashboard.html +0 -443
  85. package/test-aplicacion.con-logisession/views/auth/forgot-password.html +0 -200
  86. package/test-aplicacion.con-logisession/views/auth/login.html +0 -213
  87. package/test-aplicacion.con-logisession/views/auth/register.html +0 -294
  88. package/test-aplicacion.con-logisession/views/contact/form.html +0 -47
  89. package/test-aplicacion.con-logisession/views/products/index.html +0 -39
@@ -1,1339 +0,0 @@
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>BlackCoffee - Servidor Full-Stack</title>
7
- <meta name="description" content="BlackCoffee es un servidor full-stack de código abierto construido sobre el framework insitu-js.">
8
- <style>
9
- *, *::before, *::after {
10
- box-sizing: border-box;
11
- margin: 0;
12
- padding: 0;
13
- }
14
-
15
- :root {
16
- --bg-primary: #0f0f0f;
17
- --bg-secondary: #1a1a1a;
18
- --bg-tertiary: #242424;
19
- --accent: #c0a062;
20
- --accent-hover: #d4b476;
21
- --text-primary: #e0e0e0;
22
- --text-secondary: #a0a0a0;
23
- --text-muted: #707070;
24
- --code-bg: #0d0d0d;
25
- --border: #333333;
26
- --shadow: rgba(0, 0, 0, 0.4);
27
- --transition: all 0.3s ease;
28
- }
29
-
30
- html {
31
- scroll-behavior: smooth;
32
- }
33
-
34
- body {
35
- font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
36
- background-color: var(--bg-primary);
37
- color: var(--text-primary);
38
- line-height: 1.6;
39
- min-height: 100vh;
40
- }
41
-
42
- /* Header */
43
- .header {
44
- position: fixed;
45
- top: 0;
46
- left: 0;
47
- right: 0;
48
- background: rgba(15, 15, 15, 0.95);
49
- backdrop-filter: blur(10px);
50
- border-bottom: 1px solid var(--border);
51
- z-index: 1000;
52
- padding: 1rem 2rem;
53
- }
54
-
55
- .header-content {
56
- max-width: 1200px;
57
- margin: 0 auto;
58
- display: flex;
59
- justify-content: space-between;
60
- align-items: center;
61
- }
62
-
63
- .logo {
64
- display: flex;
65
- align-items: center;
66
- gap: 0.75rem;
67
- text-decoration: none;
68
- color: var(--text-primary);
69
- }
70
-
71
- .logo-icon {
72
- width: 40px;
73
- height: 40px;
74
- }
75
-
76
- .logo-text {
77
- font-size: 1.5rem;
78
- font-weight: 700;
79
- color: var(--accent);
80
- }
81
-
82
- .version-badge {
83
- background: var(--bg-tertiary);
84
- color: var(--accent);
85
- padding: 0.25rem 0.75rem;
86
- border-radius: 20px;
87
- font-size: 0.8rem;
88
- font-weight: 500;
89
- border: 1px solid var(--border);
90
- }
91
-
92
- .nav {
93
- display: flex;
94
- gap: 2rem;
95
- align-items: center;
96
- }
97
-
98
- .nav-link {
99
- color: var(--text-secondary);
100
- text-decoration: none;
101
- font-weight: 500;
102
- transition: var(--transition);
103
- }
104
-
105
- .nav-link:hover {
106
- color: var(--accent);
107
- }
108
-
109
- .status-indicator {
110
- display: flex;
111
- align-items: center;
112
- gap: 0.5rem;
113
- color: #4ade80;
114
- font-size: 0.9rem;
115
- }
116
-
117
- .status-dot {
118
- width: 8px;
119
- height: 8px;
120
- background: #4ade80;
121
- border-radius: 50%;
122
- animation: pulse 2s infinite;
123
- }
124
-
125
- @keyframes pulse {
126
- 0%, 100% { opacity: 1; }
127
- 50% { opacity: 0.5; }
128
- }
129
-
130
- /* Hero Section */
131
- .hero {
132
- min-height: 100vh;
133
- display: flex;
134
- align-items: center;
135
- justify-content: center;
136
- padding: 8rem 2rem 4rem;
137
- position: relative;
138
- overflow: hidden;
139
- }
140
-
141
- .hero::before {
142
- content: '';
143
- position: absolute;
144
- top: -50%;
145
- left: -50%;
146
- width: 200%;
147
- height: 200%;
148
- background: radial-gradient(circle at 30% 30%, rgba(192, 160, 98, 0.03) 0%, transparent 50%),
149
- radial-gradient(circle at 70% 70%, rgba(192, 160, 98, 0.02) 0%, transparent 50%);
150
- pointer-events: none;
151
- }
152
-
153
- .hero-content {
154
- max-width: 800px;
155
- text-align: center;
156
- position: relative;
157
- z-index: 1;
158
- }
159
-
160
- .hero-icon {
161
- width: 120px;
162
- height: 120px;
163
- margin: 0 auto 2rem;
164
- opacity: 0.9;
165
- }
166
-
167
- .hero h1 {
168
- font-size: 3.5rem;
169
- font-weight: 800;
170
- margin-bottom: 1rem;
171
- background: linear-gradient(135deg, var(--text-primary) 0%, var(--accent) 100%);
172
- -webkit-background-clip: text;
173
- -webkit-text-fill-color: transparent;
174
- background-clip: text;
175
- }
176
-
177
- .hero-subtitle {
178
- font-size: 1.25rem;
179
- color: var(--text-secondary);
180
- margin-bottom: 2.5rem;
181
- max-width: 600px;
182
- margin-left: auto;
183
- margin-right: auto;
184
- }
185
-
186
- .hero-code {
187
- background: var(--code-bg);
188
- border: 1px solid var(--border);
189
- border-radius: 12px;
190
- padding: 1.5rem;
191
- text-align: left;
192
- position: relative;
193
- margin-bottom: 2rem;
194
- }
195
-
196
- .hero-code-header {
197
- display: flex;
198
- justify-content: space-between;
199
- align-items: center;
200
- margin-bottom: 1rem;
201
- }
202
-
203
- .hero-code-label {
204
- color: var(--text-muted);
205
- font-size: 0.85rem;
206
- display: flex;
207
- align-items: center;
208
- gap: 0.5rem;
209
- }
210
-
211
- .copy-btn {
212
- background: var(--bg-tertiary);
213
- border: 1px solid var(--border);
214
- color: var(--text-secondary);
215
- padding: 0.4rem 0.8rem;
216
- border-radius: 6px;
217
- cursor: pointer;
218
- font-size: 0.8rem;
219
- transition: var(--transition);
220
- display: flex;
221
- align-items: center;
222
- gap: 0.4rem;
223
- }
224
-
225
- .copy-btn:hover {
226
- background: var(--accent);
227
- color: var(--bg-primary);
228
- border-color: var(--accent);
229
- }
230
-
231
- .hero-code code {
232
- font-family: 'Fira Code', Consolas, 'Courier New', monospace;
233
- color: var(--accent);
234
- font-size: 0.95rem;
235
- line-height: 1.8;
236
- }
237
-
238
- .hero-code .comment {
239
- color: var(--text-muted);
240
- }
241
-
242
- .hero-code .keyword {
243
- color: #c792ea;
244
- }
245
-
246
- .hero-code .string {
247
- color: #c3e88d;
248
- }
249
-
250
- .hero-actions {
251
- display: flex;
252
- gap: 1rem;
253
- justify-content: center;
254
- flex-wrap: wrap;
255
- }
256
-
257
- .btn {
258
- padding: 0.875rem 1.75rem;
259
- border-radius: 8px;
260
- font-weight: 600;
261
- text-decoration: none;
262
- transition: var(--transition);
263
- display: inline-flex;
264
- align-items: center;
265
- gap: 0.5rem;
266
- cursor: pointer;
267
- border: none;
268
- font-size: 1rem;
269
- }
270
-
271
- .btn-primary {
272
- background: var(--accent);
273
- color: var(--bg-primary);
274
- }
275
-
276
- .btn-primary:hover {
277
- background: var(--accent-hover);
278
- transform: translateY(-2px);
279
- box-shadow: 0 8px 25px rgba(192, 160, 98, 0.3);
280
- }
281
-
282
- .btn-secondary {
283
- background: var(--bg-tertiary);
284
- color: var(--text-primary);
285
- border: 1px solid var(--border);
286
- }
287
-
288
- .btn-secondary:hover {
289
- border-color: var(--accent);
290
- color: var(--accent);
291
- }
292
-
293
- /* Features Section */
294
- .features {
295
- padding: 6rem 2rem;
296
- background: var(--bg-secondary);
297
- }
298
-
299
- .section-header {
300
- text-align: center;
301
- max-width: 600px;
302
- margin: 0 auto 4rem;
303
- }
304
-
305
- .section-header h2 {
306
- font-size: 2.5rem;
307
- font-weight: 700;
308
- margin-bottom: 1rem;
309
- color: var(--text-primary);
310
- }
311
-
312
- .section-header p {
313
- color: var(--text-secondary);
314
- font-size: 1.1rem;
315
- }
316
-
317
- .features-grid {
318
- max-width: 1200px;
319
- margin: 0 auto;
320
- display: grid;
321
- grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
322
- gap: 1.5rem;
323
- }
324
-
325
- .feature-card {
326
- background: var(--bg-primary);
327
- border: 1px solid var(--border);
328
- border-radius: 16px;
329
- padding: 2rem;
330
- transition: var(--transition);
331
- position: relative;
332
- overflow: hidden;
333
- }
334
-
335
- .feature-card::before {
336
- content: '';
337
- position: absolute;
338
- top: 0;
339
- left: 0;
340
- right: 0;
341
- height: 3px;
342
- background: var(--accent);
343
- transform: scaleX(0);
344
- transition: var(--transition);
345
- }
346
-
347
- .feature-card:hover {
348
- transform: translateY(-5px);
349
- border-color: var(--accent);
350
- box-shadow: 0 20px 40px var(--shadow);
351
- }
352
-
353
- .feature-card:hover::before {
354
- transform: scaleX(1);
355
- }
356
-
357
- .feature-icon {
358
- width: 56px;
359
- height: 56px;
360
- background: var(--bg-tertiary);
361
- border-radius: 12px;
362
- display: flex;
363
- align-items: center;
364
- justify-content: center;
365
- margin-bottom: 1.5rem;
366
- color: var(--accent);
367
- }
368
-
369
- .feature-card h3 {
370
- font-size: 1.25rem;
371
- font-weight: 600;
372
- margin-bottom: 0.75rem;
373
- color: var(--text-primary);
374
- }
375
-
376
- .feature-card p {
377
- color: var(--text-secondary);
378
- font-size: 0.95rem;
379
- line-height: 1.7;
380
- }
381
-
382
- /* Architecture Section */
383
- .architecture {
384
- padding: 6rem 2rem;
385
- }
386
-
387
- .architecture-content {
388
- max-width: 1200px;
389
- margin: 0 auto;
390
- display: grid;
391
- grid-template-columns: 1fr 1fr;
392
- gap: 4rem;
393
- align-items: center;
394
- }
395
-
396
- .architecture-text h2 {
397
- font-size: 2.5rem;
398
- font-weight: 700;
399
- margin-bottom: 1.5rem;
400
- color: var(--text-primary);
401
- }
402
-
403
- .architecture-text p {
404
- color: var(--text-secondary);
405
- font-size: 1.1rem;
406
- margin-bottom: 2rem;
407
- }
408
-
409
- .architecture-list {
410
- list-style: none;
411
- }
412
-
413
- .architecture-list li {
414
- display: flex;
415
- align-items: flex-start;
416
- gap: 1rem;
417
- margin-bottom: 1.25rem;
418
- color: var(--text-secondary);
419
- }
420
-
421
- .architecture-list .icon {
422
- width: 24px;
423
- height: 24px;
424
- color: var(--accent);
425
- flex-shrink: 0;
426
- margin-top: 0.2rem;
427
- }
428
-
429
- .architecture-diagram {
430
- background: var(--bg-secondary);
431
- border: 1px solid var(--border);
432
- border-radius: 16px;
433
- padding: 2rem;
434
- }
435
-
436
- .diagram-flow {
437
- display: flex;
438
- flex-direction: column;
439
- gap: 1rem;
440
- }
441
-
442
- .diagram-row {
443
- display: flex;
444
- justify-content: center;
445
- gap: 1rem;
446
- }
447
-
448
- .diagram-node {
449
- background: var(--bg-tertiary);
450
- border: 1px solid var(--border);
451
- border-radius: 10px;
452
- padding: 1rem 1.5rem;
453
- text-align: center;
454
- min-width: 120px;
455
- transition: var(--transition);
456
- }
457
-
458
- .diagram-node:hover {
459
- border-color: var(--accent);
460
- color: var(--accent);
461
- }
462
-
463
- .diagram-node.primary {
464
- background: var(--accent);
465
- color: var(--bg-primary);
466
- border-color: var(--accent);
467
- font-weight: 600;
468
- }
469
-
470
- .diagram-arrow {
471
- display: flex;
472
- justify-content: center;
473
- color: var(--accent);
474
- padding: 0.5rem 0;
475
- }
476
-
477
- /* Examples Section */
478
- .examples {
479
- padding: 6rem 2rem;
480
- background: var(--bg-secondary);
481
- }
482
-
483
- .examples-container {
484
- max-width: 900px;
485
- margin: 0 auto;
486
- }
487
-
488
- .tabs {
489
- display: flex;
490
- gap: 0.5rem;
491
- margin-bottom: 2rem;
492
- border-bottom: 1px solid var(--border);
493
- padding-bottom: 0.5rem;
494
- overflow-x: auto;
495
- }
496
-
497
- .tab-btn {
498
- background: transparent;
499
- border: none;
500
- color: var(--text-secondary);
501
- padding: 0.75rem 1.5rem;
502
- font-size: 0.95rem;
503
- cursor: pointer;
504
- border-radius: 8px 8px 0 0;
505
- transition: var(--transition);
506
- white-space: nowrap;
507
- }
508
-
509
- .tab-btn:hover {
510
- color: var(--text-primary);
511
- background: var(--bg-tertiary);
512
- }
513
-
514
- .tab-btn.active {
515
- color: var(--accent);
516
- background: var(--bg-tertiary);
517
- border-bottom: 2px solid var(--accent);
518
- }
519
-
520
- .tab-content {
521
- display: none;
522
- animation: fadeIn 0.3s ease;
523
- }
524
-
525
- .tab-content.active {
526
- display: block;
527
- }
528
-
529
- @keyframes fadeIn {
530
- from { opacity: 0; transform: translateY(10px); }
531
- to { opacity: 1; transform: translateY(0); }
532
- }
533
-
534
- .code-block {
535
- background: var(--code-bg);
536
- border: 1px solid var(--border);
537
- border-radius: 12px;
538
- overflow: hidden;
539
- }
540
-
541
- .code-header {
542
- display: flex;
543
- justify-content: space-between;
544
- align-items: center;
545
- padding: 1rem 1.5rem;
546
- background: var(--bg-tertiary);
547
- border-bottom: 1px solid var(--border);
548
- }
549
-
550
- .code-lang {
551
- color: var(--text-muted);
552
- font-size: 0.85rem;
553
- }
554
-
555
- .code-body {
556
- padding: 1.5rem;
557
- overflow-x: auto;
558
- }
559
-
560
- .code-body pre {
561
- font-family: 'Fira Code', Consolas, 'Courier New', monospace;
562
- font-size: 0.9rem;
563
- line-height: 1.8;
564
- color: var(--text-primary);
565
- margin: 0;
566
- }
567
-
568
- .code-body .comment { color: var(--text-muted); }
569
- .code-body .keyword { color: #c792ea; }
570
- .code-body .function { color: #82aaff; }
571
- .code-body .string { color: #c3e88d; }
572
- .code-body .property { color: #ffcb6b; }
573
- .code-body .method { color: #82aaff; }
574
- .code-body .param { color: #f78c6c; }
575
-
576
- /* Directory Structure */
577
- .structure {
578
- padding: 6rem 2rem;
579
- }
580
-
581
- .structure-content {
582
- max-width: 900px;
583
- margin: 0 auto;
584
- }
585
-
586
- .structure-tree {
587
- background: var(--code-bg);
588
- border: 1px solid var(--border);
589
- border-radius: 12px;
590
- padding: 2rem;
591
- font-family: 'Fira Code', Consolas, 'Courier New', monospace;
592
- font-size: 0.9rem;
593
- line-height: 2;
594
- }
595
-
596
- .folder {
597
- color: var(--accent);
598
- }
599
-
600
- .file {
601
- color: var(--text-primary);
602
- }
603
-
604
- .comment-line {
605
- color: var(--text-muted);
606
- }
607
-
608
- /* Footer */
609
- .footer {
610
- padding: 4rem 2rem 2rem;
611
- background: var(--bg-secondary);
612
- border-top: 1px solid var(--border);
613
- }
614
-
615
- .footer-content {
616
- max-width: 1200px;
617
- margin: 0 auto;
618
- display: grid;
619
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
620
- gap: 3rem;
621
- }
622
-
623
- .footer-section h4 {
624
- color: var(--text-primary);
625
- font-size: 1rem;
626
- margin-bottom: 1.5rem;
627
- font-weight: 600;
628
- }
629
-
630
- .footer-links {
631
- list-style: none;
632
- }
633
-
634
- .footer-links li {
635
- margin-bottom: 0.75rem;
636
- }
637
-
638
- .footer-links a {
639
- color: var(--text-secondary);
640
- text-decoration: none;
641
- transition: var(--transition);
642
- font-size: 0.9rem;
643
- }
644
-
645
- .footer-links a:hover {
646
- color: var(--accent);
647
- }
648
-
649
- .footer-bottom {
650
- max-width: 1200px;
651
- margin: 3rem auto 0;
652
- padding-top: 2rem;
653
- border-top: 1px solid var(--border);
654
- display: flex;
655
- justify-content: space-between;
656
- align-items: center;
657
- flex-wrap: wrap;
658
- gap: 1rem;
659
- }
660
-
661
- .footer-bottom p {
662
- color: var(--text-muted);
663
- font-size: 0.9rem;
664
- }
665
-
666
- .social-links {
667
- display: flex;
668
- gap: 1rem;
669
- }
670
-
671
- .social-link {
672
- width: 40px;
673
- height: 40px;
674
- background: var(--bg-tertiary);
675
- border: 1px solid var(--border);
676
- border-radius: 8px;
677
- display: flex;
678
- align-items: center;
679
- justify-content: center;
680
- color: var(--text-secondary);
681
- transition: var(--transition);
682
- }
683
-
684
- .social-link:hover {
685
- border-color: var(--accent);
686
- color: var(--accent);
687
- }
688
-
689
- /* Responsive */
690
- @media (max-width: 768px) {
691
- .header {
692
- padding: 1rem;
693
- }
694
-
695
- .nav {
696
- display: none;
697
- }
698
-
699
- .hero {
700
- padding: 6rem 1rem 3rem;
701
- }
702
-
703
- .hero h1 {
704
- font-size: 2.5rem;
705
- }
706
-
707
- .hero-subtitle {
708
- font-size: 1.1rem;
709
- }
710
-
711
- .architecture-content {
712
- grid-template-columns: 1fr;
713
- }
714
-
715
- .features-grid {
716
- grid-template-columns: 1fr;
717
- }
718
-
719
- .section-header h2,
720
- .architecture-text h2 {
721
- font-size: 2rem;
722
- }
723
-
724
- .footer-bottom {
725
- flex-direction: column;
726
- text-align: center;
727
- }
728
- }
729
-
730
- /* Scrollbar */
731
- ::-webkit-scrollbar {
732
- width: 8px;
733
- height: 8px;
734
- }
735
-
736
- ::-webkit-scrollbar-track {
737
- background: var(--bg-primary);
738
- }
739
-
740
- ::-webkit-scrollbar-thumb {
741
- background: var(--border);
742
- border-radius: 4px;
743
- }
744
-
745
- ::-webkit-scrollbar-thumb:hover {
746
- background: var(--accent);
747
- }
748
- </style>
749
- </head>
750
- <body>
751
- <!-- Header -->
752
- <header class="header">
753
- <div class="header-content">
754
- <a href="#" class="logo">
755
- <svg class="logo-icon" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
756
- <circle cx="20" cy="20" r="18" stroke="#c0a062" stroke-width="2"/>
757
- <path d="M12 20 C12 15, 15 12, 20 12 C25 12, 28 15, 28 20" stroke="#c0a062" stroke-width="2" fill="none"/>
758
- <path d="M28 20 C28 25, 25 28, 20 28 C15 28, 12 25, 12 20" stroke="#c0a062" stroke-width="2" fill="none"/>
759
- <circle cx="20" cy="20" r="4" fill="#c0a062"/>
760
- </svg>
761
- <span class="logo-text">BlackCoffee</span>
762
- </a>
763
- <nav class="nav">
764
- <a href="#features" class="nav-link">Características</a>
765
- <a href="#architecture" class="nav-link">Arquitectura</a>
766
- <a href="#examples" class="nav-link">Ejemplos</a>
767
- <a href="#docs" class="nav-link">Documentación</a>
768
- </nav>
769
- <div class="status-indicator">
770
- <span class="status-dot"></span>
771
- <span>Running</span>
772
- </div>
773
- </div>
774
- </header>
775
-
776
- <!-- Hero Section -->
777
- <section class="hero">
778
- <div class="hero-content">
779
- <svg class="hero-icon" viewBox="0 0 120 120" fill="none" xmlns="http://www.w3.org/2000/svg">
780
- <circle cx="60" cy="60" r="55" stroke="#c0a062" stroke-width="3"/>
781
- <circle cx="60" cy="60" r="40" stroke="#c0a062" stroke-width="2" opacity="0.5"/>
782
- <circle cx="60" cy="60" r="25" stroke="#c0a062" stroke-width="2" opacity="0.3"/>
783
- <circle cx="60" cy="60" r="10" fill="#c0a062"/>
784
- <path d="M60 10 L60 25 M60 95 L60 110 M10 60 L25 60 M95 60 L110 60" stroke="#c0a062" stroke-width="2" opacity="0.5"/>
785
- <path d="M22 22 L42 42 M78 78 L98 98 M22 98 L42 78 M78 42 L98 22" stroke="#c0a062" stroke-width="2" opacity="0.3"/>
786
- </svg>
787
- <h1>BlackCoffee está sirviendo</h1>
788
- <p class="hero-subtitle">
789
- Servidor full-stack de código abierto construido sobre el framework insitu-js.
790
- Una solución ligera y flexible para construir aplicaciones web completas.
791
- </p>
792
- <div class="hero-code">
793
- <div class="hero-code-header">
794
- <span class="hero-code-label">
795
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
796
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
797
- <polyline points="14 2 14 8 20 8"/>
798
- <line x1="16" y1="13" x2="8" y2="13"/>
799
- <line x1="16" y1="17" x2="8" y2="17"/>
800
- <polyline points="10 9 9 9 8 9"/>
801
- </svg>
802
- Inicio Rápido
803
- </span>
804
- <button class="copy-btn" onclick="copyCode(this)">
805
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
806
- <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
807
- <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
808
- </svg>
809
- Copiar
810
- </button>
811
- </div>
812
- <code>
813
- <span class="comment"># Instalar BlackCoffee</span><br>
814
- npm install -g blackcoffee<br><br>
815
- <span class="comment"># Crear nuevo proyecto</span><br>
816
- blackcoffee create mi-proyecto<br><br>
817
- <span class="comment"># Iniciar servidor</span><br>
818
- cd mi-proyecto && node BlackCoffee.js
819
- </code>
820
- </div>
821
- <div class="hero-actions">
822
- <a href="#examples" class="btn btn-primary">
823
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
824
- <polygon points="5 3 19 12 5 21 5 3"/>
825
- </svg>
826
- Ver Ejemplos
827
- </a>
828
- <a href="#docs" class="btn btn-secondary">
829
- <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
830
- <path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/>
831
- <path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/>
832
- </svg>
833
- Documentación
834
- </a>
835
- </div>
836
- </div>
837
- </section>
838
-
839
- <!-- Features Section -->
840
- <section id="features" class="features">
841
- <div class="section-header">
842
- <h2>Características Principales</h2>
843
- <p>Todo lo que necesitas para construir aplicaciones web modernas de manera eficiente y escalable.</p>
844
- </div>
845
- <div class="features-grid">
846
- <div class="feature-card">
847
- <div class="feature-icon">
848
- <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
849
- <polyline points="16 18 22 12 16 6"/>
850
- <polyline points="8 6 2 12 8 18"/>
851
- </svg>
852
- </div>
853
- <h3>Framework insitu-js</h3>
854
- <p>Construido sobre el potente framework insitu-js que proporciona una arquitectura modular y extensible para tus aplicaciones.</p>
855
- </div>
856
- <div class="feature-card">
857
- <div class="feature-icon">
858
- <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
859
- <circle cx="12" cy="12" r="3"/>
860
- <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/>
861
- </svg>
862
- </div>
863
- <h3>Sistema de Hooks</h3>
864
- <p>Implementa un sistema de hooks flexible para extender funcionalidades y personalizar el comportamiento del servidor en puntos específicos.</p>
865
- </div>
866
- <div class="feature-card">
867
- <div class="feature-icon">
868
- <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
869
- <circle cx="12" cy="12" r="10"/>
870
- <line x1="2" y1="12" x2="22" y2="12"/>
871
- <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/>
872
- </svg>
873
- </div>
874
- <h3>Gestión de Rutas</h3>
875
- <p>Sistema flexible para definir rutas mediante archivos JSON configurables, facilitando la organización y mantenimiento del código.</p>
876
- </div>
877
- <div class="feature-card">
878
- <div class="feature-icon">
879
- <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
880
- <rect x="3" y="3" width="18" height="18" rx="2" ry="2"/>
881
- <line x1="3" y1="9" x2="21" y2="9"/>
882
- <line x1="9" y1="21" x2="9" y2="9"/>
883
- </svg>
884
- </div>
885
- <h3>Arquitectura MVC</h3>
886
- <p>Soporte completo para el patrón MVC con controladores, modelos y vistas para un desarrollo organizado y mantenible.</p>
887
- </div>
888
- <div class="feature-card">
889
- <div class="feature-icon">
890
- <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
891
- <rect x="2" y="3" width="20" height="14" rx="2" ry="2"/>
892
- <line x1="8" y1="21" x2="16" y2="21"/>
893
- <line x1="12" y1="17" x2="12" y2="21"/>
894
- </svg>
895
- </div>
896
- <h3>Backend y Frontend</h3>
897
- <p>Capacidad completa para manejar tanto la lógica del servidor como la presentación de interfaces web en un solo framework.</p>
898
- </div>
899
- <div class="feature-card">
900
- <div class="feature-icon">
901
- <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
902
- <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
903
- <polyline points="14 2 14 8 20 8"/>
904
- <line x1="16" y1="13" x2="8" y2="13"/>
905
- <line x1="16" y1="17" x2="8" y2="17"/>
906
- <polyline points="10 9 9 9 8 9"/>
907
- </svg>
908
- </div>
909
- <h3>Registro de Actividad</h3>
910
- <p>Sistema de logging detallado con diferentes niveles para monitorear todas las interacciones del servidor de manera eficiente.</p>
911
- </div>
912
- <div class="feature-card">
913
- <div class="feature-icon">
914
- <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
915
- <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>
916
- </svg>
917
- </div>
918
- <h3>Archivos Estáticos</h3>
919
- <p>Servidor de contenido estático integrado para recursos como CSS, imágenes y JavaScript del lado del cliente.</p>
920
- </div>
921
- </div>
922
- </section>
923
-
924
- <!-- Architecture Section -->
925
- <section id="architecture" class="architecture">
926
- <div class="architecture-content">
927
- <div class="architecture-text">
928
- <h2>Arquitectura Modular</h2>
929
- <p>BlackCoffee sigue una arquitectura modular que facilita la comprensión, extensión y mantenimiento del código.</p>
930
- <ul class="architecture-list">
931
- <li>
932
- <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
933
- <polyline points="20 6 9 17 4 12"/>
934
- </svg>
935
- <span><strong>Servidor API:</strong> Basado en el módulo APIServer de insitu-js para gestión eficiente de conexiones.</span>
936
- </li>
937
- <li>
938
- <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
939
- <polyline points="20 6 9 17 4 12"/>
940
- </svg>
941
- <span><strong>Sistema de Logging:</strong> Diferentes niveles de detalle ajustables según el entorno.</span>
942
- </li>
943
- <li>
944
- <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
945
- <polyline points="20 6 9 17 4 12"/>
946
- </svg>
947
- <span><strong>Cargador de Rutas:</strong> Carga dinámica de rutas desde archivos JSON configurables.</span>
948
- </li>
949
- <li>
950
- <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
951
- <polyline points="20 6 9 17 4 12"/>
952
- </svg>
953
- <span><strong>Controladores y Modelos:</strong> Clases extensibles para lógica de negocio y acceso a datos.</span>
954
- </li>
955
- <li>
956
- <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
957
- <polyline points="20 6 9 17 4 12"/>
958
- </svg>
959
- <span><strong>Motor de Vistas:</strong> Sistema de plantillas para generación de contenido HTML dinámico.</span>
960
- </li>
961
- </ul>
962
- </div>
963
- <div class="architecture-diagram">
964
- <svg viewBox="0 0 400 350" fill="none" xmlns="http://www.w3.org/2000/svg">
965
- <!-- Request -->
966
- <rect x="125" y="10" width="150" height="50" rx="10" fill="#c0a062"/>
967
- <text x="200" y="42" text-anchor="middle" fill="#0f0f0f" font-weight="600" font-size="14">Request</text>
968
-
969
- <!-- Arrow -->
970
- <path d="M200 60 L200 85" stroke="#c0a062" stroke-width="2" marker-end="url(#arrowhead)"/>
971
-
972
- <!-- Router -->
973
- <rect x="125" y="85" width="150" height="50" rx="10" fill="#1a1a1a" stroke="#c0a062" stroke-width="2"/>
974
- <text x="200" y="117" text-anchor="middle" fill="#e0e0e0" font-weight="500" font-size="14">Router</text>
975
-
976
- <!-- Arrow -->
977
- <path d="M200 135 L200 160" stroke="#c0a062" stroke-width="2"/>
978
-
979
- <!-- Controller -->
980
- <rect x="125" y="160" width="150" height="50" rx="10" fill="#1a1a1a" stroke="#c0a062" stroke-width="2"/>
981
- <text x="200" y="192" text-anchor="middle" fill="#e0e0e0" font-weight="500" font-size="14">Controller</text>
982
-
983
- <!-- Branch to Model and View -->
984
- <path d="M200 210 L200 230 M200 230 L100 260" stroke="#c0a062" stroke-width="2"/>
985
- <path d="M200 230 L300 260" stroke="#c0a062" stroke-width="2"/>
986
-
987
- <!-- Model -->
988
- <rect x="50" y="260" width="100" height="40" rx="8" fill="#1a1a1a" stroke="#333" stroke-width="1"/>
989
- <text x="100" y="285" text-anchor="middle" fill="#a0a0a0" font-size="12">Model</text>
990
-
991
- <!-- View -->
992
- <rect x="250" y="260" width="100" height="40" rx="8" fill="#1a1a1a" stroke="#333" stroke-width="1"/>
993
- <text x="300" y="285" text-anchor="middle" fill="#a0a0a0" font-size="12">View</text>
994
-
995
- <!-- Merge -->
996
- <path d="M100 300 L100 310 L300 310 L300 300" stroke="#c0a062" stroke-width="2"/>
997
- <path d="M200 310 L200 325" stroke="#c0a062" stroke-width="2"/>
998
-
999
- <!-- Response -->
1000
- <rect x="125" y="325" width="150" height="40" rx="10" fill="#c0a062"/>
1001
- <text x="200" y="350" text-anchor="middle" fill="#0f0f0f" font-weight="600" font-size="14">Response</text>
1002
-
1003
- <!-- Arrow marker -->
1004
- <defs>
1005
- <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
1006
- <polygon points="0 0, 10 3.5, 0 7" fill="#c0a062"/>
1007
- </marker>
1008
- </defs>
1009
- </svg>
1010
- </div>
1011
- </div>
1012
- </section>
1013
-
1014
- <!-- Examples Section -->
1015
- <section id="examples" class="examples">
1016
- <div class="section-header">
1017
- <h2>Ejemplos de Código</h2>
1018
- <p>Descubre cómo utilizar BlackCoffee con estos ejemplos prácticos y rápidos de implementar.</p>
1019
- </div>
1020
- <div class="examples-container">
1021
- <div class="tabs">
1022
- <button class="tab-btn active" data-tab="routes">Definir Rutas</button>
1023
- <button class="tab-btn" data-tab="controller">Controladores</button>
1024
- <button class="tab-btn" data-tab="hooks">Hooks</button>
1025
- <button class="tab-btn" data-tab="config">Configuración</button>
1026
- </div>
1027
-
1028
- <div class="tab-content active" data-tab="routes">
1029
- <div class="code-block">
1030
- <div class="code-header">
1031
- <span class="code-lang">routes.json</span>
1032
- <button class="copy-btn" onclick="copyCodeBlock(this)">
1033
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1034
- <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
1035
- <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
1036
- </svg>
1037
- Copiar
1038
- </button>
1039
- </div>
1040
- <div class="code-body">
1041
- <pre><span class="comment">// Definición de rutas en routes.json</span>
1042
- <span class="keyword">[</span>
1043
- <span class="keyword">{</span>
1044
- <span class="property">"method"</span>: <span class="string">"GET"</span>,
1045
- <span class="property">"path"</span>: <span class="string">"/api/users"</span>,
1046
- <span class="property">"controller"</span>: <span class="string">"UserController"</span>,
1047
- <span class="property">"action"</span>: <span class="string">"list"</span>
1048
- <span class="keyword">}</span>,
1049
- <span class="keyword">{</span>
1050
- <span class="property">"method"</span>: <span class="string">"POST"</span>,
1051
- <span class="property">"path"</span>: <span class="string">"/api/users"</span>,
1052
- <span class="property">"controller"</span>: <span class="string">"UserController"</span>,
1053
- <span class="property">"action"</span>: <span class="string">"create"</span>
1054
- <span class="keyword">}</span>,
1055
- <span class="keyword">{</span>
1056
- <span class="property">"method"</span>: <span class="string">"GET"</span>,
1057
- <span class="property">"path"</span>: <span class="string">"/api/coffee"</span>,
1058
- <span class="property">"controller"</span>: <span class="string">"CoffeeController"</span>,
1059
- <span class="property">"action"</span>: <span class="string">"brew"</span>
1060
- <span class="keyword">}</span>
1061
- <span class="keyword">]</span></pre>
1062
- </div>
1063
- </div>
1064
- </div>
1065
-
1066
- <div class="tab-content" data-tab="controller">
1067
- <div class="code-block">
1068
- <div class="code-header">
1069
- <span class="code-lang">controllers/UserController.js</span>
1070
- <button class="copy-btn" onclick="copyCodeBlock(this)">
1071
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1072
- <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
1073
- <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
1074
- </svg>
1075
- Copiar
1076
- </button>
1077
- </div>
1078
- <div class="code-body">
1079
- <pre><span class="keyword">const</span> <span class="function">ControllerBase</span> = <span class="keyword">require</span>(<span class="string">'@blackcoffee/core'</span>).ControllerBase;
1080
-
1081
- <span class="keyword">class</span> <span class="function">UserController</span> <span class="keyword">extends</span> <span class="function">ControllerBase</span> <span class="keyword">{</span>
1082
- <span class="function">async</span> <span class="function">list</span>(<span class="param">req</span>, <span class="param">res</span>) <span class="keyword">{</span>
1083
- <span class="keyword">const</span> users = <span class="keyword">await</span> <span class="function">this</span>.<span class="function">model</span>(<span class="string">'User'</span>).<span class="function">findAll</span>();
1084
- <span class="keyword">return</span> <span class="function">res</span>.<span class="function">json</span>(<span class="function">users</span>);
1085
- <span class="keyword">}</span>
1086
-
1087
- <span class="function">async</span> <span class="function">create</span>(<span class="param">req</span>, <span class="param">res</span>) <span class="keyword">{</span>
1088
- <span class="keyword">const</span> user = <span class="keyword">await</span> <span class="function">this</span>.<span class="function">model</span>(<span class="string">'User'</span>).<span class="function">create</span>(<span class="param">req</span>.<span class="function">body</span>);
1089
- <span class="keyword">return</span> <span class="function">res</span>.<span class="function">status</span>(<span class="string">201</span>).<span class="function">json</span>(<span class="function">user</span>);
1090
- <span class="keyword">}</span>
1091
- <span class="keyword">}</span>
1092
-
1093
- <span class="keyword">module</span>.<span class="function">exports</span> = <span class="function">UserController</span>;</pre>
1094
- </div>
1095
- </div>
1096
- </div>
1097
-
1098
- <div class="tab-content" data-tab="hooks">
1099
- <div class="code-block">
1100
- <div class="code-header">
1101
- <span class="code-lang">hooks/auth.js</span>
1102
- <button class="copy-btn" onclick="copyCodeBlock(this)">
1103
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1104
- <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
1105
- <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
1106
- </svg>
1107
- Copiar
1108
- </button>
1109
- </div>
1110
- <div class="code-body">
1111
- <pre><span class="comment">// hooks/auth.js - Sistema de autenticación</span>
1112
- <span class="keyword">const</span> <span class="function">app</span> = <span class="keyword">require</span>(<span class="string">'@blackcoffee/core'</span>);
1113
-
1114
- <span class="comment">// Hook ejecutado antes de cada petición</span>
1115
- <span class="function">app</span>.<span class="function">hook</span>(<span class="string">'request_received'</span>, <span class="keyword">async</span> (<span class="param">req</span>) <span class="keyword">=></span> <span class="keyword">{</span>
1116
- <span class="function">console</span>.<span class="function">log</span>(<span class="string">`Petición recibida: ${req.method} ${req.path}`</span>);
1117
- <span class="keyword">}</span>);
1118
-
1119
- <span class="comment">// Validación de token JWT</span>
1120
- <span class="function">app</span>.<span class="function">hook</span>(<span class="string">'token_validation_pre'</span>, <span class="keyword">async</span> (<span class="param">req</span>, <span class="param">res</span>) <span class="keyword">=></span> <span class="keyword">{</span>
1121
- <span class="keyword">const</span> token = <span class="param">req</span>.<span class="function">headers</span>.<span class="function">authorization</span>;
1122
- <span class="keyword">if</span> (!token) <span class="keyword">return</span> <span class="function">res</span>.<span class="function">status</span>(<span class="string">401</span>);
1123
- <span class="keyword">}</span>);
1124
-
1125
- <span class="comment">// Hook ejecutado después de cada petición</span>
1126
- <span class="function">app</span>.<span class="function">hook</span>(<span class="string">'request_completed'</span>, (<span class="param">req</span>, <span class="param">res</span>) <span class="keyword">=></span> <span class="keyword">{</span>
1127
- <span class="function">console</span>.<span class="function">log</span>(<span class="string">`Respuesta: ${res.statusCode}`</span>);
1128
- <span class="keyword">}</span>);</pre>
1129
- </div>
1130
- </div>
1131
- </div>
1132
-
1133
- <div class="tab-content" data-tab="config">
1134
- <div class="code-block">
1135
- <div class="code-header">
1136
- <span class="code-lang">.env - Configuración</span>
1137
- <button class="copy-btn" onclick="copyCodeBlock(this)">
1138
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1139
- <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
1140
- <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
1141
- </svg>
1142
- Copiar
1143
- </button>
1144
- </div>
1145
- <div class="code-body">
1146
- <pre><span class="comment"># Puerto del servidor (por defecto: 3000)</span>
1147
- PORT=<span class="string">3000</span>
1148
-
1149
- <span class="comment"># Tiempo máximo de espera para peticiones</span>
1150
- REQUEST_TIMEOUT=<span class="string">300000</span>
1151
-
1152
- <span class="comment"># Tiempo máximo de conexión</span>
1153
- CONNECTION_TIMEOUT=<span class="string">300000</span>
1154
-
1155
- <span class="comment"># Ruta personalizada para archivo de rutas</span>
1156
- CUSTOM_ROUTES_PATH=<span class="string">./config/routes.json</span>
1157
-
1158
- <span class="comment"># Usar rutas por defecto (false por defecto)</span>
1159
- USE_DEFAULT_ROUTES=<span class="string">false</span>
1160
-
1161
- <span class="comment"># Nivel de logging (debug, info, warn, error)</span>
1162
- LOG_LEVEL=<span class="string">info</span>
1163
-
1164
- <span class="comment"># Configuración de base de datos</span>
1165
- DB_HOST=<span class="string">localhost</span>
1166
- DB_PORT=<span class="string">5432</span>
1167
- DB_NAME=<span class="string">myapp</span>
1168
- DB_USER=<span class="string">postgres</span>
1169
- DB_PASSWORD=<span class="string">your_password</span></pre>
1170
- </div>
1171
- </div>
1172
- </div>
1173
- </div>
1174
- </section>
1175
-
1176
- <!-- Directory Structure -->
1177
- <section class="structure">
1178
- <div class="section-header">
1179
- <h2>Estructura del Proyecto</h2>
1180
- <p>Organización clara de directorios para mantener tu código estructurado y mantenible.</p>
1181
- </div>
1182
- <div class="structure-content">
1183
- <div class="structure-tree">
1184
- <span class="comment-line"># Estructura de directorios de BlackCoffee</span><br><br>
1185
- <span class="folder">blackcoffee/</span><br>
1186
- ├── <span class="file">BlackCoffee.js</span> <span class="comment-line"># Punto de entrada principal</span><br>
1187
- ├── <span class="file">routes.json</span> <span class="comment-line"># Definición de rutas</span><br>
1188
- ├── <span class="file">.env</span> <span class="comment-line"># Variables de entorno</span><br>
1189
- ├── <span class="file">package.json</span> <span class="comment-line"># Dependencias del proyecto</span><br>
1190
- ├── <span class="folder">controllers/</span> <span class="comment-line"># Controladores de la aplicación</span><br>
1191
- │ └── <span class="file">UserController.js</span><br>
1192
- ├── <span class="folder">models/</span> <span class="comment-line"># Modelos de datos</span><br>
1193
- │ └── <span class="file">User.js</span><br>
1194
- ├── <span class="folder">views/</span> <span class="comment-line"># Plantillas de vistas</span><br>
1195
- │ └── <span class="file">index.html</span><br>
1196
- ├── <span class="folder">public/</span> <span class="comment-line"># Recursos estáticos</span><br>
1197
- │ ├── <span class="file">css/</span><br>
1198
- │ ├── <span class="file">js/</span><br>
1199
- │ └── <span class="file">images/</span><br>
1200
- ├── <span class="folder">utils/</span> <span class="comment-line"># Utilidades varias</span><br>
1201
- │ └── <span class="file">helpers.js</span><br>
1202
- └── <span class="folder">hooks/</span> <span class="comment-line"># Hooks personalizados</span><br>
1203
- └── <span class="file">auth.js</span>
1204
- </div>
1205
- </div>
1206
- </section>
1207
-
1208
- <!-- Footer -->
1209
- <footer id="docs" class="footer">
1210
- <div class="footer-content">
1211
- <div class="footer-section">
1212
- <h4>BlackCoffee</h4>
1213
- <p style="color: var(--text-secondary); font-size: 0.9rem; margin-bottom: 1rem;">
1214
- Servidor full-stack de código abierto construido sobre insitu-js.
1215
- </p>
1216
- <p class="version-badge" style="display: inline-block;">v1.0.0</p>
1217
- </div>
1218
- <div class="footer-section">
1219
- <h4>Documentación</h4>
1220
- <ul class="footer-links">
1221
- <li><a href="#">Guía de Inicio</a></li>
1222
- <li><a href="#">API Reference</a></li>
1223
- <li><a href="#">Tutoriales</a></li>
1224
- <li><a href="#">Ejemplos</a></li>
1225
- </ul>
1226
- </div>
1227
- <div class="footer-section">
1228
- <h4>Recursos</h4>
1229
- <ul class="footer-links">
1230
- <li><a href="#">GitHub</a></li>
1231
- <li><a href="#">NPM</a></li>
1232
- <li><a href="#">Issues</a></li>
1233
- <li><a href="#">Releases</a></li>
1234
- </ul>
1235
- </div>
1236
- <div class="footer-section">
1237
- <h4>Comunidad</h4>
1238
- <ul class="footer-links">
1239
- <li><a href="#">Discord</a></li>
1240
- <li><a href="#">Twitter</a></li>
1241
- <li><a href="#">Stack Overflow</a></li>
1242
- <li><a href="#">Blog</a></li>
1243
- </ul>
1244
- </div>
1245
- </div>
1246
- <div class="footer-bottom">
1247
- <p>Licenciado bajo MIT - Código abierto y libre</p>
1248
- <div class="social-links">
1249
- <a href="#" class="social-link" title="GitHub">
1250
- <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
1251
- <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
1252
- </svg>
1253
- </a>
1254
- <a href="#" class="social-link" title="NPM">
1255
- <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
1256
- <path d="M1.328 12.766h6.672v10.795h-6.672v-10.795zm3.336-6.383h3.336v3.383h-3.336v-3.383zm6.672 0h3.336v3.383h-3.336v-3.383zm-3.336 6.383h3.336v10.795h-3.336v-10.795zm3.336-6.383h3.336v3.383h-3.336v-3.383zm6.672 0h3.336v3.383h-3.336v-3.383zm-6.672 6.383h6.672v10.795h-6.672v-10.795zm3.336-6.383h3.336v3.383h-3.336v-3.383z"/>
1257
- </svg>
1258
- </a>
1259
- <a href="#" class="social-link" title="Twitter">
1260
- <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
1261
- <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
1262
- </svg>
1263
- </a>
1264
- </div>
1265
- </div>
1266
- </footer>
1267
-
1268
- <script>
1269
- // Tab functionality
1270
- document.querySelectorAll('.tab-btn').forEach(btn => {
1271
- btn.addEventListener('click', () => {
1272
- const tabId = btn.dataset.tab;
1273
-
1274
- // Update active tab button
1275
- document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
1276
- btn.classList.add('active');
1277
-
1278
- // Update active tab content
1279
- document.querySelectorAll('.tab-content').forEach(content => {
1280
- content.classList.remove('active');
1281
- if (content.dataset.tab === tabId) {
1282
- content.classList.add('active');
1283
- }
1284
- });
1285
- });
1286
- });
1287
-
1288
- // Copy code functionality
1289
- function copyCode(btn) {
1290
- const codeBlock = btn.closest('.hero-code').querySelector('code');
1291
- const text = codeBlock.textContent.trim();
1292
- navigator.clipboard.writeText(text).then(() => {
1293
- const originalHTML = btn.innerHTML;
1294
- btn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg> Copiado';
1295
- setTimeout(() => {
1296
- btn.innerHTML = originalHTML;
1297
- }, 2000);
1298
- });
1299
- }
1300
-
1301
- function copyCodeBlock(btn) {
1302
- const codeBody = btn.closest('.code-block').querySelector('.code-body pre');
1303
- const text = codeBody.textContent.trim();
1304
- navigator.clipboard.writeText(text).then(() => {
1305
- const originalHTML = btn.innerHTML;
1306
- btn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg> Copiado';
1307
- setTimeout(() => {
1308
- btn.innerHTML = originalHTML;
1309
- }, 2000);
1310
- });
1311
- }
1312
-
1313
- // Smooth scroll for anchor links
1314
- document.querySelectorAll('a[href^="#"]').forEach(anchor => {
1315
- anchor.addEventListener('click', function(e) {
1316
- e.preventDefault();
1317
- const target = document.querySelector(this.getAttribute('href'));
1318
- if (target) {
1319
- target.scrollIntoView({
1320
- behavior: 'smooth',
1321
- block: 'start'
1322
- });
1323
- }
1324
- });
1325
- });
1326
-
1327
- // Add scroll effect to header
1328
- window.addEventListener('scroll', () => {
1329
- const header = document.querySelector('.header');
1330
- if (window.scrollY > 50) {
1331
- header.style.boxShadow = '0 4px 20px rgba(0, 0, 0, 0.3)';
1332
- } else {
1333
- header.style.boxShadow = 'none';
1334
- }
1335
- });
1336
- </script>
1337
- </body>
1338
- </html>
1339
- </parameter>