@weftui/router 0.20.9 → 0.21.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.
- package/dist/client/index.d.ts +5 -3
- package/dist/client/index.js +1 -1
- package/dist/server/index.d.ts +20 -2
- package/dist/server/index.js +1 -1
- package/package.json +6 -6
package/dist/client/index.d.ts
CHANGED
|
@@ -17,9 +17,11 @@ interface RouterLiveOptions {
|
|
|
17
17
|
* The app's `Boundary.rpc` foundation: the merged `RpcGroup` contract (shared
|
|
18
18
|
* with the server handler Layer). Backs the {@link AppRpcClientTag} seam so a
|
|
19
19
|
* hydrated boundary refetch — and a client-first SPA mount — resolve over the
|
|
20
|
-
* network rpc client.
|
|
20
|
+
* network rpc client. Optional: omit when the app has no `Boundary.rpc` — then
|
|
21
|
+
* no network rpc client is built and a stray `Boundary.rpc` fails with a
|
|
22
|
+
* descriptive error.
|
|
21
23
|
*/
|
|
22
|
-
readonly rpc
|
|
24
|
+
readonly rpc?: {
|
|
23
25
|
/** The app's merged `RpcGroup` (pure Schema contract). */readonly group: RpcGroup.RpcGroup<any>;
|
|
24
26
|
};
|
|
25
27
|
}
|
|
@@ -41,7 +43,7 @@ interface RouterLiveOptions {
|
|
|
41
43
|
* refetch and client-first mount) without depending on this package or
|
|
42
44
|
* `@effect/rpc`.
|
|
43
45
|
*/
|
|
44
|
-
declare function RouterLive(def: RouterDef, options
|
|
46
|
+
declare function RouterLive(def: RouterDef, options?: RouterLiveOptions): Layer.Layer<Router | AppRpcClientTag>;
|
|
45
47
|
//#endregion
|
|
46
48
|
//#region src/client/link.d.ts
|
|
47
49
|
/**
|
package/dist/client/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,r as t,t as n}from"../outlet-C7p8KXmO.js";import{r,t as i}from"../href-Dl30XcF4.js";import{FetchHttpClient as a,HttpApiClient as o}from"@effect/platform";import{Context as s,Effect as c,Layer as l,Option as u,Runtime as d,Schema as f,Stream as p,Subscribable as m,SubscriptionRef as h}from"effect";import{AppRpcClientTag as g}from"@weftui/core";import{RpcClient as _,RpcSerialization as v}from"@effect/rpc";function y(e,t){return c.gen(function*(){let n=yield*c.runtime(),i=i=>{if(i.defaultPrevented||i.button!==0||i.metaKey||i.ctrlKey||i.shiftKey||i.altKey)return;let a=i.target,o=a instanceof Element?a.closest(`a`):null;if(o===null)return;let s=o.getAttribute(`target`);if(o.hasAttribute(`download`)||s!==null&&s!==`_self`||o.getAttribute(`rel`)===`external`)return;let c=o.getAttribute(`href`);if(c===null||c.length===0)return;let l;try{l=new URL(c,window.location.href)}catch{return}if(l.origin!==window.location.origin)return;let u=`${l.pathname}${l.search}`;u!==`${window.location.pathname}${window.location.search}`&&r(e,u)._tag===`Matched`&&(i.preventDefault(),d.runFork(n)(t(u)))};yield*c.acquireRelease(c.sync(()=>document.addEventListener(`click`,i)),()=>c.sync(()=>document.removeEventListener(`click`,i)))})}function b(){return`${window.location.pathname}${window.location.search}`}function x(e){let t=new URL(e,window.location.href);return`${t.pathname}${t.search}`}function S(e,n){return l.scopedContext(c.gen(function*(){let i=yield*h.make(b()),f=yield*c.runtime(),S=yield*o.make(e.httpApi,{baseUrl:n.baseUrl??window.location.origin}).pipe(c.provide(a.layer)),C=()=>{d.runFork(f)(h.set(i,b()))};yield*c.acquireRelease(c.sync(()=>window.addEventListener(`popstate`,C)),()=>c.sync(()=>window.removeEventListener(`popstate`,C)));let w=(e,t)=>c.gen(function*(){let n=x(e);yield*c.sync(()=>{t?.replace===!0?window.history.replaceState(null,``,n):window.history.pushState(null,``,n)}),yield*h.set(i,n)});yield*y(e,w);let T=m.make({get:c.map(h.get(i),t=>r(e,t)),changes:p.map(i.changes,t=>r(e,t))}),E=String(n.baseUrl??window.location.origin).replace(/\/$/,``),
|
|
1
|
+
import{n as e,r as t,t as n}from"../outlet-C7p8KXmO.js";import{r,t as i}from"../href-Dl30XcF4.js";import{FetchHttpClient as a,HttpApiClient as o}from"@effect/platform";import{Context as s,Effect as c,Layer as l,Option as u,Runtime as d,Schema as f,Stream as p,Subscribable as m,SubscriptionRef as h}from"effect";import{AppRpcClientTag as g}from"@weftui/core";import{RpcClient as _,RpcSerialization as v}from"@effect/rpc";function y(e,t){return c.gen(function*(){let n=yield*c.runtime(),i=i=>{if(i.defaultPrevented||i.button!==0||i.metaKey||i.ctrlKey||i.shiftKey||i.altKey)return;let a=i.target,o=a instanceof Element?a.closest(`a`):null;if(o===null)return;let s=o.getAttribute(`target`);if(o.hasAttribute(`download`)||s!==null&&s!==`_self`||o.getAttribute(`rel`)===`external`)return;let c=o.getAttribute(`href`);if(c===null||c.length===0)return;let l;try{l=new URL(c,window.location.href)}catch{return}if(l.origin!==window.location.origin)return;let u=`${l.pathname}${l.search}`;u!==`${window.location.pathname}${window.location.search}`&&r(e,u)._tag===`Matched`&&(i.preventDefault(),d.runFork(n)(t(u)))};yield*c.acquireRelease(c.sync(()=>document.addEventListener(`click`,i)),()=>c.sync(()=>document.removeEventListener(`click`,i)))})}function b(){return`${window.location.pathname}${window.location.search}`}function x(e){let t=new URL(e,window.location.href);return`${t.pathname}${t.search}`}function S(e,n={}){return l.scopedContext(c.gen(function*(){let i=yield*h.make(b()),f=yield*c.runtime(),S=yield*o.make(e.httpApi,{baseUrl:n.baseUrl??window.location.origin}).pipe(c.provide(a.layer)),C=()=>{d.runFork(f)(h.set(i,b()))};yield*c.acquireRelease(c.sync(()=>window.addEventListener(`popstate`,C)),()=>c.sync(()=>window.removeEventListener(`popstate`,C)));let w=(e,t)=>c.gen(function*(){let n=x(e);yield*c.sync(()=>{t?.replace===!0?window.history.replaceState(null,``,n):window.history.pushState(null,``,n)}),yield*h.set(i,n)});yield*y(e,w);let T=m.make({get:c.map(h.get(i),t=>r(e,t)),changes:p.map(i.changes,t=>r(e,t))}),E=n.rpc,D;if(E===void 0)D=g.of({call:e=>c.fail(Error(`Boundary.rpc "${e}" cannot resolve: no \`rpc\` option was passed to RouterLive`))});else{let e=String(n.baseUrl??window.location.origin).replace(/\/$/,``),t=yield*_.make(E.group,{flatten:!0}).pipe(c.provide(_.layerProtocolHttp({url:`${e}/_eui/rpc`}).pipe(l.provide(l.mergeAll(a.layer,v.layerJson)))));D=g.of({call:(e,n)=>t(e,n)})}let O=t.of({currentMatch:T,navigate:w,httpApiClient:u.some(S)});return s.make(t,O).pipe(s.add(g,D))}))}function C(e,...n){let[r,a]=n,o=i(e,r);return c.flatMap(t,e=>e.navigate(o,a))}const w=e=>c.flatMap(t,t=>t.navigate(e)),T=e=>c.flatMap(t,t=>t.navigate(e,{replace:!0})),E=()=>c.sync(()=>window.history.go(-1)),D=()=>c.sync(()=>window.history.go(1));function O(e){let t=new URLSearchParams;for(let n of Object.keys(e).sort()){let r=e[n];r!=null&&t.append(n,String(r))}return t.toString()}function k(e){let t=e.indexOf(`?`);return t===-1?e:e.slice(0,t)}function A(e,n){return c.gen(function*(){let r=yield*t,i=yield*r.currentMatch.get;if(i._tag!==`Matched`)return;let a=e(i.query),o=O(f.encodeUnknownSync(i.leaf.querySchema)(a)),s=k(i.url);yield*r.navigate(o.length>0?`${s}?${o}`:s,n)})}const j=(e,t)=>A(()=>e,t),M=(e,t)=>A(t=>({...t,...e}),t);export{t as Router,n as RouterApp,S as RouterLive,e as RouterOutlet,e as outletNode,E as back,D as forward,y as installLinkInterceptor,C as navigate,M as patchQuery,w as push,T as replace,j as setQuery};
|
package/dist/server/index.d.ts
CHANGED
|
@@ -37,8 +37,13 @@ declare namespace RouterServer {
|
|
|
37
37
|
interface Options {
|
|
38
38
|
/** The document shell slot; reads the app to splice via `yield* Router.Outlet`. */
|
|
39
39
|
readonly document: ComponentSlot;
|
|
40
|
-
/**
|
|
41
|
-
|
|
40
|
+
/**
|
|
41
|
+
* The app's `Boundary.rpc` foundation (contract + server handlers). Optional:
|
|
42
|
+
* omit when the app has no `Boundary.rpc` — then `POST /_eui/rpc` is not
|
|
43
|
+
* served (it falls through to page dispatch) and a stray `Boundary.rpc`
|
|
44
|
+
* fails with a descriptive error instead of rendering.
|
|
45
|
+
*/
|
|
46
|
+
readonly rpc?: RpcOptions;
|
|
42
47
|
}
|
|
43
48
|
/** The result of {@link render}. */
|
|
44
49
|
interface Rendered {
|
|
@@ -61,6 +66,19 @@ declare namespace RouterServer {
|
|
|
61
66
|
* Web-platform server.
|
|
62
67
|
*/
|
|
63
68
|
function toWebHandler(def: RouterDef, options: Options): (request: Request) => Promise<Response>;
|
|
69
|
+
/**
|
|
70
|
+
* Streaming variant of {@link toWebHandler} (spec: "Streaming SSR" in
|
|
71
|
+
* `router.specs.md`, SW1 … SW7). Same `Options`, memoized separately. Per
|
|
72
|
+
* matched leaf the document renders via the dom shell-split API
|
|
73
|
+
* (`renderToHydratableShell`): the buffered shell decides the HTTP status
|
|
74
|
+
* before any bytes flush, then streams as the first chunk with the Suspense
|
|
75
|
+
* patch chunks after it. A `RouterNotFound` escaping `Boundary.suspend`
|
|
76
|
+
* children after the flush keeps 200 and patches in the `notFound` page plus
|
|
77
|
+
* a noindex robots meta (soft-404). No-match and shell-raised
|
|
78
|
+
* `RouterNotFound` stay real 404s; `POST /_eui/rpc` delegation is unchanged.
|
|
79
|
+
* `render` and `toWebHandler` remain fully buffered.
|
|
80
|
+
*/
|
|
81
|
+
function toStreamingWebHandler(def: RouterDef, options: Options): (request: Request) => Promise<Response>;
|
|
64
82
|
}
|
|
65
83
|
//#endregion
|
|
66
84
|
export { RouterServer };
|
package/dist/server/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{l as e,n as t,r as n}from"../outlet-C7p8KXmO.js";import{HttpApiBuilder as
|
|
1
|
+
import{l as e,n as t,r as n,s as r}from"../outlet-C7p8KXmO.js";import{HttpApiBuilder as i,HttpApiEndpoint as a,HttpApiGroup as o,HttpServer as s,HttpServerResponse as c}from"@effect/platform";import{Cause as l,Effect as u,Exit as d,Layer as f,Option as p,Schema as m,Scope as h,Stream as g,Subscribable as _}from"effect";import{AppRpcClientTag as v}from"@weftui/core";import{RpcSerialization as y,RpcServer as b,RpcTest as x}from"@effect/rpc";import{SuspenseFailureHandlerTag as S,renderToHydratableShell as C,renderToStringHydratable as w}from"@weftui/dom/server";let T;(function(T){function E(e,t){return c.text(`<!DOCTYPE html>\n${e}`,{status:t,contentType:`text/html; charset=utf-8`})}function D(e){return n.of({currentMatch:_.make({get:u.succeed(e),changes:g.make(e)}),navigate:()=>u.void,httpApiClient:p.none()})}function O(e){return e===void 0?f.succeed(v,v.of({call:e=>u.fail(Error(`Boundary.rpc "${e}" cannot resolve: no \`rpc\` option was passed to RouterServer`))})):f.scoped(v,u.map(x.makeClient(e.group,{flatten:!0}),e=>v.of({call:(t,n)=>e(t,n)}))).pipe(f.provide(e.handlers))}function k(e,t,r){return w(u.provideService(e.document({}),n.Outlet,t)).pipe(u.provideService(n,r),u.provide(O(e.rpc)))}function A(e,t,n,r){let i=D({_tag:`NotFound`,url:n});return k(t,e.compiled.notFound(),i).pipe(u.map(e=>E(e,r)))}function j(e,n,r){let i=D({_tag:`NotFound`,url:r});return k(n,t(e),i).pipe(u.map(e=>E(e,404)))}function M(n,r,i){let a=D(i);return k(r,t(n),a).pipe(u.map(e=>E(e,200)),u.catchIf(e,()=>A(n,r,i.url,404)))}function N(t){return{handle:n=>{let i=l.failureOption(n);return p.isSome(i)&&e(i.value)?p.some({content:t.compiled.notFound(),markNoindex:!0,failureReplay:m.encodeSync(r)(i.value)}):p.none()}}}function P(r,i,a){let o=D(a),s=t(r);return u.gen(function*(){let e=yield*h.make(),{shell:t,patches:a}=yield*C(u.provideService(i.document({}),n.Outlet,s)).pipe(u.provideService(n,o),u.provideService(S,N(r)),u.provide(O(i.rpc)),h.extend(e),u.onError(t=>h.close(e,d.failCause(t)))),l=g.make(`<!DOCTYPE html>\n${t}`).pipe(g.concat(a),g.ensuring(h.close(e,d.void)),g.encodeText);return c.stream(l,{status:200,contentType:`text/html; charset=utf-8`})}).pipe(u.catchIf(e,()=>A(r,i,a.url,404)))}let F=new WeakMap,I=new WeakMap;function L(e,t,n,r){let c=n.get(e)??new WeakMap;n.set(e,c);let l=c.get(t.document);if(l!==void 0)return l;let u=e.compiled.leaves,d=i,p=o.make(`fallback`).add(a.get(`catchAll`,`*`).addSuccess(m.String)),h=e.httpApi.add(p),g=d.group(h,`pages`,n=>u.reduce((n,i)=>n.handle(i.id,n=>r(e,t,{_tag:`Matched`,leaf:i,path:n.path,query:n.urlParams,url:n.request.url})),n)),_=d.group(h,`fallback`,n=>n.handle(`catchAll`,n=>j(e,t,n.request.url))),v=d.api(h).pipe(f.provide(f.mergeAll(g,_))),{handler:x}=i.toWebHandler(f.mergeAll(v,s.layerContext)),S=t.rpc,C=x;if(S!==void 0){let{handler:e}=b.toWebHandler(S.group,{layer:f.mergeAll(S.handlers,y.layerJson)});C=t=>new URL(t.url).pathname===`/_eui/rpc`?e(t):x(t)}return c.set(t.document,C),C}function R(e,t){return L(e,t,F,M)}function z(e){return e.startsWith(`http://`)||e.startsWith(`https://`)?e:`http://localhost${e.startsWith(`/`)?e:`/${e}`}`}function B(e,t){return u.tryPromise({try:async()=>{let n=await R(e,t)(new Request(z(t.url)));return{html:await n.text(),status:n.status}},catch:e=>e instanceof Error?e:Error(String(e))})}T.render=B;function V(e,t){return R(e,t)}T.toWebHandler=V;function H(e,t){return L(e,t,I,P)}T.toStreamingWebHandler=H})(T||={});export{T as RouterServer};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weftui/router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Universal nested router for Weft",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Stef van Wijchen",
|
|
@@ -32,15 +32,15 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@effect/platform": "^0.96.1",
|
|
34
34
|
"@effect/rpc": "^0.75.1",
|
|
35
|
-
"@weftui/core": "0.
|
|
36
|
-
"@weftui/dom": "0.
|
|
35
|
+
"@weftui/core": "0.21.0",
|
|
36
|
+
"@weftui/dom": "0.21.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/jsdom": "^28.0.3",
|
|
40
|
-
"@types/node": "^25.9.
|
|
41
|
-
"effect": "^3.21.
|
|
40
|
+
"@types/node": "^25.9.2",
|
|
41
|
+
"effect": "^3.21.3",
|
|
42
42
|
"jsdom": "^29.1.1",
|
|
43
|
-
"tsx": "^4.22.
|
|
43
|
+
"tsx": "^4.22.4",
|
|
44
44
|
"typescript": "^6.0.3",
|
|
45
45
|
"vite-plus": "latest"
|
|
46
46
|
},
|