@webtypen/webframez-react 0.0.30 → 0.0.32

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 N=Object.create;var m=Object.defineProperty;var U=Object.getOwnPropertyDescriptor;var z=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var W=(e,t)=>{for(var n in t)m(e,n,{get:t[n],enumerable:!0})},v=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of z(t))!M.call(e,r)&&r!==n&&m(e,r,{get:()=>t[r],enumerable:!(o=U(t,r))||o.enumerable});return e};var D=(e,t,n)=>(n=e!=null?N(B(e)):{},v(t||!e||!e.__esModule?m(n,"default",{value:e,enumerable:!0}):n,e)),F=e=>v(m({},"__esModule",{value:!0}),e);var oe={};W(oe,{mountWebframezClient:()=>ne,useCookie:()=>X,useRouter:()=>K});module.exports=F(oe);var i=D(require("react"),1),L=require("react-dom/client"),l=require("react-server-dom-webpack/client");var G=/^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;function u(e){let t=e?.trim();if(t)return t==="/"?"/":t.replace(/\/+$/,"")}function x(e,t){let n=e.trim(),o=u(t);return!n||!o||G.test(n)||o!=="/"&&(n===o||n.startsWith(`${o}/`))?n:o==="/"?n.startsWith("/")?n:`/${n}`:n.startsWith("/")?`${o}${n}`:`${o}/${n}`}function E(e,t){if(!e)return;let n=u(e.basename)??u(t),o={...e,...n?{basename:n}:{}};return o.favicon&&(o.favicon=x(o.favicon,n)),o.links&&(o.links=o.links.map(r=>({...r,href:x(r.href,n)}))),o}var s=require("react/jsx-runtime"),Y={push:()=>{},replace:()=>{},refresh:()=>{}},p=typeof i.default.createContext=="function"?i.default.createContext(null):null,O="__WEBFRAMEZ_ROUTER__",Z="[data-webframez-head='true']";function q(){return typeof window>"u"?null:window[O]??null}function j(e){typeof window>"u"||(window[O]=e)}function S(){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("="),d=r>=0?o.slice(0,r).trim():o,c=r>=0?o.slice(r+1):"";d&&(e[d]=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 X(){return i.default.useMemo(()=>({all:()=>S(),get:e=>S()[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 K(){let e=p?i.default.useContext(p):null;if(!e){let t=q();if(t)return t;if(typeof window>"u")return Y;throw new Error("useRouter must be used inside mountWebframezClient()")}return e}function V({active:e}){return(0,s.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 k(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 I(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 P(e){if(typeof document>"u")return;let t=E(e)??e,n=u(t.basename);window.__RSC_BASENAME=n??"",document.title=t.title||"Webframez React";for(let o of document.head.querySelectorAll(Z))o.remove();t.description&&k({name:"description",content:t.description}),t.favicon&&I({rel:"icon",href:t.favicon});for(let o of t.meta??[])k(o);for(let o of t.links??[])I(o)}function J(e){let t=new TextEncoder;return new ReadableStream({start(n){n.enqueue(t.encode(e)),n.close()}})}function Q(){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)(J(e)))}function ee(e){return Q()??(0,l.createFromFetch)(fetch(`${e}?path=${encodeURIComponent(window.location.pathname)}&search=${encodeURIComponent(window.location.search)}`,{headers:{Accept:"text/x-component"}}))}function te(e,t){return function(){let o=i.default.use(e),[r,d]=(0,i.useState)(o.model),[c,w]=(0,i.useState)(o.head),[T,h]=(0,i.useState)(!1),[$,H]=(0,i.useState)(!1);async function f(a,_="push"){h(!0);try{let g=await(0,l.createFromFetch)(fetch(`${t}?path=${encodeURIComponent(a.pathname)}&search=${encodeURIComponent(a.search)}`,{headers:{Accept:"text/x-component"}}));P(g.head),w(g.head),d(g.model);let y=`${a.pathname}${a.search}`;_==="replace"?history.replaceState(null,"",y):_==="push"&&history.pushState(null,"",y)}catch(A){console.error("[webframez-react] Failed to render route",A),d((0,s.jsx)("p",{children:"Failed to load route."}))}finally{h(!1)}}(0,i.useEffect)(()=>{P(c)},[c]),(0,i.useEffect)(()=>{H(!0);let a=()=>{f(new URL(window.location.href),"none")};return window.addEventListener("popstate",a),()=>{window.removeEventListener("popstate",a)}},[]);let R=i.default.useMemo(()=>({push:a=>{f(new URL(a,window.location.origin),"push")},replace:a=>{f(new URL(a,window.location.origin),"replace")},refresh:()=>{f(new URL(window.location.href),"none")}}),[]);j(R);let C=(0,s.jsxs)(s.Fragment,{children:[$?(0,s.jsx)(V,{active:T}):null,r??(0,s.jsx)("p",{style:{padding:24},children:"Loading..."})]});return p?(0,s.jsx)(p.Provider,{value:R,children:C}):C}}function ne(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",d=ee(r),c=te(d,r);return(0,L.hydrateRoot)(n,(0,s.jsx)(c,{}))}
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,{}))}
package/dist/client.js CHANGED
@@ -1 +1 @@
1
- import c,{useEffect as x,useState as f}from"react";import{hydrateRoot as N}from"react-dom/client";import{createFromFetch as P,createFromReadableStream as U}from"react-server-dom-webpack/client";var H=/^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;function u(t){let o=t?.trim();if(o)return o==="/"?"/":o.replace(/\/+$/,"")}function y(t,o){let n=t.trim(),e=u(o);return!n||!e||H.test(n)||e!=="/"&&(n===e||n.startsWith(`${e}/`))?n:e==="/"?n.startsWith("/")?n:`/${n}`:n.startsWith("/")?`${e}${n}`:`${e}/${n}`}function v(t,o){if(!t)return;let n=u(t.basename)??u(o),e={...t,...n?{basename:n}:{}};return e.favicon&&(e.favicon=y(e.favicon,n)),e.links&&(e.links=e.links.map(r=>({...r,href:y(r.href,n)}))),e}import{Fragment as q,jsx as d,jsxs as j}from"react/jsx-runtime";var z={push:()=>{},replace:()=>{},refresh:()=>{}},m=typeof c.createContext=="function"?c.createContext(null):null,L="__WEBFRAMEZ_ROUTER__",B="[data-webframez-head='true']";function M(){return typeof window>"u"?null:window[L]??null}function W(t){typeof window>"u"||(window[L]=t)}function E(){let t={},o=typeof document>"u"?"":document.cookie;if(!o||o.trim()==="")return t;for(let n of o.split(";")){let e=n.trim();if(!e)continue;let r=e.indexOf("="),a=r>=0?e.slice(0,r).trim():e,s=r>=0?e.slice(r+1):"";a&&(t[a]=decodeURIComponent(s))}return t}function S(t,o,n={}){let e=[`${t}=${encodeURIComponent(o)}`];return n.path&&e.push(`Path=${n.path}`),n.domain&&e.push(`Domain=${n.domain}`),typeof n.maxAge=="number"&&e.push(`Max-Age=${Math.floor(n.maxAge)}`),n.expires&&e.push(`Expires=${n.expires.toUTCString()}`),n.sameSite&&e.push(`SameSite=${n.sameSite}`),n.secure&&e.push("Secure"),e.join("; ")}function ee(){return c.useMemo(()=>({all:()=>E(),get:t=>E()[t],set:(t,o,n)=>{typeof document>"u"||(document.cookie=S(t,o,n))},remove:(t,o)=>{typeof document>"u"||(document.cookie=S(t,"",{...o??{},maxAge:0}))}}),[])}function te(){let t=m?c.useContext(m):null;if(!t){let o=M();if(o)return o;if(typeof window>"u")return z;throw new Error("useRouter must be used inside mountWebframezClient()")}return t}function D({active:t}){return d("div",{style:{position:"fixed",top:0,left:0,width:"100%",height:3,zIndex:9999,transformOrigin:"left",transform:t?"scaleX(1)":"scaleX(0)",transition:"transform 180ms ease",background:"linear-gradient(90deg, #0ea5e9, #22c55e)"}})}function b(t){let o=document.createElement("meta");o.setAttribute("data-webframez-head","true");let n=Object.entries(t).filter(([,e])=>!!e);for(let[e,r]of n)o.setAttribute(e,String(r));document.head.appendChild(o)}function k(t){let o=document.createElement("link");o.setAttribute("data-webframez-head","true");let n=Object.entries(t).filter(([,e])=>!!e);for(let[e,r]of n)o.setAttribute(e,String(r));document.head.appendChild(o)}function I(t){if(typeof document>"u")return;let o=v(t)??t,n=u(o.basename);window.__RSC_BASENAME=n??"",document.title=o.title||"Webframez React";for(let e of document.head.querySelectorAll(B))e.remove();o.description&&b({name:"description",content:o.description}),o.favicon&&k({rel:"icon",href:o.favicon});for(let e of o.meta??[])b(e);for(let e of o.links??[])k(e)}function F(t){let o=new TextEncoder;return new ReadableStream({start(n){n.enqueue(o.encode(t)),n.close()}})}function G(){if(typeof window>"u")return null;let t=window.__RSC_INITIAL_PAYLOAD;return typeof t!="string"||t===""?null:(delete window.__RSC_INITIAL_PAYLOAD,U(F(t)))}function Y(t){return G()??P(fetch(`${t}?path=${encodeURIComponent(window.location.pathname)}&search=${encodeURIComponent(window.location.search)}`,{headers:{Accept:"text/x-component"}}))}function Z(t,o){return function(){let e=c.use(t),[r,a]=f(e.model),[s,g]=f(e.head),[O,w]=f(!1),[T,$]=f(!1);async function l(i,C="push"){w(!0);try{let p=await P(fetch(`${o}?path=${encodeURIComponent(i.pathname)}&search=${encodeURIComponent(i.search)}`,{headers:{Accept:"text/x-component"}}));I(p.head),g(p.head),a(p.model);let A=`${i.pathname}${i.search}`;C==="replace"?history.replaceState(null,"",A):C==="push"&&history.pushState(null,"",A)}catch(_){console.error("[webframez-react] Failed to render route",_),a(d("p",{children:"Failed to load route."}))}finally{w(!1)}}x(()=>{I(s)},[s]),x(()=>{$(!0);let i=()=>{l(new URL(window.location.href),"none")};return window.addEventListener("popstate",i),()=>{window.removeEventListener("popstate",i)}},[]);let h=c.useMemo(()=>({push:i=>{l(new URL(i,window.location.origin),"push")},replace:i=>{l(new URL(i,window.location.origin),"replace")},refresh:()=>{l(new URL(window.location.href),"none")}}),[]);W(h);let R=j(q,{children:[T?d(D,{active:O}):null,r??d("p",{style:{padding:24},children:"Loading..."})]});return m?d(m.Provider,{value:h,children:R}):R}}function ne(t={}){let o=t.rootId??"root",n=document.getElementById(o);if(!n)throw new Error(`Missing #${o} element`);let e=typeof window<"u"&&window.__RSC_ENDPOINT,r=t.rscEndpoint??e??"/rsc",a=Y(r),s=Z(a,r);return N(n,d(s,{}))}export{ne as mountWebframezClient,ee as useCookie,te as useRouter};
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};
package/dist/http.cjs CHANGED
@@ -55,6 +55,7 @@ function createHTMLShell(options = {}) {
55
55
  rootHtml = "",
56
56
  initialFlightData = "",
57
57
  basename = "",
58
+ routeBasePath = "",
58
59
  liveReloadPath,
59
60
  liveReloadServerId
60
61
  } = options;
@@ -103,6 +104,7 @@ function createHTMLShell(options = {}) {
103
104
  <div id="root">${rootHtml}</div>
104
105
  <script>window.__RSC_ENDPOINT = "${rscEndpoint}";</script>
105
106
  <script>window.__RSC_BASENAME = "${basename}";</script>
107
+ <script>window.__RSC_ROUTE_BASE_PATH = "${routeBasePath}";</script>
106
108
  <script>window.__RSC_INITIAL_PAYLOAD = ${escapedInitialFlightData};</script>
107
109
  <script type="module" src="${clientScriptUrl}"></script>
108
110
  ${liveReloadScript}
@@ -153,12 +155,12 @@ var import_node_path2 = __toESM(require("node:path"), 1);
153
155
  // src/head.ts
154
156
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
155
157
  function normalizeHeadBasename(value) {
156
- const trimmed = value?.trim();
157
- if (!trimmed) {
158
+ if (typeof value !== "string") {
158
159
  return void 0;
159
160
  }
160
- if (trimmed === "/") {
161
- return "/";
161
+ const trimmed = value.trim();
162
+ if (!trimmed || trimmed === "/") {
163
+ return "";
162
164
  }
163
165
  return trimmed.replace(/\/+$/, "");
164
166
  }
@@ -171,6 +173,9 @@ function resolveHeadAssetUrl(assetUrl, basename) {
171
173
  if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
172
174
  return normalizedAssetUrl;
173
175
  }
176
+ if (normalizedAssetUrl.startsWith("/")) {
177
+ return normalizedAssetUrl;
178
+ }
174
179
  if (normalizedBasename !== "/" && (normalizedAssetUrl === normalizedBasename || normalizedAssetUrl.startsWith(`${normalizedBasename}/`))) {
175
180
  return normalizedAssetUrl;
176
181
  }
@@ -187,9 +192,15 @@ function normalizeHeadConfig(head, inheritedBasename) {
187
192
  return void 0;
188
193
  }
189
194
  const effectiveBasename = normalizeHeadBasename(head.basename) ?? normalizeHeadBasename(inheritedBasename);
195
+ const normalizedRouteBasePath = normalizeHeadBasename(head.routeBasePath);
196
+ const normalizedTransportBasePath = normalizeHeadBasename(
197
+ head.transportBasePath
198
+ );
190
199
  const normalizedHead = {
191
200
  ...head,
192
- ...effectiveBasename ? { basename: effectiveBasename } : {}
201
+ ...effectiveBasename !== void 0 ? { basename: effectiveBasename } : {},
202
+ ...normalizedRouteBasePath !== void 0 ? { routeBasePath: normalizedRouteBasePath } : {},
203
+ ...normalizedTransportBasePath !== void 0 ? { transportBasePath: normalizedTransportBasePath } : {}
193
204
  };
194
205
  if (normalizedHead.favicon) {
195
206
  normalizedHead.favicon = resolveHeadAssetUrl(
@@ -426,15 +437,22 @@ function mergeHead(...configs) {
426
437
  if (!config) {
427
438
  continue;
428
439
  }
440
+ const hasOwn = (key) => Object.prototype.hasOwnProperty.call(config, key);
429
441
  if (config.title) {
430
442
  merged.title = config.title;
431
443
  }
432
444
  if (config.description) {
433
445
  merged.description = config.description;
434
446
  }
435
- if (config.basename) {
447
+ if (hasOwn("basename")) {
436
448
  merged.basename = config.basename;
437
449
  }
450
+ if (hasOwn("routeBasePath")) {
451
+ merged.routeBasePath = config.routeBasePath;
452
+ }
453
+ if (hasOwn("transportBasePath")) {
454
+ merged.transportBasePath = config.transportBasePath;
455
+ }
438
456
  if (config.favicon) {
439
457
  merged.favicon = config.favicon;
440
458
  }
@@ -874,7 +892,7 @@ async function decodeFlightPayloadFromString(flightData, moduleMap) {
874
892
 
875
893
  if (typeof reactServerDomClientNode.createFromNodeStream === "function") {
876
894
  return await reactServerDomClientNode.createFromNodeStream(
877
- Readable.from([flightData]),
895
+ Readable.from([Buffer.from(flightData)]),
878
896
  serverConsumerManifest
879
897
  );
880
898
  }
@@ -999,6 +1017,23 @@ function stripBasePath(pathname, basePath) {
999
1017
  }
1000
1018
  return pathname;
1001
1019
  }
1020
+ function normalizeRuntimeBasePath(value) {
1021
+ if (typeof value !== "string") {
1022
+ return void 0;
1023
+ }
1024
+ const trimmed = value.trim();
1025
+ if (!trimmed || trimmed === "/") {
1026
+ return "";
1027
+ }
1028
+ return trimmed.replace(/\/+$/, "");
1029
+ }
1030
+ function joinRuntimeBasePath(basePath, pathname) {
1031
+ const normalizedPath = !pathname || pathname === "/" ? "/" : pathname.startsWith("/") ? pathname : `/${pathname}`;
1032
+ if (!basePath) {
1033
+ return normalizedPath;
1034
+ }
1035
+ return normalizedPath === "/" ? basePath : `${basePath}${normalizedPath}`;
1036
+ }
1002
1037
  function sanitizeInitialHtmlWorkerNodeOptions(rawNodeOptions) {
1003
1038
  if (!rawNodeOptions || rawNodeOptions.trim() === "") {
1004
1039
  return "";
@@ -1399,6 +1434,14 @@ function createNodeRequestHandler(options) {
1399
1434
  const initialFlightData = await renderRSCToString(initialPayload, {
1400
1435
  moduleMap
1401
1436
  });
1437
+ const transportBasePath = normalizeRuntimeBasePath(resolved.head.transportBasePath) ?? normalizeRuntimeBasePath(basePath) ?? "";
1438
+ const shellClientScriptUrl = joinRuntimeBasePath(
1439
+ transportBasePath,
1440
+ "/assets/client.js"
1441
+ );
1442
+ const shellRscEndpoint = joinRuntimeBasePath(transportBasePath, "/rsc");
1443
+ const shellBasename = normalizeRuntimeBasePath(resolved.head.basename) ?? normalizeRuntimeBasePath(basePath) ?? "";
1444
+ const shellRouteBasePath = normalizeRuntimeBasePath(resolved.head.routeBasePath) ?? "";
1402
1445
  let rootHtml = "";
1403
1446
  try {
1404
1447
  rootHtml = await initialHtmlWorker.renderFromFlightData({
@@ -1429,11 +1472,12 @@ function createNodeRequestHandler(options) {
1429
1472
  createHTMLShell({
1430
1473
  title: "500 - Initial HTML render failed",
1431
1474
  headTags: "",
1432
- clientScriptUrl,
1433
- rscEndpoint: rscPath,
1475
+ clientScriptUrl: shellClientScriptUrl,
1476
+ rscEndpoint: shellRscEndpoint,
1434
1477
  rootHtml: createInitialHtmlErrorMarkup("Initial HTML render failed."),
1435
1478
  initialFlightData,
1436
- basename: resolved?.head?.basename ?? basePath,
1479
+ basename: shellBasename,
1480
+ routeBasePath: shellRouteBasePath,
1437
1481
  liveReloadPath: liveReloadPath || void 0,
1438
1482
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1439
1483
  })
@@ -1448,11 +1492,12 @@ function createNodeRequestHandler(options) {
1448
1492
  createHTMLShell({
1449
1493
  title: resolved.head.title || "Webframez React",
1450
1494
  headTags: renderHeadToString(resolved.head),
1451
- clientScriptUrl,
1452
- rscEndpoint: rscPath,
1495
+ clientScriptUrl: shellClientScriptUrl,
1496
+ rscEndpoint: shellRscEndpoint,
1453
1497
  rootHtml,
1454
1498
  initialFlightData,
1455
- basename: resolved.head.basename ?? basePath,
1499
+ basename: shellBasename,
1500
+ routeBasePath: shellRouteBasePath,
1456
1501
  liveReloadPath: liveReloadPath || void 0,
1457
1502
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1458
1503
  })
package/dist/http.js CHANGED
@@ -30,6 +30,7 @@ function createHTMLShell(options = {}) {
30
30
  rootHtml = "",
31
31
  initialFlightData = "",
32
32
  basename = "",
33
+ routeBasePath = "",
33
34
  liveReloadPath,
34
35
  liveReloadServerId
35
36
  } = options;
@@ -78,6 +79,7 @@ function createHTMLShell(options = {}) {
78
79
  <div id="root">${rootHtml}</div>
79
80
  <script>window.__RSC_ENDPOINT = "${rscEndpoint}";</script>
80
81
  <script>window.__RSC_BASENAME = "${basename}";</script>
82
+ <script>window.__RSC_ROUTE_BASE_PATH = "${routeBasePath}";</script>
81
83
  <script>window.__RSC_INITIAL_PAYLOAD = ${escapedInitialFlightData};</script>
82
84
  <script type="module" src="${clientScriptUrl}"></script>
83
85
  ${liveReloadScript}
@@ -128,12 +130,12 @@ import path2 from "node:path";
128
130
  // src/head.ts
129
131
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
130
132
  function normalizeHeadBasename(value) {
131
- const trimmed = value?.trim();
132
- if (!trimmed) {
133
+ if (typeof value !== "string") {
133
134
  return void 0;
134
135
  }
135
- if (trimmed === "/") {
136
- return "/";
136
+ const trimmed = value.trim();
137
+ if (!trimmed || trimmed === "/") {
138
+ return "";
137
139
  }
138
140
  return trimmed.replace(/\/+$/, "");
139
141
  }
@@ -146,6 +148,9 @@ function resolveHeadAssetUrl(assetUrl, basename) {
146
148
  if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
147
149
  return normalizedAssetUrl;
148
150
  }
151
+ if (normalizedAssetUrl.startsWith("/")) {
152
+ return normalizedAssetUrl;
153
+ }
149
154
  if (normalizedBasename !== "/" && (normalizedAssetUrl === normalizedBasename || normalizedAssetUrl.startsWith(`${normalizedBasename}/`))) {
150
155
  return normalizedAssetUrl;
151
156
  }
@@ -162,9 +167,15 @@ function normalizeHeadConfig(head, inheritedBasename) {
162
167
  return void 0;
163
168
  }
164
169
  const effectiveBasename = normalizeHeadBasename(head.basename) ?? normalizeHeadBasename(inheritedBasename);
170
+ const normalizedRouteBasePath = normalizeHeadBasename(head.routeBasePath);
171
+ const normalizedTransportBasePath = normalizeHeadBasename(
172
+ head.transportBasePath
173
+ );
165
174
  const normalizedHead = {
166
175
  ...head,
167
- ...effectiveBasename ? { basename: effectiveBasename } : {}
176
+ ...effectiveBasename !== void 0 ? { basename: effectiveBasename } : {},
177
+ ...normalizedRouteBasePath !== void 0 ? { routeBasePath: normalizedRouteBasePath } : {},
178
+ ...normalizedTransportBasePath !== void 0 ? { transportBasePath: normalizedTransportBasePath } : {}
168
179
  };
169
180
  if (normalizedHead.favicon) {
170
181
  normalizedHead.favicon = resolveHeadAssetUrl(
@@ -401,15 +412,22 @@ function mergeHead(...configs) {
401
412
  if (!config) {
402
413
  continue;
403
414
  }
415
+ const hasOwn = (key) => Object.prototype.hasOwnProperty.call(config, key);
404
416
  if (config.title) {
405
417
  merged.title = config.title;
406
418
  }
407
419
  if (config.description) {
408
420
  merged.description = config.description;
409
421
  }
410
- if (config.basename) {
422
+ if (hasOwn("basename")) {
411
423
  merged.basename = config.basename;
412
424
  }
425
+ if (hasOwn("routeBasePath")) {
426
+ merged.routeBasePath = config.routeBasePath;
427
+ }
428
+ if (hasOwn("transportBasePath")) {
429
+ merged.transportBasePath = config.transportBasePath;
430
+ }
413
431
  if (config.favicon) {
414
432
  merged.favicon = config.favicon;
415
433
  }
@@ -849,7 +867,7 @@ async function decodeFlightPayloadFromString(flightData, moduleMap) {
849
867
 
850
868
  if (typeof reactServerDomClientNode.createFromNodeStream === "function") {
851
869
  return await reactServerDomClientNode.createFromNodeStream(
852
- Readable.from([flightData]),
870
+ Readable.from([Buffer.from(flightData)]),
853
871
  serverConsumerManifest
854
872
  );
855
873
  }
@@ -974,6 +992,23 @@ function stripBasePath(pathname, basePath) {
974
992
  }
975
993
  return pathname;
976
994
  }
995
+ function normalizeRuntimeBasePath(value) {
996
+ if (typeof value !== "string") {
997
+ return void 0;
998
+ }
999
+ const trimmed = value.trim();
1000
+ if (!trimmed || trimmed === "/") {
1001
+ return "";
1002
+ }
1003
+ return trimmed.replace(/\/+$/, "");
1004
+ }
1005
+ function joinRuntimeBasePath(basePath, pathname) {
1006
+ const normalizedPath = !pathname || pathname === "/" ? "/" : pathname.startsWith("/") ? pathname : `/${pathname}`;
1007
+ if (!basePath) {
1008
+ return normalizedPath;
1009
+ }
1010
+ return normalizedPath === "/" ? basePath : `${basePath}${normalizedPath}`;
1011
+ }
977
1012
  function sanitizeInitialHtmlWorkerNodeOptions(rawNodeOptions) {
978
1013
  if (!rawNodeOptions || rawNodeOptions.trim() === "") {
979
1014
  return "";
@@ -1374,6 +1409,14 @@ function createNodeRequestHandler(options) {
1374
1409
  const initialFlightData = await renderRSCToString(initialPayload, {
1375
1410
  moduleMap
1376
1411
  });
1412
+ const transportBasePath = normalizeRuntimeBasePath(resolved.head.transportBasePath) ?? normalizeRuntimeBasePath(basePath) ?? "";
1413
+ const shellClientScriptUrl = joinRuntimeBasePath(
1414
+ transportBasePath,
1415
+ "/assets/client.js"
1416
+ );
1417
+ const shellRscEndpoint = joinRuntimeBasePath(transportBasePath, "/rsc");
1418
+ const shellBasename = normalizeRuntimeBasePath(resolved.head.basename) ?? normalizeRuntimeBasePath(basePath) ?? "";
1419
+ const shellRouteBasePath = normalizeRuntimeBasePath(resolved.head.routeBasePath) ?? "";
1377
1420
  let rootHtml = "";
1378
1421
  try {
1379
1422
  rootHtml = await initialHtmlWorker.renderFromFlightData({
@@ -1404,11 +1447,12 @@ function createNodeRequestHandler(options) {
1404
1447
  createHTMLShell({
1405
1448
  title: "500 - Initial HTML render failed",
1406
1449
  headTags: "",
1407
- clientScriptUrl,
1408
- rscEndpoint: rscPath,
1450
+ clientScriptUrl: shellClientScriptUrl,
1451
+ rscEndpoint: shellRscEndpoint,
1409
1452
  rootHtml: createInitialHtmlErrorMarkup("Initial HTML render failed."),
1410
1453
  initialFlightData,
1411
- basename: resolved?.head?.basename ?? basePath,
1454
+ basename: shellBasename,
1455
+ routeBasePath: shellRouteBasePath,
1412
1456
  liveReloadPath: liveReloadPath || void 0,
1413
1457
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1414
1458
  })
@@ -1423,11 +1467,12 @@ function createNodeRequestHandler(options) {
1423
1467
  createHTMLShell({
1424
1468
  title: resolved.head.title || "Webframez React",
1425
1469
  headTags: renderHeadToString(resolved.head),
1426
- clientScriptUrl,
1427
- rscEndpoint: rscPath,
1470
+ clientScriptUrl: shellClientScriptUrl,
1471
+ rscEndpoint: shellRscEndpoint,
1428
1472
  rootHtml,
1429
1473
  initialFlightData,
1430
- basename: resolved.head.basename ?? basePath,
1474
+ basename: shellBasename,
1475
+ routeBasePath: shellRouteBasePath,
1431
1476
  liveReloadPath: liveReloadPath || void 0,
1432
1477
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1433
1478
  })
package/dist/index.cjs CHANGED
@@ -60,6 +60,7 @@ function createHTMLShell(options = {}) {
60
60
  rootHtml = "",
61
61
  initialFlightData = "",
62
62
  basename = "",
63
+ routeBasePath = "",
63
64
  liveReloadPath,
64
65
  liveReloadServerId
65
66
  } = options;
@@ -108,6 +109,7 @@ function createHTMLShell(options = {}) {
108
109
  <div id="root">${rootHtml}</div>
109
110
  <script>window.__RSC_ENDPOINT = "${rscEndpoint}";</script>
110
111
  <script>window.__RSC_BASENAME = "${basename}";</script>
112
+ <script>window.__RSC_ROUTE_BASE_PATH = "${routeBasePath}";</script>
111
113
  <script>window.__RSC_INITIAL_PAYLOAD = ${escapedInitialFlightData};</script>
112
114
  <script type="module" src="${clientScriptUrl}"></script>
113
115
  ${liveReloadScript}
@@ -186,12 +188,12 @@ var import_node_path2 = __toESM(require("node:path"), 1);
186
188
  // src/head.ts
187
189
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
188
190
  function normalizeHeadBasename(value) {
189
- const trimmed = value?.trim();
190
- if (!trimmed) {
191
+ if (typeof value !== "string") {
191
192
  return void 0;
192
193
  }
193
- if (trimmed === "/") {
194
- return "/";
194
+ const trimmed = value.trim();
195
+ if (!trimmed || trimmed === "/") {
196
+ return "";
195
197
  }
196
198
  return trimmed.replace(/\/+$/, "");
197
199
  }
@@ -204,6 +206,9 @@ function resolveHeadAssetUrl(assetUrl, basename) {
204
206
  if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
205
207
  return normalizedAssetUrl;
206
208
  }
209
+ if (normalizedAssetUrl.startsWith("/")) {
210
+ return normalizedAssetUrl;
211
+ }
207
212
  if (normalizedBasename !== "/" && (normalizedAssetUrl === normalizedBasename || normalizedAssetUrl.startsWith(`${normalizedBasename}/`))) {
208
213
  return normalizedAssetUrl;
209
214
  }
@@ -220,9 +225,15 @@ function normalizeHeadConfig(head, inheritedBasename) {
220
225
  return void 0;
221
226
  }
222
227
  const effectiveBasename = normalizeHeadBasename(head.basename) ?? normalizeHeadBasename(inheritedBasename);
228
+ const normalizedRouteBasePath = normalizeHeadBasename(head.routeBasePath);
229
+ const normalizedTransportBasePath = normalizeHeadBasename(
230
+ head.transportBasePath
231
+ );
223
232
  const normalizedHead = {
224
233
  ...head,
225
- ...effectiveBasename ? { basename: effectiveBasename } : {}
234
+ ...effectiveBasename !== void 0 ? { basename: effectiveBasename } : {},
235
+ ...normalizedRouteBasePath !== void 0 ? { routeBasePath: normalizedRouteBasePath } : {},
236
+ ...normalizedTransportBasePath !== void 0 ? { transportBasePath: normalizedTransportBasePath } : {}
226
237
  };
227
238
  if (normalizedHead.favicon) {
228
239
  normalizedHead.favicon = resolveHeadAssetUrl(
@@ -459,15 +470,22 @@ function mergeHead(...configs) {
459
470
  if (!config) {
460
471
  continue;
461
472
  }
473
+ const hasOwn = (key) => Object.prototype.hasOwnProperty.call(config, key);
462
474
  if (config.title) {
463
475
  merged.title = config.title;
464
476
  }
465
477
  if (config.description) {
466
478
  merged.description = config.description;
467
479
  }
468
- if (config.basename) {
480
+ if (hasOwn("basename")) {
469
481
  merged.basename = config.basename;
470
482
  }
483
+ if (hasOwn("routeBasePath")) {
484
+ merged.routeBasePath = config.routeBasePath;
485
+ }
486
+ if (hasOwn("transportBasePath")) {
487
+ merged.transportBasePath = config.transportBasePath;
488
+ }
471
489
  if (config.favicon) {
472
490
  merged.favicon = config.favicon;
473
491
  }
@@ -911,7 +929,7 @@ async function decodeFlightPayloadFromString(flightData, moduleMap) {
911
929
 
912
930
  if (typeof reactServerDomClientNode.createFromNodeStream === "function") {
913
931
  return await reactServerDomClientNode.createFromNodeStream(
914
- Readable.from([flightData]),
932
+ Readable.from([Buffer.from(flightData)]),
915
933
  serverConsumerManifest
916
934
  );
917
935
  }
@@ -1036,6 +1054,23 @@ function stripBasePath(pathname, basePath) {
1036
1054
  }
1037
1055
  return pathname;
1038
1056
  }
1057
+ function normalizeRuntimeBasePath(value) {
1058
+ if (typeof value !== "string") {
1059
+ return void 0;
1060
+ }
1061
+ const trimmed = value.trim();
1062
+ if (!trimmed || trimmed === "/") {
1063
+ return "";
1064
+ }
1065
+ return trimmed.replace(/\/+$/, "");
1066
+ }
1067
+ function joinRuntimeBasePath(basePath, pathname) {
1068
+ const normalizedPath = !pathname || pathname === "/" ? "/" : pathname.startsWith("/") ? pathname : `/${pathname}`;
1069
+ if (!basePath) {
1070
+ return normalizedPath;
1071
+ }
1072
+ return normalizedPath === "/" ? basePath : `${basePath}${normalizedPath}`;
1073
+ }
1039
1074
  function sanitizeInitialHtmlWorkerNodeOptions(rawNodeOptions) {
1040
1075
  if (!rawNodeOptions || rawNodeOptions.trim() === "") {
1041
1076
  return "";
@@ -1436,6 +1471,14 @@ function createNodeRequestHandler(options) {
1436
1471
  const initialFlightData = await renderRSCToString(initialPayload, {
1437
1472
  moduleMap
1438
1473
  });
1474
+ const transportBasePath = normalizeRuntimeBasePath(resolved.head.transportBasePath) ?? normalizeRuntimeBasePath(basePath) ?? "";
1475
+ const shellClientScriptUrl = joinRuntimeBasePath(
1476
+ transportBasePath,
1477
+ "/assets/client.js"
1478
+ );
1479
+ const shellRscEndpoint = joinRuntimeBasePath(transportBasePath, "/rsc");
1480
+ const shellBasename = normalizeRuntimeBasePath(resolved.head.basename) ?? normalizeRuntimeBasePath(basePath) ?? "";
1481
+ const shellRouteBasePath = normalizeRuntimeBasePath(resolved.head.routeBasePath) ?? "";
1439
1482
  let rootHtml = "";
1440
1483
  try {
1441
1484
  rootHtml = await initialHtmlWorker.renderFromFlightData({
@@ -1466,11 +1509,12 @@ function createNodeRequestHandler(options) {
1466
1509
  createHTMLShell({
1467
1510
  title: "500 - Initial HTML render failed",
1468
1511
  headTags: "",
1469
- clientScriptUrl,
1470
- rscEndpoint: rscPath,
1512
+ clientScriptUrl: shellClientScriptUrl,
1513
+ rscEndpoint: shellRscEndpoint,
1471
1514
  rootHtml: createInitialHtmlErrorMarkup("Initial HTML render failed."),
1472
1515
  initialFlightData,
1473
- basename: resolved?.head?.basename ?? basePath,
1516
+ basename: shellBasename,
1517
+ routeBasePath: shellRouteBasePath,
1474
1518
  liveReloadPath: liveReloadPath || void 0,
1475
1519
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1476
1520
  })
@@ -1485,11 +1529,12 @@ function createNodeRequestHandler(options) {
1485
1529
  createHTMLShell({
1486
1530
  title: resolved.head.title || "Webframez React",
1487
1531
  headTags: renderHeadToString(resolved.head),
1488
- clientScriptUrl,
1489
- rscEndpoint: rscPath,
1532
+ clientScriptUrl: shellClientScriptUrl,
1533
+ rscEndpoint: shellRscEndpoint,
1490
1534
  rootHtml,
1491
1535
  initialFlightData,
1492
- basename: resolved.head.basename ?? basePath,
1536
+ basename: shellBasename,
1537
+ routeBasePath: shellRouteBasePath,
1493
1538
  liveReloadPath: liveReloadPath || void 0,
1494
1539
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1495
1540
  })
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ function createHTMLShell(options = {}) {
24
24
  rootHtml = "",
25
25
  initialFlightData = "",
26
26
  basename = "",
27
+ routeBasePath = "",
27
28
  liveReloadPath,
28
29
  liveReloadServerId
29
30
  } = options;
@@ -72,6 +73,7 @@ function createHTMLShell(options = {}) {
72
73
  <div id="root">${rootHtml}</div>
73
74
  <script>window.__RSC_ENDPOINT = "${rscEndpoint}";</script>
74
75
  <script>window.__RSC_BASENAME = "${basename}";</script>
76
+ <script>window.__RSC_ROUTE_BASE_PATH = "${routeBasePath}";</script>
75
77
  <script>window.__RSC_INITIAL_PAYLOAD = ${escapedInitialFlightData};</script>
76
78
  <script type="module" src="${clientScriptUrl}"></script>
77
79
  ${liveReloadScript}
@@ -150,12 +152,12 @@ import path2 from "node:path";
150
152
  // src/head.ts
151
153
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
152
154
  function normalizeHeadBasename(value) {
153
- const trimmed = value?.trim();
154
- if (!trimmed) {
155
+ if (typeof value !== "string") {
155
156
  return void 0;
156
157
  }
157
- if (trimmed === "/") {
158
- return "/";
158
+ const trimmed = value.trim();
159
+ if (!trimmed || trimmed === "/") {
160
+ return "";
159
161
  }
160
162
  return trimmed.replace(/\/+$/, "");
161
163
  }
@@ -168,6 +170,9 @@ function resolveHeadAssetUrl(assetUrl, basename) {
168
170
  if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
169
171
  return normalizedAssetUrl;
170
172
  }
173
+ if (normalizedAssetUrl.startsWith("/")) {
174
+ return normalizedAssetUrl;
175
+ }
171
176
  if (normalizedBasename !== "/" && (normalizedAssetUrl === normalizedBasename || normalizedAssetUrl.startsWith(`${normalizedBasename}/`))) {
172
177
  return normalizedAssetUrl;
173
178
  }
@@ -184,9 +189,15 @@ function normalizeHeadConfig(head, inheritedBasename) {
184
189
  return void 0;
185
190
  }
186
191
  const effectiveBasename = normalizeHeadBasename(head.basename) ?? normalizeHeadBasename(inheritedBasename);
192
+ const normalizedRouteBasePath = normalizeHeadBasename(head.routeBasePath);
193
+ const normalizedTransportBasePath = normalizeHeadBasename(
194
+ head.transportBasePath
195
+ );
187
196
  const normalizedHead = {
188
197
  ...head,
189
- ...effectiveBasename ? { basename: effectiveBasename } : {}
198
+ ...effectiveBasename !== void 0 ? { basename: effectiveBasename } : {},
199
+ ...normalizedRouteBasePath !== void 0 ? { routeBasePath: normalizedRouteBasePath } : {},
200
+ ...normalizedTransportBasePath !== void 0 ? { transportBasePath: normalizedTransportBasePath } : {}
190
201
  };
191
202
  if (normalizedHead.favicon) {
192
203
  normalizedHead.favicon = resolveHeadAssetUrl(
@@ -423,15 +434,22 @@ function mergeHead(...configs) {
423
434
  if (!config) {
424
435
  continue;
425
436
  }
437
+ const hasOwn = (key) => Object.prototype.hasOwnProperty.call(config, key);
426
438
  if (config.title) {
427
439
  merged.title = config.title;
428
440
  }
429
441
  if (config.description) {
430
442
  merged.description = config.description;
431
443
  }
432
- if (config.basename) {
444
+ if (hasOwn("basename")) {
433
445
  merged.basename = config.basename;
434
446
  }
447
+ if (hasOwn("routeBasePath")) {
448
+ merged.routeBasePath = config.routeBasePath;
449
+ }
450
+ if (hasOwn("transportBasePath")) {
451
+ merged.transportBasePath = config.transportBasePath;
452
+ }
435
453
  if (config.favicon) {
436
454
  merged.favicon = config.favicon;
437
455
  }
@@ -875,7 +893,7 @@ async function decodeFlightPayloadFromString(flightData, moduleMap) {
875
893
 
876
894
  if (typeof reactServerDomClientNode.createFromNodeStream === "function") {
877
895
  return await reactServerDomClientNode.createFromNodeStream(
878
- Readable.from([flightData]),
896
+ Readable.from([Buffer.from(flightData)]),
879
897
  serverConsumerManifest
880
898
  );
881
899
  }
@@ -1000,6 +1018,23 @@ function stripBasePath(pathname, basePath) {
1000
1018
  }
1001
1019
  return pathname;
1002
1020
  }
1021
+ function normalizeRuntimeBasePath(value) {
1022
+ if (typeof value !== "string") {
1023
+ return void 0;
1024
+ }
1025
+ const trimmed = value.trim();
1026
+ if (!trimmed || trimmed === "/") {
1027
+ return "";
1028
+ }
1029
+ return trimmed.replace(/\/+$/, "");
1030
+ }
1031
+ function joinRuntimeBasePath(basePath, pathname) {
1032
+ const normalizedPath = !pathname || pathname === "/" ? "/" : pathname.startsWith("/") ? pathname : `/${pathname}`;
1033
+ if (!basePath) {
1034
+ return normalizedPath;
1035
+ }
1036
+ return normalizedPath === "/" ? basePath : `${basePath}${normalizedPath}`;
1037
+ }
1003
1038
  function sanitizeInitialHtmlWorkerNodeOptions(rawNodeOptions) {
1004
1039
  if (!rawNodeOptions || rawNodeOptions.trim() === "") {
1005
1040
  return "";
@@ -1400,6 +1435,14 @@ function createNodeRequestHandler(options) {
1400
1435
  const initialFlightData = await renderRSCToString(initialPayload, {
1401
1436
  moduleMap
1402
1437
  });
1438
+ const transportBasePath = normalizeRuntimeBasePath(resolved.head.transportBasePath) ?? normalizeRuntimeBasePath(basePath) ?? "";
1439
+ const shellClientScriptUrl = joinRuntimeBasePath(
1440
+ transportBasePath,
1441
+ "/assets/client.js"
1442
+ );
1443
+ const shellRscEndpoint = joinRuntimeBasePath(transportBasePath, "/rsc");
1444
+ const shellBasename = normalizeRuntimeBasePath(resolved.head.basename) ?? normalizeRuntimeBasePath(basePath) ?? "";
1445
+ const shellRouteBasePath = normalizeRuntimeBasePath(resolved.head.routeBasePath) ?? "";
1403
1446
  let rootHtml = "";
1404
1447
  try {
1405
1448
  rootHtml = await initialHtmlWorker.renderFromFlightData({
@@ -1430,11 +1473,12 @@ function createNodeRequestHandler(options) {
1430
1473
  createHTMLShell({
1431
1474
  title: "500 - Initial HTML render failed",
1432
1475
  headTags: "",
1433
- clientScriptUrl,
1434
- rscEndpoint: rscPath,
1476
+ clientScriptUrl: shellClientScriptUrl,
1477
+ rscEndpoint: shellRscEndpoint,
1435
1478
  rootHtml: createInitialHtmlErrorMarkup("Initial HTML render failed."),
1436
1479
  initialFlightData,
1437
- basename: resolved?.head?.basename ?? basePath,
1480
+ basename: shellBasename,
1481
+ routeBasePath: shellRouteBasePath,
1438
1482
  liveReloadPath: liveReloadPath || void 0,
1439
1483
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1440
1484
  })
@@ -1449,11 +1493,12 @@ function createNodeRequestHandler(options) {
1449
1493
  createHTMLShell({
1450
1494
  title: resolved.head.title || "Webframez React",
1451
1495
  headTags: renderHeadToString(resolved.head),
1452
- clientScriptUrl,
1453
- rscEndpoint: rscPath,
1496
+ clientScriptUrl: shellClientScriptUrl,
1497
+ rscEndpoint: shellRscEndpoint,
1454
1498
  rootHtml,
1455
1499
  initialFlightData,
1456
- basename: resolved.head.basename ?? basePath,
1500
+ basename: shellBasename,
1501
+ routeBasePath: shellRouteBasePath,
1457
1502
  liveReloadPath: liveReloadPath || void 0,
1458
1503
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1459
1504
  })
package/dist/router.cjs CHANGED
@@ -44,12 +44,12 @@ var import_node_path = __toESM(require("node:path"), 1);
44
44
  // src/head.ts
45
45
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
46
46
  function normalizeHeadBasename(value) {
47
- const trimmed = value?.trim();
48
- if (!trimmed) {
47
+ if (typeof value !== "string") {
49
48
  return void 0;
50
49
  }
51
- if (trimmed === "/") {
52
- return "/";
50
+ const trimmed = value.trim();
51
+ if (!trimmed || trimmed === "/") {
52
+ return "";
53
53
  }
54
54
  return trimmed.replace(/\/+$/, "");
55
55
  }
@@ -62,6 +62,9 @@ function resolveHeadAssetUrl(assetUrl, basename) {
62
62
  if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
63
63
  return normalizedAssetUrl;
64
64
  }
65
+ if (normalizedAssetUrl.startsWith("/")) {
66
+ return normalizedAssetUrl;
67
+ }
65
68
  if (normalizedBasename !== "/" && (normalizedAssetUrl === normalizedBasename || normalizedAssetUrl.startsWith(`${normalizedBasename}/`))) {
66
69
  return normalizedAssetUrl;
67
70
  }
@@ -78,9 +81,15 @@ function normalizeHeadConfig(head, inheritedBasename) {
78
81
  return void 0;
79
82
  }
80
83
  const effectiveBasename = normalizeHeadBasename(head.basename) ?? normalizeHeadBasename(inheritedBasename);
84
+ const normalizedRouteBasePath = normalizeHeadBasename(head.routeBasePath);
85
+ const normalizedTransportBasePath = normalizeHeadBasename(
86
+ head.transportBasePath
87
+ );
81
88
  const normalizedHead = {
82
89
  ...head,
83
- ...effectiveBasename ? { basename: effectiveBasename } : {}
90
+ ...effectiveBasename !== void 0 ? { basename: effectiveBasename } : {},
91
+ ...normalizedRouteBasePath !== void 0 ? { routeBasePath: normalizedRouteBasePath } : {},
92
+ ...normalizedTransportBasePath !== void 0 ? { transportBasePath: normalizedTransportBasePath } : {}
84
93
  };
85
94
  if (normalizedHead.favicon) {
86
95
  normalizedHead.favicon = resolveHeadAssetUrl(
@@ -317,15 +326,22 @@ function mergeHead(...configs) {
317
326
  if (!config) {
318
327
  continue;
319
328
  }
329
+ const hasOwn = (key) => Object.prototype.hasOwnProperty.call(config, key);
320
330
  if (config.title) {
321
331
  merged.title = config.title;
322
332
  }
323
333
  if (config.description) {
324
334
  merged.description = config.description;
325
335
  }
326
- if (config.basename) {
336
+ if (hasOwn("basename")) {
327
337
  merged.basename = config.basename;
328
338
  }
339
+ if (hasOwn("routeBasePath")) {
340
+ merged.routeBasePath = config.routeBasePath;
341
+ }
342
+ if (hasOwn("transportBasePath")) {
343
+ merged.transportBasePath = config.transportBasePath;
344
+ }
329
345
  if (config.favicon) {
330
346
  merged.favicon = config.favicon;
331
347
  }
package/dist/router.js CHANGED
@@ -14,12 +14,12 @@ import path from "node:path";
14
14
  // src/head.ts
15
15
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
16
16
  function normalizeHeadBasename(value) {
17
- const trimmed = value?.trim();
18
- if (!trimmed) {
17
+ if (typeof value !== "string") {
19
18
  return void 0;
20
19
  }
21
- if (trimmed === "/") {
22
- return "/";
20
+ const trimmed = value.trim();
21
+ if (!trimmed || trimmed === "/") {
22
+ return "";
23
23
  }
24
24
  return trimmed.replace(/\/+$/, "");
25
25
  }
@@ -32,6 +32,9 @@ function resolveHeadAssetUrl(assetUrl, basename) {
32
32
  if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
33
33
  return normalizedAssetUrl;
34
34
  }
35
+ if (normalizedAssetUrl.startsWith("/")) {
36
+ return normalizedAssetUrl;
37
+ }
35
38
  if (normalizedBasename !== "/" && (normalizedAssetUrl === normalizedBasename || normalizedAssetUrl.startsWith(`${normalizedBasename}/`))) {
36
39
  return normalizedAssetUrl;
37
40
  }
@@ -48,9 +51,15 @@ function normalizeHeadConfig(head, inheritedBasename) {
48
51
  return void 0;
49
52
  }
50
53
  const effectiveBasename = normalizeHeadBasename(head.basename) ?? normalizeHeadBasename(inheritedBasename);
54
+ const normalizedRouteBasePath = normalizeHeadBasename(head.routeBasePath);
55
+ const normalizedTransportBasePath = normalizeHeadBasename(
56
+ head.transportBasePath
57
+ );
51
58
  const normalizedHead = {
52
59
  ...head,
53
- ...effectiveBasename ? { basename: effectiveBasename } : {}
60
+ ...effectiveBasename !== void 0 ? { basename: effectiveBasename } : {},
61
+ ...normalizedRouteBasePath !== void 0 ? { routeBasePath: normalizedRouteBasePath } : {},
62
+ ...normalizedTransportBasePath !== void 0 ? { transportBasePath: normalizedTransportBasePath } : {}
54
63
  };
55
64
  if (normalizedHead.favicon) {
56
65
  normalizedHead.favicon = resolveHeadAssetUrl(
@@ -287,15 +296,22 @@ function mergeHead(...configs) {
287
296
  if (!config) {
288
297
  continue;
289
298
  }
299
+ const hasOwn = (key) => Object.prototype.hasOwnProperty.call(config, key);
290
300
  if (config.title) {
291
301
  merged.title = config.title;
292
302
  }
293
303
  if (config.description) {
294
304
  merged.description = config.description;
295
305
  }
296
- if (config.basename) {
306
+ if (hasOwn("basename")) {
297
307
  merged.basename = config.basename;
298
308
  }
309
+ if (hasOwn("routeBasePath")) {
310
+ merged.routeBasePath = config.routeBasePath;
311
+ }
312
+ if (hasOwn("transportBasePath")) {
313
+ merged.transportBasePath = config.transportBasePath;
314
+ }
299
315
  if (config.favicon) {
300
316
  merged.favicon = config.favicon;
301
317
  }
package/dist/types.d.ts CHANGED
@@ -61,6 +61,8 @@ export type HeadConfig = {
61
61
  title?: string;
62
62
  description?: string;
63
63
  basename?: string;
64
+ routeBasePath?: string;
65
+ transportBasePath?: string;
64
66
  favicon?: string;
65
67
  meta?: HeadMetaTag[];
66
68
  links?: HeadLinkTag[];
@@ -112,6 +114,7 @@ export type CreateHtmlShellOptions = {
112
114
  initialFlightData?: string;
113
115
  clientRenderMode?: "hydrate" | "mount";
114
116
  basename?: string;
117
+ routeBasePath?: string;
115
118
  liveReloadPath?: string;
116
119
  liveReloadServerId?: string;
117
120
  };
@@ -58,6 +58,7 @@ function createHTMLShell(options = {}) {
58
58
  rootHtml = "",
59
59
  initialFlightData = "",
60
60
  basename = "",
61
+ routeBasePath = "",
61
62
  liveReloadPath,
62
63
  liveReloadServerId
63
64
  } = options;
@@ -106,6 +107,7 @@ function createHTMLShell(options = {}) {
106
107
  <div id="root">${rootHtml}</div>
107
108
  <script>window.__RSC_ENDPOINT = "${rscEndpoint}";</script>
108
109
  <script>window.__RSC_BASENAME = "${basename}";</script>
110
+ <script>window.__RSC_ROUTE_BASE_PATH = "${routeBasePath}";</script>
109
111
  <script>window.__RSC_INITIAL_PAYLOAD = ${escapedInitialFlightData};</script>
110
112
  <script type="module" src="${clientScriptUrl}"></script>
111
113
  ${liveReloadScript}
@@ -156,12 +158,12 @@ var import_node_path2 = __toESM(require("node:path"), 1);
156
158
  // src/head.ts
157
159
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
158
160
  function normalizeHeadBasename(value) {
159
- const trimmed = value?.trim();
160
- if (!trimmed) {
161
+ if (typeof value !== "string") {
161
162
  return void 0;
162
163
  }
163
- if (trimmed === "/") {
164
- return "/";
164
+ const trimmed = value.trim();
165
+ if (!trimmed || trimmed === "/") {
166
+ return "";
165
167
  }
166
168
  return trimmed.replace(/\/+$/, "");
167
169
  }
@@ -174,6 +176,9 @@ function resolveHeadAssetUrl(assetUrl, basename) {
174
176
  if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
175
177
  return normalizedAssetUrl;
176
178
  }
179
+ if (normalizedAssetUrl.startsWith("/")) {
180
+ return normalizedAssetUrl;
181
+ }
177
182
  if (normalizedBasename !== "/" && (normalizedAssetUrl === normalizedBasename || normalizedAssetUrl.startsWith(`${normalizedBasename}/`))) {
178
183
  return normalizedAssetUrl;
179
184
  }
@@ -190,9 +195,15 @@ function normalizeHeadConfig(head, inheritedBasename) {
190
195
  return void 0;
191
196
  }
192
197
  const effectiveBasename = normalizeHeadBasename(head.basename) ?? normalizeHeadBasename(inheritedBasename);
198
+ const normalizedRouteBasePath = normalizeHeadBasename(head.routeBasePath);
199
+ const normalizedTransportBasePath = normalizeHeadBasename(
200
+ head.transportBasePath
201
+ );
193
202
  const normalizedHead = {
194
203
  ...head,
195
- ...effectiveBasename ? { basename: effectiveBasename } : {}
204
+ ...effectiveBasename !== void 0 ? { basename: effectiveBasename } : {},
205
+ ...normalizedRouteBasePath !== void 0 ? { routeBasePath: normalizedRouteBasePath } : {},
206
+ ...normalizedTransportBasePath !== void 0 ? { transportBasePath: normalizedTransportBasePath } : {}
196
207
  };
197
208
  if (normalizedHead.favicon) {
198
209
  normalizedHead.favicon = resolveHeadAssetUrl(
@@ -429,15 +440,22 @@ function mergeHead(...configs) {
429
440
  if (!config) {
430
441
  continue;
431
442
  }
443
+ const hasOwn = (key) => Object.prototype.hasOwnProperty.call(config, key);
432
444
  if (config.title) {
433
445
  merged.title = config.title;
434
446
  }
435
447
  if (config.description) {
436
448
  merged.description = config.description;
437
449
  }
438
- if (config.basename) {
450
+ if (hasOwn("basename")) {
439
451
  merged.basename = config.basename;
440
452
  }
453
+ if (hasOwn("routeBasePath")) {
454
+ merged.routeBasePath = config.routeBasePath;
455
+ }
456
+ if (hasOwn("transportBasePath")) {
457
+ merged.transportBasePath = config.transportBasePath;
458
+ }
441
459
  if (config.favicon) {
442
460
  merged.favicon = config.favicon;
443
461
  }
@@ -877,7 +895,7 @@ async function decodeFlightPayloadFromString(flightData, moduleMap) {
877
895
 
878
896
  if (typeof reactServerDomClientNode.createFromNodeStream === "function") {
879
897
  return await reactServerDomClientNode.createFromNodeStream(
880
- Readable.from([flightData]),
898
+ Readable.from([Buffer.from(flightData)]),
881
899
  serverConsumerManifest
882
900
  );
883
901
  }
@@ -1002,6 +1020,23 @@ function stripBasePath(pathname, basePath) {
1002
1020
  }
1003
1021
  return pathname;
1004
1022
  }
1023
+ function normalizeRuntimeBasePath(value) {
1024
+ if (typeof value !== "string") {
1025
+ return void 0;
1026
+ }
1027
+ const trimmed = value.trim();
1028
+ if (!trimmed || trimmed === "/") {
1029
+ return "";
1030
+ }
1031
+ return trimmed.replace(/\/+$/, "");
1032
+ }
1033
+ function joinRuntimeBasePath(basePath, pathname) {
1034
+ const normalizedPath = !pathname || pathname === "/" ? "/" : pathname.startsWith("/") ? pathname : `/${pathname}`;
1035
+ if (!basePath) {
1036
+ return normalizedPath;
1037
+ }
1038
+ return normalizedPath === "/" ? basePath : `${basePath}${normalizedPath}`;
1039
+ }
1005
1040
  function sanitizeInitialHtmlWorkerNodeOptions(rawNodeOptions) {
1006
1041
  if (!rawNodeOptions || rawNodeOptions.trim() === "") {
1007
1042
  return "";
@@ -1402,6 +1437,14 @@ function createNodeRequestHandler(options) {
1402
1437
  const initialFlightData = await renderRSCToString(initialPayload, {
1403
1438
  moduleMap
1404
1439
  });
1440
+ const transportBasePath = normalizeRuntimeBasePath(resolved.head.transportBasePath) ?? normalizeRuntimeBasePath(basePath) ?? "";
1441
+ const shellClientScriptUrl = joinRuntimeBasePath(
1442
+ transportBasePath,
1443
+ "/assets/client.js"
1444
+ );
1445
+ const shellRscEndpoint = joinRuntimeBasePath(transportBasePath, "/rsc");
1446
+ const shellBasename = normalizeRuntimeBasePath(resolved.head.basename) ?? normalizeRuntimeBasePath(basePath) ?? "";
1447
+ const shellRouteBasePath = normalizeRuntimeBasePath(resolved.head.routeBasePath) ?? "";
1405
1448
  let rootHtml = "";
1406
1449
  try {
1407
1450
  rootHtml = await initialHtmlWorker.renderFromFlightData({
@@ -1432,11 +1475,12 @@ function createNodeRequestHandler(options) {
1432
1475
  createHTMLShell({
1433
1476
  title: "500 - Initial HTML render failed",
1434
1477
  headTags: "",
1435
- clientScriptUrl,
1436
- rscEndpoint: rscPath,
1478
+ clientScriptUrl: shellClientScriptUrl,
1479
+ rscEndpoint: shellRscEndpoint,
1437
1480
  rootHtml: createInitialHtmlErrorMarkup("Initial HTML render failed."),
1438
1481
  initialFlightData,
1439
- basename: resolved?.head?.basename ?? basePath,
1482
+ basename: shellBasename,
1483
+ routeBasePath: shellRouteBasePath,
1440
1484
  liveReloadPath: liveReloadPath || void 0,
1441
1485
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1442
1486
  })
@@ -1451,11 +1495,12 @@ function createNodeRequestHandler(options) {
1451
1495
  createHTMLShell({
1452
1496
  title: resolved.head.title || "Webframez React",
1453
1497
  headTags: renderHeadToString(resolved.head),
1454
- clientScriptUrl,
1455
- rscEndpoint: rscPath,
1498
+ clientScriptUrl: shellClientScriptUrl,
1499
+ rscEndpoint: shellRscEndpoint,
1456
1500
  rootHtml,
1457
1501
  initialFlightData,
1458
- basename: resolved.head.basename ?? basePath,
1502
+ basename: shellBasename,
1503
+ routeBasePath: shellRouteBasePath,
1459
1504
  liveReloadPath: liveReloadPath || void 0,
1460
1505
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1461
1506
  })
@@ -30,6 +30,7 @@ function createHTMLShell(options = {}) {
30
30
  rootHtml = "",
31
31
  initialFlightData = "",
32
32
  basename = "",
33
+ routeBasePath = "",
33
34
  liveReloadPath,
34
35
  liveReloadServerId
35
36
  } = options;
@@ -78,6 +79,7 @@ function createHTMLShell(options = {}) {
78
79
  <div id="root">${rootHtml}</div>
79
80
  <script>window.__RSC_ENDPOINT = "${rscEndpoint}";</script>
80
81
  <script>window.__RSC_BASENAME = "${basename}";</script>
82
+ <script>window.__RSC_ROUTE_BASE_PATH = "${routeBasePath}";</script>
81
83
  <script>window.__RSC_INITIAL_PAYLOAD = ${escapedInitialFlightData};</script>
82
84
  <script type="module" src="${clientScriptUrl}"></script>
83
85
  ${liveReloadScript}
@@ -128,12 +130,12 @@ import path2 from "node:path";
128
130
  // src/head.ts
129
131
  var ABSOLUTE_ASSET_URL_PATTERN = /^(?:[a-zA-Z][a-zA-Z\d+\-.]*:|\/\/|#)/;
130
132
  function normalizeHeadBasename(value) {
131
- const trimmed = value?.trim();
132
- if (!trimmed) {
133
+ if (typeof value !== "string") {
133
134
  return void 0;
134
135
  }
135
- if (trimmed === "/") {
136
- return "/";
136
+ const trimmed = value.trim();
137
+ if (!trimmed || trimmed === "/") {
138
+ return "";
137
139
  }
138
140
  return trimmed.replace(/\/+$/, "");
139
141
  }
@@ -146,6 +148,9 @@ function resolveHeadAssetUrl(assetUrl, basename) {
146
148
  if (ABSOLUTE_ASSET_URL_PATTERN.test(normalizedAssetUrl)) {
147
149
  return normalizedAssetUrl;
148
150
  }
151
+ if (normalizedAssetUrl.startsWith("/")) {
152
+ return normalizedAssetUrl;
153
+ }
149
154
  if (normalizedBasename !== "/" && (normalizedAssetUrl === normalizedBasename || normalizedAssetUrl.startsWith(`${normalizedBasename}/`))) {
150
155
  return normalizedAssetUrl;
151
156
  }
@@ -162,9 +167,15 @@ function normalizeHeadConfig(head, inheritedBasename) {
162
167
  return void 0;
163
168
  }
164
169
  const effectiveBasename = normalizeHeadBasename(head.basename) ?? normalizeHeadBasename(inheritedBasename);
170
+ const normalizedRouteBasePath = normalizeHeadBasename(head.routeBasePath);
171
+ const normalizedTransportBasePath = normalizeHeadBasename(
172
+ head.transportBasePath
173
+ );
165
174
  const normalizedHead = {
166
175
  ...head,
167
- ...effectiveBasename ? { basename: effectiveBasename } : {}
176
+ ...effectiveBasename !== void 0 ? { basename: effectiveBasename } : {},
177
+ ...normalizedRouteBasePath !== void 0 ? { routeBasePath: normalizedRouteBasePath } : {},
178
+ ...normalizedTransportBasePath !== void 0 ? { transportBasePath: normalizedTransportBasePath } : {}
168
179
  };
169
180
  if (normalizedHead.favicon) {
170
181
  normalizedHead.favicon = resolveHeadAssetUrl(
@@ -401,15 +412,22 @@ function mergeHead(...configs) {
401
412
  if (!config) {
402
413
  continue;
403
414
  }
415
+ const hasOwn = (key) => Object.prototype.hasOwnProperty.call(config, key);
404
416
  if (config.title) {
405
417
  merged.title = config.title;
406
418
  }
407
419
  if (config.description) {
408
420
  merged.description = config.description;
409
421
  }
410
- if (config.basename) {
422
+ if (hasOwn("basename")) {
411
423
  merged.basename = config.basename;
412
424
  }
425
+ if (hasOwn("routeBasePath")) {
426
+ merged.routeBasePath = config.routeBasePath;
427
+ }
428
+ if (hasOwn("transportBasePath")) {
429
+ merged.transportBasePath = config.transportBasePath;
430
+ }
413
431
  if (config.favicon) {
414
432
  merged.favicon = config.favicon;
415
433
  }
@@ -849,7 +867,7 @@ async function decodeFlightPayloadFromString(flightData, moduleMap) {
849
867
 
850
868
  if (typeof reactServerDomClientNode.createFromNodeStream === "function") {
851
869
  return await reactServerDomClientNode.createFromNodeStream(
852
- Readable.from([flightData]),
870
+ Readable.from([Buffer.from(flightData)]),
853
871
  serverConsumerManifest
854
872
  );
855
873
  }
@@ -974,6 +992,23 @@ function stripBasePath(pathname, basePath) {
974
992
  }
975
993
  return pathname;
976
994
  }
995
+ function normalizeRuntimeBasePath(value) {
996
+ if (typeof value !== "string") {
997
+ return void 0;
998
+ }
999
+ const trimmed = value.trim();
1000
+ if (!trimmed || trimmed === "/") {
1001
+ return "";
1002
+ }
1003
+ return trimmed.replace(/\/+$/, "");
1004
+ }
1005
+ function joinRuntimeBasePath(basePath, pathname) {
1006
+ const normalizedPath = !pathname || pathname === "/" ? "/" : pathname.startsWith("/") ? pathname : `/${pathname}`;
1007
+ if (!basePath) {
1008
+ return normalizedPath;
1009
+ }
1010
+ return normalizedPath === "/" ? basePath : `${basePath}${normalizedPath}`;
1011
+ }
977
1012
  function sanitizeInitialHtmlWorkerNodeOptions(rawNodeOptions) {
978
1013
  if (!rawNodeOptions || rawNodeOptions.trim() === "") {
979
1014
  return "";
@@ -1374,6 +1409,14 @@ function createNodeRequestHandler(options) {
1374
1409
  const initialFlightData = await renderRSCToString(initialPayload, {
1375
1410
  moduleMap
1376
1411
  });
1412
+ const transportBasePath = normalizeRuntimeBasePath(resolved.head.transportBasePath) ?? normalizeRuntimeBasePath(basePath) ?? "";
1413
+ const shellClientScriptUrl = joinRuntimeBasePath(
1414
+ transportBasePath,
1415
+ "/assets/client.js"
1416
+ );
1417
+ const shellRscEndpoint = joinRuntimeBasePath(transportBasePath, "/rsc");
1418
+ const shellBasename = normalizeRuntimeBasePath(resolved.head.basename) ?? normalizeRuntimeBasePath(basePath) ?? "";
1419
+ const shellRouteBasePath = normalizeRuntimeBasePath(resolved.head.routeBasePath) ?? "";
1377
1420
  let rootHtml = "";
1378
1421
  try {
1379
1422
  rootHtml = await initialHtmlWorker.renderFromFlightData({
@@ -1404,11 +1447,12 @@ function createNodeRequestHandler(options) {
1404
1447
  createHTMLShell({
1405
1448
  title: "500 - Initial HTML render failed",
1406
1449
  headTags: "",
1407
- clientScriptUrl,
1408
- rscEndpoint: rscPath,
1450
+ clientScriptUrl: shellClientScriptUrl,
1451
+ rscEndpoint: shellRscEndpoint,
1409
1452
  rootHtml: createInitialHtmlErrorMarkup("Initial HTML render failed."),
1410
1453
  initialFlightData,
1411
- basename: resolved?.head?.basename ?? basePath,
1454
+ basename: shellBasename,
1455
+ routeBasePath: shellRouteBasePath,
1412
1456
  liveReloadPath: liveReloadPath || void 0,
1413
1457
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1414
1458
  })
@@ -1423,11 +1467,12 @@ function createNodeRequestHandler(options) {
1423
1467
  createHTMLShell({
1424
1468
  title: resolved.head.title || "Webframez React",
1425
1469
  headTags: renderHeadToString(resolved.head),
1426
- clientScriptUrl,
1427
- rscEndpoint: rscPath,
1470
+ clientScriptUrl: shellClientScriptUrl,
1471
+ rscEndpoint: shellRscEndpoint,
1428
1472
  rootHtml,
1429
1473
  initialFlightData,
1430
- basename: resolved.head.basename ?? basePath,
1474
+ basename: shellBasename,
1475
+ routeBasePath: shellRouteBasePath,
1431
1476
  liveReloadPath: liveReloadPath || void 0,
1432
1477
  liveReloadServerId: liveReloadPath ? devServerId : void 0
1433
1478
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webtypen/webframez-react",
3
- "version": "0.0.30",
3
+ "version": "0.0.32",
4
4
  "description": "TypeScript React RSC addition for @webtypen/webframez-core",
5
5
  "homepage": "https://webtypen.de/",
6
6
  "author": {