@lomray/vite-ssr-boost 8.4.0-beta.2 → 8.4.0-beta.3
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/README.md +2 -0
- package/adapters/express/render.d.ts +1 -0
- package/adapters/express/render.js +1 -1
- package/adapters/express/render.js.map +1 -1
- package/browser/entry.js +1 -1
- package/browser/entry.js.map +1 -1
- package/core/compose-html.d.ts +2 -1
- package/core/compose-html.js +1 -1
- package/core/compose-html.js.map +1 -1
- package/core/data-stream.d.ts +3 -1
- package/core/data-stream.js +1 -1
- package/core/data-stream.js.map +1 -1
- package/core/handler.d.ts +6 -2
- package/core/handler.js +1 -1
- package/core/handler.js.map +1 -1
- package/core/render.d.ts +3 -1
- package/core/render.js +1 -1
- package/core/render.js.map +1 -1
- package/package.json +29 -1
- package/services/request-timeline.d.ts +30 -0
- package/services/request-timeline.js +2 -0
- package/services/request-timeline.js.map +1 -0
- package/testing/browser-observer.d.ts +30 -0
- package/testing/browser-observer.js +2 -0
- package/testing/browser-observer.js.map +1 -0
- package/testing/create-handler.d.ts +32 -0
- package/testing/create-handler.js +2 -0
- package/testing/create-handler.js.map +1 -0
- package/testing/deferred.d.ts +9 -0
- package/testing/deferred.js +2 -0
- package/testing/deferred.js.map +1 -0
- package/testing/edge.d.ts +9 -0
- package/testing/edge.js +2 -0
- package/testing/edge.js.map +1 -0
- package/testing/parse-response.d.ts +12 -0
- package/testing/parse-response.js +2 -0
- package/testing/parse-response.js.map +1 -0
- package/testing/playwright.d.ts +17 -0
- package/testing/playwright.js +2 -0
- package/testing/playwright.js.map +1 -0
- package/testing/requests.d.ts +6 -0
- package/testing/requests.js +2 -0
- package/testing/requests.js.map +1 -0
- package/testing/response.d.ts +46 -0
- package/testing/response.js +2 -0
- package/testing/response.js.map +1 -0
- package/testing.d.ts +9 -0
- package/testing.js +2 -0
- package/testing.js.map +1 -0
package/README.md
CHANGED
|
@@ -155,6 +155,8 @@ The [example projects guide](./docs/examples/index.md) explains the wiring in ea
|
|
|
155
155
|
|
|
156
156
|
## Documentation
|
|
157
157
|
|
|
158
|
+
Test SSR routes without a server with `@lomray/vite-ssr-boost/testing`; see the [Vitest and Playwright guide](https://lomray-software.github.io/vite-ssr-boost/guide/testing).
|
|
159
|
+
|
|
158
160
|
- [Documentation site](https://lomray-software.github.io/vite-ssr-boost/), [comparison guide](./docs/guide/choosing.md) and [FAQ](./docs/reference/faq.md).
|
|
159
161
|
- [Hydration order and streaming](./docs/reference/hydration-and-streaming.md).
|
|
160
162
|
- API: [Plugin](./docs/api/plugin.md), [Browser entry](./docs/api/browser-entry.md), [Server entry](./docs/api/server-entry.md), [Node production](./docs/api/node-production.md), [Components and helpers](./docs/api/components-and-helpers.md) and [CLI](./docs/api/cli.md).
|
|
@@ -27,6 +27,7 @@ export interface IRequestContext<TAppProps = Record<any, any>> {
|
|
|
27
27
|
matches?: RouterState['matches'];
|
|
28
28
|
hasEarlyHints?: boolean;
|
|
29
29
|
didError?: StreamError;
|
|
30
|
+
timeline?: ISsrRequestContext<TAppProps>['timeline'];
|
|
30
31
|
}
|
|
31
32
|
export type TRender<TAppProps = Record<any, any>> = (config: ServerConfig, context: Omit<IRequestContext<TAppProps>, 'request' | 'response'>, options: IRenderOptions) => Promise<void>;
|
|
32
33
|
export interface IRenderParams<TAppProps = Record<string, any>> {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"chalk";import
|
|
1
|
+
import e from"chalk";import t from"react";import s from"./create-request.js";import r from"../../constants/stream-error.js";import o from"../../core/early-hints.js";import{getSetCookieHeaders as n,getHeaderEntries as a}from"../../core/headers.js";import i from"../../core/render.js";import d from"../../node/render-to-stream.js";import c from"../../node/request-signal.js";import p from"../../node/write-early-hints.js";import m,{writeFetchHeaders as l}from"../../node/write-fetch-response.js";import h,{isDiagnosticsEnabled as u}from"../../services/diagnostics.js";import f from"../../services/ssr-manifest.js";const y=(e,t,r)=>{const o={signal:t};return r&&"GET"!==e.method&&"HEAD"!==e.method&&(o.body=r(e)??null),s(e,o)},g=(e,t,s)=>{if(!t.headersSent&&!t.writableEnded){e.response.status!==s.status&&t.status(e.response.status??200);const r=new Set([...s.headers.keys(),...e.response.headers.keys()]);for(const o of r)e.response.headers.get(o)!==s.headers.get(o)&&(e.response.headers.has(o)?t.setHeader(o,"set-cookie"===o?n(e.response.headers):e.response.headers.get(o)):t.removeHeader(o))}const r=new Headers(e.response.headers);r.delete("Set-Cookie");for(const[e,s]of Object.entries(t.getHeaders()))if("set-cookie"!==e.toLowerCase()&&void 0!==s)if(Array.isArray(s))for(const t of s)r.append(e,t);else r.set(e,"number"==typeof s?String(s):s);e.response.headers=r,e.response.status=t.statusCode};async function S({App:s,handler:S,policy:x,spaShell:w},v,E,{onRouterReady:b,onShellReady:C,onResponse:j,onShellError:R,onError:H,getBody:q,getState:k,hydration:A,nonce:P,bootstrapScriptContent:D,documentHeaders:L,sessionCookie:O,protectPrivate:T,abortDelay:B=15e3}){const{appProps:G,html:U,req:$,res:z}=E,F=v.getLogger(),I=c($,z);try{const c=Object.assign(E,{request:y($,I.signal,q),response:{headers:new Headers}}),J={appProps:G,diagnostics:u(!v.isProd)?new h(new URL(c.request.url).pathname,F):void 0,html:U,request:c.request,response:c.response};if(!v.isProd&&J.diagnostics){const{diagnostics:e}=J;for(const t of["req","res"]){let s=c[t];Object.defineProperty(c,t,{configurable:!0,enumerable:!0,get:()=>(e.deprecatedReqRes(),s),set:e=>{s=e}})}}g(J,z,{headers:new Headers(J.response.headers),status:J.response.status}),200===J.response.status&&(J.response.status=void 0);const K=e=>(c.request=e.request,c.response=e.response,c.didError=e.didError,c.html=e.html,c.isStream=e.isStream,c.isSpa=e.isSpa,c.matches=e.matches,c.routerContext=e.routerContext,c.serverContext=e.serverContext,c.timeline=e.timeline,c),M=await i({createApp:(e,r)=>t.createElement(s,{server:{...r.appProps,req:$}},e),handler:S,policy:x,spaShell:w,renderToStream:d},J,{abortDelay:B,hydration:A,nonce:P,bootstrapScriptContent:D,documentHeaders:L,sessionCookie:O,protectPrivate:T,getState:k?({context:e})=>k({context:K(e)}):void 0,onError:({context:t,error:s})=>{const{code:o,message:n}=s;if(H?.({context:K(t),error:s}),F.info(e.red(`Stream error. Code: ${o}`)),[r.RenderAborted,r.RenderTimeout,r.RenderCancel].includes(o))return void F.info(e.dim(n));const{original:a}=s;F.error(a)},onResponse:j?({context:e,html:t,isEnd:s})=>j({context:K(e),html:t,isEnd:s}):void 0,onRouterReady:b?({context:e})=>b({context:K(e)}):void 0,onShellError:R?({context:e,error:t})=>R({context:K(e),error:t}):void 0,onShellReady:({context:e})=>{const t=K(e);((e,t)=>{if(t.headersSent||t.writableEnded)return;t.status(e.response.status??200),a(e.response.headers).forEach(([e,s])=>t.setHeader(e,s));const s=n(e.response.headers);s.length&&t.setHeader("Set-Cookie",s)})(e,z);const s={headers:new Headers(e.response.headers),status:e.response.status},r=C?.({context:t});return g(e,z,s),r??{}},prepare:async({context:e,executionContext:t})=>{const s=K(e),r=f.get(v);await r.prepareDevAssets(e.matches,e.isSpa);const n=r.injectAssets(s);s.hasEarlyHints&&await o(t,n)},routerRequestContext:c},{onEarlyHints:e=>p(z,e)});K(J),await(async(e,t)=>{const s=t.headers.get("Location");if(s&&t.status>=300&&t.status<400&&!e.headersSent&&!e.writableEnded&&!e.destroyed)return l(e,t),await(t.body?.cancel()),void e.redirect(t.status,s);await m(e,t)})(z,M)}finally{I.dispose()}}export{S as default};
|
|
2
2
|
//# sourceMappingURL=render.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sources":["../../../src/adapters/express/render.tsx"],"sourcesContent":[null],"names":["createRenderRequest","req","signal","getBody","options","method","body","createFetchRequest","syncResponse","context","res","previous","headersSent","writableEnded","response","status","names","Set","headers","keys","name","get","has","setHeader","getSetCookieHeaders","removeHeader","Headers","delete","value","Object","entries","getHeaders","toLowerCase","undefined","Array","isArray","item","append","set","String","statusCode","async","render","App","handler","policy","spaShell","config","initialContext","onRouterReady","onShellReady","onResponse","onShellError","onError","getState","hydration","nonce","bootstrapScriptContent","documentHeaders","sessionCookie","protectPrivate","abortDelay","appProps","html","shellHtml","Logger","getLogger","requestSignal","createRequestSignal","assign","request","coreContext","diagnostics","isDiagnosticsEnabled","isProd","Diagnostics","URL","url","pathname","defineProperty","configurable","enumerable","deprecatedReqRes","next","syncContext","updated","didError","isStream","isSpa","matches","routerContext","serverContext","coreRender","createApp","children","React","createElement","server","renderToStream","error","code","message","info","chalk","red","StreamError","RenderAborted","RenderTimeout","RenderCancel","includes","dim","original","isEnd","legacyContext","getHeaderEntries","forEach","cookies","length","prepareResponse","shell","prepare","executionContext","manifest","SsrManifest","prepareDevAssets","hints","injectAssets","hasEarlyHints","emitEarlyHints","routerRequestContext","onEarlyHints","writeEarlyHints","location","destroyed","writeFetchHeaders","cancel","redirect","writeFetchResponse","writeResponse","dispose"],"mappings":"
|
|
1
|
+
{"version":3,"file":"render.js","sources":["../../../src/adapters/express/render.tsx"],"sourcesContent":[null],"names":["createRenderRequest","req","signal","getBody","options","method","body","createFetchRequest","syncResponse","context","res","previous","headersSent","writableEnded","response","status","names","Set","headers","keys","name","get","has","setHeader","getSetCookieHeaders","removeHeader","Headers","delete","value","Object","entries","getHeaders","toLowerCase","undefined","Array","isArray","item","append","set","String","statusCode","async","render","App","handler","policy","spaShell","config","initialContext","onRouterReady","onShellReady","onResponse","onShellError","onError","getState","hydration","nonce","bootstrapScriptContent","documentHeaders","sessionCookie","protectPrivate","abortDelay","appProps","html","shellHtml","Logger","getLogger","requestSignal","createRequestSignal","assign","request","coreContext","diagnostics","isDiagnosticsEnabled","isProd","Diagnostics","URL","url","pathname","defineProperty","configurable","enumerable","deprecatedReqRes","next","syncContext","updated","didError","isStream","isSpa","matches","routerContext","serverContext","timeline","coreRender","createApp","children","React","createElement","server","renderToStream","error","code","message","info","chalk","red","StreamError","RenderAborted","RenderTimeout","RenderCancel","includes","dim","original","isEnd","legacyContext","getHeaderEntries","forEach","cookies","length","prepareResponse","shell","prepare","executionContext","manifest","SsrManifest","prepareDevAssets","hints","injectAssets","hasEarlyHints","emitEarlyHints","routerRequestContext","onEarlyHints","writeEarlyHints","location","destroyed","writeFetchHeaders","cancel","redirect","writeFetchResponse","writeResponse","dispose"],"mappings":"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"}
|
package/browser/entry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"react";import t from"react-dom/client";import{matchRoutes as o,createBrowserRouter as r,RouterProvider as n}from"react-router";import a from"./stream.js";import{IS_SSR_MODE as i}from"../constants/common.js";async function c(c,d,{init:
|
|
1
|
+
import e from"react";import t from"react-dom/client";import{matchRoutes as o,createBrowserRouter as r,RouterProvider as n}from"react-router";import a from"./stream.js";import{IS_SSR_MODE as i}from"../constants/common.js";async function c(c,d,{init:s,routerOptions:l,createRouter:m=r,rootId:u="root"}={}){const w=i?a():void 0,f=(()=>{const e="__staticRouterHydrationData";if(!("loading"!==document.readyState||i&&void 0!==Reflect.get(window,e)))return new Promise(t=>{const o=()=>{i&&Reflect.deleteProperty(window,e),t()};document.addEventListener("DOMContentLoaded",o,{once:!0}),i&&Object.defineProperty(window,e,{configurable:!0,enumerable:!0,get:()=>{},set:r=>{Object.defineProperty(window,e,{configurable:!0,enumerable:!0,writable:!0,value:r}),document.removeEventListener("DOMContentLoaded",o),t()}})})})(),y=o(d,window.location,l?.basename)?.filter(e=>e.route.lazy);(f||y?.length)&&await Promise.all([f,...(y??[]).map(async e=>{const{lazy:t}=e.route;if("function"==typeof t){const o=await t();o&&Object.assign(e.route,{...o,lazy:void 0})}})]);const p=Reflect.get(window,"__staticRouterHydrationData");w&&p?.__ssrBoostStream&&Reflect.set(window,"__staticRouterHydrationData",await w.ready);const R=m(d,l),b=document.getElementById(u),E=i&&"1"!==b.dataset.forceSpa&&"1"!==document.documentElement.dataset.forceSpa;i&&(Reflect.deleteProperty(window,"__staticRouterHydrationData"),E&&window.dispatchEvent(new CustomEvent("ssr-boost:router-ready",{detail:{rootId:u}})));const _=await(s?.({isSSRMode:E,router:R})),g=()=>e.createElement(c,{client:_},e.createElement(n,{router:R}));return E?t.hydrateRoot(b,e.createElement(g,null)):t.createRoot(b).render(e.createElement(g,null))}export{c as default,c as entry};
|
|
2
2
|
//# sourceMappingURL=entry.js.map
|
package/browser/entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.js","sources":["../../src/browser/entry.tsx"],"sourcesContent":[null],"names":["async","entry","App","routes","init","routerOptions","createRouter","createBrowserRouter","rootId","stream","IS_SSR_MODE","receiveStream","undefined","documentReady","hydrationKey","document","readyState","Reflect","get","window","Promise","resolve","onReady","deleteProperty","addEventListener","once","Object","defineProperty","configurable","enumerable","set","value","writable","removeEventListener","waitForDocument","lazyMatches","matchRoutes","location","basename","filter","m","route","lazy","length","all","map","lazyResult","assign","hydration","__ssrBoostStream","ready","router","root","getElementById","isSSRMode","dataset","documentElement","appProps","AppComponent","React","createElement","client","RouterProvider","ReactDOM","hydrateRoot","createRoot","render"],"mappings":"6NA0EAA,eAAeC,EACbC,EACAC,GACAC,KACEA,EAAIC,cACJA,EAAaC,aACbA,EAAeC,EAAmBC,OAClCA,EAAS,QACyB,CAAA,GAEpC,MAAMC,EAASC,EAAcC,SAAkBC,EACzCC,EAvDgB,MACtB,MAAMC,EAAe,8BAErB,KAC0B,YAAxBC,SAASC,YACRN,QAAqDE,IAAtCK,QAAQC,IAAIC,OAAQL,IAKtC,OAAO,IAAIM,QAAeC,IACxB,MAAMC,EAAU,KACVZ,GACFO,QAAQM,eAAeJ,OAAQL,GAGjCO,KAGFN,SAASS,iBAAiB,mBAAoBF,EAAS,CAAEG,MAAM,IAE3Df,GACFgB,OAAOC,eAAeR,OAAQL,EAAc,CAC1Cc,cAAc,EACdC,YAAY,EACZX,IAAK,OACLY,IAAMC,IACJL,OAAOC,eAAeR,OAAQL,EAAc,CAC1Cc,cAAc,EACdC,YAAY,EACZG,UAAU,EACVD,UAEFhB,SAASkB,oBAAoB,mBAAoBX,GACjDD,UAqBca,GAChBC,EAAcC,EAClBjC,EACAgB,OAAOkB,SACPhC,GAAeiC,WACdC,OAAQC,GAAMA,EAAEC,MAAMC,OAIrB7B,GAAiBsB,GAAaQ,eAC1BvB,QAAQwB,IAAI,CAChB/B,MACIsB,GAAe,IAAIU,IAAI7C,MAAOwC,IAChC,MAAME,KAAEA,GAASF,EAAEC,MAEnB,GAAoB,mBAATC,EAAqB,CAC9B,MAAMI,QAAmBJ,IAErBI,GACFpB,OAAOqB,OAAOP,EAAEC,MAAO,IAClBK,EACHJ,UAAM9B,GAGZ,MAKN,MAAMoC,EAAY/B,QAAQC,IAAIC,OAAQ,+BAGlCV,GAAUuC,GAAWC,kBACvBhC,QAAQa,IAAIX,OAAQ,oCAAqCV,EAAOyC,OAGlE,MAAMC,EAAS7C,EAAaH,EAAyBE,GAC/C+C,EAAOrC,SAASsC,eAAe7C,GAC/B8C,EACJ5C,GAC6B,MAA7B0C,EAAKG,QAAkB,UAC0B,MAAjDxC,SAASyC,gBAAgBD,QAAkB,
|
|
1
|
+
{"version":3,"file":"entry.js","sources":["../../src/browser/entry.tsx"],"sourcesContent":[null],"names":["async","entry","App","routes","init","routerOptions","createRouter","createBrowserRouter","rootId","stream","IS_SSR_MODE","receiveStream","undefined","documentReady","hydrationKey","document","readyState","Reflect","get","window","Promise","resolve","onReady","deleteProperty","addEventListener","once","Object","defineProperty","configurable","enumerable","set","value","writable","removeEventListener","waitForDocument","lazyMatches","matchRoutes","location","basename","filter","m","route","lazy","length","all","map","lazyResult","assign","hydration","__ssrBoostStream","ready","router","root","getElementById","isSSRMode","dataset","documentElement","dispatchEvent","CustomEvent","detail","appProps","AppComponent","React","createElement","client","RouterProvider","ReactDOM","hydrateRoot","createRoot","render"],"mappings":"6NA0EAA,eAAeC,EACbC,EACAC,GACAC,KACEA,EAAIC,cACJA,EAAaC,aACbA,EAAeC,EAAmBC,OAClCA,EAAS,QACyB,CAAA,GAEpC,MAAMC,EAASC,EAAcC,SAAkBC,EACzCC,EAvDgB,MACtB,MAAMC,EAAe,8BAErB,KAC0B,YAAxBC,SAASC,YACRN,QAAqDE,IAAtCK,QAAQC,IAAIC,OAAQL,IAKtC,OAAO,IAAIM,QAAeC,IACxB,MAAMC,EAAU,KACVZ,GACFO,QAAQM,eAAeJ,OAAQL,GAGjCO,KAGFN,SAASS,iBAAiB,mBAAoBF,EAAS,CAAEG,MAAM,IAE3Df,GACFgB,OAAOC,eAAeR,OAAQL,EAAc,CAC1Cc,cAAc,EACdC,YAAY,EACZX,IAAK,OACLY,IAAMC,IACJL,OAAOC,eAAeR,OAAQL,EAAc,CAC1Cc,cAAc,EACdC,YAAY,EACZG,UAAU,EACVD,UAEFhB,SAASkB,oBAAoB,mBAAoBX,GACjDD,UAqBca,GAChBC,EAAcC,EAClBjC,EACAgB,OAAOkB,SACPhC,GAAeiC,WACdC,OAAQC,GAAMA,EAAEC,MAAMC,OAIrB7B,GAAiBsB,GAAaQ,eAC1BvB,QAAQwB,IAAI,CAChB/B,MACIsB,GAAe,IAAIU,IAAI7C,MAAOwC,IAChC,MAAME,KAAEA,GAASF,EAAEC,MAEnB,GAAoB,mBAATC,EAAqB,CAC9B,MAAMI,QAAmBJ,IAErBI,GACFpB,OAAOqB,OAAOP,EAAEC,MAAO,IAClBK,EACHJ,UAAM9B,GAGZ,MAKN,MAAMoC,EAAY/B,QAAQC,IAAIC,OAAQ,+BAGlCV,GAAUuC,GAAWC,kBACvBhC,QAAQa,IAAIX,OAAQ,oCAAqCV,EAAOyC,OAGlE,MAAMC,EAAS7C,EAAaH,EAAyBE,GAC/C+C,EAAOrC,SAASsC,eAAe7C,GAC/B8C,EACJ5C,GAC6B,MAA7B0C,EAAKG,QAAkB,UAC0B,MAAjDxC,SAASyC,gBAAgBD,QAAkB,SAEzC7C,IACFO,QAAQM,eAAeJ,OAAQ,+BAE3BmC,GACFnC,OAAOsC,cAAc,IAAIC,YAAY,yBAA0B,CAAEC,OAAQ,CAAEnD,cAI/E,MAAMoD,QAAkBxD,IAAO,CAAEkD,YAAWH,YAEtCU,EAAmB,IACvBC,EAAAC,cAAC7D,EAAG,CAAC8D,OAAQJ,GACXE,EAAAC,cAACE,GAAed,OAAQA,KAI5B,OAAKG,EAIEY,EAASC,YAAYf,EAAMU,EAAAC,cAACF,EAAY,OAHtCK,EAASE,WAAWhB,GAAMiB,OAAOP,EAAAC,cAACF,EAAY,MAIzD"}
|
package/core/compose-html.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type DataStream from './data-stream.js';
|
|
2
|
+
import type RequestTimeline from '../services/request-timeline.js';
|
|
2
3
|
/** Stream shell, data frames, React bytes and footer only under downstream demand. */
|
|
3
|
-
declare const composeHtml: (header: string, body: ReadableStream<Uint8Array>, footer: string, abort?: (reason?: unknown) => void, onComplete?: () => void, data?: DataStream) => ReadableStream<Uint8Array>;
|
|
4
|
+
declare const composeHtml: (header: string, body: ReadableStream<Uint8Array>, footer: string, abort?: (reason?: unknown) => void, onComplete?: () => void, data?: DataStream, timeline?: RequestTimeline, isEarly?: boolean) => ReadableStream<Uint8Array>;
|
|
4
5
|
export default composeHtml;
|
package/core/compose-html.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"./html-boundary.js";const
|
|
1
|
+
import e from"./html-boundary.js";const t=(t,n,r,a,o,c,i,d=!1)=>{const l=new TextEncoder,u=n.getReader();let s,f="header",y=!1,h=!1;const m=e();let v,w=!0;const b=()=>{h||(h=!0,u.releaseLock())};return new ReadableStream({cancel:async e=>{y=!0,a?.(e),c?.cancel();try{h||await u.cancel(e)}finally{b(),o?.()}},async pull(e){try{if("header"===f&&(f="body",t))return d&&i?.record("state.emitted",{placement:"early"}),void e.enqueue(l.encode(t));for(;!y;){const t=w?c?.take():void 0;if(y)return;if(t)return void e.enqueue(l.encode(t));if(v)return w=m(v),e.enqueue(v),void(v=void 0);if("body"===f){s??=u.read();const e=await(c&&!c.isDone&&w?Promise.race([s,c.changed().then(()=>{})]):s);if(y)return;if(!e)continue;if(s=void 0,!e.done){v=e.value;continue}f="footer",i?.record("body.end"),w=!0,b();continue}!c||c.isDone?(r&&(d||i?.record("state.emitted",{placement:"footer"}),e.enqueue(l.encode(r))),y=!0,o?.(),e.close()):await c.changed()}}catch(t){if(y)return;y=!0,a?.(t),c?.cancel(),e.error(t);try{h||await u.cancel(t).catch(()=>{})}finally{b(),o?.()}}}},{highWaterMark:0})};export{t as default};
|
|
2
2
|
//# sourceMappingURL=compose-html.js.map
|
package/core/compose-html.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose-html.js","sources":["../../src/core/compose-html.ts"],"sourcesContent":[null],"names":["composeHtml","header","body","footer","abort","onComplete","data","encoder","TextEncoder","reader","getReader","pendingRead","phase","isStopped","isReleased","observe","htmlBoundary","heldChunk","canInject","release","releaseLock","ReadableStream","cancel","async","reason","pull","controller","enqueue","encode","frames","take","undefined","read","chunk","isDone","Promise","race","changed","then","done","value","close","error","catch","highWaterMark"],"mappings":"
|
|
1
|
+
{"version":3,"file":"compose-html.js","sources":["../../src/core/compose-html.ts"],"sourcesContent":[null],"names":["composeHtml","header","body","footer","abort","onComplete","data","timeline","isEarly","encoder","TextEncoder","reader","getReader","pendingRead","phase","isStopped","isReleased","observe","htmlBoundary","heldChunk","canInject","release","releaseLock","ReadableStream","cancel","async","reason","pull","controller","record","placement","enqueue","encode","frames","take","undefined","read","chunk","isDone","Promise","race","changed","then","done","value","close","error","catch","highWaterMark"],"mappings":"kCAKA,MAAMA,EAAc,CAClBC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,GAAU,KAEV,MAAMC,EAAU,IAAIC,YACdC,EAAST,EAAKU,YACpB,IAGIC,EAHAC,EAAsC,SACtCC,GAAY,EACZC,GAAa,EAEjB,MAAMC,EAAUC,IAChB,IACIC,EADAC,GAAY,EAIhB,MAAMC,EAAU,KACTL,IACHA,GAAa,EACbL,EAAOW,gBAIX,OAAO,IAAIC,eACT,CAEEC,OAAQC,MAAOC,IACbX,GAAY,EACZX,IAAQsB,GACRpB,GAAMkB,SAEN,IACOR,SACGL,EAAOa,OAAOE,EAExB,SACEL,IACAhB,KACF,GAIF,UAAMsB,CAAKC,GACT,IACE,GAAc,WAAVd,IACFA,EAAQ,OAEJb,GAOF,OANIO,GACFD,GAAUsB,OAAO,gBAAiB,CAAEC,UAAW,eAGjDF,EAAWG,QAAQtB,EAAQuB,OAAO/B,IAMtC,MAAQc,GAAW,CACjB,MAAMkB,EAASb,EAAYd,GAAM4B,YAASC,EAE1C,GAAIpB,EACF,OAGF,GAAIkB,EAGF,YAFAL,EAAWG,QAAQtB,EAAQuB,OAAOC,IAKpC,GAAId,EAKF,OAJAC,EAAYH,EAAQE,GACpBS,EAAWG,QAAQZ,QACnBA,OAAYgB,GAKd,GAAc,SAAVrB,EAAkB,CACpBD,IAAgBF,EAAOyB,OACvB,MAAMC,QAAe/B,IAASA,EAAKgC,QAAUlB,EACzCmB,QAAQC,KAAK,CAAC3B,EAAaP,EAAKmC,UAAUC,KAAK,UAC/C7B,GAEJ,GAAIE,EACF,OAGF,IAAKsB,EACH,SAKF,GAFAxB,OAAcsB,GAETE,EAAMM,KAAM,CACfxB,EAAYkB,EAAMO,MAElB,QACF,CAEA9B,EAAQ,SACRP,GAAUsB,OAAO,YACjBT,GAAY,EACZC,IACA,QACF,EAEIf,GAASA,EAAKgC,QAKdnC,IACGK,GACHD,GAAUsB,OAAO,gBAAiB,CAAEC,UAAW,WAGjDF,EAAWG,QAAQtB,EAAQuB,OAAO7B,KAGpCY,GAAY,EACZV,MACAuB,EAAWiB,eAdHvC,EAAKmC,SAef,CACF,CAAE,MAAOK,GACP,GAAI/B,EACF,OAGFA,GAAY,EACZX,IAAQ0C,GACRxC,GAAMkB,SACNI,EAAWkB,MAAMA,GAEjB,IACO9B,SACGL,EAAOa,OAAOsB,GAAOC,MAAM,OAErC,SACE1B,IACAhB,KACF,CACF,CACF,GAEF,CAAE2C,cAAe"}
|
package/core/data-stream.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { StaticHandlerContext } from 'react-router';
|
|
2
2
|
import type Diagnostics from '../services/diagnostics.js';
|
|
3
|
+
import type RequestTimeline from '../services/request-timeline.js';
|
|
3
4
|
interface IPending {
|
|
4
5
|
settled: boolean;
|
|
5
6
|
}
|
|
@@ -13,6 +14,7 @@ declare const errorProperties: (reason: unknown, diagnostics: boolean) => Record
|
|
|
13
14
|
declare class DataStream {
|
|
14
15
|
protected readonly diagnostics?: Diagnostics | undefined;
|
|
15
16
|
protected readonly nonce?: string | undefined;
|
|
17
|
+
protected readonly timeline?: RequestTimeline | undefined;
|
|
16
18
|
readonly initial: string;
|
|
17
19
|
readonly done: Promise<void>;
|
|
18
20
|
protected resolveDone: () => void;
|
|
@@ -25,7 +27,7 @@ declare class DataStream {
|
|
|
25
27
|
protected stopped: boolean;
|
|
26
28
|
protected aborted: boolean;
|
|
27
29
|
protected nextId: number;
|
|
28
|
-
constructor(context: StaticHandlerContext, diagnostics?: Diagnostics | undefined, nonce?: string | undefined);
|
|
30
|
+
constructor(context: StaticHandlerContext, diagnostics?: Diagnostics | undefined, nonce?: string | undefined, timeline?: RequestTimeline | undefined);
|
|
29
31
|
/** Use the codec's public plugin API, without depending on React Router internals. */
|
|
30
32
|
protected promiseId: (value: unknown) => [number] | false;
|
|
31
33
|
/** Encode one complete value, preserving the codec's built-in value representations. */
|
package/core/data-stream.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{stringify as t}from"devalue";import{isRouteErrorResponse as e}from"react-router";import i,{streamScript as s}from"./script.js";import o from"../helpers/serialize-errors.js";const r=(t,i)=>{const s=t,o=e(t),r="DataWithResponseInit"===s?.type,n=o?t.status:s?.init?.status,a=o?t.statusText:s?.init?.statusText,c={message:s?.message??(o||r?a||`Route data error (${n??500})`:String(t)),name:s?.name??"Error"};return(o||r)&&Object.assign(c,{status:n??500,statusText:a??"",data:s?.data,internal:!1}),i&&s?.stack&&(c.stack=s.stack),c};class n{diagnostics;nonce;initial;done;resolveDone;notify;change;identities=new WeakMap;pending=new Map;frames=[];initialized=!1;stopped=!1;aborted=!1;nextId=0;constructor(t,e,i){this.diagnostics=e,this.nonce=i,e?.inspectRouterState(t),this.done=new Promise(t=>{this.resolveDone=t});try{this.initial=this.encodeValue({loaderData:t.loaderData,actionData:t.actionData,errors:o(t.errors)}),this.initialized=!0,this.wake()}catch(t){throw this.cancel(),t}}promiseId=t=>{if(t instanceof Promise){let e=this.identities.get(t);if(void 0===e){e=this.nextId++,this.identities.set(t,e),this.pending.set(e,{settled:!1});const i=e;t.then(t=>this.settle(i,t,!1),t=>this.settle(i,t,!0)),this.aborted&&this.settle(e,new Error("SSR loader/action promise aborted before it settled."),!0)}return[e]}return!1};encodeValue(i){return t(i,{SSRBPromise:this.promiseId,SSRBError:t=>(t instanceof Error||e(t))&&Object.entries(r(t,Boolean(this.diagnostics))),SSRBObject:t=>Boolean(t&&"object"==typeof t&&Object.hasOwn(t,"__proto__"))&&Object.entries(t),SSRBUndefined:t=>"function"==typeof t||"symbol"==typeof t||Boolean(t&&"object"==typeof t&&!Array.isArray(t)&&![Object.prototype,null,Date.prototype,Map.prototype,Set.prototype,RegExp.prototype,Promise.prototype,Error.prototype].includes(Object.getPrototypeOf(t)))})}settle(t,e,i){const o=this.pending.get(t);if(o&&!o.settled&&!this.stopped){o.settled=!0,i||this.diagnostics?.inspectStreamValue(e,t);try{const o=this.encodeValue(i?Object.assign(new Error("Streamed loader/action rejection"),r(e,Boolean(this.diagnostics))):e);this.frames.push(s([i?"reject":"resolve",t,o],this.nonce))}catch(e){const i=this.encodeValue(new Error(`Cannot serialize streamed value: ${String(e)}`));this.frames.push(s(["reject",t,i],this.nonce))}finally{this.pending.delete(t),this.wake()}}}wake(){this.notify?.(),this.notify=void 0,this.change=void 0,this.initialized&&!this.pending.size&&this.resolveDone()}get isDone(){return this.initialized&&!this.pending.size}changed(){return this.frames.length||this.isDone?Promise.resolve():this.change??=new Promise(t=>{this.notify=t})}take(){return this.frames.splice(0).join("")}state(t){const{initial:e}=this;return i("window.__staticRouterHydrationData = {__ssrBoostStream: true};",this.nonce,!0)+s(["init",e,t],this.nonce)}abort(){this.aborted=!0;let t=0;for(const[e,i]of this.pending)i.settled||(t++,this.settle(e,new Error("SSR loader/action promise aborted before it settled."),!0));t&&this.diagnostics?.streamAborted(t)}cancel(){this.stopped=!0,this.initialized=!0,this.pending.clear(),this.frames.length=0,this.wake()}}export{n as default,r as errorProperties};
|
|
1
|
+
import{stringify as t}from"devalue";import{isRouteErrorResponse as e}from"react-router";import i,{streamScript as s}from"./script.js";import o from"../helpers/serialize-errors.js";const r=(t,i)=>{const s=t,o=e(t),r="DataWithResponseInit"===s?.type,n=o?t.status:s?.init?.status,a=o?t.statusText:s?.init?.statusText,c={message:s?.message??(o||r?a||`Route data error (${n??500})`:String(t)),name:s?.name??"Error"};return(o||r)&&Object.assign(c,{status:n??500,statusText:a??"",data:s?.data,internal:!1}),i&&s?.stack&&(c.stack=s.stack),c};class n{diagnostics;nonce;timeline;initial;done;resolveDone;notify;change;identities=new WeakMap;pending=new Map;frames=[];initialized=!1;stopped=!1;aborted=!1;nextId=0;constructor(t,e,i,s){this.diagnostics=e,this.nonce=i,this.timeline=s,e?.inspectRouterState(t),this.done=new Promise(t=>{this.resolveDone=t});try{this.initial=this.encodeValue({loaderData:t.loaderData,actionData:t.actionData,errors:o(t.errors)}),this.initialized=!0,this.wake()}catch(t){throw this.cancel(),t}}promiseId=t=>{if(t instanceof Promise){let e=this.identities.get(t);if(void 0===e){e=this.nextId++,this.identities.set(t,e),this.pending.set(e,{settled:!1});const i=e;t.then(t=>this.settle(i,t,!1),t=>this.settle(i,t,!0)),this.aborted&&this.settle(e,new Error("SSR loader/action promise aborted before it settled."),!0)}return[e]}return!1};encodeValue(i){return t(i,{SSRBPromise:this.promiseId,SSRBError:t=>(t instanceof Error||e(t))&&Object.entries(r(t,Boolean(this.diagnostics))),SSRBObject:t=>Boolean(t&&"object"==typeof t&&Object.hasOwn(t,"__proto__"))&&Object.entries(t),SSRBUndefined:t=>"function"==typeof t||"symbol"==typeof t||Boolean(t&&"object"==typeof t&&!Array.isArray(t)&&![Object.prototype,null,Date.prototype,Map.prototype,Set.prototype,RegExp.prototype,Promise.prototype,Error.prototype].includes(Object.getPrototypeOf(t)))})}settle(t,e,i){const o=this.pending.get(t);if(o&&!o.settled&&!this.stopped){o.settled=!0,i||this.diagnostics?.inspectStreamValue(e,t);try{const o=this.encodeValue(i?Object.assign(new Error("Streamed loader/action rejection"),r(e,Boolean(this.diagnostics))):e);this.frames.push(s([i?"reject":"resolve",t,o],this.nonce)),this.timeline?.record(i?"stream.reject":"stream.resolve",{id:t})}catch(e){const i=this.encodeValue(new Error(`Cannot serialize streamed value: ${String(e)}`));this.frames.push(s(["reject",t,i],this.nonce)),this.timeline?.record("stream.reject",{id:t})}finally{this.pending.delete(t),this.wake()}}}wake(){this.notify?.(),this.notify=void 0,this.change=void 0,this.initialized&&!this.pending.size&&this.resolveDone()}get isDone(){return this.initialized&&!this.pending.size}changed(){return this.frames.length||this.isDone?Promise.resolve():this.change??=new Promise(t=>{this.notify=t})}take(){return this.frames.splice(0).join("")}state(t){const{initial:e}=this;return i("window.__staticRouterHydrationData = {__ssrBoostStream: true};",this.nonce,!0)+s(["init",e,t],this.nonce)}abort(){this.aborted=!0;let t=0;for(const[e,i]of this.pending)i.settled||(t++,this.settle(e,new Error("SSR loader/action promise aborted before it settled."),!0));t&&this.diagnostics?.streamAborted(t)}cancel(){this.stopped=!0,this.initialized=!0,this.pending.clear(),this.frames.length=0,this.wake()}}export{n as default,r as errorProperties};
|
|
2
2
|
//# sourceMappingURL=data-stream.js.map
|
package/core/data-stream.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-stream.js","sources":["../../src/core/data-stream.ts"],"sourcesContent":[null],"names":["errorProperties","reason","diagnostics","value","isResponse","isRouteErrorResponse","isDataError","type","status","init","statusText","properties","message","String","name","Object","assign","data","internal","stack","DataStream","nonce","initial","done","resolveDone","notify","change","identities","WeakMap","pending","Map","frames","initialized","stopped","aborted","nextId","constructor","context","this","inspectRouterState","Promise","resolve","encodeValue","loaderData","actionData","errors","serializeErrors","wake","error","cancel","promiseId","id","get","undefined","set","settled","then","result","settle","Error","stringify","SSRBPromise","SSRBError","entries","Boolean","SSRBObject","item","hasOwn","SSRBUndefined","Array","isArray","prototype","Date","Set","RegExp","includes","getPrototypeOf","rejected","inspectStreamValue","payload","push","streamScript","delete","size","isDone","changed","length","take","splice","join","state","isEarly","script","abort","count","streamAborted","clear"],"mappings":"
|
|
1
|
+
{"version":3,"file":"data-stream.js","sources":["../../src/core/data-stream.ts"],"sourcesContent":[null],"names":["errorProperties","reason","diagnostics","value","isResponse","isRouteErrorResponse","isDataError","type","status","init","statusText","properties","message","String","name","Object","assign","data","internal","stack","DataStream","nonce","timeline","initial","done","resolveDone","notify","change","identities","WeakMap","pending","Map","frames","initialized","stopped","aborted","nextId","constructor","context","this","inspectRouterState","Promise","resolve","encodeValue","loaderData","actionData","errors","serializeErrors","wake","error","cancel","promiseId","id","get","undefined","set","settled","then","result","settle","Error","stringify","SSRBPromise","SSRBError","entries","Boolean","SSRBObject","item","hasOwn","SSRBUndefined","Array","isArray","prototype","Date","Set","RegExp","includes","getPrototypeOf","rejected","inspectStreamValue","payload","push","streamScript","record","delete","size","isDone","changed","length","take","splice","join","state","isEarly","script","abort","count","streamAborted","clear"],"mappings":"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"}
|
package/core/handler.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ICoreRenderOptions, ICoreRenderParams } from './render.js';
|
|
1
|
+
import type { ICoreRenderOptions, ICoreRenderParams, ISsrRequestContext } from './render.js';
|
|
2
2
|
import type { ISsrPolicy } from './ssr-policy.js';
|
|
3
3
|
import type { ISsrExecutionContext, TSsrHandler } from './types.js';
|
|
4
4
|
interface IHtmlShell {
|
|
@@ -23,6 +23,10 @@ interface ICreateHandlerOptions<TAppProps> extends ICoreRenderOptions<TAppProps>
|
|
|
23
23
|
* Supply the document shell, including the application's browser entry script.
|
|
24
24
|
*/
|
|
25
25
|
getHtml: (request: Request) => IHtmlShell | Promise<IHtmlShell>;
|
|
26
|
+
/** Observe the initialized context, including bypass responses, before rendering. */
|
|
27
|
+
onContext?: (params: {
|
|
28
|
+
context: ISsrRequestContext<TAppProps>;
|
|
29
|
+
}) => void;
|
|
26
30
|
/**
|
|
27
31
|
* Initialize request metadata or return a Response to bypass rendering.
|
|
28
32
|
*/
|
|
@@ -34,6 +38,6 @@ interface ICreateHandlerOptions<TAppProps> extends ICoreRenderOptions<TAppProps>
|
|
|
34
38
|
/**
|
|
35
39
|
* Create isolated request state and allow request hooks to bypass rendering.
|
|
36
40
|
*/
|
|
37
|
-
declare const createHandler: <TAppProps = Record<string, any>>(params: ICoreRenderParams<TAppProps>, { diagnostics, getHtml, onRequest, ssr, basename, ...options }: ICreateHandlerOptions<TAppProps>) => TSsrHandler;
|
|
41
|
+
declare const createHandler: <TAppProps = Record<string, any>>(params: ICoreRenderParams<TAppProps>, { diagnostics, getHtml, onContext, onRequest, ssr, basename, ...options }: ICreateHandlerOptions<TAppProps>) => TSsrHandler;
|
|
38
42
|
export type { ICreateHandlerOptions, IHtmlShell, IRequestInit, ISsrPolicy };
|
|
39
43
|
export default createHandler;
|
package/core/handler.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{hasCookie as
|
|
1
|
+
import{hasCookie as e}from"./document-headers.js";import s from"./head-response.js";import o from"./render.js";import t from"./spa-shell.js";import r from"./ssr-policy.js";import n,{isDiagnosticsEnabled as a}from"../services/diagnostics.js";import{createTimeline as i}from"../services/request-timeline.js";const p=(p,{diagnostics:c,getHtml:m,onContext:d,onRequest:l,ssr:h,basename:u,...f})=>{const w=new r(h,p.handler.dataRoutes,u),j=t();return async(t,r)=>{const h=a(c),u=i(t,h);try{const a=await(l?.({executionContext:r,request:t})),i=a instanceof Response,c=i?void 0:a,g={appProps:c?.appProps??{},diagnostics:h?new n(new URL(t.url).pathname):void 0,html:i?{header:"",footer:""}:await m(t),request:t,response:{headers:new Headers(c?.headers),status:c?.status},...u?{timeline:u}:{}};if(d?.({context:g}),i){g.diagnostics?.inspectCachePolicy(a.headers,Boolean(f.sessionCookie&&e(t,f.sessionCookie)));const o=await s(t,a);return u?.response(o)??o}return await o({...p,policy:w,spaShell:j},g,f,r)}catch(e){throw u?.abort(e),u?.end(),e}}};export{p as default};
|
|
2
2
|
//# sourceMappingURL=handler.js.map
|
package/core/handler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sources":["../../src/core/handler.ts"],"sourcesContent":[null],"names":["createHandler","params","diagnostics","getHtml","onRequest","ssr","basename","options","policy","SsrPolicy","handler","dataRoutes","spaShell","createSpaShell","async","request","executionContext","
|
|
1
|
+
{"version":3,"file":"handler.js","sources":["../../src/core/handler.ts"],"sourcesContent":[null],"names":["createHandler","params","diagnostics","getHtml","onContext","onRequest","ssr","basename","options","policy","SsrPolicy","handler","dataRoutes","spaShell","createSpaShell","async","request","executionContext","isEnabled","isDiagnosticsEnabled","timeline","createTimeline","requestInit","isBypass","Response","metadata","undefined","context","appProps","Diagnostics","URL","url","pathname","html","header","footer","response","headers","Headers","status","inspectCachePolicy","Boolean","sessionCookie","hasCookie","headResponse","render","error","abort","end"],"mappings":"kTAsDA,MAAMA,EAAgB,CACpBC,GAEEC,cACAC,UACAC,YACAC,YACAC,MACAC,cACGC,MAGL,MAAMC,EAAS,IAAIC,EAAUJ,EAAKL,EAAOU,QAAQC,WAAYL,GACvDM,EAAWC,IAKjB,OAAOC,MAAOC,EAASC,KACrB,MAAMC,EAAYC,EAAqBjB,GACjCkB,EAAWC,EAAeL,EAASE,GAEzC,IACE,MAAMI,QAAoBjB,IAAY,CAAEY,mBAAkBD,aACpDO,EAAWD,aAAuBE,SAClCC,EAAWF,OAAWG,EAAYJ,EAClCK,EAAyC,CAC7CC,SAAWH,GAAUG,UAAY,GACjC1B,YAAagB,EAAY,IAAIW,EAAY,IAAIC,IAAId,EAAQe,KAAKC,eAAYN,EAC1EO,KAAMV,EAAW,CAAEW,OAAQ,GAAIC,OAAQ,UAAahC,EAAQa,GAC5DA,UACAoB,SAAU,CACRC,QAAS,IAAIC,QAAQb,GAAUY,SAC/BE,OAAQd,GAAUc,WAEhBnB,EAAW,CAAEA,YAAa,IAKhC,GAFAhB,IAAY,CAAEuB,YAEVJ,EAAU,CACZI,EAAQzB,aAAasC,mBACnBlB,EAAYe,QACZI,QAAQjC,EAAQkC,eAAiBC,EAAU3B,EAASR,EAAQkC,iBAG9D,MAAMN,QAAiBQ,EAAa5B,EAASM,GAE7C,OAAOF,GAAUgB,SAASA,IAAaA,CACzC,CAEA,aAAaS,EAAO,IAAK5C,EAAQQ,SAAQI,YAAYc,EAASnB,EAASS,EACzE,CAAE,MAAO6B,GAGP,MAFA1B,GAAU2B,MAAMD,GAChB1B,GAAU4B,MACJF,CACR"}
|
package/core/render.d.ts
CHANGED
|
@@ -8,9 +8,11 @@ import type SsrPolicy from './ssr-policy.js';
|
|
|
8
8
|
import type { ISsrExecutionContext } from './types.js';
|
|
9
9
|
import type { IObtainStreamErrorOut } from '../helpers/obtain-stream-error.js';
|
|
10
10
|
import type Diagnostics from '../services/diagnostics.js';
|
|
11
|
+
import type RequestTimeline from '../services/request-timeline.js';
|
|
11
12
|
export interface ISsrRequestContext<TAppProps = Record<string, any>> {
|
|
12
13
|
appProps: NonNullable<TAppProps>;
|
|
13
14
|
diagnostics?: Diagnostics;
|
|
15
|
+
timeline?: RequestTimeline;
|
|
14
16
|
/**
|
|
15
17
|
* First render failure, or the explicit timeout/cancellation classification.
|
|
16
18
|
*/
|
|
@@ -113,6 +115,6 @@ export interface ICoreRenderOptions<TAppProps = Record<string, any>> extends IDo
|
|
|
113
115
|
}) => Promise<void> | void;
|
|
114
116
|
routerRequestContext?: unknown;
|
|
115
117
|
}
|
|
116
|
-
/**
|
|
118
|
+
/** Record the timeline and inspect the committed metadata, including redirect and shell-error responses, for every core consumer. */
|
|
117
119
|
declare const render: <TAppProps>(params: ICoreRenderParams<TAppProps>, context: ISsrRequestContext<TAppProps>, options: ICoreRenderOptions<TAppProps>, executionContext?: ISsrExecutionContext) => Promise<Response>;
|
|
118
120
|
export default render;
|
package/core/render.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"react";import{matchRoutes as t,createStaticRouter as r,StaticRouterProvider as s}from"react-router";import o from"../constants/stream-error.js";import{ServerProvider as a}from"../context/server.js";import n from"./compose-html.js";import
|
|
1
|
+
import e from"react";import{matchRoutes as t,createStaticRouter as r,StaticRouterProvider as s}from"react-router";import o from"../constants/stream-error.js";import{ServerProvider as a}from"../context/server.js";import n from"./compose-html.js";import i from"./data-stream.js";import c,{hasCookie as d}from"./document-headers.js";import l from"./head-response.js";import{mergeResponseHeaders as m}from"./headers.js";import h from"./transform-html.js";import u from"../helpers/build-custom-state.js";import p from"../helpers/obtain-stream-error.js";import{createTimeline as C}from"../services/request-timeline.js";const f="text/html",w="Content-Type",x=async({createApp:d,handler:C,renderToStream:x,policy:y,spaShell:R},S,{abortDelay:b=15e3,getState:q,hydration:v="footer",nonce:g,bootstrapScriptContent:E,onError:j,onResponse:k,onRouterReady:H,onShellError:P,onShellReady:T,prepare:A,routerRequestContext:B,documentHeaders:D,sessionCookie:L,protectPrivate:_},$)=>{const I=y?.select(S.request,S.diagnostics)??"ssr";if(y?.active&&!S.response.headers.has("Cache-Control")&&S.response.headers.set("Cache-Control","no-store"),"spa"===I)return S.isSpa=!0,S.isStream=!1,S.matches=t(C.dataRoutes,new URL(S.request.url),y?.basename)??[],S.html=R(S.html),await(A?.({context:S,executionContext:$})),D&&(S.response.headers=c(D,{sessionCookie:L,protectPrivate:_})(S)),S.response.status=200,S.response.headers.set(w,"text/html; charset=utf-8"),new Response("HEAD"===S.request.method?null:S.html.header+S.html.footer,{headers:S.response.headers,status:200});const U=await C.query(S.request,{requestContext:B??S});if(S.timeline?.record("router.query"),U instanceof Response)return l(S.request,m(U,S.response.headers));S.routerContext=U,S.matches=U.matches;const z=new i(U,S.diagnostics,g,S.timeline);try{await(A?.({context:S,executionContext:$})),S.timeline?.record("prepare")}catch(e){throw z.cancel(),e}const{isStream:F=!0}=await(H?.({context:S}))??{};S.isStream=F,S.serverContext={basename:S.routerContext.basename,isServer:!0,response:null};const G=r(C.dataRoutes,S.routerContext),J=e.createElement(a,{context:S.serverContext},d(e.createElement(s,{router:G,context:S.routerContext,hydrate:!1}),S)),K=new AbortController;let M,N,O=!1;const Q=()=>X(S.request.signal.reason),V=()=>clearTimeout(Y),W=()=>{V(),S.request.signal.removeEventListener("abort",Q)},X=e=>{O||(O=!0,M=e,S.timeline?.abort(e),W(),S.didError??=o.RenderCancel,z.abort(),K.abort(e),N?.abort(e))},Y=setTimeout(()=>{S.didError=o.RenderTimeout,S.timeline?.abort(new Error(`SSR render timed out after ${b}ms`)),X()},b);S.request.signal.aborted?X(S.request.signal.reason):S.request.signal.addEventListener("abort",Q,{once:!0});try{N=await x(J,{nonce:g,bootstrapScriptContent:"early"===v&&F?`(window.__ssrBoostStream = window.__ssrBoostStream || []).push(["shell"]);${E??""};document.currentScript?.remove();`:E,onError:e=>{const t=p(e);!O||t.code!==o.RenderAborted&&e!==K.signal.reason||(t.code=S.didError===o.RenderTimeout?o.RenderTimeout:o.RenderCancel);const{code:r}=t;S.didError??=r,j?.({context:S,error:t})},signal:K.signal}),O&&N.abort(M),Promise.all([N.allReady,z.done]).then(V,V),await N.shellReady,S.timeline?.record("shell.ready"),F||await Promise.all([N.allReady,z.done])}catch(e){return X(e),await(N?.stream.cancel(e).catch(()=>{})),((e,t,r)=>{const s=t instanceof Error?t:new Error(String(t)),o=r?.({context:e,error:s})||"<!doctype html><p>Internal Server Error</p>",a=new Headers(e.response.headers);return a.set(w,f),new Response("HEAD"===e.request.method?null:o,{headers:a,status:500})})(S,e,P)}try{const e=S.serverContext.response;if(e&&(Z=e,Boolean(Z&&Z.status>=300&&Z.status<400&&Z.headers.has("Location"))))return X(),await N.stream.cancel().catch(()=>{}),l(S.request,m(e,S.response.headers));const{header:t,footer:r,headers:s,status:o}=((e,{getState:t,onShellReady:r,hydration:s,nonce:o,documentHeaders:a,sessionCookie:n,protectPrivate:i},d)=>{const l=e.serverContext.response;e.response.status=l?.status??e.response.status??e.routerContext.statusCode??200,e.response.headers.has(w)||e.response.headers.set(w,f);const m=r?.({context:e})??{},h="early"===s&&e.isStream,p=u(t?.({context:e}),e.diagnostics,o,Boolean(h));let C=m.header||e.html.header;const x=m.footer||e.html.footer;e.diagnostics?.inspectShell({header:C,footer:x});let y=x;return h?C+=p+d.state(!0):y=p+d.state(!1)+d.take()+y,a&&(e.response.headers=c(a,{sessionCookie:n,protectPrivate:i})(e)),{header:C,footer:y,headers:new Headers(e.response.headers),status:e.response.status}})(S,{getState:q,onShellReady:T,hydration:v,nonce:g,documentHeaders:D,sessionCookie:L,protectPrivate:_},z);if("HEAD"===S.request.method||[204,205,304].includes(o))return X(),await N.stream.cancel().catch(()=>{}),new Response(null,{headers:s,status:o});const a=n(t,N.stream,r,X,W,z,S.timeline,"early"===v&&F),i=h(a,k?(e,t)=>k({context:S,html:e,isEnd:t}):void 0,S.diagnostics);return N.start(),new Response(i,{headers:s,status:o})}catch(e){throw X(e),N.stream.locked||await N.stream.cancel(e).catch(()=>{}),e}var Z},y=async(e,t,r,s)=>{const o=t.timeline??C(t.request,Boolean(t.diagnostics));o&&(t.timeline=o);try{const a=await x(e,t,r,s);return t.diagnostics?.inspectCachePolicy(a.headers,Boolean(r.sessionCookie&&d(t.request,r.sessionCookie))),o?.response(a)??a}catch(e){throw o?.abort(e),o?.end(),e}};export{y as default};
|
|
2
2
|
//# sourceMappingURL=render.js.map
|
package/core/render.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sources":["../../src/core/render.tsx"],"sourcesContent":[null],"names":["HTML_CONTENT_TYPE","CONTENT_TYPE","renderResponse","async","createApp","handler","renderToStream","policy","spaShell","context","abortDelay","getState","hydration","nonce","bootstrapScriptContent","onError","onResponse","onRouterReady","onShellError","onShellReady","prepare","routerRequestContext","documentHeaders","rules","sessionCookie","protectPrivate","executionContext","mode","select","request","diagnostics","active","response","headers","has","set","isSpa","isStream","matches","matchRoutes","dataRoutes","URL","url","basename","html","status","Response","method","header","footer","queried","query","requestContext","headResponse","mergeResponseHeaders","routerContext","dataStream","DataStream","error","cancel","serverContext","isServer","router","createStaticRouter","node","React","createElement","ServerProvider","StaticRouterProvider","hydrate","renderController","AbortController","abortReason","output","hasAborted","onRequestAbort","abort","signal","reason","clearAbortTimer","clearTimeout","abortTimer","cleanup","removeEventListener","didError","StreamError","RenderCancel","setTimeout","RenderTimeout","aborted","addEventListener","once","streamError","obtainStreamError","code","RenderAborted","Promise","all","allReady","done","then","shellReady","stream","catch","shellError","
|
|
1
|
+
{"version":3,"file":"render.js","sources":["../../src/core/render.tsx"],"sourcesContent":[null],"names":["HTML_CONTENT_TYPE","CONTENT_TYPE","renderResponse","async","createApp","handler","renderToStream","policy","spaShell","context","abortDelay","getState","hydration","nonce","bootstrapScriptContent","onError","onResponse","onRouterReady","onShellError","onShellReady","prepare","routerRequestContext","documentHeaders","rules","sessionCookie","protectPrivate","executionContext","mode","select","request","diagnostics","active","response","headers","has","set","isSpa","isStream","matches","matchRoutes","dataRoutes","URL","url","basename","html","status","Response","method","header","footer","queried","query","requestContext","timeline","record","headResponse","mergeResponseHeaders","routerContext","dataStream","DataStream","error","cancel","serverContext","isServer","router","createStaticRouter","node","React","createElement","ServerProvider","StaticRouterProvider","hydrate","renderController","AbortController","abortReason","output","hasAborted","onRequestAbort","abort","signal","reason","clearAbortTimer","clearTimeout","abortTimer","cleanup","removeEventListener","didError","StreamError","RenderCancel","setTimeout","RenderTimeout","Error","aborted","addEventListener","once","streamError","obtainStreamError","code","RenderAborted","Promise","all","allReady","done","then","shellReady","stream","catch","shellError","String","Headers","createShellErrorResponse","serverResponse","Boolean","statusCode","shell","isEarly","customState","buildCustomState","shellFooter","inspectShell","state","take","prepareHtmlResponse","includes","body","composeHtml","transformed","transformHtml","isEnd","undefined","start","locked","render","params","options","createTimeline","inspectCachePolicy","hasCookie","end"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lomray/vite-ssr-boost",
|
|
3
|
-
"version": "8.4.0-beta.
|
|
3
|
+
"version": "8.4.0-beta.3",
|
|
4
4
|
"description": "SSR and streaming for existing Vite + React Router apps in Data mode, without Framework mode",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -25,6 +25,30 @@
|
|
|
25
25
|
"./*": {
|
|
26
26
|
"types": "./*.d.ts",
|
|
27
27
|
"default": "./*.js"
|
|
28
|
+
},
|
|
29
|
+
"./testing": {
|
|
30
|
+
"types": "./testing.d.ts",
|
|
31
|
+
"workerd": "./testing/edge.js",
|
|
32
|
+
"worker": "./testing/edge.js",
|
|
33
|
+
"edge-light": "./testing/edge.js",
|
|
34
|
+
"browser": "./testing/edge.js",
|
|
35
|
+
"default": "./testing.js"
|
|
36
|
+
},
|
|
37
|
+
"./testing.js": {
|
|
38
|
+
"types": "./testing.d.ts",
|
|
39
|
+
"workerd": "./testing/edge.js",
|
|
40
|
+
"worker": "./testing/edge.js",
|
|
41
|
+
"edge-light": "./testing/edge.js",
|
|
42
|
+
"browser": "./testing/edge.js",
|
|
43
|
+
"default": "./testing.js"
|
|
44
|
+
},
|
|
45
|
+
"./testing/playwright": {
|
|
46
|
+
"types": "./testing/playwright.d.ts",
|
|
47
|
+
"default": "./testing/playwright.js"
|
|
48
|
+
},
|
|
49
|
+
"./testing/playwright.js": {
|
|
50
|
+
"types": "./testing/playwright.d.ts",
|
|
51
|
+
"default": "./testing/playwright.js"
|
|
28
52
|
}
|
|
29
53
|
},
|
|
30
54
|
"keywords": [
|
|
@@ -146,6 +170,7 @@
|
|
|
146
170
|
"@babel/parser": ">=7.23.0",
|
|
147
171
|
"@babel/traverse": ">=7.23.0",
|
|
148
172
|
"@babel/types": ">=7.23.0",
|
|
173
|
+
"@playwright/test": ">=1.40.0",
|
|
149
174
|
"@types/compression": ">=1.7.5",
|
|
150
175
|
"@types/express": ">=4.17.21",
|
|
151
176
|
"@types/serve-static": ">=1.15.5",
|
|
@@ -163,6 +188,9 @@
|
|
|
163
188
|
},
|
|
164
189
|
"@types/serve-static": {
|
|
165
190
|
"optional": true
|
|
191
|
+
},
|
|
192
|
+
"@playwright/test": {
|
|
193
|
+
"optional": true
|
|
166
194
|
}
|
|
167
195
|
},
|
|
168
196
|
"overrides": {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type TRequestStage = 'router.query' | 'prepare' | 'shell.ready' | 'state.emitted' | 'stream.resolve' | 'stream.reject' | 'body.end' | 'response.end' | 'abort';
|
|
2
|
+
interface ITimelineEvent {
|
|
3
|
+
stage: TRequestStage;
|
|
4
|
+
at: number;
|
|
5
|
+
id?: number;
|
|
6
|
+
placement?: 'early' | 'footer';
|
|
7
|
+
reason?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Request-local observations; never constructed on the disabled path. */
|
|
10
|
+
declare class RequestTimeline {
|
|
11
|
+
protected readonly request: Request;
|
|
12
|
+
readonly events: ITimelineEvent[];
|
|
13
|
+
readonly started: number;
|
|
14
|
+
protected ended: boolean;
|
|
15
|
+
protected aborted: boolean;
|
|
16
|
+
constructor(request: Request);
|
|
17
|
+
protected onAbort: () => void;
|
|
18
|
+
/** Offsets mark completion/emission, not the beginning of a stage. */
|
|
19
|
+
record(stage: TRequestStage, detail?: Omit<ITimelineEvent, 'stage' | 'at'>): void;
|
|
20
|
+
abort(reason?: unknown): void;
|
|
21
|
+
/** Emit one JSON line only when explicitly requested in development. */
|
|
22
|
+
end(): void;
|
|
23
|
+
/** Observe final transformed bytes without reading ahead of the consumer. */
|
|
24
|
+
response(response: Response): Response;
|
|
25
|
+
}
|
|
26
|
+
/** Keep the constructor, event array and clock reads behind the enablement check. */
|
|
27
|
+
declare const createTimeline: (request: Request, diagnostics: boolean) => RequestTimeline | undefined;
|
|
28
|
+
export { createTimeline };
|
|
29
|
+
export type { ITimelineEvent, TRequestStage };
|
|
30
|
+
export default RequestTimeline;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=e=>{if(e instanceof Error)return e.message;if("string"==typeof e)return e;try{return JSON.stringify(e)??"Render cancelled"}catch{return"Unserializable abort reason"}};class t{request;events=[];started=performance.now();ended=!1;aborted=!1;constructor(e){this.request=e,e.signal.aborted?this.onAbort():e.signal.addEventListener("abort",this.onAbort,{once:!0})}onAbort=()=>this.abort(this.request.signal.reason);record(e,t){this.ended||this.events.push({stage:e,at:performance.now()-this.started,...t})}abort(t){this.aborted||(this.aborted=!0,this.record("abort",{reason:e(t)}))}end(){this.ended||(this.record("response.end"),this.ended=!0,this.request.signal.removeEventListener("abort",this.onAbort),"undefined"!=typeof process&&"1"===process.env.SSR_BOOST_TIMELINE&&"production"!==process.env.NODE_ENV&&console.info(JSON.stringify({type:"SSR_BOOST_TIMELINE",method:this.request.method,path:new URL(this.request.url).pathname,timeline:this.events})))}response(e){if(!e.body)return this.end(),e;const t=e.body.getReader();let r=!1;const s=()=>{r=!0,t.releaseLock(),this.end()},n=new ReadableStream({cancel:async e=>{r=!0,this.abort(e);try{await t.cancel(e)}finally{s()}},pull:async e=>{try{const n=await t.read();if(r)return;n.done?(s(),e.close()):e.enqueue(n.value)}catch(t){r||(this.abort(t),s(),e.error(t))}}},{highWaterMark:0});return new Response(n,e)}}const r=(e,r)=>r||"undefined"!=typeof process&&"1"===process.env.SSR_BOOST_TIMELINE?new t(e):void 0;export{r as createTimeline,t as default};
|
|
2
|
+
//# sourceMappingURL=request-timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-timeline.js","sources":["../../src/services/request-timeline.ts"],"sourcesContent":[null],"names":["describeReason","reason","Error","message","JSON","stringify","RequestTimeline","request","events","started","performance","now","ended","aborted","constructor","this","signal","onAbort","addEventListener","once","abort","record","stage","detail","push","at","end","removeEventListener","process","env","SSR_BOOST_TIMELINE","NODE_ENV","console","info","type","method","path","URL","url","pathname","timeline","response","body","reader","getReader","isStopped","finish","releaseLock","ReadableStream","cancel","async","pull","controller","chunk","read","done","close","enqueue","value","error","highWaterMark","Response","createTimeline","diagnostics","undefined"],"mappings":"AAoBA,MAAMA,EAAkBC,IACtB,GAAIA,aAAkBC,MACpB,OAAOD,EAAOE,QAGhB,GAAsB,iBAAXF,EACT,OAAOA,EAGT,IACE,OAAOG,KAAKC,UAAUJ,IAAW,kBACnC,CAAE,MACA,MAAO,6BACT,GAIF,MAAMK,EAMkCC,QALtBC,OAA2B,GAC3BC,QAAUC,YAAYC,MAC5BC,OAAQ,EACRC,SAAU,EAEpB,WAAAC,CAAsCP,GAAAQ,KAAAR,QAAAA,EAChCA,EAAQS,OAAOH,QACjBE,KAAKE,UAELV,EAAQS,OAAOE,iBAAiB,QAASH,KAAKE,QAAS,CAAEE,MAAM,GAEnE,CAEUF,QAAU,IAAYF,KAAKK,MAAML,KAAKR,QAAQS,OAAOf,QAGxD,MAAAoB,CAAOC,EAAsBC,GAC7BR,KAAKH,OACRG,KAAKP,OAAOgB,KAAK,CAAEF,QAAOG,GAAIf,YAAYC,MAAQI,KAAKN,WAAYc,GAEvE,CAEO,KAAAH,CAAMnB,GACNc,KAAKF,UACRE,KAAKF,SAAU,EACfE,KAAKM,OAAO,QAAS,CAAEpB,OAAQD,EAAeC,KAElD,CAGO,GAAAyB,GACDX,KAAKH,QAITG,KAAKM,OAAO,gBACZN,KAAKH,OAAQ,EACbG,KAAKR,QAAQS,OAAOW,oBAAoB,QAASZ,KAAKE,SAGjC,oBAAZW,SAC4B,MAAnCA,QAAQC,IAAIC,oBACa,eAAzBF,QAAQC,IAAIE,UAEZC,QAAQC,KACN7B,KAAKC,UAAU,CACb6B,KAAM,qBACNC,OAAQpB,KAAKR,QAAQ4B,OACrBC,KAAM,IAAIC,IAAItB,KAAKR,QAAQ+B,KAAKC,SAChCC,SAAUzB,KAAKP,UAIvB,CAGO,QAAAiC,CAASA,GACd,IAAKA,EAASC,KAGZ,OAFA3B,KAAKW,MAEEe,EAGT,MAAME,EAASF,EAASC,KAAKE,YAC7B,IAAIC,GAAY,EAChB,MAAMC,EAAS,KACbD,GAAY,EACZF,EAAOI,cACPhC,KAAKW,OAEDgB,EAAO,IAAIM,eACf,CACEC,OAAQC,MAAOjD,IACb4C,GAAY,EACZ9B,KAAKK,MAAMnB,GAEX,UACQ0C,EAAOM,OAAOhD,EACtB,SACE6C,GACF,GAEFK,KAAMD,MAAOE,IACX,IACE,MAAMC,QAAcV,EAAOW,OAE3B,GAAIT,EACF,OAGEQ,EAAME,MACRT,IACAM,EAAWI,SAEXJ,EAAWK,QAAQJ,EAAMK,MAE7B,CAAE,MAAOC,GACFd,IACH9B,KAAKK,MAAMuC,GACXb,IACAM,EAAWO,MAAMA,GAErB,IAGJ,CAAEC,cAAe,IAGnB,OAAO,IAAIC,SAASnB,EAAMD,EAC5B,EAIF,MAAMqB,EAAiB,CAACvD,EAAkBwD,IACxCA,GAAmC,oBAAZnC,SAA8D,MAAnCA,QAAQC,IAAIC,mBAC1D,IAAIxB,EAAgBC,QACpByD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
interface IBrowserTimelineEvent {
|
|
2
|
+
stage: 'shell' | 'router.ready' | 'init' | 'resolve' | 'reject' | 'response.end';
|
|
3
|
+
at: number;
|
|
4
|
+
id?: number;
|
|
5
|
+
}
|
|
6
|
+
interface IBrowserObservation {
|
|
7
|
+
events: IBrowserTimelineEvent[];
|
|
8
|
+
errors: string[];
|
|
9
|
+
roots: Record<string, string>;
|
|
10
|
+
seen: WeakMap<Element, number>;
|
|
11
|
+
shellAt?: number;
|
|
12
|
+
}
|
|
13
|
+
declare global {
|
|
14
|
+
interface Window {
|
|
15
|
+
__ssrBoostTest?: IBrowserObservation;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** Serialized by addInitScript: keep every runtime dependency inside this function. */
|
|
19
|
+
declare const installBrowserObserver: () => void;
|
|
20
|
+
interface IHydrationInspection {
|
|
21
|
+
ready: boolean;
|
|
22
|
+
consumed: boolean;
|
|
23
|
+
pending: number;
|
|
24
|
+
duplicates: string[];
|
|
25
|
+
errors: string[];
|
|
26
|
+
}
|
|
27
|
+
/** Compare server text multiplicities to the hydrated root, allowing existing repeats. */
|
|
28
|
+
declare const inspectHydration: (selector: string) => IHydrationInspection;
|
|
29
|
+
export { installBrowserObserver, inspectHydration };
|
|
30
|
+
export type { IBrowserTimelineEvent, IHydrationInspection };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=()=>{if(window.__ssrBoostTest)return;const e={events:[],errors:[],roots:{},seen:new WeakMap};window.__ssrBoostTest=e;const t=(t,o)=>{e.events.push({stage:t,at:performance.now(),...void 0===o?{}:{id:o}})},o=()=>{const o=performance.now();for(const r of document.querySelectorAll("body *")){const n=r.getBoundingClientRect();!r.closest("script, style, template, [hidden]")&&n.width>0&&n.height>0&&"hidden"!==getComputedStyle(r).visibility&&(void 0===e.shellAt&&(e.shellAt=o,t("shell")),e.seen.has(r)||e.seen.set(r,o))}};new MutationObserver(o).observe(document,{childList:!0,subtree:!0,attributes:!0});const r=console.error;console.error=(...t)=>{e.errors.push(t.map(String).join(" ")),r(...t)},window.addEventListener("error",t=>e.errors.push(t.message)),window.addEventListener("unhandledrejection",t=>e.errors.push(String(t.reason))),window.addEventListener("ssr-boost:router-ready",r=>{const{rootId:n}=r.detail,s=document.getElementById(n);s&&(e.roots[n]=s.innerHTML),o(),t("router.ready")}),window.addEventListener("load",()=>t("response.end"),{once:!0});const n=[];let s=Array.prototype.push;const d=new WeakSet;Object.defineProperty(n,"push",{configurable:!0,get:()=>(...e)=>{for(const o of e){if(d.has(o))continue;d.add(o);const[e,r]=o;"init"!==e&&"resolve"!==e&&"reject"!==e||t(e,"number"==typeof r?r:void 0)}return s.apply(n,e)},set:e=>{s=e}}),Reflect.set(window,"__ssrBoostStream",n)},t=e=>{const t=window.__ssrBoostTest,o=document.querySelector(e),r=o?t?.roots[o.id]:void 0,n=document.createElement("div");n.innerHTML=r??"";const s=e=>{const t=new Map;for(const o of[e,...e.querySelectorAll("*")]){if(o.closest("script, style, template, [hidden]"))continue;const e=[...o.childNodes].filter(e=>e.nodeType===Node.TEXT_NODE).map(e=>e.textContent).join("").replace(/\s+/g," ").trim();e&&t.set(e,(t.get(e)??0)+1)}return t},d=s(n),i=o?s(o):new Map,c=(e,t)=>{let o=0;for(const[r,n]of e){const e=r.length/t.length;Number.isInteger(e)&&t.repeat(e)===r&&(o+=e*n)}return o},l=[...d].filter(([e])=>c(i,e)>c(d,e)).map(([e])=>e),a=o?document.createTreeWalker(o,NodeFilter.SHOW_COMMENT):void 0;let u=0;for(;a?.nextNode();)"$?"===a.currentNode.textContent&&u++;return{ready:void 0!==r,consumed:void 0===Reflect.get(window,"__staticRouterHydrationData"),pending:u,duplicates:l,errors:t?.errors.filter(e=>/(?:#|errors\/)(418|423|425)\b|hydrat(?:ion|ing|e|ed)|server rendered HTML|did not match/i.test(e))??[]}};export{t as inspectHydration,e as installBrowserObserver};
|
|
2
|
+
//# sourceMappingURL=browser-observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-observer.js","sources":["../../src/testing/browser-observer.ts"],"sourcesContent":[null],"names":["installBrowserObserver","window","__ssrBoostTest","state","events","errors","roots","seen","WeakMap","record","stage","id","push","at","performance","now","undefined","scan","element","document","querySelectorAll","rect","getBoundingClientRect","closest","width","height","getComputedStyle","visibility","shellAt","has","set","MutationObserver","observe","childList","subtree","attributes","originalError","console","error","args","map","String","join","addEventListener","event","message","reason","rootId","detail","root","getElementById","innerHTML","once","queue","downstream","Array","prototype","observed","WeakSet","Object","defineProperty","configurable","get","frames","frame","add","apply","replacement","Reflect","inspectHydration","selector","querySelector","html","server","createElement","texts","counts","Map","child","text","childNodes","filter","node","nodeType","Node","TEXT_NODE","textContent","replace","trim","before","after","multiplicity","total","candidate","count","copies","length","Number","isInteger","repeat","duplicates","walker","createTreeWalker","NodeFilter","SHOW_COMMENT","pending","nextNode","currentNode","ready","consumed","test"],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import type { RouteObject } from 'react-router';
|
|
3
|
+
import { createStaticHandler } from 'react-router';
|
|
4
|
+
import type { ICreateHandlerOptions, IHtmlShell } from '../core/handler.js';
|
|
5
|
+
import type { TRenderToStream } from '../core/render.js';
|
|
6
|
+
import type { TRouteObject } from '../interfaces/route-object.js';
|
|
7
|
+
import type { ILoadHtmlShellOptions } from '../node/production.js';
|
|
8
|
+
import TestResponse from './response.js';
|
|
9
|
+
interface ITestRequestInit extends RequestInit {
|
|
10
|
+
isStream?: boolean;
|
|
11
|
+
/** Whole-request deadline, including loaders and body consumption. */
|
|
12
|
+
timeout?: number;
|
|
13
|
+
}
|
|
14
|
+
interface ITestHandlerOptions<TAppProps> extends Omit<ICreateHandlerOptions<TAppProps>, 'getHtml'> {
|
|
15
|
+
routes: TRouteObject[] | RouteObject[];
|
|
16
|
+
App?: FC<PropsWithChildren<{
|
|
17
|
+
server: TAppProps;
|
|
18
|
+
}>>;
|
|
19
|
+
shell?: IHtmlShell | ILoadHtmlShellOptions;
|
|
20
|
+
routerOptions?: Parameters<typeof createStaticHandler>[1];
|
|
21
|
+
renderToStream?: TRenderToStream;
|
|
22
|
+
signal?: AbortSignal;
|
|
23
|
+
timeout?: number;
|
|
24
|
+
}
|
|
25
|
+
interface ITestHandler {
|
|
26
|
+
fetch: (input: string | Request, init?: ITestRequestInit) => Promise<TestResponse>;
|
|
27
|
+
}
|
|
28
|
+
type TLoadShell = (options: ILoadHtmlShellOptions) => Promise<() => IHtmlShell>;
|
|
29
|
+
/** Share the Fetch-only implementation between Node and conditional edge exports. */
|
|
30
|
+
declare const testHandlerFactory: (renderer: TRenderToStream, loadShell: TLoadShell) => <TAppProps = Record<string, any>>({ routes, App, shell, routerOptions, renderToStream, signal: defaultSignal, timeout: defaultTimeout, onContext, onRouterReady, ...options }: ITestHandlerOptions<TAppProps>) => ITestHandler;
|
|
31
|
+
export type { ITestHandler, ITestHandlerOptions, ITestRequestInit };
|
|
32
|
+
export default testHandlerFactory;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"react";import{createStaticHandler as t}from"react-router";import r from"../core/handler.js";import{TEST_ORIGIN as o}from"./requests.js";import n from"./response.js";const i={header:'<!doctype html><html><head></head><body><div id="root">',footer:'</div><script type="module">/* test browser entry */<\/script></body></html>'},a=(a,s)=>({routes:m,App:c,shell:l=i,routerOptions:d,renderToStream:u=a,signal:p,timeout:f,onContext:h,onRouterReady:b,...w})=>{const y=t(m,d);let g;const v=async()=>"indexFile"in l?(g??=s(l),(await g)()):{...l};return{fetch:async(t,{isStream:i,timeout:a=f,signal:s,...m}={})=>{const l=performance.now(),d=new AbortController,g=[d.signal,p,s,t instanceof Request?t.signal:void 0].filter(e=>Boolean(e)),R=AbortSignal.any(g),S=new Request("string"==typeof t?new URL(t,o):t,{...m,signal:R});let x,E,A;const T=new Promise((e,t)=>{A=t}),C=()=>A(R.reason),j=()=>{clearTimeout(x),R.removeEventListener("abort",C)};if(R.addEventListener("abort",C,{once:!0}),void 0!==a){if(!Number.isFinite(a)||a<0)throw j(),new RangeError("timeout must be a finite, non-negative number of milliseconds.");x=setTimeout(()=>d.abort(new DOMException(`SSR test timed out after ${a}ms`,"TimeoutError")),a)}try{R.throwIfAborted();const t=r({handler:y,renderToStream:u,createApp:(t,r)=>c?e.createElement(c,{server:r.appProps},t):t},{...w,getHtml:v,onContext:e=>{({timeline:E}=e.context),h?.(e)},onRouterReady:async e=>{const t=await(b?.(e));return void 0===i?t??{}:{...t,isStream:i}}})(S);t.then(e=>{if(R.aborted)return e.body?.cancel(R.reason)}).catch(()=>{});const o=await Promise.race([t,T]);return new n(o,{started:l,timeline:E,signal:R,onComplete:j})}catch(e){throw j(),E?.abort(e),E?.end(),e}}}};export{a as default};
|
|
2
|
+
//# sourceMappingURL=create-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-handler.js","sources":["../../src/testing/create-handler.tsx"],"sourcesContent":[null],"names":["DEFAULT_SHELL","header","footer","testHandlerFactory","renderer","loadShell","routes","App","shell","routerOptions","renderToStream","signal","defaultSignal","timeout","defaultTimeout","onContext","onRouterReady","options","handler","createStaticHandler","fileShell","getHtml","async","fetch","input","isStream","init","started","performance","now","controller","AbortController","signals","Request","undefined","filter","item","Boolean","combined","AbortSignal","any","request","URL","TEST_ORIGIN","timer","timeline","rejectAbort","aborted","Promise","_","reject","onAbort","reason","cleanup","clearTimeout","removeEventListener","addEventListener","once","Number","isFinite","RangeError","setTimeout","abort","DOMException","throwIfAborted","pending","createHandler","createApp","children","context","React","createElement","server","appProps","params","result","then","response","body","cancel","catch","race","TestResponse","onComplete","error","end"],"mappings":"mLAmCA,MAAMA,EAA4B,CAChCC,OAAQ,0DACRC,OAAQ,gFAIJC,EACJ,CAACC,EAA2BC,IAC5B,EACEC,SACAC,MACAC,QAAQR,EACRS,gBACAC,iBAAiBN,EACjBO,OAAQC,EACRC,QAASC,EACTC,YACAC,mBACGC,MAEH,MAAMC,EAAUC,EAAoBb,EAAyBG,GAC7D,IAAIW,EACJ,MAAMC,EAAUC,SACV,cAAed,GACjBY,IAAcf,EAAUG,UAEVY,MAGT,IAAKZ,GAGd,MAAO,CACLe,MAAOD,MAAOE,GAASC,WAAUZ,UAAUC,EAAgBH,YAAWe,GAAS,MAC7E,MAAMC,EAAUC,YAAYC,MACtBC,EAAa,IAAIC,gBACjBC,EAAU,CACdF,EAAWnB,OACXC,EACAD,EACAa,aAAiBS,QAAUT,EAAMb,YAASuB,GAC1CC,OAAQC,GAA8BC,QAAQD,IAC1CE,EAAWC,YAAYC,IAAIR,GAC3BS,EAAU,IAAIR,QACD,iBAAVT,EAAqB,IAAIkB,IAAIlB,EAAOmB,GAAenB,EAC1D,IACKE,EACHf,OAAQ2B,IAGZ,IAAIM,EACAC,EACAC,EACJ,MAAMC,EAAU,IAAIC,QAAe,CAACC,EAAGC,KACrCJ,EAAcI,IAEVC,EAAU,IAAYL,EAAYR,EAASc,QAC3CC,EAAU,KACdC,aAAaV,GACbN,EAASiB,oBAAoB,QAASJ,IAKxC,GAFAb,EAASkB,iBAAiB,QAASL,EAAS,CAAEM,MAAM,SAEpCvB,IAAZrB,EAAuB,CACzB,IAAK6C,OAAOC,SAAS9C,IAAYA,EAAU,EAEzC,MADAwC,IACM,IAAIO,WAAW,kEAGvBhB,EAAQiB,WACN,IACE/B,EAAWgC,MACT,IAAIC,aAAa,4BAA4BlD,MAAa,iBAE9DA,EAEJ,CAEA,IACEyB,EAAS0B,iBACT,MAqBMC,EArBQC,EACZ,CACEhD,UACAR,iBACAyD,UAAW,CAACC,EAAUC,IACpB9D,EAAM+D,EAAAC,cAAChE,EAAG,CAACiE,OAAQH,EAAQI,UAAWL,GAAkBA,GAE5D,IACKnD,EACHI,UACAN,UAAY2D,MACP7B,YAAa6B,EAAOL,SACvBtD,IAAY2D,IAEd1D,cAAeM,MAAOoD,IACpB,MAAMC,QAAe3D,IAAgB0D,IAErC,YAAoBxC,IAAbT,EAA0BkD,GAAU,CAAA,EAAM,IAAKA,EAAQlD,cAIpDF,CAAMkB,GAGjBwB,EACFW,KAAMC,IACL,GAAIvC,EAASS,QACX,OAAO8B,EAASC,MAAMC,OAAOzC,EAASc,UAKzC4B,MAAM,QAET,MAAMH,QAAiB7B,QAAQiC,KAAK,CAAChB,EAASlB,IAE9C,OAAO,IAAImC,EAAaL,EAAU,CAChClD,UACAkB,WACAlC,OAAQ2B,EACR6C,WAAY9B,GAEhB,CAAE,MAAO+B,GAIP,MAHA/B,IACAR,GAAUiB,MAAMsB,GAChBvC,GAAUwC,MACJD,CACR"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface IDeferred<T> {
|
|
2
|
+
promise: Promise<T>;
|
|
3
|
+
resolve: (value: T | PromiseLike<T>) => void;
|
|
4
|
+
reject: (reason?: unknown) => void;
|
|
5
|
+
}
|
|
6
|
+
/** Control loader timing without sleeps or a running HTTP server. */
|
|
7
|
+
declare const createDeferred: <T>() => IDeferred<T>;
|
|
8
|
+
export type { IDeferred };
|
|
9
|
+
export default createDeferred;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deferred.js","sources":["../../src/testing/deferred.ts"],"sourcesContent":[null],"names":["createDeferred","resolve","reject","promise","Promise","res","rej","catch"],"mappings":"AAOA,MAAMA,EAAiB,KACrB,IAAIC,EACAC,EACJ,MAAMC,EAAU,IAAIC,QAAW,CAACC,EAAKC,KACnCL,EAAUI,EACVH,EAASI,IAMX,OAFKH,EAAQI,MAAM,QAEZ,CAAEJ,UAASF,UAASC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const createTestHandler: <TAppProps = Record<string, any>>({ routes, App, shell, routerOptions, renderToStream, signal: defaultSignal, timeout: defaultTimeout, onContext, onRouterReady, ...options }: import("./create-handler.js").ITestHandlerOptions<TAppProps>) => import("./create-handler.js").ITestHandler;
|
|
2
|
+
export { createTestHandler };
|
|
3
|
+
export { default as createDeferred } from './deferred.js';
|
|
4
|
+
export { browserRequest, crawlerRequest } from './requests.js';
|
|
5
|
+
export { default as TestResponse } from './response.js';
|
|
6
|
+
export type { ITestHandler, ITestHandlerOptions, ITestRequestInit } from './create-handler.js';
|
|
7
|
+
export type { ITestChunk, ITestCookie, ITestResponseOptions } from './response.js';
|
|
8
|
+
export type { IRouterState, TStreamFrame } from './parse-response.js';
|
|
9
|
+
export type { ITimelineEvent, TRequestStage } from '../services/request-timeline.js';
|
package/testing/edge.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"../edge/render-to-stream.js";import r from"./create-handler.js";export{default as createDeferred}from"./deferred.js";export{browserRequest,crawlerRequest}from"./requests.js";export{default as TestResponse}from"./response.js";const s=r(e,()=>{throw new Error("shell.indexFile requires Node. In edge tests pass shell: { header, footer }.")});export{s as createTestHandler};
|
|
2
|
+
//# sourceMappingURL=edge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge.js","sources":["../../src/testing/edge.ts"],"sourcesContent":[null],"names":["createTestHandler","testHandlerFactory","renderToStream","Error"],"mappings":"+OAGA,MAAMA,EAAoBC,EAAmBC,EAAgB,KAC3D,MAAM,IAAIC,MAAM"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type TStreamFrame = ['init', string, boolean] | ['resolve' | 'reject', number, string] | ['shell'];
|
|
2
|
+
interface IRouterState {
|
|
3
|
+
loaderData: Record<string, any>;
|
|
4
|
+
actionData: Record<string, any> | null;
|
|
5
|
+
errors: Record<string, any> | null;
|
|
6
|
+
}
|
|
7
|
+
/** Frames contain only primitive tuple fields; encoded values are JSON strings. */
|
|
8
|
+
declare const streamFrames: (html: string) => TStreamFrame[];
|
|
9
|
+
/** Resolve nested identities and preserve native collections, holes and own keys. */
|
|
10
|
+
declare const routerState: (html: string) => IRouterState | undefined;
|
|
11
|
+
export { routerState, streamFrames };
|
|
12
|
+
export type { IRouterState, TStreamFrame };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{parse as e}from"devalue";import{parse as t}from"parse5";const r=e=>{const r=[],o=e=>{"tagName"in e&&"script"===e.tagName?r.push(e.childNodes.map(e=>"value"in e?e.value:"").join("")):"childNodes"in e&&e.childNodes.forEach(o)};return o(t(e)),r},o=e=>{const t=[];for(const o of r(e)){const e=/\(window\.__ssrBoostStream\s*=\s*window\.__ssrBoostStream\s*\|\|\s*\[\]\)\.push\((\[(?:"(?:\\.|[^"\\])*"|[^\]"\\])*\])\)/g;for(const r of o.matchAll(e)){const e=JSON.parse(r[1]);if(!Array.isArray(e)||!("shell"===e[0]&&1===e.length||"init"===e[0]&&3===e.length&&"string"==typeof e[1]&&"boolean"==typeof e[2]||["resolve","reject"].includes(e[0])&&3===e.length&&Number.isInteger(e[1])&&"string"==typeof e[2]))throw new Error("Invalid SSR Boost stream frame.");t.push(e)}}return t};class s{id;constructor(e){this.id=e}}const n=t=>e(t,{SSRBPromise:([e])=>new s(e),SSRBObject:e=>Object.fromEntries(e),SSRBError:e=>{const t=Object.fromEntries(e),r=Object.assign(new Error("Streamed loader/action rejection"),t);return t.stack||delete r.stack,r},SSRBUndefined:()=>{}}),a=e=>{const t=o(e),a=t.filter(e=>"init"===e[0]);if(!a.length){for(const t of r(e)){const e=t.match(/window\.__staticRouterHydrationData\s*=\s*JSON\.parse\(("(?:\\.|[^"\\])*")\)/);if(e)return JSON.parse(JSON.parse(e[1]))}return}if(1!==a.length)throw new Error("Expected exactly one SSR Boost init frame.");const i=new Map,c=new Set;for(const e of t)if("resolve"===e[0]||"reject"===e[0]){if(i.has(e[1]))throw new Error(`Duplicate settlement for SSR promise ${e[1]}.`);i.set(e[1],n(e[2])),"reject"===e[0]&&c.add(e[1])}const f=new WeakSet,l=new Set,d=new Map,h=e=>{if(e instanceof s){const{id:t}=e;if(!i.has(t))throw new Error(`Missing settlement for SSR promise ${t}.`);if(c.has(t))throw i.get(t);if(l.has(t))throw new Error(`Circular SSR promise ${t}.`);return d.has(t)||(l.add(t),d.set(t,h(i.get(t))),l.delete(t)),d.get(t)}if(!e||"object"!=typeof e||f.has(e))return e;if(f.add(e),e instanceof Map){const t=[...e];e.clear(),t.forEach(([t,r])=>e.set(h(t),h(r)))}else if(e instanceof Set){const t=[...e];e.clear(),t.forEach(t=>e.add(h(t)))}else for(const t of Object.keys(e))Object.defineProperty(e,t,{configurable:!0,enumerable:!0,writable:!0,value:h(Reflect.get(e,t))});return e};return h(n(a[0][1]))};export{a as routerState,o as streamFrames};
|
|
2
|
+
//# sourceMappingURL=parse-response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-response.js","sources":["../../src/testing/parse-response.ts"],"sourcesContent":[null],"names":["scripts","html","result","visit","node","tagName","push","childNodes","map","child","value","join","forEach","parse","streamFrames","frames","source","pattern","match","matchAll","frame","JSON","Array","isArray","length","includes","Number","isInteger","Error","Placeholder","id","constructor","this","payload","decode","SSRBPromise","SSRBObject","entries","Object","fromEntries","SSRBError","properties","error","assign","stack","SSRBUndefined","routerState","initial","filter","legacy","settlements","Map","rejected","Set","has","set","add","visited","WeakSet","resolving","resolved","resolve","item","get","delete","clear","key","keys","defineProperty","configurable","enumerable","writable","Reflect"],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Page } from '@playwright/test';
|
|
2
|
+
import type { IBrowserTimelineEvent } from './browser-observer.js';
|
|
3
|
+
interface IHydratedOptions {
|
|
4
|
+
root?: string;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
interface IStreamTimelineCollector {
|
|
8
|
+
read: () => Promise<IBrowserTimelineEvent[]>;
|
|
9
|
+
}
|
|
10
|
+
/** Install before navigation so console failures and the original SSR DOM cannot be missed. */
|
|
11
|
+
declare const collectStreamTimeline: (page: Page) => Promise<IStreamTimelineCollector>;
|
|
12
|
+
/** Wait for router creation, all streamed boundaries and a browser rendering opportunity. */
|
|
13
|
+
declare const expectHydrated: (page: Page, { root, timeout }?: IHydratedOptions) => Promise<void>;
|
|
14
|
+
/** Require an observed shell before this element first became visible. */
|
|
15
|
+
declare const expectStreamed: (page: Page, selector: string) => Promise<void>;
|
|
16
|
+
export { collectStreamTimeline, expectHydrated, expectStreamed };
|
|
17
|
+
export type { IBrowserTimelineEvent, IHydratedOptions, IStreamTimelineCollector };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{installBrowserObserver as e,inspectHydration as t}from"./browser-observer.js";const a=new WeakSet,o=async t=>(a.has(t)||(await t.addInitScript(e),a.add(t)),{read:()=>t.evaluate(()=>window.__ssrBoostTest?.events??[])}),s=async(e,{root:o="#root",timeout:s=5e3}={})=>{const{expect:r}=await(import("@playwright/test"));r(a.has(e),"Call collectStreamTimeline(page) before page.goto().").toBe(!0),await r.poll(async()=>(await e.evaluate(t,o)).ready,{timeout:s,message:`SSR router was not created for ${o}. Use the SSR Boost browser entry.`}).toBe(!0),await e.waitForLoadState("load",{timeout:s}),await r.poll(async()=>(await e.evaluate(t,o)).pending,{timeout:s,message:"Streamed Suspense boundaries did not settle."}).toBe(0),await e.evaluate(()=>new Promise(e=>{requestAnimationFrame(()=>requestAnimationFrame(()=>e()))}));const i=await e.evaluate(t,o);r(i.consumed,"Router hydration state was not consumed.").toBe(!0),r(i.errors,"React reported hydration errors.").toEqual([]),r(i.duplicates,"Server text was duplicated during hydration.").toEqual([])},r=async(e,t)=>{const{expect:o}=await(import("@playwright/test"));o(a.has(e),"Call collectStreamTimeline(page) before page.goto().").toBe(!0);const s=e.locator(t);await o(s).toBeVisible();const r=await s.evaluate(e=>({shell:window.__ssrBoostTest?.shellAt,element:window.__ssrBoostTest?.seen.get(e)}));o(r.shell,"No server shell was observed.").toBeDefined(),o(r.element,"The element was not observed during this navigation.").toBeDefined(),o(r.element,"The element must appear after the shell.").toBeGreaterThan(r.shell)};export{o as collectStreamTimeline,s as expectHydrated,r as expectStreamed};
|
|
2
|
+
//# sourceMappingURL=playwright.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright.js","sources":["../../src/testing/playwright.ts"],"sourcesContent":[null],"names":["installed","WeakSet","collectStreamTimeline","async","page","has","addInitScript","installBrowserObserver","add","read","evaluate","window","__ssrBoostTest","events","expectHydrated","root","timeout","expect","toBe","poll","inspectHydration","ready","message","waitForLoadState","pending","Promise","resolve","requestAnimationFrame","result","consumed","errors","toEqual","duplicates","expectStreamed","selector","element","locator","toBeVisible","timing","node","shell","shellAt","seen","get","toBeDefined","toBeGreaterThan"],"mappings":"qFAaA,MAAMA,EAAY,IAAIC,QAGhBC,EAAwBC,MAAOC,IAC9BJ,EAAUK,IAAID,WACXA,EAAKE,cAAcC,GACzBP,EAAUQ,IAAIJ,IAGT,CACLK,KAAM,IAAML,EAAKM,SAAS,IAAMC,OAAOC,gBAAgBC,QAAU,MAK/DC,EAAiBX,MACrBC,GACEW,OAAO,QAASC,UAAU,KAA4B,MAExD,MAAMC,OAAEA,gBAAwB,qBAEhCA,EAAOjB,EAAUK,IAAID,GAAO,wDAAwDc,MAAK,SACnFD,EACHE,KAAKhB,gBAAmBC,EAAKM,SAASU,EAAkBL,IAAOM,MAAO,CACrEL,UACAM,QAAS,kCAAkCP,wCAE5CG,MAAK,SACFd,EAAKmB,iBAAiB,OAAQ,CAAEP,kBAChCC,EACHE,KAAKhB,gBAAmBC,EAAKM,SAASU,EAAkBL,IAAOS,QAAS,CACvER,UACAM,QAAS,iDAEVJ,KAAK,SACFd,EAAKM,SACT,IACE,IAAIe,QAAeC,IACjBC,sBAAsB,IAAMA,sBAAsB,IAAMD,SAG9D,MAAME,QAAexB,EAAKM,SAASU,EAAkBL,GAErDE,EAAOW,EAAOC,SAAU,4CAA4CX,MAAK,GACzED,EAAOW,EAAOE,OAAQ,oCAAoCC,QAAQ,IAClEd,EAAOW,EAAOI,WAAY,gDAAgDD,QAAQ,KAI9EE,EAAiB9B,MAAOC,EAAY8B,KACxC,MAAMjB,OAAEA,gBAAwB,qBAEhCA,EAAOjB,EAAUK,IAAID,GAAO,wDAAwDc,MAAK,GACzF,MAAMiB,EAAU/B,EAAKgC,QAAQF,SAEvBjB,EAAOkB,GAASE,cACtB,MAAMC,QAAeH,EAAQzB,SAAU6B,IAAI,CACzCC,MAAO7B,OAAOC,gBAAgB6B,QAC9BN,QAASxB,OAAOC,gBAAgB8B,KAAKC,IAAIJ,MAG3CtB,EAAOqB,EAAOE,MAAO,iCAAiCI,cACtD3B,EAAOqB,EAAOH,QAAS,wDAAwDS,cAC/E3B,EAAOqB,EAAOH,QAAU,4CAA4CU,gBAClEP,EAAOE"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
declare const TEST_ORIGIN = "http://localhost";
|
|
2
|
+
/** Give relative test paths the same stable origin as createTestHandler.fetch. */
|
|
3
|
+
declare const browserRequest: (path: string) => Request;
|
|
4
|
+
/** Identification only: the application's onRouterReady hook chooses buffering. */
|
|
5
|
+
declare const crawlerRequest: (path: string) => Request;
|
|
6
|
+
export { browserRequest, crawlerRequest, TEST_ORIGIN };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e="http://localhost",t=t=>new Request(new URL(t,e),{headers:{"User-Agent":"Mozilla/5.0 (SSR Boost route test)"}}),o=t=>new Request(new URL(t,e),{headers:{"User-Agent":"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"}});export{e as TEST_ORIGIN,t as browserRequest,o as crawlerRequest};
|
|
2
|
+
//# sourceMappingURL=requests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requests.js","sources":["../../src/testing/requests.ts"],"sourcesContent":[null],"names":["TEST_ORIGIN","browserRequest","path","Request","URL","headers","crawlerRequest"],"mappings":"AAAA,MAAMA,EAAc,mBAGdC,EAAkBC,GACtB,IAAIC,QAAQ,IAAIC,IAAIF,EAAMF,GAAc,CACtCK,QAAS,CAAE,aAAc,wCAIvBC,EAAkBJ,GACtB,IAAIC,QAAQ,IAAIC,IAAIF,EAAMF,GAAc,CACtCK,QAAS,CACP,aAAc"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ITimelineEvent } from '../services/request-timeline.js';
|
|
2
|
+
import type RequestTimeline from '../services/request-timeline.js';
|
|
3
|
+
import type { IRouterState, TStreamFrame } from './parse-response.js';
|
|
4
|
+
interface ITestChunk {
|
|
5
|
+
text: string;
|
|
6
|
+
at: number;
|
|
7
|
+
}
|
|
8
|
+
interface ITestCookie {
|
|
9
|
+
name: string;
|
|
10
|
+
value: string;
|
|
11
|
+
/** Lowercase attribute names; flags are true, other values remain strings. */
|
|
12
|
+
attributes: Record<string, string | true>;
|
|
13
|
+
}
|
|
14
|
+
interface ITestResponseOptions {
|
|
15
|
+
started?: number;
|
|
16
|
+
timeline?: RequestTimeline;
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
onComplete?: () => void;
|
|
19
|
+
}
|
|
20
|
+
/** A single eager stream reader with repeatable, order-independent assertions. */
|
|
21
|
+
declare class TestResponse {
|
|
22
|
+
readonly response: Response;
|
|
23
|
+
protected readonly options: ITestResponseOptions;
|
|
24
|
+
protected readonly parts: ITestChunk[];
|
|
25
|
+
protected readonly completed: Promise<void>;
|
|
26
|
+
protected readonly started: number;
|
|
27
|
+
constructor(response: Response, options?: ITestResponseOptions);
|
|
28
|
+
get status(): number;
|
|
29
|
+
get headers(): Headers;
|
|
30
|
+
/** Decode incrementally so multibyte characters survive arbitrary transport cuts. */
|
|
31
|
+
protected read(): Promise<void>;
|
|
32
|
+
text(): Promise<string>;
|
|
33
|
+
/** The raw full document, including React boundary instructions and data scripts. */
|
|
34
|
+
html(): Promise<string>;
|
|
35
|
+
chunks(): Promise<ITestChunk[]>;
|
|
36
|
+
routerState(): Promise<IRouterState | undefined>;
|
|
37
|
+
/** Count raw markers: streamed HTML retains them even after replacement scripts arrive. */
|
|
38
|
+
pendingBoundaries(): Promise<number>;
|
|
39
|
+
streamFrames(): Promise<TStreamFrame[]>;
|
|
40
|
+
/** A failed/cancelled read still has a useful diagnostic timeline. */
|
|
41
|
+
timeline(): Promise<ITimelineEvent[]>;
|
|
42
|
+
/** Preserve separate cookies and commas in Expires, without running a browser cookie jar. */
|
|
43
|
+
cookies(): ITestCookie[];
|
|
44
|
+
}
|
|
45
|
+
export type { ITestChunk, ITestCookie, ITestResponseOptions };
|
|
46
|
+
export default TestResponse;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{routerState as t,streamFrames as e}from"./parse-response.js";class s{response;options;parts=[];completed;started;constructor(t,e={}){this.response=t,this.options=e,this.started=e.started??performance.now(),this.completed=this.read(),this.completed.catch(()=>{})}get status(){return this.response.status}get headers(){return this.response.headers}async read(){const t=this.response.body?.getReader(),e=new TextDecoder,{signal:s,onComplete:r}=this.options,a=()=>{t?.cancel(s?.reason).catch(()=>{})};s?.addEventListener("abort",a,{once:!0});try{if(s?.throwIfAborted(),t)for(;;){const r=await t.read();s?.throwIfAborted();const a=r.done?e.decode():e.decode(r.value,{stream:!0});if(a&&this.parts.push({text:a,at:performance.now()-this.started}),r.done)break}}catch(e){throw await(t?.cancel(e).catch(()=>{})),e}finally{t?.releaseLock(),s?.removeEventListener("abort",a),r?.()}}async text(){return await this.completed,this.parts.map(t=>t.text).join("")}html(){return this.text()}async chunks(){return await this.completed,this.parts.map(t=>({...t}))}async routerState(){return t(await this.text())}async pendingBoundaries(){return(await this.text()).split("\x3c!--$?--\x3e").length-1}async streamFrames(){return e(await this.text())}async timeline(){return await this.completed.catch(()=>{}),this.options.timeline?.events.map(t=>({...t}))??[]}cookies(){const t=this.headers;return(t.getSetCookie?.()??t.get("set-cookie")?.split(/,(?=\s*[^=;,\s]+=)/)??[]).map(t=>{const[e,...s]=t.split(";"),r=e.indexOf("=");return{name:e.slice(0,r).trim(),value:e.slice(r+1).trim(),attributes:Object.fromEntries(s.map(t=>{const e=t.indexOf("=");return e<0?[t.trim().toLowerCase(),!0]:[t.slice(0,e).trim().toLowerCase(),t.slice(e+1).trim()]}))}})}}export{s as default};
|
|
2
|
+
//# sourceMappingURL=response.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.js","sources":["../../src/testing/response.ts"],"sourcesContent":[null],"names":["TestResponse","response","options","parts","completed","started","constructor","this","performance","now","read","catch","status","headers","reader","body","getReader","decoder","TextDecoder","signal","onComplete","onAbort","cancel","reason","addEventListener","once","throwIfAborted","chunk","text","done","decode","value","stream","push","at","error","releaseLock","removeEventListener","map","join","html","chunks","routerState","pendingBoundaries","split","length","streamFrames","timeline","events","event","cookies","getSetCookie","get","cookie","pair","attributes","separator","indexOf","name","slice","trim","Object","fromEntries","attribute","index","toLowerCase"],"mappings":"oEAyBA,MAAMA,EAMcC,SACGC,QANFC,MAAsB,GACtBC,UACAC,QAEnB,WAAAC,CACkBL,EACGC,EAAgC,IADnCK,KAAAN,SAAAA,EACGM,KAAAL,QAAAA,EAEnBK,KAAKF,QAAUH,EAAQG,SAAWG,YAAYC,MAC9CF,KAAKH,UAAYG,KAAKG,OACjBH,KAAKH,UAAUO,MAAM,OAC5B,CAEA,UAAWC,GACT,OAAOL,KAAKN,SAASW,MACvB,CAEA,WAAWC,GACT,OAAON,KAAKN,SAASY,OACvB,CAGU,UAAMH,GACd,MAAMI,EAASP,KAAKN,SAASc,MAAMC,YAC7BC,EAAU,IAAIC,aACdC,OAAEA,EAAMC,WAAEA,GAAeb,KAAKL,QAC9BmB,EAAU,KACTP,GAAQQ,OAAOH,GAAQI,QAAQZ,MAAM,SAG5CQ,GAAQK,iBAAiB,QAASH,EAAS,CAAEI,MAAM,IAEnD,IAGE,GAFAN,GAAQO,iBAEJZ,EACF,OAAa,CACX,MAAMa,QAAcb,EAAOJ,OAE3BS,GAAQO,iBAER,MAAME,EAAOD,EAAME,KACfZ,EAAQa,SACRb,EAAQa,OAAOH,EAAMI,MAAO,CAAEC,QAAQ,IAM1C,GAJIJ,GACFrB,KAAKJ,MAAM8B,KAAK,CAAEL,OAAMM,GAAI1B,YAAYC,MAAQF,KAAKF,UAGnDsB,EAAME,KACR,KAEJ,CAEJ,CAAE,MAAOM,GAEP,YADMrB,GAAQQ,OAAOa,GAAOxB,MAAM,SAC5BwB,CACR,SACErB,GAAQsB,cACRjB,GAAQkB,oBAAoB,QAAShB,GACrCD,KACF,CACF,CAEO,UAAMQ,GAGX,aAFMrB,KAAKH,UAEJG,KAAKJ,MAAMmC,IAAKX,GAAUA,EAAMC,MAAMW,KAAK,GACpD,CAGO,IAAAC,GACL,OAAOjC,KAAKqB,MACd,CAEO,YAAMa,GAGX,aAFMlC,KAAKH,UAEJG,KAAKJ,MAAMmC,IAAKX,QAAgBA,IACzC,CAEO,iBAAMe,GACX,OAAOA,QAAkBnC,KAAKqB,OAChC,CAGO,uBAAMe,GACX,aAAcpC,KAAKqB,QAAQgB,MAAM,mBAAaC,OAAS,CACzD,CAEO,kBAAMC,GACX,OAAOA,QAAmBvC,KAAKqB,OACjC,CAGO,cAAMmB,GAGX,aAFMxC,KAAKH,UAAUO,MAAM,QAEpBJ,KAAKL,QAAQ6C,UAAUC,OAAOV,IAAKW,QAAgBA,MAAa,EACzE,CAGO,OAAAC,GACL,MAAMrC,EAAUN,KAAKM,QAIrB,OAFEA,EAAQsC,kBAAoBtC,EAAQuC,IAAI,eAAeR,MAAM,uBAAyB,IAE1EN,IAAKe,IACjB,MAAOC,KAASC,GAAcF,EAAOT,MAAM,KACrCY,EAAYF,EAAKG,QAAQ,KAE/B,MAAO,CACLC,KAAMJ,EAAKK,MAAM,EAAGH,GAAWI,OAC/B7B,MAAOuB,EAAKK,MAAMH,EAAY,GAAGI,OACjCL,WAAYM,OAAOC,YACjBP,EAAWjB,IAAKyB,IACd,MAAMC,EAAQD,EAAUN,QAAQ,KAEhC,OAAOO,EAAQ,EACX,CAACD,EAAUH,OAAOK,eAAe,GACjC,CAACF,EAAUJ,MAAM,EAAGK,GAAOJ,OAAOK,cAAeF,EAAUJ,MAAMK,EAAQ,GAAGJ,aAK1F"}
|
package/testing.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
declare const createTestHandler: <TAppProps = Record<string, any>>({ routes, App, shell, routerOptions, renderToStream, signal: defaultSignal, timeout: defaultTimeout, onContext, onRouterReady, ...options }: import("./testing.js").ITestHandlerOptions<TAppProps>) => import("./testing.js").ITestHandler;
|
|
2
|
+
export { createTestHandler };
|
|
3
|
+
export { default as createDeferred } from './testing/deferred.js';
|
|
4
|
+
export { browserRequest, crawlerRequest } from './testing/requests.js';
|
|
5
|
+
export { default as TestResponse } from './testing/response.js';
|
|
6
|
+
export type { ITestHandler, ITestHandlerOptions, ITestRequestInit } from './testing/create-handler.js';
|
|
7
|
+
export type { ITestChunk, ITestCookie, ITestResponseOptions } from './testing/response.js';
|
|
8
|
+
export type { IRouterState, TStreamFrame } from './testing/parse-response.js';
|
|
9
|
+
export type { ITimelineEvent, TRequestStage } from './services/request-timeline.js';
|
package/testing.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"./node/render-to-stream.js";import r from"./testing/create-handler.js";export{default as createDeferred}from"./testing/deferred.js";export{browserRequest,crawlerRequest}from"./testing/requests.js";export{default as TestResponse}from"./testing/response.js";const t=r(e,async e=>(await(import("./node/production.js"))).loadHtmlShell(e));export{t as createTestHandler};
|
|
2
|
+
//# sourceMappingURL=testing.js.map
|
package/testing.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.js","sources":["../src/testing.ts"],"sourcesContent":[null],"names":["createTestHandler","testHandlerFactory","renderToStream","async","options","loadHtmlShell"],"mappings":"8QAGA,MAAMA,EAAoBC,EAAmBC,EAAgBC,MAAOC,iBACpD,0BAAqBC,cAAcD"}
|