free-framework 4.8.4 → 4.8.7

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.
@@ -234,6 +234,16 @@ if (server.namedMiddlewares['auth']) server.namedMiddlewares['AuthGuard'] = serv
234
234
  " <main id=\"free-app-root\">\n" +
235
235
  " ${pageHtml}\n" +
236
236
  " </main>\n" +
237
+ " ${process.env.NODE_ENV !== 'production' ? `\n" +
238
+ " <script>\n" +
239
+ " (function connectHMR() {\n" +
240
+ " const ws = new WebSocket('ws://' + location.host + '/_free_hmr');\n" +
241
+ " ws.onclose = () => { \n" +
242
+ " setTimeout(() => fetch('/').then(() => window.location.reload()).catch(connectHMR), 500); \n" +
243
+ " };\n" +
244
+ " console.log('[Free Engine] ⚡ HMR Active');\n" +
245
+ " })();\n" +
246
+ " </script>` : ''}\n" +
237
247
  "</body>\n" +
238
248
  "</html>`;\n" +
239
249
  " res.header('Content-Type', 'text/html').send(fullHTML);\n" +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-framework",
3
- "version": "4.8.4",
3
+ "version": "4.8.7",
4
4
  "description": "Professional Node.js engine for the .free language. Blazing-fast SSR, Islands Architecture, and built-in ORM.",
5
5
  "main": "index.js",
6
6
  "bin": {
package/runtime/server.js CHANGED
@@ -15,13 +15,33 @@ const { LRUCache } = require('lru-cache');
15
15
 
16
16
  class FreeServer {
17
17
  constructor() {
18
- console.log(`[Free Engine] ⚙️ Runtime Core v4.8.3 initializing...`);
18
+ console.log(`[Free Engine] ⚙️ Runtime Core v4.8.7 initializing...`);
19
19
  this.app = new HyperExpress.Server();
20
20
  this.viewsPath = process.env.VIEWS_PATH || nodePath.join(process.cwd(), 'views');
21
21
  this.namedMiddlewares = {};
22
22
  this.errorViews = {};
23
23
  this.plugins = [];
24
24
 
25
+ // HMR (Live Reload) WebSocket Endpoint
26
+ if (process.env.NODE_ENV !== 'production') {
27
+ this.app.ws('/_free_hmr', (ws) => {
28
+ ws.on('message', () => { }); // Keep alive
29
+ });
30
+ }
31
+
32
+ // Catch-all 404 handler
33
+ this.app.set_not_found_handler((req, res) => {
34
+ const acceptsHtml = req.headers['accept']?.includes('text/html');
35
+ if (acceptsHtml) {
36
+ const premium404 = nodePath.join(__dirname, 'views/404.html');
37
+ if (fs.existsSync(premium404)) {
38
+ return res.status(404).header('Content-Type', 'text/html').send(fs.readFileSync(premium404));
39
+ }
40
+ return res.status(404).send('<h1>404</h1><p>Page Not Found</p>');
41
+ }
42
+ res.status(404).json({ success: false, error: 'Route not found' });
43
+ });
44
+
25
45
  // 1. Absolute Top Logger
26
46
  this.app.use((req, res, next) => {
27
47
  console.log(`[Free Engine] 📥 [${new Date().toLocaleTimeString()}] Incoming: ${req.method} ${req.url}`);
@@ -0,0 +1,77 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>404 | Free Ultra</title>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700;900&display=swap" rel="stylesheet">
11
+ <style>
12
+ :root {
13
+ --primary: #fff;
14
+ --bg: #000;
15
+ --border: #27272a;
16
+ }
17
+
18
+ body {
19
+ margin: 0;
20
+ font-family: 'Inter', system-ui, sans-serif;
21
+ background: var(--bg);
22
+ color: white;
23
+ height: 100vh;
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ overflow: hidden;
28
+ background-image: radial-gradient(circle at 2px 2px, rgba(255, 255, 255, 0.05) 1px, transparent 0);
29
+ background-size: 40px 40px;
30
+ }
31
+
32
+ .container {
33
+ text-align: center;
34
+ }
35
+
36
+ h1 {
37
+ font-size: 10rem;
38
+ font-weight: 900;
39
+ margin: 0;
40
+ line-height: 1;
41
+ letter-spacing: -5px;
42
+ }
43
+
44
+ p {
45
+ color: #71717a;
46
+ font-size: 1.25rem;
47
+ margin-top: 20px;
48
+ }
49
+
50
+ .btn {
51
+ display: inline-block;
52
+ margin-top: 40px;
53
+ padding: 12px 30px;
54
+ background: white;
55
+ color: black;
56
+ text-decoration: none;
57
+ font-weight: 600;
58
+ border-radius: 8px;
59
+ transition: all 0.2s;
60
+ }
61
+
62
+ .btn:hover {
63
+ opacity: 0.9;
64
+ transform: translateY(-2px);
65
+ }
66
+ </style>
67
+ </head>
68
+
69
+ <body>
70
+ <div class="container">
71
+ <h1>404</h1>
72
+ <p>The page you're looking for has vanished into the void.</p>
73
+ <a href="/" class="btn">Return Home</a>
74
+ </div>
75
+ </body>
76
+
77
+ </html>
@@ -0,0 +1,30 @@
1
+ component Docs {
2
+ div class="container-pro py-32" {
3
+ div class="max-w-3xl" {
4
+ span class="badge-pro mb-4" { text "Documentation" }
5
+ h1 class="hero-title" { text "Master the Engine." }
6
+ p class="text-xl text-zinc-400 mb-12 leading-relaxed" {
7
+ text "Everything you need to build high-performance, enterprise-grade applications with Free Ultra."
8
+ }
9
+
10
+ div class="grid gap-8" {
11
+ div class="card-pro" {
12
+ h3 class="text-xl font-bold mb-2" { text "Getting Started" }
13
+ p class="text-zinc-400" { text "Learn the basics of the .free language and how to ignite your first server." }
14
+ }
15
+ div class="card-pro" {
16
+ h3 class="text-xl font-bold mb-2" { text "Islands Architecture" }
17
+ p class="text-zinc-400" { text "Master partial hydration and build interactive UIs that load instantly." }
18
+ }
19
+ div class="card-pro" {
20
+ h3 class="text-xl font-bold mb-2" { text "Built-in ORM" }
21
+ p class="text-zinc-400" { text "Direct database access with zero boilerplate and maximum type-safety." }
22
+ }
23
+ }
24
+ }
25
+ }
26
+
27
+ style {
28
+ .hero-title { background: linear-gradient(to right, #fff, #555); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
29
+ }
30
+ }
@@ -8,17 +8,25 @@ component Header {
8
8
 
9
9
  div class="hidden md:flex gap-6" {
10
10
  a href="/" class="nav-link font-medium" { text "Home" }
11
- a href="/dashboard" class="nav-link font-medium" { text "Dashboard" }
12
11
  a href="/docs" class="nav-link font-medium" { text "Documentation" }
12
+ if (props.user) {
13
+ a href="/dashboard" class="nav-link font-medium" { text "Dashboard" }
14
+ }
13
15
  }
14
16
  }
15
17
 
16
18
  div class="flex items-center gap-4" {
17
19
  span class="badge-pro" {
18
- text "v4.8.4"
20
+ text "v4.8.7"
19
21
  }
20
- a href="/login" class="text-sm font-medium text-white hover:opacity-80 transition-opacity" {
21
- text "Sign In"
22
+ if (props.user) {
23
+ a href="/logout" class="text-sm font-medium text-white hover:opacity-80 transition-opacity" {
24
+ text "Logout (${props.user.name})"
25
+ }
26
+ } else {
27
+ a href="/login" class="text-sm font-medium text-white hover:opacity-80 transition-opacity" {
28
+ text "Sign In"
29
+ }
22
30
  }
23
31
  }
24
32
  }
@@ -0,0 +1,31 @@
1
+ component Login {
2
+ div class="min-h-screen flex items-center justify-center bg-black px-8" {
3
+ div class="w-full max-w-md" {
4
+ div class="text-center mb-10" {
5
+ h2 class="text-3xl font-bold tracking-tight text-white" { text "Welcome Back" }
6
+ p class="text-zinc-500 mt-2" { text "Sign in to your enterprise console" }
7
+ }
8
+
9
+ div class="card-pro" {
10
+ form class="space-y-6" {
11
+ div {
12
+ label class="block text-sm font-medium text-zinc-400 mb-2" { text "Email Address" }
13
+ input type="email" class="w-full bg-black border border-zinc-800 rounded-lg px-4 py-3 text-white focus:border-white transition-colors outline-none" placeholder="name@company.com";
14
+ }
15
+ div {
16
+ label class="block text-sm font-medium text-zinc-400 mb-2" { text "Password" }
17
+ input type="password" class="w-full bg-black border border-zinc-800 rounded-lg px-4 py-3 text-white focus:border-white transition-colors outline-none" placeholder="••••••••";
18
+ }
19
+ button type="submit" class="btn-pro w-full justify-center py-3" {
20
+ text "Continue"
21
+ }
22
+ }
23
+ }
24
+
25
+ p class="text-center text-zinc-500 mt-8 text-sm" {
26
+ text "Don't have an account? "
27
+ a href="/register" class="text-white hover:underline" { text "Create one" }
28
+ }
29
+ }
30
+ }
31
+ }
@@ -16,10 +16,14 @@
16
16
  // A simple GET request that renders the 'Home' view component
17
17
  get "/" -> Home
18
18
 
19
+ // Documentation & Authentication
20
+ get "/docs" -> Docs
21
+ get "/login" -> Login
22
+
19
23
  // Example of a route that points to a dedicated controller logic before rendering
20
24
  // Ensure the 'Dashboard' view is defined in resources/views
21
25
  get "/dashboard" {
22
26
  // Calling an action/controller before returning the view
23
27
  // The controller should handle checking if the user is authenticated
24
- // return Dashboard;
28
+ return Dashboard;
25
29
  }