baraqex 2.0.0 → 2.0.2

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 CHANGED
@@ -1,19 +1,47 @@
1
1
  var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
- var __esm = (fn, res) => function __init() {
5
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
- };
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
3
  var __publicField = (obj, key, value) => {
12
4
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
13
5
  return value;
14
6
  };
15
7
 
8
+ // src/core/batch.ts
9
+ var isBatching = false;
10
+ var syncQueue = [];
11
+ var asyncQueue = [];
12
+ async function batchUpdates(fn) {
13
+ if (isBatching) {
14
+ if (fn.constructor.name === "AsyncFunction") {
15
+ asyncQueue.push(fn);
16
+ } else {
17
+ syncQueue.push(fn);
18
+ }
19
+ return;
20
+ }
21
+ isBatching = true;
22
+ try {
23
+ const result = fn();
24
+ if (result instanceof Promise) {
25
+ await result;
26
+ }
27
+ while (syncQueue.length > 0) {
28
+ const nextFn = syncQueue.shift();
29
+ nextFn();
30
+ }
31
+ while (asyncQueue.length > 0) {
32
+ const nextFn = asyncQueue.shift();
33
+ await nextFn();
34
+ }
35
+ } finally {
36
+ isBatching = false;
37
+ }
38
+ }
39
+ function getIsBatching() {
40
+ return isBatching;
41
+ }
42
+
16
43
  // src/core/context.ts
44
+ var contextStacks = /* @__PURE__ */ new Map();
17
45
  function createContext(defaultValue) {
18
46
  const id = Symbol("context");
19
47
  contextStacks.set(id, []);
@@ -50,15 +78,9 @@ function useContext(context) {
50
78
  function getContextValue(context) {
51
79
  return useContext(context);
52
80
  }
53
- var contextStacks;
54
- var init_context = __esm({
55
- "src/core/context.ts"() {
56
- "use strict";
57
- contextStacks = /* @__PURE__ */ new Map();
58
- }
59
- });
60
81
 
61
82
  // src/core/hooks.ts
83
+ var rootIdCounter = 0;
62
84
  function createRootState() {
63
85
  return {
64
86
  id: ++rootIdCounter,
@@ -69,6 +91,10 @@ function createRootState() {
69
91
  currentElement: null
70
92
  };
71
93
  }
94
+ var currentRoot = null;
95
+ var currentComponentId = null;
96
+ var hookIndex = 0;
97
+ var isServer = typeof window === "undefined";
72
98
  function prepareRender(root, componentId) {
73
99
  if (root) {
74
100
  currentRoot = root;
@@ -237,6 +263,7 @@ function useErrorBoundary() {
237
263
  const resetError = () => setError(null);
238
264
  return [error, resetError];
239
265
  }
266
+ var idCounter = 0;
240
267
  function useId() {
241
268
  const ref = useRef(null);
242
269
  if (ref.current === null) {
@@ -263,20 +290,215 @@ function cleanupRoot(root) {
263
290
  });
264
291
  root.components.clear();
265
292
  }
266
- var rootIdCounter, currentRoot, currentComponentId, hookIndex, isServer, idCounter;
267
- var init_hooks = __esm({
268
- "src/core/hooks.ts"() {
269
- "use strict";
270
- rootIdCounter = 0;
271
- currentRoot = null;
272
- currentComponentId = null;
273
- hookIndex = 0;
274
- isServer = typeof window === "undefined";
275
- idCounter = 0;
293
+
294
+ // src/core/jsx-runtime.ts
295
+ var isBrowser = typeof document !== "undefined";
296
+ function jsx(type, props, key) {
297
+ const processedProps = { ...props };
298
+ if (key !== void 0) {
299
+ processedProps.key = key;
276
300
  }
277
- });
301
+ if (arguments.length > 3) {
302
+ processedProps.children = Array.prototype.slice.call(arguments, 3);
303
+ }
304
+ return { type, props: processedProps, key: processedProps.key };
305
+ }
306
+ var jsxs = jsx;
307
+ function jsxDEV(type, props, key, _isStaticChildren, _source, _self) {
308
+ return jsx(type, props, key);
309
+ }
310
+ var Fragment = ({ children }) => children;
311
+ function assertBrowser(method) {
312
+ if (!isBrowser) {
313
+ throw new Error(
314
+ `[baraqex] ${method}() can only be called in a browser environment. Use renderToString() for server-side rendering.`
315
+ );
316
+ }
317
+ }
318
+ function createTextNode(text) {
319
+ return document.createTextNode(text);
320
+ }
321
+ function applyProps(element, props) {
322
+ for (const [key, value] of Object.entries(props)) {
323
+ if (key === "children")
324
+ continue;
325
+ if (key === "className") {
326
+ element.setAttribute("class", String(value));
327
+ } else if (key === "htmlFor") {
328
+ element.setAttribute("for", String(value));
329
+ } else if (key.startsWith("on") && typeof value === "function") {
330
+ const eventName = key.slice(2).toLowerCase();
331
+ element.addEventListener(eventName, value);
332
+ } else if (key === "style" && typeof value === "object") {
333
+ Object.assign(element.style, value);
334
+ } else if (key === "dangerouslySetInnerHTML" && value && value.__html) {
335
+ element.innerHTML = value.__html;
336
+ } else if (key === "ref") {
337
+ if (typeof value === "function") {
338
+ value(element);
339
+ } else if (value && typeof value === "object" && "current" in value) {
340
+ value.current = element;
341
+ }
342
+ } else if (value !== false && value != null) {
343
+ if (value === true) {
344
+ element.setAttribute(key, "");
345
+ } else {
346
+ element.setAttribute(key, String(value));
347
+ }
348
+ }
349
+ }
350
+ }
351
+ async function createElement(vnode) {
352
+ assertBrowser("createElement");
353
+ if (vnode == null || typeof vnode === "boolean") {
354
+ return createTextNode("");
355
+ }
356
+ if (typeof vnode === "number" || typeof vnode === "string") {
357
+ return createTextNode(String(vnode));
358
+ }
359
+ if (Array.isArray(vnode)) {
360
+ const fragment = document.createDocumentFragment();
361
+ for (const child of vnode) {
362
+ const node = await createElement(child);
363
+ fragment.appendChild(node);
364
+ }
365
+ return fragment;
366
+ }
367
+ if (typeof vnode === "object" && "type" in vnode && vnode.props !== void 0) {
368
+ const { type, props } = vnode;
369
+ if (typeof type === "function") {
370
+ if (type === Fragment) {
371
+ const children2 = props?.children;
372
+ if (children2 == null)
373
+ return createTextNode("");
374
+ return createElement(children2);
375
+ }
376
+ const root = getCurrentRoot() ?? void 0;
377
+ const renderId = prepareRender(root);
378
+ try {
379
+ const result = type(props || {});
380
+ return await createElement(result);
381
+ } finally {
382
+ finishRender();
383
+ }
384
+ }
385
+ const element = document.createElement(type);
386
+ applyProps(element, props || {});
387
+ const children = props?.children;
388
+ if (children != null) {
389
+ const childArray = Array.isArray(children) ? children : [children];
390
+ for (const child of childArray) {
391
+ const childNode = await createElement(child);
392
+ element.appendChild(childNode);
393
+ }
394
+ }
395
+ return element;
396
+ }
397
+ return createTextNode(String(vnode));
398
+ }
399
+ function createElementSync(vnode) {
400
+ assertBrowser("createElementSync");
401
+ if (vnode == null || typeof vnode === "boolean") {
402
+ return createTextNode("");
403
+ }
404
+ if (typeof vnode === "number" || typeof vnode === "string") {
405
+ return createTextNode(String(vnode));
406
+ }
407
+ if (Array.isArray(vnode)) {
408
+ const fragment = document.createDocumentFragment();
409
+ for (const child of vnode) {
410
+ fragment.appendChild(createElementSync(child));
411
+ }
412
+ return fragment;
413
+ }
414
+ if (typeof vnode === "object" && "type" in vnode) {
415
+ const { type, props } = vnode;
416
+ if (typeof type === "function") {
417
+ if (type === Fragment) {
418
+ return createElementSync(props?.children);
419
+ }
420
+ const result = type(props || {});
421
+ return createElementSync(result);
422
+ }
423
+ const element = document.createElement(type);
424
+ applyProps(element, props || {});
425
+ const children = props?.children;
426
+ if (children != null) {
427
+ const childArray = Array.isArray(children) ? children : [children];
428
+ for (const child of childArray) {
429
+ element.appendChild(createElementSync(child));
430
+ }
431
+ }
432
+ return element;
433
+ }
434
+ return createTextNode(String(vnode));
435
+ }
436
+
437
+ // src/core/renderer.ts
438
+ var isBrowser2 = typeof document !== "undefined";
439
+ var rootMap = /* @__PURE__ */ new WeakMap();
440
+ async function render(element, container) {
441
+ if (!isBrowser2) {
442
+ throw new Error(
443
+ "[baraqex] render() can only be called in a browser. Use renderToString() for server-side rendering."
444
+ );
445
+ }
446
+ if (!container) {
447
+ throw new Error("[baraqex] render() requires a container element");
448
+ }
449
+ let root = rootMap.get(container);
450
+ if (!root) {
451
+ root = createRootState();
452
+ rootMap.set(container, root);
453
+ }
454
+ await batchUpdates(async () => {
455
+ prepareRender(root);
456
+ try {
457
+ setRenderCallback(render, element, container);
458
+ const domNode = await createElement(element);
459
+ container.textContent = "";
460
+ container.appendChild(domNode);
461
+ } finally {
462
+ finishRender();
463
+ }
464
+ });
465
+ }
466
+ async function hydrate(element, container) {
467
+ await render(element, container);
468
+ }
469
+ function createRoot(container) {
470
+ const root = createRootState();
471
+ rootMap.set(container, root);
472
+ return {
473
+ render: (element) => render(element, container),
474
+ unmount: () => {
475
+ cleanupRoot(root);
476
+ rootMap.delete(container);
477
+ container.textContent = "";
478
+ }
479
+ };
480
+ }
481
+ function hasRoot(container) {
482
+ return rootMap.has(container);
483
+ }
278
484
 
279
485
  // src/core/server-renderer.ts
486
+ var VOID_ELEMENTS = /* @__PURE__ */ new Set([
487
+ "area",
488
+ "base",
489
+ "br",
490
+ "col",
491
+ "embed",
492
+ "hr",
493
+ "img",
494
+ "input",
495
+ "link",
496
+ "meta",
497
+ "param",
498
+ "source",
499
+ "track",
500
+ "wbr"
501
+ ]);
280
502
  function renderToString(vnode) {
281
503
  prepareRender();
282
504
  try {
@@ -383,1663 +605,6 @@ function renderNodeToString(vnode) {
383
605
  function escapeHtml(text) {
384
606
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
385
607
  }
386
- var VOID_ELEMENTS;
387
- var init_server_renderer = __esm({
388
- "src/core/server-renderer.ts"() {
389
- "use strict";
390
- init_hooks();
391
- VOID_ELEMENTS = /* @__PURE__ */ new Set([
392
- "area",
393
- "base",
394
- "br",
395
- "col",
396
- "embed",
397
- "hr",
398
- "img",
399
- "input",
400
- "link",
401
- "meta",
402
- "param",
403
- "source",
404
- "track",
405
- "wbr"
406
- ]);
407
- }
408
- });
409
-
410
- // src/server/database.ts
411
- var Database;
412
- var init_database = __esm({
413
- "src/server/database.ts"() {
414
- "use strict";
415
- Database = class {
416
- constructor(config) {
417
- __publicField(this, "config");
418
- __publicField(this, "mongoClient", null);
419
- __publicField(this, "mongoDb", null);
420
- __publicField(this, "mysqlPool", null);
421
- __publicField(this, "pgPool", null);
422
- this.config = config;
423
- }
424
- async connect() {
425
- switch (this.config.type) {
426
- case "mongodb":
427
- await this.connectMongo();
428
- break;
429
- case "mysql":
430
- await this.connectMysql();
431
- break;
432
- case "postgres":
433
- await this.connectPostgres();
434
- break;
435
- default:
436
- throw new Error(`Unsupported database type: ${this.config.type}`);
437
- }
438
- }
439
- async connectMongo() {
440
- try {
441
- const { MongoClient } = await import("mongodb");
442
- this.mongoClient = new MongoClient(this.config.url);
443
- await this.mongoClient.connect();
444
- this.mongoDb = this.mongoClient.db();
445
- console.log("Connected to MongoDB");
446
- } catch (error) {
447
- if (error.code === "MODULE_NOT_FOUND") {
448
- throw new Error("MongoDB driver not installed. Run: npm install mongodb");
449
- }
450
- console.error("MongoDB connection error:", error);
451
- throw error;
452
- }
453
- }
454
- async connectMysql() {
455
- try {
456
- const mysql = await import("mysql2/promise");
457
- this.mysqlPool = mysql.createPool(this.config.url);
458
- await this.mysqlPool.getConnection();
459
- console.log("Connected to MySQL");
460
- } catch (error) {
461
- if (error.code === "MODULE_NOT_FOUND") {
462
- throw new Error("MySQL driver not installed. Run: npm install mysql2");
463
- }
464
- console.error("MySQL connection error:", error);
465
- throw error;
466
- }
467
- }
468
- async connectPostgres() {
469
- try {
470
- const pg = await import("pg");
471
- this.pgPool = new pg.Pool({ connectionString: this.config.url });
472
- const client = await this.pgPool.connect();
473
- client.release();
474
- console.log("Connected to PostgreSQL");
475
- } catch (error) {
476
- if (error.code === "MODULE_NOT_FOUND") {
477
- throw new Error("PostgreSQL driver not installed. Run: npm install pg @types/pg");
478
- }
479
- console.error("PostgreSQL connection error:", error);
480
- throw error;
481
- }
482
- }
483
- async disconnect() {
484
- if (this.mongoClient) {
485
- await this.mongoClient.close();
486
- this.mongoClient = null;
487
- this.mongoDb = null;
488
- }
489
- if (this.mysqlPool) {
490
- await this.mysqlPool.end();
491
- this.mysqlPool = null;
492
- }
493
- if (this.pgPool) {
494
- await this.pgPool.end();
495
- this.pgPool = null;
496
- }
497
- }
498
- // Database-specific methods
499
- getMongoDb() {
500
- return this.mongoDb;
501
- }
502
- getMysqlPool() {
503
- return this.mysqlPool;
504
- }
505
- getPgPool() {
506
- return this.pgPool;
507
- }
508
- // Generic query method
509
- async query(sql, values) {
510
- switch (this.config.type) {
511
- case "mongodb":
512
- throw new Error("For MongoDB, use getMongoDb() instead of query()");
513
- case "mysql":
514
- if (!this.mysqlPool)
515
- throw new Error("MySQL not connected");
516
- const [rows] = await this.mysqlPool.execute(sql, values || []);
517
- return rows;
518
- case "postgres":
519
- if (!this.pgPool)
520
- throw new Error("PostgreSQL not connected");
521
- const result = await this.pgPool.query(sql, values || []);
522
- return result.rows;
523
- default:
524
- throw new Error(`Unsupported database type: ${this.config.type}`);
525
- }
526
- }
527
- };
528
- }
529
- });
530
-
531
- // src/server/auth.ts
532
- var AuthService;
533
- var init_auth = __esm({
534
- "src/server/auth.ts"() {
535
- "use strict";
536
- AuthService = class {
537
- constructor(config) {
538
- __publicField(this, "config");
539
- __publicField(this, "jwtPromise", null);
540
- this.config = {
541
- expiresIn: "24h",
542
- ...config
543
- };
544
- }
545
- async getJwt() {
546
- if (!this.jwtPromise) {
547
- this.jwtPromise = import("jsonwebtoken").catch((error) => {
548
- this.jwtPromise = null;
549
- if (error.code === "MODULE_NOT_FOUND") {
550
- throw new Error(
551
- "jsonwebtoken not installed. Run: npm install jsonwebtoken @types/jsonwebtoken"
552
- );
553
- }
554
- throw error;
555
- });
556
- }
557
- return this.jwtPromise;
558
- }
559
- async hashPassword(password) {
560
- try {
561
- const bcrypt = await import("bcryptjs");
562
- return bcrypt.hash(password, 10);
563
- } catch (error) {
564
- if (error.code === "MODULE_NOT_FOUND") {
565
- throw new Error("bcryptjs not installed. Run: npm install bcryptjs @types/bcryptjs");
566
- }
567
- throw error;
568
- }
569
- }
570
- async comparePasswords(password, hashedPassword) {
571
- try {
572
- const bcrypt = await import("bcryptjs");
573
- return bcrypt.compare(password, hashedPassword);
574
- } catch (error) {
575
- if (error.code === "MODULE_NOT_FOUND") {
576
- throw new Error("bcryptjs not installed. Run: npm install bcryptjs @types/bcryptjs");
577
- }
578
- throw error;
579
- }
580
- }
581
- async generateToken(user) {
582
- const jwt = await this.getJwt();
583
- const options = {};
584
- if (this.config.expiresIn) {
585
- options.expiresIn = this.config.expiresIn;
586
- }
587
- return jwt.sign(
588
- { id: user.id, username: user.username, roles: user.roles || [] },
589
- this.config.secret,
590
- options
591
- );
592
- }
593
- async verifyToken(token) {
594
- try {
595
- const jwt = await this.getJwt();
596
- return jwt.verify(token, this.config.secret);
597
- } catch {
598
- return null;
599
- }
600
- }
601
- initialize() {
602
- return async (req, res, next) => {
603
- const token = this.extractToken(req);
604
- if (token) {
605
- const decoded = await this.verifyToken(token);
606
- if (decoded) {
607
- req.user = decoded;
608
- }
609
- }
610
- next();
611
- };
612
- }
613
- requireAuth() {
614
- return (req, res, next) => {
615
- if (!req.user) {
616
- return res.status(401).json({ message: "Unauthorized" });
617
- }
618
- return next();
619
- };
620
- }
621
- requireRoles(roles) {
622
- return (req, res, next) => {
623
- if (!req.user) {
624
- return res.status(401).json({ message: "Unauthorized" });
625
- }
626
- const userRoles = req.user.roles || [];
627
- const hasRequiredRole = roles.some((role) => userRoles.includes(role));
628
- if (!hasRequiredRole) {
629
- return res.status(403).json({ message: "Forbidden" });
630
- }
631
- return next();
632
- };
633
- }
634
- extractToken(req) {
635
- if (req.headers.authorization && req.headers.authorization.startsWith("Bearer ")) {
636
- return req.headers.authorization.substring(7);
637
- }
638
- return null;
639
- }
640
- };
641
- }
642
- });
643
-
644
- // src/server/api-router.ts
645
- import path from "path";
646
- import fs from "fs";
647
- import { pathToFileURL } from "url";
648
- var ApiRouter;
649
- var init_api_router = __esm({
650
- "src/server/api-router.ts"() {
651
- "use strict";
652
- ApiRouter = class {
653
- constructor(apiDir, auth = null) {
654
- __publicField(this, "router", null);
655
- __publicField(this, "apiDir");
656
- __publicField(this, "auth");
657
- __publicField(this, "initialized", false);
658
- this.apiDir = path.resolve(process.cwd(), apiDir);
659
- this.auth = auth;
660
- }
661
- async initialize() {
662
- if (this.initialized && this.router)
663
- return;
664
- try {
665
- const express = await import("express");
666
- this.router = express.default.Router();
667
- this.setupRoutes();
668
- this.initialized = true;
669
- console.log("\u2705 API Router initialized successfully");
670
- } catch (error) {
671
- console.error("\u274C Failed to initialize API Router:", error);
672
- if (error.code === "MODULE_NOT_FOUND") {
673
- throw new Error("Express not installed. Run: npm install express @types/express");
674
- }
675
- throw error;
676
- }
677
- }
678
- isInitialized() {
679
- return this.initialized && this.router !== null;
680
- }
681
- setupRoutes() {
682
- if (!fs.existsSync(this.apiDir)) {
683
- console.log(`API directory not found: ${this.apiDir}`);
684
- return;
685
- }
686
- this.scanDirectory(this.apiDir, "");
687
- }
688
- scanDirectory(dirPath, routePrefix) {
689
- const entries = fs.readdirSync(dirPath, { withFileTypes: true });
690
- for (const entry of entries) {
691
- const fullPath = path.join(dirPath, entry.name);
692
- if (entry.isDirectory()) {
693
- this.scanDirectory(fullPath, `${routePrefix}/${entry.name}`);
694
- } else if (this.isRouteFile(entry.name)) {
695
- const routePath = this.getRoutePath(entry.name, routePrefix);
696
- this.registerRoute(fullPath, routePath);
697
- }
698
- }
699
- }
700
- isRouteFile(filename) {
701
- return filename.endsWith(".js") || filename.endsWith(".ts") || filename.endsWith(".mjs");
702
- }
703
- getRoutePath(filename, routePrefix) {
704
- const baseName = path.basename(filename, path.extname(filename));
705
- if (baseName === "index") {
706
- return routePrefix || "/";
707
- }
708
- const paramMatch = baseName.match(/^\[(.+)\]$/);
709
- if (paramMatch) {
710
- return `${routePrefix}/:${paramMatch[1]}`;
711
- }
712
- return `${routePrefix}/${baseName}`;
713
- }
714
- async registerRoute(filePath, routePath) {
715
- try {
716
- const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(filePath);
717
- const fileUrl = pathToFileURL(absolutePath).href;
718
- const urlWithTimestamp = `${fileUrl}?t=${Date.now()}`;
719
- const routeModule = await import(urlWithTimestamp);
720
- if (!this.isValidRouteModule(routeModule)) {
721
- console.warn(`Invalid route module: ${filePath}`);
722
- return;
723
- }
724
- console.log(`Registering API route: ${routePath}`);
725
- const middleware = routeModule.middleware || [];
726
- for (const method of ["get", "post", "put", "delete", "patch", "options"]) {
727
- const handler = routeModule[method];
728
- if (typeof handler === "function") {
729
- const routerMethod = this.router[method];
730
- routerMethod.call(
731
- this.router,
732
- routePath,
733
- ...middleware,
734
- this.wrapHandler(handler)
735
- );
736
- }
737
- }
738
- } catch (error) {
739
- console.error(`Error registering route (${filePath}):`, error);
740
- }
741
- }
742
- isValidRouteModule(module) {
743
- if (!module)
744
- return false;
745
- return ["get", "post", "put", "delete", "patch", "options"].some((method) => typeof module[method] === "function");
746
- }
747
- wrapHandler(handler) {
748
- return async (req, res, next) => {
749
- try {
750
- await handler(req, res, next);
751
- } catch (error) {
752
- next(error);
753
- }
754
- };
755
- }
756
- };
757
- }
758
- });
759
-
760
- // src/server/middleware.ts
761
- function rateLimit(options) {
762
- const requests = /* @__PURE__ */ new Map();
763
- const cleanupInterval = setInterval(() => {
764
- const now = Date.now();
765
- for (const [ip, times] of requests) {
766
- const valid = times.filter((t) => now - t < options.windowMs);
767
- if (valid.length === 0) {
768
- requests.delete(ip);
769
- } else {
770
- requests.set(ip, valid);
771
- }
772
- }
773
- }, options.windowMs);
774
- if (cleanupInterval.unref) {
775
- cleanupInterval.unref();
776
- }
777
- return (req, res, next) => {
778
- const ip = req.ip || req.socket?.remoteAddress || "unknown";
779
- const now = Date.now();
780
- const reqTimes = (requests.get(ip) || []).filter((time) => now - time < options.windowMs);
781
- reqTimes.push(now);
782
- requests.set(ip, reqTimes);
783
- if (reqTimes.length > options.max) {
784
- return res.status(429).json({
785
- error: {
786
- message: "Too Many Requests",
787
- retryAfter: Math.ceil(options.windowMs / 1e3)
788
- }
789
- });
790
- }
791
- return next();
792
- };
793
- }
794
- var requestLogger, errorHandler, notFoundHandler;
795
- var init_middleware = __esm({
796
- "src/server/middleware.ts"() {
797
- "use strict";
798
- requestLogger = (req, res, next) => {
799
- console.log(`${(/* @__PURE__ */ new Date()).toISOString()} - ${req.method} ${req.url}`);
800
- next();
801
- };
802
- errorHandler = (err, req, res, _next) => {
803
- console.error(err.stack);
804
- res.status(500).json({
805
- error: {
806
- message: "Internal Server Error",
807
- ...process.env.NODE_ENV !== "production" ? { details: err.message, stack: err.stack } : {}
808
- }
809
- });
810
- };
811
- notFoundHandler = (req, res) => {
812
- res.status(404).json({
813
- error: {
814
- message: `Not Found - ${req.method} ${req.url}`
815
- }
816
- });
817
- };
818
- }
819
- });
820
-
821
- // src/server/utils.ts
822
- var utils_exports = {};
823
- __export(utils_exports, {
824
- ensureDirectory: () => ensureDirectory,
825
- generateToken: () => generateToken,
826
- getEnvironmentInfo: () => getEnvironmentInfo,
827
- getPagination: () => getPagination,
828
- hashString: () => hashString,
829
- isDirectoryEmpty: () => isDirectoryEmpty,
830
- readJsonFile: () => readJsonFile,
831
- safeJsonParse: () => safeJsonParse,
832
- sendError: () => sendError,
833
- sendSuccess: () => sendSuccess,
834
- validateFields: () => validateFields,
835
- validateFileUpload: () => validateFileUpload,
836
- writeJsonFile: () => writeJsonFile
837
- });
838
- import crypto2 from "crypto";
839
- import fs2 from "fs/promises";
840
- import path2 from "path";
841
- function safeJsonParse(json, fallback) {
842
- try {
843
- return JSON.parse(json);
844
- } catch (error) {
845
- return fallback;
846
- }
847
- }
848
- function generateToken(length = 32) {
849
- return crypto2.randomBytes(length).toString("hex");
850
- }
851
- function hashString(input, salt = "") {
852
- return crypto2.createHash("sha256").update(input + salt).digest("hex");
853
- }
854
- function getPagination(req) {
855
- const page = Math.max(1, parseInt(req.query.page) || 1);
856
- const rawLimit = parseInt(req.query.limit);
857
- let limit;
858
- if (isNaN(rawLimit) || rawLimit <= 0) {
859
- limit = 20;
860
- } else {
861
- limit = Math.max(1, Math.min(100, rawLimit));
862
- }
863
- const skip = (page - 1) * limit;
864
- return { page, limit, skip };
865
- }
866
- function sendSuccess(res, data, message = "Success") {
867
- return res.json({
868
- success: true,
869
- message,
870
- data
871
- });
872
- }
873
- function sendError(res, message = "An error occurred", statusCode = 400, errors) {
874
- return res.status(statusCode).json({
875
- success: false,
876
- message,
877
- errors: errors || void 0
878
- });
879
- }
880
- function validateFields(req, requiredFields) {
881
- const missing = requiredFields.filter((field) => {
882
- const value = req.body[field];
883
- return value === void 0 || value === null || value === "";
884
- });
885
- return {
886
- valid: missing.length === 0,
887
- missing
888
- };
889
- }
890
- function validateFileUpload(file, options = {}) {
891
- if (!file) {
892
- return { valid: false, error: "No file provided" };
893
- }
894
- if (options.maxSize && file.size > options.maxSize) {
895
- return {
896
- valid: false,
897
- error: `File too large. Maximum size allowed is ${options.maxSize / 1024 / 1024}MB`
898
- };
899
- }
900
- if (options.allowedTypes && options.allowedTypes.length > 0) {
901
- const fileType = file.mimetype;
902
- if (!options.allowedTypes.includes(fileType)) {
903
- return {
904
- valid: false,
905
- error: `Invalid file type. Allowed types: ${options.allowedTypes.join(", ")}`
906
- };
907
- }
908
- }
909
- return { valid: true };
910
- }
911
- function getEnvironmentInfo() {
912
- return {
913
- nodeVersion: process.version,
914
- platform: process.platform,
915
- arch: process.arch,
916
- memory: process.memoryUsage(),
917
- uptime: process.uptime(),
918
- env: process.env.NODE_ENV || "development"
919
- };
920
- }
921
- async function isDirectoryEmpty(dirPath) {
922
- try {
923
- const files = await fs2.readdir(dirPath);
924
- return files.length === 0;
925
- } catch (error) {
926
- return true;
927
- }
928
- }
929
- async function ensureDirectory(dirPath) {
930
- try {
931
- await fs2.access(dirPath);
932
- } catch (error) {
933
- await fs2.mkdir(dirPath, { recursive: true });
934
- }
935
- }
936
- async function writeJsonFile(filePath, data) {
937
- await ensureDirectory(path2.dirname(filePath));
938
- await fs2.writeFile(filePath, JSON.stringify(data, null, 2), "utf8");
939
- }
940
- async function readJsonFile(filePath, defaultValue) {
941
- try {
942
- const data = await fs2.readFile(filePath, "utf8");
943
- return safeJsonParse(data, defaultValue);
944
- } catch (error) {
945
- return defaultValue;
946
- }
947
- }
948
- var init_utils = __esm({
949
- "src/server/utils.ts"() {
950
- "use strict";
951
- }
952
- });
953
-
954
- // src/server/templates.ts
955
- var templates_exports = {};
956
- __export(templates_exports, {
957
- generateDocument: () => generateDocument,
958
- generateErrorPage: () => generateErrorPage,
959
- generateLoadingPage: () => generateLoadingPage
960
- });
961
- function generateDocument(content, options = {}) {
962
- const {
963
- title = "Baraqex App",
964
- description = "",
965
- lang = "en",
966
- charset = "UTF-8",
967
- viewport = "width=device-width, initial-scale=1.0",
968
- scripts = [],
969
- styles = [],
970
- meta = {},
971
- bodyClasses = "",
972
- htmlAttrs = {},
973
- bodyAttrs = {},
974
- initialData = {},
975
- componentName = ""
976
- } = options;
977
- const htmlAttributes = Object.entries(htmlAttrs).map(([key, value]) => `${key}="${escapeHtml3(value)}"`).join(" ");
978
- const bodyAttributes = Object.entries(bodyAttrs).map(([key, value]) => `${key}="${escapeHtml3(value)}"`).join(" ");
979
- const metaTags = [
980
- `<meta charset="${charset}">`,
981
- `<meta name="viewport" content="${viewport}">`,
982
- description ? `<meta name="description" content="${escapeHtml3(description)}">` : ""
983
- ];
984
- Object.entries(meta).forEach(([name, content2]) => {
985
- metaTags.push(`<meta name="${escapeHtml3(name)}" content="${escapeHtml3(content2)}">`);
986
- });
987
- const scriptTags = scripts.map((src) => {
988
- if (src.startsWith("<script")) {
989
- return src;
990
- }
991
- return `<script src="${escapeHtml3(src)}" ${src.endsWith(".js") ? 'type="module"' : ""} defer></script>`;
992
- });
993
- const styleTags = styles.map((href) => {
994
- if (href.startsWith("<style")) {
995
- return href;
996
- }
997
- return `<link rel="stylesheet" href="${escapeHtml3(href)}">`;
998
- });
999
- const initialDataScript = Object.keys(initialData).length > 0 ? `<script id="__APP_DATA__" type="application/json">${escapeHtml3(JSON.stringify(initialData))}</script>` : "";
1000
- return `<!DOCTYPE html>
1001
- <html lang="${lang}" ${htmlAttributes}>
1002
- <head>
1003
- ${metaTags.filter(Boolean).join("\n ")}
1004
- <title>${escapeHtml3(title)}</title>
1005
- ${styleTags.join("\n ")}
1006
- </head>
1007
- <body class="${bodyClasses}" ${bodyAttributes}>
1008
- <div id="app-root" data-ssr-root${componentName ? ` data-component="${escapeHtml3(componentName)}"` : ""}>${content}</div>
1009
- ${initialDataScript}
1010
- ${scriptTags.join("\n ")}
1011
- </body>
1012
- </html>`;
1013
- }
1014
- function generateErrorPage(statusCode, message, error) {
1015
- const errorMessages = {
1016
- 400: "Bad Request",
1017
- 401: "Unauthorized",
1018
- 403: "Forbidden",
1019
- 404: "Not Found",
1020
- 500: "Internal Server Error"
1021
- };
1022
- const title = `${statusCode} - ${errorMessages[statusCode] || "Error"}`;
1023
- const isDev = process.env.NODE_ENV !== "production";
1024
- const errorDetails = isDev && error ? `
1025
- <div class="error-details">
1026
- <pre>${escapeHtml3(error.stack || error.message)}</pre>
1027
- </div>
1028
- ` : "";
1029
- const content = `
1030
- <div class="error-container">
1031
- <h1>${statusCode}</h1>
1032
- <h2>${escapeHtml3(errorMessages[statusCode] || "Error")}</h2>
1033
- <p>${escapeHtml3(message)}</p>
1034
- ${errorDetails}
1035
- <a href="/" class="home-link">Back to Home</a>
1036
- </div>
1037
- `;
1038
- const styles = [`<style>
1039
- body {
1040
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
1041
- display: flex;
1042
- justify-content: center;
1043
- align-items: center;
1044
- min-height: 100vh;
1045
- margin: 0;
1046
- background-color: #f7f7f7;
1047
- color: #333;
1048
- }
1049
- .error-container {
1050
- text-align: center;
1051
- padding: 2rem;
1052
- border-radius: 8px;
1053
- background-color: white;
1054
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
1055
- max-width: 600px;
1056
- width: 100%;
1057
- }
1058
- h1 {
1059
- font-size: 6rem;
1060
- margin: 0;
1061
- color: #e74c3c;
1062
- }
1063
- h2 {
1064
- margin-top: 0;
1065
- margin-bottom: 1rem;
1066
- color: #333;
1067
- }
1068
- .error-details {
1069
- text-align: left;
1070
- margin: 2rem 0;
1071
- padding: 1rem;
1072
- background-color: #f8f8f8;
1073
- border-radius: 4px;
1074
- overflow: auto;
1075
- }
1076
- pre {
1077
- margin: 0;
1078
- font-family: monospace;
1079
- font-size: 0.85rem;
1080
- white-space: pre-wrap;
1081
- }
1082
- .home-link {
1083
- display: inline-block;
1084
- margin-top: 1.5rem;
1085
- padding: 0.75rem 1.5rem;
1086
- background-color: #3498db;
1087
- color: white;
1088
- text-decoration: none;
1089
- border-radius: 4px;
1090
- transition: background-color 0.2s;
1091
- }
1092
- .home-link:hover {
1093
- background-color: #2980b9;
1094
- }
1095
- </style>`];
1096
- return generateDocument(content, {
1097
- title,
1098
- description: `Error ${statusCode}: ${errorMessages[statusCode] || "Error"}`,
1099
- bodyClasses: "error-page",
1100
- styles
1101
- });
1102
- }
1103
- function generateLoadingPage(message = "Loading...") {
1104
- const content = `
1105
- <div class="loading-container">
1106
- <div class="spinner"></div>
1107
- <p>${escapeHtml3(message)}</p>
1108
- </div>
1109
- `;
1110
- const styles = [`<style>
1111
- body {
1112
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
1113
- display: flex;
1114
- justify-content: center;
1115
- align-items: center;
1116
- min-height: 100vh;
1117
- margin: 0;
1118
- background-color: #f7f7f7;
1119
- color: #333;
1120
- }
1121
- .loading-container {
1122
- text-align: center;
1123
- }
1124
- .spinner {
1125
- width: 50px;
1126
- height: 50px;
1127
- border: 5px solid rgba(0, 0, 0, 0.1);
1128
- border-radius: 50%;
1129
- border-top-color: #3498db;
1130
- animation: spin 1s ease-in-out infinite;
1131
- margin: 0 auto 20px;
1132
- }
1133
- @keyframes spin {
1134
- to { transform: rotate(360deg); }
1135
- }
1136
- </style>`];
1137
- return generateDocument(content, {
1138
- title: "Loading",
1139
- bodyClasses: "loading-page",
1140
- styles
1141
- });
1142
- }
1143
- function escapeHtml3(text) {
1144
- return String(text).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
1145
- }
1146
- var init_templates = __esm({
1147
- "src/server/templates.ts"() {
1148
- "use strict";
1149
- }
1150
- });
1151
-
1152
- // src/server/wasm.ts
1153
- import fs3 from "fs/promises";
1154
- import path3 from "path";
1155
- import { pathToFileURL as pathToFileURL2 } from "url";
1156
- async function initNodeWasm() {
1157
- if (initialized)
1158
- return;
1159
- try {
1160
- globalThis.TextEncoder = globalThis.TextEncoder || TextEncoder;
1161
- globalThis.TextDecoder = globalThis.TextDecoder || TextDecoder;
1162
- initialized = true;
1163
- } catch (error) {
1164
- console.error("[WASM] Failed to initialize Node.js WASM environment:", error);
1165
- throw error;
1166
- }
1167
- }
1168
- async function loadGoRuntime(goWasmPath) {
1169
- if (typeof globalThis.Go === "function") {
1170
- return globalThis.Go;
1171
- }
1172
- const possiblePaths = [
1173
- goWasmPath,
1174
- "./wasm_exec.cjs",
1175
- "./wasm_exec.js",
1176
- "./public/wasm_exec.cjs",
1177
- "./public/wasm_exec.js",
1178
- "./src/wasm_exec.cjs",
1179
- "./src/wasm_exec.js",
1180
- path3.join(process.cwd(), "wasm_exec.cjs"),
1181
- path3.join(process.cwd(), "wasm_exec.js"),
1182
- path3.join(process.cwd(), "public", "wasm_exec.cjs"),
1183
- path3.join(process.cwd(), "public", "wasm_exec.js"),
1184
- path3.join(process.cwd(), "src", "wasm_exec.cjs"),
1185
- path3.join(process.cwd(), "src", "wasm_exec.js")
1186
- ].filter(Boolean);
1187
- for (const wasmExecPath of possiblePaths) {
1188
- try {
1189
- const resolvedPath = path3.resolve(wasmExecPath);
1190
- try {
1191
- const stats = await fs3.stat(resolvedPath);
1192
- if (!stats.isFile()) {
1193
- continue;
1194
- }
1195
- } catch (statError) {
1196
- continue;
1197
- }
1198
- const wasmExecUrl = pathToFileURL2(resolvedPath).href;
1199
- if (globalThis.Go) {
1200
- delete globalThis.Go;
1201
- }
1202
- await import(wasmExecUrl);
1203
- if (typeof globalThis.Go === "function") {
1204
- console.log(`[WASM] Loaded Go runtime from: ${resolvedPath}`);
1205
- return globalThis.Go;
1206
- } else {
1207
- console.warn(`[WASM] File found but Go class not exported: ${resolvedPath}`);
1208
- }
1209
- } catch (error) {
1210
- console.warn(`[WASM] Error loading from ${wasmExecPath}:`, error.message);
1211
- continue;
1212
- }
1213
- }
1214
- throw new Error(
1215
- `[WASM] Could not find wasm_exec.js. Please ensure you have the Go WASM runtime file available.
1216
- You can get it from: https://github.com/golang/go/blob/master/misc/wasm/wasm_exec.js
1217
- Searched paths: ${possiblePaths.join(", ")}`
1218
- );
1219
- }
1220
- async function loadGoWasmFromFile(wasmFilePath, options = {}) {
1221
- try {
1222
- await initNodeWasm();
1223
- if (options.debug) {
1224
- console.log("[WASM] Loading WASM from file:", wasmFilePath);
1225
- }
1226
- const GoRuntime = await loadGoRuntime(options.goWasmPath);
1227
- const go = new GoRuntime();
1228
- const wasmBuffer = await fs3.readFile(wasmFilePath);
1229
- const wasmModule = await WebAssembly.compile(new Uint8Array(wasmBuffer));
1230
- const baseImports = go.importObject;
1231
- const finalImportObject = {
1232
- ...baseImports,
1233
- ...options.importObject
1234
- };
1235
- if (options.debug) {
1236
- console.log("[WASM] Available import modules:", Object.keys(finalImportObject));
1237
- for (const [moduleName, moduleExports] of Object.entries(finalImportObject)) {
1238
- if (typeof moduleExports === "object" && moduleExports !== null) {
1239
- const exportNames = Object.keys(moduleExports);
1240
- console.log(`[WASM] ${moduleName} import functions:`, exportNames);
1241
- }
1242
- }
1243
- }
1244
- const instance = await WebAssembly.instantiate(wasmModule, finalImportObject);
1245
- if (options.debug) {
1246
- console.log("[WASM] WASM instance created, starting Go runtime...");
1247
- }
1248
- const runPromise = go.run(instance);
1249
- if (options.debug) {
1250
- console.log("[WASM] Go runtime started, waiting for initialization...");
1251
- }
1252
- await new Promise((resolve) => setTimeout(resolve, 2e3));
1253
- if (options.debug) {
1254
- console.log("[WASM] Scanning global object for Go functions...");
1255
- }
1256
- const functions = {};
1257
- const globalObj = globalThis;
1258
- const allKeys = Object.getOwnPropertyNames(globalObj);
1259
- const goKeys = allKeys.filter((key) => key.startsWith("go"));
1260
- if (options.debug) {
1261
- console.log('[WASM] All keys starting with "go":', goKeys);
1262
- }
1263
- for (const key of goKeys) {
1264
- if (typeof globalObj[key] === "function") {
1265
- functions[key] = globalObj[key];
1266
- if (options.debug) {
1267
- console.log(`[WASM] Found function: ${key}`);
1268
- }
1269
- }
1270
- }
1271
- const wasmInstance = {
1272
- instance,
1273
- module: wasmModule,
1274
- exports: instance.exports,
1275
- functions
1276
- };
1277
- if (options.onLoad) {
1278
- options.onLoad(wasmInstance);
1279
- }
1280
- if (options.debug) {
1281
- console.log(`[WASM] Module loaded successfully with ${Object.keys(functions).length} functions`);
1282
- console.log("[WASM] Final function list:", Object.keys(functions));
1283
- }
1284
- runPromise.catch((error) => {
1285
- if (options.debug) {
1286
- console.log("[WASM] Go program finished with error:", error);
1287
- }
1288
- });
1289
- return wasmInstance;
1290
- } catch (error) {
1291
- console.error("[WASM] Failed to load Go WASM module:", error);
1292
- throw error;
1293
- }
1294
- }
1295
- var initialized;
1296
- var init_wasm = __esm({
1297
- "src/server/wasm.ts"() {
1298
- "use strict";
1299
- initialized = false;
1300
- }
1301
- });
1302
-
1303
- // src/server/index.ts
1304
- var server_exports = {};
1305
- __export(server_exports, {
1306
- ApiRouter: () => ApiRouter,
1307
- AuthService: () => AuthService,
1308
- Database: () => Database,
1309
- Server: () => Server,
1310
- createDevServer: () => createDevServer,
1311
- createProductionServer: () => createProductionServer,
1312
- createServer: () => createServer,
1313
- default: () => server_default,
1314
- ensureDirectory: () => ensureDirectory,
1315
- errorHandler: () => errorHandler,
1316
- generateDocument: () => generateDocument,
1317
- generateErrorPage: () => generateErrorPage,
1318
- generateLoadingPage: () => generateLoadingPage,
1319
- generateToken: () => generateToken,
1320
- getEnvironmentInfo: () => getEnvironmentInfo,
1321
- getPagination: () => getPagination,
1322
- getRequestIp: () => getRequestIp,
1323
- hashString: () => hashString,
1324
- initNodeWasm: () => initNodeWasm,
1325
- isDirectoryEmpty: () => isDirectoryEmpty,
1326
- loadGoWasmFromFile: () => loadGoWasmFromFile,
1327
- notFoundHandler: () => notFoundHandler,
1328
- parseCookies: () => parseCookies,
1329
- rateLimit: () => rateLimit,
1330
- readJsonFile: () => readJsonFile,
1331
- renderComponent: () => renderComponent,
1332
- renderToString: () => renderToString,
1333
- requestLogger: () => requestLogger,
1334
- safeJsonParse: () => safeJsonParse,
1335
- sendError: () => sendError,
1336
- sendSuccess: () => sendSuccess,
1337
- validateFields: () => validateFields,
1338
- validateFileUpload: () => validateFileUpload,
1339
- writeJsonFile: () => writeJsonFile
1340
- });
1341
- import path4 from "path";
1342
- import fs4 from "fs";
1343
- import { pathToFileURL as pathToFileURL3 } from "url";
1344
- function getComponentName(filePath, pagesDir) {
1345
- try {
1346
- const relativePath = path4.relative(pagesDir, filePath);
1347
- const withoutExt = relativePath.replace(/\.[^/.]+$/, "");
1348
- const cleanPath = withoutExt.replace(/\/index$/, "");
1349
- return `/pages/${cleanPath}`;
1350
- } catch (e) {
1351
- return "";
1352
- }
1353
- }
1354
- function createServer(config = {}) {
1355
- return new Server(config);
1356
- }
1357
- function createDevServer(options = {}) {
1358
- return new Server({
1359
- port: options.port || 3e3,
1360
- enableCors: options.enableCors !== false,
1361
- apiDir: "./src/api",
1362
- pagesDir: "./src/pages",
1363
- staticDir: "./public"
1364
- });
1365
- }
1366
- function createProductionServer(config) {
1367
- const server = new Server({
1368
- ...config,
1369
- // Fix the PORT parsing
1370
- port: config.port || (process.env.PORT ? parseInt(process.env.PORT) : 8080)
1371
- });
1372
- server.addShutdownHandler();
1373
- return server;
1374
- }
1375
- function getRequestIp(req) {
1376
- return req.ip || req.headers["x-forwarded-for"]?.split(",")[0].trim() || req.socket.remoteAddress || "";
1377
- }
1378
- function parseCookies(req) {
1379
- const cookies = {};
1380
- const cookieHeader = req.headers.cookie;
1381
- if (cookieHeader) {
1382
- cookieHeader.split(";").forEach((cookie) => {
1383
- const [name, value] = cookie.split("=").map((c) => c.trim());
1384
- cookies[name] = value;
1385
- });
1386
- }
1387
- return cookies;
1388
- }
1389
- var Server, renderComponent, server_default;
1390
- var init_server = __esm({
1391
- "src/server/index.ts"() {
1392
- "use strict";
1393
- init_server_renderer();
1394
- init_database();
1395
- init_auth();
1396
- init_api_router();
1397
- init_middleware();
1398
- init_utils();
1399
- init_templates();
1400
- init_wasm();
1401
- init_wasm();
1402
- init_utils();
1403
- init_templates();
1404
- init_database();
1405
- init_auth();
1406
- init_api_router();
1407
- init_middleware();
1408
- Server = class {
1409
- constructor(config = {}) {
1410
- __publicField(this, "app");
1411
- __publicField(this, "server", null);
1412
- __publicField(this, "config");
1413
- __publicField(this, "db", null);
1414
- __publicField(this, "auth", null);
1415
- __publicField(this, "initialized", false);
1416
- this.config = {
1417
- port: 3e3,
1418
- apiDir: "./api",
1419
- pagesDir: "./pages",
1420
- staticDir: "./public",
1421
- enableCors: true,
1422
- ...config
1423
- };
1424
- }
1425
- async initializeApp() {
1426
- if (this.initialized)
1427
- return;
1428
- try {
1429
- const express = await import("express");
1430
- this.app = express.default();
1431
- this.app.use(express.default.json());
1432
- this.app.use(express.default.urlencoded({ extended: true }));
1433
- if (this.config.enableCors) {
1434
- try {
1435
- const cors = await import("cors");
1436
- this.app.use(cors.default(this.config.corsOptions));
1437
- } catch (error) {
1438
- console.warn("CORS not available - install with: npm install cors @types/cors");
1439
- }
1440
- }
1441
- if (this.config.db) {
1442
- this.db = new Database(this.config.db);
1443
- }
1444
- if (this.config.auth) {
1445
- this.auth = new AuthService({
1446
- secret: this.config.auth.secret,
1447
- expiresIn: this.config.auth.expiresIn
1448
- });
1449
- this.app.use(this.auth.initialize());
1450
- }
1451
- const staticPath = path4.resolve(process.cwd(), this.config.staticDir);
1452
- if (fs4.existsSync(staticPath)) {
1453
- this.app.use(express.default.static(staticPath));
1454
- }
1455
- this.setupApiRoutes();
1456
- this.setupPageRoutes();
1457
- this.app.use(notFoundHandler);
1458
- this.app.use(errorHandler);
1459
- this.initialized = true;
1460
- } catch (error) {
1461
- if (error.code === "MODULE_NOT_FOUND" && error.message.includes("express")) {
1462
- throw new Error("Express not installed. Run: npm install express @types/express");
1463
- }
1464
- throw error;
1465
- }
1466
- }
1467
- async setupApiRoutes() {
1468
- const apiRouter = new ApiRouter(this.config.apiDir, this.auth);
1469
- await apiRouter.initialize();
1470
- if (!apiRouter.isInitialized() || !apiRouter.router) {
1471
- console.warn("\u26A0\uFE0F API router not initialized properly - skipping API routes");
1472
- return;
1473
- }
1474
- console.log("\u2705 Setting up API routes...");
1475
- this.app.use("/api", requestLogger, apiRouter.router);
1476
- this.app.get("/api-docs", (req, res) => {
1477
- const apiDocs = this.generateApiDocs();
1478
- res.json(apiDocs);
1479
- });
1480
- }
1481
- generateApiDocs() {
1482
- const apiDir = path4.resolve(process.cwd(), this.config.apiDir);
1483
- const docs = { endpoints: [] };
1484
- if (fs4.existsSync(apiDir)) {
1485
- this.scanApiDirectory(apiDir, "", docs.endpoints);
1486
- }
1487
- return docs;
1488
- }
1489
- scanApiDirectory(dirPath, routePrefix, endpoints) {
1490
- const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
1491
- for (const entry of entries) {
1492
- const fullPath = path4.join(dirPath, entry.name);
1493
- if (entry.isDirectory()) {
1494
- this.scanApiDirectory(fullPath, `${routePrefix}/${entry.name}`, endpoints);
1495
- } else if (entry.name.endsWith(".js") || entry.name.endsWith(".ts")) {
1496
- const routePath = this.getRoutePath(entry.name, routePrefix);
1497
- endpoints.push({
1498
- path: routePath,
1499
- file: path4.relative(process.cwd(), fullPath),
1500
- methods: this.detectApiMethods(fullPath)
1501
- });
1502
- }
1503
- }
1504
- }
1505
- getRoutePath(filename, routePrefix) {
1506
- const baseName = path4.basename(filename, path4.extname(filename));
1507
- if (baseName === "index") {
1508
- return routePrefix || "/";
1509
- }
1510
- const paramMatch = baseName.match(/^\[(.+)\]$/);
1511
- if (paramMatch) {
1512
- return `${routePrefix}/:${paramMatch[1]}`;
1513
- }
1514
- return `${routePrefix}/${baseName}`;
1515
- }
1516
- detectApiMethods(filePath) {
1517
- try {
1518
- const content = fs4.readFileSync(filePath, "utf8");
1519
- const methods = ["get", "post", "put", "delete", "patch", "options"];
1520
- return methods.filter(
1521
- (method) => new RegExp(`export (async )?function ${method}\\s*\\(`).test(content) || new RegExp(`export const ${method}\\s*=`).test(content)
1522
- );
1523
- } catch (error) {
1524
- return [];
1525
- }
1526
- }
1527
- setupPageRoutes() {
1528
- const pagesPath = path4.resolve(process.cwd(), this.config.pagesDir);
1529
- if (!fs4.existsSync(pagesPath)) {
1530
- return;
1531
- }
1532
- this.app.get("*", async (req, res) => {
1533
- try {
1534
- const { html, statusCode } = await this.renderPage(req.path);
1535
- res.status(statusCode || 200).send(html);
1536
- } catch (error) {
1537
- console.error("Error rendering page:", error);
1538
- const errorHtml = generateErrorPage(500, "Server Error");
1539
- res.status(500).send(errorHtml);
1540
- }
1541
- });
1542
- }
1543
- async renderPage(routePath) {
1544
- try {
1545
- const pagesDir = this.config.pagesDir ? path4.resolve(process.cwd(), this.config.pagesDir) : "";
1546
- if (!pagesDir || !fs4.existsSync(pagesDir)) {
1547
- return {
1548
- html: generateErrorPage(404, "Pages directory not found"),
1549
- statusCode: 404
1550
- };
1551
- }
1552
- let normalizedPath = routePath;
1553
- if (!normalizedPath.startsWith("/")) {
1554
- normalizedPath = "/" + normalizedPath;
1555
- }
1556
- if (normalizedPath === "/") {
1557
- normalizedPath = "/index";
1558
- }
1559
- let pagePath = "";
1560
- const possiblePaths = [
1561
- path4.join(pagesDir, `${normalizedPath}.js`),
1562
- path4.join(pagesDir, `${normalizedPath}.ts`),
1563
- path4.join(pagesDir, `${normalizedPath}.jsx`),
1564
- path4.join(pagesDir, `${normalizedPath}.tsx`),
1565
- path4.join(pagesDir, `${normalizedPath}/index.js`),
1566
- path4.join(pagesDir, `${normalizedPath}/index.ts`),
1567
- path4.join(pagesDir, `${normalizedPath}/index.jsx`),
1568
- path4.join(pagesDir, `${normalizedPath}/index.tsx`)
1569
- ];
1570
- for (const p of possiblePaths) {
1571
- if (fs4.existsSync(p)) {
1572
- pagePath = p;
1573
- break;
1574
- }
1575
- }
1576
- if (!pagePath) {
1577
- return {
1578
- html: generateErrorPage(404, `Page not found: ${normalizedPath}`),
1579
- statusCode: 404
1580
- };
1581
- }
1582
- try {
1583
- const absolutePath = path4.isAbsolute(pagePath) ? pagePath : path4.resolve(pagePath);
1584
- const fileUrl = pathToFileURL3(absolutePath).href;
1585
- const urlWithTimestamp = `${fileUrl}?t=${Date.now()}`;
1586
- const pageModule = await import(urlWithTimestamp);
1587
- if (!pageModule || !pageModule.default) {
1588
- throw new Error(`No default export found in ${pagePath}`);
1589
- }
1590
- const PageComponent = pageModule.default;
1591
- const initialProps = {
1592
- // Provide any initial props here
1593
- path: normalizedPath,
1594
- query: {},
1595
- // Could be parsed from URL
1596
- api: { serverTime: (/* @__PURE__ */ new Date()).toISOString() }
1597
- };
1598
- const renderResult = await renderComponent(PageComponent, initialProps);
1599
- if (!renderResult.success) {
1600
- return {
1601
- html: generateErrorPage(500, "Failed to render page", renderResult.error instanceof Error ? renderResult.error : new Error("Unknown error")),
1602
- statusCode: 500
1603
- };
1604
- }
1605
- const htmlContent = renderResult.html;
1606
- let pageTitle = "My App";
1607
- try {
1608
- if (typeof PageComponent.getTitle === "function") {
1609
- pageTitle = PageComponent.getTitle(initialProps);
1610
- } else if (PageComponent.title) {
1611
- pageTitle = PageComponent.title;
1612
- }
1613
- } catch (e) {
1614
- }
1615
- const componentName = getComponentName(pagePath, pagesDir);
1616
- const fullHtml = generateDocument(htmlContent, {
1617
- title: pageTitle,
1618
- // Get description from component if available
1619
- description: typeof PageComponent.getDescription === "function" ? PageComponent.getDescription(initialProps) : PageComponent.description || "",
1620
- // Add scripts for client-side hydration
1621
- scripts: ["/client.js"],
1622
- // Add any custom meta tags
1623
- meta: typeof PageComponent.getMeta === "function" ? PageComponent.getMeta(initialProps) : {},
1624
- // Add custom styles
1625
- styles: ["/styles.css"],
1626
- // Add initial data for client-side hydration
1627
- initialData: initialProps,
1628
- // Add component information for hydration
1629
- componentName
1630
- });
1631
- return { html: fullHtml, statusCode: 200 };
1632
- } catch (error) {
1633
- console.error("Error rendering page:", error);
1634
- return {
1635
- html: generateErrorPage(500, "Error rendering page", error instanceof Error ? error : new Error("Unknown error")),
1636
- statusCode: 500
1637
- };
1638
- }
1639
- } catch (error) {
1640
- console.error("Error finding page:", error);
1641
- return {
1642
- html: generateErrorPage(500, "Server error", error instanceof Error ? error : new Error("Unknown error")),
1643
- statusCode: 500
1644
- };
1645
- }
1646
- }
1647
- getExpressApp() {
1648
- return this.app;
1649
- }
1650
- getDatabase() {
1651
- return this.db;
1652
- }
1653
- getAuth() {
1654
- return this.auth;
1655
- }
1656
- async start() {
1657
- await this.initializeApp();
1658
- return new Promise((resolve) => {
1659
- this.server = this.app.listen(this.config.port, () => {
1660
- console.log(`Server running at http://localhost:${this.config.port}`);
1661
- resolve();
1662
- });
1663
- });
1664
- }
1665
- stop() {
1666
- return new Promise((resolve, reject) => {
1667
- if (!this.server) {
1668
- return resolve();
1669
- }
1670
- this.server.close((err) => {
1671
- if (err)
1672
- return reject(err);
1673
- this.server = null;
1674
- resolve();
1675
- });
1676
- });
1677
- }
1678
- restart() {
1679
- return this.stop().then(() => this.start());
1680
- }
1681
- enableSSR(options = {}) {
1682
- if (!fs4.existsSync(path4.resolve(process.cwd(), this.config.pagesDir))) {
1683
- fs4.mkdirSync(path4.resolve(process.cwd(), this.config.pagesDir), { recursive: true });
1684
- }
1685
- if (options.hydratable) {
1686
- const staticDir = path4.resolve(process.cwd(), this.config.staticDir);
1687
- if (!fs4.existsSync(staticDir)) {
1688
- fs4.mkdirSync(staticDir, { recursive: true });
1689
- }
1690
- const clientJsPath = path4.join(staticDir, "client.js");
1691
- if (!fs4.existsSync(clientJsPath)) {
1692
- const clientJsContent = `
1693
- // Auto-generated hydration script
1694
- import { hydrate } from 'baraqex';
1695
-
1696
- // Find SSR content and hydrate it
1697
- document.addEventListener('DOMContentLoaded', () => {
1698
- const ssrRoots = document.querySelectorAll('[data-ssr-root]');
1699
- ssrRoots.forEach(root => {
1700
- const componentPath = root.getAttribute('data-component');
1701
- if (componentPath) {
1702
- import(componentPath).then(module => {
1703
- hydrate(module.default, root);
1704
- });
1705
- }
1706
- });
1707
- });
1708
- `;
1709
- fs4.writeFileSync(clientJsPath, clientJsContent);
1710
- }
1711
- }
1712
- }
1713
- registerPlugin(plugin) {
1714
- plugin(this);
1715
- }
1716
- addShutdownHandler() {
1717
- const gracefulShutdown = async () => {
1718
- console.log("Received shutdown signal, closing server...");
1719
- try {
1720
- await this.stop();
1721
- if (this.db) {
1722
- await this.db.disconnect();
1723
- }
1724
- console.log("Server shut down gracefully");
1725
- process.exit(0);
1726
- } catch (error) {
1727
- console.error("Error during shutdown:", error);
1728
- process.exit(1);
1729
- }
1730
- };
1731
- process.on("SIGTERM", gracefulShutdown);
1732
- process.on("SIGINT", gracefulShutdown);
1733
- }
1734
- };
1735
- renderComponent = (Component2, props = {}) => {
1736
- try {
1737
- const html = renderToString(Component2(props));
1738
- return {
1739
- html: typeof html === "string" ? html : String(html),
1740
- success: true
1741
- };
1742
- } catch (error) {
1743
- console.error("Error rendering component:", error);
1744
- return {
1745
- html: `<div class="error">Error rendering component</div>`,
1746
- success: false,
1747
- error
1748
- };
1749
- }
1750
- };
1751
- server_default = {
1752
- Server,
1753
- createServer,
1754
- createDevServer,
1755
- createProductionServer,
1756
- rateLimit,
1757
- requestLogger,
1758
- errorHandler,
1759
- notFoundHandler,
1760
- loadGoWasmFromFile,
1761
- // Template utilities
1762
- templates: templates_exports,
1763
- // Server utilities
1764
- utils: utils_exports,
1765
- // Additional exports
1766
- renderComponent,
1767
- renderToString,
1768
- getRequestIp,
1769
- parseCookies,
1770
- Database,
1771
- AuthService,
1772
- ApiRouter
1773
- };
1774
- }
1775
- });
1776
-
1777
- // src/server-renderer.ts
1778
- var server_renderer_exports = {};
1779
- __export(server_renderer_exports, {
1780
- renderToString: () => renderToString2
1781
- });
1782
- function renderToString2(component) {
1783
- try {
1784
- if (typeof component === "function") {
1785
- const result = component();
1786
- if (typeof result === "string") {
1787
- return result;
1788
- }
1789
- if (result && typeof result === "object") {
1790
- return JSON.stringify(result);
1791
- }
1792
- return String(result || "");
1793
- }
1794
- if (typeof component === "string") {
1795
- return component;
1796
- }
1797
- return String(component || "");
1798
- } catch (error) {
1799
- console.error("Error in renderToString:", error);
1800
- return "<div>Error rendering component</div>";
1801
- }
1802
- }
1803
- var init_server_renderer2 = __esm({
1804
- "src/server-renderer.ts"() {
1805
- "use strict";
1806
- }
1807
- });
1808
-
1809
- // src/core/batch.ts
1810
- var isBatching = false;
1811
- var syncQueue = [];
1812
- var asyncQueue = [];
1813
- async function batchUpdates(fn) {
1814
- if (isBatching) {
1815
- if (fn.constructor.name === "AsyncFunction") {
1816
- asyncQueue.push(fn);
1817
- } else {
1818
- syncQueue.push(fn);
1819
- }
1820
- return;
1821
- }
1822
- isBatching = true;
1823
- try {
1824
- const result = fn();
1825
- if (result instanceof Promise) {
1826
- await result;
1827
- }
1828
- while (syncQueue.length > 0) {
1829
- const nextFn = syncQueue.shift();
1830
- nextFn();
1831
- }
1832
- while (asyncQueue.length > 0) {
1833
- const nextFn = asyncQueue.shift();
1834
- await nextFn();
1835
- }
1836
- } finally {
1837
- isBatching = false;
1838
- }
1839
- }
1840
- function getIsBatching() {
1841
- return isBatching;
1842
- }
1843
-
1844
- // src/core/index.ts
1845
- init_context();
1846
- init_hooks();
1847
-
1848
- // src/core/jsx-runtime.ts
1849
- init_hooks();
1850
- var isBrowser = typeof document !== "undefined";
1851
- function jsx(type, props, key) {
1852
- const processedProps = { ...props };
1853
- if (key !== void 0) {
1854
- processedProps.key = key;
1855
- }
1856
- if (arguments.length > 3) {
1857
- processedProps.children = Array.prototype.slice.call(arguments, 3);
1858
- }
1859
- return { type, props: processedProps, key: processedProps.key };
1860
- }
1861
- var jsxs = jsx;
1862
- function jsxDEV(type, props, key, _isStaticChildren, _source, _self) {
1863
- return jsx(type, props, key);
1864
- }
1865
- var Fragment = ({ children }) => children;
1866
- function assertBrowser(method) {
1867
- if (!isBrowser) {
1868
- throw new Error(
1869
- `[baraqex] ${method}() can only be called in a browser environment. Use renderToString() for server-side rendering.`
1870
- );
1871
- }
1872
- }
1873
- function createTextNode(text) {
1874
- return document.createTextNode(text);
1875
- }
1876
- function applyProps(element, props) {
1877
- for (const [key, value] of Object.entries(props)) {
1878
- if (key === "children")
1879
- continue;
1880
- if (key === "className") {
1881
- element.setAttribute("class", String(value));
1882
- } else if (key === "htmlFor") {
1883
- element.setAttribute("for", String(value));
1884
- } else if (key.startsWith("on") && typeof value === "function") {
1885
- const eventName = key.slice(2).toLowerCase();
1886
- element.addEventListener(eventName, value);
1887
- } else if (key === "style" && typeof value === "object") {
1888
- Object.assign(element.style, value);
1889
- } else if (key === "dangerouslySetInnerHTML" && value && value.__html) {
1890
- element.innerHTML = value.__html;
1891
- } else if (key === "ref") {
1892
- if (typeof value === "function") {
1893
- value(element);
1894
- } else if (value && typeof value === "object" && "current" in value) {
1895
- value.current = element;
1896
- }
1897
- } else if (value !== false && value != null) {
1898
- if (value === true) {
1899
- element.setAttribute(key, "");
1900
- } else {
1901
- element.setAttribute(key, String(value));
1902
- }
1903
- }
1904
- }
1905
- }
1906
- async function createElement(vnode) {
1907
- assertBrowser("createElement");
1908
- if (vnode == null || typeof vnode === "boolean") {
1909
- return createTextNode("");
1910
- }
1911
- if (typeof vnode === "number" || typeof vnode === "string") {
1912
- return createTextNode(String(vnode));
1913
- }
1914
- if (Array.isArray(vnode)) {
1915
- const fragment = document.createDocumentFragment();
1916
- for (const child of vnode) {
1917
- const node = await createElement(child);
1918
- fragment.appendChild(node);
1919
- }
1920
- return fragment;
1921
- }
1922
- if (typeof vnode === "object" && "type" in vnode && vnode.props !== void 0) {
1923
- const { type, props } = vnode;
1924
- if (typeof type === "function") {
1925
- if (type === Fragment) {
1926
- const children2 = props?.children;
1927
- if (children2 == null)
1928
- return createTextNode("");
1929
- return createElement(children2);
1930
- }
1931
- const root = getCurrentRoot() ?? void 0;
1932
- const renderId = prepareRender(root);
1933
- try {
1934
- const result = type(props || {});
1935
- return await createElement(result);
1936
- } finally {
1937
- finishRender();
1938
- }
1939
- }
1940
- const element = document.createElement(type);
1941
- applyProps(element, props || {});
1942
- const children = props?.children;
1943
- if (children != null) {
1944
- const childArray = Array.isArray(children) ? children : [children];
1945
- for (const child of childArray) {
1946
- const childNode = await createElement(child);
1947
- element.appendChild(childNode);
1948
- }
1949
- }
1950
- return element;
1951
- }
1952
- return createTextNode(String(vnode));
1953
- }
1954
- function createElementSync(vnode) {
1955
- assertBrowser("createElementSync");
1956
- if (vnode == null || typeof vnode === "boolean") {
1957
- return createTextNode("");
1958
- }
1959
- if (typeof vnode === "number" || typeof vnode === "string") {
1960
- return createTextNode(String(vnode));
1961
- }
1962
- if (Array.isArray(vnode)) {
1963
- const fragment = document.createDocumentFragment();
1964
- for (const child of vnode) {
1965
- fragment.appendChild(createElementSync(child));
1966
- }
1967
- return fragment;
1968
- }
1969
- if (typeof vnode === "object" && "type" in vnode) {
1970
- const { type, props } = vnode;
1971
- if (typeof type === "function") {
1972
- if (type === Fragment) {
1973
- return createElementSync(props?.children);
1974
- }
1975
- const result = type(props || {});
1976
- return createElementSync(result);
1977
- }
1978
- const element = document.createElement(type);
1979
- applyProps(element, props || {});
1980
- const children = props?.children;
1981
- if (children != null) {
1982
- const childArray = Array.isArray(children) ? children : [children];
1983
- for (const child of childArray) {
1984
- element.appendChild(createElementSync(child));
1985
- }
1986
- }
1987
- return element;
1988
- }
1989
- return createTextNode(String(vnode));
1990
- }
1991
-
1992
- // src/core/renderer.ts
1993
- init_hooks();
1994
- var isBrowser2 = typeof document !== "undefined";
1995
- var rootMap = /* @__PURE__ */ new WeakMap();
1996
- async function render(element, container) {
1997
- if (!isBrowser2) {
1998
- throw new Error(
1999
- "[baraqex] render() can only be called in a browser. Use renderToString() for server-side rendering."
2000
- );
2001
- }
2002
- if (!container) {
2003
- throw new Error("[baraqex] render() requires a container element");
2004
- }
2005
- let root = rootMap.get(container);
2006
- if (!root) {
2007
- root = createRootState();
2008
- rootMap.set(container, root);
2009
- }
2010
- await batchUpdates(async () => {
2011
- prepareRender(root);
2012
- try {
2013
- setRenderCallback(render, element, container);
2014
- const domNode = await createElement(element);
2015
- container.textContent = "";
2016
- container.appendChild(domNode);
2017
- } finally {
2018
- finishRender();
2019
- }
2020
- });
2021
- }
2022
- async function hydrate(element, container) {
2023
- await render(element, container);
2024
- }
2025
- function createRoot(container) {
2026
- const root = createRootState();
2027
- rootMap.set(container, root);
2028
- return {
2029
- render: (element) => render(element, container),
2030
- unmount: () => {
2031
- cleanupRoot(root);
2032
- rootMap.delete(container);
2033
- container.textContent = "";
2034
- }
2035
- };
2036
- }
2037
- function hasRoot(container) {
2038
- return rootMap.has(container);
2039
- }
2040
-
2041
- // src/core/index.ts
2042
- init_server_renderer();
2043
608
 
2044
609
  // src/core/vdom.ts
2045
610
  var isBrowser3 = typeof document !== "undefined";
@@ -2417,8 +982,6 @@ function useEvent(event, handler, options = {}) {
2417
982
  }
2418
983
 
2419
984
  // src/core/router.ts
2420
- init_context();
2421
- init_hooks();
2422
985
  var RouterContext = createContext({
2423
986
  pathname: "/",
2424
987
  search: "",
@@ -2660,7 +1223,6 @@ function useMatch(pattern) {
2660
1223
  }
2661
1224
 
2662
1225
  // src/core/forms.ts
2663
- init_hooks();
2664
1226
  function validateFieldValue(value, rules, allValues) {
2665
1227
  if (rules.required) {
2666
1228
  const isEmpty2 = value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
@@ -2891,8 +1453,6 @@ var patterns = {
2891
1453
  };
2892
1454
 
2893
1455
  // src/core/store.ts
2894
- init_context();
2895
- init_hooks();
2896
1456
  function createStore(reducer, initialState, middlewares = []) {
2897
1457
  let state = initialState;
2898
1458
  let listeners = /* @__PURE__ */ new Set();
@@ -3024,740 +1584,1563 @@ function createSlice(config) {
3024
1584
  return reducers[key](state, action);
3025
1585
  }
3026
1586
  }
3027
- return state;
1587
+ return state;
1588
+ };
1589
+ return {
1590
+ name,
1591
+ reducer,
1592
+ actions
1593
+ };
1594
+ }
1595
+
1596
+ // src/core/lifecycle-events.ts
1597
+ var LifecycleEvents = /* @__PURE__ */ ((LifecycleEvents2) => {
1598
+ LifecycleEvents2["APP_INIT"] = "app:init";
1599
+ LifecycleEvents2["APP_MOUNTED"] = "app:mounted";
1600
+ LifecycleEvents2["APP_UPDATED"] = "app:updated";
1601
+ LifecycleEvents2["APP_ERROR"] = "app:error";
1602
+ LifecycleEvents2["APP_DESTROYED"] = "app:destroyed";
1603
+ LifecycleEvents2["COMPONENT_CREATED"] = "component:created";
1604
+ LifecycleEvents2["COMPONENT_MOUNTED"] = "component:mounted";
1605
+ LifecycleEvents2["COMPONENT_UPDATED"] = "component:updated";
1606
+ LifecycleEvents2["COMPONENT_ERROR"] = "component:error";
1607
+ LifecycleEvents2["COMPONENT_UNMOUNTED"] = "component:unmounted";
1608
+ LifecycleEvents2["ROUTER_BEFORE_CHANGE"] = "router:before-change";
1609
+ LifecycleEvents2["ROUTER_AFTER_CHANGE"] = "router:after-change";
1610
+ LifecycleEvents2["ROUTER_ERROR"] = "router:error";
1611
+ LifecycleEvents2["STORE_INITIALIZED"] = "store:initialized";
1612
+ LifecycleEvents2["STORE_BEFORE_ACTION"] = "store:before-action";
1613
+ LifecycleEvents2["STORE_AFTER_ACTION"] = "store:after-action";
1614
+ LifecycleEvents2["STORE_ERROR"] = "store:error";
1615
+ return LifecycleEvents2;
1616
+ })(LifecycleEvents || {});
1617
+ function emitAppInit(data) {
1618
+ eventBus.emit("app:init" /* APP_INIT */, data);
1619
+ }
1620
+ function emitAppMounted(rootElement) {
1621
+ eventBus.emit("app:mounted" /* APP_MOUNTED */, rootElement);
1622
+ }
1623
+ function emitAppUpdated() {
1624
+ eventBus.emit("app:updated" /* APP_UPDATED */);
1625
+ }
1626
+ function emitAppError(error) {
1627
+ eventBus.emit("app:error" /* APP_ERROR */, error);
1628
+ }
1629
+ function emitAppDestroyed() {
1630
+ eventBus.emit("app:destroyed" /* APP_DESTROYED */);
1631
+ }
1632
+ function emitComponentCreated(info) {
1633
+ eventBus.emit("component:created" /* COMPONENT_CREATED */, info);
1634
+ }
1635
+ function emitComponentMounted(info, element) {
1636
+ eventBus.emit("component:mounted" /* COMPONENT_MOUNTED */, info, element);
1637
+ }
1638
+ function emitComponentUpdated(info, prevProps, newProps) {
1639
+ eventBus.emit("component:updated" /* COMPONENT_UPDATED */, info, prevProps, newProps);
1640
+ }
1641
+ function emitComponentError(info, error) {
1642
+ eventBus.emit("component:error" /* COMPONENT_ERROR */, info, error);
1643
+ }
1644
+ function emitComponentUnmounted(info) {
1645
+ eventBus.emit("component:unmounted" /* COMPONENT_UNMOUNTED */, info);
1646
+ }
1647
+ function emitRouterBeforeChange(info) {
1648
+ return new Promise((resolve) => {
1649
+ let prevented = false;
1650
+ const prevent = () => {
1651
+ prevented = true;
1652
+ };
1653
+ eventBus.emit("router:before-change" /* ROUTER_BEFORE_CHANGE */, info, prevent);
1654
+ resolve(!prevented);
1655
+ });
1656
+ }
1657
+ function emitRouterAfterChange(info) {
1658
+ eventBus.emit("router:after-change" /* ROUTER_AFTER_CHANGE */, info);
1659
+ }
1660
+ function emitRouterError(error, info) {
1661
+ eventBus.emit("router:error" /* ROUTER_ERROR */, error, info);
1662
+ }
1663
+ function emitStoreInitialized(state) {
1664
+ eventBus.emit("store:initialized" /* STORE_INITIALIZED */, state);
1665
+ }
1666
+ function emitStoreBeforeAction(actionType, payload, state) {
1667
+ eventBus.emit("store:before-action" /* STORE_BEFORE_ACTION */, actionType, payload, state);
1668
+ }
1669
+ function emitStoreAfterAction(info) {
1670
+ eventBus.emit("store:after-action" /* STORE_AFTER_ACTION */, info);
1671
+ }
1672
+ function emitStoreError(error, actionType, payload) {
1673
+ eventBus.emit("store:error" /* STORE_ERROR */, error, actionType, payload);
1674
+ }
1675
+ function onAppInit(handler) {
1676
+ return eventBus.on("app:init" /* APP_INIT */, handler);
1677
+ }
1678
+ function onAppMounted(handler) {
1679
+ return eventBus.on("app:mounted" /* APP_MOUNTED */, handler);
1680
+ }
1681
+ function onAppUpdated(handler) {
1682
+ return eventBus.on("app:updated" /* APP_UPDATED */, handler);
1683
+ }
1684
+ function onAppError(handler) {
1685
+ return eventBus.on("app:error" /* APP_ERROR */, handler);
1686
+ }
1687
+ function onAppDestroyed(handler) {
1688
+ return eventBus.on("app:destroyed" /* APP_DESTROYED */, handler);
1689
+ }
1690
+ function onComponentCreated(handler) {
1691
+ return eventBus.on("component:created" /* COMPONENT_CREATED */, handler);
1692
+ }
1693
+ function onComponentMounted(handler) {
1694
+ return eventBus.on("component:mounted" /* COMPONENT_MOUNTED */, handler);
1695
+ }
1696
+ function onComponentUpdated(handler) {
1697
+ return eventBus.on("component:updated" /* COMPONENT_UPDATED */, handler);
1698
+ }
1699
+ function onComponentError(handler) {
1700
+ return eventBus.on("component:error" /* COMPONENT_ERROR */, handler);
1701
+ }
1702
+ function onComponentUnmounted(handler) {
1703
+ return eventBus.on("component:unmounted" /* COMPONENT_UNMOUNTED */, handler);
1704
+ }
1705
+ function onRouterBeforeChange(handler) {
1706
+ return eventBus.on("router:before-change" /* ROUTER_BEFORE_CHANGE */, handler);
1707
+ }
1708
+ function onRouterAfterChange(handler) {
1709
+ return eventBus.on("router:after-change" /* ROUTER_AFTER_CHANGE */, handler);
1710
+ }
1711
+ function onRouterError(handler) {
1712
+ return eventBus.on("router:error" /* ROUTER_ERROR */, handler);
1713
+ }
1714
+ function onStoreInitialized(handler) {
1715
+ return eventBus.on("store:initialized" /* STORE_INITIALIZED */, handler);
1716
+ }
1717
+ function onStoreBeforeAction(handler) {
1718
+ return eventBus.on("store:before-action" /* STORE_BEFORE_ACTION */, handler);
1719
+ }
1720
+ function onStoreAfterAction(handler) {
1721
+ return eventBus.on("store:after-action" /* STORE_AFTER_ACTION */, handler);
1722
+ }
1723
+ function onStoreError(handler) {
1724
+ return eventBus.on("store:error" /* STORE_ERROR */, handler);
1725
+ }
1726
+
1727
+ // src/core/utils.ts
1728
+ function debounce(func, wait, options = {}) {
1729
+ let timeoutId = null;
1730
+ let lastArgs = null;
1731
+ let lastThis = null;
1732
+ let result;
1733
+ let lastCallTime;
1734
+ let lastInvokeTime = 0;
1735
+ const { leading = false, trailing = true } = options;
1736
+ const invokeFunc = (time) => {
1737
+ const args = lastArgs;
1738
+ const thisArg = lastThis;
1739
+ lastArgs = null;
1740
+ lastThis = null;
1741
+ lastInvokeTime = time;
1742
+ result = func.apply(thisArg, args);
1743
+ return result;
1744
+ };
1745
+ const shouldInvoke = (time) => {
1746
+ const timeSinceLastCall = lastCallTime === void 0 ? 0 : time - lastCallTime;
1747
+ const timeSinceLastInvoke = time - lastInvokeTime;
1748
+ return lastCallTime === void 0 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || timeSinceLastInvoke >= wait;
1749
+ };
1750
+ const trailingEdge = (time) => {
1751
+ timeoutId = null;
1752
+ if (trailing && lastArgs) {
1753
+ return invokeFunc(time);
1754
+ }
1755
+ lastArgs = null;
1756
+ lastThis = null;
1757
+ return result;
1758
+ };
1759
+ const remainingWait = (time) => {
1760
+ const timeSinceLastCall = lastCallTime === void 0 ? 0 : time - lastCallTime;
1761
+ const timeSinceLastInvoke = time - lastInvokeTime;
1762
+ const timeWaiting = wait - timeSinceLastCall;
1763
+ return timeWaiting;
1764
+ };
1765
+ const timerExpired = () => {
1766
+ const time = Date.now();
1767
+ if (shouldInvoke(time)) {
1768
+ return trailingEdge(time);
1769
+ }
1770
+ timeoutId = setTimeout(timerExpired, remainingWait(time));
1771
+ return result;
1772
+ };
1773
+ const debounced = function(...args) {
1774
+ const time = Date.now();
1775
+ const isInvoking = shouldInvoke(time);
1776
+ lastArgs = args;
1777
+ lastThis = this;
1778
+ lastCallTime = time;
1779
+ if (isInvoking) {
1780
+ if (timeoutId === null) {
1781
+ lastInvokeTime = time;
1782
+ timeoutId = setTimeout(timerExpired, wait);
1783
+ if (leading) {
1784
+ return invokeFunc(time);
1785
+ }
1786
+ }
1787
+ }
1788
+ if (timeoutId === null) {
1789
+ timeoutId = setTimeout(timerExpired, wait);
1790
+ }
1791
+ return result;
1792
+ };
1793
+ debounced.cancel = () => {
1794
+ if (timeoutId !== null) {
1795
+ clearTimeout(timeoutId);
1796
+ }
1797
+ lastInvokeTime = 0;
1798
+ lastArgs = null;
1799
+ lastThis = null;
1800
+ lastCallTime = void 0;
1801
+ timeoutId = null;
1802
+ };
1803
+ debounced.flush = () => {
1804
+ if (timeoutId !== null) {
1805
+ return trailingEdge(Date.now());
1806
+ }
1807
+ return result;
1808
+ };
1809
+ return debounced;
1810
+ }
1811
+ function throttle(func, wait, options = {}) {
1812
+ let timeoutId = null;
1813
+ let lastArgs = null;
1814
+ let lastThis = null;
1815
+ let result;
1816
+ let lastCallTime = 0;
1817
+ const { leading = true, trailing = true } = options;
1818
+ const invokeFunc = () => {
1819
+ const args = lastArgs;
1820
+ const thisArg = lastThis;
1821
+ lastArgs = null;
1822
+ lastThis = null;
1823
+ lastCallTime = Date.now();
1824
+ result = func.apply(thisArg, args);
1825
+ return result;
1826
+ };
1827
+ const throttled = function(...args) {
1828
+ const now = Date.now();
1829
+ const remaining = wait - (now - lastCallTime);
1830
+ lastArgs = args;
1831
+ lastThis = this;
1832
+ if (remaining <= 0 || remaining > wait) {
1833
+ if (timeoutId) {
1834
+ clearTimeout(timeoutId);
1835
+ timeoutId = null;
1836
+ }
1837
+ if (leading || lastCallTime !== 0) {
1838
+ return invokeFunc();
1839
+ }
1840
+ }
1841
+ if (!timeoutId && trailing) {
1842
+ timeoutId = setTimeout(() => {
1843
+ timeoutId = null;
1844
+ if (trailing && lastArgs) {
1845
+ invokeFunc();
1846
+ }
1847
+ }, remaining);
1848
+ }
1849
+ return result;
3028
1850
  };
3029
- return {
3030
- name,
3031
- reducer,
3032
- actions
1851
+ throttled.cancel = () => {
1852
+ if (timeoutId !== null) {
1853
+ clearTimeout(timeoutId);
1854
+ }
1855
+ timeoutId = null;
1856
+ lastArgs = null;
1857
+ lastThis = null;
1858
+ lastCallTime = 0;
3033
1859
  };
1860
+ return throttled;
3034
1861
  }
3035
-
3036
- // src/core/lifecycle-events.ts
3037
- var LifecycleEvents = /* @__PURE__ */ ((LifecycleEvents2) => {
3038
- LifecycleEvents2["APP_INIT"] = "app:init";
3039
- LifecycleEvents2["APP_MOUNTED"] = "app:mounted";
3040
- LifecycleEvents2["APP_UPDATED"] = "app:updated";
3041
- LifecycleEvents2["APP_ERROR"] = "app:error";
3042
- LifecycleEvents2["APP_DESTROYED"] = "app:destroyed";
3043
- LifecycleEvents2["COMPONENT_CREATED"] = "component:created";
3044
- LifecycleEvents2["COMPONENT_MOUNTED"] = "component:mounted";
3045
- LifecycleEvents2["COMPONENT_UPDATED"] = "component:updated";
3046
- LifecycleEvents2["COMPONENT_ERROR"] = "component:error";
3047
- LifecycleEvents2["COMPONENT_UNMOUNTED"] = "component:unmounted";
3048
- LifecycleEvents2["ROUTER_BEFORE_CHANGE"] = "router:before-change";
3049
- LifecycleEvents2["ROUTER_AFTER_CHANGE"] = "router:after-change";
3050
- LifecycleEvents2["ROUTER_ERROR"] = "router:error";
3051
- LifecycleEvents2["STORE_INITIALIZED"] = "store:initialized";
3052
- LifecycleEvents2["STORE_BEFORE_ACTION"] = "store:before-action";
3053
- LifecycleEvents2["STORE_AFTER_ACTION"] = "store:after-action";
3054
- LifecycleEvents2["STORE_ERROR"] = "store:error";
3055
- return LifecycleEvents2;
3056
- })(LifecycleEvents || {});
3057
- function emitAppInit(data) {
3058
- eventBus.emit("app:init" /* APP_INIT */, data);
3059
- }
3060
- function emitAppMounted(rootElement) {
3061
- eventBus.emit("app:mounted" /* APP_MOUNTED */, rootElement);
3062
- }
3063
- function emitAppUpdated() {
3064
- eventBus.emit("app:updated" /* APP_UPDATED */);
3065
- }
3066
- function emitAppError(error) {
3067
- eventBus.emit("app:error" /* APP_ERROR */, error);
3068
- }
3069
- function emitAppDestroyed() {
3070
- eventBus.emit("app:destroyed" /* APP_DESTROYED */);
3071
- }
3072
- function emitComponentCreated(info) {
3073
- eventBus.emit("component:created" /* COMPONENT_CREATED */, info);
3074
- }
3075
- function emitComponentMounted(info, element) {
3076
- eventBus.emit("component:mounted" /* COMPONENT_MOUNTED */, info, element);
3077
- }
3078
- function emitComponentUpdated(info, prevProps, newProps) {
3079
- eventBus.emit("component:updated" /* COMPONENT_UPDATED */, info, prevProps, newProps);
1862
+ function deepClone(obj) {
1863
+ if (obj === null || typeof obj !== "object") {
1864
+ return obj;
1865
+ }
1866
+ if (obj instanceof Date) {
1867
+ return new Date(obj.getTime());
1868
+ }
1869
+ if (obj instanceof RegExp) {
1870
+ return new RegExp(obj.source, obj.flags);
1871
+ }
1872
+ if (Array.isArray(obj)) {
1873
+ return obj.map((item) => deepClone(item));
1874
+ }
1875
+ if (obj instanceof Map) {
1876
+ const clonedMap = /* @__PURE__ */ new Map();
1877
+ obj.forEach((value, key) => {
1878
+ clonedMap.set(deepClone(key), deepClone(value));
1879
+ });
1880
+ return clonedMap;
1881
+ }
1882
+ if (obj instanceof Set) {
1883
+ const clonedSet = /* @__PURE__ */ new Set();
1884
+ obj.forEach((value) => {
1885
+ clonedSet.add(deepClone(value));
1886
+ });
1887
+ return clonedSet;
1888
+ }
1889
+ const clonedObj = {};
1890
+ for (const key in obj) {
1891
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
1892
+ clonedObj[key] = deepClone(obj[key]);
1893
+ }
1894
+ }
1895
+ return clonedObj;
3080
1896
  }
3081
- function emitComponentError(info, error) {
3082
- eventBus.emit("component:error" /* COMPONENT_ERROR */, info, error);
1897
+ function deepMerge(target, ...sources) {
1898
+ if (!sources.length)
1899
+ return target;
1900
+ const source = sources.shift();
1901
+ if (source === void 0)
1902
+ return target;
1903
+ for (const key in source) {
1904
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
1905
+ const sourceValue = source[key];
1906
+ const targetValue = target[key];
1907
+ if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) {
1908
+ target[key] = deepMerge(targetValue, sourceValue);
1909
+ } else {
1910
+ target[key] = deepClone(sourceValue);
1911
+ }
1912
+ }
1913
+ }
1914
+ return deepMerge(target, ...sources);
3083
1915
  }
3084
- function emitComponentUnmounted(info) {
3085
- eventBus.emit("component:unmounted" /* COMPONENT_UNMOUNTED */, info);
1916
+ function memoize(fn, options = {}) {
1917
+ const { maxSize = 100, keyGenerator = (...args) => JSON.stringify(args) } = options;
1918
+ const cache = /* @__PURE__ */ new Map();
1919
+ const memoized = function(...args) {
1920
+ const key = keyGenerator(...args);
1921
+ if (cache.has(key)) {
1922
+ return cache.get(key);
1923
+ }
1924
+ const result = fn(...args);
1925
+ if (cache.size >= maxSize) {
1926
+ const firstKey = cache.keys().next().value;
1927
+ if (firstKey !== void 0) {
1928
+ cache.delete(firstKey);
1929
+ }
1930
+ }
1931
+ cache.set(key, result);
1932
+ return result;
1933
+ };
1934
+ memoized.cache = cache;
1935
+ memoized.clear = () => cache.clear();
1936
+ return memoized;
3086
1937
  }
3087
- function emitRouterBeforeChange(info) {
3088
- return new Promise((resolve) => {
3089
- let prevented = false;
3090
- const prevent = () => {
3091
- prevented = true;
3092
- };
3093
- eventBus.emit("router:before-change" /* ROUTER_BEFORE_CHANGE */, info, prevent);
3094
- resolve(!prevented);
1938
+ function uuid() {
1939
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
1940
+ return crypto.randomUUID();
1941
+ }
1942
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
1943
+ const r = Math.random() * 16 | 0;
1944
+ const v = c === "x" ? r : r & 3 | 8;
1945
+ return v.toString(16);
3095
1946
  });
3096
1947
  }
3097
- function emitRouterAfterChange(info) {
3098
- eventBus.emit("router:after-change" /* ROUTER_AFTER_CHANGE */, info);
3099
- }
3100
- function emitRouterError(error, info) {
3101
- eventBus.emit("router:error" /* ROUTER_ERROR */, error, info);
3102
- }
3103
- function emitStoreInitialized(state) {
3104
- eventBus.emit("store:initialized" /* STORE_INITIALIZED */, state);
3105
- }
3106
- function emitStoreBeforeAction(actionType, payload, state) {
3107
- eventBus.emit("store:before-action" /* STORE_BEFORE_ACTION */, actionType, payload, state);
1948
+ function formatDate(date, format = "YYYY-MM-DD HH:mm:ss") {
1949
+ const d = date instanceof Date ? date : new Date(date);
1950
+ if (isNaN(d.getTime())) {
1951
+ return "Invalid Date";
1952
+ }
1953
+ const pad = (n, len = 2) => String(n).padStart(len, "0");
1954
+ const tokens = {
1955
+ "YYYY": String(d.getFullYear()),
1956
+ "YY": String(d.getFullYear()).slice(-2),
1957
+ "MM": pad(d.getMonth() + 1),
1958
+ "M": String(d.getMonth() + 1),
1959
+ "DD": pad(d.getDate()),
1960
+ "D": String(d.getDate()),
1961
+ "HH": pad(d.getHours()),
1962
+ "H": String(d.getHours()),
1963
+ "hh": pad(d.getHours() % 12 || 12),
1964
+ "h": String(d.getHours() % 12 || 12),
1965
+ "mm": pad(d.getMinutes()),
1966
+ "m": String(d.getMinutes()),
1967
+ "ss": pad(d.getSeconds()),
1968
+ "s": String(d.getSeconds()),
1969
+ "SSS": pad(d.getMilliseconds(), 3),
1970
+ "A": d.getHours() < 12 ? "AM" : "PM",
1971
+ "a": d.getHours() < 12 ? "am" : "pm"
1972
+ };
1973
+ let result = format;
1974
+ for (const token in tokens) {
1975
+ result = result.replace(new RegExp(token, "g"), tokens[token]);
1976
+ }
1977
+ return result;
3108
1978
  }
3109
- function emitStoreAfterAction(info) {
3110
- eventBus.emit("store:after-action" /* STORE_AFTER_ACTION */, info);
1979
+ function shallowEqual(a, b) {
1980
+ if (a === b)
1981
+ return true;
1982
+ if (!a || !b)
1983
+ return false;
1984
+ if (typeof a !== "object" || typeof b !== "object")
1985
+ return false;
1986
+ const keysA = Object.keys(a);
1987
+ const keysB = Object.keys(b);
1988
+ if (keysA.length !== keysB.length)
1989
+ return false;
1990
+ for (const key of keysA) {
1991
+ if (a[key] !== b[key])
1992
+ return false;
1993
+ }
1994
+ return true;
3111
1995
  }
3112
- function emitStoreError(error, actionType, payload) {
3113
- eventBus.emit("store:error" /* STORE_ERROR */, error, actionType, payload);
1996
+ function deepEqual(a, b) {
1997
+ if (a === b)
1998
+ return true;
1999
+ if (a === null || b === null)
2000
+ return false;
2001
+ if (typeof a !== typeof b)
2002
+ return false;
2003
+ if (typeof a !== "object")
2004
+ return false;
2005
+ if (Array.isArray(a) !== Array.isArray(b))
2006
+ return false;
2007
+ if (Array.isArray(a)) {
2008
+ if (a.length !== b.length)
2009
+ return false;
2010
+ return a.every((item, index) => deepEqual(item, b[index]));
2011
+ }
2012
+ if (a instanceof Date && b instanceof Date) {
2013
+ return a.getTime() === b.getTime();
2014
+ }
2015
+ if (a instanceof RegExp && b instanceof RegExp) {
2016
+ return a.source === b.source && a.flags === b.flags;
2017
+ }
2018
+ const keysA = Object.keys(a);
2019
+ const keysB = Object.keys(b);
2020
+ if (keysA.length !== keysB.length)
2021
+ return false;
2022
+ return keysA.every((key) => deepEqual(a[key], b[key]));
3114
2023
  }
3115
- function onAppInit(handler) {
3116
- return eventBus.on("app:init" /* APP_INIT */, handler);
2024
+ function escapeHtml2(str) {
2025
+ const htmlEscapes = {
2026
+ "&": "&amp;",
2027
+ "<": "&lt;",
2028
+ ">": "&gt;",
2029
+ '"': "&quot;",
2030
+ "'": "&#39;"
2031
+ };
2032
+ return str.replace(/[&<>"']/g, (char) => htmlEscapes[char]);
3117
2033
  }
3118
- function onAppMounted(handler) {
3119
- return eventBus.on("app:mounted" /* APP_MOUNTED */, handler);
2034
+ function unescapeHtml(str) {
2035
+ const htmlUnescapes = {
2036
+ "&amp;": "&",
2037
+ "&lt;": "<",
2038
+ "&gt;": ">",
2039
+ "&quot;": '"',
2040
+ "&#39;": "'"
2041
+ };
2042
+ return str.replace(/&(?:amp|lt|gt|quot|#39);/g, (entity) => htmlUnescapes[entity] || entity);
3120
2043
  }
3121
- function onAppUpdated(handler) {
3122
- return eventBus.on("app:updated" /* APP_UPDATED */, handler);
2044
+ function capitalize(str) {
2045
+ return str.charAt(0).toUpperCase() + str.slice(1);
3123
2046
  }
3124
- function onAppError(handler) {
3125
- return eventBus.on("app:error" /* APP_ERROR */, handler);
2047
+ function camelCase(str) {
2048
+ return str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "").replace(/^(.)/, (char) => char.toLowerCase());
3126
2049
  }
3127
- function onAppDestroyed(handler) {
3128
- return eventBus.on("app:destroyed" /* APP_DESTROYED */, handler);
2050
+ function kebabCase(str) {
2051
+ return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
3129
2052
  }
3130
- function onComponentCreated(handler) {
3131
- return eventBus.on("component:created" /* COMPONENT_CREATED */, handler);
2053
+ function sleep(ms) {
2054
+ return new Promise((resolve) => setTimeout(resolve, ms));
3132
2055
  }
3133
- function onComponentMounted(handler) {
3134
- return eventBus.on("component:mounted" /* COMPONENT_MOUNTED */, handler);
2056
+ async function retry(fn, options = {}) {
2057
+ const { retries = 3, delay = 1e3, backoff = 2, onRetry } = options;
2058
+ let lastError;
2059
+ for (let attempt = 0; attempt <= retries; attempt++) {
2060
+ try {
2061
+ return await fn();
2062
+ } catch (error) {
2063
+ lastError = error;
2064
+ if (attempt < retries) {
2065
+ if (onRetry) {
2066
+ onRetry(lastError, attempt + 1);
2067
+ }
2068
+ await sleep(delay * Math.pow(backoff, attempt));
2069
+ }
2070
+ }
2071
+ }
2072
+ throw lastError;
3135
2073
  }
3136
- function onComponentUpdated(handler) {
3137
- return eventBus.on("component:updated" /* COMPONENT_UPDATED */, handler);
2074
+ function deferred() {
2075
+ let resolve;
2076
+ let reject;
2077
+ const promise = new Promise((res, rej) => {
2078
+ resolve = res;
2079
+ reject = rej;
2080
+ });
2081
+ return { promise, resolve, reject };
3138
2082
  }
3139
- function onComponentError(handler) {
3140
- return eventBus.on("component:error" /* COMPONENT_ERROR */, handler);
2083
+ function pick(obj, keys) {
2084
+ const result = {};
2085
+ for (const key of keys) {
2086
+ if (key in obj) {
2087
+ result[key] = obj[key];
2088
+ }
2089
+ }
2090
+ return result;
3141
2091
  }
3142
- function onComponentUnmounted(handler) {
3143
- return eventBus.on("component:unmounted" /* COMPONENT_UNMOUNTED */, handler);
2092
+ function omit(obj, keys) {
2093
+ const result = { ...obj };
2094
+ for (const key of keys) {
2095
+ delete result[key];
2096
+ }
2097
+ return result;
3144
2098
  }
3145
- function onRouterBeforeChange(handler) {
3146
- return eventBus.on("router:before-change" /* ROUTER_BEFORE_CHANGE */, handler);
2099
+ function groupBy(array, key) {
2100
+ return array.reduce((result, item) => {
2101
+ const groupKey = typeof key === "function" ? key(item) : String(item[key]);
2102
+ if (!result[groupKey]) {
2103
+ result[groupKey] = [];
2104
+ }
2105
+ result[groupKey].push(item);
2106
+ return result;
2107
+ }, {});
3147
2108
  }
3148
- function onRouterAfterChange(handler) {
3149
- return eventBus.on("router:after-change" /* ROUTER_AFTER_CHANGE */, handler);
2109
+ function isEmpty(value) {
2110
+ if (value === null || value === void 0)
2111
+ return true;
2112
+ if (typeof value === "string")
2113
+ return value.trim() === "";
2114
+ if (Array.isArray(value))
2115
+ return value.length === 0;
2116
+ if (value instanceof Map || value instanceof Set)
2117
+ return value.size === 0;
2118
+ if (typeof value === "object")
2119
+ return Object.keys(value).length === 0;
2120
+ return false;
3150
2121
  }
3151
- function onRouterError(handler) {
3152
- return eventBus.on("router:error" /* ROUTER_ERROR */, handler);
2122
+ function clamp(value, min, max) {
2123
+ return Math.min(Math.max(value, min), max);
3153
2124
  }
3154
- function onStoreInitialized(handler) {
3155
- return eventBus.on("store:initialized" /* STORE_INITIALIZED */, handler);
2125
+ function get(obj, path5, defaultValue) {
2126
+ const keys = Array.isArray(path5) ? path5 : path5.split(".");
2127
+ let result = obj;
2128
+ for (const key of keys) {
2129
+ if (result === null || result === void 0) {
2130
+ return defaultValue;
2131
+ }
2132
+ result = result[key];
2133
+ }
2134
+ return result === void 0 ? defaultValue : result;
3156
2135
  }
3157
- function onStoreBeforeAction(handler) {
3158
- return eventBus.on("store:before-action" /* STORE_BEFORE_ACTION */, handler);
2136
+ function set(obj, path5, value) {
2137
+ const keys = Array.isArray(path5) ? path5 : path5.split(".");
2138
+ let current = obj;
2139
+ for (let i = 0; i < keys.length - 1; i++) {
2140
+ const key = keys[i];
2141
+ if (!(key in current) || typeof current[key] !== "object") {
2142
+ current[key] = {};
2143
+ }
2144
+ current = current[key];
2145
+ }
2146
+ current[keys[keys.length - 1]] = value;
2147
+ return obj;
3159
2148
  }
3160
- function onStoreAfterAction(handler) {
3161
- return eventBus.on("store:after-action" /* STORE_AFTER_ACTION */, handler);
2149
+
2150
+ // src/core/errors.ts
2151
+ var BaraqexError = class extends Error {
2152
+ constructor(message, options) {
2153
+ super(message);
2154
+ __publicField(this, "code");
2155
+ __publicField(this, "hint");
2156
+ __publicField(this, "docs");
2157
+ __publicField(this, "originalCause");
2158
+ this.name = "BaraqexError";
2159
+ this.code = options.code;
2160
+ this.hint = options.hint;
2161
+ this.docs = options.docs;
2162
+ this.originalCause = options.cause;
2163
+ Error.captureStackTrace?.(this, this.constructor);
2164
+ }
2165
+ /**
2166
+ * Format error for console output with helpful hints
2167
+ */
2168
+ format() {
2169
+ let output = `
2170
+ \u274C ${this.name}: ${this.message}
2171
+ `;
2172
+ output += ` Code: ${this.code}
2173
+ `;
2174
+ if (this.hint) {
2175
+ output += ` \u{1F4A1} Hint: ${this.hint}
2176
+ `;
2177
+ }
2178
+ if (this.docs) {
2179
+ output += ` \u{1F4DA} Docs: ${this.docs}
2180
+ `;
2181
+ }
2182
+ return output;
2183
+ }
2184
+ };
2185
+ var ConfigError = class extends BaraqexError {
2186
+ constructor(message, options) {
2187
+ super(message, {
2188
+ code: "CONFIG_ERROR",
2189
+ hint: options?.hint || "Check your baraqex.config.js or server configuration",
2190
+ docs: "https://baraqex.tech/docs/configuration",
2191
+ cause: options?.cause
2192
+ });
2193
+ this.name = "ConfigError";
2194
+ }
2195
+ };
2196
+ var DatabaseError = class extends BaraqexError {
2197
+ constructor(message, options) {
2198
+ super(message, {
2199
+ code: "DATABASE_ERROR",
2200
+ hint: options?.hint || "Verify your database connection string and credentials",
2201
+ docs: "https://baraqex.tech/docs/database",
2202
+ cause: options?.cause
2203
+ });
2204
+ __publicField(this, "dbType");
2205
+ this.name = "DatabaseError";
2206
+ this.dbType = options?.dbType;
2207
+ }
2208
+ };
2209
+ var AuthError = class extends BaraqexError {
2210
+ constructor(message, options) {
2211
+ super(message, {
2212
+ code: "AUTH_ERROR",
2213
+ hint: options?.hint || "Check your JWT secret and token configuration",
2214
+ docs: "https://baraqex.tech/docs/authentication",
2215
+ cause: options?.cause
2216
+ });
2217
+ this.name = "AuthError";
2218
+ }
2219
+ };
2220
+ var WasmError = class extends BaraqexError {
2221
+ constructor(message, options) {
2222
+ super(message, {
2223
+ code: "WASM_ERROR",
2224
+ hint: options?.hint || "Ensure your .wasm file is accessible and properly compiled",
2225
+ docs: "https://baraqex.tech/docs/webassembly",
2226
+ cause: options?.cause
2227
+ });
2228
+ this.name = "WasmError";
2229
+ }
2230
+ };
2231
+ var RouterError = class extends BaraqexError {
2232
+ constructor(message, options) {
2233
+ super(message, {
2234
+ code: "ROUTER_ERROR",
2235
+ hint: options?.hint || "Check your API route file structure and exports",
2236
+ docs: "https://baraqex.tech/docs/routing",
2237
+ cause: options?.cause
2238
+ });
2239
+ this.name = "RouterError";
2240
+ }
2241
+ };
2242
+ var ValidationError = class extends BaraqexError {
2243
+ constructor(message, options) {
2244
+ super(message, {
2245
+ code: "VALIDATION_ERROR",
2246
+ hint: options?.hint,
2247
+ cause: options?.cause
2248
+ });
2249
+ __publicField(this, "field");
2250
+ __publicField(this, "value");
2251
+ this.name = "ValidationError";
2252
+ this.field = options?.field;
2253
+ this.value = options?.value;
2254
+ }
2255
+ };
2256
+ function formatError(error) {
2257
+ if (error instanceof BaraqexError) {
2258
+ return error.format();
2259
+ }
2260
+ if (error instanceof Error) {
2261
+ return `
2262
+ \u274C Error: ${error.message}
2263
+ `;
2264
+ }
2265
+ return `
2266
+ \u274C Unknown error: ${String(error)}
2267
+ `;
3162
2268
  }
3163
- function onStoreError(handler) {
3164
- return eventBus.on("store:error" /* STORE_ERROR */, handler);
2269
+ function withErrorHandling(fn, errorHandler2) {
2270
+ return async (...args) => {
2271
+ try {
2272
+ return await fn(...args);
2273
+ } catch (error) {
2274
+ if (errorHandler2) {
2275
+ errorHandler2(error);
2276
+ } else {
2277
+ console.error(formatError(error));
2278
+ }
2279
+ throw error;
2280
+ }
2281
+ };
3165
2282
  }
3166
2283
 
3167
- // src/core/utils.ts
3168
- function debounce(func, wait, options = {}) {
3169
- let timeoutId = null;
3170
- let lastArgs = null;
3171
- let lastThis = null;
3172
- let result;
3173
- let lastCallTime;
3174
- let lastInvokeTime = 0;
3175
- const { leading = false, trailing = true } = options;
3176
- const invokeFunc = (time) => {
3177
- const args = lastArgs;
3178
- const thisArg = lastThis;
3179
- lastArgs = null;
3180
- lastThis = null;
3181
- lastInvokeTime = time;
3182
- result = func.apply(thisArg, args);
3183
- return result;
3184
- };
3185
- const shouldInvoke = (time) => {
3186
- const timeSinceLastCall = lastCallTime === void 0 ? 0 : time - lastCallTime;
3187
- const timeSinceLastInvoke = time - lastInvokeTime;
3188
- return lastCallTime === void 0 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || timeSinceLastInvoke >= wait;
3189
- };
3190
- const trailingEdge = (time) => {
3191
- timeoutId = null;
3192
- if (trailing && lastArgs) {
3193
- return invokeFunc(time);
2284
+ // src/wasm.ts
2285
+ async function loadGoWasm(wasmUrl, options = {}) {
2286
+ if (typeof window === "undefined") {
2287
+ throw new Error("loadGoWasm() is for browser use only. Use loadGoWasmFromFile() in Node.js.");
2288
+ }
2289
+ try {
2290
+ if (!window.Go) {
2291
+ throw new Error("Go WASM runtime not available. Make sure wasm_exec.js is loaded.");
3194
2292
  }
3195
- lastArgs = null;
3196
- lastThis = null;
3197
- return result;
3198
- };
3199
- const remainingWait = (time) => {
3200
- const timeSinceLastCall = lastCallTime === void 0 ? 0 : time - lastCallTime;
3201
- const timeSinceLastInvoke = time - lastInvokeTime;
3202
- const timeWaiting = wait - timeSinceLastCall;
3203
- return timeWaiting;
3204
- };
3205
- const timerExpired = () => {
3206
- const time = Date.now();
3207
- if (shouldInvoke(time)) {
3208
- return trailingEdge(time);
2293
+ if (options.debug) {
2294
+ console.log("[WASM] Loading WASM from:", wasmUrl);
3209
2295
  }
3210
- timeoutId = setTimeout(timerExpired, remainingWait(time));
3211
- return result;
3212
- };
3213
- const debounced = function(...args) {
3214
- const time = Date.now();
3215
- const isInvoking = shouldInvoke(time);
3216
- lastArgs = args;
3217
- lastThis = this;
3218
- lastCallTime = time;
3219
- if (isInvoking) {
3220
- if (timeoutId === null) {
3221
- lastInvokeTime = time;
3222
- timeoutId = setTimeout(timerExpired, wait);
3223
- if (leading) {
3224
- return invokeFunc(time);
2296
+ const response = await fetch(wasmUrl);
2297
+ if (!response.ok) {
2298
+ throw new Error(`Failed to fetch WASM file: ${response.status}`);
2299
+ }
2300
+ const wasmBytes = await response.arrayBuffer();
2301
+ const go = new window.Go();
2302
+ const wasmModule = await WebAssembly.instantiate(wasmBytes, go.importObject);
2303
+ go.run(wasmModule.instance);
2304
+ await new Promise((resolve) => setTimeout(resolve, 100));
2305
+ if (options.debug) {
2306
+ console.log("[WASM] Go program started, checking for registered functions...");
2307
+ }
2308
+ const functions = {};
2309
+ for (const key in window) {
2310
+ if (typeof window[key] === "function" && key.startsWith("go")) {
2311
+ functions[key] = window[key];
2312
+ if (options.debug) {
2313
+ console.log(`[WASM] Found function: ${key}`);
3225
2314
  }
3226
2315
  }
3227
2316
  }
3228
- if (timeoutId === null) {
3229
- timeoutId = setTimeout(timerExpired, wait);
3230
- }
3231
- return result;
3232
- };
3233
- debounced.cancel = () => {
3234
- if (timeoutId !== null) {
3235
- clearTimeout(timeoutId);
2317
+ const wasmInstance = {
2318
+ instance: wasmModule.instance,
2319
+ module: wasmModule,
2320
+ exports: wasmModule.instance.exports,
2321
+ functions
2322
+ };
2323
+ if (options.onLoad) {
2324
+ options.onLoad(wasmInstance);
3236
2325
  }
3237
- lastInvokeTime = 0;
3238
- lastArgs = null;
3239
- lastThis = null;
3240
- lastCallTime = void 0;
3241
- timeoutId = null;
3242
- };
3243
- debounced.flush = () => {
3244
- if (timeoutId !== null) {
3245
- return trailingEdge(Date.now());
2326
+ if (options.debug) {
2327
+ console.log(`[WASM] Module loaded successfully with ${Object.keys(functions).length} functions`);
3246
2328
  }
3247
- return result;
3248
- };
3249
- return debounced;
2329
+ return wasmInstance;
2330
+ } catch (error) {
2331
+ console.error("[WASM] Error loading Go WASM module:", error);
2332
+ throw error;
2333
+ }
3250
2334
  }
3251
- function throttle(func, wait, options = {}) {
3252
- let timeoutId = null;
3253
- let lastArgs = null;
3254
- let lastThis = null;
3255
- let result;
3256
- let lastCallTime = 0;
3257
- const { leading = true, trailing = true } = options;
3258
- const invokeFunc = () => {
3259
- const args = lastArgs;
3260
- const thisArg = lastThis;
3261
- lastArgs = null;
3262
- lastThis = null;
3263
- lastCallTime = Date.now();
3264
- result = func.apply(thisArg, args);
3265
- return result;
2335
+ function callWasmFunction(funcName, ...args) {
2336
+ if (typeof window === "undefined") {
2337
+ throw new Error("callWasmFunction() is for browser use only.");
2338
+ }
2339
+ const func = window[funcName];
2340
+ if (typeof func !== "function") {
2341
+ throw new Error(`Function ${funcName} not found. Make sure the WASM module is loaded.`);
2342
+ }
2343
+ return func(...args);
2344
+ }
2345
+ function isWasmReady() {
2346
+ if (typeof window === "undefined") {
2347
+ return false;
2348
+ }
2349
+ return !!(window.Go && Object.keys(window).some(
2350
+ (key) => key.startsWith("go") && typeof window[key] === "function"
2351
+ ));
2352
+ }
2353
+ function getWasmFunctions() {
2354
+ if (typeof window === "undefined") {
2355
+ return [];
2356
+ }
2357
+ return Object.keys(window).filter(
2358
+ (key) => key.startsWith("go") && typeof window[key] === "function"
2359
+ );
2360
+ }
2361
+ function useGoWasm(wasmUrl, options = {}) {
2362
+ if (typeof window === "undefined") {
2363
+ throw new Error("useGoWasm() is for browser use only.");
2364
+ }
2365
+ return {
2366
+ loadWasm: () => loadGoWasm(wasmUrl, options),
2367
+ callFunction: callWasmFunction,
2368
+ isReady: isWasmReady,
2369
+ getFunctions: getWasmFunctions
3266
2370
  };
3267
- const throttled = function(...args) {
3268
- const now = Date.now();
3269
- const remaining = wait - (now - lastCallTime);
3270
- lastArgs = args;
3271
- lastThis = this;
3272
- if (remaining <= 0 || remaining > wait) {
3273
- if (timeoutId) {
3274
- clearTimeout(timeoutId);
3275
- timeoutId = null;
2371
+ }
2372
+
2373
+ // src/server/index.ts
2374
+ import path4 from "path";
2375
+ import fs4 from "fs";
2376
+
2377
+ // src/server/database.ts
2378
+ var Database = class {
2379
+ constructor(config) {
2380
+ __publicField(this, "config");
2381
+ __publicField(this, "mongoClient", null);
2382
+ __publicField(this, "mongoDb", null);
2383
+ __publicField(this, "mysqlPool", null);
2384
+ __publicField(this, "pgPool", null);
2385
+ this.config = config;
2386
+ }
2387
+ async connect() {
2388
+ switch (this.config.type) {
2389
+ case "mongodb":
2390
+ await this.connectMongo();
2391
+ break;
2392
+ case "mysql":
2393
+ await this.connectMysql();
2394
+ break;
2395
+ case "postgres":
2396
+ await this.connectPostgres();
2397
+ break;
2398
+ default:
2399
+ throw new Error(`Unsupported database type: ${this.config.type}`);
2400
+ }
2401
+ }
2402
+ async connectMongo() {
2403
+ try {
2404
+ const { MongoClient } = await import("mongodb");
2405
+ this.mongoClient = new MongoClient(this.config.url);
2406
+ await this.mongoClient.connect();
2407
+ this.mongoDb = this.mongoClient.db();
2408
+ console.log("Connected to MongoDB");
2409
+ } catch (error) {
2410
+ if (error.code === "MODULE_NOT_FOUND") {
2411
+ throw new Error("MongoDB driver not installed. Run: npm install mongodb");
3276
2412
  }
3277
- if (leading || lastCallTime !== 0) {
3278
- return invokeFunc();
2413
+ console.error("MongoDB connection error:", error);
2414
+ throw error;
2415
+ }
2416
+ }
2417
+ async connectMysql() {
2418
+ try {
2419
+ const mysql = await import("mysql2/promise");
2420
+ this.mysqlPool = mysql.createPool(this.config.url);
2421
+ await this.mysqlPool.getConnection();
2422
+ console.log("Connected to MySQL");
2423
+ } catch (error) {
2424
+ if (error.code === "MODULE_NOT_FOUND") {
2425
+ throw new Error("MySQL driver not installed. Run: npm install mysql2");
3279
2426
  }
2427
+ console.error("MySQL connection error:", error);
2428
+ throw error;
3280
2429
  }
3281
- if (!timeoutId && trailing) {
3282
- timeoutId = setTimeout(() => {
3283
- timeoutId = null;
3284
- if (trailing && lastArgs) {
3285
- invokeFunc();
2430
+ }
2431
+ async connectPostgres() {
2432
+ try {
2433
+ const pg = await import("pg");
2434
+ this.pgPool = new pg.Pool({ connectionString: this.config.url });
2435
+ const client = await this.pgPool.connect();
2436
+ client.release();
2437
+ console.log("Connected to PostgreSQL");
2438
+ } catch (error) {
2439
+ if (error.code === "MODULE_NOT_FOUND") {
2440
+ throw new Error("PostgreSQL driver not installed. Run: npm install pg @types/pg");
2441
+ }
2442
+ console.error("PostgreSQL connection error:", error);
2443
+ throw error;
2444
+ }
2445
+ }
2446
+ async disconnect() {
2447
+ if (this.mongoClient) {
2448
+ await this.mongoClient.close();
2449
+ this.mongoClient = null;
2450
+ this.mongoDb = null;
2451
+ }
2452
+ if (this.mysqlPool) {
2453
+ await this.mysqlPool.end();
2454
+ this.mysqlPool = null;
2455
+ }
2456
+ if (this.pgPool) {
2457
+ await this.pgPool.end();
2458
+ this.pgPool = null;
2459
+ }
2460
+ }
2461
+ // Database-specific methods
2462
+ getMongoDb() {
2463
+ return this.mongoDb;
2464
+ }
2465
+ getMysqlPool() {
2466
+ return this.mysqlPool;
2467
+ }
2468
+ getPgPool() {
2469
+ return this.pgPool;
2470
+ }
2471
+ // Generic query method
2472
+ async query(sql, values) {
2473
+ switch (this.config.type) {
2474
+ case "mongodb":
2475
+ throw new Error("For MongoDB, use getMongoDb() instead of query()");
2476
+ case "mysql":
2477
+ if (!this.mysqlPool)
2478
+ throw new Error("MySQL not connected");
2479
+ const [rows] = await this.mysqlPool.execute(sql, values || []);
2480
+ return rows;
2481
+ case "postgres":
2482
+ if (!this.pgPool)
2483
+ throw new Error("PostgreSQL not connected");
2484
+ const result = await this.pgPool.query(sql, values || []);
2485
+ return result.rows;
2486
+ default:
2487
+ throw new Error(`Unsupported database type: ${this.config.type}`);
2488
+ }
2489
+ }
2490
+ };
2491
+
2492
+ // src/server/auth.ts
2493
+ var AuthService = class {
2494
+ constructor(config) {
2495
+ __publicField(this, "config");
2496
+ __publicField(this, "jwtPromise", null);
2497
+ this.config = {
2498
+ expiresIn: "24h",
2499
+ ...config
2500
+ };
2501
+ }
2502
+ async getJwt() {
2503
+ if (!this.jwtPromise) {
2504
+ this.jwtPromise = import("jsonwebtoken").catch((error) => {
2505
+ this.jwtPromise = null;
2506
+ if (error.code === "MODULE_NOT_FOUND") {
2507
+ throw new Error(
2508
+ "jsonwebtoken not installed. Run: npm install jsonwebtoken @types/jsonwebtoken"
2509
+ );
3286
2510
  }
3287
- }, remaining);
2511
+ throw error;
2512
+ });
2513
+ }
2514
+ return this.jwtPromise;
2515
+ }
2516
+ async hashPassword(password) {
2517
+ try {
2518
+ const bcrypt = await import("bcryptjs");
2519
+ return bcrypt.hash(password, 10);
2520
+ } catch (error) {
2521
+ if (error.code === "MODULE_NOT_FOUND") {
2522
+ throw new Error("bcryptjs not installed. Run: npm install bcryptjs @types/bcryptjs");
2523
+ }
2524
+ throw error;
2525
+ }
2526
+ }
2527
+ async comparePasswords(password, hashedPassword) {
2528
+ try {
2529
+ const bcrypt = await import("bcryptjs");
2530
+ return bcrypt.compare(password, hashedPassword);
2531
+ } catch (error) {
2532
+ if (error.code === "MODULE_NOT_FOUND") {
2533
+ throw new Error("bcryptjs not installed. Run: npm install bcryptjs @types/bcryptjs");
2534
+ }
2535
+ throw error;
3288
2536
  }
3289
- return result;
3290
- };
3291
- throttled.cancel = () => {
3292
- if (timeoutId !== null) {
3293
- clearTimeout(timeoutId);
2537
+ }
2538
+ async generateToken(user) {
2539
+ const jwt = await this.getJwt();
2540
+ const options = {};
2541
+ if (this.config.expiresIn) {
2542
+ options.expiresIn = this.config.expiresIn;
3294
2543
  }
3295
- timeoutId = null;
3296
- lastArgs = null;
3297
- lastThis = null;
3298
- lastCallTime = 0;
3299
- };
3300
- return throttled;
3301
- }
3302
- function deepClone(obj) {
3303
- if (obj === null || typeof obj !== "object") {
3304
- return obj;
2544
+ return jwt.sign(
2545
+ { id: user.id, username: user.username, roles: user.roles || [] },
2546
+ this.config.secret,
2547
+ options
2548
+ );
3305
2549
  }
3306
- if (obj instanceof Date) {
3307
- return new Date(obj.getTime());
2550
+ async verifyToken(token) {
2551
+ try {
2552
+ const jwt = await this.getJwt();
2553
+ return jwt.verify(token, this.config.secret);
2554
+ } catch {
2555
+ return null;
2556
+ }
3308
2557
  }
3309
- if (obj instanceof RegExp) {
3310
- return new RegExp(obj.source, obj.flags);
2558
+ initialize() {
2559
+ return async (req, res, next) => {
2560
+ const token = this.extractToken(req);
2561
+ if (token) {
2562
+ const decoded = await this.verifyToken(token);
2563
+ if (decoded) {
2564
+ req.user = decoded;
2565
+ }
2566
+ }
2567
+ next();
2568
+ };
3311
2569
  }
3312
- if (Array.isArray(obj)) {
3313
- return obj.map((item) => deepClone(item));
2570
+ requireAuth() {
2571
+ return (req, res, next) => {
2572
+ if (!req.user) {
2573
+ return res.status(401).json({ message: "Unauthorized" });
2574
+ }
2575
+ return next();
2576
+ };
3314
2577
  }
3315
- if (obj instanceof Map) {
3316
- const clonedMap = /* @__PURE__ */ new Map();
3317
- obj.forEach((value, key) => {
3318
- clonedMap.set(deepClone(key), deepClone(value));
3319
- });
3320
- return clonedMap;
2578
+ requireRoles(roles) {
2579
+ return (req, res, next) => {
2580
+ if (!req.user) {
2581
+ return res.status(401).json({ message: "Unauthorized" });
2582
+ }
2583
+ const userRoles = req.user.roles || [];
2584
+ const hasRequiredRole = roles.some((role) => userRoles.includes(role));
2585
+ if (!hasRequiredRole) {
2586
+ return res.status(403).json({ message: "Forbidden" });
2587
+ }
2588
+ return next();
2589
+ };
3321
2590
  }
3322
- if (obj instanceof Set) {
3323
- const clonedSet = /* @__PURE__ */ new Set();
3324
- obj.forEach((value) => {
3325
- clonedSet.add(deepClone(value));
3326
- });
3327
- return clonedSet;
2591
+ extractToken(req) {
2592
+ if (req.headers.authorization && req.headers.authorization.startsWith("Bearer ")) {
2593
+ return req.headers.authorization.substring(7);
2594
+ }
2595
+ return null;
3328
2596
  }
3329
- const clonedObj = {};
3330
- for (const key in obj) {
3331
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
3332
- clonedObj[key] = deepClone(obj[key]);
2597
+ };
2598
+
2599
+ // src/server/api-router.ts
2600
+ import path from "path";
2601
+ import fs from "fs";
2602
+ import { pathToFileURL } from "url";
2603
+ var ApiRouter = class {
2604
+ constructor(apiDir, auth = null) {
2605
+ __publicField(this, "router", null);
2606
+ __publicField(this, "apiDir");
2607
+ __publicField(this, "auth");
2608
+ __publicField(this, "initialized", false);
2609
+ this.apiDir = path.resolve(process.cwd(), apiDir);
2610
+ this.auth = auth;
2611
+ }
2612
+ async initialize() {
2613
+ if (this.initialized && this.router)
2614
+ return;
2615
+ try {
2616
+ const express = await import("express");
2617
+ this.router = express.default.Router();
2618
+ this.setupRoutes();
2619
+ this.initialized = true;
2620
+ console.log("\u2705 API Router initialized successfully");
2621
+ } catch (error) {
2622
+ console.error("\u274C Failed to initialize API Router:", error);
2623
+ if (error.code === "MODULE_NOT_FOUND") {
2624
+ throw new Error("Express not installed. Run: npm install express @types/express");
2625
+ }
2626
+ throw error;
3333
2627
  }
3334
2628
  }
3335
- return clonedObj;
3336
- }
3337
- function deepMerge(target, ...sources) {
3338
- if (!sources.length)
3339
- return target;
3340
- const source = sources.shift();
3341
- if (source === void 0)
3342
- return target;
3343
- for (const key in source) {
3344
- if (Object.prototype.hasOwnProperty.call(source, key)) {
3345
- const sourceValue = source[key];
3346
- const targetValue = target[key];
3347
- if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) {
3348
- target[key] = deepMerge(targetValue, sourceValue);
3349
- } else {
3350
- target[key] = deepClone(sourceValue);
2629
+ isInitialized() {
2630
+ return this.initialized && this.router !== null;
2631
+ }
2632
+ setupRoutes() {
2633
+ if (!fs.existsSync(this.apiDir)) {
2634
+ console.log(`API directory not found: ${this.apiDir}`);
2635
+ return;
2636
+ }
2637
+ this.scanDirectory(this.apiDir, "");
2638
+ }
2639
+ scanDirectory(dirPath, routePrefix) {
2640
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
2641
+ for (const entry of entries) {
2642
+ const fullPath = path.join(dirPath, entry.name);
2643
+ if (entry.isDirectory()) {
2644
+ this.scanDirectory(fullPath, `${routePrefix}/${entry.name}`);
2645
+ } else if (this.isRouteFile(entry.name)) {
2646
+ const routePath = this.getRoutePath(entry.name, routePrefix);
2647
+ this.registerRoute(fullPath, routePath);
3351
2648
  }
3352
2649
  }
3353
2650
  }
3354
- return deepMerge(target, ...sources);
3355
- }
3356
- function memoize(fn, options = {}) {
3357
- const { maxSize = 100, keyGenerator = (...args) => JSON.stringify(args) } = options;
3358
- const cache = /* @__PURE__ */ new Map();
3359
- const memoized = function(...args) {
3360
- const key = keyGenerator(...args);
3361
- if (cache.has(key)) {
3362
- return cache.get(key);
2651
+ isRouteFile(filename) {
2652
+ return filename.endsWith(".js") || filename.endsWith(".ts") || filename.endsWith(".mjs");
2653
+ }
2654
+ getRoutePath(filename, routePrefix) {
2655
+ const baseName = path.basename(filename, path.extname(filename));
2656
+ if (baseName === "index") {
2657
+ return routePrefix || "/";
3363
2658
  }
3364
- const result = fn(...args);
3365
- if (cache.size >= maxSize) {
3366
- const firstKey = cache.keys().next().value;
3367
- if (firstKey !== void 0) {
3368
- cache.delete(firstKey);
2659
+ const paramMatch = baseName.match(/^\[(.+)\]$/);
2660
+ if (paramMatch) {
2661
+ return `${routePrefix}/:${paramMatch[1]}`;
2662
+ }
2663
+ return `${routePrefix}/${baseName}`;
2664
+ }
2665
+ async registerRoute(filePath, routePath) {
2666
+ try {
2667
+ const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(filePath);
2668
+ const fileUrl = pathToFileURL(absolutePath).href;
2669
+ const urlWithTimestamp = `${fileUrl}?t=${Date.now()}`;
2670
+ const routeModule = await import(urlWithTimestamp);
2671
+ if (!this.isValidRouteModule(routeModule)) {
2672
+ console.warn(`Invalid route module: ${filePath}`);
2673
+ return;
2674
+ }
2675
+ console.log(`Registering API route: ${routePath}`);
2676
+ const middleware = routeModule.middleware || [];
2677
+ for (const method of ["get", "post", "put", "delete", "patch", "options"]) {
2678
+ const handler = routeModule[method];
2679
+ if (typeof handler === "function") {
2680
+ const routerMethod = this.router[method];
2681
+ routerMethod.call(
2682
+ this.router,
2683
+ routePath,
2684
+ ...middleware,
2685
+ this.wrapHandler(handler)
2686
+ );
2687
+ }
3369
2688
  }
2689
+ } catch (error) {
2690
+ console.error(`Error registering route (${filePath}):`, error);
3370
2691
  }
3371
- cache.set(key, result);
3372
- return result;
3373
- };
3374
- memoized.cache = cache;
3375
- memoized.clear = () => cache.clear();
3376
- return memoized;
3377
- }
3378
- function uuid() {
3379
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
3380
- return crypto.randomUUID();
3381
2692
  }
3382
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
3383
- const r = Math.random() * 16 | 0;
3384
- const v = c === "x" ? r : r & 3 | 8;
3385
- return v.toString(16);
2693
+ isValidRouteModule(module) {
2694
+ if (!module)
2695
+ return false;
2696
+ return ["get", "post", "put", "delete", "patch", "options"].some((method) => typeof module[method] === "function");
2697
+ }
2698
+ wrapHandler(handler) {
2699
+ return async (req, res, next) => {
2700
+ try {
2701
+ await handler(req, res, next);
2702
+ } catch (error) {
2703
+ next(error);
2704
+ }
2705
+ };
2706
+ }
2707
+ };
2708
+
2709
+ // src/server/middleware.ts
2710
+ var requestLogger = (req, res, next) => {
2711
+ console.log(`${(/* @__PURE__ */ new Date()).toISOString()} - ${req.method} ${req.url}`);
2712
+ next();
2713
+ };
2714
+ var errorHandler = (err, req, res, _next) => {
2715
+ console.error(err.stack);
2716
+ res.status(500).json({
2717
+ error: {
2718
+ message: "Internal Server Error",
2719
+ ...process.env.NODE_ENV !== "production" ? { details: err.message, stack: err.stack } : {}
2720
+ }
3386
2721
  });
3387
- }
3388
- function formatDate(date, format = "YYYY-MM-DD HH:mm:ss") {
3389
- const d = date instanceof Date ? date : new Date(date);
3390
- if (isNaN(d.getTime())) {
3391
- return "Invalid Date";
2722
+ };
2723
+ var notFoundHandler = (req, res) => {
2724
+ res.status(404).json({
2725
+ error: {
2726
+ message: `Not Found - ${req.method} ${req.url}`
2727
+ }
2728
+ });
2729
+ };
2730
+ function rateLimit(options) {
2731
+ const requests = /* @__PURE__ */ new Map();
2732
+ const cleanupInterval = setInterval(() => {
2733
+ const now = Date.now();
2734
+ for (const [ip, times] of requests) {
2735
+ const valid = times.filter((t) => now - t < options.windowMs);
2736
+ if (valid.length === 0) {
2737
+ requests.delete(ip);
2738
+ } else {
2739
+ requests.set(ip, valid);
2740
+ }
2741
+ }
2742
+ }, options.windowMs);
2743
+ if (cleanupInterval.unref) {
2744
+ cleanupInterval.unref();
3392
2745
  }
3393
- const pad = (n, len = 2) => String(n).padStart(len, "0");
3394
- const tokens = {
3395
- "YYYY": String(d.getFullYear()),
3396
- "YY": String(d.getFullYear()).slice(-2),
3397
- "MM": pad(d.getMonth() + 1),
3398
- "M": String(d.getMonth() + 1),
3399
- "DD": pad(d.getDate()),
3400
- "D": String(d.getDate()),
3401
- "HH": pad(d.getHours()),
3402
- "H": String(d.getHours()),
3403
- "hh": pad(d.getHours() % 12 || 12),
3404
- "h": String(d.getHours() % 12 || 12),
3405
- "mm": pad(d.getMinutes()),
3406
- "m": String(d.getMinutes()),
3407
- "ss": pad(d.getSeconds()),
3408
- "s": String(d.getSeconds()),
3409
- "SSS": pad(d.getMilliseconds(), 3),
3410
- "A": d.getHours() < 12 ? "AM" : "PM",
3411
- "a": d.getHours() < 12 ? "am" : "pm"
2746
+ return (req, res, next) => {
2747
+ const ip = req.ip || req.socket?.remoteAddress || "unknown";
2748
+ const now = Date.now();
2749
+ const reqTimes = (requests.get(ip) || []).filter((time) => now - time < options.windowMs);
2750
+ reqTimes.push(now);
2751
+ requests.set(ip, reqTimes);
2752
+ if (reqTimes.length > options.max) {
2753
+ return res.status(429).json({
2754
+ error: {
2755
+ message: "Too Many Requests",
2756
+ retryAfter: Math.ceil(options.windowMs / 1e3)
2757
+ }
2758
+ });
2759
+ }
2760
+ return next();
3412
2761
  };
3413
- let result = format;
3414
- for (const token in tokens) {
3415
- result = result.replace(new RegExp(token, "g"), tokens[token]);
2762
+ }
2763
+
2764
+ // src/server/utils.ts
2765
+ import crypto2 from "crypto";
2766
+ import fs2 from "fs/promises";
2767
+ import path2 from "path";
2768
+ function safeJsonParse(json, fallback) {
2769
+ try {
2770
+ return JSON.parse(json);
2771
+ } catch (error) {
2772
+ return fallback;
3416
2773
  }
3417
- return result;
3418
2774
  }
3419
- function shallowEqual(a, b) {
3420
- if (a === b)
3421
- return true;
3422
- if (!a || !b)
3423
- return false;
3424
- if (typeof a !== "object" || typeof b !== "object")
3425
- return false;
3426
- const keysA = Object.keys(a);
3427
- const keysB = Object.keys(b);
3428
- if (keysA.length !== keysB.length)
3429
- return false;
3430
- for (const key of keysA) {
3431
- if (a[key] !== b[key])
3432
- return false;
2775
+ function hashString(input, salt = "") {
2776
+ return crypto2.createHash("sha256").update(input + salt).digest("hex");
2777
+ }
2778
+ function getPagination(req) {
2779
+ const page = Math.max(1, parseInt(req.query.page) || 1);
2780
+ const rawLimit = parseInt(req.query.limit);
2781
+ let limit;
2782
+ if (isNaN(rawLimit) || rawLimit <= 0) {
2783
+ limit = 20;
2784
+ } else {
2785
+ limit = Math.max(1, Math.min(100, rawLimit));
3433
2786
  }
3434
- return true;
2787
+ const skip = (page - 1) * limit;
2788
+ return { page, limit, skip };
2789
+ }
2790
+ function sendSuccess(res, data, message = "Success") {
2791
+ return res.json({
2792
+ success: true,
2793
+ message,
2794
+ data
2795
+ });
2796
+ }
2797
+ function sendError(res, message = "An error occurred", statusCode = 400, errors) {
2798
+ return res.status(statusCode).json({
2799
+ success: false,
2800
+ message,
2801
+ errors: errors || void 0
2802
+ });
2803
+ }
2804
+ function validateFields(req, requiredFields) {
2805
+ const missing = requiredFields.filter((field) => {
2806
+ const value = req.body[field];
2807
+ return value === void 0 || value === null || value === "";
2808
+ });
2809
+ return {
2810
+ valid: missing.length === 0,
2811
+ missing
2812
+ };
3435
2813
  }
3436
- function deepEqual(a, b) {
3437
- if (a === b)
3438
- return true;
3439
- if (a === null || b === null)
3440
- return false;
3441
- if (typeof a !== typeof b)
3442
- return false;
3443
- if (typeof a !== "object")
3444
- return false;
3445
- if (Array.isArray(a) !== Array.isArray(b))
3446
- return false;
3447
- if (Array.isArray(a)) {
3448
- if (a.length !== b.length)
3449
- return false;
3450
- return a.every((item, index) => deepEqual(item, b[index]));
2814
+ function validateFileUpload(file, options = {}) {
2815
+ if (!file) {
2816
+ return { valid: false, error: "No file provided" };
3451
2817
  }
3452
- if (a instanceof Date && b instanceof Date) {
3453
- return a.getTime() === b.getTime();
2818
+ if (options.maxSize && file.size > options.maxSize) {
2819
+ return {
2820
+ valid: false,
2821
+ error: `File too large. Maximum size allowed is ${options.maxSize / 1024 / 1024}MB`
2822
+ };
3454
2823
  }
3455
- if (a instanceof RegExp && b instanceof RegExp) {
3456
- return a.source === b.source && a.flags === b.flags;
2824
+ if (options.allowedTypes && options.allowedTypes.length > 0) {
2825
+ const fileType = file.mimetype;
2826
+ if (!options.allowedTypes.includes(fileType)) {
2827
+ return {
2828
+ valid: false,
2829
+ error: `Invalid file type. Allowed types: ${options.allowedTypes.join(", ")}`
2830
+ };
2831
+ }
3457
2832
  }
3458
- const keysA = Object.keys(a);
3459
- const keysB = Object.keys(b);
3460
- if (keysA.length !== keysB.length)
3461
- return false;
3462
- return keysA.every((key) => deepEqual(a[key], b[key]));
3463
- }
3464
- function escapeHtml2(str) {
3465
- const htmlEscapes = {
3466
- "&": "&amp;",
3467
- "<": "&lt;",
3468
- ">": "&gt;",
3469
- '"': "&quot;",
3470
- "'": "&#39;"
3471
- };
3472
- return str.replace(/[&<>"']/g, (char) => htmlEscapes[char]);
2833
+ return { valid: true };
3473
2834
  }
3474
- function unescapeHtml(str) {
3475
- const htmlUnescapes = {
3476
- "&amp;": "&",
3477
- "&lt;": "<",
3478
- "&gt;": ">",
3479
- "&quot;": '"',
3480
- "&#39;": "'"
2835
+ function getEnvironmentInfo() {
2836
+ return {
2837
+ nodeVersion: process.version,
2838
+ platform: process.platform,
2839
+ arch: process.arch,
2840
+ memory: process.memoryUsage(),
2841
+ uptime: process.uptime(),
2842
+ env: process.env.NODE_ENV || "development"
3481
2843
  };
3482
- return str.replace(/&(?:amp|lt|gt|quot|#39);/g, (entity) => htmlUnescapes[entity] || entity);
3483
- }
3484
- function capitalize(str) {
3485
- return str.charAt(0).toUpperCase() + str.slice(1);
3486
2844
  }
3487
- function camelCase(str) {
3488
- return str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "").replace(/^(.)/, (char) => char.toLowerCase());
2845
+ async function isDirectoryEmpty(dirPath) {
2846
+ try {
2847
+ const files = await fs2.readdir(dirPath);
2848
+ return files.length === 0;
2849
+ } catch (error) {
2850
+ return true;
2851
+ }
3489
2852
  }
3490
- function kebabCase(str) {
3491
- return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
2853
+ async function ensureDirectory(dirPath) {
2854
+ try {
2855
+ await fs2.access(dirPath);
2856
+ } catch (error) {
2857
+ await fs2.mkdir(dirPath, { recursive: true });
2858
+ }
3492
2859
  }
3493
- function sleep(ms) {
3494
- return new Promise((resolve) => setTimeout(resolve, ms));
2860
+ async function writeJsonFile(filePath, data) {
2861
+ await ensureDirectory(path2.dirname(filePath));
2862
+ await fs2.writeFile(filePath, JSON.stringify(data, null, 2), "utf8");
3495
2863
  }
3496
- async function retry(fn, options = {}) {
3497
- const { retries = 3, delay = 1e3, backoff = 2, onRetry } = options;
3498
- let lastError;
3499
- for (let attempt = 0; attempt <= retries; attempt++) {
3500
- try {
3501
- return await fn();
3502
- } catch (error) {
3503
- lastError = error;
3504
- if (attempt < retries) {
3505
- if (onRetry) {
3506
- onRetry(lastError, attempt + 1);
3507
- }
3508
- await sleep(delay * Math.pow(backoff, attempt));
3509
- }
3510
- }
2864
+ async function readJsonFile(filePath, defaultValue) {
2865
+ try {
2866
+ const data = await fs2.readFile(filePath, "utf8");
2867
+ return safeJsonParse(data, defaultValue);
2868
+ } catch (error) {
2869
+ return defaultValue;
3511
2870
  }
3512
- throw lastError;
3513
2871
  }
3514
- function deferred() {
3515
- let resolve;
3516
- let reject;
3517
- const promise = new Promise((res, rej) => {
3518
- resolve = res;
3519
- reject = rej;
2872
+
2873
+ // src/server/templates.ts
2874
+ function generateDocument(content, options = {}) {
2875
+ const {
2876
+ title = "Baraqex App",
2877
+ description = "",
2878
+ lang = "en",
2879
+ charset = "UTF-8",
2880
+ viewport = "width=device-width, initial-scale=1.0",
2881
+ scripts = [],
2882
+ styles = [],
2883
+ meta = {},
2884
+ bodyClasses = "",
2885
+ htmlAttrs = {},
2886
+ bodyAttrs = {},
2887
+ initialData = {},
2888
+ componentName = ""
2889
+ } = options;
2890
+ const htmlAttributes = Object.entries(htmlAttrs).map(([key, value]) => `${key}="${escapeHtml3(value)}"`).join(" ");
2891
+ const bodyAttributes = Object.entries(bodyAttrs).map(([key, value]) => `${key}="${escapeHtml3(value)}"`).join(" ");
2892
+ const metaTags = [
2893
+ `<meta charset="${charset}">`,
2894
+ `<meta name="viewport" content="${viewport}">`,
2895
+ description ? `<meta name="description" content="${escapeHtml3(description)}">` : ""
2896
+ ];
2897
+ Object.entries(meta).forEach(([name, content2]) => {
2898
+ metaTags.push(`<meta name="${escapeHtml3(name)}" content="${escapeHtml3(content2)}">`);
3520
2899
  });
3521
- return { promise, resolve, reject };
3522
- }
3523
- function pick(obj, keys) {
3524
- const result = {};
3525
- for (const key of keys) {
3526
- if (key in obj) {
3527
- result[key] = obj[key];
2900
+ const scriptTags = scripts.map((src) => {
2901
+ if (src.startsWith("<script")) {
2902
+ return src;
3528
2903
  }
3529
- }
3530
- return result;
3531
- }
3532
- function omit(obj, keys) {
3533
- const result = { ...obj };
3534
- for (const key of keys) {
3535
- delete result[key];
3536
- }
3537
- return result;
2904
+ return `<script src="${escapeHtml3(src)}" ${src.endsWith(".js") ? 'type="module"' : ""} defer></script>`;
2905
+ });
2906
+ const styleTags = styles.map((href) => {
2907
+ if (href.startsWith("<style")) {
2908
+ return href;
2909
+ }
2910
+ return `<link rel="stylesheet" href="${escapeHtml3(href)}">`;
2911
+ });
2912
+ const initialDataScript = Object.keys(initialData).length > 0 ? `<script id="__APP_DATA__" type="application/json">${escapeHtml3(JSON.stringify(initialData))}</script>` : "";
2913
+ return `<!DOCTYPE html>
2914
+ <html lang="${lang}" ${htmlAttributes}>
2915
+ <head>
2916
+ ${metaTags.filter(Boolean).join("\n ")}
2917
+ <title>${escapeHtml3(title)}</title>
2918
+ ${styleTags.join("\n ")}
2919
+ </head>
2920
+ <body class="${bodyClasses}" ${bodyAttributes}>
2921
+ <div id="app-root" data-ssr-root${componentName ? ` data-component="${escapeHtml3(componentName)}"` : ""}>${content}</div>
2922
+ ${initialDataScript}
2923
+ ${scriptTags.join("\n ")}
2924
+ </body>
2925
+ </html>`;
3538
2926
  }
3539
- function groupBy(array, key) {
3540
- return array.reduce((result, item) => {
3541
- const groupKey = typeof key === "function" ? key(item) : String(item[key]);
3542
- if (!result[groupKey]) {
3543
- result[groupKey] = [];
2927
+ function generateErrorPage(statusCode, message, error) {
2928
+ const errorMessages = {
2929
+ 400: "Bad Request",
2930
+ 401: "Unauthorized",
2931
+ 403: "Forbidden",
2932
+ 404: "Not Found",
2933
+ 500: "Internal Server Error"
2934
+ };
2935
+ const title = `${statusCode} - ${errorMessages[statusCode] || "Error"}`;
2936
+ const isDev = process.env.NODE_ENV !== "production";
2937
+ const errorDetails = isDev && error ? `
2938
+ <div class="error-details">
2939
+ <pre>${escapeHtml3(error.stack || error.message)}</pre>
2940
+ </div>
2941
+ ` : "";
2942
+ const content = `
2943
+ <div class="error-container">
2944
+ <h1>${statusCode}</h1>
2945
+ <h2>${escapeHtml3(errorMessages[statusCode] || "Error")}</h2>
2946
+ <p>${escapeHtml3(message)}</p>
2947
+ ${errorDetails}
2948
+ <a href="/" class="home-link">Back to Home</a>
2949
+ </div>
2950
+ `;
2951
+ const styles = [`<style>
2952
+ body {
2953
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
2954
+ display: flex;
2955
+ justify-content: center;
2956
+ align-items: center;
2957
+ min-height: 100vh;
2958
+ margin: 0;
2959
+ background-color: #f7f7f7;
2960
+ color: #333;
2961
+ }
2962
+ .error-container {
2963
+ text-align: center;
2964
+ padding: 2rem;
2965
+ border-radius: 8px;
2966
+ background-color: white;
2967
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
2968
+ max-width: 600px;
2969
+ width: 100%;
2970
+ }
2971
+ h1 {
2972
+ font-size: 6rem;
2973
+ margin: 0;
2974
+ color: #e74c3c;
2975
+ }
2976
+ h2 {
2977
+ margin-top: 0;
2978
+ margin-bottom: 1rem;
2979
+ color: #333;
2980
+ }
2981
+ .error-details {
2982
+ text-align: left;
2983
+ margin: 2rem 0;
2984
+ padding: 1rem;
2985
+ background-color: #f8f8f8;
2986
+ border-radius: 4px;
2987
+ overflow: auto;
2988
+ }
2989
+ pre {
2990
+ margin: 0;
2991
+ font-family: monospace;
2992
+ font-size: 0.85rem;
2993
+ white-space: pre-wrap;
3544
2994
  }
3545
- result[groupKey].push(item);
3546
- return result;
3547
- }, {});
3548
- }
3549
- function isEmpty(value) {
3550
- if (value === null || value === void 0)
3551
- return true;
3552
- if (typeof value === "string")
3553
- return value.trim() === "";
3554
- if (Array.isArray(value))
3555
- return value.length === 0;
3556
- if (value instanceof Map || value instanceof Set)
3557
- return value.size === 0;
3558
- if (typeof value === "object")
3559
- return Object.keys(value).length === 0;
3560
- return false;
3561
- }
3562
- function clamp(value, min, max) {
3563
- return Math.min(Math.max(value, min), max);
3564
- }
3565
- function get(obj, path5, defaultValue) {
3566
- const keys = Array.isArray(path5) ? path5 : path5.split(".");
3567
- let result = obj;
3568
- for (const key of keys) {
3569
- if (result === null || result === void 0) {
3570
- return defaultValue;
2995
+ .home-link {
2996
+ display: inline-block;
2997
+ margin-top: 1.5rem;
2998
+ padding: 0.75rem 1.5rem;
2999
+ background-color: #3498db;
3000
+ color: white;
3001
+ text-decoration: none;
3002
+ border-radius: 4px;
3003
+ transition: background-color 0.2s;
3571
3004
  }
3572
- result = result[key];
3573
- }
3574
- return result === void 0 ? defaultValue : result;
3575
- }
3576
- function set(obj, path5, value) {
3577
- const keys = Array.isArray(path5) ? path5 : path5.split(".");
3578
- let current = obj;
3579
- for (let i = 0; i < keys.length - 1; i++) {
3580
- const key = keys[i];
3581
- if (!(key in current) || typeof current[key] !== "object") {
3582
- current[key] = {};
3005
+ .home-link:hover {
3006
+ background-color: #2980b9;
3583
3007
  }
3584
- current = current[key];
3585
- }
3586
- current[keys[keys.length - 1]] = value;
3587
- return obj;
3008
+ </style>`];
3009
+ return generateDocument(content, {
3010
+ title,
3011
+ description: `Error ${statusCode}: ${errorMessages[statusCode] || "Error"}`,
3012
+ bodyClasses: "error-page",
3013
+ styles
3014
+ });
3015
+ }
3016
+ function escapeHtml3(text) {
3017
+ return String(text).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
3588
3018
  }
3589
3019
 
3590
- // src/core/errors.ts
3591
- var BaraqexError = class extends Error {
3592
- constructor(message, options) {
3593
- super(message);
3594
- __publicField(this, "code");
3595
- __publicField(this, "hint");
3596
- __publicField(this, "docs");
3597
- __publicField(this, "originalCause");
3598
- this.name = "BaraqexError";
3599
- this.code = options.code;
3600
- this.hint = options.hint;
3601
- this.docs = options.docs;
3602
- this.originalCause = options.cause;
3603
- Error.captureStackTrace?.(this, this.constructor);
3604
- }
3605
- /**
3606
- * Format error for console output with helpful hints
3607
- */
3608
- format() {
3609
- let output = `
3610
- \u274C ${this.name}: ${this.message}
3611
- `;
3612
- output += ` Code: ${this.code}
3613
- `;
3614
- if (this.hint) {
3615
- output += ` \u{1F4A1} Hint: ${this.hint}
3616
- `;
3617
- }
3618
- if (this.docs) {
3619
- output += ` \u{1F4DA} Docs: ${this.docs}
3620
- `;
3621
- }
3622
- return output;
3623
- }
3624
- };
3625
- var ConfigError = class extends BaraqexError {
3626
- constructor(message, options) {
3627
- super(message, {
3628
- code: "CONFIG_ERROR",
3629
- hint: options?.hint || "Check your baraqex.config.js or server configuration",
3630
- docs: "https://baraqex.tech/docs/configuration",
3631
- cause: options?.cause
3632
- });
3633
- this.name = "ConfigError";
3634
- }
3635
- };
3636
- var DatabaseError = class extends BaraqexError {
3637
- constructor(message, options) {
3638
- super(message, {
3639
- code: "DATABASE_ERROR",
3640
- hint: options?.hint || "Verify your database connection string and credentials",
3641
- docs: "https://baraqex.tech/docs/database",
3642
- cause: options?.cause
3643
- });
3644
- __publicField(this, "dbType");
3645
- this.name = "DatabaseError";
3646
- this.dbType = options?.dbType;
3647
- }
3648
- };
3649
- var AuthError = class extends BaraqexError {
3650
- constructor(message, options) {
3651
- super(message, {
3652
- code: "AUTH_ERROR",
3653
- hint: options?.hint || "Check your JWT secret and token configuration",
3654
- docs: "https://baraqex.tech/docs/authentication",
3655
- cause: options?.cause
3656
- });
3657
- this.name = "AuthError";
3658
- }
3659
- };
3660
- var WasmError = class extends BaraqexError {
3661
- constructor(message, options) {
3662
- super(message, {
3663
- code: "WASM_ERROR",
3664
- hint: options?.hint || "Ensure your .wasm file is accessible and properly compiled",
3665
- docs: "https://baraqex.tech/docs/webassembly",
3666
- cause: options?.cause
3667
- });
3668
- this.name = "WasmError";
3669
- }
3670
- };
3671
- var RouterError = class extends BaraqexError {
3672
- constructor(message, options) {
3673
- super(message, {
3674
- code: "ROUTER_ERROR",
3675
- hint: options?.hint || "Check your API route file structure and exports",
3676
- docs: "https://baraqex.tech/docs/routing",
3677
- cause: options?.cause
3678
- });
3679
- this.name = "RouterError";
3680
- }
3681
- };
3682
- var ValidationError = class extends BaraqexError {
3683
- constructor(message, options) {
3684
- super(message, {
3685
- code: "VALIDATION_ERROR",
3686
- hint: options?.hint,
3687
- cause: options?.cause
3688
- });
3689
- __publicField(this, "field");
3690
- __publicField(this, "value");
3691
- this.name = "ValidationError";
3692
- this.field = options?.field;
3693
- this.value = options?.value;
3694
- }
3695
- };
3696
- function formatError(error) {
3697
- if (error instanceof BaraqexError) {
3698
- return error.format();
3699
- }
3700
- if (error instanceof Error) {
3701
- return `
3702
- \u274C Error: ${error.message}
3703
- `;
3020
+ // src/server/wasm.ts
3021
+ import fs3 from "fs/promises";
3022
+ import path3 from "path";
3023
+ import { pathToFileURL as pathToFileURL2 } from "url";
3024
+ var initialized = false;
3025
+ async function initNodeWasm() {
3026
+ if (initialized)
3027
+ return;
3028
+ try {
3029
+ globalThis.TextEncoder = globalThis.TextEncoder || TextEncoder;
3030
+ globalThis.TextDecoder = globalThis.TextDecoder || TextDecoder;
3031
+ initialized = true;
3032
+ } catch (error) {
3033
+ console.error("[WASM] Failed to initialize Node.js WASM environment:", error);
3034
+ throw error;
3704
3035
  }
3705
- return `
3706
- \u274C Unknown error: ${String(error)}
3707
- `;
3708
3036
  }
3709
- function withErrorHandling(fn, errorHandler3) {
3710
- return async (...args) => {
3037
+ async function loadGoRuntime(goWasmPath) {
3038
+ if (typeof globalThis.Go === "function") {
3039
+ return globalThis.Go;
3040
+ }
3041
+ const possiblePaths = [
3042
+ goWasmPath,
3043
+ "./wasm_exec.cjs",
3044
+ "./wasm_exec.js",
3045
+ "./public/wasm_exec.cjs",
3046
+ "./public/wasm_exec.js",
3047
+ "./src/wasm_exec.cjs",
3048
+ "./src/wasm_exec.js",
3049
+ path3.join(process.cwd(), "wasm_exec.cjs"),
3050
+ path3.join(process.cwd(), "wasm_exec.js"),
3051
+ path3.join(process.cwd(), "public", "wasm_exec.cjs"),
3052
+ path3.join(process.cwd(), "public", "wasm_exec.js"),
3053
+ path3.join(process.cwd(), "src", "wasm_exec.cjs"),
3054
+ path3.join(process.cwd(), "src", "wasm_exec.js")
3055
+ ].filter(Boolean);
3056
+ for (const wasmExecPath of possiblePaths) {
3711
3057
  try {
3712
- return await fn(...args);
3713
- } catch (error) {
3714
- if (errorHandler3) {
3715
- errorHandler3(error);
3058
+ const resolvedPath = path3.resolve(wasmExecPath);
3059
+ try {
3060
+ const stats = await fs3.stat(resolvedPath);
3061
+ if (!stats.isFile()) {
3062
+ continue;
3063
+ }
3064
+ } catch (statError) {
3065
+ continue;
3066
+ }
3067
+ const wasmExecUrl = pathToFileURL2(resolvedPath).href;
3068
+ if (globalThis.Go) {
3069
+ delete globalThis.Go;
3070
+ }
3071
+ await import(wasmExecUrl);
3072
+ if (typeof globalThis.Go === "function") {
3073
+ console.log(`[WASM] Loaded Go runtime from: ${resolvedPath}`);
3074
+ return globalThis.Go;
3716
3075
  } else {
3717
- console.error(formatError(error));
3076
+ console.warn(`[WASM] File found but Go class not exported: ${resolvedPath}`);
3718
3077
  }
3719
- throw error;
3078
+ } catch (error) {
3079
+ console.warn(`[WASM] Error loading from ${wasmExecPath}:`, error.message);
3080
+ continue;
3720
3081
  }
3721
- };
3722
- }
3723
-
3724
- // src/wasm.ts
3725
- async function loadGoWasm(wasmUrl, options = {}) {
3726
- if (typeof window === "undefined") {
3727
- throw new Error("loadGoWasm() is for browser use only. Use loadGoWasmFromFile() in Node.js.");
3728
3082
  }
3083
+ throw new Error(
3084
+ `[WASM] Could not find wasm_exec.js. Please ensure you have the Go WASM runtime file available.
3085
+ You can get it from: https://github.com/golang/go/blob/master/misc/wasm/wasm_exec.js
3086
+ Searched paths: ${possiblePaths.join(", ")}`
3087
+ );
3088
+ }
3089
+ async function loadGoWasmFromFile(wasmFilePath, options = {}) {
3729
3090
  try {
3730
- if (!window.Go) {
3731
- throw new Error("Go WASM runtime not available. Make sure wasm_exec.js is loaded.");
3091
+ await initNodeWasm();
3092
+ if (options.debug) {
3093
+ console.log("[WASM] Loading WASM from file:", wasmFilePath);
3732
3094
  }
3095
+ const GoRuntime = await loadGoRuntime(options.goWasmPath);
3096
+ const go = new GoRuntime();
3097
+ const wasmBuffer = await fs3.readFile(wasmFilePath);
3098
+ const wasmModule = await WebAssembly.compile(new Uint8Array(wasmBuffer));
3099
+ const baseImports = go.importObject;
3100
+ const finalImportObject = {
3101
+ ...baseImports,
3102
+ ...options.importObject
3103
+ };
3733
3104
  if (options.debug) {
3734
- console.log("[WASM] Loading WASM from:", wasmUrl);
3105
+ console.log("[WASM] Available import modules:", Object.keys(finalImportObject));
3106
+ for (const [moduleName, moduleExports] of Object.entries(finalImportObject)) {
3107
+ if (typeof moduleExports === "object" && moduleExports !== null) {
3108
+ const exportNames = Object.keys(moduleExports);
3109
+ console.log(`[WASM] ${moduleName} import functions:`, exportNames);
3110
+ }
3111
+ }
3735
3112
  }
3736
- const response = await fetch(wasmUrl);
3737
- if (!response.ok) {
3738
- throw new Error(`Failed to fetch WASM file: ${response.status}`);
3113
+ const instance = await WebAssembly.instantiate(wasmModule, finalImportObject);
3114
+ if (options.debug) {
3115
+ console.log("[WASM] WASM instance created, starting Go runtime...");
3739
3116
  }
3740
- const wasmBytes = await response.arrayBuffer();
3741
- const go = new window.Go();
3742
- const wasmModule = await WebAssembly.instantiate(wasmBytes, go.importObject);
3743
- go.run(wasmModule.instance);
3744
- await new Promise((resolve) => setTimeout(resolve, 100));
3117
+ const runPromise = go.run(instance);
3745
3118
  if (options.debug) {
3746
- console.log("[WASM] Go program started, checking for registered functions...");
3119
+ console.log("[WASM] Go runtime started, waiting for initialization...");
3120
+ }
3121
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
3122
+ if (options.debug) {
3123
+ console.log("[WASM] Scanning global object for Go functions...");
3747
3124
  }
3748
3125
  const functions = {};
3749
- for (const key in window) {
3750
- if (typeof window[key] === "function" && key.startsWith("go")) {
3751
- functions[key] = window[key];
3126
+ const globalObj = globalThis;
3127
+ const allKeys = Object.getOwnPropertyNames(globalObj);
3128
+ const goKeys = allKeys.filter((key) => key.startsWith("go"));
3129
+ if (options.debug) {
3130
+ console.log('[WASM] All keys starting with "go":', goKeys);
3131
+ }
3132
+ for (const key of goKeys) {
3133
+ if (typeof globalObj[key] === "function") {
3134
+ functions[key] = globalObj[key];
3752
3135
  if (options.debug) {
3753
3136
  console.log(`[WASM] Found function: ${key}`);
3754
3137
  }
3755
3138
  }
3756
3139
  }
3757
3140
  const wasmInstance = {
3758
- instance: wasmModule.instance,
3141
+ instance,
3759
3142
  module: wasmModule,
3760
- exports: wasmModule.instance.exports,
3143
+ exports: instance.exports,
3761
3144
  functions
3762
3145
  };
3763
3146
  if (options.onLoad) {
@@ -3765,50 +3148,396 @@ async function loadGoWasm(wasmUrl, options = {}) {
3765
3148
  }
3766
3149
  if (options.debug) {
3767
3150
  console.log(`[WASM] Module loaded successfully with ${Object.keys(functions).length} functions`);
3151
+ console.log("[WASM] Final function list:", Object.keys(functions));
3768
3152
  }
3153
+ runPromise.catch((error) => {
3154
+ if (options.debug) {
3155
+ console.log("[WASM] Go program finished with error:", error);
3156
+ }
3157
+ });
3769
3158
  return wasmInstance;
3770
3159
  } catch (error) {
3771
- console.error("[WASM] Error loading Go WASM module:", error);
3160
+ console.error("[WASM] Failed to load Go WASM module:", error);
3772
3161
  throw error;
3773
3162
  }
3774
3163
  }
3775
- function callWasmFunction(funcName, ...args) {
3776
- if (typeof window === "undefined") {
3777
- throw new Error("callWasmFunction() is for browser use only.");
3778
- }
3779
- const func = window[funcName];
3780
- if (typeof func !== "function") {
3781
- throw new Error(`Function ${funcName} not found. Make sure the WASM module is loaded.`);
3164
+
3165
+ // src/server/index.ts
3166
+ import { pathToFileURL as pathToFileURL3 } from "url";
3167
+ function getComponentName(filePath, pagesDir) {
3168
+ try {
3169
+ const relativePath = path4.relative(pagesDir, filePath);
3170
+ const withoutExt = relativePath.replace(/\.[^/.]+$/, "");
3171
+ const cleanPath = withoutExt.replace(/\/index$/, "");
3172
+ return `/pages/${cleanPath}`;
3173
+ } catch (e) {
3174
+ return "";
3782
3175
  }
3783
- return func(...args);
3784
3176
  }
3785
- function isWasmReady() {
3786
- if (typeof window === "undefined") {
3787
- return false;
3177
+ var Server = class {
3178
+ constructor(config = {}) {
3179
+ __publicField(this, "app");
3180
+ __publicField(this, "server", null);
3181
+ __publicField(this, "config");
3182
+ __publicField(this, "db", null);
3183
+ __publicField(this, "auth", null);
3184
+ __publicField(this, "initialized", false);
3185
+ this.config = {
3186
+ port: 3e3,
3187
+ apiDir: "./api",
3188
+ pagesDir: "./pages",
3189
+ staticDir: "./public",
3190
+ enableCors: true,
3191
+ ...config
3192
+ };
3788
3193
  }
3789
- return !!(window.Go && Object.keys(window).some(
3790
- (key) => key.startsWith("go") && typeof window[key] === "function"
3791
- ));
3792
- }
3793
- function getWasmFunctions() {
3794
- if (typeof window === "undefined") {
3795
- return [];
3194
+ async initializeApp() {
3195
+ if (this.initialized)
3196
+ return;
3197
+ try {
3198
+ const express = await import("express");
3199
+ this.app = express.default();
3200
+ this.app.use(express.default.json());
3201
+ this.app.use(express.default.urlencoded({ extended: true }));
3202
+ if (this.config.enableCors) {
3203
+ try {
3204
+ const cors = await import("cors");
3205
+ this.app.use(cors.default(this.config.corsOptions));
3206
+ } catch (error) {
3207
+ console.warn("CORS not available - install with: npm install cors @types/cors");
3208
+ }
3209
+ }
3210
+ if (this.config.db) {
3211
+ this.db = new Database(this.config.db);
3212
+ }
3213
+ if (this.config.auth) {
3214
+ this.auth = new AuthService({
3215
+ secret: this.config.auth.secret,
3216
+ expiresIn: this.config.auth.expiresIn
3217
+ });
3218
+ this.app.use(this.auth.initialize());
3219
+ }
3220
+ const staticPath = path4.resolve(process.cwd(), this.config.staticDir);
3221
+ if (fs4.existsSync(staticPath)) {
3222
+ this.app.use(express.default.static(staticPath));
3223
+ }
3224
+ this.setupApiRoutes();
3225
+ this.setupPageRoutes();
3226
+ this.app.use(notFoundHandler);
3227
+ this.app.use(errorHandler);
3228
+ this.initialized = true;
3229
+ } catch (error) {
3230
+ if (error.code === "MODULE_NOT_FOUND" && error.message.includes("express")) {
3231
+ throw new Error("Express not installed. Run: npm install express @types/express");
3232
+ }
3233
+ throw error;
3234
+ }
3796
3235
  }
3797
- return Object.keys(window).filter(
3798
- (key) => key.startsWith("go") && typeof window[key] === "function"
3799
- );
3800
- }
3801
- function useGoWasm(wasmUrl, options = {}) {
3802
- if (typeof window === "undefined") {
3803
- throw new Error("useGoWasm() is for browser use only.");
3236
+ async setupApiRoutes() {
3237
+ const apiRouter = new ApiRouter(this.config.apiDir, this.auth);
3238
+ await apiRouter.initialize();
3239
+ if (!apiRouter.isInitialized() || !apiRouter.router) {
3240
+ console.warn("\u26A0\uFE0F API router not initialized properly - skipping API routes");
3241
+ return;
3242
+ }
3243
+ console.log("\u2705 Setting up API routes...");
3244
+ this.app.use("/api", requestLogger, apiRouter.router);
3245
+ this.app.get("/api-docs", (req, res) => {
3246
+ const apiDocs = this.generateApiDocs();
3247
+ res.json(apiDocs);
3248
+ });
3804
3249
  }
3805
- return {
3806
- loadWasm: () => loadGoWasm(wasmUrl, options),
3807
- callFunction: callWasmFunction,
3808
- isReady: isWasmReady,
3809
- getFunctions: getWasmFunctions
3810
- };
3250
+ generateApiDocs() {
3251
+ const apiDir = path4.resolve(process.cwd(), this.config.apiDir);
3252
+ const docs = { endpoints: [] };
3253
+ if (fs4.existsSync(apiDir)) {
3254
+ this.scanApiDirectory(apiDir, "", docs.endpoints);
3255
+ }
3256
+ return docs;
3257
+ }
3258
+ scanApiDirectory(dirPath, routePrefix, endpoints) {
3259
+ const entries = fs4.readdirSync(dirPath, { withFileTypes: true });
3260
+ for (const entry of entries) {
3261
+ const fullPath = path4.join(dirPath, entry.name);
3262
+ if (entry.isDirectory()) {
3263
+ this.scanApiDirectory(fullPath, `${routePrefix}/${entry.name}`, endpoints);
3264
+ } else if (entry.name.endsWith(".js") || entry.name.endsWith(".ts")) {
3265
+ const routePath = this.getRoutePath(entry.name, routePrefix);
3266
+ endpoints.push({
3267
+ path: routePath,
3268
+ file: path4.relative(process.cwd(), fullPath),
3269
+ methods: this.detectApiMethods(fullPath)
3270
+ });
3271
+ }
3272
+ }
3273
+ }
3274
+ getRoutePath(filename, routePrefix) {
3275
+ const baseName = path4.basename(filename, path4.extname(filename));
3276
+ if (baseName === "index") {
3277
+ return routePrefix || "/";
3278
+ }
3279
+ const paramMatch = baseName.match(/^\[(.+)\]$/);
3280
+ if (paramMatch) {
3281
+ return `${routePrefix}/:${paramMatch[1]}`;
3282
+ }
3283
+ return `${routePrefix}/${baseName}`;
3284
+ }
3285
+ detectApiMethods(filePath) {
3286
+ try {
3287
+ const content = fs4.readFileSync(filePath, "utf8");
3288
+ const methods = ["get", "post", "put", "delete", "patch", "options"];
3289
+ return methods.filter(
3290
+ (method) => new RegExp(`export (async )?function ${method}\\s*\\(`).test(content) || new RegExp(`export const ${method}\\s*=`).test(content)
3291
+ );
3292
+ } catch (error) {
3293
+ return [];
3294
+ }
3295
+ }
3296
+ setupPageRoutes() {
3297
+ const pagesPath = path4.resolve(process.cwd(), this.config.pagesDir);
3298
+ if (!fs4.existsSync(pagesPath)) {
3299
+ return;
3300
+ }
3301
+ this.app.get("*", async (req, res) => {
3302
+ try {
3303
+ const { html, statusCode } = await this.renderPage(req.path);
3304
+ res.status(statusCode || 200).send(html);
3305
+ } catch (error) {
3306
+ console.error("Error rendering page:", error);
3307
+ const errorHtml = generateErrorPage(500, "Server Error");
3308
+ res.status(500).send(errorHtml);
3309
+ }
3310
+ });
3311
+ }
3312
+ async renderPage(routePath) {
3313
+ try {
3314
+ const pagesDir = this.config.pagesDir ? path4.resolve(process.cwd(), this.config.pagesDir) : "";
3315
+ if (!pagesDir || !fs4.existsSync(pagesDir)) {
3316
+ return {
3317
+ html: generateErrorPage(404, "Pages directory not found"),
3318
+ statusCode: 404
3319
+ };
3320
+ }
3321
+ let normalizedPath = routePath;
3322
+ if (!normalizedPath.startsWith("/")) {
3323
+ normalizedPath = "/" + normalizedPath;
3324
+ }
3325
+ if (normalizedPath === "/") {
3326
+ normalizedPath = "/index";
3327
+ }
3328
+ let pagePath = "";
3329
+ const possiblePaths = [
3330
+ path4.join(pagesDir, `${normalizedPath}.js`),
3331
+ path4.join(pagesDir, `${normalizedPath}.ts`),
3332
+ path4.join(pagesDir, `${normalizedPath}.jsx`),
3333
+ path4.join(pagesDir, `${normalizedPath}.tsx`),
3334
+ path4.join(pagesDir, `${normalizedPath}/index.js`),
3335
+ path4.join(pagesDir, `${normalizedPath}/index.ts`),
3336
+ path4.join(pagesDir, `${normalizedPath}/index.jsx`),
3337
+ path4.join(pagesDir, `${normalizedPath}/index.tsx`)
3338
+ ];
3339
+ for (const p of possiblePaths) {
3340
+ if (fs4.existsSync(p)) {
3341
+ pagePath = p;
3342
+ break;
3343
+ }
3344
+ }
3345
+ if (!pagePath) {
3346
+ return {
3347
+ html: generateErrorPage(404, `Page not found: ${normalizedPath}`),
3348
+ statusCode: 404
3349
+ };
3350
+ }
3351
+ try {
3352
+ const absolutePath = path4.isAbsolute(pagePath) ? pagePath : path4.resolve(pagePath);
3353
+ const fileUrl = pathToFileURL3(absolutePath).href;
3354
+ const urlWithTimestamp = `${fileUrl}?t=${Date.now()}`;
3355
+ const pageModule = await import(urlWithTimestamp);
3356
+ if (!pageModule || !pageModule.default) {
3357
+ throw new Error(`No default export found in ${pagePath}`);
3358
+ }
3359
+ const PageComponent = pageModule.default;
3360
+ const initialProps = {
3361
+ // Provide any initial props here
3362
+ path: normalizedPath,
3363
+ query: {},
3364
+ // Could be parsed from URL
3365
+ api: { serverTime: (/* @__PURE__ */ new Date()).toISOString() }
3366
+ };
3367
+ const renderResult = await renderComponent(PageComponent, initialProps);
3368
+ if (!renderResult.success) {
3369
+ return {
3370
+ html: generateErrorPage(500, "Failed to render page", renderResult.error instanceof Error ? renderResult.error : new Error("Unknown error")),
3371
+ statusCode: 500
3372
+ };
3373
+ }
3374
+ const htmlContent = renderResult.html;
3375
+ let pageTitle = "My App";
3376
+ try {
3377
+ if (typeof PageComponent.getTitle === "function") {
3378
+ pageTitle = PageComponent.getTitle(initialProps);
3379
+ } else if (PageComponent.title) {
3380
+ pageTitle = PageComponent.title;
3381
+ }
3382
+ } catch (e) {
3383
+ }
3384
+ const componentName = getComponentName(pagePath, pagesDir);
3385
+ const fullHtml = generateDocument(htmlContent, {
3386
+ title: pageTitle,
3387
+ // Get description from component if available
3388
+ description: typeof PageComponent.getDescription === "function" ? PageComponent.getDescription(initialProps) : PageComponent.description || "",
3389
+ // Add scripts for client-side hydration
3390
+ scripts: ["/client.js"],
3391
+ // Add any custom meta tags
3392
+ meta: typeof PageComponent.getMeta === "function" ? PageComponent.getMeta(initialProps) : {},
3393
+ // Add custom styles
3394
+ styles: ["/styles.css"],
3395
+ // Add initial data for client-side hydration
3396
+ initialData: initialProps,
3397
+ // Add component information for hydration
3398
+ componentName
3399
+ });
3400
+ return { html: fullHtml, statusCode: 200 };
3401
+ } catch (error) {
3402
+ console.error("Error rendering page:", error);
3403
+ return {
3404
+ html: generateErrorPage(500, "Error rendering page", error instanceof Error ? error : new Error("Unknown error")),
3405
+ statusCode: 500
3406
+ };
3407
+ }
3408
+ } catch (error) {
3409
+ console.error("Error finding page:", error);
3410
+ return {
3411
+ html: generateErrorPage(500, "Server error", error instanceof Error ? error : new Error("Unknown error")),
3412
+ statusCode: 500
3413
+ };
3414
+ }
3415
+ }
3416
+ getExpressApp() {
3417
+ return this.app;
3418
+ }
3419
+ getDatabase() {
3420
+ return this.db;
3421
+ }
3422
+ getAuth() {
3423
+ return this.auth;
3424
+ }
3425
+ async start() {
3426
+ await this.initializeApp();
3427
+ return new Promise((resolve) => {
3428
+ this.server = this.app.listen(this.config.port, () => {
3429
+ console.log(`Server running at http://localhost:${this.config.port}`);
3430
+ resolve();
3431
+ });
3432
+ });
3433
+ }
3434
+ stop() {
3435
+ return new Promise((resolve, reject) => {
3436
+ if (!this.server) {
3437
+ return resolve();
3438
+ }
3439
+ this.server.close((err) => {
3440
+ if (err)
3441
+ return reject(err);
3442
+ this.server = null;
3443
+ resolve();
3444
+ });
3445
+ });
3446
+ }
3447
+ restart() {
3448
+ return this.stop().then(() => this.start());
3449
+ }
3450
+ enableSSR(options = {}) {
3451
+ if (!fs4.existsSync(path4.resolve(process.cwd(), this.config.pagesDir))) {
3452
+ fs4.mkdirSync(path4.resolve(process.cwd(), this.config.pagesDir), { recursive: true });
3453
+ }
3454
+ if (options.hydratable) {
3455
+ const staticDir = path4.resolve(process.cwd(), this.config.staticDir);
3456
+ if (!fs4.existsSync(staticDir)) {
3457
+ fs4.mkdirSync(staticDir, { recursive: true });
3458
+ }
3459
+ const clientJsPath = path4.join(staticDir, "client.js");
3460
+ if (!fs4.existsSync(clientJsPath)) {
3461
+ const clientJsContent = `
3462
+ // Auto-generated hydration script
3463
+ import { hydrate } from 'baraqex';
3464
+
3465
+ // Find SSR content and hydrate it
3466
+ document.addEventListener('DOMContentLoaded', () => {
3467
+ const ssrRoots = document.querySelectorAll('[data-ssr-root]');
3468
+ ssrRoots.forEach(root => {
3469
+ const componentPath = root.getAttribute('data-component');
3470
+ if (componentPath) {
3471
+ import(componentPath).then(module => {
3472
+ hydrate(module.default, root);
3473
+ });
3474
+ }
3475
+ });
3476
+ });
3477
+ `;
3478
+ fs4.writeFileSync(clientJsPath, clientJsContent);
3479
+ }
3480
+ }
3481
+ }
3482
+ registerPlugin(plugin) {
3483
+ plugin(this);
3484
+ }
3485
+ addShutdownHandler() {
3486
+ const gracefulShutdown = async () => {
3487
+ console.log("Received shutdown signal, closing server...");
3488
+ try {
3489
+ await this.stop();
3490
+ if (this.db) {
3491
+ await this.db.disconnect();
3492
+ }
3493
+ console.log("Server shut down gracefully");
3494
+ process.exit(0);
3495
+ } catch (error) {
3496
+ console.error("Error during shutdown:", error);
3497
+ process.exit(1);
3498
+ }
3499
+ };
3500
+ process.on("SIGTERM", gracefulShutdown);
3501
+ process.on("SIGINT", gracefulShutdown);
3502
+ }
3503
+ };
3504
+ function createServer(config = {}) {
3505
+ return new Server(config);
3506
+ }
3507
+ function createDevServer(options = {}) {
3508
+ return new Server({
3509
+ port: options.port || 3e3,
3510
+ enableCors: options.enableCors !== false,
3511
+ apiDir: "./src/api",
3512
+ pagesDir: "./src/pages",
3513
+ staticDir: "./public"
3514
+ });
3515
+ }
3516
+ function createProductionServer(config) {
3517
+ const server = new Server({
3518
+ ...config,
3519
+ // Fix the PORT parsing
3520
+ port: config.port || (process.env.PORT ? parseInt(process.env.PORT) : 8080)
3521
+ });
3522
+ server.addShutdownHandler();
3523
+ return server;
3811
3524
  }
3525
+ var renderComponent = (Component2, props = {}) => {
3526
+ try {
3527
+ const html = renderToString(Component2(props));
3528
+ return {
3529
+ html: typeof html === "string" ? html : String(html),
3530
+ success: true
3531
+ };
3532
+ } catch (error) {
3533
+ console.error("Error rendering component:", error);
3534
+ return {
3535
+ html: `<div class="error">Error rendering component</div>`,
3536
+ success: false,
3537
+ error
3538
+ };
3539
+ }
3540
+ };
3812
3541
 
3813
3542
  // src/index.ts
3814
3543
  var safeJsonParse2 = (json, fallback) => {
@@ -3818,7 +3547,7 @@ var safeJsonParse2 = (json, fallback) => {
3818
3547
  return fallback;
3819
3548
  }
3820
3549
  };
3821
- var generateToken2 = (length = 32) => {
3550
+ var generateToken = (length = 32) => {
3822
3551
  const array = new Uint8Array(length);
3823
3552
  if (typeof crypto !== "undefined" && crypto.getRandomValues) {
3824
3553
  crypto.getRandomValues(array);
@@ -3831,7 +3560,7 @@ var generateToken2 = (length = 32) => {
3831
3560
  };
3832
3561
  var generateDocument2 = (content, options = {}) => `<!DOCTYPE html><html><head><title>${options.title || "App"}</title></head><body>${content}</body></html>`;
3833
3562
  var generateErrorPage2 = (code, message) => `<div>Error ${code}: ${message}</div>`;
3834
- var generateLoadingPage2 = (message = "Loading...") => `<div>${message}</div>`;
3563
+ var generateLoadingPage = (message = "Loading...") => `<div>${message}</div>`;
3835
3564
  var fallbackRenderToString = (component) => {
3836
3565
  try {
3837
3566
  if (typeof component === "function") {
@@ -3843,113 +3572,15 @@ var fallbackRenderToString = (component) => {
3843
3572
  return "<div>Error rendering component</div>";
3844
3573
  }
3845
3574
  };
3846
- function createLazyLoader(importFn, fallback) {
3847
- let cached = null;
3848
- let loading = null;
3849
- async function ensure() {
3850
- if (cached)
3851
- return cached;
3852
- if (!loading) {
3853
- loading = importFn().then((mod) => {
3854
- cached = mod;
3855
- return mod;
3856
- });
3857
- }
3858
- return loading;
3859
- }
3860
- return new Proxy({}, {
3861
- get(_target, prop) {
3862
- if (cached?.[prop] !== void 0) {
3863
- return cached[prop];
3864
- }
3865
- if (fallback && fallback[prop]) {
3866
- return fallback[prop];
3867
- }
3868
- return async (...args) => {
3869
- const mod = await ensure();
3870
- const fn = mod[prop];
3871
- if (typeof fn !== "function") {
3872
- throw new Error(
3873
- `[baraqex] '${prop}' is not exported from the server module.`
3874
- );
3875
- }
3876
- return fn(...args);
3877
- };
3878
- }
3879
- });
3880
- }
3881
- var notAvailable = (name) => () => {
3882
- throw new Error(
3883
- `[baraqex] ${name} is only available in a Node.js environment with Express installed. Run: npm install express @types/express`
3884
- );
3885
- };
3886
- var serverNotFound = {
3887
- createServer: notAvailable("createServer"),
3888
- createDevServer: notAvailable("createDevServer"),
3889
- createProductionServer: notAvailable("createProductionServer"),
3890
- Server: notAvailable("Server"),
3891
- renderComponent: notAvailable("renderComponent"),
3892
- Database: notAvailable("Database"),
3893
- AuthService: notAvailable("AuthService"),
3894
- ApiRouter: notAvailable("ApiRouter"),
3895
- requestLogger: notAvailable("requestLogger"),
3896
- errorHandler: notAvailable("errorHandler"),
3897
- notFoundHandler: notAvailable("notFoundHandler"),
3898
- rateLimit: notAvailable("rateLimit"),
3899
- initNodeWasm: notAvailable("initNodeWasm"),
3900
- loadGoWasmFromFile: notAvailable("loadGoWasmFromFile")
3901
- };
3902
- var isNode = typeof process !== "undefined" && !!process.versions?.node;
3903
- var isBrowser4 = typeof window !== "undefined";
3904
- var serverModules = createLazyLoader(
3905
- () => Promise.all([
3906
- Promise.resolve().then(() => (init_server(), server_exports)),
3907
- Promise.resolve().then(() => (init_utils(), utils_exports)),
3908
- Promise.resolve().then(() => (init_templates(), templates_exports)),
3909
- Promise.resolve().then(() => (init_server_renderer2(), server_renderer_exports))
3910
- ]).then(([server, utils, templates, renderer]) => ({
3911
- ...server,
3912
- ...utils,
3913
- ...templates,
3914
- ...renderer
3915
- })),
3916
- isNode && !isBrowser4 ? serverNotFound : serverNotFound
3917
- );
3918
- var lazy = (name) => (...args) => serverModules[name](...args);
3919
- var createServer2 = lazy("createServer");
3920
- var createDevServer2 = lazy("createDevServer");
3921
- var createProductionServer2 = lazy("createProductionServer");
3922
- var BaraqexServer = serverModules.Server;
3923
- var Database2 = serverModules.Database;
3924
- var AuthService2 = serverModules.AuthService;
3925
- var ApiRouter2 = serverModules.ApiRouter;
3926
- var requestLogger2 = lazy("requestLogger");
3927
- var errorHandler2 = lazy("errorHandler");
3928
- var notFoundHandler2 = lazy("notFoundHandler");
3929
- var rateLimit2 = lazy("rateLimit");
3930
- var initNodeWasm3 = lazy("initNodeWasm");
3931
- var loadGoWasmFromFile2 = lazy("loadGoWasmFromFile");
3932
- var hashString2 = lazy("hashString");
3933
- var getPagination2 = lazy("getPagination");
3934
- var sendSuccess2 = lazy("sendSuccess");
3935
- var sendError2 = lazy("sendError");
3936
- var validateFields2 = lazy("validateFields");
3937
- var validateFileUpload2 = lazy("validateFileUpload");
3938
- var getEnvironmentInfo2 = lazy("getEnvironmentInfo");
3939
- var isDirectoryEmpty2 = lazy("isDirectoryEmpty");
3940
- var ensureDirectory2 = lazy("ensureDirectory");
3941
- var writeJsonFile2 = lazy("writeJsonFile");
3942
- var readJsonFile2 = lazy("readJsonFile");
3943
- var renderComponent2 = lazy("renderComponent");
3944
3575
  export {
3945
- ApiRouter2 as ApiRouter,
3576
+ ApiRouter,
3946
3577
  AuthError,
3947
- AuthService2 as AuthService,
3578
+ AuthService,
3948
3579
  BaraqexError,
3949
- BaraqexServer,
3580
+ Server as BaraqexServer,
3950
3581
  Component,
3951
3582
  ConfigError,
3952
- Database2 as Database,
3583
+ Database,
3953
3584
  DatabaseError,
3954
3585
  Fragment,
3955
3586
  LifecycleEvents,
@@ -3980,14 +3611,14 @@ export {
3980
3611
  createAction,
3981
3612
  createClassComponent,
3982
3613
  createContext,
3983
- createDevServer2 as createDevServer,
3614
+ createDevServer,
3984
3615
  createElement,
3985
3616
  createElementSync,
3986
3617
  createEventBus,
3987
- createProductionServer2 as createProductionServer,
3618
+ createProductionServer,
3988
3619
  createRoot,
3989
3620
  createRootState,
3990
- createServer2 as createServer,
3621
+ createServer,
3991
3622
  createSlice,
3992
3623
  createStore,
3993
3624
  debounce,
@@ -4014,8 +3645,8 @@ export {
4014
3645
  emitStoreBeforeAction,
4015
3646
  emitStoreError,
4016
3647
  emitStoreInitialized,
4017
- ensureDirectory2 as ensureDirectory,
4018
- errorHandler2 as errorHandler,
3648
+ ensureDirectory,
3649
+ errorHandler,
4019
3650
  escapeHtml2 as escapeHtml,
4020
3651
  eventBus,
4021
3652
  fallbackRenderToString,
@@ -4023,21 +3654,21 @@ export {
4023
3654
  formatDate,
4024
3655
  generateDocument2 as generateDocument,
4025
3656
  generateErrorPage2 as generateErrorPage,
4026
- generateLoadingPage2 as generateLoadingPage,
4027
- generateToken2 as generateToken,
3657
+ generateLoadingPage,
3658
+ generateToken,
4028
3659
  get,
4029
3660
  getContextValue,
4030
3661
  getCurrentRoot,
4031
- getEnvironmentInfo2 as getEnvironmentInfo,
3662
+ getEnvironmentInfo,
4032
3663
  getIsBatching,
4033
- getPagination2 as getPagination,
3664
+ getPagination,
4034
3665
  getWasmFunctions,
4035
3666
  groupBy,
4036
3667
  hasRoot,
4037
- hashString2 as hashString,
3668
+ hashString,
4038
3669
  hydrate,
4039
- initNodeWasm3 as initNodeWasm,
4040
- isDirectoryEmpty2 as isDirectoryEmpty,
3670
+ initNodeWasm,
3671
+ isDirectoryEmpty,
4041
3672
  isEmpty,
4042
3673
  isWasmReady,
4043
3674
  jsx,
@@ -4045,10 +3676,10 @@ export {
4045
3676
  jsxs,
4046
3677
  kebabCase,
4047
3678
  loadGoWasm,
4048
- loadGoWasmFromFile2 as loadGoWasmFromFile,
3679
+ loadGoWasmFromFile,
4049
3680
  logger,
4050
3681
  memoize,
4051
- notFoundHandler2 as notFoundHandler,
3682
+ notFoundHandler,
4052
3683
  omit,
4053
3684
  onAppDestroyed,
4054
3685
  onAppError,
@@ -4070,18 +3701,18 @@ export {
4070
3701
  patterns,
4071
3702
  pick,
4072
3703
  prepareRender,
4073
- rateLimit2 as rateLimit,
4074
- readJsonFile2 as readJsonFile,
3704
+ rateLimit,
3705
+ readJsonFile,
4075
3706
  render,
4076
- renderComponent2 as renderComponent,
3707
+ renderComponent,
4077
3708
  renderToStream,
4078
3709
  renderToString,
4079
3710
  renderToStringWithData,
4080
- requestLogger2 as requestLogger,
3711
+ requestLogger,
4081
3712
  retry,
4082
3713
  safeJsonParse2 as safeJsonParse,
4083
- sendError2 as sendError,
4084
- sendSuccess2 as sendSuccess,
3714
+ sendError,
3715
+ sendSuccess,
4085
3716
  set,
4086
3717
  setCurrentRoot,
4087
3718
  shallowEqual,
@@ -4114,9 +3745,9 @@ export {
4114
3745
  useState,
4115
3746
  useStore,
4116
3747
  uuid,
4117
- validateFields2 as validateFields,
4118
- validateFileUpload2 as validateFileUpload,
3748
+ validateFields,
3749
+ validateFileUpload,
4119
3750
  withErrorHandling,
4120
- writeJsonFile2 as writeJsonFile
3751
+ writeJsonFile
4121
3752
  };
4122
3753
  //# sourceMappingURL=index.js.map