free-framework 4.8.11 → 5.0.1
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/README.md +20 -9
- package/cli/commands/make.js +21 -12
- package/compiler/generator.js +88 -191
- package/compiler/lexer.js +2 -1
- package/compiler/parser.js +16 -13
- package/package.json +1 -1
- package/runtime/cluster.js +5 -5
- package/runtime/middleware/firewall.js +38 -0
- package/runtime/server.js +6 -2
- package/templates/app-template/app/controllers/ProductController.free +31 -0
- package/templates/app-template/app/models/Product.free +12 -0
- package/templates/app-template/package.json +1 -1
- package/templates/app-template/public/free-runtime.js +1 -0
- package/templates/app-template/resources/components/ProductCard.free +16 -0
- package/templates/app-template/resources/views/counter.free +3 -6
- package/templates/app-template/resources/views/docs.free +20 -30
- package/templates/app-template/resources/views/header.free +1 -1
- package/templates/app-template/resources/views/home.free +80 -55
- package/templates/app-template/routes/web.free +4 -4
- /package/templates/app-template/{resources → public}/css/app.css +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Free Framework
|
|
1
|
+
# Free Ultra Framework v5.0.0 [Convergence Royale]
|
|
2
2
|
|
|
3
|
-
> The
|
|
4
|
-
>
|
|
3
|
+
> **The High-Octane Engineering Ecosystem.**
|
|
4
|
+
> Bridging the gap between Laravel's elegance, React's reactivity, and Node.js's raw performance. 🛡️ Blazing-fast, Secure, and Scalable by default.
|
|
5
5
|
|
|
6
6
|
[](https://www.npmjs.com/package/free-framework)
|
|
7
7
|
[](LICENSE)
|
|
@@ -165,13 +165,24 @@ server.use(ChatPlugin());
|
|
|
165
165
|
|
|
166
166
|
---
|
|
167
167
|
|
|
168
|
-
## 🔒 Security
|
|
168
|
+
## 🔒 Security: Aura Shield (v5.0.0)
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
- **
|
|
173
|
-
- **
|
|
174
|
-
- **
|
|
170
|
+
Free Ultra v5.0.0 introduces the **Active Security Engine**, a proactive layer that protects your app from day one.
|
|
171
|
+
|
|
172
|
+
- **Aura Firewall**: Real-time pattern matching against SQL Injection, Directory Traversal, and malicious User-Agents.
|
|
173
|
+
- **Strict Headers**: CSP, HSTS, and Permissions-Policy enforced by default.
|
|
174
|
+
- **Strict-Typed Validation**: High-performance payload verification via `runtime/validator.js`.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 📖 The Gigantic Encyclopedia
|
|
179
|
+
|
|
180
|
+
Access the comprehensive, 7-chapter masterclass on building industrial-grade web applications.
|
|
181
|
+
- [Aura Architecture & AST Compilation]
|
|
182
|
+
- [Security Protocols & Firewall Deep-Dives]
|
|
183
|
+
- [.free Language Specs & Reactive State]
|
|
184
|
+
- [ORM 2.0 & CLI Scaffolding]
|
|
185
|
+
- [SPA Transitions & Partial SSR]
|
|
175
186
|
|
|
176
187
|
---
|
|
177
188
|
|
package/cli/commands/make.js
CHANGED
|
@@ -20,8 +20,8 @@ const make = {
|
|
|
20
20
|
fs.ensureDirSync(dir);
|
|
21
21
|
const filePath = path.join(dir, `${name}.free`);
|
|
22
22
|
guard(filePath, `Model ${name}`);
|
|
23
|
-
fs.writeFileSync(filePath,
|
|
24
|
-
console.log(`✅ Created model: app/models/${name}.free`);
|
|
23
|
+
fs.writeFileSync(filePath, `// Free Ultra Enterprise Model: ${name}\n// Optimized for SQLite / ORM v5.0.0\n\nmodel ${name} {\n id integer primary_key autoincrement\n uuid string unique\n name string index\n email string unique\n status string default('active')\n created_at timestamp default(now)\n updated_at timestamp default(now)\n}\n`);
|
|
24
|
+
console.log(`✅ [Laravel-scaffold] Created model: app/models/${name}.free`);
|
|
25
25
|
},
|
|
26
26
|
|
|
27
27
|
controller: (name) => {
|
|
@@ -29,8 +29,8 @@ const make = {
|
|
|
29
29
|
fs.ensureDirSync(dir);
|
|
30
30
|
const filePath = path.join(dir, `${name}Controller.free`);
|
|
31
31
|
guard(filePath, `Controller ${name}`);
|
|
32
|
-
fs.writeFileSync(filePath, `/**\n * ${name} Controller\n */\n\naction
|
|
33
|
-
console.log(`✅ Created controller: app/controllers/${name}Controller.free`);
|
|
32
|
+
fs.writeFileSync(filePath, `/**\n * ${name} Controller (v5.0.0 [Convergence])\n * Unified Logic for API and Web\n */\n\naction index {\n // Laravel-style Collection logic\n const data = await ORM.all('${name}');\n return { success: true, data };\n}\n\naction show {\n const item = await ORM.find('${name}', { id: params.id });\n return { success: !!item, data: item };\n}\n\naction store {\n // Validation logic here\n const newItem = await ORM.create('${name}', body);\n return { success: true, id: newItem.id };\n}\n\naction update {\n await ORM.update('${name}', { id: params.id }, body);\n return { success: true };\n}\n\naction delete {\n await ORM.delete('${name}', { id: params.id });\n return { success: true };\n}\n`);
|
|
33
|
+
console.log(`✅ [Laravel-scaffold] Created controller: app/controllers/${name}Controller.free`);
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
middleware: (name) => {
|
|
@@ -38,8 +38,8 @@ const make = {
|
|
|
38
38
|
fs.ensureDirSync(dir);
|
|
39
39
|
const filePath = path.join(dir, `${name}.js`);
|
|
40
40
|
guard(filePath, `Middleware ${name}`);
|
|
41
|
-
fs.writeFileSync(filePath, `/**\n * app/middleware/${name}.js\n */\nmodule.exports = async function ${name}Middleware(req, res, next) {\n //
|
|
42
|
-
console.log(`✅ Created middleware: app/middleware/${name}.js`);
|
|
41
|
+
fs.writeFileSync(filePath, `/**\n * app/middleware/${name}.js\n * Professional Request Filter (Node.js style)\n */\n\nmodule.exports = async function ${name}Middleware(req, res, next) {\n try {\n // Enter your security/auth logic here\n // Example: if (!req.headers.authorization) throw new Error("Unauthorized");\n \n next();\n } catch (err) {\n res.status(401).json({ success: false, message: err.message });\n }\n};\n`);
|
|
42
|
+
console.log(`✅ [NodeJS-style] Created middleware: app/middleware/${name}.js`);
|
|
43
43
|
},
|
|
44
44
|
|
|
45
45
|
migration: (name) => {
|
|
@@ -48,8 +48,8 @@ const make = {
|
|
|
48
48
|
const timestamp = Date.now();
|
|
49
49
|
const filePath = path.join(dir, `${timestamp}_${name}.js`);
|
|
50
50
|
guard(filePath, `Migration ${name}`);
|
|
51
|
-
fs.writeFileSync(filePath,
|
|
52
|
-
console.log(`✅ Created migration: database/migrations/${timestamp}_${name}.js`);
|
|
51
|
+
fs.writeFileSync(filePath, `/**\n * Migration: ${name}\n * Knex.js Query Builder compatible\n */\n\nexports.up = function(knex) {\n return knex.schema.createTable('${name}', table => {\n table.increments('id');\n table.uuid('uuid').defaultTo(knex.fn.uuid());\n table.timestamps(true, true);\n });\n};\n\nexports.down = function(knex) {\n return knex.schema.dropTable('${name}');\n};\n`);
|
|
52
|
+
console.log(`✅ [Laravel-style] Created migration: database/migrations/${timestamp}_${name}.js`);
|
|
53
53
|
},
|
|
54
54
|
|
|
55
55
|
page: (name) => {
|
|
@@ -57,8 +57,17 @@ const make = {
|
|
|
57
57
|
fs.ensureDirSync(dir);
|
|
58
58
|
const filePath = path.join(dir, `${name}.free`);
|
|
59
59
|
guard(filePath, `Page ${name}`);
|
|
60
|
-
fs.writeFileSync(filePath,
|
|
61
|
-
console.log(`✅ Created view: app/views/${name}.free`);
|
|
60
|
+
fs.writeFileSync(filePath, `// Free Ultra Page: ${name} (React-inspired)\n\ncomponent ${name} {\n let title = "${name} Hub";\n\n div class="min-h-screen bg-zinc-950 text-white p-20" {\n h1 class="text-6xl font-black tracking-tighter" { text title }\n p class="text-zinc-500 mt-4" { text "Welcome to your high-performance island." }\n }\n\n style {\n h1 { background: linear-gradient(to right, #fff, #444); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }\n }\n}\n`);
|
|
61
|
+
console.log(`✅ [React-inspired] Created view: app/views/${name}.free`);
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
component: (name) => {
|
|
65
|
+
const dir = path.join(process.cwd(), "resources/components");
|
|
66
|
+
fs.ensureDirSync(dir);
|
|
67
|
+
const filePath = path.join(dir, `${name}.free`);
|
|
68
|
+
guard(filePath, `Component ${name}`);
|
|
69
|
+
fs.writeFileSync(filePath, `/**\n * Component: ${name}\n * High-performance Interactive Island\n */\n\ncomponent ${name} {\n let status = state("idle");\n\n div class="p-4 border border-zinc-800 rounded-xl" {\n span { text "Status: " + status }\n button class="ml-4 px-3 py-1 bg-white text-black text-xs font-bold" \n onClick={() => status = "active"} {\n text "Activate"\n }\n }\n}\n`);
|
|
70
|
+
console.log(`✅ [Island-scaffold] Created component: resources/components/${name}.free`);
|
|
62
71
|
},
|
|
63
72
|
|
|
64
73
|
service: (name) => {
|
|
@@ -66,8 +75,8 @@ const make = {
|
|
|
66
75
|
fs.ensureDirSync(dir);
|
|
67
76
|
const filePath = path.join(dir, `${name}.js`);
|
|
68
77
|
guard(filePath, `Service ${name}`);
|
|
69
|
-
fs.writeFileSync(filePath, `/**\n * app/services/${name}.js\n * Enterprise
|
|
70
|
-
console.log(`✅ Created service: app/services/${name}.js`);
|
|
78
|
+
fs.writeFileSync(filePath, `/**\n * app/services/${name}.js\n * Enterprise Service Layer (Laravel-inspired)\n */\n\nclass ${name} {\n /**\n * Executes the primary business logic for this service.\n */\n static async handle(payload) {\n console.log("[Service] Processing ${name} with payload:", payload);\n // Complex business logic goes here\n return { success: true };\n }\n}\n\nmodule.exports = ${name};\n`);
|
|
79
|
+
console.log(`✅ [Laravel-inspired] Created service: app/services/${name}.js`);
|
|
71
80
|
},
|
|
72
81
|
};
|
|
73
82
|
|
package/compiler/generator.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* compiler/generator.js
|
|
3
|
-
* Code Generator for Free Ultra (
|
|
3
|
+
* Code Generator for Free Ultra (v5.0.0 Convergence).
|
|
4
4
|
* Optimized for Islands Architecture and Component Composition.
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -22,8 +22,7 @@ function generate(ast) {
|
|
|
22
22
|
"const modelsRegistry = {};\n";
|
|
23
23
|
|
|
24
24
|
const CleanCSS = require('clean-css');
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
|
|
27
26
|
const components = {};
|
|
28
27
|
const actions = {};
|
|
29
28
|
let globalCSS = "";
|
|
@@ -98,205 +97,101 @@ function generate(ast) {
|
|
|
98
97
|
ast.forEach(node => {
|
|
99
98
|
if (node.type === 'action') {
|
|
100
99
|
output += `\nserver.app.post("/_free/action/${node.name}", async (req, res) => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (node.params && node.params.length > 0) {
|
|
111
|
-
output += ` const { ${node.params.join(', ')} } = body;\n`;
|
|
112
|
-
}
|
|
113
|
-
output += " " + node.code.replace(/res\.locals/g, 'res.context') + "\n" +
|
|
114
|
-
" })();\n" +
|
|
115
|
-
" if (!res.headersSent) res.json({ success: true, result });\n" +
|
|
116
|
-
" } catch(e) {\n" +
|
|
117
|
-
" if (!res.headersSent) res.status(500).json({ success: false, error: e.message });\n" +
|
|
118
|
-
" }\n" +
|
|
119
|
-
"});\n";
|
|
100
|
+
const body = req.body || {};
|
|
101
|
+
const logic = async (body, res) => { ${node.code} };
|
|
102
|
+
try {
|
|
103
|
+
const result = await logic(body, res);
|
|
104
|
+
if (!res.completed) res.json({ success: true, data: result });
|
|
105
|
+
} catch(e) {
|
|
106
|
+
if (!res.completed) res.status(500).json({ success: false, error: e.message });
|
|
107
|
+
}
|
|
108
|
+
});\n`;
|
|
120
109
|
}
|
|
121
110
|
});
|
|
122
111
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
output += `\nserver.renderRegistry = {\n`;
|
|
127
|
-
Object.keys(components).forEach((name, i) => {
|
|
128
|
-
output += ` ${name}: render${name}${i === Object.keys(components).length - 1 ? '' : ','}\n`;
|
|
112
|
+
output += "\n// Components (Islands Animation)\n";
|
|
113
|
+
Object.keys(components).forEach(name => {
|
|
114
|
+
output += generateComponentCode(components[name]);
|
|
129
115
|
});
|
|
130
|
-
output += `};\n`;
|
|
131
116
|
|
|
132
|
-
output += `\
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
117
|
+
output += `\n// Routes & Global Rendering\n`;
|
|
118
|
+
output += `const helpers = {
|
|
119
|
+
renderComponent: (name, props, h) => {
|
|
120
|
+
const comp = islandsRegistry[name];
|
|
121
|
+
return comp ? comp(props, h) : \`<!-- error: \${name} not found -->\`;
|
|
122
|
+
},
|
|
123
|
+
e: (val) => String(val).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''')
|
|
124
|
+
};\n`;
|
|
125
|
+
|
|
126
|
+
output += `const islandsRegistry = {\n`;
|
|
127
|
+
Object.keys(components).forEach(name => {
|
|
128
|
+
output += ` '${name}': render_${name},\n`;
|
|
141
129
|
});
|
|
142
|
-
|
|
143
|
-
// ── Auto-register Custom Middlewares from app/middleware ─────────────────
|
|
144
|
-
output += `
|
|
145
|
-
const mwDir = path.join(process.cwd(), 'app/middleware');
|
|
146
|
-
if (fs.existsSync(mwDir)) {
|
|
147
|
-
fs.readdirSync(mwDir).forEach(file => {
|
|
148
|
-
if (file.endsWith('.js')) {
|
|
149
|
-
const name = file.replace('.js', '');
|
|
150
|
-
server.registerMiddleware(name, require(path.join(mwDir, file)));
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
if (server.namedMiddlewares['auth']) server.namedMiddlewares['AuthGuard'] = server.namedMiddlewares['auth'];
|
|
155
|
-
\n`;
|
|
130
|
+
output += `};\n\n`;
|
|
156
131
|
|
|
157
132
|
ast.forEach(node => {
|
|
158
133
|
if (node.type === 'route') {
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (req.headers['content-type'] && req.headers['content-type'].includes('application/json')) {
|
|
181
|
-
body = await req.json().catch(() => ({}));
|
|
182
|
-
} else {
|
|
183
|
-
body = await req.urlencoded().catch(() => ({}));
|
|
184
|
-
}
|
|
134
|
+
const method = node.method.toLowerCase() === 'get' || node.method === 'Get' ? 'get' : node.method.toLowerCase();
|
|
135
|
+
if (node.handler && node.handler.type === 'action_ref') {
|
|
136
|
+
output += `server.app.${method}('${node.path}', async (req, res) => {
|
|
137
|
+
const actionResults = await fetch(\`http://localhost:\${process.env.PORT || 3000}/_free/action/${node.handler.name}\`, { method: 'POST', body: JSON.stringify(req.body) }).then(r => r.json());
|
|
138
|
+
res.header('Content-Type', 'text/html');
|
|
139
|
+
res.send(render_${node.view}({ user: req.user, ...actionResults.data }, helpers));
|
|
140
|
+
});\n`;
|
|
141
|
+
} else if (node.handler) {
|
|
142
|
+
output += `server.app.${method}('${node.path}', async (req, res) => {
|
|
143
|
+
const logic = async (req, res) => { ${node.handler} };
|
|
144
|
+
const viewToRender = await logic(req, res);
|
|
145
|
+
if (viewToRender && islandsRegistry[viewToRender.name]) {
|
|
146
|
+
res.header('Content-Type', 'text/html');
|
|
147
|
+
res.send(islandsRegistry[viewToRender.name]({ user: req.user, ...req.body }, helpers));
|
|
148
|
+
}
|
|
149
|
+
});\n`;
|
|
150
|
+
} else if (node.view) {
|
|
151
|
+
output += `server.app.${method}('${node.path}', async (req, res) => {
|
|
152
|
+
res.header('Content-Type', 'text/html');
|
|
153
|
+
res.send(render_${node.view}({ user: req.user }, helpers));
|
|
154
|
+
});\n`;
|
|
185
155
|
}
|
|
186
|
-
} catch(e) {}
|
|
187
|
-
|
|
188
|
-
const result = await (async () => {\n` +
|
|
189
|
-
" " + handlerCode.replace(/res\.locals/g, 'res.context') + "\n" +
|
|
190
|
-
" })();\n\n" +
|
|
191
|
-
" if (res.headersSent) return;\n" +
|
|
192
|
-
"\n" +
|
|
193
|
-
" // If it's a PAGE route (has a view), render HTML\n" +
|
|
194
|
-
" if (" + (node.view ? 'true' : 'false') + ") {\n" +
|
|
195
|
-
" const stylesRegistry = " + JSON.stringify(stylesRegistry) + ";\n" +
|
|
196
|
-
" const helpers = {\n" +
|
|
197
|
-
" renderComponent: (name, props = {}) => {\n" +
|
|
198
|
-
" server.renderRegistry = server.renderRegistry || {\n" +
|
|
199
|
-
" " + Object.keys(components).map(name => `${name}: render${name}`).join(',\n ') + "\n" +
|
|
200
|
-
" };\n" +
|
|
201
|
-
" return server.renderRegistry[name] ? server.renderRegistry[name](props, helpers) : '<!-- Component ' + name + ' not found -->';\n" +
|
|
202
|
-
" },\n" +
|
|
203
|
-
" getScopedCSS: (used = []) => {\n" +
|
|
204
|
-
" return used.map(name => stylesRegistry[name] || '').join('\\n');\n" +
|
|
205
|
-
" }\n" +
|
|
206
|
-
" };\n" +
|
|
207
|
-
" const props = result || (res.context && res.context.props ? res.context.props : {});\n" +
|
|
208
|
-
" const pageHtml = helpers.renderComponent('" + viewName + "', props);\n" +
|
|
209
|
-
" const scopedCSS = helpers.getScopedCSS(['" + viewName + "', 'Header']);\n" +
|
|
210
|
-
" if (req.headers['x-free-partial']) {\n" +
|
|
211
|
-
" return res.json({ title: 'Free Ultra | " + viewName + "', content: pageHtml, url: req.url, css: scopedCSS });\n" +
|
|
212
|
-
" }\n" +
|
|
213
|
-
" const headerHtml = helpers.renderComponent('Header', props);\n" +
|
|
214
|
-
" const fullHTML = `<!DOCTYPE html>\n" +
|
|
215
|
-
"<html lang=\"en\">\n" +
|
|
216
|
-
"<head>\n" +
|
|
217
|
-
" <meta charset=\"UTF-8\">\n" +
|
|
218
|
-
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n" +
|
|
219
|
-
" <title>Free Ultra | " + viewName + "</title>\n" +
|
|
220
|
-
" <meta name=\"csrf-token\" content=\"${res.context.csrfToken || ''}\">\n" +
|
|
221
|
-
" <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n" +
|
|
222
|
-
" <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n" +
|
|
223
|
-
" <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&display=swap\" rel=\"stylesheet\">\n" +
|
|
224
|
-
" <link rel=\"stylesheet\" href=\"/css/app.css\">\n" +
|
|
225
|
-
" <style>\n" +
|
|
226
|
-
" :root { --primary:#fff; --bg:#000; --border:#27272a; }\n" +
|
|
227
|
-
" body { margin:0; font-family:'Inter', system-ui, sans-serif; background:var(--bg); color:#fff; -webkit-font-smoothing:antialiased; }\n" +
|
|
228
|
-
" ${scopedCSS}\n" +
|
|
229
|
-
" </style>\n" +
|
|
230
|
-
" <script src=\"/free-runtime.js\" defer></script>\n" +
|
|
231
|
-
"</head>\n" +
|
|
232
|
-
"<body>\n" +
|
|
233
|
-
" ${headerHtml}\n" +
|
|
234
|
-
" <main id=\"free-app-root\">\n" +
|
|
235
|
-
" ${pageHtml}\n" +
|
|
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" +
|
|
247
|
-
"</body>\n" +
|
|
248
|
-
"</html>`;\n" +
|
|
249
|
-
" res.header('Content-Type', 'text/html').send(fullHTML);\n" +
|
|
250
|
-
" } else {\n" +
|
|
251
|
-
" res.json({ success: true, result });\n" +
|
|
252
|
-
" }\n" +
|
|
253
|
-
" });\n";
|
|
254
156
|
}
|
|
255
157
|
});
|
|
256
158
|
|
|
257
|
-
output += `\
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
159
|
+
output += `\n// Global Finalizing\n`;
|
|
160
|
+
output += `const cssMinifier = new CleanCSS({});\n`;
|
|
161
|
+
output += `const minifiedCSS = cssMinifier.minify(\`${globalCSS}\`).styles;\n`;
|
|
162
|
+
output += `server.app.get('/_free/styles.css', (req, res) => {
|
|
163
|
+
res.header('Content-Type', 'text/css');
|
|
164
|
+
res.send(minifiedCSS);
|
|
165
|
+
});\n`;
|
|
262
166
|
|
|
263
|
-
|
|
264
|
-
`;
|
|
167
|
+
output += `\nserver.start(process.env.PORT || 3000);\n`;
|
|
265
168
|
|
|
266
169
|
return output;
|
|
267
170
|
}
|
|
268
171
|
|
|
269
|
-
function
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
let code = `\nfunction render${node.name}(props = { }, helpers = { }) {\n`;
|
|
276
|
-
code += ` const e = (str) => String(str).replace(/[&<>'"]/g, m => ({'&': '&', '<': '<', '>': '>', "'": ''', '"': '"' }[m]));\n`;
|
|
277
|
-
code += ` const state = {\n`;
|
|
278
|
-
node.states.forEach(s => {
|
|
279
|
-
let val = s.default;
|
|
280
|
-
const isExpression = typeof val === 'string' && (val.includes('props.') || val.includes('||') || val.includes('&&') || val === 'true' || val === 'false' || val === 'null' || val.trim().startsWith('{') || val.trim().startsWith('['));
|
|
281
|
-
const finalVal = (isExpression || typeof val === 'number') ? val : `"${val}"`;
|
|
282
|
-
code += ` "${s.name}": ${finalVal},\n`;
|
|
283
|
-
});
|
|
284
|
-
code += ` };\n`;
|
|
285
|
-
if (stateNames.length > 0) {
|
|
286
|
-
code += ` const { ${stateNames.join(', ')} } = state;\n`;
|
|
287
|
-
}
|
|
288
|
-
|
|
172
|
+
function generateComponentCode(node) {
|
|
173
|
+
let stateNames = node.states.map(s => s.name);
|
|
174
|
+
let isInteractive = hasInteractivity(node.body);
|
|
175
|
+
let code = `\nfunction render_${node.name}(props = {}, helpers) {\n`;
|
|
176
|
+
code += ` const { e } = helpers;\n`;
|
|
177
|
+
code += ` let html = "";\n`;
|
|
289
178
|
code += ` const _events = [];\n`;
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
179
|
+
|
|
180
|
+
// Inject state initializers for the island
|
|
181
|
+
if (node.states.length > 0) {
|
|
182
|
+
code += ` const state = { \n`;
|
|
183
|
+
node.states.forEach(s => {
|
|
184
|
+
code += ` ${s.name}: ${s.default},\n`;
|
|
185
|
+
});
|
|
186
|
+
code += ` };\n`;
|
|
187
|
+
} else {
|
|
188
|
+
code += ` const state = {};\n`;
|
|
296
189
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
190
|
+
|
|
191
|
+
code += ` html += "<div class='free-component' data-component='${node.name}'";\n`;
|
|
192
|
+
if (isInteractive) {
|
|
193
|
+
code += ` html += " data-island='true'";\n`;
|
|
194
|
+
code += ` html += " data-state='" + JSON.stringify(state).replace(/'/g, "'") + "'";\n`;
|
|
300
195
|
}
|
|
301
196
|
|
|
302
197
|
code += ` html += ">";\n`;
|
|
@@ -355,7 +250,7 @@ function generateTagCode(tag, stateNames) {
|
|
|
355
250
|
let propsStr = "{";
|
|
356
251
|
if (tag.attributes) {
|
|
357
252
|
Object.keys(tag.attributes).forEach((a, i) => {
|
|
358
|
-
let val = tag.attributes[a].replace(
|
|
253
|
+
let val = tag.attributes[a].replace(/([^\\]|^)\{([a-zA-Z0-9_$.]+)\}/g, '$1${$2}');
|
|
359
254
|
propsStr += (i === 0 ? "" : ", ") + '"' + a + '": `' + val + '`';
|
|
360
255
|
});
|
|
361
256
|
}
|
|
@@ -378,7 +273,7 @@ function generateTagCode(tag, stateNames) {
|
|
|
378
273
|
}
|
|
379
274
|
code += ` html += " data-on-${eventName}='${uniqueId}'";\n`;
|
|
380
275
|
} else {
|
|
381
|
-
let val = tag.attributes[a].replace(
|
|
276
|
+
let val = tag.attributes[a].replace(/([^\\]|^)\{([a-zA-Z0-9_$.]+)\}/g, '$1${e($2)}');
|
|
382
277
|
code += " html += \" \" + " + JSON.stringify(a) + " + \"='\" + `" + val + "` + \"'\";\n";
|
|
383
278
|
}
|
|
384
279
|
});
|
|
@@ -398,15 +293,17 @@ function generateTagCode(tag, stateNames) {
|
|
|
398
293
|
code += ` html += ">";\n`;
|
|
399
294
|
|
|
400
295
|
if (tag.content) {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
406
|
-
|
|
296
|
+
// Ultra-safe: only interpolate if it's a simple variable-like name with no whitespace
|
|
297
|
+
let val = tag.content.replace(/([^\\]|^)\{([a-zA-Z0-9_$.]+)\}/g, '$1${e($2)}');
|
|
298
|
+
// Handle escaped braces
|
|
299
|
+
val = val.replace(/\\\{/g, '{').replace(/\\\}/g, '}');
|
|
300
|
+
code += ` html += \`${val}\`;\n`;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (tag.children) {
|
|
304
|
+
code += generateComponentBody(tag.children, stateNames);
|
|
407
305
|
}
|
|
408
306
|
|
|
409
|
-
if (tag.children) code += generateComponentBody(tag.children, stateNames);
|
|
410
307
|
code += ` html += "</${tag.name}>";\n`;
|
|
411
308
|
return code;
|
|
412
309
|
}
|
package/compiler/lexer.js
CHANGED
|
@@ -24,7 +24,8 @@ const KEYWORDS = new Set([
|
|
|
24
24
|
'middleware', 'auth', 'login', 'register', 'upload', 'path', 'maxSize', 'error',
|
|
25
25
|
'text', 'action', 'validate', 'store', 'onMount', 'onDestroy', 'queue', 'mail',
|
|
26
26
|
'loop', 'condition', 'script', 'if', 'for',
|
|
27
|
-
'get', 'post', 'put', 'delete', 'patch', 'head', 'options'
|
|
27
|
+
'get', 'post', 'put', 'delete', 'patch', 'head', 'options',
|
|
28
|
+
'Get', 'Post', 'Put', 'Delete', 'Patch', 'Head', 'Options'
|
|
28
29
|
]);
|
|
29
30
|
|
|
30
31
|
function tokenize(code, filename = 'unknown.free') {
|
package/compiler/parser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* compiler/parser.js
|
|
3
|
-
* Parser for the Free Framework (
|
|
3
|
+
* Parser for the Free Framework (v5.0.0 Convergence).
|
|
4
4
|
* Standardized braced-body parsing and raw code slicing.
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -21,7 +21,7 @@ function parse(tokens, filename = 'unknown.free', source = '') {
|
|
|
21
21
|
if (token.type === 'KEYWORD') {
|
|
22
22
|
if (token.value === 'route') {
|
|
23
23
|
ast.push(parseRoute(tokens, filename, source));
|
|
24
|
-
} else if (['get', 'post', 'put', 'delete', 'patch', 'head', 'options'].includes(token.value)) {
|
|
24
|
+
} else if (['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'Get', 'Post', 'Put', 'Delete', 'Patch', 'Head', 'Options'].includes(token.value)) {
|
|
25
25
|
tokens.unshift(token); // put back the method
|
|
26
26
|
ast.push(parseRoute(tokens, filename, source));
|
|
27
27
|
} else if (token.value === 'model') {
|
|
@@ -175,7 +175,7 @@ function parseComponent(tokens, filename, source) {
|
|
|
175
175
|
body.push({ type: next.value, code: parseActionBody(tokens, source) });
|
|
176
176
|
} else if (next.value === 'style') {
|
|
177
177
|
body.push({ type: 'style', content: parseActionBody(tokens, source) });
|
|
178
|
-
} else if (next.type === 'IDENTIFIER') {
|
|
178
|
+
} else if (next.type === 'IDENTIFIER' || next.type === 'KEYWORD') {
|
|
179
179
|
body.push(parseTag(next, tokens, filename, source));
|
|
180
180
|
}
|
|
181
181
|
}
|
|
@@ -194,7 +194,6 @@ function parseComponentBody(tokens, filename, source) {
|
|
|
194
194
|
let item, list = "";
|
|
195
195
|
|
|
196
196
|
if (isLoop) {
|
|
197
|
-
// loop list item {
|
|
198
197
|
const loopTokens = [];
|
|
199
198
|
while (tokens.length > 0 && tokens[0].value !== '{') {
|
|
200
199
|
loopTokens.push(tokens.shift());
|
|
@@ -203,7 +202,6 @@ function parseComponentBody(tokens, filename, source) {
|
|
|
203
202
|
item = loopTokens.pop().value;
|
|
204
203
|
list = loopTokens.map(t => (t.type === 'STRING' ? `"${t.value.replace(/"/g, '')}"` : t.value)).join('');
|
|
205
204
|
} else {
|
|
206
|
-
// for item in list {
|
|
207
205
|
item = tokens.shift().value;
|
|
208
206
|
if (tokens[0] && tokens[0].value === 'in') tokens.shift();
|
|
209
207
|
while (tokens.length > 0 && tokens[0].value !== '{') {
|
|
@@ -235,7 +233,12 @@ function parseComponentBody(tokens, filename, source) {
|
|
|
235
233
|
}
|
|
236
234
|
children.push({ type: 'tag', name: 'a', attributes: attrs, content: txt });
|
|
237
235
|
} else if (next.type === 'IDENTIFIER' || next.type === 'KEYWORD') {
|
|
238
|
-
|
|
236
|
+
if (['class', 'id', 'style'].includes(next.value)) {
|
|
237
|
+
// Skip attribute-like identifiers inside bodies to prevent malformed HTML tags
|
|
238
|
+
if (tokens[0] && (tokens[0].type === 'STRING' || tokens[0].type === 'IDENTIFIER')) tokens.shift();
|
|
239
|
+
} else {
|
|
240
|
+
children.push(parseTag(next, tokens, filename, source));
|
|
241
|
+
}
|
|
239
242
|
}
|
|
240
243
|
}
|
|
241
244
|
if (tokens[0] && tokens[0].value === '}') tokens.shift();
|
|
@@ -251,13 +254,11 @@ function parseTag(token, tokens, filename, source) {
|
|
|
251
254
|
|
|
252
255
|
while (tokens.length > 0) {
|
|
253
256
|
const next = tokens[0];
|
|
254
|
-
// Break on braces or other symbols (except - for identifiers)
|
|
255
257
|
if (next.value === '{' || next.value === '}' || (next.type === 'SYMBOL' && next.value !== '-' && next.value !== '=')) break;
|
|
256
258
|
|
|
257
259
|
const attrNameToken = tokens.shift();
|
|
258
260
|
const attrName = attrNameToken.value;
|
|
259
261
|
|
|
260
|
-
// Skip = if present
|
|
261
262
|
if (tokens[0] && tokens[0].value === '=') tokens.shift();
|
|
262
263
|
|
|
263
264
|
if (tokens[0] && tokens[0].value === '{') {
|
|
@@ -318,7 +319,11 @@ function parseTag(token, tokens, filename, source) {
|
|
|
318
319
|
}
|
|
319
320
|
children.push({ type: 'tag', name: 'a', attributes: attrs, content: txt });
|
|
320
321
|
} else if (next.type === 'IDENTIFIER' || next.type === 'KEYWORD') {
|
|
321
|
-
|
|
322
|
+
if (['class', 'id', 'style'].includes(next.value)) {
|
|
323
|
+
if (tokens[0] && (tokens[0].type === 'STRING' || tokens[0].type === 'IDENTIFIER')) tokens.shift();
|
|
324
|
+
} else {
|
|
325
|
+
children.push(parseTag(next, tokens, filename, source));
|
|
326
|
+
}
|
|
322
327
|
}
|
|
323
328
|
}
|
|
324
329
|
if (tokens[0] && tokens[0].value === '}') tokens.shift();
|
|
@@ -347,18 +352,16 @@ function parseAction(tokens, source) {
|
|
|
347
352
|
let name = nameToken.value;
|
|
348
353
|
let params = [];
|
|
349
354
|
|
|
350
|
-
// Support for parameterized actions: action myAction(id, name) { ... }
|
|
351
355
|
if (tokens[0] && tokens[0].value === '(') {
|
|
352
|
-
tokens.shift();
|
|
356
|
+
tokens.shift();
|
|
353
357
|
while (tokens.length > 0 && tokens[0].value !== ')') {
|
|
354
358
|
const pt = tokens.shift();
|
|
355
359
|
if (pt.value !== ',') {
|
|
356
360
|
params.push(pt.value);
|
|
357
361
|
}
|
|
358
362
|
}
|
|
359
|
-
if (tokens[0] && tokens[0].value === ')') tokens.shift();
|
|
363
|
+
if (tokens[0] && tokens[0].value === ')') tokens.shift();
|
|
360
364
|
} else if (name.includes('(')) {
|
|
361
|
-
// Handle case where lexer smushed it together: myAction(id)
|
|
362
365
|
const parts = name.split('(');
|
|
363
366
|
name = parts[0];
|
|
364
367
|
const argPart = parts[1].replace(')', '');
|
package/package.json
CHANGED
package/runtime/cluster.js
CHANGED
|
@@ -11,7 +11,7 @@ class ClusterManager {
|
|
|
11
11
|
static ignite(startServerCallback) {
|
|
12
12
|
if (cluster.isMaster || cluster.isPrimary) {
|
|
13
13
|
const numCPUs = os.cpus().length;
|
|
14
|
-
console.log(`\n🛡️ Free Engine Cluster Manager Intercepting...`);
|
|
14
|
+
console.log(`\n🛡️ [High-Octane] Free Engine Cluster Manager Intercepting...`);
|
|
15
15
|
console.log(`🔥 Igniting ${numCPUs} Worker Processes natively...\n`);
|
|
16
16
|
|
|
17
17
|
for (let i = 0; i < numCPUs; i++) {
|
|
@@ -19,15 +19,15 @@ class ClusterManager {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
cluster.on('exit', (worker, code, signal) => {
|
|
22
|
-
console.error(
|
|
23
|
-
cluster.fork(); // Auto-healing
|
|
22
|
+
console.error(`⚠️ [Resilience] Worker ${worker.process.pid} died (Code: ${code}). Resurrecting immediately...`);
|
|
23
|
+
cluster.fork(); // Auto-healing for 99.9% uptime
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
console.log(`✅ Master Process PID: ${process.pid} is routing traffic.`);
|
|
26
|
+
console.log(`✅ [Convergence] Master Process PID: ${process.pid} is routing traffic.`);
|
|
27
27
|
} else {
|
|
28
28
|
// Workers share the TCP connection in Node.js Cluster mode
|
|
29
29
|
startServerCallback();
|
|
30
|
-
console.log(` └─ Worker PID: ${process.pid} ready for combat.`);
|
|
30
|
+
console.log(` └─ [Active] Worker PID: ${process.pid} ready for combat.`);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runtime/middleware/firewall.js
|
|
3
|
+
* High-Performance Framework Firewall for Free Ultra v5.0.0.
|
|
4
|
+
* Protects against malicious bots, scrapers, and rapid-fire signatures.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const BLOCKED_AGENTS = [
|
|
8
|
+
'sqlmap', 'nikto', 'dirbuster', 'gobuster', 'nmap', 'masscan',
|
|
9
|
+
'dotbot', 'rogerbot', 'baiduspider', 'ahrefsbot'
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
const MALICIOUS_PATTERNS = [
|
|
13
|
+
/\.\.\//, // Directory traversal
|
|
14
|
+
/<script/i, // XSS attempt
|
|
15
|
+
/union\s+select/i, // SQL Injection
|
|
16
|
+
/OR\s+1=1/i, // SQL Injection
|
|
17
|
+
/etc\/passwd/i, // Linux system file access
|
|
18
|
+
/cmd\.exe/i // Windows command execution
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
module.exports = function firewallMiddleware(req, res, next) {
|
|
22
|
+
const userAgent = (req.headers['user-agent'] || '').toLowerCase();
|
|
23
|
+
|
|
24
|
+
// 1. Check User-Agent Blacklist
|
|
25
|
+
if (BLOCKED_AGENTS.some(agent => userAgent.includes(agent))) {
|
|
26
|
+
console.warn(`[Firewall] 🛡️ Blocked Malicious Agent: ${userAgent}`);
|
|
27
|
+
return res.status(403).json({ success: false, error: 'Firewall Breach: Access Denied' });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 2. Scan URL and Query for Malicious Patterns
|
|
31
|
+
const fullUrl = req.url + (req.query_string || '');
|
|
32
|
+
if (MALICIOUS_PATTERNS.some(regex => regex.test(fullUrl))) {
|
|
33
|
+
console.warn(`[Firewall] 🛡️ Blocked Malicious Request Pattern: ${req.url}`);
|
|
34
|
+
return res.status(403).json({ success: false, error: 'Firewall Breach: Invalid Signature detected' });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
next();
|
|
38
|
+
};
|
package/runtime/server.js
CHANGED
|
@@ -10,13 +10,16 @@ const fs = require('fs');
|
|
|
10
10
|
const crypto = require('crypto');
|
|
11
11
|
const securityMiddleware = require('./middleware/security');
|
|
12
12
|
const maintenanceMiddleware = require('./middleware/maintenance');
|
|
13
|
+
const firewallMiddleware = require('./middleware/firewall');
|
|
13
14
|
|
|
14
15
|
const { LRUCache } = require('lru-cache');
|
|
15
16
|
|
|
16
17
|
class FreeServer {
|
|
17
18
|
constructor() {
|
|
18
|
-
console.log(`[Free Engine] ⚙️ Runtime Core
|
|
19
|
-
this.app = new HyperExpress.Server(
|
|
19
|
+
console.log(`[Free Engine] ⚙️ Runtime Core v5.0.0 [Convergence] initializing...`);
|
|
20
|
+
this.app = new HyperExpress.Server({
|
|
21
|
+
compression: true
|
|
22
|
+
});
|
|
20
23
|
this.viewsPath = process.env.VIEWS_PATH || nodePath.join(process.cwd(), 'views');
|
|
21
24
|
this.namedMiddlewares = {};
|
|
22
25
|
this.errorViews = {};
|
|
@@ -109,6 +112,7 @@ class FreeServer {
|
|
|
109
112
|
});
|
|
110
113
|
|
|
111
114
|
// Apply Global Middleware
|
|
115
|
+
this.app.use(firewallMiddleware); // Firewall First
|
|
112
116
|
this.app.use(maintenanceMiddleware);
|
|
113
117
|
this.app.use(securityMiddleware);
|
|
114
118
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product Controller (v5.0.0 [Convergence])
|
|
3
|
+
* Unified Logic for API and Web
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
action index {
|
|
7
|
+
// Laravel-style Collection logic
|
|
8
|
+
const data = await ORM.all('Product');
|
|
9
|
+
return { success: true, data };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
action show {
|
|
13
|
+
const item = await ORM.find('Product', { id: params.id });
|
|
14
|
+
return { success: !!item, data: item };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
action store {
|
|
18
|
+
// Validation logic here
|
|
19
|
+
const newItem = await ORM.create('Product', body);
|
|
20
|
+
return { success: true, id: newItem.id };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
action update {
|
|
24
|
+
await ORM.update('Product', { id: params.id }, body);
|
|
25
|
+
return { success: true };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
action delete {
|
|
29
|
+
await ORM.delete('Product', { id: params.id });
|
|
30
|
+
return { success: true };
|
|
31
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Free Ultra Enterprise Model: Product
|
|
2
|
+
// Optimized for SQLite / ORM v5.0.0
|
|
3
|
+
|
|
4
|
+
model Product {
|
|
5
|
+
id integer primary_key autoincrement
|
|
6
|
+
uuid string unique
|
|
7
|
+
name string index
|
|
8
|
+
email string unique
|
|
9
|
+
status string default('active')
|
|
10
|
+
created_at timestamp default(now)
|
|
11
|
+
updated_at timestamp default(now)
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(()=>{var _=(s,i)=>()=>(i||s((i={exports:{}}).exports,i),i.exports);var g=_(()=>{(function(){console.log("\u{1F48E} Free Ultra Engine Activated");let s=document.getElementById("free-app-root"),i=document.createElement("div");i.id="free-loader",Object.assign(i.style,{position:"fixed",top:"0",left:"0",height:"3px",width:"0%",backgroundColor:"#00ff88",zIndex:"10000",transition:"width 0.3s ease, opacity 0.3s ease",boxShadow:"0 0 10px #00ff88"}),document.body.appendChild(i);function f(o){i.style.opacity="1",i.style.width=o+"%",o>=100&&setTimeout(()=>{i.style.opacity="0",setTimeout(()=>i.style.width="0%",300)},300)}async function d(o,t=!0){f(30);try{let e=await fetch(o,{headers:{"X-Free-Partial":"true"}});if(f(70),!e.ok)throw new Error("Navigation failed");let r=await e.json();s.style.opacity="0",s.style.transform="translateY(10px)",s.style.transition="opacity 0.2s ease, transform 0.2s ease",setTimeout(()=>{s.innerHTML=r.content,document.title=r.title,t&&history.pushState({url:o},r.title,o),u(),s.style.opacity="1",s.style.transform="translateY(0)",f(100),window.scrollTo(0,0)},200)}catch(e){console.error("SPA Error:",e),window.location.href=o}}function u(){document.querySelectorAll(".free-component[data-component]").forEach(t=>{if(t.getAttribute("data-hydrated"))return;let e=t.getAttribute("data-component"),r=JSON.parse(t.getAttribute("data-state")||"{}"),a=t.getAttribute("data-free-on-mount"),n=t.getAttribute("data-free-on-destroy");if(a&&window.__free_actions&&window.__free_actions[e]&&window.__free_actions[e][a])try{window.__free_actions[e][a](r)}catch(c){console.error(`[onMount] ${e}:`,c)}if(t.querySelectorAll("*").forEach(c=>{for(let l of c.attributes)if(l.name.startsWith("data-on-")){let w=l.name.replace("data-on-",""),m=l.value;c.addEventListener(w,h=>{let y=l.value;if(window.__free_actions&&window.__free_actions[e]&&window.__free_actions[e][y])try{window.__free_actions[e][y](r,h),t.setAttribute("data-state",JSON.stringify(r))}catch(p){console.error(`[Action] ${e} (${w}):`,p)}else console.warn(`Missing action handler for ${y} on ${w}`)})}}),t.setAttribute("data-hydrated","true"),n){let c=new MutationObserver(l=>{l.forEach(w=>{w.removedNodes.forEach(m=>{if(m===t){if(window.__free_actions&&window.__free_actions[e]&&window.__free_actions[e][n])try{window.__free_actions[e][n](r)}catch(h){console.error(`[onDestroy] ${e}:`,h)}c.disconnect()}})})});c.observe(t.parentNode,{childList:!0})}})}document.addEventListener("click",o=>{let t=o.target.closest("a");if(t&&t.href&&t.href.startsWith(window.location.origin)){let e=new URL(t.href);(e.pathname!==window.location.pathname||e.search!==window.location.search)&&(o.preventDefault(),d(t.href))}}),document.addEventListener("submit",async o=>{let t=o.target;if(t&&t.action&&t.action.startsWith(window.location.origin)){o.preventDefault(),f(30);let e=new FormData(t),r=Object.fromEntries(e.entries());try{let a=await fetch(t.action,{method:t.method||"POST",headers:{"Content-Type":"application/json","X-Free-Partial":"true"},body:JSON.stringify(r),redirect:"follow"});if(f(70),a.redirected){d(a.url);return}if(!a.ok){let n="An error occurred";try{n=(await a.json()).error||n}catch{}t.action.includes("/api/login")?d("/login?error="+encodeURIComponent(n)):d(window.location.pathname+"?error="+encodeURIComponent(n));return}try{let n=await a.json();n&&n.content?(s.style.opacity="0",setTimeout(()=>{s.innerHTML=n.content,n.title&&(document.title=n.title),u(),s.style.opacity="1",f(100)},200)):n&&n.success&&d(window.location.pathname+window.location.search)}catch{window.location.reload()}}catch(a){console.error("Form submit failed:",a),t.submit()}}},!0),window.addEventListener("popstate",o=>{o.state&&o.state.url&&d(o.state.url,!1)}),window.Free={navigate:d,async call(o,t={}){let e=document.querySelector('meta[name="csrf-token"]')?.getAttribute("content");try{let r=await fetch(`/_free/action/${o}`,{method:"POST",headers:{"Content-Type":"application/json","X-CSRF-Token":e},body:JSON.stringify(t)}),a=await r.json();if(!r.ok)throw new Error(a.error||"Action failed");return a}catch(r){throw console.error(`\u274C Action Error [${o}]:`,r.message),r}}},document.readyState==="loading"?document.addEventListener("DOMContentLoaded",u):u()})()});g();})();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component: ProductCard
|
|
3
|
+
* High-performance Interactive Island
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
component ProductCard {
|
|
7
|
+
let status = state("idle");
|
|
8
|
+
|
|
9
|
+
div class="p-4 border border-zinc-800 rounded-xl" {
|
|
10
|
+
span { text "Status: " + status }
|
|
11
|
+
button class="ml-4 px-3 py-1 bg-white text-black text-xs font-bold"
|
|
12
|
+
onClick={() => status = "active"} {
|
|
13
|
+
text "Activate"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -3,15 +3,12 @@ component Counter {
|
|
|
3
3
|
count: 0
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
div {
|
|
7
|
-
class "p-4 bg-gray-800 rounded-lg text-center"
|
|
6
|
+
div class="p-4 bg-gray-800 rounded-lg text-center" {
|
|
8
7
|
h2 { text "Reactive Counter" }
|
|
9
|
-
p {
|
|
10
|
-
class "text-4xl font-black text-primary my-4"
|
|
8
|
+
p class="text-4xl font-black text-primary my-4" {
|
|
11
9
|
text "{count}"
|
|
12
10
|
}
|
|
13
|
-
button {
|
|
14
|
-
class "px-6 py-2 bg-primary text-dark font-bold rounded-full hover:scale-105 transition-transform"
|
|
11
|
+
button class="px-6 py-2 bg-primary text-dark font-bold rounded-full hover:scale-105 transition-transform" {
|
|
15
12
|
text "Increment"
|
|
16
13
|
on-click { state.count++ }
|
|
17
14
|
}
|
|
@@ -2,7 +2,7 @@ component Docs {
|
|
|
2
2
|
div class="min-h-screen bg-black text-zinc-300 font-sans selection:bg-white selection:text-black" {
|
|
3
3
|
// Navigation / Header Space
|
|
4
4
|
div class="container-pro pt-32 pb-20" {
|
|
5
|
-
span class="badge-pro mb-4 animate-pulse" { text "
|
|
5
|
+
span class="badge-pro mb-4 animate-pulse" { text "v5.0.1 | High-Octane Docs" }
|
|
6
6
|
h1 class="text-6xl md:text-8xl font-black text-white tracking-tighter mb-8 leading-none" {
|
|
7
7
|
text "Free Ultra"
|
|
8
8
|
br;
|
|
@@ -22,7 +22,6 @@ component Docs {
|
|
|
22
22
|
// Content Sections
|
|
23
23
|
div class="container-pro space-y-32 pb-40" {
|
|
24
24
|
|
|
25
|
-
// 1. Core Philosophy
|
|
26
25
|
section id="philosophy" {
|
|
27
26
|
div class="grid md:grid-cols-2 gap-16 items-start" {
|
|
28
27
|
div {
|
|
@@ -35,26 +34,30 @@ component Docs {
|
|
|
35
34
|
text " to ensure your pages load instantly while remaining fully interactive."
|
|
36
35
|
}
|
|
37
36
|
ul class="space-y-4 text-sm" {
|
|
38
|
-
li class="flex gap-3" {
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
li class="flex gap-3" {
|
|
38
|
+
span class="text-white" { text "•" }
|
|
39
|
+
text "Blazing-fast SSR powered by HyperExpress."
|
|
40
|
+
}
|
|
41
|
+
li class="flex gap-3" {
|
|
42
|
+
span class="text-white" { text "•" }
|
|
43
|
+
text "Selective Hydration: Only JavaScript that's needed enters the browser."
|
|
44
|
+
}
|
|
45
|
+
li class="flex gap-3" {
|
|
46
|
+
span class="text-white" { text "•" }
|
|
47
|
+
text "Unified Syntax: The .free language unifies HTML, CSS, and Logic."
|
|
48
|
+
}
|
|
41
49
|
}
|
|
42
50
|
}
|
|
43
51
|
div class="card-pro bg-zinc-900/20" {
|
|
44
52
|
pre {
|
|
45
53
|
code {
|
|
46
|
-
text "// Pure Performance\n"
|
|
47
|
-
text "component Fast {\n"
|
|
48
|
-
text " h1 { text 'Zero Delay' }\n"
|
|
49
|
-
text " // Static by default\n"
|
|
50
|
-
text "}"
|
|
54
|
+
text "// Pure Performance\ncomponent Fast { \n h1 { text 'Zero Delay' }\n // Static by default\n}\n"
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
// 2. The Free Language
|
|
58
61
|
section id="language" {
|
|
59
62
|
h2 class="text-4xl font-bold text-white mb-12 tracking-tight" { text "2. The .free Language" }
|
|
60
63
|
div class="grid md:grid-cols-3 gap-8" {
|
|
@@ -85,7 +88,6 @@ component Docs {
|
|
|
85
88
|
}
|
|
86
89
|
}
|
|
87
90
|
|
|
88
|
-
// 3. Routing & ORM
|
|
89
91
|
section id="orm" {
|
|
90
92
|
div class="grid md:grid-cols-2 gap-16" {
|
|
91
93
|
div {
|
|
@@ -109,18 +111,13 @@ component Docs {
|
|
|
109
111
|
div class="card-pro bg-zinc-950" {
|
|
110
112
|
pre {
|
|
111
113
|
code {
|
|
112
|
-
text "get
|
|
113
|
-
text "post \"/api/login\" {\n"
|
|
114
|
-
text " const user = await ORM.find('User', { email: body.email });\n"
|
|
115
|
-
text " return { success: !!user };\n"
|
|
116
|
-
text "}"
|
|
114
|
+
text "get /dashboard -> Dashboard\n\npost /api/login { \n const user = await ORM.find('User', { email: body.email });\n return { success: !!user };\n}"
|
|
117
115
|
}
|
|
118
116
|
}
|
|
119
117
|
}
|
|
120
118
|
}
|
|
121
119
|
}
|
|
122
120
|
|
|
123
|
-
// 4. CLI Power-user
|
|
124
121
|
section id="cli" {
|
|
125
122
|
h2 class="text-4xl font-bold text-white mb-12 tracking-tight" { text "4. CLI Power-user Guide" }
|
|
126
123
|
div class="grid grid-cols-1 md:grid-cols-2 gap-4" {
|
|
@@ -147,15 +144,15 @@ component Docs {
|
|
|
147
144
|
}
|
|
148
145
|
}
|
|
149
146
|
|
|
150
|
-
// 5. IDE Extensions
|
|
151
147
|
section id="vscode" {
|
|
152
148
|
div class="bg-zinc-900/10 border border-zinc-800 rounded-3xl p-12" {
|
|
153
149
|
h2 class="text-4xl font-bold text-white mb-8 tracking-tight" { text "5. IDE Ecosystem" }
|
|
154
|
-
|
|
155
150
|
div class="grid md:grid-cols-2 gap-12" {
|
|
156
151
|
div {
|
|
157
152
|
h3 class="text-2xl font-bold text-white mb-4" { text "Visual Studio Code" }
|
|
158
|
-
p class="mb-6 text-sm" {
|
|
153
|
+
p class="mb-6 text-sm" {
|
|
154
|
+
text "Get syntax highlighting, auto-completion, and deep linting for .free files."
|
|
155
|
+
}
|
|
159
156
|
div class="space-y-4" {
|
|
160
157
|
a href="https://marketplace.visualstudio.com/items?itemName=dev-omartolba.free-vscode" class="block text-zinc-400 hover:text-white transition-colors flex items-center gap-2" {
|
|
161
158
|
text "→ Install from VS Marketplace"
|
|
@@ -181,20 +178,13 @@ component Docs {
|
|
|
181
178
|
}
|
|
182
179
|
}
|
|
183
180
|
|
|
184
|
-
// Footer
|
|
185
181
|
footer class="border-t border-zinc-900 py-20" {
|
|
186
182
|
div class="container-pro text-center" {
|
|
187
183
|
p class="text-sm text-zinc-600" {
|
|
188
184
|
text "Free Ultra Framework © 2026. Built for professionals. "
|
|
189
185
|
a href="https://omar-fathy.xyz/free-docs/guide.php" class="text-zinc-400 hover:text-white" { text "Official Encyclopedia" }
|
|
190
186
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
style {
|
|
196
|
-
html { scroll-behavior: smooth; }
|
|
197
|
-
.hero-title { background: linear-gradient(to right, #fff, #555); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
|
|
198
|
-
.badge-pro { display: inline-block; }
|
|
187
|
+
}
|
|
188
|
+
</footer>
|
|
199
189
|
}
|
|
200
190
|
}
|
|
@@ -1,67 +1,92 @@
|
|
|
1
1
|
component Home {
|
|
2
|
-
main class="
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
h1 class="hero-title" {
|
|
11
|
-
text "The Engine for"
|
|
12
|
-
br { }
|
|
13
|
-
span class="text-zinc-600" { text "High-Performance." }
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
p class="text-xl md:text-2xl text-zinc-500 max-w-3xl mx-auto mb-12 leading-relaxed font-medium" {
|
|
17
|
-
text "Experience the future of SSR with Islands Architecture, built-in Reactive state, and Enterprise-grade security. Small footprint, infinite power."
|
|
18
|
-
}
|
|
2
|
+
main class="min-h-screen bg-black text-white selection:bg-primary/30" {
|
|
3
|
+
|
|
4
|
+
// Taskfy-themed Aura Background
|
|
5
|
+
div class="fixed inset-0 pointer-events-none opacity-20 overflow-hidden" {
|
|
6
|
+
div class="absolute -top-1/4 -left-1/4 w-1/2 h-1/2 bg-primary blur-[160px] rounded-full animate-pulse" { }
|
|
7
|
+
div class="absolute -bottom-1/4 -right-1/4 w-1/2 h-1/2 bg-blue-600 blur-[160px] rounded-full" { }
|
|
8
|
+
}
|
|
19
9
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
10
|
+
// Navigation Header
|
|
11
|
+
header class="fixed top-0 w-full z-50 px-8 py-6 backdrop-blur-md border-b border-white/5" {
|
|
12
|
+
div class="max-w-7xl mx-auto flex justify-between items-center" {
|
|
13
|
+
div class="text-xl font-black italic tracking-tighter" {
|
|
14
|
+
text "FREE "
|
|
15
|
+
span class="text-primary" { text "ULTRA" }
|
|
16
|
+
}
|
|
17
|
+
div class="flex gap-8 items-center text-[10px] font-bold uppercase tracking-widest text-zinc-500" {
|
|
18
|
+
a href="#" class="hover:text-white transition-colors" { text "Engine" }
|
|
19
|
+
a href="#" class="hover:text-white transition-colors" { text "Ecosystem" }
|
|
20
|
+
a href="https://omar-fathy.xyz/free-docs/guide.php" class="px-5 py-2 bg-white text-black rounded-lg hover:bg-primary hover:text-white transition-all shadow-xl shadow-white/5" {
|
|
21
|
+
text "Read Encyclopedia"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
29
24
|
}
|
|
30
|
-
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Hero Section: The Taskfy Portal Entrance
|
|
28
|
+
section class="relative pt-48 pb-32 px-8 overflow-hidden" {
|
|
29
|
+
div class="max-w-5xl mx-auto text-center relative z-10" {
|
|
30
|
+
div class="inline-block px-4 py-1 rounded-full bg-primary/20 border border-primary/30 mb-8" {
|
|
31
|
+
span class="text-[9px] font-black tracking-[.4em] uppercase text-primary" { text "Aura v5.0.1 High-Octane" }
|
|
32
|
+
}
|
|
33
|
+
h1 class="text-7xl md:text-9xl font-black tracking-tighter leading-none mb-10" {
|
|
34
|
+
text "The Taskfy"
|
|
35
|
+
br { }
|
|
36
|
+
span class="italic text-transparent bg-clip-text bg-gradient-to-r from-primary to-blue-400" { text "Ecosystem." }
|
|
37
|
+
}
|
|
38
|
+
p class="text-xl md:text-2xl text-zinc-500 max-w-3xl mx-auto mb-16 font-medium leading-relaxed" {
|
|
39
|
+
text "Welcome to the future of high-performance engineering. Free Ultra merges Laravel's elegance, React's reactivity, and Node.js speed into one world-class engine."
|
|
40
|
+
}
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
div class="flex flex-wrap justify-center gap-6" {
|
|
43
|
+
a href="/taskfy" class="px-10 py-5 bg-primary text-white font-black uppercase tracking-widest text-xs rounded-2xl shadow-2xl shadow-primary/40 hover:scale-105 transition-all" {
|
|
44
|
+
text "Enter Portal"
|
|
45
|
+
}
|
|
46
|
+
a href="https://github.com/dev-omartolba" class="px-10 py-5 border border-white/10 text-zinc-500 font-bold uppercase tracking-widest text-xs rounded-2xl hover:bg-white/5 transition-all" {
|
|
47
|
+
text "Signal Terminal"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
36
50
|
}
|
|
37
|
-
}
|
|
38
51
|
}
|
|
39
52
|
|
|
40
|
-
//
|
|
41
|
-
section class="
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
// Infrastructure Visualizer
|
|
54
|
+
section class="py-32 px-8 relative" {
|
|
55
|
+
div class="max-w-7xl mx-auto grid md:grid-cols-3 gap-12" {
|
|
56
|
+
div class="p-10 rounded-3xl bg-zinc-950 border border-white/5 group hover:border-primary/50 transition-all" {
|
|
57
|
+
div class="text-primary text-4xl mb-6" { text "⚙️" }
|
|
58
|
+
h3 class="text-2xl font-black mb-4 italic tracking-tighter" { text "Convergence Core" }
|
|
59
|
+
p class="text-zinc-500 leading-relaxed" {
|
|
60
|
+
text "A unified runtime that automatically optimizes your components using industry-standard patterns from the Big Three."
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
div class="p-10 rounded-3xl bg-zinc-950 border border-white/5 group hover:border-primary/50 transition-all transform md:translate-y-12" {
|
|
64
|
+
div class="text-primary text-4xl mb-6" { text "🛡️" }
|
|
65
|
+
h3 class="text-2xl font-black mb-4 italic tracking-tighter" { text "Aura Firewall" }
|
|
66
|
+
p class="text-zinc-500 leading-relaxed" {
|
|
67
|
+
text "Real-time threat detection and surgical request filtering embedded directly into the framework's heartbeat."
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
div class="p-10 rounded-3xl bg-zinc-950 border border-white/5 group hover:border-primary/50 transition-all" {
|
|
71
|
+
div class="text-primary text-4xl mb-6" { text "🚀" }
|
|
72
|
+
h3 class="text-2xl font-black mb-4 italic tracking-tighter" { text "Hyper Speed" }
|
|
73
|
+
p class="text-zinc-500 leading-relaxed" {
|
|
74
|
+
text "Native Brotli compression and uWebSockets.js integration deliver sub-millisecond response times under heavy load."
|
|
75
|
+
}
|
|
76
|
+
}
|
|
49
77
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
p class="text-base text-zinc-500 leading-relaxed" { text "Partial hydration logic that ships minimal JavaScript for maximum SEO benefits." }
|
|
56
|
-
}
|
|
57
|
-
div class="card-pro" {
|
|
58
|
-
div class="w-10 h-10 rounded-lg bg-zinc-900 border border-border flex items-center justify-center mb-6" {
|
|
59
|
-
text "🛡️"
|
|
60
|
-
}
|
|
61
|
-
h3 class="text-xl font-bold mb-3" { text "Security" }
|
|
62
|
-
p class="text-base text-zinc-500 leading-relaxed" { text "Built-in DDoS protection, CSRF guards, and secure-by-default environment." }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
footer class="py-20 border-t border-white/5 text-center" {
|
|
81
|
+
p class="text-[10px] font-black uppercase tracking-[.6em] text-zinc-700" {
|
|
82
|
+
text "FREE ULTRA © 2026. ALL PROTOCOLS VERIFIED."
|
|
63
83
|
}
|
|
64
|
-
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
style {
|
|
87
|
+
h1 { text-shadow: 0 20px 80px rgba(59, 130, 246, 0.2); }
|
|
88
|
+
.bg-primary { background-color: #3b82f6; }
|
|
89
|
+
.text-primary { color: #3b82f6; }
|
|
65
90
|
}
|
|
66
91
|
}
|
|
67
92
|
}
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
// A simple GET request that renders the 'Home' view component
|
|
17
|
-
|
|
17
|
+
Get "/" -> Home
|
|
18
18
|
|
|
19
19
|
// Documentation & Authentication
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
Get "/docs" -> Docs
|
|
21
|
+
Get "/login" -> Login
|
|
22
22
|
|
|
23
23
|
// Example of a route that points to a dedicated controller logic before rendering
|
|
24
24
|
// Ensure the 'Dashboard' view is defined in resources/views
|
|
25
|
-
|
|
25
|
+
Get "/dashboard" {
|
|
26
26
|
// Calling an action/controller before returning the view
|
|
27
27
|
// The controller should handle checking if the user is authenticated
|
|
28
28
|
return Dashboard;
|
|
File without changes
|