frontend-hamroun 1.2.9 → 1.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/frontend-hamroun.es.js +182 -179
- package/dist/frontend-hamroun.umd.js +9 -9
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/dist/jsx-runtime/index.d.ts +4 -2
- package/dist/jsx-runtime/index.js +5 -2
- package/dist/jsx-runtime/jsx-runtime.d.ts +1 -0
- package/dist/jsx-runtime/jsx-runtime.js +4 -0
- package/package.json +1 -1
- package/scripts/build-cli.js +35 -0
- package/src/index.ts +3 -1
- package/src/jsx-runtime/index.ts +4 -1
- package/src/jsx-runtime/jsx-runtime.ts +5 -0
- package/templates/basic-app/src/main.ts +2 -1
- package/templates/basic-app/src/shims.ts +9 -0
- package/templates/basic-app/tsconfig.json +7 -1
- package/templates/basic-app/vite.config.ts +11 -1
- package/templates/full-stack/src/shims.ts +9 -0
- package/templates/full-stack/vite.config.ts +6 -1
@@ -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,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}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,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}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(
|
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(
|
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"}">${
|
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(
|
20
|
+
${h.scripts?h.scripts.map(q=>`<script src="${q}"><\/script>`).join(`
|
21
21
|
`):""}
|
22
22
|
</body>
|
23
23
|
</html>
|
24
|
-
`)}catch(
|
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(
|
62
|
+
${Object.keys(me).length>0?`
|
63
63
|
🖥️ Registered SSR Routes:
|
64
|
-
${Object.keys(
|
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,
|
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,
|
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,
|
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,
|
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
package/scripts/build-cli.js
CHANGED
@@ -733,3 +733,38 @@ export default defineConfig({
|
|
733
733
|
|
734
734
|
console.log(`✅ Created minimal basic template at ${templateDir}`);
|
735
735
|
}
|
736
|
+
|
737
|
+
// Create React compatibility shims
|
738
|
+
function createTemplateShims(templateDir) {
|
739
|
+
// Create src directory if it doesn't exist
|
740
|
+
const srcDir = path.join(templateDir, 'src');
|
741
|
+
if (!fs.existsSync(srcDir)) {
|
742
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
743
|
+
}
|
744
|
+
|
745
|
+
// Create shims.ts file for React JSX compatibility
|
746
|
+
fs.writeFileSync(
|
747
|
+
path.join(srcDir, 'shims.ts'),
|
748
|
+
`// This file provides compatibility shims for React JSX imports
|
749
|
+
|
750
|
+
import { jsx } from 'frontend-hamroun';
|
751
|
+
|
752
|
+
// Export the jsx function as jsxDEV for React compatibility
|
753
|
+
export const jsxDEV = jsx;
|
754
|
+
|
755
|
+
// Export a Fragment symbol
|
756
|
+
export const Fragment = Symbol('Fragment');
|
757
|
+
|
758
|
+
// Default export as React compatibility layer
|
759
|
+
export default {
|
760
|
+
createElement: jsx,
|
761
|
+
Fragment
|
762
|
+
};
|
763
|
+
`
|
764
|
+
);
|
765
|
+
|
766
|
+
console.log(`✅ Created React compatibility shims in ${templateDir}`);
|
767
|
+
}
|
768
|
+
|
769
|
+
// Call this function when creating templates
|
770
|
+
// ...existing code...
|
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,
|
package/src/jsx-runtime/index.ts
CHANGED
@@ -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
|
@@ -12,7 +12,8 @@ const api = createApiClient({
|
|
12
12
|
document.addEventListener('DOMContentLoaded', () => {
|
13
13
|
const rootElement = document.getElementById('app');
|
14
14
|
if (rootElement) {
|
15
|
-
|
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');
|
@@ -0,0 +1,9 @@
|
|
1
|
+
// This file provides compatibility shims for React JSX imports
|
2
|
+
|
3
|
+
import { jsx } from 'frontend-hamroun';
|
4
|
+
|
5
|
+
// Export the jsx function as jsxDEV for React compatibility
|
6
|
+
export const jsxDEV = jsx;
|
7
|
+
|
8
|
+
// Export a Fragment symbol
|
9
|
+
export const Fragment = Symbol('Fragment');
|
@@ -13,7 +13,13 @@
|
|
13
13
|
"strict": true,
|
14
14
|
"noUnusedLocals": true,
|
15
15
|
"noUnusedParameters": true,
|
16
|
-
"noFallthroughCasesInSwitch": true
|
16
|
+
"noFallthroughCasesInSwitch": true,
|
17
|
+
"paths": {
|
18
|
+
"react": ["./node_modules/frontend-hamroun"],
|
19
|
+
"react-dom": ["./node_modules/frontend-hamroun"],
|
20
|
+
"react/jsx-runtime": ["./node_modules/frontend-hamroun"],
|
21
|
+
"react/jsx-dev-runtime": ["./node_modules/frontend-hamroun"]
|
22
|
+
}
|
17
23
|
},
|
18
24
|
"include": ["src"],
|
19
25
|
"references": [{ "path": "./tsconfig.node.json" }]
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { defineConfig } from 'vite';
|
2
2
|
import { nodePolyfills } from 'vite-plugin-node-polyfills';
|
3
|
+
import path from 'path';
|
3
4
|
|
4
5
|
export default defineConfig({
|
5
6
|
build: {
|
@@ -8,6 +9,10 @@ export default defineConfig({
|
|
8
9
|
rollupOptions: {
|
9
10
|
// Mark server-side dependencies as external
|
10
11
|
external: [
|
12
|
+
'react',
|
13
|
+
'react-dom',
|
14
|
+
'react/jsx-runtime',
|
15
|
+
'react/jsx-dev-runtime',
|
11
16
|
'express',
|
12
17
|
'compression',
|
13
18
|
'helmet',
|
@@ -42,7 +47,12 @@ export default defineConfig({
|
|
42
47
|
// Remove any Node.js specific imports that might cause issues
|
43
48
|
'bcrypt': 'frontend-hamroun',
|
44
49
|
'jsonwebtoken': 'frontend-hamroun',
|
45
|
-
'mongoose': 'frontend-hamroun'
|
50
|
+
'mongoose': 'frontend-hamroun',
|
51
|
+
// Alias React imports to empty modules
|
52
|
+
'react': path.resolve(__dirname, 'src/shims.ts'),
|
53
|
+
'react-dom': 'frontend-hamroun',
|
54
|
+
'react/jsx-runtime': path.resolve(__dirname, 'src/shims.ts'),
|
55
|
+
'react/jsx-dev-runtime': path.resolve(__dirname, 'src/shims.ts')
|
46
56
|
}
|
47
57
|
}
|
48
58
|
});
|
@@ -0,0 +1,9 @@
|
|
1
|
+
// This file provides compatibility shims for React JSX imports
|
2
|
+
|
3
|
+
import { jsx } from 'frontend-hamroun';
|
4
|
+
|
5
|
+
// Export the jsx function as jsxDEV for React compatibility
|
6
|
+
export const jsxDEV = jsx;
|
7
|
+
|
8
|
+
// Export a Fragment symbol
|
9
|
+
export const Fragment = Symbol('Fragment');
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { defineConfig } from 'vite';
|
2
2
|
import { nodePolyfills } from 'vite-plugin-node-polyfills';
|
3
|
+
import path from 'path';
|
3
4
|
|
4
5
|
export default defineConfig({
|
5
6
|
esbuild: {
|
@@ -74,7 +75,11 @@ export default defineConfig({
|
|
74
75
|
resolve: {
|
75
76
|
alias: {
|
76
77
|
'@mswjs/interceptors/presets/node': { find: /^@mswjs\/interceptors\/presets\/node/, replacement: '{}' },
|
77
|
-
'./util/nw-pre-gyp/index.html': { find: './util/nw-pre-gyp/index.html', replacement: '{}' }
|
78
|
+
'./util/nw-pre-gyp/index.html': { find: './util/nw-pre-gyp/index.html', replacement: '{}' },
|
79
|
+
'react/jsx-runtime': path.resolve(__dirname, 'src/shims.ts'),
|
80
|
+
'react/jsx-dev-runtime': path.resolve(__dirname, 'src/shims.ts'),
|
81
|
+
'react': path.resolve(__dirname, 'src/shims.ts'),
|
82
|
+
'react-dom': 'frontend-hamroun'
|
78
83
|
}
|
79
84
|
}
|
80
85
|
});
|