rari 0.10.2 → 0.10.4
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.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as e,c as t,d as n,f as r,g as i,h as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,s as p,t as m,u as h}from"./runtime-client-Bg4V1Ksp.mjs";import{Component as g,useEffect as _,useRef as v,useState as y}from"react";import{Fragment as b,jsx as x,jsxs as S}from"react/jsx-runtime";function C(e,t,n={}){let r=null,i=0,a=0,o=null,s=null,{leading:c=!1,trailing:l=!0,maxWait:u}=n;function d(t){let n=o,r=s;return o=null,s=null,a=t,e.apply(r,n)}function f(e){let n=e-i,r=e-a;return i===0||n>=t||n<0||u!==void 0&&r>=u}function p(){let e=Date.now();if(f(e))return h(e);let n=e-i,o=e-a,s=t-n,c=u===void 0?1/0:u-o,l=Math.min(s,c);r=setTimeout(p,l)}function m(e){return a=e,r=setTimeout(p,t),c?d(e):void 0}function h(e){if(r=null,l&&o)return d(e);o=null,s=null}function g(){r!==null&&clearTimeout(r),a=0,o=null,i=0,s=null,r=null}function _(){return r===null?void 0:h(Date.now())}function v(){return r!==null}function y(...e){let n=Date.now(),a=f(n);if(o=e,s=this,i=n,a){if(r===null)return m(i);if(u!==void 0)return r=setTimeout(p,t),d(i)}r===null&&(r=setTimeout(p,t))}return y.cancel=g,y.flush=_,y.pending=v,y}function w(e,t){if(e instanceof Error&&e.name===`AbortError`)return{type:`abort`,message:`Navigation was cancelled`,originalError:e,url:t,timestamp:Date.now(),retryable:!1};if(e instanceof Error&&e.message.includes(`timeout`))return{type:`timeout`,message:`Navigation request timed out`,originalError:e,url:t,timestamp:Date.now(),retryable:!0};if(e instanceof Error&&`status`in e){let n=e.status;return n===404?{type:`not-found`,message:`Page not found`,originalError:e,statusCode:n,url:t,timestamp:Date.now(),retryable:!1}:n>=500?{type:`server-error`,message:`Server error: ${n}`,originalError:e,statusCode:n,url:t,timestamp:Date.now(),retryable:!0}:{type:`fetch-error`,message:`HTTP error: ${n}`,originalError:e,statusCode:n,url:t,timestamp:Date.now(),retryable:n>=500}}return e instanceof TypeError&&e.message.includes(`fetch`)?{type:`network-error`,message:`Network error - check your connection`,originalError:e,url:t,timestamp:Date.now(),retryable:!0}:e instanceof SyntaxError||e instanceof Error&&e.message.includes(`parse`)?{type:`parse-error`,message:`Failed to parse server response`,originalError:e instanceof Error?e:void 0,url:t,timestamp:Date.now(),retryable:!1}:{type:`fetch-error`,message:e instanceof Error?e.message:`Unknown error occurred`,originalError:e instanceof Error?e:void 0,url:t,timestamp:Date.now(),retryable:!1}}var T=class{options;retryCount;constructor(e={}){this.options={timeout:e.timeout??1e4,maxRetries:e.maxRetries??3,onError:e.onError??(()=>{}),onRetry:e.onRetry??(()=>{})},this.retryCount=new Map}handleError(e,t){let n=w(e,t);return this.options.onError(n),console.error(`[rari] Navigation:`,n.type,n.message,{url:n.url,statusCode:n.statusCode,retryable:n.retryable}),typeof window<`u`&&window.dispatchEvent(new CustomEvent(`rari:navigation-error`,{detail:n})),n}canRetry(e,t){return e.retryable?(this.retryCount.get(t)??0)<this.options.maxRetries:!1}incrementRetry(e){let t=(this.retryCount.get(e)??0)+1;return this.retryCount.set(e,t),this.options.onRetry(t,{type:`fetch-error`,message:`Retry attempt ${t}`,url:e,timestamp:Date.now(),retryable:!0}),t}resetRetry(e){this.retryCount.delete(e)}getRetryCount(e){return this.retryCount.get(e)??0}clearRetries(){this.retryCount.clear()}};function E(e){if(!e||e===`/`)return`/`;let t=e;for(;t.endsWith(`/`)&&t.length>1;)t=t.slice(0,-1);return t.startsWith(`/`)||(t=`/${t}`),t}function D(e,t){try{return new URL(e,t||window.location.origin).origin!==(t||window.location.origin)}catch{return!1}}function O(e){try{let t=new URL(e,window.location.origin);return t.pathname+t.hash}catch{return e}}function k({error:e,onRetry:t,onReload:n,onDismiss:r,retryCount:i=0,maxRetries:a=3}){let o=e.retryable&&i<a;return x(`div`,{style:{position:`fixed`,top:0,left:0,right:0,bottom:0,background:`rgba(0, 0, 0, 0.5)`,display:`flex`,alignItems:`center`,justifyContent:`center`,zIndex:1e4,padding:`20px`},onClick:e=>{e.target===e.currentTarget&&r&&r()},children:S(`div`,{style:{background:`white`,borderRadius:`8px`,padding:`24px`,maxWidth:`500px`,width:`100%`,boxShadow:`0 4px 12px rgba(0, 0, 0, 0.15)`},onClick:e=>e.stopPropagation(),children:[S(`div`,{style:{display:`flex`,alignItems:`center`,gap:`12px`,marginBottom:`16px`},children:[x(`span`,{style:{fontSize:`32px`},children:(()=>{switch(e.type){case`timeout`:return`⏱️`;case`network-error`:return`📡`;case`not-found`:return`🔍`;case`server-error`:return`⚠️`;case`parse-error`:return`📄`;case`abort`:return`🚫`;default:return`❌`}})()}),x(`h2`,{style:{margin:0,fontSize:`20px`,fontWeight:`600`,color:`#1f2937`},children:`Navigation Error`})]}),x(`p`,{style:{margin:`0 0 16px 0`,fontSize:`15px`,lineHeight:`1.5`,color:`#4b5563`},children:(()=>{switch(e.type){case`timeout`:return`The page took too long to load. Please try again.`;case`network-error`:return`Unable to connect to the server. Please check your internet connection.`;case`not-found`:return`The page you're looking for doesn't exist.`;case`server-error`:return`The server encountered an error. Please try again in a moment.`;case`parse-error`:return`Unable to load the page content. Please try reloading.`;case`abort`:return`Navigation was cancelled.`;default:return e.message||`An unexpected error occurred.`}})()}),e.url&&S(`details`,{style:{marginBottom:`16px`,fontSize:`13px`,color:`#6b7280`},children:[x(`summary`,{style:{cursor:`pointer`,userSelect:`none`,marginBottom:`8px`},children:`Technical details`}),S(`div`,{style:{padding:`12px`,background:`#f9fafb`,borderRadius:`4px`,fontFamily:`monospace`,fontSize:`12px`,wordBreak:`break-all`},children:[S(`div`,{style:{marginBottom:`4px`},children:[x(`strong`,{children:`URL:`}),` `,e.url]}),e.statusCode&&S(`div`,{style:{marginBottom:`4px`},children:[x(`strong`,{children:`Status:`}),` `,e.statusCode]}),S(`div`,{style:{marginBottom:`4px`},children:[x(`strong`,{children:`Type:`}),` `,e.type]}),e.originalError&&S(`div`,{children:[x(`strong`,{children:`Error:`}),` `,e.originalError.message]})]})]}),o&&i>0&&S(`div`,{style:{marginBottom:`16px`,padding:`8px 12px`,background:`#fef3c7`,border:`1px solid #fbbf24`,borderRadius:`4px`,fontSize:`13px`,color:`#92400e`},children:[`Retry attempt`,` `,i,` `,`of`,` `,a]}),S(`div`,{style:{display:`flex`,gap:`8px`,flexWrap:`wrap`},children:[o&&t&&x(`button`,{onClick:t,type:`button`,style:{flex:1,minWidth:`120px`,padding:`10px 16px`,background:`#3b82f6`,color:`white`,border:`none`,borderRadius:`6px`,fontSize:`14px`,fontWeight:`500`,cursor:`pointer`,transition:`background 0.2s`},onMouseEnter:e=>{e.currentTarget.style.background=`#2563eb`},onMouseLeave:e=>{e.currentTarget.style.background=`#3b82f6`},children:`Try Again`}),n&&x(`button`,{onClick:n,type:`button`,style:{flex:1,minWidth:`120px`,padding:`10px 16px`,background:`#6b7280`,color:`white`,border:`none`,borderRadius:`6px`,fontSize:`14px`,fontWeight:`500`,cursor:`pointer`,transition:`background 0.2s`},onMouseEnter:e=>{e.currentTarget.style.background=`#4b5563`},onMouseLeave:e=>{e.currentTarget.style.background=`#6b7280`},children:`Reload Page`}),r&&x(`button`,{onClick:r,type:`button`,style:{flex:1,minWidth:`120px`,padding:`10px 16px`,background:`transparent`,color:`#6b7280`,border:`1px solid #d1d5db`,borderRadius:`6px`,fontSize:`14px`,fontWeight:`500`,cursor:`pointer`,transition:`all 0.2s`},onMouseEnter:e=>{e.currentTarget.style.background=`#f9fafb`,e.currentTarget.style.borderColor=`#9ca3af`},onMouseLeave:e=>{e.currentTarget.style.background=`transparent`,e.currentTarget.style.borderColor=`#d1d5db`},children:`Dismiss`})]}),x(`p`,{style:{marginTop:`16px`,marginBottom:0,fontSize:`12px`,color:`#9ca3af`,textAlign:`center`},children:`Your current page is still available below this message`})]})})}const A=new class{cache=new Map;pendingRequests=new Map;async get(e){let t=this.cache.get(e);if(t)return t;let n=this.pendingRequests.get(e);if(n)return n;let r=this.fetchRouteInfo(e);this.pendingRequests.set(e,r);try{let t=await r;return this.cache.set(e,t),t}finally{this.pendingRequests.delete(e)}}async fetchRouteInfo(e){let t={path:e},n=await fetch(`/_rari/route-info`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=null;try{e=await n.json()}catch{}throw e?.error?Error(e.error):Error(`Failed to fetch route info: ${n.status} ${n.statusText}`)}let r=n.clone();try{return await n.json()}catch(t){try{let e=await r.text();return JSON.parse(e)}catch(n){throw console.error(`[RouteInfo] Failed to parse response:`,{error:t,parseError:n,path:e}),Error(`Failed to parse route info response`)}}}clear(){this.cache.clear(),this.pendingRequests.clear()}invalidate(e){this.cache.delete(e)}};if(typeof window<`u`){let e=window[`~rari`]||{};window[`~rari`]||(window[`~rari`]=e),e.routeInfoCache=A}var j=class{stateHistory;routeAccessOrder;maxHistorySize;scrollableSelector;constructor(e={}){this.stateHistory=new Map,this.routeAccessOrder=[],this.maxHistorySize=e.maxHistorySize||50,this.scrollableSelector=e.scrollableSelector||`[data-scrollable], .scrollable, [style*="overflow"]`}captureState(e){let t={scrollPositions:this.captureScrollPositions(),formData:this.captureFormData(),focusedElement:this.captureFocusedElement()};return this.storeState(e,t),t}captureScrollPositions(){let e=new Map;try{e.set(`window`,{x:window.scrollX,y:window.scrollY,element:`window`}),document.querySelectorAll(this.scrollableSelector).forEach((t,n)=>{if(t instanceof HTMLElement){let r=t.id||`scrollable-${n}`;(t.scrollHeight>t.clientHeight||t.scrollWidth>t.clientWidth)&&e.set(r,{x:t.scrollLeft,y:t.scrollTop,element:r})}})}catch{}return e}captureFormData(){let e=new Map;try{document.querySelectorAll(`form`).forEach((t,n)=>{let r=t.id||t.name||`form-${n}`,i=new FormData(t);i.entries().next().done||e.set(r,i)})}catch{}return e}captureFocusedElement(){try{let e=document.activeElement;if(e&&e!==document.body){if(e.id)return`#${e.id}`;if((e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement)&&e.name)return`[name="${e.name}"]`}}catch{}return null}storeState(e,t){let n=this.routeAccessOrder.indexOf(e);for(n!==-1&&this.routeAccessOrder.splice(n,1),this.routeAccessOrder.push(e),this.stateHistory.set(e,t);this.routeAccessOrder.length>this.maxHistorySize;){let e=this.routeAccessOrder.shift();e&&this.stateHistory.delete(e)}}getHistorySize(){return this.stateHistory.size}hasState(e){return this.stateHistory.has(e)}getState(e){return this.stateHistory.get(e)}clearAll(){this.stateHistory.clear(),this.routeAccessOrder=[]}clearState(e){this.stateHistory.delete(e);let t=this.routeAccessOrder.indexOf(e);t!==-1&&this.routeAccessOrder.splice(t,1)}restoreState(e){let t=this.stateHistory.get(e);if(!t)return!1;let n=!0;return this.restoreScrollPositions(t.scrollPositions)||(n=!1),this.restoreFormData(t.formData)||(n=!1),t.focusedElement&&this.restoreFocus(t.focusedElement),n}restoreScrollPositions(e){let t=!0;try{e.forEach((e,n)=>{try{if(n===`window`)window.scrollTo(e.x,e.y);else{let r=document.getElementById(n)||document.querySelector(`[data-scrollable-id="${n}"]`);r instanceof HTMLElement?(r.scrollLeft=e.x,r.scrollTop=e.y):t=!1}}catch{t=!1}})}catch(e){console.error(`[rari] Router: Failed to restore scroll positions:`,e),t=!1}return t}restoreFormData(e){let t=!0;try{e.forEach((e,n)=>{try{let r=document.getElementById(n)||document.querySelector(`form[name="${n}"]`)||document.querySelectorAll(`form`)[Number.parseInt(n.replace(`form-`,``),10)];r instanceof HTMLFormElement?e.forEach((e,n)=>{try{let t=r.elements.namedItem(n);t instanceof RadioNodeList?t.forEach(t=>{t instanceof HTMLInputElement&&(t.type===`radio`||t.type===`checkbox`?t.checked=t.value===e:t.value=e)}):(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&(t instanceof HTMLInputElement&&(t.type===`checkbox`||t.type===`radio`)?t.checked=t.value===e:t.value=e)}catch{t=!1}}):t=!1}catch{t=!1}})}catch(e){console.error(`[rari] Router: Failed to restore form data:`,e),t=!1}return t}restoreFocus(e){try{let t=document.querySelector(e);t instanceof HTMLElement&&requestAnimationFrame(()=>{try{t.focus()}catch{}})}catch{}}};function M(e){e.title&&(document.title=e.title);let t=(e,t)=>{let n=document.querySelector(e);if(n)t.content&&n.setAttribute(`content`,t.content);else{n=document.createElement(`meta`);for(let[e,r]of Object.entries(t))n.setAttribute(e,r);document.head.appendChild(n)}};if(e.description&&t(`meta[name="description"]`,{name:`description`,content:e.description}),e.keywords&&e.keywords.length>0&&t(`meta[name="keywords"]`,{name:`keywords`,content:e.keywords.join(`, `)}),e.viewport&&t(`meta[name="viewport"]`,{name:`viewport`,content:e.viewport}),e.canonical){let t=document.querySelector(`link[rel="canonical"]`);t||(t=document.createElement(`link`),t.setAttribute(`rel`,`canonical`),document.head.appendChild(t)),t.setAttribute(`href`,e.canonical)}if(e.robots){let n=[];e.robots.index!==void 0&&n.push(e.robots.index?`index`:`noindex`),e.robots.follow!==void 0&&n.push(e.robots.follow?`follow`:`nofollow`),e.robots.nocache&&n.push(`nocache`),n.length>0&&t(`meta[name="robots"]`,{name:`robots`,content:n.join(`, `)})}if(e.openGraph){let n=e.openGraph;if(n.title&&t(`meta[property="og:title"]`,{property:`og:title`,content:n.title}),n.description&&t(`meta[property="og:description"]`,{property:`og:description`,content:n.description}),n.url&&t(`meta[property="og:url"]`,{property:`og:url`,content:n.url}),n.siteName&&t(`meta[property="og:site_name"]`,{property:`og:site_name`,content:n.siteName}),n.type&&t(`meta[property="og:type"]`,{property:`og:type`,content:n.type}),n.images&&n.images.length>0){document.querySelectorAll(`meta[property="og:image"]`).forEach(e=>e.remove());for(let e of n.images){let t=document.createElement(`meta`);t.setAttribute(`property`,`og:image`),t.setAttribute(`content`,e),document.head.appendChild(t)}}}if(e.twitter){let n=e.twitter;if(n.card&&t(`meta[name="twitter:card"]`,{name:`twitter:card`,content:n.card}),n.site&&t(`meta[name="twitter:site"]`,{name:`twitter:site`,content:n.site}),n.creator&&t(`meta[name="twitter:creator"]`,{name:`twitter:creator`,content:n.creator}),n.title&&t(`meta[name="twitter:title"]`,{name:`twitter:title`,content:n.title}),n.description&&t(`meta[name="twitter:description"]`,{name:`twitter:description`,content:n.description}),n.images&&n.images.length>0){document.querySelectorAll(`meta[name="twitter:image"]`).forEach(e=>e.remove());for(let e of n.images){let t=document.createElement(`meta`);t.setAttribute(`name`,`twitter:image`),t.setAttribute(`content`,e),document.head.appendChild(t)}}}}function N({children:e,initialRoute:t,staleWindowMs:n=3e4}){let[r,i]=y(()=>({currentRoute:E(t),navigationId:0,error:null})),a=v(null),o=v(!0),s=v(E(t)),c=v(new T({timeout:1e4,maxRetries:3,onError:e=>{console.error(`[rari] Router: Navigation error:`,e)},onRetry:()=>{}})),l=v(new Map),u=v([]),d=v(new j({maxHistorySize:50})),f=v(null),p=v(n),m=()=>`${Date.now()}-${Math.random().toString(36).substring(2,9)}`,h=()=>{a.current&&=(a.current.abort(),null)},g=()=>{for(let[,e]of l.current.entries())e.abortController.abort();l.current.clear()},w=(e,t)=>{l.current.delete(e),o.current&&r.navigationId===t&&i(e=>({...e}))},N=async e=>A.get(e),P=v(null),F=async(e,t={})=>{if(!e||typeof e!=`string`){console.error(`[rari] Router: Invalid navigation target:`,e);return}let[n,u]=e.includes(`#`)?e.split(`#`):[e,``],f=E(n);if(f===s.current&&!t.replace){if(u){let e=document.getElementById(u);e&&(e.scrollIntoView({behavior:`smooth`,block:`start`}),window.history.pushState(window.history.state,``,`${f}#${u}`))}return}let p=l.current.get(f);if(p)return p.promise;let _=await N(f);g(),h();let v=new AbortController;a.current=v;let y=r.navigationId+1,b=(async()=>{let e=s.current;try{t.historyKey||d.current.captureState(e);let n=t.historyKey||m(),r={route:f,navigationId:y,scrollPosition:{x:window.scrollX,y:window.scrollY},timestamp:Date.now(),key:n},a=u?`${f}#${u}`:f;t.replace?window.history.replaceState(r,``,a):window.history.pushState(r,``,a);let p=window.location.origin+f,h=await fetch(p,{headers:{Accept:`text/x-component`},signal:v.signal});if(!h.ok&&h.status!==404)throw Error(`Failed to fetch: ${h.status}`);let g=new URL(h.url).pathname,b=g===f?f:g;if(g!==f){let e=u?`${g}#${u}`:g;window.history.replaceState({route:g,navigationId:y,scrollPosition:{x:window.scrollX,y:window.scrollY},timestamp:Date.now(),key:t.historyKey||m()},``,e)}if(v.signal.aborted){w(b,y);return}try{let e=h.headers.get(`x-rari-metadata`);if(e){let t=decodeURIComponent(e);M(JSON.parse(t))}}catch{}if(h.headers.get(`x-render-mode`)===`streaming`&&h.body){let n=h.body.getReader(),r=new TextDecoder,i=``;try{for(;;){let{done:e,value:t}=await n.read();if(e)break;if(v.signal.aborted){await n.cancel(),w(b,y);return}i+=r.decode(t,{stream:!0});let a=i.split(`
|
|
2
|
-
`);i=a.pop()||``;for(let e of a)e.trim()&&window.dispatchEvent(new CustomEvent(`rari:rsc-row`,{detail:{rscRow:e}}))}i.trim()&&window.dispatchEvent(new CustomEvent(`rari:rsc-row`,{detail:{rscRow:i}})),window.dispatchEvent(new CustomEvent(`rari:navigate`,{detail:{from:e,to:b,navigationId:y,options:t,routeInfo:_,abortSignal:v.signal,isStreaming:!0}}))}catch(e){throw console.error(`[rari] Router: Streaming error:`,e),e}}else{let n=await h.text();window.dispatchEvent(new CustomEvent(`rari:navigate`,{detail:{from:e,to:b,navigationId:y,options:t,routeInfo:_,abortSignal:v.signal,rscWireFormat:n}}))}if(v.signal.aborted){
|
|
3
|
-
`,this.state.error.stack]})]}),
|
|
1
|
+
import{a as e,c as t,d as n,f as r,g as i,h as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,s as p,t as m,u as h}from"./runtime-client-Bg4V1Ksp.mjs";import{Component as g,useEffect as _,useLayoutEffect as v,useRef as y,useState as b}from"react";import{Fragment as x,jsx as S,jsxs as C}from"react/jsx-runtime";function w(e,t,n={}){let r=null,i=0,a=0,o=null,s=null,{leading:c=!1,trailing:l=!0,maxWait:u}=n;function d(t){let n=o,r=s;return o=null,s=null,a=t,e.apply(r,n)}function f(e){let n=e-i,r=e-a;return i===0||n>=t||n<0||u!==void 0&&r>=u}function p(){let e=Date.now();if(f(e))return h(e);let n=e-i,o=e-a,s=t-n,c=u===void 0?1/0:u-o,l=Math.min(s,c);r=setTimeout(p,l)}function m(e){return a=e,r=setTimeout(p,t),c?d(e):void 0}function h(e){if(r=null,l&&o)return d(e);o=null,s=null}function g(){r!==null&&clearTimeout(r),a=0,o=null,i=0,s=null,r=null}function _(){return r===null?void 0:h(Date.now())}function v(){return r!==null}function y(...e){let n=Date.now(),a=f(n);if(o=e,s=this,i=n,a){if(r===null)return m(i);if(u!==void 0)return r=setTimeout(p,t),d(i)}r===null&&(r=setTimeout(p,t))}return y.cancel=g,y.flush=_,y.pending=v,y}function T(e,t){if(e instanceof Error&&e.name===`AbortError`)return{type:`abort`,message:`Navigation was cancelled`,originalError:e,url:t,timestamp:Date.now(),retryable:!1};if(e instanceof Error&&e.message.includes(`timeout`))return{type:`timeout`,message:`Navigation request timed out`,originalError:e,url:t,timestamp:Date.now(),retryable:!0};if(e instanceof Error&&`status`in e){let n=e.status;return n===404?{type:`not-found`,message:`Page not found`,originalError:e,statusCode:n,url:t,timestamp:Date.now(),retryable:!1}:n>=500?{type:`server-error`,message:`Server error: ${n}`,originalError:e,statusCode:n,url:t,timestamp:Date.now(),retryable:!0}:{type:`fetch-error`,message:`HTTP error: ${n}`,originalError:e,statusCode:n,url:t,timestamp:Date.now(),retryable:n>=500}}return e instanceof TypeError&&e.message.includes(`fetch`)?{type:`network-error`,message:`Network error - check your connection`,originalError:e,url:t,timestamp:Date.now(),retryable:!0}:e instanceof SyntaxError||e instanceof Error&&e.message.includes(`parse`)?{type:`parse-error`,message:`Failed to parse server response`,originalError:e instanceof Error?e:void 0,url:t,timestamp:Date.now(),retryable:!1}:{type:`fetch-error`,message:e instanceof Error?e.message:`Unknown error occurred`,originalError:e instanceof Error?e:void 0,url:t,timestamp:Date.now(),retryable:!1}}var E=class{options;retryCount;constructor(e={}){this.options={timeout:e.timeout??1e4,maxRetries:e.maxRetries??3,onError:e.onError??(()=>{}),onRetry:e.onRetry??(()=>{})},this.retryCount=new Map}handleError(e,t){let n=T(e,t);return this.options.onError(n),console.error(`[rari] Navigation:`,n.type,n.message,{url:n.url,statusCode:n.statusCode,retryable:n.retryable}),typeof window<`u`&&window.dispatchEvent(new CustomEvent(`rari:navigation-error`,{detail:n})),n}canRetry(e,t){return e.retryable?(this.retryCount.get(t)??0)<this.options.maxRetries:!1}incrementRetry(e){let t=(this.retryCount.get(e)??0)+1;return this.retryCount.set(e,t),this.options.onRetry(t,{type:`fetch-error`,message:`Retry attempt ${t}`,url:e,timestamp:Date.now(),retryable:!0}),t}resetRetry(e){this.retryCount.delete(e)}getRetryCount(e){return this.retryCount.get(e)??0}clearRetries(){this.retryCount.clear()}};function D(e){if(!e||e===`/`)return`/`;let t=e;for(;t.endsWith(`/`)&&t.length>1;)t=t.slice(0,-1);return t.startsWith(`/`)||(t=`/${t}`),t}function O(e,t){try{return new URL(e,t||window.location.origin).origin!==(t||window.location.origin)}catch{return!1}}function k(e){try{let t=new URL(e,window.location.origin);return t.pathname+t.hash}catch{return e}}function A({error:e,onRetry:t,onReload:n,onDismiss:r,retryCount:i=0,maxRetries:a=3}){let o=e.retryable&&i<a;return S(`div`,{style:{position:`fixed`,top:0,left:0,right:0,bottom:0,background:`rgba(0, 0, 0, 0.5)`,display:`flex`,alignItems:`center`,justifyContent:`center`,zIndex:1e4,padding:`20px`},onClick:e=>{e.target===e.currentTarget&&r&&r()},children:C(`div`,{style:{background:`white`,borderRadius:`8px`,padding:`24px`,maxWidth:`500px`,width:`100%`,boxShadow:`0 4px 12px rgba(0, 0, 0, 0.15)`},onClick:e=>e.stopPropagation(),children:[C(`div`,{style:{display:`flex`,alignItems:`center`,gap:`12px`,marginBottom:`16px`},children:[S(`span`,{style:{fontSize:`32px`},children:(()=>{switch(e.type){case`timeout`:return`⏱️`;case`network-error`:return`📡`;case`not-found`:return`🔍`;case`server-error`:return`⚠️`;case`parse-error`:return`📄`;case`abort`:return`🚫`;default:return`❌`}})()}),S(`h2`,{style:{margin:0,fontSize:`20px`,fontWeight:`600`,color:`#1f2937`},children:`Navigation Error`})]}),S(`p`,{style:{margin:`0 0 16px 0`,fontSize:`15px`,lineHeight:`1.5`,color:`#4b5563`},children:(()=>{switch(e.type){case`timeout`:return`The page took too long to load. Please try again.`;case`network-error`:return`Unable to connect to the server. Please check your internet connection.`;case`not-found`:return`The page you're looking for doesn't exist.`;case`server-error`:return`The server encountered an error. Please try again in a moment.`;case`parse-error`:return`Unable to load the page content. Please try reloading.`;case`abort`:return`Navigation was cancelled.`;default:return e.message||`An unexpected error occurred.`}})()}),e.url&&C(`details`,{style:{marginBottom:`16px`,fontSize:`13px`,color:`#6b7280`},children:[S(`summary`,{style:{cursor:`pointer`,userSelect:`none`,marginBottom:`8px`},children:`Technical details`}),C(`div`,{style:{padding:`12px`,background:`#f9fafb`,borderRadius:`4px`,fontFamily:`monospace`,fontSize:`12px`,wordBreak:`break-all`},children:[C(`div`,{style:{marginBottom:`4px`},children:[S(`strong`,{children:`URL:`}),` `,e.url]}),e.statusCode&&C(`div`,{style:{marginBottom:`4px`},children:[S(`strong`,{children:`Status:`}),` `,e.statusCode]}),C(`div`,{style:{marginBottom:`4px`},children:[S(`strong`,{children:`Type:`}),` `,e.type]}),e.originalError&&C(`div`,{children:[S(`strong`,{children:`Error:`}),` `,e.originalError.message]})]})]}),o&&i>0&&C(`div`,{style:{marginBottom:`16px`,padding:`8px 12px`,background:`#fef3c7`,border:`1px solid #fbbf24`,borderRadius:`4px`,fontSize:`13px`,color:`#92400e`},children:[`Retry attempt`,` `,i,` `,`of`,` `,a]}),C(`div`,{style:{display:`flex`,gap:`8px`,flexWrap:`wrap`},children:[o&&t&&S(`button`,{onClick:t,type:`button`,style:{flex:1,minWidth:`120px`,padding:`10px 16px`,background:`#3b82f6`,color:`white`,border:`none`,borderRadius:`6px`,fontSize:`14px`,fontWeight:`500`,cursor:`pointer`,transition:`background 0.2s`},onMouseEnter:e=>{e.currentTarget.style.background=`#2563eb`},onMouseLeave:e=>{e.currentTarget.style.background=`#3b82f6`},children:`Try Again`}),n&&S(`button`,{onClick:n,type:`button`,style:{flex:1,minWidth:`120px`,padding:`10px 16px`,background:`#6b7280`,color:`white`,border:`none`,borderRadius:`6px`,fontSize:`14px`,fontWeight:`500`,cursor:`pointer`,transition:`background 0.2s`},onMouseEnter:e=>{e.currentTarget.style.background=`#4b5563`},onMouseLeave:e=>{e.currentTarget.style.background=`#6b7280`},children:`Reload Page`}),r&&S(`button`,{onClick:r,type:`button`,style:{flex:1,minWidth:`120px`,padding:`10px 16px`,background:`transparent`,color:`#6b7280`,border:`1px solid #d1d5db`,borderRadius:`6px`,fontSize:`14px`,fontWeight:`500`,cursor:`pointer`,transition:`all 0.2s`},onMouseEnter:e=>{e.currentTarget.style.background=`#f9fafb`,e.currentTarget.style.borderColor=`#9ca3af`},onMouseLeave:e=>{e.currentTarget.style.background=`transparent`,e.currentTarget.style.borderColor=`#d1d5db`},children:`Dismiss`})]}),S(`p`,{style:{marginTop:`16px`,marginBottom:0,fontSize:`12px`,color:`#9ca3af`,textAlign:`center`},children:`Your current page is still available below this message`})]})})}const j=new class{cache=new Map;pendingRequests=new Map;async get(e){let t=this.cache.get(e);if(t)return t;let n=this.pendingRequests.get(e);if(n)return n;let r=this.fetchRouteInfo(e);this.pendingRequests.set(e,r);try{let t=await r;return this.cache.set(e,t),t}finally{this.pendingRequests.delete(e)}}async fetchRouteInfo(e){let t={path:e},n=await fetch(`/_rari/route-info`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=null;try{e=await n.json()}catch{}throw e?.error?Error(e.error):Error(`Failed to fetch route info: ${n.status} ${n.statusText}`)}let r=n.clone();try{return await n.json()}catch(t){try{let e=await r.text();return JSON.parse(e)}catch(n){throw console.error(`[RouteInfo] Failed to parse response:`,{error:t,parseError:n,path:e}),Error(`Failed to parse route info response`)}}}clear(){this.cache.clear(),this.pendingRequests.clear()}invalidate(e){this.cache.delete(e)}};if(typeof window<`u`){let e=window[`~rari`]||{};window[`~rari`]||(window[`~rari`]=e),e.routeInfoCache=j}var M=class{stateHistory;routeAccessOrder;maxHistorySize;scrollableSelector;constructor(e={}){this.stateHistory=new Map,this.routeAccessOrder=[],this.maxHistorySize=e.maxHistorySize||50,this.scrollableSelector=e.scrollableSelector||`[data-scrollable], .scrollable, [style*="overflow"]`}captureState(e){let t={scrollPositions:this.captureScrollPositions(),formData:this.captureFormData(),focusedElement:this.captureFocusedElement()};return this.storeState(e,t),t}captureScrollPositions(){let e=new Map;try{e.set(`window`,{x:window.scrollX,y:window.scrollY,element:`window`}),document.querySelectorAll(this.scrollableSelector).forEach((t,n)=>{if(t instanceof HTMLElement){let r=t.id||`scrollable-${n}`;(t.scrollHeight>t.clientHeight||t.scrollWidth>t.clientWidth)&&e.set(r,{x:t.scrollLeft,y:t.scrollTop,element:r})}})}catch{}return e}captureFormData(){let e=new Map;try{document.querySelectorAll(`form`).forEach((t,n)=>{let r=t.id||t.name||`form-${n}`,i=new FormData(t);i.entries().next().done||e.set(r,i)})}catch{}return e}captureFocusedElement(){try{let e=document.activeElement;if(e&&e!==document.body){if(e.id)return`#${e.id}`;if((e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement)&&e.name)return`[name="${e.name}"]`}}catch{}return null}storeState(e,t){let n=this.routeAccessOrder.indexOf(e);for(n!==-1&&this.routeAccessOrder.splice(n,1),this.routeAccessOrder.push(e),this.stateHistory.set(e,t);this.routeAccessOrder.length>this.maxHistorySize;){let e=this.routeAccessOrder.shift();e&&this.stateHistory.delete(e)}}getHistorySize(){return this.stateHistory.size}hasState(e){return this.stateHistory.has(e)}getState(e){return this.stateHistory.get(e)}clearAll(){this.stateHistory.clear(),this.routeAccessOrder=[]}clearState(e){this.stateHistory.delete(e);let t=this.routeAccessOrder.indexOf(e);t!==-1&&this.routeAccessOrder.splice(t,1)}restoreState(e){let t=this.stateHistory.get(e);if(!t)return!1;let n=!0;return this.restoreScrollPositions(t.scrollPositions)||(n=!1),this.restoreFormData(t.formData)||(n=!1),t.focusedElement&&this.restoreFocus(t.focusedElement),n}restoreScrollPositions(e){let t=!0;try{e.forEach((e,n)=>{try{if(n===`window`)window.scrollTo(e.x,e.y);else{let r=document.getElementById(n)||document.querySelector(`[data-scrollable-id="${n}"]`);r instanceof HTMLElement?(r.scrollLeft=e.x,r.scrollTop=e.y):t=!1}}catch{t=!1}})}catch(e){console.error(`[rari] Router: Failed to restore scroll positions:`,e),t=!1}return t}restoreFormData(e){let t=!0;try{e.forEach((e,n)=>{try{let r=document.getElementById(n)||document.querySelector(`form[name="${n}"]`)||document.querySelectorAll(`form`)[Number.parseInt(n.replace(`form-`,``),10)];r instanceof HTMLFormElement?e.forEach((e,n)=>{try{let t=r.elements.namedItem(n);t instanceof RadioNodeList?t.forEach(t=>{t instanceof HTMLInputElement&&(t.type===`radio`||t.type===`checkbox`?t.checked=t.value===e:t.value=e)}):(t instanceof HTMLInputElement||t instanceof HTMLTextAreaElement||t instanceof HTMLSelectElement)&&(t instanceof HTMLInputElement&&(t.type===`checkbox`||t.type===`radio`)?t.checked=t.value===e:t.value=e)}catch{t=!1}}):t=!1}catch{t=!1}})}catch(e){console.error(`[rari] Router: Failed to restore form data:`,e),t=!1}return t}restoreFocus(e){try{let t=document.querySelector(e);t instanceof HTMLElement&&requestAnimationFrame(()=>{try{t.focus()}catch{}})}catch{}}};function N(e){e.title&&(document.title=e.title);let t=(e,t)=>{let n=document.querySelector(e);if(n)t.content&&n.setAttribute(`content`,t.content);else{n=document.createElement(`meta`);for(let[e,r]of Object.entries(t))n.setAttribute(e,r);document.head.appendChild(n)}};if(e.description&&t(`meta[name="description"]`,{name:`description`,content:e.description}),e.keywords&&e.keywords.length>0&&t(`meta[name="keywords"]`,{name:`keywords`,content:e.keywords.join(`, `)}),e.viewport&&t(`meta[name="viewport"]`,{name:`viewport`,content:e.viewport}),e.canonical){let t=document.querySelector(`link[rel="canonical"]`);t||(t=document.createElement(`link`),t.setAttribute(`rel`,`canonical`),document.head.appendChild(t)),t.setAttribute(`href`,e.canonical)}if(e.robots){let n=[];e.robots.index!==void 0&&n.push(e.robots.index?`index`:`noindex`),e.robots.follow!==void 0&&n.push(e.robots.follow?`follow`:`nofollow`),e.robots.nocache&&n.push(`nocache`),n.length>0&&t(`meta[name="robots"]`,{name:`robots`,content:n.join(`, `)})}if(e.openGraph){let n=e.openGraph;if(n.title&&t(`meta[property="og:title"]`,{property:`og:title`,content:n.title}),n.description&&t(`meta[property="og:description"]`,{property:`og:description`,content:n.description}),n.url&&t(`meta[property="og:url"]`,{property:`og:url`,content:n.url}),n.siteName&&t(`meta[property="og:site_name"]`,{property:`og:site_name`,content:n.siteName}),n.type&&t(`meta[property="og:type"]`,{property:`og:type`,content:n.type}),n.images&&n.images.length>0){document.querySelectorAll(`meta[property="og:image"]`).forEach(e=>e.remove());for(let e of n.images){let t=document.createElement(`meta`);t.setAttribute(`property`,`og:image`),t.setAttribute(`content`,e),document.head.appendChild(t)}}}if(e.twitter){let n=e.twitter;if(n.card&&t(`meta[name="twitter:card"]`,{name:`twitter:card`,content:n.card}),n.site&&t(`meta[name="twitter:site"]`,{name:`twitter:site`,content:n.site}),n.creator&&t(`meta[name="twitter:creator"]`,{name:`twitter:creator`,content:n.creator}),n.title&&t(`meta[name="twitter:title"]`,{name:`twitter:title`,content:n.title}),n.description&&t(`meta[name="twitter:description"]`,{name:`twitter:description`,content:n.description}),n.images&&n.images.length>0){document.querySelectorAll(`meta[name="twitter:image"]`).forEach(e=>e.remove());for(let e of n.images){let t=document.createElement(`meta`);t.setAttribute(`name`,`twitter:image`),t.setAttribute(`content`,e),document.head.appendChild(t)}}}}function P({children:e,initialRoute:t,staleWindowMs:n=3e4}){let[r,i]=b(()=>({currentRoute:D(t),navigationId:0,error:null})),a=y(null),o=y(!0),s=y(D(t)),c=y(new E({timeout:1e4,maxRetries:3,onError:e=>{console.error(`[rari] Router: Navigation error:`,e)},onRetry:()=>{}})),l=y(new Map),u=y([]),d=y(new M({maxHistorySize:50})),f=y(null),p=y(n),m=()=>`${Date.now()}-${Math.random().toString(36).substring(2,9)}`,h=()=>{a.current&&=(a.current.abort(),null)},g=()=>{for(let[,e]of l.current.entries())e.abortController.abort();l.current.clear()},T=(e,t)=>{l.current.delete(e),o.current&&r.navigationId===t&&i(e=>({...e}))},P=async e=>j.get(e),F=y(null),I=async(e,t={})=>{if(!e||typeof e!=`string`){console.error(`[rari] Router: Invalid navigation target:`,e);return}let[n,u]=e.includes(`#`)?e.split(`#`):[e,``],f=D(n);if(f===s.current&&!t.replace){if(u){let e=document.getElementById(u);e&&(e.scrollIntoView({behavior:`smooth`,block:`start`}),window.history.pushState(window.history.state,``,`${f}#${u}`))}return}let p=l.current.get(f);if(p)return p.promise;let _=await P(f);g(),h();let v=new AbortController;a.current=v;let y=r.navigationId+1,b=(async()=>{let e=s.current;try{t.historyKey||d.current.captureState(e);let n=t.historyKey||m(),r={route:f,navigationId:y,scrollPosition:{x:window.scrollX,y:window.scrollY},timestamp:Date.now(),key:n},a=u?`${f}#${u}`:f;t.replace?window.history.replaceState(r,``,a):window.history.pushState(r,``,a);let p=window.location.origin+f,h=await fetch(p,{headers:{Accept:`text/x-component`},signal:v.signal});if(!h.ok&&h.status!==404)throw Error(`Failed to fetch: ${h.status}`);let g=new URL(h.url).pathname,b=g===f?f:g;if(g!==f){let e=u?`${g}#${u}`:g;window.history.replaceState({route:g,navigationId:y,scrollPosition:{x:window.scrollX,y:window.scrollY},timestamp:Date.now(),key:t.historyKey||m()},``,e)}if(v.signal.aborted){T(b,y);return}try{let e=h.headers.get(`x-rari-metadata`);if(e){let t=decodeURIComponent(e);N(JSON.parse(t))}}catch{}if(h.headers.get(`x-render-mode`)===`streaming`&&h.body){let n=h.body.getReader(),r=new TextDecoder,i=``;try{for(;;){let{done:e,value:t}=await n.read();if(e)break;if(v.signal.aborted){await n.cancel(),T(b,y);return}i+=r.decode(t,{stream:!0});let a=i.split(`
|
|
2
|
+
`);i=a.pop()||``;for(let e of a)e.trim()&&window.dispatchEvent(new CustomEvent(`rari:rsc-row`,{detail:{rscRow:e}}))}i.trim()&&window.dispatchEvent(new CustomEvent(`rari:rsc-row`,{detail:{rscRow:i}})),window.dispatchEvent(new CustomEvent(`rari:navigate`,{detail:{from:e,to:b,navigationId:y,options:t,routeInfo:_,abortSignal:v.signal,isStreaming:!0}}))}catch(e){throw console.error(`[rari] Router: Streaming error:`,e),e}}else{let n=await h.text();window.dispatchEvent(new CustomEvent(`rari:navigate`,{detail:{from:e,to:b,navigationId:y,options:t,routeInfo:_,abortSignal:v.signal,rscWireFormat:n}}))}if(v.signal.aborted){T(b,y);return}o.current&&(s.current=b,i(e=>({...e,currentRoute:b,error:null})),c.current.resetRetry(b),t.historyKey?requestAnimationFrame(()=>{d.current.restoreState(b)}):u&&requestAnimationFrame(()=>{let e=(t=0)=>{let n=document.getElementById(u);n?n.scrollIntoView({behavior:`smooth`,block:`start`}):t<10&&setTimeout(e,50,t+1)};e()})),l.current.delete(f),F.current?.()}catch(t){if(t instanceof Error&&t.name===`AbortError`){T(f,y);return}let n=c.current.handleError(t,f);o.current&&i(e=>({...e,error:n})),l.current.delete(f),window.dispatchEvent(new CustomEvent(`rari:navigate-error`,{detail:{from:e,to:f,error:n,navigationId:y}})),F.current?.()}})();return l.current.set(f,{targetPath:f,navigationId:y,promise:b,abortController:v}),b},L=async()=>{if(u.current.length===0)return;let e=u.current.at(-1);e&&(u.current=[],await I(e.path,e.options))},R=y(I);v(()=>(F.current=L,R.current=I,()=>{F.current=null,R.current=null}));let z=y(null);z.current||=w((e,t)=>{R.current?.(e,t)},50,{leading:!1,trailing:!0,maxWait:200});let B=e=>{if(e.button!==0||e.ctrlKey||e.shiftKey||e.altKey||e.metaKey)return;let t=e.target;for(;t&&t.tagName!==`A`;)t=t.parentElement;if(!t||t.tagName!==`A`)return;let n=t;if(n.target&&n.target!==`_self`||n.hasAttribute(`download`))return;let r=n.getAttribute(`href`);if(!r||O(r))return;if(r.startsWith(`#`)){e.preventDefault();let t=r.slice(1),n=document.getElementById(t);n&&(n.scrollIntoView({behavior:`smooth`,block:`start`}),window.history.pushState(window.history.state,``,r));return}e.preventDefault();let i=k(r);z.current&&z.current(i,{replace:!1})},V=e=>{let t=window.location.pathname,n=e.state;R.current&&R.current(t,{replace:!0,scroll:!1,historyKey:n?.key})},H=()=>{if(r.error&&r.error.url){let e=r.error.url;c.current.incrementRetry(e),I(e,{replace:!1})}},U=()=>{window.location.reload()},W=()=>{i(e=>({...e,error:null}))};_(()=>{let e=window.history.state;if(!e||!e.key){let e={route:r.currentRoute,navigationId:r.navigationId,scrollPosition:{x:window.scrollX,y:window.scrollY},timestamp:Date.now(),key:m()};window.history.replaceState(e,``,window.location.pathname+window.location.search)}},[]);let G=e=>{if(e.persisted){let e=window.location.pathname;d.current.captureState(e)}},K=e=>{if(e.persisted){let e=window.location.pathname,t=window.history.state;requestAnimationFrame(()=>{d.current.restoreState(e),t?.scrollPosition&&window.scrollTo(t.scrollPosition.x,t.scrollPosition.y)})}};return _(()=>(document.addEventListener(`click`,B),window.addEventListener(`popstate`,V),window.addEventListener(`pagehide`,G),window.addEventListener(`pageshow`,K),()=>{document.removeEventListener(`click`,B),window.removeEventListener(`popstate`,V),window.removeEventListener(`pagehide`,G),window.removeEventListener(`pageshow`,K)}),[]),_(()=>{p.current=n;let e=()=>{document.hidden?f.current=Date.now():f.current!==null&&Date.now()-f.current>p.current&&j.clear()};return document.addEventListener(`visibilitychange`,e),()=>{document.removeEventListener(`visibilitychange`,e)}},[n]),_(()=>(o.current=!0,()=>{o.current=!1,h(),g(),z.current?.cancel&&z.current.cancel()}),[]),C(x,{children:[e,r.error&&S(A,{error:r.error,onRetry:H,onReload:U,onDismiss:W,retryCount:c.current.getRetryCount(r.error.url||``),maxRetries:3})]})}var F=class extends g{constructor(e){super(e),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,t){console.error(`[rari] Layout: Error in layout "${this.props.layoutPath}":`,e,t),this.props.onError&&this.props.onError(e,t),typeof window<`u`&&window.dispatchEvent(new CustomEvent(`rari:layout-error`,{detail:{layoutPath:this.props.layoutPath,error:e,errorInfo:t,timestamp:Date.now()}}))}reset=()=>{this.setState({hasError:!1,error:null})};render(){return this.state.hasError&&this.state.error?this.props.fallback?this.props.fallback(this.state.error,this.reset):C(`div`,{style:{padding:`16px`,margin:`16px 0`,background:`#fee`,border:`1px solid #fcc`,borderRadius:`4px`},children:[S(`h3`,{style:{margin:`0 0 8px 0`,color:`#c00`},children:`Layout Error`}),C(`p`,{style:{margin:`0 0 8px 0`,fontSize:`14px`},children:[`An error occurred in layout:`,` `,S(`code`,{children:this.props.layoutPath})]}),C(`details`,{style:{fontSize:`12px`,marginBottom:`8px`},children:[S(`summary`,{style:{cursor:`pointer`},children:`Error details`}),C(`pre`,{style:{marginTop:`8px`,padding:`8px`,background:`#fff`,border:`1px solid #ddd`,borderRadius:`2px`,overflow:`auto`},children:[this.state.error.message,`
|
|
3
|
+
`,this.state.error.stack]})]}),S(`button`,{onClick:this.reset,type:`button`,style:{padding:`6px 12px`,background:`#c00`,color:`white`,border:`none`,borderRadius:`4px`,cursor:`pointer`,fontSize:`14px`},children:`Try Again`})]}):this.props.children}};export{P as ClientRouter,m as DefaultError,l as DefaultLoading,f as ErrorBoundary,o as HttpRuntimeClient,F as LayoutErrorBoundary,e as LoadingSpinner,E as NavigationErrorHandler,A as NavigationErrorOverlay,u as NotFound,M as StatePreserver,h as clearPropsCache,n as clearPropsCacheForComponent,p as createErrorBoundary,t as createHttpRuntimeClient,s as createLoadingBoundary,r as extractMetadata,d as extractServerProps,c as extractServerPropsWithCache,a as extractStaticParams,i as hasServerSideDataFetching};
|
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
}
|
|
5
5
|
`})]})}function h({children:h,initialPayload:g,onNavigate:_}){let[v,y]=s(g),[,b]=s(0),x=o({x:0,y:0}),S=o(new Map),C=o(null),[,w]=c(),T=o(0),E=o(new Map),D=o([]),O=o(null),k=o(0),[A,j]=s(null),M=()=>{if(typeof document>`u`)return;let e=document.querySelectorAll(`form`);S.current.clear(),e.forEach((e,t)=>{let n=new FormData(e);S.current.set(`form-${t}`,n)})},N=()=>{typeof document>`u`||document.querySelectorAll(`form`).forEach((e,t)=>{let n=S.current.get(`form-${t}`);n&&n.forEach((t,n)=>{let r=e.elements.namedItem(n);r&&(r.type===`checkbox`||r.type===`radio`?r.checked=t===`on`:r.value=t)})})},P=(e,t,n,r)=>{let i={timestamp:Date.now(),error:e,type:t,details:n,filePath:r};D.current.push(i),k.current+=1,D.current.length>10&&D.current.shift(),console.error(`[rari] HMR: Failure detected`,{type:t,details:n,filePath:r,consecutiveFailures:k.current,error:e.message,stack:e.stack,timestamp:new Date(i.timestamp).toISOString()}),k.current>=2&&j(i),typeof window<`u`&&window.dispatchEvent(new CustomEvent(`rari:hmr-failure`,{detail:i}))},F=()=>{setTimeout(()=>{window.location.reload()},1e3)},I=()=>{k.current>0&&(k.current=0)},L=e=>{if(!O.current)return!1;if(e===O.current)return!0;let t=e.match(f);if(t){let e=Number.parseInt(t[1],10);if(Date.now()-e>5e3)return!0}return!1};function R(e,n,i,a,o){if(!e)return null;if(typeof e==`string`||typeof e==`number`||typeof e==`boolean`)return e;if(Array.isArray(e)){if(e.length>=4&&e[0]===`$`){let[,s,c,l]=e,u=s;if(typeof s==`string`&&s.startsWith(`$`)&&a){let e=s.substring(1);if(t.test(e)){let e=a.get(s);e&&(e===`$Sreact.suspense`||e===`react.suspense`?u=`Suspense`:console.warn(`[rari] AppRouter: Unknown symbol:`,e))}}if(u===`Suspense`||s===`Suspense`){let e=K(l,n,i,a,o);return r.createElement(r.Suspense,c?{...e,key:c}:e)}if(typeof u==`string`&&u.startsWith(`$L`)){let e=n.get(u);if(!e)return null;let t=globalThis[`~clientComponents`]?.[e.id]?.component;if(!t||typeof t!=`function`)return null;let s=c||`fallback-${Math.random()}`,d={...l,children:l.children?R(l.children,n,i,a,o):void 0};return r.createElement(t,{key:s,...d})}if(!u||typeof u!=`string`&&typeof u!=`function`)return console.error(`[rari] AppRouter: Invalid component type:`,{type:u,typeOf:typeof u,serverKey:c,props:l,rscData:e}),null;let d=K(l,n,i,a,o);return r.createElement(u,c?{...d,key:c}:d)}return e.map((e,t)=>{let s=R(e,n,i,a,o);return s?typeof s==`object`&&r.isValidElement(s)&&!s.key?r.cloneElement(s,{key:t}):s:null}).filter(Boolean)}return e}let z=o(new Set),B=o(new Map),V=o(new Map),H=o(new Map),U=o(new Map);function W(e){if(!U.current.has(e)){let t=new Promise(()=>{});U.current.set(e,t)}return U.current.get(e)}function G({contentRef:e}){let t=B.current,n=V.current,r=H.current;if(t.has(e))return U.current.delete(e),R(t.get(e),n,void 0,r,t);throw W(e)}function K(e,t,n,i,a){if(!e||typeof e!=`object`)return e;a&&(B.current=a),t&&(V.current=t),i&&(H.current=i);let o={};for(let s in e)if(Object.hasOwn(e,s))if(s===`children`){let c=e.children;if(typeof c==`string`&&c.startsWith(`$L`))if(a&&a.has(c)){let e=a.get(c);z.current.delete(c),o[s]=R(e,t,n,i,a)}else z.current.add(c),o[s]=r.createElement(G,{key:`lazy-${c}`,contentRef:c});else o[s]=c?R(c,t,n,i,a):void 0}else s===`dangerouslySetInnerHTML`?o[s]=e[s]:o[s]=R(e[s],t,n,i,a);return o}let q=(e,t)=>{try{let n=t===`array`?`[`:`{`,r=t===`array`?`]`:`}`,i=0,a=-1,o=!1,s=!1;for(let t=0;t<e.length;t++){let c=e[t];if(s){s=!1;continue}if(c===`\\`){s=!0;continue}if(c===`"`&&!s){o=!o;continue}if(!o){if(c===n)i++;else if(c===r&&(i--,i===0)){a=t+1;break}}}if(a===-1)return null;let c=e.substring(0,a),l=e.substring(a).trim();return l.length>0&&!p.test(l)&&console.warn(`[rari] Sanitized corrupted JSON (possible userscript injection):`,{extracted:c.substring(0,100),discarded:l.substring(0,50)}),c}catch(e){return console.error(`[rari] Failed to sanitize JSON:`,e),null}},J=async(e,i=!1)=>{try{let a=e.trim().split(`
|
|
6
6
|
`),o=new Map,s=new Map,c=new Map,l=null,u=[],d=null,f=null;for(let e=0;e<a.length;e++){let n=a[e].trim();if(!n)continue;let r=n.indexOf(`:`);if(r===-1)continue;let p=n.substring(0,r);if(!t.test(p)){console.warn(`[rari] AppRouter: Invalid row ID (non-numeric), skipping line:`,n.substring(0,50));continue}let m=n.substring(r+1);try{if(m.startsWith(`"$S`)){let e=m.slice(1,-1);s.set(`$${p}`,e);continue}if(m.startsWith(`I[`)){let t=q(m.substring(1),`array`);if(!t){console.warn(`[rari] AppRouter: Could not sanitize import line, skipping:`,n.substring(0,80));continue}let r=JSON.parse(t);if(Array.isArray(r)&&r.length>=3){let[t,n,a]=r;o.set(`$L${p}`,{id:t,chunks:Array.isArray(n)?n:[n],name:a||`default`}),i&&t.includes(`layout`)&&(d!==null&&f!==null&&u.push({layoutPath:d,startLine:f,endLine:e-1,props:{}}),d=t,f=e)}}else if(m.startsWith(`[`)){let e=JSON.parse(m);if(c.set(`$L${p}`,e),i&&Array.isArray(e)&&e.length>=4&&typeof e[1]==`string`&&e[1].startsWith(`$L`)){let t=e[1],n=o.get(t);if(n&&n.id.includes(`layout`)){let t=e[3]||{};if(d&&f!==null){let e=u.find(e=>e.layoutPath===d&&e.startLine===f);e&&(e.props=t)}}}!l&&Array.isArray(e)&&(e[0]===`$`?l=e:Array.isArray(e[0])&&e[0][0]===`$`&&(l=e.length===1?e[0]:e))}}catch(e){console.error(`[rari] AppRouter: Failed to parse RSC line:`,n,e)}}if(await n(o),i&&d!==null&&f!==null&&u.push({layoutPath:d,startLine:f,endLine:a.length-1,props:{}}),l&&Array.isArray(l)){if(l[0]===`$`)l=R(l,o,void 0,s,c);else if(Array.isArray(l[0])){let e=l.map(e=>Array.isArray(e)&&e[0]===`$`?R(e,o,void 0,s,c):e).filter(e=>e==null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`||r.isValidElement(e));l=e.length===1?e[0]:e}}return{element:l,modules:o,symbols:s,wireFormat:e,layoutBoundaries:i?u:void 0}}catch(e){throw console.error(`[rari] AppRouter: Failed to parse RSC wire format:`,e),e}},Y=async(t,n)=>{let r=t||window.location.pathname,i=E.current.get(r);if(i)return i;let a=(async()=>{try{let t=(import.meta.env.RARI_SERVER_URL||window.location.origin).replace(e,``)+r+window.location.search,i=await fetch(t,{headers:{Accept:`text/x-component`,"Cache-Control":`no-cache`,Pragma:`no-cache`},cache:`no-store`,signal:n});if(!i.ok){let e=Error(`Failed to fetch RSC data: ${i.status} ${i.statusText}`);throw P(e,`fetch`,`HTTP ${i.status} when fetching ${t}`,window.location.pathname),e}let a=await i.text();if(L(a)&&v)return v;let o;try{o=await J(a,!1)}catch(e){let t=e instanceof Error?e:Error(String(e));throw P(t,`parse`,`Failed to parse RSC wire format: ${t.message}`,window.location.pathname),t}return y(o),O.current=a,I(),o}catch(e){throw e instanceof Error&&!e.message.includes(`Failed to fetch RSC data`)&&!e.message.includes(`Failed to parse`)&&P(e,`network`,`Network error: ${e.message}`,window.location.pathname),console.error(`[rari] AppRouter: Error fetching RSC payload:`,e),e}finally{E.current.delete(r)}})();return E.current.set(r,a),a};a(()=>{if(typeof window>`u`)return;let e=async e=>{let t=e.detail;T.current=t.navigationId,C.current=null,x.current={x:window.scrollX,y:window.scrollY},M(),w(async()=>{try{t.rscWireFormat?(y(await J(t.rscWireFormat,!1)),O.current=t.rscWireFormat,I()):t.isStreaming?C.current=[]:await Y(t.to,t.abortSignal),T.current===t.navigationId&&(b(e=>e+1),j(null),_&&_(t))}catch(e){if(e instanceof Error&&e.name===`AbortError`)return;console.error(`[rari] AppRouter: Navigation failed:`,e),window.dispatchEvent(new CustomEvent(`rari:navigate-error`,{detail:{from:t.from,to:t.to,error:e,navigationId:t.navigationId}})),k.current>=3&&F()}finally{t.options?.historyKey||requestAnimationFrame(()=>{t.options?.scroll!==!1&&window.scrollTo(0,0)})}})},t=async()=>{x.current={x:window.scrollX,y:window.scrollY},M();try{await Y(),b(e=>e+1),j(null)}catch(e){console.error(`[rari] AppRouter: HMR update failed:`,e),k.current>=3&&F()}finally{requestAnimationFrame(()=>{window.scrollTo(x.current.x,x.current.y),N()})}},n=async()=>{try{await Y(),b(e=>e+1),j(null)}catch(e){console.error(`[rari] AppRouter: RSC invalidation failed:`,e),k.current>=3&&F()}},r=async()=>{try{await Y(),j(null)}catch(e){console.error(`[rari] AppRouter: Manifest update failed:`,e),k.current>=3&&F()}},i=async e=>{let t=e.detail.rscRow;if(!(!t||!t.trim())){C.current||=[],C.current.push(t);try{let e=C.current.join(`
|
|
7
|
-
`),t=await J(e,!1);C.current.length<=2&&e.includes(`~boundaryId`)?(y(t),b(e=>e+1)):w(()=>{y(t),b(e=>e+1)})}catch(e){console.error(`[rari] AppRouter: Failed to parse streaming RSC row:`,e)}}};return window.addEventListener(`rari:navigate`,e),window.addEventListener(`rari:app-router-rerender`,t),window.addEventListener(`rari:rsc-invalidate`,n),window.addEventListener(`rari:app-router-manifest-updated`,r),window.addEventListener(`rari:rsc-row`,i),()=>{window.removeEventListener(`rari:navigate`,e),window.removeEventListener(`rari:app-router-rerender`,t),window.removeEventListener(`rari:rsc-invalidate`,n),window.removeEventListener(`rari:app-router-manifest-updated`,r),window.removeEventListener(`rari:rsc-row`,i)}},[_]);let X=()=>{window.location.reload()},Z=()=>{j(null)},Q=e=>{if(!e||typeof e!=`object`)return null;if(e.type===`html`&&e.props?.children){let t=Array.isArray(e.props.children)?e.props.children:[e.props.children];for(let e of t)if(e&&typeof e==`object`&&e.type===`body`)return e.props?.children||null}return e},$=h;return v?.element&&($=Q(v.element)||v.element),Array.isArray($)&&$.length===1&&r.isValidElement($[0])
|
|
7
|
+
`),t=await J(e,!1);C.current.length<=2&&e.includes(`~boundaryId`)?(y(t),b(e=>e+1)):w(()=>{y(t),b(e=>e+1)})}catch(e){console.error(`[rari] AppRouter: Failed to parse streaming RSC row:`,e)}}};return window.addEventListener(`rari:navigate`,e),window.addEventListener(`rari:app-router-rerender`,t),window.addEventListener(`rari:rsc-invalidate`,n),window.addEventListener(`rari:app-router-manifest-updated`,r),window.addEventListener(`rari:rsc-row`,i),()=>{window.removeEventListener(`rari:navigate`,e),window.removeEventListener(`rari:app-router-rerender`,t),window.removeEventListener(`rari:rsc-invalidate`,n),window.removeEventListener(`rari:app-router-manifest-updated`,r),window.removeEventListener(`rari:rsc-row`,i)}},[_]);let X=()=>{window.location.reload()},Z=()=>{j(null)},Q=e=>{if(!e||typeof e!=`object`)return null;if(e.type===`html`&&e.props?.children){let t=Array.isArray(e.props.children)?e.props.children:[e.props.children];for(let e of t)if(e&&typeof e==`object`&&e.type===`body`)return e.props?.children||null}return e},$=h;return v?.element&&($=Q(v.element)||v.element),Array.isArray($)&&$.length===1&&r.isValidElement($[0])?$=$[0]:Array.isArray($)&&$.length>0&&$.every(e=>r.isValidElement(e)||e==null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`)&&($=r.createElement(r.Fragment,null,...$)),$&&typeof $==`object`&&!r.isValidElement($)&&(console.error(`[rari] AppRouter: Invalid content to render:`,$),$=h),d(l,{children:[A&&d(`div`,{style:{position:`fixed`,top:`50%`,left:`50%`,transform:`translate(-50%, -50%)`,padding:`24px`,background:`rgba(220, 38, 38, 0.95)`,color:`white`,borderRadius:`8px`,fontSize:`14px`,zIndex:1e4,maxWidth:`500px`,boxShadow:`0 4px 6px rgba(0, 0, 0, 0.3)`},children:[u(`div`,{style:{marginBottom:`16px`,fontWeight:`bold`,fontSize:`16px`},children:`⚠️ HMR Update Failed`}),d(`div`,{style:{marginBottom:`12px`,opacity:.9},children:[A.type===`fetch`&&`Failed to fetch updated content from server.`,A.type===`parse`&&`Failed to parse server response.`,A.type===`stale`&&`Server returned stale content.`,A.type===`network`&&`Network error occurred.`]}),u(`div`,{style:{marginBottom:`16px`,fontSize:`12px`,opacity:.8,fontFamily:`monospace`},children:A.details}),d(`div`,{style:{marginBottom:`12px`,fontSize:`12px`,opacity:.7},children:[`Consecutive failures:`,` `,k.current,` `,`/`,` `,3]}),d(`div`,{style:{display:`flex`,gap:`8px`},children:[u(`button`,{onClick:X,type:`button`,style:{padding:`8px 16px`,background:`white`,color:`#dc2626`,border:`none`,borderRadius:`4px`,cursor:`pointer`,fontWeight:`bold`,fontSize:`14px`},children:`Refresh Page`}),u(`button`,{onClick:Z,type:`button`,style:{padding:`8px 16px`,background:`rgba(255, 255, 255, 0.2)`,color:`white`,border:`1px solid rgba(255, 255, 255, 0.3)`,borderRadius:`4px`,cursor:`pointer`,fontSize:`14px`},children:`Dismiss`})]}),u(`div`,{style:{marginTop:`12px`,fontSize:`11px`,opacity:.6},children:`Check the console for detailed error logs.`})]}),u(i,{fallback:u(m,{}),children:$})]})}export{h as AppRouterProvider};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rari",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.10.
|
|
4
|
+
"version": "0.10.4",
|
|
5
5
|
"description": "Runtime Accelerated Rendering Infrastructure (rari)",
|
|
6
6
|
"author": "Ryan Skinner",
|
|
7
7
|
"license": "MIT",
|
|
@@ -102,18 +102,18 @@
|
|
|
102
102
|
"rolldown": "1.0.0-rc.2"
|
|
103
103
|
},
|
|
104
104
|
"optionalDependencies": {
|
|
105
|
-
"rari-darwin-arm64": "0.10.
|
|
106
|
-
"rari-darwin-x64": "0.10.
|
|
107
|
-
"rari-linux-arm64": "0.10.
|
|
108
|
-
"rari-linux-x64": "0.10.
|
|
109
|
-
"rari-win32-x64": "0.10.
|
|
105
|
+
"rari-darwin-arm64": "0.10.4",
|
|
106
|
+
"rari-darwin-x64": "0.10.4",
|
|
107
|
+
"rari-linux-arm64": "0.10.4",
|
|
108
|
+
"rari-linux-x64": "0.10.4",
|
|
109
|
+
"rari-win32-x64": "0.10.4"
|
|
110
110
|
},
|
|
111
111
|
"devDependencies": {
|
|
112
112
|
"@types/node": "^25.3.0",
|
|
113
113
|
"@types/react": "^19.2.14",
|
|
114
114
|
"@types/react-dom": "^19.2.3",
|
|
115
|
-
"@typescript/native-preview": "^7.0.0-dev.
|
|
116
|
-
"oxlint": "^1.
|
|
115
|
+
"@typescript/native-preview": "^7.0.0-dev.20260223.1",
|
|
116
|
+
"oxlint": "^1.50.0",
|
|
117
117
|
"rolldown-vite": "^7.3.1",
|
|
118
118
|
"tsdown": "^0.20.3",
|
|
119
119
|
"@rari/deploy": "0.1.0",
|