baraqex 1.0.47 → 1.0.49
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.js +236 -189
- package/dist/index.js.map +4 -4
- package/dist/server.js +1282 -864
- package/dist/server.js.map +4 -4
- package/package.json +1 -1
- package/templates/fullstack-template/package-lock.json +931 -4
- package/templates/fullstack-template/package.json +7 -5
- package/templates/fullstack-template/server.js +548 -15
- package/templates/fullstack-template/src/api/hello.js +9 -11
- package/templates/fullstack-template/src/pages/index.js +196 -114
- package/templates/fullstack-app/package-lock.json +0 -3683
- package/templates/fullstack-app/package.json +0 -26
- package/templates/fullstack-app/public/client.js +0 -139
- package/templates/fullstack-app/public/fullstack-styles.css +0 -445
- package/templates/fullstack-app/server.js +0 -32
- package/templates/fullstack-app/src/api/auth.js +0 -48
- package/templates/fullstack-app/src/api/users.js +0 -85
- package/templates/fullstack-app/src/pages/index.js +0 -0
- package/templates/fullstack-app/src/pages/index.jsx +0 -181
- package/templates/fullstack-app/src/pages/login.js +0 -139
- package/templates/fullstack-app/src/pages/login.jsx +0 -150
- package/templates/fullstack-template/public/client.js +0 -17
- package/templates/fullstack-template/src/api/users/index.js +0 -43
- package/templates/go-wasm-app/package.json +0 -24
- package/templates/go-wasm-app/public/wasm-styles.css +0 -184
- package/templates/go-wasm-app/server.js +0 -36
- package/templates/go-wasm-app/src/pages/index.jsx +0 -161
- package/templates/go-wasm-app/src/wasm/main.go +0 -164
package/dist/server.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
2
5
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
6
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
7
|
}) : x)(function(x) {
|
|
@@ -6,524 +9,116 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
6
9
|
return require.apply(this, arguments);
|
|
7
10
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
8
11
|
});
|
|
12
|
+
var __esm = (fn, res) => function __init() {
|
|
13
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
14
|
+
};
|
|
9
15
|
var __export = (target, all) => {
|
|
10
16
|
for (var name in all)
|
|
11
17
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
18
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// src/server/database.ts
|
|
20
|
-
var Database = class {
|
|
21
|
-
constructor(config) {
|
|
22
|
-
this.mongoClient = null;
|
|
23
|
-
this.mongoDb = null;
|
|
24
|
-
this.mysqlPool = null;
|
|
25
|
-
this.pgPool = null;
|
|
26
|
-
this.config = config;
|
|
27
|
-
}
|
|
28
|
-
async connect() {
|
|
29
|
-
switch (this.config.type) {
|
|
30
|
-
case "mongodb":
|
|
31
|
-
await this.connectMongo();
|
|
32
|
-
break;
|
|
33
|
-
case "mysql":
|
|
34
|
-
await this.connectMysql();
|
|
35
|
-
break;
|
|
36
|
-
case "postgres":
|
|
37
|
-
await this.connectPostgres();
|
|
38
|
-
break;
|
|
39
|
-
default:
|
|
40
|
-
throw new Error(`Unsupported database type: ${this.config.type}`);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
async connectMongo() {
|
|
44
|
-
try {
|
|
45
|
-
const { MongoClient } = await import("mongodb");
|
|
46
|
-
this.mongoClient = new MongoClient(this.config.url);
|
|
47
|
-
await this.mongoClient.connect();
|
|
48
|
-
this.mongoDb = this.mongoClient.db();
|
|
49
|
-
console.log("Connected to MongoDB");
|
|
50
|
-
} catch (error) {
|
|
51
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
52
|
-
throw new Error("MongoDB driver not installed. Run: npm install mongodb");
|
|
53
|
-
}
|
|
54
|
-
console.error("MongoDB connection error:", error);
|
|
55
|
-
throw error;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
async connectMysql() {
|
|
59
|
-
try {
|
|
60
|
-
const mysql = await import("mysql2/promise");
|
|
61
|
-
this.mysqlPool = mysql.createPool(this.config.url);
|
|
62
|
-
await this.mysqlPool.getConnection();
|
|
63
|
-
console.log("Connected to MySQL");
|
|
64
|
-
} catch (error) {
|
|
65
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
66
|
-
throw new Error("MySQL driver not installed. Run: npm install mysql2");
|
|
67
|
-
}
|
|
68
|
-
console.error("MySQL connection error:", error);
|
|
69
|
-
throw error;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
async connectPostgres() {
|
|
73
|
-
try {
|
|
74
|
-
const pg = await import("pg");
|
|
75
|
-
this.pgPool = new pg.Pool({ connectionString: this.config.url });
|
|
76
|
-
const client = await this.pgPool.connect();
|
|
77
|
-
client.release();
|
|
78
|
-
console.log("Connected to PostgreSQL");
|
|
79
|
-
} catch (error) {
|
|
80
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
81
|
-
throw new Error("PostgreSQL driver not installed. Run: npm install pg @types/pg");
|
|
82
|
-
}
|
|
83
|
-
console.error("PostgreSQL connection error:", error);
|
|
84
|
-
throw error;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
async disconnect() {
|
|
88
|
-
if (this.mongoClient) {
|
|
89
|
-
await this.mongoClient.close();
|
|
90
|
-
this.mongoClient = null;
|
|
91
|
-
this.mongoDb = null;
|
|
92
|
-
}
|
|
93
|
-
if (this.mysqlPool) {
|
|
94
|
-
await this.mysqlPool.end();
|
|
95
|
-
this.mysqlPool = null;
|
|
96
|
-
}
|
|
97
|
-
if (this.pgPool) {
|
|
98
|
-
await this.pgPool.end();
|
|
99
|
-
this.pgPool = null;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
// Database-specific methods
|
|
103
|
-
getMongoDb() {
|
|
104
|
-
return this.mongoDb;
|
|
105
|
-
}
|
|
106
|
-
getMysqlPool() {
|
|
107
|
-
return this.mysqlPool;
|
|
108
|
-
}
|
|
109
|
-
getPgPool() {
|
|
110
|
-
return this.pgPool;
|
|
111
|
-
}
|
|
112
|
-
// Generic query method
|
|
113
|
-
async query(sql, values) {
|
|
114
|
-
switch (this.config.type) {
|
|
115
|
-
case "mongodb":
|
|
116
|
-
throw new Error("For MongoDB, use getMongoDb() instead of query()");
|
|
117
|
-
case "mysql":
|
|
118
|
-
if (!this.mysqlPool)
|
|
119
|
-
throw new Error("MySQL not connected");
|
|
120
|
-
const [rows] = await this.mysqlPool.execute(sql, values || []);
|
|
121
|
-
return rows;
|
|
122
|
-
case "postgres":
|
|
123
|
-
if (!this.pgPool)
|
|
124
|
-
throw new Error("PostgreSQL not connected");
|
|
125
|
-
const result = await this.pgPool.query(sql, values || []);
|
|
126
|
-
return result.rows;
|
|
127
|
-
default:
|
|
128
|
-
throw new Error(`Unsupported database type: ${this.config.type}`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
// src/server/auth.ts
|
|
134
|
-
var AuthService = class {
|
|
135
|
-
constructor(config) {
|
|
136
|
-
this.config = {
|
|
137
|
-
expiresIn: "24h",
|
|
138
|
-
...config
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
async hashPassword(password) {
|
|
142
|
-
try {
|
|
143
|
-
const bcrypt = await import("bcryptjs");
|
|
144
|
-
return bcrypt.hash(password, 10);
|
|
145
|
-
} catch (error) {
|
|
146
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
147
|
-
throw new Error("bcryptjs not installed. Run: npm install bcryptjs @types/bcryptjs");
|
|
148
|
-
}
|
|
149
|
-
throw error;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
async comparePasswords(password, hashedPassword) {
|
|
153
|
-
try {
|
|
154
|
-
const bcrypt = await import("bcryptjs");
|
|
155
|
-
return bcrypt.compare(password, hashedPassword);
|
|
156
|
-
} catch (error) {
|
|
157
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
158
|
-
throw new Error("bcryptjs not installed. Run: npm install bcryptjs @types/bcryptjs");
|
|
159
|
-
}
|
|
160
|
-
throw error;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
generateToken(user) {
|
|
164
|
-
try {
|
|
165
|
-
const jwt = __require("jsonwebtoken");
|
|
166
|
-
const options = {};
|
|
167
|
-
if (this.config.expiresIn) {
|
|
168
|
-
options.expiresIn = this.config.expiresIn;
|
|
169
|
-
}
|
|
170
|
-
return jwt.sign(
|
|
171
|
-
{ id: user.id, username: user.username, roles: user.roles || [] },
|
|
172
|
-
this.config.secret,
|
|
173
|
-
options
|
|
174
|
-
);
|
|
175
|
-
} catch (error) {
|
|
176
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
177
|
-
throw new Error("jsonwebtoken not installed. Run: npm install jsonwebtoken @types/jsonwebtoken");
|
|
178
|
-
}
|
|
179
|
-
throw error;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
verifyToken(token) {
|
|
183
|
-
try {
|
|
184
|
-
const jwt = __require("jsonwebtoken");
|
|
185
|
-
return jwt.verify(token, this.config.secret);
|
|
186
|
-
} catch (error) {
|
|
187
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
188
|
-
throw new Error("jsonwebtoken not installed. Run: npm install jsonwebtoken @types/jsonwebtoken");
|
|
189
|
-
}
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
// Express middleware for authentication
|
|
194
|
-
initialize() {
|
|
195
|
-
return (req, res, next) => {
|
|
196
|
-
const token = this.extractToken(req);
|
|
197
|
-
if (token) {
|
|
198
|
-
const decoded = this.verifyToken(token);
|
|
199
|
-
if (decoded) {
|
|
200
|
-
req.user = decoded;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
next();
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
// Express middleware for requiring authentication
|
|
207
|
-
requireAuth() {
|
|
208
|
-
return (req, res, next) => {
|
|
209
|
-
if (!req.user) {
|
|
210
|
-
return res.status(401).json({ message: "Unauthorized" });
|
|
211
|
-
}
|
|
212
|
-
return next();
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
// Express middleware for requiring specific roles
|
|
216
|
-
requireRoles(roles) {
|
|
217
|
-
return (req, res, next) => {
|
|
218
|
-
if (!req.user) {
|
|
219
|
-
return res.status(401).json({ message: "Unauthorized" });
|
|
220
|
-
}
|
|
221
|
-
const userRoles = req.user.roles || [];
|
|
222
|
-
const hasRequiredRole = roles.some((role) => userRoles.includes(role));
|
|
223
|
-
if (!hasRequiredRole) {
|
|
224
|
-
return res.status(403).json({ message: "Forbidden" });
|
|
225
|
-
}
|
|
226
|
-
return next();
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
extractToken(req) {
|
|
230
|
-
if (req.headers.authorization && req.headers.authorization.startsWith("Bearer ")) {
|
|
231
|
-
return req.headers.authorization.substring(7);
|
|
232
|
-
}
|
|
233
|
-
return null;
|
|
19
|
+
var __copyProps = (to, from, except, desc) => {
|
|
20
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
21
|
+
for (let key of __getOwnPropNames(from))
|
|
22
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
23
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
234
24
|
}
|
|
25
|
+
return to;
|
|
235
26
|
};
|
|
27
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
236
28
|
|
|
237
|
-
// src/
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
var ApiRouter = class {
|
|
242
|
-
constructor(apiDir, auth = null) {
|
|
243
|
-
this.router = null;
|
|
244
|
-
this.apiDir = path.resolve(process.cwd(), apiDir);
|
|
245
|
-
this.auth = auth;
|
|
246
|
-
this.initializeRouter();
|
|
247
|
-
}
|
|
248
|
-
async initializeRouter() {
|
|
249
|
-
try {
|
|
250
|
-
const express = await import("express");
|
|
251
|
-
this.router = express.default.Router();
|
|
252
|
-
this.setupRoutes();
|
|
253
|
-
} catch (error) {
|
|
254
|
-
if (error.code === "MODULE_NOT_FOUND") {
|
|
255
|
-
throw new Error("Express not installed. Run: npm install express @types/express");
|
|
256
|
-
}
|
|
257
|
-
throw error;
|
|
258
|
-
}
|
|
29
|
+
// src/wasm.ts
|
|
30
|
+
async function loadGoWasm(wasmUrl, options = {}) {
|
|
31
|
+
if (typeof window === "undefined") {
|
|
32
|
+
throw new Error("loadGoWasm() is for browser use only. Use loadGoWasmFromFile() in Node.js.");
|
|
259
33
|
}
|
|
260
|
-
|
|
261
|
-
if (!
|
|
262
|
-
|
|
263
|
-
return;
|
|
34
|
+
try {
|
|
35
|
+
if (!window.Go) {
|
|
36
|
+
throw new Error("Go WASM runtime not available. Make sure wasm_exec.js is loaded.");
|
|
264
37
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
scanDirectory(dirPath, routePrefix) {
|
|
268
|
-
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
269
|
-
for (const entry of entries) {
|
|
270
|
-
const fullPath = path.join(dirPath, entry.name);
|
|
271
|
-
if (entry.isDirectory()) {
|
|
272
|
-
this.scanDirectory(fullPath, `${routePrefix}/${entry.name}`);
|
|
273
|
-
} else if (this.isRouteFile(entry.name)) {
|
|
274
|
-
const routePath = this.getRoutePath(entry.name, routePrefix);
|
|
275
|
-
this.registerRoute(fullPath, routePath);
|
|
276
|
-
}
|
|
38
|
+
if (options.debug) {
|
|
39
|
+
console.log("[WASM] Loading WASM from:", wasmUrl);
|
|
277
40
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
getRoutePath(filename, routePrefix) {
|
|
283
|
-
const baseName = path.basename(filename, path.extname(filename));
|
|
284
|
-
if (baseName === "index") {
|
|
285
|
-
return routePrefix || "/";
|
|
41
|
+
const response = await fetch(wasmUrl);
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
throw new Error(`Failed to fetch WASM file: ${response.status}`);
|
|
286
44
|
}
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
45
|
+
const wasmBytes = await response.arrayBuffer();
|
|
46
|
+
const go = new window.Go();
|
|
47
|
+
const wasmModule = await WebAssembly.instantiate(wasmBytes, go.importObject);
|
|
48
|
+
go.run(wasmModule.instance);
|
|
49
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
50
|
+
if (options.debug) {
|
|
51
|
+
console.log("[WASM] Go program started, checking for registered functions...");
|
|
290
52
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (process.platform === "win32") {
|
|
298
|
-
const urlWithTimestamp = `${fileUrl}?t=${Date.now()}`;
|
|
299
|
-
const routeModule = await import(urlWithTimestamp);
|
|
300
|
-
if (!this.isValidRouteModule(routeModule)) {
|
|
301
|
-
console.warn(`Invalid route module: ${filePath}`);
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
console.log(`Registering API route: ${routePath}`);
|
|
305
|
-
const middleware = routeModule.middleware || [];
|
|
306
|
-
for (const method of ["get", "post", "put", "delete", "patch", "options"]) {
|
|
307
|
-
const handler = routeModule[method];
|
|
308
|
-
if (typeof handler === "function") {
|
|
309
|
-
const routerMethod = this.router[method];
|
|
310
|
-
routerMethod.call(
|
|
311
|
-
this.router,
|
|
312
|
-
routePath,
|
|
313
|
-
...middleware,
|
|
314
|
-
this.wrapHandler(handler)
|
|
315
|
-
);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
} else {
|
|
319
|
-
const routeModule = await import(fileUrl);
|
|
320
|
-
if (!this.isValidRouteModule(routeModule)) {
|
|
321
|
-
console.warn(`Invalid route module: ${filePath}`);
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
console.log(`Registering API route: ${routePath}`);
|
|
325
|
-
const middleware = routeModule.middleware || [];
|
|
326
|
-
for (const method of ["get", "post", "put", "delete", "patch", "options"]) {
|
|
327
|
-
const handler = routeModule[method];
|
|
328
|
-
if (typeof handler === "function") {
|
|
329
|
-
const routerMethod = this.router[method];
|
|
330
|
-
routerMethod.call(
|
|
331
|
-
this.router,
|
|
332
|
-
routePath,
|
|
333
|
-
...middleware,
|
|
334
|
-
this.wrapHandler(handler)
|
|
335
|
-
);
|
|
336
|
-
}
|
|
53
|
+
const functions = {};
|
|
54
|
+
for (const key in window) {
|
|
55
|
+
if (typeof window[key] === "function" && key.startsWith("go")) {
|
|
56
|
+
functions[key] = window[key];
|
|
57
|
+
if (options.debug) {
|
|
58
|
+
console.log(`[WASM] Found function: ${key}`);
|
|
337
59
|
}
|
|
338
60
|
}
|
|
339
|
-
} catch (error) {
|
|
340
|
-
console.error(`Error registering route (${filePath}):`, error);
|
|
341
61
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
}
|
|
348
|
-
wrapHandler(handler) {
|
|
349
|
-
return async (req, res, next) => {
|
|
350
|
-
try {
|
|
351
|
-
await handler(req, res, next);
|
|
352
|
-
} catch (error) {
|
|
353
|
-
next(error);
|
|
354
|
-
}
|
|
62
|
+
const wasmInstance = {
|
|
63
|
+
instance: wasmModule.instance,
|
|
64
|
+
module: wasmModule,
|
|
65
|
+
exports: wasmModule.instance.exports,
|
|
66
|
+
functions
|
|
355
67
|
};
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
// src/server/middleware.ts
|
|
360
|
-
var requestLogger = (req, res, next) => {
|
|
361
|
-
console.log(`${(/* @__PURE__ */ new Date()).toISOString()} - ${req.method} ${req.url}`);
|
|
362
|
-
next();
|
|
363
|
-
};
|
|
364
|
-
var errorHandler = (err, req, res, next) => {
|
|
365
|
-
console.error(err.stack);
|
|
366
|
-
res.status(500).json({
|
|
367
|
-
error: {
|
|
368
|
-
message: "Internal Server Error",
|
|
369
|
-
...process.env.NODE_ENV !== "production" ? { details: err.message, stack: err.stack } : {}
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
};
|
|
373
|
-
var notFoundHandler = (req, res) => {
|
|
374
|
-
res.status(404).json({
|
|
375
|
-
error: {
|
|
376
|
-
message: `Not Found - ${req.method} ${req.url}`
|
|
68
|
+
if (options.onLoad) {
|
|
69
|
+
options.onLoad(wasmInstance);
|
|
377
70
|
}
|
|
378
|
-
|
|
379
|
-
};
|
|
380
|
-
function rateLimit(options) {
|
|
381
|
-
const requests = /* @__PURE__ */ new Map();
|
|
382
|
-
return (req, res, next) => {
|
|
383
|
-
const ip = req.ip || req.socket.remoteAddress || "unknown";
|
|
384
|
-
const now = Date.now();
|
|
385
|
-
const reqTimes = (requests.get(ip) || []).filter((time) => now - time < options.windowMs);
|
|
386
|
-
reqTimes.push(now);
|
|
387
|
-
requests.set(ip, reqTimes);
|
|
388
|
-
if (reqTimes.length > options.max) {
|
|
389
|
-
return res.status(429).json({
|
|
390
|
-
error: {
|
|
391
|
-
message: "Too Many Requests",
|
|
392
|
-
retryAfter: Math.ceil(options.windowMs / 1e3)
|
|
393
|
-
}
|
|
394
|
-
});
|
|
71
|
+
if (options.debug) {
|
|
72
|
+
console.log(`[WASM] Module loaded successfully with ${Object.keys(functions).length} functions`);
|
|
395
73
|
}
|
|
396
|
-
return
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// src/server/utils.ts
|
|
401
|
-
var utils_exports = {};
|
|
402
|
-
__export(utils_exports, {
|
|
403
|
-
ensureDirectory: () => ensureDirectory,
|
|
404
|
-
generateToken: () => generateToken,
|
|
405
|
-
getEnvironmentInfo: () => getEnvironmentInfo,
|
|
406
|
-
getPagination: () => getPagination,
|
|
407
|
-
hashString: () => hashString,
|
|
408
|
-
isDirectoryEmpty: () => isDirectoryEmpty,
|
|
409
|
-
readJsonFile: () => readJsonFile,
|
|
410
|
-
safeJsonParse: () => safeJsonParse,
|
|
411
|
-
sendError: () => sendError,
|
|
412
|
-
sendSuccess: () => sendSuccess,
|
|
413
|
-
validateFields: () => validateFields,
|
|
414
|
-
validateFileUpload: () => validateFileUpload,
|
|
415
|
-
writeJsonFile: () => writeJsonFile
|
|
416
|
-
});
|
|
417
|
-
import crypto from "crypto";
|
|
418
|
-
import fs2 from "fs/promises";
|
|
419
|
-
import path2 from "path";
|
|
420
|
-
function safeJsonParse(json, fallback) {
|
|
421
|
-
try {
|
|
422
|
-
return JSON.parse(json);
|
|
74
|
+
return wasmInstance;
|
|
423
75
|
} catch (error) {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
function generateToken(length = 32) {
|
|
428
|
-
return crypto.randomBytes(length).toString("hex");
|
|
429
|
-
}
|
|
430
|
-
function hashString(input, salt = "") {
|
|
431
|
-
return crypto.createHash("sha256").update(input + salt).digest("hex");
|
|
432
|
-
}
|
|
433
|
-
function getPagination(req) {
|
|
434
|
-
const page = Math.max(1, parseInt(req.query.page) || 1);
|
|
435
|
-
const rawLimit = parseInt(req.query.limit);
|
|
436
|
-
let limit;
|
|
437
|
-
if (isNaN(rawLimit) || rawLimit <= 0) {
|
|
438
|
-
limit = 20;
|
|
439
|
-
} else {
|
|
440
|
-
limit = Math.max(1, Math.min(100, rawLimit));
|
|
76
|
+
console.error("[WASM] Error loading Go WASM module:", error);
|
|
77
|
+
throw error;
|
|
441
78
|
}
|
|
442
|
-
const skip = (page - 1) * limit;
|
|
443
|
-
return { page, limit, skip };
|
|
444
|
-
}
|
|
445
|
-
function sendSuccess(res, data, message = "Success") {
|
|
446
|
-
return res.json({
|
|
447
|
-
success: true,
|
|
448
|
-
message,
|
|
449
|
-
data
|
|
450
|
-
});
|
|
451
|
-
}
|
|
452
|
-
function sendError(res, message = "An error occurred", statusCode = 400, errors) {
|
|
453
|
-
return res.status(statusCode).json({
|
|
454
|
-
success: false,
|
|
455
|
-
message,
|
|
456
|
-
errors: errors || void 0
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
function validateFields(req, requiredFields) {
|
|
460
|
-
const missing = requiredFields.filter((field) => {
|
|
461
|
-
const value = req.body[field];
|
|
462
|
-
return value === void 0 || value === null || value === "";
|
|
463
|
-
});
|
|
464
|
-
return {
|
|
465
|
-
valid: missing.length === 0,
|
|
466
|
-
missing
|
|
467
|
-
};
|
|
468
79
|
}
|
|
469
|
-
function
|
|
470
|
-
if (
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
if (options.maxSize && file.size > options.maxSize) {
|
|
474
|
-
return {
|
|
475
|
-
valid: false,
|
|
476
|
-
error: `File too large. Maximum size allowed is ${options.maxSize / 1024 / 1024}MB`
|
|
477
|
-
};
|
|
80
|
+
function callWasmFunction(funcName, ...args) {
|
|
81
|
+
if (typeof window === "undefined") {
|
|
82
|
+
throw new Error("callWasmFunction() is for browser use only.");
|
|
478
83
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return {
|
|
483
|
-
valid: false,
|
|
484
|
-
error: `Invalid file type. Allowed types: ${options.allowedTypes.join(", ")}`
|
|
485
|
-
};
|
|
486
|
-
}
|
|
84
|
+
const func = window[funcName];
|
|
85
|
+
if (typeof func !== "function") {
|
|
86
|
+
throw new Error(`Function ${funcName} not found. Make sure the WASM module is loaded.`);
|
|
487
87
|
}
|
|
488
|
-
return
|
|
88
|
+
return func(...args);
|
|
489
89
|
}
|
|
490
|
-
function
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
platform: process.platform,
|
|
494
|
-
arch: process.arch,
|
|
495
|
-
memory: process.memoryUsage(),
|
|
496
|
-
uptime: process.uptime(),
|
|
497
|
-
env: process.env.NODE_ENV || "development"
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
async function isDirectoryEmpty(dirPath) {
|
|
501
|
-
try {
|
|
502
|
-
const files = await fs2.readdir(dirPath);
|
|
503
|
-
return files.length === 0;
|
|
504
|
-
} catch (error) {
|
|
505
|
-
return true;
|
|
90
|
+
function isWasmReady() {
|
|
91
|
+
if (typeof window === "undefined") {
|
|
92
|
+
return false;
|
|
506
93
|
}
|
|
94
|
+
return !!(window.Go && Object.keys(window).some(
|
|
95
|
+
(key) => key.startsWith("go") && typeof window[key] === "function"
|
|
96
|
+
));
|
|
507
97
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
} catch (error) {
|
|
512
|
-
await fs2.mkdir(dirPath, { recursive: true });
|
|
98
|
+
function getWasmFunctions() {
|
|
99
|
+
if (typeof window === "undefined") {
|
|
100
|
+
return [];
|
|
513
101
|
}
|
|
102
|
+
return Object.keys(window).filter(
|
|
103
|
+
(key) => key.startsWith("go") && typeof window[key] === "function"
|
|
104
|
+
);
|
|
514
105
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
async function readJsonFile(filePath, defaultValue) {
|
|
520
|
-
try {
|
|
521
|
-
const data = await fs2.readFile(filePath, "utf8");
|
|
522
|
-
return safeJsonParse(data, defaultValue);
|
|
523
|
-
} catch (error) {
|
|
524
|
-
return defaultValue;
|
|
106
|
+
function useGoWasm(wasmUrl, options = {}) {
|
|
107
|
+
if (typeof window === "undefined") {
|
|
108
|
+
throw new Error("useGoWasm() is for browser use only.");
|
|
525
109
|
}
|
|
110
|
+
return {
|
|
111
|
+
loadWasm: () => loadGoWasm(wasmUrl, options),
|
|
112
|
+
callFunction: callWasmFunction,
|
|
113
|
+
isReady: isWasmReady,
|
|
114
|
+
getFunctions: getWasmFunctions
|
|
115
|
+
};
|
|
526
116
|
}
|
|
117
|
+
var init_wasm = __esm({
|
|
118
|
+
"src/wasm.ts"() {
|
|
119
|
+
"use strict";
|
|
120
|
+
}
|
|
121
|
+
});
|
|
527
122
|
|
|
528
123
|
// src/server/templates.ts
|
|
529
124
|
var templates_exports = {};
|
|
@@ -717,13 +312,762 @@ function generateLoadingPage(message = "Loading...") {
|
|
|
717
312
|
function escapeHtml(text) {
|
|
718
313
|
return String(text).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
719
314
|
}
|
|
315
|
+
var init_templates = __esm({
|
|
316
|
+
"src/server/templates.ts"() {
|
|
317
|
+
"use strict";
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// src/server/utils.ts
|
|
322
|
+
var utils_exports = {};
|
|
323
|
+
__export(utils_exports, {
|
|
324
|
+
ensureDirectory: () => ensureDirectory,
|
|
325
|
+
generateToken: () => generateToken,
|
|
326
|
+
getEnvironmentInfo: () => getEnvironmentInfo,
|
|
327
|
+
getPagination: () => getPagination,
|
|
328
|
+
hashString: () => hashString,
|
|
329
|
+
isDirectoryEmpty: () => isDirectoryEmpty,
|
|
330
|
+
readJsonFile: () => readJsonFile,
|
|
331
|
+
safeJsonParse: () => safeJsonParse,
|
|
332
|
+
sendError: () => sendError,
|
|
333
|
+
sendSuccess: () => sendSuccess,
|
|
334
|
+
validateFields: () => validateFields,
|
|
335
|
+
validateFileUpload: () => validateFileUpload,
|
|
336
|
+
writeJsonFile: () => writeJsonFile
|
|
337
|
+
});
|
|
338
|
+
import crypto2 from "crypto";
|
|
339
|
+
import fs from "fs/promises";
|
|
340
|
+
import path from "path";
|
|
341
|
+
function safeJsonParse(json, fallback) {
|
|
342
|
+
try {
|
|
343
|
+
return JSON.parse(json);
|
|
344
|
+
} catch (error) {
|
|
345
|
+
return fallback;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function generateToken(length = 32) {
|
|
349
|
+
return crypto2.randomBytes(length).toString("hex");
|
|
350
|
+
}
|
|
351
|
+
function hashString(input, salt = "") {
|
|
352
|
+
return crypto2.createHash("sha256").update(input + salt).digest("hex");
|
|
353
|
+
}
|
|
354
|
+
function getPagination(req) {
|
|
355
|
+
const page = Math.max(1, parseInt(req.query.page) || 1);
|
|
356
|
+
const rawLimit = parseInt(req.query.limit);
|
|
357
|
+
let limit;
|
|
358
|
+
if (isNaN(rawLimit) || rawLimit <= 0) {
|
|
359
|
+
limit = 20;
|
|
360
|
+
} else {
|
|
361
|
+
limit = Math.max(1, Math.min(100, rawLimit));
|
|
362
|
+
}
|
|
363
|
+
const skip = (page - 1) * limit;
|
|
364
|
+
return { page, limit, skip };
|
|
365
|
+
}
|
|
366
|
+
function sendSuccess(res, data, message = "Success") {
|
|
367
|
+
return res.json({
|
|
368
|
+
success: true,
|
|
369
|
+
message,
|
|
370
|
+
data
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
function sendError(res, message = "An error occurred", statusCode = 400, errors) {
|
|
374
|
+
return res.status(statusCode).json({
|
|
375
|
+
success: false,
|
|
376
|
+
message,
|
|
377
|
+
errors: errors || void 0
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
function validateFields(req, requiredFields) {
|
|
381
|
+
const missing = requiredFields.filter((field) => {
|
|
382
|
+
const value = req.body[field];
|
|
383
|
+
return value === void 0 || value === null || value === "";
|
|
384
|
+
});
|
|
385
|
+
return {
|
|
386
|
+
valid: missing.length === 0,
|
|
387
|
+
missing
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function validateFileUpload(file, options = {}) {
|
|
391
|
+
if (!file) {
|
|
392
|
+
return { valid: false, error: "No file provided" };
|
|
393
|
+
}
|
|
394
|
+
if (options.maxSize && file.size > options.maxSize) {
|
|
395
|
+
return {
|
|
396
|
+
valid: false,
|
|
397
|
+
error: `File too large. Maximum size allowed is ${options.maxSize / 1024 / 1024}MB`
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
if (options.allowedTypes && options.allowedTypes.length > 0) {
|
|
401
|
+
const fileType = file.mimetype;
|
|
402
|
+
if (!options.allowedTypes.includes(fileType)) {
|
|
403
|
+
return {
|
|
404
|
+
valid: false,
|
|
405
|
+
error: `Invalid file type. Allowed types: ${options.allowedTypes.join(", ")}`
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return { valid: true };
|
|
410
|
+
}
|
|
411
|
+
function getEnvironmentInfo() {
|
|
412
|
+
return {
|
|
413
|
+
nodeVersion: process.version,
|
|
414
|
+
platform: process.platform,
|
|
415
|
+
arch: process.arch,
|
|
416
|
+
memory: process.memoryUsage(),
|
|
417
|
+
uptime: process.uptime(),
|
|
418
|
+
env: process.env.NODE_ENV || "development"
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
async function isDirectoryEmpty(dirPath) {
|
|
422
|
+
try {
|
|
423
|
+
const files = await fs.readdir(dirPath);
|
|
424
|
+
return files.length === 0;
|
|
425
|
+
} catch (error) {
|
|
426
|
+
return true;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
async function ensureDirectory(dirPath) {
|
|
430
|
+
try {
|
|
431
|
+
await fs.access(dirPath);
|
|
432
|
+
} catch (error) {
|
|
433
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
async function writeJsonFile(filePath, data) {
|
|
437
|
+
await ensureDirectory(path.dirname(filePath));
|
|
438
|
+
await fs.writeFile(filePath, JSON.stringify(data, null, 2), "utf8");
|
|
439
|
+
}
|
|
440
|
+
async function readJsonFile(filePath, defaultValue) {
|
|
441
|
+
try {
|
|
442
|
+
const data = await fs.readFile(filePath, "utf8");
|
|
443
|
+
return safeJsonParse(data, defaultValue);
|
|
444
|
+
} catch (error) {
|
|
445
|
+
return defaultValue;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
var init_utils = __esm({
|
|
449
|
+
"src/server/utils.ts"() {
|
|
450
|
+
"use strict";
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// src/server-renderer.ts
|
|
455
|
+
var server_renderer_exports = {};
|
|
456
|
+
__export(server_renderer_exports, {
|
|
457
|
+
renderToString: () => renderToString
|
|
458
|
+
});
|
|
459
|
+
function renderToString(component) {
|
|
460
|
+
try {
|
|
461
|
+
if (typeof component === "function") {
|
|
462
|
+
const result = component();
|
|
463
|
+
if (typeof result === "string") {
|
|
464
|
+
return result;
|
|
465
|
+
}
|
|
466
|
+
if (result && typeof result === "object") {
|
|
467
|
+
return JSON.stringify(result);
|
|
468
|
+
}
|
|
469
|
+
return String(result || "");
|
|
470
|
+
}
|
|
471
|
+
if (typeof component === "string") {
|
|
472
|
+
return component;
|
|
473
|
+
}
|
|
474
|
+
return String(component || "");
|
|
475
|
+
} catch (error) {
|
|
476
|
+
console.error("Error in renderToString:", error);
|
|
477
|
+
return "<div>Error rendering component</div>";
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
var init_server_renderer = __esm({
|
|
481
|
+
"src/server-renderer.ts"() {
|
|
482
|
+
"use strict";
|
|
483
|
+
}
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
// src/index.ts
|
|
487
|
+
var src_exports = {};
|
|
488
|
+
__export(src_exports, {
|
|
489
|
+
ApiRouter: () => ApiRouter,
|
|
490
|
+
AuthService: () => AuthService,
|
|
491
|
+
BaraqexServer: () => BaraqexServer,
|
|
492
|
+
Database: () => Database,
|
|
493
|
+
baraqexRenderToString: () => baraqexRenderToString,
|
|
494
|
+
callWasmFunction: () => callWasmFunction,
|
|
495
|
+
createBaraqexServer: () => createBaraqexServer,
|
|
496
|
+
createDevServer: () => createDevServer,
|
|
497
|
+
createProductionServer: () => createProductionServer,
|
|
498
|
+
createServer: () => createServer,
|
|
499
|
+
ensureDirectory: () => ensureDirectory2,
|
|
500
|
+
errorHandler: () => errorHandler,
|
|
501
|
+
generateDocument: () => generateDocument,
|
|
502
|
+
generateErrorPage: () => generateErrorPage,
|
|
503
|
+
generateLoadingPage: () => generateLoadingPage,
|
|
504
|
+
generateToken: () => generateToken2,
|
|
505
|
+
getEnvironmentInfo: () => getEnvironmentInfo2,
|
|
506
|
+
getPagination: () => getPagination2,
|
|
507
|
+
getWasmFunctions: () => getWasmFunctions,
|
|
508
|
+
hashString: () => hashString2,
|
|
509
|
+
initNodeWasm: () => initNodeWasm,
|
|
510
|
+
isDirectoryEmpty: () => isDirectoryEmpty2,
|
|
511
|
+
isWasmReady: () => isWasmReady,
|
|
512
|
+
loadGoWasm: () => loadGoWasm,
|
|
513
|
+
loadGoWasmFromFile: () => loadGoWasmFromFile,
|
|
514
|
+
notFoundHandler: () => notFoundHandler,
|
|
515
|
+
rateLimit: () => rateLimit,
|
|
516
|
+
readJsonFile: () => readJsonFile2,
|
|
517
|
+
renderComponent: () => renderComponent,
|
|
518
|
+
requestLogger: () => requestLogger,
|
|
519
|
+
safeJsonParse: () => safeJsonParse2,
|
|
520
|
+
sendError: () => sendError2,
|
|
521
|
+
sendSuccess: () => sendSuccess2,
|
|
522
|
+
useGoWasm: () => useGoWasm,
|
|
523
|
+
validateFields: () => validateFields2,
|
|
524
|
+
validateFileUpload: () => validateFileUpload2,
|
|
525
|
+
writeJsonFile: () => writeJsonFile2
|
|
526
|
+
});
|
|
527
|
+
import * as frontend_hamroun_star from "frontend-hamroun";
|
|
528
|
+
function createBaraqexServer(options = {}) {
|
|
529
|
+
return new Promise((resolve, reject) => {
|
|
530
|
+
const checkServer = () => {
|
|
531
|
+
if (createDevServer && typeof createDevServer === "function") {
|
|
532
|
+
resolve(createDevServer(options));
|
|
533
|
+
} else if (isNode) {
|
|
534
|
+
setTimeout(checkServer, 100);
|
|
535
|
+
} else {
|
|
536
|
+
reject(new Error("Server functionality not available in browser environment"));
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
checkServer();
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
var isNode, isBrowser, BaraqexServer, createServer, createDevServer, createProductionServer, renderComponent, Database, AuthService, ApiRouter, requestLogger, errorHandler, notFoundHandler, rateLimit, initNodeWasm, loadGoWasmFromFile, safeJsonParse2, generateToken2, hashString2, getPagination2, sendSuccess2, sendError2, validateFields2, validateFileUpload2, getEnvironmentInfo2, isDirectoryEmpty2, ensureDirectory2, writeJsonFile2, readJsonFile2, baraqexRenderToString;
|
|
543
|
+
var init_src = __esm({
|
|
544
|
+
"src/index.ts"() {
|
|
545
|
+
"use strict";
|
|
546
|
+
__reExport(src_exports, frontend_hamroun_star);
|
|
547
|
+
init_wasm();
|
|
548
|
+
init_templates();
|
|
549
|
+
isNode = typeof process !== "undefined" && process.versions?.node;
|
|
550
|
+
isBrowser = typeof window !== "undefined";
|
|
551
|
+
BaraqexServer = null;
|
|
552
|
+
createServer = null;
|
|
553
|
+
createDevServer = null;
|
|
554
|
+
createProductionServer = null;
|
|
555
|
+
renderComponent = null;
|
|
556
|
+
Database = null;
|
|
557
|
+
AuthService = null;
|
|
558
|
+
ApiRouter = null;
|
|
559
|
+
requestLogger = null;
|
|
560
|
+
errorHandler = null;
|
|
561
|
+
notFoundHandler = null;
|
|
562
|
+
rateLimit = null;
|
|
563
|
+
initNodeWasm = null;
|
|
564
|
+
loadGoWasmFromFile = null;
|
|
565
|
+
safeJsonParse2 = (json, fallback) => {
|
|
566
|
+
try {
|
|
567
|
+
return JSON.parse(json);
|
|
568
|
+
} catch {
|
|
569
|
+
return fallback;
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
generateToken2 = (length = 32) => {
|
|
573
|
+
const array = new Uint8Array(length);
|
|
574
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
575
|
+
crypto.getRandomValues(array);
|
|
576
|
+
} else {
|
|
577
|
+
for (let i = 0; i < array.length; i++) {
|
|
578
|
+
array[i] = Math.floor(Math.random() * 256);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
582
|
+
};
|
|
583
|
+
hashString2 = null;
|
|
584
|
+
getPagination2 = null;
|
|
585
|
+
sendSuccess2 = null;
|
|
586
|
+
sendError2 = null;
|
|
587
|
+
validateFields2 = null;
|
|
588
|
+
validateFileUpload2 = null;
|
|
589
|
+
getEnvironmentInfo2 = null;
|
|
590
|
+
isDirectoryEmpty2 = null;
|
|
591
|
+
ensureDirectory2 = null;
|
|
592
|
+
writeJsonFile2 = null;
|
|
593
|
+
readJsonFile2 = null;
|
|
594
|
+
baraqexRenderToString = null;
|
|
595
|
+
if (isNode && !isBrowser) {
|
|
596
|
+
Promise.resolve().then(async () => {
|
|
597
|
+
try {
|
|
598
|
+
try {
|
|
599
|
+
await import("express");
|
|
600
|
+
} catch {
|
|
601
|
+
console.warn("Express not available - server functionality disabled");
|
|
602
|
+
return;
|
|
603
|
+
}
|
|
604
|
+
const serverModule = await Promise.resolve().then(() => (init_server(), server_exports));
|
|
605
|
+
Object.assign(exports, {
|
|
606
|
+
BaraqexServer: serverModule.Server,
|
|
607
|
+
createServer: serverModule.createServer,
|
|
608
|
+
createDevServer: serverModule.createDevServer,
|
|
609
|
+
createProductionServer: serverModule.createProductionServer,
|
|
610
|
+
renderComponent: serverModule.renderComponent,
|
|
611
|
+
Database: serverModule.Database,
|
|
612
|
+
AuthService: serverModule.AuthService,
|
|
613
|
+
ApiRouter: serverModule.ApiRouter,
|
|
614
|
+
requestLogger: serverModule.requestLogger,
|
|
615
|
+
errorHandler: serverModule.errorHandler,
|
|
616
|
+
notFoundHandler: serverModule.notFoundHandler,
|
|
617
|
+
rateLimit: serverModule.rateLimit,
|
|
618
|
+
initNodeWasm: serverModule.initNodeWasm,
|
|
619
|
+
loadGoWasmFromFile: serverModule.loadGoWasmFromFile
|
|
620
|
+
});
|
|
621
|
+
BaraqexServer = serverModule.Server;
|
|
622
|
+
createServer = serverModule.createServer;
|
|
623
|
+
createDevServer = serverModule.createDevServer;
|
|
624
|
+
createProductionServer = serverModule.createProductionServer;
|
|
625
|
+
renderComponent = serverModule.renderComponent;
|
|
626
|
+
Database = serverModule.Database;
|
|
627
|
+
AuthService = serverModule.AuthService;
|
|
628
|
+
ApiRouter = serverModule.ApiRouter;
|
|
629
|
+
requestLogger = serverModule.requestLogger;
|
|
630
|
+
errorHandler = serverModule.errorHandler;
|
|
631
|
+
notFoundHandler = serverModule.notFoundHandler;
|
|
632
|
+
rateLimit = serverModule.rateLimit;
|
|
633
|
+
initNodeWasm = serverModule.initNodeWasm;
|
|
634
|
+
loadGoWasmFromFile = serverModule.loadGoWasmFromFile;
|
|
635
|
+
const utilsModule = await Promise.resolve().then(() => (init_utils(), utils_exports));
|
|
636
|
+
safeJsonParse2 = utilsModule.safeJsonParse;
|
|
637
|
+
generateToken2 = utilsModule.generateToken;
|
|
638
|
+
hashString2 = utilsModule.hashString;
|
|
639
|
+
getPagination2 = utilsModule.getPagination;
|
|
640
|
+
sendSuccess2 = utilsModule.sendSuccess;
|
|
641
|
+
sendError2 = utilsModule.sendError;
|
|
642
|
+
validateFields2 = utilsModule.validateFields;
|
|
643
|
+
validateFileUpload2 = utilsModule.validateFileUpload;
|
|
644
|
+
getEnvironmentInfo2 = utilsModule.getEnvironmentInfo;
|
|
645
|
+
isDirectoryEmpty2 = utilsModule.isDirectoryEmpty;
|
|
646
|
+
ensureDirectory2 = utilsModule.ensureDirectory;
|
|
647
|
+
writeJsonFile2 = utilsModule.writeJsonFile;
|
|
648
|
+
readJsonFile2 = utilsModule.readJsonFile;
|
|
649
|
+
const rendererModule = await Promise.resolve().then(() => (init_server_renderer(), server_renderer_exports));
|
|
650
|
+
baraqexRenderToString = rendererModule.renderToString;
|
|
651
|
+
console.log("\u2705 Baraqex server modules loaded successfully");
|
|
652
|
+
} catch (error) {
|
|
653
|
+
console.warn("Server modules not available:", error.message);
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
console.log("Baraqex - powered by Frontend Hamroun Framework with additional utilities");
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
// src/server/database.ts
|
|
662
|
+
var Database2;
|
|
663
|
+
var init_database = __esm({
|
|
664
|
+
"src/server/database.ts"() {
|
|
665
|
+
"use strict";
|
|
666
|
+
Database2 = class {
|
|
667
|
+
constructor(config) {
|
|
668
|
+
this.mongoClient = null;
|
|
669
|
+
this.mongoDb = null;
|
|
670
|
+
this.mysqlPool = null;
|
|
671
|
+
this.pgPool = null;
|
|
672
|
+
this.config = config;
|
|
673
|
+
}
|
|
674
|
+
async connect() {
|
|
675
|
+
switch (this.config.type) {
|
|
676
|
+
case "mongodb":
|
|
677
|
+
await this.connectMongo();
|
|
678
|
+
break;
|
|
679
|
+
case "mysql":
|
|
680
|
+
await this.connectMysql();
|
|
681
|
+
break;
|
|
682
|
+
case "postgres":
|
|
683
|
+
await this.connectPostgres();
|
|
684
|
+
break;
|
|
685
|
+
default:
|
|
686
|
+
throw new Error(`Unsupported database type: ${this.config.type}`);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
async connectMongo() {
|
|
690
|
+
try {
|
|
691
|
+
const { MongoClient } = await import("mongodb");
|
|
692
|
+
this.mongoClient = new MongoClient(this.config.url);
|
|
693
|
+
await this.mongoClient.connect();
|
|
694
|
+
this.mongoDb = this.mongoClient.db();
|
|
695
|
+
console.log("Connected to MongoDB");
|
|
696
|
+
} catch (error) {
|
|
697
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
698
|
+
throw new Error("MongoDB driver not installed. Run: npm install mongodb");
|
|
699
|
+
}
|
|
700
|
+
console.error("MongoDB connection error:", error);
|
|
701
|
+
throw error;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
async connectMysql() {
|
|
705
|
+
try {
|
|
706
|
+
const mysql = await import("mysql2/promise");
|
|
707
|
+
this.mysqlPool = mysql.createPool(this.config.url);
|
|
708
|
+
await this.mysqlPool.getConnection();
|
|
709
|
+
console.log("Connected to MySQL");
|
|
710
|
+
} catch (error) {
|
|
711
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
712
|
+
throw new Error("MySQL driver not installed. Run: npm install mysql2");
|
|
713
|
+
}
|
|
714
|
+
console.error("MySQL connection error:", error);
|
|
715
|
+
throw error;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
async connectPostgres() {
|
|
719
|
+
try {
|
|
720
|
+
const pg = await import("pg");
|
|
721
|
+
this.pgPool = new pg.Pool({ connectionString: this.config.url });
|
|
722
|
+
const client = await this.pgPool.connect();
|
|
723
|
+
client.release();
|
|
724
|
+
console.log("Connected to PostgreSQL");
|
|
725
|
+
} catch (error) {
|
|
726
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
727
|
+
throw new Error("PostgreSQL driver not installed. Run: npm install pg @types/pg");
|
|
728
|
+
}
|
|
729
|
+
console.error("PostgreSQL connection error:", error);
|
|
730
|
+
throw error;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
async disconnect() {
|
|
734
|
+
if (this.mongoClient) {
|
|
735
|
+
await this.mongoClient.close();
|
|
736
|
+
this.mongoClient = null;
|
|
737
|
+
this.mongoDb = null;
|
|
738
|
+
}
|
|
739
|
+
if (this.mysqlPool) {
|
|
740
|
+
await this.mysqlPool.end();
|
|
741
|
+
this.mysqlPool = null;
|
|
742
|
+
}
|
|
743
|
+
if (this.pgPool) {
|
|
744
|
+
await this.pgPool.end();
|
|
745
|
+
this.pgPool = null;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
// Database-specific methods
|
|
749
|
+
getMongoDb() {
|
|
750
|
+
return this.mongoDb;
|
|
751
|
+
}
|
|
752
|
+
getMysqlPool() {
|
|
753
|
+
return this.mysqlPool;
|
|
754
|
+
}
|
|
755
|
+
getPgPool() {
|
|
756
|
+
return this.pgPool;
|
|
757
|
+
}
|
|
758
|
+
// Generic query method
|
|
759
|
+
async query(sql, values) {
|
|
760
|
+
switch (this.config.type) {
|
|
761
|
+
case "mongodb":
|
|
762
|
+
throw new Error("For MongoDB, use getMongoDb() instead of query()");
|
|
763
|
+
case "mysql":
|
|
764
|
+
if (!this.mysqlPool)
|
|
765
|
+
throw new Error("MySQL not connected");
|
|
766
|
+
const [rows] = await this.mysqlPool.execute(sql, values || []);
|
|
767
|
+
return rows;
|
|
768
|
+
case "postgres":
|
|
769
|
+
if (!this.pgPool)
|
|
770
|
+
throw new Error("PostgreSQL not connected");
|
|
771
|
+
const result = await this.pgPool.query(sql, values || []);
|
|
772
|
+
return result.rows;
|
|
773
|
+
default:
|
|
774
|
+
throw new Error(`Unsupported database type: ${this.config.type}`);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
// src/server/auth.ts
|
|
782
|
+
var AuthService2;
|
|
783
|
+
var init_auth = __esm({
|
|
784
|
+
"src/server/auth.ts"() {
|
|
785
|
+
"use strict";
|
|
786
|
+
AuthService2 = class {
|
|
787
|
+
constructor(config) {
|
|
788
|
+
this.config = {
|
|
789
|
+
expiresIn: "24h",
|
|
790
|
+
...config
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
async hashPassword(password) {
|
|
794
|
+
try {
|
|
795
|
+
const bcrypt = await import("bcryptjs");
|
|
796
|
+
return bcrypt.hash(password, 10);
|
|
797
|
+
} catch (error) {
|
|
798
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
799
|
+
throw new Error("bcryptjs not installed. Run: npm install bcryptjs @types/bcryptjs");
|
|
800
|
+
}
|
|
801
|
+
throw error;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
async comparePasswords(password, hashedPassword) {
|
|
805
|
+
try {
|
|
806
|
+
const bcrypt = await import("bcryptjs");
|
|
807
|
+
return bcrypt.compare(password, hashedPassword);
|
|
808
|
+
} catch (error) {
|
|
809
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
810
|
+
throw new Error("bcryptjs not installed. Run: npm install bcryptjs @types/bcryptjs");
|
|
811
|
+
}
|
|
812
|
+
throw error;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
generateToken(user) {
|
|
816
|
+
try {
|
|
817
|
+
const jwt = __require("jsonwebtoken");
|
|
818
|
+
const options = {};
|
|
819
|
+
if (this.config.expiresIn) {
|
|
820
|
+
options.expiresIn = this.config.expiresIn;
|
|
821
|
+
}
|
|
822
|
+
return jwt.sign(
|
|
823
|
+
{ id: user.id, username: user.username, roles: user.roles || [] },
|
|
824
|
+
this.config.secret,
|
|
825
|
+
options
|
|
826
|
+
);
|
|
827
|
+
} catch (error) {
|
|
828
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
829
|
+
throw new Error("jsonwebtoken not installed. Run: npm install jsonwebtoken @types/jsonwebtoken");
|
|
830
|
+
}
|
|
831
|
+
throw error;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
verifyToken(token) {
|
|
835
|
+
try {
|
|
836
|
+
const jwt = __require("jsonwebtoken");
|
|
837
|
+
return jwt.verify(token, this.config.secret);
|
|
838
|
+
} catch (error) {
|
|
839
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
840
|
+
throw new Error("jsonwebtoken not installed. Run: npm install jsonwebtoken @types/jsonwebtoken");
|
|
841
|
+
}
|
|
842
|
+
return null;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
// Express middleware for authentication
|
|
846
|
+
initialize() {
|
|
847
|
+
return (req, res, next) => {
|
|
848
|
+
const token = this.extractToken(req);
|
|
849
|
+
if (token) {
|
|
850
|
+
const decoded = this.verifyToken(token);
|
|
851
|
+
if (decoded) {
|
|
852
|
+
req.user = decoded;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
next();
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
// Express middleware for requiring authentication
|
|
859
|
+
requireAuth() {
|
|
860
|
+
return (req, res, next) => {
|
|
861
|
+
if (!req.user) {
|
|
862
|
+
return res.status(401).json({ message: "Unauthorized" });
|
|
863
|
+
}
|
|
864
|
+
return next();
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
// Express middleware for requiring specific roles
|
|
868
|
+
requireRoles(roles) {
|
|
869
|
+
return (req, res, next) => {
|
|
870
|
+
if (!req.user) {
|
|
871
|
+
return res.status(401).json({ message: "Unauthorized" });
|
|
872
|
+
}
|
|
873
|
+
const userRoles = req.user.roles || [];
|
|
874
|
+
const hasRequiredRole = roles.some((role) => userRoles.includes(role));
|
|
875
|
+
if (!hasRequiredRole) {
|
|
876
|
+
return res.status(403).json({ message: "Forbidden" });
|
|
877
|
+
}
|
|
878
|
+
return next();
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
extractToken(req) {
|
|
882
|
+
if (req.headers.authorization && req.headers.authorization.startsWith("Bearer ")) {
|
|
883
|
+
return req.headers.authorization.substring(7);
|
|
884
|
+
}
|
|
885
|
+
return null;
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
|
|
891
|
+
// src/server/api-router.ts
|
|
892
|
+
import path2 from "path";
|
|
893
|
+
import fs2 from "fs";
|
|
894
|
+
import { pathToFileURL } from "url";
|
|
895
|
+
var ApiRouter2;
|
|
896
|
+
var init_api_router = __esm({
|
|
897
|
+
"src/server/api-router.ts"() {
|
|
898
|
+
"use strict";
|
|
899
|
+
ApiRouter2 = class {
|
|
900
|
+
constructor(apiDir, auth = null) {
|
|
901
|
+
this.router = null;
|
|
902
|
+
this.apiDir = path2.resolve(process.cwd(), apiDir);
|
|
903
|
+
this.auth = auth;
|
|
904
|
+
this.initializeRouter();
|
|
905
|
+
}
|
|
906
|
+
async initializeRouter() {
|
|
907
|
+
try {
|
|
908
|
+
const express = await import("express");
|
|
909
|
+
this.router = express.default.Router();
|
|
910
|
+
this.setupRoutes();
|
|
911
|
+
} catch (error) {
|
|
912
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
913
|
+
throw new Error("Express not installed. Run: npm install express @types/express");
|
|
914
|
+
}
|
|
915
|
+
throw error;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
setupRoutes() {
|
|
919
|
+
if (!fs2.existsSync(this.apiDir)) {
|
|
920
|
+
console.log(`API directory not found: ${this.apiDir}`);
|
|
921
|
+
return;
|
|
922
|
+
}
|
|
923
|
+
this.scanDirectory(this.apiDir, "");
|
|
924
|
+
}
|
|
925
|
+
scanDirectory(dirPath, routePrefix) {
|
|
926
|
+
const entries = fs2.readdirSync(dirPath, { withFileTypes: true });
|
|
927
|
+
for (const entry of entries) {
|
|
928
|
+
const fullPath = path2.join(dirPath, entry.name);
|
|
929
|
+
if (entry.isDirectory()) {
|
|
930
|
+
this.scanDirectory(fullPath, `${routePrefix}/${entry.name}`);
|
|
931
|
+
} else if (this.isRouteFile(entry.name)) {
|
|
932
|
+
const routePath = this.getRoutePath(entry.name, routePrefix);
|
|
933
|
+
this.registerRoute(fullPath, routePath);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
isRouteFile(filename) {
|
|
938
|
+
return filename.endsWith(".js") || filename.endsWith(".ts") || filename.endsWith(".mjs");
|
|
939
|
+
}
|
|
940
|
+
getRoutePath(filename, routePrefix) {
|
|
941
|
+
const baseName = path2.basename(filename, path2.extname(filename));
|
|
942
|
+
if (baseName === "index") {
|
|
943
|
+
return routePrefix || "/";
|
|
944
|
+
}
|
|
945
|
+
const paramMatch = baseName.match(/^\[(.+)\]$/);
|
|
946
|
+
if (paramMatch) {
|
|
947
|
+
return `${routePrefix}/:${paramMatch[1]}`;
|
|
948
|
+
}
|
|
949
|
+
return `${routePrefix}/${baseName}`;
|
|
950
|
+
}
|
|
951
|
+
async registerRoute(filePath, routePath) {
|
|
952
|
+
try {
|
|
953
|
+
const absolutePath = path2.isAbsolute(filePath) ? filePath : path2.resolve(filePath);
|
|
954
|
+
const fileUrl = pathToFileURL(absolutePath).href;
|
|
955
|
+
if (process.platform === "win32") {
|
|
956
|
+
const urlWithTimestamp = `${fileUrl}?t=${Date.now()}`;
|
|
957
|
+
const routeModule = await import(urlWithTimestamp);
|
|
958
|
+
if (!this.isValidRouteModule(routeModule)) {
|
|
959
|
+
console.warn(`Invalid route module: ${filePath}`);
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
console.log(`Registering API route: ${routePath}`);
|
|
963
|
+
const middleware = routeModule.middleware || [];
|
|
964
|
+
for (const method of ["get", "post", "put", "delete", "patch", "options"]) {
|
|
965
|
+
const handler = routeModule[method];
|
|
966
|
+
if (typeof handler === "function") {
|
|
967
|
+
const routerMethod = this.router[method];
|
|
968
|
+
routerMethod.call(
|
|
969
|
+
this.router,
|
|
970
|
+
routePath,
|
|
971
|
+
...middleware,
|
|
972
|
+
this.wrapHandler(handler)
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
} else {
|
|
977
|
+
const routeModule = await import(fileUrl);
|
|
978
|
+
if (!this.isValidRouteModule(routeModule)) {
|
|
979
|
+
console.warn(`Invalid route module: ${filePath}`);
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
console.log(`Registering API route: ${routePath}`);
|
|
983
|
+
const middleware = routeModule.middleware || [];
|
|
984
|
+
for (const method of ["get", "post", "put", "delete", "patch", "options"]) {
|
|
985
|
+
const handler = routeModule[method];
|
|
986
|
+
if (typeof handler === "function") {
|
|
987
|
+
const routerMethod = this.router[method];
|
|
988
|
+
routerMethod.call(
|
|
989
|
+
this.router,
|
|
990
|
+
routePath,
|
|
991
|
+
...middleware,
|
|
992
|
+
this.wrapHandler(handler)
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
} catch (error) {
|
|
998
|
+
console.error(`Error registering route (${filePath}):`, error);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
isValidRouteModule(module) {
|
|
1002
|
+
if (!module)
|
|
1003
|
+
return false;
|
|
1004
|
+
return ["get", "post", "put", "delete", "patch", "options"].some((method) => typeof module[method] === "function");
|
|
1005
|
+
}
|
|
1006
|
+
wrapHandler(handler) {
|
|
1007
|
+
return async (req, res, next) => {
|
|
1008
|
+
try {
|
|
1009
|
+
await handler(req, res, next);
|
|
1010
|
+
} catch (error) {
|
|
1011
|
+
next(error);
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
1018
|
+
|
|
1019
|
+
// src/server/middleware.ts
|
|
1020
|
+
function rateLimit2(options) {
|
|
1021
|
+
const requests = /* @__PURE__ */ new Map();
|
|
1022
|
+
return (req, res, next) => {
|
|
1023
|
+
const ip = req.ip || req.socket.remoteAddress || "unknown";
|
|
1024
|
+
const now = Date.now();
|
|
1025
|
+
const reqTimes = (requests.get(ip) || []).filter((time) => now - time < options.windowMs);
|
|
1026
|
+
reqTimes.push(now);
|
|
1027
|
+
requests.set(ip, reqTimes);
|
|
1028
|
+
if (reqTimes.length > options.max) {
|
|
1029
|
+
return res.status(429).json({
|
|
1030
|
+
error: {
|
|
1031
|
+
message: "Too Many Requests",
|
|
1032
|
+
retryAfter: Math.ceil(options.windowMs / 1e3)
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
return next();
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
var requestLogger2, errorHandler2, notFoundHandler2;
|
|
1040
|
+
var init_middleware = __esm({
|
|
1041
|
+
"src/server/middleware.ts"() {
|
|
1042
|
+
"use strict";
|
|
1043
|
+
requestLogger2 = (req, res, next) => {
|
|
1044
|
+
console.log(`${(/* @__PURE__ */ new Date()).toISOString()} - ${req.method} ${req.url}`);
|
|
1045
|
+
next();
|
|
1046
|
+
};
|
|
1047
|
+
errorHandler2 = (err, req, res, next) => {
|
|
1048
|
+
console.error(err.stack);
|
|
1049
|
+
res.status(500).json({
|
|
1050
|
+
error: {
|
|
1051
|
+
message: "Internal Server Error",
|
|
1052
|
+
...process.env.NODE_ENV !== "production" ? { details: err.message, stack: err.stack } : {}
|
|
1053
|
+
}
|
|
1054
|
+
});
|
|
1055
|
+
};
|
|
1056
|
+
notFoundHandler2 = (req, res) => {
|
|
1057
|
+
res.status(404).json({
|
|
1058
|
+
error: {
|
|
1059
|
+
message: `Not Found - ${req.method} ${req.url}`
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
720
1065
|
|
|
721
1066
|
// src/server/wasm.ts
|
|
722
1067
|
import fs3 from "fs/promises";
|
|
723
1068
|
import path3 from "path";
|
|
724
1069
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
725
|
-
|
|
726
|
-
async function initNodeWasm() {
|
|
1070
|
+
async function initNodeWasm2() {
|
|
727
1071
|
if (initialized)
|
|
728
1072
|
return;
|
|
729
1073
|
try {
|
|
@@ -787,9 +1131,9 @@ You can get it from: https://github.com/golang/go/blob/master/misc/wasm/wasm_exe
|
|
|
787
1131
|
Searched paths: ${possiblePaths.join(", ")}`
|
|
788
1132
|
);
|
|
789
1133
|
}
|
|
790
|
-
async function
|
|
1134
|
+
async function loadGoWasmFromFile2(wasmFilePath, options = {}) {
|
|
791
1135
|
try {
|
|
792
|
-
await
|
|
1136
|
+
await initNodeWasm2();
|
|
793
1137
|
if (options.debug) {
|
|
794
1138
|
console.log("[WASM] Loading WASM from file:", wasmFilePath);
|
|
795
1139
|
}
|
|
@@ -862,8 +1206,55 @@ async function loadGoWasmFromFile(wasmFilePath, options = {}) {
|
|
|
862
1206
|
throw error;
|
|
863
1207
|
}
|
|
864
1208
|
}
|
|
1209
|
+
var initialized;
|
|
1210
|
+
var init_wasm2 = __esm({
|
|
1211
|
+
"src/server/wasm.ts"() {
|
|
1212
|
+
"use strict";
|
|
1213
|
+
initialized = false;
|
|
1214
|
+
}
|
|
1215
|
+
});
|
|
865
1216
|
|
|
866
1217
|
// src/server/index.ts
|
|
1218
|
+
var server_exports = {};
|
|
1219
|
+
__export(server_exports, {
|
|
1220
|
+
ApiRouter: () => ApiRouter2,
|
|
1221
|
+
AuthService: () => AuthService2,
|
|
1222
|
+
Database: () => Database2,
|
|
1223
|
+
Server: () => Server,
|
|
1224
|
+
createDevServer: () => createDevServer2,
|
|
1225
|
+
createProductionServer: () => createProductionServer2,
|
|
1226
|
+
createServer: () => createServer2,
|
|
1227
|
+
default: () => server_default,
|
|
1228
|
+
ensureDirectory: () => ensureDirectory,
|
|
1229
|
+
errorHandler: () => errorHandler2,
|
|
1230
|
+
generateDocument: () => generateDocument,
|
|
1231
|
+
generateErrorPage: () => generateErrorPage,
|
|
1232
|
+
generateLoadingPage: () => generateLoadingPage,
|
|
1233
|
+
generateToken: () => generateToken,
|
|
1234
|
+
getEnvironmentInfo: () => getEnvironmentInfo,
|
|
1235
|
+
getPagination: () => getPagination,
|
|
1236
|
+
getRequestIp: () => getRequestIp,
|
|
1237
|
+
hashString: () => hashString,
|
|
1238
|
+
initNodeWasm: () => initNodeWasm2,
|
|
1239
|
+
isDirectoryEmpty: () => isDirectoryEmpty,
|
|
1240
|
+
loadGoWasmFromFile: () => loadGoWasmFromFile2,
|
|
1241
|
+
notFoundHandler: () => notFoundHandler2,
|
|
1242
|
+
parseCookies: () => parseCookies,
|
|
1243
|
+
rateLimit: () => rateLimit2,
|
|
1244
|
+
readJsonFile: () => readJsonFile,
|
|
1245
|
+
renderComponent: () => renderComponent2,
|
|
1246
|
+
renderToString: () => src_exports.renderToString,
|
|
1247
|
+
requestLogger: () => requestLogger2,
|
|
1248
|
+
safeJsonParse: () => safeJsonParse,
|
|
1249
|
+
sendError: () => sendError,
|
|
1250
|
+
sendSuccess: () => sendSuccess,
|
|
1251
|
+
validateFields: () => validateFields,
|
|
1252
|
+
validateFileUpload: () => validateFileUpload,
|
|
1253
|
+
writeJsonFile: () => writeJsonFile
|
|
1254
|
+
});
|
|
1255
|
+
import path4 from "path";
|
|
1256
|
+
import fs4 from "fs";
|
|
1257
|
+
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
867
1258
|
function getComponentName(filePath, pagesDir) {
|
|
868
1259
|
try {
|
|
869
1260
|
const relativePath = path4.relative(pagesDir, filePath);
|
|
@@ -874,291 +1265,349 @@ function getComponentName(filePath, pagesDir) {
|
|
|
874
1265
|
return "";
|
|
875
1266
|
}
|
|
876
1267
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
1268
|
+
function createServer2(config = {}) {
|
|
1269
|
+
return new Server(config);
|
|
1270
|
+
}
|
|
1271
|
+
function createDevServer2(options = {}) {
|
|
1272
|
+
return new Server({
|
|
1273
|
+
port: options.port || 3e3,
|
|
1274
|
+
enableCors: options.enableCors !== false,
|
|
1275
|
+
apiDir: "./src/api",
|
|
1276
|
+
pagesDir: "./src/pages",
|
|
1277
|
+
staticDir: "./public"
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
function createProductionServer2(config) {
|
|
1281
|
+
const server = new Server({
|
|
1282
|
+
...config,
|
|
1283
|
+
port: config.port || (process.env.PORT ? parseInt(process.env.PORT) : 8080)
|
|
1284
|
+
});
|
|
1285
|
+
server.addShutdownHandler();
|
|
1286
|
+
return server;
|
|
1287
|
+
}
|
|
1288
|
+
function getRequestIp(req) {
|
|
1289
|
+
return req.ip || req.headers["x-forwarded-for"]?.split(",")[0].trim() || req.socket.remoteAddress || "";
|
|
1290
|
+
}
|
|
1291
|
+
function parseCookies(req) {
|
|
1292
|
+
const cookies = {};
|
|
1293
|
+
const cookieHeader = req.headers.cookie;
|
|
1294
|
+
if (cookieHeader) {
|
|
1295
|
+
cookieHeader.split(";").forEach((cookie) => {
|
|
1296
|
+
const [name, value] = cookie.split("=").map((c) => c.trim());
|
|
1297
|
+
cookies[name] = value;
|
|
1298
|
+
});
|
|
891
1299
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
1300
|
+
return cookies;
|
|
1301
|
+
}
|
|
1302
|
+
var Server, renderComponent2, server_default;
|
|
1303
|
+
var init_server = __esm({
|
|
1304
|
+
"src/server/index.ts"() {
|
|
1305
|
+
init_src();
|
|
1306
|
+
init_database();
|
|
1307
|
+
init_auth();
|
|
1308
|
+
init_api_router();
|
|
1309
|
+
init_middleware();
|
|
1310
|
+
init_utils();
|
|
1311
|
+
init_templates();
|
|
1312
|
+
init_wasm2();
|
|
1313
|
+
init_wasm2();
|
|
1314
|
+
init_utils();
|
|
1315
|
+
init_templates();
|
|
1316
|
+
init_database();
|
|
1317
|
+
init_auth();
|
|
1318
|
+
init_api_router();
|
|
1319
|
+
init_middleware();
|
|
1320
|
+
Server = class {
|
|
1321
|
+
constructor(config = {}) {
|
|
1322
|
+
this.server = null;
|
|
1323
|
+
this.db = null;
|
|
1324
|
+
this.auth = null;
|
|
1325
|
+
this.initialized = false;
|
|
1326
|
+
this.config = {
|
|
1327
|
+
port: 3e3,
|
|
1328
|
+
apiDir: "./api",
|
|
1329
|
+
pagesDir: "./pages",
|
|
1330
|
+
staticDir: "./public",
|
|
1331
|
+
enableCors: true,
|
|
1332
|
+
...config
|
|
1333
|
+
};
|
|
1334
|
+
this.initializeApp().catch((error) => {
|
|
1335
|
+
console.error("Failed to initialize server:", error);
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
async initializeApp() {
|
|
1339
|
+
if (this.initialized) {
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
902
1342
|
try {
|
|
903
|
-
const
|
|
904
|
-
this.app.
|
|
1343
|
+
const express = await import("express");
|
|
1344
|
+
this.app = express.default();
|
|
1345
|
+
this.app.use(express.default.json());
|
|
1346
|
+
this.app.use(express.default.urlencoded({ extended: true }));
|
|
1347
|
+
if (this.config.enableCors) {
|
|
1348
|
+
try {
|
|
1349
|
+
const cors = await import("cors");
|
|
1350
|
+
this.app.use(cors.default(this.config.corsOptions));
|
|
1351
|
+
} catch (error) {
|
|
1352
|
+
console.warn("CORS not available - install with: npm install cors @types/cors");
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
if (this.config.db) {
|
|
1356
|
+
this.db = new Database2(this.config.db);
|
|
1357
|
+
}
|
|
1358
|
+
if (this.config.auth) {
|
|
1359
|
+
this.auth = new AuthService2({
|
|
1360
|
+
secret: this.config.auth.secret,
|
|
1361
|
+
expiresIn: this.config.auth.expiresIn
|
|
1362
|
+
});
|
|
1363
|
+
this.app.use(this.auth.initialize());
|
|
1364
|
+
}
|
|
1365
|
+
const staticPath = path4.resolve(process.cwd(), this.config.staticDir);
|
|
1366
|
+
if (fs4.existsSync(staticPath)) {
|
|
1367
|
+
this.app.use(express.default.static(staticPath));
|
|
1368
|
+
}
|
|
1369
|
+
this.setupApiRoutes();
|
|
1370
|
+
this.setupPageRoutes();
|
|
1371
|
+
this.app.use(notFoundHandler2);
|
|
1372
|
+
this.app.use(errorHandler2);
|
|
1373
|
+
this.initialized = true;
|
|
1374
|
+
console.log("\u2705 Baraqex server initialized successfully");
|
|
905
1375
|
} catch (error) {
|
|
906
|
-
|
|
1376
|
+
if (error.code === "MODULE_NOT_FOUND" && error.message.includes("express")) {
|
|
1377
|
+
throw new Error("Express not installed. Run: npm install express @types/express");
|
|
1378
|
+
}
|
|
1379
|
+
throw error;
|
|
907
1380
|
}
|
|
908
1381
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
expiresIn: this.config.auth.expiresIn
|
|
916
|
-
});
|
|
917
|
-
this.app.use(this.auth.initialize());
|
|
918
|
-
}
|
|
919
|
-
const staticPath = path4.resolve(process.cwd(), this.config.staticDir);
|
|
920
|
-
if (fs4.existsSync(staticPath)) {
|
|
921
|
-
this.app.use(express.default.static(staticPath));
|
|
922
|
-
}
|
|
923
|
-
this.setupApiRoutes();
|
|
924
|
-
this.setupPageRoutes();
|
|
925
|
-
this.app.use(notFoundHandler);
|
|
926
|
-
this.app.use(errorHandler);
|
|
927
|
-
this.initialized = true;
|
|
928
|
-
console.log("Server initialized successfully");
|
|
929
|
-
} catch (error) {
|
|
930
|
-
if (error.code === "MODULE_NOT_FOUND" && error.message.includes("express")) {
|
|
931
|
-
throw new Error("Express not installed. Run: npm install express @types/express");
|
|
932
|
-
}
|
|
933
|
-
throw error;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
setupApiRoutes() {
|
|
937
|
-
const apiRouter = new ApiRouter(this.config.apiDir, this.auth);
|
|
938
|
-
this.app.use("/api", requestLogger, apiRouter.router);
|
|
939
|
-
this.app.get("/api-docs", (req, res) => {
|
|
940
|
-
const apiDocs = this.generateApiDocs();
|
|
941
|
-
res.json(apiDocs);
|
|
942
|
-
});
|
|
943
|
-
}
|
|
944
|
-
generateApiDocs() {
|
|
945
|
-
const apiDir = path4.resolve(process.cwd(), this.config.apiDir);
|
|
946
|
-
const docs = { endpoints: [] };
|
|
947
|
-
if (fs4.existsSync(apiDir)) {
|
|
948
|
-
this.scanApiDirectory(apiDir, "", docs.endpoints);
|
|
949
|
-
}
|
|
950
|
-
return docs;
|
|
951
|
-
}
|
|
952
|
-
scanApiDirectory(dirPath, routePrefix, endpoints) {
|
|
953
|
-
const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
|
|
954
|
-
for (const entry of entries) {
|
|
955
|
-
const fullPath = path4.join(dirPath, entry.name);
|
|
956
|
-
if (entry.isDirectory()) {
|
|
957
|
-
this.scanApiDirectory(fullPath, `${routePrefix}/${entry.name}`, endpoints);
|
|
958
|
-
} else if (entry.name.endsWith(".js") || entry.name.endsWith(".ts")) {
|
|
959
|
-
const routePath = this.getRoutePath(entry.name, routePrefix);
|
|
960
|
-
endpoints.push({
|
|
961
|
-
path: routePath,
|
|
962
|
-
file: path4.relative(process.cwd(), fullPath),
|
|
963
|
-
methods: this.detectApiMethods(fullPath)
|
|
1382
|
+
setupApiRoutes() {
|
|
1383
|
+
const apiRouter = new ApiRouter2(this.config.apiDir, this.auth);
|
|
1384
|
+
this.app.use("/api", requestLogger2, apiRouter.router);
|
|
1385
|
+
this.app.get("/api-docs", (req, res) => {
|
|
1386
|
+
const apiDocs = this.generateApiDocs();
|
|
1387
|
+
res.json(apiDocs);
|
|
964
1388
|
});
|
|
965
1389
|
}
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
const paramMatch = baseName.match(/^\[(.+)\]$/);
|
|
974
|
-
if (paramMatch) {
|
|
975
|
-
return `${routePrefix}/:${paramMatch[1]}`;
|
|
976
|
-
}
|
|
977
|
-
return `${routePrefix}/${baseName}`;
|
|
978
|
-
}
|
|
979
|
-
detectApiMethods(filePath) {
|
|
980
|
-
try {
|
|
981
|
-
const content = fs4.readFileSync(filePath, "utf8");
|
|
982
|
-
const methods = ["get", "post", "put", "delete", "patch", "options"];
|
|
983
|
-
return methods.filter(
|
|
984
|
-
(method) => new RegExp(`export (async )?function ${method}\\s*\\(`).test(content) || new RegExp(`export const ${method}\\s*=`).test(content)
|
|
985
|
-
);
|
|
986
|
-
} catch (error) {
|
|
987
|
-
return [];
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
setupPageRoutes() {
|
|
991
|
-
const pagesPath = path4.resolve(process.cwd(), this.config.pagesDir);
|
|
992
|
-
if (!fs4.existsSync(pagesPath)) {
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
|
-
this.app.get("*", async (req, res) => {
|
|
996
|
-
try {
|
|
997
|
-
const { html, statusCode } = await this.renderPage(req.path);
|
|
998
|
-
res.status(statusCode || 200).send(html);
|
|
999
|
-
} catch (error) {
|
|
1000
|
-
console.error("Error rendering page:", error);
|
|
1001
|
-
const errorHtml = generateErrorPage(500, "Server Error");
|
|
1002
|
-
res.status(500).send(errorHtml);
|
|
1003
|
-
}
|
|
1004
|
-
});
|
|
1005
|
-
}
|
|
1006
|
-
async renderPage(routePath) {
|
|
1007
|
-
try {
|
|
1008
|
-
const pagesDir = this.config.pagesDir ? path4.resolve(process.cwd(), this.config.pagesDir) : "";
|
|
1009
|
-
if (!pagesDir || !fs4.existsSync(pagesDir)) {
|
|
1010
|
-
return {
|
|
1011
|
-
html: generateErrorPage(404, "Pages directory not found"),
|
|
1012
|
-
statusCode: 404
|
|
1013
|
-
};
|
|
1014
|
-
}
|
|
1015
|
-
let normalizedPath = routePath;
|
|
1016
|
-
if (!normalizedPath.startsWith("/")) {
|
|
1017
|
-
normalizedPath = "/" + normalizedPath;
|
|
1390
|
+
generateApiDocs() {
|
|
1391
|
+
const apiDir = path4.resolve(process.cwd(), this.config.apiDir);
|
|
1392
|
+
const docs = { endpoints: [] };
|
|
1393
|
+
if (fs4.existsSync(apiDir)) {
|
|
1394
|
+
this.scanApiDirectory(apiDir, "", docs.endpoints);
|
|
1395
|
+
}
|
|
1396
|
+
return docs;
|
|
1018
1397
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1398
|
+
scanApiDirectory(dirPath, routePrefix, endpoints) {
|
|
1399
|
+
const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
|
|
1400
|
+
for (const entry of entries) {
|
|
1401
|
+
const fullPath = path4.join(dirPath, entry.name);
|
|
1402
|
+
if (entry.isDirectory()) {
|
|
1403
|
+
this.scanApiDirectory(fullPath, `${routePrefix}/${entry.name}`, endpoints);
|
|
1404
|
+
} else if (entry.name.endsWith(".js") || entry.name.endsWith(".ts")) {
|
|
1405
|
+
const routePath = this.getRoutePath(entry.name, routePrefix);
|
|
1406
|
+
endpoints.push({
|
|
1407
|
+
path: routePath,
|
|
1408
|
+
file: path4.relative(process.cwd(), fullPath),
|
|
1409
|
+
methods: this.detectApiMethods(fullPath)
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1021
1413
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
path4.join(pagesDir, `${normalizedPath}.jsx`),
|
|
1027
|
-
path4.join(pagesDir, `${normalizedPath}.tsx`),
|
|
1028
|
-
path4.join(pagesDir, `${normalizedPath}/index.js`),
|
|
1029
|
-
path4.join(pagesDir, `${normalizedPath}/index.ts`),
|
|
1030
|
-
path4.join(pagesDir, `${normalizedPath}/index.jsx`),
|
|
1031
|
-
path4.join(pagesDir, `${normalizedPath}/index.tsx`)
|
|
1032
|
-
];
|
|
1033
|
-
for (const p of possiblePaths) {
|
|
1034
|
-
if (fs4.existsSync(p)) {
|
|
1035
|
-
pagePath = p;
|
|
1036
|
-
break;
|
|
1414
|
+
getRoutePath(filename, routePrefix) {
|
|
1415
|
+
const baseName = path4.basename(filename, path4.extname(filename));
|
|
1416
|
+
if (baseName === "index") {
|
|
1417
|
+
return routePrefix || "/";
|
|
1037
1418
|
}
|
|
1419
|
+
const paramMatch = baseName.match(/^\[(.+)\]$/);
|
|
1420
|
+
if (paramMatch) {
|
|
1421
|
+
return `${routePrefix}/:${paramMatch[1]}`;
|
|
1422
|
+
}
|
|
1423
|
+
return `${routePrefix}/${baseName}`;
|
|
1038
1424
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1425
|
+
detectApiMethods(filePath) {
|
|
1426
|
+
try {
|
|
1427
|
+
const content = fs4.readFileSync(filePath, "utf8");
|
|
1428
|
+
const methods = ["get", "post", "put", "delete", "patch", "options"];
|
|
1429
|
+
return methods.filter(
|
|
1430
|
+
(method) => new RegExp(`export (async )?function ${method}\\s*\\(`).test(content) || new RegExp(`export const ${method}\\s*=`).test(content)
|
|
1431
|
+
);
|
|
1432
|
+
} catch (error) {
|
|
1433
|
+
return [];
|
|
1434
|
+
}
|
|
1044
1435
|
}
|
|
1045
|
-
|
|
1046
|
-
const
|
|
1047
|
-
if (!
|
|
1048
|
-
|
|
1436
|
+
setupPageRoutes() {
|
|
1437
|
+
const pagesPath = path4.resolve(process.cwd(), this.config.pagesDir);
|
|
1438
|
+
if (!fs4.existsSync(pagesPath)) {
|
|
1439
|
+
return;
|
|
1049
1440
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1441
|
+
this.app.get("*", async (req, res) => {
|
|
1442
|
+
try {
|
|
1443
|
+
const { html, statusCode } = await this.renderPage(req.path);
|
|
1444
|
+
res.status(statusCode || 200).send(html);
|
|
1445
|
+
} catch (error) {
|
|
1446
|
+
console.error("Error rendering page:", error);
|
|
1447
|
+
const errorHtml = generateErrorPage(500, "Server Error");
|
|
1448
|
+
res.status(500).send(errorHtml);
|
|
1449
|
+
}
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
async renderPage(routePath) {
|
|
1453
|
+
try {
|
|
1454
|
+
const pagesDir = this.config.pagesDir ? path4.resolve(process.cwd(), this.config.pagesDir) : "";
|
|
1455
|
+
if (!pagesDir || !fs4.existsSync(pagesDir)) {
|
|
1456
|
+
return {
|
|
1457
|
+
html: generateErrorPage(404, "Pages directory not found"),
|
|
1458
|
+
statusCode: 404
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
let normalizedPath = routePath;
|
|
1462
|
+
if (!normalizedPath.startsWith("/")) {
|
|
1463
|
+
normalizedPath = "/" + normalizedPath;
|
|
1464
|
+
}
|
|
1465
|
+
if (normalizedPath === "/") {
|
|
1466
|
+
normalizedPath = "/index";
|
|
1467
|
+
}
|
|
1468
|
+
let pagePath = "";
|
|
1469
|
+
const possiblePaths = [
|
|
1470
|
+
path4.join(pagesDir, `${normalizedPath}.js`),
|
|
1471
|
+
path4.join(pagesDir, `${normalizedPath}.ts`),
|
|
1472
|
+
path4.join(pagesDir, `${normalizedPath}.jsx`),
|
|
1473
|
+
path4.join(pagesDir, `${normalizedPath}.tsx`),
|
|
1474
|
+
path4.join(pagesDir, `${normalizedPath}/index.js`),
|
|
1475
|
+
path4.join(pagesDir, `${normalizedPath}/index.ts`),
|
|
1476
|
+
path4.join(pagesDir, `${normalizedPath}/index.jsx`),
|
|
1477
|
+
path4.join(pagesDir, `${normalizedPath}/index.tsx`)
|
|
1478
|
+
];
|
|
1479
|
+
for (const p of possiblePaths) {
|
|
1480
|
+
if (fs4.existsSync(p)) {
|
|
1481
|
+
pagePath = p;
|
|
1482
|
+
break;
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
if (!pagePath) {
|
|
1486
|
+
return {
|
|
1487
|
+
html: generateErrorPage(404, `Page not found: ${normalizedPath}`),
|
|
1488
|
+
statusCode: 404
|
|
1489
|
+
};
|
|
1490
|
+
}
|
|
1491
|
+
try {
|
|
1492
|
+
const absolutePath = path4.resolve(pagePath);
|
|
1493
|
+
const fileUrl = pathToFileURL3(absolutePath).href;
|
|
1494
|
+
const urlWithTimestamp = `${fileUrl}?t=${Date.now()}`;
|
|
1495
|
+
const pageModule = await import(urlWithTimestamp);
|
|
1496
|
+
if (!pageModule || !pageModule.default) {
|
|
1497
|
+
throw new Error(`No default export found in ${pagePath}`);
|
|
1498
|
+
}
|
|
1499
|
+
const PageComponent = pageModule.default;
|
|
1500
|
+
const initialProps = {
|
|
1501
|
+
// Provide any initial props here
|
|
1502
|
+
path: normalizedPath,
|
|
1503
|
+
query: {},
|
|
1504
|
+
// Could be parsed from URL
|
|
1505
|
+
api: { serverTime: (/* @__PURE__ */ new Date()).toISOString() }
|
|
1506
|
+
};
|
|
1507
|
+
const renderResult = await renderComponent2(PageComponent, initialProps);
|
|
1508
|
+
if (!renderResult.success) {
|
|
1509
|
+
return {
|
|
1510
|
+
html: generateErrorPage(500, "Failed to render page", renderResult.error instanceof Error ? renderResult.error : new Error("Unknown error")),
|
|
1511
|
+
statusCode: 500
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
const htmlContent = renderResult.html;
|
|
1515
|
+
let pageTitle = "My App";
|
|
1516
|
+
try {
|
|
1517
|
+
if (typeof PageComponent.getTitle === "function") {
|
|
1518
|
+
pageTitle = PageComponent.getTitle(initialProps);
|
|
1519
|
+
} else if (PageComponent.title) {
|
|
1520
|
+
pageTitle = PageComponent.title;
|
|
1521
|
+
}
|
|
1522
|
+
} catch (e) {
|
|
1523
|
+
}
|
|
1524
|
+
const componentName = getComponentName(pagePath, pagesDir);
|
|
1525
|
+
const fullHtml = generateDocument(htmlContent, {
|
|
1526
|
+
title: pageTitle,
|
|
1527
|
+
// Get description from component if available
|
|
1528
|
+
description: typeof PageComponent.getDescription === "function" ? PageComponent.getDescription(initialProps) : PageComponent.description || "",
|
|
1529
|
+
// Add scripts for client-side hydration
|
|
1530
|
+
scripts: ["/client.js"],
|
|
1531
|
+
// Add any custom meta tags
|
|
1532
|
+
meta: typeof PageComponent.getMeta === "function" ? PageComponent.getMeta(initialProps) : {},
|
|
1533
|
+
// Add custom styles
|
|
1534
|
+
styles: ["/styles.css"],
|
|
1535
|
+
// Add initial data for client-side hydration
|
|
1536
|
+
initialData: initialProps,
|
|
1537
|
+
// Add component information for hydration
|
|
1538
|
+
componentName
|
|
1539
|
+
});
|
|
1540
|
+
return { html: fullHtml, statusCode: 200 };
|
|
1541
|
+
} catch (error) {
|
|
1542
|
+
console.error("Error rendering page:", error);
|
|
1543
|
+
return {
|
|
1544
|
+
html: generateErrorPage(500, "Error rendering page", error instanceof Error ? error : new Error("Unknown error")),
|
|
1545
|
+
statusCode: 500
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
} catch (error) {
|
|
1549
|
+
console.error("Error finding page:", error);
|
|
1060
1550
|
return {
|
|
1061
|
-
html: generateErrorPage(500, "
|
|
1551
|
+
html: generateErrorPage(500, "Server error", error instanceof Error ? error : new Error("Unknown error")),
|
|
1062
1552
|
statusCode: 500
|
|
1063
1553
|
};
|
|
1064
1554
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1555
|
+
}
|
|
1556
|
+
getExpressApp() {
|
|
1557
|
+
return this.app;
|
|
1558
|
+
}
|
|
1559
|
+
getDatabase() {
|
|
1560
|
+
return this.db;
|
|
1561
|
+
}
|
|
1562
|
+
getAuth() {
|
|
1563
|
+
return this.auth;
|
|
1564
|
+
}
|
|
1565
|
+
async start() {
|
|
1566
|
+
while (!this.initialized) {
|
|
1567
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1074
1568
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
initialData: initialProps,
|
|
1088
|
-
// Add component information for hydration
|
|
1089
|
-
componentName
|
|
1569
|
+
return new Promise((resolve, reject) => {
|
|
1570
|
+
if (!this.app) {
|
|
1571
|
+
reject(new Error("Server not initialized. Express app is missing."));
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
this.server = this.app.listen(this.config.port, () => {
|
|
1575
|
+
console.log(`\u{1F680} Server running at http://localhost:${this.config.port}`);
|
|
1576
|
+
resolve();
|
|
1577
|
+
});
|
|
1578
|
+
this.server.on("error", (error) => {
|
|
1579
|
+
reject(error);
|
|
1580
|
+
});
|
|
1090
1581
|
});
|
|
1091
|
-
return { html: fullHtml, statusCode: 200 };
|
|
1092
|
-
} catch (error) {
|
|
1093
|
-
console.error("Error rendering page:", error);
|
|
1094
|
-
return {
|
|
1095
|
-
html: generateErrorPage(500, "Error rendering page", error instanceof Error ? error : new Error("Unknown error")),
|
|
1096
|
-
statusCode: 500
|
|
1097
|
-
};
|
|
1098
|
-
}
|
|
1099
|
-
} catch (error) {
|
|
1100
|
-
console.error("Error finding page:", error);
|
|
1101
|
-
return {
|
|
1102
|
-
html: generateErrorPage(500, "Server error", error instanceof Error ? error : new Error("Unknown error")),
|
|
1103
|
-
statusCode: 500
|
|
1104
|
-
};
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
getExpressApp() {
|
|
1108
|
-
return this.app;
|
|
1109
|
-
}
|
|
1110
|
-
getDatabase() {
|
|
1111
|
-
return this.db;
|
|
1112
|
-
}
|
|
1113
|
-
getAuth() {
|
|
1114
|
-
return this.auth;
|
|
1115
|
-
}
|
|
1116
|
-
async start() {
|
|
1117
|
-
if (!this.initialized) {
|
|
1118
|
-
await this.initializeApp();
|
|
1119
|
-
}
|
|
1120
|
-
return new Promise((resolve, reject) => {
|
|
1121
|
-
if (!this.app) {
|
|
1122
|
-
reject(new Error("Server not initialized. Express app is missing."));
|
|
1123
|
-
return;
|
|
1124
1582
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
return resolve();
|
|
1583
|
+
stop() {
|
|
1584
|
+
return new Promise((resolve, reject) => {
|
|
1585
|
+
if (!this.server) {
|
|
1586
|
+
return resolve();
|
|
1587
|
+
}
|
|
1588
|
+
this.server.close((err) => {
|
|
1589
|
+
if (err)
|
|
1590
|
+
return reject(err);
|
|
1591
|
+
this.server = null;
|
|
1592
|
+
resolve();
|
|
1593
|
+
});
|
|
1594
|
+
});
|
|
1138
1595
|
}
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
return reject(err);
|
|
1142
|
-
this.server = null;
|
|
1143
|
-
resolve();
|
|
1144
|
-
});
|
|
1145
|
-
});
|
|
1146
|
-
}
|
|
1147
|
-
restart() {
|
|
1148
|
-
return this.stop().then(() => this.start());
|
|
1149
|
-
}
|
|
1150
|
-
enableSSR(options = {}) {
|
|
1151
|
-
if (!fs4.existsSync(path4.resolve(process.cwd(), this.config.pagesDir))) {
|
|
1152
|
-
fs4.mkdirSync(path4.resolve(process.cwd(), this.config.pagesDir), { recursive: true });
|
|
1153
|
-
}
|
|
1154
|
-
if (options.hydratable) {
|
|
1155
|
-
const staticDir = path4.resolve(process.cwd(), this.config.staticDir);
|
|
1156
|
-
if (!fs4.existsSync(staticDir)) {
|
|
1157
|
-
fs4.mkdirSync(staticDir, { recursive: true });
|
|
1596
|
+
restart() {
|
|
1597
|
+
return this.stop().then(() => this.start());
|
|
1158
1598
|
}
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1599
|
+
enableSSR(options = {}) {
|
|
1600
|
+
if (!fs4.existsSync(path4.resolve(process.cwd(), this.config.pagesDir))) {
|
|
1601
|
+
fs4.mkdirSync(path4.resolve(process.cwd(), this.config.pagesDir), { recursive: true });
|
|
1602
|
+
}
|
|
1603
|
+
if (options.hydratable) {
|
|
1604
|
+
const staticDir = path4.resolve(process.cwd(), this.config.staticDir);
|
|
1605
|
+
if (!fs4.existsSync(staticDir)) {
|
|
1606
|
+
fs4.mkdirSync(staticDir, { recursive: true });
|
|
1607
|
+
}
|
|
1608
|
+
const clientJsPath = path4.join(staticDir, "client.js");
|
|
1609
|
+
if (!fs4.existsSync(clientJsPath)) {
|
|
1610
|
+
const clientJsContent = `
|
|
1162
1611
|
// Auto-generated hydration script
|
|
1163
1612
|
import { hydrate } from 'frontend-hamroun';
|
|
1164
1613
|
|
|
@@ -1175,119 +1624,88 @@ var Server = class {
|
|
|
1175
1624
|
});
|
|
1176
1625
|
});
|
|
1177
1626
|
`;
|
|
1178
|
-
|
|
1627
|
+
fs4.writeFileSync(clientJsPath, clientJsContent);
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1179
1630
|
}
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1631
|
+
registerPlugin(plugin) {
|
|
1632
|
+
plugin(this);
|
|
1633
|
+
}
|
|
1634
|
+
addShutdownHandler() {
|
|
1635
|
+
const gracefulShutdown = async () => {
|
|
1636
|
+
console.log("Received shutdown signal, closing server...");
|
|
1637
|
+
try {
|
|
1638
|
+
await this.stop();
|
|
1639
|
+
if (this.db) {
|
|
1640
|
+
await this.db.disconnect();
|
|
1641
|
+
}
|
|
1642
|
+
console.log("Server shut down gracefully");
|
|
1643
|
+
process.exit(0);
|
|
1644
|
+
} catch (error) {
|
|
1645
|
+
console.error("Error during shutdown:", error);
|
|
1646
|
+
process.exit(1);
|
|
1647
|
+
}
|
|
1648
|
+
};
|
|
1649
|
+
process.on("SIGTERM", gracefulShutdown);
|
|
1650
|
+
process.on("SIGINT", gracefulShutdown);
|
|
1651
|
+
}
|
|
1652
|
+
};
|
|
1653
|
+
renderComponent2 = async (Component, props = {}) => {
|
|
1188
1654
|
try {
|
|
1189
|
-
await
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1655
|
+
const { jsx, renderToString: renderToString3 } = await import("frontend-hamroun");
|
|
1656
|
+
const element = jsx(Component, props);
|
|
1657
|
+
const html = renderToString3(element);
|
|
1658
|
+
return {
|
|
1659
|
+
html: typeof html === "string" ? html : String(html),
|
|
1660
|
+
success: true
|
|
1661
|
+
};
|
|
1195
1662
|
} catch (error) {
|
|
1196
|
-
console.error("Error
|
|
1197
|
-
|
|
1663
|
+
console.error("Error rendering component:", error);
|
|
1664
|
+
return {
|
|
1665
|
+
html: `<div class="error">Error rendering component: ${error instanceof Error ? error.message : "Unknown error"}</div>`,
|
|
1666
|
+
success: false,
|
|
1667
|
+
error
|
|
1668
|
+
};
|
|
1198
1669
|
}
|
|
1199
1670
|
};
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
server.addShutdownHandler();
|
|
1223
|
-
return server;
|
|
1224
|
-
}
|
|
1225
|
-
function getRequestIp(req) {
|
|
1226
|
-
return req.ip || req.headers["x-forwarded-for"]?.split(",")[0].trim() || req.socket.remoteAddress || "";
|
|
1227
|
-
}
|
|
1228
|
-
function parseCookies(req) {
|
|
1229
|
-
const cookies = {};
|
|
1230
|
-
const cookieHeader = req.headers.cookie;
|
|
1231
|
-
if (cookieHeader) {
|
|
1232
|
-
cookieHeader.split(";").forEach((cookie) => {
|
|
1233
|
-
const [name, value] = cookie.split("=").map((c) => c.trim());
|
|
1234
|
-
cookies[name] = value;
|
|
1235
|
-
});
|
|
1236
|
-
}
|
|
1237
|
-
return cookies;
|
|
1238
|
-
}
|
|
1239
|
-
var renderComponent = async (Component, props = {}) => {
|
|
1240
|
-
try {
|
|
1241
|
-
const { jsx, renderToString: renderToString2 } = await import("frontend-hamroun");
|
|
1242
|
-
const element = jsx(Component, props);
|
|
1243
|
-
const html = renderToString2(element);
|
|
1244
|
-
return {
|
|
1245
|
-
html: typeof html === "string" ? html : String(html),
|
|
1246
|
-
success: true
|
|
1247
|
-
};
|
|
1248
|
-
} catch (error) {
|
|
1249
|
-
console.error("Error rendering component:", error);
|
|
1250
|
-
return {
|
|
1251
|
-
html: `<div class="error">Error rendering component: ${error instanceof Error ? error.message : "Unknown error"}</div>`,
|
|
1252
|
-
success: false,
|
|
1253
|
-
error
|
|
1671
|
+
server_default = {
|
|
1672
|
+
Server,
|
|
1673
|
+
createServer: createServer2,
|
|
1674
|
+
createDevServer: createDevServer2,
|
|
1675
|
+
createProductionServer: createProductionServer2,
|
|
1676
|
+
rateLimit: rateLimit2,
|
|
1677
|
+
requestLogger: requestLogger2,
|
|
1678
|
+
errorHandler: errorHandler2,
|
|
1679
|
+
notFoundHandler: notFoundHandler2,
|
|
1680
|
+
loadGoWasmFromFile: loadGoWasmFromFile2,
|
|
1681
|
+
// Template utilities
|
|
1682
|
+
templates: templates_exports,
|
|
1683
|
+
// Server utilities
|
|
1684
|
+
utils: utils_exports,
|
|
1685
|
+
// Additional exports
|
|
1686
|
+
renderComponent: renderComponent2,
|
|
1687
|
+
renderToString: src_exports.renderToString,
|
|
1688
|
+
getRequestIp,
|
|
1689
|
+
parseCookies,
|
|
1690
|
+
Database: Database2,
|
|
1691
|
+
AuthService: AuthService2,
|
|
1692
|
+
ApiRouter: ApiRouter2
|
|
1254
1693
|
};
|
|
1255
1694
|
}
|
|
1256
|
-
};
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
createServer,
|
|
1260
|
-
createDevServer,
|
|
1261
|
-
createProductionServer,
|
|
1262
|
-
rateLimit,
|
|
1263
|
-
requestLogger,
|
|
1264
|
-
errorHandler,
|
|
1265
|
-
notFoundHandler,
|
|
1266
|
-
loadGoWasmFromFile,
|
|
1267
|
-
// Template utilities
|
|
1268
|
-
templates: templates_exports,
|
|
1269
|
-
// Server utilities
|
|
1270
|
-
utils: utils_exports,
|
|
1271
|
-
// Additional exports
|
|
1272
|
-
renderComponent,
|
|
1273
|
-
renderToString,
|
|
1274
|
-
getRequestIp,
|
|
1275
|
-
parseCookies,
|
|
1276
|
-
Database,
|
|
1277
|
-
AuthService,
|
|
1278
|
-
ApiRouter
|
|
1279
|
-
};
|
|
1695
|
+
});
|
|
1696
|
+
init_server();
|
|
1697
|
+
var export_renderToString = src_exports.renderToString;
|
|
1280
1698
|
export {
|
|
1281
|
-
ApiRouter,
|
|
1282
|
-
AuthService,
|
|
1283
|
-
Database,
|
|
1699
|
+
ApiRouter2 as ApiRouter,
|
|
1700
|
+
AuthService2 as AuthService,
|
|
1701
|
+
Database2 as Database,
|
|
1284
1702
|
Server,
|
|
1285
|
-
createDevServer,
|
|
1286
|
-
createProductionServer,
|
|
1287
|
-
createServer,
|
|
1703
|
+
createDevServer2 as createDevServer,
|
|
1704
|
+
createProductionServer2 as createProductionServer,
|
|
1705
|
+
createServer2 as createServer,
|
|
1288
1706
|
server_default as default,
|
|
1289
1707
|
ensureDirectory,
|
|
1290
|
-
errorHandler,
|
|
1708
|
+
errorHandler2 as errorHandler,
|
|
1291
1709
|
generateDocument,
|
|
1292
1710
|
generateErrorPage,
|
|
1293
1711
|
generateLoadingPage,
|
|
@@ -1296,16 +1714,16 @@ export {
|
|
|
1296
1714
|
getPagination,
|
|
1297
1715
|
getRequestIp,
|
|
1298
1716
|
hashString,
|
|
1299
|
-
initNodeWasm,
|
|
1717
|
+
initNodeWasm2 as initNodeWasm,
|
|
1300
1718
|
isDirectoryEmpty,
|
|
1301
|
-
loadGoWasmFromFile,
|
|
1302
|
-
notFoundHandler,
|
|
1719
|
+
loadGoWasmFromFile2 as loadGoWasmFromFile,
|
|
1720
|
+
notFoundHandler2 as notFoundHandler,
|
|
1303
1721
|
parseCookies,
|
|
1304
|
-
rateLimit,
|
|
1722
|
+
rateLimit2 as rateLimit,
|
|
1305
1723
|
readJsonFile,
|
|
1306
|
-
renderComponent,
|
|
1307
|
-
renderToString,
|
|
1308
|
-
requestLogger,
|
|
1724
|
+
renderComponent2 as renderComponent,
|
|
1725
|
+
export_renderToString as renderToString,
|
|
1726
|
+
requestLogger2 as requestLogger,
|
|
1309
1727
|
safeJsonParse,
|
|
1310
1728
|
sendError,
|
|
1311
1729
|
sendSuccess,
|