frontend-hamroun 1.2.79 → 1.2.82
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/LICENSE +21 -0
- package/README.md +129 -1513
- package/bin/cli.js +506 -145
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.client.cjs +2 -0
- package/dist/index.client.cjs.map +1 -0
- package/dist/index.client.js +26 -0
- package/dist/index.client.js.map +1 -0
- package/dist/index.js +299 -1
- package/dist/index.js.map +1 -0
- package/dist/jsx-runtime.cjs +2 -0
- package/dist/jsx-runtime.cjs.map +1 -0
- package/dist/jsx-runtime.js +93 -1
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/renderer-Bo9zkUZ_.js +52 -0
- package/dist/renderer-Bo9zkUZ_.js.map +1 -0
- package/dist/renderer-Din1y3YM.cjs +2 -0
- package/dist/renderer-Din1y3YM.cjs.map +1 -0
- package/dist/server-renderer-CqIpQ-od.cjs +2 -0
- package/dist/server-renderer-CqIpQ-od.cjs.map +1 -0
- package/dist/server-renderer-QHt45Ip2.js +255 -0
- package/dist/server-renderer-QHt45Ip2.js.map +1 -0
- package/dist/server-renderer.cjs +2 -0
- package/dist/server-renderer.cjs.map +1 -0
- package/dist/server-renderer.js +5 -1
- package/dist/server-renderer.js.map +1 -0
- package/package.json +77 -120
- package/templates/basic-app/build.js +22 -0
- package/templates/basic-app/dev.js +27 -0
- package/templates/basic-app/esbuild.config.js +28 -0
- package/templates/basic-app/index.html +1 -1
- package/templates/basic-app/package.json +29 -28
- package/templates/basic-app/server.js +24 -0
- package/templates/basic-app/src/App.jsx +16 -0
- package/templates/basic-app/src/App.tsx +26 -0
- package/templates/basic-app/src/client.jsx +5 -0
- package/templates/basic-app/src/client.tsx +11 -0
- package/templates/basic-app/src/components/Counter.jsx +13 -0
- package/templates/basic-app/src/components/Counter.tsx +18 -0
- package/templates/basic-app/src/jsx-shim.js +3 -0
- package/templates/basic-app/src/jsx-shim.ts +11 -0
- package/templates/basic-app/src/main.jsx +98 -0
- package/templates/basic-app/src/main.tsx +0 -1
- package/templates/basic-app/src/server.js +47 -0
- package/templates/basic-app/src/server.ts +52 -0
- package/templates/basic-app/tsconfig.server.json +11 -0
- package/templates/complete-app/lib/frontend-hamroun.js +182 -0
- package/templates/complete-app/package.json +2 -1
- package/templates/complete-app/pages/about.jsx +0 -0
- package/templates/complete-app/pages/index.jsx +0 -0
- package/templates/complete-app/pages/wasm-demo.jsx +0 -0
- package/templates/complete-app/public/client.js +58 -49
- package/templates/complete-app/public/index.html +88 -17
- package/templates/complete-app/public/styles.css +30 -533
- package/templates/complete-app/server.js +31 -222
- package/templates/complete-app/wasm/build.bat +0 -0
- package/templates/complete-app/wasm/build.sh +0 -0
- package/templates/complete-app/wasm/example.go +0 -0
- package/templates/fullstack-app/build/main.js +130 -101
- package/templates/fullstack-app/build/main.js.map +4 -4
- package/templates/fullstack-app/package-lock.json +1773 -566
- package/templates/ssr-template/esbuild.config.js +33 -0
- package/templates/ssr-template/jsx-shim.js +1 -0
- package/templates/ssr-template/package.json +22 -16
- package/templates/ssr-template/src/App.tsx +12 -52
- package/templates/ssr-template/src/client.tsx +3 -17
- package/templates/ssr-template/src/server.ts +21 -204
- package/templates/ssr-template/tsconfig.json +10 -13
- package/templates/ssr-template/tsconfig.server.json +6 -14
- package/templates/wasm/build-wasm.js +228 -0
- package/templates/wasm/esbuild.config.js +63 -0
- package/templates/wasm/go/main.go +256 -0
- package/templates/wasm/go/wasm_exec.js +0 -0
- package/templates/wasm/index.html +97 -0
- package/templates/wasm/jsx-shim.js +9 -0
- package/templates/{go-wasm-app → wasm}/package-lock.json +5307 -3732
- package/templates/wasm/package.json +42 -0
- package/templates/wasm/public/example.wasm +0 -0
- package/templates/wasm/src/App.tsx +564 -0
- package/templates/wasm/src/client.tsx +220 -0
- package/templates/wasm/src/index.tsx +21 -0
- package/templates/wasm/src/server.ts +145 -0
- package/templates/wasm/tsconfig.json +21 -0
- package/templates/wasm/tsconfig.node.json +13 -0
- package/templates/wasm/tsconfig.server.json +23 -0
- package/templates/wasm/vite.config.ts +56 -0
- package/templates/wasm/wasm-loader.js +103 -0
- package/dist/batch/package.json +0 -16
- package/dist/client-router/package.json +0 -16
- package/dist/component/package.json +0 -16
- package/dist/context/package.json +0 -16
- package/dist/event-bus/package.json +0 -16
- package/dist/forms/package.json +0 -16
- package/dist/hooks/package.json +0 -16
- package/dist/hooks-0728361a.cjs +0 -1
- package/dist/hooks-b58f947c.js +0 -133
- package/dist/hooks.js +0 -1
- package/dist/hooks.mjs +0 -13
- package/dist/index.mjs +0 -137
- package/dist/jsx-runtime/package.json +0 -16
- package/dist/jsx-runtime.mjs +0 -64
- package/dist/lifecycle-events/package.json +0 -16
- package/dist/package.json +0 -71
- package/dist/render-component/package.json +0 -16
- package/dist/renderer/package.json +0 -16
- package/dist/renderer.js +0 -1
- package/dist/renderer.mjs +0 -27
- package/dist/router/package.json +0 -16
- package/dist/server/package.json +0 -17
- package/dist/server/src/batch.d.ts +0 -3
- package/dist/server/src/batch.js +0 -23
- package/dist/server/src/batch.js.map +0 -1
- package/dist/server/src/client-router.d.ts +0 -60
- package/dist/server/src/client-router.js +0 -210
- package/dist/server/src/client-router.js.map +0 -1
- package/dist/server/src/component.d.ts +0 -14
- package/dist/server/src/component.js +0 -106
- package/dist/server/src/component.js.map +0 -1
- package/dist/server/src/context.d.ts +0 -13
- package/dist/server/src/context.js +0 -21
- package/dist/server/src/context.js.map +0 -1
- package/dist/server/src/event-bus.d.ts +0 -23
- package/dist/server/src/event-bus.js +0 -75
- package/dist/server/src/event-bus.js.map +0 -1
- package/dist/server/src/forms.d.ts +0 -40
- package/dist/server/src/forms.js +0 -148
- package/dist/server/src/forms.js.map +0 -1
- package/dist/server/src/hooks.d.ts +0 -12
- package/dist/server/src/hooks.js +0 -170
- package/dist/server/src/hooks.js.map +0 -1
- package/dist/server/src/index.client.d.ts +0 -12
- package/dist/server/src/index.client.js +0 -14
- package/dist/server/src/index.client.js.map +0 -1
- package/dist/server/src/index.d.ts +0 -88
- package/dist/server/src/index.js +0 -79
- package/dist/server/src/index.js.map +0 -1
- package/dist/server/src/jsx-runtime/jsx-dev-runtime.d.ts +0 -1
- package/dist/server/src/jsx-runtime/jsx-dev-runtime.js +0 -2
- package/dist/server/src/jsx-runtime/jsx-dev-runtime.js.map +0 -1
- package/dist/server/src/jsx-runtime/jsx-runtime.d.ts +0 -4
- package/dist/server/src/jsx-runtime/jsx-runtime.js +0 -41
- package/dist/server/src/jsx-runtime/jsx-runtime.js.map +0 -1
- package/dist/server/src/jsx-runtime.d.ts +0 -20
- package/dist/server/src/jsx-runtime.js +0 -105
- package/dist/server/src/jsx-runtime.js.map +0 -1
- package/dist/server/src/lifecycle-events.d.ts +0 -108
- package/dist/server/src/lifecycle-events.js +0 -177
- package/dist/server/src/lifecycle-events.js.map +0 -1
- package/dist/server/src/renderComponent.d.ts +0 -13
- package/dist/server/src/renderComponent.js +0 -30
- package/dist/server/src/renderComponent.js.map +0 -1
- package/dist/server/src/renderer.d.ts +0 -2
- package/dist/server/src/renderer.js +0 -31
- package/dist/server/src/renderer.js.map +0 -1
- package/dist/server/src/router.d.ts +0 -55
- package/dist/server/src/router.js +0 -166
- package/dist/server/src/router.js.map +0 -1
- package/dist/server/src/server/api-router.d.ts +0 -15
- package/dist/server/src/server/api-router.js +0 -111
- package/dist/server/src/server/api-router.js.map +0 -1
- package/dist/server/src/server/auth.d.ts +0 -32
- package/dist/server/src/server/auth.js +0 -80
- package/dist/server/src/server/auth.js.map +0 -1
- package/dist/server/src/server/database.d.ts +0 -24
- package/dist/server/src/server/database.js +0 -135
- package/dist/server/src/server/database.js.map +0 -1
- package/dist/server/src/server/index.d.ts +0 -116
- package/dist/server/src/server/index.js +0 -508
- package/dist/server/src/server/index.js.map +0 -1
- package/dist/server/src/server/middleware.d.ts +0 -11
- package/dist/server/src/server/middleware.js +0 -46
- package/dist/server/src/server/middleware.js.map +0 -1
- package/dist/server/src/server/server.d.ts +0 -9
- package/dist/server/src/server/server.js +0 -87
- package/dist/server/src/server/server.js.map +0 -1
- package/dist/server/src/server/templates.d.ts +0 -30
- package/dist/server/src/server/templates.js +0 -208
- package/dist/server/src/server/templates.js.map +0 -1
- package/dist/server/src/server/types.d.ts +0 -38
- package/dist/server/src/server/types.js +0 -4
- package/dist/server/src/server/types.js.map +0 -1
- package/dist/server/src/server/utils.d.ts +0 -70
- package/dist/server/src/server/utils.js +0 -156
- package/dist/server/src/server/utils.js.map +0 -1
- package/dist/server/src/server/wasm.d.ts +0 -9
- package/dist/server/src/server/wasm.js +0 -117
- package/dist/server/src/server/wasm.js.map +0 -1
- package/dist/server/src/server-renderer.d.ts +0 -5
- package/dist/server/src/server-renderer.js +0 -106
- package/dist/server/src/server-renderer.js.map +0 -1
- package/dist/server/src/server-types.d.ts +0 -42
- package/dist/server/src/server-types.js +0 -6
- package/dist/server/src/server-types.js.map +0 -1
- package/dist/server/src/store.d.ts +0 -41
- package/dist/server/src/store.js +0 -99
- package/dist/server/src/store.js.map +0 -1
- package/dist/server/src/types.d.ts +0 -19
- package/dist/server/src/types.js +0 -2
- package/dist/server/src/types.js.map +0 -1
- package/dist/server/src/utils.d.ts +0 -46
- package/dist/server/src/utils.js +0 -144
- package/dist/server/src/utils.js.map +0 -1
- package/dist/server/src/vdom.d.ts +0 -8
- package/dist/server/src/vdom.js +0 -22
- package/dist/server/src/vdom.js.map +0 -1
- package/dist/server/src/wasm.d.ts +0 -36
- package/dist/server/src/wasm.js +0 -159
- package/dist/server/src/wasm.js.map +0 -1
- package/dist/server/tsconfig.server.tsbuildinfo +0 -1
- package/dist/server-renderer/package.json +0 -16
- package/dist/server-renderer.mjs +0 -64
- package/dist/store/package.json +0 -16
- package/dist/types/package.json +0 -16
- package/dist/utils/package.json +0 -16
- package/dist/vdom/package.json +0 -16
- package/dist/wasm/package.json +0 -16
- package/dist/wasm.js +0 -1
- package/dist/wasm.mjs +0 -103
- package/templates/basic-app/docs/rapport_pfe.aux +0 -27
- package/templates/basic-app/docs/rapport_pfe.log +0 -399
- package/templates/basic-app/docs/rapport_pfe.out +0 -10
- package/templates/basic-app/docs/rapport_pfe.pdf +0 -0
- package/templates/basic-app/docs/rapport_pfe.tex +0 -68
- package/templates/basic-app/docs/rapport_pfe.toc +0 -14
- package/templates/complete-app/package-lock.json +0 -2536
- package/templates/go-wasm-app/README.md +0 -38
- package/templates/go-wasm-app/babel.config.js +0 -21
- package/templates/go-wasm-app/build-client.js +0 -49
- package/templates/go-wasm-app/build-wasm.js +0 -237
- package/templates/go-wasm-app/build.config.js +0 -62
- package/templates/go-wasm-app/build.js +0 -218
- package/templates/go-wasm-app/package.json +0 -32
- package/templates/go-wasm-app/public/index.html +0 -128
- package/templates/go-wasm-app/public/styles.css +0 -197
- package/templates/go-wasm-app/public/wasm/example.wasm +0 -0
- package/templates/go-wasm-app/public/wasm/wasm_exec_node.js +0 -39
- package/templates/go-wasm-app/server.js +0 -70
- package/templates/go-wasm-app/src/App.jsx +0 -38
- package/templates/go-wasm-app/src/app.js +0 -173
- package/templates/go-wasm-app/src/client.js +0 -57
- package/templates/go-wasm-app/src/components/Footer.jsx +0 -13
- package/templates/go-wasm-app/src/components/Header.jsx +0 -19
- package/templates/go-wasm-app/src/components/WasmDemo.jsx +0 -120
- package/templates/go-wasm-app/src/main.jsx +0 -12
- package/templates/go-wasm-app/src/wasm/example.go +0 -75
- package/templates/go-wasm-app/tsconfig.server.json +0 -18
- package/templates/go-wasm-app/vite.config.js +0 -45
- package/templates/ssr-template/client.js +0 -58
- package/templates/ssr-template/package-lock.json +0 -2478
- package/templates/ssr-template/public/index.html +0 -47
- package/templates/ssr-template/readme.md +0 -188
- package/templates/ssr-template/server.js +0 -369
- package/templates/ssr-template/server.ts +0 -275
- package/templates/ssr-template/src/client.ts +0 -61
- package/templates/ssr-template/src/pages/index.tsx +0 -51
- package/templates/ssr-template/vite.config.js +0 -57
- /package/{dist/Counter.d.ts → templates/complete-app/api/hello.js} +0 -0
- /package/templates/{go-wasm-app/public/wasm → wasm/public}/wasm_exec.js +0 -0
@@ -2,17 +2,15 @@ import express from 'express';
|
|
2
2
|
import path from 'path';
|
3
3
|
import { fileURLToPath } from 'url';
|
4
4
|
import fs from 'fs';
|
5
|
+
// Fix imports by using only the exports that exist
|
5
6
|
import {
|
6
7
|
renderToString,
|
7
|
-
jsx,
|
8
|
-
Server,
|
9
|
-
createServer,
|
10
|
-
rateLimit,
|
8
|
+
jsx,
|
11
9
|
requestLogger,
|
12
10
|
errorHandler,
|
13
11
|
notFoundHandler,
|
14
|
-
|
15
|
-
} from 'frontend-hamroun';
|
12
|
+
rateLimit
|
13
|
+
} from './lib/frontend-hamroun.js';
|
16
14
|
import dotenv from 'dotenv';
|
17
15
|
import compression from 'compression';
|
18
16
|
import cors from 'cors';
|
@@ -42,6 +40,7 @@ app.use(rateLimit({
|
|
42
40
|
}));
|
43
41
|
|
44
42
|
// Serve static files from the public directory
|
43
|
+
// Important: This middleware should be defined BEFORE your catch-all route
|
45
44
|
app.use(express.static(path.join(__dirname, 'public')));
|
46
45
|
|
47
46
|
// Add correct MIME type for client.js module
|
@@ -55,7 +54,7 @@ app.get('*.wasm', (req, res, next) => {
|
|
55
54
|
next();
|
56
55
|
});
|
57
56
|
|
58
|
-
// Add API routes example
|
57
|
+
// Add API routes example
|
59
58
|
app.get('/api/hello', (req, res) => {
|
60
59
|
res.json({
|
61
60
|
message: 'Hello from the API!',
|
@@ -63,31 +62,6 @@ app.get('/api/hello', (req, res) => {
|
|
63
62
|
});
|
64
63
|
});
|
65
64
|
|
66
|
-
// Load WebAssembly modules if available
|
67
|
-
async function loadWasmModules() {
|
68
|
-
const wasmDir = path.join(__dirname, 'wasm');
|
69
|
-
|
70
|
-
if (fs.existsSync(wasmDir)) {
|
71
|
-
try {
|
72
|
-
const wasmFiles = fs.readdirSync(wasmDir).filter(file => file.endsWith('.wasm'));
|
73
|
-
|
74
|
-
for (const wasmFile of wasmFiles) {
|
75
|
-
const wasmPath = path.join(wasmDir, wasmFile);
|
76
|
-
const wasmModule = await loadGoWasmFromFile(wasmPath, { debug: true });
|
77
|
-
|
78
|
-
console.log(`Loaded WASM module: ${wasmFile}`);
|
79
|
-
console.log(`Available functions:`, Object.keys(wasmModule.functions));
|
80
|
-
|
81
|
-
// Store modules globally for API routes to use
|
82
|
-
global.wasmModules = global.wasmModules || {};
|
83
|
-
global.wasmModules[wasmFile.replace('.wasm', '')] = wasmModule;
|
84
|
-
}
|
85
|
-
} catch (error) {
|
86
|
-
console.error('Failed to load WASM modules:', error);
|
87
|
-
}
|
88
|
-
}
|
89
|
-
}
|
90
|
-
|
91
65
|
// Find the pages directory
|
92
66
|
const getPagesDirectory = () => {
|
93
67
|
return path.join(__dirname, 'pages');
|
@@ -103,31 +77,6 @@ const fileExists = async (filePath) => {
|
|
103
77
|
}
|
104
78
|
};
|
105
79
|
|
106
|
-
// Generate meta tags for SEO
|
107
|
-
async function generateMetaTags(content, title = '') {
|
108
|
-
// Extract title from content or use provided title
|
109
|
-
const pageTitle = title || 'Frontend Hamroun App';
|
110
|
-
|
111
|
-
// Generate description from content
|
112
|
-
const plainText = content.replace(/<[^>]*>/g, ' ').trim();
|
113
|
-
const description = plainText.substring(0, 160) + (plainText.length > 160 ? '...' : '');
|
114
|
-
|
115
|
-
// Extract keywords
|
116
|
-
const keywords = plainText
|
117
|
-
.toLowerCase()
|
118
|
-
.replace(/[^\w\s]/g, '')
|
119
|
-
.split(/\s+/)
|
120
|
-
.filter(w => w.length > 3)
|
121
|
-
.slice(0, 5)
|
122
|
-
.join(', ');
|
123
|
-
|
124
|
-
return {
|
125
|
-
title: pageTitle,
|
126
|
-
description,
|
127
|
-
keywords
|
128
|
-
};
|
129
|
-
}
|
130
|
-
|
131
80
|
// Map URL path to component path
|
132
81
|
const getComponentPath = async (urlPath) => {
|
133
82
|
const pagesDir = getPagesDirectory();
|
@@ -144,8 +93,7 @@ const getComponentPath = async (urlPath) => {
|
|
144
93
|
}
|
145
94
|
|
146
95
|
// Try direct match (e.g., /about -> /pages/about.js)
|
147
|
-
|
148
|
-
const possibleExtensions = ['.js']; // Remove .jsx, .ts, .tsx
|
96
|
+
const possibleExtensions = ['.js'];
|
149
97
|
|
150
98
|
for (const ext of possibleExtensions) {
|
151
99
|
const directPath = path.join(pagesDir, `${urlPath.slice(1)}${ext}`);
|
@@ -168,80 +116,24 @@ const getComponentPath = async (urlPath) => {
|
|
168
116
|
}
|
169
117
|
}
|
170
118
|
|
171
|
-
// Look for dynamic routes (with [param] in filename)
|
172
|
-
const segments = urlPath.split('/').filter(Boolean);
|
173
|
-
const dynamicRoutes = [];
|
174
|
-
|
175
|
-
// Recursively scan pages directory for all files
|
176
|
-
const scanDir = (dir, basePath = '') => {
|
177
|
-
const items = fs.readdirSync(dir, { withFileTypes: true });
|
178
|
-
|
179
|
-
for (const item of items) {
|
180
|
-
const itemPath = path.join(dir, item.name);
|
181
|
-
const routePath = path.join(basePath, item.name);
|
182
|
-
|
183
|
-
if (item.isDirectory()) {
|
184
|
-
scanDir(itemPath, routePath);
|
185
|
-
} else if (item.name.endsWith('.js')) {
|
186
|
-
if (item.name.includes('[')) {
|
187
|
-
// This is a dynamic route file
|
188
|
-
const urlPattern = routePath
|
189
|
-
.replace(/\.js$/, '')
|
190
|
-
.replace(/\[([^\]]+)\]/g, ':$1');
|
191
|
-
|
192
|
-
dynamicRoutes.push({
|
193
|
-
pattern: urlPattern,
|
194
|
-
componentPath: itemPath
|
195
|
-
});
|
196
|
-
}
|
197
|
-
}
|
198
|
-
}
|
199
|
-
};
|
200
|
-
|
201
|
-
scanDir(pagesDir);
|
202
|
-
|
203
|
-
// Check if any dynamic routes match
|
204
|
-
for (const route of dynamicRoutes) {
|
205
|
-
const routeSegments = route.pattern.split('/').filter(Boolean);
|
206
|
-
if (routeSegments.length !== segments.length) continue;
|
207
|
-
|
208
|
-
const params = {};
|
209
|
-
let matches = true;
|
210
|
-
|
211
|
-
for (let i = 0; i < segments.length; i++) {
|
212
|
-
const routeSeg = routeSegments[i];
|
213
|
-
const urlSeg = segments[i];
|
214
|
-
|
215
|
-
if (routeSeg.startsWith(':')) {
|
216
|
-
// This is a parameter
|
217
|
-
const paramName = routeSeg.slice(1);
|
218
|
-
params[paramName] = urlSeg;
|
219
|
-
} else if (routeSeg !== urlSeg) {
|
220
|
-
matches = false;
|
221
|
-
break;
|
222
|
-
}
|
223
|
-
}
|
224
|
-
|
225
|
-
if (matches) {
|
226
|
-
return {
|
227
|
-
componentPath: route.componentPath,
|
228
|
-
params
|
229
|
-
};
|
230
|
-
}
|
231
|
-
}
|
232
|
-
|
233
119
|
// No match found
|
234
120
|
return null;
|
235
121
|
};
|
236
122
|
|
237
|
-
// Handle all routes with SSR
|
123
|
+
// Handle all GET routes with SSR - explicitly exclude /public/ paths
|
238
124
|
app.get('*', async (req, res, next) => {
|
239
125
|
try {
|
240
|
-
// Skip
|
241
|
-
if (req.path.
|
126
|
+
// Skip API routes
|
127
|
+
if (req.path.startsWith('/api/')) {
|
242
128
|
return next();
|
243
129
|
}
|
244
|
-
|
130
|
+
|
131
|
+
// Skip static assets - check file extensions that should be handled as static
|
132
|
+
if (req.path.match(/\.(js|css|ico|png|jpg|jpeg|gif|svg|wasm|txt|pdf|json|map)$/)) {
|
133
|
+
return next();
|
134
|
+
}
|
135
|
+
|
136
|
+
// Try to find the matching component
|
245
137
|
const routeResult = await getComponentPath(req.path);
|
246
138
|
|
247
139
|
if (!routeResult) {
|
@@ -271,16 +163,14 @@ app.get('*', async (req, res, next) => {
|
|
271
163
|
`);
|
272
164
|
}
|
273
165
|
|
274
|
-
//
|
275
|
-
const componentUrl = new URL(`file://${routeResult.componentPath}`).href;
|
276
|
-
|
166
|
+
// Import the component
|
277
167
|
try {
|
278
|
-
|
168
|
+
const componentUrl = `file://${routeResult.componentPath}`;
|
279
169
|
const moduleImport = await import(componentUrl);
|
280
170
|
const PageComponent = moduleImport.default || moduleImport;
|
281
171
|
|
282
172
|
if (!PageComponent || typeof PageComponent !== 'function') {
|
283
|
-
throw new Error(`Invalid component in ${routeResult.componentPath}
|
173
|
+
throw new Error(`Invalid component in ${routeResult.componentPath}`);
|
284
174
|
}
|
285
175
|
|
286
176
|
// Create props with route data
|
@@ -293,40 +183,9 @@ app.get('*', async (req, res, next) => {
|
|
293
183
|
}
|
294
184
|
};
|
295
185
|
|
296
|
-
//
|
297
|
-
|
298
|
-
|
299
|
-
// Create a simple HTML structure based on the component's output
|
300
|
-
const result = PageComponent(initialProps);
|
301
|
-
|
302
|
-
// Create a fallback HTML if the result is not valid
|
303
|
-
if (!result || typeof result !== 'object' || !result.type) {
|
304
|
-
html = `
|
305
|
-
<div class="error-container">
|
306
|
-
<h1>Frontend Hamroun App</h1>
|
307
|
-
<p>This is a simple fallback page.</p>
|
308
|
-
<p>Path: ${req.path}</p>
|
309
|
-
<p>Server time: ${initialProps.api.serverTime}</p>
|
310
|
-
</div>
|
311
|
-
`;
|
312
|
-
} else {
|
313
|
-
// Use renderToString with error handling
|
314
|
-
html = renderToString(result) || '<div>Rendering failed</div>';
|
315
|
-
}
|
316
|
-
} catch (err) {
|
317
|
-
console.error("Error with renderToString:", err);
|
318
|
-
html = `
|
319
|
-
<div class="error-container">
|
320
|
-
<h1>Rendering Error</h1>
|
321
|
-
<p>There was an error rendering this page: ${err.message}</p>
|
322
|
-
<p>Path: ${req.path}</p>
|
323
|
-
</div>
|
324
|
-
`;
|
325
|
-
}
|
326
|
-
|
327
|
-
// Generate meta tags
|
328
|
-
const metaTags = await generateMetaTags(html,
|
329
|
-
typeof PageComponent.getTitle === 'function' ? PageComponent.getTitle(initialProps) : 'Frontend Hamroun App');
|
186
|
+
// Render the component
|
187
|
+
const result = PageComponent(initialProps);
|
188
|
+
let html = renderToString(result);
|
330
189
|
|
331
190
|
// Send complete HTML with hydration data
|
332
191
|
res.send(`
|
@@ -335,61 +194,22 @@ app.get('*', async (req, res, next) => {
|
|
335
194
|
<head>
|
336
195
|
<meta charset="UTF-8">
|
337
196
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
338
|
-
|
339
|
-
<!-- Generated Meta Tags -->
|
340
|
-
<title>${metaTags.title}</title>
|
341
|
-
<meta name="description" content="${metaTags.description}">
|
342
|
-
<meta name="keywords" content="${metaTags.keywords}">
|
343
|
-
|
344
|
-
<!-- Open Graph Meta Tags -->
|
345
|
-
<meta property="og:title" content="${metaTags.title}">
|
346
|
-
<meta property="og:description" content="${metaTags.description}">
|
347
|
-
<meta property="og:type" content="website">
|
348
|
-
<meta property="og:url" content="${req.protocol}://${req.get('host')}${req.originalUrl}">
|
349
|
-
|
350
|
-
<!-- Import styles -->
|
197
|
+
<title>Frontend Hamroun App</title>
|
351
198
|
<link href="/styles.css" rel="stylesheet" type="text/css">
|
352
199
|
</head>
|
353
200
|
<body>
|
354
201
|
<div id="app">${html}</div>
|
355
|
-
|
356
|
-
<!-- Add initial state for hydration -->
|
357
202
|
<script id="__APP_DATA__" type="application/json">${JSON.stringify(initialProps)}</script>
|
358
203
|
<script type="module" src="/client.js"></script>
|
359
204
|
</body>
|
360
205
|
</html>
|
361
206
|
`);
|
362
|
-
} catch (
|
363
|
-
console.error(
|
364
|
-
|
207
|
+
} catch (error) {
|
208
|
+
console.error('Error rendering component:', error);
|
209
|
+
next(error);
|
365
210
|
}
|
366
211
|
} catch (error) {
|
367
|
-
|
368
|
-
res.status(500).send(`
|
369
|
-
<!DOCTYPE html>
|
370
|
-
<html>
|
371
|
-
<head>
|
372
|
-
<title>500 - Server Error</title>
|
373
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
374
|
-
<link href="/styles.css" rel="stylesheet" type="text/css">
|
375
|
-
</head>
|
376
|
-
<body>
|
377
|
-
<div id="app">
|
378
|
-
<div class="container">
|
379
|
-
<h1>500 - Server Error</h1>
|
380
|
-
<p>Something went wrong on the server.</p>
|
381
|
-
${process.env.NODE_ENV === 'development' ? `<pre>${error.stack}</pre>` : ''}
|
382
|
-
<a href="/" class="button">Go to Home</a>
|
383
|
-
</div>
|
384
|
-
</div>
|
385
|
-
<script id="__APP_DATA__" type="application/json">${JSON.stringify({
|
386
|
-
path: req.path,
|
387
|
-
error: 'server_error'
|
388
|
-
})}</script>
|
389
|
-
<script type="module" src="/client.js"></script>
|
390
|
-
</body>
|
391
|
-
</html>
|
392
|
-
`);
|
212
|
+
next(error);
|
393
213
|
}
|
394
214
|
});
|
395
215
|
|
@@ -400,18 +220,7 @@ app.use(errorHandler);
|
|
400
220
|
app.use(notFoundHandler);
|
401
221
|
|
402
222
|
// Start the server
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
// Start the server
|
408
|
-
app.listen(PORT, () => {
|
409
|
-
console.log(`Server running at http://localhost:${PORT}`);
|
410
|
-
console.log(`Mode: ${process.env.NODE_ENV || 'development'}`);
|
411
|
-
});
|
412
|
-
};
|
413
|
-
|
414
|
-
startServer().catch(err => {
|
415
|
-
console.error('Failed to start server:', err);
|
416
|
-
process.exit(1);
|
223
|
+
app.listen(PORT, () => {
|
224
|
+
console.log(`Server running at http://localhost:${PORT}`);
|
225
|
+
console.log(`Mode: ${process.env.NODE_ENV || 'development'}`);
|
417
226
|
});
|
File without changes
|
File without changes
|
File without changes
|
@@ -14,7 +14,90 @@ var __export = (target, all) => {
|
|
14
14
|
__defProp(target, name, { get: all[name], enumerable: true });
|
15
15
|
};
|
16
16
|
|
17
|
-
// node_modules/frontend-hamroun/dist/
|
17
|
+
// node_modules/frontend-hamroun/dist/jsx-runtime.js
|
18
|
+
function jsx(type, props) {
|
19
|
+
console.log("JSX Transform:", { type, props });
|
20
|
+
const processedProps = { ...props };
|
21
|
+
if (arguments.length > 2) {
|
22
|
+
processedProps.children = Array.prototype.slice.call(arguments, 2);
|
23
|
+
}
|
24
|
+
return { type, props: processedProps };
|
25
|
+
}
|
26
|
+
async function createElement(vnode) {
|
27
|
+
console.log("Creating element from:", vnode);
|
28
|
+
if (vnode == null) {
|
29
|
+
return document.createTextNode("");
|
30
|
+
}
|
31
|
+
if (typeof vnode === "boolean") {
|
32
|
+
return document.createTextNode("");
|
33
|
+
}
|
34
|
+
if (typeof vnode === "number" || typeof vnode === "string") {
|
35
|
+
return document.createTextNode(String(vnode));
|
36
|
+
}
|
37
|
+
if (Array.isArray(vnode)) {
|
38
|
+
const fragment = document.createDocumentFragment();
|
39
|
+
for (const child of vnode) {
|
40
|
+
const node = await createElement(child);
|
41
|
+
fragment.appendChild(node);
|
42
|
+
}
|
43
|
+
return fragment;
|
44
|
+
}
|
45
|
+
if ("type" in vnode && vnode.props !== void 0) {
|
46
|
+
const { type, props } = vnode;
|
47
|
+
if (typeof type === "function") {
|
48
|
+
try {
|
49
|
+
const result = await type(props || {});
|
50
|
+
const node = await createElement(result);
|
51
|
+
if (node instanceof Element) {
|
52
|
+
node.setAttribute("data-component-id", type.name || type.toString());
|
53
|
+
}
|
54
|
+
return node;
|
55
|
+
} catch (error) {
|
56
|
+
console.error("Error rendering component:", error);
|
57
|
+
return document.createTextNode("");
|
58
|
+
}
|
59
|
+
}
|
60
|
+
const element = document.createElement(type);
|
61
|
+
for (const [key, value] of Object.entries(props || {})) {
|
62
|
+
if (key === "children")
|
63
|
+
continue;
|
64
|
+
if (key.startsWith("on") && typeof value === "function") {
|
65
|
+
const eventName = key.toLowerCase().slice(2);
|
66
|
+
const existingHandler = element.__events?.[eventName];
|
67
|
+
if (existingHandler) {
|
68
|
+
element.removeEventListener(eventName, existingHandler);
|
69
|
+
}
|
70
|
+
element.addEventListener(eventName, value);
|
71
|
+
if (!element.__events) {
|
72
|
+
element.__events = {};
|
73
|
+
}
|
74
|
+
element.__events[eventName] = value;
|
75
|
+
} else if (key === "style" && typeof value === "object") {
|
76
|
+
Object.assign(element.style, value);
|
77
|
+
} else if (key === "className") {
|
78
|
+
element.setAttribute("class", String(value));
|
79
|
+
} else if (key !== "key" && key !== "ref") {
|
80
|
+
element.setAttribute(key, String(value));
|
81
|
+
}
|
82
|
+
}
|
83
|
+
const children = props?.children;
|
84
|
+
if (children != null) {
|
85
|
+
const childArray = Array.isArray(children) ? children.flat() : [children];
|
86
|
+
for (const child of childArray) {
|
87
|
+
const childNode = await createElement(child);
|
88
|
+
element.appendChild(childNode);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
return element;
|
92
|
+
}
|
93
|
+
return document.createTextNode(String(vnode));
|
94
|
+
}
|
95
|
+
var init_jsx_runtime = __esm({
|
96
|
+
"node_modules/frontend-hamroun/dist/jsx-runtime.js"() {
|
97
|
+
}
|
98
|
+
});
|
99
|
+
|
100
|
+
// node_modules/frontend-hamroun/dist/server-renderer-QHt45Ip2.js
|
18
101
|
function batchUpdates(fn) {
|
19
102
|
if (isBatching) {
|
20
103
|
queue.push(fn);
|
@@ -25,7 +108,7 @@ function batchUpdates(fn) {
|
|
25
108
|
fn();
|
26
109
|
while (queue.length > 0) {
|
27
110
|
const nextFn = queue.shift();
|
28
|
-
nextFn
|
111
|
+
nextFn?.();
|
29
112
|
}
|
30
113
|
} finally {
|
31
114
|
isBatching = false;
|
@@ -61,7 +144,7 @@ function useState(initial) {
|
|
61
144
|
componentState.set(index2, initial);
|
62
145
|
}
|
63
146
|
const state2 = componentState.get(index2);
|
64
|
-
const setState2 = (
|
147
|
+
const setState2 = (_newValue) => {
|
65
148
|
};
|
66
149
|
stateIndices.set(currentRender, index2 + 1);
|
67
150
|
return [state2, setState2];
|
@@ -70,7 +153,7 @@ function useState(initial) {
|
|
70
153
|
states.set(currentRender, []);
|
71
154
|
}
|
72
155
|
const componentStates = states.get(currentRender);
|
73
|
-
const index = stateIndices.get(currentRender);
|
156
|
+
const index = stateIndices.get(currentRender) || 0;
|
74
157
|
if (index >= componentStates.length) {
|
75
158
|
componentStates.push(initial);
|
76
159
|
}
|
@@ -92,19 +175,24 @@ function useState(initial) {
|
|
92
175
|
function useEffect(callback, deps) {
|
93
176
|
if (!currentRender)
|
94
177
|
throw new Error("useEffect must be called within a render");
|
95
|
-
|
178
|
+
if (isServer) {
|
179
|
+
const effectIndex2 = stateIndices.get(currentRender) || 0;
|
180
|
+
stateIndices.set(currentRender, effectIndex2 + 1);
|
181
|
+
return;
|
182
|
+
}
|
183
|
+
const effectIndex = stateIndices.get(currentRender) || 0;
|
96
184
|
if (!effects.has(currentRender)) {
|
97
185
|
effects.set(currentRender, []);
|
98
186
|
}
|
99
187
|
const componentEffects = effects.get(currentRender);
|
100
188
|
const prevEffect = componentEffects[effectIndex];
|
101
189
|
if (!prevEffect || !deps || !prevEffect.deps || deps.some((dep, i) => dep !== prevEffect.deps[i])) {
|
102
|
-
if (prevEffect
|
190
|
+
if (prevEffect?.cleanup) {
|
103
191
|
prevEffect.cleanup();
|
104
192
|
}
|
105
193
|
queueMicrotask(() => {
|
106
194
|
const cleanup = callback() || void 0;
|
107
|
-
componentEffects[effectIndex] = { cleanup, deps };
|
195
|
+
componentEffects[effectIndex] = { cleanup, deps: deps || [] };
|
108
196
|
});
|
109
197
|
}
|
110
198
|
stateIndices.set(currentRender, effectIndex + 1);
|
@@ -112,7 +200,7 @@ function useEffect(callback, deps) {
|
|
112
200
|
function useMemo(factory, deps) {
|
113
201
|
if (!currentRender)
|
114
202
|
throw new Error("useMemo must be called within a render");
|
115
|
-
const memoIndex = stateIndices.get(currentRender);
|
203
|
+
const memoIndex = stateIndices.get(currentRender) || 0;
|
116
204
|
if (!memos.has(currentRender)) {
|
117
205
|
memos.set(currentRender, []);
|
118
206
|
}
|
@@ -120,7 +208,7 @@ function useMemo(factory, deps) {
|
|
120
208
|
const prevMemo = componentMemos[memoIndex];
|
121
209
|
if (!prevMemo || deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i]))) {
|
122
210
|
const value = factory();
|
123
|
-
componentMemos[memoIndex] = { value, deps };
|
211
|
+
componentMemos[memoIndex] = { value, deps: deps || [] };
|
124
212
|
stateIndices.set(currentRender, memoIndex + 1);
|
125
213
|
return value;
|
126
214
|
}
|
@@ -148,84 +236,25 @@ function useErrorBoundary() {
|
|
148
236
|
const [error, setError] = useState(null);
|
149
237
|
return [error, () => setError(null)];
|
150
238
|
}
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
return document.createTextNode("");
|
167
|
-
}
|
168
|
-
if (typeof vnode === "number" || typeof vnode === "string") {
|
169
|
-
return document.createTextNode(String(vnode));
|
170
|
-
}
|
171
|
-
if (Array.isArray(vnode)) {
|
172
|
-
const fragment = document.createDocumentFragment();
|
173
|
-
for (const child of vnode) {
|
174
|
-
const node = await createElement(child);
|
175
|
-
fragment.appendChild(node);
|
176
|
-
}
|
177
|
-
return fragment;
|
178
|
-
}
|
179
|
-
if ("type" in vnode && vnode.props !== void 0) {
|
180
|
-
const { type, props } = vnode;
|
181
|
-
if (typeof type === "function") {
|
182
|
-
try {
|
183
|
-
const result = await type(props || {});
|
184
|
-
const node = await createElement(result);
|
185
|
-
if (node instanceof Element) {
|
186
|
-
node.setAttribute("data-component-id", type.name || type.toString());
|
187
|
-
}
|
188
|
-
return node;
|
189
|
-
} catch (error) {
|
190
|
-
console.error("Error rendering component:", error);
|
191
|
-
return document.createTextNode("");
|
192
|
-
}
|
193
|
-
}
|
194
|
-
const element = document.createElement(type);
|
195
|
-
for (const [key, value] of Object.entries(props || {})) {
|
196
|
-
if (key === "children")
|
197
|
-
continue;
|
198
|
-
if (key.startsWith("on") && typeof value === "function") {
|
199
|
-
const eventName = key.toLowerCase().slice(2);
|
200
|
-
const existingHandler = (_a = element.__events) == null ? void 0 : _a[eventName];
|
201
|
-
if (existingHandler) {
|
202
|
-
element.removeEventListener(eventName, existingHandler);
|
203
|
-
}
|
204
|
-
element.addEventListener(eventName, value);
|
205
|
-
if (!element.__events) {
|
206
|
-
element.__events = {};
|
207
|
-
}
|
208
|
-
element.__events[eventName] = value;
|
209
|
-
} else if (key === "style" && typeof value === "object") {
|
210
|
-
Object.assign(element.style, value);
|
211
|
-
} else if (key === "className") {
|
212
|
-
element.setAttribute("class", String(value));
|
213
|
-
} else if (key !== "key" && key !== "ref") {
|
214
|
-
element.setAttribute(key, String(value));
|
215
|
-
}
|
216
|
-
}
|
217
|
-
const children = props == null ? void 0 : props.children;
|
218
|
-
if (children != null) {
|
219
|
-
const childArray = Array.isArray(children) ? children.flat() : [children];
|
220
|
-
for (const child of childArray) {
|
221
|
-
const childNode = await createElement(child);
|
222
|
-
element.appendChild(childNode);
|
223
|
-
}
|
224
|
-
}
|
225
|
-
return element;
|
239
|
+
var isBatching, queue, currentRender, states, stateIndices, effects, memos, isServer, serverStates, globalRenderCallback, globalContainer, currentElement;
|
240
|
+
var init_server_renderer_QHt45Ip2 = __esm({
|
241
|
+
"node_modules/frontend-hamroun/dist/server-renderer-QHt45Ip2.js"() {
|
242
|
+
isBatching = false;
|
243
|
+
queue = [];
|
244
|
+
currentRender = 0;
|
245
|
+
states = /* @__PURE__ */ new Map();
|
246
|
+
stateIndices = /* @__PURE__ */ new Map();
|
247
|
+
effects = /* @__PURE__ */ new Map();
|
248
|
+
memos = /* @__PURE__ */ new Map();
|
249
|
+
isServer = typeof window === "undefined";
|
250
|
+
serverStates = /* @__PURE__ */ new Map();
|
251
|
+
globalRenderCallback = null;
|
252
|
+
globalContainer = null;
|
253
|
+
currentElement = null;
|
226
254
|
}
|
227
|
-
|
228
|
-
|
255
|
+
});
|
256
|
+
|
257
|
+
// node_modules/frontend-hamroun/dist/renderer-Bo9zkUZ_.js
|
229
258
|
async function hydrate(element, container) {
|
230
259
|
isHydrating = true;
|
231
260
|
try {
|
@@ -250,25 +279,25 @@ async function render(element, container) {
|
|
250
279
|
}
|
251
280
|
});
|
252
281
|
}
|
253
|
-
var
|
254
|
-
var
|
255
|
-
"node_modules/frontend-hamroun/dist/
|
256
|
-
|
257
|
-
|
258
|
-
currentRender = 0;
|
259
|
-
states = /* @__PURE__ */ new Map();
|
260
|
-
stateIndices = /* @__PURE__ */ new Map();
|
261
|
-
effects = /* @__PURE__ */ new Map();
|
262
|
-
memos = /* @__PURE__ */ new Map();
|
263
|
-
globalRenderCallback = null;
|
264
|
-
globalContainer = null;
|
265
|
-
currentElement = null;
|
266
|
-
isServer = typeof window === "undefined";
|
267
|
-
serverStates = /* @__PURE__ */ new Map();
|
282
|
+
var isHydrating;
|
283
|
+
var init_renderer_Bo9zkUZ = __esm({
|
284
|
+
"node_modules/frontend-hamroun/dist/renderer-Bo9zkUZ_.js"() {
|
285
|
+
init_jsx_runtime();
|
286
|
+
init_server_renderer_QHt45Ip2();
|
268
287
|
isHydrating = false;
|
269
288
|
}
|
270
289
|
});
|
271
290
|
|
291
|
+
// node_modules/frontend-hamroun/dist/index.js
|
292
|
+
var init_dist = __esm({
|
293
|
+
"node_modules/frontend-hamroun/dist/index.js"() {
|
294
|
+
init_jsx_runtime();
|
295
|
+
init_renderer_Bo9zkUZ();
|
296
|
+
init_server_renderer_QHt45Ip2();
|
297
|
+
init_server_renderer_QHt45Ip2();
|
298
|
+
}
|
299
|
+
});
|
300
|
+
|
272
301
|
// src/pages/404.tsx
|
273
302
|
var __exports = {};
|
274
303
|
__export(__exports, {
|