@webtypen/webframez-react 0.0.32 → 0.0.33

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/client.cjs CHANGED
@@ -1 +1 @@
1
- var M=Object.create;var m=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var q=Object.getPrototypeOf,G=Object.prototype.hasOwnProperty;var Y=(e,t)=>{for(var n in t)m(e,n,{get:t[n],enumerable:!0})},S=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of F(t))!G.call(e,r)&&r!==n&&m(e,r,{get:()=>t[r],enumerable:!(o=D(t,r))||o.enumerable});return e};var Z=(e,t,n)=>(n=e!=null?M(q(e)):{},S(t||!e||!e.__esModule?m(n,"default",{value:e,enumerable:!0}):n,e)),j=e=>S(m({},"__esModule",{value:!0}),e);var ce={};Y(ce,{mountWebframezClient:()=>ue,useCookie:()=>ne,useRouter:()=>oe});module.exports=j(ce);var a=Z(require("react"),1),b=require("react-dom/client"),l=require("react-server-dom-webpack/client");var X=/^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;function u(e){if(typeof e!="string")return;let t=e.trim();return!t||t==="/"?"":t.replace(/\/+$/,"")}function y(e,t){let n=e.trim(),o=u(t);return!n||!o||X.test(n)||n.startsWith("/")||o!=="/"&&(n===o||n.startsWith(`${o}/`))?n:o==="/"?n.startsWith("/")?n:`/${n}`:n.startsWith("/")?`${o}${n}`:`${o}/${n}`}function v(e,t){if(!e)return;let n=u(e.basename)??u(t),o=u(e.routeBasePath),r=u(e.transportBasePath),i={...e,...n!==void 0?{basename:n}:{},...o!==void 0?{routeBasePath:o}:{},...r!==void 0?{transportBasePath:r}:{}};return i.favicon&&(i.favicon=y(i.favicon,n)),i.links&&(i.links=i.links.map(c=>({...c,href:y(c.href,n)}))),i}var d=require("react/jsx-runtime"),K={push:()=>{},replace:()=>{},refresh:()=>{}},p=typeof a.default.createContext=="function"?a.default.createContext(null):null,N="__WEBFRAMEZ_ROUTER__",V="[data-webframez-head='true']";function w(e){return u(e)??""}function J(e,t){return t?e===t?"/":e.startsWith(`${t}/`)?e.slice(t.length)||"/":e||"/":e||"/"}function k(e,t){let n=!t||t==="/"?"/":t.startsWith("/")?t:`/${t}`;return e?n==="/"?e:`${e}${n}`:n}function Q(){return w(typeof window>"u"?globalThis.__RSC_ROUTE_BASE_PATH:window.__RSC_ROUTE_BASE_PATH)}function H(e){if(typeof window>"u")return e||"/";let t=w(window.__RSC_BASENAME),n=Q(),o=J(e||"/",t);return k(n,o)}function U(e){if(typeof window>"u")return e;let t=window.__RSC_ENDPOINT;return typeof t=="string"&&t.trim()!==""?t:e}function ee(){return typeof window>"u"?null:window[N]??null}function te(e){typeof window>"u"||(window[N]=e)}function T(){let e={},t=typeof document>"u"?"":document.cookie;if(!t||t.trim()==="")return e;for(let n of t.split(";")){let o=n.trim();if(!o)continue;let r=o.indexOf("="),i=r>=0?o.slice(0,r).trim():o,c=r>=0?o.slice(r+1):"";i&&(e[i]=decodeURIComponent(c))}return e}function B(e,t,n={}){let o=[`${e}=${encodeURIComponent(t)}`];return n.path&&o.push(`Path=${n.path}`),n.domain&&o.push(`Domain=${n.domain}`),typeof n.maxAge=="number"&&o.push(`Max-Age=${Math.floor(n.maxAge)}`),n.expires&&o.push(`Expires=${n.expires.toUTCString()}`),n.sameSite&&o.push(`SameSite=${n.sameSite}`),n.secure&&o.push("Secure"),o.join("; ")}function ne(){return a.default.useMemo(()=>({all:()=>T(),get:e=>T()[e],set:(e,t,n)=>{typeof document>"u"||(document.cookie=B(e,t,n))},remove:(e,t)=>{typeof document>"u"||(document.cookie=B(e,"",{...t??{},maxAge:0}))}}),[])}function oe(){let e=p?a.default.useContext(p):null;if(!e){let t=ee();if(t)return t;if(typeof window>"u")return K;throw new Error("useRouter must be used inside mountWebframezClient()")}return e}function re({active:e}){return(0,d.jsx)("div",{style:{position:"fixed",top:0,left:0,width:"100%",height:3,zIndex:9999,transformOrigin:"left",transform:e?"scaleX(1)":"scaleX(0)",transition:"transform 180ms ease",background:"linear-gradient(90deg, #0ea5e9, #22c55e)"}})}function x(e){let t=document.createElement("meta");t.setAttribute("data-webframez-head","true");let n=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of n)t.setAttribute(o,String(r));document.head.appendChild(t)}function O(e){let t=document.createElement("link");t.setAttribute("data-webframez-head","true");let n=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of n)t.setAttribute(o,String(r));document.head.appendChild(t)}function I(e){if(typeof document>"u")return;let t=v(e)??e,n=u(t.basename),o=u(t.routeBasePath),r=u(t.transportBasePath);window.__RSC_BASENAME=n??"",window.__RSC_ROUTE_BASE_PATH=o??"",r!==void 0&&(window.__RSC_ENDPOINT=k(r,"/rsc")),document.title=t.title||"Webframez React";for(let i of document.head.querySelectorAll(V))i.remove();t.description&&x({name:"description",content:t.description}),t.favicon&&O({rel:"icon",href:t.favicon});for(let i of t.meta??[])x(i);for(let i of t.links??[])O(i)}function ie(e){let t=new TextEncoder;return new ReadableStream({start(n){n.enqueue(t.encode(e)),n.close()}})}function ae(){if(typeof window>"u")return null;let e=window.__RSC_INITIAL_PAYLOAD;return typeof e!="string"||e===""?null:(delete window.__RSC_INITIAL_PAYLOAD,(0,l.createFromReadableStream)(ie(e)))}function se(e){let t=U(e),n=H(window.location.pathname);return ae()??(0,l.createFromFetch)(fetch(`${t}?path=${encodeURIComponent(n)}&search=${encodeURIComponent(window.location.search)}`,{headers:{Accept:"text/x-component"}}))}function de(e,t){return function(){let o=a.default.use(e),[r,i]=(0,a.useState)(o.model),[c,R]=(0,a.useState)(o.head),[$,h]=(0,a.useState)(!1),[L,z]=(0,a.useState)(!1);async function f(s,E="push"){h(!0);try{let g=U(t),W=H(s.pathname),_=await(0,l.createFromFetch)(fetch(`${g}?path=${encodeURIComponent(W)}&search=${encodeURIComponent(s.search)}`,{headers:{Accept:"text/x-component"}}));I(_.head),R(_.head),i(_.model);let P=`${s.pathname}${s.search}`;E==="replace"?history.replaceState(null,"",P):E==="push"&&history.pushState(null,"",P)}catch(g){console.error("[webframez-react] Failed to render route",g),i((0,d.jsx)("p",{children:"Failed to load route."}))}finally{h(!1)}}(0,a.useEffect)(()=>{I(c)},[c]),(0,a.useEffect)(()=>{z(!0);let s=()=>{f(new URL(window.location.href),"none")};return window.addEventListener("popstate",s),()=>{window.removeEventListener("popstate",s)}},[]);let C=a.default.useMemo(()=>({push:s=>{f(new URL(s,window.location.origin),"push")},replace:s=>{f(new URL(s,window.location.origin),"replace")},refresh:()=>{f(new URL(window.location.href),"none")}}),[]);te(C);let A=(0,d.jsxs)(d.Fragment,{children:[L?(0,d.jsx)(re,{active:$}):null,r??(0,d.jsx)("p",{style:{padding:24},children:"Loading..."})]});return p?(0,d.jsx)(p.Provider,{value:C,children:A}):A}}function ue(e={}){let t=e.rootId??"root",n=document.getElementById(t);if(!n)throw new Error(`Missing #${t} element`);let o=typeof window<"u"&&window.__RSC_ENDPOINT,r=e.rscEndpoint??o??"/rsc",i=se(r),c=de(i,r);return(0,b.hydrateRoot)(n,(0,d.jsx)(c,{}))}
1
+ var ae=Object.create;var y=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var ce=Object.getOwnPropertyNames;var de=Object.getPrototypeOf,ue=Object.prototype.hasOwnProperty;var le=(e,t)=>{for(var n in t)y(e,n,{get:t[n],enumerable:!0})},L=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ce(t))!ue.call(e,r)&&r!==n&&y(e,r,{get:()=>t[r],enumerable:!(o=se(t,r))||o.enumerable});return e};var H=(e,t,n)=>(n=e!=null?ae(de(e)):{},L(t||!e||!e.__esModule?y(n,"default",{value:e,enumerable:!0}):n,e)),fe=e=>L(y({},"__esModule",{value:!0}),e);var ve={};le(ve,{mountWebframezClient:()=>xe,useCookie:()=>ye,useRouter:()=>Ee});module.exports=fe(ve);var s=H(require("react"),1),Y=require("react-dom/client"),g=require("react-server-dom-webpack/client"),Z=require("@webtypen/webframez-react/route-slot");var pe=/^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;function u(e){if(typeof e!="string")return;let t=e.trim();return!t||t==="/"?"":t.replace(/\/+$/,"")}function U(e,t){let n=e.trim(),o=u(t);return!n||!o||pe.test(n)||n.startsWith("/")||o!=="/"&&(n===o||n.startsWith(`${o}/`))?n:o==="/"?n.startsWith("/")?n:`/${n}`:n.startsWith("/")?`${o}${n}`:`${o}/${n}`}function S(e,t){if(!e)return;let n=u(e.basename)??u(t),o=u(e.routeBasePath),r=u(e.transportBasePath),a={...e,...n!==void 0?{basename:n}:{},...o!==void 0?{routeBasePath:o}:{},...r!==void 0?{transportBasePath:r}:{}};return a.favicon&&(a.favicon=U(a.favicon,n)),a.links&&(a.links=a.links.map(c=>({...c,href:U(c.href,n)}))),a}var R=H(require("react"),1),$="webframez-route-children",W="__webframezRouteChildren",D="WebframezRouteChildren",N=()=>R.default.createElement($);N.displayName=D;N[W]=!0;var me=N;function z(e){if(e===$||e===me)return!0;if(!e||typeof e!="function"&&typeof e!="object")return!1;try{let t=e;return t[W]===!0||t.displayName===D||t.name==="RouteChildren"}catch{return!1}}function M(e){if(!e||typeof e!="object")return!1;try{return"type"in e&&"props"in e}catch{return!1}}function E(e,t){if(e==null||typeof e=="boolean")return e;if(Array.isArray(e)){let m=!1,f=e.map(p=>{let h=E(p,t);return h!==p&&(m=!0),h});return m?f:e}if(M(e)&&z(e.type))return t;let n=R.default.isValidElement(e);if(!n&&!M(e))return e;if(n&&z(e.type))return t;let o=e.props??{};if(!("children"in o))return e;let r=E(o.children,t);if(r===o.children)return e;if(n)return Array.isArray(r)?R.default.cloneElement(e,void 0,...r):R.default.cloneElement(e,void 0,r);let a=e,c={...a.props??{},children:r,...a.key!==void 0&&a.key!==null?{key:a.key}:{}};return R.default.createElement(a.type,c)}var d=require("react/jsx-runtime"),Re={push:()=>{},replace:()=>{},refresh:()=>{},refreshContext:()=>{}},A=typeof s.default.createContext=="function"?s.default.createContext(null):null,K="__WEBFRAMEZ_ROUTER__",ge="[data-webframez-head='true']";function v(e){return u(e)??""}function he(e,t){return t?e===t?"/":e.startsWith(`${t}/`)?e.slice(t.length)||"/":e||"/":e||"/"}function V(e,t){let n=!t||t==="/"?"/":t.startsWith("/")?t:`/${t}`;return e?n==="/"?e:`${e}${n}`:n}function _e(){return v(typeof window>"u"?globalThis.__RSC_ROUTE_BASE_PATH:window.__RSC_ROUTE_BASE_PATH)}function X(e){if(typeof window>"u")return e||"/";let t=v(window.__RSC_BASENAME),n=_e(),o=he(e||"/",t);return V(n,o)}function J(e){if(typeof window>"u")return e;let t=window.__RSC_ENDPOINT;return typeof t=="string"&&t.trim()!==""?t:e}function we(){return typeof window>"u"?null:window[K]??null}function Ce(e){typeof window>"u"||(window[K]=e)}function F(){let e={},t=typeof document>"u"?"":document.cookie;if(!t||t.trim()==="")return e;for(let n of t.split(";")){let o=n.trim();if(!o)continue;let r=o.indexOf("="),a=r>=0?o.slice(0,r).trim():o,c=r>=0?o.slice(r+1):"";a&&(e[a]=decodeURIComponent(c))}return e}function j(e,t,n={}){let o=[`${e}=${encodeURIComponent(t)}`];return n.path&&o.push(`Path=${n.path}`),n.domain&&o.push(`Domain=${n.domain}`),typeof n.maxAge=="number"&&o.push(`Max-Age=${Math.floor(n.maxAge)}`),n.expires&&o.push(`Expires=${n.expires.toUTCString()}`),n.sameSite&&o.push(`SameSite=${n.sameSite}`),n.secure&&o.push("Secure"),o.join("; ")}function ye(){return s.default.useMemo(()=>({all:()=>F(),get:e=>F()[e],set:(e,t,n)=>{typeof document>"u"||(document.cookie=j(e,t,n))},remove:(e,t)=>{typeof document>"u"||(document.cookie=j(e,"",{...t??{},maxAge:0}))}}),[])}function Ee(){let e=A?s.default.useContext(A):null;if(!e){let t=we();if(t)return t;if(typeof window>"u")return Re;throw new Error("useRouter must be used inside mountWebframezClient()")}return e}function Ae({active:e}){return(0,d.jsx)("div",{style:{position:"fixed",top:0,left:0,width:"100%",height:3,zIndex:9999,transformOrigin:"left",transform:e?"scaleX(1)":"scaleX(0)",transition:"transform 180ms ease",background:"linear-gradient(90deg, #0ea5e9, #22c55e)"}})}function G(e){let t=document.createElement("meta");t.setAttribute("data-webframez-head","true");let n=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of n)t.setAttribute(o,String(r));document.head.appendChild(t)}function q(e){let t=document.createElement("link");t.setAttribute("data-webframez-head","true");let n=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of n)t.setAttribute(o,String(r));document.head.appendChild(t)}function x(e){if(typeof document>"u")return;let t=S(e)??e;Q(t),document.title=t.title||"Webframez React";for(let n of document.head.querySelectorAll(ge))n.remove();t.description&&G({name:"description",content:t.description}),t.favicon&&q({rel:"icon",href:t.favicon});for(let n of t.meta??[])G(n);for(let n of t.links??[])q(n)}function Q(e){if(typeof window>"u")return;let t=S(e)??e,n=u(t.basename),o=u(t.routeBasePath),r=u(t.transportBasePath);window.__RSC_BASENAME=n??"",window.__RSC_ROUTE_BASE_PATH=o??"",r!==void 0&&(window.__RSC_ENDPOINT=V(r,"/rsc"))}function Pe(e){let t=new TextEncoder;return new ReadableStream({start(n){n.enqueue(t.encode(e)),n.close()}})}function Te(){if(typeof window>"u")return null;let e=window.__RSC_INITIAL_PAYLOAD;return typeof e!="string"||e===""?null:(delete window.__RSC_INITIAL_PAYLOAD,(0,g.createFromReadableStream)(Pe(e)))}function Se(e){let t=J(e),n=X(window.location.pathname);return Te()??(0,g.createFromFetch)(fetch(`${t}?path=${encodeURIComponent(n)}&search=${encodeURIComponent(window.location.search)}`,{cache:"no-store",credentials:"same-origin",headers:{Accept:"text/x-component"}}))}function Ne(e,t){return function(){let o=s.default.use(e),r=typeof o.contextModel<"u"&&typeof o.pageModel<"u",[a,c]=(0,s.useState)(o.model),[m,f]=(0,s.useState)(o.contextModel),[p,h]=(0,s.useState)(o.pageModel),[I,b]=(0,s.useState)(o.head),[ee,_]=(0,s.useState)(!1),[te,ne]=(0,s.useState)(!1),[oe,P]=(0,s.useState)(r);async function O(i){let C=J(t),l=X(i.pathname);return await(0,g.createFromFetch)(fetch(`${C}?path=${encodeURIComponent(l)}&search=${encodeURIComponent(i.search)}`,{cache:"no-store",credentials:"same-origin",headers:{Accept:"text/x-component"}}))}async function w(i,C="push"){_(!0);try{let l=await O(i);x(l.head),b(l.head),c(l.model),f(l.contextModel),h(l.pageModel),P(!0);let T=`${i.pathname}${i.search}`;C==="replace"?history.replaceState(null,"",T):C==="push"&&history.pushState(null,"",T)}catch(l){console.error("[webframez-react] Failed to render route",l),c((0,d.jsx)("p",{children:"Failed to load route."}))}finally{_(!1)}}async function re(){_(!0);try{let i=await O(new URL(window.location.href));if(x(i.head),b(i.head),Object.prototype.hasOwnProperty.call(i,"contextModel")){f(i.contextModel),P(!0);return}c(i.model),P(!1)}catch(i){console.error("[webframez-react] Failed to refresh route context",i)}finally{_(!1)}}(0,s.useEffect)(()=>{x(I)},[I]),(0,s.useEffect)(()=>{ne(!0);let i=()=>{w(new URL(window.location.href),"none")};return window.addEventListener("popstate",i),()=>{window.removeEventListener("popstate",i)}},[]);let k=s.default.useMemo(()=>({push:i=>{w(new URL(i,window.location.origin),"push")},replace:i=>{w(new URL(i,window.location.origin),"replace")},refresh:()=>{w(new URL(window.location.href),"none")},refreshContext:()=>{re()}}),[]);Ce(k);let ie=oe&&typeof p<"u"?m?(0,d.jsx)(Z.RouteChildrenSlotProvider,{page:p,children:E(m,p)}):p:a,B=(0,d.jsxs)(d.Fragment,{children:[te?(0,d.jsx)(Ae,{active:ee}):null,ie??(0,d.jsx)("p",{style:{padding:24},children:"Loading..."})]});return A?(0,d.jsx)(A.Provider,{value:k,children:B}):B}}function xe(e={}){let t=e.rootId??"root",n=document.getElementById(t);if(!n)throw new Error(`Missing #${t} element`);let o=typeof window<"u"&&window.__RSC_ENDPOINT,r=e.rscEndpoint??o??"/rsc",a=Promise.resolve(Se(r)).then(f=>(f?.head&&Q(f.head),f)),c=Ne(a,r);return(0,Y.hydrateRoot)(n,(0,d.jsx)(c,{}))}
package/dist/client.d.ts CHANGED
@@ -9,6 +9,7 @@ export type RouterClient = {
9
9
  push: (href: string) => void;
10
10
  replace: (href: string) => void;
11
11
  refresh: () => void;
12
+ refreshContext: () => void;
12
13
  };
13
14
 
14
15
  export type CookieOptions = {
package/dist/client.js CHANGED
@@ -1 +1 @@
1
- import c,{useEffect as y,useState as f}from"react";import{hydrateRoot as M}from"react-dom/client";import{createFromFetch as I,createFromReadableStream as D}from"react-server-dom-webpack/client";var W=/^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;function s(e){if(typeof e!="string")return;let t=e.trim();return!t||t==="/"?"":t.replace(/\/+$/,"")}function P(e,t){let n=e.trim(),o=s(t);return!n||!o||W.test(n)||n.startsWith("/")||o!=="/"&&(n===o||n.startsWith(`${o}/`))?n:o==="/"?n.startsWith("/")?n:`/${n}`:n.startsWith("/")?`${o}${n}`:`${o}/${n}`}function S(e,t){if(!e)return;let n=s(e.basename)??s(t),o=s(e.routeBasePath),i=s(e.transportBasePath),r={...e,...n!==void 0?{basename:n}:{},...o!==void 0?{routeBasePath:o}:{},...i!==void 0?{transportBasePath:i}:{}};return r.favicon&&(r.favicon=P(r.favicon,n)),r.links&&(r.links=r.links.map(d=>({...d,href:P(d.href,n)}))),r}import{Fragment as ee,jsx as u,jsxs as te}from"react/jsx-runtime";var F={push:()=>{},replace:()=>{},refresh:()=>{}},m=typeof c.createContext=="function"?c.createContext(null):null,b="__WEBFRAMEZ_ROUTER__",q="[data-webframez-head='true']";function _(e){return s(e)??""}function G(e,t){return t?e===t?"/":e.startsWith(`${t}/`)?e.slice(t.length)||"/":e||"/":e||"/"}function N(e,t){let n=!t||t==="/"?"/":t.startsWith("/")?t:`/${t}`;return e?n==="/"?e:`${e}${n}`:n}function Y(){return _(typeof window>"u"?globalThis.__RSC_ROUTE_BASE_PATH:window.__RSC_ROUTE_BASE_PATH)}function k(e){if(typeof window>"u")return e||"/";let t=_(window.__RSC_BASENAME),n=Y(),o=G(e||"/",t);return N(n,o)}function H(e){if(typeof window>"u")return e;let t=window.__RSC_ENDPOINT;return typeof t=="string"&&t.trim()!==""?t:e}function Z(){return typeof window>"u"?null:window[b]??null}function j(e){typeof window>"u"||(window[b]=e)}function v(){let e={},t=typeof document>"u"?"":document.cookie;if(!t||t.trim()==="")return e;for(let n of t.split(";")){let o=n.trim();if(!o)continue;let i=o.indexOf("="),r=i>=0?o.slice(0,i).trim():o,d=i>=0?o.slice(i+1):"";r&&(e[r]=decodeURIComponent(d))}return e}function T(e,t,n={}){let o=[`${e}=${encodeURIComponent(t)}`];return n.path&&o.push(`Path=${n.path}`),n.domain&&o.push(`Domain=${n.domain}`),typeof n.maxAge=="number"&&o.push(`Max-Age=${Math.floor(n.maxAge)}`),n.expires&&o.push(`Expires=${n.expires.toUTCString()}`),n.sameSite&&o.push(`SameSite=${n.sameSite}`),n.secure&&o.push("Secure"),o.join("; ")}function de(){return c.useMemo(()=>({all:()=>v(),get:e=>v()[e],set:(e,t,n)=>{typeof document>"u"||(document.cookie=T(e,t,n))},remove:(e,t)=>{typeof document>"u"||(document.cookie=T(e,"",{...t??{},maxAge:0}))}}),[])}function ue(){let e=m?c.useContext(m):null;if(!e){let t=Z();if(t)return t;if(typeof window>"u")return F;throw new Error("useRouter must be used inside mountWebframezClient()")}return e}function X({active:e}){return u("div",{style:{position:"fixed",top:0,left:0,width:"100%",height:3,zIndex:9999,transformOrigin:"left",transform:e?"scaleX(1)":"scaleX(0)",transition:"transform 180ms ease",background:"linear-gradient(90deg, #0ea5e9, #22c55e)"}})}function B(e){let t=document.createElement("meta");t.setAttribute("data-webframez-head","true");let n=Object.entries(e).filter(([,o])=>!!o);for(let[o,i]of n)t.setAttribute(o,String(i));document.head.appendChild(t)}function x(e){let t=document.createElement("link");t.setAttribute("data-webframez-head","true");let n=Object.entries(e).filter(([,o])=>!!o);for(let[o,i]of n)t.setAttribute(o,String(i));document.head.appendChild(t)}function O(e){if(typeof document>"u")return;let t=S(e)??e,n=s(t.basename),o=s(t.routeBasePath),i=s(t.transportBasePath);window.__RSC_BASENAME=n??"",window.__RSC_ROUTE_BASE_PATH=o??"",i!==void 0&&(window.__RSC_ENDPOINT=N(i,"/rsc")),document.title=t.title||"Webframez React";for(let r of document.head.querySelectorAll(q))r.remove();t.description&&B({name:"description",content:t.description}),t.favicon&&x({rel:"icon",href:t.favicon});for(let r of t.meta??[])B(r);for(let r of t.links??[])x(r)}function K(e){let t=new TextEncoder;return new ReadableStream({start(n){n.enqueue(t.encode(e)),n.close()}})}function V(){if(typeof window>"u")return null;let e=window.__RSC_INITIAL_PAYLOAD;return typeof e!="string"||e===""?null:(delete window.__RSC_INITIAL_PAYLOAD,D(K(e)))}function J(e){let t=H(e),n=k(window.location.pathname);return V()??I(fetch(`${t}?path=${encodeURIComponent(n)}&search=${encodeURIComponent(window.location.search)}`,{headers:{Accept:"text/x-component"}}))}function Q(e,t){return function(){let o=c.use(e),[i,r]=f(o.model),[d,w]=f(o.head),[U,R]=f(!1),[$,L]=f(!1);async function l(a,A="push"){R(!0);try{let p=H(t),z=k(a.pathname),g=await I(fetch(`${p}?path=${encodeURIComponent(z)}&search=${encodeURIComponent(a.search)}`,{headers:{Accept:"text/x-component"}}));O(g.head),w(g.head),r(g.model);let E=`${a.pathname}${a.search}`;A==="replace"?history.replaceState(null,"",E):A==="push"&&history.pushState(null,"",E)}catch(p){console.error("[webframez-react] Failed to render route",p),r(u("p",{children:"Failed to load route."}))}finally{R(!1)}}y(()=>{O(d)},[d]),y(()=>{L(!0);let a=()=>{l(new URL(window.location.href),"none")};return window.addEventListener("popstate",a),()=>{window.removeEventListener("popstate",a)}},[]);let h=c.useMemo(()=>({push:a=>{l(new URL(a,window.location.origin),"push")},replace:a=>{l(new URL(a,window.location.origin),"replace")},refresh:()=>{l(new URL(window.location.href),"none")}}),[]);j(h);let C=te(ee,{children:[$?u(X,{active:U}):null,i??u("p",{style:{padding:24},children:"Loading..."})]});return m?u(m.Provider,{value:h,children:C}):C}}function ce(e={}){let t=e.rootId??"root",n=document.getElementById(t);if(!n)throw new Error(`Missing #${t} element`);let o=typeof window<"u"&&window.__RSC_ENDPOINT,i=e.rscEndpoint??o??"/rsc",r=J(i),d=Q(r,i);return M(n,u(d,{}))}export{ce as mountWebframezClient,de as useCookie,ue as useRouter};
1
+ import R,{useEffect as $,useState as f}from"react";import{hydrateRoot as ie}from"react-dom/client";import{createFromFetch as G,createFromReadableStream as ae}from"react-server-dom-webpack/client";import{RouteChildrenSlotProvider as se}from"@webtypen/webframez-react/route-slot";var oe=/^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;function c(e){if(typeof e!="string")return;let t=e.trim();return!t||t==="/"?"":t.replace(/\/+$/,"")}function B(e,t){let n=e.trim(),o=c(t);return!n||!o||oe.test(n)||n.startsWith("/")||o!=="/"&&(n===o||n.startsWith(`${o}/`))?n:o==="/"?n.startsWith("/")?n:`/${n}`:n.startsWith("/")?`${o}${n}`:`${o}/${n}`}function T(e,t){if(!e)return;let n=c(e.basename)??c(t),o=c(e.routeBasePath),r=c(e.transportBasePath),a={...e,...n!==void 0?{basename:n}:{},...o!==void 0?{routeBasePath:o}:{},...r!==void 0?{transportBasePath:r}:{}};return a.favicon&&(a.favicon=B(a.favicon,n)),a.links&&(a.links=a.links.map(s=>({...s,href:B(s.href,n)}))),a}import g from"react";var U="webframez-route-children",z="__webframezRouteChildren",M="WebframezRouteChildren",S=()=>g.createElement(U);S.displayName=M;S[z]=!0;var re=S;function L(e){if(e===U||e===re)return!0;if(!e||typeof e!="function"&&typeof e!="object")return!1;try{let t=e;return t[z]===!0||t.displayName===M||t.name==="RouteChildren"}catch{return!1}}function H(e){if(!e||typeof e!="object")return!1;try{return"type"in e&&"props"in e}catch{return!1}}function y(e,t){if(e==null||typeof e=="boolean")return e;if(Array.isArray(e)){let m=!1,u=e.map(l=>{let h=y(l,t);return h!==l&&(m=!0),h});return m?u:e}if(H(e)&&L(e.type))return t;let n=g.isValidElement(e);if(!n&&!H(e))return e;if(n&&L(e.type))return t;let o=e.props??{};if(!("children"in o))return e;let r=y(o.children,t);if(r===o.children)return e;if(n)return Array.isArray(r)?g.cloneElement(e,void 0,...r):g.cloneElement(e,void 0,r);let a=e,s={...a.props??{},children:r,...a.key!==void 0&&a.key!==null?{key:a.key}:{}};return g.createElement(a.type,s)}import{Fragment as we,jsx as p,jsxs as Ce}from"react/jsx-runtime";var ce={push:()=>{},replace:()=>{},refresh:()=>{},refreshContext:()=>{}},E=typeof R.createContext=="function"?R.createContext(null):null,q="__WEBFRAMEZ_ROUTER__",de="[data-webframez-head='true']";function x(e){return c(e)??""}function ue(e,t){return t?e===t?"/":e.startsWith(`${t}/`)?e.slice(t.length)||"/":e||"/":e||"/"}function Y(e,t){let n=!t||t==="/"?"/":t.startsWith("/")?t:`/${t}`;return e?n==="/"?e:`${e}${n}`:n}function le(){return x(typeof window>"u"?globalThis.__RSC_ROUTE_BASE_PATH:window.__RSC_ROUTE_BASE_PATH)}function Z(e){if(typeof window>"u")return e||"/";let t=x(window.__RSC_BASENAME),n=le(),o=ue(e||"/",t);return Y(n,o)}function K(e){if(typeof window>"u")return e;let t=window.__RSC_ENDPOINT;return typeof t=="string"&&t.trim()!==""?t:e}function fe(){return typeof window>"u"?null:window[q]??null}function pe(e){typeof window>"u"||(window[q]=e)}function W(){let e={},t=typeof document>"u"?"":document.cookie;if(!t||t.trim()==="")return e;for(let n of t.split(";")){let o=n.trim();if(!o)continue;let r=o.indexOf("="),a=r>=0?o.slice(0,r).trim():o,s=r>=0?o.slice(r+1):"";a&&(e[a]=decodeURIComponent(s))}return e}function D(e,t,n={}){let o=[`${e}=${encodeURIComponent(t)}`];return n.path&&o.push(`Path=${n.path}`),n.domain&&o.push(`Domain=${n.domain}`),typeof n.maxAge=="number"&&o.push(`Max-Age=${Math.floor(n.maxAge)}`),n.expires&&o.push(`Expires=${n.expires.toUTCString()}`),n.sameSite&&o.push(`SameSite=${n.sameSite}`),n.secure&&o.push("Secure"),o.join("; ")}function Ie(){return R.useMemo(()=>({all:()=>W(),get:e=>W()[e],set:(e,t,n)=>{typeof document>"u"||(document.cookie=D(e,t,n))},remove:(e,t)=>{typeof document>"u"||(document.cookie=D(e,"",{...t??{},maxAge:0}))}}),[])}function be(){let e=E?R.useContext(E):null;if(!e){let t=fe();if(t)return t;if(typeof window>"u")return ce;throw new Error("useRouter must be used inside mountWebframezClient()")}return e}function me({active:e}){return p("div",{style:{position:"fixed",top:0,left:0,width:"100%",height:3,zIndex:9999,transformOrigin:"left",transform:e?"scaleX(1)":"scaleX(0)",transition:"transform 180ms ease",background:"linear-gradient(90deg, #0ea5e9, #22c55e)"}})}function F(e){let t=document.createElement("meta");t.setAttribute("data-webframez-head","true");let n=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of n)t.setAttribute(o,String(r));document.head.appendChild(t)}function j(e){let t=document.createElement("link");t.setAttribute("data-webframez-head","true");let n=Object.entries(e).filter(([,o])=>!!o);for(let[o,r]of n)t.setAttribute(o,String(r));document.head.appendChild(t)}function N(e){if(typeof document>"u")return;let t=T(e)??e;V(t),document.title=t.title||"Webframez React";for(let n of document.head.querySelectorAll(de))n.remove();t.description&&F({name:"description",content:t.description}),t.favicon&&j({rel:"icon",href:t.favicon});for(let n of t.meta??[])F(n);for(let n of t.links??[])j(n)}function V(e){if(typeof window>"u")return;let t=T(e)??e,n=c(t.basename),o=c(t.routeBasePath),r=c(t.transportBasePath);window.__RSC_BASENAME=n??"",window.__RSC_ROUTE_BASE_PATH=o??"",r!==void 0&&(window.__RSC_ENDPOINT=Y(r,"/rsc"))}function Re(e){let t=new TextEncoder;return new ReadableStream({start(n){n.enqueue(t.encode(e)),n.close()}})}function ge(){if(typeof window>"u")return null;let e=window.__RSC_INITIAL_PAYLOAD;return typeof e!="string"||e===""?null:(delete window.__RSC_INITIAL_PAYLOAD,ae(Re(e)))}function he(e){let t=K(e),n=Z(window.location.pathname);return ge()??G(fetch(`${t}?path=${encodeURIComponent(n)}&search=${encodeURIComponent(window.location.search)}`,{cache:"no-store",credentials:"same-origin",headers:{Accept:"text/x-component"}}))}function _e(e,t){return function(){let o=R.use(e),r=typeof o.contextModel<"u"&&typeof o.pageModel<"u",[a,s]=f(o.model),[m,u]=f(o.contextModel),[l,h]=f(o.pageModel),[v,I]=f(o.head),[X,_]=f(!1),[J,Q]=f(!1),[ee,A]=f(r);async function b(i){let C=K(t),d=Z(i.pathname);return await G(fetch(`${C}?path=${encodeURIComponent(d)}&search=${encodeURIComponent(i.search)}`,{cache:"no-store",credentials:"same-origin",headers:{Accept:"text/x-component"}}))}async function w(i,C="push"){_(!0);try{let d=await b(i);N(d.head),I(d.head),s(d.model),u(d.contextModel),h(d.pageModel),A(!0);let P=`${i.pathname}${i.search}`;C==="replace"?history.replaceState(null,"",P):C==="push"&&history.pushState(null,"",P)}catch(d){console.error("[webframez-react] Failed to render route",d),s(p("p",{children:"Failed to load route."}))}finally{_(!1)}}async function te(){_(!0);try{let i=await b(new URL(window.location.href));if(N(i.head),I(i.head),Object.prototype.hasOwnProperty.call(i,"contextModel")){u(i.contextModel),A(!0);return}s(i.model),A(!1)}catch(i){console.error("[webframez-react] Failed to refresh route context",i)}finally{_(!1)}}$(()=>{N(v)},[v]),$(()=>{Q(!0);let i=()=>{w(new URL(window.location.href),"none")};return window.addEventListener("popstate",i),()=>{window.removeEventListener("popstate",i)}},[]);let O=R.useMemo(()=>({push:i=>{w(new URL(i,window.location.origin),"push")},replace:i=>{w(new URL(i,window.location.origin),"replace")},refresh:()=>{w(new URL(window.location.href),"none")},refreshContext:()=>{te()}}),[]);pe(O);let ne=ee&&typeof l<"u"?m?p(se,{page:l,children:y(m,l)}):l:a,k=Ce(we,{children:[J?p(me,{active:X}):null,ne??p("p",{style:{padding:24},children:"Loading..."})]});return E?p(E.Provider,{value:O,children:k}):k}}function Oe(e={}){let t=e.rootId??"root",n=document.getElementById(t);if(!n)throw new Error(`Missing #${t} element`);let o=typeof window<"u"&&window.__RSC_ENDPOINT,r=e.rscEndpoint??o??"/rsc",a=Promise.resolve(he(r)).then(u=>(u?.head&&V(u.head),u)),s=_e(a,r);return ie(n,p(s,{}))}export{Oe as mountWebframezClient,Ie as useCookie,be as useRouter};
package/dist/http.cjs CHANGED
@@ -142,6 +142,7 @@ function sendRSC(res, model, options = {}) {
142
142
  } = options;
143
143
  res.statusCode = statusCode;
144
144
  res.setHeader("Content-Type", contentType);
145
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
145
146
  const stream = (0, import_server.renderToPipeableStream)(model, moduleMap, { onError });
146
147
  stream.pipe(res);
147
148
  return stream;
@@ -151,6 +152,7 @@ function sendRSC(res, model, options = {}) {
151
152
  var import_node_fs = __toESM(require("node:fs"), 1);
152
153
  var import_node_module2 = __toESM(require("node:module"), 1);
153
154
  var import_node_path2 = __toESM(require("node:path"), 1);
155
+ var import_route_slot = require("@webtypen/webframez-react/route-slot");
154
156
 
155
157
  // src/head.ts
156
158
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -240,6 +242,16 @@ function isRouteChildrenType(type) {
240
242
  return false;
241
243
  }
242
244
  }
245
+ function isReactElementLike(node) {
246
+ if (!node || typeof node !== "object") {
247
+ return false;
248
+ }
249
+ try {
250
+ return "type" in node && "props" in node;
251
+ } catch {
252
+ return false;
253
+ }
254
+ }
243
255
  function injectRouteChildren(node, routeChildren) {
244
256
  if (node === null || node === void 0 || typeof node === "boolean") {
245
257
  return node;
@@ -255,13 +267,17 @@ function injectRouteChildren(node, routeChildren) {
255
267
  });
256
268
  return changed ? next : node;
257
269
  }
258
- if (!import_react.default.isValidElement(node)) {
270
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
271
+ return routeChildren;
272
+ }
273
+ const isValidElement = import_react.default.isValidElement(node);
274
+ if (!isValidElement && !isReactElementLike(node)) {
259
275
  return node;
260
276
  }
261
- if (isRouteChildrenType(node.type)) {
277
+ if (isValidElement && isRouteChildrenType(node.type)) {
262
278
  return routeChildren;
263
279
  }
264
- const props = node.props;
280
+ const props = node.props ?? {};
265
281
  if (!("children" in props)) {
266
282
  return node;
267
283
  }
@@ -269,10 +285,19 @@ function injectRouteChildren(node, routeChildren) {
269
285
  if (nextChildren === props.children) {
270
286
  return node;
271
287
  }
272
- if (Array.isArray(nextChildren)) {
273
- return import_react.default.cloneElement(node, void 0, ...nextChildren);
288
+ if (isValidElement) {
289
+ if (Array.isArray(nextChildren)) {
290
+ return import_react.default.cloneElement(node, void 0, ...nextChildren);
291
+ }
292
+ return import_react.default.cloneElement(node, void 0, nextChildren);
274
293
  }
275
- return import_react.default.cloneElement(node, void 0, nextChildren);
294
+ const elementLike = node;
295
+ const nextProps = {
296
+ ...elementLike.props ?? {},
297
+ children: nextChildren,
298
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
299
+ };
300
+ return import_react.default.createElement(elementLike.type, nextProps);
276
301
  }
277
302
 
278
303
  // src/file-router.tsx
@@ -613,9 +638,12 @@ function createFileRouter(options) {
613
638
  const errorHead = await resolveHead(errorModule, errorProps);
614
639
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
615
640
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
641
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
616
642
  return {
617
643
  statusCode,
618
644
  model,
645
+ contextModel,
646
+ pageModel: errorNode,
619
647
  head: mergeHead(layoutHead, errorHead)
620
648
  };
621
649
  }
@@ -735,9 +763,12 @@ function createFileRouter(options) {
735
763
  const pageHead = await resolveHead(pageModule, pageContext);
736
764
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
737
765
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
766
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
738
767
  return {
739
768
  statusCode: 200,
740
769
  model,
770
+ contextModel,
771
+ pageModel: pageNode,
741
772
  head: mergeHead(layoutHead, pageHead)
742
773
  };
743
774
  } catch (error) {
@@ -917,7 +948,21 @@ async function renderHtmlFromFlightData(flightData, moduleMap) {
917
948
  ? payload.model
918
949
  : payload;
919
950
 
920
- return renderHtml(model);
951
+ const basename =
952
+ payload &&
953
+ typeof payload === "object" &&
954
+ payload.head &&
955
+ typeof payload.head.basename === "string"
956
+ ? payload.head.basename
957
+ : "";
958
+
959
+ const previousBasename = globalThis.__RSC_BASENAME;
960
+ globalThis.__RSC_BASENAME = basename;
961
+ try {
962
+ return await renderHtml(model);
963
+ } finally {
964
+ globalThis.__RSC_BASENAME = previousBasename;
965
+ }
921
966
  }
922
967
 
923
968
  process.on("message", async (message) => {
@@ -1384,6 +1429,8 @@ function createNodeRequestHandler(options) {
1384
1429
  );
1385
1430
  const payload = {
1386
1431
  model: resolved2.model,
1432
+ contextModel: resolved2.contextModel,
1433
+ pageModel: resolved2.pageModel,
1387
1434
  head: resolved2.head
1388
1435
  };
1389
1436
  sendRSC(res, payload, {
@@ -1406,6 +1453,7 @@ function createNodeRequestHandler(options) {
1406
1453
  } else if (ext === ".json") {
1407
1454
  res.setHeader("Content-Type", "application/json; charset=utf-8");
1408
1455
  }
1456
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
1409
1457
  const stream = import_node_fs2.default.createReadStream(filePath);
1410
1458
  stream.on("error", () => {
1411
1459
  res.statusCode = 404;
@@ -1429,6 +1477,8 @@ function createNodeRequestHandler(options) {
1429
1477
  );
1430
1478
  const initialPayload = {
1431
1479
  model: resolved.model,
1480
+ contextModel: resolved.contextModel,
1481
+ pageModel: resolved.pageModel,
1432
1482
  head: resolved.head
1433
1483
  };
1434
1484
  const initialFlightData = await renderRSCToString(initialPayload, {
package/dist/http.js CHANGED
@@ -117,6 +117,7 @@ function sendRSC(res, model, options = {}) {
117
117
  } = options;
118
118
  res.statusCode = statusCode;
119
119
  res.setHeader("Content-Type", contentType);
120
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
120
121
  const stream = renderToPipeableStream(model, moduleMap, { onError });
121
122
  stream.pipe(res);
122
123
  return stream;
@@ -126,6 +127,7 @@ function sendRSC(res, model, options = {}) {
126
127
  import fs from "node:fs";
127
128
  import Module from "node:module";
128
129
  import path2 from "node:path";
130
+ import { RouteChildrenSlot } from "@webtypen/webframez-react/route-slot";
129
131
 
130
132
  // src/head.ts
131
133
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -215,6 +217,16 @@ function isRouteChildrenType(type) {
215
217
  return false;
216
218
  }
217
219
  }
220
+ function isReactElementLike(node) {
221
+ if (!node || typeof node !== "object") {
222
+ return false;
223
+ }
224
+ try {
225
+ return "type" in node && "props" in node;
226
+ } catch {
227
+ return false;
228
+ }
229
+ }
218
230
  function injectRouteChildren(node, routeChildren) {
219
231
  if (node === null || node === void 0 || typeof node === "boolean") {
220
232
  return node;
@@ -230,13 +242,17 @@ function injectRouteChildren(node, routeChildren) {
230
242
  });
231
243
  return changed ? next : node;
232
244
  }
233
- if (!React.isValidElement(node)) {
245
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
246
+ return routeChildren;
247
+ }
248
+ const isValidElement = React.isValidElement(node);
249
+ if (!isValidElement && !isReactElementLike(node)) {
234
250
  return node;
235
251
  }
236
- if (isRouteChildrenType(node.type)) {
252
+ if (isValidElement && isRouteChildrenType(node.type)) {
237
253
  return routeChildren;
238
254
  }
239
- const props = node.props;
255
+ const props = node.props ?? {};
240
256
  if (!("children" in props)) {
241
257
  return node;
242
258
  }
@@ -244,10 +260,19 @@ function injectRouteChildren(node, routeChildren) {
244
260
  if (nextChildren === props.children) {
245
261
  return node;
246
262
  }
247
- if (Array.isArray(nextChildren)) {
248
- return React.cloneElement(node, void 0, ...nextChildren);
263
+ if (isValidElement) {
264
+ if (Array.isArray(nextChildren)) {
265
+ return React.cloneElement(node, void 0, ...nextChildren);
266
+ }
267
+ return React.cloneElement(node, void 0, nextChildren);
249
268
  }
250
- return React.cloneElement(node, void 0, nextChildren);
269
+ const elementLike = node;
270
+ const nextProps = {
271
+ ...elementLike.props ?? {},
272
+ children: nextChildren,
273
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
274
+ };
275
+ return React.createElement(elementLike.type, nextProps);
251
276
  }
252
277
 
253
278
  // src/file-router.tsx
@@ -588,9 +613,12 @@ function createFileRouter(options) {
588
613
  const errorHead = await resolveHead(errorModule, errorProps);
589
614
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
590
615
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
616
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildrenSlot, {})) : void 0;
591
617
  return {
592
618
  statusCode,
593
619
  model,
620
+ contextModel,
621
+ pageModel: errorNode,
594
622
  head: mergeHead(layoutHead, errorHead)
595
623
  };
596
624
  }
@@ -710,9 +738,12 @@ function createFileRouter(options) {
710
738
  const pageHead = await resolveHead(pageModule, pageContext);
711
739
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
712
740
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
741
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildrenSlot, {})) : void 0;
713
742
  return {
714
743
  statusCode: 200,
715
744
  model,
745
+ contextModel,
746
+ pageModel: pageNode,
716
747
  head: mergeHead(layoutHead, pageHead)
717
748
  };
718
749
  } catch (error) {
@@ -892,7 +923,21 @@ async function renderHtmlFromFlightData(flightData, moduleMap) {
892
923
  ? payload.model
893
924
  : payload;
894
925
 
895
- return renderHtml(model);
926
+ const basename =
927
+ payload &&
928
+ typeof payload === "object" &&
929
+ payload.head &&
930
+ typeof payload.head.basename === "string"
931
+ ? payload.head.basename
932
+ : "";
933
+
934
+ const previousBasename = globalThis.__RSC_BASENAME;
935
+ globalThis.__RSC_BASENAME = basename;
936
+ try {
937
+ return await renderHtml(model);
938
+ } finally {
939
+ globalThis.__RSC_BASENAME = previousBasename;
940
+ }
896
941
  }
897
942
 
898
943
  process.on("message", async (message) => {
@@ -1359,6 +1404,8 @@ function createNodeRequestHandler(options) {
1359
1404
  );
1360
1405
  const payload = {
1361
1406
  model: resolved2.model,
1407
+ contextModel: resolved2.contextModel,
1408
+ pageModel: resolved2.pageModel,
1362
1409
  head: resolved2.head
1363
1410
  };
1364
1411
  sendRSC(res, payload, {
@@ -1381,6 +1428,7 @@ function createNodeRequestHandler(options) {
1381
1428
  } else if (ext === ".json") {
1382
1429
  res.setHeader("Content-Type", "application/json; charset=utf-8");
1383
1430
  }
1431
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
1384
1432
  const stream = fs2.createReadStream(filePath);
1385
1433
  stream.on("error", () => {
1386
1434
  res.statusCode = 404;
@@ -1404,6 +1452,8 @@ function createNodeRequestHandler(options) {
1404
1452
  );
1405
1453
  const initialPayload = {
1406
1454
  model: resolved.model,
1455
+ contextModel: resolved.contextModel,
1456
+ pageModel: resolved.pageModel,
1407
1457
  head: resolved.head
1408
1458
  };
1409
1459
  const initialFlightData = await renderRSCToString(initialPayload, {
package/dist/index.cjs CHANGED
@@ -147,6 +147,7 @@ function sendRSC(res, model, options = {}) {
147
147
  } = options;
148
148
  res.statusCode = statusCode;
149
149
  res.setHeader("Content-Type", contentType);
150
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
150
151
  const stream = (0, import_server.renderToPipeableStream)(model, moduleMap, { onError });
151
152
  stream.pipe(res);
152
153
  return stream;
@@ -184,6 +185,7 @@ function createRSCHandler(options) {
184
185
  var import_node_fs = __toESM(require("node:fs"), 1);
185
186
  var import_node_module2 = __toESM(require("node:module"), 1);
186
187
  var import_node_path2 = __toESM(require("node:path"), 1);
188
+ var import_route_slot = require("@webtypen/webframez-react/route-slot");
187
189
 
188
190
  // src/head.ts
189
191
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -273,6 +275,16 @@ function isRouteChildrenType(type) {
273
275
  return false;
274
276
  }
275
277
  }
278
+ function isReactElementLike(node) {
279
+ if (!node || typeof node !== "object") {
280
+ return false;
281
+ }
282
+ try {
283
+ return "type" in node && "props" in node;
284
+ } catch {
285
+ return false;
286
+ }
287
+ }
276
288
  function injectRouteChildren(node, routeChildren) {
277
289
  if (node === null || node === void 0 || typeof node === "boolean") {
278
290
  return node;
@@ -288,13 +300,17 @@ function injectRouteChildren(node, routeChildren) {
288
300
  });
289
301
  return changed ? next : node;
290
302
  }
291
- if (!import_react.default.isValidElement(node)) {
303
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
304
+ return routeChildren;
305
+ }
306
+ const isValidElement = import_react.default.isValidElement(node);
307
+ if (!isValidElement && !isReactElementLike(node)) {
292
308
  return node;
293
309
  }
294
- if (isRouteChildrenType(node.type)) {
310
+ if (isValidElement && isRouteChildrenType(node.type)) {
295
311
  return routeChildren;
296
312
  }
297
- const props = node.props;
313
+ const props = node.props ?? {};
298
314
  if (!("children" in props)) {
299
315
  return node;
300
316
  }
@@ -302,10 +318,19 @@ function injectRouteChildren(node, routeChildren) {
302
318
  if (nextChildren === props.children) {
303
319
  return node;
304
320
  }
305
- if (Array.isArray(nextChildren)) {
306
- return import_react.default.cloneElement(node, void 0, ...nextChildren);
321
+ if (isValidElement) {
322
+ if (Array.isArray(nextChildren)) {
323
+ return import_react.default.cloneElement(node, void 0, ...nextChildren);
324
+ }
325
+ return import_react.default.cloneElement(node, void 0, nextChildren);
307
326
  }
308
- return import_react.default.cloneElement(node, void 0, nextChildren);
327
+ const elementLike = node;
328
+ const nextProps = {
329
+ ...elementLike.props ?? {},
330
+ children: nextChildren,
331
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
332
+ };
333
+ return import_react.default.createElement(elementLike.type, nextProps);
309
334
  }
310
335
 
311
336
  // src/file-router.tsx
@@ -646,9 +671,12 @@ function createFileRouter(options) {
646
671
  const errorHead = await resolveHead(errorModule, errorProps);
647
672
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
648
673
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
674
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
649
675
  return {
650
676
  statusCode,
651
677
  model,
678
+ contextModel,
679
+ pageModel: errorNode,
652
680
  head: mergeHead(layoutHead, errorHead)
653
681
  };
654
682
  }
@@ -768,9 +796,12 @@ function createFileRouter(options) {
768
796
  const pageHead = await resolveHead(pageModule, pageContext);
769
797
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
770
798
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
799
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
771
800
  return {
772
801
  statusCode: 200,
773
802
  model,
803
+ contextModel,
804
+ pageModel: pageNode,
774
805
  head: mergeHead(layoutHead, pageHead)
775
806
  };
776
807
  } catch (error) {
@@ -954,7 +985,21 @@ async function renderHtmlFromFlightData(flightData, moduleMap) {
954
985
  ? payload.model
955
986
  : payload;
956
987
 
957
- return renderHtml(model);
988
+ const basename =
989
+ payload &&
990
+ typeof payload === "object" &&
991
+ payload.head &&
992
+ typeof payload.head.basename === "string"
993
+ ? payload.head.basename
994
+ : "";
995
+
996
+ const previousBasename = globalThis.__RSC_BASENAME;
997
+ globalThis.__RSC_BASENAME = basename;
998
+ try {
999
+ return await renderHtml(model);
1000
+ } finally {
1001
+ globalThis.__RSC_BASENAME = previousBasename;
1002
+ }
958
1003
  }
959
1004
 
960
1005
  process.on("message", async (message) => {
@@ -1421,6 +1466,8 @@ function createNodeRequestHandler(options) {
1421
1466
  );
1422
1467
  const payload = {
1423
1468
  model: resolved2.model,
1469
+ contextModel: resolved2.contextModel,
1470
+ pageModel: resolved2.pageModel,
1424
1471
  head: resolved2.head
1425
1472
  };
1426
1473
  sendRSC(res, payload, {
@@ -1443,6 +1490,7 @@ function createNodeRequestHandler(options) {
1443
1490
  } else if (ext === ".json") {
1444
1491
  res.setHeader("Content-Type", "application/json; charset=utf-8");
1445
1492
  }
1493
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
1446
1494
  const stream = import_node_fs2.default.createReadStream(filePath);
1447
1495
  stream.on("error", () => {
1448
1496
  res.statusCode = 404;
@@ -1466,6 +1514,8 @@ function createNodeRequestHandler(options) {
1466
1514
  );
1467
1515
  const initialPayload = {
1468
1516
  model: resolved.model,
1517
+ contextModel: resolved.contextModel,
1518
+ pageModel: resolved.pageModel,
1469
1519
  head: resolved.head
1470
1520
  };
1471
1521
  const initialFlightData = await renderRSCToString(initialPayload, {
package/dist/index.js CHANGED
@@ -111,6 +111,7 @@ function sendRSC(res, model, options = {}) {
111
111
  } = options;
112
112
  res.statusCode = statusCode;
113
113
  res.setHeader("Content-Type", contentType);
114
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
114
115
  const stream = renderToPipeableStream(model, moduleMap, { onError });
115
116
  stream.pipe(res);
116
117
  return stream;
@@ -148,6 +149,7 @@ function createRSCHandler(options) {
148
149
  import fs from "node:fs";
149
150
  import Module from "node:module";
150
151
  import path2 from "node:path";
152
+ import { RouteChildrenSlot } from "@webtypen/webframez-react/route-slot";
151
153
 
152
154
  // src/head.ts
153
155
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -237,6 +239,16 @@ function isRouteChildrenType(type) {
237
239
  return false;
238
240
  }
239
241
  }
242
+ function isReactElementLike(node) {
243
+ if (!node || typeof node !== "object") {
244
+ return false;
245
+ }
246
+ try {
247
+ return "type" in node && "props" in node;
248
+ } catch {
249
+ return false;
250
+ }
251
+ }
240
252
  function injectRouteChildren(node, routeChildren) {
241
253
  if (node === null || node === void 0 || typeof node === "boolean") {
242
254
  return node;
@@ -252,13 +264,17 @@ function injectRouteChildren(node, routeChildren) {
252
264
  });
253
265
  return changed ? next : node;
254
266
  }
255
- if (!React.isValidElement(node)) {
267
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
268
+ return routeChildren;
269
+ }
270
+ const isValidElement = React.isValidElement(node);
271
+ if (!isValidElement && !isReactElementLike(node)) {
256
272
  return node;
257
273
  }
258
- if (isRouteChildrenType(node.type)) {
274
+ if (isValidElement && isRouteChildrenType(node.type)) {
259
275
  return routeChildren;
260
276
  }
261
- const props = node.props;
277
+ const props = node.props ?? {};
262
278
  if (!("children" in props)) {
263
279
  return node;
264
280
  }
@@ -266,10 +282,19 @@ function injectRouteChildren(node, routeChildren) {
266
282
  if (nextChildren === props.children) {
267
283
  return node;
268
284
  }
269
- if (Array.isArray(nextChildren)) {
270
- return React.cloneElement(node, void 0, ...nextChildren);
285
+ if (isValidElement) {
286
+ if (Array.isArray(nextChildren)) {
287
+ return React.cloneElement(node, void 0, ...nextChildren);
288
+ }
289
+ return React.cloneElement(node, void 0, nextChildren);
271
290
  }
272
- return React.cloneElement(node, void 0, nextChildren);
291
+ const elementLike = node;
292
+ const nextProps = {
293
+ ...elementLike.props ?? {},
294
+ children: nextChildren,
295
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
296
+ };
297
+ return React.createElement(elementLike.type, nextProps);
273
298
  }
274
299
 
275
300
  // src/file-router.tsx
@@ -610,9 +635,12 @@ function createFileRouter(options) {
610
635
  const errorHead = await resolveHead(errorModule, errorProps);
611
636
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
612
637
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
638
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildrenSlot, {})) : void 0;
613
639
  return {
614
640
  statusCode,
615
641
  model,
642
+ contextModel,
643
+ pageModel: errorNode,
616
644
  head: mergeHead(layoutHead, errorHead)
617
645
  };
618
646
  }
@@ -732,9 +760,12 @@ function createFileRouter(options) {
732
760
  const pageHead = await resolveHead(pageModule, pageContext);
733
761
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
734
762
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
763
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildrenSlot, {})) : void 0;
735
764
  return {
736
765
  statusCode: 200,
737
766
  model,
767
+ contextModel,
768
+ pageModel: pageNode,
738
769
  head: mergeHead(layoutHead, pageHead)
739
770
  };
740
771
  } catch (error) {
@@ -918,7 +949,21 @@ async function renderHtmlFromFlightData(flightData, moduleMap) {
918
949
  ? payload.model
919
950
  : payload;
920
951
 
921
- return renderHtml(model);
952
+ const basename =
953
+ payload &&
954
+ typeof payload === "object" &&
955
+ payload.head &&
956
+ typeof payload.head.basename === "string"
957
+ ? payload.head.basename
958
+ : "";
959
+
960
+ const previousBasename = globalThis.__RSC_BASENAME;
961
+ globalThis.__RSC_BASENAME = basename;
962
+ try {
963
+ return await renderHtml(model);
964
+ } finally {
965
+ globalThis.__RSC_BASENAME = previousBasename;
966
+ }
922
967
  }
923
968
 
924
969
  process.on("message", async (message) => {
@@ -1385,6 +1430,8 @@ function createNodeRequestHandler(options) {
1385
1430
  );
1386
1431
  const payload = {
1387
1432
  model: resolved2.model,
1433
+ contextModel: resolved2.contextModel,
1434
+ pageModel: resolved2.pageModel,
1388
1435
  head: resolved2.head
1389
1436
  };
1390
1437
  sendRSC(res, payload, {
@@ -1407,6 +1454,7 @@ function createNodeRequestHandler(options) {
1407
1454
  } else if (ext === ".json") {
1408
1455
  res.setHeader("Content-Type", "application/json; charset=utf-8");
1409
1456
  }
1457
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
1410
1458
  const stream = fs2.createReadStream(filePath);
1411
1459
  stream.on("error", () => {
1412
1460
  res.statusCode = 404;
@@ -1430,6 +1478,8 @@ function createNodeRequestHandler(options) {
1430
1478
  );
1431
1479
  const initialPayload = {
1432
1480
  model: resolved.model,
1481
+ contextModel: resolved.contextModel,
1482
+ pageModel: resolved.pageModel,
1433
1483
  head: resolved.head
1434
1484
  };
1435
1485
  const initialFlightData = await renderRSCToString(initialPayload, {
@@ -0,0 +1,53 @@
1
+ "use client";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/route-slot.tsx
31
+ var route_slot_exports = {};
32
+ __export(route_slot_exports, {
33
+ RouteChildrenSlot: () => RouteChildrenSlot,
34
+ RouteChildrenSlotProvider: () => RouteChildrenSlotProvider
35
+ });
36
+ module.exports = __toCommonJS(route_slot_exports);
37
+ var import_react = __toESM(require("react"), 1);
38
+ var import_jsx_runtime = require("react/jsx-runtime");
39
+ var RouteChildrenSlotContext = import_react.default.createContext(null);
40
+ function RouteChildrenSlotProvider({
41
+ children,
42
+ page
43
+ }) {
44
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RouteChildrenSlotContext.Provider, { value: page, children });
45
+ }
46
+ function RouteChildrenSlot() {
47
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: import_react.default.useContext(RouteChildrenSlotContext) });
48
+ }
49
+ // Annotate the CommonJS export names for ESM import in node:
50
+ 0 && (module.exports = {
51
+ RouteChildrenSlot,
52
+ RouteChildrenSlotProvider
53
+ });
@@ -0,0 +1,7 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ export function RouteChildrenSlotProvider(props: {
4
+ children: ReactNode;
5
+ page: ReactNode;
6
+ }): ReactNode;
7
+ export function RouteChildrenSlot(): ReactNode;
@@ -0,0 +1,19 @@
1
+ "use client";
2
+
3
+ // src/route-slot.tsx
4
+ import React from "react";
5
+ import { Fragment, jsx } from "react/jsx-runtime";
6
+ var RouteChildrenSlotContext = React.createContext(null);
7
+ function RouteChildrenSlotProvider({
8
+ children,
9
+ page
10
+ }) {
11
+ return /* @__PURE__ */ jsx(RouteChildrenSlotContext.Provider, { value: page, children });
12
+ }
13
+ function RouteChildrenSlot() {
14
+ return /* @__PURE__ */ jsx(Fragment, { children: React.useContext(RouteChildrenSlotContext) });
15
+ }
16
+ export {
17
+ RouteChildrenSlot,
18
+ RouteChildrenSlotProvider
19
+ };
package/dist/router.cjs CHANGED
@@ -40,6 +40,7 @@ module.exports = __toCommonJS(router_exports);
40
40
  var import_node_fs = __toESM(require("node:fs"), 1);
41
41
  var import_node_module = __toESM(require("node:module"), 1);
42
42
  var import_node_path = __toESM(require("node:path"), 1);
43
+ var import_route_slot = require("@webtypen/webframez-react/route-slot");
43
44
 
44
45
  // src/head.ts
45
46
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -129,6 +130,16 @@ function isRouteChildrenType(type) {
129
130
  return false;
130
131
  }
131
132
  }
133
+ function isReactElementLike(node) {
134
+ if (!node || typeof node !== "object") {
135
+ return false;
136
+ }
137
+ try {
138
+ return "type" in node && "props" in node;
139
+ } catch {
140
+ return false;
141
+ }
142
+ }
132
143
  function injectRouteChildren(node, routeChildren) {
133
144
  if (node === null || node === void 0 || typeof node === "boolean") {
134
145
  return node;
@@ -144,13 +155,17 @@ function injectRouteChildren(node, routeChildren) {
144
155
  });
145
156
  return changed ? next : node;
146
157
  }
147
- if (!import_react.default.isValidElement(node)) {
158
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
159
+ return routeChildren;
160
+ }
161
+ const isValidElement = import_react.default.isValidElement(node);
162
+ if (!isValidElement && !isReactElementLike(node)) {
148
163
  return node;
149
164
  }
150
- if (isRouteChildrenType(node.type)) {
165
+ if (isValidElement && isRouteChildrenType(node.type)) {
151
166
  return routeChildren;
152
167
  }
153
- const props = node.props;
168
+ const props = node.props ?? {};
154
169
  if (!("children" in props)) {
155
170
  return node;
156
171
  }
@@ -158,10 +173,19 @@ function injectRouteChildren(node, routeChildren) {
158
173
  if (nextChildren === props.children) {
159
174
  return node;
160
175
  }
161
- if (Array.isArray(nextChildren)) {
162
- return import_react.default.cloneElement(node, void 0, ...nextChildren);
176
+ if (isValidElement) {
177
+ if (Array.isArray(nextChildren)) {
178
+ return import_react.default.cloneElement(node, void 0, ...nextChildren);
179
+ }
180
+ return import_react.default.cloneElement(node, void 0, nextChildren);
163
181
  }
164
- return import_react.default.cloneElement(node, void 0, nextChildren);
182
+ const elementLike = node;
183
+ const nextProps = {
184
+ ...elementLike.props ?? {},
185
+ children: nextChildren,
186
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
187
+ };
188
+ return import_react.default.createElement(elementLike.type, nextProps);
165
189
  }
166
190
 
167
191
  // src/file-router.tsx
@@ -502,9 +526,12 @@ function createFileRouter(options) {
502
526
  const errorHead = await resolveHead(errorModule, errorProps);
503
527
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
504
528
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
529
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
505
530
  return {
506
531
  statusCode,
507
532
  model,
533
+ contextModel,
534
+ pageModel: errorNode,
508
535
  head: mergeHead(layoutHead, errorHead)
509
536
  };
510
537
  }
@@ -624,9 +651,12 @@ function createFileRouter(options) {
624
651
  const pageHead = await resolveHead(pageModule, pageContext);
625
652
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
626
653
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
654
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
627
655
  return {
628
656
  statusCode: 200,
629
657
  model,
658
+ contextModel,
659
+ pageModel: pageNode,
630
660
  head: mergeHead(layoutHead, pageHead)
631
661
  };
632
662
  } catch (error) {
package/dist/router.d.ts CHANGED
@@ -5,6 +5,8 @@ export type ResolvedRoute = {
5
5
  statusCode: number;
6
6
  model: ReactNode;
7
7
  head: HeadConfig;
8
+ contextModel?: ReactNode;
9
+ pageModel?: ReactNode;
8
10
  };
9
11
 
10
12
  export function createFileRouter(options: { pagesDir: string }): {
package/dist/router.js CHANGED
@@ -10,6 +10,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
10
10
  import fs from "node:fs";
11
11
  import Module from "node:module";
12
12
  import path from "node:path";
13
+ import { RouteChildrenSlot } from "@webtypen/webframez-react/route-slot";
13
14
 
14
15
  // src/head.ts
15
16
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -99,6 +100,16 @@ function isRouteChildrenType(type) {
99
100
  return false;
100
101
  }
101
102
  }
103
+ function isReactElementLike(node) {
104
+ if (!node || typeof node !== "object") {
105
+ return false;
106
+ }
107
+ try {
108
+ return "type" in node && "props" in node;
109
+ } catch {
110
+ return false;
111
+ }
112
+ }
102
113
  function injectRouteChildren(node, routeChildren) {
103
114
  if (node === null || node === void 0 || typeof node === "boolean") {
104
115
  return node;
@@ -114,13 +125,17 @@ function injectRouteChildren(node, routeChildren) {
114
125
  });
115
126
  return changed ? next : node;
116
127
  }
117
- if (!React.isValidElement(node)) {
128
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
129
+ return routeChildren;
130
+ }
131
+ const isValidElement = React.isValidElement(node);
132
+ if (!isValidElement && !isReactElementLike(node)) {
118
133
  return node;
119
134
  }
120
- if (isRouteChildrenType(node.type)) {
135
+ if (isValidElement && isRouteChildrenType(node.type)) {
121
136
  return routeChildren;
122
137
  }
123
- const props = node.props;
138
+ const props = node.props ?? {};
124
139
  if (!("children" in props)) {
125
140
  return node;
126
141
  }
@@ -128,10 +143,19 @@ function injectRouteChildren(node, routeChildren) {
128
143
  if (nextChildren === props.children) {
129
144
  return node;
130
145
  }
131
- if (Array.isArray(nextChildren)) {
132
- return React.cloneElement(node, void 0, ...nextChildren);
146
+ if (isValidElement) {
147
+ if (Array.isArray(nextChildren)) {
148
+ return React.cloneElement(node, void 0, ...nextChildren);
149
+ }
150
+ return React.cloneElement(node, void 0, nextChildren);
133
151
  }
134
- return React.cloneElement(node, void 0, nextChildren);
152
+ const elementLike = node;
153
+ const nextProps = {
154
+ ...elementLike.props ?? {},
155
+ children: nextChildren,
156
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
157
+ };
158
+ return React.createElement(elementLike.type, nextProps);
135
159
  }
136
160
 
137
161
  // src/file-router.tsx
@@ -472,9 +496,12 @@ function createFileRouter(options) {
472
496
  const errorHead = await resolveHead(errorModule, errorProps);
473
497
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
474
498
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
499
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildrenSlot, {})) : void 0;
475
500
  return {
476
501
  statusCode,
477
502
  model,
503
+ contextModel,
504
+ pageModel: errorNode,
478
505
  head: mergeHead(layoutHead, errorHead)
479
506
  };
480
507
  }
@@ -594,9 +621,12 @@ function createFileRouter(options) {
594
621
  const pageHead = await resolveHead(pageModule, pageContext);
595
622
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
596
623
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
624
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildrenSlot, {})) : void 0;
597
625
  return {
598
626
  statusCode: 200,
599
627
  model,
628
+ contextModel,
629
+ pageModel: pageNode,
600
630
  head: mergeHead(layoutHead, pageHead)
601
631
  };
602
632
  } catch (error) {
package/dist/types.d.ts CHANGED
@@ -71,6 +71,8 @@ export type HeadConfig = {
71
71
  export type ClientNavigationPayload = {
72
72
  model: ReactNode;
73
73
  head: HeadConfig;
74
+ contextModel?: ReactNode;
75
+ pageModel?: ReactNode;
74
76
  };
75
77
 
76
78
  export type HeadResolver<TContext = RouteContext> = (
@@ -145,6 +145,7 @@ function sendRSC(res, model, options = {}) {
145
145
  } = options;
146
146
  res.statusCode = statusCode;
147
147
  res.setHeader("Content-Type", contentType);
148
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
148
149
  const stream = (0, import_server.renderToPipeableStream)(model, moduleMap, { onError });
149
150
  stream.pipe(res);
150
151
  return stream;
@@ -154,6 +155,7 @@ function sendRSC(res, model, options = {}) {
154
155
  var import_node_fs = __toESM(require("node:fs"), 1);
155
156
  var import_node_module2 = __toESM(require("node:module"), 1);
156
157
  var import_node_path2 = __toESM(require("node:path"), 1);
158
+ var import_route_slot = require("@webtypen/webframez-react/route-slot");
157
159
 
158
160
  // src/head.ts
159
161
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -243,6 +245,16 @@ function isRouteChildrenType(type) {
243
245
  return false;
244
246
  }
245
247
  }
248
+ function isReactElementLike(node) {
249
+ if (!node || typeof node !== "object") {
250
+ return false;
251
+ }
252
+ try {
253
+ return "type" in node && "props" in node;
254
+ } catch {
255
+ return false;
256
+ }
257
+ }
246
258
  function injectRouteChildren(node, routeChildren) {
247
259
  if (node === null || node === void 0 || typeof node === "boolean") {
248
260
  return node;
@@ -258,13 +270,17 @@ function injectRouteChildren(node, routeChildren) {
258
270
  });
259
271
  return changed ? next : node;
260
272
  }
261
- if (!import_react.default.isValidElement(node)) {
273
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
274
+ return routeChildren;
275
+ }
276
+ const isValidElement = import_react.default.isValidElement(node);
277
+ if (!isValidElement && !isReactElementLike(node)) {
262
278
  return node;
263
279
  }
264
- if (isRouteChildrenType(node.type)) {
280
+ if (isValidElement && isRouteChildrenType(node.type)) {
265
281
  return routeChildren;
266
282
  }
267
- const props = node.props;
283
+ const props = node.props ?? {};
268
284
  if (!("children" in props)) {
269
285
  return node;
270
286
  }
@@ -272,10 +288,19 @@ function injectRouteChildren(node, routeChildren) {
272
288
  if (nextChildren === props.children) {
273
289
  return node;
274
290
  }
275
- if (Array.isArray(nextChildren)) {
276
- return import_react.default.cloneElement(node, void 0, ...nextChildren);
291
+ if (isValidElement) {
292
+ if (Array.isArray(nextChildren)) {
293
+ return import_react.default.cloneElement(node, void 0, ...nextChildren);
294
+ }
295
+ return import_react.default.cloneElement(node, void 0, nextChildren);
277
296
  }
278
- return import_react.default.cloneElement(node, void 0, nextChildren);
297
+ const elementLike = node;
298
+ const nextProps = {
299
+ ...elementLike.props ?? {},
300
+ children: nextChildren,
301
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
302
+ };
303
+ return import_react.default.createElement(elementLike.type, nextProps);
279
304
  }
280
305
 
281
306
  // src/file-router.tsx
@@ -616,9 +641,12 @@ function createFileRouter(options) {
616
641
  const errorHead = await resolveHead(errorModule, errorProps);
617
642
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
618
643
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
644
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
619
645
  return {
620
646
  statusCode,
621
647
  model,
648
+ contextModel,
649
+ pageModel: errorNode,
622
650
  head: mergeHead(layoutHead, errorHead)
623
651
  };
624
652
  }
@@ -738,9 +766,12 @@ function createFileRouter(options) {
738
766
  const pageHead = await resolveHead(pageModule, pageContext);
739
767
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
740
768
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
769
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_route_slot.RouteChildrenSlot, {})) : void 0;
741
770
  return {
742
771
  statusCode: 200,
743
772
  model,
773
+ contextModel,
774
+ pageModel: pageNode,
744
775
  head: mergeHead(layoutHead, pageHead)
745
776
  };
746
777
  } catch (error) {
@@ -920,7 +951,21 @@ async function renderHtmlFromFlightData(flightData, moduleMap) {
920
951
  ? payload.model
921
952
  : payload;
922
953
 
923
- return renderHtml(model);
954
+ const basename =
955
+ payload &&
956
+ typeof payload === "object" &&
957
+ payload.head &&
958
+ typeof payload.head.basename === "string"
959
+ ? payload.head.basename
960
+ : "";
961
+
962
+ const previousBasename = globalThis.__RSC_BASENAME;
963
+ globalThis.__RSC_BASENAME = basename;
964
+ try {
965
+ return await renderHtml(model);
966
+ } finally {
967
+ globalThis.__RSC_BASENAME = previousBasename;
968
+ }
924
969
  }
925
970
 
926
971
  process.on("message", async (message) => {
@@ -1387,6 +1432,8 @@ function createNodeRequestHandler(options) {
1387
1432
  );
1388
1433
  const payload = {
1389
1434
  model: resolved2.model,
1435
+ contextModel: resolved2.contextModel,
1436
+ pageModel: resolved2.pageModel,
1390
1437
  head: resolved2.head
1391
1438
  };
1392
1439
  sendRSC(res, payload, {
@@ -1409,6 +1456,7 @@ function createNodeRequestHandler(options) {
1409
1456
  } else if (ext === ".json") {
1410
1457
  res.setHeader("Content-Type", "application/json; charset=utf-8");
1411
1458
  }
1459
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
1412
1460
  const stream = import_node_fs2.default.createReadStream(filePath);
1413
1461
  stream.on("error", () => {
1414
1462
  res.statusCode = 404;
@@ -1432,6 +1480,8 @@ function createNodeRequestHandler(options) {
1432
1480
  );
1433
1481
  const initialPayload = {
1434
1482
  model: resolved.model,
1483
+ contextModel: resolved.contextModel,
1484
+ pageModel: resolved.pageModel,
1435
1485
  head: resolved.head
1436
1486
  };
1437
1487
  const initialFlightData = await renderRSCToString(initialPayload, {
@@ -117,6 +117,7 @@ function sendRSC(res, model, options = {}) {
117
117
  } = options;
118
118
  res.statusCode = statusCode;
119
119
  res.setHeader("Content-Type", contentType);
120
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
120
121
  const stream = renderToPipeableStream(model, moduleMap, { onError });
121
122
  stream.pipe(res);
122
123
  return stream;
@@ -126,6 +127,7 @@ function sendRSC(res, model, options = {}) {
126
127
  import fs from "node:fs";
127
128
  import Module from "node:module";
128
129
  import path2 from "node:path";
130
+ import { RouteChildrenSlot } from "@webtypen/webframez-react/route-slot";
129
131
 
130
132
  // src/head.ts
131
133
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
@@ -215,6 +217,16 @@ function isRouteChildrenType(type) {
215
217
  return false;
216
218
  }
217
219
  }
220
+ function isReactElementLike(node) {
221
+ if (!node || typeof node !== "object") {
222
+ return false;
223
+ }
224
+ try {
225
+ return "type" in node && "props" in node;
226
+ } catch {
227
+ return false;
228
+ }
229
+ }
218
230
  function injectRouteChildren(node, routeChildren) {
219
231
  if (node === null || node === void 0 || typeof node === "boolean") {
220
232
  return node;
@@ -230,13 +242,17 @@ function injectRouteChildren(node, routeChildren) {
230
242
  });
231
243
  return changed ? next : node;
232
244
  }
233
- if (!React.isValidElement(node)) {
245
+ if (isReactElementLike(node) && isRouteChildrenType(node.type)) {
246
+ return routeChildren;
247
+ }
248
+ const isValidElement = React.isValidElement(node);
249
+ if (!isValidElement && !isReactElementLike(node)) {
234
250
  return node;
235
251
  }
236
- if (isRouteChildrenType(node.type)) {
252
+ if (isValidElement && isRouteChildrenType(node.type)) {
237
253
  return routeChildren;
238
254
  }
239
- const props = node.props;
255
+ const props = node.props ?? {};
240
256
  if (!("children" in props)) {
241
257
  return node;
242
258
  }
@@ -244,10 +260,19 @@ function injectRouteChildren(node, routeChildren) {
244
260
  if (nextChildren === props.children) {
245
261
  return node;
246
262
  }
247
- if (Array.isArray(nextChildren)) {
248
- return React.cloneElement(node, void 0, ...nextChildren);
263
+ if (isValidElement) {
264
+ if (Array.isArray(nextChildren)) {
265
+ return React.cloneElement(node, void 0, ...nextChildren);
266
+ }
267
+ return React.cloneElement(node, void 0, nextChildren);
249
268
  }
250
- return React.cloneElement(node, void 0, nextChildren);
269
+ const elementLike = node;
270
+ const nextProps = {
271
+ ...elementLike.props ?? {},
272
+ children: nextChildren,
273
+ ...elementLike.key !== void 0 && elementLike.key !== null ? { key: elementLike.key } : {}
274
+ };
275
+ return React.createElement(elementLike.type, nextProps);
251
276
  }
252
277
 
253
278
  // src/file-router.tsx
@@ -588,9 +613,12 @@ function createFileRouter(options) {
588
613
  const errorHead = await resolveHead(errorModule, errorProps);
589
614
  const layoutNode = layoutModule ? await layoutModule.default(context) : null;
590
615
  const model = layoutNode ? injectRouteChildren(layoutNode, errorNode) : errorNode;
616
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildrenSlot, {})) : void 0;
591
617
  return {
592
618
  statusCode,
593
619
  model,
620
+ contextModel,
621
+ pageModel: errorNode,
594
622
  head: mergeHead(layoutHead, errorHead)
595
623
  };
596
624
  }
@@ -710,9 +738,12 @@ function createFileRouter(options) {
710
738
  const pageHead = await resolveHead(pageModule, pageContext);
711
739
  const layoutNode = layoutModule ? await layoutModule.default(pageContext) : null;
712
740
  const model = layoutNode ? injectRouteChildren(layoutNode, pageNode) : pageNode;
741
+ const contextModel = layoutNode ? injectRouteChildren(layoutNode, /* @__PURE__ */ jsx(RouteChildrenSlot, {})) : void 0;
713
742
  return {
714
743
  statusCode: 200,
715
744
  model,
745
+ contextModel,
746
+ pageModel: pageNode,
716
747
  head: mergeHead(layoutHead, pageHead)
717
748
  };
718
749
  } catch (error) {
@@ -892,7 +923,21 @@ async function renderHtmlFromFlightData(flightData, moduleMap) {
892
923
  ? payload.model
893
924
  : payload;
894
925
 
895
- return renderHtml(model);
926
+ const basename =
927
+ payload &&
928
+ typeof payload === "object" &&
929
+ payload.head &&
930
+ typeof payload.head.basename === "string"
931
+ ? payload.head.basename
932
+ : "";
933
+
934
+ const previousBasename = globalThis.__RSC_BASENAME;
935
+ globalThis.__RSC_BASENAME = basename;
936
+ try {
937
+ return await renderHtml(model);
938
+ } finally {
939
+ globalThis.__RSC_BASENAME = previousBasename;
940
+ }
896
941
  }
897
942
 
898
943
  process.on("message", async (message) => {
@@ -1359,6 +1404,8 @@ function createNodeRequestHandler(options) {
1359
1404
  );
1360
1405
  const payload = {
1361
1406
  model: resolved2.model,
1407
+ contextModel: resolved2.contextModel,
1408
+ pageModel: resolved2.pageModel,
1362
1409
  head: resolved2.head
1363
1410
  };
1364
1411
  sendRSC(res, payload, {
@@ -1381,6 +1428,7 @@ function createNodeRequestHandler(options) {
1381
1428
  } else if (ext === ".json") {
1382
1429
  res.setHeader("Content-Type", "application/json; charset=utf-8");
1383
1430
  }
1431
+ res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
1384
1432
  const stream = fs2.createReadStream(filePath);
1385
1433
  stream.on("error", () => {
1386
1434
  res.statusCode = 404;
@@ -1404,6 +1452,8 @@ function createNodeRequestHandler(options) {
1404
1452
  );
1405
1453
  const initialPayload = {
1406
1454
  model: resolved.model,
1455
+ contextModel: resolved.contextModel,
1456
+ pageModel: resolved.pageModel,
1407
1457
  head: resolved.head
1408
1458
  };
1409
1459
  const initialFlightData = await renderRSCToString(initialPayload, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webtypen/webframez-react",
3
- "version": "0.0.32",
3
+ "version": "0.0.33",
4
4
  "description": "TypeScript React RSC addition for @webtypen/webframez-core",
5
5
  "homepage": "https://webtypen.de/",
6
6
  "author": {
@@ -43,6 +43,11 @@
43
43
  "import": "./dist/navigation.js",
44
44
  "require": "./dist/navigation.cjs"
45
45
  },
46
+ "./route-slot": {
47
+ "types": "./dist/route-slot.d.ts",
48
+ "import": "./dist/route-slot.js",
49
+ "require": "./dist/route-slot.cjs"
50
+ },
46
51
  "./types": {
47
52
  "types": "./dist/types.d.ts",
48
53
  "import": "./dist/types.js",