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.
Files changed (259) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -1513
  3. package/bin/cli.js +506 -145
  4. package/dist/index.cjs +2 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.client.cjs +2 -0
  7. package/dist/index.client.cjs.map +1 -0
  8. package/dist/index.client.js +26 -0
  9. package/dist/index.client.js.map +1 -0
  10. package/dist/index.js +299 -1
  11. package/dist/index.js.map +1 -0
  12. package/dist/jsx-runtime.cjs +2 -0
  13. package/dist/jsx-runtime.cjs.map +1 -0
  14. package/dist/jsx-runtime.js +93 -1
  15. package/dist/jsx-runtime.js.map +1 -0
  16. package/dist/renderer-Bo9zkUZ_.js +52 -0
  17. package/dist/renderer-Bo9zkUZ_.js.map +1 -0
  18. package/dist/renderer-Din1y3YM.cjs +2 -0
  19. package/dist/renderer-Din1y3YM.cjs.map +1 -0
  20. package/dist/server-renderer-CqIpQ-od.cjs +2 -0
  21. package/dist/server-renderer-CqIpQ-od.cjs.map +1 -0
  22. package/dist/server-renderer-QHt45Ip2.js +255 -0
  23. package/dist/server-renderer-QHt45Ip2.js.map +1 -0
  24. package/dist/server-renderer.cjs +2 -0
  25. package/dist/server-renderer.cjs.map +1 -0
  26. package/dist/server-renderer.js +5 -1
  27. package/dist/server-renderer.js.map +1 -0
  28. package/package.json +77 -120
  29. package/templates/basic-app/build.js +22 -0
  30. package/templates/basic-app/dev.js +27 -0
  31. package/templates/basic-app/esbuild.config.js +28 -0
  32. package/templates/basic-app/index.html +1 -1
  33. package/templates/basic-app/package.json +29 -28
  34. package/templates/basic-app/server.js +24 -0
  35. package/templates/basic-app/src/App.jsx +16 -0
  36. package/templates/basic-app/src/App.tsx +26 -0
  37. package/templates/basic-app/src/client.jsx +5 -0
  38. package/templates/basic-app/src/client.tsx +11 -0
  39. package/templates/basic-app/src/components/Counter.jsx +13 -0
  40. package/templates/basic-app/src/components/Counter.tsx +18 -0
  41. package/templates/basic-app/src/jsx-shim.js +3 -0
  42. package/templates/basic-app/src/jsx-shim.ts +11 -0
  43. package/templates/basic-app/src/main.jsx +98 -0
  44. package/templates/basic-app/src/main.tsx +0 -1
  45. package/templates/basic-app/src/server.js +47 -0
  46. package/templates/basic-app/src/server.ts +52 -0
  47. package/templates/basic-app/tsconfig.server.json +11 -0
  48. package/templates/complete-app/lib/frontend-hamroun.js +182 -0
  49. package/templates/complete-app/package.json +2 -1
  50. package/templates/complete-app/pages/about.jsx +0 -0
  51. package/templates/complete-app/pages/index.jsx +0 -0
  52. package/templates/complete-app/pages/wasm-demo.jsx +0 -0
  53. package/templates/complete-app/public/client.js +58 -49
  54. package/templates/complete-app/public/index.html +88 -17
  55. package/templates/complete-app/public/styles.css +30 -533
  56. package/templates/complete-app/server.js +31 -222
  57. package/templates/complete-app/wasm/build.bat +0 -0
  58. package/templates/complete-app/wasm/build.sh +0 -0
  59. package/templates/complete-app/wasm/example.go +0 -0
  60. package/templates/fullstack-app/build/main.js +130 -101
  61. package/templates/fullstack-app/build/main.js.map +4 -4
  62. package/templates/fullstack-app/package-lock.json +1773 -566
  63. package/templates/ssr-template/esbuild.config.js +33 -0
  64. package/templates/ssr-template/jsx-shim.js +1 -0
  65. package/templates/ssr-template/package.json +22 -16
  66. package/templates/ssr-template/src/App.tsx +12 -52
  67. package/templates/ssr-template/src/client.tsx +3 -17
  68. package/templates/ssr-template/src/server.ts +21 -204
  69. package/templates/ssr-template/tsconfig.json +10 -13
  70. package/templates/ssr-template/tsconfig.server.json +6 -14
  71. package/templates/wasm/build-wasm.js +228 -0
  72. package/templates/wasm/esbuild.config.js +63 -0
  73. package/templates/wasm/go/main.go +256 -0
  74. package/templates/wasm/go/wasm_exec.js +0 -0
  75. package/templates/wasm/index.html +97 -0
  76. package/templates/wasm/jsx-shim.js +9 -0
  77. package/templates/{go-wasm-app → wasm}/package-lock.json +5307 -3732
  78. package/templates/wasm/package.json +42 -0
  79. package/templates/wasm/public/example.wasm +0 -0
  80. package/templates/wasm/src/App.tsx +564 -0
  81. package/templates/wasm/src/client.tsx +220 -0
  82. package/templates/wasm/src/index.tsx +21 -0
  83. package/templates/wasm/src/server.ts +145 -0
  84. package/templates/wasm/tsconfig.json +21 -0
  85. package/templates/wasm/tsconfig.node.json +13 -0
  86. package/templates/wasm/tsconfig.server.json +23 -0
  87. package/templates/wasm/vite.config.ts +56 -0
  88. package/templates/wasm/wasm-loader.js +103 -0
  89. package/dist/batch/package.json +0 -16
  90. package/dist/client-router/package.json +0 -16
  91. package/dist/component/package.json +0 -16
  92. package/dist/context/package.json +0 -16
  93. package/dist/event-bus/package.json +0 -16
  94. package/dist/forms/package.json +0 -16
  95. package/dist/hooks/package.json +0 -16
  96. package/dist/hooks-0728361a.cjs +0 -1
  97. package/dist/hooks-b58f947c.js +0 -133
  98. package/dist/hooks.js +0 -1
  99. package/dist/hooks.mjs +0 -13
  100. package/dist/index.mjs +0 -137
  101. package/dist/jsx-runtime/package.json +0 -16
  102. package/dist/jsx-runtime.mjs +0 -64
  103. package/dist/lifecycle-events/package.json +0 -16
  104. package/dist/package.json +0 -71
  105. package/dist/render-component/package.json +0 -16
  106. package/dist/renderer/package.json +0 -16
  107. package/dist/renderer.js +0 -1
  108. package/dist/renderer.mjs +0 -27
  109. package/dist/router/package.json +0 -16
  110. package/dist/server/package.json +0 -17
  111. package/dist/server/src/batch.d.ts +0 -3
  112. package/dist/server/src/batch.js +0 -23
  113. package/dist/server/src/batch.js.map +0 -1
  114. package/dist/server/src/client-router.d.ts +0 -60
  115. package/dist/server/src/client-router.js +0 -210
  116. package/dist/server/src/client-router.js.map +0 -1
  117. package/dist/server/src/component.d.ts +0 -14
  118. package/dist/server/src/component.js +0 -106
  119. package/dist/server/src/component.js.map +0 -1
  120. package/dist/server/src/context.d.ts +0 -13
  121. package/dist/server/src/context.js +0 -21
  122. package/dist/server/src/context.js.map +0 -1
  123. package/dist/server/src/event-bus.d.ts +0 -23
  124. package/dist/server/src/event-bus.js +0 -75
  125. package/dist/server/src/event-bus.js.map +0 -1
  126. package/dist/server/src/forms.d.ts +0 -40
  127. package/dist/server/src/forms.js +0 -148
  128. package/dist/server/src/forms.js.map +0 -1
  129. package/dist/server/src/hooks.d.ts +0 -12
  130. package/dist/server/src/hooks.js +0 -170
  131. package/dist/server/src/hooks.js.map +0 -1
  132. package/dist/server/src/index.client.d.ts +0 -12
  133. package/dist/server/src/index.client.js +0 -14
  134. package/dist/server/src/index.client.js.map +0 -1
  135. package/dist/server/src/index.d.ts +0 -88
  136. package/dist/server/src/index.js +0 -79
  137. package/dist/server/src/index.js.map +0 -1
  138. package/dist/server/src/jsx-runtime/jsx-dev-runtime.d.ts +0 -1
  139. package/dist/server/src/jsx-runtime/jsx-dev-runtime.js +0 -2
  140. package/dist/server/src/jsx-runtime/jsx-dev-runtime.js.map +0 -1
  141. package/dist/server/src/jsx-runtime/jsx-runtime.d.ts +0 -4
  142. package/dist/server/src/jsx-runtime/jsx-runtime.js +0 -41
  143. package/dist/server/src/jsx-runtime/jsx-runtime.js.map +0 -1
  144. package/dist/server/src/jsx-runtime.d.ts +0 -20
  145. package/dist/server/src/jsx-runtime.js +0 -105
  146. package/dist/server/src/jsx-runtime.js.map +0 -1
  147. package/dist/server/src/lifecycle-events.d.ts +0 -108
  148. package/dist/server/src/lifecycle-events.js +0 -177
  149. package/dist/server/src/lifecycle-events.js.map +0 -1
  150. package/dist/server/src/renderComponent.d.ts +0 -13
  151. package/dist/server/src/renderComponent.js +0 -30
  152. package/dist/server/src/renderComponent.js.map +0 -1
  153. package/dist/server/src/renderer.d.ts +0 -2
  154. package/dist/server/src/renderer.js +0 -31
  155. package/dist/server/src/renderer.js.map +0 -1
  156. package/dist/server/src/router.d.ts +0 -55
  157. package/dist/server/src/router.js +0 -166
  158. package/dist/server/src/router.js.map +0 -1
  159. package/dist/server/src/server/api-router.d.ts +0 -15
  160. package/dist/server/src/server/api-router.js +0 -111
  161. package/dist/server/src/server/api-router.js.map +0 -1
  162. package/dist/server/src/server/auth.d.ts +0 -32
  163. package/dist/server/src/server/auth.js +0 -80
  164. package/dist/server/src/server/auth.js.map +0 -1
  165. package/dist/server/src/server/database.d.ts +0 -24
  166. package/dist/server/src/server/database.js +0 -135
  167. package/dist/server/src/server/database.js.map +0 -1
  168. package/dist/server/src/server/index.d.ts +0 -116
  169. package/dist/server/src/server/index.js +0 -508
  170. package/dist/server/src/server/index.js.map +0 -1
  171. package/dist/server/src/server/middleware.d.ts +0 -11
  172. package/dist/server/src/server/middleware.js +0 -46
  173. package/dist/server/src/server/middleware.js.map +0 -1
  174. package/dist/server/src/server/server.d.ts +0 -9
  175. package/dist/server/src/server/server.js +0 -87
  176. package/dist/server/src/server/server.js.map +0 -1
  177. package/dist/server/src/server/templates.d.ts +0 -30
  178. package/dist/server/src/server/templates.js +0 -208
  179. package/dist/server/src/server/templates.js.map +0 -1
  180. package/dist/server/src/server/types.d.ts +0 -38
  181. package/dist/server/src/server/types.js +0 -4
  182. package/dist/server/src/server/types.js.map +0 -1
  183. package/dist/server/src/server/utils.d.ts +0 -70
  184. package/dist/server/src/server/utils.js +0 -156
  185. package/dist/server/src/server/utils.js.map +0 -1
  186. package/dist/server/src/server/wasm.d.ts +0 -9
  187. package/dist/server/src/server/wasm.js +0 -117
  188. package/dist/server/src/server/wasm.js.map +0 -1
  189. package/dist/server/src/server-renderer.d.ts +0 -5
  190. package/dist/server/src/server-renderer.js +0 -106
  191. package/dist/server/src/server-renderer.js.map +0 -1
  192. package/dist/server/src/server-types.d.ts +0 -42
  193. package/dist/server/src/server-types.js +0 -6
  194. package/dist/server/src/server-types.js.map +0 -1
  195. package/dist/server/src/store.d.ts +0 -41
  196. package/dist/server/src/store.js +0 -99
  197. package/dist/server/src/store.js.map +0 -1
  198. package/dist/server/src/types.d.ts +0 -19
  199. package/dist/server/src/types.js +0 -2
  200. package/dist/server/src/types.js.map +0 -1
  201. package/dist/server/src/utils.d.ts +0 -46
  202. package/dist/server/src/utils.js +0 -144
  203. package/dist/server/src/utils.js.map +0 -1
  204. package/dist/server/src/vdom.d.ts +0 -8
  205. package/dist/server/src/vdom.js +0 -22
  206. package/dist/server/src/vdom.js.map +0 -1
  207. package/dist/server/src/wasm.d.ts +0 -36
  208. package/dist/server/src/wasm.js +0 -159
  209. package/dist/server/src/wasm.js.map +0 -1
  210. package/dist/server/tsconfig.server.tsbuildinfo +0 -1
  211. package/dist/server-renderer/package.json +0 -16
  212. package/dist/server-renderer.mjs +0 -64
  213. package/dist/store/package.json +0 -16
  214. package/dist/types/package.json +0 -16
  215. package/dist/utils/package.json +0 -16
  216. package/dist/vdom/package.json +0 -16
  217. package/dist/wasm/package.json +0 -16
  218. package/dist/wasm.js +0 -1
  219. package/dist/wasm.mjs +0 -103
  220. package/templates/basic-app/docs/rapport_pfe.aux +0 -27
  221. package/templates/basic-app/docs/rapport_pfe.log +0 -399
  222. package/templates/basic-app/docs/rapport_pfe.out +0 -10
  223. package/templates/basic-app/docs/rapport_pfe.pdf +0 -0
  224. package/templates/basic-app/docs/rapport_pfe.tex +0 -68
  225. package/templates/basic-app/docs/rapport_pfe.toc +0 -14
  226. package/templates/complete-app/package-lock.json +0 -2536
  227. package/templates/go-wasm-app/README.md +0 -38
  228. package/templates/go-wasm-app/babel.config.js +0 -21
  229. package/templates/go-wasm-app/build-client.js +0 -49
  230. package/templates/go-wasm-app/build-wasm.js +0 -237
  231. package/templates/go-wasm-app/build.config.js +0 -62
  232. package/templates/go-wasm-app/build.js +0 -218
  233. package/templates/go-wasm-app/package.json +0 -32
  234. package/templates/go-wasm-app/public/index.html +0 -128
  235. package/templates/go-wasm-app/public/styles.css +0 -197
  236. package/templates/go-wasm-app/public/wasm/example.wasm +0 -0
  237. package/templates/go-wasm-app/public/wasm/wasm_exec_node.js +0 -39
  238. package/templates/go-wasm-app/server.js +0 -70
  239. package/templates/go-wasm-app/src/App.jsx +0 -38
  240. package/templates/go-wasm-app/src/app.js +0 -173
  241. package/templates/go-wasm-app/src/client.js +0 -57
  242. package/templates/go-wasm-app/src/components/Footer.jsx +0 -13
  243. package/templates/go-wasm-app/src/components/Header.jsx +0 -19
  244. package/templates/go-wasm-app/src/components/WasmDemo.jsx +0 -120
  245. package/templates/go-wasm-app/src/main.jsx +0 -12
  246. package/templates/go-wasm-app/src/wasm/example.go +0 -75
  247. package/templates/go-wasm-app/tsconfig.server.json +0 -18
  248. package/templates/go-wasm-app/vite.config.js +0 -45
  249. package/templates/ssr-template/client.js +0 -58
  250. package/templates/ssr-template/package-lock.json +0 -2478
  251. package/templates/ssr-template/public/index.html +0 -47
  252. package/templates/ssr-template/readme.md +0 -188
  253. package/templates/ssr-template/server.js +0 -369
  254. package/templates/ssr-template/server.ts +0 -275
  255. package/templates/ssr-template/src/client.ts +0 -61
  256. package/templates/ssr-template/src/pages/index.tsx +0 -51
  257. package/templates/ssr-template/vite.config.js +0 -57
  258. /package/{dist/Counter.d.ts → templates/complete-app/api/hello.js} +0 -0
  259. /package/templates/{go-wasm-app/public/wasm → wasm/public}/wasm_exec.js +0 -0
@@ -0,0 +1,33 @@
1
+ import { build } from 'esbuild';
2
+
3
+ // Build client
4
+ await build({
5
+ entryPoints: ['src/client.tsx'],
6
+ bundle: true,
7
+ outfile: 'dist/client.js',
8
+ platform: 'browser',
9
+ format: 'esm',
10
+ minify: false,
11
+ jsx: 'transform',
12
+ jsxFactory: 'jsx',
13
+ jsxFragment: 'Fragment',
14
+ inject: ['./jsx-shim.js'],
15
+ });
16
+
17
+ // Build server
18
+ await build({
19
+ entryPoints: ['src/server.ts'],
20
+ bundle: true,
21
+ outfile: 'dist/server.js',
22
+ platform: 'node',
23
+ format: 'esm',
24
+ external: ['frontend-hamroun'],
25
+ packages: 'external',
26
+ minify: false,
27
+ jsx: 'transform',
28
+ jsxFactory: 'jsx',
29
+ jsxFragment: 'Fragment',
30
+ inject: ['./jsx-shim.js'],
31
+ });
32
+
33
+ console.log('Build completed successfully!');
@@ -0,0 +1 @@
1
+ export { jsx, Fragment } from 'frontend-hamroun';
@@ -1,16 +1,22 @@
1
- {
2
- "name": "ssr-app",
3
- "version": "0.1.0",
4
- "type": "module",
5
- "scripts": {
6
- "dev": "node server.js",
7
- "start": "node server.js",
8
- "build": "echo 'No build step required for this template'"
9
- },
10
- "dependencies": {
11
- "dotenv": "^16.0.3",
12
- "express": "^4.18.2",
13
- "frontend-hamroun": "latest",
14
- "node-fetch": "^3.3.1"
15
- }
16
- }
1
+ {
2
+ "name": "ssr-version",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build:client": "esbuild src/client.tsx --bundle --outfile=dist/client.js --platform=browser --format=esm",
8
+ "build:server": "esbuild src/server.ts --bundle --outfile=dist/server.js --platform=node --format=esm --external:frontend-hamroun --packages=external",
9
+ "build": "node esbuild.config.js",
10
+ "start": "node dist/server.js"
11
+ },
12
+ "dependencies": {
13
+ "express": "^4.18.2",
14
+ "frontend-hamroun": "latest"
15
+ },
16
+ "devDependencies": {
17
+ "@types/express": "^4.17.17",
18
+ "@types/node": "^20.5.0",
19
+ "esbuild": "^0.19.12",
20
+ "typescript": "^5.0.0"
21
+ }
22
+ }
@@ -1,59 +1,19 @@
1
- import { useState, useEffect, useMemo, useRef, createContext } from 'frontend-hamroun';
2
-
3
- // Create a theme context
4
- const ThemeContext = createContext('light');
1
+ import { useState } from 'frontend-hamroun';
5
2
 
6
3
  export function App() {
7
- // Initialize with a default state that works on both server and client
8
4
  const [count, setCount] = useState(0);
9
- const [theme, setTheme] = useState<'light' | 'dark'>('light');
10
- const renderCount = useRef(0);
11
-
12
- // Client-side only effect
13
- useEffect(() => {
14
- if (typeof window !== 'undefined') {
15
- renderCount.current += 1;
16
- console.log('Component rendered', renderCount.current, 'times');
17
- }
18
- return () => console.log('Component unmounting');
19
- }, [count]);
20
-
21
- // Memoized value
22
- const doubled = useMemo(() => count * 2, [count]);
23
-
5
+
6
+ const increment = () => setCount(count + 1);
7
+ const decrement = () => setCount(count - 1);
8
+
24
9
  return (
25
- <ThemeContext.Provider value={theme}>
26
- <div style={{
27
- padding: '20px',
28
- backgroundColor: theme === 'dark' ? '#333' : '#fff',
29
- color: theme === 'dark' ? '#fff' : '#333'
30
- }}>
31
- <h1>Server-Side Rendered App</h1>
32
- <div>
33
- <button
34
- onClick={() => setCount(count - 1)}
35
- data-action="decrement"
36
- >-</button>
37
- <span style={{ margin: '0 10px' }}>{count}</span>
38
- <button
39
- onClick={() => setCount(count + 1)}
40
- data-action="increment"
41
- >+</button>
42
- </div>
43
- <p>Doubled value: {doubled}</p>
44
- {typeof window !== 'undefined' && (
45
- <p>Render count: {renderCount.current}</p>
46
- )}
47
- <button
48
- onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
49
- style={{ marginTop: '10px' }}
50
- >
51
- Toggle Theme ({theme})
52
- </button>
53
- <script dangerouslySetInnerHTML={{
54
- __html: `window.__INITIAL_STATE__ = ${JSON.stringify({ count: 0, theme: 'light' })};`
55
- }} />
10
+ <div>
11
+ <h1>Server-Side Rendered App</h1>
12
+ <div>
13
+ <button onClick={decrement} data-action="decrement">-</button>
14
+ <span style={{ margin: '0 10px' }}>{count}</span>
15
+ <button onClick={increment} data-action="increment">+</button>
56
16
  </div>
57
- </ThemeContext.Provider>
17
+ </div>
58
18
  );
59
19
  }
@@ -1,18 +1,4 @@
1
- import { hydrate, createElement } from 'frontend-hamroun';
1
+ import { hydrate, jsx } from 'frontend-hamroun';
2
+ import { App } from './App.js';
2
3
 
3
- // For simplicity in this example, we just hydrate the root component
4
- // In a more complex app, you might use a router
5
- import HomePage from './pages/index';
6
-
7
- // When the DOM is ready, hydrate the server-rendered HTML
8
- document.addEventListener('DOMContentLoaded', () => {
9
- const rootElement = document.getElementById('app');
10
-
11
- if (rootElement) {
12
- // Hydrate the app with the same component that was rendered on the server
13
- hydrate(<HomePage />, rootElement);
14
- console.log('Hydration complete');
15
- } else {
16
- console.error('Could not find root element with id "app"');
17
- }
18
- });
4
+ hydrate(jsx(App, {}), document.getElementById('root')!);
@@ -3,214 +3,31 @@ import path from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { renderToString, jsx } from 'frontend-hamroun';
5
5
  import { App } from './App.js';
6
- import fs from 'fs';
7
6
 
8
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
9
10
  const app = express();
10
11
  const port = 3000;
11
12
 
12
- // Find the client entry file
13
- const getClientEntry = () => {
14
- const assetsDir = path.join(__dirname, './');
15
- const files = fs.readdirSync(assetsDir);
16
- return files.find(file => file.startsWith("client") && file.endsWith('.js'));
17
- };
18
-
19
- // Serve static files from dist/assets
20
- app.use('/assets', express.static(path.join(__dirname, './')));
21
-
22
- // Serve static files from dist
23
- app.use(express.static(path.join(__dirname, 'dist')));
24
-
25
- // Auto-routing middleware - scans the pages directory for components
26
- const getPagesDirectory = () => {
27
- return path.join(__dirname, 'pages');
28
- };
29
-
30
- // Helper to check if a file exists
31
- const fileExists = async (filePath) => {
32
- try {
33
- await fs.promises.access(filePath);
34
- return true;
35
- } catch {
36
- return false;
37
- }
38
- };
39
-
40
- // Map URL path to component path
41
- const getComponentPath = async (urlPath) => {
42
- const pagesDir = getPagesDirectory();
43
-
44
- // Handle root path
45
- if (urlPath === '/') {
46
- const indexPath = path.join(pagesDir, 'index.js');
47
- if (await fileExists(indexPath)) {
48
- return {
49
- componentPath: indexPath,
50
- params: {}
51
- };
52
- }
53
- }
54
-
55
- // Try direct match (e.g., /about -> /pages/about.js)
56
- const directPath = path.join(pagesDir, `${urlPath.slice(1)}.js`);
57
- if (await fileExists(directPath)) {
58
- return {
59
- componentPath: directPath,
60
- params: {}
61
- };
62
- }
63
-
64
- // Try directory index (e.g., /about -> /pages/about/index.js)
65
- const dirIndexPath = path.join(pagesDir, urlPath.slice(1), 'index.js');
66
- if (await fileExists(dirIndexPath)) {
67
- return {
68
- componentPath: dirIndexPath,
69
- params: {}
70
- };
71
- }
72
-
73
- // Look for dynamic routes (with [param] in filename)
74
- const segments = urlPath.split('/').filter(Boolean);
75
- const dynamicRoutes = [];
76
-
77
- // Recursively scan pages directory for all files
78
- const scanDir = (dir, basePath = '') => {
79
- const items = fs.readdirSync(dir, { withFileTypes: true });
80
-
81
- for (const item of items) {
82
- const itemPath = path.join(dir, item.name);
83
- const routePath = path.join(basePath, item.name);
84
-
85
- if (item.isDirectory()) {
86
- scanDir(itemPath, routePath);
87
- } else if (item.name.endsWith('.js') && item.name.includes('[')) {
88
- // This is a dynamic route file
89
- const urlPattern = routePath
90
- .replace(/\.js$/, '')
91
- .replace(/\[([^\]]+)\]/g, ':$1');
92
-
93
- dynamicRoutes.push({
94
- pattern: urlPattern,
95
- componentPath: itemPath
96
- });
97
- }
98
- }
99
- };
100
-
101
- scanDir(pagesDir);
102
-
103
- // Check if any dynamic routes match
104
- for (const route of dynamicRoutes) {
105
- const routeSegments = route.pattern.split('/').filter(Boolean);
106
- if (routeSegments.length !== segments.length) continue;
107
-
108
- const params = {};
109
- let matches = true;
110
-
111
- for (let i = 0; i < segments.length; i++) {
112
- const routeSeg = routeSegments[i];
113
- const urlSeg = segments[i];
114
-
115
- if (routeSeg.startsWith(':')) {
116
- // This is a parameter
117
- const paramName = routeSeg.slice(1);
118
- params[paramName] = urlSeg;
119
- } else if (routeSeg !== urlSeg) {
120
- matches = false;
121
- break;
122
- }
123
- }
124
-
125
- if (matches) {
126
- return {
127
- componentPath: route.componentPath,
128
- params
129
- };
130
- }
131
- }
132
-
133
- // No match found
134
- return null;
135
- };
136
-
137
- // Handle all routes with auto-routing
138
- app.get('*', async (req, res) => {
139
- try {
140
- const clientEntry = getClientEntry();
141
- const routeResult = await getComponentPath(req.path);
142
-
143
- if (!routeResult) {
144
- return res.status(404).send(`
145
- <!DOCTYPE html>
146
- <html>
147
- <head>
148
- <title>404 - Page Not Found</title>
149
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
150
- </head>
151
- <body>
152
- <div id="root">
153
- <h1>404 - Page Not Found</h1>
154
- <p>The page you requested could not be found.</p>
155
- </div>
156
- <script type="module" src="/assets/${clientEntry}"></script>
157
- </body>
158
- </html>
159
- `);
160
- }
161
-
162
- // Import the component dynamically
163
- const { default: PageComponent } = await import(routeResult.componentPath);
164
-
165
- if (!PageComponent) {
166
- throw new Error(`Invalid component in ${routeResult.componentPath}`);
167
- }
168
-
169
- // Render the component with params
170
- const html = await renderToString(jsx(PageComponent, { params: routeResult.params }));
171
-
172
- // Create route data for client hydration
173
- const initialState = {
174
- route: req.path,
175
- params: routeResult.params,
176
- timestamp: new Date().toISOString()
177
- };
178
-
179
- res.send(`
180
- <!DOCTYPE html>
181
- <html>
182
- <head>
183
- <title>Frontend Hamroun SSR</title>
184
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
185
- <meta charset="UTF-8">
186
- </head>
187
- <body>
188
- <div id="root">${html}</div>
189
- <script>window.__INITIAL_STATE__ = ${JSON.stringify(initialState)}</script>
190
- <script type="module" src="/assets/${clientEntry}"></script>
191
- </body>
192
- </html>
193
- `);
194
- } catch (error) {
195
- console.error('Rendering error:', error);
196
- res.status(500).send(`
197
- <!DOCTYPE html>
198
- <html>
199
- <head>
200
- <title>500 - Server Error</title>
201
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
202
- </head>
203
- <body>
204
- <div id="root">
205
- <h1>500 - Server Error</h1>
206
- <p>Something went wrong on the server.</p>
207
- <pre>${process.env.NODE_ENV === 'production' ? '' : error.stack}</pre>
208
- </div>
209
- <script type="module" src="/assets/${clientEntry}"></script>
210
- </body>
211
- </html>
212
- `);
213
- }
13
+ // Serve static files from dist directory
14
+ app.use(express.static(path.join(__dirname)));
15
+
16
+ app.get('/', async (req, res) => {
17
+ const html = await renderToString(jsx(App, {}));
18
+
19
+ res.send(`
20
+ <!DOCTYPE html>
21
+ <html>
22
+ <head>
23
+ <title>SSR App</title>
24
+ </head>
25
+ <body>
26
+ <div id="root">${html}</div>
27
+ <script type="module" src="/client.js"></script>
28
+ </body>
29
+ </html>
30
+ `);
214
31
  });
215
32
 
216
33
  app.listen(port, () => {
@@ -1,22 +1,19 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "ESNext",
4
- "useDefineForClassFields": true,
5
- "lib": ["DOM", "DOM.Iterable", "ESNext"],
6
- "allowJs": false,
7
- "skipLibCheck": true,
8
- "esModuleInterop": true,
9
- "allowSyntheticDefaultImports": true,
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "jsx": "preserve",
10
7
  "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
11
10
  "forceConsistentCasingInFileNames": true,
12
- "module": "ESNext",
13
- "moduleResolution": "Node",
11
+ "allowSyntheticDefaultImports": true,
14
12
  "resolveJsonModule": true,
15
13
  "isolatedModules": true,
16
14
  "noEmit": true,
17
- "jsx": "preserve",
18
- "jsxFactory": "createElement",
19
- "jsxFragmentFactory": "Fragment"
15
+ "types": ["node"]
20
16
  },
21
- "include": ["src"]
17
+ "include": ["src"],
18
+ "exclude": ["node_modules", "dist"]
22
19
  }
@@ -1,19 +1,11 @@
1
1
  {
2
2
  "extends": "./tsconfig.json",
3
3
  "compilerOptions": {
4
- "target": "ES2020",
5
- "module": "NodeNext",
6
- "moduleResolution": "NodeNext",
7
- "esModuleInterop": true,
8
- "outDir": "./dist/server",
9
- "declaration": true,
10
- "sourceMap": true,
11
- "strict": true,
12
- "skipLibCheck": true,
13
- "jsx": "react",
14
- "jsxFactory": "createElement",
15
- "jsxFragmentFactory": "Fragment"
4
+ "module": "ESNext",
5
+ "outDir": "dist",
6
+ "noEmit": false,
7
+ "jsx": "preserve",
8
+ "moduleResolution": "bundler"
16
9
  },
17
- "include": ["server.ts", "src/pages/**/*.tsx"],
18
- "exclude": ["node_modules", "dist"]
10
+ "include": ["src/server.ts"]
19
11
  }