baraqex 1.0.49 → 1.0.51
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 +189 -251
- package/dist/index.js.map +4 -4
- package/dist/server.js +849 -1282
- package/dist/server.js.map +4 -4
- package/package.json +1 -1
- package/templates/basic-app/.eslintignore +5 -0
- package/templates/basic-app/.eslintrc.json +25 -0
- package/templates/basic-app/README.md +166 -0
- package/templates/basic-app/esbuild.config.js +37 -0
- package/templates/basic-app/favicon.ico +0 -0
- package/templates/basic-app/index.html +13 -0
- package/templates/basic-app/main.css +3 -0
- package/templates/basic-app/package-lock.json +6856 -0
- package/templates/basic-app/package.json +31 -20
- package/templates/basic-app/postcss.config.js +6 -0
- package/templates/basic-app/public/logo.png +0 -0
- package/templates/basic-app/src/main.css +77 -0
- package/templates/basic-app/src/main.tsx +465 -0
- package/templates/basic-app/tailwind.config.js +38 -0
- package/templates/basic-app/tsconfig.json +13 -0
- package/templates/basic-app/vite.config.ts +8 -0
- package/templates/fullstack-template/package.json +5 -23
- package/templates/fullstack-template/server.js +11 -572
- package/templates/basic-app/public/index.html +0 -13
- package/templates/basic-app/public/styles.css +0 -158
- package/templates/basic-app/server.js +0 -15
- package/templates/basic-app/src/App.jsx +0 -68
- package/templates/basic-template/README.md +0 -24
- package/templates/basic-template/package.json +0 -13
- package/templates/basic-template/server.js +0 -36
- package/templates/fullstack-template/package-lock.json +0 -1895
package/dist/server.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
2
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
6
3
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
7
4
|
}) : x)(function(x) {
|
|
@@ -9,116 +6,524 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
9
6
|
return require.apply(this, arguments);
|
|
10
7
|
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
11
8
|
});
|
|
12
|
-
var __esm = (fn, res) => function __init() {
|
|
13
|
-
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
14
|
-
};
|
|
15
9
|
var __export = (target, all) => {
|
|
16
10
|
for (var name in all)
|
|
17
11
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
18
12
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
|
|
14
|
+
// src/server/index.ts
|
|
15
|
+
import path4 from "path";
|
|
16
|
+
import fs4 from "fs";
|
|
17
|
+
import { renderToString } from "frontend-hamroun";
|
|
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
|
+
}
|
|
24
130
|
}
|
|
25
|
-
return to;
|
|
26
131
|
};
|
|
27
|
-
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
28
132
|
|
|
29
|
-
// src/
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
133
|
+
// src/server/auth.ts
|
|
134
|
+
var AuthService = class {
|
|
135
|
+
constructor(config) {
|
|
136
|
+
this.config = {
|
|
137
|
+
expiresIn: "24h",
|
|
138
|
+
...config
|
|
139
|
+
};
|
|
33
140
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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;
|
|
37
150
|
}
|
|
38
|
-
|
|
39
|
-
|
|
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;
|
|
40
161
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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;
|
|
44
180
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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;
|
|
52
191
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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;
|
|
59
201
|
}
|
|
60
202
|
}
|
|
61
|
-
|
|
62
|
-
const wasmInstance = {
|
|
63
|
-
instance: wasmModule.instance,
|
|
64
|
-
module: wasmModule,
|
|
65
|
-
exports: wasmModule.instance.exports,
|
|
66
|
-
functions
|
|
203
|
+
next();
|
|
67
204
|
};
|
|
68
|
-
|
|
69
|
-
|
|
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);
|
|
70
232
|
}
|
|
71
|
-
|
|
72
|
-
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// src/server/api-router.ts
|
|
238
|
+
import path from "path";
|
|
239
|
+
import fs from "fs";
|
|
240
|
+
import { pathToFileURL } from "url";
|
|
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;
|
|
73
258
|
}
|
|
74
|
-
return wasmInstance;
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.error("[WASM] Error loading Go WASM module:", error);
|
|
77
|
-
throw error;
|
|
78
259
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
260
|
+
setupRoutes() {
|
|
261
|
+
if (!fs.existsSync(this.apiDir)) {
|
|
262
|
+
console.log(`API directory not found: ${this.apiDir}`);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
this.scanDirectory(this.apiDir, "");
|
|
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
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
isRouteFile(filename) {
|
|
280
|
+
return filename.endsWith(".js") || filename.endsWith(".ts") || filename.endsWith(".mjs");
|
|
281
|
+
}
|
|
282
|
+
getRoutePath(filename, routePrefix) {
|
|
283
|
+
const baseName = path.basename(filename, path.extname(filename));
|
|
284
|
+
if (baseName === "index") {
|
|
285
|
+
return routePrefix || "/";
|
|
286
|
+
}
|
|
287
|
+
const paramMatch = baseName.match(/^\[(.+)\]$/);
|
|
288
|
+
if (paramMatch) {
|
|
289
|
+
return `${routePrefix}/:${paramMatch[1]}`;
|
|
290
|
+
}
|
|
291
|
+
return `${routePrefix}/${baseName}`;
|
|
292
|
+
}
|
|
293
|
+
async registerRoute(filePath, routePath) {
|
|
294
|
+
try {
|
|
295
|
+
const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(filePath);
|
|
296
|
+
const fileUrl = pathToFileURL(absolutePath).href;
|
|
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
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
} catch (error) {
|
|
340
|
+
console.error(`Error registering route (${filePath}):`, error);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
isValidRouteModule(module) {
|
|
344
|
+
if (!module)
|
|
345
|
+
return false;
|
|
346
|
+
return ["get", "post", "put", "delete", "patch", "options"].some((method) => typeof module[method] === "function");
|
|
83
347
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
348
|
+
wrapHandler(handler) {
|
|
349
|
+
return async (req, res, next) => {
|
|
350
|
+
try {
|
|
351
|
+
await handler(req, res, next);
|
|
352
|
+
} catch (error) {
|
|
353
|
+
next(error);
|
|
354
|
+
}
|
|
355
|
+
};
|
|
87
356
|
}
|
|
88
|
-
|
|
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}`
|
|
377
|
+
}
|
|
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
|
+
});
|
|
395
|
+
}
|
|
396
|
+
return next();
|
|
397
|
+
};
|
|
89
398
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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);
|
|
423
|
+
} catch (error) {
|
|
424
|
+
return fallback;
|
|
93
425
|
}
|
|
94
|
-
return !!(window.Go && Object.keys(window).some(
|
|
95
|
-
(key) => key.startsWith("go") && typeof window[key] === "function"
|
|
96
|
-
));
|
|
97
426
|
}
|
|
98
|
-
function
|
|
99
|
-
|
|
100
|
-
|
|
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));
|
|
101
441
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
+
};
|
|
105
468
|
}
|
|
106
|
-
function
|
|
107
|
-
if (
|
|
108
|
-
|
|
469
|
+
function validateFileUpload(file, options = {}) {
|
|
470
|
+
if (!file) {
|
|
471
|
+
return { valid: false, error: "No file provided" };
|
|
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
|
+
};
|
|
478
|
+
}
|
|
479
|
+
if (options.allowedTypes && options.allowedTypes.length > 0) {
|
|
480
|
+
const fileType = file.mimetype;
|
|
481
|
+
if (!options.allowedTypes.includes(fileType)) {
|
|
482
|
+
return {
|
|
483
|
+
valid: false,
|
|
484
|
+
error: `Invalid file type. Allowed types: ${options.allowedTypes.join(", ")}`
|
|
485
|
+
};
|
|
486
|
+
}
|
|
109
487
|
}
|
|
488
|
+
return { valid: true };
|
|
489
|
+
}
|
|
490
|
+
function getEnvironmentInfo() {
|
|
110
491
|
return {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
492
|
+
nodeVersion: process.version,
|
|
493
|
+
platform: process.platform,
|
|
494
|
+
arch: process.arch,
|
|
495
|
+
memory: process.memoryUsage(),
|
|
496
|
+
uptime: process.uptime(),
|
|
497
|
+
env: process.env.NODE_ENV || "development"
|
|
115
498
|
};
|
|
116
499
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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;
|
|
120
506
|
}
|
|
121
|
-
}
|
|
507
|
+
}
|
|
508
|
+
async function ensureDirectory(dirPath) {
|
|
509
|
+
try {
|
|
510
|
+
await fs2.access(dirPath);
|
|
511
|
+
} catch (error) {
|
|
512
|
+
await fs2.mkdir(dirPath, { recursive: true });
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
async function writeJsonFile(filePath, data) {
|
|
516
|
+
await ensureDirectory(path2.dirname(filePath));
|
|
517
|
+
await fs2.writeFile(filePath, JSON.stringify(data, null, 2), "utf8");
|
|
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;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
122
527
|
|
|
123
528
|
// src/server/templates.ts
|
|
124
529
|
var templates_exports = {};
|
|
@@ -312,762 +717,13 @@ function generateLoadingPage(message = "Loading...") {
|
|
|
312
717
|
function escapeHtml(text) {
|
|
313
718
|
return String(text).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
314
719
|
}
|
|
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
|
-
});
|
|
1065
720
|
|
|
1066
721
|
// src/server/wasm.ts
|
|
1067
722
|
import fs3 from "fs/promises";
|
|
1068
723
|
import path3 from "path";
|
|
1069
724
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
1070
|
-
|
|
725
|
+
var initialized = false;
|
|
726
|
+
async function initNodeWasm() {
|
|
1071
727
|
if (initialized)
|
|
1072
728
|
return;
|
|
1073
729
|
try {
|
|
@@ -1131,9 +787,9 @@ You can get it from: https://github.com/golang/go/blob/master/misc/wasm/wasm_exe
|
|
|
1131
787
|
Searched paths: ${possiblePaths.join(", ")}`
|
|
1132
788
|
);
|
|
1133
789
|
}
|
|
1134
|
-
async function
|
|
790
|
+
async function loadGoWasmFromFile(wasmFilePath, options = {}) {
|
|
1135
791
|
try {
|
|
1136
|
-
await
|
|
792
|
+
await initNodeWasm();
|
|
1137
793
|
if (options.debug) {
|
|
1138
794
|
console.log("[WASM] Loading WASM from file:", wasmFilePath);
|
|
1139
795
|
}
|
|
@@ -1206,55 +862,8 @@ async function loadGoWasmFromFile2(wasmFilePath, options = {}) {
|
|
|
1206
862
|
throw error;
|
|
1207
863
|
}
|
|
1208
864
|
}
|
|
1209
|
-
var initialized;
|
|
1210
|
-
var init_wasm2 = __esm({
|
|
1211
|
-
"src/server/wasm.ts"() {
|
|
1212
|
-
"use strict";
|
|
1213
|
-
initialized = false;
|
|
1214
|
-
}
|
|
1215
|
-
});
|
|
1216
865
|
|
|
1217
866
|
// 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";
|
|
1258
867
|
function getComponentName(filePath, pagesDir) {
|
|
1259
868
|
try {
|
|
1260
869
|
const relativePath = path4.relative(pagesDir, filePath);
|
|
@@ -1265,349 +874,276 @@ function getComponentName(filePath, pagesDir) {
|
|
|
1265
874
|
return "";
|
|
1266
875
|
}
|
|
1267
876
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
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
|
-
});
|
|
877
|
+
var Server = class {
|
|
878
|
+
constructor(config = {}) {
|
|
879
|
+
this.server = null;
|
|
880
|
+
this.db = null;
|
|
881
|
+
this.auth = null;
|
|
882
|
+
this.config = {
|
|
883
|
+
port: 3e3,
|
|
884
|
+
apiDir: "./api",
|
|
885
|
+
pagesDir: "./pages",
|
|
886
|
+
staticDir: "./public",
|
|
887
|
+
enableCors: true,
|
|
888
|
+
...config
|
|
889
|
+
};
|
|
890
|
+
this.initializeApp();
|
|
1299
891
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
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
|
-
}
|
|
892
|
+
async initializeApp() {
|
|
893
|
+
try {
|
|
894
|
+
const express = await import("express");
|
|
895
|
+
this.app = express.default();
|
|
896
|
+
this.app.use(express.default.json());
|
|
897
|
+
this.app.use(express.default.urlencoded({ extended: true }));
|
|
898
|
+
if (this.config.enableCors) {
|
|
1342
899
|
try {
|
|
1343
|
-
const
|
|
1344
|
-
this.app
|
|
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");
|
|
900
|
+
const cors = await import("cors");
|
|
901
|
+
this.app.use(cors.default(this.config.corsOptions));
|
|
1375
902
|
} catch (error) {
|
|
1376
|
-
|
|
1377
|
-
throw new Error("Express not installed. Run: npm install express @types/express");
|
|
1378
|
-
}
|
|
1379
|
-
throw error;
|
|
903
|
+
console.warn("CORS not available - install with: npm install cors @types/cors");
|
|
1380
904
|
}
|
|
1381
905
|
}
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
906
|
+
if (this.config.db) {
|
|
907
|
+
this.db = new Database(this.config.db);
|
|
908
|
+
}
|
|
909
|
+
if (this.config.auth) {
|
|
910
|
+
this.auth = new AuthService({
|
|
911
|
+
secret: this.config.auth.secret,
|
|
912
|
+
expiresIn: this.config.auth.expiresIn
|
|
1388
913
|
});
|
|
914
|
+
this.app.use(this.auth.initialize());
|
|
1389
915
|
}
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
if (fs4.existsSync(apiDir)) {
|
|
1394
|
-
this.scanApiDirectory(apiDir, "", docs.endpoints);
|
|
1395
|
-
}
|
|
1396
|
-
return docs;
|
|
916
|
+
const staticPath = path4.resolve(process.cwd(), this.config.staticDir);
|
|
917
|
+
if (fs4.existsSync(staticPath)) {
|
|
918
|
+
this.app.use(express.default.static(staticPath));
|
|
1397
919
|
}
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
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
|
-
}
|
|
920
|
+
this.setupApiRoutes();
|
|
921
|
+
this.setupPageRoutes();
|
|
922
|
+
this.app.use(notFoundHandler);
|
|
923
|
+
this.app.use(errorHandler);
|
|
924
|
+
} catch (error) {
|
|
925
|
+
if (error.code === "MODULE_NOT_FOUND" && error.message.includes("express")) {
|
|
926
|
+
throw new Error("Express not installed. Run: npm install express @types/express");
|
|
1413
927
|
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
928
|
+
throw error;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
setupApiRoutes() {
|
|
932
|
+
const apiRouter = new ApiRouter(this.config.apiDir, this.auth);
|
|
933
|
+
this.app.use("/api", requestLogger, apiRouter.router);
|
|
934
|
+
this.app.get("/api-docs", (req, res) => {
|
|
935
|
+
const apiDocs = this.generateApiDocs();
|
|
936
|
+
res.json(apiDocs);
|
|
937
|
+
});
|
|
938
|
+
}
|
|
939
|
+
generateApiDocs() {
|
|
940
|
+
const apiDir = path4.resolve(process.cwd(), this.config.apiDir);
|
|
941
|
+
const docs = { endpoints: [] };
|
|
942
|
+
if (fs4.existsSync(apiDir)) {
|
|
943
|
+
this.scanApiDirectory(apiDir, "", docs.endpoints);
|
|
944
|
+
}
|
|
945
|
+
return docs;
|
|
946
|
+
}
|
|
947
|
+
scanApiDirectory(dirPath, routePrefix, endpoints) {
|
|
948
|
+
const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
|
|
949
|
+
for (const entry of entries) {
|
|
950
|
+
const fullPath = path4.join(dirPath, entry.name);
|
|
951
|
+
if (entry.isDirectory()) {
|
|
952
|
+
this.scanApiDirectory(fullPath, `${routePrefix}/${entry.name}`, endpoints);
|
|
953
|
+
} else if (entry.name.endsWith(".js") || entry.name.endsWith(".ts")) {
|
|
954
|
+
const routePath = this.getRoutePath(entry.name, routePrefix);
|
|
955
|
+
endpoints.push({
|
|
956
|
+
path: routePath,
|
|
957
|
+
file: path4.relative(process.cwd(), fullPath),
|
|
958
|
+
methods: this.detectApiMethods(fullPath)
|
|
959
|
+
});
|
|
1424
960
|
}
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
getRoutePath(filename, routePrefix) {
|
|
964
|
+
const baseName = path4.basename(filename, path4.extname(filename));
|
|
965
|
+
if (baseName === "index") {
|
|
966
|
+
return routePrefix || "/";
|
|
967
|
+
}
|
|
968
|
+
const paramMatch = baseName.match(/^\[(.+)\]$/);
|
|
969
|
+
if (paramMatch) {
|
|
970
|
+
return `${routePrefix}/:${paramMatch[1]}`;
|
|
971
|
+
}
|
|
972
|
+
return `${routePrefix}/${baseName}`;
|
|
973
|
+
}
|
|
974
|
+
detectApiMethods(filePath) {
|
|
975
|
+
try {
|
|
976
|
+
const content = fs4.readFileSync(filePath, "utf8");
|
|
977
|
+
const methods = ["get", "post", "put", "delete", "patch", "options"];
|
|
978
|
+
return methods.filter(
|
|
979
|
+
(method) => new RegExp(`export (async )?function ${method}\\s*\\(`).test(content) || new RegExp(`export const ${method}\\s*=`).test(content)
|
|
980
|
+
);
|
|
981
|
+
} catch (error) {
|
|
982
|
+
return [];
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
setupPageRoutes() {
|
|
986
|
+
const pagesPath = path4.resolve(process.cwd(), this.config.pagesDir);
|
|
987
|
+
if (!fs4.existsSync(pagesPath)) {
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
this.app.get("*", async (req, res) => {
|
|
991
|
+
try {
|
|
992
|
+
const { html, statusCode } = await this.renderPage(req.path);
|
|
993
|
+
res.status(statusCode || 200).send(html);
|
|
994
|
+
} catch (error) {
|
|
995
|
+
console.error("Error rendering page:", error);
|
|
996
|
+
const errorHtml = generateErrorPage(500, "Server Error");
|
|
997
|
+
res.status(500).send(errorHtml);
|
|
1435
998
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
console.error("Error rendering page:", error);
|
|
1447
|
-
const errorHtml = generateErrorPage(500, "Server Error");
|
|
1448
|
-
res.status(500).send(errorHtml);
|
|
1449
|
-
}
|
|
1450
|
-
});
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
async renderPage(routePath) {
|
|
1002
|
+
try {
|
|
1003
|
+
const pagesDir = this.config.pagesDir ? path4.resolve(process.cwd(), this.config.pagesDir) : "";
|
|
1004
|
+
if (!pagesDir || !fs4.existsSync(pagesDir)) {
|
|
1005
|
+
return {
|
|
1006
|
+
html: generateErrorPage(404, "Pages directory not found"),
|
|
1007
|
+
statusCode: 404
|
|
1008
|
+
};
|
|
1451
1009
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
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);
|
|
1550
|
-
return {
|
|
1551
|
-
html: generateErrorPage(500, "Server error", error instanceof Error ? error : new Error("Unknown error")),
|
|
1552
|
-
statusCode: 500
|
|
1553
|
-
};
|
|
1554
|
-
}
|
|
1010
|
+
let normalizedPath = routePath;
|
|
1011
|
+
if (!normalizedPath.startsWith("/")) {
|
|
1012
|
+
normalizedPath = "/" + normalizedPath;
|
|
1555
1013
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
1014
|
+
if (normalizedPath === "/") {
|
|
1015
|
+
normalizedPath = "/index";
|
|
1558
1016
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1017
|
+
let pagePath = "";
|
|
1018
|
+
const possiblePaths = [
|
|
1019
|
+
path4.join(pagesDir, `${normalizedPath}.js`),
|
|
1020
|
+
path4.join(pagesDir, `${normalizedPath}.ts`),
|
|
1021
|
+
path4.join(pagesDir, `${normalizedPath}.jsx`),
|
|
1022
|
+
path4.join(pagesDir, `${normalizedPath}.tsx`),
|
|
1023
|
+
path4.join(pagesDir, `${normalizedPath}/index.js`),
|
|
1024
|
+
path4.join(pagesDir, `${normalizedPath}/index.ts`),
|
|
1025
|
+
path4.join(pagesDir, `${normalizedPath}/index.jsx`),
|
|
1026
|
+
path4.join(pagesDir, `${normalizedPath}/index.tsx`)
|
|
1027
|
+
];
|
|
1028
|
+
for (const p of possiblePaths) {
|
|
1029
|
+
if (fs4.existsSync(p)) {
|
|
1030
|
+
pagePath = p;
|
|
1031
|
+
break;
|
|
1032
|
+
}
|
|
1561
1033
|
}
|
|
1562
|
-
|
|
1563
|
-
return
|
|
1034
|
+
if (!pagePath) {
|
|
1035
|
+
return {
|
|
1036
|
+
html: generateErrorPage(404, `Page not found: ${normalizedPath}`),
|
|
1037
|
+
statusCode: 404
|
|
1038
|
+
};
|
|
1564
1039
|
}
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1040
|
+
try {
|
|
1041
|
+
const pageModule = await import(pagePath);
|
|
1042
|
+
if (!pageModule || !pageModule.default) {
|
|
1043
|
+
throw new Error(`No default export found in ${pagePath}`);
|
|
1044
|
+
}
|
|
1045
|
+
const PageComponent = pageModule.default;
|
|
1046
|
+
const initialProps = {
|
|
1047
|
+
// Provide any initial props here
|
|
1048
|
+
path: normalizedPath,
|
|
1049
|
+
query: {},
|
|
1050
|
+
// Could be parsed from URL
|
|
1051
|
+
api: { serverTime: (/* @__PURE__ */ new Date()).toISOString() }
|
|
1052
|
+
};
|
|
1053
|
+
const renderResult = await renderComponent(PageComponent, initialProps);
|
|
1054
|
+
if (!renderResult.success) {
|
|
1055
|
+
return {
|
|
1056
|
+
html: generateErrorPage(500, "Failed to render page", renderResult.error instanceof Error ? renderResult.error : new Error("Unknown error")),
|
|
1057
|
+
statusCode: 500
|
|
1058
|
+
};
|
|
1568
1059
|
}
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1060
|
+
const htmlContent = renderResult.html;
|
|
1061
|
+
let pageTitle = "My App";
|
|
1062
|
+
try {
|
|
1063
|
+
if (typeof PageComponent.getTitle === "function") {
|
|
1064
|
+
pageTitle = PageComponent.getTitle(initialProps);
|
|
1065
|
+
} else if (PageComponent.title) {
|
|
1066
|
+
pageTitle = PageComponent.title;
|
|
1573
1067
|
}
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1068
|
+
} catch (e) {
|
|
1069
|
+
}
|
|
1070
|
+
const componentName = getComponentName(pagePath, pagesDir);
|
|
1071
|
+
const fullHtml = generateDocument(htmlContent, {
|
|
1072
|
+
title: pageTitle,
|
|
1073
|
+
// Get description from component if available
|
|
1074
|
+
description: typeof PageComponent.getDescription === "function" ? PageComponent.getDescription(initialProps) : PageComponent.description || "",
|
|
1075
|
+
// Add scripts for client-side hydration
|
|
1076
|
+
scripts: ["/client.js"],
|
|
1077
|
+
// Add any custom meta tags
|
|
1078
|
+
meta: typeof PageComponent.getMeta === "function" ? PageComponent.getMeta(initialProps) : {},
|
|
1079
|
+
// Add custom styles
|
|
1080
|
+
styles: ["/styles.css"],
|
|
1081
|
+
// Add initial data for client-side hydration
|
|
1082
|
+
initialData: initialProps,
|
|
1083
|
+
// Add component information for hydration
|
|
1084
|
+
componentName
|
|
1581
1085
|
});
|
|
1086
|
+
return { html: fullHtml, statusCode: 200 };
|
|
1087
|
+
} catch (error) {
|
|
1088
|
+
console.error("Error rendering page:", error);
|
|
1089
|
+
return {
|
|
1090
|
+
html: generateErrorPage(500, "Error rendering page", error instanceof Error ? error : new Error("Unknown error")),
|
|
1091
|
+
statusCode: 500
|
|
1092
|
+
};
|
|
1582
1093
|
}
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1094
|
+
} catch (error) {
|
|
1095
|
+
console.error("Error finding page:", error);
|
|
1096
|
+
return {
|
|
1097
|
+
html: generateErrorPage(500, "Server error", error instanceof Error ? error : new Error("Unknown error")),
|
|
1098
|
+
statusCode: 500
|
|
1099
|
+
};
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
getExpressApp() {
|
|
1103
|
+
return this.app;
|
|
1104
|
+
}
|
|
1105
|
+
getDatabase() {
|
|
1106
|
+
return this.db;
|
|
1107
|
+
}
|
|
1108
|
+
getAuth() {
|
|
1109
|
+
return this.auth;
|
|
1110
|
+
}
|
|
1111
|
+
start() {
|
|
1112
|
+
return new Promise((resolve) => {
|
|
1113
|
+
this.server = this.app.listen(this.config.port, () => {
|
|
1114
|
+
console.log(`Server running at http://localhost:${this.config.port}`);
|
|
1115
|
+
resolve();
|
|
1116
|
+
});
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
stop() {
|
|
1120
|
+
return new Promise((resolve, reject) => {
|
|
1121
|
+
if (!this.server) {
|
|
1122
|
+
return resolve();
|
|
1595
1123
|
}
|
|
1596
|
-
|
|
1597
|
-
|
|
1124
|
+
this.server.close((err) => {
|
|
1125
|
+
if (err)
|
|
1126
|
+
return reject(err);
|
|
1127
|
+
this.server = null;
|
|
1128
|
+
resolve();
|
|
1129
|
+
});
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
restart() {
|
|
1133
|
+
return this.stop().then(() => this.start());
|
|
1134
|
+
}
|
|
1135
|
+
enableSSR(options = {}) {
|
|
1136
|
+
if (!fs4.existsSync(path4.resolve(process.cwd(), this.config.pagesDir))) {
|
|
1137
|
+
fs4.mkdirSync(path4.resolve(process.cwd(), this.config.pagesDir), { recursive: true });
|
|
1138
|
+
}
|
|
1139
|
+
if (options.hydratable) {
|
|
1140
|
+
const staticDir = path4.resolve(process.cwd(), this.config.staticDir);
|
|
1141
|
+
if (!fs4.existsSync(staticDir)) {
|
|
1142
|
+
fs4.mkdirSync(staticDir, { recursive: true });
|
|
1598
1143
|
}
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
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 = `
|
|
1144
|
+
const clientJsPath = path4.join(staticDir, "client.js");
|
|
1145
|
+
if (!fs4.existsSync(clientJsPath)) {
|
|
1146
|
+
const clientJsContent = `
|
|
1611
1147
|
// Auto-generated hydration script
|
|
1612
1148
|
import { hydrate } from 'frontend-hamroun';
|
|
1613
1149
|
|
|
@@ -1624,88 +1160,119 @@ var init_server = __esm({
|
|
|
1624
1160
|
});
|
|
1625
1161
|
});
|
|
1626
1162
|
`;
|
|
1627
|
-
|
|
1628
|
-
}
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
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);
|
|
1163
|
+
fs4.writeFileSync(clientJsPath, clientJsContent);
|
|
1651
1164
|
}
|
|
1652
|
-
}
|
|
1653
|
-
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
registerPlugin(plugin) {
|
|
1168
|
+
plugin(this);
|
|
1169
|
+
}
|
|
1170
|
+
addShutdownHandler() {
|
|
1171
|
+
const gracefulShutdown = async () => {
|
|
1172
|
+
console.log("Received shutdown signal, closing server...");
|
|
1654
1173
|
try {
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
};
|
|
1174
|
+
await this.stop();
|
|
1175
|
+
if (this.db) {
|
|
1176
|
+
await this.db.disconnect();
|
|
1177
|
+
}
|
|
1178
|
+
console.log("Server shut down gracefully");
|
|
1179
|
+
process.exit(0);
|
|
1662
1180
|
} catch (error) {
|
|
1663
|
-
console.error("Error
|
|
1664
|
-
|
|
1665
|
-
html: `<div class="error">Error rendering component: ${error instanceof Error ? error.message : "Unknown error"}</div>`,
|
|
1666
|
-
success: false,
|
|
1667
|
-
error
|
|
1668
|
-
};
|
|
1181
|
+
console.error("Error during shutdown:", error);
|
|
1182
|
+
process.exit(1);
|
|
1669
1183
|
}
|
|
1670
1184
|
};
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1185
|
+
process.on("SIGTERM", gracefulShutdown);
|
|
1186
|
+
process.on("SIGINT", gracefulShutdown);
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
function createServer(config = {}) {
|
|
1190
|
+
return new Server(config);
|
|
1191
|
+
}
|
|
1192
|
+
function createDevServer(options = {}) {
|
|
1193
|
+
return new Server({
|
|
1194
|
+
port: options.port || 3e3,
|
|
1195
|
+
enableCors: options.enableCors !== false,
|
|
1196
|
+
apiDir: "./src/api",
|
|
1197
|
+
pagesDir: "./src/pages",
|
|
1198
|
+
staticDir: "./public"
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
function createProductionServer(config) {
|
|
1202
|
+
const server = new Server({
|
|
1203
|
+
...config,
|
|
1204
|
+
// Fix the PORT parsing
|
|
1205
|
+
port: config.port || (process.env.PORT ? parseInt(process.env.PORT) : 8080)
|
|
1206
|
+
});
|
|
1207
|
+
server.addShutdownHandler();
|
|
1208
|
+
return server;
|
|
1209
|
+
}
|
|
1210
|
+
function getRequestIp(req) {
|
|
1211
|
+
return req.ip || req.headers["x-forwarded-for"]?.split(",")[0].trim() || req.socket.remoteAddress || "";
|
|
1212
|
+
}
|
|
1213
|
+
function parseCookies(req) {
|
|
1214
|
+
const cookies = {};
|
|
1215
|
+
const cookieHeader = req.headers.cookie;
|
|
1216
|
+
if (cookieHeader) {
|
|
1217
|
+
cookieHeader.split(";").forEach((cookie) => {
|
|
1218
|
+
const [name, value] = cookie.split("=").map((c) => c.trim());
|
|
1219
|
+
cookies[name] = value;
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
return cookies;
|
|
1223
|
+
}
|
|
1224
|
+
var renderComponent = async (Component, props = {}) => {
|
|
1225
|
+
try {
|
|
1226
|
+
const { jsx, renderToString: renderToString2 } = await import("frontend-hamroun");
|
|
1227
|
+
const element = jsx(Component, props);
|
|
1228
|
+
const html = renderToString2(element);
|
|
1229
|
+
return {
|
|
1230
|
+
html: typeof html === "string" ? html : String(html),
|
|
1231
|
+
success: true
|
|
1232
|
+
};
|
|
1233
|
+
} catch (error) {
|
|
1234
|
+
console.error("Error rendering component:", error);
|
|
1235
|
+
return {
|
|
1236
|
+
html: `<div class="error">Error rendering component: ${error instanceof Error ? error.message : "Unknown error"}</div>`,
|
|
1237
|
+
success: false,
|
|
1238
|
+
error
|
|
1693
1239
|
};
|
|
1694
1240
|
}
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1241
|
+
};
|
|
1242
|
+
var server_default = {
|
|
1243
|
+
Server,
|
|
1244
|
+
createServer,
|
|
1245
|
+
createDevServer,
|
|
1246
|
+
createProductionServer,
|
|
1247
|
+
rateLimit,
|
|
1248
|
+
requestLogger,
|
|
1249
|
+
errorHandler,
|
|
1250
|
+
notFoundHandler,
|
|
1251
|
+
loadGoWasmFromFile,
|
|
1252
|
+
// Template utilities
|
|
1253
|
+
templates: templates_exports,
|
|
1254
|
+
// Server utilities
|
|
1255
|
+
utils: utils_exports,
|
|
1256
|
+
// Additional exports
|
|
1257
|
+
renderComponent,
|
|
1258
|
+
renderToString,
|
|
1259
|
+
getRequestIp,
|
|
1260
|
+
parseCookies,
|
|
1261
|
+
Database,
|
|
1262
|
+
AuthService,
|
|
1263
|
+
ApiRouter
|
|
1264
|
+
};
|
|
1698
1265
|
export {
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1266
|
+
ApiRouter,
|
|
1267
|
+
AuthService,
|
|
1268
|
+
Database,
|
|
1702
1269
|
Server,
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1270
|
+
createDevServer,
|
|
1271
|
+
createProductionServer,
|
|
1272
|
+
createServer,
|
|
1706
1273
|
server_default as default,
|
|
1707
1274
|
ensureDirectory,
|
|
1708
|
-
|
|
1275
|
+
errorHandler,
|
|
1709
1276
|
generateDocument,
|
|
1710
1277
|
generateErrorPage,
|
|
1711
1278
|
generateLoadingPage,
|
|
@@ -1714,16 +1281,16 @@ export {
|
|
|
1714
1281
|
getPagination,
|
|
1715
1282
|
getRequestIp,
|
|
1716
1283
|
hashString,
|
|
1717
|
-
|
|
1284
|
+
initNodeWasm,
|
|
1718
1285
|
isDirectoryEmpty,
|
|
1719
|
-
|
|
1720
|
-
|
|
1286
|
+
loadGoWasmFromFile,
|
|
1287
|
+
notFoundHandler,
|
|
1721
1288
|
parseCookies,
|
|
1722
|
-
|
|
1289
|
+
rateLimit,
|
|
1723
1290
|
readJsonFile,
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1291
|
+
renderComponent,
|
|
1292
|
+
renderToString,
|
|
1293
|
+
requestLogger,
|
|
1727
1294
|
safeJsonParse,
|
|
1728
1295
|
sendError,
|
|
1729
1296
|
sendSuccess,
|