frontend-hamroun 1.2.4 → 1.2.5

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.
@@ -1,2 +1,66 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("express"),require("path"),require("compression"),require("helmet"),require("morgan"),require("mongoose"),require("fs"),require("jsonwebtoken"),require("bcrypt")):"function"==typeof define&&define.amd?define(["exports","express","path","compression","helmet","morgan","mongoose","fs","jsonwebtoken","bcrypt"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["frontend-hamroun"]={},e.express,e.path,e.compression,e.helmet,e.morgan,e.mongoose,e.fs,e.jwt,e.bcrypt)}(this,(function(e,t,n,s,r,o,i,a,c,d){"use strict";const u="undefined"!=typeof window?window:"undefined"!=typeof global?global:{};function l(e,t,n){return{type:e,props:t||{},key:n}}function p(e,t,n){return l(e,t,n)}function h(e){if("string"==typeof e||"number"==typeof e)return document.createTextNode(String(e));if("function"==typeof e.type){return h(e.type(e.props))}const t=document.createElement(e.type);return Object.entries(e.props||{}).forEach((([e,n])=>{if("children"===e){(Array.isArray(n)?n:[n]).forEach((e=>{if(null!=e){const n=h(e);"test"===process.env.NODE_ENV&&"undefined"!=typeof window&&(u.__renderStats||(u.__renderStats={elementsCreated:0,textNodesCreated:0,eventsAttached:0,renderTime:0},"function"==typeof afterAll&&afterAll((()=>{try{const e=require("fs"),t=require("path").resolve(process.cwd(),"jsx-runtime-stats.json");e.writeFileSync(t,JSON.stringify(u.__renderStats,null,2)),console.log(`JSX runtime stats written to ${t}`)}catch(e){console.error("Failed to write stats file:",e)}}))),n instanceof Text?u.__renderStats.textNodesCreated++:u.__renderStats.elementsCreated++),t.appendChild(n)}}))}else if(e.startsWith("on")){const s=e.toLowerCase().substring(2);t.addEventListener(s,n),"test"===process.env.NODE_ENV&&"undefined"!=typeof window&&u.__renderStats&&u.__renderStats.eventsAttached++}else"className"===e?t.setAttribute("class",n):"style"===e&&"object"==typeof n?Object.entries(n).forEach((([e,n])=>{t.style[e]=String(n)})):t.setAttribute(e,n)})),t}const f=Symbol("Fragment");"undefined"!=typeof window&&(window.jsx=l,window.jsxs=p,window.Fragment=f);const y="undefined"!=typeof window&&"undefined"!=typeof document;async function m(e){var t;if(console.log("Creating element from:",e),!y){if(null==e)return{nodeType:3,textContent:""};if("boolean"==typeof e)return{nodeType:3,textContent:""};if("number"==typeof e||"string"==typeof e)return{nodeType:3,textContent:String(e)};if(Array.isArray(e)){const t={nodeType:11,childNodes:[]};for(const n of e){const e=await m(n);t.childNodes.push(e)}return t}if("type"in e&&void 0!==e.props){const{type:t,props:s}=e;if("function"==typeof t)try{const e=await t(s||{});return await m(e)}catch(n){return console.error("Error rendering component:",n),{nodeType:3,textContent:""}}const r={nodeType:1,tagName:t,attributes:{},style:{},childNodes:[],setAttribute:function(e,t){this.attributes[e]=t},appendChild:function(e){this.childNodes.push(e)}};for(const[e,n]of Object.entries(s||{}))if("children"!==e)if(e.startsWith("on")&&"function"==typeof n){const t=e.toLowerCase().slice(2);r.__events||(r.__events={}),r.__events[t]=n}else"style"===e&&"object"==typeof n?Object.assign(r.style,n):"className"===e?r.setAttribute("class",String(n)):"key"!==e&&"ref"!==e&&r.setAttribute(e,String(n));const o=null==s?void 0:s.children;if(null!=o){const e=Array.isArray(o)?o.flat():[o];for(const t of e){const e=await m(t);r.appendChild(e)}}return r}return{nodeType:3,textContent:String(e)}}if(null==e)return document.createTextNode("");if("boolean"==typeof e)return document.createTextNode("");if("number"==typeof e||"string"==typeof e)return document.createTextNode(String(e));if(Array.isArray(e)){const t=document.createDocumentFragment();for(const n of e){const e=await m(n);t.appendChild(e)}return t}if("type"in e&&void 0!==e.props){const{type:s,props:r}=e;if("function"==typeof s)try{const e=await s(r||{}),t=await m(e);return t instanceof Element&&t.setAttribute("data-component-id",s.name||s.toString()),t}catch(n){return console.error("Error rendering component:",n),document.createTextNode("")}const o=document.createElement(s);for(const[e,n]of Object.entries(r||{}))if("children"!==e)if(e.startsWith("on")&&"function"==typeof n){const s=e.toLowerCase().slice(2),r=null==(t=o.__events)?void 0:t[s];r&&o.removeEventListener(s,r),o.addEventListener(s,n),o.__events||(o.__events={}),o.__events[s]=n}else"style"===e&&"object"==typeof n?Object.assign(o.style,n):"className"===e?o.setAttribute("class",String(n)):"key"!==e&&"ref"!==e&&o.setAttribute(e,String(n));const i=null==r?void 0:r.children;if(null!=i){const e=Array.isArray(i)?i.flat():[i];for(const t of e){const e=await m(t);o.appendChild(e)}}return o}return document.createTextNode(String(e))}class g{constructor(e={}){this.state={},this.element=null,this._mounted=!1,this.props=e}componentDidMount(){}async setState(e){const t={...this.state};this.state={...t,...e},console.log(`${this.constructor.name} state updated:`,{prev:t,next:this.state}),await Promise.resolve(),this._mounted,await this.update()}_replayEvents(e,t){const n=e.__events||{};Object.entries(n).forEach((([e,n])=>{t.addEventListener(e,n)})),t.__events=n}_deepCloneWithEvents(e){const t=e.cloneNode(!1),n=e.__events||{};return t.__events=n,Object.entries(n).forEach((([e,n])=>{t.addEventListener(e,n)})),Array.from(e.childNodes).forEach((e=>{e instanceof HTMLElement?t.appendChild(this._deepCloneWithEvents(e)):t.appendChild(e.cloneNode(!0))})),t}async update(){const e=this.render();if(!e)return document.createTextNode("");const t=await m(e);if(t instanceof HTMLElement)return this._updateElement(t);const n=document.createElement("div");return n.appendChild(t),this._updateElement(n)}async _updateElement(e){const t=this._deepCloneWithEvents(e);return t.__instance=this,this.element?this.element.parentNode&&(this.element.parentNode.replaceChild(t,this.element),this.element=t):(this.element=t,this._mounted||(this._mounted=!0,queueMicrotask((()=>this.componentDidMount())))),this.element}render(){throw new Error("Component must implement render() method")}}let w=!1;const v=[];function b(e){if(w)v.push(e);else{w=!0;try{for(e();v.length>0;){const e=v.shift();null==e||e()}}finally{w=!1}}}let E=0;const k=new Map,S=new Map,T=new Map,x=new Map,A=new Map;let j=null,$=null,_=null;const C="undefined"==typeof window,I=new Map;function R(e,t,n){j=e,$=n,_=t}function N(){return E++,S.set(E,0),E}function O(){C&&I.delete(E),E=0}function q(e){if(!E)throw new Error("useState must be called within a render");if(C){I.has(E)||I.set(E,new Map);const t=I.get(E),n=S.get(E)||0;t.has(n)||t.set(n,e);const s=t.get(n),r=e=>{};return S.set(E,n+1),[s,r]}k.has(E)||k.set(E,[]);const t=k.get(E),n=S.get(E);n>=t.length&&t.push(e);const s=t[n];return S.set(E,n+1),[s,e=>{const s="function"==typeof e?e(t[n]):e;t[n]!==s&&(t[n]=s,w?b((()=>F(E))):F(E))}]}function D(e,t){if(!E)throw new Error("useEffect must be called within a render");const n=S.get(E);T.has(E)||T.set(E,[]);const s=T.get(E),r=s[n];r&&t&&r.deps&&!t.some(((e,t)=>e!==r.deps[t]))||((null==r?void 0:r.cleanup)&&r.cleanup(),queueMicrotask((()=>{const r=e()||void 0;s[n]={cleanup:r,deps:t}}))),S.set(E,n+1)}function P(e,t){if(!E)throw new Error("useMemo must be called within a render");const n=S.get(E);x.has(E)||x.set(E,[]);const s=x.get(E),r=s[n];if(!r||t&&t.some(((e,t)=>!Object.is(e,r.deps[t])))){const r=e();return s[n]={value:r,deps:t},S.set(E,n+1),r}return S.set(E,n+1),r.value}function M(e){if(!E)throw new Error("useRef must be called within a render");const t=S.get(E);A.has(E)||A.set(E,[]);const n=A.get(E);if(t>=n.length){const s={current:e};return n.push(s),S.set(E,t+1),s}const s=n[t];return S.set(E,t+1),s}async function F(e){try{const t=T.get(e);t&&(t.forEach((e=>{e.cleanup&&e.cleanup()})),T.set(e,[])),j&&$&&_&&await j(_,$)}catch(t){console.error("Error during rerender:",t)}}function L(){const[e,t]=q(null);return[e,()=>t(null)]}let B=!1;async function H(e,t){B=!0;try{await V(e,t)}finally{B=!1}}async function V(e,t){console.log("Rendering to:",t.id||"unnamed-container"),b((async()=>{N();try{R(V,e,t);const n=await m(e);B||(t.innerHTML=""),B&&t.firstChild?console.log("Hydrating existing DOM"):t.appendChild(n)}finally{O()}}))}async function W(e){N(),R((()=>{}),e,null);try{if(null==e)return"";if("boolean"==typeof e)return"";if("number"==typeof e||"string"==typeof e)return U(String(e));if(Array.isArray(e)){return(await Promise.all(e.map(W))).join("")}if("type"in e&&void 0!==e.props){const{type:s,props:r}=e;if("function"==typeof s)try{N();const e=await s(r||{}),t=await W(e);return O(),t}catch(n){return console.error("Error rendering component:",n),""}if(s===Symbol.for("react.fragment")||"Fragment"===s.name){if(r.children){const e=Array.isArray(r.children)?r.children:[r.children];return(await Promise.all(e.map(W))).join("")}return""}let o=`<${s}`;for(const[e,n]of Object.entries(r||{}))"children"!==e&&"key"!==e&&("className"===e?o+=` class="${U(String(n))}"`:"style"===e&&"object"==typeof n?o+=` style="${t=n||{},Object.entries(t).map((([e,t])=>{return`${n=e,n.replace(/[A-Z]/g,(e=>"-"+e.toLowerCase()))}:${t}`;var n})).join(";")}"`:e.startsWith("on")||(o+=` ${e}="${U(String(n))}"`));if(new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]).has(s))return o+"/>";if(o+=">",null==r?void 0:r.children){const e=Array.isArray(r.children)?r.children:[r.children];for(const t of e)o+=await W(t)}return o+`</${s}>`}return U(String(e))}finally{O()}var t}function U(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}class G{constructor(e){this.connection=null,this._connected=!1,this.options={retryAttempts:3,retryDelay:1e3,connectionTimeout:1e4,autoIndex:!0,...e}}async connect(){try{if(this._connected&&this.connection)return this.connection;i.set("strictQuery",!0);let t=0;for(;t<(this.options.retryAttempts||3);)try{await i.connect(this.options.uri,{dbName:this.options.name,connectTimeoutMS:this.options.connectionTimeout,autoIndex:this.options.autoIndex,...this.options.options});break}catch(e){if(t++,t>=(this.options.retryAttempts||3))throw e;console.log(`Connection attempt ${t} failed. Retrying in ${this.options.retryDelay}ms...`),await new Promise((e=>setTimeout(e,this.options.retryDelay)))}return this.connection=i.connection,this._connected=!0,console.log(`Connected to MongoDB at ${this.options.uri}/${this.options.name}`),this.connection.on("error",(e=>{console.error("MongoDB connection error:",e),this._connected=!1})),this.connection.on("disconnected",(()=>{console.log("MongoDB disconnected"),this._connected=!1})),this.connection}catch(e){throw console.error("Failed to connect to MongoDB:",e),e}}async disconnect(){this.connection&&(await i.disconnect(),this._connected=!1,this.connection=null,console.log("Disconnected from MongoDB"))}isConnected(){return this._connected}getConnection(){return this.connection}}function J(e={}){const i=t(),{port:c=3e3,staticDir:d="public",enableCors:u=!0,apiPrefix:l="/api",ssrEnabled:p=!0,middlewares:h=[],enableCompression:f=!0,enableHelmet:y=!0,logFormat:m="dev",trustProxy:g=!1,showErrorDetails:w="production"!==process.env.NODE_ENV}=e;if(g&&i.set("trust proxy",g),i.use(t.json()),i.use(t.urlencoded({extended:!0})),f&&i.use(s()),y&&i.use(r({contentSecurityPolicy:!e.disableCSP&&void 0})),m&&i.use(o(m)),u&&i.use(((e,t,n)=>{if(t.header("Access-Control-Allow-Origin","*"),t.header("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),t.header("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, Authorization"),"OPTIONS"===e.method)return t.sendStatus(200);n()})),h.forEach((e=>i.use(e))),d){const s=n.resolve(process.cwd(),d);a.existsSync(s)?(i.use(t.static(s,{maxAge:e.staticCacheAge||"1d",etag:!0})),console.log(`📂 Serving static files from: ${s}`)):console.warn(`⚠️ Static directory not found: ${s}`)}let v=null;i.connectToDatabase=async e=>{try{return v&&v.isConnected()?(console.log("✅ Using existing database connection"),v):(v=new G(e),await v.connect(),console.log("✅ Database connected successfully"),process.on("SIGTERM",(async()=>{v&&v.isConnected()&&(await v.disconnect(),console.log("Database connection closed"))})),v)}catch(t){throw console.error("❌ Failed to connect to database:",t),t}};const b={},E={};return i.registerApi=(e,t,s={})=>{try{const{prefix:r=l}=s,o=n.posix.join(r,e).replace(/\\/g,"/");i.use(o,t),b[o]={router:t,options:s},console.log(`🔌 API registered: ${o}`)}catch(r){console.error(`❌ Failed to register API at ${e}:`,r)}return i},i.registerSSR=(e,t,n={})=>p?(E[e]={component:t,options:n},i.get(e,(async(e,s,r)=>{try{if("true"===e.query.nossr)return r();const o={req:e,res:s,params:e.params,query:e.query,user:e.user,...n.props},i=await W(t(o));s.send(`\n <!DOCTYPE html>\n <html lang="${n.lang||"en"}">\n <head>\n <meta charset="UTF-8">\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <title>${n.title||"Frontend Hamroun App"}</title>\n ${n.meta?n.meta.map((e=>`<meta ${Object.entries(e).map((([e,t])=>`${e}="${t}"`)).join(" ")}>`)).join("\n "):""}\n ${n.head||""}\n ${n.styles?`<style>${n.styles}</style>`:""}\n ${n.styleSheets?n.styleSheets.map((e=>`<link rel="stylesheet" href="${e}">`)).join("\n "):""}\n </head>\n <body ${n.bodyAttributes||""}>\n <div id="${n.rootId||"root"}">${i}</div>\n <script>\n window.__INITIAL_DATA__ = ${JSON.stringify(n.initialData||{})};\n <\/script>\n ${n.scripts?n.scripts.map((e=>`<script src="${e}"><\/script>`)).join("\n "):""}\n </body>\n </html>\n `)}catch(o){if(console.error("SSR Error:",o),n.fallback)return r();s.status(500).send("Server rendering error")}})),console.log(`🖥️ SSR registered: ${e}`),i):(console.log(`⚠️ SSR disabled: skipping registration of ${e}`),i),i.use(((e,t,n,s)=>{console.error("Server error:",e);const r=e.statusCode||e.status||500;t.path.startsWith(l)?n.status(r).json({success:!1,error:w?e.message:"Internal Server Error",stack:w?e.stack:void 0}):n.status(r).send(`\n <!DOCTYPE html>\n <html>\n <head>\n <title>Error - ${r}</title>\n <style>\n body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }\n .error { background: #f8d7da; border: 1px solid #f5c6cb; padding: 1rem; border-radius: 4px; }\n .stack { background: #f8f9fa; padding: 1rem; border-radius: 4px; overflow: auto; }\n </style>\n </head>\n <body>\n <h1>Error ${r}</h1>\n <div class="error">${w?e.message:"Internal Server Error"}</div>\n ${w&&e.stack?`<pre class="stack">${e.stack}</pre>`:""}\n </body>\n </html>\n `)})),i.use(((e,t)=>{e.path.startsWith(l)?t.status(404).json({success:!1,error:"Not Found"}):t.status(404).send('\n <!DOCTYPE html>\n <html>\n <head>\n <title>404 - Not Found</title>\n <style>\n body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }\n </style>\n </head>\n <body>\n <h1>404 - Not Found</h1>\n <p>The requested resource was not found on this server.</p>\n <p><a href="/">Return to homepage</a></p>\n </body>\n </html>\n ')})),i.start=e=>{const t=i.listen(c,(()=>{console.log(`\n🚀 Frontend Hamroun server running at http://localhost:${c}\n${Object.keys(b).length>0?`\n📡 Registered API Routes:\n${Object.keys(b).map((e=>` ${e}`)).join("\n")}`:""}\n${Object.keys(E).length>0?`\n🖥️ Registered SSR Routes:\n${Object.keys(E).map((e=>` ${e}`)).join("\n")}`:""}\n `),e&&e()})),n=async e=>{console.log(`${e} signal received: closing HTTP server and cleaning up`),t.close((async()=>{console.log("HTTP server closed"),v&&v.isConnected()&&(await v.disconnect(),console.log("Database connection closed")),process.exit(0)})),setTimeout((()=>{console.error("Could not close connections in time, forcefully shutting down"),process.exit(1)}),1e4)};return process.on("SIGTERM",(()=>n("SIGTERM"))),process.on("SIGINT",(()=>n("SIGINT"))),t},i}const Y=(e,{res:t})=>{console.error("API Error:",e);const n=e.status||e.statusCode||500,s=e.message||"Internal server error";t.status(n).json({success:!1,error:s,stack:"production"!==process.env.NODE_ENV?e.stack:void 0})};function z(e,t,n,s,r){const o={success:e};return void 0!==t&&(o.data=t),n&&(o.message=n),s&&(o.error=s),r&&(o.meta=r),o}function X(e,t,n,s=200,r){e.status(s).json(z(!0,t,n,void 0,r))}function Q(e,t,n=400,s){const r=t instanceof Error?t.message:t;e.status(n).json(z(!1,void 0,void 0,r,s))}function Z(e){return{page:parseInt(e.query.page)||1,limit:parseInt(e.query.limit)||10,sort:e.query.sort||"createdAt",order:"asc"===e.query.order?"asc":"desc"}}function K(e,t,n){e.pagination=Z(e),n()}function ee(e={},n){const s=t.Router();return e.requireAuth&&n&&(s.use(n.authenticate),e.requiredRole&&s.use(n.hasRole(e.requiredRole))),e.rateLimit&&console.warn("Rate limiting is disabled: express-rate-limit dependency is not installed"),s}function te(e){return(t,n,s)=>{e(t,n,s).catch(s)}}const ne={};class se{constructor(e){if(this.loginAttempts=new Map,this.login=async(e,t)=>{try{const{username:n,password:s}=e.body,r=e.ip||e.connection.remoteAddress||"";if(!this.checkRateLimit(r))return void t.status(429).json({success:!1,message:"Too many login attempts. Please try again later."});if(!n||!s)return void t.status(400).json({success:!1,message:"Username and password are required"});if(!this.options.findUser)return void t.status(500).json({success:!1,message:"User finder function not configured"});const o=await this.options.findUser(n);if(!o)return void t.status(401).json({success:!1,message:"Invalid credentials"});if(!(await this.options.verifyPassword(s,o.password)))return void t.status(401).json({success:!1,message:"Invalid credentials"});const i={...o};delete i.password;const a=this.generateTokenPair({id:o.id||o._id,username:o.username,role:o.role||"user"});if(this.options.saveRefreshToken){const e=new Date;e.setSeconds(e.getSeconds()+this.getExpirationSeconds(this.options.refreshExpiration||"7d")),await this.options.saveRefreshToken(o.id||o._id,a.refreshToken,e)}e.body.useCookies&&this.setAuthCookies(t,a),t.json({success:!0,message:"Authentication successful",tokens:a,user:i})}catch(n){console.error("Authentication error:",n),t.status(500).json({success:!1,message:"Authentication failed",error:"production"!==process.env.NODE_ENV?n.message:void 0})}},this.refreshToken=async(e,t)=>{var n,s;try{const r=(null==(n=e.cookies)?void 0:n.refreshToken)||e.body.refreshToken;if(!r)return void t.status(401).json({success:!1,message:"Refresh token required"});const o=this.verifyToken(r,"refresh");if(this.options.verifyRefreshToken){if(!(await this.options.verifyRefreshToken(o.id,r)))return this.clearAuthCookies(t),void t.status(401).json({success:!1,message:"Invalid refresh token"})}const i=this.generateTokenPair({id:o.id,...this.options.findUser?await this.options.findUser(o.id):{}});if(this.options.saveRefreshToken){const e=new Date;e.setSeconds(e.getSeconds()+this.getExpirationSeconds(this.options.refreshExpiration||"7d")),await this.options.saveRefreshToken(o.id,i.refreshToken,e)}((null==(s=e.cookies)?void 0:s.accessToken)||e.body.useCookies)&&this.setAuthCookies(t,i),t.json({success:!0,message:"Token refreshed successfully",tokens:i})}catch(r){this.clearAuthCookies(t),t.status(401).json({success:!1,message:"Invalid or expired refresh token",error:"production"!==process.env.NODE_ENV?r.message:void 0})}},this.logout=async(e,t)=>{var n;try{this.clearAuthCookies(t);const r=(null==(n=e.cookies)?void 0:n.refreshToken)||e.body.refreshToken;if(r&&this.options.saveRefreshToken)try{const e=this.verifyToken(r,"refresh");"function"==typeof this.options.saveRefreshToken&&await this.options.saveRefreshToken(e.id,"",new Date)}catch(s){}t.json({success:!0,message:"Logged out successfully"})}catch(r){console.error("Logout error:",r),t.status(500).json({success:!1,message:"Logout failed",error:r.message})}},this.authenticate=(e,t,n)=>{var s;try{let r=null==(s=e.cookies)?void 0:s.accessToken;if(!r){const t=e.headers.authorization;t&&t.startsWith("Bearer ")&&(r=t.split(" ")[1])}if(!r)return void t.status(401).json({success:!1,message:"Authentication required"});const o=this.verifyToken(r,"access");e.user=o,n()}catch(r){t.status(401).json({success:!1,message:"Invalid or expired token",error:"production"!==process.env.NODE_ENV?r.message:void 0})}},this.hasRole=e=>(t,n,s)=>{const r=t.user;if(!r)return void n.status(401).json({success:!1,message:"Authentication required"});(Array.isArray(e)?e:[e]).includes(r.role)?s():n.status(403).json({success:!1,message:"Insufficient permissions"})},this.options={tokenExpiration:"15m",refreshExpiration:"7d",saltRounds:10,secureCookies:"production"===process.env.NODE_ENV,httpOnlyCookies:!0,rateLimit:!0,...e,refreshSecret:e.refreshSecret||e.jwtSecret},!e.jwtSecret)throw new Error("JWT secret is required for authentication");this.options.verifyPassword||(this.options.verifyPassword=this.verifyPasswordWithBcrypt)}async hashPassword(e){return await d.hash(e,this.options.saltRounds||10)}async verifyPasswordWithBcrypt(e,t){return await d.compare(e,t)}generateSecureToken(e=32){return ne.randomBytes(e).toString("hex")}generateTokenPair(e){const t=this.getExpirationSeconds(this.options.tokenExpiration||"15m");return{accessToken:c.sign({...e,type:"access"},this.options.jwtSecret,{expiresIn:this.options.tokenExpiration}),refreshToken:c.sign({id:e.id,type:"refresh"},this.options.refreshSecret,{expiresIn:this.options.refreshExpiration}),expiresIn:t}}getExpirationSeconds(e){const t=e.charAt(e.length-1),n=parseInt(e.slice(0,-1));switch(t){case"s":return n;case"m":return 60*n;case"h":return 60*n*60;case"d":return 60*n*60*24;default:return 3600}}verifyToken(e,t="access"){try{const n="access"===t?this.options.jwtSecret:this.options.refreshSecret,s=c.verify(e,n);if("object"==typeof s&&s.type!==t)throw new Error("Invalid token type");return s}catch(n){throw new Error("Invalid or expired token")}}setAuthCookies(e,t){e.cookie("accessToken",t.accessToken,{httpOnly:this.options.httpOnlyCookies,secure:this.options.secureCookies,domain:this.options.cookieDomain,sameSite:"strict",maxAge:1e3*t.expiresIn});const n=this.getExpirationSeconds(this.options.refreshExpiration||"7d");e.cookie("refreshToken",t.refreshToken,{httpOnly:!0,secure:this.options.secureCookies,domain:this.options.cookieDomain,sameSite:"strict",maxAge:1e3*n,path:"/api/auth/refresh"})}clearAuthCookies(e){e.clearCookie("accessToken"),e.clearCookie("refreshToken",{path:"/api/auth/refresh"})}checkRateLimit(e){if(!this.options.rateLimit)return!0;const t=Date.now(),n=this.loginAttempts.get(e);return n?t>n.resetTime?(this.loginAttempts.set(e,{count:1,resetTime:t+36e5}),!0):!(n.count>=5)&&(n.count++,this.loginAttempts.set(e,n),!0):(this.loginAttempts.set(e,{count:1,resetTime:t+36e5}),!0)}}const re={String:{type:String},Number:{type:Number},Boolean:{type:Boolean},Date:{type:Date},ObjectId:{type:String},Required:e=>({...e,required:!0}),Unique:e=>({...e,unique:!0}),Ref:e=>({type:String,ref:e}),Enum:e=>({type:String,enum:e}),Default:(e,t)=>({...e,default:t}),Array:e=>({type:[e]})},oe={jsx:l,jsxs:p,createElement:h,Fragment:f,Component:g,useState:q,useEffect:D,useRef:M,useMemo:P,useErrorBoundary:L,render:V,hydrate:H,renderToString:W,prepareRender:N,finishRender:O,batchUpdates:b,createServer:J,Router:t.Router,createApiRouter:ee};Object.defineProperty(e,"Router",{enumerable:!0,get:()=>t.Router}),e.Component=g,e.DatabaseConnector=G,e.FieldTypes=re,e.Fragment=f,e.apiResponse=z,e.asyncHandler=te,e.batchUpdates=b,e.createApiRouter=ee,e.createAuth=function(e){return new se(e)},e.createCustomRouter=function(e,n={}){const s=t.Router(),{middleware:r=[],errorHandler:o=Y}=n;return r.forEach((e=>s.use(e))),Object.entries(e).forEach((([e,t])=>{const{method:n,handler:r}=t;s[n](e,(e=>async(t,n,s)=>{try{const r={req:t,res:n,next:s,params:t.params,query:t.query,body:t.body};if(n.headersSent)return;return await e(r)}catch(r){if(n.headersSent)return void console.error("Error occurred after response was sent:",r);const e={req:t,res:n,next:s,params:t.params,query:t.query,body:t.body};return o(r,e)}})(r))})),s},e.createElement=h,e.createModel=function(e,t){const n=i.model(e,t);return{getAll:async t=>{try{const{page:e=1,limit:s=10,sort:r="_id",order:o="desc"}=t||{},i=(e-1)*s,a="asc"===o?1:-1,c={[r]:a},[d,u]=await Promise.all([n.find().sort(c).skip(i).limit(s).exec(),n.countDocuments().exec()]),l=Math.ceil(u/s);return{data:d,pagination:{total:u,totalPages:l,currentPage:e,limit:s,hasNextPage:e<l,hasPrevPage:e>1}}}catch(s){throw console.error(`Error in ${e}.getAll:`,s),new Error(`Failed to retrieve ${e} records: ${s.message}`)}},getById:async t=>{try{return i.isValidObjectId(t)?await n.findById(t).exec():null}catch(s){throw console.error(`Error in ${e}.getById:`,s),new Error(`Failed to retrieve ${e} by ID: ${s.message}`)}},create:async t=>{try{const e=new n(t);return await e.save()}catch(s){throw console.error(`Error in ${e}.create:`,s),new Error(`Failed to create ${e}: ${s.message}`)}},createMany:async t=>{try{return await n.insertMany(t)}catch(s){throw console.error(`Error in ${e}.createMany:`,s),new Error(`Failed to create multiple ${e} records: ${s.message}`)}},update:async(t,s)=>{try{return i.isValidObjectId(t)?await n.findByIdAndUpdate(t,{$set:s},{new:!0,runValidators:!0}).exec():null}catch(r){throw console.error(`Error in ${e}.update:`,r),new Error(`Failed to update ${e}: ${r.message}`)}},delete:async t=>{try{if(!i.isValidObjectId(t))return!1;return null!==await n.findByIdAndDelete(t).exec()}catch(s){throw console.error(`Error in ${e}.delete:`,s),new Error(`Failed to delete ${e}: ${s.message}`)}},find:async(t,s)=>{try{const{page:e=1,limit:r=10,sort:o="_id",order:i="desc"}=s||{},a=(e-1)*r,c="asc"===i?1:-1,d={[o]:c},[u,l]=await Promise.all([n.find(t).sort(d).skip(a).limit(r).exec(),n.countDocuments(t).exec()]),p=Math.ceil(l/r);return{data:u,pagination:{total:l,totalPages:p,currentPage:e,limit:r,hasNextPage:e<p,hasPrevPage:e>1}}}catch(r){throw console.error(`Error in ${e}.find:`,r),new Error(`Failed to find ${e} records: ${r.message}`)}},count:async t=>{try{return await n.countDocuments(t||{}).exec()}catch(s){throw console.error(`Error in ${e}.count:`,s),new Error(`Failed to count ${e} records: ${s.message}`)}},findOne:async t=>{try{return await n.findOne(t).exec()}catch(s){throw console.error(`Error in ${e}.findOne:`,s),new Error(`Failed to find ${e} record: ${s.message}`)}}}},e.createModelRouter=function(e,n={}){const s=t.Router(),{middleware:r=[],errorHandler:o=Y}=n;r.forEach((e=>s.use(e)));const i=e=>async(t,n,s)=>{try{const r={req:t,res:n,next:s,params:t.params,query:t.query,body:t.body};return await e(r)}catch(r){const e={req:t,res:n,next:s,params:t.params,query:t.query,body:t.body};return o(r,e)}};return s.get("/",i((async({req:t,res:n})=>{const s=t.pagination||{page:1,limit:10},r=await e.getAll(s);n.json({success:!0,...r})}))),s.get("/:id",i((async({params:t,res:n})=>{const s=await e.getById(t.id);s?n.json({success:!0,data:s}):n.status(404).json({success:!1,error:"Item not found"})}))),s.post("/",i((async({body:t,res:n})=>{const s=await e.create(t);n.status(201).json({success:!0,data:s,message:"Item created successfully"})}))),s.put("/:id",i((async({params:t,body:n,res:s})=>{const r=await e.update(t.id,n);r?s.json({success:!0,data:r,message:"Item updated successfully"}):s.status(404).json({success:!1,error:"Item not found"})}))),s.delete("/:id",i((async({params:t,res:n})=>{await e.delete(t.id)?n.json({success:!0,message:"Item deleted successfully"}):n.status(404).json({success:!1,error:"Item not found"})}))),s},e.createRestEndpoints=function(e){const n=t.Router();return n.get("/",K,te((async(t,n)=>{X(n,await e.getAll(t.pagination))}))),n.get("/:id",te((async(t,n)=>{const s=await e.getById(t.params.id);if(!s)return Q(n,"Item not found",404);X(n,s)}))),n.post("/",te((async(t,n)=>{X(n,await e.create(t.body),"Item created successfully",201)}))),n.put("/:id",te((async(t,n)=>{const s=await e.update(t.params.id,t.body);if(!s)return Q(n,"Item not found",404);X(n,s,"Item updated successfully")}))),n.delete("/:id",te((async(t,n)=>{if(!(await e.delete(t.params.id)))return Q(n,"Item not found",404);X(n,null,"Item deleted successfully")}))),n},e.createServer=J,e.default=oe,e.finishRender=O,e.getPaginationParams=Z,e.hydrate=H,e.jsx=l,e.jsxs=p,e.paginationMiddleware=K,e.prepareRender=N,e.render=V,e.renderToString=W,e.sendError=Q,e.sendSuccess=X,e.useEffect=D,e.useErrorBoundary=L,e.useMemo=P,e.useRef=M,e.useState=q,e.validateRequest=function(e){return(t,n,s)=>{try{const{error:r,value:o}=e.validate(t.body);if(r)return void Q(n,`Validation error: ${r.message}`,400);t.body=o,s()}catch(r){Q(n,"Validation error",400)}}},Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
2
- //# sourceMappingURL=frontend-hamroun.umd.js.map
1
+ (function(c,b){typeof exports=="object"&&typeof module<"u"?b(exports,require("express"),require("path"),require("compression"),require("helmet"),require("morgan"),require("mongoose"),require("fs"),require("jsonwebtoken"),require("bcrypt"),require("crypto")):typeof define=="function"&&define.amd?define(["exports","express","path","compression","helmet","morgan","mongoose","fs","jsonwebtoken","bcrypt","crypto"],b):(c=typeof globalThis<"u"?globalThis:c||self,b(c["frontend-hamroun"]={},c.express,c.path,c.compression,c.helmet,c.morgan,c.mongoose,c.fs,c.jwt,c.bcrypt,c.crypto))})(this,function(c,b,ye,Fe,Le,Be,_,He,Z,qe,Ve){"use strict";function We(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const e in r)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(r,e);Object.defineProperty(t,e,n.get?n:{enumerable:!0,get:()=>r[e]})}}return t.default=r,Object.freeze(t)}const me=We(qe),ge=globalThis||void 0||self;function Ue(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}var we={exports:{}},y=we.exports={},v,A;function K(){throw new Error("setTimeout has not been defined")}function ee(){throw new Error("clearTimeout has not been defined")}(function(){try{typeof setTimeout=="function"?v=setTimeout:v=K}catch{v=K}try{typeof clearTimeout=="function"?A=clearTimeout:A=ee}catch{A=ee}})();function Ee(r){if(v===setTimeout)return setTimeout(r,0);if((v===K||!v)&&setTimeout)return v=setTimeout,setTimeout(r,0);try{return v(r,0)}catch{try{return v.call(null,r,0)}catch{return v.call(this,r,0)}}}function Ge(r){if(A===clearTimeout)return clearTimeout(r);if((A===ee||!A)&&clearTimeout)return A=clearTimeout,clearTimeout(r);try{return A(r)}catch{try{return A.call(null,r)}catch{return A.call(this,r)}}}var j=[],P=!1,I,V=-1;function Je(){!P||!I||(P=!1,I.length?j=I.concat(j):V=-1,j.length&&be())}function be(){if(!P){var r=Ee(Je);P=!0;for(var t=j.length;t;){for(I=j,j=[];++V<t;)I&&I[V].run();V=-1,t=j.length}I=null,P=!1,Ge(r)}}y.nextTick=function(r){var t=new Array(arguments.length-1);if(arguments.length>1)for(var e=1;e<arguments.length;e++)t[e-1]=arguments[e];j.push(new Te(r,t)),j.length===1&&!P&&Ee(be)};function Te(r,t){this.fun=r,this.array=t}Te.prototype.run=function(){this.fun.apply(null,this.array)},y.title="browser",y.browser=!0,y.env={},y.argv=[],y.version="",y.versions={};function C(){}y.on=C,y.addListener=C,y.once=C,y.off=C,y.removeListener=C,y.removeAllListeners=C,y.emit=C,y.prependListener=C,y.prependOnceListener=C,y.listeners=function(r){return[]},y.binding=function(r){throw new Error("process.binding is not supported")},y.cwd=function(){return"/"},y.chdir=function(r){throw new Error("process.chdir is not supported")},y.umask=function(){return 0};var ze=we.exports;const E=Ue(ze),O=typeof window<"u"?window:typeof ge<"u"?ge:{};function W(r,t,e){return{type:r,props:t||{},key:e}}function te(r,t,e){return W(r,t,e)}function U(r){if(typeof r=="string"||typeof r=="number")return document.createTextNode(String(r));if(typeof r.type=="function"){const e=r.type(r.props);return U(e)}const t=document.createElement(r.type);return Object.entries(r.props||{}).forEach(([e,n])=>{if(e==="children")(Array.isArray(n)?n:[n]).forEach(i=>{if(i!=null){const o=U(i);E.env.NODE_ENV==="test"&&typeof window<"u"&&(O.__renderStats||(O.__renderStats={elementsCreated:0,textNodesCreated:0,eventsAttached:0,renderTime:0},typeof afterAll=="function"&&afterAll(()=>{try{const a=require("fs"),f=require("path").resolve(E.cwd(),"jsx-runtime-stats.json");a.writeFileSync(f,JSON.stringify(O.__renderStats,null,2)),console.log(`JSX runtime stats written to ${f}`)}catch(a){console.error("Failed to write stats file:",a)}})),o instanceof Text?O.__renderStats.textNodesCreated++:O.__renderStats.elementsCreated++),t.appendChild(o)}});else if(e.startsWith("on")){const s=e.toLowerCase().substring(2);t.addEventListener(s,n),E.env.NODE_ENV==="test"&&typeof window<"u"&&O.__renderStats&&O.__renderStats.eventsAttached++}else e==="className"?t.setAttribute("class",n):e==="style"&&typeof n=="object"?Object.entries(n).forEach(([s,i])=>{t.style[s]=String(i)}):t.setAttribute(e,n)}),t}const re=Symbol("Fragment");typeof window<"u"&&(window.jsx=W,window.jsxs=te,window.Fragment=re);const Qe=typeof window<"u"&&typeof document<"u";async function R(r){var t;if(console.log("Creating element from:",r),!Qe){if(r==null)return{nodeType:3,textContent:""};if(typeof r=="boolean")return{nodeType:3,textContent:""};if(typeof r=="number"||typeof r=="string")return{nodeType:3,textContent:String(r)};if(Array.isArray(r)){const e={nodeType:11,childNodes:[]};for(const n of r){const s=await R(n);e.childNodes.push(s)}return e}if("type"in r&&r.props!==void 0){const{type:e,props:n}=r;if(typeof e=="function")try{const o=await e(n||{});return await R(o)}catch(o){return console.error("Error rendering component:",o),{nodeType:3,textContent:""}}const s={nodeType:1,tagName:e,attributes:{},style:{},childNodes:[],setAttribute:function(o,a){this.attributes[o]=a},appendChild:function(o){this.childNodes.push(o)}};for(const[o,a]of Object.entries(n||{}))if(o!=="children")if(o.startsWith("on")&&typeof a=="function"){const u=o.toLowerCase().slice(2);s.__events||(s.__events={}),s.__events[u]=a}else o==="style"&&typeof a=="object"?Object.assign(s.style,a):o==="className"?s.setAttribute("class",String(a)):o!=="key"&&o!=="ref"&&s.setAttribute(o,String(a));const i=n==null?void 0:n.children;if(i!=null){const o=Array.isArray(i)?i.flat():[i];for(const a of o){const u=await R(a);s.appendChild(u)}}return s}return{nodeType:3,textContent:String(r)}}if(r==null||typeof r=="boolean")return document.createTextNode("");if(typeof r=="number"||typeof r=="string")return document.createTextNode(String(r));if(Array.isArray(r)){const e=document.createDocumentFragment();for(const n of r){const s=await R(n);e.appendChild(s)}return e}if("type"in r&&r.props!==void 0){const{type:e,props:n}=r;if(typeof e=="function")try{const o=await e(n||{}),a=await R(o);return a instanceof Element&&a.setAttribute("data-component-id",e.name||e.toString()),a}catch(o){return console.error("Error rendering component:",o),document.createTextNode("")}const s=document.createElement(e);for(const[o,a]of Object.entries(n||{}))if(o!=="children")if(o.startsWith("on")&&typeof a=="function"){const u=o.toLowerCase().slice(2),f=(t=s.__events)==null?void 0:t[u];f&&s.removeEventListener(u,f),s.addEventListener(u,a),s.__events||(s.__events={}),s.__events[u]=a}else o==="style"&&typeof a=="object"?Object.assign(s.style,a):o==="className"?s.setAttribute("class",String(a)):o!=="key"&&o!=="ref"&&s.setAttribute(o,String(a));const i=n==null?void 0:n.children;if(i!=null){const o=Array.isArray(i)?i.flat():[i];for(const a of o){const u=await R(a);s.appendChild(u)}}return s}return document.createTextNode(String(r))}class Se{constructor(t={}){this.state={},this.element=null,this._mounted=!1,this.props=t}componentDidMount(){}async setState(t){const e={...this.state};this.state={...e,...t},console.log(`${this.constructor.name} state updated:`,{prev:e,next:this.state}),await Promise.resolve(),this._mounted?await this.update():await this.update()}_replayEvents(t,e){const n=t.__events||{};Object.entries(n).forEach(([s,i])=>{e.addEventListener(s,i)}),e.__events=n}_deepCloneWithEvents(t){const e=t.cloneNode(!1),n=t.__events||{};return e.__events=n,Object.entries(n).forEach(([s,i])=>{e.addEventListener(s,i)}),Array.from(t.childNodes).forEach(s=>{s instanceof HTMLElement?e.appendChild(this._deepCloneWithEvents(s)):e.appendChild(s.cloneNode(!0))}),e}async update(){const t=this.render();if(!t)return document.createTextNode("");const e=await R(t);if(e instanceof HTMLElement)return this._updateElement(e);const n=document.createElement("div");return n.appendChild(e),this._updateElement(n)}async _updateElement(t){const e=this._deepCloneWithEvents(t);return e.__instance=this,this.element?this.element.parentNode&&(this.element.parentNode.replaceChild(e,this.element),this.element=e):(this.element=e,this._mounted||(this._mounted=!0,queueMicrotask(()=>this.componentDidMount()))),this.element}render(){throw new Error("Component must implement render() method")}}let G=!1;const ne=[];function J(r){if(G){ne.push(r);return}G=!0;try{for(r();ne.length>0;){const t=ne.shift();t==null||t()}}finally{G=!1}}let l=0;const se=new Map,S=new Map,L=new Map,oe=new Map,ie=new Map;let ae=null,ce=null,ue=null;const ke=typeof window>"u",z=new Map;function ve(r,t,e){ae=r,ce=e,ue=t}function B(){return l++,S.set(l,0),l}function H(){ke&&z.delete(l),l=0}function le(r){if(!l)throw new Error("useState must be called within a render");if(ke){z.has(l)||z.set(l,new Map);const i=z.get(l),o=S.get(l)||0;i.has(o)||i.set(o,r);const a=i.get(o),u=f=>{};return S.set(l,o+1),[a,u]}se.has(l)||se.set(l,[]);const t=se.get(l),e=S.get(l);e>=t.length&&t.push(r);const n=t[e],s=i=>{const o=typeof i=="function"?i(t[e]):i;t[e]!==o&&(t[e]=o,G?J(()=>$e(l)):$e(l))};return S.set(l,e+1),[n,s]}function Ae(r,t){if(!l)throw new Error("useEffect must be called within a render");const e=S.get(l);L.has(l)||L.set(l,[]);const n=L.get(l),s=n[e];(!s||!t||!s.deps||t.some((i,o)=>i!==s.deps[o]))&&(s!=null&&s.cleanup&&s.cleanup(),queueMicrotask(()=>{const i=r()||void 0;n[e]={cleanup:i,deps:t}})),S.set(l,e+1)}function je(r,t){if(!l)throw new Error("useMemo must be called within a render");const e=S.get(l);oe.has(l)||oe.set(l,[]);const n=oe.get(l),s=n[e];if(!s||t&&t.some((i,o)=>!Object.is(i,s.deps[o]))){const i=r();return n[e]={value:i,deps:t},S.set(l,e+1),i}return S.set(l,e+1),s.value}function Ce(r){if(!l)throw new Error("useRef must be called within a render");const t=S.get(l);ie.has(l)||ie.set(l,[]);const e=ie.get(l);if(t>=e.length){const s={current:r};return e.push(s),S.set(l,t+1),s}const n=e[t];return S.set(l,t+1),n}async function $e(r){try{const t=L.get(r);t&&(t.forEach(e=>{e.cleanup&&e.cleanup()}),L.set(r,[])),ae&&ce&&ue&&await ae(ue,ce)}catch(t){console.error("Error during rerender:",t)}}function _e(){const[r,t]=le(null);return[r,()=>t(null)]}let Q=!1;async function Re(r,t){Q=!0;try{await Y(r,t)}finally{Q=!1}}async function Y(r,t){console.log("Rendering to:",t.id||"unnamed-container"),J(async()=>{const e=B();try{ve(Y,r,t);const n=await R(r);Q||(t.innerHTML=""),Q&&t.firstChild?console.log("Hydrating existing DOM"):t.appendChild(n)}finally{H()}})}async function N(r){B(),ve(()=>{},r,null);try{if(r==null||typeof r=="boolean")return"";if(typeof r=="number"||typeof r=="string")return X(String(r));if(Array.isArray(r))return(await Promise.all(r.map(N))).join("");if("type"in r&&r.props!==void 0){const{type:t,props:e}=r;if(typeof t=="function")try{B();const i=await t(e||{}),o=await N(i);return H(),o}catch(i){return console.error("Error rendering component:",i),""}if(t===Symbol.for("react.fragment")||t.name==="Fragment"){if(e.children){const i=Array.isArray(e.children)?e.children:[e.children];return(await Promise.all(i.map(N))).join("")}return""}let n=`<${t}`;for(const[i,o]of Object.entries(e||{}))i==="children"||i==="key"||(i==="className"?n+=` class="${X(String(o))}"`:i==="style"&&typeof o=="object"?n+=` style="${Ye(o||{})}"`:i.startsWith("on")||(n+=` ${i}="${X(String(o))}"`));if(new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]).has(t))return n+"/>";if(n+=">",e!=null&&e.children){const i=Array.isArray(e.children)?e.children:[e.children];for(const o of i)n+=await N(o)}return n+`</${t}>`}return X(String(r))}finally{H()}}function X(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function Ye(r){return Object.entries(r).map(([t,e])=>`${Xe(t)}:${e}`).join(";")}function Xe(r){return r.replace(/[A-Z]/g,t=>"-"+t.toLowerCase())}class Ie{constructor(t){this.connection=null,this._connected=!1,this.options={retryAttempts:3,retryDelay:1e3,connectionTimeout:1e4,autoIndex:!0,...t}}async connect(){try{if(this._connected&&this.connection)return this.connection;_.set("strictQuery",!0);let t=0;for(;t<(this.options.retryAttempts||3);)try{await _.connect(this.options.uri,{dbName:this.options.name,connectTimeoutMS:this.options.connectionTimeout,autoIndex:this.options.autoIndex,...this.options.options});break}catch(e){if(t++,t>=(this.options.retryAttempts||3))throw e;console.log(`Connection attempt ${t} failed. Retrying in ${this.options.retryDelay}ms...`),await new Promise(n=>setTimeout(n,this.options.retryDelay))}return this.connection=_.connection,this._connected=!0,console.log(`Connected to MongoDB at ${this.options.uri}/${this.options.name}`),this.connection.on("error",e=>{console.error("MongoDB connection error:",e),this._connected=!1}),this.connection.on("disconnected",()=>{console.log("MongoDB disconnected"),this._connected=!1}),this.connection}catch(t){throw console.error("Failed to connect to MongoDB:",t),t}}async disconnect(){this.connection&&(await _.disconnect(),this._connected=!1,this.connection=null,console.log("Disconnected from MongoDB"))}isConnected(){return this._connected}getConnection(){return this.connection}}function Oe(r={}){const t=b(),{port:e=3e3,staticDir:n="public",enableCors:s=!0,apiPrefix:i="/api",ssrEnabled:o=!0,middlewares:a=[],enableCompression:u=!0,enableHelmet:f=!0,logFormat:p="dev",trustProxy:T=!1,showErrorDetails:$=E.env.NODE_ENV!=="production"}=r;if(T&&t.set("trust proxy",T),t.use(b.json()),t.use(b.urlencoded({extended:!0})),u&&t.use(Fe()),f&&t.use(Le({contentSecurityPolicy:r.disableCSP?!1:void 0})),p&&t.use(Be(p)),s&&t.use((d,m,h)=>{if(m.header("Access-Control-Allow-Origin","*"),m.header("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, PATCH, OPTIONS"),m.header("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept, Authorization"),d.method==="OPTIONS")return m.sendStatus(200);h()}),a.forEach(d=>t.use(d)),n){const d=ye.resolve(E.cwd(),n);He.existsSync(d)?(t.use(b.static(d,{maxAge:r.staticCacheAge||"1d",etag:!0})),console.log(`📂 Serving static files from: ${d}`)):console.warn(`⚠️ Static directory not found: ${d}`)}let g=null;t.connectToDatabase=async d=>{try{return g&&g.isConnected()?(console.log("✅ Using existing database connection"),g):(g=new Ie(d),await g.connect(),console.log("✅ Database connected successfully"),E.on("SIGTERM",async()=>{g&&g.isConnected()&&(await g.disconnect(),console.log("Database connection closed"))}),g)}catch(m){throw console.error("❌ Failed to connect to database:",m),m}};const F={},fe={};return t.registerApi=(d,m,h={})=>{try{const{prefix:w=i}=h,k=ye.posix.join(w,d).replace(/\\/g,"/");t.use(k,m),F[k]={router:m,options:h},console.log(`🔌 API registered: ${k}`)}catch(w){console.error(`❌ Failed to register API at ${d}:`,w)}return t},t.registerSSR=(d,m,h={})=>o?(fe[d]={component:m,options:h},t.get(d,async(w,k,he)=>{try{if(w.query.nossr==="true")return he();const pe={req:w,res:k,params:w.params,query:w.query,user:w.user,...h.props},at=await N(m(pe));k.send(`
2
+ <!DOCTYPE html>
3
+ <html lang="${h.lang||"en"}">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>${h.title||"Frontend Hamroun App"}</title>
8
+ ${h.meta?h.meta.map(q=>`<meta ${Object.entries(q).map(([ct,ut])=>`${ct}="${ut}"`).join(" ")}>`).join(`
9
+ `):""}
10
+ ${h.head||""}
11
+ ${h.styles?`<style>${h.styles}</style>`:""}
12
+ ${h.styleSheets?h.styleSheets.map(q=>`<link rel="stylesheet" href="${q}">`).join(`
13
+ `):""}
14
+ </head>
15
+ <body ${h.bodyAttributes||""}>
16
+ <div id="${h.rootId||"root"}">${at}</div>
17
+ <script>
18
+ window.__INITIAL_DATA__ = ${JSON.stringify(h.initialData||{})};
19
+ <\/script>
20
+ ${h.scripts?h.scripts.map(q=>`<script src="${q}"><\/script>`).join(`
21
+ `):""}
22
+ </body>
23
+ </html>
24
+ `)}catch(pe){if(console.error("SSR Error:",pe),h.fallback)return he();k.status(500).send("Server rendering error")}}),console.log(`🖥️ SSR registered: ${d}`),t):(console.log(`⚠️ SSR disabled: skipping registration of ${d}`),t),t.use((d,m,h,w)=>{console.error("Server error:",d);const k=d.statusCode||d.status||500;m.path.startsWith(i)?h.status(k).json({success:!1,error:$?d.message:"Internal Server Error",stack:$?d.stack:void 0}):h.status(k).send(`
25
+ <!DOCTYPE html>
26
+ <html>
27
+ <head>
28
+ <title>Error - ${k}</title>
29
+ <style>
30
+ body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }
31
+ .error { background: #f8d7da; border: 1px solid #f5c6cb; padding: 1rem; border-radius: 4px; }
32
+ .stack { background: #f8f9fa; padding: 1rem; border-radius: 4px; overflow: auto; }
33
+ </style>
34
+ </head>
35
+ <body>
36
+ <h1>Error ${k}</h1>
37
+ <div class="error">${$?d.message:"Internal Server Error"}</div>
38
+ ${$&&d.stack?`<pre class="stack">${d.stack}</pre>`:""}
39
+ </body>
40
+ </html>
41
+ `)}),t.use((d,m)=>{d.path.startsWith(i)?m.status(404).json({success:!1,error:"Not Found"}):m.status(404).send(`
42
+ <!DOCTYPE html>
43
+ <html>
44
+ <head>
45
+ <title>404 - Not Found</title>
46
+ <style>
47
+ body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }
48
+ </style>
49
+ </head>
50
+ <body>
51
+ <h1>404 - Not Found</h1>
52
+ <p>The requested resource was not found on this server.</p>
53
+ <p><a href="/">Return to homepage</a></p>
54
+ </body>
55
+ </html>
56
+ `)}),t.start=d=>{const m=t.listen(e,()=>{console.log(`
57
+ 🚀 Frontend Hamroun server running at http://localhost:${e}
58
+ ${Object.keys(F).length>0?`
59
+ 📡 Registered API Routes:
60
+ ${Object.keys(F).map(w=>` ${w}`).join(`
61
+ `)}`:""}
62
+ ${Object.keys(fe).length>0?`
63
+ 🖥️ Registered SSR Routes:
64
+ ${Object.keys(fe).map(w=>` ${w}`).join(`
65
+ `)}`:""}
66
+ `),d&&d()}),h=async w=>{console.log(`${w} signal received: closing HTTP server and cleaning up`),m.close(async()=>{console.log("HTTP server closed"),g&&g.isConnected()&&(await g.disconnect(),console.log("Database connection closed")),E.exit(0)}),setTimeout(()=>{console.error("Could not close connections in time, forcefully shutting down"),E.exit(1)},1e4)};return E.on("SIGTERM",()=>h("SIGTERM")),E.on("SIGINT",()=>h("SIGINT")),m},t}const Ne=(r,{res:t})=>{console.error("API Error:",r);const e=r.status||r.statusCode||500,n=r.message||"Internal server error";t.status(e).json({success:!1,error:n,stack:E.env.NODE_ENV!=="production"?r.stack:void 0})};function Ze(r,t={}){const e=b.Router(),{middleware:n=[],errorHandler:s=Ne}=t;n.forEach(o=>e.use(o));const i=o=>async(a,u,f)=>{try{const p={req:a,res:u,next:f,params:a.params,query:a.query,body:a.body};return await o(p)}catch(p){const T={req:a,res:u,next:f,params:a.params,query:a.query,body:a.body};return s(p,T)}};return e.get("/",i(async({req:o,res:a})=>{const u=o.pagination||{page:1,limit:10},f=await r.getAll(u);a.json({success:!0,...f})})),e.get("/:id",i(async({params:o,res:a})=>{const u=await r.getById(o.id);if(!u){a.status(404).json({success:!1,error:"Item not found"});return}a.json({success:!0,data:u})})),e.post("/",i(async({body:o,res:a})=>{const u=await r.create(o);a.status(201).json({success:!0,data:u,message:"Item created successfully"})})),e.put("/:id",i(async({params:o,body:a,res:u})=>{const f=await r.update(o.id,a);if(!f){u.status(404).json({success:!1,error:"Item not found"});return}u.json({success:!0,data:f,message:"Item updated successfully"})})),e.delete("/:id",i(async({params:o,res:a})=>{if(!await r.delete(o.id)){a.status(404).json({success:!1,error:"Item not found"});return}a.json({success:!0,message:"Item deleted successfully"})})),e}function Ke(r,t={}){const e=b.Router(),{middleware:n=[],errorHandler:s=Ne}=t;n.forEach(o=>e.use(o));const i=o=>async(a,u,f)=>{try{const p={req:a,res:u,next:f,params:a.params,query:a.query,body:a.body};return u.headersSent?void 0:await o(p)}catch(p){if(u.headersSent){console.error("Error occurred after response was sent:",p);return}const T={req:a,res:u,next:f,params:a.params,query:a.query,body:a.body};return s(p,T)}};return Object.entries(r).forEach(([o,a])=>{const{method:u,handler:f}=a;e[u](o,i(f))}),e}function de(r,t,e,n,s){const i={success:r};return t!==void 0&&(i.data=t),e&&(i.message=e),n&&(i.error=n),s&&(i.meta=s),i}function x(r,t,e,n=200,s){r.status(n).json(de(!0,t,e,void 0,s))}function D(r,t,e=400,n){const s=t instanceof Error?t.message:t;r.status(e).json(de(!1,void 0,void 0,s,n))}function Pe(r){const t=parseInt(r.query.page)||1,e=parseInt(r.query.limit)||10,n=r.query.sort||"createdAt",s=r.query.order==="asc"?"asc":"desc";return{page:t,limit:e,sort:n,order:s}}function xe(r,t,e){r.pagination=Pe(r),e()}function et(r){return(t,e,n)=>{try{const{error:s,value:i}=r.validate(t.body);if(s){D(e,`Validation error: ${s.message}`,400);return}t.body=i,n()}catch{D(e,"Validation error",400)}}}function De(r={},t){const e=b.Router();return r.requireAuth&&t&&(e.use(t.authenticate),r.requiredRole&&e.use(t.hasRole(r.requiredRole))),r.rateLimit&&console.warn("Rate limiting is disabled: express-rate-limit dependency is not installed"),e}function M(r){return(t,e,n)=>{r(t,e,n).catch(n)}}function tt(r){const t=b.Router();return t.get("/",xe,M(async(e,n)=>{const s=await r.getAll(e.pagination);x(n,s)})),t.get("/:id",M(async(e,n)=>{const s=await r.getById(e.params.id);if(!s)return D(n,"Item not found",404);x(n,s)})),t.post("/",M(async(e,n)=>{const s=await r.create(e.body);x(n,s,"Item created successfully",201)})),t.put("/:id",M(async(e,n)=>{const s=await r.update(e.params.id,e.body);if(!s)return D(n,"Item not found",404);x(n,s,"Item updated successfully")})),t.delete("/:id",M(async(e,n)=>{if(!await r.delete(e.params.id))return D(n,"Item not found",404);x(n,null,"Item deleted successfully")})),t}const Me=me.default||me;class rt{constructor(t){if(this.loginAttempts=new Map,this.login=async(e,n)=>{try{const{username:s,password:i}=e.body,o=e.ip||e.connection.remoteAddress||"";if(!this.checkRateLimit(o)){n.status(429).json({success:!1,message:"Too many login attempts. Please try again later."});return}if(!s||!i){n.status(400).json({success:!1,message:"Username and password are required"});return}if(!this.options.findUser){n.status(500).json({success:!1,message:"User finder function not configured"});return}const a=await this.options.findUser(s);if(!a){n.status(401).json({success:!1,message:"Invalid credentials"});return}if(!await this.options.verifyPassword(i,a.password)){n.status(401).json({success:!1,message:"Invalid credentials"});return}const f={...a};delete f.password;const p=this.generateTokenPair({id:a.id||a._id,username:a.username,role:a.role||"user"});if(this.options.saveRefreshToken){const T=new Date;T.setSeconds(T.getSeconds()+this.getExpirationSeconds(this.options.refreshExpiration||"7d")),await this.options.saveRefreshToken(a.id||a._id,p.refreshToken,T)}e.body.useCookies&&this.setAuthCookies(n,p),n.json({success:!0,message:"Authentication successful",tokens:p,user:f})}catch(s){console.error("Authentication error:",s),n.status(500).json({success:!1,message:"Authentication failed",error:E.env.NODE_ENV!=="production"?s.message:void 0})}},this.refreshToken=async(e,n)=>{var s,i;try{const o=((s=e.cookies)==null?void 0:s.refreshToken)||e.body.refreshToken;if(!o){n.status(401).json({success:!1,message:"Refresh token required"});return}const a=this.verifyToken(o,"refresh");if(this.options.verifyRefreshToken&&!await this.options.verifyRefreshToken(a.id,o)){this.clearAuthCookies(n),n.status(401).json({success:!1,message:"Invalid refresh token"});return}const u=this.generateTokenPair({id:a.id,...this.options.findUser?await this.options.findUser(a.id):{}});if(this.options.saveRefreshToken){const p=new Date;p.setSeconds(p.getSeconds()+this.getExpirationSeconds(this.options.refreshExpiration||"7d")),await this.options.saveRefreshToken(a.id,u.refreshToken,p)}(((i=e.cookies)==null?void 0:i.accessToken)||e.body.useCookies)&&this.setAuthCookies(n,u),n.json({success:!0,message:"Token refreshed successfully",tokens:u})}catch(o){this.clearAuthCookies(n),n.status(401).json({success:!1,message:"Invalid or expired refresh token",error:E.env.NODE_ENV!=="production"?o.message:void 0})}},this.logout=async(e,n)=>{var s;try{this.clearAuthCookies(n);const i=((s=e.cookies)==null?void 0:s.refreshToken)||e.body.refreshToken;if(i&&this.options.saveRefreshToken)try{const o=this.verifyToken(i,"refresh");typeof this.options.saveRefreshToken=="function"&&await this.options.saveRefreshToken(o.id,"",new Date)}catch{}n.json({success:!0,message:"Logged out successfully"})}catch(i){console.error("Logout error:",i),n.status(500).json({success:!1,message:"Logout failed",error:i.message})}},this.authenticate=(e,n,s)=>{var i;try{let o=(i=e.cookies)==null?void 0:i.accessToken;if(!o){const u=e.headers.authorization;u&&u.startsWith("Bearer ")&&(o=u.split(" ")[1])}if(!o){n.status(401).json({success:!1,message:"Authentication required"});return}const a=this.verifyToken(o,"access");e.user=a,s()}catch(o){n.status(401).json({success:!1,message:"Invalid or expired token",error:E.env.NODE_ENV!=="production"?o.message:void 0})}},this.hasRole=e=>(n,s,i)=>{const o=n.user;if(!o){s.status(401).json({success:!1,message:"Authentication required"});return}(Array.isArray(e)?e:[e]).includes(o.role)?i():s.status(403).json({success:!1,message:"Insufficient permissions"})},this.options={tokenExpiration:"15m",refreshExpiration:"7d",saltRounds:10,secureCookies:E.env.NODE_ENV==="production",httpOnlyCookies:!0,rateLimit:!0,...t,refreshSecret:t.refreshSecret||t.jwtSecret},!t.jwtSecret)throw new Error("JWT secret is required for authentication");this.options.verifyPassword||(this.options.verifyPassword=this.verifyPasswordWithBcrypt)}async hashPassword(t){return await Me.hash(t,this.options.saltRounds||10)}async verifyPasswordWithBcrypt(t,e){return await Me.compare(t,e)}generateSecureToken(t=32){return Ve.randomBytes(t).toString("hex")}generateTokenPair(t){const e=this.getExpirationSeconds(this.options.tokenExpiration||"15m"),n=Z.sign({...t,type:"access"},this.options.jwtSecret,{expiresIn:this.options.tokenExpiration}),s=Z.sign({id:t.id,type:"refresh"},this.options.refreshSecret,{expiresIn:this.options.refreshExpiration});return{accessToken:n,refreshToken:s,expiresIn:e}}getExpirationSeconds(t){const e=t.charAt(t.length-1),n=parseInt(t.slice(0,-1));switch(e){case"s":return n;case"m":return n*60;case"h":return n*60*60;case"d":return n*60*60*24;default:return 3600}}verifyToken(t,e="access"){try{const n=e==="access"?this.options.jwtSecret:this.options.refreshSecret,s=Z.verify(t,n);if(typeof s=="object"&&s.type!==e)throw new Error("Invalid token type");return s}catch{throw new Error("Invalid or expired token")}}setAuthCookies(t,e){t.cookie("accessToken",e.accessToken,{httpOnly:this.options.httpOnlyCookies,secure:this.options.secureCookies,domain:this.options.cookieDomain,sameSite:"strict",maxAge:e.expiresIn*1e3});const n=this.getExpirationSeconds(this.options.refreshExpiration||"7d");t.cookie("refreshToken",e.refreshToken,{httpOnly:!0,secure:this.options.secureCookies,domain:this.options.cookieDomain,sameSite:"strict",maxAge:n*1e3,path:"/api/auth/refresh"})}clearAuthCookies(t){t.clearCookie("accessToken"),t.clearCookie("refreshToken",{path:"/api/auth/refresh"})}checkRateLimit(t){if(!this.options.rateLimit)return!0;const e=Date.now(),n=this.loginAttempts.get(t);return n?e>n.resetTime?(this.loginAttempts.set(t,{count:1,resetTime:e+36e5}),!0):n.count>=5?!1:(n.count++,this.loginAttempts.set(t,n),!0):(this.loginAttempts.set(t,{count:1,resetTime:e+36e5}),!0)}}function nt(r){return new rt(r)}function st(r,t){const e=_.model(r,t);return{getAll:async n=>{try{const{page:s=1,limit:i=10,sort:o="_id",order:a="desc"}=n||{},u=(s-1)*i,f=a==="asc"?1:-1,p={[o]:f},[T,$]=await Promise.all([e.find().sort(p).skip(u).limit(i).exec(),e.countDocuments().exec()]),g=Math.ceil($/i);return{data:T,pagination:{total:$,totalPages:g,currentPage:s,limit:i,hasNextPage:s<g,hasPrevPage:s>1}}}catch(s){throw console.error(`Error in ${r}.getAll:`,s),new Error(`Failed to retrieve ${r} records: ${s.message}`)}},getById:async n=>{try{return _.isValidObjectId(n)?await e.findById(n).exec():null}catch(s){throw console.error(`Error in ${r}.getById:`,s),new Error(`Failed to retrieve ${r} by ID: ${s.message}`)}},create:async n=>{try{return await new e(n).save()}catch(s){throw console.error(`Error in ${r}.create:`,s),new Error(`Failed to create ${r}: ${s.message}`)}},createMany:async n=>{try{return await e.insertMany(n)}catch(s){throw console.error(`Error in ${r}.createMany:`,s),new Error(`Failed to create multiple ${r} records: ${s.message}`)}},update:async(n,s)=>{try{return _.isValidObjectId(n)?await e.findByIdAndUpdate(n,{$set:s},{new:!0,runValidators:!0}).exec():null}catch(i){throw console.error(`Error in ${r}.update:`,i),new Error(`Failed to update ${r}: ${i.message}`)}},delete:async n=>{try{return _.isValidObjectId(n)?await e.findByIdAndDelete(n).exec()!==null:!1}catch(s){throw console.error(`Error in ${r}.delete:`,s),new Error(`Failed to delete ${r}: ${s.message}`)}},find:async(n,s)=>{try{const{page:i=1,limit:o=10,sort:a="_id",order:u="desc"}=s||{},f=(i-1)*o,p=u==="asc"?1:-1,T={[a]:p},[$,g]=await Promise.all([e.find(n).sort(T).skip(f).limit(o).exec(),e.countDocuments(n).exec()]),F=Math.ceil(g/o);return{data:$,pagination:{total:g,totalPages:F,currentPage:i,limit:o,hasNextPage:i<F,hasPrevPage:i>1}}}catch(i){throw console.error(`Error in ${r}.find:`,i),new Error(`Failed to find ${r} records: ${i.message}`)}},count:async n=>{try{return await e.countDocuments(n||{}).exec()}catch(s){throw console.error(`Error in ${r}.count:`,s),new Error(`Failed to count ${r} records: ${s.message}`)}},findOne:async n=>{try{return await e.findOne(n).exec()}catch(s){throw console.error(`Error in ${r}.findOne:`,s),new Error(`Failed to find ${r} record: ${s.message}`)}}}}const ot={String:{type:String},Number:{type:Number},Boolean:{type:Boolean},Date:{type:Date},ObjectId:{type:String},Required:r=>({...r,required:!0}),Unique:r=>({...r,unique:!0}),Ref:r=>({type:String,ref:r}),Enum:r=>({type:String,enum:r}),Default:(r,t)=>({...r,default:t}),Array:r=>({type:[r]})},it={jsx:W,jsxs:te,createElement:U,Fragment:re,Component:Se,useState:le,useEffect:Ae,useRef:Ce,useMemo:je,useErrorBoundary:_e,render:Y,hydrate:Re,renderToString:N,prepareRender:B,finishRender:H,batchUpdates:J,createServer:Oe,Router:b.Router,createApiRouter:De};Object.defineProperty(c,"Router",{enumerable:!0,get:()=>b.Router}),c.Component=Se,c.DatabaseConnector=Ie,c.FieldTypes=ot,c.Fragment=re,c.apiResponse=de,c.asyncHandler=M,c.batchUpdates=J,c.createApiRouter=De,c.createAuth=nt,c.createCustomRouter=Ke,c.createElement=U,c.createModel=st,c.createModelRouter=Ze,c.createRestEndpoints=tt,c.createServer=Oe,c.default=it,c.finishRender=H,c.getPaginationParams=Pe,c.hydrate=Re,c.jsx=W,c.jsxs=te,c.paginationMiddleware=xe,c.prepareRender=B,c.render=Y,c.renderToString=N,c.sendError=D,c.sendSuccess=x,c.useEffect=Ae,c.useErrorBoundary=_e,c.useMemo=je,c.useRef=Ce,c.useState=le,c.validateRequest=et,Object.defineProperties(c,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontend-hamroun",
3
- "version": "1.2.4",
3
+ "version": "1.2.5",
4
4
  "description": "A lightweight frontend and backend framework for building modern web applications",
5
5
  "type": "module",
6
6
  "main": "dist/frontend-hamroun.umd.js",
@@ -1,6 +1,7 @@
1
1
  import { Request, Response, NextFunction } from 'express';
2
2
  import jwt from 'jsonwebtoken';
3
- import bcrypt from 'bcrypt';
3
+ import * as bcryptModule from 'bcrypt';
4
+ const bcrypt = bcryptModule.default || bcryptModule;
4
5
  import crypto from 'crypto';
5
6
 
6
7
  /**
@@ -1,5 +1,7 @@
1
1
  import mongoose, { Schema, Document, SortOrder } from 'mongoose';
2
2
  import { Model, PaginationOptions, PaginatedResult } from './types';
3
+ import * as bcryptModule from 'bcrypt';
4
+ const bcrypt = bcryptModule.default || bcryptModule;
3
5
 
4
6
  /**
5
7
  * Creates a data model from a Mongoose schema
package/src/shims.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Module declaration shims for third-party libraries
3
+ */
4
+
5
+ // Handle bcrypt CommonJS module in ESM context
6
+ declare module 'bcrypt' {
7
+ export function genSalt(rounds?: number): Promise<string>;
8
+ export function hash(data: string, saltOrRounds: string | number): Promise<string>;
9
+ export function compare(data: string, encrypted: string): Promise<boolean>;
10
+
11
+ // Allow either default or named imports to work
12
+ const bcrypt: {
13
+ genSalt: typeof genSalt;
14
+ hash: typeof hash;
15
+ compare: typeof compare;
16
+ };
17
+ export default bcrypt;
18
+ }
19
+
20
+ // Add similar declarations for other problematic Node.js modules if needed
@@ -10,7 +10,7 @@ export default defineConfig({
10
10
  outDir: 'dist',
11
11
  emptyOutDir: true,
12
12
  rollupOptions: {
13
- // Mark testing dependencies and Node.js dependencies as external
13
+ // Mark server dependencies as external
14
14
  external: [
15
15
  'mock-aws-s3',
16
16
  'aws-sdk',
@@ -19,8 +19,6 @@ export default defineConfig({
19
19
  'jest-mock',
20
20
  '@testing-library/react',
21
21
  '@testing-library/jest-dom',
22
- '@mswjs/interceptors',
23
- 'node-pre-gyp',
24
22
  'bcrypt',
25
23
  'jsonwebtoken',
26
24
  'mongoose',
@@ -37,50 +35,25 @@ export default defineConfig({
37
35
  open: true
38
36
  },
39
37
  optimizeDeps: {
38
+ // Prevent Vite from optimizing Node.js modules
39
+ exclude: ['bcrypt', 'jsonwebtoken', 'mongoose', 'express', 'compression', 'helmet', 'morgan'],
40
40
  esbuildOptions: {
41
- // Node.js global to browser globalThis
42
41
  define: {
43
42
  global: 'globalThis'
44
- },
45
- // Enable esbuild polyfill plugins
46
- plugins: [
47
- {
48
- name: 'node-modules-polyfill',
49
- setup(build) {
50
- // Exclude node:* imports and html files
51
- build.onResolve({ filter: /^node:/ }, () => {
52
- return { external: true };
53
- });
54
- build.onResolve({ filter: /\.html$/ }, () => {
55
- return { external: true };
56
- });
57
- }
58
- }
59
- ]
60
- },
61
- // Exclude problematic dependencies from optimization
62
- exclude: [
63
- 'mock-aws-s3',
64
- 'aws-sdk',
65
- 'nock',
66
- '@mswjs/interceptors',
67
- 'node-pre-gyp',
68
- 'bcrypt'
69
- ]
43
+ }
44
+ }
70
45
  },
71
46
  plugins: [
72
- // Add node polyfills for browser environment
73
47
  nodePolyfills({
74
- // Whether to polyfill `node:` protocol imports
75
48
  protocolImports: true,
76
49
  }),
77
50
  ],
78
51
  resolve: {
79
- // Add node compatibility
80
52
  alias: {
81
- // Handle missing imports specifically
82
- '@mswjs/interceptors/presets/node': { find: /^@mswjs\/interceptors\/presets\/node/, replacement: '{}' },
83
- './util/nw-pre-gyp/index.html': { find: './util/nw-pre-gyp/index.html', replacement: '{}' }
53
+ // Remove any Node.js specific imports that might cause issues
54
+ 'bcrypt': 'frontend-hamroun',
55
+ 'jsonwebtoken': 'frontend-hamroun',
56
+ 'mongoose': 'frontend-hamroun'
84
57
  }
85
58
  }
86
59
  });