frontend-hamroun 1.2.75 → 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.
- package/dist/batch/package.json +16 -0
- package/dist/client-router/package.json +16 -0
- package/dist/component/package.json +16 -0
- package/dist/context/package.json +16 -0
- package/dist/event-bus/package.json +16 -0
- package/dist/forms/package.json +16 -0
- package/dist/hooks/package.json +16 -0
- package/dist/jsx-runtime/package.json +16 -0
- package/dist/lifecycle-events/package.json +16 -0
- package/dist/package.json +71 -0
- package/dist/render-component/package.json +16 -0
- package/dist/renderer/package.json +16 -0
- package/dist/router/package.json +16 -0
- package/dist/server/package.json +17 -0
- package/dist/server/src/client-router.d.ts +60 -0
- package/dist/server/src/client-router.js +210 -0
- package/dist/server/src/client-router.js.map +1 -0
- package/dist/server/src/component.js +1 -1
- package/dist/server/src/event-bus.d.ts +23 -0
- package/dist/server/src/event-bus.js +75 -0
- package/dist/server/src/event-bus.js.map +1 -0
- package/dist/server/src/forms.d.ts +40 -0
- package/dist/server/src/forms.js +148 -0
- package/dist/server/src/forms.js.map +1 -0
- package/dist/server/src/hooks.js +2 -2
- package/dist/server/src/index.js +19 -11
- package/dist/server/src/lifecycle-events.d.ts +108 -0
- package/dist/server/src/lifecycle-events.js +177 -0
- package/dist/server/src/lifecycle-events.js.map +1 -0
- package/dist/server/src/renderComponent.js +1 -1
- package/dist/server/src/renderer.js +3 -3
- package/dist/server/src/router.d.ts +55 -0
- package/dist/server/src/router.js +166 -0
- package/dist/server/src/router.js.map +1 -0
- package/dist/server/src/server/index.d.ts +75 -2
- package/dist/server/src/server/index.js +224 -8
- package/dist/server/src/server/index.js.map +1 -1
- package/dist/server/src/server/server.js +1 -1
- package/dist/server/src/server/templates.d.ts +28 -0
- package/dist/server/src/server/templates.js +204 -0
- package/dist/server/src/server/templates.js.map +1 -0
- package/dist/server/src/server/utils.d.ts +70 -0
- package/dist/server/src/server/utils.js +156 -0
- package/dist/server/src/server/utils.js.map +1 -0
- package/dist/server/src/server-renderer.js +1 -1
- package/dist/server/src/store.d.ts +41 -0
- package/dist/server/src/store.js +99 -0
- package/dist/server/src/store.js.map +1 -0
- package/dist/server/src/utils.d.ts +46 -0
- package/dist/server/src/utils.js +144 -0
- package/dist/server/src/utils.js.map +1 -0
- package/dist/server/tsconfig.server.tsbuildinfo +1 -1
- package/dist/server-renderer/package.json +16 -0
- package/dist/store/package.json +16 -0
- package/dist/types/package.json +16 -0
- package/dist/utils/package.json +16 -0
- package/dist/vdom/package.json +16 -0
- package/dist/wasm/package.json +16 -0
- package/package.json +14 -13
- package/templates/complete-app/build.js +284 -0
- package/templates/complete-app/package.json +40 -0
- package/templates/complete-app/public/styles.css +345 -0
- package/templates/complete-app/src/api/index.js +31 -0
- package/templates/complete-app/src/client.js +93 -0
- package/templates/complete-app/src/components/App.js +66 -0
- package/templates/complete-app/src/components/Footer.js +19 -0
- package/templates/complete-app/src/components/Header.js +38 -0
- package/templates/complete-app/src/pages/About.js +59 -0
- package/templates/complete-app/src/pages/Home.js +54 -0
- package/templates/complete-app/src/pages/WasmDemo.js +136 -0
- package/templates/complete-app/src/server.js +186 -0
- package/templates/complete-app/src/wasm/build.bat +16 -0
- package/templates/complete-app/src/wasm/build.sh +16 -0
- package/templates/complete-app/src/wasm/example.go +101 -0
- package/templates/fullstack-app/build/main.css +225 -15
- package/templates/fullstack-app/build/main.css.map +2 -2
- package/templates/fullstack-app/build/main.js +657 -372
- package/templates/fullstack-app/build/main.js.map +4 -4
- package/templates/fullstack-app/build.ts +3 -4
- package/templates/fullstack-app/public/styles.css +222 -15
- package/templates/fullstack-app/server.ts +46 -12
- package/templates/fullstack-app/src/components/ClientHome.tsx +0 -0
- package/templates/fullstack-app/src/components/ErrorBoundary.tsx +36 -0
- package/templates/fullstack-app/src/components/Layout.tsx +23 -26
- package/templates/fullstack-app/src/components/StateDemo.tsx +207 -0
- package/templates/fullstack-app/src/components/UserList.tsx +30 -13
- package/templates/fullstack-app/src/data/api.ts +173 -38
- package/templates/fullstack-app/src/main.tsx +88 -154
- package/templates/fullstack-app/src/middleware.ts +28 -0
- package/templates/fullstack-app/src/pages/404.tsx +28 -0
- package/templates/fullstack-app/src/pages/[id].tsx +0 -0
- package/templates/fullstack-app/src/pages/_app.tsx +11 -0
- package/templates/fullstack-app/src/pages/_document.tsx +25 -0
- package/templates/fullstack-app/src/pages/_error.tsx +45 -0
- package/templates/fullstack-app/src/pages/about.tsx +71 -0
- package/templates/fullstack-app/src/pages/api/users/[id].ts +73 -0
- package/templates/fullstack-app/src/pages/api/users/index.ts +43 -0
- package/templates/fullstack-app/src/pages/index.tsx +97 -20
- package/templates/fullstack-app/src/pages/users/[id].tsx +153 -0
- package/templates/fullstack-app/src/pages/wasm-demo.tsx +1 -0
- package/templates/go/example.go +99 -86
- package/templates/go-wasm-app/babel.config.js +8 -2
- package/templates/go-wasm-app/build.config.js +62 -0
- package/templates/go-wasm-app/build.js +218 -0
- package/templates/go-wasm-app/package.json +21 -12
- package/templates/go-wasm-app/server.js +59 -510
- package/templates/go-wasm-app/src/app.js +173 -0
- package/templates/go-wasm-app/vite.config.js +16 -5
- package/templates/ssr-template/client.js +54 -26
- package/templates/ssr-template/server.js +5 -28
- package/templates/ssr-template/vite.config.js +21 -5
- package/dist/server/wasm.d.ts +0 -7
- package/dist/wasm.d.ts +0 -37
@@ -1,33 +1,110 @@
|
|
1
|
-
import { jsx } from 'frontend-hamroun';
|
2
|
-
import Layout from '../components/Layout';
|
1
|
+
import { jsx, useState, useEffect, batchUpdates } from 'frontend-hamroun';
|
3
2
|
import UserList from '../components/UserList';
|
3
|
+
import StateDemo from '../components/StateDemo';
|
4
|
+
import { ErrorBoundary } from '../components/ErrorBoundary';
|
4
5
|
import { UserApi } from '../data/api';
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
// Home Page Component with Server Side Props
|
8
|
+
export default function HomePage({ users, posts, initialState }) {
|
9
|
+
const [state, setState] = useState(initialState || {});
|
10
|
+
const [refreshTrigger, setRefreshTrigger] = useState(0);
|
11
|
+
|
12
|
+
// Fetch data when refresh is triggered
|
13
|
+
useEffect(() => {
|
14
|
+
if (refreshTrigger === 0) return; // Skip initial render
|
15
|
+
|
16
|
+
async function fetchData() {
|
17
|
+
try {
|
18
|
+
const [users, posts] = await Promise.all([
|
19
|
+
UserApi.getAll(),
|
20
|
+
UserApi.getPosts()
|
21
|
+
]);
|
22
|
+
|
23
|
+
// Use batch updates for efficiency
|
24
|
+
batchUpdates(() => {
|
25
|
+
setState(prev => ({
|
26
|
+
...prev,
|
27
|
+
data: {
|
28
|
+
...prev.data,
|
29
|
+
users,
|
30
|
+
posts
|
31
|
+
},
|
32
|
+
lastUpdate: new Date().toISOString()
|
33
|
+
}));
|
34
|
+
});
|
35
|
+
} catch (error) {
|
36
|
+
console.error('Error fetching data:', error);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
fetchData();
|
41
|
+
}, [refreshTrigger]);
|
42
|
+
|
43
|
+
const handleRefresh = () => {
|
44
|
+
setRefreshTrigger(t => t + 1);
|
45
|
+
};
|
46
|
+
|
47
|
+
return (
|
8
48
|
<div className="max-w-4xl mx-auto py-8">
|
9
|
-
<h1 className="text-3xl font-bold text-blue-600 mb-6">
|
49
|
+
<h1 className="text-3xl font-bold text-blue-600 mb-6">
|
50
|
+
Welcome to your Next-style Frontend Hamroun application!
|
51
|
+
</h1>
|
10
52
|
|
11
|
-
<div className="
|
12
|
-
<
|
13
|
-
|
53
|
+
<div className="mb-8">
|
54
|
+
<button
|
55
|
+
className="mb-4 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
|
56
|
+
onClick={handleRefresh}
|
57
|
+
>
|
58
|
+
Refresh Data
|
59
|
+
</button>
|
60
|
+
|
61
|
+
<div className="bg-blue-50 p-4 rounded-lg border border-blue-100 mb-6">
|
62
|
+
<p className="text-blue-700">
|
63
|
+
Last updated: {state.lastUpdate || 'Never'}
|
64
|
+
</p>
|
65
|
+
</div>
|
14
66
|
</div>
|
15
67
|
|
16
|
-
<
|
68
|
+
<ErrorBoundary>
|
69
|
+
<div className="bg-white shadow-lg rounded-lg p-6 mb-8">
|
70
|
+
<h2 className="text-xl font-semibold text-gray-800 mb-4">User List</h2>
|
71
|
+
<UserList users={users || state.data?.users || []} />
|
72
|
+
</div>
|
73
|
+
</ErrorBoundary>
|
74
|
+
|
75
|
+
<ErrorBoundary>
|
76
|
+
<StateDemo />
|
77
|
+
</ErrorBoundary>
|
78
|
+
|
79
|
+
<div className="bg-gray-50 rounded-lg p-6 border border-gray-200 mt-8">
|
17
80
|
<h3 className="text-lg font-medium text-gray-700 mb-3">Application State</h3>
|
18
81
|
<pre className="overflow-auto p-4 bg-gray-100 rounded-md text-sm text-gray-800">
|
19
|
-
{JSON.stringify(
|
82
|
+
{JSON.stringify({ users, posts, ...state }, null, 2)}
|
20
83
|
</pre>
|
21
84
|
</div>
|
22
85
|
</div>
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
// Static method to fetch initial data for this page
|
27
|
-
HomePage.getInitialData = async () => {
|
28
|
-
return {
|
29
|
-
users: await UserApi.getAll()
|
30
|
-
};
|
31
|
-
};
|
86
|
+
);
|
87
|
+
}
|
32
88
|
|
33
|
-
|
89
|
+
// Server-side data fetching (Next.js style)
|
90
|
+
export async function getServerSideProps() {
|
91
|
+
try {
|
92
|
+
const users = await UserApi.getAll();
|
93
|
+
const posts = await UserApi.getPosts();
|
94
|
+
|
95
|
+
return {
|
96
|
+
props: {
|
97
|
+
users,
|
98
|
+
posts
|
99
|
+
}
|
100
|
+
};
|
101
|
+
} catch (error) {
|
102
|
+
console.error('Error fetching initial data:', error);
|
103
|
+
return {
|
104
|
+
props: {
|
105
|
+
users: [],
|
106
|
+
posts: []
|
107
|
+
}
|
108
|
+
};
|
109
|
+
}
|
110
|
+
}
|
@@ -0,0 +1,153 @@
|
|
1
|
+
import { jsx, useState, useEffect } from 'frontend-hamroun';
|
2
|
+
import { UserApi } from '../../data/api';
|
3
|
+
|
4
|
+
export default function UserDetail({ user, posts, initialState }) {
|
5
|
+
// State for client-side data fetching when needed
|
6
|
+
const [userData, setUserData] = useState(user);
|
7
|
+
const [userPosts, setUserPosts] = useState(posts || []);
|
8
|
+
const [loading, setLoading] = useState(false);
|
9
|
+
const [error, setError] = useState(null);
|
10
|
+
|
11
|
+
// Get user ID from route params
|
12
|
+
const { id } = initialState?.params || {};
|
13
|
+
|
14
|
+
// Fetch user data if not provided from server
|
15
|
+
useEffect(() => {
|
16
|
+
if (!userData && id) {
|
17
|
+
setLoading(true);
|
18
|
+
|
19
|
+
Promise.all([
|
20
|
+
UserApi.getById(id),
|
21
|
+
UserApi.getPosts(id)
|
22
|
+
])
|
23
|
+
.then(([userData, postsData]) => {
|
24
|
+
setUserData(userData);
|
25
|
+
setUserPosts(postsData);
|
26
|
+
setLoading(false);
|
27
|
+
})
|
28
|
+
.catch(err => {
|
29
|
+
console.error('Error fetching user data:', err);
|
30
|
+
setError(err.message || 'Failed to load user data');
|
31
|
+
setLoading(false);
|
32
|
+
});
|
33
|
+
}
|
34
|
+
}, [userData, id]);
|
35
|
+
|
36
|
+
if (loading) {
|
37
|
+
return (
|
38
|
+
<div className="max-w-4xl mx-auto p-4">
|
39
|
+
<div className="animate-pulse rounded-md bg-gray-100 p-8">
|
40
|
+
<div className="h-8 bg-gray-200 rounded w-1/4 mb-4"></div>
|
41
|
+
<div className="h-4 bg-gray-200 rounded w-1/2 mb-2"></div>
|
42
|
+
<div className="h-4 bg-gray-200 rounded w-3/4 mb-4"></div>
|
43
|
+
<div className="h-40 bg-gray-200 rounded mb-4"></div>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
);
|
47
|
+
}
|
48
|
+
|
49
|
+
if (error) {
|
50
|
+
return (
|
51
|
+
<div className="max-w-4xl mx-auto p-4">
|
52
|
+
<div className="rounded-md bg-red-50 p-4 border border-red-200">
|
53
|
+
<h2 className="text-lg font-bold text-red-700">Error Loading User</h2>
|
54
|
+
<p className="text-red-600">{error}</p>
|
55
|
+
</div>
|
56
|
+
</div>
|
57
|
+
);
|
58
|
+
}
|
59
|
+
|
60
|
+
if (!userData) {
|
61
|
+
return (
|
62
|
+
<div className="max-w-4xl mx-auto p-4">
|
63
|
+
<div className="rounded-md bg-yellow-50 p-4 border border-yellow-200">
|
64
|
+
<h2 className="text-lg font-bold text-yellow-700">User Not Found</h2>
|
65
|
+
<p className="text-yellow-600">Could not find user with ID: {id}</p>
|
66
|
+
<a href="/users" className="text-blue-600 hover:underline mt-2 block">
|
67
|
+
Back to Users List
|
68
|
+
</a>
|
69
|
+
</div>
|
70
|
+
</div>
|
71
|
+
);
|
72
|
+
}
|
73
|
+
|
74
|
+
return (
|
75
|
+
<div className="max-w-4xl mx-auto p-4">
|
76
|
+
<div className="bg-white shadow-lg rounded-lg p-6 mb-6">
|
77
|
+
<h1 className="text-2xl font-bold text-gray-800 mb-4">{userData.name}</h1>
|
78
|
+
<div className="user-info mb-6">
|
79
|
+
<p className="text-gray-600">
|
80
|
+
<span className="font-bold">ID:</span> {userData.id}
|
81
|
+
</p>
|
82
|
+
<p className="text-gray-600">
|
83
|
+
<span className="font-bold">Email:</span> {userData.email}
|
84
|
+
</p>
|
85
|
+
</div>
|
86
|
+
|
87
|
+
<a href="/users" className="text-blue-600 hover:underline">
|
88
|
+
Back to Users List
|
89
|
+
</a>
|
90
|
+
</div>
|
91
|
+
|
92
|
+
{userPosts && userPosts.length > 0 ? (
|
93
|
+
<div className="bg-white shadow-lg rounded-lg p-6">
|
94
|
+
<h2 className="text-xl font-bold text-gray-800 mb-4">Posts by {userData.name}</h2>
|
95
|
+
<div className="space-y-4">
|
96
|
+
{userPosts.map(post => (
|
97
|
+
<div key={post.id} className="border-b pb-4">
|
98
|
+
<h3 className="text-lg font-semibold">{post.title}</h3>
|
99
|
+
<p className="text-gray-600">{post.content}</p>
|
100
|
+
</div>
|
101
|
+
))}
|
102
|
+
</div>
|
103
|
+
</div>
|
104
|
+
) : (
|
105
|
+
<div className="bg-white shadow-lg rounded-lg p-6">
|
106
|
+
<h2 className="text-xl font-bold text-gray-800 mb-4">Posts by {userData.name}</h2>
|
107
|
+
<p className="text-gray-500 italic">No posts found for this user.</p>
|
108
|
+
</div>
|
109
|
+
)}
|
110
|
+
</div>
|
111
|
+
);
|
112
|
+
}
|
113
|
+
|
114
|
+
// Next.js style server-side data fetching
|
115
|
+
export async function getServerSideProps({ params }) {
|
116
|
+
try {
|
117
|
+
const userId = params.id;
|
118
|
+
|
119
|
+
// Parallel data fetching
|
120
|
+
const [user, posts] = await Promise.all([
|
121
|
+
UserApi.getById(parseInt(userId)),
|
122
|
+
UserApi.getPosts(parseInt(userId))
|
123
|
+
]);
|
124
|
+
|
125
|
+
// Handle user not found
|
126
|
+
if (!user) {
|
127
|
+
return {
|
128
|
+
notFound: true
|
129
|
+
};
|
130
|
+
}
|
131
|
+
|
132
|
+
return {
|
133
|
+
props: {
|
134
|
+
user,
|
135
|
+
posts
|
136
|
+
}
|
137
|
+
};
|
138
|
+
} catch (error) {
|
139
|
+
console.error(`Error fetching user ${params.id}:`, error);
|
140
|
+
|
141
|
+
// Pass the error for client-side handling
|
142
|
+
return {
|
143
|
+
props: {
|
144
|
+
error: {
|
145
|
+
message: error.message,
|
146
|
+
status: error.status || 500
|
147
|
+
},
|
148
|
+
user: null,
|
149
|
+
posts: []
|
150
|
+
}
|
151
|
+
};
|
152
|
+
}
|
153
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
// This file will be removed as it contains WASM functionality
|
package/templates/go/example.go
CHANGED
@@ -9,10 +9,10 @@ import (
|
|
9
9
|
"syscall/js"
|
10
10
|
)
|
11
11
|
|
12
|
-
//
|
12
|
+
// Basic arithmetic functions
|
13
13
|
func add(this js.Value, args []js.Value) interface{} {
|
14
14
|
if len(args) != 2 {
|
15
|
-
return js.ValueOf("Error:
|
15
|
+
return js.ValueOf("Error: add requires 2 arguments")
|
16
16
|
}
|
17
17
|
|
18
18
|
a := args[0].Int()
|
@@ -20,118 +20,131 @@ func add(this js.Value, args []js.Value) interface{} {
|
|
20
20
|
return js.ValueOf(a + b)
|
21
21
|
}
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
}
|
23
|
+
func subtract(this js.Value, args []js.Value) interface{} {
|
24
|
+
if len(args) != 2 {
|
25
|
+
return js.ValueOf("Error: subtract requires 2 arguments")
|
26
|
+
}
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
return
|
28
|
+
a := args[0].Int()
|
29
|
+
b := args[1].Int()
|
30
|
+
return js.ValueOf(a - b)
|
31
31
|
}
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
if err != nil {
|
37
|
-
return js.ValueOf("Error: Failed to marshal JSON")
|
33
|
+
func multiply(this js.Value, args []js.Value) interface{} {
|
34
|
+
if len(args) != 2 {
|
35
|
+
return js.ValueOf("Error: multiply requires 2 arguments")
|
38
36
|
}
|
39
|
-
return stringToJS(string(data))
|
40
|
-
}
|
41
37
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
var result interface{}
|
46
|
-
err := json.Unmarshal([]byte(jsonStr), &result)
|
47
|
-
return result, err
|
38
|
+
a := args[0].Int()
|
39
|
+
b := args[1].Int()
|
40
|
+
return js.ValueOf(a * b)
|
48
41
|
}
|
49
42
|
|
50
|
-
//
|
51
|
-
func
|
52
|
-
if len(args)
|
53
|
-
return js.ValueOf("
|
43
|
+
// String operations
|
44
|
+
func concat(this js.Value, args []js.Value) interface{} {
|
45
|
+
if len(args) < 1 {
|
46
|
+
return js.ValueOf("")
|
54
47
|
}
|
55
48
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
return js.ValueOf("Error: Expected JSON object")
|
60
|
-
}
|
61
|
-
|
62
|
-
// Convert JS object to Go map
|
63
|
-
jsonStr := js.Global().Get("JSON").Call("stringify", data).String()
|
64
|
-
var inputMap map[string]interface{}
|
65
|
-
if err := json.Unmarshal([]byte(jsonStr), &inputMap); err != nil {
|
66
|
-
return js.ValueOf(fmt.Sprintf("Error parsing JSON: %s", err.Error()))
|
49
|
+
result := ""
|
50
|
+
for _, arg := range args {
|
51
|
+
result += arg.String()
|
67
52
|
}
|
53
|
+
return js.ValueOf(result)
|
54
|
+
}
|
68
55
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
// Add some computed fields
|
74
|
-
if values, ok := inputMap["values"].([]interface{}); ok {
|
75
|
-
sum := 0.0
|
76
|
-
for _, v := range values {
|
77
|
-
if num, ok := v.(float64); ok {
|
78
|
-
sum += num
|
79
|
-
}
|
80
|
-
}
|
81
|
-
inputMap["sum"] = sum
|
56
|
+
// JSON operations
|
57
|
+
func parseJSON(this js.Value, args []js.Value) interface{} {
|
58
|
+
if len(args) != 1 {
|
59
|
+
return js.ValueOf("Error: parseJSON requires 1 argument")
|
82
60
|
}
|
83
61
|
|
84
|
-
|
85
|
-
|
62
|
+
jsonStr := args[0].String()
|
63
|
+
var result interface{}
|
64
|
+
err := json.Unmarshal([]byte(jsonStr), &result)
|
86
65
|
if err != nil {
|
87
|
-
return js.ValueOf(
|
66
|
+
return js.ValueOf("Error parsing JSON: " + err.Error())
|
88
67
|
}
|
89
68
|
|
90
|
-
|
69
|
+
// Convert result to JS value
|
70
|
+
return mapToJSValue(result)
|
91
71
|
}
|
92
72
|
|
93
|
-
// Helper functions
|
94
|
-
func
|
95
|
-
|
96
|
-
|
97
|
-
|
73
|
+
// Helper functions for JSON conversion
|
74
|
+
func mapToJSValue(value interface{}) js.Value {
|
75
|
+
switch v := value.(type) {
|
76
|
+
case map[string]interface{}:
|
77
|
+
result := js.Global().Get("Object").New()
|
78
|
+
for key, val := range v {
|
79
|
+
result.Set(key, mapToJSValue(val))
|
98
80
|
}
|
99
|
-
return
|
100
|
-
}
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
return nil
|
81
|
+
return result
|
82
|
+
case []interface{}:
|
83
|
+
result := js.Global().Get("Array").New(len(v))
|
84
|
+
for i, val := range v {
|
85
|
+
result.SetIndex(i, mapToJSValue(val))
|
105
86
|
}
|
106
|
-
return
|
107
|
-
|
87
|
+
return result
|
88
|
+
case string:
|
89
|
+
return js.ValueOf(v)
|
90
|
+
case float64:
|
91
|
+
return js.ValueOf(v)
|
92
|
+
case bool:
|
93
|
+
return js.ValueOf(v)
|
94
|
+
case nil:
|
95
|
+
return js.ValueOf(nil)
|
96
|
+
default:
|
97
|
+
return js.ValueOf(fmt.Sprint(v))
|
98
|
+
}
|
99
|
+
}
|
108
100
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
101
|
+
// Special utility functions for string handling between Go and JS
|
102
|
+
func __stringToGo(this js.Value, args []js.Value) interface{} {
|
103
|
+
if len(args) != 1 {
|
104
|
+
return js.ValueOf(-1)
|
105
|
+
}
|
106
|
+
return args[0] // Pass through
|
107
|
+
}
|
116
108
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
109
|
+
func __stringFromGo(this js.Value, args []js.Value) interface{} {
|
110
|
+
if len(args) != 1 {
|
111
|
+
return js.ValueOf("")
|
112
|
+
}
|
113
|
+
return args[0] // Pass through
|
114
|
+
}
|
115
|
+
|
116
|
+
func __objectToGo(this js.Value, args []js.Value) interface{} {
|
117
|
+
if len(args) != 1 {
|
118
|
+
return js.ValueOf(-1)
|
119
|
+
}
|
120
|
+
return args[0] // Pass through
|
121
|
+
}
|
122
|
+
|
123
|
+
func __objectFromGo(this js.Value, args []js.Value) interface{} {
|
124
|
+
if len(args) != 1 {
|
125
|
+
return js.ValueOf("")
|
126
|
+
}
|
127
|
+
return args[0] // Pass through
|
123
128
|
}
|
124
129
|
|
125
130
|
func main() {
|
126
|
-
fmt.Println("Go
|
131
|
+
fmt.Println("Go WebAssembly module initialized")
|
127
132
|
|
128
|
-
// Register functions to
|
133
|
+
// Register functions to make available to JavaScript
|
129
134
|
js.Global().Set("goAdd", js.FuncOf(add))
|
130
|
-
js.Global().Set("
|
135
|
+
js.Global().Set("goSubtract", js.FuncOf(subtract))
|
136
|
+
js.Global().Set("goMultiply", js.FuncOf(multiply))
|
137
|
+
js.Global().Set("goConcat", js.FuncOf(concat))
|
138
|
+
js.Global().Set("goParseJSON", js.FuncOf(parseJSON))
|
131
139
|
|
132
|
-
// Register
|
133
|
-
|
140
|
+
// Register special utility functions for frontend-hamroun integration
|
141
|
+
js.Global().Set("__stringToGo", js.FuncOf(__stringToGo))
|
142
|
+
js.Global().Set("__stringFromGo", js.FuncOf(__stringFromGo))
|
143
|
+
js.Global().Set("__objectToGo", js.FuncOf(__objectToGo))
|
144
|
+
js.Global().Set("__objectFromGo", js.FuncOf(__objectFromGo))
|
134
145
|
|
135
146
|
// Keep the program running
|
136
|
-
|
147
|
+
c := make(chan struct{}, 0)
|
148
|
+
fmt.Println("Go WebAssembly module ready")
|
149
|
+
<-c
|
137
150
|
}
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
1
|
+
const config = {
|
2
2
|
presets: [
|
3
3
|
['@babel/preset-env', {
|
4
4
|
targets: {
|
5
5
|
node: 'current'
|
6
|
-
}
|
6
|
+
},
|
7
|
+
// Enable dynamic imports for both ESM and CommonJS
|
8
|
+
modules: false
|
7
9
|
}]
|
8
10
|
],
|
9
11
|
plugins: [
|
@@ -13,3 +15,7 @@ export default {
|
|
13
15
|
}]
|
14
16
|
]
|
15
17
|
};
|
18
|
+
|
19
|
+
// Support both ESM and CommonJS
|
20
|
+
export default config;
|
21
|
+
module.exports = config;
|
@@ -0,0 +1,62 @@
|
|
1
|
+
// CommonJS/ESM compatible build configuration
|
2
|
+
const buildConfig = {
|
3
|
+
/**
|
4
|
+
* Determines if we should build for dual module support
|
5
|
+
*/
|
6
|
+
dualModuleSupport: true,
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Entry points for both client and server
|
10
|
+
*/
|
11
|
+
entryPoints: {
|
12
|
+
client: 'src/client.js',
|
13
|
+
server: 'src/server.js'
|
14
|
+
},
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Output formats to generate
|
18
|
+
*/
|
19
|
+
outputFormats: ['esm', 'cjs'],
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Output directory configuration
|
23
|
+
*/
|
24
|
+
output: {
|
25
|
+
dir: 'dist',
|
26
|
+
client: {
|
27
|
+
esm: 'assets/[name].mjs',
|
28
|
+
cjs: 'assets/[name].js'
|
29
|
+
},
|
30
|
+
server: {
|
31
|
+
esm: 'server/[name].mjs',
|
32
|
+
cjs: 'server/[name].js'
|
33
|
+
}
|
34
|
+
},
|
35
|
+
|
36
|
+
/**
|
37
|
+
* WebAssembly configuration
|
38
|
+
*/
|
39
|
+
wasm: {
|
40
|
+
enabled: true,
|
41
|
+
goBinaryPath: 'go',
|
42
|
+
sourceDir: 'src/wasm',
|
43
|
+
outputDir: 'public/wasm',
|
44
|
+
copyGoRuntime: true
|
45
|
+
},
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Additional build options
|
49
|
+
*/
|
50
|
+
options: {
|
51
|
+
minify: process.env.NODE_ENV === 'production',
|
52
|
+
sourcemap: true,
|
53
|
+
target: 'es2020'
|
54
|
+
}
|
55
|
+
};
|
56
|
+
|
57
|
+
// Make it work in both ESM and CommonJS environments
|
58
|
+
if (typeof module !== 'undefined' && module.exports) {
|
59
|
+
module.exports = buildConfig;
|
60
|
+
}
|
61
|
+
|
62
|
+
export default buildConfig;
|