create-lumina-project 1.1.1 → 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.
- package/package.json +3 -3
- package/template/.env.example +2 -1
- package/template/nodemon.json +1 -1
- package/template/package.json +33 -21
- package/template/resources/css/app.css +491 -0
- package/template/resources/js/Pages/Errors/404.tsx +32 -0
- package/template/resources/js/Pages/Maintenance.tsx +34 -0
- package/template/resources/js/Pages/Status.tsx +103 -0
- package/template/resources/js/Pages/Welcome.tsx +82 -0
- package/template/resources/js/app.tsx +43 -0
- package/template/resources/js/tsconfig.json +20 -0
- package/template/resources/js/vite-env.d.ts +1 -0
- package/template/resources/views/app.html +14 -0
- package/template/scripts/create-migration.ts +457 -16
- package/template/src/controllers/UserController.ts +5 -1
- package/template/src/controllers/WebController.ts +94 -0
- package/template/src/database/migrations/20260420050854-create_users.js +68 -0
- package/template/src/database/migrations/20260420050855-create_refresh_tokens.js +65 -0
- package/template/src/exceptions/Handler.ts +4 -4
- package/template/src/middlewares/ApiAuth.ts +67 -0
- package/template/src/middlewares/Csrf.ts +5 -4
- package/template/src/middlewares/InertiaMiddleware.ts +95 -0
- package/template/src/middlewares/Maintenance.ts +5 -5
- package/template/src/middlewares/RoleGuard.ts +20 -0
- package/template/src/middlewares/Validator.ts +17 -1
- package/template/src/middlewares/WebAuth.ts +122 -0
- package/template/src/models/BaseModel.ts +24 -0
- package/template/src/models/RefreshToken.ts +6 -5
- package/template/src/models/User.ts +3 -5
- package/template/src/routes/api.ts +16 -8
- package/template/src/routes/web.ts +10 -43
- package/template/src/server.ts +115 -0
- package/template/src/types/express/index.d.ts +8 -1
- package/template/src/types/express-inertia.d.ts +28 -0
- package/template/src/utils/Logger.ts +13 -1
- package/template/vite.config.ts +20 -0
- package/template/views/404.html +0 -233
- package/template/views/maintenance.html +0 -464
- package/template/views/status.html +0 -545
- package/template/views/welcome.html +0 -495
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
interface StatusProps {
|
|
2
|
+
status: string;
|
|
3
|
+
environment: string;
|
|
4
|
+
uptime: number;
|
|
5
|
+
memoryMB: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function Status({ status, environment, uptime, memoryMB }: StatusProps) {
|
|
9
|
+
const formatUptime = (seconds: number) => {
|
|
10
|
+
const d = Math.floor(seconds / (3600 * 24));
|
|
11
|
+
const h = Math.floor((seconds % (3600 * 24)) / 3600);
|
|
12
|
+
const m = Math.floor((seconds % 3600) / 60);
|
|
13
|
+
return `${d}d ${h}h ${m}m`;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<>
|
|
18
|
+
<div className="bg-gradient"></div>
|
|
19
|
+
<div className="orb orb-1"></div>
|
|
20
|
+
<div className="orb orb-2"></div>
|
|
21
|
+
<div className="orb orb-3"></div>
|
|
22
|
+
<div className="grid-pattern"></div>
|
|
23
|
+
|
|
24
|
+
<div className="main">
|
|
25
|
+
<div className="header">
|
|
26
|
+
<a href="/" className="back-link">
|
|
27
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="2.5" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" /></svg>
|
|
28
|
+
Back to Home
|
|
29
|
+
</a>
|
|
30
|
+
<h1 className="title">System Status</h1>
|
|
31
|
+
<p className="subtitle">Real-time health overview of the Lumina application</p>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div className="status-bar" style={{ animationDelay: '0s', marginBottom: '-0.5rem' }}>
|
|
35
|
+
<div className={`status ${status === 'UP' ? '' : 'status-error'}`}>
|
|
36
|
+
<span className={`status-dot ${status === 'UP' ? '' : 'error'}`}></span>
|
|
37
|
+
{status === 'UP' ? 'All Systems Operational' : 'System Degraded'}
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div className="card">
|
|
42
|
+
<div className="card-title">Application</div>
|
|
43
|
+
<div className="info-grid">
|
|
44
|
+
<div className="info-row">
|
|
45
|
+
<div className="info-label">
|
|
46
|
+
<div className="info-icon">🔒</div>
|
|
47
|
+
Status
|
|
48
|
+
</div>
|
|
49
|
+
<div className={`info-value ${status === 'UP' ? 'status-up' : 'status-down'}`}>{status}</div>
|
|
50
|
+
</div>
|
|
51
|
+
<div className="info-row">
|
|
52
|
+
<div className="info-label">
|
|
53
|
+
<div className="info-icon">🌐</div>
|
|
54
|
+
Environment
|
|
55
|
+
</div>
|
|
56
|
+
<div className="info-value env-badge">{environment}</div>
|
|
57
|
+
</div>
|
|
58
|
+
<div className="info-row">
|
|
59
|
+
<div className="info-label">
|
|
60
|
+
<div className="info-icon">⏱️</div>
|
|
61
|
+
Uptime
|
|
62
|
+
</div>
|
|
63
|
+
<div className="info-value">{formatUptime(uptime)}</div>
|
|
64
|
+
</div>
|
|
65
|
+
<div className="info-row">
|
|
66
|
+
<div className="info-label">
|
|
67
|
+
<div className="info-icon">🧠</div>
|
|
68
|
+
Memory Usage
|
|
69
|
+
</div>
|
|
70
|
+
<div className="info-value">{memoryMB} MB</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div className="card">
|
|
76
|
+
<div className="card-title">Services</div>
|
|
77
|
+
<div className="services-grid">
|
|
78
|
+
<div className="service-item">
|
|
79
|
+
<span className={`service-dot ${status === 'UP' ? 'up' : 'down'}`}></span>
|
|
80
|
+
<span className="service-name">Express Server</span>
|
|
81
|
+
</div>
|
|
82
|
+
<div className="service-item">
|
|
83
|
+
<span className={`service-dot ${status === 'UP' ? 'up' : 'down'}`}></span>
|
|
84
|
+
<span className="service-name">Database</span>
|
|
85
|
+
</div>
|
|
86
|
+
<div className="service-item">
|
|
87
|
+
<span className={`service-dot ${status === 'UP' ? 'up' : 'down'}`}></span>
|
|
88
|
+
<span className="service-name">Authentication</span>
|
|
89
|
+
</div>
|
|
90
|
+
<div className="service-item">
|
|
91
|
+
<span className={`service-dot ${status === 'UP' ? 'up' : 'down'}`}></span>
|
|
92
|
+
<span className="service-name">Logging</span>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<div className="footer">
|
|
98
|
+
<a href="https://github.com/glensonansin/lumina" target="_blank">Lumina</a> — Built with Express & Sequelize
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
</>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
interface WelcomeProps {
|
|
2
|
+
version: string;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export default function Welcome({ version }: WelcomeProps) {
|
|
6
|
+
return (
|
|
7
|
+
<>
|
|
8
|
+
<div className="bg-gradient"></div>
|
|
9
|
+
<div className="orb orb-1"></div>
|
|
10
|
+
<div className="orb orb-2"></div>
|
|
11
|
+
<div className="orb orb-3"></div>
|
|
12
|
+
<div className="grid-pattern"></div>
|
|
13
|
+
|
|
14
|
+
<div className="main">
|
|
15
|
+
<div className="logo-wrapper">
|
|
16
|
+
<div className="logo-glow"></div>
|
|
17
|
+
<img src="/img/logo2.png" alt="Lumina Logo" className="logo" />
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div className="header">
|
|
21
|
+
<h1 className="title">Lumina</h1>
|
|
22
|
+
<p className="subtitle">A production-grade Express starter kit with Sequelize. Featuring OOP architecture, Singleton services, and type-safe database interactions.</p>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div className="card">
|
|
26
|
+
<div className="features">
|
|
27
|
+
<div className="feature">
|
|
28
|
+
<div className="feature-icon">🔷</div>
|
|
29
|
+
<div className="feature-text">
|
|
30
|
+
<h3>TypeScript</h3>
|
|
31
|
+
<p>End-to-end type safety</p>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
<div className="feature">
|
|
35
|
+
<div className="feature-icon">🏗️</div>
|
|
36
|
+
<div className="feature-text">
|
|
37
|
+
<h3>OOP Architecture</h3>
|
|
38
|
+
<p>Clean, scalable patterns</p>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
<div className="feature">
|
|
42
|
+
<div className="feature-icon">⚡</div>
|
|
43
|
+
<div className="feature-text">
|
|
44
|
+
<h3>Singleton Services</h3>
|
|
45
|
+
<p>Efficient resource management</p>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
<div className="feature">
|
|
49
|
+
<div className="feature-icon">🗄️</div>
|
|
50
|
+
<div className="feature-text">
|
|
51
|
+
<h3>Database Ready</h3>
|
|
52
|
+
<p>Type-safe DB interactions</p>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div className="status-bar">
|
|
59
|
+
<div className="status">
|
|
60
|
+
<span className="status-dot"></span>
|
|
61
|
+
Application is Running
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div className="actions">
|
|
66
|
+
<a href="/status" className="btn btn-primary">
|
|
67
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="2" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" d="M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z" /></svg>
|
|
68
|
+
System Status
|
|
69
|
+
</a>
|
|
70
|
+
<a href="https://github.com/glensonansin/lumina" target="_blank" className="btn btn-secondary">
|
|
71
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.6.11.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.23A11.509 11.509 0 0112 5.803c1.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.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"/></svg>
|
|
72
|
+
Documentation
|
|
73
|
+
</a>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div className="footer">
|
|
77
|
+
<a href="https://github.com/glensonansin/lumina" target="_blank">Lumina</a> — Built with Express & Sequelize
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createRoot } from 'react-dom/client';
|
|
2
|
+
import { createInertiaApp } from '@inertiajs/react';
|
|
3
|
+
import '../css/app.css';
|
|
4
|
+
|
|
5
|
+
import type { ComponentType } from 'react';
|
|
6
|
+
|
|
7
|
+
// Catch global errors and render them to the screen
|
|
8
|
+
window.addEventListener('error', (e) => {
|
|
9
|
+
document.body.innerHTML = `<div style="padding: 2rem; color: red; background: white; z-index: 9999; position: absolute; top: 0; left: 0; width: 100vw; height: 100vh;">
|
|
10
|
+
<h1>React Crash!</h1>
|
|
11
|
+
<pre>${e.error?.stack || e.message}</pre>
|
|
12
|
+
</div>`;
|
|
13
|
+
});
|
|
14
|
+
window.addEventListener('unhandledrejection', (e) => {
|
|
15
|
+
document.body.innerHTML = `<div style="padding: 2rem; color: red; background: white; z-index: 9999; position: absolute; top: 0; left: 0; width: 100vw; height: 100vh;">
|
|
16
|
+
<h1>Unhandled Promise Rejection!</h1>
|
|
17
|
+
<pre>${e.reason?.stack || e.reason}</pre>
|
|
18
|
+
</div>`;
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const el = document.getElementById('lumina-app');
|
|
23
|
+
if (!el || !el.dataset.page) throw new Error('Missing root element or data-page attribute');
|
|
24
|
+
|
|
25
|
+
const initialPage = JSON.parse(el.dataset.page);
|
|
26
|
+
|
|
27
|
+
createInertiaApp({
|
|
28
|
+
id: 'lumina-app',
|
|
29
|
+
page: initialPage,
|
|
30
|
+
resolve: name => {
|
|
31
|
+
const pages = import.meta.glob<{ default: ComponentType }>('./Pages/**/*.tsx', { eager: true });
|
|
32
|
+
if (!pages[`./Pages/${name}.tsx`]) {
|
|
33
|
+
throw new Error(`Inertia Error: Component './Pages/${name}.tsx' not found!`);
|
|
34
|
+
}
|
|
35
|
+
return pages[`./Pages/${name}.tsx`];
|
|
36
|
+
},
|
|
37
|
+
setup({ el, App, props }) {
|
|
38
|
+
createRoot(el).render(<App {...props} />);
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
} catch (e: any) {
|
|
42
|
+
document.body.innerHTML = `<div style="padding: 2rem; color: red; background: white;"><h1>Setup Crash!</h1><pre>${e.stack || e.message}</pre></div>`;
|
|
43
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
|
5
|
+
"types": ["vite/client"],
|
|
6
|
+
"allowJs": false,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"esModuleInterop": false,
|
|
9
|
+
"allowSyntheticDefaultImports": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"module": "ESNext",
|
|
13
|
+
"moduleResolution": "Node",
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"jsx": "react-jsx"
|
|
18
|
+
},
|
|
19
|
+
"include": ["./**/*.ts", "./**/*.tsx", "./vite-env.d.ts"]
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,14 @@
|
|
|
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</title>
|
|
7
|
+
|
|
8
|
+
<!-- Vite injected assets -->
|
|
9
|
+
{{viteAssets}}
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
<div id="lumina-app" data-page='{{page}}'></div>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|