frontend-hamroun 1.2.15 → 1.2.17
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/README.md +4 -0
- package/bin/cli.js +673 -0
- package/dist/component.d.ts +1 -1
- package/dist/context.d.ts +4 -3
- package/dist/index.client.d.ts +11 -0
- package/dist/index.d.ts +9 -89
- package/dist/index.js +396 -67
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +392 -0
- package/dist/index.mjs.map +1 -0
- package/dist/jsx-runtime/jsx-runtime.d.ts +0 -1
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/renderer.d.ts +0 -10
- package/dist/server-renderer.d.ts +0 -3
- package/dist/server-types.d.ts +42 -0
- package/package.json +69 -50
- package/templates/basic-app/index.html +6 -6
- package/templates/basic-app/package.json +15 -11
- package/templates/basic-app/postcss.config.js +0 -1
- package/templates/basic-app/src/main.tsx +1 -10
- package/templates/basic-app/tailwind.config.js +2 -23
- package/templates/basic-app/tsconfig.json +4 -17
- package/templates/basic-app/vite.config.ts +3 -54
- package/templates/fullstack-app/api/hello.ts +18 -0
- package/templates/fullstack-app/api/users/[id].ts +73 -0
- package/templates/fullstack-app/api/users/index.ts +32 -0
- package/templates/fullstack-app/package.json +31 -0
- package/templates/fullstack-app/server.ts +46 -0
- package/templates/fullstack-app/src/pages/index.tsx +59 -0
- package/templates/ssr-template/vite.config.ts +1 -11
- package/bin/cli.cjs +0 -16
- package/bin/cli.mjs +0 -237
- package/dist/backend/api-utils.d.ts +0 -38
- package/dist/backend/api-utils.js +0 -135
- package/dist/backend/auth.d.ts +0 -134
- package/dist/backend/auth.js +0 -387
- package/dist/backend/database.d.ts +0 -27
- package/dist/backend/database.js +0 -91
- package/dist/backend/model.d.ts +0 -43
- package/dist/backend/model.js +0 -178
- package/dist/backend/router.d.ts +0 -27
- package/dist/backend/router.js +0 -137
- package/dist/backend/server.d.ts +0 -19
- package/dist/backend/server.js +0 -268
- package/dist/backend/types.d.ts +0 -217
- package/dist/backend/types.js +0 -1
- package/dist/batch.js +0 -22
- package/dist/cli/index.d.ts +0 -2
- package/dist/cli/index.js +0 -215
- package/dist/component.js +0 -84
- package/dist/components/Counter.js +0 -2
- package/dist/context.js +0 -18
- package/dist/frontend-hamroun.es.js +0 -1378
- package/dist/frontend-hamroun.umd.js +0 -66
- package/dist/hooks.js +0 -164
- package/dist/jsx-runtime/index.d.ts +0 -11
- package/dist/jsx-runtime/index.js +0 -19
- package/dist/jsx-runtime/jsx-dev-runtime.js +0 -1
- package/dist/jsx-runtime/jsx-runtime.js +0 -95
- package/dist/jsx-runtime.js +0 -192
- package/dist/renderer.js +0 -51
- package/dist/server-renderer.js +0 -102
- package/dist/types.js +0 -1
- package/dist/vdom.js +0 -27
- package/scripts/build-cli.js +0 -1107
- package/scripts/generate.js +0 -134
- package/src/backend/api-utils.ts +0 -178
- package/src/backend/auth.ts +0 -544
- package/src/backend/database.ts +0 -104
- package/src/backend/model.ts +0 -198
- package/src/backend/router.ts +0 -176
- package/src/backend/server.ts +0 -330
- package/src/backend/types.ts +0 -257
- package/src/batch.ts +0 -24
- package/src/cli/index.js +0 -554
- package/src/cli/index.ts +0 -257
- package/src/component.ts +0 -98
- package/src/components/Counter.tsx +0 -4
- package/src/context.ts +0 -29
- package/src/hooks.ts +0 -211
- package/src/index.ts +0 -144
- package/src/jsx-runtime/index.ts +0 -27
- package/src/jsx-runtime/jsx-dev-runtime.ts +0 -0
- package/src/jsx-runtime/jsx-runtime.ts +0 -104
- package/src/jsx-runtime.ts +0 -226
- package/src/renderer.ts +0 -55
- package/src/server-renderer.ts +0 -114
- package/src/shims.d.ts +0 -20
- package/src/types/bcrypt.d.ts +0 -30
- package/src/types/jsonwebtoken.d.ts +0 -55
- package/src/types.d.ts +0 -26
- package/src/types.ts +0 -21
- package/src/vdom.ts +0 -34
- package/templates/basic/.eslintignore +0 -5
- package/templates/basic/.eslintrc.json +0 -25
- package/templates/basic/docs/rapport_pfe.aux +0 -27
- package/templates/basic/docs/rapport_pfe.log +0 -399
- package/templates/basic/docs/rapport_pfe.out +0 -10
- package/templates/basic/docs/rapport_pfe.pdf +0 -0
- package/templates/basic/docs/rapport_pfe.tex +0 -68
- package/templates/basic/docs/rapport_pfe.toc +0 -14
- package/templates/basic/index.html +0 -12
- package/templates/basic/jsconfig.json +0 -14
- package/templates/basic/package.json +0 -20
- package/templates/basic/postcss.config.js +0 -7
- package/templates/basic/src/App.js +0 -105
- package/templates/basic/src/App.tsx +0 -65
- package/templates/basic/src/api.ts +0 -58
- package/templates/basic/src/components/Counter.tsx +0 -26
- package/templates/basic/src/components/Header.tsx +0 -9
- package/templates/basic/src/components/TodoList.tsx +0 -90
- package/templates/basic/src/main.css +0 -3
- package/templates/basic/src/main.js +0 -11
- package/templates/basic/src/main.ts +0 -20
- package/templates/basic/src/main.tsx +0 -144
- package/templates/basic/src/server.ts +0 -99
- package/templates/basic/tailwind.config.js +0 -32
- package/templates/basic/tsconfig.json +0 -20
- package/templates/basic/tsconfig.node.json +0 -10
- package/templates/basic/vite.config.js +0 -18
- package/templates/basic/vite.config.ts +0 -86
- package/templates/basic-app/src/App.js +0 -105
- package/templates/basic-app/src/App.tsx +0 -143
- package/templates/basic-app/src/api.ts +0 -58
- package/templates/basic-app/src/components/Counter.tsx +0 -26
- package/templates/basic-app/src/components/Header.tsx +0 -9
- package/templates/basic-app/src/components/TodoList.tsx +0 -90
- package/templates/basic-app/src/main.js +0 -10
- package/templates/basic-app/src/main.ts +0 -21
- package/templates/basic-app/src/react/index.ts +0 -35
- package/templates/basic-app/src/react/jsx-dev-runtime.ts +0 -13
- package/templates/basic-app/src/react/jsx-runtime.ts +0 -12
- package/templates/basic-app/src/server.ts +0 -99
- package/templates/basic-app/src/shims.ts +0 -9
- package/templates/basic-app/tsconfig.node.json +0 -10
- package/templates/basic-app/vite.config.js +0 -22
- package/templates/full-stack/.env.example +0 -11
- package/templates/full-stack/README.md +0 -51
- package/templates/full-stack/index.html +0 -12
- package/templates/full-stack/jsconfig.json +0 -14
- package/templates/full-stack/package.json +0 -20
- package/templates/full-stack/src/App.js +0 -105
- package/templates/full-stack/src/client/App.tsx +0 -50
- package/templates/full-stack/src/client/components/Header.tsx +0 -42
- package/templates/full-stack/src/client/components/UserList.tsx +0 -29
- package/templates/full-stack/src/client/main.tsx +0 -5
- package/templates/full-stack/src/main.css +0 -3
- package/templates/full-stack/src/main.js +0 -11
- package/templates/full-stack/src/main.ts +0 -20
- package/templates/full-stack/src/server/index.ts +0 -99
- package/templates/full-stack/src/server/routes/auth.ts +0 -39
- package/templates/full-stack/src/server/routes/users.ts +0 -48
- package/templates/full-stack/src/shims.ts +0 -9
- package/templates/full-stack/tsconfig.json +0 -20
- package/templates/full-stack/tsconfig.node.json +0 -10
- package/templates/full-stack/tsconfig.server.json +0 -15
- package/templates/full-stack/vite.config.js +0 -18
- package/templates/full-stack/vite.config.ts +0 -85
@@ -1,66 +0,0 @@
|
|
1
|
-
(function(u,v){typeof exports=="object"&&typeof module<"u"?v(exports,require("express"),require("path"),require("compression"),require("helmet"),require("morgan"),require("mongoose"),require("fs"),require("bcrypt")):typeof define=="function"&&define.amd?define(["exports","express","path","compression","helmet","morgan","mongoose","fs","bcrypt"],v):(u=typeof globalThis<"u"?globalThis:u||self,v(u["frontend-hamroun"]={},u.express,u.path,u.compression,u.helmet,u.morgan,u.mongoose,u.fs))})(this,function(u,v,Ee,Je,Qe,Ye,_,ze){"use strict";const be=globalThis||void 0||self;function Xe(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}var Te={exports:{}},y=Te.exports={},k,A;function K(){throw new Error("setTimeout has not been defined")}function ee(){throw new Error("clearTimeout has not been defined")}(function(){try{typeof setTimeout=="function"?k=setTimeout:k=K}catch{k=K}try{typeof clearTimeout=="function"?A=clearTimeout:A=ee}catch{A=ee}})();function ve(r){if(k===setTimeout)return setTimeout(r,0);if((k===K||!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 Ze(r){if(A===clearTimeout)return clearTimeout(r);if((A===ee||!A)&&clearTimeout)return A=clearTimeout,clearTimeout(r);try{return A(r)}catch{try{return A.call(null,r)}catch{return A.call(this,r)}}}var C=[],M=!1,R,W=-1;function Ke(){!M||!R||(M=!1,R.length?C=R.concat(C):W=-1,C.length&&Se())}function Se(){if(!M){var r=ve(Ke);M=!0;for(var t=C.length;t;){for(R=C,C=[];++W<t;)R&&R[W].run();W=-1,t=C.length}R=null,M=!1,Ze(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 et=Te.exports;const E=Xe(et),x=typeof window<"u"?window:typeof be<"u"?be:{};function L(r,t,e){return{type:r,props:t||{},key:e}}function te(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 a=require("fs"),f=require("path").resolve(E.cwd(),"jsx-runtime-stats.json");a.writeFileSync(f,JSON.stringify(x.__renderStats,null,2)),console.log(`JSX runtime stats written to ${f}`)}catch(a){console.error("Failed to write stats file:",a)}})),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 re=Symbol("Fragment"),ne=L;typeof window<"u"&&(window.jsx=L,window.jsxs=te,window.jsxDEV=ne,window.Fragment=re);const tt=typeof window<"u"&&typeof document<"u";async function I(r){var t;if(console.log("Creating element from:",r),!tt){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,a){this.attributes[o]=a},appendChild:function(o){this.childNodes.push(o)}};for(const[o,a]of Object.entries(n||{}))if(o!=="children")if(o.startsWith("on")&&typeof a=="function"){const c=o.toLowerCase().slice(2);s.__events||(s.__events={}),s.__events[c]=a}else o==="style"&&typeof a=="object"?Object.assign(s.style,a):o==="className"?s.setAttribute("class",String(a)):o!=="key"&&o!=="ref"&&s.setAttribute(o,String(a));const i=n==null?void 0:n.children;if(i!=null){const o=Array.isArray(i)?i.flat():[i];for(const a of o){const c=await I(a);s.appendChild(c)}}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||{}),a=await I(o);return a instanceof Element&&a.setAttribute("data-component-id",e.name||e.toString()),a}catch(o){return console.error("Error rendering component:",o),document.createTextNode("")}const s=document.createElement(e);for(const[o,a]of Object.entries(n||{}))if(o!=="children")if(o.startsWith("on")&&typeof a=="function"){const c=o.toLowerCase().slice(2),f=(t=s.__events)==null?void 0:t[c];f&&s.removeEventListener(c,f),s.addEventListener(c,a),s.__events||(s.__events={}),s.__events[c]=a}else o==="style"&&typeof a=="object"?Object.assign(s.style,a):o==="className"?s.setAttribute("class",String(a)):o!=="key"&&o!=="ref"&&s.setAttribute(o,String(a));const i=n==null?void 0:n.children;if(i!=null){const o=Array.isArray(i)?i.flat():[i];for(const a of o){const c=await I(a);s.appendChild(c)}}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,V=new Map,ie=new Map,ae=new Map;let ce=null,ue=null,le=null;const Ce=typeof window>"u",Q=new Map;function je(r,t,e){ce=r,ue=e,le=t}function B(){return l++,T.set(l,0),l}function q(){Ce&&Q.delete(l),l=0}function de(r){if(!l)throw new Error("useState must be called within a render");if(Ce){Q.has(l)||Q.set(l,new Map);const i=Q.get(l),o=T.get(l)||0;i.has(o)||i.set(o,r);const a=i.get(o),c=f=>{};return T.set(l,o+1),[a,c]}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);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 _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);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 Re(r){try{const t=V.get(r);t&&(t.forEach(e=>{e.cleanup&&e.cleanup()}),V.set(r,[])),ce&&ue&&le&&await ce(le,ue)}catch(t){console.error("Error during rerender:",t)}}function xe(){const[r,t]=de(null);return[r,()=>t(null)]}let Y=!1;async function Ne(r,t){Y=!0;try{await z(r,t)}finally{Y=!1}}async function z(r,t){console.log("Rendering to:",t.id||"unnamed-container"),J(async()=>{const e=B();try{je(z,r,t);const n=await I(r);Y||(t.innerHTML=""),Y&&t.firstChild?console.log("Hydrating existing DOM"):t.appendChild(n)}finally{q()}})}async function N(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(N))).join("");if("type"in r&&r.props!==void 0){const{type:t,props:e}=r;if(typeof t=="function")try{B();const i=await t(e||{}),o=await N(i);return q(),o}catch(i){return console.error("Error rendering component:",i),""}if(t===Symbol.for("react.fragment")||t.name==="Fragment"){if(e.children){const i=Array.isArray(e.children)?e.children:[e.children];return(await Promise.all(i.map(N))).join("")}return""}let n=`<${t}`;for(const[i,o]of Object.entries(e||{}))i==="children"||i==="key"||(i==="className"?n+=` class="${X(String(o))}"`:i==="style"&&typeof o=="object"?n+=` style="${rt(o||{})}"`:i.startsWith("on")||(n+=` ${i}="${X(String(o))}"`));if(new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]).has(t))return n+"/>";if(n+=">",e!=null&&e.children){const i=Array.isArray(e.children)?e.children:[e.children];for(const o of i)n+=await N(o)}return n+`</${t}>`}return X(String(r))}finally{q()}}function X(r){return r.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function rt(r){return Object.entries(r).map(([t,e])=>`${nt(t)}:${e}`).join(";")}function nt(r){return r.replace(/[A-Z]/g,t=>"-"+t.toLowerCase())}function Oe(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:a=[],enableCompression:c=!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})),c&&t.use(Je()),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()}),a.forEach(d=>t.use(d)),n){const d=Ee.resolve(E.cwd(),n);ze.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={},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},at=await N(m(we));S.send(`
|
2
|
-
<!DOCTYPE html>
|
3
|
-
<html lang="${h.lang||"en"}">
|
4
|
-
<head>
|
5
|
-
<meta charset="UTF-8">
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
-
<title>${h.title||"Frontend Hamroun App"}</title>
|
8
|
-
${h.meta?h.meta.map(H=>`<meta ${Object.entries(H).map(([ct,ut])=>`${ct}="${ut}"`).join(" ")}>`).join(`
|
9
|
-
`):""}
|
10
|
-
${h.head||""}
|
11
|
-
${h.styles?`<style>${h.styles}</style>`:""}
|
12
|
-
${h.styleSheets?h.styleSheets.map(H=>`<link rel="stylesheet" href="${H}">`).join(`
|
13
|
-
`):""}
|
14
|
-
</head>
|
15
|
-
<body ${h.bodyAttributes||""}>
|
16
|
-
<div id="${h.rootId||"root"}">${at}</div>
|
17
|
-
<script>
|
18
|
-
window.__INITIAL_DATA__ = ${JSON.stringify(h.initialData||{})};
|
19
|
-
<\/script>
|
20
|
-
${h.scripts?h.scripts.map(H=>`<script src="${H}"><\/script>`).join(`
|
21
|
-
`):""}
|
22
|
-
</body>
|
23
|
-
</html>
|
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
|
-
<!DOCTYPE html>
|
26
|
-
<html>
|
27
|
-
<head>
|
28
|
-
<title>Error - ${S}</title>
|
29
|
-
<style>
|
30
|
-
body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }
|
31
|
-
.error { background: #f8d7da; border: 1px solid #f5c6cb; padding: 1rem; border-radius: 4px; }
|
32
|
-
.stack { background: #f8f9fa; padding: 1rem; border-radius: 4px; overflow: auto; }
|
33
|
-
</style>
|
34
|
-
</head>
|
35
|
-
<body>
|
36
|
-
<h1>Error ${S}</h1>
|
37
|
-
<div class="error">${$?d.message:"Internal Server Error"}</div>
|
38
|
-
${$&&d.stack?`<pre class="stack">${d.stack}</pre>`:""}
|
39
|
-
</body>
|
40
|
-
</html>
|
41
|
-
`)}),t.use((d,m)=>{d.path.startsWith(i)?m.status(404).json({success:!1,error:"Not Found"}):m.status(404).send(`
|
42
|
-
<!DOCTYPE html>
|
43
|
-
<html>
|
44
|
-
<head>
|
45
|
-
<title>404 - Not Found</title>
|
46
|
-
<style>
|
47
|
-
body { font-family: system-ui, sans-serif; padding: 2rem; max-width: 800px; margin: 0 auto; }
|
48
|
-
</style>
|
49
|
-
</head>
|
50
|
-
<body>
|
51
|
-
<h1>404 - Not Found</h1>
|
52
|
-
<p>The requested resource was not found on this server.</p>
|
53
|
-
<p><a href="/">Return to homepage</a></p>
|
54
|
-
</body>
|
55
|
-
</html>
|
56
|
-
`)}),t.start=d=>{const m=t.listen(e,()=>{console.log(`
|
57
|
-
🚀 Frontend Hamroun server running at http://localhost:${e}
|
58
|
-
${Object.keys(F).length>0?`
|
59
|
-
📡 Registered API Routes:
|
60
|
-
${Object.keys(F).map(w=>` ${w}`).join(`
|
61
|
-
`)}`:""}
|
62
|
-
${Object.keys(me).length>0?`
|
63
|
-
🖥️ Registered SSR Routes:
|
64
|
-
${Object.keys(me).map(w=>` ${w}`).join(`
|
65
|
-
`)}`:""}
|
66
|
-
`),d&&d()}),h=async w=>{console.log(`${w} signal received: closing HTTP server and cleaning up`),m.close(async()=>{console.log("HTTP server closed"),g&&g.isConnected()&&(await g.disconnect(),console.log("Database connection closed")),E.exit(0)}),setTimeout(()=>{console.error("Could not close connections in time, forcefully shutting down"),E.exit(1)},1e4)};return E.on("SIGTERM",()=>h("SIGTERM")),E.on("SIGINT",()=>h("SIGINT")),m},t}const he=require("jsonwebtoken"),Me=require("bcrypt"),st=require("crypto");class ot{constructor(t){if(this.loginAttempts=new Map,this.login=async(e,n)=>{try{const{username:s,password:i}=e.body,o=e.ip||e.connection.remoteAddress||"";if(!this.checkRateLimit(o)){n.status(429).json({success:!1,message:"Too many login attempts. Please try again later."});return}if(!s||!i){n.status(400).json({success:!1,message:"Username and password are required"});return}if(!this.options.findUser){n.status(500).json({success:!1,message:"User finder function not configured"});return}const a=await this.options.findUser(s);if(!a){n.status(401).json({success:!1,message:"Invalid credentials"});return}if(!await this.options.verifyPassword(i,a.password)){n.status(401).json({success:!1,message:"Invalid credentials"});return}const f={...a};delete f.password;const p=this.generateTokenPair({id:a.id||a._id,username:a.username,role:a.role||"user"});if(this.options.saveRefreshToken){const b=new Date;b.setSeconds(b.getSeconds()+this.getExpirationSeconds(this.options.refreshExpiration||"7d")),await this.options.saveRefreshToken(a.id||a._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 a=this.verifyToken(o,"refresh");if(this.options.verifyRefreshToken&&!await this.options.verifyRefreshToken(a.id,o)){this.clearAuthCookies(n),n.status(401).json({success:!1,message:"Invalid refresh token"});return}const c=this.generateTokenPair({id:a.id,...this.options.findUser?await this.options.findUser(a.id):{}});if(this.options.saveRefreshToken){const p=new Date;p.setSeconds(p.getSeconds()+this.getExpirationSeconds(this.options.refreshExpiration||"7d")),await this.options.saveRefreshToken(a.id,c.refreshToken,p)}(((i=e.cookies)==null?void 0:i.accessToken)||e.body.useCookies)&&this.setAuthCookies(n,c),n.json({success:!0,message:"Token refreshed successfully",tokens:c})}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 c=e.headers.authorization;c&&c.startsWith("Bearer ")&&(o=c.split(" ")[1])}if(!o){n.status(401).json({success:!1,message:"Authentication required"});return}const a=this.verifyToken(o,"access");e.user=a,s()}catch(o){n.status(401).json({success:!1,message:"Invalid or expired token",error:E.env.NODE_ENV!=="production"?o.message:void 0})}},this.hasRole=e=>(n,s,i)=>{const o=n.user;if(!o){s.status(401).json({success:!1,message:"Authentication required"});return}(Array.isArray(e)?e:[e]).includes(o.role)?i():s.status(403).json({success:!1,message:"Insufficient permissions"})},this.options={tokenExpiration:"15m",refreshExpiration:"7d",saltRounds:10,secureCookies:E.env.NODE_ENV==="production",httpOnlyCookies:!0,rateLimit:!0,...t,refreshSecret:t.refreshSecret||t.jwtSecret},!t.jwtSecret)throw new Error("JWT secret is required for authentication");this.options.verifyPassword||(this.options.verifyPassword=this.verifyPasswordWithBcrypt)}async hashPassword(t){return await Me.hash(t,this.options.saltRounds||10)}async verifyPasswordWithBcrypt(t,e){return await Me.compare(t,e)}generateSecureToken(t=32){return st.randomBytes(t).toString("hex")}generateTokenPair(t){const e=this.getExpirationSeconds(this.options.tokenExpiration||"15m"),n=he.sign({...t,type:"access"},this.options.jwtSecret,{expiresIn:this.options.tokenExpiration}),s=he.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=he.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 ot(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:a="desc"}=n||{},c=(s-1)*i,f=a==="asc"?1:-1,p={[o]:f},[b,$]=await Promise.all([e.find().sort(p).skip(c).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:a="_id",order:c="desc"}=s||{},f=(i-1)*o,p=c==="asc"?1:-1,b={[a]: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 Ve={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]})},Be=(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=Be}=t;n.forEach(o=>e.use(o));const i=o=>async(a,c,f)=>{try{const p={req:a,res:c,next:f,params:a.params,query:a.query,body:a.body};return await o(p)}catch(p){const b={req:a,res:c,next:f,params:a.params,query:a.query,body:a.body};return s(p,b)}};return e.get("/",i(async({req:o,res:a})=>{const c=o.pagination||{page:1,limit:10},f=await r.getAll(c);a.json({success:!0,...f})})),e.get("/:id",i(async({params:o,res:a})=>{const c=await r.getById(o.id);if(!c){a.status(404).json({success:!1,error:"Item not found"});return}a.json({success:!0,data:c})})),e.post("/",i(async({body:o,res:a})=>{const c=await r.create(o);a.status(201).json({success:!0,data:c,message:"Item created successfully"})})),e.put("/:id",i(async({params:o,body:a,res:c})=>{const f=await r.update(o.id,a);if(!f){c.status(404).json({success:!1,error:"Item not found"});return}c.json({success:!0,data:f,message:"Item updated successfully"})})),e.delete("/:id",i(async({params:o,res:a})=>{if(!await r.delete(o.id)){a.status(404).json({success:!1,error:"Item not found"});return}a.json({success:!0,message:"Item deleted successfully"})})),e}function He(r,t={}){const e=v.Router(),{middleware:n=[],errorHandler:s=Be}=t;n.forEach(o=>e.use(o));const i=o=>async(a,c,f)=>{try{const p={req:a,res:c,next:f,params:a.params,query:a.query,body:a.body};return c.headersSent?void 0:await o(p)}catch(p){if(c.headersSent){console.error("Error occurred after response was sent:",p);return}const b={req:a,res:c,next:f,params:a.params,query:a.query,body:a.body};return s(p,b)}};return Object.entries(r).forEach(([o,a])=>{const{method:c,handler:f}=a;e[c](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 O(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 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("/",ye,D(async(e,n)=>{const s=await r.getAll(e.pagination);O(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);O(n,s)})),t.post("/",D(async(e,n)=>{const s=await r.create(e.body);O(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);O(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);O(n,null,"Item deleted successfully")})),t}const it={jsx:L,jsxs:te,jsxDEV:ne,createElement:U,Fragment:re,Component:Ae,useState:de,useEffect:$e,useRef:Ie,useMemo:_e,useErrorBoundary:xe,render:z,hydrate:Ne,renderToString:N,prepareRender:B,finishRender:q,batchUpdates:J,createContext:Oe,useContext:Pe,createServer:De,createAuth:Fe,createModel:Le,FieldTypes:Ve,createModelRouter:qe,createCustomRouter:He,createApiRouter:Ue,sendSuccess:O,sendError:P,apiResponse:Z,getPaginationParams:pe,paginationMiddleware:ye,validateRequest:We,asyncHandler:D,createRestEndpoints:Ge,DatabaseConnector:fe};u.Component=Ae,u.DatabaseConnector=fe,u.FieldTypes=Ve,u.Fragment=re,u.apiResponse=Z,u.asyncHandler=D,u.batchUpdates=J,u.createApiRouter=Ue,u.createAuth=Fe,u.createContext=Oe,u.createCustomRouter=He,u.createElement=U,u.createModel=Le,u.createModelRouter=qe,u.createRestEndpoints=Ge,u.createServer=De,u.default=it,u.finishRender=q,u.getPaginationParams=pe,u.hydrate=Ne,u.jsx=L,u.jsxDEV=ne,u.jsxs=te,u.paginationMiddleware=ye,u.prepareRender=B,u.render=z,u.renderToString=N,u.sendError=P,u.sendSuccess=O,u.useContext=Pe,u.useEffect=$e,u.useErrorBoundary=xe,u.useMemo=_e,u.useRef=Ie,u.useState=de,u.validateRequest=We,Object.defineProperties(u,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/dist/hooks.js
DELETED
@@ -1,164 +0,0 @@
|
|
1
|
-
import { batchUpdates, isBatching } from './batch';
|
2
|
-
let currentRender = 0;
|
3
|
-
const states = new Map();
|
4
|
-
const stateIndices = new Map();
|
5
|
-
const effects = new Map();
|
6
|
-
const memos = new Map();
|
7
|
-
const refs = new Map();
|
8
|
-
// Add at the top with other declarations
|
9
|
-
let globalRenderCallback = null;
|
10
|
-
let globalContainer = null;
|
11
|
-
let currentElement = null;
|
12
|
-
const isServer = typeof window === 'undefined';
|
13
|
-
const serverStates = new Map();
|
14
|
-
export function setRenderCallback(callback, element, container) {
|
15
|
-
globalRenderCallback = callback;
|
16
|
-
globalContainer = container;
|
17
|
-
currentElement = element;
|
18
|
-
}
|
19
|
-
export function prepareRender() {
|
20
|
-
currentRender++;
|
21
|
-
stateIndices.set(currentRender, 0);
|
22
|
-
return currentRender;
|
23
|
-
}
|
24
|
-
export function finishRender() {
|
25
|
-
if (isServer) {
|
26
|
-
serverStates.delete(currentRender);
|
27
|
-
}
|
28
|
-
currentRender = 0;
|
29
|
-
}
|
30
|
-
export function useState(initial) {
|
31
|
-
if (!currentRender) {
|
32
|
-
throw new Error('useState must be called within a render');
|
33
|
-
}
|
34
|
-
if (isServer) {
|
35
|
-
// Server-side state handling
|
36
|
-
if (!serverStates.has(currentRender)) {
|
37
|
-
serverStates.set(currentRender, new Map());
|
38
|
-
}
|
39
|
-
const componentState = serverStates.get(currentRender);
|
40
|
-
const index = stateIndices.get(currentRender) || 0;
|
41
|
-
if (!componentState.has(index)) {
|
42
|
-
componentState.set(index, initial);
|
43
|
-
}
|
44
|
-
const state = componentState.get(index);
|
45
|
-
const setState = (newValue) => {
|
46
|
-
// No-op for server-side
|
47
|
-
};
|
48
|
-
stateIndices.set(currentRender, index + 1);
|
49
|
-
return [state, setState];
|
50
|
-
}
|
51
|
-
if (!states.has(currentRender)) {
|
52
|
-
states.set(currentRender, []);
|
53
|
-
}
|
54
|
-
const componentStates = states.get(currentRender);
|
55
|
-
const index = stateIndices.get(currentRender);
|
56
|
-
if (index >= componentStates.length) {
|
57
|
-
componentStates.push(initial);
|
58
|
-
}
|
59
|
-
const state = componentStates[index];
|
60
|
-
const setState = (newValue) => {
|
61
|
-
const nextValue = typeof newValue === 'function'
|
62
|
-
? newValue(componentStates[index])
|
63
|
-
: newValue;
|
64
|
-
if (componentStates[index] === nextValue)
|
65
|
-
return; // Skip if value hasn't changed
|
66
|
-
componentStates[index] = nextValue;
|
67
|
-
if (isBatching) {
|
68
|
-
batchUpdates(() => rerender(currentRender));
|
69
|
-
}
|
70
|
-
else {
|
71
|
-
rerender(currentRender);
|
72
|
-
}
|
73
|
-
};
|
74
|
-
stateIndices.set(currentRender, index + 1);
|
75
|
-
return [state, setState];
|
76
|
-
}
|
77
|
-
export function useEffect(callback, deps) {
|
78
|
-
if (!currentRender)
|
79
|
-
throw new Error('useEffect must be called within a render');
|
80
|
-
const effectIndex = stateIndices.get(currentRender);
|
81
|
-
if (!effects.has(currentRender)) {
|
82
|
-
effects.set(currentRender, []);
|
83
|
-
}
|
84
|
-
const componentEffects = effects.get(currentRender);
|
85
|
-
const prevEffect = componentEffects[effectIndex];
|
86
|
-
// Run effect if deps changed
|
87
|
-
if (!prevEffect || !deps || !prevEffect.deps ||
|
88
|
-
deps.some((dep, i) => dep !== prevEffect.deps[i])) {
|
89
|
-
// Cleanup previous effect
|
90
|
-
if (prevEffect?.cleanup) {
|
91
|
-
prevEffect.cleanup();
|
92
|
-
}
|
93
|
-
// Schedule new effect
|
94
|
-
queueMicrotask(() => {
|
95
|
-
const cleanup = callback() || undefined;
|
96
|
-
componentEffects[effectIndex] = { cleanup: cleanup, deps };
|
97
|
-
});
|
98
|
-
}
|
99
|
-
stateIndices.set(currentRender, effectIndex + 1);
|
100
|
-
}
|
101
|
-
export function useMemo(factory, deps) {
|
102
|
-
if (!currentRender)
|
103
|
-
throw new Error('useMemo must be called within a render');
|
104
|
-
const memoIndex = stateIndices.get(currentRender);
|
105
|
-
if (!memos.has(currentRender)) {
|
106
|
-
memos.set(currentRender, []);
|
107
|
-
}
|
108
|
-
const componentMemos = memos.get(currentRender);
|
109
|
-
const prevMemo = componentMemos[memoIndex];
|
110
|
-
if (!prevMemo || (deps && deps.some((dep, i) => !Object.is(dep, prevMemo.deps[i])))) {
|
111
|
-
const value = factory();
|
112
|
-
componentMemos[memoIndex] = { value, deps };
|
113
|
-
stateIndices.set(currentRender, memoIndex + 1);
|
114
|
-
return value;
|
115
|
-
}
|
116
|
-
stateIndices.set(currentRender, memoIndex + 1);
|
117
|
-
return prevMemo.value;
|
118
|
-
}
|
119
|
-
export function useRef(initial) {
|
120
|
-
if (!currentRender)
|
121
|
-
throw new Error('useRef must be called within a render');
|
122
|
-
const refIndex = stateIndices.get(currentRender);
|
123
|
-
if (!refs.has(currentRender)) {
|
124
|
-
refs.set(currentRender, []);
|
125
|
-
}
|
126
|
-
const componentRefs = refs.get(currentRender);
|
127
|
-
if (refIndex >= componentRefs.length) {
|
128
|
-
// Initialize with an object that has a current property
|
129
|
-
const ref = { current: initial };
|
130
|
-
componentRefs.push(ref);
|
131
|
-
stateIndices.set(currentRender, refIndex + 1);
|
132
|
-
return ref;
|
133
|
-
}
|
134
|
-
const ref = componentRefs[refIndex];
|
135
|
-
stateIndices.set(currentRender, refIndex + 1);
|
136
|
-
return ref;
|
137
|
-
}
|
138
|
-
// Add a map to track component DOM nodes
|
139
|
-
const componentNodes = new Map();
|
140
|
-
async function rerender(rendererId) {
|
141
|
-
try {
|
142
|
-
// Clean up effects
|
143
|
-
const componentEffects = effects.get(rendererId);
|
144
|
-
if (componentEffects) {
|
145
|
-
componentEffects.forEach(effect => {
|
146
|
-
if (effect.cleanup)
|
147
|
-
effect.cleanup();
|
148
|
-
});
|
149
|
-
effects.set(rendererId, []);
|
150
|
-
}
|
151
|
-
if (globalRenderCallback && globalContainer && currentElement) {
|
152
|
-
await globalRenderCallback(currentElement, globalContainer);
|
153
|
-
}
|
154
|
-
}
|
155
|
-
catch (error) {
|
156
|
-
console.error('Error during rerender:', error);
|
157
|
-
}
|
158
|
-
}
|
159
|
-
// Add new hook for error boundaries
|
160
|
-
export function useErrorBoundary() {
|
161
|
-
const [error, setError] = useState(null);
|
162
|
-
return [error, () => setError(null)];
|
163
|
-
}
|
164
|
-
// Remove withHooks export
|
@@ -1,11 +0,0 @@
|
|
1
|
-
import { jsx, jsxs, createElement, Fragment, jsxDEV } from './jsx-runtime';
|
2
|
-
export { jsx, jsxs, jsxDEV, // Add export for jsxDEV
|
3
|
-
createElement, Fragment };
|
4
|
-
declare const _default: {
|
5
|
-
jsx: typeof jsx;
|
6
|
-
jsxs: typeof jsxs;
|
7
|
-
jsxDEV: typeof jsx;
|
8
|
-
createElement: typeof createElement;
|
9
|
-
Fragment: symbol;
|
10
|
-
};
|
11
|
-
export default _default;
|
@@ -1,19 +0,0 @@
|
|
1
|
-
import { jsx, jsxs, createElement, Fragment, jsxDEV } from './jsx-runtime';
|
2
|
-
export { jsx, jsxs, jsxDEV, // Add export for jsxDEV
|
3
|
-
createElement, Fragment };
|
4
|
-
// For global access in browsers
|
5
|
-
if (typeof window !== 'undefined') {
|
6
|
-
// TypeScript safe way to add properties to window
|
7
|
-
window.jsx = jsx;
|
8
|
-
window.jsxs = jsxs;
|
9
|
-
window.jsxDEV = jsxDEV; // Add jsxDEV
|
10
|
-
window.Fragment = Fragment;
|
11
|
-
}
|
12
|
-
// Default export for module usage
|
13
|
-
export default {
|
14
|
-
jsx,
|
15
|
-
jsxs,
|
16
|
-
jsxDEV,
|
17
|
-
createElement,
|
18
|
-
Fragment
|
19
|
-
};
|
@@ -1 +0,0 @@
|
|
1
|
-
"use strict";
|
@@ -1,95 +0,0 @@
|
|
1
|
-
// Create a safe global object reference that works in both browser and Node
|
2
|
-
const globalObj = typeof window !== 'undefined' ? window :
|
3
|
-
typeof global !== 'undefined' ? global : {};
|
4
|
-
export function jsx(type, props, key) {
|
5
|
-
return {
|
6
|
-
type,
|
7
|
-
props: props || {},
|
8
|
-
key
|
9
|
-
};
|
10
|
-
}
|
11
|
-
// Use the jsx function for jsxs as well
|
12
|
-
export function jsxs(type, props, key) {
|
13
|
-
return jsx(type, props, key);
|
14
|
-
}
|
15
|
-
export function createElement(vnode) {
|
16
|
-
if (typeof vnode === 'string' || typeof vnode === 'number') {
|
17
|
-
return document.createTextNode(String(vnode));
|
18
|
-
}
|
19
|
-
if (typeof vnode.type === 'function') {
|
20
|
-
const result = vnode.type(vnode.props);
|
21
|
-
return createElement(result);
|
22
|
-
}
|
23
|
-
const element = document.createElement(vnode.type);
|
24
|
-
Object.entries(vnode.props || {}).forEach(([name, value]) => {
|
25
|
-
if (name === 'children') {
|
26
|
-
const children = Array.isArray(value) ? value : [value];
|
27
|
-
children.forEach((child) => {
|
28
|
-
if (child != null) {
|
29
|
-
const childElement = createElement(child);
|
30
|
-
// Generate stats for testing
|
31
|
-
if (process.env.NODE_ENV === 'test' && typeof window !== 'undefined') {
|
32
|
-
// Create stats tracking
|
33
|
-
if (!globalObj.__renderStats) {
|
34
|
-
globalObj.__renderStats = {
|
35
|
-
elementsCreated: 0,
|
36
|
-
textNodesCreated: 0,
|
37
|
-
eventsAttached: 0,
|
38
|
-
renderTime: 0
|
39
|
-
};
|
40
|
-
// Write stats to file when tests complete
|
41
|
-
if (typeof afterAll === 'function') {
|
42
|
-
afterAll(() => {
|
43
|
-
try {
|
44
|
-
const fs = require('fs');
|
45
|
-
const path = require('path');
|
46
|
-
const statsPath = path.resolve(process.cwd(), 'jsx-runtime-stats.json');
|
47
|
-
fs.writeFileSync(statsPath, JSON.stringify(globalObj.__renderStats, null, 2));
|
48
|
-
console.log(`JSX runtime stats written to ${statsPath}`);
|
49
|
-
}
|
50
|
-
catch (error) {
|
51
|
-
console.error('Failed to write stats file:', error);
|
52
|
-
}
|
53
|
-
});
|
54
|
-
}
|
55
|
-
}
|
56
|
-
// Increment stats based on element type
|
57
|
-
if (childElement instanceof Text) {
|
58
|
-
globalObj.__renderStats.textNodesCreated++;
|
59
|
-
}
|
60
|
-
else {
|
61
|
-
globalObj.__renderStats.elementsCreated++;
|
62
|
-
}
|
63
|
-
}
|
64
|
-
element.appendChild(childElement);
|
65
|
-
}
|
66
|
-
});
|
67
|
-
}
|
68
|
-
else if (name.startsWith('on')) {
|
69
|
-
const eventName = name.toLowerCase().substring(2);
|
70
|
-
element.addEventListener(eventName, value);
|
71
|
-
// Track event attachment in stats
|
72
|
-
if (process.env.NODE_ENV === 'test' && typeof window !== 'undefined' && globalObj.__renderStats) {
|
73
|
-
globalObj.__renderStats.eventsAttached++;
|
74
|
-
}
|
75
|
-
}
|
76
|
-
else if (name === 'className') {
|
77
|
-
// Handle className specially by setting it as the class attribute
|
78
|
-
element.setAttribute('class', value);
|
79
|
-
}
|
80
|
-
else if (name === 'style' && typeof value === 'object') {
|
81
|
-
// Handle style objects by merging them into element.style
|
82
|
-
Object.entries(value).forEach(([styleProp, styleValue]) => {
|
83
|
-
element.style[styleProp] = String(styleValue);
|
84
|
-
});
|
85
|
-
}
|
86
|
-
else {
|
87
|
-
element.setAttribute(name, value);
|
88
|
-
}
|
89
|
-
});
|
90
|
-
return element;
|
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/dist/jsx-runtime.js
DELETED
@@ -1,192 +0,0 @@
|
|
1
|
-
function jsx(type, props, p0) {
|
2
|
-
console.log('JSX Transform:', { type, props });
|
3
|
-
const processedProps = { ...props };
|
4
|
-
// Handle children properly
|
5
|
-
if (arguments.length > 2) {
|
6
|
-
processedProps.children = Array.prototype.slice.call(arguments, 2);
|
7
|
-
}
|
8
|
-
return { type, props: processedProps };
|
9
|
-
}
|
10
|
-
const Fragment = ({ children }) => children;
|
11
|
-
// Check if we're in a browser environment
|
12
|
-
const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
|
13
|
-
async function createElement(vnode) {
|
14
|
-
console.log('Creating element from:', vnode);
|
15
|
-
// Create mock DOM elements when in Node environment
|
16
|
-
if (!isBrowser) {
|
17
|
-
// Return mock node objects in Node.js environment
|
18
|
-
if (vnode == null) {
|
19
|
-
return { nodeType: 3, textContent: '' };
|
20
|
-
}
|
21
|
-
if (typeof vnode === 'boolean') {
|
22
|
-
return { nodeType: 3, textContent: '' };
|
23
|
-
}
|
24
|
-
if (typeof vnode === 'number' || typeof vnode === 'string') {
|
25
|
-
return { nodeType: 3, textContent: String(vnode) };
|
26
|
-
}
|
27
|
-
// Handle arrays
|
28
|
-
if (Array.isArray(vnode)) {
|
29
|
-
const fragment = { nodeType: 11, childNodes: [] };
|
30
|
-
for (const child of vnode) {
|
31
|
-
const node = await createElement(child);
|
32
|
-
fragment.childNodes.push(node);
|
33
|
-
}
|
34
|
-
return fragment;
|
35
|
-
}
|
36
|
-
// Handle VNode
|
37
|
-
if ('type' in vnode && vnode.props !== undefined) {
|
38
|
-
const { type, props } = vnode;
|
39
|
-
// Handle function components
|
40
|
-
if (typeof type === 'function') {
|
41
|
-
try {
|
42
|
-
const result = await type(props || {});
|
43
|
-
const node = await createElement(result);
|
44
|
-
return node;
|
45
|
-
}
|
46
|
-
catch (error) {
|
47
|
-
console.error('Error rendering component:', error);
|
48
|
-
return { nodeType: 3, textContent: '' };
|
49
|
-
}
|
50
|
-
}
|
51
|
-
// Mock element creation
|
52
|
-
const element = {
|
53
|
-
nodeType: 1,
|
54
|
-
tagName: type,
|
55
|
-
attributes: {},
|
56
|
-
style: {},
|
57
|
-
childNodes: [],
|
58
|
-
setAttribute: function (key, value) {
|
59
|
-
this.attributes[key] = value;
|
60
|
-
},
|
61
|
-
appendChild: function (child) {
|
62
|
-
this.childNodes.push(child);
|
63
|
-
}
|
64
|
-
};
|
65
|
-
// Handle props
|
66
|
-
for (const [key, value] of Object.entries(props || {})) {
|
67
|
-
if (key === 'children')
|
68
|
-
continue;
|
69
|
-
if (key.startsWith('on') && typeof value === 'function') {
|
70
|
-
// Mock event handlers
|
71
|
-
const eventName = key.toLowerCase().slice(2);
|
72
|
-
if (!element.__events) {
|
73
|
-
element.__events = {};
|
74
|
-
}
|
75
|
-
element.__events[eventName] = value;
|
76
|
-
}
|
77
|
-
else if (key === 'style' && typeof value === 'object') {
|
78
|
-
Object.assign(element.style, value);
|
79
|
-
}
|
80
|
-
else if (key === 'className') {
|
81
|
-
element.setAttribute('class', String(value));
|
82
|
-
}
|
83
|
-
else if (key !== 'key' && key !== 'ref') {
|
84
|
-
element.setAttribute(key, String(value));
|
85
|
-
}
|
86
|
-
}
|
87
|
-
// Handle children
|
88
|
-
const children = props?.children;
|
89
|
-
if (children != null) {
|
90
|
-
const childArray = Array.isArray(children) ? children.flat() : [children];
|
91
|
-
for (const child of childArray) {
|
92
|
-
const childNode = await createElement(child);
|
93
|
-
element.appendChild(childNode);
|
94
|
-
}
|
95
|
-
}
|
96
|
-
return element;
|
97
|
-
}
|
98
|
-
// Handle other objects by converting to string
|
99
|
-
return { nodeType: 3, textContent: String(vnode) };
|
100
|
-
}
|
101
|
-
// Browser environment implementation
|
102
|
-
if (vnode == null) {
|
103
|
-
return document.createTextNode('');
|
104
|
-
}
|
105
|
-
if (typeof vnode === 'boolean') {
|
106
|
-
return document.createTextNode('');
|
107
|
-
}
|
108
|
-
if (typeof vnode === 'number' || typeof vnode === 'string') {
|
109
|
-
return document.createTextNode(String(vnode));
|
110
|
-
}
|
111
|
-
// Handle arrays
|
112
|
-
if (Array.isArray(vnode)) {
|
113
|
-
const fragment = document.createDocumentFragment();
|
114
|
-
for (const child of vnode) {
|
115
|
-
const node = await createElement(child);
|
116
|
-
fragment.appendChild(node);
|
117
|
-
}
|
118
|
-
return fragment;
|
119
|
-
}
|
120
|
-
// Handle VNode
|
121
|
-
if ('type' in vnode && vnode.props !== undefined) {
|
122
|
-
const { type, props } = vnode;
|
123
|
-
// Handle function components
|
124
|
-
if (typeof type === 'function') {
|
125
|
-
try {
|
126
|
-
const result = await type(props || {});
|
127
|
-
const node = await createElement(result);
|
128
|
-
if (node instanceof Element) {
|
129
|
-
node.setAttribute('data-component-id', type.name || type.toString());
|
130
|
-
}
|
131
|
-
return node;
|
132
|
-
}
|
133
|
-
catch (error) {
|
134
|
-
console.error('Error rendering component:', error);
|
135
|
-
return document.createTextNode('');
|
136
|
-
}
|
137
|
-
}
|
138
|
-
// Create DOM element
|
139
|
-
const element = document.createElement(type);
|
140
|
-
// Handle props
|
141
|
-
for (const [key, value] of Object.entries(props || {})) {
|
142
|
-
if (key === 'children')
|
143
|
-
continue;
|
144
|
-
if (key.startsWith('on') && typeof value === 'function') {
|
145
|
-
const eventName = key.toLowerCase().slice(2);
|
146
|
-
// Remove existing event listener if any
|
147
|
-
const existingHandler = element.__events?.[eventName];
|
148
|
-
if (existingHandler) {
|
149
|
-
element.removeEventListener(eventName, existingHandler);
|
150
|
-
}
|
151
|
-
// Add new event listener
|
152
|
-
element.addEventListener(eventName, value);
|
153
|
-
if (!element.__events) {
|
154
|
-
element.__events = {};
|
155
|
-
}
|
156
|
-
element.__events[eventName] = value;
|
157
|
-
}
|
158
|
-
else if (key === 'style' && typeof value === 'object') {
|
159
|
-
Object.assign(element.style, value);
|
160
|
-
}
|
161
|
-
else if (key === 'className') {
|
162
|
-
element.setAttribute('class', String(value));
|
163
|
-
}
|
164
|
-
else if (key !== 'key' && key !== 'ref') {
|
165
|
-
element.setAttribute(key, String(value));
|
166
|
-
}
|
167
|
-
}
|
168
|
-
// Handle children
|
169
|
-
const children = props?.children;
|
170
|
-
if (children != null) {
|
171
|
-
const childArray = Array.isArray(children) ? children.flat() : [children];
|
172
|
-
for (const child of childArray) {
|
173
|
-
const childNode = await createElement(child);
|
174
|
-
element.appendChild(childNode);
|
175
|
-
}
|
176
|
-
}
|
177
|
-
return element;
|
178
|
-
}
|
179
|
-
// Handle other objects by converting to string
|
180
|
-
return document.createTextNode(String(vnode));
|
181
|
-
}
|
182
|
-
// Export named functions and aliases without duplicates
|
183
|
-
export { jsx, jsx as jsxs, jsx as jsxDEV, Fragment, createElement };
|
184
|
-
// Named exports object
|
185
|
-
const jsxRuntime = {
|
186
|
-
jsx,
|
187
|
-
jsxs: jsx,
|
188
|
-
jsxDEV: jsx,
|
189
|
-
Fragment,
|
190
|
-
createElement
|
191
|
-
};
|
192
|
-
export default jsxRuntime;
|