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.d.ts +7 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2105 -2474
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
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
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
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
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
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
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
}
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
}
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
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
|
|
3082
|
-
|
|
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
|
|
3085
|
-
|
|
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
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
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
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
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
|
|
3110
|
-
|
|
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
|
|
3113
|
-
|
|
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
|
|
3116
|
-
|
|
2024
|
+
function escapeHtml2(str) {
|
|
2025
|
+
const htmlEscapes = {
|
|
2026
|
+
"&": "&",
|
|
2027
|
+
"<": "<",
|
|
2028
|
+
">": ">",
|
|
2029
|
+
'"': """,
|
|
2030
|
+
"'": "'"
|
|
2031
|
+
};
|
|
2032
|
+
return str.replace(/[&<>"']/g, (char) => htmlEscapes[char]);
|
|
3117
2033
|
}
|
|
3118
|
-
function
|
|
3119
|
-
|
|
2034
|
+
function unescapeHtml(str) {
|
|
2035
|
+
const htmlUnescapes = {
|
|
2036
|
+
"&": "&",
|
|
2037
|
+
"<": "<",
|
|
2038
|
+
">": ">",
|
|
2039
|
+
""": '"',
|
|
2040
|
+
"'": "'"
|
|
2041
|
+
};
|
|
2042
|
+
return str.replace(/&(?:amp|lt|gt|quot|#39);/g, (entity) => htmlUnescapes[entity] || entity);
|
|
3120
2043
|
}
|
|
3121
|
-
function
|
|
3122
|
-
return
|
|
2044
|
+
function capitalize(str) {
|
|
2045
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
3123
2046
|
}
|
|
3124
|
-
function
|
|
3125
|
-
return
|
|
2047
|
+
function camelCase(str) {
|
|
2048
|
+
return str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "").replace(/^(.)/, (char) => char.toLowerCase());
|
|
3126
2049
|
}
|
|
3127
|
-
function
|
|
3128
|
-
return
|
|
2050
|
+
function kebabCase(str) {
|
|
2051
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
3129
2052
|
}
|
|
3130
|
-
function
|
|
3131
|
-
return
|
|
2053
|
+
function sleep(ms) {
|
|
2054
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3132
2055
|
}
|
|
3133
|
-
function
|
|
3134
|
-
|
|
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
|
|
3137
|
-
|
|
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
|
|
3140
|
-
|
|
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
|
|
3143
|
-
|
|
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
|
|
3146
|
-
return
|
|
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
|
|
3149
|
-
|
|
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
|
|
3152
|
-
return
|
|
2122
|
+
function clamp(value, min, max) {
|
|
2123
|
+
return Math.min(Math.max(value, min), max);
|
|
3153
2124
|
}
|
|
3154
|
-
function
|
|
3155
|
-
|
|
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
|
|
3158
|
-
|
|
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
|
-
|
|
3161
|
-
|
|
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
|
|
3164
|
-
return
|
|
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/
|
|
3168
|
-
function
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
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
|
-
|
|
3196
|
-
|
|
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
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
const
|
|
3215
|
-
const
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
if (
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
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
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
if (
|
|
3235
|
-
|
|
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
|
-
|
|
3238
|
-
|
|
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
|
|
3248
|
-
}
|
|
3249
|
-
|
|
2329
|
+
return wasmInstance;
|
|
2330
|
+
} catch (error) {
|
|
2331
|
+
console.error("[WASM] Error loading Go WASM module:", error);
|
|
2332
|
+
throw error;
|
|
2333
|
+
}
|
|
3250
2334
|
}
|
|
3251
|
-
function
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
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
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
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
|
-
|
|
3278
|
-
|
|
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
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
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
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
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
|
-
|
|
3307
|
-
|
|
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
|
-
|
|
3310
|
-
return
|
|
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
|
-
|
|
3313
|
-
return
|
|
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
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
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
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
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
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
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
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
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
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
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
|
|
3365
|
-
if (
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
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
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
return
|
|
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
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
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
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
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
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
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
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
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
|
-
|
|
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
|
|
3437
|
-
if (
|
|
3438
|
-
return
|
|
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 (
|
|
3453
|
-
return
|
|
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 (
|
|
3456
|
-
|
|
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
|
-
|
|
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
|
-
"&": "&",
|
|
3467
|
-
"<": "<",
|
|
3468
|
-
">": ">",
|
|
3469
|
-
'"': """,
|
|
3470
|
-
"'": "'"
|
|
3471
|
-
};
|
|
3472
|
-
return str.replace(/[&<>"']/g, (char) => htmlEscapes[char]);
|
|
2833
|
+
return { valid: true };
|
|
3473
2834
|
}
|
|
3474
|
-
function
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
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
|
|
3488
|
-
|
|
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
|
|
3491
|
-
|
|
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
|
|
3494
|
-
|
|
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
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
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
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
const
|
|
3518
|
-
|
|
3519
|
-
|
|
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
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
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
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
}
|
|
3537
|
-
|
|
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
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
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
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
3588
3018
|
}
|
|
3589
3019
|
|
|
3590
|
-
// src/
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
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
|
|
3710
|
-
|
|
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
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
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.
|
|
3076
|
+
console.warn(`[WASM] File found but Go class not exported: ${resolvedPath}`);
|
|
3718
3077
|
}
|
|
3719
|
-
|
|
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
|
-
|
|
3731
|
-
|
|
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]
|
|
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
|
|
3737
|
-
if (
|
|
3738
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
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
|
|
3141
|
+
instance,
|
|
3759
3142
|
module: wasmModule,
|
|
3760
|
-
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]
|
|
3160
|
+
console.error("[WASM] Failed to load Go WASM module:", error);
|
|
3772
3161
|
throw error;
|
|
3773
3162
|
}
|
|
3774
3163
|
}
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
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
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
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
|
-
|
|
3790
|
-
(
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
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
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
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
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
3576
|
+
ApiRouter,
|
|
3946
3577
|
AuthError,
|
|
3947
|
-
|
|
3578
|
+
AuthService,
|
|
3948
3579
|
BaraqexError,
|
|
3949
|
-
BaraqexServer,
|
|
3580
|
+
Server as BaraqexServer,
|
|
3950
3581
|
Component,
|
|
3951
3582
|
ConfigError,
|
|
3952
|
-
|
|
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
|
-
|
|
3614
|
+
createDevServer,
|
|
3984
3615
|
createElement,
|
|
3985
3616
|
createElementSync,
|
|
3986
3617
|
createEventBus,
|
|
3987
|
-
|
|
3618
|
+
createProductionServer,
|
|
3988
3619
|
createRoot,
|
|
3989
3620
|
createRootState,
|
|
3990
|
-
|
|
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
|
-
|
|
4018
|
-
|
|
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
|
-
|
|
4027
|
-
|
|
3657
|
+
generateLoadingPage,
|
|
3658
|
+
generateToken,
|
|
4028
3659
|
get,
|
|
4029
3660
|
getContextValue,
|
|
4030
3661
|
getCurrentRoot,
|
|
4031
|
-
|
|
3662
|
+
getEnvironmentInfo,
|
|
4032
3663
|
getIsBatching,
|
|
4033
|
-
|
|
3664
|
+
getPagination,
|
|
4034
3665
|
getWasmFunctions,
|
|
4035
3666
|
groupBy,
|
|
4036
3667
|
hasRoot,
|
|
4037
|
-
|
|
3668
|
+
hashString,
|
|
4038
3669
|
hydrate,
|
|
4039
|
-
|
|
4040
|
-
|
|
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
|
-
|
|
3679
|
+
loadGoWasmFromFile,
|
|
4049
3680
|
logger,
|
|
4050
3681
|
memoize,
|
|
4051
|
-
|
|
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
|
-
|
|
4074
|
-
|
|
3704
|
+
rateLimit,
|
|
3705
|
+
readJsonFile,
|
|
4075
3706
|
render,
|
|
4076
|
-
|
|
3707
|
+
renderComponent,
|
|
4077
3708
|
renderToStream,
|
|
4078
3709
|
renderToString,
|
|
4079
3710
|
renderToStringWithData,
|
|
4080
|
-
|
|
3711
|
+
requestLogger,
|
|
4081
3712
|
retry,
|
|
4082
3713
|
safeJsonParse2 as safeJsonParse,
|
|
4083
|
-
|
|
4084
|
-
|
|
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
|
-
|
|
4118
|
-
|
|
3748
|
+
validateFields,
|
|
3749
|
+
validateFileUpload,
|
|
4119
3750
|
withErrorHandling,
|
|
4120
|
-
|
|
3751
|
+
writeJsonFile
|
|
4121
3752
|
};
|
|
4122
3753
|
//# sourceMappingURL=index.js.map
|