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.
Files changed (31) hide show
  1. package/dist/index.js +189 -251
  2. package/dist/index.js.map +4 -4
  3. package/dist/server.js +849 -1282
  4. package/dist/server.js.map +4 -4
  5. package/package.json +1 -1
  6. package/templates/basic-app/.eslintignore +5 -0
  7. package/templates/basic-app/.eslintrc.json +25 -0
  8. package/templates/basic-app/README.md +166 -0
  9. package/templates/basic-app/esbuild.config.js +37 -0
  10. package/templates/basic-app/favicon.ico +0 -0
  11. package/templates/basic-app/index.html +13 -0
  12. package/templates/basic-app/main.css +3 -0
  13. package/templates/basic-app/package-lock.json +6856 -0
  14. package/templates/basic-app/package.json +31 -20
  15. package/templates/basic-app/postcss.config.js +6 -0
  16. package/templates/basic-app/public/logo.png +0 -0
  17. package/templates/basic-app/src/main.css +77 -0
  18. package/templates/basic-app/src/main.tsx +465 -0
  19. package/templates/basic-app/tailwind.config.js +38 -0
  20. package/templates/basic-app/tsconfig.json +13 -0
  21. package/templates/basic-app/vite.config.ts +8 -0
  22. package/templates/fullstack-template/package.json +5 -23
  23. package/templates/fullstack-template/server.js +11 -572
  24. package/templates/basic-app/public/index.html +0 -13
  25. package/templates/basic-app/public/styles.css +0 -158
  26. package/templates/basic-app/server.js +0 -15
  27. package/templates/basic-app/src/App.jsx +0 -68
  28. package/templates/basic-template/README.md +0 -24
  29. package/templates/basic-template/package.json +0 -13
  30. package/templates/basic-template/server.js +0 -36
  31. 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
- 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 });
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/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.");
133
+ // src/server/auth.ts
134
+ var AuthService = class {
135
+ constructor(config) {
136
+ this.config = {
137
+ expiresIn: "24h",
138
+ ...config
139
+ };
33
140
  }
34
- try {
35
- if (!window.Go) {
36
- throw new Error("Go WASM runtime not available. Make sure wasm_exec.js is loaded.");
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
- if (options.debug) {
39
- console.log("[WASM] Loading WASM from:", wasmUrl);
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
- const response = await fetch(wasmUrl);
42
- if (!response.ok) {
43
- throw new Error(`Failed to fetch WASM file: ${response.status}`);
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
- 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...");
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
- 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}`);
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
- if (options.onLoad) {
69
- options.onLoad(wasmInstance);
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
- if (options.debug) {
72
- console.log(`[WASM] Module loaded successfully with ${Object.keys(functions).length} functions`);
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
- function callWasmFunction(funcName, ...args) {
81
- if (typeof window === "undefined") {
82
- throw new Error("callWasmFunction() is for browser use only.");
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
- const func = window[funcName];
85
- if (typeof func !== "function") {
86
- throw new Error(`Function ${funcName} not found. Make sure the WASM module is loaded.`);
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
- return func(...args);
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
- function isWasmReady() {
91
- if (typeof window === "undefined") {
92
- return false;
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 getWasmFunctions() {
99
- if (typeof window === "undefined") {
100
- return [];
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
- return Object.keys(window).filter(
103
- (key) => key.startsWith("go") && typeof window[key] === "function"
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 useGoWasm(wasmUrl, options = {}) {
107
- if (typeof window === "undefined") {
108
- throw new Error("useGoWasm() is for browser use only.");
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
- loadWasm: () => loadGoWasm(wasmUrl, options),
112
- callFunction: callWasmFunction,
113
- isReady: isWasmReady,
114
- getFunctions: getWasmFunctions
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
- var init_wasm = __esm({
118
- "src/wasm.ts"() {
119
- "use strict";
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, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
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
- async function initNodeWasm2() {
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 loadGoWasmFromFile2(wasmFilePath, options = {}) {
790
+ async function loadGoWasmFromFile(wasmFilePath, options = {}) {
1135
791
  try {
1136
- await initNodeWasm2();
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
- 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
- });
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
- 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
- }
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 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");
900
+ const cors = await import("cors");
901
+ this.app.use(cors.default(this.config.corsOptions));
1375
902
  } catch (error) {
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;
903
+ console.warn("CORS not available - install with: npm install cors @types/cors");
1380
904
  }
1381
905
  }
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);
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
- 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;
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
- 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
- }
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
- getRoutePath(filename, routePrefix) {
1415
- const baseName = path4.basename(filename, path4.extname(filename));
1416
- if (baseName === "index") {
1417
- return routePrefix || "/";
1418
- }
1419
- const paramMatch = baseName.match(/^\[(.+)\]$/);
1420
- if (paramMatch) {
1421
- return `${routePrefix}/:${paramMatch[1]}`;
1422
- }
1423
- return `${routePrefix}/${baseName}`;
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
- 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
- }
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
- setupPageRoutes() {
1437
- const pagesPath = path4.resolve(process.cwd(), this.config.pagesDir);
1438
- if (!fs4.existsSync(pagesPath)) {
1439
- return;
1440
- }
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
- });
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
- 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);
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
- getExpressApp() {
1557
- return this.app;
1014
+ if (normalizedPath === "/") {
1015
+ normalizedPath = "/index";
1558
1016
  }
1559
- getDatabase() {
1560
- return this.db;
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
- getAuth() {
1563
- return this.auth;
1034
+ if (!pagePath) {
1035
+ return {
1036
+ html: generateErrorPage(404, `Page not found: ${normalizedPath}`),
1037
+ statusCode: 404
1038
+ };
1564
1039
  }
1565
- async start() {
1566
- while (!this.initialized) {
1567
- await new Promise((resolve) => setTimeout(resolve, 50));
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
- return new Promise((resolve, reject) => {
1570
- if (!this.app) {
1571
- reject(new Error("Server not initialized. Express app is missing."));
1572
- return;
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
- 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
- });
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
- 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
- });
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
- restart() {
1597
- return this.stop().then(() => this.start());
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
- 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 = `
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
- fs4.writeFileSync(clientJsPath, clientJsContent);
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
- renderComponent2 = async (Component, props = {}) => {
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
- 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
- };
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 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
- };
1181
+ console.error("Error during shutdown:", error);
1182
+ process.exit(1);
1669
1183
  }
1670
1184
  };
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
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
- init_server();
1697
- var export_renderToString = src_exports.renderToString;
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
- ApiRouter2 as ApiRouter,
1700
- AuthService2 as AuthService,
1701
- Database2 as Database,
1266
+ ApiRouter,
1267
+ AuthService,
1268
+ Database,
1702
1269
  Server,
1703
- createDevServer2 as createDevServer,
1704
- createProductionServer2 as createProductionServer,
1705
- createServer2 as createServer,
1270
+ createDevServer,
1271
+ createProductionServer,
1272
+ createServer,
1706
1273
  server_default as default,
1707
1274
  ensureDirectory,
1708
- errorHandler2 as errorHandler,
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
- initNodeWasm2 as initNodeWasm,
1284
+ initNodeWasm,
1718
1285
  isDirectoryEmpty,
1719
- loadGoWasmFromFile2 as loadGoWasmFromFile,
1720
- notFoundHandler2 as notFoundHandler,
1286
+ loadGoWasmFromFile,
1287
+ notFoundHandler,
1721
1288
  parseCookies,
1722
- rateLimit2 as rateLimit,
1289
+ rateLimit,
1723
1290
  readJsonFile,
1724
- renderComponent2 as renderComponent,
1725
- export_renderToString as renderToString,
1726
- requestLogger2 as requestLogger,
1291
+ renderComponent,
1292
+ renderToString,
1293
+ requestLogger,
1727
1294
  safeJsonParse,
1728
1295
  sendError,
1729
1296
  sendSuccess,