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
@@ -1,275 +0,0 @@
|
|
1
|
-
import express from 'express';
|
2
|
-
import { fileURLToPath } from 'url';
|
3
|
-
import { dirname, join } from 'path';
|
4
|
-
import { renderToString } from 'frontend-hamroun';
|
5
|
-
import { Database } from 'frontend-hamroun';
|
6
|
-
import { AuthService } from 'frontend-hamroun';
|
7
|
-
import { requestLogger, errorHandler, notFoundHandler, rateLimit } from 'frontend-hamroun';
|
8
|
-
import dotenv from 'dotenv';
|
9
|
-
import fetch from 'node-fetch';
|
10
|
-
|
11
|
-
// Load environment variables
|
12
|
-
dotenv.config();
|
13
|
-
|
14
|
-
// Get directory name in ESM
|
15
|
-
const __filename = fileURLToPath(import.meta.url);
|
16
|
-
const __dirname = dirname(__filename);
|
17
|
-
|
18
|
-
// Create Express app
|
19
|
-
const app = express();
|
20
|
-
const port = process.env.PORT ? parseInt(process.env.PORT) : 3000;
|
21
|
-
|
22
|
-
// Add middleware
|
23
|
-
app.use(express.json());
|
24
|
-
app.use(express.urlencoded({ extended: true }));
|
25
|
-
app.use(requestLogger);
|
26
|
-
|
27
|
-
// Rate limiting for API routes
|
28
|
-
app.use('/api', rateLimit({
|
29
|
-
windowMs: 15 * 60 * 1000, // 15 minutes
|
30
|
-
max: 100 // limit each IP to 100 requests per windowMs
|
31
|
-
}));
|
32
|
-
|
33
|
-
// Configure database if connection string is provided
|
34
|
-
let db = null;
|
35
|
-
if (process.env.DATABASE_URL) {
|
36
|
-
db = new Database({
|
37
|
-
url: process.env.DATABASE_URL,
|
38
|
-
type: (process.env.DATABASE_TYPE || 'mongodb') as 'mongodb' | 'mysql' | 'postgres'
|
39
|
-
});
|
40
|
-
|
41
|
-
// Connect to database
|
42
|
-
try {
|
43
|
-
await db.connect();
|
44
|
-
console.log('Database connected successfully');
|
45
|
-
} catch (error) {
|
46
|
-
console.error('Database connection failed:', error);
|
47
|
-
}
|
48
|
-
}
|
49
|
-
|
50
|
-
// Configure auth if secret is provided
|
51
|
-
let auth = null;
|
52
|
-
if (process.env.JWT_SECRET) {
|
53
|
-
auth = new AuthService({
|
54
|
-
secret: process.env.JWT_SECRET,
|
55
|
-
expiresIn: process.env.JWT_EXPIRES_IN || '24h'
|
56
|
-
});
|
57
|
-
|
58
|
-
// Add auth middleware
|
59
|
-
app.use(auth.initialize());
|
60
|
-
|
61
|
-
// Example protected route
|
62
|
-
app.get('/api/protected', auth.requireAuth(), (req, res) => {
|
63
|
-
res.json({ message: 'Protected route accessed successfully' });
|
64
|
-
});
|
65
|
-
|
66
|
-
// Example role-based protection
|
67
|
-
app.get('/api/admin', auth.requireRoles(['admin']), (req, res) => {
|
68
|
-
res.json({ message: 'Admin route accessed successfully' });
|
69
|
-
});
|
70
|
-
|
71
|
-
// Login route
|
72
|
-
app.post('/api/login', async (req, res) => {
|
73
|
-
const { username, password } = req.body;
|
74
|
-
|
75
|
-
// In a real app, fetch user from database
|
76
|
-
const user = { id: 1, username, roles: ['user'] };
|
77
|
-
const token = auth.generateToken(user);
|
78
|
-
|
79
|
-
res.json({ token, user: { id: user.id, username: user.username, roles: user.roles } });
|
80
|
-
});
|
81
|
-
}
|
82
|
-
|
83
|
-
// Serve static files from public directory
|
84
|
-
app.use(express.static(join(__dirname, 'public')));
|
85
|
-
|
86
|
-
// API endpoint example
|
87
|
-
app.get('/api/page-data', (req, res) => {
|
88
|
-
res.json({
|
89
|
-
title: 'Server-side Data',
|
90
|
-
content: 'This data was fetched from the server',
|
91
|
-
timestamp: new Date().toISOString()
|
92
|
-
});
|
93
|
-
});
|
94
|
-
|
95
|
-
// Meta tag generation function (using local logic for simplicity)
|
96
|
-
async function generateMetaTags(pageContent) {
|
97
|
-
// Extract title from page content
|
98
|
-
const title = pageContent.split('\n')[0].replace(/[#*]/g, '').trim() ||
|
99
|
-
'Frontend Hamroun SSR Page';
|
100
|
-
|
101
|
-
// Generate description from content
|
102
|
-
const description = pageContent.substring(0, 150) + '...';
|
103
|
-
|
104
|
-
// Extract keywords
|
105
|
-
const keywords = pageContent
|
106
|
-
.toLowerCase()
|
107
|
-
.replace(/[^\w\s]/g, '')
|
108
|
-
.split(/\s+/)
|
109
|
-
.filter(w => w.length > 3)
|
110
|
-
.slice(0, 5)
|
111
|
-
.join(', ');
|
112
|
-
|
113
|
-
return {
|
114
|
-
title,
|
115
|
-
description,
|
116
|
-
keywords
|
117
|
-
};
|
118
|
-
}
|
119
|
-
|
120
|
-
// Helper function to check if file exists
|
121
|
-
async function fileExists(path) {
|
122
|
-
try {
|
123
|
-
const fs = await import('fs/promises');
|
124
|
-
await fs.access(path);
|
125
|
-
return true;
|
126
|
-
} catch {
|
127
|
-
return false;
|
128
|
-
}
|
129
|
-
}
|
130
|
-
|
131
|
-
// Implement basic SSR without relying on complex server functionality
|
132
|
-
app.get('*', async (req, res) => {
|
133
|
-
try {
|
134
|
-
// Import the page component
|
135
|
-
const pagesDir = join(__dirname, 'src', 'pages');
|
136
|
-
let componentPath;
|
137
|
-
|
138
|
-
// Map URL path to component file
|
139
|
-
if (req.path === '/') {
|
140
|
-
componentPath = join(pagesDir, 'index.js');
|
141
|
-
} else {
|
142
|
-
componentPath = join(pagesDir, `${req.path}.js`);
|
143
|
-
// Check if it's a directory with index.js
|
144
|
-
if (!await fileExists(componentPath)) {
|
145
|
-
componentPath = join(pagesDir, req.path, 'index.js');
|
146
|
-
}
|
147
|
-
}
|
148
|
-
|
149
|
-
// If component doesn't exist, return 404
|
150
|
-
if (!await fileExists(componentPath)) {
|
151
|
-
return res.status(404).send(`
|
152
|
-
<!DOCTYPE html>
|
153
|
-
<html>
|
154
|
-
<head>
|
155
|
-
<title>404 - Page Not Found</title>
|
156
|
-
</head>
|
157
|
-
<body>
|
158
|
-
<h1>404 - Page Not Found</h1>
|
159
|
-
<p>The page you requested does not exist.</p>
|
160
|
-
</body>
|
161
|
-
</html>
|
162
|
-
`);
|
163
|
-
}
|
164
|
-
|
165
|
-
// Import the component
|
166
|
-
const { default: PageComponent } = await import(componentPath);
|
167
|
-
|
168
|
-
// Generate page content for meta tags
|
169
|
-
const pageContent = `
|
170
|
-
Frontend Hamroun SSR Page
|
171
|
-
This is a server-rendered page using the Frontend Hamroun framework.
|
172
|
-
Path: ${req.path}
|
173
|
-
Timestamp: ${new Date().toISOString()}
|
174
|
-
`;
|
175
|
-
|
176
|
-
// Generate meta tags
|
177
|
-
const metaTags = await generateMetaTags(pageContent);
|
178
|
-
|
179
|
-
// Render the component to string
|
180
|
-
const content = renderToString(PageComponent());
|
181
|
-
|
182
|
-
// Send the HTML response
|
183
|
-
res.send(`
|
184
|
-
<!DOCTYPE html>
|
185
|
-
<html lang="en">
|
186
|
-
<head>
|
187
|
-
<meta charset="UTF-8">
|
188
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
189
|
-
|
190
|
-
<!-- Generated Meta Tags -->
|
191
|
-
<title>${metaTags.title}</title>
|
192
|
-
<meta name="description" content="${metaTags.description}">
|
193
|
-
<meta name="keywords" content="${metaTags.keywords}">
|
194
|
-
|
195
|
-
<!-- Open Graph Meta Tags -->
|
196
|
-
<meta property="og:title" content="${metaTags.title}">
|
197
|
-
<meta property="og:description" content="${metaTags.description}">
|
198
|
-
<meta property="og:type" content="website">
|
199
|
-
<meta property="og:url" content="${req.protocol}://${req.get('host')}${req.originalUrl}">
|
200
|
-
|
201
|
-
<!-- Import Tailwind-like styles for quick styling -->
|
202
|
-
<link href="https://cdn.jsdelivr.net/npm/daisyui@3.7.4/dist/full.css" rel="stylesheet" type="text/css" />
|
203
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
204
|
-
|
205
|
-
<!-- Client-side script for hydration -->
|
206
|
-
<script type="module" src="/assets/client.js"></script>
|
207
|
-
</head>
|
208
|
-
<body>
|
209
|
-
<div id="app">${content}</div>
|
210
|
-
|
211
|
-
<!-- Add initial state for hydration -->
|
212
|
-
<script>
|
213
|
-
window.__INITIAL_STATE__ = ${JSON.stringify({
|
214
|
-
path: req.path,
|
215
|
-
timestamp: new Date().toISOString(),
|
216
|
-
metaTags
|
217
|
-
})};
|
218
|
-
</script>
|
219
|
-
</body>
|
220
|
-
</html>
|
221
|
-
`);
|
222
|
-
} catch (error) {
|
223
|
-
console.error('Error rendering page:', error);
|
224
|
-
res.status(500).send(`
|
225
|
-
<!DOCTYPE html>
|
226
|
-
<html>
|
227
|
-
<head>
|
228
|
-
<title>500 - Server Error</title>
|
229
|
-
</head>
|
230
|
-
<body>
|
231
|
-
<h1>500 - Server Error</h1>
|
232
|
-
<p>There was an error processing your request.</p>
|
233
|
-
${process.env.NODE_ENV === 'development' ? `<pre>${error.stack}</pre>` : ''}
|
234
|
-
</body>
|
235
|
-
</html>
|
236
|
-
`);
|
237
|
-
}
|
238
|
-
});
|
239
|
-
|
240
|
-
// Add error handler middleware
|
241
|
-
app.use(errorHandler);
|
242
|
-
|
243
|
-
// Add not found handler for API routes that weren't caught
|
244
|
-
app.use(notFoundHandler);
|
245
|
-
|
246
|
-
// Graceful shutdown function to close database connections
|
247
|
-
function gracefulShutdown() {
|
248
|
-
console.log('Shutting down server...');
|
249
|
-
|
250
|
-
// Close database connection if it exists
|
251
|
-
if (db) {
|
252
|
-
db.disconnect()
|
253
|
-
.then(() => console.log('Database disconnected'))
|
254
|
-
.catch(err => console.error('Error disconnecting from database:', err))
|
255
|
-
.finally(() => process.exit(0));
|
256
|
-
} else {
|
257
|
-
process.exit(0);
|
258
|
-
}
|
259
|
-
}
|
260
|
-
|
261
|
-
// Start the server
|
262
|
-
const server = app.listen(port, () => {
|
263
|
-
console.log(`Server running at http://localhost:${port}`);
|
264
|
-
console.log(`Available API endpoints:`);
|
265
|
-
console.log(` - GET /api/page-data`);
|
266
|
-
console.log(` - POST /api/login`);
|
267
|
-
if (process.env.JWT_SECRET) {
|
268
|
-
console.log(` - GET /api/protected (requires authentication)`);
|
269
|
-
console.log(` - GET /api/admin (requires admin role)`);
|
270
|
-
}
|
271
|
-
});
|
272
|
-
|
273
|
-
// Handle graceful shutdown
|
274
|
-
process.on('SIGINT', gracefulShutdown);
|
275
|
-
process.on('SIGTERM', gracefulShutdown);
|
@@ -1,61 +0,0 @@
|
|
1
|
-
import { hydrate, jsx } from 'frontend-hamroun';
|
2
|
-
|
3
|
-
// Dynamically import the appropriate page component
|
4
|
-
async function hydratePage() {
|
5
|
-
try {
|
6
|
-
// Get initial state from server
|
7
|
-
const initialState = window.__INITIAL_STATE__ || {};
|
8
|
-
|
9
|
-
// Get current path
|
10
|
-
const path = initialState.route || window.location.pathname;
|
11
|
-
const normalizedPath = path === '/' ? '/index' : path;
|
12
|
-
|
13
|
-
// Create path to module
|
14
|
-
const modulePath = `.${normalizedPath.replace(/\/$/, '')}.js`;
|
15
|
-
|
16
|
-
try {
|
17
|
-
// Dynamically import the component
|
18
|
-
const module = await import(`./pages${normalizedPath}.js`).catch(() =>
|
19
|
-
import(`./pages${normalizedPath}/index.js`));
|
20
|
-
|
21
|
-
const PageComponent = module.default;
|
22
|
-
|
23
|
-
// Find the root element
|
24
|
-
const rootElement = document.getElementById('root');
|
25
|
-
|
26
|
-
if (rootElement && PageComponent) {
|
27
|
-
// Hydrate the application with the same params from the server
|
28
|
-
hydrate(jsx(PageComponent, { params: initialState.params || {} }), rootElement);
|
29
|
-
console.log('Hydration complete');
|
30
|
-
} else {
|
31
|
-
console.error('Could not find root element or page component');
|
32
|
-
}
|
33
|
-
} catch (importError) {
|
34
|
-
console.error('Error importing page component:', importError);
|
35
|
-
|
36
|
-
// Fallback to App component if available
|
37
|
-
try {
|
38
|
-
const { App } = await import('./App.js');
|
39
|
-
const rootElement = document.getElementById('root');
|
40
|
-
|
41
|
-
if (rootElement && App) {
|
42
|
-
hydrate(jsx(App, {}), rootElement);
|
43
|
-
console.log('Fallback hydration complete');
|
44
|
-
}
|
45
|
-
} catch (fallbackError) {
|
46
|
-
console.error('Fallback hydration failed:', fallbackError);
|
47
|
-
}
|
48
|
-
}
|
49
|
-
} catch (error) {
|
50
|
-
console.error('Hydration error:', error);
|
51
|
-
}
|
52
|
-
}
|
53
|
-
|
54
|
-
// Add global variable for JSX
|
55
|
-
window.jsx = jsx;
|
56
|
-
|
57
|
-
// Hydrate when DOM is ready
|
58
|
-
document.addEventListener('DOMContentLoaded', hydratePage);
|
59
|
-
|
60
|
-
// Handle client-side navigation (if implemented)
|
61
|
-
window.addEventListener('popstate', hydratePage);
|
@@ -1,51 +0,0 @@
|
|
1
|
-
import { useState, useEffect } from 'frontend-hamroun';
|
2
|
-
|
3
|
-
// This component will be rendered on both server and client
|
4
|
-
export default function HomePage() {
|
5
|
-
const [count, setCount] = useState(0);
|
6
|
-
const [serverTime, setServerTime] = useState('');
|
7
|
-
|
8
|
-
// This effect only runs on the client after hydration
|
9
|
-
useEffect(() => {
|
10
|
-
// Set server render time (only when hydrating)
|
11
|
-
if (!serverTime) {
|
12
|
-
setServerTime('Client-side hydration complete');
|
13
|
-
}
|
14
|
-
|
15
|
-
// Simple cleanup function
|
16
|
-
return () => {
|
17
|
-
console.log('Component unmounting');
|
18
|
-
};
|
19
|
-
}, []);
|
20
|
-
|
21
|
-
return (
|
22
|
-
<div id="app">
|
23
|
-
<div className="hero min-h-screen bg-base-200">
|
24
|
-
<div className="hero-content text-center">
|
25
|
-
<div className="max-w-md">
|
26
|
-
<h1 className="text-5xl font-bold">Frontend Hamroun SSR</h1>
|
27
|
-
<p className="py-6">
|
28
|
-
This page was rendered on the server and hydrated on the client.
|
29
|
-
</p>
|
30
|
-
|
31
|
-
{/* Interactive counter demonstrates client-side hydration */}
|
32
|
-
<div className="my-4 p-4 bg-base-300 rounded-lg">
|
33
|
-
<p>Counter: {count}</p>
|
34
|
-
<button
|
35
|
-
className="btn btn-primary mt-2"
|
36
|
-
onClick={() => setCount(count + 1)}
|
37
|
-
>
|
38
|
-
Increment
|
39
|
-
</button>
|
40
|
-
</div>
|
41
|
-
|
42
|
-
{/* Shows server render time or hydration status */}
|
43
|
-
<div className="text-sm opacity-70 mt-4">
|
44
|
-
{serverTime ? serverTime : `Server rendered at: ${new Date().toISOString()}`}
|
45
|
-
</div>
|
46
|
-
</div>
|
47
|
-
</div>
|
48
|
-
</div>
|
49
|
-
</div>
|
50
|
-
);
|
51
|
-
}
|
@@ -1,57 +0,0 @@
|
|
1
|
-
import { defineConfig } from 'vite';
|
2
|
-
import { resolve } from 'path';
|
3
|
-
|
4
|
-
export default defineConfig({
|
5
|
-
// Configure JSX
|
6
|
-
esbuild: {
|
7
|
-
jsxFactory: 'createElement',
|
8
|
-
jsxFragment: 'Fragment',
|
9
|
-
jsxInject: `import { createElement, Fragment } from 'frontend-hamroun'`
|
10
|
-
},
|
11
|
-
|
12
|
-
// Configure build
|
13
|
-
build: {
|
14
|
-
outDir: 'dist/public',
|
15
|
-
emptyOutDir: true,
|
16
|
-
rollupOptions: {
|
17
|
-
input: {
|
18
|
-
client: resolve(__dirname, 'src/client.ts')
|
19
|
-
},
|
20
|
-
output: [
|
21
|
-
{
|
22
|
-
// ESM output
|
23
|
-
entryFileNames: 'assets/[name].mjs',
|
24
|
-
chunkFileNames: 'assets/[name]-[hash].mjs',
|
25
|
-
assetFileNames: 'assets/[name]-[hash].[ext]',
|
26
|
-
format: 'es',
|
27
|
-
},
|
28
|
-
{
|
29
|
-
// CommonJS output
|
30
|
-
entryFileNames: 'assets/[name].js',
|
31
|
-
chunkFileNames: 'assets/[name]-[hash].js',
|
32
|
-
assetFileNames: 'assets/[name]-[hash].[ext]',
|
33
|
-
format: 'cjs',
|
34
|
-
}
|
35
|
-
]
|
36
|
-
}
|
37
|
-
},
|
38
|
-
|
39
|
-
// Add optimizations for frontend-hamroun
|
40
|
-
optimizeDeps: {
|
41
|
-
include: ['frontend-hamroun']
|
42
|
-
},
|
43
|
-
|
44
|
-
// Resolve aliases for better imports
|
45
|
-
resolve: {
|
46
|
-
alias: {
|
47
|
-
'@': resolve(__dirname, 'src')
|
48
|
-
}
|
49
|
-
},
|
50
|
-
|
51
|
-
// Development server
|
52
|
-
server: {
|
53
|
-
proxy: {
|
54
|
-
'/api': 'http://localhost:3000'
|
55
|
-
}
|
56
|
-
}
|
57
|
-
});
|
File without changes
|
File without changes
|