frontend-hamroun 1.2.8 → 1.2.10

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,27 +1,27 @@
1
- (function(a,v){typeof exports=="object"&&typeof module<"u"?v(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"],v):(a=typeof globalThis<"u"?globalThis:a||self,v(a["frontend-hamroun"]={},a.express,a.path,a.compression,a.helmet,a.morgan,a.mongoose,a.fs,a.jwt,a.bcrypt,a.crypto))})(this,function(a,v,we,Je,ze,Qe,$,Ye,K,Xe,Ze){"use strict";function Ke(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 Ee=Ke(Xe),be=globalThis||void 0||self;function et(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}var Te={exports:{}},y=Te.exports={},k,A;function ee(){throw new Error("setTimeout has not been defined")}function te(){throw new Error("clearTimeout has not been defined")}(function(){try{typeof setTimeout=="function"?k=setTimeout:k=ee}catch{k=ee}try{typeof clearTimeout=="function"?A=clearTimeout:A=te}catch{A=te}})();function ve(r){if(k===setTimeout)return setTimeout(r,0);if((k===ee||!k)&&setTimeout)return k=setTimeout,setTimeout(r,0);try{return k(r,0)}catch{try{return k.call(null,r,0)}catch{return k.call(this,r,0)}}}function tt(r){if(A===clearTimeout)return clearTimeout(r);if((A===te||!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 C=[],M=!1,R,q=-1;function rt(){!M||!R||(M=!1,R.length?C=R.concat(C):q=-1,C.length&&Se())}function Se(){if(!M){var r=ve(rt);M=!0;for(var t=C.length;t;){for(R=C,C=[];++q<t;)R&&R[q].run();q=-1,t=C.length}R=null,M=!1,tt(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];C.push(new ke(r,t)),C.length===1&&!M&&ve(Se)};function ke(r,t){this.fun=r,this.array=t}ke.prototype.run=function(){this.fun.apply(null,this.array)},y.title="browser",y.browser=!0,y.env={},y.argv=[],y.version="",y.versions={};function j(){}y.on=j,y.addListener=j,y.once=j,y.off=j,y.removeListener=j,y.removeAllListeners=j,y.emit=j,y.prependListener=j,y.prependOnceListener=j,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 nt=Te.exports;const E=et(nt),O=typeof window<"u"?window:typeof be<"u"?be:{};function W(r,t,e){return{type:r,props:t||{},key:e}}function re(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 c=require("fs"),f=require("path").resolve(E.cwd(),"jsx-runtime-stats.json");c.writeFileSync(f,JSON.stringify(O.__renderStats,null,2)),console.log(`JSX runtime stats written to ${f}`)}catch(c){console.error("Failed to write stats file:",c)}})),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 ne=Symbol("Fragment");typeof window<"u"&&(window.jsx=W,window.jsxs=re,window.Fragment=ne);const st=typeof window<"u"&&typeof document<"u";async function I(r){var t;if(console.log("Creating element from:",r),!st){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 I(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 I(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,c){this.attributes[o]=c},appendChild:function(o){this.childNodes.push(o)}};for(const[o,c]of Object.entries(n||{}))if(o!=="children")if(o.startsWith("on")&&typeof c=="function"){const u=o.toLowerCase().slice(2);s.__events||(s.__events={}),s.__events[u]=c}else o==="style"&&typeof c=="object"?Object.assign(s.style,c):o==="className"?s.setAttribute("class",String(c)):o!=="key"&&o!=="ref"&&s.setAttribute(o,String(c));const i=n==null?void 0:n.children;if(i!=null){const o=Array.isArray(i)?i.flat():[i];for(const c of o){const u=await I(c);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 I(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||{}),c=await I(o);return c instanceof Element&&c.setAttribute("data-component-id",e.name||e.toString()),c}catch(o){return console.error("Error rendering component:",o),document.createTextNode("")}const s=document.createElement(e);for(const[o,c]of Object.entries(n||{}))if(o!=="children")if(o.startsWith("on")&&typeof c=="function"){const u=o.toLowerCase().slice(2),f=(t=s.__events)==null?void 0:t[u];f&&s.removeEventListener(u,f),s.addEventListener(u,c),s.__events||(s.__events={}),s.__events[u]=c}else o==="style"&&typeof c=="object"?Object.assign(s.style,c):o==="className"?s.setAttribute("class",String(c)):o!=="key"&&o!=="ref"&&s.setAttribute(o,String(c));const i=n==null?void 0:n.children;if(i!=null){const o=Array.isArray(i)?i.flat():[i];for(const c of o){const u=await I(c);s.appendChild(u)}}return s}return document.createTextNode(String(r))}class Ae{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 I(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 se=[];function J(r){if(G){se.push(r);return}G=!0;try{for(r();se.length>0;){const t=se.shift();t==null||t()}}finally{G=!1}}let l=0;const oe=new Map,T=new Map,L=new Map,ie=new Map,ce=new Map;let ae=null,ue=null,le=null;const Ce=typeof window>"u",z=new Map;function je(r,t,e){ae=r,ue=e,le=t}function B(){return l++,T.set(l,0),l}function V(){Ce&&z.delete(l),l=0}function de(r){if(!l)throw new Error("useState must be called within a render");if(Ce){z.has(l)||z.set(l,new Map);const i=z.get(l),o=T.get(l)||0;i.has(o)||i.set(o,r);const c=i.get(o),u=f=>{};return T.set(l,o+1),[c,u]}oe.has(l)||oe.set(l,[]);const t=oe.get(l),e=T.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(()=>Re(l)):Re(l))};return T.set(l,e+1),[n,s]}function _e(r,t){if(!l)throw new Error("useEffect must be called within a render");const e=T.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}})),T.set(l,e+1)}function $e(r,t){if(!l)throw new Error("useMemo must be called within a render");const e=T.get(l);ie.has(l)||ie.set(l,[]);const n=ie.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},T.set(l,e+1),i}return T.set(l,e+1),s.value}function Ie(r){if(!l)throw new Error("useRef must be called within a render");const t=T.get(l);ce.has(l)||ce.set(l,[]);const e=ce.get(l);if(t>=e.length){const s={current:r};return e.push(s),T.set(l,t+1),s}const n=e[t];return T.set(l,t+1),n}async function Re(r){try{const t=L.get(r);t&&(t.forEach(e=>{e.cleanup&&e.cleanup()}),L.set(r,[])),ae&&ue&&le&&await ae(le,ue)}catch(t){console.error("Error during rerender:",t)}}function Oe(){const[r,t]=de(null);return[r,()=>t(null)]}let Q=!1;async function xe(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{je(Y,r,t);const n=await I(r);Q||(t.innerHTML=""),Q&&t.firstChild?console.log("Hydrating existing DOM"):t.appendChild(n)}finally{V()}})}async function x(r){B(),je(()=>{},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(x))).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 x(i);return V(),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(x))).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="${ot(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 x(o)}return n+`</${t}>`}return X(String(r))}finally{V()}}function X(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function ot(r){return Object.entries(r).map(([t,e])=>`${it(t)}:${e}`).join(";")}function it(r){return r.replace(/[A-Z]/g,t=>"-"+t.toLowerCase())}function Ne(r){const t={_currentValue:r,Provider:function({value:n,children:s}){return t._currentValue=n,s},Consumer:function({children:n}){return n(t._currentValue)}};return t}function Pe(r){return r._currentValue}class fe{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 De(r={}){const t=v(),{port:e=3e3,staticDir:n="public",enableCors:s=!0,apiPrefix:i="/api",ssrEnabled:o=!0,middlewares:c=[],enableCompression:u=!0,enableHelmet:f=!0,logFormat:p="dev",trustProxy:b=!1,showErrorDetails:_=E.env.NODE_ENV!=="production"}=r;if(b&&t.set("trust proxy",b),t.use(v.json()),t.use(v.urlencoded({extended:!0})),u&&t.use(Je()),f&&t.use(ze({contentSecurityPolicy:r.disableCSP?!1:void 0})),p&&t.use(Qe(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()}),c.forEach(d=>t.use(d)),n){const d=we.resolve(E.cwd(),n);Ye.existsSync(d)?(t.use(v.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 fe(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={},ye={};return t.registerApi=(d,m,h={})=>{try{const{prefix:w=i}=h,S=we.posix.join(w,d).replace(/\\/g,"/");t.use(S,m),F[S]={router:m,options:h},console.log(`🔌 API registered: ${S}`)}catch(w){console.error(`❌ Failed to register API at ${d}:`,w)}return t},t.registerSSR=(d,m,h={})=>o?(ye[d]={component:m,options:h},t.get(d,async(w,S,me)=>{try{if(w.query.nossr==="true")return me();const ge={req:w,res:S,params:w.params,query:w.query,user:w.user,...h.props},ut=await x(m(ge));S.send(`
1
+ (function(a,v){typeof exports=="object"&&typeof module<"u"?v(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"],v):(a=typeof globalThis<"u"?globalThis:a||self,v(a["frontend-hamroun"]={},a.express,a.path,a.compression,a.helmet,a.morgan,a.mongoose,a.fs,a.jwt,a.bcrypt,a.crypto))})(this,function(a,v,Ee,ze,Qe,Ye,$,Xe,K,Ze,Ke){"use strict";function et(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 be=et(Ze),Te=globalThis||void 0||self;function tt(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}var ve={exports:{}},y=ve.exports={},k,A;function ee(){throw new Error("setTimeout has not been defined")}function te(){throw new Error("clearTimeout has not been defined")}(function(){try{typeof setTimeout=="function"?k=setTimeout:k=ee}catch{k=ee}try{typeof clearTimeout=="function"?A=clearTimeout:A=te}catch{A=te}})();function Se(r){if(k===setTimeout)return setTimeout(r,0);if((k===ee||!k)&&setTimeout)return k=setTimeout,setTimeout(r,0);try{return k(r,0)}catch{try{return k.call(null,r,0)}catch{return k.call(this,r,0)}}}function rt(r){if(A===clearTimeout)return clearTimeout(r);if((A===te||!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=[],M=!1,R,W=-1;function nt(){!M||!R||(M=!1,R.length?j=R.concat(j):W=-1,j.length&&ke())}function ke(){if(!M){var r=Se(nt);M=!0;for(var t=j.length;t;){for(R=j,j=[];++W<t;)R&&R[W].run();W=-1,t=j.length}R=null,M=!1,rt(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 Ae(r,t)),j.length===1&&!M&&Se(ke)};function Ae(r,t){this.fun=r,this.array=t}Ae.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 st=ve.exports;const E=tt(st),x=typeof window<"u"?window:typeof Te<"u"?Te:{};function L(r,t,e){return{type:r,props:t||{},key:e}}function re(r,t,e){return L(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"&&(x.__renderStats||(x.__renderStats={elementsCreated:0,textNodesCreated:0,eventsAttached:0,renderTime:0},typeof afterAll=="function"&&afterAll(()=>{try{const c=require("fs"),f=require("path").resolve(E.cwd(),"jsx-runtime-stats.json");c.writeFileSync(f,JSON.stringify(x.__renderStats,null,2)),console.log(`JSX runtime stats written to ${f}`)}catch(c){console.error("Failed to write stats file:",c)}})),o instanceof Text?x.__renderStats.textNodesCreated++:x.__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"&&x.__renderStats&&x.__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 ne=Symbol("Fragment"),se=L;typeof window<"u"&&(window.jsx=L,window.jsxs=re,window.jsxDEV=se,window.Fragment=ne);const ot=typeof window<"u"&&typeof document<"u";async function I(r){var t;if(console.log("Creating element from:",r),!ot){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 I(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 I(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,c){this.attributes[o]=c},appendChild:function(o){this.childNodes.push(o)}};for(const[o,c]of Object.entries(n||{}))if(o!=="children")if(o.startsWith("on")&&typeof c=="function"){const u=o.toLowerCase().slice(2);s.__events||(s.__events={}),s.__events[u]=c}else o==="style"&&typeof c=="object"?Object.assign(s.style,c):o==="className"?s.setAttribute("class",String(c)):o!=="key"&&o!=="ref"&&s.setAttribute(o,String(c));const i=n==null?void 0:n.children;if(i!=null){const o=Array.isArray(i)?i.flat():[i];for(const c of o){const u=await I(c);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 I(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||{}),c=await I(o);return c instanceof Element&&c.setAttribute("data-component-id",e.name||e.toString()),c}catch(o){return console.error("Error rendering component:",o),document.createTextNode("")}const s=document.createElement(e);for(const[o,c]of Object.entries(n||{}))if(o!=="children")if(o.startsWith("on")&&typeof c=="function"){const u=o.toLowerCase().slice(2),f=(t=s.__events)==null?void 0:t[u];f&&s.removeEventListener(u,f),s.addEventListener(u,c),s.__events||(s.__events={}),s.__events[u]=c}else o==="style"&&typeof c=="object"?Object.assign(s.style,c):o==="className"?s.setAttribute("class",String(c)):o!=="key"&&o!=="ref"&&s.setAttribute(o,String(c));const i=n==null?void 0:n.children;if(i!=null){const o=Array.isArray(i)?i.flat():[i];for(const c of o){const u=await I(c);s.appendChild(u)}}return s}return document.createTextNode(String(r))}class je{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 I(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 oe=[];function J(r){if(G){oe.push(r);return}G=!0;try{for(r();oe.length>0;){const t=oe.shift();t==null||t()}}finally{G=!1}}let l=0;const ie=new Map,T=new Map,V=new Map,ce=new Map,ae=new Map;let ue=null,le=null,de=null;const Ce=typeof window>"u",z=new Map;function _e(r,t,e){ue=r,le=e,de=t}function B(){return l++,T.set(l,0),l}function H(){Ce&&z.delete(l),l=0}function fe(r){if(!l)throw new Error("useState must be called within a render");if(Ce){z.has(l)||z.set(l,new Map);const i=z.get(l),o=T.get(l)||0;i.has(o)||i.set(o,r);const c=i.get(o),u=f=>{};return T.set(l,o+1),[c,u]}ie.has(l)||ie.set(l,[]);const t=ie.get(l),e=T.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(()=>xe(l)):xe(l))};return T.set(l,e+1),[n,s]}function $e(r,t){if(!l)throw new Error("useEffect must be called within a render");const e=T.get(l);V.has(l)||V.set(l,[]);const n=V.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}})),T.set(l,e+1)}function Ie(r,t){if(!l)throw new Error("useMemo must be called within a render");const e=T.get(l);ce.has(l)||ce.set(l,[]);const n=ce.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},T.set(l,e+1),i}return T.set(l,e+1),s.value}function Re(r){if(!l)throw new Error("useRef must be called within a render");const t=T.get(l);ae.has(l)||ae.set(l,[]);const e=ae.get(l);if(t>=e.length){const s={current:r};return e.push(s),T.set(l,t+1),s}const n=e[t];return T.set(l,t+1),n}async function xe(r){try{const t=V.get(r);t&&(t.forEach(e=>{e.cleanup&&e.cleanup()}),V.set(r,[])),ue&&le&&de&&await ue(de,le)}catch(t){console.error("Error during rerender:",t)}}function Oe(){const[r,t]=fe(null);return[r,()=>t(null)]}let Q=!1;async function Ne(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{_e(Y,r,t);const n=await I(r);Q||(t.innerHTML=""),Q&&t.firstChild?console.log("Hydrating existing DOM"):t.appendChild(n)}finally{H()}})}async function O(r){B(),_e(()=>{},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(O))).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 O(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(O))).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="${it(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 O(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 it(r){return Object.entries(r).map(([t,e])=>`${ct(t)}:${e}`).join(";")}function ct(r){return r.replace(/[A-Z]/g,t=>"-"+t.toLowerCase())}function Pe(r){const t={_currentValue:r,Provider:function({value:n,children:s}){return t._currentValue=n,s},Consumer:function({children:n}){return n(t._currentValue)}};return t}function De(r){return r._currentValue}class he{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 Me(r={}){const t=v(),{port:e=3e3,staticDir:n="public",enableCors:s=!0,apiPrefix:i="/api",ssrEnabled:o=!0,middlewares:c=[],enableCompression:u=!0,enableHelmet:f=!0,logFormat:p="dev",trustProxy:b=!1,showErrorDetails:_=E.env.NODE_ENV!=="production"}=r;if(b&&t.set("trust proxy",b),t.use(v.json()),t.use(v.urlencoded({extended:!0})),u&&t.use(ze()),f&&t.use(Qe({contentSecurityPolicy:r.disableCSP?!1:void 0})),p&&t.use(Ye(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()}),c.forEach(d=>t.use(d)),n){const d=Ee.resolve(E.cwd(),n);Xe.existsSync(d)?(t.use(v.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 he(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={},me={};return t.registerApi=(d,m,h={})=>{try{const{prefix:w=i}=h,S=Ee.posix.join(w,d).replace(/\\/g,"/");t.use(S,m),F[S]={router:m,options:h},console.log(`🔌 API registered: ${S}`)}catch(w){console.error(`❌ Failed to register API at ${d}:`,w)}return t},t.registerSSR=(d,m,h={})=>o?(me[d]={component:m,options:h},t.get(d,async(w,S,ge)=>{try{if(w.query.nossr==="true")return ge();const we={req:w,res:S,params:w.params,query:w.query,user:w.user,...h.props},lt=await O(m(we));S.send(`
2
2
  <!DOCTYPE html>
3
3
  <html lang="${h.lang||"en"}">
4
4
  <head>
5
5
  <meta charset="UTF-8">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
7
  <title>${h.title||"Frontend Hamroun App"}</title>
8
- ${h.meta?h.meta.map(H=>`<meta ${Object.entries(H).map(([lt,dt])=>`${lt}="${dt}"`).join(" ")}>`).join(`
8
+ ${h.meta?h.meta.map(q=>`<meta ${Object.entries(q).map(([dt,ft])=>`${dt}="${ft}"`).join(" ")}>`).join(`
9
9
  `):""}
10
10
  ${h.head||""}
11
11
  ${h.styles?`<style>${h.styles}</style>`:""}
12
- ${h.styleSheets?h.styleSheets.map(H=>`<link rel="stylesheet" href="${H}">`).join(`
12
+ ${h.styleSheets?h.styleSheets.map(q=>`<link rel="stylesheet" href="${q}">`).join(`
13
13
  `):""}
14
14
  </head>
15
15
  <body ${h.bodyAttributes||""}>
16
- <div id="${h.rootId||"root"}">${ut}</div>
16
+ <div id="${h.rootId||"root"}">${lt}</div>
17
17
  <script>
18
18
  window.__INITIAL_DATA__ = ${JSON.stringify(h.initialData||{})};
19
19
  <\/script>
20
- ${h.scripts?h.scripts.map(H=>`<script src="${H}"><\/script>`).join(`
20
+ ${h.scripts?h.scripts.map(q=>`<script src="${q}"><\/script>`).join(`
21
21
  `):""}
22
22
  </body>
23
23
  </html>
24
- `)}catch(ge){if(console.error("SSR Error:",ge),h.fallback)return me();S.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 S=d.statusCode||d.status||500;m.path.startsWith(i)?h.status(S).json({success:!1,error:_?d.message:"Internal Server Error",stack:_?d.stack:void 0}):h.status(S).send(`
24
+ `)}catch(we){if(console.error("SSR Error:",we),h.fallback)return ge();S.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 S=d.statusCode||d.status||500;m.path.startsWith(i)?h.status(S).json({success:!1,error:_?d.message:"Internal Server Error",stack:_?d.stack:void 0}):h.status(S).send(`
25
25
  <!DOCTYPE html>
26
26
  <html>
27
27
  <head>
@@ -59,8 +59,8 @@ ${Object.keys(F).length>0?`
59
59
  📡 Registered API Routes:
60
60
  ${Object.keys(F).map(w=>` ${w}`).join(`
61
61
  `)}`:""}
62
- ${Object.keys(ye).length>0?`
62
+ ${Object.keys(me).length>0?`
63
63
  🖥️ Registered SSR Routes:
64
- ${Object.keys(ye).map(w=>` ${w}`).join(`
64
+ ${Object.keys(me).map(w=>` ${w}`).join(`
65
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 Me=Ee.default||Ee;class ct{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 c=await this.options.findUser(s);if(!c){n.status(401).json({success:!1,message:"Invalid credentials"});return}if(!await this.options.verifyPassword(i,c.password)){n.status(401).json({success:!1,message:"Invalid credentials"});return}const f={...c};delete f.password;const p=this.generateTokenPair({id:c.id||c._id,username:c.username,role:c.role||"user"});if(this.options.saveRefreshToken){const b=new Date;b.setSeconds(b.getSeconds()+this.getExpirationSeconds(this.options.refreshExpiration||"7d")),await this.options.saveRefreshToken(c.id||c._id,p.refreshToken,b)}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 c=this.verifyToken(o,"refresh");if(this.options.verifyRefreshToken&&!await this.options.verifyRefreshToken(c.id,o)){this.clearAuthCookies(n),n.status(401).json({success:!1,message:"Invalid refresh token"});return}const u=this.generateTokenPair({id:c.id,...this.options.findUser?await this.options.findUser(c.id):{}});if(this.options.saveRefreshToken){const p=new Date;p.setSeconds(p.getSeconds()+this.getExpirationSeconds(this.options.refreshExpiration||"7d")),await this.options.saveRefreshToken(c.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 c=this.verifyToken(o,"access");e.user=c,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 Ze.randomBytes(t).toString("hex")}generateTokenPair(t){const e=this.getExpirationSeconds(this.options.tokenExpiration||"15m"),n=K.sign({...t,type:"access"},this.options.jwtSecret,{expiresIn:this.options.tokenExpiration}),s=K.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=K.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 Fe(r){return new ct(r)}function Le(r,t){const e=$.model(r,t);return{getAll:async n=>{try{const{page:s=1,limit:i=10,sort:o="_id",order:c="desc"}=n||{},u=(s-1)*i,f=c==="asc"?1:-1,p={[o]:f},[b,_]=await Promise.all([e.find().sort(p).skip(u).limit(i).exec(),e.countDocuments().exec()]),g=Math.ceil(_/i);return{data:b,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:c="_id",order:u="desc"}=s||{},f=(i-1)*o,p=u==="asc"?1:-1,b={[c]:p},[_,g]=await Promise.all([e.find(n).sort(b).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 Be={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]})},Ve=(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 He(r,t={}){const e=v.Router(),{middleware:n=[],errorHandler:s=Ve}=t;n.forEach(o=>e.use(o));const i=o=>async(c,u,f)=>{try{const p={req:c,res:u,next:f,params:c.params,query:c.query,body:c.body};return await o(p)}catch(p){const b={req:c,res:u,next:f,params:c.params,query:c.query,body:c.body};return s(p,b)}};return e.get("/",i(async({req:o,res:c})=>{const u=o.pagination||{page:1,limit:10},f=await r.getAll(u);c.json({success:!0,...f})})),e.get("/:id",i(async({params:o,res:c})=>{const u=await r.getById(o.id);if(!u){c.status(404).json({success:!1,error:"Item not found"});return}c.json({success:!0,data:u})})),e.post("/",i(async({body:o,res:c})=>{const u=await r.create(o);c.status(201).json({success:!0,data:u,message:"Item created successfully"})})),e.put("/:id",i(async({params:o,body:c,res:u})=>{const f=await r.update(o.id,c);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:c})=>{if(!await r.delete(o.id)){c.status(404).json({success:!1,error:"Item not found"});return}c.json({success:!0,message:"Item deleted successfully"})})),e}function qe(r,t={}){const e=v.Router(),{middleware:n=[],errorHandler:s=Ve}=t;n.forEach(o=>e.use(o));const i=o=>async(c,u,f)=>{try{const p={req:c,res:u,next:f,params:c.params,query:c.query,body:c.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 b={req:c,res:u,next:f,params:c.params,query:c.query,body:c.body};return s(p,b)}};return Object.entries(r).forEach(([o,c])=>{const{method:u,handler:f}=c;e[u](o,i(f))}),e}function Z(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 N(r,t,e,n=200,s){r.status(n).json(Z(!0,t,e,void 0,s))}function P(r,t,e=400,n){const s=t instanceof Error?t.message:t;r.status(e).json(Z(!1,void 0,void 0,s,n))}function he(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 pe(r,t,e){r.pagination=he(r),e()}function We(r){return(t,e,n)=>{try{const{error:s,value:i}=r.validate(t.body);if(s){P(e,`Validation error: ${s.message}`,400);return}t.body=i,n()}catch{P(e,"Validation error",400)}}}function Ue(r={},t){const e=v.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 D(r){return(t,e,n)=>{r(t,e,n).catch(n)}}function Ge(r){const t=v.Router();return t.get("/",pe,D(async(e,n)=>{const s=await r.getAll(e.pagination);N(n,s)})),t.get("/:id",D(async(e,n)=>{const s=await r.getById(e.params.id);if(!s)return P(n,"Item not found",404);N(n,s)})),t.post("/",D(async(e,n)=>{const s=await r.create(e.body);N(n,s,"Item created successfully",201)})),t.put("/:id",D(async(e,n)=>{const s=await r.update(e.params.id,e.body);if(!s)return P(n,"Item not found",404);N(n,s,"Item updated successfully")})),t.delete("/:id",D(async(e,n)=>{if(!await r.delete(e.params.id))return P(n,"Item not found",404);N(n,null,"Item deleted successfully")})),t}const at={jsx:W,jsxs:re,createElement:U,Fragment:ne,Component:Ae,useState:de,useEffect:_e,useRef:Ie,useMemo:$e,useErrorBoundary:Oe,render:Y,hydrate:xe,renderToString:x,prepareRender:B,finishRender:V,batchUpdates:J,createContext:Ne,useContext:Pe,createServer:De,createAuth:Fe,createModel:Le,FieldTypes:Be,createModelRouter:He,createCustomRouter:qe,createApiRouter:Ue,sendSuccess:N,sendError:P,apiResponse:Z,getPaginationParams:he,paginationMiddleware:pe,validateRequest:We,asyncHandler:D,createRestEndpoints:Ge,DatabaseConnector:fe};a.Component=Ae,a.DatabaseConnector=fe,a.FieldTypes=Be,a.Fragment=ne,a.apiResponse=Z,a.asyncHandler=D,a.batchUpdates=J,a.createApiRouter=Ue,a.createAuth=Fe,a.createContext=Ne,a.createCustomRouter=qe,a.createElement=U,a.createModel=Le,a.createModelRouter=He,a.createRestEndpoints=Ge,a.createServer=De,a.default=at,a.finishRender=V,a.getPaginationParams=he,a.hydrate=xe,a.jsx=W,a.jsxs=re,a.paginationMiddleware=pe,a.prepareRender=B,a.render=Y,a.renderToString=x,a.sendError=P,a.sendSuccess=N,a.useContext=Pe,a.useEffect=_e,a.useErrorBoundary=Oe,a.useMemo=$e,a.useRef=Ie,a.useState=de,a.validateRequest=We,Object.defineProperties(a,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
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 Fe=be.default||be;class at{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 c=await this.options.findUser(s);if(!c){n.status(401).json({success:!1,message:"Invalid credentials"});return}if(!await this.options.verifyPassword(i,c.password)){n.status(401).json({success:!1,message:"Invalid credentials"});return}const f={...c};delete f.password;const p=this.generateTokenPair({id:c.id||c._id,username:c.username,role:c.role||"user"});if(this.options.saveRefreshToken){const b=new Date;b.setSeconds(b.getSeconds()+this.getExpirationSeconds(this.options.refreshExpiration||"7d")),await this.options.saveRefreshToken(c.id||c._id,p.refreshToken,b)}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 c=this.verifyToken(o,"refresh");if(this.options.verifyRefreshToken&&!await this.options.verifyRefreshToken(c.id,o)){this.clearAuthCookies(n),n.status(401).json({success:!1,message:"Invalid refresh token"});return}const u=this.generateTokenPair({id:c.id,...this.options.findUser?await this.options.findUser(c.id):{}});if(this.options.saveRefreshToken){const p=new Date;p.setSeconds(p.getSeconds()+this.getExpirationSeconds(this.options.refreshExpiration||"7d")),await this.options.saveRefreshToken(c.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 c=this.verifyToken(o,"access");e.user=c,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 Fe.hash(t,this.options.saltRounds||10)}async verifyPasswordWithBcrypt(t,e){return await Fe.compare(t,e)}generateSecureToken(t=32){return Ke.randomBytes(t).toString("hex")}generateTokenPair(t){const e=this.getExpirationSeconds(this.options.tokenExpiration||"15m"),n=K.sign({...t,type:"access"},this.options.jwtSecret,{expiresIn:this.options.tokenExpiration}),s=K.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=K.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 Le(r){return new at(r)}function Ve(r,t){const e=$.model(r,t);return{getAll:async n=>{try{const{page:s=1,limit:i=10,sort:o="_id",order:c="desc"}=n||{},u=(s-1)*i,f=c==="asc"?1:-1,p={[o]:f},[b,_]=await Promise.all([e.find().sort(p).skip(u).limit(i).exec(),e.countDocuments().exec()]),g=Math.ceil(_/i);return{data:b,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:c="_id",order:u="desc"}=s||{},f=(i-1)*o,p=u==="asc"?1:-1,b={[c]:p},[_,g]=await Promise.all([e.find(n).sort(b).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 Be={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]})},He=(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 qe(r,t={}){const e=v.Router(),{middleware:n=[],errorHandler:s=He}=t;n.forEach(o=>e.use(o));const i=o=>async(c,u,f)=>{try{const p={req:c,res:u,next:f,params:c.params,query:c.query,body:c.body};return await o(p)}catch(p){const b={req:c,res:u,next:f,params:c.params,query:c.query,body:c.body};return s(p,b)}};return e.get("/",i(async({req:o,res:c})=>{const u=o.pagination||{page:1,limit:10},f=await r.getAll(u);c.json({success:!0,...f})})),e.get("/:id",i(async({params:o,res:c})=>{const u=await r.getById(o.id);if(!u){c.status(404).json({success:!1,error:"Item not found"});return}c.json({success:!0,data:u})})),e.post("/",i(async({body:o,res:c})=>{const u=await r.create(o);c.status(201).json({success:!0,data:u,message:"Item created successfully"})})),e.put("/:id",i(async({params:o,body:c,res:u})=>{const f=await r.update(o.id,c);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:c})=>{if(!await r.delete(o.id)){c.status(404).json({success:!1,error:"Item not found"});return}c.json({success:!0,message:"Item deleted successfully"})})),e}function We(r,t={}){const e=v.Router(),{middleware:n=[],errorHandler:s=He}=t;n.forEach(o=>e.use(o));const i=o=>async(c,u,f)=>{try{const p={req:c,res:u,next:f,params:c.params,query:c.query,body:c.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 b={req:c,res:u,next:f,params:c.params,query:c.query,body:c.body};return s(p,b)}};return Object.entries(r).forEach(([o,c])=>{const{method:u,handler:f}=c;e[u](o,i(f))}),e}function Z(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 N(r,t,e,n=200,s){r.status(n).json(Z(!0,t,e,void 0,s))}function P(r,t,e=400,n){const s=t instanceof Error?t.message:t;r.status(e).json(Z(!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 ye(r,t,e){r.pagination=pe(r),e()}function Ue(r){return(t,e,n)=>{try{const{error:s,value:i}=r.validate(t.body);if(s){P(e,`Validation error: ${s.message}`,400);return}t.body=i,n()}catch{P(e,"Validation error",400)}}}function Ge(r={},t){const e=v.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 D(r){return(t,e,n)=>{r(t,e,n).catch(n)}}function Je(r){const t=v.Router();return t.get("/",ye,D(async(e,n)=>{const s=await r.getAll(e.pagination);N(n,s)})),t.get("/:id",D(async(e,n)=>{const s=await r.getById(e.params.id);if(!s)return P(n,"Item not found",404);N(n,s)})),t.post("/",D(async(e,n)=>{const s=await r.create(e.body);N(n,s,"Item created successfully",201)})),t.put("/:id",D(async(e,n)=>{const s=await r.update(e.params.id,e.body);if(!s)return P(n,"Item not found",404);N(n,s,"Item updated successfully")})),t.delete("/:id",D(async(e,n)=>{if(!await r.delete(e.params.id))return P(n,"Item not found",404);N(n,null,"Item deleted successfully")})),t}const ut={jsx:L,jsxs:re,jsxDEV:se,createElement:U,Fragment:ne,Component:je,useState:fe,useEffect:$e,useRef:Re,useMemo:Ie,useErrorBoundary:Oe,render:Y,hydrate:Ne,renderToString:O,prepareRender:B,finishRender:H,batchUpdates:J,createContext:Pe,useContext:De,createServer:Me,createAuth:Le,createModel:Ve,FieldTypes:Be,createModelRouter:qe,createCustomRouter:We,createApiRouter:Ge,sendSuccess:N,sendError:P,apiResponse:Z,getPaginationParams:pe,paginationMiddleware:ye,validateRequest:Ue,asyncHandler:D,createRestEndpoints:Je,DatabaseConnector:he};a.Component=je,a.DatabaseConnector=he,a.FieldTypes=Be,a.Fragment=ne,a.apiResponse=Z,a.asyncHandler=D,a.batchUpdates=J,a.createApiRouter=Ge,a.createAuth=Le,a.createContext=Pe,a.createCustomRouter=We,a.createElement=U,a.createModel=Ve,a.createModelRouter=qe,a.createRestEndpoints=Je,a.createServer=Me,a.default=ut,a.finishRender=H,a.getPaginationParams=pe,a.hydrate=Ne,a.jsx=L,a.jsxDEV=se,a.jsxs=re,a.paginationMiddleware=ye,a.prepareRender=B,a.render=Y,a.renderToString=O,a.sendError=P,a.sendSuccess=N,a.useContext=De,a.useEffect=$e,a.useErrorBoundary=Oe,a.useMemo=Ie,a.useRef=Re,a.useState=fe,a.validateRequest=Ue,Object.defineProperties(a,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { jsx, jsxs, createElement, Fragment } from './jsx-runtime/index';
1
+ import { jsx, jsxs, jsxDEV, createElement, Fragment } from './jsx-runtime/index';
2
2
  import { Component } from './component';
3
3
  import { useState, useEffect, useRef, useMemo, useErrorBoundary } from './hooks';
4
4
  import { render, hydrate } from './renderer';
@@ -12,7 +12,8 @@ import { createModel, FieldTypes } from './backend/model';
12
12
  import { createModelRouter, createApiRouter as createCustomRouter } from './backend/router';
13
13
  import { sendSuccess, sendError, apiResponse, getPaginationParams, paginationMiddleware, validateRequest, asyncHandler, createRestEndpoints, createApiRouter } from './backend/api-utils';
14
14
  import { DatabaseConnector } from './backend/database';
15
- export { jsx, jsxs, createElement, Fragment };
15
+ export { jsx, jsxs, jsxDEV, // Add jsxDEV export
16
+ createElement, Fragment };
16
17
  export { useState, useEffect, useRef, useMemo, useErrorBoundary, prepareRender, finishRender, batchUpdates, createContext, useContext };
17
18
  export { Component };
18
19
  export { render, hydrate, renderToString };
@@ -24,6 +25,7 @@ export type { AuthOptions, TokenPair } from './backend/auth';
24
25
  declare const _default: {
25
26
  jsx: typeof jsx;
26
27
  jsxs: typeof jsxs;
28
+ jsxDEV: typeof jsx;
27
29
  createElement: typeof createElement;
28
30
  Fragment: symbol;
29
31
  Component: typeof Component;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Frontend exports
2
- import { jsx, jsxs, createElement, Fragment } from './jsx-runtime/index';
2
+ import { jsx, jsxs, jsxDEV, createElement, Fragment } from './jsx-runtime/index';
3
3
  import { Component } from './component';
4
4
  import { useState, useEffect, useRef, useMemo, useErrorBoundary } from './hooks';
5
5
  import { render, hydrate } from './renderer';
@@ -15,7 +15,8 @@ import { createModelRouter, createApiRouter as createCustomRouter } from './back
15
15
  import { sendSuccess, sendError, apiResponse, getPaginationParams, paginationMiddleware, validateRequest, asyncHandler, createRestEndpoints, createApiRouter } from './backend/api-utils';
16
16
  import { DatabaseConnector } from './backend/database';
17
17
  // Export JSX runtime
18
- export { jsx, jsxs, createElement, Fragment };
18
+ export { jsx, jsxs, jsxDEV, // Add jsxDEV export
19
+ createElement, Fragment };
19
20
  // Export hooks
20
21
  export { useState, useEffect, useRef, useMemo, useErrorBoundary, prepareRender, finishRender, batchUpdates, createContext, useContext };
21
22
  // Export component base class
@@ -29,6 +30,7 @@ export default {
29
30
  // Frontend
30
31
  jsx,
31
32
  jsxs,
33
+ jsxDEV, // Add to default export
32
34
  createElement,
33
35
  Fragment,
34
36
  Component,
@@ -1,8 +1,10 @@
1
- import { jsx, jsxs, createElement, Fragment } from './jsx-runtime';
2
- export { jsx, jsxs, createElement, Fragment };
1
+ import { jsx, jsxs, createElement, Fragment, jsxDEV } from './jsx-runtime';
2
+ export { jsx, jsxs, jsxDEV, // Add export for jsxDEV
3
+ createElement, Fragment };
3
4
  declare const _default: {
4
5
  jsx: typeof jsx;
5
6
  jsxs: typeof jsxs;
7
+ jsxDEV: typeof jsx;
6
8
  createElement: typeof createElement;
7
9
  Fragment: symbol;
8
10
  };
@@ -1,16 +1,19 @@
1
- import { jsx, jsxs, createElement, Fragment } from './jsx-runtime';
2
- export { jsx, jsxs, createElement, Fragment };
1
+ import { jsx, jsxs, createElement, Fragment, jsxDEV } from './jsx-runtime';
2
+ export { jsx, jsxs, jsxDEV, // Add export for jsxDEV
3
+ createElement, Fragment };
3
4
  // For global access in browsers
4
5
  if (typeof window !== 'undefined') {
5
6
  // TypeScript safe way to add properties to window
6
7
  window.jsx = jsx;
7
8
  window.jsxs = jsxs;
9
+ window.jsxDEV = jsxDEV; // Add jsxDEV
8
10
  window.Fragment = Fragment;
9
11
  }
10
12
  // Default export for module usage
11
13
  export default {
12
14
  jsx,
13
15
  jsxs,
16
+ jsxDEV,
14
17
  createElement,
15
18
  Fragment
16
19
  };
@@ -2,3 +2,4 @@ export declare function jsx(type: string | Function, props: any, key?: string):
2
2
  export declare function jsxs(type: string | Function, props: any, key?: string): any;
3
3
  export declare function createElement(vnode: any): HTMLElement | Text;
4
4
  export declare const Fragment: unique symbol;
5
+ export declare const jsxDEV: typeof jsx;
@@ -8,6 +8,7 @@ export function jsx(type, props, key) {
8
8
  key
9
9
  };
10
10
  }
11
+ // Use the jsx function for jsxs as well
11
12
  export function jsxs(type, props, key) {
12
13
  return jsx(type, props, key);
13
14
  }
@@ -89,3 +90,6 @@ export function createElement(vnode) {
89
90
  return element;
90
91
  }
91
92
  export const Fragment = Symbol('Fragment');
93
+ // Add named exports for React JSX compatibility
94
+ export const jsxDEV = jsx;
95
+ // Don't export jsxs again - it's already exported above
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontend-hamroun",
3
- "version": "1.2.8",
3
+ "version": "1.2.10",
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",
@@ -491,3 +491,245 @@ fs.chmodSync(path.join(binDir, 'cli.cjs'), '755');
491
491
  console.log('✅ Created CJS wrapper: bin/cli.cjs');
492
492
 
493
493
  console.log('✅ CLI build process completed');
494
+
495
+ // Create a minimal basic template (update existing code)
496
+ function createBasicTemplate(templateDir) {
497
+ console.log(`📝 Creating minimal basic template at ${templateDir}`);
498
+
499
+ // Create package.json
500
+ const packageJson = {
501
+ "name": "frontend-hamroun-app",
502
+ "private": true,
503
+ "version": "0.1.0",
504
+ "type": "module",
505
+ "scripts": {
506
+ "dev": "vite",
507
+ "build": "tsc && vite build",
508
+ "preview": "vite preview"
509
+ },
510
+ "dependencies": {
511
+ "frontend-hamroun": "latest"
512
+ },
513
+ "devDependencies": {
514
+ "@types/node": "^20.10.0",
515
+ "typescript": "^5.3.2",
516
+ "vite": "^5.0.0",
517
+ "vite-plugin-node-polyfills": "^0.21.0"
518
+ }
519
+ };
520
+
521
+ fs.writeFileSync(
522
+ path.join(templateDir, 'package.json'),
523
+ JSON.stringify(packageJson, null, 2)
524
+ );
525
+
526
+ // Create index.html
527
+ fs.writeFileSync(
528
+ path.join(templateDir, 'index.html'),
529
+ `<!DOCTYPE html>
530
+ <html lang="en">
531
+ <head>
532
+ <meta charset="UTF-8">
533
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
534
+ <title>Frontend Hamroun App</title>
535
+ </head>
536
+ <body>
537
+ <div id="app"></div>
538
+ <script type="module" src="/src/main.ts"></script>
539
+ </body>
540
+ </html>`
541
+ );
542
+
543
+ // Create src directory
544
+ const srcDir = path.join(templateDir, 'src');
545
+ fs.mkdirSync(srcDir, { recursive: true });
546
+
547
+ // Create main.ts
548
+ fs.writeFileSync(
549
+ path.join(srcDir, 'main.ts'),
550
+ `import { render } from 'frontend-hamroun';
551
+ import { App } from './App';
552
+
553
+ document.addEventListener('DOMContentLoaded', () => {
554
+ const rootElement = document.getElementById('app');
555
+ if (rootElement) {
556
+ render(App({}), rootElement);
557
+ console.log('App rendered successfully');
558
+ }
559
+ });`
560
+ );
561
+
562
+ // Create App.ts (not App.tsx)
563
+ fs.writeFileSync(
564
+ path.join(srcDir, 'App.ts'),
565
+ `import { useState, useRef } from 'frontend-hamroun';
566
+
567
+ export function App(props) {
568
+ const [count, setCount] = useState(0);
569
+ const renderCount = useRef(0);
570
+
571
+ renderCount.current++;
572
+
573
+ return {
574
+ type: 'div',
575
+ props: {
576
+ style: {
577
+ fontFamily: 'Arial, sans-serif',
578
+ maxWidth: '600px',
579
+ margin: '0 auto',
580
+ padding: '2rem'
581
+ },
582
+ children: [
583
+ {
584
+ type: 'h1',
585
+ props: {
586
+ style: { textAlign: 'center' },
587
+ children: 'Frontend Hamroun App'
588
+ }
589
+ },
590
+ {
591
+ type: 'p',
592
+ props: {
593
+ style: { textAlign: 'center' },
594
+ children: \`Render count: \${renderCount.current}\`
595
+ }
596
+ },
597
+ {
598
+ type: 'div',
599
+ props: {
600
+ style: {
601
+ display: 'flex',
602
+ flexDirection: 'column',
603
+ alignItems: 'center',
604
+ padding: '1rem',
605
+ border: '1px solid #ccc',
606
+ borderRadius: '8px'
607
+ },
608
+ children: [
609
+ {
610
+ type: 'h2',
611
+ props: {
612
+ children: 'Counter Example'
613
+ }
614
+ },
615
+ {
616
+ type: 'p',
617
+ props: {
618
+ children: \`Count: \${count}\`
619
+ }
620
+ },
621
+ {
622
+ type: 'div',
623
+ props: {
624
+ style: {
625
+ display: 'flex',
626
+ gap: '8px'
627
+ },
628
+ children: [
629
+ {
630
+ type: 'button',
631
+ props: {
632
+ onClick: () => setCount(count - 1),
633
+ style: {
634
+ padding: '8px 16px',
635
+ backgroundColor: '#ff4d4d',
636
+ color: 'white',
637
+ border: 'none',
638
+ borderRadius: '4px',
639
+ cursor: 'pointer'
640
+ },
641
+ children: 'Decrement'
642
+ }
643
+ },
644
+ {
645
+ type: 'button',
646
+ props: {
647
+ onClick: () => setCount(count + 1),
648
+ style: {
649
+ padding: '8px 16px',
650
+ backgroundColor: '#4d79ff',
651
+ color: 'white',
652
+ border: 'none',
653
+ borderRadius: '4px',
654
+ cursor: 'pointer'
655
+ },
656
+ children: 'Increment'
657
+ }
658
+ }
659
+ ]
660
+ }
661
+ }
662
+ ]
663
+ }
664
+ }
665
+ ]
666
+ }
667
+ };
668
+ }`
669
+ );
670
+
671
+ // Create vite.config.ts
672
+ fs.writeFileSync(
673
+ path.join(templateDir, 'vite.config.ts'),
674
+ `import { defineConfig } from 'vite';
675
+ import { nodePolyfills } from 'vite-plugin-node-polyfills';
676
+
677
+ export default defineConfig({
678
+ build: {
679
+ outDir: 'dist',
680
+ emptyOutDir: true
681
+ },
682
+ server: {
683
+ port: 3000,
684
+ open: true
685
+ },
686
+ plugins: [
687
+ nodePolyfills({
688
+ protocolImports: true,
689
+ }),
690
+ ]
691
+ });`
692
+ );
693
+
694
+ // Create tsconfig.json
695
+ fs.writeFileSync(
696
+ path.join(templateDir, 'tsconfig.json'),
697
+ `{
698
+ "compilerOptions": {
699
+ "target": "ES2020",
700
+ "useDefineForClassFields": true,
701
+ "module": "ESNext",
702
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
703
+ "skipLibCheck": true,
704
+ "moduleResolution": "bundler",
705
+ "allowImportingTsExtensions": true,
706
+ "resolveJsonModule": true,
707
+ "isolatedModules": true,
708
+ "noEmit": true,
709
+ "strict": true,
710
+ "noUnusedLocals": true,
711
+ "noUnusedParameters": true,
712
+ "noFallthroughCasesInSwitch": true
713
+ },
714
+ "include": ["src"],
715
+ "references": [{ "path": "./tsconfig.node.json" }]
716
+ }`
717
+ );
718
+
719
+ // Create tsconfig.node.json
720
+ fs.writeFileSync(
721
+ path.join(templateDir, 'tsconfig.node.json'),
722
+ `{
723
+ "compilerOptions": {
724
+ "composite": true,
725
+ "skipLibCheck": true,
726
+ "module": "ESNext",
727
+ "moduleResolution": "bundler",
728
+ "allowSyntheticDefaultImports": true
729
+ },
730
+ "include": ["vite.config.ts"]
731
+ }`
732
+ );
733
+
734
+ console.log(`✅ Created minimal basic template at ${templateDir}`);
735
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  // Frontend exports
2
- import { jsx, jsxs, createElement, Fragment } from './jsx-runtime/index';
2
+ import { jsx, jsxs, jsxDEV, createElement, Fragment } from './jsx-runtime/index';
3
3
  import { Component } from './component';
4
4
  import { useState, useEffect, useRef, useMemo, useErrorBoundary } from './hooks';
5
5
  import { render, hydrate } from './renderer';
@@ -30,6 +30,7 @@ import { DatabaseConnector } from './backend/database';
30
30
  export {
31
31
  jsx,
32
32
  jsxs,
33
+ jsxDEV, // Add jsxDEV export
33
34
  createElement,
34
35
  Fragment
35
36
  };
@@ -104,6 +105,7 @@ export default {
104
105
  // Frontend
105
106
  jsx,
106
107
  jsxs,
108
+ jsxDEV, // Add to default export
107
109
  createElement,
108
110
  Fragment,
109
111
  Component,
@@ -1,8 +1,9 @@
1
- import { jsx, jsxs, createElement, Fragment } from './jsx-runtime';
1
+ import { jsx, jsxs, createElement, Fragment, jsxDEV } from './jsx-runtime';
2
2
 
3
3
  export {
4
4
  jsx,
5
5
  jsxs,
6
+ jsxDEV, // Add export for jsxDEV
6
7
  createElement,
7
8
  Fragment
8
9
  };
@@ -12,6 +13,7 @@ if (typeof window !== 'undefined') {
12
13
  // TypeScript safe way to add properties to window
13
14
  (window as any).jsx = jsx;
14
15
  (window as any).jsxs = jsxs;
16
+ (window as any).jsxDEV = jsxDEV; // Add jsxDEV
15
17
  (window as any).Fragment = Fragment;
16
18
  }
17
19
 
@@ -19,6 +21,7 @@ if (typeof window !== 'undefined') {
19
21
  export default {
20
22
  jsx,
21
23
  jsxs,
24
+ jsxDEV,
22
25
  createElement,
23
26
  Fragment
24
27
  };
@@ -12,6 +12,7 @@ export function jsx(type: string | Function, props: any, key?: string): any {
12
12
  };
13
13
  }
14
14
 
15
+ // Use the jsx function for jsxs as well
15
16
  export function jsxs(type: string | Function, props: any, key?: string): any {
16
17
  return jsx(type, props, key);
17
18
  }
@@ -97,3 +98,7 @@ export function createElement(vnode: any): HTMLElement | Text {
97
98
  }
98
99
 
99
100
  export const Fragment = Symbol('Fragment');
101
+
102
+ // Add named exports for React JSX compatibility
103
+ export const jsxDEV = jsx;
104
+ // Don't export jsxs again - it's already exported above
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true
8
+ },
9
+ "include": ["vite.config.ts"]
10
+ }
@@ -12,7 +12,8 @@ const api = createApiClient({
12
12
  document.addEventListener('DOMContentLoaded', () => {
13
13
  const rootElement = document.getElementById('app');
14
14
  if (rootElement) {
15
- render(<App api={api} />, rootElement);
15
+ // Call App as a function to create the VDOM structure
16
+ render(App({ api }), rootElement);
16
17
  console.log('App rendered successfully');
17
18
  } else {
18
19
  console.error('Root element #app not found');