@weftui/dom 0.29.0 → 0.30.0

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.
@@ -1 +1 @@
1
- import{t as e}from"../rolldown-runtime-DK3Fl9T5.js";import{_ as t,a as n,b as r,c as i,d as a,f as o,g as s,h as c,i as l,l as u,m as d,n as f,o as p,p as m,r as h,s as g,u as _,y as v}from"../shared-Dz0KM9ku.js";import{n as ee}from"../boundary-replay-BY4GyLot.js";import{Cause as y,Context as b,Deferred as x,Effect as S,Exit as C,Fiber as te,HashMap as w,HashSet as T,Layer as ne,ManagedRuntime as re,Option as E,PubSub as D,Ref as O,Schema as ie,Scope as k,Stream as A,SubscriptionRef as j,pipe as M}from"effect";import{AppRpcClientTag as ae,FAILURE_BOUNDARY as oe,FRAGMENT as se,LIST as ce,SERVER_BOUNDARY as le,SUSPENSE_BOUNDARY as ue,Source as de,Subscribable as fe,getElementDescriptor as N,isStream as P,toStream as F}from"@weftui/core";function I(){return S.gen(function*(){let e=yield*s;return++e.streamIdCounter.current})}const pe=I;let me=0;const L=()=>++me;function R(e,t){return S.gen(function*(){for(let[n,r]of Object.entries(t))if(n!==`children`){if(l(n)){yield*xe(e,n,r);continue}if(n===`ref`&&typeof r==`object`&&j.isSubscriptionRef(r)){yield*j.set(r,E.some(e));continue}if(n===`ref`&&Array.isArray(r)){yield*S.forEach(r.filter(e=>j.isSubscriptionRef(e)),t=>j.set(t,E.some(e)),{discard:!0});continue}if(n===`style`){yield*ye(e,r);continue}he(e,n)?yield*ge(e,n,r):yield*_e(e,n,r)}})}function he(e,t){if(t.startsWith(`data-`)||t.startsWith(`aria-`))return!1;let n=Object.getPrototypeOf(e);for(;n!==null;){if(Object.hasOwn(n,t))return!0;n=Object.getPrototypeOf(n)}return t in e}function ge(e,t,n){return S.gen(function*(){P(n)||S.isEffect(n)?yield*V(F(n),n=>{n==null?delete e[t]:e[t]=n},`property:${t}`):n!=null&&(e[t]=n)})}function _e(e,t,n){return S.gen(function*(){if(P(n)||S.isEffect(n))yield*V(F(n),n=>{if(n==null)e.removeAttribute(t);else{let r=ve(n);r!==void 0&&(typeof n==`boolean`?n?e.setAttribute(t,``):e.removeAttribute(t):e.setAttribute(t,r))}},`attribute:${t}`);else{let r=ve(n);r!==void 0&&(typeof n==`boolean`?n?e.setAttribute(t,``):e.removeAttribute(t):e.setAttribute(t,r))}})}function ve(e){if(e!=null)return String(e)}function ye(e,t){return S.gen(function*(){if(P(t)||S.isEffect(t)){yield*V(F(t),t=>{if(typeof t==`string`)e.setAttribute(`style`,t);else if(typeof t==`object`&&t){e.style.cssText=``;for(let[n,r]of Object.entries(t))r!=null&&e.style.setProperty(z(n),String(r))}},`style`);return}if(typeof t==`string`){e.setAttribute(`style`,t);return}typeof t==`object`&&t&&(yield*be(e,t))})}function be(e,t){return S.gen(function*(){for(let[n,r]of Object.entries(t))P(r)||S.isEffect(r)?yield*V(F(r),t=>{t!=null&&e.style.setProperty(z(n),String(t))},`style.${n}`):r!=null&&e.style.setProperty(z(n),String(r))})}function z(e){return e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}function B(e,t,n,r){return S.gen(function*(){let i=yield*S.serviceOption(d);if(E.isNone(i)){let i=yield*S.forkIn(e,t);return yield*M(te.await(i),S.flatMap(e=>C.isFailure(e)&&!y.hasInterruptsOnly(e.cause)?r(e.cause,n):S.void),S.forkIn(t)),i}let a=yield*S.forkIn(e,t);return yield*M(te.await(a),S.flatMap(e=>C.isFailure(e)?i.value.reportError(e.cause):S.void),S.forkIn(t)),a})}function V(e,t,n){return S.gen(function*(){let r=yield*s;yield*B(A.runForEach(e,e=>S.sync(()=>void t(e))),r.scope,n,r.reportUnhandled)})}function xe(e,t,n){return S.gen(function*(){let r=yield*s,i=t.slice(2).toLowerCase(),a=null,o=()=>{a&&=(e.removeEventListener(i,a),null)},c=n=>{o(),!(n==null||n===!1)&&typeof n==`function`&&(a=e=>{let i=n(e);S.isEffect(i)&&r.runtime.runFork(M(i,S.provideService(k.Scope,r.rootScope),S.exit,S.flatMap(e=>C.isFailure(e)&&!y.hasInterruptsOnly(e.cause)?r.reportUnhandled(e.cause,`event:${t}`):S.void)))},e.addEventListener(i,a))};yield*k.addFinalizer(r.scope,S.sync(o)),P(n)||S.isEffect(n)?yield*V(F(n),e=>c(e),`event:${t}`):c(n)})}function Se(e,t,n,r,i,a){return S.gen(function*(){let o=yield*s,c=yield*x.await(t).pipe(S.flip,S.catch(()=>S.interrupt)),l=e.match(c);if(yield*k.close(n,C.void),l===null)return E.isSome(r)?yield*r.value.reportError(c):yield*o.reportUnhandled(c,`boundary:outermost`);K(i,a);let u=yield*H(l),d=a.parentNode;if(d!==null&&u!==null)if(Array.isArray(u))for(let e of u)d.insertBefore(e,a);else d.insertBefore(u,a)})}function Ce(e){return S.gen(function*(){let t=yield*s,n=yield*S.serviceOption(d),r=L(),i=document.createComment(h(r)),a=document.createComment(f(r)),o=yield*k.fork(t.scope,`sequential`),c={...t,scope:o},l=yield*x.make(),u=yield*M(U(e.children),S.provideService(d,{reportError:e=>x.fail(l,e).pipe(S.asVoid)}),S.provideService(s,c),S.provideService(k.Scope,o),S.catchCause(t=>{let n=e.match(t);return n===null?S.failCause(t):M(k.close(o,C.void),S.flatMap(()=>H(n)),S.map(e=>e===null?[]:Array.isArray(e)?e:[e]))}));return yield*S.forkIn(Se(e,l,o,n,i,a),t.scope),[i,...u,a]})}function we(e){return S.gen(function*(){let t=yield*s,n=yield*O.make(1),r=yield*x.make(),i=M(O.updateAndGet(n,e=>e-1),S.flatMap(e=>e<=0?S.asVoid(x.succeed(r,void 0)):S.void)),a={register:O.update(n,e=>e+1),settle:i},c=e.children,l=yield*H((c===void 0?[]:Array.isArray(c)?c:[c]).map(e=>N(e)===void 0&&(S.isEffect(e)||P(e))?{type:()=>e,props:{}}:e)).pipe(S.provideService(v,a)),u=l===null?[]:Array.isArray(l)?l:[l];yield*i;let d=yield*x.poll(r);if(E.isSome(d))return u;let f=yield*pe(),p=document.createComment(m(f)),h=document.createComment(o(f)),g=yield*H(e.fallback??null),_=[];g!==null&&(Array.isArray(g)?_.push(...g):_.push(g));let ee=document.createDocumentFragment();for(let e of u)ee.appendChild(e);let y=S.gen(function*(){yield*x.await(r),K(p,h);let e=h.parentNode;e!==null&&(e.insertBefore(ee,h),p.remove(),h.remove())});return yield*S.forkIn(y,t.scope),[p,..._,h]})}function Te(e){return S.gen(function*(){let n=yield*s,r=yield*S.serviceOption(ae);if(E.isNone(r))return yield*S.fail(new t({cause:void 0,message:`Boundary.rpc "${e.tag}" was mounted client-first without an AppRpcClient in context. Mount the app under @weftui/router (RouterLive), which provides the rpc client, so the boundary can resolve its data.`}));let i=r.value,a=L(),o=document.createComment(h(a)),c=document.createComment(f(a)),l=yield*H(e.fallback??null),u=[];l!==null&&(Array.isArray(l)?u.push(...l):u.push(l));let d=S.gen(function*(){let t=yield*i.call(e.tag,e.payload()),n=yield*Qe(e.tag,e.payload,t,r),a=yield*H(e.render(n));K(o,c);let s=c.parentNode;if(s!==null&&a!==null)if(Array.isArray(a))for(let e of a)s.insertBefore(e,c);else s.insertBefore(a,c)}).pipe(S.catchCause(t=>S.logError(`[weft] Boundary.rpc "${e.tag}" mount failed to resolve; fallback left in place.`,t)));return yield*S.forkIn(d,n.scope),[o,...u,c]})}function H(e){return S.gen(function*(){if(typeof e==`string`||typeof e==`number`||typeof e==`bigint`)return document.createTextNode(String(e));if(typeof e==`boolean`||e==null)return null;if(P(e)||S.isEffect(e)){let t=N(e);if(t!==void 0)return yield*H(t);if(S.isEffect(e)){let t=yield*S.context(),n=S.runSyncExitWith(t)(e);if(C.isSuccess(n))return yield*H(n.value)}return yield*W(F(e))}if(typeof e==`object`&&Symbol.iterator in e&&!(`type`in e))return yield*U(Ee(e));if(typeof e==`object`&&`type`in e&&!(Symbol.iterator in e)){let{type:t,props:n}=e;return t===se?yield*De(n):t===ue?yield*we(n):t===le?yield*Te(n):t===oe?yield*Ce(n):t===ce?yield*Ie(n):typeof t==`string`?yield*Oe(t,n):typeof t==`function`?yield*ke(t,n):yield*S.fail(new r({type:t,message:`Invalid Renderable type: expected string, FRAGMENT, or function, got ${typeof t}`}))}return null})}function Ee(e){let t=[];function n(e){if(P(e)||S.isEffect(e)){t.push(e);return}if(typeof e==`object`&&e&&Symbol.iterator in e&&!(`type`in e))for(let t of e)n(t);else t.push(e)}return n(e),t}function U(e){return S.gen(function*(){let t=[];for(let n of e)if(N(n)===void 0&&(P(n)||S.isEffect(n))){let e=yield*W(F(n));t.push(...e)}else{let e=yield*H(n);e!==null&&(Array.isArray(e)?t.push(...e):t.push(e))}return t})}function De(e){return S.gen(function*(){let t=`children`in e?e.children:void 0;return t===void 0?[]:yield*U(Array.isArray(t)?t:[t])})}function Oe(e,t){return S.gen(function*(){let n=document.createElement(e);yield*R(n,t);let r=`children`in t?t.children:void 0;if(r!==void 0){let e=Array.isArray(r)?r:[r];for(let t of e)if(N(t)===void 0&&(P(t)||S.isEffect(t))){let e=yield*W(F(t));for(let t of e)n.appendChild(t)}else{let e=yield*H(t);if(e!==null)if(Array.isArray(e))for(let t of e)n.appendChild(t);else n.appendChild(e)}}return n})}function ke(e,t){return S.gen(function*(){let n=e(t);if(P(n)||S.isEffect(n)){let e=yield*s,t=yield*k.fork(e.scope,`sequential`),r={...e,scope:t},i=yield*S.serviceOption(v),a=F(n);return E.isSome(i)&&(yield*i.value.register,a=M(a,A.zipWithIndex,A.flatMap(([e,t])=>t===0?A.fromEffect(S.as(i.value.settle,e)):A.make(e)))),yield*W(a).pipe(S.provideService(s,r),S.provideService(k.Scope,t))}return yield*H(n)})}function W(e){return S.gen(function*(){let t=yield*s,n=yield*I(),[r,i]=Ae(n),a=null;return yield*B(A.runForEach(e,e=>S.gen(function*(){a!==null&&(yield*k.close(a,C.void)),a=yield*k.fork(t.scope,`sequential`);let n={...t,scope:a};yield*G(r,i,e).pipe(S.provideService(s,n),S.provideService(k.Scope,a))})),t.scope,`child:stream-${n}`,t.reportUnhandled),[r,i]})}function Ae(e){return[document.createComment(a(e)),document.createComment(_(e))]}function G(e,t,n){return S.gen(function*(){let r=e.nextSibling,i=r!==null&&r!==t&&r.nextSibling===t;if(i&&r.nodeType===at&&je(n)){let e=String(n);r.data!==e&&(r.data=e);return}if(i&&r.nodeType===Y){let e=Me(n);if(e!==void 0&&typeof e.type==`string`&&r.tagName.toLowerCase()===e.type.toLowerCase()){yield*Ne(r,e);return}}K(e,t);let a=yield*H(n),o=e.parentNode;if(o!==null&&a!==null)if(Array.isArray(a))for(let e of a)o.insertBefore(e,t);else o.insertBefore(a,t)})}function je(e){return typeof e==`string`||typeof e==`number`||typeof e==`bigint`}function Me(e){let t=N(e);if(t!==void 0)return t;if(typeof e==`object`&&e&&`type`in e&&!(Symbol.iterator in e)&&!P(e)&&!S.isEffect(e))return e}function Ne(e,t){return S.gen(function*(){yield*R(e,t.props);let n=t.props.children,r=n===void 0?[]:Array.isArray(n)?n:[n];if(!(yield*Pe(e,r))){for(;e.firstChild!==null;)e.firstChild.remove();yield*Fe(e,r)}})}function Pe(e,t){return S.gen(function*(){let n=Array.from(e.childNodes);if(n.length!==t.length)return!1;for(let e=0;e<t.length;e++){let r=t[e],i=n[e];if(je(r)){if(i.nodeType!==at)return!1}else{let e=Me(r);if(e===void 0||typeof e.type!=`string`||i.nodeType!==Y||i.tagName.toLowerCase()!==e.type.toLowerCase())return!1}}for(let e=0;e<t.length;e++){let r=t[e],i=n[e];if(je(r)){let e=String(r);i.data!==e&&(i.data=e)}else yield*Ne(i,Me(r))}return!0})}function Fe(e,t){return S.gen(function*(){for(let n of t)if(P(n)||S.isEffect(n)){let t=yield*W(F(n));for(let n of t)e.appendChild(n)}else{let t=yield*H(n);if(t!==null)if(Array.isArray(t))for(let n of t)e.appendChild(n);else e.appendChild(t)}})}function K(e,t){let n=e.nextSibling;for(;n!==null&&n!==t;){let e=n.nextSibling;n.remove(),n=e}}function Ie(e){return S.gen(function*(){let t=yield*s,{of:n,by:r,render:i}=e,a=yield*I(),[o,c]=Ae(a),l=yield*k.fork(t.scope,`sequential`),u=(yield*de.toSubscribable(n).pipe(S.provideService(k.Scope,l))).changes,d={records:w.empty(),order:[]};return yield*B(A.runForEach(u,e=>S.gen(function*(){d=yield*Re(Array.from(e),r,i,d,l,c,t)})),l,`list:stream-${a}`,t.reportUnhandled),[o,c]})}function Le(e,n){return S.gen(function*(){let r=[],i=T.empty();for(let a=0;a<e.length;a++){let o=n===void 0?e[a]:n(e[a],a);if(T.has(i,o))return yield*S.fail(new t({cause:o,message:`List.each: duplicate key ${He(o)} in a single emission; keys must be unique (set a stable \`by\`).`}));i=T.add(i,o),r.push(o)}return r})}function Re(e,t,n,r,i,a,o){return S.gen(function*(){let s=yield*Le(e,t),c=w.empty();r.order.forEach((e,t)=>{c=w.set(c,e,t)});let l=[],u=[];for(let t=0;t<e.length;t++){let a=s[t],d=w.get(r.records,a);if(E.isSome(d))l.push(d.value),u.push(E.getOrElse(w.get(c,a),()=>-1));else{let r=yield*ze(a,e[t],t,n,i,o);l.push(r),u.push(-1)}}let d=T.empty();for(let e of s)d=T.add(d,e);for(let e of r.order)if(!T.has(d,e)){let t=w.get(r.records,e);E.isSome(t)&&(yield*k.close(t.value.scope,C.void),Ve(t.value.startMarker,t.value.endMarker))}let f=Ue(u),p=a.parentNode;if(p!==null)for(let e=l.length-1;e>=0;e--){let t=l[e];if(u[e]!==-1&&f.has(e))continue;let n=e+1<l.length?l[e+1].startMarker:a,r=u[e]===-1?[t.startMarker,...t.nodes,t.endMarker]:Be(t.startMarker,t.endMarker);for(let e of r)p.insertBefore(e,n)}let m=w.empty();for(let e of l)m=w.set(m,e.key,e);return{records:m,order:s}})}function ze(e,t,r,i,a,o){return S.gen(function*(){let c=yield*k.fork(a,`sequential`),l={...o,scope:c},u=yield*I(),d=document.createComment(p(u)),f=document.createComment(n(u)),m=yield*H(i(t,r)).pipe(S.provideService(s,l),S.provideService(k.Scope,c));return{key:e,scope:c,startMarker:d,endMarker:f,nodes:m===null?[]:Array.isArray(m)?m:[m]}})}function Be(e,t){let n=[],r=e;for(;r!==null&&(n.push(r),r!==t);)r=r.nextSibling;return n}function Ve(e,t){let n=e;for(;n!==null;){let e=n.nextSibling;if(n.remove(),n===t)break;n=e}}function He(e){if(typeof e==`string`)return JSON.stringify(e);if(typeof e==`object`&&e)try{return JSON.stringify(e)}catch{return Object.prototype.toString.call(e)}return String(e)}function Ue(e){let t=e.length,n=[],r=Array.from({length:t},()=>-1);for(let i=0;i<t;i++){let t=e[i];if(t===-1)continue;let a=0,o=n.length;for(;a<o;){let r=a+o>>1;e[n[r]]<t?a=r+1:o=r}a>0&&(r[i]=n[a-1]),n[a]=i}let i=new Set,a=n.length>0?n[n.length-1]:-1;for(;a!==-1;)i.add(a),a=r[a];return i}function q(e,t,n){return S.gen(function*(){if(typeof e==`string`||typeof e==`number`||typeof e==`bigint`)return yield*We(String(e),t,n);if(typeof e==`boolean`||e==null)return t;if(P(e)||S.isEffect(e)){let r=N(e);if(r!==void 0)return yield*q(r,t,n);if(S.isEffect(e)){let r=S.runSyncExit(e);if(C.isSuccess(r))return yield*q(r.value,t,n)}return yield*qe(F(e),t,n)}if(typeof e==`object`&&Symbol.iterator in e&&!(`type`in e)){let r=t,i=0;for(let t of e)r=yield*q(t,r,`${n}[${i}]`),i++;return r}if(typeof e==`object`&&`type`in e&&!(Symbol.iterator in e)){let{type:i,props:a}=e;if(i===se)return yield*J(a,t,n);if(i===ue){if(t!==null&&t.nodeType===X){let e=u(t);if(e!==null&&e.kind===`start`)return yield*Ye(t,n)}return yield*J(a,t,n)}return i===oe?yield*Ze(a,t,n):i===le?yield*$e(a,t,n):i===ce?yield*tt(a,t,n):typeof i==`string`?yield*et(i,a,t,n):typeof i==`function`?yield*q(i(a),t,n):yield*S.fail(new r({type:i,message:`Invalid Renderable type during hydration at ${n}: expected string, FRAGMENT, or function, got ${typeof i}`}))}return t})}function We(e,t,n){return S.gen(function*(){if(e.length===0)return t;if(t===null||t.nodeType!==at)return yield*Q(`text ${JSON.stringify(e)}`,Z(t),n);let r=t;return r.data.startsWith(e)?r.data.length>e.length?r.splitText(e.length):r.nextSibling:yield*Q(`text ${JSON.stringify(e)}`,Z(t),n)})}function Ge(){return S.gen(function*(){let e=yield*O.make(1),t=yield*x.make(),n=M(O.updateAndGet(e,e=>e-1),S.flatMap(e=>e<=0?S.asVoid(x.succeed(t,void 0)):S.void));return{register:O.update(e,e=>e+1),settle:n,awaitReady:x.await(t)}})}function Ke(e){let t=!1;return S.suspend(()=>t||e===void 0?S.void:(t=!0,e.settle))}function qe(e,t,n){return S.gen(function*(){let r=yield*s;if(t===null||t.nodeType!==X)return yield*Q(`reactive region start marker`,Z(t),n);let a=t,o=i(a);if(o===null||o.kind!==`start`)return yield*Q(`reactive region start marker`,Z(t),n);let c=st(a);if(c===null)return yield*Q(`reactive region end marker`,`unterminated region starting at ${JSON.stringify(a.data)}`,n);let l=Ke(r.hydrationReady),u=!0,d=null,f=A.runForEach(e,e=>S.gen(function*(){d!==null&&(yield*k.close(d,C.void)),d=yield*k.fork(r.scope,`sequential`);let t={...r,scope:d};yield*S.gen(function*(){u?(u=!1,yield*Je(e,a,c,n),yield*l):yield*G(a,c,e)}).pipe(S.provideService(s,t),S.provideService(k.Scope,d))})).pipe(S.ensuring(l));return r.hydrationReady!==void 0&&(yield*r.hydrationReady.register),yield*B(f,r.scope,`hydrate:stream-${o.id} (${n})`,r.reportUnhandled),c.nextSibling})}function Je(e,t,n,r){return S.gen(function*(){let i=yield*q(e,t.nextSibling,`${r}<resume>`).pipe(S.map(e=>e===n?null:`adopted content did not align with the end marker`),S.catchTag(`HydrationMismatchError`,e=>S.succeed(`expected ${e.expected}, found ${e.actual} at ${e.path}`)));i!==null&&(console.error(`[weft] hydrate: reactive region at ${r} diverged from server output (${i}); patching.`),yield*G(t,n,e))})}function Ye(e,t){return S.gen(function*(){let n=Xe(e);if(n===null)return yield*Q(`substituted suspense end marker`,`unterminated region starting at ${JSON.stringify(e.data)}`,t);let r=null;for(let t=e.nextSibling;t!==null&&t!==n;t=t.nextSibling)if(t.nodeType===Y&&t.tagName===`SCRIPT`&&t.getAttribute(`type`)===`application/json`&&t.hasAttribute(`data-weft-suspense-failure`)){r=t;break}let i=null;if(r!==null){let e=r.textContent??``;i=yield*S.try({try:()=>JSON.parse(e),catch:e=>e}).pipe(S.catch(()=>S.succeed(null)))}if(typeof i!=`object`||!i||!(`error`in i))return console.error(`[weft] hydrate: substituted suspense region at ${t} has no decodable failure sentinel; leaving its static content.`),n.nextSibling;let a=yield*S.serviceOption(d);return E.isNone(a)?(console.error(`[weft] hydrate: substituted suspense region at ${t} has no enclosing Boundary to replay its failure to; leaving its static content.`,i.error),n.nextSibling):(yield*a.value.reportError(y.fail(i.error)),n.nextSibling)})}function Xe(e){let t=0,n=e.nextSibling;for(;n!==null;){if(n.nodeType===X){let e=u(n);if(e!==null)if(e.kind===`start`)t++;else if(t===0)return n;else t--}n=n.nextSibling}return null}function Ze(e,t,n){return S.gen(function*(){if(t===null||t.nodeType!==Y||t.tagName!==`SCRIPT`||t.getAttribute(`type`)!==`application/json`||!t.hasAttribute(`data-weft-boundary-failure`)){let r=yield*s,i=yield*S.serviceOption(d),a=yield*k.fork(r.scope,`sequential`),o={...r,scope:a},c=yield*x.make(),l=yield*J(e,t,n).pipe(S.provideService(d,{reportError:e=>x.fail(c,e).pipe(S.asVoid)}),S.provideService(s,o),S.provideService(k.Scope,a)),u=t?.parentNode??null;if(t===null||t===l||u===null)return console.error(`[weft] hydrate: boundary at ${n} adopted an empty extent; live failure recovery is not installed for it.`),l;let p=L(),m=document.createComment(h(p)),g=document.createComment(f(p));return u.insertBefore(m,t),l===null?u.appendChild(g):u.insertBefore(g,l),yield*S.forkIn(Se(e,c,a,i,m,g),r.scope),l}let r=t,i=r.textContent??``,a=yield*S.gen(function*(){let t=yield*S.try({try:()=>JSON.parse(i),catch:e=>e}),n=ee(e.children)[t.index];if(n===void 0)return null;let r=yield*ie.decodeUnknownEffect(n.errorSchema)(t.error);return e.match(y.fail(r))}).pipe(S.catch(e=>(console.error(`[weft] hydrate: boundary failure payload at ${n} failed to decode; cannot replay.`,e),S.succeed(null))));if(a===null)return yield*Q(`replayable boundary failure`,`undecodable failure payload`,n);let o=yield*q(a,r.nextSibling,n);return r.remove(),o})}function Qe(e,t,n,r){return S.gen(function*(){let i=yield*j.make(n),a=yield*j.make(!1),o=yield*j.make(E.none()),s=E.match(r,{onNone:()=>S.void,onSome:n=>S.gen(function*(){(yield*j.get(a))||(yield*j.set(a,!0),yield*S.gen(function*(){let r=yield*S.exit(n.call(e,t()));C.isSuccess(r)?(yield*j.set(i,r.value),yield*j.set(o,E.none())):yield*j.set(o,E.some(y.squash(r.cause)))}).pipe(S.ensuring(j.set(a,!1))))})});return{value:fe.make({get:j.get(i),changes:j.changes(i)}),refetch:s,pending:fe.make({get:j.get(a),changes:j.changes(a)}),error:fe.make({get:j.get(o),changes:j.changes(o)})}})}function $e(e,t,n){return S.gen(function*(){if(t===null||t.nodeType!==Y||t.tagName!==`SCRIPT`||t.getAttribute(`type`)!==`application/json`)return yield*Q(`server boundary payload <script type="application/json">`,Z(t),n);if(t.hasAttribute(`data-weft-boundary-failure`))return yield*Q(`server boundary success payload <script type="application/json">`,`boundary failure payload`,n);let r=t,i=r.textContent??``,a=yield*S.try({try:()=>JSON.parse(i),catch:e=>e}).pipe(S.flatMap(t=>ie.decodeUnknownEffect(e.successSchema)(t)),S.catch(e=>(console.error(`[weft] hydrate: server boundary payload at ${n} failed to decode; cannot replay.`,e),Q(`decodable server boundary payload`,`undecodable payload`,n)))),o=yield*S.serviceOption(ae),s=yield*Qe(e.tag,e.payload,a,o),c=yield*q(e.render(s),r.nextSibling,n);return r.remove(),c})}function et(e,t,n,r){return S.gen(function*(){if(n===null||n.nodeType!==Y)return yield*Q(`<${e}>`,Z(n),r);let i=n;return i.tagName.toLowerCase()===e.toLowerCase()?(yield*R(i,t),yield*J(t,i.firstChild,`${r} > ${e}`),i.nextSibling):yield*Q(`<${e}>`,Z(n),r)})}function J(e,t,n){return S.gen(function*(){let r=`children`in e?e.children:void 0;if(r===void 0)return t;let i=Array.isArray(r)?r:[r],a=t,o=0;for(let e of i)a=yield*q(e,a,`${n}[${o}]`),o++;return a})}function tt(e,t,n){return S.gen(function*(){let r=yield*s,{of:a,by:o,render:c}=e;if(t===null||t.nodeType!==X)return yield*Q(`list region start marker`,Z(t),n);let l=t,u=i(l);if(u===null||u.kind!==`start`)return yield*Q(`list region start marker`,Z(t),n);let d=st(l);if(d===null)return yield*Q(`list region end marker`,`unterminated region starting at ${JSON.stringify(l.data)}`,n);let f=nt(l,d),p=yield*k.fork(r.scope,`sequential`),m=(yield*de.toSubscribable(a).pipe(S.provideService(k.Scope,p))).changes,h={records:w.empty(),order:[]},g=!0,_=Ke(r.hydrationReady),v=A.runForEach(m,e=>S.gen(function*(){let t=Array.from(e);g?(g=!1,h=yield*rt(t,o,c,f,p,l,d,r,n),yield*_):h=yield*Re(t,o,c,h,p,d,r)})).pipe(S.ensuring(_));return r.hydrationReady!==void 0&&(yield*r.hydrationReady.register),yield*B(v,p,`hydrate:list-${u.id} (${n})`,r.reportUnhandled),d.nextSibling})}function nt(e,t){let n=[],r=e.nextSibling;for(;r!==null&&r!==t;){let e=r.nodeType===X?g(r):null;if(e===null||e.kind!==`start`){r=r.nextSibling;continue}let i=r,a=[],o=0,s=null,c=i.nextSibling;for(;c!==null&&c!==t;){if(c.nodeType===X){let e=g(c);if(e!==null)if(e.kind===`start`)o++;else if(o===0){s=c;break}else o--}a.push(c),c=c.nextSibling}if(s===null)break;n.push({startMarker:i,endMarker:s,nodes:a}),r=s.nextSibling}return n}function rt(e,t,n,r,i,a,o,s,c){return S.gen(function*(){let l=yield*Le(e,t);if(l.length!==r.length)return console.error(`[weft] hydrate: list region at ${c} had ${r.length} server item(s) but the first emission has ${l.length}; rebuilding.`),K(a,o),yield*Re(e,t,n,{records:w.empty(),order:[]},i,o,s);let u=[];for(let t=0;t<e.length;t++){let a=yield*it(l[t],e[t],t,n,r[t],i,s,c);u.push(a)}let d=w.empty();for(let e of u)d=w.set(d,e.key,e);return{records:d,order:l}})}function it(e,t,n,r,i,a,o,c){return S.gen(function*(){let l=yield*k.fork(a,`sequential`),u={...o,scope:l},d=r(t,n),f=yield*q(d,i.startMarker.nextSibling,`${c}<item>`).pipe(S.provideService(s,u),S.provideService(k.Scope,l),S.map(e=>e===i.endMarker?null:`adopted item content did not align with its end marker`),S.catchTag(`HydrationMismatchError`,e=>S.succeed(`expected ${e.expected}, found ${e.actual} at ${e.path}`)));if(f===null)return{key:e,scope:l,startMarker:i.startMarker,endMarker:i.endMarker,nodes:i.nodes};console.error(`[weft] hydrate: list item at ${c} diverged from server output (${f}); patching.`),yield*k.close(l,C.void);let p=yield*k.fork(a,`sequential`),m={...o,scope:p};K(i.startMarker,i.endMarker);let h=yield*H(d).pipe(S.provideService(s,m),S.provideService(k.Scope,p)),g=h===null?[]:Array.isArray(h)?h:[h],_=i.endMarker.parentNode;if(_!==null)for(let e of g)_.insertBefore(e,i.endMarker);return{key:e,scope:p,startMarker:i.startMarker,endMarker:i.endMarker,nodes:g}})}const Y=1,at=3,X=8;function ot(e,t){let n=document.createTreeWalker(e,128),r=t.current;for(let e=n.nextNode();e!==null;e=n.nextNode()){let t=e,n=i(t)??u(t)??g(t);n!==null&&n.id>r&&(r=n.id)}t.current=r}function st(e){let t=0,n=e.nextSibling;for(;n!==null;){if(n.nodeType===8){let e=i(n);if(e!==null)if(e.kind===`start`)t++;else if(t===0)return n;else t--}n=n.nextSibling}return null}function Z(e){if(e===null)return`end of children`;switch(e.nodeType){case 1:return`<${e.tagName.toLowerCase()}>`;case 3:return`text ${JSON.stringify(e.data)}`;case 8:return`comment ${JSON.stringify(e.data)}`;default:return`node(type ${e.nodeType})`}}function Q(e,t,n){return S.fail(new c({expected:e,actual:t,path:n}))}var ct=e({TypeId:()=>lt,dispose:()=>yt,errors:()=>vt,hydrate:()=>_t,make:()=>ht,mount:()=>gt});const lt=Symbol.for(`@weftui/dom/WeftApp`),ut=new WeakMap;function $(e){let t=ut.get(e);if(t===void 0)throw Error(`Expected a WeftApp created by WeftApp.make`);return t}function dt(e,t){return S.gen(function*(){e.subscribers===0&&(yield*M(S.logError(t.cause),S.annotateLogs(`weft.region`,t.region))),yield*D.publish(e.hub,t)})}function ft(e){return S.suspend(()=>$(e).disposed?S.die(Error(`Cannot mount on a disposed WeftApp`)):e.runtime.contextEffect)}function pt(e,t){return S.gen(function*(){let n=$(e),r=yield*k.fork(n.appScope,`sequential`),i=!1,a={element:t,unmount:()=>S.suspend(()=>i?S.void:(i=!0,k.close(r,C.void)))};return{context:{runtime:e.runtime,scope:r,rootScope:r,streamIdCounter:{current:0},reportUnhandled:(e,t)=>dt(n,{cause:e,region:t,root:a})},handle:a,rootScope:r}})}function mt(e,t){let n=re.make(e??ne.empty,t),r=S.runSync(D.unbounded()),i={[lt]:lt,runtime:n};return ut.set(i,{appScope:k.makeUnsafe(`sequential`),hub:r,subscribers:0,disposed:!1}),i}const ht=mt,gt=(e,t,n)=>S.gen(function*(){let r=yield*ft(e),{context:i,handle:a,rootScope:o}=yield*pt(e,n);n.innerHTML=``;let c=yield*M(H(t),S.setContext(M(r,b.add(s,i),b.add(k.Scope,o))),S.tapError(()=>k.close(o,C.void)));if(c!==null)if(Array.isArray(c))for(let e of c)n.appendChild(e);else n.appendChild(c);return a});function _t(e,t,n){return S.gen(function*(){let r=yield*ft(e),{context:i,handle:a,rootScope:o}=yield*pt(e,n),c=yield*Ge(),l={...i,hydrationReady:c};return ot(n,l.streamIdCounter),yield*M(q(t,n.firstChild,`root`),S.setContext(M(r,b.add(s,l),b.add(k.Scope,o))),S.tapError(()=>k.close(o,C.void))),yield*c.settle,yield*c.awaitReady,a})}const vt=e=>{let t=$(e);return A.unwrap(S.sync(()=>(t.subscribers++,M(A.fromPubSub(t.hub),A.ensuring(S.sync(()=>{t.subscribers--}))))))},yt=e=>S.suspend(()=>{let t=$(e);return t.disposed?S.void:(t.disposed=!0,M(k.close(t.appScope,C.void),S.andThen(e.runtime.disposeEffect),S.andThen(D.shutdown(t.hub))))});export{ct as WeftApp};
1
+ import{t as e}from"../rolldown-runtime-DK3Fl9T5.js";import{_ as t,a as n,b as r,c as i,d as a,f as o,g as s,h as c,i as l,l as u,m as d,n as f,o as p,p as m,r as h,s as g,u as _,y as v}from"../shared-Dz0KM9ku.js";import{n as y}from"../boundary-replay-BY4GyLot.js";import{Cause as b,Context as x,Deferred as S,Effect as C,Exit as w,Fiber as ee,HashMap as T,HashSet as E,Layer as te,ManagedRuntime as ne,Option as D,PubSub as O,Ref as k,Schema as re,Scope as A,Stream as j,SubscriptionRef as M,pipe as N}from"effect";import{AppRpcClientTag as ie,FAILURE_BOUNDARY as ae,FRAGMENT as oe,LIST as se,SERVER_BOUNDARY as ce,SUSPENSE_BOUNDARY as le,Source as ue,Subscribable as P,getElementDescriptor as F,isStream as I,toStream as L}from"@weftui/core";function R(){return C.gen(function*(){let e=yield*s;return++e.streamIdCounter.current})}const de=R;let fe=0;const z=()=>++fe;function B(e,t){return C.gen(function*(){for(let[n,r]of Object.entries(t))if(n!==`children`){if(l(n)){yield*ye(e,n,r);continue}if(n===`ref`&&typeof r==`object`&&M.isSubscriptionRef(r)){yield*M.set(r,D.some(e));continue}if(n===`ref`&&Array.isArray(r)){yield*C.forEach(r.filter(e=>M.isSubscriptionRef(e)),t=>M.set(t,D.some(e)),{discard:!0});continue}if(n===`style`){yield*_e(e,r);continue}pe(e,n)?yield*me(e,n,r):yield*he(e,n,r)}})}function pe(e,t){if(t.startsWith(`data-`)||t.startsWith(`aria-`))return!1;let n=Object.getPrototypeOf(e);for(;n!==null;){if(Object.hasOwn(n,t))return!0;n=Object.getPrototypeOf(n)}return t in e}function me(e,t,n){return C.gen(function*(){I(n)||C.isEffect(n)?yield*U(L(n),n=>{n==null?delete e[t]:e[t]=n},`property:${t}`):n!=null&&(e[t]=n)})}function he(e,t,n){return C.gen(function*(){if(I(n)||C.isEffect(n))yield*U(L(n),n=>{if(n==null)e.removeAttribute(t);else{let r=ge(n);r!==void 0&&(typeof n==`boolean`?n?e.setAttribute(t,``):e.removeAttribute(t):e.setAttribute(t,r))}},`attribute:${t}`);else{let r=ge(n);r!==void 0&&(typeof n==`boolean`?n?e.setAttribute(t,``):e.removeAttribute(t):e.setAttribute(t,r))}})}function ge(e){if(e!=null)return String(e)}function _e(e,t){return C.gen(function*(){if(I(t)||C.isEffect(t)){yield*U(L(t),t=>{if(typeof t==`string`)e.setAttribute(`style`,t);else if(typeof t==`object`&&t){e.style.cssText=``;for(let[n,r]of Object.entries(t))r!=null&&e.style.setProperty(V(n),String(r))}},`style`);return}if(typeof t==`string`){e.setAttribute(`style`,t);return}typeof t==`object`&&t&&(yield*ve(e,t))})}function ve(e,t){return C.gen(function*(){for(let[n,r]of Object.entries(t))I(r)||C.isEffect(r)?yield*U(L(r),t=>{t!=null&&e.style.setProperty(V(n),String(t))},`style.${n}`):r!=null&&e.style.setProperty(V(n),String(r))})}function V(e){return e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}function H(e,t,n,r){return C.gen(function*(){let i=yield*C.serviceOption(d);if(D.isNone(i)){let i=yield*C.forkIn(e,t);return yield*N(ee.await(i),C.flatMap(e=>w.isFailure(e)&&!b.hasInterruptsOnly(e.cause)?r(e.cause,n):C.void),C.forkIn(t)),i}let a=yield*C.forkIn(e,t);return yield*N(ee.await(a),C.flatMap(e=>w.isFailure(e)?i.value.reportError(e.cause):C.void),C.forkIn(t)),a})}function U(e,t,n){return C.gen(function*(){let r=yield*s;yield*H(j.runForEach(e,e=>C.sync(()=>void t(e))),r.scope,n,r.reportUnhandled)})}function ye(e,t,n){return C.gen(function*(){let r=yield*s,i=t.slice(2).toLowerCase(),a=null,o=()=>{a&&=(e.removeEventListener(i,a),null)},c=n=>{o(),!(n==null||n===!1)&&typeof n==`function`&&(a=e=>{let i=n(e);C.isEffect(i)&&r.runtime.runFork(N(i,C.provideService(A.Scope,r.rootScope),C.exit,C.flatMap(e=>w.isFailure(e)&&!b.hasInterruptsOnly(e.cause)?r.reportUnhandled(e.cause,`event:${t}`):C.void)))},e.addEventListener(i,a))};yield*A.addFinalizer(r.scope,C.sync(o)),I(n)||C.isEffect(n)?yield*U(L(n),e=>c(e),`event:${t}`):c(n)})}function be(e,t,n,r,i,a){return C.gen(function*(){let o=yield*s,c=yield*S.await(t).pipe(C.flip,C.catch(()=>C.interrupt)),l=e.match(c);if(yield*A.close(n,w.void),l===null)return D.isSome(r)?yield*r.value.reportError(c):yield*o.reportUnhandled(c,`boundary:outermost`);K(i,a);let u=yield*W(l),d=a.parentNode;if(d!==null&&u!==null)if(Array.isArray(u))for(let e of u)d.insertBefore(e,a);else d.insertBefore(u,a)})}function xe(e){return C.gen(function*(){let t=yield*s,n=yield*C.serviceOption(d),r=z(),i=document.createComment(h(r)),a=document.createComment(f(r)),o=yield*A.fork(t.scope,`sequential`),c={...t,scope:o},l=yield*S.make(),u=yield*N(Te(e.children),C.provideService(d,{reportError:e=>S.fail(l,e).pipe(C.asVoid)}),C.provideService(s,c),C.provideService(A.Scope,o),C.catchCause(t=>{let n=e.match(t);return n===null?C.failCause(t):N(A.close(o,w.void),C.flatMap(()=>W(n)),C.map(e=>e===null?[]:Array.isArray(e)?e:[e]))}));return yield*C.forkIn(be(e,l,o,n,i,a),t.scope),[i,...u,a]})}function Se(e){return C.gen(function*(){let t=yield*s,n=yield*k.make(1),r=yield*S.make(),i=N(k.updateAndGet(n,e=>e-1),C.flatMap(e=>e<=0?C.asVoid(S.succeed(r,void 0)):C.void)),a={register:k.update(n,e=>e+1),settle:i},c=e.children,l=yield*W((c===void 0?[]:Array.isArray(c)?c:[c]).map(e=>F(e)===void 0&&(C.isEffect(e)||I(e))?{type:()=>e,props:{}}:e)).pipe(C.provideService(v,a)),u=l===null?[]:Array.isArray(l)?l:[l];yield*i;let d=yield*S.poll(r);if(D.isSome(d))return u;let f=yield*de(),p=document.createComment(m(f)),h=document.createComment(o(f)),g=yield*W(e.fallback??null),_=[];g!==null&&(Array.isArray(g)?_.push(...g):_.push(g));let y=document.createDocumentFragment();for(let e of u)y.appendChild(e);let b=C.gen(function*(){yield*S.await(r),K(p,h);let e=h.parentNode;e!==null&&(e.insertBefore(y,h),p.remove(),h.remove())});return yield*C.forkIn(b,t.scope),[p,..._,h]})}function Ce(e){return C.gen(function*(){let n=yield*s,r=yield*C.serviceOption(ie);if(D.isNone(r))return yield*C.fail(new t({cause:void 0,message:`Boundary.rpc "${e.tag}" was mounted client-first without an AppRpcClient in context. Mount the app under @weftui/router (RouterLive), which provides the rpc client, so the boundary can resolve its data.`}));let i=r.value,a=z(),o=document.createComment(h(a)),c=document.createComment(f(a)),l=yield*W(e.fallback??null),u=[];l!==null&&(Array.isArray(l)?u.push(...l):u.push(l));let d=C.gen(function*(){let t=yield*i.call(e.tag,e.payload()),n=yield*Qe(e.tag,e.payload,t,r),a=yield*W(e.render(n));K(o,c);let s=c.parentNode;if(s!==null&&a!==null)if(Array.isArray(a))for(let e of a)s.insertBefore(e,c);else s.insertBefore(a,c)}).pipe(C.catchCause(t=>C.logError(`[weft] Boundary.rpc "${e.tag}" mount failed to resolve; fallback left in place.`,t)));return yield*C.forkIn(d,n.scope),[o,...u,c]})}function W(e){return C.gen(function*(){if(typeof e==`string`||typeof e==`number`||typeof e==`bigint`)return document.createTextNode(String(e));if(typeof e==`boolean`||e==null)return null;if(I(e)||C.isEffect(e)){let t=F(e);if(t!==void 0)return yield*W(t);if(C.isEffect(e)){let t=yield*C.context(),n=C.runSyncExitWith(t)(e);if(w.isSuccess(n))return yield*W(n.value)}return yield*G(L(e))}if(typeof e==`object`&&Symbol.iterator in e&&!(`type`in e))return yield*Te(we(e));if(typeof e==`object`&&`type`in e&&!(Symbol.iterator in e)){let{type:t,props:n}=e;return t===oe?yield*Ee(n):t===le?yield*Se(n):t===ce?yield*Ce(n):t===ae?yield*xe(n):t===se?yield*Ie(n):typeof t==`string`?yield*De(t,n):typeof t==`function`?yield*Oe(t,n):yield*C.fail(new r({type:t,message:`Invalid Renderable type: expected string, FRAGMENT, or function, got ${typeof t}`}))}return null})}function we(e){let t=[];function n(e){if(I(e)||C.isEffect(e)){t.push(e);return}if(typeof e==`object`&&e&&Symbol.iterator in e&&!(`type`in e))for(let t of e)n(t);else t.push(e)}return n(e),t}function Te(e){return C.gen(function*(){let t=[];for(let n of e)if(F(n)===void 0&&(I(n)||C.isEffect(n))){let e=yield*G(L(n));t.push(...e)}else{let e=yield*W(n);e!==null&&(Array.isArray(e)?t.push(...e):t.push(e))}return t})}function Ee(e){return C.gen(function*(){let t=`children`in e?e.children:void 0;return t===void 0?[]:yield*Te(Array.isArray(t)?t:[t])})}function De(e,t){return C.gen(function*(){let n=document.createElement(e);yield*B(n,t);let r=`children`in t?t.children:void 0;if(r!==void 0){let e=Array.isArray(r)?r:[r];for(let t of e)if(F(t)===void 0&&(I(t)||C.isEffect(t))){let e=yield*G(L(t));for(let t of e)n.appendChild(t)}else{let e=yield*W(t);if(e!==null)if(Array.isArray(e))for(let t of e)n.appendChild(t);else n.appendChild(e)}}return n})}function Oe(e,t){return C.gen(function*(){let n=e(t);if(I(n)||C.isEffect(n)){let e=yield*s,t=yield*A.fork(e.scope,`sequential`),r={...e,scope:t},i=yield*C.serviceOption(v),a=L(n);return D.isSome(i)&&(yield*i.value.register,a=N(a,j.zipWithIndex,j.flatMap(([e,t])=>t===0?j.fromEffect(C.as(i.value.settle,e)):j.make(e)))),yield*G(a).pipe(C.provideService(s,r),C.provideService(A.Scope,t))}return yield*W(n)})}function G(e){return C.gen(function*(){let t=yield*s,n=yield*R(),[r,i]=ke(n),a=null;return yield*H(j.runForEach(e,e=>C.gen(function*(){a!==null&&(yield*A.close(a,w.void)),a=yield*A.fork(t.scope,`sequential`);let n={...t,scope:a};yield*Ae(r,i,e).pipe(C.provideService(s,n),C.provideService(A.Scope,a))})),t.scope,`child:stream-${n}`,t.reportUnhandled),[r,i]})}function ke(e){return[document.createComment(a(e)),document.createComment(_(e))]}function Ae(e,t,n){return C.gen(function*(){let r=e.nextSibling,i=r!==null&&r!==t&&r.nextSibling===t;if(i&&r.nodeType===at&&je(n)){let e=String(n);r.data!==e&&(r.data=e);return}if(i&&r.nodeType===Y){let e=Me(n);if(e!==void 0&&typeof e.type==`string`&&r.tagName.toLowerCase()===e.type.toLowerCase()){yield*Ne(r,e);return}}K(e,t);let a=yield*W(n),o=e.parentNode;if(o!==null&&a!==null)if(Array.isArray(a))for(let e of a)o.insertBefore(e,t);else o.insertBefore(a,t)})}function je(e){return typeof e==`string`||typeof e==`number`||typeof e==`bigint`}function Me(e){let t=F(e);if(t!==void 0)return t;if(typeof e==`object`&&e&&`type`in e&&!(Symbol.iterator in e)&&!I(e)&&!C.isEffect(e))return e}function Ne(e,t){return C.gen(function*(){yield*B(e,t.props);let n=t.props.children,r=n===void 0?[]:Array.isArray(n)?n:[n];if(!(yield*Pe(e,r))){for(;e.firstChild!==null;)e.firstChild.remove();yield*Fe(e,r)}})}function Pe(e,t){return C.gen(function*(){let n=Array.from(e.childNodes);if(n.length!==t.length)return!1;for(let e=0;e<t.length;e++){let r=t[e],i=n[e];if(je(r)){if(i.nodeType!==at)return!1}else{let e=Me(r);if(e===void 0||typeof e.type!=`string`||i.nodeType!==Y||i.tagName.toLowerCase()!==e.type.toLowerCase())return!1}}for(let e=0;e<t.length;e++){let r=t[e],i=n[e];if(je(r)){let e=String(r);i.data!==e&&(i.data=e)}else yield*Ne(i,Me(r))}return!0})}function Fe(e,t){return C.gen(function*(){for(let n of t)if(I(n)||C.isEffect(n)){let t=yield*G(L(n));for(let n of t)e.appendChild(n)}else{let t=yield*W(n);if(t!==null)if(Array.isArray(t))for(let n of t)e.appendChild(n);else e.appendChild(t)}})}function K(e,t){let n=e.nextSibling;for(;n!==null&&n!==t;){let e=n.nextSibling;n.remove(),n=e}}function Ie(e){return C.gen(function*(){let t=yield*s,{of:n,by:r,render:i}=e,a=yield*R(),[o,c]=ke(a),l=yield*A.fork(t.scope,`sequential`),u=yield*ue.toSubscribable(n).pipe(C.provideService(A.Scope,l)),d=P.changes(u),f={records:T.empty(),order:[]};return yield*H(j.runForEach(d,e=>C.gen(function*(){f=yield*Re(Array.from(e),r,i,f,l,c,t)})),l,`list:stream-${a}`,t.reportUnhandled),[o,c]})}function Le(e,n){return C.gen(function*(){let r=[],i=E.empty();for(let a=0;a<e.length;a++){let o=n===void 0?e[a]:n(e[a],a);if(E.has(i,o))return yield*C.fail(new t({cause:o,message:`List.each: duplicate key ${He(o)} in a single emission; keys must be unique (set a stable \`by\`).`}));i=E.add(i,o),r.push(o)}return r})}function Re(e,t,n,r,i,a,o){return C.gen(function*(){let s=yield*Le(e,t),c=T.empty();r.order.forEach((e,t)=>{c=T.set(c,e,t)});let l=[],u=[];for(let t=0;t<e.length;t++){let a=s[t],d=T.get(r.records,a);if(D.isSome(d))l.push(d.value),u.push(D.getOrElse(T.get(c,a),()=>-1));else{let r=yield*ze(a,e[t],t,n,i,o);l.push(r),u.push(-1)}}let d=E.empty();for(let e of s)d=E.add(d,e);for(let e of r.order)if(!E.has(d,e)){let t=T.get(r.records,e);D.isSome(t)&&(yield*A.close(t.value.scope,w.void),Ve(t.value.startMarker,t.value.endMarker))}let f=Ue(u),p=a.parentNode;if(p!==null)for(let e=l.length-1;e>=0;e--){let t=l[e];if(u[e]!==-1&&f.has(e))continue;let n=e+1<l.length?l[e+1].startMarker:a,r=u[e]===-1?[t.startMarker,...t.nodes,t.endMarker]:Be(t.startMarker,t.endMarker);for(let e of r)p.insertBefore(e,n)}let m=T.empty();for(let e of l)m=T.set(m,e.key,e);return{records:m,order:s}})}function ze(e,t,r,i,a,o){return C.gen(function*(){let c=yield*A.fork(a,`sequential`),l={...o,scope:c},u=yield*R(),d=document.createComment(p(u)),f=document.createComment(n(u)),m=yield*W(i(t,r)).pipe(C.provideService(s,l),C.provideService(A.Scope,c));return{key:e,scope:c,startMarker:d,endMarker:f,nodes:m===null?[]:Array.isArray(m)?m:[m]}})}function Be(e,t){let n=[],r=e;for(;r!==null&&(n.push(r),r!==t);)r=r.nextSibling;return n}function Ve(e,t){let n=e;for(;n!==null;){let e=n.nextSibling;if(n.remove(),n===t)break;n=e}}function He(e){if(typeof e==`string`)return JSON.stringify(e);if(typeof e==`object`&&e)try{return JSON.stringify(e)}catch{return Object.prototype.toString.call(e)}return String(e)}function Ue(e){let t=e.length,n=[],r=Array.from({length:t},()=>-1);for(let i=0;i<t;i++){let t=e[i];if(t===-1)continue;let a=0,o=n.length;for(;a<o;){let r=a+o>>1;e[n[r]]<t?a=r+1:o=r}a>0&&(r[i]=n[a-1]),n[a]=i}let i=new Set,a=n.length>0?n[n.length-1]:-1;for(;a!==-1;)i.add(a),a=r[a];return i}function q(e,t,n){return C.gen(function*(){if(typeof e==`string`||typeof e==`number`||typeof e==`bigint`)return yield*We(String(e),t,n);if(typeof e==`boolean`||e==null)return t;if(I(e)||C.isEffect(e)){let r=F(e);if(r!==void 0)return yield*q(r,t,n);if(C.isEffect(e)){let r=C.runSyncExit(e);if(w.isSuccess(r))return yield*q(r.value,t,n)}return yield*qe(L(e),t,n)}if(typeof e==`object`&&Symbol.iterator in e&&!(`type`in e)){let r=t,i=0;for(let t of e)r=yield*q(t,r,`${n}[${i}]`),i++;return r}if(typeof e==`object`&&`type`in e&&!(Symbol.iterator in e)){let{type:i,props:a}=e;if(i===oe)return yield*J(a,t,n);if(i===le){if(t!==null&&t.nodeType===X){let e=u(t);if(e!==null&&e.kind===`start`)return yield*Ye(t,n)}return yield*J(a,t,n)}return i===ae?yield*Ze(a,t,n):i===ce?yield*$e(a,t,n):i===se?yield*tt(a,t,n):typeof i==`string`?yield*et(i,a,t,n):typeof i==`function`?yield*q(i(a),t,n):yield*C.fail(new r({type:i,message:`Invalid Renderable type during hydration at ${n}: expected string, FRAGMENT, or function, got ${typeof i}`}))}return t})}function We(e,t,n){return C.gen(function*(){if(e.length===0)return t;if(t===null||t.nodeType!==at)return yield*Q(`text ${JSON.stringify(e)}`,Z(t),n);let r=t;return r.data.startsWith(e)?r.data.length>e.length?r.splitText(e.length):r.nextSibling:yield*Q(`text ${JSON.stringify(e)}`,Z(t),n)})}function Ge(){return C.gen(function*(){let e=yield*k.make(1),t=yield*S.make(),n=N(k.updateAndGet(e,e=>e-1),C.flatMap(e=>e<=0?C.asVoid(S.succeed(t,void 0)):C.void));return{register:k.update(e,e=>e+1),settle:n,awaitReady:S.await(t)}})}function Ke(e){let t=!1;return C.suspend(()=>t||e===void 0?C.void:(t=!0,e.settle))}function qe(e,t,n){return C.gen(function*(){let r=yield*s;if(t===null||t.nodeType!==X)return yield*Q(`reactive region start marker`,Z(t),n);let a=t,o=i(a);if(o===null||o.kind!==`start`)return yield*Q(`reactive region start marker`,Z(t),n);let c=st(a);if(c===null)return yield*Q(`reactive region end marker`,`unterminated region starting at ${JSON.stringify(a.data)}`,n);let l=Ke(r.hydrationReady),u=!0,d=null,f=j.runForEach(e,e=>C.gen(function*(){d!==null&&(yield*A.close(d,w.void)),d=yield*A.fork(r.scope,`sequential`);let t={...r,scope:d};yield*C.gen(function*(){u?(u=!1,yield*Je(e,a,c,n),yield*l):yield*Ae(a,c,e)}).pipe(C.provideService(s,t),C.provideService(A.Scope,d))})).pipe(C.ensuring(l));return r.hydrationReady!==void 0&&(yield*r.hydrationReady.register),yield*H(f,r.scope,`hydrate:stream-${o.id} (${n})`,r.reportUnhandled),c.nextSibling})}function Je(e,t,n,r){return C.gen(function*(){let i=yield*q(e,t.nextSibling,`${r}<resume>`).pipe(C.map(e=>e===n?null:`adopted content did not align with the end marker`),C.catchTag(`HydrationMismatchError`,e=>C.succeed(`expected ${e.expected}, found ${e.actual} at ${e.path}`)));i!==null&&(console.error(`[weft] hydrate: reactive region at ${r} diverged from server output (${i}); patching.`),yield*Ae(t,n,e))})}function Ye(e,t){return C.gen(function*(){let n=Xe(e);if(n===null)return yield*Q(`substituted suspense end marker`,`unterminated region starting at ${JSON.stringify(e.data)}`,t);let r=null;for(let t=e.nextSibling;t!==null&&t!==n;t=t.nextSibling)if(t.nodeType===Y&&t.tagName===`SCRIPT`&&t.getAttribute(`type`)===`application/json`&&t.hasAttribute(`data-weft-suspense-failure`)){r=t;break}let i=null;if(r!==null){let e=r.textContent??``;i=yield*C.try({try:()=>JSON.parse(e),catch:e=>e}).pipe(C.catch(()=>C.succeed(null)))}if(typeof i!=`object`||!i||!(`error`in i))return console.error(`[weft] hydrate: substituted suspense region at ${t} has no decodable failure sentinel; leaving its static content.`),n.nextSibling;let a=yield*C.serviceOption(d);return D.isNone(a)?(console.error(`[weft] hydrate: substituted suspense region at ${t} has no enclosing Boundary to replay its failure to; leaving its static content.`,i.error),n.nextSibling):(yield*a.value.reportError(b.fail(i.error)),n.nextSibling)})}function Xe(e){let t=0,n=e.nextSibling;for(;n!==null;){if(n.nodeType===X){let e=u(n);if(e!==null)if(e.kind===`start`)t++;else if(t===0)return n;else t--}n=n.nextSibling}return null}function Ze(e,t,n){return C.gen(function*(){if(t===null||t.nodeType!==Y||t.tagName!==`SCRIPT`||t.getAttribute(`type`)!==`application/json`||!t.hasAttribute(`data-weft-boundary-failure`)){let r=yield*s,i=yield*C.serviceOption(d),a=yield*A.fork(r.scope,`sequential`),o={...r,scope:a},c=yield*S.make(),l=yield*J(e,t,n).pipe(C.provideService(d,{reportError:e=>S.fail(c,e).pipe(C.asVoid)}),C.provideService(s,o),C.provideService(A.Scope,a)),u=t?.parentNode??null;if(t===null||t===l||u===null)return console.error(`[weft] hydrate: boundary at ${n} adopted an empty extent; live failure recovery is not installed for it.`),l;let p=z(),m=document.createComment(h(p)),g=document.createComment(f(p));return u.insertBefore(m,t),l===null?u.appendChild(g):u.insertBefore(g,l),yield*C.forkIn(be(e,c,a,i,m,g),r.scope),l}let r=t,i=r.textContent??``,a=yield*C.gen(function*(){let t=yield*C.try({try:()=>JSON.parse(i),catch:e=>e}),n=y(e.children)[t.index];if(n===void 0)return null;let r=yield*re.decodeUnknownEffect(n.errorSchema)(t.error);return e.match(b.fail(r))}).pipe(C.catch(e=>(console.error(`[weft] hydrate: boundary failure payload at ${n} failed to decode; cannot replay.`,e),C.succeed(null))));if(a===null)return yield*Q(`replayable boundary failure`,`undecodable failure payload`,n);let o=yield*q(a,r.nextSibling,n);return r.remove(),o})}function Qe(e,t,n,r){return C.gen(function*(){let i=yield*M.make(n),a=yield*M.make(!1),o=yield*M.make(D.none()),s=D.match(r,{onNone:()=>C.void,onSome:n=>C.gen(function*(){(yield*M.get(a))||(yield*M.set(a,!0),yield*C.gen(function*(){let r=yield*C.exit(n.call(e,t()));w.isSuccess(r)?(yield*M.set(i,r.value),yield*M.set(o,D.none())):yield*M.set(o,D.some(b.squash(r.cause)))}).pipe(C.ensuring(M.set(a,!1))))})});return{value:P.make({get:M.get(i),changes:M.changes(i)}),refetch:s,pending:P.make({get:M.get(a),changes:M.changes(a)}),error:P.make({get:M.get(o),changes:M.changes(o)})}})}function $e(e,t,n){return C.gen(function*(){if(t===null||t.nodeType!==Y||t.tagName!==`SCRIPT`||t.getAttribute(`type`)!==`application/json`)return yield*Q(`server boundary payload <script type="application/json">`,Z(t),n);if(t.hasAttribute(`data-weft-boundary-failure`))return yield*Q(`server boundary success payload <script type="application/json">`,`boundary failure payload`,n);let r=t,i=r.textContent??``,a=yield*C.try({try:()=>JSON.parse(i),catch:e=>e}).pipe(C.flatMap(t=>re.decodeUnknownEffect(e.successSchema)(t)),C.catch(e=>(console.error(`[weft] hydrate: server boundary payload at ${n} failed to decode; cannot replay.`,e),Q(`decodable server boundary payload`,`undecodable payload`,n)))),o=yield*C.serviceOption(ie),s=yield*Qe(e.tag,e.payload,a,o),c=yield*q(e.render(s),r.nextSibling,n);return r.remove(),c})}function et(e,t,n,r){return C.gen(function*(){if(n===null||n.nodeType!==Y)return yield*Q(`<${e}>`,Z(n),r);let i=n;return i.tagName.toLowerCase()===e.toLowerCase()?(yield*B(i,t),yield*J(t,i.firstChild,`${r} > ${e}`),i.nextSibling):yield*Q(`<${e}>`,Z(n),r)})}function J(e,t,n){return C.gen(function*(){let r=`children`in e?e.children:void 0;if(r===void 0)return t;let i=Array.isArray(r)?r:[r],a=t,o=0;for(let e of i)a=yield*q(e,a,`${n}[${o}]`),o++;return a})}function tt(e,t,n){return C.gen(function*(){let r=yield*s,{of:a,by:o,render:c}=e;if(t===null||t.nodeType!==X)return yield*Q(`list region start marker`,Z(t),n);let l=t,u=i(l);if(u===null||u.kind!==`start`)return yield*Q(`list region start marker`,Z(t),n);let d=st(l);if(d===null)return yield*Q(`list region end marker`,`unterminated region starting at ${JSON.stringify(l.data)}`,n);let f=nt(l,d),p=yield*A.fork(r.scope,`sequential`),m=yield*ue.toSubscribable(a).pipe(C.provideService(A.Scope,p)),h=P.changes(m),g={records:T.empty(),order:[]},_=!0,v=Ke(r.hydrationReady),y=j.runForEach(h,e=>C.gen(function*(){let t=Array.from(e);_?(_=!1,g=yield*rt(t,o,c,f,p,l,d,r,n),yield*v):g=yield*Re(t,o,c,g,p,d,r)})).pipe(C.ensuring(v));return r.hydrationReady!==void 0&&(yield*r.hydrationReady.register),yield*H(y,p,`hydrate:list-${u.id} (${n})`,r.reportUnhandled),d.nextSibling})}function nt(e,t){let n=[],r=e.nextSibling;for(;r!==null&&r!==t;){let e=r.nodeType===X?g(r):null;if(e===null||e.kind!==`start`){r=r.nextSibling;continue}let i=r,a=[],o=0,s=null,c=i.nextSibling;for(;c!==null&&c!==t;){if(c.nodeType===X){let e=g(c);if(e!==null)if(e.kind===`start`)o++;else if(o===0){s=c;break}else o--}a.push(c),c=c.nextSibling}if(s===null)break;n.push({startMarker:i,endMarker:s,nodes:a}),r=s.nextSibling}return n}function rt(e,t,n,r,i,a,o,s,c){return C.gen(function*(){let l=yield*Le(e,t);if(l.length!==r.length)return console.error(`[weft] hydrate: list region at ${c} had ${r.length} server item(s) but the first emission has ${l.length}; rebuilding.`),K(a,o),yield*Re(e,t,n,{records:T.empty(),order:[]},i,o,s);let u=[];for(let t=0;t<e.length;t++){let a=yield*it(l[t],e[t],t,n,r[t],i,s,c);u.push(a)}let d=T.empty();for(let e of u)d=T.set(d,e.key,e);return{records:d,order:l}})}function it(e,t,n,r,i,a,o,c){return C.gen(function*(){let l=yield*A.fork(a,`sequential`),u={...o,scope:l},d=r(t,n),f=yield*q(d,i.startMarker.nextSibling,`${c}<item>`).pipe(C.provideService(s,u),C.provideService(A.Scope,l),C.map(e=>e===i.endMarker?null:`adopted item content did not align with its end marker`),C.catchTag(`HydrationMismatchError`,e=>C.succeed(`expected ${e.expected}, found ${e.actual} at ${e.path}`)));if(f===null)return{key:e,scope:l,startMarker:i.startMarker,endMarker:i.endMarker,nodes:i.nodes};console.error(`[weft] hydrate: list item at ${c} diverged from server output (${f}); patching.`),yield*A.close(l,w.void);let p=yield*A.fork(a,`sequential`),m={...o,scope:p};K(i.startMarker,i.endMarker);let h=yield*W(d).pipe(C.provideService(s,m),C.provideService(A.Scope,p)),g=h===null?[]:Array.isArray(h)?h:[h],_=i.endMarker.parentNode;if(_!==null)for(let e of g)_.insertBefore(e,i.endMarker);return{key:e,scope:p,startMarker:i.startMarker,endMarker:i.endMarker,nodes:g}})}const Y=1,at=3,X=8;function ot(e,t){let n=document.createTreeWalker(e,128),r=t.current;for(let e=n.nextNode();e!==null;e=n.nextNode()){let t=e,n=i(t)??u(t)??g(t);n!==null&&n.id>r&&(r=n.id)}t.current=r}function st(e){let t=0,n=e.nextSibling;for(;n!==null;){if(n.nodeType===8){let e=i(n);if(e!==null)if(e.kind===`start`)t++;else if(t===0)return n;else t--}n=n.nextSibling}return null}function Z(e){if(e===null)return`end of children`;switch(e.nodeType){case 1:return`<${e.tagName.toLowerCase()}>`;case 3:return`text ${JSON.stringify(e.data)}`;case 8:return`comment ${JSON.stringify(e.data)}`;default:return`node(type ${e.nodeType})`}}function Q(e,t,n){return C.fail(new c({expected:e,actual:t,path:n}))}var ct=e({TypeId:()=>lt,dispose:()=>yt,errors:()=>vt,hydrate:()=>_t,make:()=>ht,mount:()=>gt});const lt=Symbol.for(`@weftui/dom/WeftApp`),ut=new WeakMap;function $(e){let t=ut.get(e);if(t===void 0)throw Error(`Expected a WeftApp created by WeftApp.make`);return t}function dt(e,t){return C.gen(function*(){e.subscribers===0&&(yield*N(C.logError(t.cause),C.annotateLogs(`weft.region`,t.region))),yield*O.publish(e.hub,t)})}function ft(e){return C.suspend(()=>$(e).disposed?C.die(Error(`Cannot mount on a disposed WeftApp`)):e.runtime.contextEffect)}function pt(e,t){return C.gen(function*(){let n=$(e),r=yield*A.fork(n.appScope,`sequential`),i=!1,a={element:t,unmount:()=>C.suspend(()=>i?C.void:(i=!0,A.close(r,w.void)))};return{context:{runtime:e.runtime,scope:r,rootScope:r,streamIdCounter:{current:0},reportUnhandled:(e,t)=>dt(n,{cause:e,region:t,root:a})},handle:a,rootScope:r}})}function mt(e,t){let n=ne.make(e??te.empty,t),r=C.runSync(O.unbounded()),i={[lt]:lt,runtime:n};return ut.set(i,{appScope:A.makeUnsafe(`sequential`),hub:r,subscribers:0,disposed:!1}),i}const ht=mt,gt=(e,t,n)=>C.gen(function*(){let r=yield*ft(e),{context:i,handle:a,rootScope:o}=yield*pt(e,n);n.innerHTML=``;let c=yield*N(W(t),C.setContext(N(r,x.add(s,i),x.add(A.Scope,o))),C.tapError(()=>A.close(o,w.void)));if(c!==null)if(Array.isArray(c))for(let e of c)n.appendChild(e);else n.appendChild(c);return a});function _t(e,t,n){return C.gen(function*(){let r=yield*ft(e),{context:i,handle:a,rootScope:o}=yield*pt(e,n),c=yield*Ge(),l={...i,hydrationReady:c};return ot(n,l.streamIdCounter),yield*N(q(t,n.firstChild,`root`),C.setContext(N(r,x.add(s,l),x.add(A.Scope,o))),C.tapError(()=>A.close(o,w.void))),yield*c.settle,yield*c.awaitReady,a})}const vt=e=>{let t=$(e);return j.unwrap(C.sync(()=>(t.subscribers++,N(j.fromPubSub(t.hub),j.ensuring(C.sync(()=>{t.subscribers--}))))))},yt=e=>C.suspend(()=>{let t=$(e);return t.disposed?C.void:(t.disposed=!0,N(A.close(t.appScope,w.void),C.andThen(e.runtime.disposeEffect),C.andThen(O.shutdown(t.hub))))});export{ct as WeftApp};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./rolldown-runtime-DK3Fl9T5.js";import{_ as t,b as n,h as r,i,v as a}from"./shared-Dz0KM9ku.js";import{Cause as o,Effect as s,Exit as c,Stream as l,pipe as u}from"effect";import{NoPropValue as d,Subscribable as f,isStream as p}from"@weftui/core";var m=e({cx:()=>C,merge:()=>h});function h(...e){return e.reduce((e,t)=>g(e,t),{})}function g(e,t){let n={...e};for(let[r,i]of Object.entries(t))n[r]=Object.hasOwn(e,r)?y(r,e[r],i):i;return n}function _(e){return p(e)||s.isEffect(e)||f.isSubscribable(e)}function v(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&!_(e)&&w(e)}function y(e,t,n){return e===`ref`?[...b(t),...b(n)]:e===`class`?k([t,n],`class`):e===`style`?v(t)&&v(n)?{...t,...n}:n:i(e)?typeof t==`function`&&typeof n==`function`?S(t,n):n??t:n}function b(e){return(Array.isArray(e)?e:[e]).filter(e=>e!=null)}function x(e,t){try{let n=e(t);return s.isEffect(n)?n:s.void}catch(e){return s.die(e)}}function S(e,t){return n=>{let r=x(e,n),i=x(t,n);return s.gen(function*(){let e=yield*s.exit(r),t=yield*s.exit(i);if(c.isFailure(e)&&c.isFailure(t))return yield*s.failCause(o.fromReasons([...e.cause.reasons,...t.cause.reasons]));if(c.isFailure(e))return yield*s.failCause(e.cause);if(c.isFailure(t))return yield*s.failCause(t.cause)})}}function C(...e){return k(e)}function w(e){let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function T(e,t){for(let n of e)if(!(n===!1||n==null)){if(typeof n==`string`){n!==``&&t.push({kind:`static`,text:n});continue}if(Array.isArray(n)){T(n,t);continue}if(_(n)){t.push({kind:`value`,source:n});continue}if(w(n))for(let[e,r]of Object.entries(n))_(r)?t.push({kind:`toggle`,name:e,source:r}):r&&t.push({kind:`static`,text:e})}}function E(e,t){let n=[],r=0;for(let i of e){if(i.kind===`static`){n.push(i.text);continue}let e=t[r];r+=1,i.kind===`value`?typeof e==`string`&&e!==``&&n.push(e):e&&n.push(i.name)}return n.join(` `)}function D(e,t){return l.suspend(()=>{let n=!1;return u(e,l.tap(()=>s.sync(()=>{n=!0})),l.concat(l.suspend(()=>n?l.empty:l.fail(new d({key:t})))))})}function O(e,t){if(p(e))return D(e,t);if(s.isEffect(e))return l.fromEffect(e);let n=e;return l.concat(l.fromEffect(n.get),n.changes)}function k(e,t){let n=[];T(e,n);let r=n.filter(e=>e.kind!==`static`);if(r.length===0)return E(n,[]);let i=r.map(e=>O(e.source,t));return u(l.zipLatestAll(...i),l.map(e=>E(n,e)))}export{r as HydrationMismatchError,m as Props,t as RenderError,a as StreamSubscriptionError,n as UnsupportedNodeTypeError};
1
+ import{t as e}from"./rolldown-runtime-DK3Fl9T5.js";import{_ as t,b as n,h as r,i,v as a}from"./shared-Dz0KM9ku.js";import{Cause as o,Effect as s,Exit as c,Stream as l,pipe as u}from"effect";import{NoPropValue as d,Subscribable as f,isStream as p}from"@weftui/core";var m=e({cx:()=>C,merge:()=>h});function h(...e){return e.reduce((e,t)=>g(e,t),{})}function g(e,t){let n={...e};for(let[r,i]of Object.entries(t))n[r]=Object.hasOwn(e,r)?y(r,e[r],i):i;return n}function _(e){return p(e)||s.isEffect(e)||f.isSubscribable(e)}function v(e){return typeof e==`object`&&!!e&&!Array.isArray(e)&&!_(e)&&w(e)}function y(e,t,n){return e===`ref`?[...b(t),...b(n)]:e===`class`?k([t,n],`class`):e===`style`?v(t)&&v(n)?{...t,...n}:n:i(e)?typeof t==`function`&&typeof n==`function`?S(t,n):n??t:n}function b(e){return(Array.isArray(e)?e:[e]).filter(e=>e!=null)}function x(e,t){try{let n=e(t);return s.isEffect(n)?n:s.void}catch(e){return s.die(e)}}function S(e,t){return n=>{let r=x(e,n),i=x(t,n);return s.gen(function*(){let e=yield*s.exit(r),t=yield*s.exit(i);if(c.isFailure(e)&&c.isFailure(t))return yield*s.failCause(o.fromReasons([...e.cause.reasons,...t.cause.reasons]));if(c.isFailure(e))return yield*s.failCause(e.cause);if(c.isFailure(t))return yield*s.failCause(t.cause)})}}function C(...e){return k(e)}function w(e){let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function T(e,t){for(let n of e)if(!(n===!1||n==null)){if(typeof n==`string`){n!==``&&t.push({kind:`static`,text:n});continue}if(Array.isArray(n)){T(n,t);continue}if(_(n)){t.push({kind:`value`,source:n});continue}if(w(n))for(let[e,r]of Object.entries(n))_(r)?t.push({kind:`toggle`,name:e,source:r}):r&&t.push({kind:`static`,text:e})}}function E(e,t){let n=[],r=0;for(let i of e){if(i.kind===`static`){n.push(i.text);continue}let e=t[r];r+=1,i.kind===`value`?typeof e==`string`&&e!==``&&n.push(e):e&&n.push(i.name)}return n.join(` `)}function D(e,t){return l.suspend(()=>{let n=!1;return u(e,l.tap(()=>s.sync(()=>{n=!0})),l.concat(l.suspend(()=>n?l.empty:l.fail(new d({key:t})))))})}function O(e,t){if(p(e))return D(e,t);if(s.isEffect(e))return l.fromEffect(e);let n=e;return l.concat(l.fromEffect(f.get(n)),f.changes(n))}function k(e,t){let n=[];T(e,n);let r=n.filter(e=>e.kind!==`static`);if(r.length===0)return E(n,[]);let i=r.map(e=>O(e.source,t));return u(l.zipLatestAll(...i),l.map(e=>E(n,e)))}export{r as HydrationMismatchError,m as Props,t as RenderError,a as StreamSubscriptionError,n as UnsupportedNodeTypeError};
@@ -1 +1 @@
1
- import{a as e,b as t,d as n,f as r,i,o as a,p as o,t as s,u as c}from"../shared-Dz0KM9ku.js";import{n as l,t as u}from"../boundary-replay-BY4GyLot.js";import{Cause as d,Context as f,Effect as p,Exit as m,Option as h,Queue as g,Ref as _,Schema as v,Scope as y,Stream as b}from"effect";import{AppRpcClientTag as ee,FAILURE_BOUNDARY as x,FRAGMENT as S,LIST as C,SERVER_BOUNDARY as w,SUSPENSE_BOUNDARY as T,Source as te,Subscribable as E,getElementDescriptor as D,isStream as O,toStream as k}from"@weftui/core";const A=new Set([`area`,`base`,`br`,`col`,`embed`,`hr`,`img`,`input`,`link`,`meta`,`param`,`source`,`track`,`wbr`]),j={'"':`&quot;`,"&":`&amp;`,"'":`&#x27;`,"<":`&lt;`,">":`&gt;`};function M(e){return e.replace(/["'&<>]/g,e=>j[e]??e)}const N=new Set([38,60,62,8232,8233]);function P(e){let t=JSON.stringify(e),n=``;for(let e=0;e<t.length;e++){let r=t.charCodeAt(e);N.has(r)?n+=`\\u${r.toString(16).padStart(4,`0`)}`:n+=t[e]}return n}function F(e){return e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}function I(e){return p.gen(function*(){let t=``;for(let[n,r]of Object.entries(e))if(!(n===`children`||n===`ref`||i(n))){if(n===`style`){t+=yield*R(r);continue}t+=yield*ne(n,r)}return t})}function L(e){return O(e)||p.isEffect(e)?k(e).pipe(b.runHead,p.map(h.getOrElse(()=>void 0))):p.succeed(e)}function ne(e,t){return p.gen(function*(){let n=yield*L(t);return n==null?``:typeof n==`boolean`?n?` ${e}=""`:``:` ${e}="${M(String(n))}"`})}function R(e){return p.gen(function*(){let t=yield*L(e);if(t==null)return``;if(typeof t==`string`)return t===``?``:` style="${M(t)}"`;if(typeof t==`object`){let e=[];for(let[n,r]of Object.entries(t)){let t=yield*L(r);t!=null&&e.push(`${F(n)}: ${String(t)}`)}return e.length===0?``:` style="${M(e.join(`; `))}"`}return``})}var z=class extends f.Service()(`@weftui/dom/SuspenseFailureHandler`){};function B(e,t,n=!1,i){let a=o(e),c=r(e),l=n?`var m=document.createElement("meta");m.setAttribute("name","robots");m.setAttribute("content","noindex");document.head.appendChild(m);`:``,u=i!==void 0,d=u?`<script type="application/json" ${s}>`+P({error:i})+`<\/script>`+t:t,f=u?``:`p.removeChild(s);p.removeChild(e);`;return`<template id="ef-s-${e}">${d}</template><script>(function(){`+l+`var w=document.createTreeWalker(document,128),s,e;while(w.nextNode()){var d=w.currentNode.data;if(d==="${a}")s=w.currentNode;if(d==="${c}"){e=w.currentNode;break;}}if(!s||!e)return;var p=s.parentNode,c=s.nextSibling,n;while(c&&c!==e){n=c.nextSibling;p.removeChild(c);c=n;}var t=document.getElementById("ef-s-${e}");p.insertBefore(t.content,e);`+f+`t.remove();document.currentScript.remove();})();<\/script>`}function V(e,t,n){return b.unwrap(p.gen(function*(){let i=++t.idCounter.current;yield*_.update(t.pendingCount,e=>e+1);let a=e.children===void 0?null:(Array.isArray(e.children),e.children),s=p.gen(function*(){let e=yield*b.mkString(n(a));yield*g.offer(t.patchQueue,h.some(B(i,e)))}).pipe(p.catchCause(e=>d.hasInterruptsOnly(e)?p.failCause(e):p.gen(function*(){let r=yield*p.serviceOption(z);if(h.isNone(r))return;let a=r.value.handle(e);if(h.isNone(a))return;let o=yield*b.mkString(n(a.value.content));yield*g.offer(t.patchQueue,h.some(B(i,o,a.value.markNoindex,a.value.failureReplay)))})),p.ensuring(_.updateAndGet(t.pendingCount,e=>e-1).pipe(p.flatMap(e=>e<=0?g.offer(t.patchQueue,h.none()).pipe(p.asVoid):p.void))),p.ignore);yield*p.forkIn(s,t.scope);let c=`<!--${o(i)}-->`,l=`<!--${r(i)}-->`,u=e.fallback??null;return b.make(c).pipe(b.concat(n(u)),b.concat(b.make(l)))}))}function H(e,t,n){let r=e.children.length===0?null:e.children.length===1?e.children[0]:e.children;return b.unwrap(p.gen(function*(){let i=yield*b.mkString(n(r)).pipe(p.catchCause(r=>p.gen(function*(){let i=e.match(r);if(i===null)return yield*p.failCause(r);let a=yield*b.mkString(n(i));if(t===null)return a;let o=yield*_.getAndSet(t,h.none());return h.isNone(o)?a:`<script type="application/json" ${u}>${P({index:l(e.children).indexOf(o.value.owner),error:o.value.encoded})}<\/script>`+a})));return b.make(i)}))}function re(e,t,n){if(t===null)return p.failCause(n);let r=d.findErrorOption(n);return h.isNone(r)?p.failCause(n):v.encodeEffect(e.errorSchema)(r.value).pipe(p.flatMap(n=>_.set(t,h.some({owner:e,encoded:n}))),p.matchCauseEffect({onFailure:()=>p.failCause(n),onSuccess:()=>p.failCause(n)}))}function ie(e){return{value:E.make({get:p.succeed(e),changes:b.make(e)}),refetch:p.void,pending:E.make({get:p.succeed(!1),changes:b.make(!1)}),error:E.make({get:p.succeed(h.none()),changes:b.make(h.none())})}}function U(e,t,n,r){return b.unwrap(p.gen(function*(){let i=yield*(yield*ee).call(e.tag,e.payload()).pipe(p.catchCause(t=>re(e,n,t))),a=r(e.render(ie(i)));if(!t)return a;let o=`<script type="application/json">${P(yield*v.encodeEffect(e.successSchema)(i))}<\/script>`;return b.make(o).pipe(b.concat(a))}))}function W(e){return p.scoped(te.toSubscribable(e).pipe(p.flatMap(e=>e.get),p.map(e=>Array.from(e)),p.catchTag(`NoPropValue`,()=>p.succeed([]))))}function G(e,n){if(e==null||typeof e==`boolean`)return b.empty;if(typeof e==`string`||typeof e==`number`||typeof e==`bigint`)return b.make(M(String(e)));if(O(e)||p.isEffect(e)){let t=D(e);if(t!==void 0)return G(t,n);if(p.isEffect(e)){let t=p.runSyncExit(e);if(m.isSuccess(t))return G(t.value,n)}return k(e).pipe(b.runHead,p.map(h.match({onNone:()=>b.empty,onSome:e=>G(e,n)})),b.unwrap)}if(typeof e==`object`&&Symbol.iterator in e&&!(`type`in e))return b.flatMap(b.fromIterable(e),e=>G(e,n));if(typeof e==`object`&&`type`in e&&!(Symbol.iterator in e)){let{type:t,props:r}=e;if(t===S)return q(r,n);if(t===T){let e=r;return n===null?G(e.fallback??null,null):V(e,n,e=>G(e,n))}if(t===x)return H(r,null,e=>G(e,n));if(t===w)return U(r,!1,null,e=>G(e,n));if(t===C)return K(r,n);if(typeof t==`string`){let e=b.fromEffect(I(r).pipe(p.map(e=>`<${t}${e}>`)));return A.has(t)?e:e.pipe(b.concat(q(r,n)),b.concat(b.make(`</${t}>`)))}if(typeof t==`function`)return G(t(r),n)}return b.fail(new t({type:e.type,message:`Invalid Renderable type: expected string, FRAGMENT, or function, got ${typeof e.type}`}))}function K(e,t){return b.unwrap(p.gen(function*(){let n=yield*W(e.of),r=b.empty;return n.forEach((n,i)=>{r=r.pipe(b.concat(G(e.render(n,i),t)))}),r}))}function q(e,t){let n=`children`in e?e.children:void 0;if(n==null)return b.empty;let r=Array.isArray(n)?n:[n];return b.flatMap(b.fromIterable(r),e=>G(e,t))}function J(e,r,i){if(e==null||typeof e==`boolean`)return b.empty;if(typeof e==`string`||typeof e==`number`||typeof e==`bigint`)return b.make(M(String(e)));if(O(e)||p.isEffect(e)){let t=D(e);if(t!==void 0)return J(t,r,i);if(p.isEffect(e)){let t=p.runSyncExit(e);if(m.isSuccess(t))return J(t.value,r,i)}return k(e).pipe(b.runHead,p.map(e=>{let t=++r.current,a=h.match(e,{onNone:()=>b.empty,onSome:e=>J(e,r,i)});return b.make(`<!--${n(t)}-->`).pipe(b.concat(a),b.concat(b.make(`<!--${c(t)}-->`)))}),b.unwrap)}if(typeof e==`object`&&Symbol.iterator in e&&!(`type`in e))return b.flatMap(b.fromIterable(e),e=>J(e,r,i));if(typeof e==`object`&&`type`in e&&!(Symbol.iterator in e)){let{type:t,props:n}=e;if(t===S)return Y(n,r,i);if(t===T){let e=n;return i===null?J(e.fallback??null,r,null):V(e,i,e=>J(e,r,i))}if(t===x)return H(n,i?.failureCollector??null,e=>J(e,r,i));if(t===w)return U(n,!0,i?.failureCollector??null,e=>J(e,r,i));if(t===C)return ae(n,r,i);if(typeof t==`string`){let e=b.fromEffect(I(n).pipe(p.map(e=>`<${t}${e}>`)));return A.has(t)?e:e.pipe(b.concat(Y(n,r,i)),b.concat(b.make(`</${t}>`)))}if(typeof t==`function`)return J(t(n),r,i)}return b.fail(new t({type:e.type,message:`Invalid Renderable type: expected string, FRAGMENT, or function, got ${typeof e.type}`}))}function ae(t,r,i){return b.unwrap(p.gen(function*(){let o=++r.current,s=yield*W(t.of),l=b.empty;return s.forEach((n,o)=>{let s=++r.current;l=l.pipe(b.concat(b.make(`<!--${a(s)}-->`)),b.concat(J(t.render(n,o),r,i)),b.concat(b.make(`<!--${e(s)}-->`)))}),b.make(`<!--${n(o)}-->`).pipe(b.concat(l),b.concat(b.make(`<!--${c(o)}-->`)))}))}function Y(e,t,n){let r=`children`in e?e.children:void 0;if(r==null)return b.empty;let i=Array.isArray(r)?r:[r];return b.flatMap(b.fromIterable(i),e=>J(e,t,n))}const X=e=>G(e,null),oe=e=>b.unwrap(p.gen(function*(){let t=yield*g.unbounded(),n=yield*_.make(0),r=G(e,{patchQueue:t,pendingCount:n,idCounter:{current:0},scope:yield*p.scope,failureCollector:null}).pipe(b.ensuring(_.get(n).pipe(p.flatMap(e=>e===0?g.offer(t,h.none()).pipe(p.asVoid):p.void))));return b.concat(r,Z(t))})),Z=e=>b.fromQueue(e).pipe(b.takeWhile(h.isSome),b.map(e=>e.value)),Q=(e,t)=>p.gen(function*(){let n=yield*g.unbounded();yield*y.addFinalizer(t,p.asVoid(g.offer(n,h.none())));let r=yield*_.make(0);return{mainStream:J(e,{current:0},{patchQueue:n,pendingCount:r,idCounter:{current:0},scope:t,failureCollector:yield*_.make(h.none())}).pipe(b.ensuring(_.get(r).pipe(p.flatMap(e=>e===0?g.offer(n,h.none()).pipe(p.asVoid):p.void)))),patches:Z(n)}}),$=e=>b.unwrap(p.gen(function*(){let t=yield*p.scope,{mainStream:n,patches:r}=yield*Q(e,t);return b.concat(n,r)})),se=e=>X(e).pipe(b.mkString),ce=e=>$(e).pipe(b.mkString),le=e=>p.gen(function*(){let t=yield*p.scope,n=yield*y.fork(t,`sequential`),{mainStream:r,patches:i}=yield*Q(e,n);return{shell:yield*b.mkString(r).pipe(p.onError(e=>y.close(n,m.failCause(e)))),patches:i}});export{z as SuspenseFailureHandlerTag,le as renderToHydratableShell,oe as renderToStream,$ as renderToStreamHydratable,se as renderToString,ce as renderToStringHydratable};
1
+ import{a as e,b as t,d as n,f as r,i,o as a,p as o,t as s,u as c}from"../shared-Dz0KM9ku.js";import{n as l,t as u}from"../boundary-replay-BY4GyLot.js";import{Cause as d,Context as f,Effect as p,Exit as m,Option as h,Queue as g,Ref as _,Schema as v,Scope as y,Stream as b}from"effect";import{AppRpcClientTag as x,FAILURE_BOUNDARY as S,FRAGMENT as C,LIST as w,SERVER_BOUNDARY as T,SUSPENSE_BOUNDARY as E,Source as D,Subscribable as O,getElementDescriptor as k,isStream as A,toStream as j}from"@weftui/core";const M=new Set([`area`,`base`,`br`,`col`,`embed`,`hr`,`img`,`input`,`link`,`meta`,`param`,`source`,`track`,`wbr`]),N={'"':`&quot;`,"&":`&amp;`,"'":`&#x27;`,"<":`&lt;`,">":`&gt;`};function P(e){return e.replace(/["'&<>]/g,e=>N[e]??e)}const ee=new Set([38,60,62,8232,8233]);function F(e){let t=JSON.stringify(e),n=``;for(let e=0;e<t.length;e++){let r=t.charCodeAt(e);ee.has(r)?n+=`\\u${r.toString(16).padStart(4,`0`)}`:n+=t[e]}return n}function I(e){return e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}function L(e){return p.gen(function*(){let t=``;for(let[n,r]of Object.entries(e))if(!(n===`children`||n===`ref`||i(n))){if(n===`style`){t+=yield*z(r);continue}t+=yield*te(n,r)}return t})}function R(e){return A(e)||p.isEffect(e)?j(e).pipe(b.runHead,p.map(h.getOrElse(()=>void 0))):p.succeed(e)}function te(e,t){return p.gen(function*(){let n=yield*R(t);return n==null?``:typeof n==`boolean`?n?` ${e}=""`:``:` ${e}="${P(String(n))}"`})}function z(e){return p.gen(function*(){let t=yield*R(e);if(t==null)return``;if(typeof t==`string`)return t===``?``:` style="${P(t)}"`;if(typeof t==`object`){let e=[];for(let[n,r]of Object.entries(t)){let t=yield*R(r);t!=null&&e.push(`${I(n)}: ${String(t)}`)}return e.length===0?``:` style="${P(e.join(`; `))}"`}return``})}var B=class extends f.Service()(`@weftui/dom/SuspenseFailureHandler`){};function V(e,t,n=!1,i){let a=o(e),c=r(e),l=n?`var m=document.createElement("meta");m.setAttribute("name","robots");m.setAttribute("content","noindex");document.head.appendChild(m);`:``,u=i!==void 0,d=u?`<script type="application/json" ${s}>`+F({error:i})+`<\/script>`+t:t,f=u?``:`p.removeChild(s);p.removeChild(e);`;return`<template id="ef-s-${e}">${d}</template><script>(function(){`+l+`var w=document.createTreeWalker(document,128),s,e;while(w.nextNode()){var d=w.currentNode.data;if(d==="${a}")s=w.currentNode;if(d==="${c}"){e=w.currentNode;break;}}if(!s||!e)return;var p=s.parentNode,c=s.nextSibling,n;while(c&&c!==e){n=c.nextSibling;p.removeChild(c);c=n;}var t=document.getElementById("ef-s-${e}");p.insertBefore(t.content,e);`+f+`t.remove();document.currentScript.remove();})();<\/script>`}function H(e,t,n){return b.unwrap(p.gen(function*(){let i=++t.idCounter.current;yield*_.update(t.pendingCount,e=>e+1);let a=e.children===void 0?null:(Array.isArray(e.children),e.children),s=p.gen(function*(){let e=yield*b.mkString(n(a));yield*g.offer(t.patchQueue,h.some(V(i,e)))}).pipe(p.catchCause(e=>d.hasInterruptsOnly(e)?p.failCause(e):p.gen(function*(){let r=yield*p.serviceOption(B);if(h.isNone(r))return;let a=r.value.handle(e);if(h.isNone(a))return;let o=yield*b.mkString(n(a.value.content));yield*g.offer(t.patchQueue,h.some(V(i,o,a.value.markNoindex,a.value.failureReplay)))})),p.ensuring(_.updateAndGet(t.pendingCount,e=>e-1).pipe(p.flatMap(e=>e<=0?g.offer(t.patchQueue,h.none()).pipe(p.asVoid):p.void))),p.ignore);yield*p.forkIn(s,t.scope);let c=`<!--${o(i)}-->`,l=`<!--${r(i)}-->`,u=e.fallback??null;return b.make(c).pipe(b.concat(n(u)),b.concat(b.make(l)))}))}function U(e,t,n){let r=e.children.length===0?null:e.children.length===1?e.children[0]:e.children;return b.unwrap(p.gen(function*(){let i=yield*b.mkString(n(r)).pipe(p.catchCause(r=>p.gen(function*(){let i=e.match(r);if(i===null)return yield*p.failCause(r);let a=yield*b.mkString(n(i));if(t===null)return a;let o=yield*_.getAndSet(t,h.none());return h.isNone(o)?a:`<script type="application/json" ${u}>${F({index:l(e.children).indexOf(o.value.owner),error:o.value.encoded})}<\/script>`+a})));return b.make(i)}))}function ne(e,t,n){if(t===null)return p.failCause(n);let r=d.findErrorOption(n);return h.isNone(r)?p.failCause(n):v.encodeEffect(e.errorSchema)(r.value).pipe(p.flatMap(n=>_.set(t,h.some({owner:e,encoded:n}))),p.matchCauseEffect({onFailure:()=>p.failCause(n),onSuccess:()=>p.failCause(n)}))}function re(e){return{value:O.make({get:p.succeed(e),changes:b.make(e)}),refetch:p.void,pending:O.make({get:p.succeed(!1),changes:b.make(!1)}),error:O.make({get:p.succeed(h.none()),changes:b.make(h.none())})}}function W(e,t,n,r){return b.unwrap(p.gen(function*(){let i=yield*(yield*x).call(e.tag,e.payload()).pipe(p.catchCause(t=>ne(e,n,t))),a=r(e.render(re(i)));if(!t)return a;let o=`<script type="application/json">${F(yield*v.encodeEffect(e.successSchema)(i))}<\/script>`;return b.make(o).pipe(b.concat(a))}))}function G(e){return p.scoped(D.toSubscribable(e).pipe(p.flatMap(e=>O.get(e)),p.map(e=>Array.from(e)),p.catchTag(`NoPropValue`,()=>p.succeed([]))))}function K(e,n){if(e==null||typeof e==`boolean`)return b.empty;if(typeof e==`string`||typeof e==`number`||typeof e==`bigint`)return b.make(P(String(e)));if(A(e)||p.isEffect(e)){let t=k(e);if(t!==void 0)return K(t,n);if(p.isEffect(e)){let t=p.runSyncExit(e);if(m.isSuccess(t))return K(t.value,n)}return j(e).pipe(b.runHead,p.map(h.match({onNone:()=>b.empty,onSome:e=>K(e,n)})),b.unwrap)}if(typeof e==`object`&&Symbol.iterator in e&&!(`type`in e))return b.flatMap(b.fromIterable(e),e=>K(e,n));if(typeof e==`object`&&`type`in e&&!(Symbol.iterator in e)){let{type:t,props:r}=e;if(t===C)return J(r,n);if(t===E){let e=r;return n===null?K(e.fallback??null,null):H(e,n,e=>K(e,n))}if(t===S)return U(r,null,e=>K(e,n));if(t===T)return W(r,!1,null,e=>K(e,n));if(t===w)return q(r,n);if(typeof t==`string`){let e=b.fromEffect(L(r).pipe(p.map(e=>`<${t}${e}>`)));return M.has(t)?e:e.pipe(b.concat(J(r,n)),b.concat(b.make(`</${t}>`)))}if(typeof t==`function`)return K(t(r),n)}return b.fail(new t({type:e.type,message:`Invalid Renderable type: expected string, FRAGMENT, or function, got ${typeof e.type}`}))}function q(e,t){return b.unwrap(p.gen(function*(){let n=yield*G(e.of),r=b.empty;return n.forEach((n,i)=>{r=r.pipe(b.concat(K(e.render(n,i),t)))}),r}))}function J(e,t){let n=`children`in e?e.children:void 0;if(n==null)return b.empty;let r=Array.isArray(n)?n:[n];return b.flatMap(b.fromIterable(r),e=>K(e,t))}function Y(e,r,i){if(e==null||typeof e==`boolean`)return b.empty;if(typeof e==`string`||typeof e==`number`||typeof e==`bigint`)return b.make(P(String(e)));if(A(e)||p.isEffect(e)){let t=k(e);if(t!==void 0)return Y(t,r,i);if(p.isEffect(e)){let t=p.runSyncExit(e);if(m.isSuccess(t))return Y(t.value,r,i)}return j(e).pipe(b.runHead,p.map(e=>{let t=++r.current,a=h.match(e,{onNone:()=>b.empty,onSome:e=>Y(e,r,i)});return b.make(`<!--${n(t)}-->`).pipe(b.concat(a),b.concat(b.make(`<!--${c(t)}-->`)))}),b.unwrap)}if(typeof e==`object`&&Symbol.iterator in e&&!(`type`in e))return b.flatMap(b.fromIterable(e),e=>Y(e,r,i));if(typeof e==`object`&&`type`in e&&!(Symbol.iterator in e)){let{type:t,props:n}=e;if(t===C)return X(n,r,i);if(t===E){let e=n;return i===null?Y(e.fallback??null,r,null):H(e,i,e=>Y(e,r,i))}if(t===S)return U(n,i?.failureCollector??null,e=>Y(e,r,i));if(t===T)return W(n,!0,i?.failureCollector??null,e=>Y(e,r,i));if(t===w)return ie(n,r,i);if(typeof t==`string`){let e=b.fromEffect(L(n).pipe(p.map(e=>`<${t}${e}>`)));return M.has(t)?e:e.pipe(b.concat(X(n,r,i)),b.concat(b.make(`</${t}>`)))}if(typeof t==`function`)return Y(t(n),r,i)}return b.fail(new t({type:e.type,message:`Invalid Renderable type: expected string, FRAGMENT, or function, got ${typeof e.type}`}))}function ie(t,r,i){return b.unwrap(p.gen(function*(){let o=++r.current,s=yield*G(t.of),l=b.empty;return s.forEach((n,o)=>{let s=++r.current;l=l.pipe(b.concat(b.make(`<!--${a(s)}-->`)),b.concat(Y(t.render(n,o),r,i)),b.concat(b.make(`<!--${e(s)}-->`)))}),b.make(`<!--${n(o)}-->`).pipe(b.concat(l),b.concat(b.make(`<!--${c(o)}-->`)))}))}function X(e,t,n){let r=`children`in e?e.children:void 0;if(r==null)return b.empty;let i=Array.isArray(r)?r:[r];return b.flatMap(b.fromIterable(i),e=>Y(e,t,n))}const ae=e=>K(e,null),oe=e=>b.unwrap(p.gen(function*(){let t=yield*g.unbounded(),n=yield*_.make(0),r=K(e,{patchQueue:t,pendingCount:n,idCounter:{current:0},scope:yield*p.scope,failureCollector:null}).pipe(b.ensuring(_.get(n).pipe(p.flatMap(e=>e===0?g.offer(t,h.none()).pipe(p.asVoid):p.void))));return b.concat(r,Z(t))})),Z=e=>b.fromQueue(e).pipe(b.takeWhile(h.isSome),b.map(e=>e.value)),Q=(e,t)=>p.gen(function*(){let n=yield*g.unbounded();yield*y.addFinalizer(t,p.asVoid(g.offer(n,h.none())));let r=yield*_.make(0);return{mainStream:Y(e,{current:0},{patchQueue:n,pendingCount:r,idCounter:{current:0},scope:t,failureCollector:yield*_.make(h.none())}).pipe(b.ensuring(_.get(r).pipe(p.flatMap(e=>e===0?g.offer(n,h.none()).pipe(p.asVoid):p.void)))),patches:Z(n)}}),$=e=>b.unwrap(p.gen(function*(){let t=yield*p.scope,{mainStream:n,patches:r}=yield*Q(e,t);return b.concat(n,r)})),se=e=>ae(e).pipe(b.mkString),ce=e=>$(e).pipe(b.mkString),le=e=>p.gen(function*(){let t=yield*p.scope,n=yield*y.fork(t,`sequential`),{mainStream:r,patches:i}=yield*Q(e,n);return{shell:yield*b.mkString(r).pipe(p.onError(e=>y.close(n,m.failCause(e)))),patches:i}});export{B as SuspenseFailureHandlerTag,le as renderToHydratableShell,oe as renderToStream,$ as renderToStreamHydratable,se as renderToString,ce as renderToStringHydratable};
@@ -81,13 +81,13 @@ On the server, `renderToStreamHydratable` emits the fallback inline and appends
81
81
  Conceptually it is the same idea as the other boundaries: a node that decides what renders in a subtree. But the thing it intercepts is a **round-trip to a server handler**. Instead of a children array, it takes a `render` function that receives a reactive [`Resource`](https://weftui.dev/docs/reference/core#resourcea).
82
82
 
83
83
  ```typescript
84
- import { Boundary, h } from "@weftui/core";
84
+ import { Boundary, h, Subscribable } from "@weftui/core";
85
85
  import { Stream } from "effect";
86
86
 
87
87
  Boundary.rpc(
88
88
  GetStock,
89
89
  () => ({ id: productId }),
90
- (resource) => h.span([Stream.map(resource.value.changes, (s) => String(s.units))]),
90
+ (resource) => h.span([Stream.map(Subscribable.changes(resource.value), (s) => String(s.units))]),
91
91
  { fallback: h.p("loading…") },
92
92
  );
93
93
  ```
@@ -9,10 +9,10 @@ description: "@weftui/router: universal nested routing, Router.route / Router.la
9
9
 
10
10
  `@weftui/router` is a universal (server + client) nested router for Weft. It maps a URL to a rendered `Node` tree on both sides:
11
11
 
12
- - **Server**: matches an incoming request path, renders the matched nested page to hydratable HTML, and responds with `text/html` (HTTP 404 for not-found).
13
- - **Client**: matches `window.location`, swaps pages reactively via the History API, and keeps unchanged ancestor layouts mounted across navigations.
12
+ - **Server**: matches an incoming request path, renders to hydratable HTML.
13
+ - **Client**: matches reactively via the History API.
14
14
 
15
- The package mirrors `@weftui/dom`: a shared (universal) root, a `./client` entry, and a `./server` entry.
15
+ The package exports a shared (universal) root, a `./client` entry, and a `./server` entry.
16
16
 
17
17
  ```bash
18
18
  npm install @weftui/router
@@ -20,9 +20,22 @@ npm install @weftui/router
20
20
 
21
21
  ## The mental model
22
22
 
23
- A route's **component is its handler**. A page is a component that renders, and its `component` slot is invoked at render time on whichever side the request arrives. Server-resolved data stays with [`Boundary.rpc`](https://weftui.dev/docs/how-to/load-data-with-rpc); client-side async stays with `Boundary.suspend`.
23
+ A route's **component is its handler**. A page is a component that renders, and its `component` slot is invoked at render time.
24
24
 
25
- You author an **explicit nested route tree** with three namespaced combinators (mirroring the `h.div` / `Component.gen` / `Boundary.catchTag` surface) and seal it once:
25
+ ```typescript
26
+ const homeRoute = Router.route("", { component: Home });
27
+ const aboutRoute = Router.route("about", { component: About });
28
+ const userRoute = Router.route("users/:id", {
29
+ path: { id: Schema.NumberFromString },
30
+ component: ({ path }) => h.h1(`User ${path.id}`),
31
+ });
32
+
33
+ const App = Router.router(Router.layout({ component: Shell }, [homeRoute, aboutRoute, userRoute]), {
34
+ notFound: () => h.h1("404"),
35
+ });
36
+ ```
37
+
38
+ You author a **nested route tree** with namespaced combinators and seal it once:
26
39
 
27
40
  | Combinator | Builds |
28
41
  | ----------------------------------------------------- | ---------------------------------------------------------------- |
@@ -34,7 +47,7 @@ The tree is the source of truth. The same sealed `RouterDef` drives both server
34
47
 
35
48
  ## Authoring routes
36
49
 
37
- Every `component` slot is a **`ComponentSlot`**: a callable producing a `Node`, passed **uncalled**. Use [`Component.make` / `Component.gen`](https://weftui.dev/docs/how-to/author-components) (or a plain `() => Node` thunk). The router invokes it at render time, which lets `href(…)` resolve after the tree is compiled.
50
+ Every **`ComponentSlot`** produces a `Node` when called. Use [`Component.make` / `Component.gen`](https://weftui.dev/docs/how-to/author-components) (or a plain `() => Node` thunk). The router invokes it at render time, which lets `href(…)` resolve after the tree is compiled.
38
51
 
39
52
  ```typescript
40
53
  import { Component, h } from "@weftui/core";
@@ -54,10 +67,13 @@ const User = Router.route("users/:id", {
54
67
  });
55
68
  ```
56
69
 
57
- - **`segment`** is relative to the parent and may contain `:name` path-param placeholders (e.g. `"users/:id"`). A leading/trailing `/` is tolerated. Each leaf carries its full relative path (e.g. `"users/:id/settings"`).
58
- - **`path` / `query`** are `Schema.Struct.Fields` (a record of `name → Schema`), declared **only on routes**. The compiler covers every `:name` placeholder in `pathSchema`, defaulting to `Schema.String` when a placeholder has no declared field. Query fields are optional by default.
70
+ - **`segment`** is relative to the parent and may contain `:name` path-param placeholders (e.g. `"users/:id"`). A leading/trailing `/` is tolerated.
71
+
72
+ Each leaf carries its full relative path (e.g. `"users/:id/settings"`).
59
73
 
60
- > Authoring components with `Component.make` / `Component.gen` keeps every slot fully typed: the router never sees a `Node<any, any>`. Each component's `E`/`R` channels aggregate up through `Router.layout` / `Router.router` into the sealed `RouterDef`.
74
+ **`path` / `query`** are `Schema.Struct.Fields` (a record of `name → Schema`), declared **only on routes**. The compiler covers every `:name` placeholder in `pathSchema`, defaulting to `Schema.String` when a placeholder has no declared field. Query fields are optional by default.
75
+
76
+ > Authoring components with `Component.make` / `Component.gen` keeps every slot fully typed: Each component's `E`/`R` channels aggregate up through `Router.layout` / `Router.router` into the sealed `RouterDef`.
61
77
 
62
78
  ## Reading the match: handler-arg props vs. injection
63
79
 
@@ -97,9 +113,29 @@ const UserShell = Component.gen(function* () {
97
113
 
98
114
  `Router.params(fields)` / `Router.query(fields)` read the live match and pick the requested `fields` keys (already decoded by the matcher, so no re-validation). They return the typed values. When no route matches, they fail with a tagged [`RouterParamsError`](#errors) carrying `source: "path" | "query"` and the requested `keys`.
99
115
 
100
- That error bubbles into the app node's aggregate `E`, so a user may recover it with `Boundary.catchTag("RouterParamsError", …)`.
116
+ That error bubbles into the app node's aggregate `E`, so a user may recover it with `Boundary.catchTag(…)`.
117
+
118
+ ### Reactive accessors: `paramsStream` / `queryStream`
119
+
120
+ `Router.paramsStream(fields)` / `Router.queryStream(fields)` are the reactive counterparts of `params` / `query`. Each resolves a `Subscribable` derived from `Subscribable.changes(currentMatch)`, so a component can update **in place** even when the same leaf stays mounted, the case a query-only navigation (`setQuery` / `patchQuery`, see [Programmatic navigation](#programmatic-navigation)) produces and a snapshot `Router.query` would miss:
121
+
122
+ ```typescript
123
+ import { Component, h, Subscribable } from "@weftui/core";
124
+ import { Router } from "@weftui/router";
125
+ import { Schema, Stream } from "effect";
126
+
127
+ const sortQuery = { sort: Schema.optional(Schema.String) };
128
+
129
+ const ProductsPage = Component.gen(function* () {
130
+ const query = yield* Router.queryStream(sortQuery);
131
+ return yield* h.section([
132
+ h.h2("Products"),
133
+ h.p(["sort: ", Stream.map(Subscribable.changes(query), (q) => q.sort ?? "none")]),
134
+ ]);
135
+ });
136
+ ```
101
137
 
102
- > **Reactive accessors.** `Router.paramsStream(fields)` / `Router.queryStream(fields)` are the reactive counterparts. Each resolves a `Subscribable` derived from `currentMatch.changes`. A component can render `[(yield* Router.queryStream(sortQuery)).changes]` and update **in place** even when the same leaf stays mounted (the query-only case `Router.query` would miss). See [Programmatic navigation](#programmatic-navigation).
138
+ A `NotFound` match yields the empty subset rather than failing, so the stream stays live across navigations.
103
139
 
104
140
  ## Layouts and the outlet
105
141
 
@@ -121,7 +157,30 @@ A layout owns **no `segment` or `path`**; all path structure lives on routes. A
121
157
 
122
158
  ### Layout persistence
123
159
 
124
- Each nesting level renders as a reactive stream child keyed by `(pattern + the param values that level depends on)` and `dedupe`d. An unchanged ancestor layout therefore **stays mounted** across a navigation that only changes a deeper level. Its DOM identity and any local state (a `SubscriptionRef`, a scroll position) survive while only the inner outlet swaps.
160
+ Each nesting level renders as a reactive stream child keyed by `(pattern + the param values that level depends on)` and `dedupe`d. An unchanged ancestor layout therefore **stays mounted** across a navigation that only changes a deeper level: its DOM identity and any local state (a `SubscriptionRef`, a scroll position) survive while only the inner outlet swaps.
161
+
162
+ ```typescript
163
+ import { Component, h } from "@weftui/core";
164
+ import { Router } from "@weftui/router";
165
+ import { Clock } from "effect";
166
+
167
+ // UserShell's body runs once per distinct `:id`. Navigating between
168
+ // /users/1/settings and /users/1/posts doesn't change `:id`, so this
169
+ // instance (and `sessionStart`) is never recreated: only `outlet` swaps.
170
+ const UserShell = Component.gen(function* () {
171
+ const { id } = yield* Router.params(idParam);
172
+ const outlet = yield* Router.Outlet;
173
+ const sessionStart = yield* Clock.currentTimeMillis;
174
+
175
+ return yield* h.div({ class: "user" }, [
176
+ h.p(`shell mounted at ${sessionStart}`),
177
+ h.h1(`User ${id}`),
178
+ outlet,
179
+ ]);
180
+ });
181
+ ```
182
+
183
+ Navigate from `/users/1/settings` to `/users/1/posts` and the mounted timestamp stays the same; navigate to `/users/2/settings` and it re-renders, since `:id` changed.
125
184
 
126
185
  ## Sealing the tree
127
186
 
@@ -175,7 +234,7 @@ Router.route("users/:id", {
175
234
  });
176
235
  ```
177
236
 
178
- `RouterNotFound` is exported, so a `Boundary.catchTag("RouterNotFound", …)` placed inside a subtree overrides the app-level fallback for that subtree. The router's internal boundary is outermost, so a nearer user boundary wins.
237
+ `RouterNotFound` is exported, so a `Boundary.catchTag(…)` placed inside a subtree overrides the app-level fallback for that subtree. The router's internal boundary is outermost, so a nearer user boundary wins.
179
238
 
180
239
  > **`Schema.NumberFromString` gotcha.** Decoding no longer fails on a non-numeric segment: `/users/abc` decodes `id` to `NaN` instead of missing the route. A leaf that guards a numeric param must check `Number.isFinite(id)` itself (as above). Relying on the schema alone to 404 non-numeric input no longer works.
181
240
 
@@ -183,21 +242,103 @@ Router.route("users/:id", {
183
242
 
184
243
  On the client, provide the `Router` via `RouterLive(def)` and render `RouterApp(def)`. `RouterLive` is a **scoped layer**: it owns the `popstate` listener and the same-origin link-click interceptor, so it must outlive the mount.
185
244
 
186
- Give it to `WeftApp.make`. The app runtime owns it for the app's lifetime, built lazily on first hydrate and released only at `WeftApp.dispose`. Do not wrap `Effect.provide` around the mount/hydrate call; services come exclusively from the app layer.
245
+ Give it to `WeftApp.make`. The app runtime owns it for the app's lifetime, built lazily on first mount/hydrate and released only at `WeftApp.dispose`. Do not wrap `Effect.provide` around the mount/hydrate call; services come exclusively from the app layer. `RouterLive`'s only required argument is the sealed `App`; a second `options` argument adds an rpc group or a custom `baseUrl` when needed (see [`Boundary.rpc` interplay](#boundaryrpc-interplay)).
246
+
247
+ ```typescript
248
+ const app = WeftApp.make(RouterLive(App));
249
+ void Effect.runPromise(WeftApp.mount(app, RouterApp(App), root));
250
+ ```
251
+
252
+ ### Client-only app
253
+
254
+ A complete, no-SSR app: three routes under one `Shell` layout, mounted directly into an empty `#root`. This is the whole file set, copy/paste runnable in a `vite` + `@weftui/router` project.
255
+
256
+ ```html
257
+ <!-- index.html -->
258
+ <!doctype html>
259
+ <html lang="en">
260
+ <head>
261
+ <meta charset="UTF-8" />
262
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
263
+ <title>Weft routing demo</title>
264
+ </head>
265
+ <body>
266
+ <div id="root"></div>
267
+ <script type="module" src="/src/main.ts"></script>
268
+ </body>
269
+ </html>
270
+ ```
271
+
272
+ ```typescript
273
+ // src/app.ts
274
+ /**
275
+ * Client-only routing demo: a Shell layout with Home, About, and a dynamic
276
+ * User page, sealed into a single RouterDef. Side-effect-free (no mount call),
277
+ * so `main.ts` and any test can import `App` directly.
278
+ */
279
+ import { Component, h } from "@weftui/core";
280
+ import { href, notFound, Router } from "@weftui/router";
281
+ import { Schema } from "effect";
282
+
283
+ const idParam = { id: Schema.NumberFromString };
284
+
285
+ const homeRoute = Router.route("", {
286
+ component: Component.make(() => h.section({ id: "page" }, [h.h2("Home")])),
287
+ });
288
+
289
+ const aboutRoute = Router.route("about", {
290
+ component: Component.make(() => h.section({ id: "page" }, [h.h2("About")])),
291
+ });
292
+
293
+ const userRoute = Router.route("users/:id", {
294
+ path: idParam,
295
+ component: ({ path }) => {
296
+ if (!Number.isFinite(path.id) || path.id < 0) return notFound();
297
+ return h.section({ id: "page" }, [h.h2(`User ${path.id}`)]);
298
+ },
299
+ });
300
+
301
+ const Shell = Component.gen(function* () {
302
+ const outlet = yield* Router.Outlet;
303
+ return yield* h.div({ id: "app" }, [
304
+ h.nav([
305
+ h.a({ href: href(homeRoute) }, "Home"),
306
+ " · ",
307
+ h.a({ href: href(aboutRoute) }, "About"),
308
+ " · ",
309
+ h.a({ href: href(userRoute, { path: { id: 1 } }) }, "User 1"),
310
+ ]),
311
+ h.main([outlet]),
312
+ ]);
313
+ });
314
+
315
+ export const App = Router.router(
316
+ Router.layout({ component: Shell }, [homeRoute, aboutRoute, userRoute]),
317
+ { notFound: () => h.section({ id: "page" }, [h.h2("404: page not found")]) },
318
+ );
319
+ ```
187
320
 
188
321
  ```typescript
189
- // entry-client.ts
322
+ // src/main.ts
323
+ /**
324
+ * Browser entry: mounts the routing demo into `#root`. No server render to
325
+ * hydrate, so this uses `WeftApp.mount`, not `hydrate`.
326
+ */
190
327
  import { WeftApp } from "@weftui/dom/client";
191
328
  import { RouterApp, RouterLive } from "@weftui/router/client";
192
329
  import { Effect } from "effect";
193
330
  import { App } from "./app";
194
331
 
195
- const root = document.getElementById("root")!;
332
+ const root = document.getElementById("root");
333
+ if (root === null) {
334
+ throw new Error("#root not found");
335
+ }
336
+
196
337
  const app = WeftApp.make(RouterLive(App));
197
- void Effect.runPromise(WeftApp.hydrate(app, RouterApp(App), root));
338
+ void Effect.runPromise(WeftApp.mount(app, RouterApp(App), root));
198
339
  ```
199
340
 
200
- For a client-only app (no SSR), swap `WeftApp.hydrate` for `WeftApp.mount`; everything else is identical.
341
+ `WeftApp.mount(app, node, root)` clears `root` and renders `node` fresh, in contrast to `hydrate`, which adopts existing server-rendered DOM (see [Full SSR example](#full-ssr-example) below). Everything else, the layout, `href`, params, navigation, is identical between the two setups.
201
342
 
202
343
  ### Link interception
203
344
 
@@ -209,6 +350,11 @@ A plain `h.a({ href })` to a same-origin, route-matching URL performs SPA naviga
209
350
  - same-document (hash-only) navigations
210
351
  - hrefs that don't resolve to a route
211
352
 
353
+ ```typescript
354
+ h.a({ href: "/about" }, "About"); // intercepted: SPA navigation, no reload
355
+ h.a({ href: "/about", target: "_blank" }, "About"); // native: falls through
356
+ ```
357
+
212
358
  You don't wire anything up. `RouterLive` installs the delegated listener for the layer's lifetime and removes it on teardown.
213
359
 
214
360
  ## Programmatic navigation
@@ -265,10 +411,98 @@ On the server, `RouterServer`:
265
411
  - renders `RouterApp` to hydratable HTML inside a **document shell**
266
412
  - reports a status (404 when no route matches or a page raises `RouterNotFound`)
267
413
 
268
- The document shell is itself a `ComponentSlot` that splices the app via `yield* Router.Outlet`, exactly like a layout receives its outlet:
414
+ The document shell is itself a `ComponentSlot` that splices the app via `yield* Router.Outlet`, exactly like a layout receives its outlet.
415
+
416
+ ```typescript
417
+ const { html, status } = await Effect.runPromise(
418
+ RouterServer.render(App, { document: documentShell, url }),
419
+ );
420
+ ```
421
+
422
+ ### Full SSR example
423
+
424
+ The same three routes as the [client-only app](#client-only-app), rendered on the server as hydratable HTML and hydrated in the browser. This is the whole file set (drop it alongside a dev server that bridges `entry-server.ts`'s `handler` into Vite or any Web-platform server; see [`examples/router-ssr/server.ts`](https://github.com/stefvw93/weft/blob/main/examples/router-ssr/server.ts) for a working one).
425
+
426
+ ```typescript
427
+ // src/app.ts
428
+ /**
429
+ * Shared, isomorphic router app: three pages under one persistent Shell
430
+ * layout. Side-effect-free: it never mounts or serves. `entry-server.ts`
431
+ * renders the matched route on the server; `entry-client.ts` hydrates over it.
432
+ */
433
+ import { Component, h } from "@weftui/core";
434
+ import { href, notFound, Router } from "@weftui/router";
435
+ import { Schema } from "effect";
436
+
437
+ const idParam = { id: Schema.NumberFromString };
438
+
439
+ export const homeRoute = Router.route("", {
440
+ component: Component.make(() => h.section({ id: "page" }, [h.h2("Home")])),
441
+ });
442
+
443
+ export const aboutRoute = Router.route("about", {
444
+ component: Component.make(() => h.section({ id: "page" }, [h.h2("About")])),
445
+ });
446
+
447
+ export const userRoute = Router.route("users/:id", {
448
+ path: idParam,
449
+ component: ({ path }) => {
450
+ if (!Number.isFinite(path.id) || path.id < 0) return notFound();
451
+ return h.section({ id: "page" }, [h.h2(`User ${path.id}`)]);
452
+ },
453
+ });
454
+
455
+ const Shell = Component.gen(function* () {
456
+ const outlet = yield* Router.Outlet;
457
+ return yield* h.div({ id: "app" }, [
458
+ h.nav([
459
+ h.a({ href: href(homeRoute) }, "Home"),
460
+ " · ",
461
+ h.a({ href: href(aboutRoute) }, "About"),
462
+ ]),
463
+ h.main([outlet]),
464
+ ]);
465
+ });
466
+
467
+ export const App = Router.router(
468
+ Router.layout({ component: Shell }, [homeRoute, aboutRoute, userRoute]),
469
+ { notFound: () => h.section({ id: "page" }, [h.h2("404: page not found")]) },
470
+ );
471
+ ```
472
+
473
+ ```typescript
474
+ // src/entry-client.ts
475
+ /**
476
+ * Client entry: hydrates the server-rendered markup in `#root`.
477
+ *
478
+ * `RouterApp(App)` is the universal router root; `RouterLive(App)` provides
479
+ * the History-API-backed `Router` (seeded from `window.location`, with the
480
+ * same-origin link click interceptor installed). `hydrate` adopts the server
481
+ * DOM in place and resumes the reactive outlet.
482
+ */
483
+ import { WeftApp } from "@weftui/dom/client";
484
+ import { RouterApp, RouterLive } from "@weftui/router/client";
485
+ import { Effect } from "effect";
486
+ import { App } from "./app";
487
+
488
+ const root = document.getElementById("root");
489
+ if (root === null) {
490
+ throw new Error("#root not found");
491
+ }
492
+
493
+ const app = WeftApp.make(RouterLive(App));
494
+ void Effect.runPromise(WeftApp.hydrate(app, RouterApp(App), root));
495
+ ```
269
496
 
270
497
  ```typescript
271
- // entry-server.ts
498
+ // src/entry-server.ts
499
+ /**
500
+ * Server entry: renders the matched route to a hydratable HTML document.
501
+ *
502
+ * `documentShell` splices the app via `yield* Router.Outlet` (injected per
503
+ * request by `RouterServer`). `render` drives it for a single `url`; `handler`
504
+ * is a Web `fetch`-style handler ready to bridge into Vite or any Web server.
505
+ */
272
506
  import { Component, h } from "@weftui/core";
273
507
  import { Router } from "@weftui/router";
274
508
  import { RouterServer } from "@weftui/router/server";
@@ -287,14 +521,16 @@ const documentShell = Component.gen(function* () {
287
521
  });
288
522
 
289
523
  // { html, status }: `<!DOCTYPE html>` is prepended for you.
290
- export const render = (url: string) =>
524
+ export const render = (url: string): Promise<{ html: string; status: number }> =>
291
525
  Effect.runPromise(RouterServer.render(App, { document: documentShell, url }));
292
526
 
293
- // Or a Web fetch-style handler, ready to bridge into Vite or any Web server.
527
+ // A Web fetch-style handler, ready to bridge into Vite or any Web server.
294
528
  export const handler = RouterServer.toWebHandler(App, { document: documentShell });
295
529
  ```
296
530
 
297
- `render` provides both `Router.Outlet` (the app, per request) and `Router` (so the shell may read params). It renders through `renderToStringHydratable` so the client can `hydrate` in place.
531
+ `render` provides both `Router.Outlet` (the app, per request) and `Router` (so the shell may read params). It renders through `renderToStringHydratable` so the client can `hydrate` in place. Neither `RouterLive` nor `RouterServer` needs an `rpc` option here: it's optional and only required once a page uses [`Boundary.rpc`](#boundaryrpc-interplay).
532
+
533
+ `handler` still needs a server to call it. [`examples/router-ssr/server.ts`](https://github.com/stefvw93/weft/blob/main/examples/router-ssr/server.ts) shows the shape: a Node HTTP server that runs Vite in middleware mode, converts each request to a Web `Request`, calls `handler`, and runs HTML responses through `vite.transformIndexHtml` for HMR (non-HTML responses, like a `Boundary.rpc` refetch, are forwarded untouched). See that file and its co-located [`vite.config.ts`](https://github.com/stefvw93/weft/blob/main/examples/router-ssr/vite.config.ts) for the full dev-server wiring; it's the same shape in production behind any Web-platform host.
298
534
 
299
535
  ### `effect/unstable/httpapi` is the spine
300
536
 
@@ -305,27 +541,68 @@ The result is a single `"pages"` group with one GET endpoint per leaf at its ful
305
541
  - **Server**: `RouterServer` dispatches through `HttpApiBuilder` (platform owns request→leaf matching, path/query decode, and the 404 status).
306
542
  - **Client**: `RouterLive` derives a real `HttpApiClient` from the same `def.httpApi` (exposed as `Router.httpApiClient`) for network work. SPA URL→leaf resolution stays **local**; there is no public client-side "match this URL against my `HttpApi`" utility in platform. It is fed from the same endpoint definitions, so it never drifts from the server.
307
543
 
544
+ ```typescript
545
+ import { Option } from "effect";
546
+
547
+ App.httpApi; // HttpApi.Top: one "pages" group, a GET endpoint per leaf
548
+
549
+ const { httpApiClient } = yield * Router;
550
+ Option.isSome(httpApiClient); // true under RouterLive, false under RouterServer
551
+ ```
552
+
308
553
  ## Errors
309
554
 
310
- | Error | Raised by | Recover with |
311
- | ------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------- |
312
- | `RouterNotFound` | `notFound()`, or no route matched | `Boundary.catchTag("RouterNotFound", …)` (or the app-level `notFound` page) |
313
- | `RouterParamsError` | `Router.params` / `Router.query` on a missing/invalid key or no match | `Boundary.catchTag("RouterParamsError", …)` |
555
+ | Error | Raised by | Recover with |
556
+ | ------------------- | --------------------------------------------------------------------- | --------------------------------------------------------- |
557
+ | `RouterNotFound` | `notFound()`, or no route matched | `Boundary.catchTag(…)` (or the app-level `notFound` page) |
558
+ | `RouterParamsError` | `Router.params` / `Router.query` on a missing/invalid key or no match | `Boundary.catchTag(…)` |
314
559
 
315
560
  Both are modeled as `Schema.TaggedErrorClass`, so they encode/decode across the wire the same way `Boundary.rpc` replays typed failures.
316
561
 
562
+ Recover locally by wrapping just the subtree that can fail, rather than relying on the app-level `notFound` page for everything:
563
+
564
+ ```typescript
565
+ import { Boundary, Component, h } from "@weftui/core";
566
+ import { Router } from "@weftui/router";
567
+
568
+ const UserShell = Component.gen(function* () {
569
+ const outlet = yield* Router.Outlet;
570
+ return yield* h.div({ class: "user" }, [
571
+ Boundary.catchTag(
572
+ {
573
+ tag: "RouterParamsError",
574
+ fallback: () => h.p({ class: "error" }, "Couldn't read this page's params."),
575
+ },
576
+ [outlet],
577
+ ),
578
+ ]);
579
+ });
580
+ ```
581
+
582
+ The matched tag is removed from the boundary's output `E`; an unmatched error (e.g. `RouterNotFound`) re-raises to the nearest parent boundary, which is the router's own not-found boundary if nothing closer catches it.
583
+
317
584
  ## `Boundary.rpc` interplay
318
585
 
319
586
  Initial SSR navigation works end to end: the server resolves the rpc and inlines its payload, and the client replays it during `hydrate`.
320
587
 
321
588
  **Client-side** navigation into a page containing a `Boundary.rpc` has no SSR payload, so the boundary performs a **client-first mount**. It renders the boundary's `fallback`, forks the rpc call over `POST /_eui/rpc`, and swaps in the result.
322
589
 
323
- `@weftui/router` provides the `AppRpcClientTag` seam on both sides (network client on the client, in-process on the server). The same rpc backs SSR-replay, refetch, and client-first mount. See the [rpc data boundaries guide](https://weftui.dev/docs/how-to/load-data-with-rpc).
590
+ `@weftui/router` provides the `AppRpcClientTag` seam on both sides (network client on the client, in-process on the server). The same rpc backs SSR-replay, refetch, and client-first mount. Both `RouterLive` and `RouterServer` take an optional `{ rpc: { group } }` (server also needs `handlers`) to wire it: see the [rpc data boundaries guide](https://weftui.dev/docs/how-to/load-data-with-rpc) and [`examples/router-ssr`](https://github.com/stefvw93/weft/tree/main/examples/router-ssr) for the full contract/handler split.
591
+
592
+ ```typescript
593
+ // client (entry-client.ts): network rpc client over the shared group
594
+ const app = WeftApp.make(RouterLive(App, { rpc: { group: StockRpcs } }));
595
+
596
+ // server (entry-server.ts): same group, plus its handler Layer
597
+ const rpc = { group: StockRpcs, handlers: StockLive };
598
+ export const handler = RouterServer.toWebHandler(App, { document: documentShell, rpc });
599
+ ```
324
600
 
325
601
  ## See also
326
602
 
327
603
  - [`@weftui/router` API reference](https://weftui.dev/docs/reference/router)
328
- - [examples/router-ssr](https://github.com/stefvw93/weft/tree/main/examples/router-ssr): a runnable SSR + hydration app with nested layouts, persistent layout state, type-safe `href`s, handler-arg props, and programmatic navigation over the `effect/unstable/httpapi` spine
604
+ - [examples/router-ssr](https://github.com/stefvw93/weft/tree/main/examples/router-ssr): a runnable SSR + hydration app with nested layouts, persistent layout state, type-safe `href`s, handler-arg props, `Boundary.rpc`, and programmatic navigation over the `effect/unstable/httpapi` spine
605
+ - [examples/router-client](https://github.com/stefvw93/weft/tree/main/examples/router-client): the client-only counterpart, no server, no SSR, no `Boundary.rpc`
329
606
  - [Component Authoring](https://weftui.dev/docs/how-to/author-components): `Component.make` / `Component.gen`, the idiomatic way to write route components
330
607
  - [Server-Side Rendering](https://weftui.dev/docs/how-to/render-on-the-server): `renderToStringHydratable`, `hydrate`, and `Boundary.rpc`
331
608
  - [RPC Data Boundaries](https://weftui.dev/docs/how-to/load-data-with-rpc): `Boundary.rpc`, the `Resource` handle, and the four lifecycles
@@ -193,13 +193,13 @@ When a caller passes a plain string, the component's node type has `never` for t
193
193
  Splicing a `Source` straight into `h` (`[props.label]`) is enough when you only place it in the tree. When the body needs to **read or derive** from the value (combine two props, feed a stream operator, drive logic), normalize it first with [`Source.toSubscribable`](https://weftui.dev/docs/reference/core#sourcetosubscribablesource-key). It turns any `Source<A>` into an await-first, hot `Subscribable<A>`:
194
194
 
195
195
  ```typescript
196
- import { Component, h, Source } from "@weftui/core";
196
+ import { Component, h, Source, Subscribable } from "@weftui/core";
197
197
  import { Stream } from "effect";
198
198
 
199
199
  const LoudLabel = Component.gen(function* (props: { label: Source.Source<string> }) {
200
200
  const label = yield* Source.toSubscribable(props.label); // Subscribable<string>
201
201
  // Now derive from it like any Subscribable: static, Effect, and Stream inputs all work.
202
- return yield* h.strong([Stream.map(label.changes, (text) => text.toUpperCase())]);
202
+ return yield* h.strong([Stream.map(Subscribable.changes(label), (text) => text.toUpperCase())]);
203
203
  });
204
204
  ```
205
205
 
@@ -14,7 +14,7 @@ description: Boundary.rpc, server-resolved and client-refreshable data; the cont
14
14
  A `Boundary.rpc` is a **thin consumer**. It carries an rpc, a payload thunk, and a `render` that receives a reactive [`Resource`](https://weftui.dev/docs/reference/core#resourcea). The renderer resolves the rpc through the ambient [`AppRpcClientTag`](https://weftui.dev/docs/reference/core#apprpcclienttag) seam (provided by `@weftui/router`). The same rpc serves every lifecycle, so SSR-replay, refetch, and client-first mount are one mechanism, not three.
15
15
 
16
16
  ```typescript
17
- import { Boundary, h } from "@weftui/core";
17
+ import { Boundary, h, Subscribable } from "@weftui/core";
18
18
  import { Stream } from "effect";
19
19
  import { GetStock } from "./data/inventory";
20
20
 
@@ -26,7 +26,7 @@ Boundary.rpc(
26
26
  ) =>
27
27
  h.p([
28
28
  "in stock: ",
29
- h.span([Stream.map(resource.value.changes, (s) => String(s.units))]),
29
+ h.span([Stream.map(Subscribable.changes(resource.value), (s) => String(s.units))]),
30
30
  h.button({ type: "button", onclick: () => resource.refetch }, "Refresh"),
31
31
  ]),
32
32
  { fallback: h.p("loading stock…") }, // shown only on a client-first mount
@@ -127,8 +127,8 @@ Because the SSR path seeds `value` await-first (it emits the seed immediately),
127
127
  ```typescript
128
128
  (resource) =>
129
129
  h.section({ class: "product" }, [
130
- h.span([Stream.map(resource.value.changes, (s) => String(s.units))]),
131
- h.span([Stream.map(resource.pending.changes, (p) => (p ? "refreshing…" : ""))]),
130
+ h.span([Stream.map(Subscribable.changes(resource.value), (s) => String(s.units))]),
131
+ h.span([Stream.map(Subscribable.changes(resource.pending), (p) => (p ? "refreshing…" : ""))]),
132
132
  h.button({ type: "button", onclick: () => resource.refetch }, "Refresh stock"),
133
133
  ]);
134
134
  ```
@@ -12,14 +12,14 @@ description: Render a reactive collection with List.each so reordering, insertin
12
12
  Use [`List.each`](https://weftui.dev/docs/reference/core#listeach), the keyed-list combinator. It renders each item **once per key** and reconciles across emissions. A reorder _moves_ existing DOM nodes, an insert adds one, a remove drops one, and untouched rows are left entirely alone.
13
13
 
14
14
  ```typescript
15
- import { h, List } from "@weftui/core";
15
+ import { h, List, Subscribable } from "@weftui/core";
16
16
  import { Stream } from "effect";
17
17
 
18
18
  declare const rows: Subscribable.Subscribable<ReadonlyArray<{ id: number; name: string }>>;
19
19
 
20
20
  h.ul([
21
21
  List.each(
22
- { of: rows.changes, by: (row) => row.id }, // key by stable identity
22
+ { of: Subscribable.changes(rows), by: (row) => row.id }, // key by stable identity
23
23
  (row) => h.li(row.name),
24
24
  ),
25
25
  ]);
@@ -30,7 +30,7 @@ h.ul([
30
30
 
31
31
  ## Why not `map`?
32
32
 
33
- Mapping items by hand (`Stream.map(rows.changes, (rs) => rs.map(r => h.li(r.name)))`) produces a **new children array on every emission**. The renderer then rebuilds the whole region: every row's DOM node is recreated even if only one item moved.
33
+ Mapping items by hand (`Stream.map(Subscribable.changes(rows), (rs) => rs.map(r => h.li(r.name)))`) produces a **new children array on every emission**. The renderer then rebuilds the whole region: every row's DOM node is recreated even if only one item moved.
34
34
 
35
35
  `List.each` reconciles by key instead, so DOM identity (and the focus/scroll/typed-input state attached to it) survives across updates.
36
36
 
@@ -39,8 +39,8 @@ Mapping items by hand (`Stream.map(rows.changes, (rs) => rs.map(r => h.li(r.name
39
39
  Because `render` runs **exactly once per key**, reconciliation never re-runs it for a kept row, so it never refreshes that row's content on its own. To make a row's content reactive, thread a `Stream` **inside** the row rather than expecting a re-render:
40
40
 
41
41
  ```typescript
42
- List.each({ of: rows.changes, by: (row) => row.id }, (row) =>
43
- h.li([h.span([Stream.map(row.status.changes, (s) => s)])]),
42
+ List.each({ of: Subscribable.changes(rows), by: (row) => row.id }, (row) =>
43
+ h.li([h.span([Stream.map(Subscribable.changes(row.status), (s) => s)])]),
44
44
  );
45
45
  ```
46
46
 
@@ -54,7 +54,7 @@ Use a hydratable renderer whenever the client will call `hydrate`. The plain ren
54
54
  It follows the same server/client split: the rpc **contract** (pure Schema) is shared, while its **handler** lives in a server-only Layer the client never imports.
55
55
 
56
56
  ```typescript
57
- import { Boundary, h } from "@weftui/core";
57
+ import { Boundary, h, Subscribable } from "@weftui/core";
58
58
  import { Stream } from "effect";
59
59
  import { GetStock } from "./data/inventory";
60
60
 
@@ -65,7 +65,7 @@ const StockPanel = (productId: number) =>
65
65
  (resource) =>
66
66
  h.p([
67
67
  "in stock: ",
68
- h.span([Stream.map(resource.value.changes, (stock) => String(stock.units))]),
68
+ h.span([Stream.map(Subscribable.changes(resource.value), (stock) => String(stock.units))]),
69
69
  h.button({ type: "button", onclick: () => resource.refetch }, "Refresh"),
70
70
  ]),
71
71
  { fallback: h.p("loading stock…") }, // shown only on a client-first SPA mount
@@ -14,7 +14,7 @@ When you navigate to a route, the router is **deferred-commit**. It resolves the
14
14
  That resolve window is exposed as a reactive signal, [`Router.navigating`](https://weftui.dev/docs/reference/router#routernavigating), that you read to render pending UI.
15
15
 
16
16
  ```typescript
17
- import { Component, h } from "@weftui/core";
17
+ import { Component, h, Subscribable } from "@weftui/core";
18
18
  import { Router } from "@weftui/router";
19
19
  import { Stream } from "effect";
20
20
 
@@ -25,7 +25,7 @@ const Shell = Component.gen(function* () {
25
25
  h.div({
26
26
  id: "nav-progress",
27
27
  "aria-hidden": "true",
28
- class: Stream.map(nav.changes, (s) =>
28
+ class: Stream.map(Subscribable.changes(nav), (s) =>
29
29
  s._tag === "Navigating" ? "nav-progress is-navigating" : "nav-progress",
30
30
  ),
31
31
  }),
@@ -358,9 +358,9 @@ The keyed-list combinator. It is the opt-in alternative to wholesale child rebui
358
358
  > elements.
359
359
 
360
360
  ```typescript
361
- import { h, List } from "@weftui/core";
361
+ import { h, List, Subscribable } from "@weftui/core";
362
362
 
363
- h.ul([List.each({ of: rows.changes, by: (row) => row.id }, (row) => h.li(row.name))]);
363
+ h.ul([List.each({ of: Subscribable.changes(rows), by: (row) => row.id }, (row) => h.li(row.name))]);
364
364
  ```
365
365
 
366
366
  #### `List.each`
@@ -111,7 +111,7 @@ Router.params<F extends Fields>(fields: F): Effect<FieldsType<F>, RouterParamsEr
111
111
  Router.query<F extends Fields>(fields: F): Effect<FieldsType<F>, RouterParamsError, Router>;
112
112
  ```
113
113
 
114
- Snapshot accessors that read the **live match** (`currentMatch.get`) and pick the requested `fields` keys from the decoded path/query. The matcher already decoded the values against the leaf's full schema, so they are returned directly (no re-validation).
114
+ Snapshot accessors that read the **live match** (`Subscribable.get(currentMatch)`) and pick the requested `fields` keys from the decoded path/query. The matcher already decoded the values against the leaf's full schema, so they are returned directly (no re-validation).
115
115
 
116
116
  Readable from **any** component, not just the leaf: this is the dependency-injection path layouts and deep nodes use (leaves can instead take [handler-arg props](#routerroute)). They fail with a [`RouterParamsError`](#routerparamserror) (`source: "path" | "query"`, plus the requested `keys`) when no route matches.
117
117
 
@@ -122,7 +122,7 @@ Router.paramsStream<F extends Fields>(fields: F): Effect<Subscribable<FieldsType
122
122
  Router.queryStream<F extends Fields>(fields: F): Effect<Subscribable<FieldsType<F>>, never, Router>;
123
123
  ```
124
124
 
125
- The **reactive** counterparts. Each resolves a `Subscribable<FieldsType<F>>` derived from `currentMatch.changes`. A component can render `[(yield* Router.queryStream(fields)).changes]` and update **in place** even when the outlet keeps the same leaf mounted. That is exactly the query-only case (`setQuery` / `patchQuery`) a snapshot `Router.query` would miss.
125
+ The **reactive** counterparts. Each resolves a `Subscribable<FieldsType<F>>` derived from `Subscribable.changes(currentMatch)`. A component can render `[Subscribable.changes(yield* Router.queryStream(fields))]` and update **in place** even when the outlet keeps the same leaf mounted. That is exactly the query-only case (`setQuery` / `patchQuery`) a snapshot `Router.query` would miss.
126
126
 
127
127
  Resilient across navigations: a `NotFound` match yields the empty subset rather than failing, so the stream stays live.
128
128
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weftui/dom",
3
- "version": "0.29.0",
3
+ "version": "0.30.0",
4
4
  "description": "DOM renderer for Weft: mount and hydrate in the browser, render to string or stream on the server",
5
5
  "keywords": [
6
6
  "dom",
@@ -44,7 +44,7 @@
44
44
  "access": "public"
45
45
  },
46
46
  "dependencies": {
47
- "@weftui/core": "0.29.0"
47
+ "@weftui/core": "0.30.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/jsdom": "^28.0.3",