@lomray/vite-ssr-boost 8.4.0-beta.2 → 8.4.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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/cloudflare.d.ts +57 -0
- package/cloudflare.js +2 -0
- package/cloudflare.js.map +1 -0
- 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 +4 -1
- package/core/render.js +1 -1
- package/core/render.js.map +1 -1
- package/core/types.d.ts +5 -1
- package/node/production.d.ts +10 -4
- package/node/production.js +1 -1
- package/node/production.js.map +1 -1
- package/package.json +36 -3
- package/services/request-timeline.d.ts +30 -0
- package/services/request-timeline.js +2 -0
- package/services/request-timeline.js.map +1 -0
- package/services/route-asset-preparer.d.ts +7 -0
- package/services/route-asset-preparer.js +2 -0
- package/services/route-asset-preparer.js.map +1 -0
- package/services/route-assets-memory.d.ts +63 -0
- package/services/route-assets-memory.js +2 -0
- package/services/route-assets-memory.js.map +1 -0
- package/services/route-assets.d.ts +9 -55
- package/services/route-assets.js +1 -1
- package/services/route-assets.js.map +1 -1
- package/services/ssr-manifest.js +1 -1
- package/services/ssr-manifest.js.map +1 -1
- 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
|
@@ -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"}
|