baraqex 1.0.8 → 1.0.10
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/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -5
- package/dist/index.js.map +1 -1
- package/dist/renderComponent.d.ts +9 -0
- package/dist/renderComponent.d.ts.map +1 -0
- package/dist/renderComponent.js +39 -0
- package/dist/renderComponent.js.map +1 -0
- package/dist/server/api-router.d.ts +16 -0
- package/dist/server/api-router.d.ts.map +1 -0
- package/dist/server/api-router.js +93 -0
- package/dist/server/api-router.js.map +1 -0
- package/dist/server/auth.d.ts +33 -0
- package/dist/server/auth.d.ts.map +1 -0
- package/dist/server/auth.js +74 -0
- package/dist/server/auth.js.map +1 -0
- package/dist/server/database.d.ts +25 -0
- package/dist/server/database.d.ts.map +1 -0
- package/dist/server/database.js +109 -0
- package/dist/server/database.js.map +1 -0
- package/dist/server/index.d.ts +117 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +465 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/middleware.d.ts +12 -0
- package/dist/server/middleware.d.ts.map +1 -0
- package/dist/server/middleware.js +46 -0
- package/dist/server/middleware.js.map +1 -0
- package/dist/server/server.d.ts +10 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +81 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/templates.d.ts +31 -0
- package/dist/server/templates.d.ts.map +1 -0
- package/dist/server/templates.js +208 -0
- package/dist/server/templates.js.map +1 -0
- package/dist/server/types.d.ts +39 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +4 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/utils.d.ts +71 -0
- package/dist/server/utils.d.ts.map +1 -0
- package/dist/server/utils.js +156 -0
- package/dist/server/utils.js.map +1 -0
- package/dist/server/wasm.d.ts +10 -0
- package/dist/server/wasm.d.ts.map +1 -0
- package/dist/server/wasm.js +117 -0
- package/dist/server/wasm.js.map +1 -0
- package/dist/server-renderer.d.ts +6 -0
- package/dist/server-renderer.d.ts.map +1 -0
- package/dist/server-renderer.js +39 -0
- package/dist/server-renderer.js.map +1 -0
- package/dist/wasm.d.ts +17 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +48 -0
- package/dist/wasm.js.map +1 -0
- package/package.json +15 -3
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML template generators for server-side rendering
|
|
3
|
+
*/
|
|
4
|
+
export interface DocumentOptions {
|
|
5
|
+
title?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
lang?: string;
|
|
8
|
+
charset?: string;
|
|
9
|
+
viewport?: string;
|
|
10
|
+
scripts?: string[];
|
|
11
|
+
styles?: string[];
|
|
12
|
+
meta?: Record<string, string>;
|
|
13
|
+
bodyClasses?: string;
|
|
14
|
+
htmlAttrs?: Record<string, string>;
|
|
15
|
+
bodyAttrs?: Record<string, string>;
|
|
16
|
+
initialData?: any;
|
|
17
|
+
componentName?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generate a complete HTML document
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateDocument(content: string, options?: DocumentOptions): string;
|
|
23
|
+
/**
|
|
24
|
+
* Generate an error page
|
|
25
|
+
*/
|
|
26
|
+
export declare function generateErrorPage(statusCode: number, message: string, error?: Error): string;
|
|
27
|
+
/**
|
|
28
|
+
* Generate a loading page
|
|
29
|
+
*/
|
|
30
|
+
export declare function generateLoadingPage(message?: string): string;
|
|
31
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/server/templates.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,eAAoB,GAC5B,MAAM,CAyER;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,KAAK,GACZ,MAAM,CAgGR;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,MAAqB,GAAG,MAAM,CAyC1E"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML template generators for server-side rendering
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Generate a complete HTML document
|
|
6
|
+
*/
|
|
7
|
+
export function generateDocument(content, options = {}) {
|
|
8
|
+
const { title = 'Frontend Hamroun App', description = '', lang = 'en', charset = 'UTF-8', viewport = 'width=device-width, initial-scale=1.0', scripts = [], styles = [], meta = {}, bodyClasses = '', htmlAttrs = {}, bodyAttrs = {}, initialData = {}, componentName = '' } = options;
|
|
9
|
+
// Generate HTML attributes
|
|
10
|
+
const htmlAttributes = Object.entries(htmlAttrs)
|
|
11
|
+
.map(([key, value]) => `${key}="${escapeHtml(value)}"`)
|
|
12
|
+
.join(' ');
|
|
13
|
+
// Generate body attributes
|
|
14
|
+
const bodyAttributes = Object.entries(bodyAttrs)
|
|
15
|
+
.map(([key, value]) => `${key}="${escapeHtml(value)}"`)
|
|
16
|
+
.join(' ');
|
|
17
|
+
// Generate meta tags
|
|
18
|
+
const metaTags = [
|
|
19
|
+
`<meta charset="${charset}">`,
|
|
20
|
+
`<meta name="viewport" content="${viewport}">`,
|
|
21
|
+
description ? `<meta name="description" content="${escapeHtml(description)}">` : ''
|
|
22
|
+
];
|
|
23
|
+
// Add custom meta tags
|
|
24
|
+
Object.entries(meta).forEach(([name, content]) => {
|
|
25
|
+
metaTags.push(`<meta name="${escapeHtml(name)}" content="${escapeHtml(content)}">`);
|
|
26
|
+
});
|
|
27
|
+
// Generate script tags
|
|
28
|
+
const scriptTags = scripts.map(src => {
|
|
29
|
+
if (src.startsWith('<script')) {
|
|
30
|
+
return src; // Allow inline scripts
|
|
31
|
+
}
|
|
32
|
+
return `<script src="${escapeHtml(src)}" ${src.endsWith('.js') ? 'type="module"' : ''} defer></script>`;
|
|
33
|
+
});
|
|
34
|
+
// Generate style tags
|
|
35
|
+
const styleTags = styles.map(href => {
|
|
36
|
+
if (href.startsWith('<style')) {
|
|
37
|
+
return href; // Allow inline styles
|
|
38
|
+
}
|
|
39
|
+
return `<link rel="stylesheet" href="${escapeHtml(href)}">`;
|
|
40
|
+
});
|
|
41
|
+
// Create initial data script
|
|
42
|
+
const initialDataScript = Object.keys(initialData).length > 0 ?
|
|
43
|
+
`<script id="__APP_DATA__" type="application/json">${escapeHtml(JSON.stringify(initialData))}</script>` : '';
|
|
44
|
+
// Create the complete HTML document
|
|
45
|
+
return `<!DOCTYPE html>
|
|
46
|
+
<html lang="${lang}" ${htmlAttributes}>
|
|
47
|
+
<head>
|
|
48
|
+
${metaTags.filter(Boolean).join('\n ')}
|
|
49
|
+
<title>${escapeHtml(title)}</title>
|
|
50
|
+
${styleTags.join('\n ')}
|
|
51
|
+
</head>
|
|
52
|
+
<body class="${bodyClasses}" ${bodyAttributes}>
|
|
53
|
+
<div id="app-root" data-ssr-root${componentName ? ` data-component="${escapeHtml(componentName)}"` : ''}>${content}</div>
|
|
54
|
+
${initialDataScript}
|
|
55
|
+
${scriptTags.join('\n ')}
|
|
56
|
+
</body>
|
|
57
|
+
</html>`;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Generate an error page
|
|
61
|
+
*/
|
|
62
|
+
export function generateErrorPage(statusCode, message, error) {
|
|
63
|
+
const errorMessages = {
|
|
64
|
+
400: 'Bad Request',
|
|
65
|
+
401: 'Unauthorized',
|
|
66
|
+
403: 'Forbidden',
|
|
67
|
+
404: 'Not Found',
|
|
68
|
+
500: 'Internal Server Error'
|
|
69
|
+
};
|
|
70
|
+
const title = `${statusCode} - ${errorMessages[statusCode] || 'Error'}`;
|
|
71
|
+
// Generate error details (only in development)
|
|
72
|
+
const isDev = process.env.NODE_ENV !== 'production';
|
|
73
|
+
const errorDetails = isDev && error ? `
|
|
74
|
+
<div class="error-details">
|
|
75
|
+
<pre>${escapeHtml(error.stack || error.message)}</pre>
|
|
76
|
+
</div>
|
|
77
|
+
` : '';
|
|
78
|
+
// Create error content
|
|
79
|
+
const content = `
|
|
80
|
+
<div class="error-container">
|
|
81
|
+
<h1>${statusCode}</h1>
|
|
82
|
+
<h2>${escapeHtml(errorMessages[statusCode] || 'Error')}</h2>
|
|
83
|
+
<p>${escapeHtml(message)}</p>
|
|
84
|
+
${errorDetails}
|
|
85
|
+
<a href="/" class="home-link">Back to Home</a>
|
|
86
|
+
</div>
|
|
87
|
+
`;
|
|
88
|
+
// Add error page styling
|
|
89
|
+
const styles = [`<style>
|
|
90
|
+
body {
|
|
91
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
92
|
+
display: flex;
|
|
93
|
+
justify-content: center;
|
|
94
|
+
align-items: center;
|
|
95
|
+
min-height: 100vh;
|
|
96
|
+
margin: 0;
|
|
97
|
+
background-color: #f7f7f7;
|
|
98
|
+
color: #333;
|
|
99
|
+
}
|
|
100
|
+
.error-container {
|
|
101
|
+
text-align: center;
|
|
102
|
+
padding: 2rem;
|
|
103
|
+
border-radius: 8px;
|
|
104
|
+
background-color: white;
|
|
105
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
106
|
+
max-width: 600px;
|
|
107
|
+
width: 100%;
|
|
108
|
+
}
|
|
109
|
+
h1 {
|
|
110
|
+
font-size: 6rem;
|
|
111
|
+
margin: 0;
|
|
112
|
+
color: #e74c3c;
|
|
113
|
+
}
|
|
114
|
+
h2 {
|
|
115
|
+
margin-top: 0;
|
|
116
|
+
margin-bottom: 1rem;
|
|
117
|
+
color: #333;
|
|
118
|
+
}
|
|
119
|
+
.error-details {
|
|
120
|
+
text-align: left;
|
|
121
|
+
margin: 2rem 0;
|
|
122
|
+
padding: 1rem;
|
|
123
|
+
background-color: #f8f8f8;
|
|
124
|
+
border-radius: 4px;
|
|
125
|
+
overflow: auto;
|
|
126
|
+
}
|
|
127
|
+
pre {
|
|
128
|
+
margin: 0;
|
|
129
|
+
font-family: monospace;
|
|
130
|
+
font-size: 0.85rem;
|
|
131
|
+
white-space: pre-wrap;
|
|
132
|
+
}
|
|
133
|
+
.home-link {
|
|
134
|
+
display: inline-block;
|
|
135
|
+
margin-top: 1.5rem;
|
|
136
|
+
padding: 0.75rem 1.5rem;
|
|
137
|
+
background-color: #3498db;
|
|
138
|
+
color: white;
|
|
139
|
+
text-decoration: none;
|
|
140
|
+
border-radius: 4px;
|
|
141
|
+
transition: background-color 0.2s;
|
|
142
|
+
}
|
|
143
|
+
.home-link:hover {
|
|
144
|
+
background-color: #2980b9;
|
|
145
|
+
}
|
|
146
|
+
</style>`];
|
|
147
|
+
return generateDocument(content, {
|
|
148
|
+
title,
|
|
149
|
+
description: `Error ${statusCode}: ${errorMessages[statusCode] || 'Error'}`,
|
|
150
|
+
bodyClasses: 'error-page',
|
|
151
|
+
styles
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Generate a loading page
|
|
156
|
+
*/
|
|
157
|
+
export function generateLoadingPage(message = 'Loading...') {
|
|
158
|
+
const content = `
|
|
159
|
+
<div class="loading-container">
|
|
160
|
+
<div class="spinner"></div>
|
|
161
|
+
<p>${escapeHtml(message)}</p>
|
|
162
|
+
</div>
|
|
163
|
+
`;
|
|
164
|
+
const styles = [`<style>
|
|
165
|
+
body {
|
|
166
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
167
|
+
display: flex;
|
|
168
|
+
justify-content: center;
|
|
169
|
+
align-items: center;
|
|
170
|
+
min-height: 100vh;
|
|
171
|
+
margin: 0;
|
|
172
|
+
background-color: #f7f7f7;
|
|
173
|
+
color: #333;
|
|
174
|
+
}
|
|
175
|
+
.loading-container {
|
|
176
|
+
text-align: center;
|
|
177
|
+
}
|
|
178
|
+
.spinner {
|
|
179
|
+
width: 50px;
|
|
180
|
+
height: 50px;
|
|
181
|
+
border: 5px solid rgba(0, 0, 0, 0.1);
|
|
182
|
+
border-radius: 50%;
|
|
183
|
+
border-top-color: #3498db;
|
|
184
|
+
animation: spin 1s ease-in-out infinite;
|
|
185
|
+
margin: 0 auto 20px;
|
|
186
|
+
}
|
|
187
|
+
@keyframes spin {
|
|
188
|
+
to { transform: rotate(360deg); }
|
|
189
|
+
}
|
|
190
|
+
</style>`];
|
|
191
|
+
return generateDocument(content, {
|
|
192
|
+
title: 'Loading',
|
|
193
|
+
bodyClasses: 'loading-page',
|
|
194
|
+
styles
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Escape HTML special characters
|
|
199
|
+
*/
|
|
200
|
+
function escapeHtml(text) {
|
|
201
|
+
return String(text)
|
|
202
|
+
.replace(/&/g, '&')
|
|
203
|
+
.replace(/</g, '<')
|
|
204
|
+
.replace(/>/g, '>')
|
|
205
|
+
.replace(/"/g, '"')
|
|
206
|
+
.replace(/'/g, ''');
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/server/templates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface ServerConfig {
|
|
2
|
+
port?: number;
|
|
3
|
+
apiDir?: string;
|
|
4
|
+
pagesDir?: string;
|
|
5
|
+
staticDir?: string;
|
|
6
|
+
enableCors?: boolean;
|
|
7
|
+
corsOptions?: any;
|
|
8
|
+
db?: {
|
|
9
|
+
url: string;
|
|
10
|
+
type: 'mongodb' | 'mysql' | 'postgres';
|
|
11
|
+
};
|
|
12
|
+
auth?: {
|
|
13
|
+
secret: string;
|
|
14
|
+
expiresIn?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface Server {
|
|
18
|
+
start(): Promise<void>;
|
|
19
|
+
stop(): Promise<void>;
|
|
20
|
+
getExpressApp(): any;
|
|
21
|
+
getDatabase(): any;
|
|
22
|
+
getAuth(): any;
|
|
23
|
+
}
|
|
24
|
+
export interface User {
|
|
25
|
+
id: string | number;
|
|
26
|
+
username: string;
|
|
27
|
+
password?: string;
|
|
28
|
+
email?: string;
|
|
29
|
+
roles?: string[];
|
|
30
|
+
[key: string]: any;
|
|
31
|
+
}
|
|
32
|
+
export interface DbConfig {
|
|
33
|
+
url: string;
|
|
34
|
+
type: 'mongodb' | 'mysql' | 'postgres';
|
|
35
|
+
}
|
|
36
|
+
export interface MiddlewareFunction {
|
|
37
|
+
(req: any, res: any, next: any): void | Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,EAAE,CAAC,EAAE;QACH,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;KACxC,CAAC;IACF,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,MAAM;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,aAAa,IAAI,GAAG,CAAC;IACrB,WAAW,IAAI,GAAG,CAAC;IACnB,OAAO,IAAI,GAAG,CAAC;CAChB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;CACxC;AAED,MAAM,WAAW,kBAAkB;IACjC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,kDAAkD"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Utility functions for server-side operations
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Safely parse JSON with error handling
|
|
7
|
+
*/
|
|
8
|
+
export declare function safeJsonParse<T>(json: string, fallback: T): T;
|
|
9
|
+
/**
|
|
10
|
+
* Generate a secure random token
|
|
11
|
+
*/
|
|
12
|
+
export declare function generateToken(length?: number): string;
|
|
13
|
+
/**
|
|
14
|
+
* Hash a string using SHA-256
|
|
15
|
+
*/
|
|
16
|
+
export declare function hashString(input: string, salt?: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Get pagination parameters from request
|
|
19
|
+
*/
|
|
20
|
+
export declare function getPagination(req: Request): {
|
|
21
|
+
page: number;
|
|
22
|
+
limit: number;
|
|
23
|
+
skip: number;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Standard success response format
|
|
27
|
+
*/
|
|
28
|
+
export declare function sendSuccess<T>(res: Response, data: T, message?: string): Response;
|
|
29
|
+
/**
|
|
30
|
+
* Standard error response format
|
|
31
|
+
*/
|
|
32
|
+
export declare function sendError(res: Response, message?: string, statusCode?: number, errors?: any): Response;
|
|
33
|
+
/**
|
|
34
|
+
* Validate required fields in request body
|
|
35
|
+
*/
|
|
36
|
+
export declare function validateFields(req: Request, requiredFields: string[]): {
|
|
37
|
+
valid: boolean;
|
|
38
|
+
missing: string[];
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Handle file upload validation
|
|
42
|
+
*/
|
|
43
|
+
export declare function validateFileUpload(file: any, // Using 'any' to avoid the Express.Multer dependency
|
|
44
|
+
options?: {
|
|
45
|
+
maxSize?: number;
|
|
46
|
+
allowedTypes?: string[];
|
|
47
|
+
}): {
|
|
48
|
+
valid: boolean;
|
|
49
|
+
error?: string;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Get server environment information
|
|
53
|
+
*/
|
|
54
|
+
export declare function getEnvironmentInfo(): Record<string, any>;
|
|
55
|
+
/**
|
|
56
|
+
* Check if a directory is empty
|
|
57
|
+
*/
|
|
58
|
+
export declare function isDirectoryEmpty(dirPath: string): Promise<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Create directory if it doesn't exist
|
|
61
|
+
*/
|
|
62
|
+
export declare function ensureDirectory(dirPath: string): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Write JSON to file
|
|
65
|
+
*/
|
|
66
|
+
export declare function writeJsonFile(filePath: string, data: any): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Read JSON from file
|
|
69
|
+
*/
|
|
70
|
+
export declare function readJsonFile<T>(filePath: string, defaultValue: T): Promise<T>;
|
|
71
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/server/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAK5C;;GAEG;AAEH;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAM7D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAEzD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,MAAW,GAAG,MAAM,CAEnE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAMzF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,GAAE,MAAkB,GAAG,QAAQ,CAM5F;AAED;;GAEG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,QAAQ,EACb,OAAO,GAAE,MAA4B,EACrC,UAAU,GAAE,MAAY,EACxB,MAAM,CAAC,EAAE,GAAG,GACX,QAAQ,CAMV;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,cAAc,EAAE,MAAM,EAAE,GACvB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAUvC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,GAAG,EAAE,qDAAqD;AAChE,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,GACL;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAyBpC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CASxD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQxE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOpE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOnF"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
/**
|
|
5
|
+
* Utility functions for server-side operations
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Safely parse JSON with error handling
|
|
9
|
+
*/
|
|
10
|
+
export function safeJsonParse(json, fallback) {
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(json);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
return fallback;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generate a secure random token
|
|
20
|
+
*/
|
|
21
|
+
export function generateToken(length = 32) {
|
|
22
|
+
return crypto.randomBytes(length).toString('hex');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Hash a string using SHA-256
|
|
26
|
+
*/
|
|
27
|
+
export function hashString(input, salt = '') {
|
|
28
|
+
return crypto.createHash('sha256').update(input + salt).digest('hex');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get pagination parameters from request
|
|
32
|
+
*/
|
|
33
|
+
export function getPagination(req) {
|
|
34
|
+
const page = Math.max(1, parseInt(req.query.page) || 1);
|
|
35
|
+
const limit = Math.max(1, Math.min(100, parseInt(req.query.limit) || 20));
|
|
36
|
+
const skip = (page - 1) * limit;
|
|
37
|
+
return { page, limit, skip };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Standard success response format
|
|
41
|
+
*/
|
|
42
|
+
export function sendSuccess(res, data, message = 'Success') {
|
|
43
|
+
return res.json({
|
|
44
|
+
success: true,
|
|
45
|
+
message,
|
|
46
|
+
data
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Standard error response format
|
|
51
|
+
*/
|
|
52
|
+
export function sendError(res, message = 'An error occurred', statusCode = 400, errors) {
|
|
53
|
+
return res.status(statusCode).json({
|
|
54
|
+
success: false,
|
|
55
|
+
message,
|
|
56
|
+
errors: errors || undefined
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Validate required fields in request body
|
|
61
|
+
*/
|
|
62
|
+
export function validateFields(req, requiredFields) {
|
|
63
|
+
const missing = requiredFields.filter(field => {
|
|
64
|
+
const value = req.body[field];
|
|
65
|
+
return value === undefined || value === null || value === '';
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
valid: missing.length === 0,
|
|
69
|
+
missing
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Handle file upload validation
|
|
74
|
+
*/
|
|
75
|
+
export function validateFileUpload(file, // Using 'any' to avoid the Express.Multer dependency
|
|
76
|
+
options = {}) {
|
|
77
|
+
if (!file) {
|
|
78
|
+
return { valid: false, error: 'No file provided' };
|
|
79
|
+
}
|
|
80
|
+
// Check file size
|
|
81
|
+
if (options.maxSize && file.size > options.maxSize) {
|
|
82
|
+
return {
|
|
83
|
+
valid: false,
|
|
84
|
+
error: `File too large. Maximum size allowed is ${options.maxSize / 1024 / 1024}MB`
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// Check file type
|
|
88
|
+
if (options.allowedTypes && options.allowedTypes.length > 0) {
|
|
89
|
+
const fileType = file.mimetype;
|
|
90
|
+
if (!options.allowedTypes.includes(fileType)) {
|
|
91
|
+
return {
|
|
92
|
+
valid: false,
|
|
93
|
+
error: `Invalid file type. Allowed types: ${options.allowedTypes.join(', ')}`
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { valid: true };
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get server environment information
|
|
101
|
+
*/
|
|
102
|
+
export function getEnvironmentInfo() {
|
|
103
|
+
return {
|
|
104
|
+
nodeVersion: process.version,
|
|
105
|
+
platform: process.platform,
|
|
106
|
+
arch: process.arch,
|
|
107
|
+
memory: process.memoryUsage(),
|
|
108
|
+
uptime: process.uptime(),
|
|
109
|
+
env: process.env.NODE_ENV || 'development'
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if a directory is empty
|
|
114
|
+
*/
|
|
115
|
+
export async function isDirectoryEmpty(dirPath) {
|
|
116
|
+
try {
|
|
117
|
+
const files = await fs.readdir(dirPath);
|
|
118
|
+
return files.length === 0;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
// Directory doesn't exist or can't be read
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Create directory if it doesn't exist
|
|
127
|
+
*/
|
|
128
|
+
export async function ensureDirectory(dirPath) {
|
|
129
|
+
try {
|
|
130
|
+
await fs.access(dirPath);
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
// Directory doesn't exist, create it
|
|
134
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Write JSON to file
|
|
139
|
+
*/
|
|
140
|
+
export async function writeJsonFile(filePath, data) {
|
|
141
|
+
await ensureDirectory(path.dirname(filePath));
|
|
142
|
+
await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf8');
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Read JSON from file
|
|
146
|
+
*/
|
|
147
|
+
export async function readJsonFile(filePath, defaultValue) {
|
|
148
|
+
try {
|
|
149
|
+
const data = await fs.readFile(filePath, 'utf8');
|
|
150
|
+
return safeJsonParse(data, defaultValue);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
return defaultValue;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/server/utils.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;GAEG;AAEH;;GAEG;AACH,MAAM,UAAU,aAAa,CAAI,IAAY,EAAE,QAAW;IACxD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,QAAQ,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE;IAC/C,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,OAAe,EAAE;IACzD,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACxE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAe,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACpF,MAAM,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;IAEhC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAI,GAAa,EAAE,IAAO,EAAE,UAAkB,SAAS;IAChF,OAAO,GAAG,CAAC,IAAI,CAAC;QACd,OAAO,EAAE,IAAI;QACb,OAAO;QACP,IAAI;KACL,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CACvB,GAAa,EACb,UAAkB,mBAAmB,EACrC,aAAqB,GAAG,EACxB,MAAY;IAEZ,OAAO,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC;QACjC,OAAO,EAAE,KAAK;QACd,OAAO;QACP,MAAM,EAAE,MAAM,IAAI,SAAS;KAC5B,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAY,EACZ,cAAwB;IAExB,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC;QAC3B,OAAO;KACR,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAS,EAAE,qDAAqD;AAChE,UAGI,EAAE;IAEN,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IACrD,CAAC;IAED,kBAAkB;IAClB,IAAI,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QACnD,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,2CAA2C,OAAO,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,IAAI;SACpF,CAAC;IACJ,CAAC;IAED,kBAAkB;IAClB,IAAI,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7C,OAAO;gBACL,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,qCAAqC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aAC9E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,OAAO;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE;QAC7B,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;QACxB,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa;KAC3C,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAe;IACpD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,2CAA2C;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAe;IACnD,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,qCAAqC;QACrC,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB,EAAE,IAAS;IAC7D,MAAM,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,QAAgB,EAAE,YAAe;IACrE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjD,OAAO,aAAa,CAAI,IAAI,EAAE,YAAY,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,YAAY,CAAC;IACtB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { GoWasmInstance, GoWasmOptions } from '../wasm.js';
|
|
2
|
+
/**
|
|
3
|
+
* Initialize the Node.js environment for running Go WASM modules
|
|
4
|
+
*/
|
|
5
|
+
export declare function initNodeWasm(): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Load a Go WASM module from a file path for server-side usage
|
|
8
|
+
*/
|
|
9
|
+
export declare function loadGoWasmFromFile(wasmFilePath: string, options?: GoWasmOptions): Promise<GoWasmInstance>;
|
|
10
|
+
//# sourceMappingURL=wasm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasm.d.ts","sourceRoot":"","sources":["../../src/server/wasm.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAK3D;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CA0BlD;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,cAAc,CAAC,CA4FzB"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side Go WASM integration for Node.js
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'fs/promises';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
// Global flag to ensure we only initialize WASM once
|
|
8
|
+
let initialized = false;
|
|
9
|
+
/**
|
|
10
|
+
* Initialize the Node.js environment for running Go WASM modules
|
|
11
|
+
*/
|
|
12
|
+
export async function initNodeWasm() {
|
|
13
|
+
if (initialized)
|
|
14
|
+
return;
|
|
15
|
+
try {
|
|
16
|
+
// Check if node requires WASM flags
|
|
17
|
+
const nodeVersion = process.version;
|
|
18
|
+
const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0], 10);
|
|
19
|
+
// Node.js version check for WASM flags requirement
|
|
20
|
+
if (majorVersion < 16) {
|
|
21
|
+
console.warn('[WASM] Note: Node.js version < 16 detected. ' +
|
|
22
|
+
'You may need --experimental-wasm-bigint flag for Go WASM modules.');
|
|
23
|
+
}
|
|
24
|
+
// Global WASM environment setup for Node.js
|
|
25
|
+
globalThis.TextEncoder = globalThis.TextEncoder || TextEncoder;
|
|
26
|
+
globalThis.TextDecoder = globalThis.TextDecoder || TextDecoder;
|
|
27
|
+
// Mark as initialized
|
|
28
|
+
initialized = true;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
console.error('[WASM] Failed to initialize Node.js WASM environment:', error);
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Load a Go WASM module from a file path for server-side usage
|
|
37
|
+
*/
|
|
38
|
+
export async function loadGoWasmFromFile(wasmFilePath, options = {}) {
|
|
39
|
+
try {
|
|
40
|
+
// Initialize Node.js WASM environment
|
|
41
|
+
await initNodeWasm();
|
|
42
|
+
// Get __dirname equivalent in ESM
|
|
43
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
44
|
+
const __dirname = path.dirname(__filename);
|
|
45
|
+
// Load Go runtime
|
|
46
|
+
const goRuntimePath = options.goWasmPath ||
|
|
47
|
+
path.join(__dirname, '..', '..', 'templates', 'go', 'wasm_exec_node.js');
|
|
48
|
+
// Import the Go runtime
|
|
49
|
+
const { Go } = await import(goRuntimePath);
|
|
50
|
+
const go = new Go();
|
|
51
|
+
// Load WASM binary
|
|
52
|
+
const wasmBuffer = await fs.readFile(wasmFilePath);
|
|
53
|
+
const wasmModule = await WebAssembly.compile(wasmBuffer);
|
|
54
|
+
// Create imports object
|
|
55
|
+
const finalImportObject = {
|
|
56
|
+
...go.importObject,
|
|
57
|
+
...options.importObject
|
|
58
|
+
};
|
|
59
|
+
// Instantiate the WASM module
|
|
60
|
+
const instance = await WebAssembly.instantiate(wasmModule, finalImportObject);
|
|
61
|
+
// Initialize Go runtime
|
|
62
|
+
go.run(instance);
|
|
63
|
+
// Extract exported functions
|
|
64
|
+
const exports = instance.exports;
|
|
65
|
+
const functions = {};
|
|
66
|
+
// Generate wrapper functions for all exports that are functions
|
|
67
|
+
for (const key in exports) {
|
|
68
|
+
if (typeof exports[key] === 'function') {
|
|
69
|
+
// Fix the type assertion
|
|
70
|
+
const exportedFunc = exports[key];
|
|
71
|
+
functions[key] = (...args) => exportedFunc(...args);
|
|
72
|
+
if (options.debug) {
|
|
73
|
+
const originalFn = functions[key];
|
|
74
|
+
functions[key] = (...args) => {
|
|
75
|
+
console.log(`[WASM] Calling ${key}(${args.join(', ')})`);
|
|
76
|
+
const result = originalFn(...args);
|
|
77
|
+
console.log(`[WASM] ${key} returned:`, result);
|
|
78
|
+
return result;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Also capture global functions exported by Go
|
|
84
|
+
for (const key in global) {
|
|
85
|
+
if (key.startsWith('go') && typeof global[key] === 'function') {
|
|
86
|
+
// Fix the type assertion
|
|
87
|
+
const globalFunc = global[key];
|
|
88
|
+
functions[key] = (...args) => globalFunc(...args);
|
|
89
|
+
if (options.debug) {
|
|
90
|
+
const originalFn = functions[key];
|
|
91
|
+
functions[key] = (...args) => {
|
|
92
|
+
console.log(`[WASM] Calling global ${key}(${args.join(', ')})`);
|
|
93
|
+
const result = originalFn(...args);
|
|
94
|
+
console.log(`[WASM] ${key} returned:`, result);
|
|
95
|
+
return result;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const wasmInstance = {
|
|
101
|
+
instance,
|
|
102
|
+
module: wasmModule,
|
|
103
|
+
exports,
|
|
104
|
+
functions
|
|
105
|
+
};
|
|
106
|
+
// Run onLoad callback if provided
|
|
107
|
+
if (options.onLoad) {
|
|
108
|
+
options.onLoad(wasmInstance);
|
|
109
|
+
}
|
|
110
|
+
return wasmInstance;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error('[WASM] Failed to load Go WASM module:', error);
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=wasm.js.map
|