create-lumina-project 1.2.0 → 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 (37) hide show
  1. package/package.json +3 -3
  2. package/template/.env.example +2 -1
  3. package/template/nodemon.json +1 -1
  4. package/template/package.json +26 -15
  5. package/template/resources/css/app.css +491 -0
  6. package/template/resources/js/Pages/Errors/404.tsx +32 -0
  7. package/template/resources/js/Pages/Maintenance.tsx +34 -0
  8. package/template/resources/js/Pages/Status.tsx +103 -0
  9. package/template/resources/js/Pages/Welcome.tsx +82 -0
  10. package/template/resources/js/app.tsx +43 -0
  11. package/template/resources/js/tsconfig.json +20 -0
  12. package/template/resources/js/vite-env.d.ts +1 -0
  13. package/template/resources/views/app.html +14 -0
  14. package/template/src/controllers/UserController.ts +5 -1
  15. package/template/src/controllers/WebController.ts +94 -0
  16. package/template/src/database/migrations/20260420050855-create_refresh_tokens.js +5 -0
  17. package/template/src/exceptions/Handler.ts +4 -4
  18. package/template/src/middlewares/ApiAuth.ts +67 -0
  19. package/template/src/middlewares/Csrf.ts +5 -4
  20. package/template/src/middlewares/InertiaMiddleware.ts +95 -0
  21. package/template/src/middlewares/Maintenance.ts +5 -5
  22. package/template/src/middlewares/RoleGuard.ts +20 -0
  23. package/template/src/middlewares/Validator.ts +17 -1
  24. package/template/src/middlewares/WebAuth.ts +122 -0
  25. package/template/src/models/BaseModel.ts +24 -0
  26. package/template/src/models/RefreshToken.ts +6 -5
  27. package/template/src/models/User.ts +3 -5
  28. package/template/src/routes/api.ts +16 -8
  29. package/template/src/routes/web.ts +10 -43
  30. package/template/src/server.ts +115 -0
  31. package/template/src/types/express/index.d.ts +8 -1
  32. package/template/src/types/express-inertia.d.ts +28 -0
  33. package/template/vite.config.ts +20 -0
  34. package/template/views/404.html +0 -233
  35. package/template/views/maintenance.html +0 -464
  36. package/template/views/status.html +0 -545
  37. package/template/views/welcome.html +0 -495
@@ -1,545 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Lumina — System Status</title>
7
- <meta name="description" content="Lumina system status dashboard showing application health and environment details.">
8
- <link rel="shortcut icon" href="/img/logo2.png" type="image/x-icon">
9
- <link rel="preconnect" href="https://fonts.googleapis.com">
10
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
12
- <style>
13
- *, *::before, *::after {
14
- margin: 0;
15
- padding: 0;
16
- box-sizing: border-box;
17
- }
18
-
19
- :root {
20
- --indigo-100: #e0e7ff;
21
- --indigo-200: #c7d2fe;
22
- --indigo-400: #818cf8;
23
- --indigo-500: #6366f1;
24
- --indigo-600: #4f46e5;
25
- --slate-50: #f8fafc;
26
- --slate-100: #f1f5f9;
27
- --slate-300: #cbd5e1;
28
- --slate-400: #94a3b8;
29
- --slate-500: #64748b;
30
- --slate-600: #475569;
31
- --slate-800: #1e293b;
32
- --slate-900: #0f172a;
33
- --emerald-400: #34d399;
34
- --emerald-500: #10b981;
35
- --red-400: #f87171;
36
- --amber-400: #fbbf24;
37
- }
38
-
39
- body {
40
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
41
- background-color: var(--slate-900);
42
- color: var(--slate-100);
43
- min-height: 100vh;
44
- display: flex;
45
- flex-direction: column;
46
- justify-content: center;
47
- align-items: center;
48
- overflow-x: hidden;
49
- position: relative;
50
- }
51
-
52
- /* Animated gradient background */
53
- .bg-gradient {
54
- position: fixed;
55
- inset: 0;
56
- z-index: 0;
57
- background:
58
- radial-gradient(ellipse 80% 60% at 20% 20%, rgba(99, 102, 241, 0.15) 0%, transparent 60%),
59
- radial-gradient(ellipse 60% 80% at 80% 80%, rgba(79, 70, 229, 0.12) 0%, transparent 60%),
60
- radial-gradient(ellipse 50% 50% at 50% 50%, rgba(129, 140, 248, 0.06) 0%, transparent 70%);
61
- animation: bgShift 12s ease-in-out infinite alternate;
62
- }
63
-
64
- @keyframes bgShift {
65
- 0% { opacity: 0.7; transform: scale(1); }
66
- 50% { opacity: 1; transform: scale(1.05); }
67
- 100% { opacity: 0.8; transform: scale(1.02); }
68
- }
69
-
70
- /* Floating orbs */
71
- .orb {
72
- position: fixed;
73
- border-radius: 50%;
74
- filter: blur(80px);
75
- z-index: 0;
76
- animation: float 20s ease-in-out infinite;
77
- pointer-events: none;
78
- }
79
-
80
- .orb-1 {
81
- width: 400px;
82
- height: 400px;
83
- background: rgba(99, 102, 241, 0.12);
84
- top: -10%;
85
- left: -5%;
86
- }
87
-
88
- .orb-2 {
89
- width: 300px;
90
- height: 300px;
91
- background: rgba(52, 211, 153, 0.06);
92
- bottom: -5%;
93
- right: -5%;
94
- animation-delay: -7s;
95
- }
96
-
97
- .orb-3 {
98
- width: 200px;
99
- height: 200px;
100
- background: rgba(79, 70, 229, 0.1);
101
- top: 50%;
102
- left: 60%;
103
- animation-delay: -14s;
104
- }
105
-
106
- @keyframes float {
107
- 0%, 100% { transform: translate(0, 0) rotate(0deg); }
108
- 25% { transform: translate(30px, -40px) rotate(5deg); }
109
- 50% { transform: translate(-20px, 20px) rotate(-3deg); }
110
- 75% { transform: translate(15px, 30px) rotate(2deg); }
111
- }
112
-
113
- /* Grid pattern overlay */
114
- .grid-pattern {
115
- position: fixed;
116
- inset: 0;
117
- z-index: 0;
118
- background-image:
119
- linear-gradient(rgba(148, 163, 184, 0.03) 1px, transparent 1px),
120
- linear-gradient(90deg, rgba(148, 163, 184, 0.03) 1px, transparent 1px);
121
- background-size: 60px 60px;
122
- mask-image: radial-gradient(ellipse 70% 70% at 50% 50%, black 30%, transparent 80%);
123
- -webkit-mask-image: radial-gradient(ellipse 70% 70% at 50% 50%, black 30%, transparent 80%);
124
- }
125
-
126
- /* Main content */
127
- .main {
128
- position: relative;
129
- z-index: 1;
130
- display: flex;
131
- flex-direction: column;
132
- align-items: center;
133
- gap: 1.75rem;
134
- padding: 2rem;
135
- width: 100%;
136
- max-width: 600px;
137
- animation: fadeInUp 0.8s ease-out both;
138
- }
139
-
140
- @keyframes fadeInUp {
141
- from { opacity: 0; transform: translateY(30px); }
142
- to { opacity: 1; transform: translateY(0); }
143
- }
144
-
145
- @keyframes pulse {
146
- 0%, 100% { opacity: 0.2; transform: scale(1); }
147
- 50% { opacity: 0.35; transform: scale(1.1); }
148
- }
149
-
150
- /* Header */
151
- .header {
152
- text-align: center;
153
- }
154
-
155
- .back-link {
156
- display: inline-flex;
157
- align-items: center;
158
- gap: 0.4rem;
159
- font-size: 0.8rem;
160
- font-weight: 500;
161
- color: var(--slate-400);
162
- text-decoration: none;
163
- margin-bottom: 1.25rem;
164
- transition: color 0.2s ease;
165
- }
166
-
167
- .back-link:hover {
168
- color: var(--indigo-400);
169
- }
170
-
171
- .back-link svg {
172
- width: 14px;
173
- height: 14px;
174
- }
175
-
176
- .title {
177
- font-size: 2.25rem;
178
- font-weight: 800;
179
- letter-spacing: -0.03em;
180
- background: linear-gradient(135deg, #fff 0%, var(--indigo-200) 50%, var(--indigo-400) 100%);
181
- -webkit-background-clip: text;
182
- -webkit-text-fill-color: transparent;
183
- background-clip: text;
184
- line-height: 1.1;
185
- margin-bottom: 0.6rem;
186
- }
187
-
188
- .subtitle {
189
- font-size: 0.95rem;
190
- color: var(--slate-400);
191
- line-height: 1.6;
192
- font-weight: 400;
193
- }
194
-
195
- /* Overall status banner */
196
- .status-hero {
197
- width: 100%;
198
- display: flex;
199
- align-items: center;
200
- justify-content: center;
201
- gap: 0.75rem;
202
- padding: 1rem 1.5rem;
203
- border-radius: 14px;
204
- font-size: 0.95rem;
205
- font-weight: 700;
206
- animation: fadeInUp 0.8s ease-out 0.15s both;
207
- transition: background 0.3s ease, border-color 0.3s ease;
208
- }
209
-
210
- .status-hero.up {
211
- background: rgba(16, 185, 129, 0.08);
212
- border: 1px solid rgba(16, 185, 129, 0.15);
213
- color: var(--emerald-400);
214
- }
215
-
216
- .status-hero.down {
217
- background: rgba(248, 113, 113, 0.08);
218
- border: 1px solid rgba(248, 113, 113, 0.15);
219
- color: var(--red-400);
220
- }
221
-
222
- .status-hero-dot {
223
- width: 10px;
224
- height: 10px;
225
- border-radius: 50%;
226
- animation: blink 2s ease-in-out infinite;
227
- }
228
-
229
- .status-hero.up .status-hero-dot {
230
- background: var(--emerald-400);
231
- box-shadow: 0 0 10px rgba(52, 211, 153, 0.5);
232
- }
233
-
234
- .status-hero.down .status-hero-dot {
235
- background: var(--red-400);
236
- box-shadow: 0 0 10px rgba(248, 113, 113, 0.5);
237
- }
238
-
239
- @keyframes blink {
240
- 0%, 100% { opacity: 1; }
241
- 50% { opacity: 0.4; }
242
- }
243
-
244
- /* Glass cards */
245
- .card {
246
- width: 100%;
247
- background: rgba(30, 41, 59, 0.5);
248
- backdrop-filter: blur(20px);
249
- -webkit-backdrop-filter: blur(20px);
250
- border: 1px solid rgba(148, 163, 184, 0.08);
251
- border-radius: 16px;
252
- padding: 1.5rem;
253
- animation: fadeInUp 0.8s ease-out 0.25s both;
254
- }
255
-
256
- .card + .card {
257
- animation-delay: 0.35s;
258
- }
259
-
260
- .card-title {
261
- font-size: 0.75rem;
262
- font-weight: 600;
263
- color: var(--slate-500);
264
- text-transform: uppercase;
265
- letter-spacing: 0.08em;
266
- margin-bottom: 1rem;
267
- }
268
-
269
- /* Info rows */
270
- .info-grid {
271
- display: flex;
272
- flex-direction: column;
273
- gap: 0;
274
- }
275
-
276
- .info-row {
277
- display: flex;
278
- align-items: center;
279
- justify-content: space-between;
280
- padding: 0.75rem 0;
281
- border-bottom: 1px solid rgba(148, 163, 184, 0.06);
282
- }
283
-
284
- .info-row:last-child {
285
- border-bottom: none;
286
- padding-bottom: 0;
287
- }
288
-
289
- .info-row:first-child {
290
- padding-top: 0;
291
- }
292
-
293
- .info-label {
294
- display: flex;
295
- align-items: center;
296
- gap: 0.6rem;
297
- font-size: 0.82rem;
298
- color: var(--slate-400);
299
- font-weight: 500;
300
- }
301
-
302
- .info-icon {
303
- width: 32px;
304
- height: 32px;
305
- border-radius: 8px;
306
- background: rgba(148, 163, 184, 0.06);
307
- display: flex;
308
- align-items: center;
309
- justify-content: center;
310
- font-size: 0.85rem;
311
- flex-shrink: 0;
312
- }
313
-
314
- .info-value {
315
- font-family: 'JetBrains Mono', monospace;
316
- font-size: 0.8rem;
317
- font-weight: 500;
318
- color: var(--slate-200);
319
- background: rgba(148, 163, 184, 0.06);
320
- padding: 0.3rem 0.7rem;
321
- border-radius: 6px;
322
- }
323
-
324
- .info-value.env-badge {
325
- background: rgba(99, 102, 241, 0.1);
326
- color: var(--indigo-400);
327
- border: 1px solid rgba(99, 102, 241, 0.15);
328
- }
329
-
330
- .info-value.status-up {
331
- background: rgba(16, 185, 129, 0.1);
332
- color: var(--emerald-400);
333
- border: 1px solid rgba(16, 185, 129, 0.15);
334
- }
335
-
336
- .info-value.status-down {
337
- background: rgba(248, 113, 113, 0.1);
338
- color: var(--red-400);
339
- border: 1px solid rgba(248, 113, 113, 0.15);
340
- }
341
-
342
- /* Services list */
343
- .services-grid {
344
- display: grid;
345
- grid-template-columns: 1fr 1fr;
346
- gap: 0.6rem;
347
- }
348
-
349
- .service-item {
350
- display: flex;
351
- align-items: center;
352
- gap: 0.6rem;
353
- padding: 0.7rem 0.85rem;
354
- border-radius: 10px;
355
- background: rgba(148, 163, 184, 0.03);
356
- border: 1px solid rgba(148, 163, 184, 0.05);
357
- transition: background 0.2s ease, border-color 0.2s ease;
358
- }
359
-
360
- .service-item:hover {
361
- background: rgba(148, 163, 184, 0.06);
362
- border-color: rgba(148, 163, 184, 0.1);
363
- }
364
-
365
- .service-dot {
366
- width: 7px;
367
- height: 7px;
368
- border-radius: 50%;
369
- flex-shrink: 0;
370
- }
371
-
372
- .service-dot.up {
373
- background: var(--emerald-400);
374
- box-shadow: 0 0 6px rgba(52, 211, 153, 0.4);
375
- }
376
-
377
- .service-dot.down {
378
- background: var(--red-400);
379
- box-shadow: 0 0 6px rgba(248, 113, 113, 0.4);
380
- }
381
-
382
- .service-name {
383
- font-size: 0.78rem;
384
- font-weight: 500;
385
- color: var(--slate-300);
386
- }
387
-
388
- /* Footer */
389
- .footer {
390
- margin-top: 0.25rem;
391
- font-size: 0.75rem;
392
- color: var(--slate-600);
393
- animation: fadeInUp 0.8s ease-out 0.5s both;
394
- letter-spacing: 0.02em;
395
- display: flex;
396
- align-items: center;
397
- gap: 0.75rem;
398
- }
399
-
400
- .footer a {
401
- color: var(--indigo-400);
402
- text-decoration: none;
403
- font-weight: 500;
404
- transition: color 0.2s ease;
405
- }
406
-
407
- .footer a:hover {
408
- color: var(--indigo-200);
409
- }
410
-
411
- .last-checked {
412
- color: var(--slate-600);
413
- font-family: 'JetBrains Mono', monospace;
414
- font-size: 0.7rem;
415
- }
416
-
417
- /* Loading state */
418
- .loading {
419
- display: flex;
420
- align-items: center;
421
- justify-content: center;
422
- gap: 0.4rem;
423
- padding: 2rem;
424
- }
425
-
426
- .loading-dot {
427
- width: 6px;
428
- height: 6px;
429
- border-radius: 50%;
430
- background: var(--indigo-400);
431
- animation: loadBounce 1.4s ease-in-out infinite;
432
- }
433
-
434
- .loading-dot:nth-child(2) { animation-delay: 0.16s; }
435
- .loading-dot:nth-child(3) { animation-delay: 0.32s; }
436
-
437
- @keyframes loadBounce {
438
- 0%, 80%, 100% { opacity: 0.3; transform: scale(0.8); }
439
- 40% { opacity: 1; transform: scale(1.2); }
440
- }
441
-
442
- /* Responsive */
443
- @media (max-width: 540px) {
444
- .title { font-size: 1.75rem; }
445
- .services-grid { grid-template-columns: 1fr; }
446
- .info-label { font-size: 0.78rem; }
447
- .info-value { font-size: 0.75rem; }
448
- .footer { flex-direction: column; gap: 0.35rem; }
449
- }
450
- </style>
451
- </head>
452
- <body>
453
- <!-- Background effects -->
454
- <div class="bg-gradient"></div>
455
- <div class="orb orb-1"></div>
456
- <div class="orb orb-2"></div>
457
- <div class="orb orb-3"></div>
458
- <div class="grid-pattern"></div>
459
-
460
- <div class="main">
461
- <!-- Back navigation -->
462
- <div class="header">
463
- <a href="/" class="back-link">
464
- <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" /></svg>
465
- Back to Home
466
- </a>
467
- <h1 class="title">System Status</h1>
468
- <p class="subtitle">Real-time health overview of the Lumina application</p>
469
- </div>
470
-
471
- <!-- Overall status -->
472
- <div id="statusHero" class="status-hero up">
473
- <span class="status-hero-dot"></span>
474
- <span id="statusHeroText">All Systems Operational</span>
475
- </div>
476
-
477
- <!-- Application info card -->
478
- <div class="card">
479
- <div class="card-title">Application</div>
480
- <div class="info-grid">
481
- <div class="info-row">
482
- <div class="info-label">
483
- <div class="info-icon">🔒</div>
484
- Status
485
- </div>
486
- <div id="appStatus" class="info-value status-up">UP</div>
487
- </div>
488
- <div class="info-row">
489
- <div class="info-label">
490
- <div class="info-icon">🌐</div>
491
- Environment
492
- </div>
493
- <div id="appEnv" class="info-value env-badge">—</div>
494
- </div>
495
- <div class="info-row">
496
- <div class="info-label">
497
- <div class="info-icon">⏱️</div>
498
- Uptime
499
- </div>
500
- <div id="appUptime" class="info-value">—</div>
501
- </div>
502
- <div class="info-row">
503
- <div class="info-label">
504
- <div class="info-icon">🧠</div>
505
- Memory Usage
506
- </div>
507
- <div id="appMemory" class="info-value">—</div>
508
- </div>
509
- </div>
510
- </div>
511
-
512
- <!-- Services card -->
513
- <div class="card">
514
- <div class="card-title">Services</div>
515
- <div class="services-grid">
516
- <div class="service-item">
517
- <span id="svcExpressDot" class="service-dot up"></span>
518
- <span class="service-name">Express Server</span>
519
- </div>
520
- <div class="service-item">
521
- <span id="svcDbDot" class="service-dot up"></span>
522
- <span class="service-name">Database</span>
523
- </div>
524
- <div class="service-item">
525
- <span id="svcAuthDot" class="service-dot up"></span>
526
- <span class="service-name">Authentication</span>
527
- </div>
528
- <div class="service-item">
529
- <span id="svcLogDot" class="service-dot up"></span>
530
- <span class="service-name">Logging</span>
531
- </div>
532
- </div>
533
- </div>
534
-
535
- <span class="last-checked" id="lastChecked"></span>
536
-
537
- <!-- Footer -->
538
- <div class="footer">
539
- <a href="https://github.com/glensonansin/lumina" target="_blank">Lumina</a> — Built with Express.js & TypeScript
540
- </div>
541
- </div>
542
-
543
- <script src="/js/status.js"></script>
544
- </body>
545
- </html>