UNPKG

baraqex

Version:

A powerful full-stack framework for modern web development

1,554 lines (1,545 loc) 66.5 kB
var __defProp = Object.defineProperty; var __getOwnPropNames = Object.getOwnPropertyNames; var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) { if (typeof require !== "undefined") return require.apply(this, arguments); throw Error('Dynamic require of "' + x + '" is not supported'); }); var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; // node_modules/frontend-hamroun/dist/index.mjs function batchUpdates(fn) { if (isBatching) { queue.push(fn); return; } isBatching = true; try { fn(); while (queue.length > 0) { const nextFn = queue.shift(); nextFn == null ? void 0 : nextFn(); } } finally { isBatching = false; } } function setRenderCallback(callback, element, container) { globalRenderCallback = callback; globalContainer = container; currentElement = element; } function prepareRender() { currentRender++; stateIndices.set(currentRender, 0); return currentRender; } function finishRender() { if (isServer) { serverStates.delete(currentRender); } currentRender = 0; } function useState(initial) { if (!currentRender) { throw new Error("useState must be called within a render"); } if (isServer) { if (!serverStates.has(currentRender)) { serverStates.set(currentRender, /* @__PURE__ */ new Map()); } const componentState = serverStates.get(currentRender); const index2 = stateIndices.get(currentRender) || 0; if (!componentState.has(index2)) { componentState.set(index2, initial); } const state2 = componentState.get(index2); const setState2 = (newValue) => { }; stateIndices.set(currentRender, index2 + 1); return [state2, setState2]; } if (!states.has(currentRender)) { states.set(currentRender, []); } const componentStates = states.get(currentRender); const index = stateIndices.get(currentRender); if (index >= componentStates.length) { componentStates.push(initial); } const state = componentStates[index]; const setState = (newValue) => { const nextValue = typeof newValue === "function" ? newValue(componentStates[index]) : newValue; if (componentStates[index] === nextValue) return; componentStates[index] = nextValue; if (isBatching) { batchUpdates(() => rerender(currentRender)); } else { rerender(currentRender); } }; stateIndices.set(currentRender, index + 1); return [state, setState]; } function useEffect(callback, deps) { if (!currentRender) throw new Error("useEffect must be called within a render"); const effectIndex = stateIndices.get(currentRender); if (!effects.has(currentRender)) { effects.set(currentRender, []); } const componentEffects = effects.get(currentRender); const prevEffect = componentEffects[effectIndex]; if (!prevEffect || !deps || !prevEffect.deps || deps.some((dep, i) => dep !== prevEffect.deps[i])) { if (prevEffect == null ? void 0 : prevEffect.cleanup) { prevEffect.cleanup(); } queueMicrotask(() => { const cleanup = callback() || void 0; componentEffects[effectIndex] = { cleanup, deps }; }); } stateIndices.set(currentRender, effectIndex + 1); } function useMemo(factory, deps) { if (!currentRender) throw new Error("useMemo must be called within a render"); const memoIndex = stateIndices.get(currentRender); if (!memos.has(currentRender)) { memos.set(currentRender, []); } const componentMemos = memos.get(currentRender); const prevMemo = componentMemos[memoIndex]; if (!prevMemo || deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i]))) { const value = factory(); componentMemos[memoIndex] = { value, deps }; stateIndices.set(currentRender, memoIndex + 1); return value; } stateIndices.set(currentRender, memoIndex + 1); return prevMemo.value; } function useRef(initial) { if (!currentRender) throw new Error("useRef must be called within a render"); const refIndex = stateIndices.get(currentRender); if (!refs.has(currentRender)) { refs.set(currentRender, []); } const componentRefs = refs.get(currentRender); if (refIndex >= componentRefs.length) { const ref2 = { current: initial }; componentRefs.push(ref2); stateIndices.set(currentRender, refIndex + 1); return ref2; } const ref = componentRefs[refIndex]; stateIndices.set(currentRender, refIndex + 1); return ref; } async function rerender(rendererId) { try { const componentEffects = effects.get(rendererId); if (componentEffects) { componentEffects.forEach((effect) => { if (effect.cleanup) effect.cleanup(); }); effects.set(rendererId, []); } if (globalRenderCallback && globalContainer && currentElement) { await globalRenderCallback(currentElement, globalContainer); } } catch (error) { console.error("Error during rerender:", error); } } function useErrorBoundary() { const [error, setError] = useState(null); return [error, () => setError(null)]; } function createContext(defaultValue) { const context = { Provider: ({ value, children }) => { return children; }, Consumer: ({ children }) => { return children(defaultValue); }, _id: Symbol(), useSelector: (selector) => { return selector(defaultValue); } }; return context; } function useContext(context) { return context; } function jsx(type, props) { console.log("JSX Transform:", { type, props }); const processedProps = { ...props }; if (arguments.length > 2) { processedProps.children = Array.prototype.slice.call(arguments, 2); } return { type, props: processedProps }; } async function createElement(vnode) { var _a; console.log("Creating element from:", vnode); if (vnode == null) { return document.createTextNode(""); } if (typeof vnode === "boolean") { return document.createTextNode(""); } if (typeof vnode === "number" || typeof vnode === "string") { return document.createTextNode(String(vnode)); } if (Array.isArray(vnode)) { const fragment = document.createDocumentFragment(); for (const child of vnode) { const node = await createElement(child); fragment.appendChild(node); } return fragment; } if ("type" in vnode && vnode.props !== void 0) { const { type, props } = vnode; if (typeof type === "function") { try { const result = await type(props || {}); const node = await createElement(result); if (node instanceof Element) { node.setAttribute("data-component-id", type.name || type.toString()); } return node; } catch (error) { console.error("Error rendering component:", error); return document.createTextNode(""); } } const element = document.createElement(type); for (const [key, value] of Object.entries(props || {})) { if (key === "children") continue; if (key.startsWith("on") && typeof value === "function") { const eventName = key.toLowerCase().slice(2); const existingHandler = (_a = element.__events) == null ? void 0 : _a[eventName]; if (existingHandler) { element.removeEventListener(eventName, existingHandler); } element.addEventListener(eventName, value); if (!element.__events) { element.__events = {}; } element.__events[eventName] = value; } else if (key === "style" && typeof value === "object") { Object.assign(element.style, value); } else if (key === "className") { element.setAttribute("class", String(value)); } else if (key !== "key" && key !== "ref") { element.setAttribute(key, String(value)); } } const children = props == null ? void 0 : props.children; if (children != null) { const childArray = Array.isArray(children) ? children.flat() : [children]; for (const child of childArray) { const childNode = await createElement(child); element.appendChild(childNode); } } return element; } return document.createTextNode(String(vnode)); } async function hydrate(element, container) { isHydrating = true; try { await render(element, container); } finally { isHydrating = false; } } async function render(element, container) { console.log("Rendering to:", container.id); batchUpdates(async () => { const rendererId = prepareRender(); try { setRenderCallback(render, element, container); const domNode = await createElement(element); if (!isHydrating) { container.innerHTML = ""; } container.appendChild(domNode); } finally { finishRender(); } }); } function renderToString(vnode) { prepareRender(); const html = renderNodeToString(vnode); finishRender(); return html; } function renderNodeToString(vnode) { var _a, _b, _c; if (vnode === null || vnode === void 0) return ""; if (typeof vnode === "boolean") return ""; if (typeof vnode === "number" || typeof vnode === "string") return escapeHtml(String(vnode)); if (typeof vnode.type === "function") { const Component2 = vnode.type; const renderedNode = Component2(vnode.props || {}); return renderNodeToString(renderedNode); } if (typeof vnode.type === "string") { const tag = vnode.type; let attrs = ""; let children = ""; if (vnode.props) { for (const [key, value] of Object.entries(vnode.props)) { if (key === "children") continue; if (key.startsWith("on")) continue; if (key === "className") { attrs += ` class="${escapeHtml(value)}"`; continue; } if (typeof value === "string" || typeof value === "number") { attrs += ` ${key}="${escapeHtml(String(value))}"`; } else if (value === true) { attrs += ` ${key}`; } } } const childrenArray = ((_a = vnode.props) == null ? void 0 : _a.children) ? Array.isArray(vnode.props.children) ? vnode.props.children : [vnode.props.children] : []; for (const child of childrenArray) { children += renderNodeToString(child); } const selfClosing = [ "area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr" ]; if (selfClosing.includes(tag)) { return `<${tag}${attrs}/>`; } return `<${tag}${attrs}>${children}</${tag}>`; } if (vnode.type === Symbol.for("react.fragment")) { let fragmentOutput = ""; const children = Array.isArray((_b = vnode.props) == null ? void 0 : _b.children) ? vnode.props.children : ((_c = vnode.props) == null ? void 0 : _c.children) ? [vnode.props.children] : []; for (const child of children) { fragmentOutput += renderNodeToString(child); } return fragmentOutput; } console.warn("Unknown vnode type:", vnode.type); return ""; } function escapeHtml(text) { return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;"); } var isBatching, queue, currentRender, states, stateIndices, effects, memos, refs, globalRenderCallback, globalContainer, currentElement, isServer, serverStates, Fragment, isHydrating, server; var init_dist = __esm({ "node_modules/frontend-hamroun/dist/index.mjs"() { isBatching = false; queue = []; currentRender = 0; states = /* @__PURE__ */ new Map(); stateIndices = /* @__PURE__ */ new Map(); effects = /* @__PURE__ */ new Map(); memos = /* @__PURE__ */ new Map(); refs = /* @__PURE__ */ new Map(); globalRenderCallback = null; globalContainer = null; currentElement = null; isServer = typeof window === "undefined"; serverStates = /* @__PURE__ */ new Map(); Fragment = ({ children }) => children; isHydrating = false; server = { async getServer() { throw new Error("Server module can only be used in Node.js environment"); } }; } }); // src/server/database.ts var Database; var init_database = __esm({ "src/server/database.ts"() { "use strict"; Database = class { constructor(config) { this.mongoClient = null; this.mongoDb = null; this.mysqlPool = null; this.pgPool = null; this.config = config; } async connect() { switch (this.config.type) { case "mongodb": await this.connectMongo(); break; case "mysql": await this.connectMysql(); break; case "postgres": await this.connectPostgres(); break; default: throw new Error(`Unsupported database type: ${this.config.type}`); } } async connectMongo() { try { const { MongoClient } = await import("mongodb"); this.mongoClient = new MongoClient(this.config.url); await this.mongoClient.connect(); this.mongoDb = this.mongoClient.db(); console.log("Connected to MongoDB"); } catch (error) { if (error.code === "MODULE_NOT_FOUND") { throw new Error("MongoDB driver not installed. Run: npm install mongodb"); } console.error("MongoDB connection error:", error); throw error; } } async connectMysql() { try { const mysql = await import("mysql2/promise"); this.mysqlPool = mysql.createPool(this.config.url); await this.mysqlPool.getConnection(); console.log("Connected to MySQL"); } catch (error) { if (error.code === "MODULE_NOT_FOUND") { throw new Error("MySQL driver not installed. Run: npm install mysql2"); } console.error("MySQL connection error:", error); throw error; } } async connectPostgres() { try { const pg = await import("pg"); this.pgPool = new pg.Pool({ connectionString: this.config.url }); const client = await this.pgPool.connect(); client.release(); console.log("Connected to PostgreSQL"); } catch (error) { if (error.code === "MODULE_NOT_FOUND") { throw new Error("PostgreSQL driver not installed. Run: npm install pg @types/pg"); } console.error("PostgreSQL connection error:", error); throw error; } } async disconnect() { if (this.mongoClient) { await this.mongoClient.close(); this.mongoClient = null; this.mongoDb = null; } if (this.mysqlPool) { await this.mysqlPool.end(); this.mysqlPool = null; } if (this.pgPool) { await this.pgPool.end(); this.pgPool = null; } } // Database-specific methods getMongoDb() { return this.mongoDb; } getMysqlPool() { return this.mysqlPool; } getPgPool() { return this.pgPool; } // Generic query method async query(sql, values) { switch (this.config.type) { case "mongodb": throw new Error("For MongoDB, use getMongoDb() instead of query()"); case "mysql": if (!this.mysqlPool) throw new Error("MySQL not connected"); const [rows] = await this.mysqlPool.execute(sql, values || []); return rows; case "postgres": if (!this.pgPool) throw new Error("PostgreSQL not connected"); const result = await this.pgPool.query(sql, values || []); return result.rows; default: throw new Error(`Unsupported database type: ${this.config.type}`); } } }; } }); // src/server/auth.ts var AuthService; var init_auth = __esm({ "src/server/auth.ts"() { "use strict"; AuthService = class { constructor(config) { this.config = { expiresIn: "24h", ...config }; } async hashPassword(password) { try { const bcrypt = await import("bcryptjs"); return bcrypt.hash(password, 10); } catch (error) { if (error.code === "MODULE_NOT_FOUND") { throw new Error("bcryptjs not installed. Run: npm install bcryptjs @types/bcryptjs"); } throw error; } } async comparePasswords(password, hashedPassword) { try { const bcrypt = await import("bcryptjs"); return bcrypt.compare(password, hashedPassword); } catch (error) { if (error.code === "MODULE_NOT_FOUND") { throw new Error("bcryptjs not installed. Run: npm install bcryptjs @types/bcryptjs"); } throw error; } } generateToken(user) { try { const jwt = __require("jsonwebtoken"); const options = {}; if (this.config.expiresIn) { options.expiresIn = this.config.expiresIn; } return jwt.sign( { id: user.id, username: user.username, roles: user.roles || [] }, this.config.secret, options ); } catch (error) { if (error.code === "MODULE_NOT_FOUND") { throw new Error("jsonwebtoken not installed. Run: npm install jsonwebtoken @types/jsonwebtoken"); } throw error; } } verifyToken(token) { try { const jwt = __require("jsonwebtoken"); return jwt.verify(token, this.config.secret); } catch (error) { if (error.code === "MODULE_NOT_FOUND") { throw new Error("jsonwebtoken not installed. Run: npm install jsonwebtoken @types/jsonwebtoken"); } return null; } } // Express middleware for authentication initialize() { return (req, res, next) => { const token = this.extractToken(req); if (token) { const decoded = this.verifyToken(token); if (decoded) { req.user = decoded; } } next(); }; } // Express middleware for requiring authentication requireAuth() { return (req, res, next) => { if (!req.user) { return res.status(401).json({ message: "Unauthorized" }); } return next(); }; } // Express middleware for requiring specific roles requireRoles(roles) { return (req, res, next) => { if (!req.user) { return res.status(401).json({ message: "Unauthorized" }); } const userRoles = req.user.roles || []; const hasRequiredRole = roles.some((role) => userRoles.includes(role)); if (!hasRequiredRole) { return res.status(403).json({ message: "Forbidden" }); } return next(); }; } extractToken(req) { if (req.headers.authorization && req.headers.authorization.startsWith("Bearer ")) { return req.headers.authorization.substring(7); } return null; } }; } }); // src/server/api-router.ts import path from "path"; import fs from "fs"; import { pathToFileURL } from "url"; var ApiRouter; var init_api_router = __esm({ "src/server/api-router.ts"() { "use strict"; ApiRouter = class { constructor(apiDir, auth = null) { this.router = null; this.initialized = false; this.apiDir = path.resolve(process.cwd(), apiDir); this.auth = auth; } async initialize() { if (this.initialized && this.router) return; try { const express = await import("express"); this.router = express.default.Router(); this.setupRoutes(); this.initialized = true; console.log("\u2705 API Router initialized successfully"); } catch (error) { console.error("\u274C Failed to initialize API Router:", error); if (error.code === "MODULE_NOT_FOUND") { throw new Error("Express not installed. Run: npm install express @types/express"); } throw error; } } isInitialized() { return this.initialized && this.router !== null; } setupRoutes() { if (!fs.existsSync(this.apiDir)) { console.log(`API directory not found: ${this.apiDir}`); return; } this.scanDirectory(this.apiDir, ""); } scanDirectory(dirPath, routePrefix) { const entries = fs.readdirSync(dirPath, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dirPath, entry.name); if (entry.isDirectory()) { this.scanDirectory(fullPath, `${routePrefix}/${entry.name}`); } else if (this.isRouteFile(entry.name)) { const routePath = this.getRoutePath(entry.name, routePrefix); this.registerRoute(fullPath, routePath); } } } isRouteFile(filename) { return filename.endsWith(".js") || filename.endsWith(".ts") || filename.endsWith(".mjs"); } getRoutePath(filename, routePrefix) { const baseName = path.basename(filename, path.extname(filename)); if (baseName === "index") { return routePrefix || "/"; } const paramMatch = baseName.match(/^\[(.+)\]$/); if (paramMatch) { return `${routePrefix}/:${paramMatch[1]}`; } return `${routePrefix}/${baseName}`; } async registerRoute(filePath, routePath) { try { const absolutePath = path.isAbsolute(filePath) ? filePath : path.resolve(filePath); const fileUrl = pathToFileURL(absolutePath).href; const urlWithTimestamp = `${fileUrl}?t=${Date.now()}`; const routeModule = await import(urlWithTimestamp); if (!this.isValidRouteModule(routeModule)) { console.warn(`Invalid route module: ${filePath}`); return; } console.log(`Registering API route: ${routePath}`); const middleware = routeModule.middleware || []; for (const method of ["get", "post", "put", "delete", "patch", "options"]) { const handler = routeModule[method]; if (typeof handler === "function") { const routerMethod = this.router[method]; routerMethod.call( this.router, routePath, ...middleware, this.wrapHandler(handler) ); } } } catch (error) { console.error(`Error registering route (${filePath}):`, error); } } isValidRouteModule(module) { if (!module) return false; return ["get", "post", "put", "delete", "patch", "options"].some((method) => typeof module[method] === "function"); } wrapHandler(handler) { return async (req, res, next) => { try { await handler(req, res, next); } catch (error) { next(error); } }; } }; } }); // src/server/middleware.ts function rateLimit(options) { const requests = /* @__PURE__ */ new Map(); return (req, res, next) => { const ip = req.ip || req.socket.remoteAddress || "unknown"; const now = Date.now(); const reqTimes = (requests.get(ip) || []).filter((time) => now - time < options.windowMs); reqTimes.push(now); requests.set(ip, reqTimes); if (reqTimes.length > options.max) { return res.status(429).json({ error: { message: "Too Many Requests", retryAfter: Math.ceil(options.windowMs / 1e3) } }); } return next(); }; } var requestLogger, errorHandler, notFoundHandler; var init_middleware = __esm({ "src/server/middleware.ts"() { "use strict"; requestLogger = (req, res, next) => { console.log(`${(/* @__PURE__ */ new Date()).toISOString()} - ${req.method} ${req.url}`); next(); }; errorHandler = (err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: { message: "Internal Server Error", ...process.env.NODE_ENV !== "production" ? { details: err.message, stack: err.stack } : {} } }); }; notFoundHandler = (req, res) => { res.status(404).json({ error: { message: `Not Found - ${req.method} ${req.url}` } }); }; } }); // src/server/utils.ts var utils_exports = {}; __export(utils_exports, { ensureDirectory: () => ensureDirectory, generateToken: () => generateToken, getEnvironmentInfo: () => getEnvironmentInfo, getPagination: () => getPagination, hashString: () => hashString, isDirectoryEmpty: () => isDirectoryEmpty, readJsonFile: () => readJsonFile, safeJsonParse: () => safeJsonParse, sendError: () => sendError, sendSuccess: () => sendSuccess, validateFields: () => validateFields, validateFileUpload: () => validateFileUpload, writeJsonFile: () => writeJsonFile }); import crypto2 from "crypto"; import fs2 from "fs/promises"; import path2 from "path"; function safeJsonParse(json, fallback) { try { return JSON.parse(json); } catch (error) { return fallback; } } function generateToken(length = 32) { return crypto2.randomBytes(length).toString("hex"); } function hashString(input, salt = "") { return crypto2.createHash("sha256").update(input + salt).digest("hex"); } function getPagination(req) { const page = Math.max(1, parseInt(req.query.page) || 1); const rawLimit = parseInt(req.query.limit); let limit; if (isNaN(rawLimit) || rawLimit <= 0) { limit = 20; } else { limit = Math.max(1, Math.min(100, rawLimit)); } const skip = (page - 1) * limit; return { page, limit, skip }; } function sendSuccess(res, data, message = "Success") { return res.json({ success: true, message, data }); } function sendError(res, message = "An error occurred", statusCode = 400, errors) { return res.status(statusCode).json({ success: false, message, errors: errors || void 0 }); } function validateFields(req, requiredFields) { const missing = requiredFields.filter((field) => { const value = req.body[field]; return value === void 0 || value === null || value === ""; }); return { valid: missing.length === 0, missing }; } function validateFileUpload(file, options = {}) { if (!file) { return { valid: false, error: "No file provided" }; } if (options.maxSize && file.size > options.maxSize) { return { valid: false, error: `File too large. Maximum size allowed is ${options.maxSize / 1024 / 1024}MB` }; } if (options.allowedTypes && options.allowedTypes.length > 0) { const fileType = file.mimetype; if (!options.allowedTypes.includes(fileType)) { return { valid: false, error: `Invalid file type. Allowed types: ${options.allowedTypes.join(", ")}` }; } } return { valid: true }; } function getEnvironmentInfo() { return { nodeVersion: process.version, platform: process.platform, arch: process.arch, memory: process.memoryUsage(), uptime: process.uptime(), env: process.env.NODE_ENV || "development" }; } async function isDirectoryEmpty(dirPath) { try { const files = await fs2.readdir(dirPath); return files.length === 0; } catch (error) { return true; } } async function ensureDirectory(dirPath) { try { await fs2.access(dirPath); } catch (error) { await fs2.mkdir(dirPath, { recursive: true }); } } async function writeJsonFile(filePath, data) { await ensureDirectory(path2.dirname(filePath)); await fs2.writeFile(filePath, JSON.stringify(data, null, 2), "utf8"); } async function readJsonFile(filePath, defaultValue) { try { const data = await fs2.readFile(filePath, "utf8"); return safeJsonParse(data, defaultValue); } catch (error) { return defaultValue; } } var init_utils = __esm({ "src/server/utils.ts"() { "use strict"; } }); // src/server/templates.ts var templates_exports = {}; __export(templates_exports, { generateDocument: () => generateDocument, generateErrorPage: () => generateErrorPage, generateLoadingPage: () => generateLoadingPage }); function generateDocument(content, options = {}) { const { title = "Frontend Hamroun App", description = "", lang = "en", charset = "UTF-8", viewport = "width=device-width, initial-scale=1.0", scripts = [], styles = [], meta = {}, bodyClasses = "", htmlAttrs = {}, bodyAttrs = {}, initialData = {}, componentName = "" } = options; const htmlAttributes = Object.entries(htmlAttrs).map(([key, value]) => `${key}="${escapeHtml2(value)}"`).join(" "); const bodyAttributes = Object.entries(bodyAttrs).map(([key, value]) => `${key}="${escapeHtml2(value)}"`).join(" "); const metaTags = [ `<meta charset="${charset}">`, `<meta name="viewport" content="${viewport}">`, description ? `<meta name="description" content="${escapeHtml2(description)}">` : "" ]; Object.entries(meta).forEach(([name, content2]) => { metaTags.push(`<meta name="${escapeHtml2(name)}" content="${escapeHtml2(content2)}">`); }); const scriptTags = scripts.map((src) => { if (src.startsWith("<script")) { return src; } return `<script src="${escapeHtml2(src)}" ${src.endsWith(".js") ? 'type="module"' : ""} defer></script>`; }); const styleTags = styles.map((href) => { if (href.startsWith("<style")) { return href; } return `<link rel="stylesheet" href="${escapeHtml2(href)}">`; }); const initialDataScript = Object.keys(initialData).length > 0 ? `<script id="__APP_DATA__" type="application/json">${escapeHtml2(JSON.stringify(initialData))}</script>` : ""; return `<!DOCTYPE html> <html lang="${lang}" ${htmlAttributes}> <head> ${metaTags.filter(Boolean).join("\n ")} <title>${escapeHtml2(title)}</title> ${styleTags.join("\n ")} </head> <body class="${bodyClasses}" ${bodyAttributes}> <div id="app-root" data-ssr-root${componentName ? ` data-component="${escapeHtml2(componentName)}"` : ""}>${content}</div> ${initialDataScript} ${scriptTags.join("\n ")} </body> </html>`; } function generateErrorPage(statusCode, message, error) { const errorMessages = { 400: "Bad Request", 401: "Unauthorized", 403: "Forbidden", 404: "Not Found", 500: "Internal Server Error" }; const title = `${statusCode} - ${errorMessages[statusCode] || "Error"}`; const isDev = process.env.NODE_ENV !== "production"; const errorDetails = isDev && error ? ` <div class="error-details"> <pre>${escapeHtml2(error.stack || error.message)}</pre> </div> ` : ""; const content = ` <div class="error-container"> <h1>${statusCode}</h1> <h2>${escapeHtml2(errorMessages[statusCode] || "Error")}</h2> <p>${escapeHtml2(message)}</p> ${errorDetails} <a href="/" class="home-link">Back to Home</a> </div> `; const styles = [`<style> body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background-color: #f7f7f7; color: #333; } .error-container { text-align: center; padding: 2rem; border-radius: 8px; background-color: white; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); max-width: 600px; width: 100%; } h1 { font-size: 6rem; margin: 0; color: #e74c3c; } h2 { margin-top: 0; margin-bottom: 1rem; color: #333; } .error-details { text-align: left; margin: 2rem 0; padding: 1rem; background-color: #f8f8f8; border-radius: 4px; overflow: auto; } pre { margin: 0; font-family: monospace; font-size: 0.85rem; white-space: pre-wrap; } .home-link { display: inline-block; margin-top: 1.5rem; padding: 0.75rem 1.5rem; background-color: #3498db; color: white; text-decoration: none; border-radius: 4px; transition: background-color 0.2s; } .home-link:hover { background-color: #2980b9; } </style>`]; return generateDocument(content, { title, description: `Error ${statusCode}: ${errorMessages[statusCode] || "Error"}`, bodyClasses: "error-page", styles }); } function generateLoadingPage(message = "Loading...") { const content = ` <div class="loading-container"> <div class="spinner"></div> <p>${escapeHtml2(message)}</p> </div> `; const styles = [`<style> body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; background-color: #f7f7f7; color: #333; } .loading-container { text-align: center; } .spinner { width: 50px; height: 50px; border: 5px solid rgba(0, 0, 0, 0.1); border-radius: 50%; border-top-color: #3498db; animation: spin 1s ease-in-out infinite; margin: 0 auto 20px; } @keyframes spin { to { transform: rotate(360deg); } } </style>`]; return generateDocument(content, { title: "Loading", bodyClasses: "loading-page", styles }); } function escapeHtml2(text) { return String(text).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;"); } var init_templates = __esm({ "src/server/templates.ts"() { "use strict"; } }); // src/server/wasm.ts import fs3 from "fs/promises"; import path3 from "path"; import { pathToFileURL as pathToFileURL2 } from "url"; async function initNodeWasm() { if (initialized) return; try { globalThis.TextEncoder = globalThis.TextEncoder || TextEncoder; globalThis.TextDecoder = globalThis.TextDecoder || TextDecoder; initialized = true; } catch (error) { console.error("[WASM] Failed to initialize Node.js WASM environment:", error); throw error; } } async function loadGoRuntime(goWasmPath) { if (typeof globalThis.Go === "function") { return globalThis.Go; } const possiblePaths = [ goWasmPath, "./wasm_exec.cjs", "./wasm_exec.js", "./public/wasm_exec.cjs", "./public/wasm_exec.js", "./src/wasm_exec.cjs", "./src/wasm_exec.js", path3.join(process.cwd(), "wasm_exec.cjs"), path3.join(process.cwd(), "wasm_exec.js"), path3.join(process.cwd(), "public", "wasm_exec.cjs"), path3.join(process.cwd(), "public", "wasm_exec.js"), path3.join(process.cwd(), "src", "wasm_exec.cjs"), path3.join(process.cwd(), "src", "wasm_exec.js") ].filter(Boolean); for (const wasmExecPath of possiblePaths) { try { const resolvedPath = path3.resolve(wasmExecPath); try { const stats = await fs3.stat(resolvedPath); if (!stats.isFile()) { continue; } } catch (statError) { continue; } const wasmExecUrl = pathToFileURL2(resolvedPath).href; if (globalThis.Go) { delete globalThis.Go; } await import(wasmExecUrl); if (typeof globalThis.Go === "function") { console.log(`[WASM] Loaded Go runtime from: ${resolvedPath}`); return globalThis.Go; } else { console.warn(`[WASM] File found but Go class not exported: ${resolvedPath}`); } } catch (error) { console.warn(`[WASM] Error loading from ${wasmExecPath}:`, error.message); continue; } } throw new Error( `[WASM] Could not find wasm_exec.js. Please ensure you have the Go WASM runtime file available. You can get it from: https://github.com/golang/go/blob/master/misc/wasm/wasm_exec.js Searched paths: ${possiblePaths.join(", ")}` ); } async function loadGoWasmFromFile(wasmFilePath, options = {}) { try { await initNodeWasm(); if (options.debug) { console.log("[WASM] Loading WASM from file:", wasmFilePath); } const GoRuntime = await loadGoRuntime(options.goWasmPath); const go = new GoRuntime(); const wasmBuffer = await fs3.readFile(wasmFilePath); const wasmModule = await WebAssembly.compile(wasmBuffer); const baseImports = go.importObject; const finalImportObject = { ...baseImports, ...options.importObject }; if (options.debug) { console.log("[WASM] Available import modules:", Object.keys(finalImportObject)); for (const [moduleName, moduleExports] of Object.entries(finalImportObject)) { if (typeof moduleExports === "object" && moduleExports !== null) { const exportNames = Object.keys(moduleExports); console.log(`[WASM] ${moduleName} import functions:`, exportNames); } } } const instance = await WebAssembly.instantiate(wasmModule, finalImportObject); if (options.debug) { console.log("[WASM] WASM instance created, starting Go runtime..."); } const runPromise = go.run(instance); if (options.debug) { console.log("[WASM] Go runtime started, waiting for initialization..."); } await new Promise((resolve) => setTimeout(resolve, 2e3)); if (options.debug) { console.log("[WASM] Scanning global object for Go functions..."); } const functions = {}; const globalObj = globalThis; const allKeys = Object.getOwnPropertyNames(globalObj); const goKeys = allKeys.filter((key) => key.startsWith("go")); if (options.debug) { console.log('[WASM] All keys starting with "go":', goKeys); } for (const key of goKeys) { if (typeof globalObj[key] === "function") { functions[key] = globalObj[key]; if (options.debug) { console.log(`[WASM] Found function: ${key}`); } } } const wasmInstance = { instance, module: wasmModule, exports: instance.exports, functions }; if (options.onLoad) { options.onLoad(wasmInstance); } if (options.debug) { console.log(`[WASM] Module loaded successfully with ${Object.keys(functions).length} functions`); console.log("[WASM] Final function list:", Object.keys(functions)); } runPromise.catch((error) => { if (options.debug) { console.log("[WASM] Go program finished with error:", error); } }); return wasmInstance; } catch (error) { console.error("[WASM] Failed to load Go WASM module:", error); throw error; } } var initialized; var init_wasm = __esm({ "src/server/wasm.ts"() { "use strict"; initialized = false; } }); // src/server/index.ts var server_exports = {}; __export(server_exports, { ApiRouter: () => ApiRouter, AuthService: () => AuthService, Database: () => Database, Server: () => Server, createDevServer: () => createDevServer, createProductionServer: () => createProductionServer, createServer: () => createServer, default: () => server_default, ensureDirectory: () => ensureDirectory, errorHandler: () => errorHandler, generateDocument: () => generateDocument, generateErrorPage: () => generateErrorPage, generateLoadingPage: () => generateLoadingPage, generateToken: () => generateToken, getEnvironmentInfo: () => getEnvironmentInfo, getPagination: () => getPagination, getRequestIp: () => getRequestIp, hashString: () => hashString, initNodeWasm: () => initNodeWasm, isDirectoryEmpty: () => isDirectoryEmpty, loadGoWasmFromFile: () => loadGoWasmFromFile, notFoundHandler: () => notFoundHandler, parseCookies: () => parseCookies, rateLimit: () => rateLimit, readJsonFile: () => readJsonFile, renderComponent: () => renderComponent, renderToString: () => renderToString, requestLogger: () => requestLogger, safeJsonParse: () => safeJsonParse, sendError: () => sendError, sendSuccess: () => sendSuccess, validateFields: () => validateFields, validateFileUpload: () => validateFileUpload, writeJsonFile: () => writeJsonFile }); import path4 from "path"; import fs4 from "fs"; import { pathToFileURL as pathToFileURL3 } from "url"; function getComponentName(filePath, pagesDir) { try { const relativePath = path4.relative(pagesDir, filePath); const withoutExt = relativePath.replace(/\.[^/.]+$/, ""); const cleanPath = withoutExt.replace(/\/index$/, ""); return `/pages/${cleanPath}`; } catch (e) { return ""; } } function createServer(config = {}) { return new Server(config); } function createDevServer(options = {}) { return new Server({ port: options.port || 3e3, enableCors: options.enableCors !== false, apiDir: "./src/api", pagesDir: "./src/pages", staticDir: "./public" }); } function createProductionServer(config) { const server2 = new Server({ ...config, // Fix the PORT parsing port: config.port || (process.env.PORT ? parseInt(process.env.PORT) : 8080) }); server2.addShutdownHandler(); return server2; } function getRequestIp(req) { return req.ip || req.headers["x-forwarded-for"]?.split(",")[0].trim() || req.socket.remoteAddress || ""; } function parseCookies(req) { const cookies = {}; const cookieHeader = req.headers.cookie; if (cookieHeader) { cookieHeader.split(";").forEach((cookie) => { const [name, value] = cookie.split("=").map((c) => c.trim()); cookies[name] = value; }); } return cookies; } var Server, renderComponent, server_default; var init_server = __esm({ "src/server/index.ts"() { "use strict"; init_dist(); init_database(); init_auth(); init_api_router(); init_middleware(); init_utils(); init_templates(); init_wasm(); init_wasm(); init_utils(); init_templates(); init_database(); init_auth(); init_api_router(); init_middleware(); Server = class { constructor(config = {}) { this.server = null; this.db = null; this.auth = null; this.initialized = false; this.config = { port: 3e3, apiDir: "./api", pagesDir: "./pages", staticDir: "./public", enableCors: true, ...config }; } async initializeApp() { if (this.initialized) return; try { const express = await import("express"); this.app = express.default(); this.app.use(express.default.json()); this.app.use(express.default.urlencoded({ extended: true })); if (this.config.enableCors) { try { const cors = await import("cors"); this.app.use(cors.default(this.config.corsOptions)); } catch (error) { console.warn("CORS not available - install with: npm install cors @types/cors"); } } if (this.config.db) { this.db = new Database(this.config.db); } if (this.config.auth) { this.auth = new AuthService({ secret: this.config.auth.secret, expiresIn: this.config.auth.expiresIn }); this.app.use(this.auth.initialize()); } const staticPath = path4.resolve(process.cwd(), this.config.staticDir); if (fs4.existsSync(staticPath)) { this.app.use(express.default.static(staticPath)); } this.setupApiRoutes(); this.setupPageRoutes(); this.app.use(notFoundHandler); this.app.use(errorHandler); this.initialized = true; } catch (error) { if (error.code === "MODULE_NOT_FOUND" && error.message.includes("express")) { throw new Error("Express not installed. Run: npm install express @types/express"); } throw error; } } async setupApiRoutes() { const apiRouter = new ApiRouter(this.config.apiDir, this.auth); await apiRouter.initialize(); if (!apiRouter.isInitialized() || !apiRouter.router) { console.warn("\u26A0\uFE0F API router not initialized properly - skipping API routes"); return; } console.log("\u2705 Setting up API routes..."); this.app.use("/api", requestLogger, apiRouter.router); this.app.get("/api-docs", (req, res) => { const apiDocs = this.generateApiDocs(); res.json(apiDocs); }); } generateApiDocs() { const apiDir = path4.resolve(process.cwd(), this.config.apiDir); const docs = { endpoints: [] }; if (fs4.existsSync(apiDir)) { this.scanApiDirectory(apiDir, "", docs.endpoints); } return docs; } scanApiDirectory(dirPath, routePrefix, endpoints) { const entries = fs4.readdirSync(dirPath, { withFileTypes: true }); for (const entry of entries) { const fullPath = path4.join(dirPath, entry.name); if (entry.isDirectory()) { this.scanApiDirectory(fullPath, `${routePrefix}/${entry.name}`, endpoints); } else if (entry.name.endsWith(".js") || entry.name.endsWith(".ts")) { const routePath = this.getRoutePath(entry.name, routePrefix); endpoints.push({ path: routePath, file: path4.relative(process.cwd(), fullPath), methods: this.detectApiMethods(fullPath) }); } } } getRoutePath(filename, routePrefix) { const baseName = path4.basename(filename, path4.extname(filename)); if (baseName === "index") { return routePrefix || "/"; } const paramMatch = baseName.match(/^\[(.+)\]$/); if (paramMatch) { return `${routePrefix}/:${paramMatch[1]}`; } return `${routePrefix}/${baseName}`; } detectApiMethods(filePath) { try { const content = fs4.readFileSync(filePath, "utf8"); const methods = ["get", "post", "put", "delete", "patch", "options"]; return methods.filter( (method) => new RegExp(`export (async )?function ${method}\\s*\\(`).test(content) || new RegExp(`export const ${method}\\s*=`).test(content) ); } catch (error) { return []; } } setupPageRoutes() { const pagesPath = path4.resolve(process.cwd(), this.config.pagesDir); if (!fs4.existsSync(pagesPath)) { return; } this.app.get("*", async (req, res) => { try { const { html, statusCode } = await this.renderPage(req.path); res.status(statusCode || 200).send(html); } catch (error) { console.error("Error rendering page:", error); const errorHtml = generateErrorPage(500, "Server Error"); res.status(500).send(errorHtml); } }); } async renderPage(routePath) { try { const pagesDir = this.config.pagesDir ? path4.resolve(process.cwd(), this.config.pagesDir) : ""; if (!pagesDir || !fs4.existsSync(pagesDir)) { return { html: generateErrorPage(404, "Pages directory not found"), statusCode: 404 }; } let normalizedPath = routePath; if (!normalizedPath.startsWith("/")) { normalizedPath = "/" + normalizedPath; } if (normalizedPath === "/") { normalizedPath = "/index"; } let pagePath = ""; const possiblePaths = [ path4.join(pagesDir, `${normalizedPath}.js`), path4.join(pagesDir, `${normalizedPath}.ts`), path4.join(pagesDir, `${normalizedPath}.jsx`), path4.join(pagesDir, `${normalizedPath}.tsx`), path4.join(pagesDir, `${normalizedPath}/index.js`), path4.join(pagesDir, `${normalizedPath}/index.ts`), path4.join(pagesDir, `${normalizedPath}/index.jsx`), path4.join(pagesDir, `${normalizedPath}/index.tsx`) ]; for (const p of possiblePaths) { if (fs4.existsSync(p)) { pagePath = p; break; } } if (!pagePath) { return { html: generateErrorPage(404, `Page not found: ${normalizedPath}`), statusCode: 404 }; } try { const absolutePath = path4.isAbsolute(pagePath) ? pagePath : path4.resolve(pagePath); const fileUrl = pathToFileURL3(absolutePath).href; const urlWithTimestamp = `${fileUrl}?t=${Date.now()}`; const pageModule = await import(urlWithTimestamp); if (!pageModule || !pageModule.default) { throw new Error(`No default export found in ${pagePath}`); } const PageComponent = pageModule.default; const initial