frontend-hamroun 1.2.74 → 1.2.77

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 (194) hide show
  1. package/dist/Counter.d.ts +0 -0
  2. package/dist/batch/package.json +16 -0
  3. package/dist/client-router/package.json +16 -0
  4. package/dist/component/package.json +16 -0
  5. package/dist/context/package.json +16 -0
  6. package/dist/event-bus/package.json +16 -0
  7. package/dist/forms/package.json +16 -0
  8. package/dist/hooks/package.json +16 -0
  9. package/dist/hooks-0728361a.cjs +1 -0
  10. package/dist/hooks-b58f947c.js +133 -0
  11. package/dist/hooks.js +1 -0
  12. package/dist/hooks.mjs +13 -0
  13. package/dist/index.js +1 -384
  14. package/dist/index.mjs +130 -374
  15. package/dist/jsx-runtime/package.json +16 -0
  16. package/dist/jsx-runtime.js +1 -0
  17. package/dist/jsx-runtime.mjs +64 -0
  18. package/dist/lifecycle-events/package.json +16 -0
  19. package/dist/package.json +71 -0
  20. package/dist/render-component/package.json +16 -0
  21. package/dist/renderer/package.json +16 -0
  22. package/dist/renderer.js +1 -0
  23. package/dist/renderer.mjs +27 -0
  24. package/dist/router/package.json +16 -0
  25. package/dist/server/package.json +17 -0
  26. package/dist/server/src/batch.d.ts +3 -0
  27. package/dist/server/src/batch.js +23 -0
  28. package/dist/server/src/batch.js.map +1 -0
  29. package/dist/server/src/client-router.d.ts +60 -0
  30. package/dist/server/src/client-router.js +210 -0
  31. package/dist/server/src/client-router.js.map +1 -0
  32. package/dist/server/src/component.d.ts +14 -0
  33. package/dist/server/src/component.js +106 -0
  34. package/dist/server/src/component.js.map +1 -0
  35. package/dist/server/src/context.d.ts +13 -0
  36. package/dist/server/src/context.js +21 -0
  37. package/dist/server/src/context.js.map +1 -0
  38. package/dist/server/src/event-bus.d.ts +23 -0
  39. package/dist/server/src/event-bus.js +75 -0
  40. package/dist/server/src/event-bus.js.map +1 -0
  41. package/dist/server/src/forms.d.ts +40 -0
  42. package/dist/server/src/forms.js +148 -0
  43. package/dist/server/src/forms.js.map +1 -0
  44. package/dist/server/src/hooks.d.ts +12 -0
  45. package/dist/server/src/hooks.js +170 -0
  46. package/dist/server/src/hooks.js.map +1 -0
  47. package/dist/server/src/index.client.d.ts +12 -0
  48. package/dist/server/src/index.client.js +14 -0
  49. package/dist/server/src/index.client.js.map +1 -0
  50. package/dist/server/src/index.d.ts +88 -0
  51. package/dist/server/src/index.js +78 -0
  52. package/dist/server/src/index.js.map +1 -0
  53. package/dist/server/src/jsx-runtime/jsx-dev-runtime.d.ts +1 -0
  54. package/dist/server/src/jsx-runtime/jsx-dev-runtime.js +2 -0
  55. package/dist/server/src/jsx-runtime/jsx-dev-runtime.js.map +1 -0
  56. package/dist/server/src/jsx-runtime/jsx-runtime.d.ts +4 -0
  57. package/dist/server/src/jsx-runtime/jsx-runtime.js +41 -0
  58. package/dist/server/src/jsx-runtime/jsx-runtime.js.map +1 -0
  59. package/dist/server/src/jsx-runtime.d.ts +20 -0
  60. package/dist/server/src/jsx-runtime.js +105 -0
  61. package/dist/server/src/jsx-runtime.js.map +1 -0
  62. package/dist/server/src/lifecycle-events.d.ts +108 -0
  63. package/dist/server/src/lifecycle-events.js +177 -0
  64. package/dist/server/src/lifecycle-events.js.map +1 -0
  65. package/dist/server/src/renderComponent.d.ts +14 -0
  66. package/dist/server/src/renderComponent.js +25 -0
  67. package/dist/server/src/renderComponent.js.map +1 -0
  68. package/dist/server/src/renderer.d.ts +2 -0
  69. package/dist/server/src/renderer.js +31 -0
  70. package/dist/server/src/renderer.js.map +1 -0
  71. package/dist/server/src/router.d.ts +55 -0
  72. package/dist/server/src/router.js +166 -0
  73. package/dist/server/src/router.js.map +1 -0
  74. package/dist/server/src/server/api-router.d.ts +15 -0
  75. package/dist/server/src/server/api-router.js +111 -0
  76. package/dist/server/src/server/api-router.js.map +1 -0
  77. package/dist/server/src/server/auth.d.ts +32 -0
  78. package/dist/server/src/server/auth.js +80 -0
  79. package/dist/server/src/server/auth.js.map +1 -0
  80. package/dist/server/src/server/database.d.ts +24 -0
  81. package/dist/server/src/server/database.js +135 -0
  82. package/dist/server/src/server/database.js.map +1 -0
  83. package/dist/server/src/server/index.d.ts +127 -0
  84. package/dist/server/src/server/index.js +388 -0
  85. package/dist/server/src/server/index.js.map +1 -0
  86. package/dist/server/src/server/middleware.d.ts +11 -0
  87. package/dist/server/src/server/middleware.js +46 -0
  88. package/dist/server/src/server/middleware.js.map +1 -0
  89. package/dist/server/src/server/server.d.ts +9 -0
  90. package/dist/server/src/server/server.js +87 -0
  91. package/dist/server/src/server/server.js.map +1 -0
  92. package/dist/server/src/server/templates.d.ts +28 -0
  93. package/dist/server/src/server/templates.js +204 -0
  94. package/dist/server/src/server/templates.js.map +1 -0
  95. package/dist/server/src/server/types.d.ts +38 -0
  96. package/dist/server/src/server/types.js +4 -0
  97. package/dist/server/src/server/types.js.map +1 -0
  98. package/dist/server/src/server/utils.d.ts +70 -0
  99. package/dist/server/src/server/utils.js +156 -0
  100. package/dist/server/src/server/utils.js.map +1 -0
  101. package/dist/server/src/server/wasm.d.ts +9 -0
  102. package/dist/server/src/server/wasm.js +117 -0
  103. package/dist/server/src/server/wasm.js.map +1 -0
  104. package/dist/server/src/server-renderer.d.ts +5 -0
  105. package/dist/server/src/server-renderer.js +106 -0
  106. package/dist/server/src/server-renderer.js.map +1 -0
  107. package/dist/server/src/server-types.d.ts +42 -0
  108. package/dist/server/src/server-types.js +6 -0
  109. package/dist/server/src/server-types.js.map +1 -0
  110. package/dist/server/src/store.d.ts +41 -0
  111. package/dist/server/src/store.js +99 -0
  112. package/dist/server/src/store.js.map +1 -0
  113. package/dist/server/src/types.d.ts +19 -0
  114. package/dist/server/src/types.js +2 -0
  115. package/dist/server/src/types.js.map +1 -0
  116. package/dist/server/src/utils.d.ts +46 -0
  117. package/dist/server/src/utils.js +144 -0
  118. package/dist/server/src/utils.js.map +1 -0
  119. package/dist/server/src/vdom.d.ts +8 -0
  120. package/dist/server/src/vdom.js +22 -0
  121. package/dist/server/src/vdom.js.map +1 -0
  122. package/dist/server/src/wasm.d.ts +36 -0
  123. package/dist/server/src/wasm.js +159 -0
  124. package/dist/server/src/wasm.js.map +1 -0
  125. package/dist/server/tsconfig.server.tsbuildinfo +1 -0
  126. package/dist/server-renderer/package.json +16 -0
  127. package/dist/server-renderer.js +1 -0
  128. package/dist/server-renderer.mjs +64 -0
  129. package/dist/store/package.json +16 -0
  130. package/dist/types/package.json +16 -0
  131. package/dist/utils/package.json +16 -0
  132. package/dist/vdom/package.json +16 -0
  133. package/dist/wasm/package.json +16 -0
  134. package/dist/wasm.js +1 -0
  135. package/dist/wasm.mjs +103 -0
  136. package/package.json +14 -13
  137. package/templates/complete-app/build.js +284 -0
  138. package/templates/complete-app/package.json +40 -0
  139. package/templates/complete-app/public/styles.css +345 -0
  140. package/templates/complete-app/src/api/index.js +31 -0
  141. package/templates/complete-app/src/client.js +93 -0
  142. package/templates/complete-app/src/components/App.js +66 -0
  143. package/templates/complete-app/src/components/Footer.js +19 -0
  144. package/templates/complete-app/src/components/Header.js +38 -0
  145. package/templates/complete-app/src/pages/About.js +59 -0
  146. package/templates/complete-app/src/pages/Home.js +54 -0
  147. package/templates/complete-app/src/pages/WasmDemo.js +136 -0
  148. package/templates/complete-app/src/server.js +186 -0
  149. package/templates/complete-app/src/wasm/build.bat +16 -0
  150. package/templates/complete-app/src/wasm/build.sh +16 -0
  151. package/templates/complete-app/src/wasm/example.go +101 -0
  152. package/templates/fullstack-app/build/main.css +225 -15
  153. package/templates/fullstack-app/build/main.css.map +2 -2
  154. package/templates/fullstack-app/build/main.js +657 -372
  155. package/templates/fullstack-app/build/main.js.map +4 -4
  156. package/templates/fullstack-app/build.ts +3 -4
  157. package/templates/fullstack-app/public/styles.css +222 -15
  158. package/templates/fullstack-app/server.ts +46 -12
  159. package/templates/fullstack-app/src/components/ClientHome.tsx +0 -0
  160. package/templates/fullstack-app/src/components/ErrorBoundary.tsx +36 -0
  161. package/templates/fullstack-app/src/components/Layout.tsx +23 -26
  162. package/templates/fullstack-app/src/components/StateDemo.tsx +207 -0
  163. package/templates/fullstack-app/src/components/UserList.tsx +30 -13
  164. package/templates/fullstack-app/src/data/api.ts +173 -38
  165. package/templates/fullstack-app/src/main.tsx +88 -154
  166. package/templates/fullstack-app/src/middleware.ts +28 -0
  167. package/templates/fullstack-app/src/pages/404.tsx +28 -0
  168. package/templates/fullstack-app/src/pages/[id].tsx +0 -0
  169. package/templates/fullstack-app/src/pages/_app.tsx +11 -0
  170. package/templates/fullstack-app/src/pages/_document.tsx +25 -0
  171. package/templates/fullstack-app/src/pages/_error.tsx +45 -0
  172. package/templates/fullstack-app/src/pages/about.tsx +71 -0
  173. package/templates/fullstack-app/src/pages/api/users/[id].ts +73 -0
  174. package/templates/fullstack-app/src/pages/api/users/index.ts +43 -0
  175. package/templates/fullstack-app/src/pages/index.tsx +97 -20
  176. package/templates/fullstack-app/src/pages/users/[id].tsx +153 -0
  177. package/templates/fullstack-app/src/pages/wasm-demo.tsx +1 -0
  178. package/templates/go/build.sh +43 -43
  179. package/templates/go/example.go +99 -86
  180. package/templates/go-wasm-app/babel.config.js +8 -2
  181. package/templates/go-wasm-app/build-wasm.js +84 -84
  182. package/templates/go-wasm-app/build.config.js +62 -0
  183. package/templates/go-wasm-app/build.js +218 -0
  184. package/templates/go-wasm-app/package.json +21 -11
  185. package/templates/go-wasm-app/public/index.html +49 -53
  186. package/templates/go-wasm-app/server.js +56 -695
  187. package/templates/go-wasm-app/src/app.js +173 -0
  188. package/templates/go-wasm-app/vite.config.js +16 -5
  189. package/templates/ssr-template/client.js +54 -26
  190. package/templates/ssr-template/server.js +5 -28
  191. package/templates/ssr-template/vite.config.js +21 -5
  192. package/dist/index.d.ts +0 -1
  193. package/dist/index.js.map +0 -1
  194. package/dist/index.mjs.map +0 -1
@@ -1,709 +1,70 @@
1
- import express from 'express';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import { fileURLToPath } from 'url';
5
- import { execSync } from 'child_process';
6
- import os from 'os';
7
-
8
- // ESM __dirname equivalent
9
- const __filename = fileURLToPath(import.meta.url);
10
- const __dirname = path.dirname(__filename);
11
-
12
- // Configuration
13
- const PORT = process.env.PORT || 3000;
14
- const isProduction = process.env.NODE_ENV === 'production';
15
-
16
- // Path to WASM files
17
- const WASM_PATH = path.join(__dirname, isProduction ? 'dist' : 'public', 'wasm', 'example.wasm');
18
- const WASM_EXEC_NODE_PATH = path.join(__dirname, isProduction ? 'dist' : 'public', 'wasm', 'wasm_exec_node.js');
19
-
20
- // Express app setup
21
- const app = express();
22
-
23
- // IMPORTANT: Configure routes in correct order for Express
24
-
25
- // 1. Special route for WASM files to set correct MIME type
26
- app.get('*.wasm', (req, res, next) => {
27
- res.set('Content-Type', 'application/wasm');
28
- next();
29
- });
30
-
31
- // 2. Serve static files EXCEPT index.html (this prevents the static index.html from being served)
32
- app.use(express.static(path.join(__dirname, 'public'), {
33
- index: false // Don't serve index.html automatically
34
- }));
35
-
36
- // Setup WASM support on the server - this needs to be done before defining routes
37
- async function setupWasmSupport() {
38
- try {
39
- // Add WebAssembly support for Node.js
40
- global.WebAssembly = WebAssembly;
41
-
42
- // Check if WASM file exists
43
- if (!fs.existsSync(WASM_PATH)) {
44
- console.warn(`⚠️ WASM file not found at: ${WASM_PATH}`);
45
- }
46
-
47
- // Since we're having issues with direct WASM loading in Node.js,
48
- // use the mock implementation for template development
49
- console.log('Using mock WASM implementation for template development');
50
- return {
51
- functions: {
52
- goAdd: (a, b) => Number(a) + Number(b),
53
- goProcessData: (data) => JSON.stringify({
54
- ...data,
55
- processed: true,
56
- processor: "Mock Go WASM (Server)",
57
- timestamp: new Date().toISOString(),
58
- sum: Array.isArray(data.values) ?
59
- data.values.reduce((sum, val) => sum + Number(val), 0) : 0
60
- })
61
- }
62
- };
63
- } catch (error) {
64
- console.error('Setup WASM error:', error);
65
- // Return mock implementation as fallback
66
- return {
67
- functions: {
68
- goAdd: (a, b) => Number(a) + Number(b),
69
- goProcessData: (data) => JSON.stringify({
70
- ...data,
71
- processed: true,
72
- processor: "Mock Go WASM (Server)",
73
- error: error.message
74
- })
75
- }
76
- };
77
- }
1
+ // Server script with dual module support (ESM/CommonJS)
2
+
3
+ // Dynamically import dependencies based on module system
4
+ const isESM = typeof require === 'undefined';
5
+ let express, path, fs;
6
+
7
+ if (isESM) {
8
+ // ESM imports
9
+ import('express').then(module => express = module.default);
10
+ import('path').then(module => path = module);
11
+ import('fs').then(module => fs = module);
12
+ } else {
13
+ // CommonJS requires
14
+ express = require('express');
15
+ path = require('path');
16
+ fs = require('fs');
78
17
  }
79
18
 
80
- // Simple JSX-like renderer for server-side rendering
81
- function renderToString(component) {
82
- // Simple JSX-like rendering
83
- const renderElement = (el) => {
84
- if (typeof el === 'string' || typeof el === 'number' || el == null) {
85
- return String(el);
86
- }
87
-
88
- if (Array.isArray(el)) {
89
- return el.map(renderElement).join('');
90
- }
91
-
92
- if (!el.type) return '';
93
-
94
- if (typeof el.type === 'function') {
95
- return renderElement(el.type(el.props || {}));
96
- }
97
-
98
- const { children, ...props } = el.props || {};
99
- const attrs = Object.entries(props || {})
100
- .filter(([_, v]) => v !== undefined)
101
- .map(([k, v]) => {
102
- if (k === 'className') k = 'class';
103
- if (k === 'style' && typeof v === 'object') {
104
- const styleStr = Object.entries(v)
105
- .map(([sk, sv]) => `${sk.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`)}:${sv}`)
106
- .join(';');
107
- return `${k}="${styleStr}"`;
108
- }
109
- return `${k}="${v}"`;
110
- })
111
- .join(' ');
112
-
113
- const childrenContent = children
114
- ? (Array.isArray(children) ? children : [children]).map(renderElement).join('')
115
- : '';
116
-
117
- return `<${el.type}${attrs ? ' ' + attrs : ''}>${childrenContent}</${el.type}>`;
118
- };
119
-
120
- try {
121
- return renderElement(component);
122
- } catch (error) {
123
- console.error('Render error:', error);
124
- return `<div>Render error: ${error.message}</div>`;
125
- }
126
- }
127
-
128
- // Global WASM instance for server-side processing
129
- let serverWasmInstance = null;
130
-
131
- // Initialize server and WASM
19
+ // Wait for all imports to resolve
132
20
  async function startServer() {
133
- try {
134
- // Set up WASM support before defining routes
135
- serverWasmInstance = await setupWasmSupport();
136
-
137
- // 3. Handle root path with server-side rendering
138
- app.get('/', (req, res) => {
139
- renderPage(req, res);
140
- });
141
-
142
- // 4. Handle all other routes with server-side rendering
143
- app.get('*', (req, res) => {
144
- renderPage(req, res);
145
- });
146
-
147
- // Start the server
148
- const server = app.listen(PORT, () => {
149
- console.log(`\n🚀 Server running at http://localhost:${PORT}\n`);
150
- });
151
-
152
- return server;
153
- } catch (error) {
154
- console.error('Failed to start server:', error);
155
- throw error;
156
- }
157
- }
158
-
159
- // Function to render the page with server-side rendering
160
- function renderPage(req, res) {
161
- try {
162
- // Initial state
163
- const initialState = {
164
- path: req.path,
165
- wasmAvailable: serverWasmInstance !== null && Object.keys(serverWasmInstance.functions || {}).length > 0,
166
- ssrRendered: true,
167
- timestamp: new Date().toISOString()
168
- };
169
-
170
- // Process data with WASM if available
171
- if (serverWasmInstance && serverWasmInstance.functions.goProcessData) {
172
- try {
173
- const processDataFn = serverWasmInstance.functions.goProcessData;
174
- const processedData = processDataFn({
175
- source: 'server',
176
- timestamp: new Date().toISOString(),
177
- values: [10, 20, 30, 40, 50]
178
- });
179
-
180
- initialState.processedData = typeof processedData === 'string'
181
- ? JSON.parse(processedData)
182
- : processedData;
183
- } catch (error) {
184
- console.error('Error using WASM on server:', error);
185
- initialState.wasmError = error.message;
186
- }
187
- }
188
-
189
- // Component for SSR
190
- const App = ({ initialState }) => ({
191
- type: 'div',
192
- props: {
193
- className: 'app',
194
- children: [
195
- {
196
- type: 'header',
197
- props: {
198
- children: [
199
- { type: 'h1', props: { children: 'Frontend Hamroun + Go WebAssembly' } },
200
- { type: 'p', props: { children: 'Server-side rendered template' } },
201
- {
202
- type: 'div',
203
- props: {
204
- className: 'rendering-info',
205
- children: [
206
- {
207
- type: 'span',
208
- props: {
209
- className: 'badge active',
210
- children: 'Server Rendered'
211
- }
212
- },
213
- {
214
- type: 'span',
215
- props: {
216
- className: 'badge',
217
- children: 'Hydrated'
218
- }
219
- }
220
- ]
221
- }
222
- }
223
- ]
224
- }
225
- },
226
- {
227
- type: 'main',
228
- props: {
229
- children: [
230
- {
231
- type: 'div',
232
- props: {
233
- className: 'card',
234
- children: [
235
- { type: 'h2', props: { children: 'WebAssembly Status' } },
236
- { type: 'p', props: {
237
- children: initialState.wasmAvailable
238
- ? '✅ WebAssembly module loaded and ready'
239
- : '⚠️ WebAssembly module not available'
240
- } },
241
- initialState.wasmAvailable && {
242
- type: 'p',
243
- props: {
244
- children: [
245
- 'Available functions: ',
246
- Object.keys(serverWasmInstance?.functions || {}).join(', ')
247
- ]
248
- }
249
- },
250
- initialState.wasmError && {
251
- type: 'div',
252
- props: {
253
- className: 'error',
254
- children: initialState.wasmError
255
- }
256
- }
257
- ].filter(Boolean)
258
- }
259
- },
260
- initialState.processedData && {
261
- type: 'div',
262
- props: {
263
- className: 'card',
264
- children: [
265
- { type: 'h2', props: { children: 'WASM-Processed Data' } },
266
- { type: 'p', props: { children: 'This data was processed by Go WASM on the server:' } },
267
- {
268
- type: 'pre',
269
- props: {
270
- className: 'result',
271
- children: JSON.stringify(initialState.processedData, null, 2)
272
- }
273
- }
274
- ]
275
- }
276
- }
277
- ].filter(Boolean)
278
- }
279
- },
280
- {
281
- type: 'footer',
282
- props: {
283
- children: [
284
- {
285
- type: 'p',
286
- props: {
287
- children: [
288
- 'Built with ',
289
- {
290
- type: 'a',
291
- props: {
292
- href: 'https://github.com/hamroun/frontend-hamroun',
293
- target: '_blank',
294
- rel: 'noopener noreferrer',
295
- children: 'Frontend Hamroun'
296
- }
297
- },
298
- ' and Go WebAssembly'
299
- ]
300
- }
301
- }
302
- ]
303
- }
304
- }
305
- ]
306
- }
307
- });
308
-
309
- // Render the app
310
- const content = renderToString(App({ initialState }));
311
-
312
- // Send HTML with server-side rendered content
313
- res.send(`<!DOCTYPE html>
314
- <html lang="en">
315
- <head>
316
- <meta charset="UTF-8">
317
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
318
- <title>Frontend Hamroun + Go WebAssembly</title>
319
- <style>
320
- :root {
321
- --primary-color: #0070f3;
322
- --secondary-color: #0051cc;
323
- --background: #f9f9f9;
324
- --text-color: #333;
325
- --card-background: #fff;
326
- --border-color: #eaeaea;
327
- --error-color: #f44336;
328
- --success-color: #4caf50;
329
- }
330
-
331
- * {
332
- box-sizing: border-box;
333
- }
334
-
335
- body {
336
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
337
- background-color: var(--background);
338
- color: var(--text-color);
339
- margin: 0;
340
- padding: 0;
341
- line-height: 1.6;
342
- }
343
-
344
- .app {
345
- max-width: 900px;
346
- margin: 0 auto;
347
- padding: 20px;
348
- }
349
-
350
- header {
351
- text-align: center;
352
- margin-bottom: 2rem;
21
+ // Ensure all modules are loaded
22
+ if (!express || !path || !fs) {
23
+ if (isESM) {
24
+ express = (await import('express')).default;
25
+ path = await import('path');
26
+ fs = await import('fs');
353
27
  }
354
-
355
- header h1 {
356
- margin-bottom: 0.5rem;
357
- color: var(--primary-color);
358
- }
359
-
360
- .rendering-info {
361
- display: flex;
362
- gap: 10px;
363
- justify-content: center;
364
- margin-top: 10px;
365
- }
366
-
367
- .badge {
368
- display: inline-block;
369
- padding: 4px 8px;
370
- border-radius: 4px;
371
- background-color: #eaeaea;
372
- color: #666;
373
- font-size: 0.8rem;
374
- }
375
-
376
- .badge.active {
377
- background-color: var(--success-color);
378
- color: white;
379
- }
380
-
381
- .card {
382
- background-color: var(--card-background);
383
- border: 1px solid var(--border-color);
384
- border-radius: 8px;
385
- padding: 1.5rem;
386
- margin-bottom: 2rem;
387
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
388
- }
389
-
390
- .result {
391
- background-color: #f0f7ff;
392
- padding: 1rem;
393
- border-radius: 4px;
394
- margin-top: 1rem;
395
- white-space: pre-wrap;
396
- overflow-x: auto;
397
- font-family: monospace;
398
- font-size: 0.9rem;
399
- }
400
-
401
- .error {
402
- background-color: #ffebee;
403
- color: #c62828;
404
- padding: 0.75rem;
405
- border-radius: 4px;
406
- margin-top: 0.5rem;
407
- }
408
-
409
- footer {
410
- margin-top: 3rem;
411
- text-align: center;
412
- color: #666;
413
- padding: 1rem 0;
414
- border-top: 1px solid var(--border-color);
415
- }
416
-
417
- footer a {
418
- color: var(--primary-color);
419
- text-decoration: none;
420
- }
421
- </style>
422
- </head>
423
- <body>
424
- <div id="root">${content}</div>
425
- <script>
426
- // Store initial state from server
427
- window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};
428
-
429
- // Client-side hydration script
430
- document.addEventListener('DOMContentLoaded', function() {
431
- // Mark the app as hydrated
432
- const badges = document.querySelectorAll('.badge');
433
- if (badges.length >= 2) {
434
- badges[0].classList.remove('active');
435
- badges[1].classList.add('active');
436
- }
437
-
438
- // Load WebAssembly if available
439
- if (typeof WebAssembly !== 'undefined') {
440
- const wasmExecScript = document.createElement('script');
441
- wasmExecScript.src = '/wasm/wasm_exec.js';
442
- wasmExecScript.onload = loadWasmModule;
443
- document.head.appendChild(wasmExecScript);
444
- }
445
-
446
- function loadWasmModule() {
447
- if (typeof Go !== 'function') return;
448
-
449
- const go = new Go();
450
- fetch('/wasm/example.wasm')
451
- .then(response => response.arrayBuffer())
452
- .then(bytes => WebAssembly.instantiate(bytes, go.importObject))
453
- .then(result => {
454
- // Run the Go instance
455
- go.run(result.instance);
456
-
457
- // Add demo component when WebAssembly is loaded
458
- addWasmDemo();
459
- })
460
- .catch(err => {
461
- console.error('Error loading WebAssembly:', err);
462
- });
463
- }
464
-
465
- function addWasmDemo() {
466
- if (typeof window.goAdd !== 'function') return;
467
-
468
- const mainElement = document.querySelector('main');
469
- const demoCard = document.createElement('div');
470
- demoCard.className = 'card';
471
- demoCard.innerHTML = \`
472
- <h2>Client-Side WebAssembly Demo</h2>
473
- <div>
474
- <p>Try using the WebAssembly module in the browser:</p>
475
- <div style="display:flex;gap:8px;align-items:center;margin-bottom:16px;">
476
- <input type="number" id="num1" value="10" style="padding:8px;width:80px;">
477
- <span>+</span>
478
- <input type="number" id="num2" value="5" style="padding:8px;width:80px;">
479
- <button onclick="calculateSum()" style="background-color:var(--primary-color);color:white;border:none;padding:8px 16px;border-radius:4px;cursor:pointer;">Calculate</button>
480
- </div>
481
- <div id="result"></div>
482
- </div>
483
- \`;
484
-
485
- mainElement.appendChild(demoCard);
486
-
487
- // Add calculation function
488
- window.calculateSum = function() {
489
- const num1 = parseInt(document.getElementById('num1').value) || 0;
490
- const num2 = parseInt(document.getElementById('num2').value) || 0;
491
-
492
- try {
493
- // Call Go function
494
- const sum = window.goAdd(num1, num2);
495
- document.getElementById('result').innerHTML =
496
- \`<p>Result: <strong>\${sum}</strong> (calculated by Go WebAssembly)</p>\`;
497
- } catch (error) {
498
- document.getElementById('result').innerHTML =
499
- \`<p class="error">Error: \${error.message}</p>\`;
500
- }
501
- };
502
- }
503
- });
504
- </script>
505
- </body>
506
- </html>`);
507
- } catch (error) {
508
- console.error('Server rendering error:', error);
509
- res.status(500).send(`
510
- <h1>Server Error</h1>
511
- <p>${error.message}</p>
512
- <pre>${error.stack}</pre>
513
- `);
514
- }
515
- }
516
-
517
- // Configure Express file serving
518
- app.get('/wasm/wasm_exec.js', (req, res) => {
519
- res.sendFile(WASM_EXEC_NODE_PATH);
520
- });
521
-
522
- app.get('/wasm/example.wasm', (req, res) => {
523
- res.sendFile(WASM_PATH);
524
- });
525
-
526
- // Dynamic Go code generation endpoint
527
- app.post('/api/generate-wasm', async (req, res) => {
528
- try {
529
- const { functionName, functionBody, inputTypes, returnType } = req.body;
530
-
531
- if (!functionName || !functionBody) {
532
- return res.status(400).json({ error: 'Missing required fields: functionName and functionBody' });
533
- }
534
-
535
- // Create Go source directory if it doesn't exist
536
- const goSourceDir = path.join(__dirname, 'src', 'wasm');
537
- if (!fs.existsSync(goSourceDir)) {
538
- fs.mkdirSync(goSourceDir, { recursive: true });
539
- }
540
-
541
- // Create the Go file with the user-provided function
542
- const goFilePath = path.join(goSourceDir, `${functionName}.go`);
543
-
544
- // Generate Go code with the user's function
545
- const goCode = generateGoCode(functionName, functionBody, inputTypes, returnType);
546
-
547
- // Write Go file
548
- fs.writeFileSync(goFilePath, goCode);
549
- console.log(`Created Go file: ${goFilePath}`);
550
-
551
- // Build the WASM module
552
- const wasmOutputDir = path.join(__dirname, 'public', 'wasm');
553
- if (!fs.existsSync(wasmOutputDir)) {
554
- fs.mkdirSync(wasmOutputDir, { recursive: true });
555
- }
556
-
557
- const wasmFilePath = path.join(wasmOutputDir, `${functionName}.wasm`);
558
-
559
- // Import the build function from build-wasm.js
560
- const { buildGoFile } = await import('./build-wasm.js');
561
-
562
- // Build the Go file to WASM
563
- const result = await buildGoFile(goFilePath, wasmFilePath);
564
-
565
- if (result.success) {
566
- res.json({
567
- success: true,
568
- message: 'WebAssembly module generated successfully',
569
- function: functionName,
570
- wasmPath: `/wasm/${functionName}.wasm`,
571
- jsUsage: `
572
- // Load and use the WASM module:
573
- const wasm = await loadGoWasm('/wasm/${functionName}.wasm');
574
- const result = wasm.functions.${functionName}(...args);
575
- `
576
- });
577
- } else {
578
- res.status(500).json({
579
- success: false,
580
- error: result.error,
581
- message: 'Failed to build WebAssembly module'
582
- });
583
- }
584
- } catch (error) {
585
- console.error('Error generating WASM:', error);
586
- res.status(500).json({ error: error.message });
587
28
  }
588
- });
589
29
 
590
- // Helper function to generate Go code
591
- function generateGoCode(functionName, functionBody, inputTypes = [], returnType = 'int') {
592
- // Default input types to interface{} (any) if not provided
593
- const goInputTypes = inputTypes.length > 0
594
- ? inputTypes.map(t => mapJsTypeToGo(t)).join(', ')
595
- : 'interface{}, interface{}';
30
+ const app = express();
31
+ const PORT = process.env.PORT || 3000;
596
32
 
597
- // Default return type to int if not provided
598
- const goReturnType = mapJsTypeToGo(returnType);
33
+ // Serve static files from public directory
34
+ app.use(express.static(path.join(__dirname, 'public')));
35
+
36
+ // Special handling for wasm files to ensure correct MIME type
37
+ app.get('*.wasm', (req, res, next) => {
38
+ res.set('Content-Type', 'application/wasm');
39
+ next();
40
+ });
599
41
 
600
- return `//go:build js && wasm
601
- // +build js,wasm
602
-
603
- package main
604
-
605
- import (
606
- "encoding/json"
607
- "fmt"
608
- "syscall/js"
609
- )
610
-
611
- // Generated ${functionName} function from template
612
- func ${functionName}(this js.Value, args []js.Value) interface{} {
613
- // Validate input arguments
614
- if len(args) < ${inputTypes.length || 1} {
615
- return js.ValueOf("Error: Not enough arguments")
616
- }
617
-
618
- // Implementation
619
- ${functionBody}
620
- }
621
-
622
- // Example Go function to be called from JavaScript
623
- func goAdd(this js.Value, args []js.Value) interface{} {
624
- if len(args) != 2 {
625
- return js.ValueOf("Error: Expected two arguments")
626
- }
627
-
628
- a := args[0].Int()
629
- b := args[1].Int()
630
- return js.ValueOf(a + b)
42
+ // Always return index.html for client-side routing
43
+ app.get('*', (req, res) => {
44
+ res.sendFile(path.join(__dirname, 'public', 'index.html'));
45
+ });
46
+
47
+ // Start the server
48
+ app.listen(PORT, () => {
49
+ console.log(`
50
+ ┌────────────────────────────────────────────────────┐
51
+ │ │
52
+ │ Go WASM Demo Server running on port ${PORT} │
53
+ │ │
54
+ │ Local: http://localhost:${PORT}
55
+ │ │
56
+ └────────────────────────────────────────────────────┘
57
+ `);
58
+ });
631
59
  }
632
60
 
633
- // Process complex data in Go
634
- func goProcessData(this js.Value, args []js.Value) interface{} {
635
- if len(args) == 0 {
636
- return js.ValueOf("Error: Expected at least one argument")
637
- }
638
-
639
- // Get input data
640
- data := args[0]
641
- if data.Type() != js.TypeObject {
642
- return js.ValueOf("Error: Expected JSON object")
643
- }
644
-
645
- // Convert JS object to Go map
646
- jsonStr := js.Global().Get("JSON").Call("stringify", data).String()
647
- var inputMap map[string]interface{}
648
- if err := json.Unmarshal([]byte(jsonStr), &inputMap); err != nil {
649
- return js.ValueOf(fmt.Sprintf("Error parsing JSON: %s", err.Error()))
650
- }
61
+ startServer();
651
62
 
652
- // Add new fields
653
- inputMap["processed"] = true
654
- inputMap["processor"] = "Go WASM"
63
+ // Module export for both ESM and CommonJS
64
+ const server = { startServer };
655
65
 
656
- // Add some computed fields
657
- if values, ok := inputMap["values"].([]interface{}); ok {
658
- sum := 0.0
659
- for _, v := range values {
660
- if num, ok := v.(float64); ok {
661
- sum += num
662
- }
663
- }
664
- inputMap["sum"] = sum
665
- }
666
-
667
- // Convert back to JS
668
- resultJSON, err := json.Marshal(inputMap)
669
- if err != nil {
670
- return js.ValueOf(fmt.Sprintf("Error generating JSON: %s", err.Error()))
671
- }
672
-
673
- return js.ValueOf(string(resultJSON))
674
- }
675
-
676
- func main() {
677
- fmt.Println("Go WASM Module initialized")
678
-
679
- // Register functions to be callable from JavaScript
680
- js.Global().Set("goAdd", js.FuncOf(goAdd))
681
- js.Global().Set("goProcessData", js.FuncOf(goProcessData))
682
- js.Global().Set("${functionName}", js.FuncOf(${functionName}))
683
-
684
- // Keep the program running
685
- <-make(chan bool)
686
- }
687
- `;
688
- }
689
-
690
- // Map JavaScript types to Go types
691
- function mapJsTypeToGo(jsType) {
692
- const typeMap = {
693
- 'string': 'string',
694
- 'number': 'float64',
695
- 'integer': 'int',
696
- 'boolean': 'bool',
697
- 'object': 'map[string]interface{}',
698
- 'array': '[]interface{}',
699
- 'any': 'interface{}'
700
- };
701
-
702
- return typeMap[jsType] || 'interface{}';
66
+ if (typeof module !== 'undefined' && module.exports) {
67
+ module.exports = server;
703
68
  }
704
69
 
705
- // Start the server
706
- startServer().catch(err => {
707
- console.error('Failed to start server:', err);
708
- process.exit(1);
709
- });
70
+ export default server;