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
@@ -0,0 +1,47 @@
|
|
1
|
+
import express from 'express';
|
2
|
+
import path from 'path';
|
3
|
+
import { fileURLToPath } from 'url';
|
4
|
+
import { renderToString, jsx } from 'frontend-hamroun';
|
5
|
+
import { App } from './App.js';
|
6
|
+
import fs from 'fs';
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
8
|
+
const app = express();
|
9
|
+
const port = 3000;
|
10
|
+
// Find the client entry file
|
11
|
+
function getClientEntry() {
|
12
|
+
const assetsDir = path.join(__dirname, './');
|
13
|
+
const files = fs.readdirSync(assetsDir);
|
14
|
+
const entry = files.find(file => file.startsWith("client") && file.endsWith('.js'));
|
15
|
+
if (!entry) {
|
16
|
+
throw new Error('Client entry file not found');
|
17
|
+
}
|
18
|
+
return entry;
|
19
|
+
}
|
20
|
+
// Static file serving
|
21
|
+
app.use('/assets', express.static(path.join(__dirname, './')));
|
22
|
+
app.use(express.static(path.join(__dirname, 'dist')));
|
23
|
+
// Main route handler
|
24
|
+
app.get('/', async (_req, res) => {
|
25
|
+
try {
|
26
|
+
const clientEntry = getClientEntry();
|
27
|
+
const html = await renderToString({
|
28
|
+
element: jsx(App, null),
|
29
|
+
title: 'SSR App',
|
30
|
+
scripts: [`/assets/${clientEntry}`],
|
31
|
+
initialState: {
|
32
|
+
// Add any initial state here
|
33
|
+
},
|
34
|
+
meta: {
|
35
|
+
'viewport': 'width=device-width, initial-scale=1.0',
|
36
|
+
}
|
37
|
+
});
|
38
|
+
res.send(html);
|
39
|
+
}
|
40
|
+
catch (error) {
|
41
|
+
console.error('Rendering error:', error);
|
42
|
+
res.status(500).send('Server Error');
|
43
|
+
}
|
44
|
+
});
|
45
|
+
app.listen(port, () => {
|
46
|
+
console.log(`Server running at http://localhost:${port}`);
|
47
|
+
});
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import express from 'express';
|
2
|
+
import path from 'path';
|
3
|
+
import { fileURLToPath } from 'url';
|
4
|
+
import { renderToString, jsx } from 'frontend-hamroun';
|
5
|
+
import { App } from './App.js';
|
6
|
+
import fs from 'fs';
|
7
|
+
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
9
|
+
const app = express();
|
10
|
+
const port = 3000;
|
11
|
+
|
12
|
+
// Find the client entry file
|
13
|
+
function getClientEntry(): string {
|
14
|
+
const assetsDir = path.join(__dirname, './');
|
15
|
+
const files = fs.readdirSync(assetsDir);
|
16
|
+
const entry = files.find(file => file.startsWith("client") && file.endsWith('.js'));
|
17
|
+
if (!entry) {
|
18
|
+
throw new Error('Client entry file not found');
|
19
|
+
}
|
20
|
+
return entry;
|
21
|
+
}
|
22
|
+
|
23
|
+
// Static file serving
|
24
|
+
app.use('/assets', express.static(path.join(__dirname, './')));
|
25
|
+
app.use(express.static(path.join(__dirname, 'dist')));
|
26
|
+
|
27
|
+
// Main route handler
|
28
|
+
app.get('/', async (_req: express.Request, res: express.Response) => {
|
29
|
+
try {
|
30
|
+
const clientEntry = getClientEntry();
|
31
|
+
const html = await renderToString({
|
32
|
+
element: jsx(App, null),
|
33
|
+
title: 'SSR App',
|
34
|
+
scripts: [`/assets/${clientEntry}`],
|
35
|
+
initialState: {
|
36
|
+
// Add any initial state here
|
37
|
+
},
|
38
|
+
meta: {
|
39
|
+
'viewport': 'width=device-width, initial-scale=1.0',
|
40
|
+
}
|
41
|
+
});
|
42
|
+
|
43
|
+
res.send(html);
|
44
|
+
} catch (error) {
|
45
|
+
console.error('Rendering error:', error);
|
46
|
+
res.status(500).send('Server Error');
|
47
|
+
}
|
48
|
+
});
|
49
|
+
|
50
|
+
app.listen(port, () => {
|
51
|
+
console.log(`Server running at http://localhost:${port}`);
|
52
|
+
});
|
@@ -0,0 +1,182 @@
|
|
1
|
+
/**
|
2
|
+
* Simple JSX implementation for server-side rendering
|
3
|
+
*/
|
4
|
+
|
5
|
+
// Render a virtual DOM node to HTML string
|
6
|
+
export function renderToString(vnode) {
|
7
|
+
// Handle null or undefined
|
8
|
+
if (vnode == null) return '';
|
9
|
+
|
10
|
+
// Handle primitive values
|
11
|
+
if (typeof vnode === 'string' || typeof vnode === 'number')
|
12
|
+
return escapeHtml(String(vnode));
|
13
|
+
|
14
|
+
// Handle arrays (like fragments)
|
15
|
+
if (Array.isArray(vnode))
|
16
|
+
return vnode.map(renderToString).join('');
|
17
|
+
|
18
|
+
// Handle functional components
|
19
|
+
if (typeof vnode.type === 'function') {
|
20
|
+
try {
|
21
|
+
const result = vnode.type(vnode.props || {});
|
22
|
+
return renderToString(result);
|
23
|
+
} catch (err) {
|
24
|
+
console.error('Error rendering component:', err);
|
25
|
+
return `<div class="error">Error: ${escapeHtml(err.message)}</div>`;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
// Handle Fragment
|
30
|
+
if (vnode.type === Symbol.for('react.fragment')) {
|
31
|
+
return renderToString(vnode.props.children);
|
32
|
+
}
|
33
|
+
|
34
|
+
// Handle regular DOM elements
|
35
|
+
if (typeof vnode.type === 'string') {
|
36
|
+
let props = vnode.props || {};
|
37
|
+
let children = props.children || [];
|
38
|
+
if (!Array.isArray(children)) {
|
39
|
+
children = [children];
|
40
|
+
}
|
41
|
+
|
42
|
+
// Build opening tag with attributes
|
43
|
+
let html = `<${vnode.type}`;
|
44
|
+
|
45
|
+
for (const [key, value] of Object.entries(props)) {
|
46
|
+
if (key === 'children' || key === 'dangerouslySetInnerHTML') continue;
|
47
|
+
|
48
|
+
// Handle event handlers (they should be ignored in SSR)
|
49
|
+
if (key.startsWith('on')) continue;
|
50
|
+
|
51
|
+
// Handle className -> class
|
52
|
+
if (key === 'className') {
|
53
|
+
html += ` class="${escapeHtml(value)}"`;
|
54
|
+
continue;
|
55
|
+
}
|
56
|
+
|
57
|
+
// Handle style objects
|
58
|
+
if (key === 'style' && typeof value === 'object') {
|
59
|
+
const styleStr = Object.entries(value)
|
60
|
+
.map(([k, v]) => `${kebabCase(k)}:${v}`)
|
61
|
+
.join(';');
|
62
|
+
html += ` style="${escapeHtml(styleStr)}"`;
|
63
|
+
continue;
|
64
|
+
}
|
65
|
+
|
66
|
+
// Handle boolean attributes
|
67
|
+
if (value === true) {
|
68
|
+
html += ` ${key}`;
|
69
|
+
continue;
|
70
|
+
}
|
71
|
+
|
72
|
+
// Skip false boolean attributes
|
73
|
+
if (value === false) continue;
|
74
|
+
|
75
|
+
// Regular attributes
|
76
|
+
if (value != null) {
|
77
|
+
html += ` ${key}="${escapeHtml(value)}"`;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
// Handle self-closing tags
|
82
|
+
const selfClosing = ['img', 'input', 'br', 'hr', 'meta', 'link', 'area', 'base', 'col', 'embed', 'param', 'source', 'track', 'wbr'];
|
83
|
+
if (selfClosing.includes(vnode.type)) {
|
84
|
+
return `${html} />`;
|
85
|
+
}
|
86
|
+
|
87
|
+
// Add closing bracket for opening tag
|
88
|
+
html += '>';
|
89
|
+
|
90
|
+
// Handle dangerouslySetInnerHTML
|
91
|
+
if (props.dangerouslySetInnerHTML) {
|
92
|
+
html += props.dangerouslySetInnerHTML.__html || '';
|
93
|
+
} else {
|
94
|
+
// Add children
|
95
|
+
for (const child of children) {
|
96
|
+
html += renderToString(child);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
// Add closing tag
|
101
|
+
html += `</${vnode.type}>`;
|
102
|
+
|
103
|
+
return html;
|
104
|
+
}
|
105
|
+
|
106
|
+
// Unknown node type
|
107
|
+
console.warn('Unknown vnode type:', vnode.type);
|
108
|
+
return '';
|
109
|
+
}
|
110
|
+
|
111
|
+
// Create a JSX element
|
112
|
+
export function jsx(type, props, ...children) {
|
113
|
+
props = props || {};
|
114
|
+
if (children.length) {
|
115
|
+
props.children = children.length === 1 ? children[0] : children;
|
116
|
+
}
|
117
|
+
return { type, props };
|
118
|
+
}
|
119
|
+
|
120
|
+
// Helper for escaping HTML
|
121
|
+
function escapeHtml(str) {
|
122
|
+
return String(str)
|
123
|
+
.replace(/&/g, '&')
|
124
|
+
.replace(/</g, '<')
|
125
|
+
.replace(/>/g, '>')
|
126
|
+
.replace(/"/g, '"')
|
127
|
+
.replace(/'/g, ''');
|
128
|
+
}
|
129
|
+
|
130
|
+
// Helper to convert camelCase to kebab-case for CSS properties
|
131
|
+
function kebabCase(str) {
|
132
|
+
return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
133
|
+
}
|
134
|
+
|
135
|
+
// Create a basic requestLogger middleware
|
136
|
+
export function requestLogger(req, res, next) {
|
137
|
+
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
|
138
|
+
next();
|
139
|
+
}
|
140
|
+
|
141
|
+
// Create a basic error handler middleware
|
142
|
+
export function errorHandler(err, req, res, next) {
|
143
|
+
console.error('Server error:', err);
|
144
|
+
res.status(500).send('Server Error');
|
145
|
+
}
|
146
|
+
|
147
|
+
// Create a basic 404 handler middleware
|
148
|
+
export function notFoundHandler(req, res) {
|
149
|
+
res.status(404).send('Not Found');
|
150
|
+
}
|
151
|
+
|
152
|
+
// Create a basic rate limiter middleware
|
153
|
+
export function rateLimit(options = { windowMs: 60000, max: 100 }) {
|
154
|
+
const requests = new Map();
|
155
|
+
|
156
|
+
return (req, res, next) => {
|
157
|
+
const ip = req.ip || 'unknown';
|
158
|
+
const now = Date.now();
|
159
|
+
|
160
|
+
if (!requests.has(ip)) {
|
161
|
+
requests.set(ip, []);
|
162
|
+
}
|
163
|
+
|
164
|
+
const reqs = requests.get(ip);
|
165
|
+
const validReqs = reqs.filter(time => now - time < options.windowMs);
|
166
|
+
|
167
|
+
validReqs.push(now);
|
168
|
+
requests.set(ip, validReqs);
|
169
|
+
|
170
|
+
if (validReqs.length > options.max) {
|
171
|
+
return res.status(429).send('Too Many Requests');
|
172
|
+
}
|
173
|
+
|
174
|
+
next();
|
175
|
+
};
|
176
|
+
}
|
177
|
+
|
178
|
+
// Export other necessary functions
|
179
|
+
export const Fragment = Symbol.for('react.fragment');
|
180
|
+
export function loadGoWasmFromFile() {
|
181
|
+
throw new Error('WASM not supported in this environment');
|
182
|
+
}
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,4 +1,57 @@
|
|
1
|
-
|
1
|
+
// Simple client-side hydration script
|
2
|
+
|
3
|
+
// Helper to create a jsx element
|
4
|
+
function jsx(type, props, ...children) {
|
5
|
+
props = props || {};
|
6
|
+
if (children.length) {
|
7
|
+
props.children = children.length === 1 ? children[0] : children;
|
8
|
+
}
|
9
|
+
return { type, props };
|
10
|
+
}
|
11
|
+
|
12
|
+
// Global Fragment symbol
|
13
|
+
const Fragment = Symbol.for('react.fragment');
|
14
|
+
|
15
|
+
// Basic hydration logic for interactivity
|
16
|
+
function hydrate(element, container) {
|
17
|
+
console.log('Hydrating app...');
|
18
|
+
|
19
|
+
// Simple event delegation for the entire app container
|
20
|
+
container.addEventListener('click', (event) => {
|
21
|
+
const target = event.target;
|
22
|
+
|
23
|
+
// Handle button clicks
|
24
|
+
if (target.tagName === 'BUTTON') {
|
25
|
+
console.log('Button clicked:', target.textContent);
|
26
|
+
|
27
|
+
// Add some visual feedback
|
28
|
+
const originalColor = target.style.backgroundColor;
|
29
|
+
target.style.backgroundColor = '#ccc';
|
30
|
+
|
31
|
+
setTimeout(() => {
|
32
|
+
target.style.backgroundColor = originalColor;
|
33
|
+
}, 200);
|
34
|
+
}
|
35
|
+
|
36
|
+
// Handle links
|
37
|
+
if (target.tagName === 'A' && target.getAttribute('href') && !target.getAttribute('href').startsWith('http')) {
|
38
|
+
event.preventDefault();
|
39
|
+
const href = target.getAttribute('href');
|
40
|
+
console.log('Link clicked:', href);
|
41
|
+
|
42
|
+
// Simple client-side navigation simulation
|
43
|
+
history.pushState(null, '', href);
|
44
|
+
|
45
|
+
// Show a loading message - in a real app, you would fetch the new page
|
46
|
+
container.innerHTML = '<div class="container"><h3>Loading...</h3></div>';
|
47
|
+
|
48
|
+
// Reload the page after a short delay to demonstrate
|
49
|
+
setTimeout(() => {
|
50
|
+
window.location.reload();
|
51
|
+
}, 300);
|
52
|
+
}
|
53
|
+
});
|
54
|
+
}
|
2
55
|
|
3
56
|
// Immediately invoked function to handle hydration
|
4
57
|
(async function() {
|
@@ -22,55 +75,10 @@ import { hydrate, jsx, useState, useEffect, useMemo, useRef, useContext, batchUp
|
|
22
75
|
console.error('Error parsing initial data:', err);
|
23
76
|
}
|
24
77
|
|
25
|
-
//
|
26
|
-
|
27
|
-
const normalizedPath = path === '/' ? '/index' : path;
|
78
|
+
// Make the app interactive
|
79
|
+
hydrate({ type: 'div', props: { initialData } }, appRoot);
|
28
80
|
|
29
|
-
|
30
|
-
// Import the component for the current path
|
31
|
-
console.log(`Importing component for path: ${normalizedPath}`);
|
32
|
-
// First attempt to load the page component
|
33
|
-
const module = await import(`/pages${normalizedPath}.js`).catch(() =>
|
34
|
-
import(`/pages${normalizedPath}/index.js`));
|
35
|
-
|
36
|
-
if (!module || !module.default) {
|
37
|
-
throw new Error(`No default export found for ${normalizedPath}`);
|
38
|
-
}
|
39
|
-
|
40
|
-
// Get the component
|
41
|
-
const PageComponent = module.default;
|
42
|
-
|
43
|
-
// Use batchUpdates for better performance during hydration
|
44
|
-
batchUpdates(() => {
|
45
|
-
console.log('Hydrating app with props:', initialData);
|
46
|
-
// Hydrate the component
|
47
|
-
hydrate(jsx(PageComponent, initialData), appRoot);
|
48
|
-
console.log('Hydration complete for', normalizedPath);
|
49
|
-
});
|
50
|
-
|
51
|
-
} catch (err) {
|
52
|
-
console.error(`Error loading or hydrating component: ${err.message}`);
|
53
|
-
|
54
|
-
// Fallback to a simple component that shows the error
|
55
|
-
const ErrorComponent = (props) => {
|
56
|
-
const [showDetails, setShowDetails] = useState(false);
|
57
|
-
|
58
|
-
return jsx('div', { className: 'error-container' }, [
|
59
|
-
jsx('h1', {}, 'Error Loading Page'),
|
60
|
-
jsx('p', {}, `Failed to load: ${normalizedPath}`),
|
61
|
-
jsx('button', {
|
62
|
-
onClick: () => setShowDetails(!showDetails),
|
63
|
-
className: 'btn'
|
64
|
-
}, showDetails ? 'Hide Details' : 'Show Details'),
|
65
|
-
showDetails && jsx('pre', { className: 'error-details' },
|
66
|
-
`${err.message}\n${err.stack || ''}`
|
67
|
-
),
|
68
|
-
jsx('a', { href: '/', className: 'button' }, 'Go Home')
|
69
|
-
]);
|
70
|
-
};
|
71
|
-
|
72
|
-
hydrate(jsx(ErrorComponent, initialData), appRoot);
|
73
|
-
}
|
81
|
+
console.log('App hydrated successfully');
|
74
82
|
} catch (err) {
|
75
83
|
console.error('Hydration failed:', err);
|
76
84
|
}
|
@@ -78,3 +86,4 @@ import { hydrate, jsx, useState, useEffect, useMemo, useRef, useContext, batchUp
|
|
78
86
|
|
79
87
|
// Make jsx globally available
|
80
88
|
window.jsx = jsx;
|
89
|
+
window.Fragment = Fragment;
|
@@ -3,45 +3,116 @@
|
|
3
3
|
<head>
|
4
4
|
<meta charset="UTF-8">
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
-
<title>Static Fallback</title>
|
7
|
-
|
8
|
-
<link href="https://cdn.jsdelivr.net/npm/daisyui@3.7.4/dist/full.css" rel="stylesheet" type="text/css" />
|
9
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
10
|
-
<!-- Client-side script for hydration -->
|
11
|
-
<script type="module" src="/src/client.tsx"></script>
|
6
|
+
<title>Static Fallback - Frontend Hamroun</title>
|
7
|
+
<link href="/styles.css" rel="stylesheet" type="text/css">
|
12
8
|
<style>
|
13
9
|
body {
|
14
|
-
font-family: sans-serif;
|
10
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
11
|
+
background-color: #f8f9fa;
|
12
|
+
color: #212529;
|
13
|
+
line-height: 1.5;
|
14
|
+
margin: 0;
|
15
|
+
padding: 0;
|
16
|
+
display: flex;
|
17
|
+
flex-direction: column;
|
18
|
+
min-height: 100vh;
|
19
|
+
}
|
20
|
+
.container {
|
15
21
|
max-width: 800px;
|
16
22
|
margin: 0 auto;
|
17
23
|
padding: 2rem;
|
18
|
-
|
24
|
+
flex: 1;
|
25
|
+
display: flex;
|
26
|
+
flex-direction: column;
|
27
|
+
justify-content: center;
|
28
|
+
}
|
29
|
+
.alert {
|
30
|
+
background-color: #f8d7da;
|
31
|
+
color: #721c24;
|
32
|
+
border: 1px solid #f5c6cb;
|
33
|
+
border-radius: 4px;
|
34
|
+
padding: 1.5rem;
|
35
|
+
margin-bottom: 2rem;
|
19
36
|
}
|
20
37
|
.warning {
|
21
38
|
background-color: #fff3cd;
|
22
|
-
border: 1px solid #ffecb5;
|
23
39
|
color: #856404;
|
24
|
-
|
40
|
+
border: 1px solid #ffeeba;
|
25
41
|
border-radius: 4px;
|
26
|
-
|
42
|
+
padding: 1.5rem;
|
43
|
+
margin-bottom: 2rem;
|
44
|
+
}
|
45
|
+
.steps {
|
46
|
+
background-color: #e9ecef;
|
47
|
+
border-radius: 4px;
|
48
|
+
padding: 1.5rem;
|
49
|
+
}
|
50
|
+
h1 {
|
51
|
+
margin-top: 0;
|
52
|
+
color: #0066cc;
|
53
|
+
}
|
54
|
+
footer {
|
55
|
+
text-align: center;
|
56
|
+
padding: 1rem;
|
57
|
+
background-color: #f1f1f1;
|
58
|
+
font-size: 0.875rem;
|
59
|
+
color: #6c757d;
|
27
60
|
}
|
28
61
|
code {
|
29
|
-
background-color: #
|
62
|
+
background-color: #f1f1f1;
|
30
63
|
padding: 0.2rem 0.4rem;
|
31
64
|
border-radius: 3px;
|
32
65
|
}
|
66
|
+
.logo {
|
67
|
+
font-size: 2rem;
|
68
|
+
margin-bottom: 2rem;
|
69
|
+
color: #0066cc;
|
70
|
+
font-weight: bold;
|
71
|
+
text-align: center;
|
72
|
+
}
|
73
|
+
ul {
|
74
|
+
margin-bottom: 0;
|
75
|
+
}
|
76
|
+
li {
|
77
|
+
margin-bottom: 0.5rem;
|
78
|
+
}
|
79
|
+
li:last-child {
|
80
|
+
margin-bottom: 0;
|
81
|
+
}
|
33
82
|
</style>
|
34
83
|
</head>
|
35
84
|
<body>
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
<
|
85
|
+
<div class="container">
|
86
|
+
<div class="logo">Frontend Hamroun</div>
|
87
|
+
|
88
|
+
<div class="alert">
|
89
|
+
<h1>STATIC INDEX.HTML FILE</h1>
|
90
|
+
<p><strong>You should NOT be seeing this page if the server is running correctly.</strong></p>
|
41
91
|
<p>This is a static file that should only be used as a fallback when the server is not running.</p>
|
92
|
+
</div>
|
93
|
+
|
94
|
+
<div class="warning">
|
42
95
|
<p>If you're seeing this while running <code>npm run dev</code>, there's likely an issue with the Express route handling.</p>
|
43
96
|
<p>Try clearing your browser cache and refreshing the page.</p>
|
44
97
|
</div>
|
98
|
+
|
99
|
+
<div class="steps">
|
100
|
+
<h2>Troubleshooting Steps:</h2>
|
101
|
+
<ul>
|
102
|
+
<li>Check your terminal for any error messages</li>
|
103
|
+
<li>Verify that you've installed all dependencies with <code>npm install</code></li>
|
104
|
+
<li>Check that the server port (default: 3000) is not already in use</li>
|
105
|
+
<li>Make sure your Express routes are configured correctly</li>
|
106
|
+
<li>Try restarting the server with <code>npm run dev</code></li>
|
107
|
+
<li>Check that all required environment variables are set</li>
|
108
|
+
</ul>
|
109
|
+
</div>
|
45
110
|
</div>
|
111
|
+
|
112
|
+
<footer class="footer">
|
113
|
+
<div class="container">
|
114
|
+
<p>© 2025 Frontend Hamroun - A lightweight full-stack JavaScript framework</p>
|
115
|
+
</div>
|
116
|
+
</footer>
|
46
117
|
</body>
|
47
118
|
</html>
|