frontend-hamroun 1.2.80 → 1.2.83

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.
Files changed (128) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.client.cjs +1 -1
  4. package/dist/index.client.js +2 -2
  5. package/dist/index.js +11 -7
  6. package/dist/index.js.map +1 -1
  7. package/dist/{renderer-Din1y3YM.cjs → renderer-BL3gq8cW.cjs} +2 -2
  8. package/dist/{renderer-Din1y3YM.cjs.map → renderer-BL3gq8cW.cjs.map} +1 -1
  9. package/dist/{renderer-Bo9zkUZ_.js → renderer-Dyy-o05F.js} +2 -2
  10. package/dist/{renderer-Bo9zkUZ_.js.map → renderer-Dyy-o05F.js.map} +1 -1
  11. package/dist/{server-renderer-QHt45Ip2.js → server-renderer-C1WXH-zV.js} +99 -73
  12. package/dist/server-renderer-C1WXH-zV.js.map +1 -0
  13. package/dist/server-renderer-Chs-nmJm.cjs +2 -0
  14. package/dist/server-renderer-Chs-nmJm.cjs.map +1 -0
  15. package/dist/server-renderer.cjs +1 -1
  16. package/dist/server-renderer.js +1 -1
  17. package/package.json +1 -1
  18. package/templates/basic-app/src/App.jsx +16 -0
  19. package/templates/basic-app/src/client.jsx +5 -0
  20. package/templates/basic-app/src/components/Counter.jsx +13 -0
  21. package/templates/basic-app/src/jsx-shim.js +3 -0
  22. package/templates/basic-app/src/jsx-shim.ts +7 -0
  23. package/templates/basic-app/src/main.jsx +98 -0
  24. package/templates/basic-app/src/server.js +47 -0
  25. package/templates/complete-app/api/hello.js +0 -0
  26. package/templates/complete-app/lib/frontend-hamroun.js +182 -0
  27. package/templates/complete-app/package.json +18 -0
  28. package/templates/complete-app/pages/about.js +119 -0
  29. package/templates/complete-app/pages/about.jsx +0 -0
  30. package/templates/complete-app/pages/index.js +157 -0
  31. package/templates/complete-app/pages/index.jsx +0 -0
  32. package/templates/complete-app/pages/wasm-demo.js +290 -0
  33. package/templates/complete-app/pages/wasm-demo.jsx +0 -0
  34. package/templates/complete-app/public/client.js +89 -0
  35. package/templates/complete-app/public/index.html +118 -0
  36. package/templates/complete-app/public/styles.css +76 -0
  37. package/templates/complete-app/server.js +226 -0
  38. package/templates/complete-app/src/App.tsx +59 -0
  39. package/templates/complete-app/src/client.tsx +18 -0
  40. package/templates/complete-app/src/server.ts +218 -0
  41. package/templates/complete-app/tsconfig.json +22 -0
  42. package/templates/complete-app/tsconfig.server.json +19 -0
  43. package/templates/{ssr-template → complete-app}/vite.config.js +16 -5
  44. package/templates/complete-app/vite.config.ts +30 -0
  45. package/templates/complete-app/wasm/build.bat +0 -0
  46. package/templates/complete-app/wasm/build.sh +0 -0
  47. package/templates/complete-app/wasm/example.go +0 -0
  48. package/templates/fullstack-app/build/main.css +874 -874
  49. package/templates/fullstack-app/build/main.css.map +7 -7
  50. package/templates/fullstack-app/build/main.js +996 -967
  51. package/templates/fullstack-app/build/main.js.map +7 -7
  52. package/templates/fullstack-app/package-lock.json +6301 -0
  53. package/templates/fullstack-app/public/styles.css +768 -768
  54. package/templates/go/example.go +154 -99
  55. package/templates/ssr-template/dist/client/assets/main-D-VH3xOb.js +1 -0
  56. package/templates/ssr-template/dist/client/index.html +23 -0
  57. package/templates/ssr-template/dist/client.js +951 -0
  58. package/templates/ssr-template/dist/server.js +739 -0
  59. package/templates/ssr-template/esbuild.config.js +33 -0
  60. package/templates/ssr-template/jsx-shim.js +1 -0
  61. package/templates/ssr-template/package.json +14 -8
  62. package/templates/ssr-template/src/App.tsx +847 -49
  63. package/templates/ssr-template/src/client.tsx +3 -17
  64. package/templates/ssr-template/src/server.ts +21 -204
  65. package/templates/ssr-template/tsconfig.json +9 -8
  66. package/templates/ssr-template/tsconfig.server.json +6 -14
  67. package/templates/ssr-template/vite.config.ts +19 -17
  68. package/templates/wasm/build-wasm.js +228 -0
  69. package/templates/wasm/dist/assets/index-BNqTDBdE.js +295 -0
  70. package/templates/wasm/dist/example.wasm +0 -0
  71. package/templates/wasm/dist/index.html +53 -0
  72. package/templates/{go-wasm-app/public/wasm → wasm/dist}/wasm_exec.js +572 -561
  73. package/templates/wasm/esbuild.config.js +63 -0
  74. package/templates/wasm/go/main.go +256 -0
  75. package/templates/wasm/go/wasm_exec.js +0 -0
  76. package/templates/wasm/index.html +97 -0
  77. package/templates/wasm/jsx-shim.js +9 -0
  78. package/templates/wasm/package-lock.json +4577 -0
  79. package/templates/wasm/package.json +25 -0
  80. package/templates/wasm/public/example.wasm +0 -0
  81. package/templates/wasm/public/wasm_exec.js +572 -0
  82. package/templates/wasm/src/App.tsx +550 -0
  83. package/templates/wasm/src/client.tsx +220 -0
  84. package/templates/wasm/src/index.tsx +21 -0
  85. package/templates/wasm/src/server.ts +145 -0
  86. package/templates/wasm/tsconfig.json +21 -0
  87. package/templates/wasm/tsconfig.node.json +13 -0
  88. package/templates/wasm/tsconfig.server.json +23 -0
  89. package/templates/wasm/vite.config.ts +38 -0
  90. package/templates/wasm/wasm-loader.js +103 -0
  91. package/dist/server-renderer-CqIpQ-od.cjs +0 -2
  92. package/dist/server-renderer-CqIpQ-od.cjs.map +0 -1
  93. package/dist/server-renderer-QHt45Ip2.js.map +0 -1
  94. package/templates/basic-app/bun.lock +0 -196
  95. package/templates/basic-app/docs/rapport_pfe.aux +0 -27
  96. package/templates/basic-app/docs/rapport_pfe.out +0 -10
  97. package/templates/basic-app/docs/rapport_pfe.pdf +0 -0
  98. package/templates/basic-app/docs/rapport_pfe.tex +0 -68
  99. package/templates/basic-app/docs/rapport_pfe.toc +0 -14
  100. package/templates/basic-app/package-lock.json +0 -4185
  101. package/templates/go-wasm-app/README.md +0 -38
  102. package/templates/go-wasm-app/babel.config.js +0 -15
  103. package/templates/go-wasm-app/build-client.js +0 -49
  104. package/templates/go-wasm-app/build-wasm.js +0 -237
  105. package/templates/go-wasm-app/package.json +0 -23
  106. package/templates/go-wasm-app/public/index.html +0 -128
  107. package/templates/go-wasm-app/public/styles.css +0 -197
  108. package/templates/go-wasm-app/public/wasm/example.wasm +0 -0
  109. package/templates/go-wasm-app/public/wasm/wasm_exec_node.js +0 -39
  110. package/templates/go-wasm-app/server.js +0 -521
  111. package/templates/go-wasm-app/src/App.jsx +0 -38
  112. package/templates/go-wasm-app/src/app.js +0 -153
  113. package/templates/go-wasm-app/src/client.js +0 -57
  114. package/templates/go-wasm-app/src/components/Footer.jsx +0 -13
  115. package/templates/go-wasm-app/src/components/Header.jsx +0 -19
  116. package/templates/go-wasm-app/src/components/WasmDemo.jsx +0 -120
  117. package/templates/go-wasm-app/src/main.jsx +0 -12
  118. package/templates/go-wasm-app/src/wasm/example.go +0 -75
  119. package/templates/go-wasm-app/tsconfig.server.json +0 -18
  120. package/templates/go-wasm-app/vite.config.js +0 -34
  121. package/templates/ssr-template/package-lock.json +0 -2478
  122. package/templates/ssr-template/public/index.html +0 -47
  123. package/templates/ssr-template/server.js +0 -369
  124. /package/templates/{ssr-template → complete-app}/client.js +0 -0
  125. /package/templates/{ssr-template → complete-app}/readme.md +0 -0
  126. /package/templates/{ssr-template → complete-app}/server.ts +0 -0
  127. /package/templates/{ssr-template → complete-app}/src/client.ts +0 -0
  128. /package/templates/{ssr-template → complete-app}/src/pages/index.tsx +0 -0
@@ -1,47 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Static Fallback</title>
7
- <!-- Import Tailwind-like styles for quick styling -->
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>
12
- <style>
13
- body {
14
- font-family: sans-serif;
15
- max-width: 800px;
16
- margin: 0 auto;
17
- padding: 2rem;
18
- line-height: 1.6;
19
- }
20
- .warning {
21
- background-color: #fff3cd;
22
- border: 1px solid #ffecb5;
23
- color: #856404;
24
- padding: 1rem;
25
- border-radius: 4px;
26
- margin-bottom: 1rem;
27
- }
28
- code {
29
- background-color: #f5f5f5;
30
- padding: 0.2rem 0.4rem;
31
- border-radius: 3px;
32
- }
33
- </style>
34
- </head>
35
- <body>
36
- <!-- App will be rendered here by SSR -->
37
- <div id="app">
38
- <div class="warning">
39
- <h2>STATIC INDEX.HTML FILE</h2>
40
- <p>You should NOT be seeing this page if the server is running correctly.</p>
41
- <p>This is a static file that should only be used as a fallback when the server is not running.</p>
42
- <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
- <p>Try clearing your browser cache and refreshing the page.</p>
44
- </div>
45
- </div>
46
- </body>
47
- </html>
@@ -1,369 +0,0 @@
1
- import express from 'express';
2
- import path from 'path';
3
- import { fileURLToPath } from 'url';
4
- import fetch from 'node-fetch';
5
- import dotenv from 'dotenv';
6
- import fs from 'fs';
7
- import { renderToString } from 'frontend-hamroun';
8
-
9
- // Load environment variables
10
- dotenv.config();
11
-
12
- // Get __dirname equivalent in ESM
13
- const __filename = fileURLToPath(import.meta.url);
14
- const __dirname = path.dirname(__filename);
15
-
16
- // Initialize express app
17
- const app = express();
18
- const PORT = process.env.PORT || 3000;
19
-
20
- // Simple API endpoint
21
- app.get('/api/hello', (req, res) => {
22
- res.json({
23
- message: 'Hello from Server-Side API',
24
- time: new Date().toISOString()
25
- });
26
- });
27
-
28
- // Function to generate meta tags locally without requiring OpenAI
29
- function generateMetaTagsLocally(pageContent) {
30
- // Simple keyword extraction - get common meaningful words
31
- const keywordExtraction = (text) => {
32
- // Remove common words and extract potential keywords
33
- const commonWords = ['a', 'an', 'the', 'and', 'or', 'but', 'is', 'are', 'was', 'were',
34
- 'has', 'have', 'had', 'be', 'been', 'being', 'to', 'of', 'for', 'with', 'about', 'at'];
35
-
36
- const words = text.toLowerCase()
37
- .replace(/[^\w\s]/g, '') // Remove punctuation
38
- .split(/\s+/) // Split by whitespace
39
- .filter(word => word.length > 3 && !commonWords.includes(word)); // Filter short and common words
40
-
41
- // Count word frequency
42
- const wordCount = {};
43
- words.forEach(word => {
44
- wordCount[word] = (wordCount[word] || 0) + 1;
45
- });
46
-
47
- // Sort by frequency and get top keywords
48
- return Object.entries(wordCount)
49
- .sort((a, b) => b[1] - a[1])
50
- .slice(0, 5)
51
- .map(entry => entry[0])
52
- .join(', ');
53
- };
54
-
55
- // Extract main topic (first heading or first sentence)
56
- const getMainTopic = (text) => {
57
- const headingMatch = text.match(/<h1[^>]*>(.*?)<\/h1>/i) ||
58
- text.match(/<h2[^>]*>(.*?)<\/h2>/i);
59
-
60
- if (headingMatch) {
61
- return headingMatch[1].trim();
62
- }
63
-
64
- // If no heading, use first sentence
65
- const firstSentence = text.split(/[.!?]/).filter(s => s.trim().length > 0)[0];
66
- return firstSentence ? firstSentence.trim() : "Frontend Hamroun SSR Page";
67
- };
68
-
69
- // Generate description (first few sentences, truncated)
70
- const getDescription = (text) => {
71
- const plainText = text.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
72
- const sentences = plainText.split(/[.!?]/).filter(s => s.trim().length > 0);
73
- const description = sentences.slice(0, 2).join('. ');
74
-
75
- return description.length > 160
76
- ? description.substring(0, 157) + '...'
77
- : description;
78
- };
79
-
80
- // Generate the meta tags
81
- const title = getMainTopic(pageContent);
82
- const description = getDescription(pageContent);
83
- const keywords = keywordExtraction(pageContent);
84
-
85
- return {
86
- title: title || 'Frontend Hamroun SSR App',
87
- description: description || 'A server-side rendered application using Frontend Hamroun framework',
88
- keywords: keywords || 'ssr, javascript, frontend, hamroun, web development'
89
- };
90
- }
91
-
92
- // Function to generate meta tags - using Gemini with local fallback
93
- async function generateMetaTags(pageContent) {
94
- // Remove forcing local generation
95
- process.env.USE_LOCAL_GENERATION = 'false';
96
-
97
- // Check if local generation is forced
98
- if (process.env.USE_LOCAL_GENERATION === 'true') {
99
- console.log('Using local meta tag generation (forced by config)');
100
- return generateMetaTagsLocally(pageContent);
101
- }
102
-
103
- try {
104
- console.log('Attempting to generate meta tags with Gemini AI...');
105
- return await generateMetaTagsWithGemini(pageContent);
106
- } catch (error) {
107
- console.error('Error generating meta tags with Gemini, falling back to local generation:', error);
108
- return generateMetaTagsLocally(pageContent);
109
- }
110
- }
111
-
112
- // Function to generate meta tags using Google's Gemini API
113
- async function generateMetaTagsWithGemini(pageContent) {
114
- if (!process.env.GEMINI_API_KEY) {
115
- console.log('Gemini API key not found. Using local meta tag generation.');
116
- return generateMetaTagsLocally(pageContent);
117
- }
118
-
119
- try {
120
- console.log('Connecting to Gemini AI...');
121
- // Use the correct model as indicated in the working curl example
122
- const endpoints = [
123
- 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent'
124
- ];
125
-
126
- let response = null;
127
- let responseData = null;
128
-
129
- // Try the endpoint
130
- for (const url of endpoints) {
131
- try {
132
- console.log(`Trying Gemini endpoint: ${url}`);
133
-
134
- const requestBody = {
135
- contents: [{
136
- parts: [{
137
- text: `Generate SEO-friendly meta tags as JSON with the following format:
138
- {
139
- "title": "A concise and engaging title",
140
- "description": "A compelling description under 160 characters",
141
- "keywords": "keyword1, keyword2, keyword3, keyword4, keyword5"
142
- }
143
-
144
- The meta tags should be based on this content: ${pageContent}`
145
- }]
146
- }]
147
- };
148
-
149
- // Log the exact request for debugging
150
- console.log('Sending request to Gemini:', JSON.stringify(requestBody, null, 2).substring(0, 150) + '...');
151
-
152
- response = await fetch(`${url}?key=${process.env.GEMINI_API_KEY}`, {
153
- method: 'POST',
154
- headers: {
155
- 'Content-Type': 'application/json'
156
- },
157
- body: JSON.stringify(requestBody)
158
- });
159
-
160
- // Get the response data
161
- responseData = await response.text();
162
-
163
- // Try to parse it as JSON
164
- try {
165
- responseData = JSON.parse(responseData);
166
-
167
- if (response.ok) {
168
- console.log('Successfully received response from Gemini');
169
- break;
170
- } else {
171
- console.error('Gemini API error response:', responseData);
172
- }
173
- } catch (parseError) {
174
- console.error('Failed to parse Gemini response as JSON:', responseData.substring(0, 150));
175
- throw parseError;
176
- }
177
- } catch (err) {
178
- console.log(`Endpoint ${url} failed:`, err.message);
179
- }
180
- }
181
-
182
- if (!response || !response.ok) {
183
- throw new Error('Failed to get valid response from Gemini API');
184
- }
185
-
186
- // Extract the text response - using the correct response format for gemini-2.0-flash
187
- const textResponse = responseData.candidates[0].content.parts[0].text;
188
-
189
- // Extract the JSON object from the text response
190
- const jsonMatch = textResponse.match(/\{[\s\S]*\}/);
191
- if (!jsonMatch) {
192
- console.error('Could not find JSON in response:', textResponse);
193
- throw new Error('Could not parse JSON from Gemini response');
194
- }
195
-
196
- try {
197
- const metaTagsJson = jsonMatch[0];
198
- const metaTags = JSON.parse(metaTagsJson);
199
- console.log('Generated meta tags using Gemini:', metaTags);
200
-
201
- return metaTags;
202
- } catch (jsonError) {
203
- console.error('Failed to parse extracted JSON:', jsonMatch[0]);
204
- throw jsonError;
205
- }
206
- } catch (error) {
207
- console.error('Error generating meta tags with Gemini:', error);
208
- throw error;
209
- }
210
- }
211
-
212
- // Basic server-side rendering implementation
213
- app.get('/', async (req, res) => {
214
- console.log('Handling root route for SSR');
215
- try {
216
- // Create a simple virtual DOM tree
217
- const vnode = {
218
- type: 'div',
219
- props: {
220
- id: 'app',
221
- children: [
222
- {
223
- type: 'h1',
224
- props: {
225
- children: 'Hello from Server-Side Rendering!'
226
- }
227
- },
228
- {
229
- type: 'p',
230
- props: {
231
- children: `This page was rendered at ${new Date().toISOString()}`
232
- }
233
- },
234
- {
235
- type: 'button',
236
- props: {
237
- id: 'counter-btn',
238
- className: 'btn',
239
- children: 'Click me (0)'
240
- }
241
- }
242
- ]
243
- }
244
- };
245
-
246
- // Generate content for meta tag creation
247
- const contentForMetaTags = 'Server-side rendered page using Frontend Hamroun framework. ' +
248
- 'This demonstrates SSR capabilities with dynamic content generation and client-side hydration.';
249
-
250
- console.log('Fetching meta tags for the page...');
251
- const metaTags = await generateMetaTags(contentForMetaTags);
252
-
253
- // Generate HTML from our virtual node directly using imported renderToString
254
- const content =await renderToString(vnode);
255
-
256
- // Send complete HTML document with explicit content type
257
- res.setHeader('Content-Type', 'text/html');
258
- res.send(`
259
- <!DOCTYPE html>
260
- <html>
261
- <head>
262
- <meta charset="UTF-8">
263
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
264
-
265
- <!-- AI Generated Meta Tags -->
266
- <title>${metaTags.title}</title>
267
- <meta name="description" content="${metaTags.description}">
268
- <meta name="keywords" content="${metaTags.keywords}">
269
-
270
- <!-- Open Graph tags -->
271
- <meta property="og:title" content="${metaTags.title}">
272
- <meta property="og:description" content="${metaTags.description}">
273
- <meta property="og:type" content="website">
274
- <meta property="og:url" content="${req.protocol}://${req.get('host')}${req.originalUrl}">
275
-
276
- <!-- Twitter Card tags -->
277
- <meta name="twitter:card" content="summary_large_image">
278
- <meta name="twitter:title" content="${metaTags.title}">
279
- <meta name="twitter:description" content="${metaTags.description}">
280
-
281
- <style>
282
- body {
283
- font-family: sans-serif;
284
- max-width: 800px;
285
- margin: 0 auto;
286
- padding: 2rem;
287
- }
288
- .btn {
289
- background-color: #4CAF50;
290
- border: none;
291
- color: white;
292
- padding: 10px 20px;
293
- cursor: pointer;
294
- border-radius: 4px;
295
- margin-top: 1rem;
296
- }
297
- </style>
298
- <script>
299
- // Simple client-side interactivity
300
- document.addEventListener('DOMContentLoaded', () => {
301
- const btn = document.getElementById('counter-btn');
302
- if (btn) {
303
- let count = 0;
304
- btn.addEventListener('click', () => {
305
- count++;
306
- btn.textContent = \`Click me (\${count})\`;
307
- });
308
- console.log('Button click handler attached');
309
- }
310
- });
311
- </script>
312
- </head>
313
- <body>${content || '<div>Error: No content generated</div>'}</body>
314
- </html>
315
- `);
316
- } catch (error) {
317
- console.error('SSR Error:', error);
318
-
319
- // Fallback HTML with error details
320
- res.status(500).send(`
321
- <!DOCTYPE html>
322
- <html>
323
- <head>
324
- <title>SSR Error</title>
325
- <style>
326
- body { font-family: sans-serif; padding: 2rem; }
327
- pre { background: #f5f5f5; padding: 1rem; overflow: auto; }
328
- </style>
329
- </head>
330
- <body>
331
- <h1>Server-Side Rendering Error</h1>
332
- <p>There was a problem rendering the page.</p>
333
- <pre>${error.stack}</pre>
334
- <p>Try refreshing the page or contact the administrator if the problem persists.</p>
335
- </body>
336
- </html>
337
- `);
338
- }
339
- });
340
-
341
- // Serve static files AFTER routes that need SSR
342
- app.use(express.static(path.join(__dirname, 'public')));
343
-
344
- // A catch-all route for any other requests
345
- app.get('*', (req, res) => {
346
- console.log(`Handling catch-all route: ${req.path}`);
347
- res.status(404).send(`
348
- <!DOCTYPE html>
349
- <html>
350
- <head>
351
- <title>Page Not Found</title>
352
- <style>
353
- body { font-family: sans-serif; padding: 2rem; }
354
- </style>
355
- </head>
356
- <body>
357
- <h1>Page Not Found</h1>
358
- <p>The page you requested does not exist.</p>
359
- <p><a href="/">Go to home page</a></p>
360
- </body>
361
- </html>
362
- `);
363
- });
364
-
365
- // Start the server
366
- app.listen(PORT, () => {
367
- console.log(`Server running at http://localhost:${PORT}`);
368
- console.log(`Open your browser and navigate to http://localhost:${PORT}`);
369
- });