@lomray/vite-ssr-boost 8.1.0-beta.1 → 8.2.0-beta.1

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 CHANGED
@@ -1,6 +1,56 @@
1
1
  # Vite SSR BOOST
2
2
 
3
- SSR for React Router apps in [Data mode](https://reactrouter.com/start/modes), without moving to Framework mode and without rewriting the app. `@lomray/vite-ssr-boost` adds server rendering to your Vite project while keeping your route objects and components. Build SSR and SPA output from the same app, and choose a managed Express server or a Fetch handler for your own transport.
3
+ <p align="center"><img src="https://raw.githubusercontent.com/Lomray-Software/vite-ssr-boost/prod/logo.png" alt="Vite SSR BOOST logo" width="250" height="250"></p>
4
+
5
+ <p align="center">SSR for React Router apps in <a href="https://reactrouter.com/start/modes">Data mode</a>, without moving to Framework mode and without rewriting the app.</p>
6
+
7
+ <p align="center">
8
+ <a href="https://sonarcloud.io/dashboard?id=vite-ssr-boost"><img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&amp;metric=reliability_rating" alt="Reliability Rating"></a>
9
+ <a href="https://sonarcloud.io/dashboard?id=vite-ssr-boost"><img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&amp;metric=security_rating" alt="Security Rating"></a>
10
+ <a href="https://sonarcloud.io/dashboard?id=vite-ssr-boost"><img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&amp;metric=sqale_rating" alt="Maintainability Rating"></a>
11
+ <a href="https://sonarcloud.io/dashboard?id=vite-ssr-boost"><img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&amp;metric=vulnerabilities" alt="Vulnerabilities"></a>
12
+ <a href="https://sonarcloud.io/dashboard?id=vite-ssr-boost"><img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&amp;metric=bugs" alt="Bugs"></a>
13
+ <a href="https://sonarcloud.io/dashboard?id=vite-ssr-boost"><img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&amp;metric=ncloc" alt="Lines of Code"></a>
14
+ <a href="https://sonarcloud.io/dashboard?id=vite-ssr-boost"><img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&amp;metric=coverage" alt="Code Coverage"></a>
15
+ <a href="https://www.npmjs.com/package/@lomray/vite-ssr-boost"><img src="https://img.shields.io/npm/v/@lomray/vite-ssr-boost?label=semantic%20release&amp;logo=semantic-release" alt="npm version"></a>
16
+ <a href="https://www.npmjs.com/package/@lomray/vite-ssr-boost"><img src="https://img.shields.io/npm/dm/@lomray/vite-ssr-boost" alt="npm monthly downloads"></a>
17
+ <a href="./LICENSE"><img src="https://img.shields.io/npm/l/@lomray/vite-ssr-boost" alt="MIT License"></a>
18
+ <a href="https://www.npmjs.com/package/@lomray/vite-ssr-boost"><img src="https://img.shields.io/node/v/@lomray/vite-ssr-boost" alt="Node version requirement"></a>
19
+ </p>
20
+
21
+ ## Quick start
22
+
23
+ **Start a new app** with the `minimal` template (default):
24
+
25
+ ```bash
26
+ npm create @lomray/ssr-app@latest my-app
27
+ ```
28
+
29
+ Choose the `full` template by passing the flag after `--`:
30
+
31
+ ```bash
32
+ npm create @lomray/ssr-app@latest my-app -- --template full
33
+ ```
34
+
35
+ **Add to an existing app:**
36
+
37
+ ```bash
38
+ npm i @lomray/vite-ssr-boost
39
+ ```
40
+
41
+ `@lomray/vite-ssr-boost` adds server rendering to your Vite project while keeping your route objects and components. Build SSR and SPA output from the same app, and choose a managed Express server or a Fetch handler for your own transport.
42
+
43
+ The [migration guide](./docs/guide/migrate-existing-spa.md) walks through the five-file change:
44
+
45
+ | File | Change |
46
+ | ---------------- | ---------------------------------------------------- |
47
+ | `vite.config.ts` | Add `SsrBoost()` to the plugins. |
48
+ | `src/index.html` | Add the SSR outlet inside the root element. |
49
+ | `src/client.ts` | Use the browser entry for hydration or SPA mounting. |
50
+ | `src/server.ts` | Add the server entry and request-scoped setup. |
51
+ | `package.json` | Use the `ssr-boost` dev, build and start commands. |
52
+
53
+ Starting a new app? Choose one of the [template branches](./docs/examples/index.md) with the [`npm create` command](./docs/guide/getting-started.md#create-a-new-app) or clone the branch directly.
4
54
 
5
55
  ## Who this is for
6
56
 
@@ -34,32 +84,68 @@ Add `SsrBoost()` to the Vite plugins, wire `client.ts` and `server.ts`, and repl
34
84
 
35
85
  ## Install and template quick start
36
86
 
87
+ The package declares `engines.node: ">=22.12.0"`. The example uses Node 22.23.2; React Router and build tools can raise the required Node version.
88
+
89
+ Start with the [minimal template](https://github.com/Lomray-Software/vite-template/tree/example/minimal):
90
+
37
91
  ```bash
38
- npm i @lomray/vite-ssr-boost
92
+ npm create @lomray/ssr-app@latest my-app
93
+ cd my-app
94
+ npm run develop
39
95
  ```
40
96
 
41
- The package declares `engines.node: ">=22.12.0"`. The example uses Node 22.23.2; React Router and build tools can raise the required Node version.
97
+ Or clone the template branch directly:
42
98
 
43
- Start with the [minimal template](https://github.com/Lomray-Software/vite-template/tree/example/minimal): run `git clone --branch example/minimal https://github.com/Lomray-Software/vite-template.git`, then `cd vite-template`, `npm ci` and `npm run develop`. Its six direct runtime dependencies are React, React DOM, React Router, vite-ssr-boost, `@lomray/react-head-manager` and `isbot`.
99
+ ```bash
100
+ git clone --branch example/minimal https://github.com/Lomray-Software/vite-template.git
101
+ cd vite-template
102
+ npm ci
103
+ npm run develop
104
+ ```
105
+
106
+ Its six direct runtime dependencies are React, React DOM, React Router, vite-ssr-boost, `@lomray/react-head-manager` and `isbot`.
44
107
 
45
108
  For production, run `npm run build` and `npm run start:ssr`. For a SPA build, run `npm run build:spa` and `npm run start:spa`. See [Example projects](./docs/examples/index.md) for the `prod` template with state management and deployment workflows.
46
109
 
47
110
  Already running this in production? Point our [free performance audit](https://audit.lomray.com/?utm_source=github&utm_medium=readme-vite-ssr-boost&utm_campaign=owned-surface-github) at the URL. It reports Core Web Vitals, JavaScript bundle weight and whether the HTML really arrives server-rendered. No signup.
48
111
 
49
- ## Documentation
112
+ ## Compatibility
50
113
 
51
- Read the [documentation site](https://lomray-software.github.io/vite-ssr-boost/), the [comparison guide](./docs/guide/choosing.md) and the [FAQ](./docs/reference/faq.md).
114
+ The package is tested against the current and previous major of React, React Router and Vite, with an additional Vite 6 row. The [compatibility workflow](./.github/workflows/react-compatibility.yml) runs the full test suite and a built Worker check on Node 22.23.2 with these exact combinations:
52
115
 
53
- <p align="center">
54
- <img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=reliability_rating" alt="reliability">
55
- <img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=security_rating" alt="Security Rating">
56
- <img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=sqale_rating" alt="Maintainability Rating">
57
- <img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=vulnerabilities" alt="Vulnerabilities">
58
- <img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=bugs" alt="Bugs">
59
- <img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=ncloc" alt="Lines of Code">
60
- <img src="https://sonarcloud.io/api/project_badges/measure?project=vite-ssr-boost&metric=coverage" alt="code coverage">
61
- <img src="https://img.shields.io/npm/v/@lomray/vite-ssr-boost?label=semantic%20release&logo=semantic-release" alt="semantic version">
62
- </p>
116
+ | React / React DOM | React Router | Vite |
117
+ | ----------------- | ------------ | ------- |
118
+ | `18.2.0` | `7.18.3` | `6.4.3` |
119
+ | `19.2.8` | `7.18.3` | `7.3.6` |
120
+ | `19.2.8` | `8.3.1` | `8.2.2` |
121
+
122
+ [package.json](./package.json) declares Node `>=22.12.0` and these peer ranges:
123
+
124
+ | Peer | Range |
125
+ | -------------- | ---------- |
126
+ | `react` | `>=18.2.0` |
127
+ | `react-dom` | `>=18.2.0` |
128
+ | `react-router` | `>=7.0.1` |
129
+ | `vite` | `>=5` |
130
+
131
+ Peer ranges allow installation; the matrix tests only the combinations above. It does not test every version in those ranges or every combination of majors.
132
+
133
+ ## Examples
134
+
135
+ The [example projects guide](./docs/examples/index.md) explains the wiring in each template branch.
136
+
137
+ | Template branch | What it includes |
138
+ | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
139
+ | [`prod`](https://github.com/Lomray-Software/vite-template/tree/prod) | MobX state management, component-level data streaming, metadata and deployment workflows. |
140
+ | [`example/minimal`](https://github.com/Lomray-Software/vite-template/tree/example/minimal) | Six runtime dependencies, loaders, a lazy route with CSS, redirects, 404s, metadata and a browser-only route. |
141
+ | [`example/custom-server`](https://github.com/Lomray-Software/vite-template/tree/example/custom-server) | Managed CLI development and an application-owned Fastify 5 production server with static assets, compression, route assets and Early Hints. |
142
+ | [`example/localization`](https://github.com/Lomray-Software/vite-template/tree/example/localization) | Per-request i18next, cookie and header language selection, and language state restored before hydration. |
143
+
144
+ ## Documentation
145
+
146
+ - [Documentation site](https://lomray-software.github.io/vite-ssr-boost/), [comparison guide](./docs/guide/choosing.md) and [FAQ](./docs/reference/faq.md).
147
+ - [Hydration order and streaming](./docs/reference/hydration-and-streaming.md).
148
+ - 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).
63
149
 
64
150
  ## License
65
151
 
@@ -1,2 +1,2 @@
1
- import e from"node:fs";import t from"node:path";import r from"node:process";import{pathToFileURL as i}from"node:url";import o from"chalk";import s from"../../services/server-api.js";class n{onServerStarted;config;serverApi;entrypoint;onServerCreated;html;middlewaresConfigs;constructor(e,t){this.config=e,this.serverApi=t??new s}static init(e,t){return new n(e,t)}async loadEntrypoint(e=!0){if(this.entrypoint&&this.config.isProd)return this.entrypoint;const{root:s,isProd:n,serverFile:a}=this.config.getParams(),l=t.resolve(`${s}/${a}`);let d;try{d=n?(await(import(i(l).toString()))).default:(await this.config.getVite().ssrLoadModule(l,{fixStacktrace:!0})).default}catch(e){if(e instanceof Error&&e.message.includes("Cannot find module")&&e.message.includes("/build/"))return this.config.getLogger().error(o.red(`Before starting the server, you need to create a build: ${o.yellow("ssr-boost build")} or provide path to build dir: ${o.yellow("ssr-boost start --build-dir build")}`)),r.exit(1);throw e}!e&&d.init&&delete d.init;const{render:c,init:g,routes:h,abortDelay:f,loggerProd:p,loggerDev:m,middlewares:u}=d;this.middlewaresConfigs=u,p&&n?this.config.setLogger(p):m&&!n&&this.config.setLogger(m);const{onServerCreated:y,onServerStarted:v,...w}=await(g?.({config:this.config}))??{};return this.entrypoint={render:c,routes:h,abortDelay:f,...w},this.onServerCreated=y,this.onServerStarted=v,this.entrypoint}async loadHtml(r){const{isProd:i,root:o,indexFile:s,clientFile:n}=this.config.getParams();this.html&&i||(this.html=e.readFileSync(t.resolve(`${o}/${s}`),"utf-8"));let a=this.html;if(!i){const e=t.posix.normalize(`${this.config.getVite()?.config.base}/${n}`);a=(await this.config.getVite().transformIndexHtml(r.originalUrl,this.html,s)).replace(new RegExp(String.raw`<script[^>]*?\bsrc=["']/?${e}([^"']*)["'][^>]*?\sasync\b`,"g"),e=>e.replace(/\sasync\b/,""))}return a.split("\x3c!--ssr-outlet--\x3e")}async onAppCreated(){return await this.loadEntrypoint(),await(this.onServerCreated?.(this.config.getApp(),this.serverApi)),this}getMiddlewaresConfig(){const{compression:e,expressStatic:t}=this.middlewaresConfigs??{};return{compression:!1!==e&&{...e},expressStatic:!1!==t&&{...t,basename:t?.basename??"/"}}}}export{n as default};
1
+ import e from"node:fs";import t from"node:path";import r from"node:process";import{pathToFileURL as i}from"node:url";import o from"chalk";import{splitHtmlShell as s}from"../../services/diagnostics.js";import n from"../../services/server-api.js";class a{onServerStarted;config;serverApi;entrypoint;onServerCreated;html;middlewaresConfigs;constructor(e,t){this.config=e,this.serverApi=t??new n}static init(e,t){return new a(e,t)}async loadEntrypoint(e=!0){if(this.entrypoint&&this.config.isProd)return this.entrypoint;const{root:s,isProd:n,serverFile:a}=this.config.getParams(),d=t.resolve(`${s}/${a}`);let l;try{l=n?(await(import(i(d).toString()))).default:(await this.config.getVite().ssrLoadModule(d,{fixStacktrace:!0})).default}catch(e){if(e instanceof Error&&e.message.includes("Cannot find module")&&e.message.includes("/build/"))return this.config.getLogger().error(o.red(`Before starting the server, you need to create a build: ${o.yellow("ssr-boost build")} or provide path to build dir: ${o.yellow("ssr-boost start --build-dir build")}`)),r.exit(1);throw e}!e&&l.init&&delete l.init;const{render:c,init:g,routes:h,abortDelay:f,loggerProd:m,loggerDev:p,middlewares:u}=l;this.middlewaresConfigs=u,m&&n?this.config.setLogger(m):p&&!n&&this.config.setLogger(p);const{onServerCreated:v,onServerStarted:y,...w}=await(g?.({config:this.config}))??{};return this.entrypoint={render:c,routes:h,abortDelay:f,...w},this.onServerCreated=v,this.onServerStarted=y,this.entrypoint}async loadHtml(r){const{isProd:i,root:o,indexFile:n,clientFile:a}=this.config.getParams();this.html&&i||(this.html=e.readFileSync(t.resolve(`${o}/${n}`),"utf-8"));let d=this.html;if(!i){const e=t.posix.normalize(`${this.config.getVite()?.config.base}/${a}`);d=(await this.config.getVite().transformIndexHtml(r.originalUrl,this.html,n)).replace(new RegExp(String.raw`<script[^>]*?\bsrc=["']/?${e}([^"']*)["'][^>]*?\sasync\b`,"g"),e=>e.replace(/\sasync\b/,""))}return s(d,t.resolve(`${o}/${n}`))}async onAppCreated(){return await this.loadEntrypoint(),await(this.onServerCreated?.(this.config.getApp(),this.serverApi)),this}getMiddlewaresConfig(){const{compression:e,expressStatic:t}=this.middlewaresConfigs??{};return{compression:!1!==e&&{...e},expressStatic:!1!==t&&{...t,basename:t?.basename??"/"}}}}export{a as default};
2
2
  //# sourceMappingURL=prepare-server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prepare-server.js","sources":["../../../src/adapters/express/prepare-server.ts"],"sourcesContent":[null],"names":["PrepareServer","onServerStarted","config","serverApi","entrypoint","onServerCreated","html","middlewaresConfigs","constructor","this","ServerApi","init","loadEntrypoint","shouldInit","isProd","root","serverFile","getParams","entrypointPath","path","resolve","resolvedEntrypoint","pathToFileURL","toString","default","getVite","ssrLoadModule","fixStacktrace","e","Error","message","includes","getLogger","error","chalk","red","yellow","process","exit","render","routes","abortDelay","loggerProd","loggerDev","middlewares","setLogger","renderParams","loadHtml","req","indexFile","clientFile","fs","readFileSync","modifiedHtml","clientFileEntry","posix","normalize","base","transformIndexHtml","originalUrl","replace","RegExp","String","raw","match","split","onAppCreated","getApp","getMiddlewaresConfig","compression","expressStatic","basename"],"mappings":"sLAyBA,MAAMA,EAIGC,gBAKYC,OAKAC,UAKTC,WAKAC,gBAKAC,KAKAC,mBAKV,WAAAC,CAAsBN,EAAsBC,GAC1CM,KAAKP,OAASA,EACdO,KAAKN,UAAYA,GAAa,IAAIO,CACpC,CAKO,WAAOC,CAAKT,EAAsBC,GACvC,OAAO,IAAIH,EAAcE,EAAQC,EACnC,CAKO,oBAAMS,CAAeC,GAAa,GAIvC,GAAIJ,KAAKL,YAAcK,KAAKP,OAAOY,OACjC,OAAOL,KAAKL,WAGd,MAAMW,KAAEA,EAAID,OAAEA,EAAME,WAAEA,GAAeP,KAAKP,OAAOe,YAC3CC,EAAiBC,EAAKC,QAAQ,GAAGL,KAAQC,KAE/C,IAAIK,EAEJ,IAQIA,EAPGP,gBAQaQ,EAAcJ,GAAgBK,cAC5CC,eAPMf,KAAKP,OAAOuB,UAAWC,cAAcR,EAAgB,CACzDS,eAAe,KAEjBH,OAMN,CAAE,MAAOI,GACP,GACEA,aAAaC,OACbD,EAAEE,QAAQC,SAAS,uBACnBH,EAAEE,QAAQC,SAAS,WAcnB,OAZAtB,KAAKP,OACF8B,YACAC,MACCC,EAAMC,IACJ,2DAA2DD,EAAME,OAC/D,oDACiCF,EAAME,OACvC,yCAKDC,EAAQC,KAAK,GAGtB,MAAMV,CACR,EAEKf,GAAcQ,EAAmBV,aAC7BU,EAAmBV,KAG5B,MAAM4B,OAAEA,EAAM5B,KAAEA,EAAI6B,OAAEA,EAAMC,WAAEA,EAAUC,WAAEA,EAAUC,UAAEA,EAASC,YAAEA,GAC/DvB,EAEFZ,KAAKF,mBAAqBqC,EAEtBF,GAAc5B,EAChBL,KAAKP,OAAO2C,UAAUH,GACbC,IAAc7B,GACvBL,KAAKP,OAAO2C,UAAUF,GAGxB,MAAMtC,gBAAEA,EAAeJ,gBAAEA,KAAoB6C,SACpCnC,IAAO,CACZT,OAAQO,KAAKP,WACR,CAAA,EAWT,OATAO,KAAKL,WAAa,CAChBmC,SACAC,SACAC,gBACGK,GAELrC,KAAKJ,gBAAkBA,EACvBI,KAAKR,gBAAkBA,EAEhBQ,KAAKL,UACd,CAKO,cAAM2C,CAASC,GACpB,MAAMlC,OAAEA,EAAMC,KAAEA,EAAIkC,UAAEA,EAASC,WAAEA,GAAezC,KAAKP,OAAOe,YAEvDR,KAAKH,MAASQ,IACjBL,KAAKH,KAAO6C,EAAGC,aAAajC,EAAKC,QAAQ,GAAGL,KAAQkC,KAAc,UAGpE,IAAII,EAAe5C,KAAKH,KAExB,IAAKQ,EAAQ,CACX,MAAMwC,EAAkBnC,EAAKoC,MAAMC,UACjC,GAAG/C,KAAKP,OAAOuB,WAAWvB,OAAOuD,QAAQP,KAM3CG,SACQ5C,KAAKP,OAAOuB,UAAWiC,mBAAmBV,EAAIW,YAAalD,KAAKH,KAAM2C,IAC5EW,QACA,IAAIC,OACFC,OAAOC,GAAG,4BAA4BT,+BACtC,KAEDU,GAAUA,EAAMJ,QAAQ,YAAa,IAE1C,CAEA,OAAOP,EAAaY,MAAM,0BAC5B,CAKO,kBAAMC,GAIX,aAHMzD,KAAKG,uBACLH,KAAKJ,kBAAkBI,KAAKP,OAAOiE,SAAoB1D,KAAKN,YAE3DM,IACT,CAKO,oBAAA2D,GACL,MAAMC,YAAEA,EAAWC,cAAEA,GAAkB7D,KAAKF,oBAAsB,CAAA,EAElE,MAAO,CACL8D,aACkB,IAAhBA,GACI,IACKA,GAGXC,eACoB,IAAlBA,GACI,IACKA,EACHC,SAAUD,GAAeC,UAAY,KAIjD"}
1
+ {"version":3,"file":"prepare-server.js","sources":["../../../src/adapters/express/prepare-server.ts"],"sourcesContent":[null],"names":["PrepareServer","onServerStarted","config","serverApi","entrypoint","onServerCreated","html","middlewaresConfigs","constructor","this","ServerApi","init","loadEntrypoint","shouldInit","isProd","root","serverFile","getParams","entrypointPath","path","resolve","resolvedEntrypoint","pathToFileURL","toString","default","getVite","ssrLoadModule","fixStacktrace","e","Error","message","includes","getLogger","error","chalk","red","yellow","process","exit","render","routes","abortDelay","loggerProd","loggerDev","middlewares","setLogger","renderParams","loadHtml","req","indexFile","clientFile","fs","readFileSync","modifiedHtml","clientFileEntry","posix","normalize","base","transformIndexHtml","originalUrl","replace","RegExp","String","raw","match","splitHtmlShell","onAppCreated","getApp","getMiddlewaresConfig","compression","expressStatic","basename"],"mappings":"qPA0BA,MAAMA,EAIGC,gBAKYC,OAKAC,UAKTC,WAKAC,gBAKAC,KAKAC,mBAKV,WAAAC,CAAsBN,EAAsBC,GAC1CM,KAAKP,OAASA,EACdO,KAAKN,UAAYA,GAAa,IAAIO,CACpC,CAKO,WAAOC,CAAKT,EAAsBC,GACvC,OAAO,IAAIH,EAAcE,EAAQC,EACnC,CAKO,oBAAMS,CAAeC,GAAa,GAIvC,GAAIJ,KAAKL,YAAcK,KAAKP,OAAOY,OACjC,OAAOL,KAAKL,WAGd,MAAMW,KAAEA,EAAID,OAAEA,EAAME,WAAEA,GAAeP,KAAKP,OAAOe,YAC3CC,EAAiBC,EAAKC,QAAQ,GAAGL,KAAQC,KAE/C,IAAIK,EAEJ,IAQIA,EAPGP,gBAQaQ,EAAcJ,GAAgBK,cAC5CC,eAPMf,KAAKP,OAAOuB,UAAWC,cAAcR,EAAgB,CACzDS,eAAe,KAEjBH,OAMN,CAAE,MAAOI,GACP,GACEA,aAAaC,OACbD,EAAEE,QAAQC,SAAS,uBACnBH,EAAEE,QAAQC,SAAS,WAcnB,OAZAtB,KAAKP,OACF8B,YACAC,MACCC,EAAMC,IACJ,2DAA2DD,EAAME,OAC/D,oDACiCF,EAAME,OACvC,yCAKDC,EAAQC,KAAK,GAGtB,MAAMV,CACR,EAEKf,GAAcQ,EAAmBV,aAC7BU,EAAmBV,KAG5B,MAAM4B,OAAEA,EAAM5B,KAAEA,EAAI6B,OAAEA,EAAMC,WAAEA,EAAUC,WAAEA,EAAUC,UAAEA,EAASC,YAAEA,GAC/DvB,EAEFZ,KAAKF,mBAAqBqC,EAEtBF,GAAc5B,EAChBL,KAAKP,OAAO2C,UAAUH,GACbC,IAAc7B,GACvBL,KAAKP,OAAO2C,UAAUF,GAGxB,MAAMtC,gBAAEA,EAAeJ,gBAAEA,KAAoB6C,SACpCnC,IAAO,CACZT,OAAQO,KAAKP,WACR,CAAA,EAWT,OATAO,KAAKL,WAAa,CAChBmC,SACAC,SACAC,gBACGK,GAELrC,KAAKJ,gBAAkBA,EACvBI,KAAKR,gBAAkBA,EAEhBQ,KAAKL,UACd,CAKO,cAAM2C,CAASC,GACpB,MAAMlC,OAAEA,EAAMC,KAAEA,EAAIkC,UAAEA,EAASC,WAAEA,GAAezC,KAAKP,OAAOe,YAEvDR,KAAKH,MAASQ,IACjBL,KAAKH,KAAO6C,EAAGC,aAAajC,EAAKC,QAAQ,GAAGL,KAAQkC,KAAc,UAGpE,IAAII,EAAe5C,KAAKH,KAExB,IAAKQ,EAAQ,CACX,MAAMwC,EAAkBnC,EAAKoC,MAAMC,UACjC,GAAG/C,KAAKP,OAAOuB,WAAWvB,OAAOuD,QAAQP,KAM3CG,SACQ5C,KAAKP,OAAOuB,UAAWiC,mBAAmBV,EAAIW,YAAalD,KAAKH,KAAM2C,IAC5EW,QACA,IAAIC,OACFC,OAAOC,GAAG,4BAA4BT,+BACtC,KAEDU,GAAUA,EAAMJ,QAAQ,YAAa,IAE1C,CAEA,OAAOK,EAAeZ,EAAclC,EAAKC,QAAQ,GAAGL,KAAQkC,KAC9D,CAKO,kBAAMiB,GAIX,aAHMzD,KAAKG,uBACLH,KAAKJ,kBAAkBI,KAAKP,OAAOiE,SAAoB1D,KAAKN,YAE3DM,IACT,CAKO,oBAAA2D,GACL,MAAMC,YAAEA,EAAWC,cAAEA,GAAkB7D,KAAKF,oBAAsB,CAAA,EAElE,MAAO,CACL8D,aACkB,IAAhBA,GACI,IACKA,GAGXC,eACoB,IAAlBA,GACI,IACKA,EACHC,SAAUD,GAAeC,UAAY,KAIjD"}
@@ -1,2 +1,2 @@
1
- import e from"chalk";import r from"react";import t from"./create-request.js";import o from"../../constants/stream-error.js";import s from"../../core/early-hints.js";import{getHeaderEntries as n,getSetCookieHeaders 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 m from"../../node/write-early-hints.js";import p,{writeFetchHeaders as l}from"../../node/write-fetch-response.js";import u from"../../services/ssr-manifest.js";const h=(e,r,o)=>{const s={signal:r};return o&&"GET"!==e.method&&"HEAD"!==e.method&&(s.body=o(e)??null),t(e,s)};async function f({App:t,handler:f},x,y,{onRouterReady:g,onShellReady:E,onResponse:S,onShellError:j,onError:w,getBody:C,getState:v,abortDelay:R=15e3}){const{appProps:b,html:q,req:A,res:H}=y,k=x.getLogger(),D=c(A,H);try{const c=Object.assign(y,{request:h(A,D.signal,C)}),L={appProps:b,html:q,request:c.request,response:{headers:new Headers}},P=e=>(c.request=e.request,c.didError=e.didError,c.html=e.html,c.isStream=e.isStream,c.routerContext=e.routerContext,c.serverContext=e.serverContext,c),T=await i({createApp:(e,o)=>r.createElement(t,{server:{...o.appProps,req:A}},e),handler:f,renderToStream:d},L,{abortDelay:R,getState:v?({context:e})=>v({context:P(e)}):void 0,onError:({context:r,error:t})=>{const{code:s,message:n}=t;if(w?.({context:P(r),error:t}),k.info(e.red(`Stream error. Code: ${s}`)),[o.RenderAborted,o.RenderTimeout,o.RenderCancel].includes(s))return void k.info(e.dim(n));const{original:a}=t;k.error(a)},onResponse:S?({context:e,html:r,isEnd:t})=>S({context:P(e),html:r,isEnd:t}):void 0,onRouterReady:g?({context:e})=>g({context:P(e)}):void 0,onShellError:j?({context:e,error:r})=>j({context:P(e),error:r}):void 0,onShellReady:({context:e})=>{const r=P(e);((e,r)=>{if(r.headersSent||r.writableEnded)return;r.status(e.response.status??200),n(e.response.headers).forEach(([e,t])=>r.setHeader(e,t));const t=a(e.response.headers);t.length&&r.setHeader("Set-Cookie",t)})(e,H);const t=E?.({context:r});return((e,r)=>{const t=new Headers(e.response.headers);t.delete("Set-Cookie");for(const[e,o]of Object.entries(r.getHeaders()))if("set-cookie"!==e.toLowerCase()&&void 0!==o)if(Array.isArray(o))for(const r of o)t.append(e,r);else t.set(e,"number"==typeof o?String(o):o);e.response.headers=t,e.response.status=r.statusCode})(e,H),t??{}},prepare:async({context:e,executionContext:r})=>{const t=P(e),o=u.get(x);await o.prepareDevAssets(e.routerContext?.matches);const n=o.injectAssets(t);t.hasEarlyHints&&await s(r,n)},routerRequestContext:c},{onEarlyHints:e=>m(H,e)});P(L),await(async(e,r)=>{const t=r.headers.get("Location");if(t&&r.status>=300&&r.status<400&&!e.headersSent&&!e.writableEnded&&!e.destroyed)return l(e,r),await(r.body?.cancel()),void e.redirect(r.status,t);await p(e,r)})(H,T)}finally{D.dispose()}}export{f as default};
1
+ import e from"chalk";import r from"react";import t from"./create-request.js";import o from"../../constants/stream-error.js";import s from"../../core/early-hints.js";import{getHeaderEntries as n,getSetCookieHeaders 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 m from"../../node/write-early-hints.js";import p,{writeFetchHeaders as l}from"../../node/write-fetch-response.js";import u,{isDiagnosticsEnabled as h}from"../../services/diagnostics.js";import f from"../../services/ssr-manifest.js";const x=(e,r,o)=>{const s={signal:r};return o&&"GET"!==e.method&&"HEAD"!==e.method&&(s.body=o(e)??null),t(e,s)};async function y({App:t,handler:y},g,E,{onRouterReady:w,onShellReady:S,onResponse:j,onShellError:v,onError:C,getBody:R,getState:q,abortDelay:b=15e3}){const{appProps:A,html:H,req:k,res:D}=E,L=g.getLogger(),P=c(k,D);try{const c=Object.assign(E,{request:x(k,P.signal,R)}),T={appProps:A,diagnostics:h(!g.isProd)?new u(new URL(c.request.url).pathname,L):void 0,html:H,request:c.request,response:{headers:new Headers}},O=e=>(c.request=e.request,c.didError=e.didError,c.html=e.html,c.isStream=e.isStream,c.routerContext=e.routerContext,c.serverContext=e.serverContext,c),B=await i({createApp:(e,o)=>r.createElement(t,{server:{...o.appProps,req:k}},e),handler:y,renderToStream:d},T,{abortDelay:b,getState:q?({context:e})=>q({context:O(e)}):void 0,onError:({context:r,error:t})=>{const{code:s,message:n}=t;if(C?.({context:O(r),error:t}),L.info(e.red(`Stream error. Code: ${s}`)),[o.RenderAborted,o.RenderTimeout,o.RenderCancel].includes(s))return void L.info(e.dim(n));const{original:a}=t;L.error(a)},onResponse:j?({context:e,html:r,isEnd:t})=>j({context:O(e),html:r,isEnd:t}):void 0,onRouterReady:w?({context:e})=>w({context:O(e)}):void 0,onShellError:v?({context:e,error:r})=>v({context:O(e),error:r}):void 0,onShellReady:({context:e})=>{const r=O(e);((e,r)=>{if(r.headersSent||r.writableEnded)return;r.status(e.response.status??200),n(e.response.headers).forEach(([e,t])=>r.setHeader(e,t));const t=a(e.response.headers);t.length&&r.setHeader("Set-Cookie",t)})(e,D);const t=S?.({context:r});return((e,r)=>{const t=new Headers(e.response.headers);t.delete("Set-Cookie");for(const[e,o]of Object.entries(r.getHeaders()))if("set-cookie"!==e.toLowerCase()&&void 0!==o)if(Array.isArray(o))for(const r of o)t.append(e,r);else t.set(e,"number"==typeof o?String(o):o);e.response.headers=t,e.response.status=r.statusCode})(e,D),t??{}},prepare:async({context:e,executionContext:r})=>{const t=O(e),o=f.get(g);await o.prepareDevAssets(e.routerContext?.matches);const n=o.injectAssets(t);t.hasEarlyHints&&await s(r,n)},routerRequestContext:c},{onEarlyHints:e=>m(D,e)});O(T),await(async(e,r)=>{const t=r.headers.get("Location");if(t&&r.status>=300&&r.status<400&&!e.headersSent&&!e.writableEnded&&!e.destroyed)return l(e,r),await(r.body?.cancel()),void e.redirect(r.status,t);await p(e,r)})(D,B)}finally{P.dispose()}}export{y 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","async","render","App","handler","config","initialContext","onRouterReady","onShellReady","onResponse","onShellError","onError","getState","abortDelay","appProps","html","shellHtml","res","Logger","getLogger","requestSignal","createRequestSignal","context","Object","assign","request","coreContext","response","headers","Headers","syncContext","updated","didError","isStream","routerContext","serverContext","coreRender","createApp","children","React","createElement","server","renderToStream","undefined","error","code","message","info","chalk","red","StreamError","RenderAborted","RenderTimeout","RenderCancel","includes","dim","original","isEnd","legacyContext","headersSent","writableEnded","status","getHeaderEntries","forEach","name","value","setHeader","cookies","getSetCookieHeaders","length","prepareResponse","shell","delete","entries","getHeaders","toLowerCase","Array","isArray","item","append","set","String","statusCode","syncResponse","prepare","executionContext","manifest","SsrManifest","get","prepareDevAssets","matches","hints","injectAssets","hasEarlyHints","emitEarlyHints","routerRequestContext","onEarlyHints","writeEarlyHints","location","destroyed","writeFetchHeaders","cancel","redirect","writeFetchResponse","writeResponse","dispose"],"mappings":"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"}
1
+ {"version":3,"file":"render.js","sources":["../../../src/adapters/express/render.tsx"],"sourcesContent":[null],"names":["createRenderRequest","req","signal","getBody","options","method","body","createFetchRequest","async","render","App","handler","config","initialContext","onRouterReady","onShellReady","onResponse","onShellError","onError","getState","abortDelay","appProps","html","shellHtml","res","Logger","getLogger","requestSignal","createRequestSignal","context","Object","assign","request","coreContext","diagnostics","isDiagnosticsEnabled","isProd","Diagnostics","URL","url","pathname","undefined","response","headers","Headers","syncContext","updated","didError","isStream","routerContext","serverContext","coreRender","createApp","children","React","createElement","server","renderToStream","error","code","message","info","chalk","red","StreamError","RenderAborted","RenderTimeout","RenderCancel","includes","dim","original","isEnd","legacyContext","headersSent","writableEnded","status","getHeaderEntries","forEach","name","value","setHeader","cookies","getSetCookieHeaders","length","prepareResponse","shell","delete","entries","getHeaders","toLowerCase","Array","isArray","item","append","set","String","statusCode","syncResponse","prepare","executionContext","manifest","SsrManifest","get","prepareDevAssets","matches","hints","injectAssets","hasEarlyHints","emitEarlyHints","routerRequestContext","onEarlyHints","writeEarlyHints","location","destroyed","writeFetchHeaders","cancel","redirect","writeFetchResponse","writeResponse","dispose"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=(e,a,r,o,n)=>{const t=new TextEncoder,c=a.getReader();let l="header";return new ReadableStream({cancel:async e=>{if(o?.(e),"footer"!==l)try{await c.cancel(e)}finally{c.releaseLock(),n?.()}},async pull(a){if("header"===l&&(l="body",e))a.enqueue(t.encode(e));else{if("body"===l){let e;try{e=await c.read()}catch(e){return o?.(e),c.releaseLock(),n?.(),void a.error(e)}if(!e.done)return void a.enqueue(e.value);l="footer",c.releaseLock(),n?.()}r&&a.enqueue(t.encode(r)),a.close()}}})};export{e as default};
1
+ const e=(e,a,r,o,t)=>{const n=new TextEncoder,c=a.getReader();let l="header";return new ReadableStream({cancel:async e=>{if(o?.(e),"footer"!==l)try{await c.cancel(e)}finally{c.releaseLock(),t?.()}},async pull(a){if("header"===l&&(l="body",e))a.enqueue(n.encode(e));else{if("body"===l){let e;try{e=await c.read()}catch(e){return o?.(e),c.releaseLock(),t?.(),void a.error(e)}if(!e.done)return void a.enqueue(e.value);l="footer",c.releaseLock(),t?.()}r&&a.enqueue(n.encode(r)),a.close()}}},{highWaterMark:0})};export{e as default};
2
2
  //# sourceMappingURL=compose-html.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compose-html.js","sources":["../../src/core/compose-html.ts"],"sourcesContent":[null],"names":["composeHtml","header","body","footer","abort","onComplete","encoder","TextEncoder","reader","getReader","phase","ReadableStream","cancel","async","reason","releaseLock","pull","controller","enqueue","encode","chunk","read","error","done","value","close"],"mappings":"AAGA,MAAMA,EAAc,CAClBC,EACAC,EACAC,EACAC,EACAC,KAEA,MAAMC,EAAU,IAAIC,YACdC,EAASN,EAAKO,YACpB,IAAIC,EAAsC,SAE1C,OAAO,IAAIC,eAA2B,CAIpCC,OAAQC,MAAOC,IAGb,GAFAV,IAAQU,GAEM,WAAVJ,EAIJ,UACQF,EAAOI,OAAOE,EACtB,SACEN,EAAOO,cACPV,KACF,GAMF,UAAMW,CAAKC,GACT,GAAc,WAAVP,IACFA,EAAQ,OAEJT,GACFgB,EAAWC,QAAQZ,EAAQa,OAAOlB,QAJtC,CAUA,GAAc,SAAVS,EAAkB,CACpB,IAAIU,EAEJ,IACEA,QAAcZ,EAAOa,MACvB,CAAE,MAAOC,GAMP,OALAlB,IAAQkB,GACRd,EAAOO,cACPV,WACAY,EAAWK,MAAMA,EAGnB,CAEA,IAAKF,EAAMG,KAGT,YAFAN,EAAWC,QAAQE,EAAMI,OAK3Bd,EAAQ,SACRF,EAAOO,cACPV,KACF,CAEIF,GACFc,EAAWC,QAAQZ,EAAQa,OAAOhB,IAGpCc,EAAWQ,OA/BX,CAgCF"}
1
+ {"version":3,"file":"compose-html.js","sources":["../../src/core/compose-html.ts"],"sourcesContent":[null],"names":["composeHtml","header","body","footer","abort","onComplete","encoder","TextEncoder","reader","getReader","phase","ReadableStream","cancel","async","reason","releaseLock","pull","controller","enqueue","encode","chunk","read","error","done","value","close","highWaterMark"],"mappings":"AAGA,MAAMA,EAAc,CAClBC,EACAC,EACAC,EACAC,EACAC,KAEA,MAAMC,EAAU,IAAIC,YACdC,EAASN,EAAKO,YACpB,IAAIC,EAAsC,SAE1C,OAAO,IAAIC,eACT,CAIEC,OAAQC,MAAOC,IAGb,GAFAV,IAAQU,GAEM,WAAVJ,EAIJ,UACQF,EAAOI,OAAOE,EACtB,SACEN,EAAOO,cACPV,KACF,GAMF,UAAMW,CAAKC,GACT,GAAc,WAAVP,IACFA,EAAQ,OAEJT,GACFgB,EAAWC,QAAQZ,EAAQa,OAAOlB,QAJtC,CAUA,GAAc,SAAVS,EAAkB,CACpB,IAAIU,EAEJ,IACEA,QAAcZ,EAAOa,MACvB,CAAE,MAAOC,GAMP,OALAlB,IAAQkB,GACRd,EAAOO,cACPV,WACAY,EAAWK,MAAMA,EAGnB,CAEA,IAAKF,EAAMG,KAGT,YAFAN,EAAWC,QAAQE,EAAMI,OAK3Bd,EAAQ,SACRF,EAAOO,cACPV,KACF,CAEIF,GACFc,EAAWC,QAAQZ,EAAQa,OAAOhB,IAGpCc,EAAWQ,OA/BX,CAgCF,GAGF,CAAEC,cAAe"}
package/core/handler.d.ts CHANGED
@@ -10,6 +10,10 @@ interface IRequestInit<TAppProps> {
10
10
  status?: number;
11
11
  }
12
12
  interface ICreateHandlerOptions<TAppProps> extends ICoreRenderOptions<TAppProps> {
13
+ /**
14
+ * Development checks; defaults to NODE_ENV !== 'production', overridden by SSR_BOOST_DIAGNOSTICS.
15
+ */
16
+ diagnostics?: boolean;
13
17
  /**
14
18
  * Supply the document shell, including the application's browser entry script.
15
19
  */
@@ -25,6 +29,6 @@ interface ICreateHandlerOptions<TAppProps> extends ICoreRenderOptions<TAppProps>
25
29
  /**
26
30
  * Create isolated request state and allow request hooks to bypass rendering.
27
31
  */
28
- declare const createHandler: <TAppProps = Record<string, any>>(params: ICoreRenderParams<TAppProps>, { getHtml, onRequest, ...options }: ICreateHandlerOptions<TAppProps>) => TSsrHandler;
32
+ declare const createHandler: <TAppProps = Record<string, any>>(params: ICoreRenderParams<TAppProps>, { diagnostics, getHtml, onRequest, ...options }: ICreateHandlerOptions<TAppProps>) => TSsrHandler;
29
33
  export type { ICreateHandlerOptions, IHtmlShell, IRequestInit };
30
34
  export default createHandler;
package/core/handler.js CHANGED
@@ -1,2 +1,2 @@
1
- import e from"./head-response.js";import s from"./render.js";const t=(t,{getHtml:r,onRequest:o,...a})=>async(n,p)=>{const u=await(o?.({executionContext:p,request:n}));if(u instanceof Response)return e(n,u);const i={appProps:u?.appProps??{},html:await r(n),request:n,response:{headers:new Headers(u?.headers),status:u?.status}};return s(t,i,a,p)};export{t as default};
1
+ import e from"./head-response.js";import s from"./render.js";import t,{isDiagnosticsEnabled as r}from"../services/diagnostics.js";const o=(o,{diagnostics:n,getHtml:a,onRequest:i,...p})=>async(c,d)=>{const u=await(i?.({executionContext:d,request:c}));if(u instanceof Response)return e(c,u);const m={appProps:u?.appProps??{},diagnostics:r(n)?new t(new URL(c.url).pathname):void 0,html:await a(c),request:c,response:{headers:new Headers(u?.headers),status:u?.status}};return s(o,m,p,d)};export{o as default};
2
2
  //# sourceMappingURL=handler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handler.js","sources":["../../src/core/handler.ts"],"sourcesContent":[null],"names":["createHandler","params","getHtml","onRequest","options","async","request","executionContext","requestInit","Response","headResponse","context","appProps","html","response","headers","Headers","status","render"],"mappings":"6DAkCA,MAAMA,EAAgB,CACpBC,GACEC,UAASC,eAAcC,KAKlBC,MAAOC,EAASC,KACrB,MAAMC,QAAoBL,IAAY,CAAEI,mBAAkBD,aAE1D,GAAIE,aAAuBC,SACzB,OAAOC,EAAaJ,EAASE,GAG/B,MAAMG,EAAyC,CAC7CC,SAAWJ,GAAaI,UAAY,GACpCC,WAAYX,EAAQI,GACpBA,UACAQ,SAAU,CACRC,QAAS,IAAIC,QAAQR,GAAaO,SAClCE,OAAQT,GAAaS,SAIzB,OAAOC,EAAOjB,EAAQU,EAASP,EAASG"}
1
+ {"version":3,"file":"handler.js","sources":["../../src/core/handler.ts"],"sourcesContent":[null],"names":["createHandler","params","diagnostics","getHtml","onRequest","options","async","request","executionContext","requestInit","Response","headResponse","context","appProps","isDiagnosticsEnabled","Diagnostics","URL","url","pathname","undefined","html","response","headers","Headers","status","render"],"mappings":"kIAwCA,MAAMA,EAAgB,CACpBC,GACEC,cAAaC,UAASC,eAAcC,KAK/BC,MAAOC,EAASC,KACrB,MAAMC,QAAoBL,IAAY,CAAEI,mBAAkBD,aAE1D,GAAIE,aAAuBC,SACzB,OAAOC,EAAaJ,EAASE,GAG/B,MAAMG,EAAyC,CAC7CC,SAAWJ,GAAaI,UAAY,GACpCX,YAAaY,EAAqBZ,GAC9B,IAAIa,EAAY,IAAIC,IAAIT,EAAQU,KAAKC,eACrCC,EACJC,WAAYjB,EAAQI,GACpBA,UACAc,SAAU,CACRC,QAAS,IAAIC,QAAQd,GAAaa,SAClCE,OAAQf,GAAae,SAIzB,OAAOC,EAAOxB,EAAQW,EAASP,EAASG"}
package/core/render.d.ts CHANGED
@@ -4,8 +4,10 @@ import StreamError from '../constants/stream-error.js';
4
4
  import type { IServerContext } from '../context/server.js';
5
5
  import type { ISsrExecutionContext } from './types.js';
6
6
  import type { IObtainStreamErrorOut } from '../helpers/obtain-stream-error.js';
7
+ import type Diagnostics from '../services/diagnostics.js';
7
8
  export interface ISsrRequestContext<TAppProps = Record<string, any>> {
8
9
  appProps: NonNullable<TAppProps>;
10
+ diagnostics?: Diagnostics;
9
11
  /**
10
12
  * First render failure, or the explicit timeout/cancellation classification.
11
13
  */
package/core/render.js CHANGED
@@ -1,2 +1,2 @@
1
- import e from"react";import{createStaticRouter as t,StaticRouterProvider as r}from"react-router";import o from"../constants/stream-error.js";import{ServerProvider as s}from"../context/server.js";import a from"./compose-html.js";import n from"./head-response.js";import{mergeResponseHeaders as c}from"./headers.js";import d from"./transform-html.js";import l from"../helpers/build-custom-state.js";import u from"../helpers/build-router-state.js";import i from"../helpers/obtain-stream-error.js";const m="text/html",h="Content-Type",p=async({createApp:p,handler:x,renderToStream:f},R,{abortDelay:C=15e3,getState:w,onError:E,onResponse:y,onRouterReady:b,onShellError:q,onShellReady:S,prepare:g,routerRequestContext:v},j)=>{const T=await x.query(R.request,{requestContext:v??R});if(T instanceof Response)return n(R.request,c(T,R.response.headers));R.routerContext=T,await(g?.({context:R,executionContext:j}));const{isStream:A=!0}=await(b?.({context:R}))??{};R.isStream=A,R.serverContext={basename:R.routerContext.basename,isServer:!0,response:null};const H=t(x.dataRoutes,R.routerContext),D=e.createElement(s,{context:R.serverContext},p(e.createElement(r,{router:H,context:R.routerContext,hydrate:!1}),R)),L=new AbortController;let k,B,I=!1;const z=()=>J(R.request.signal.reason),F=()=>clearTimeout(K),G=()=>{F(),R.request.signal.removeEventListener("abort",z)},J=e=>{I||(I=!0,k=e,G(),R.didError??=o.RenderCancel,L.abort(e),B?.abort(e))},K=setTimeout(()=>{R.didError=o.RenderTimeout,J()},C);R.request.signal.aborted?J(R.request.signal.reason):R.request.signal.addEventListener("abort",z,{once:!0});try{B=await f(D,{onError:e=>{const t=i(e);!I||t.code!==o.RenderAborted&&e!==L.signal.reason||(t.code=R.didError===o.RenderTimeout?o.RenderTimeout:o.RenderCancel);const{code:r}=t;R.didError??=r,E?.({context:R,error:t})},signal:L.signal}),I&&B.abort(k),B.allReady.then(F,F),await(A?B.shellReady:B.allReady)}catch(e){return J(e),await(B?.stream.cancel(e).catch(()=>{})),((e,t,r)=>{const o=t instanceof Error?t:new Error(String(t)),s=r?.({context:e,error:o})||"<!doctype html><p>Internal Server Error</p>",a=new Headers(e.response.headers);return a.set(h,m),new Response("HEAD"===e.request.method?null:s,{headers:a,status:500})})(R,e,q)}try{const e=R.serverContext.response;if(e&&(M=e,Boolean(M&&M.status>=300&&M.status<400&&M.headers.has("Location"))))return J(),await B.stream.cancel().catch(()=>{}),n(R.request,c(e,R.response.headers));const{header:t,footer:r,headers:o,status:s}=((e,{getState:t,onShellReady:r})=>{const o=e.serverContext.response;e.response.status=o?.status??e.response.status??e.routerContext.statusCode??200,e.response.headers.has(h)||e.response.headers.set(h,m);const s=r?.({context:e})??{},a=u(e.routerContext),n=l(t?.({context:e}));return{header:s.header||e.html.header,footer:n+a+(s.footer||e.html.footer),headers:new Headers(e.response.headers),status:e.response.status}})(R,{getState:w,onShellReady:S});if("HEAD"===R.request.method||[204,205,304].includes(s))return J(),await B.stream.cancel().catch(()=>{}),new Response(null,{headers:o,status:s});const i=a(t,B.stream,r,J,G),p=d(i,y?(e,t)=>y({context:R,html:e,isEnd:t}):void 0);return B.start(),new Response(p,{headers:o,status:s})}catch(e){throw J(e),B.stream.locked||await B.stream.cancel(e).catch(()=>{}),e}var M};export{p as default};
1
+ import e from"react";import{createStaticRouter as t,StaticRouterProvider as r}from"react-router";import s from"../constants/stream-error.js";import{ServerProvider as o}from"../context/server.js";import a from"./compose-html.js";import n from"./head-response.js";import{mergeResponseHeaders as c}from"./headers.js";import d from"./transform-html.js";import i from"../helpers/build-custom-state.js";import l from"../helpers/build-router-state.js";import u from"../helpers/obtain-stream-error.js";const m="text/html",h="Content-Type",p=async({createApp:p,handler:x,renderToStream:f},R,{abortDelay:C=15e3,getState:w,onError:E,onResponse:g,onRouterReady:y,onShellError:b,onShellReady:S,prepare:q,routerRequestContext:v},j)=>{const T=await x.query(R.request,{requestContext:v??R});if(T instanceof Response)return n(R.request,c(T,R.response.headers));R.routerContext=T,await(q?.({context:R,executionContext:j}));const{isStream:A=!0}=await(y?.({context:R}))??{};R.isStream=A,R.serverContext={basename:R.routerContext.basename,isServer:!0,response:null};const H=t(x.dataRoutes,R.routerContext),D=e.createElement(o,{context:R.serverContext},p(e.createElement(r,{router:H,context:R.routerContext,hydrate:!1}),R)),L=new AbortController;let k,B,I=!1;const z=()=>J(R.request.signal.reason),F=()=>clearTimeout(K),G=()=>{F(),R.request.signal.removeEventListener("abort",z)},J=e=>{I||(I=!0,k=e,G(),R.didError??=s.RenderCancel,L.abort(e),B?.abort(e))},K=setTimeout(()=>{R.didError=s.RenderTimeout,J()},C);R.request.signal.aborted?J(R.request.signal.reason):R.request.signal.addEventListener("abort",z,{once:!0});try{B=await f(D,{onError:e=>{const t=u(e);!I||t.code!==s.RenderAborted&&e!==L.signal.reason||(t.code=R.didError===s.RenderTimeout?s.RenderTimeout:s.RenderCancel);const{code:r}=t;R.didError??=r,E?.({context:R,error:t})},signal:L.signal}),I&&B.abort(k),B.allReady.then(F,F),await(A?B.shellReady:B.allReady)}catch(e){return J(e),await(B?.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(h,m),new Response("HEAD"===e.request.method?null:o,{headers:a,status:500})})(R,e,b)}try{const e=R.serverContext.response;if(e&&(M=e,Boolean(M&&M.status>=300&&M.status<400&&M.headers.has("Location"))))return J(),await B.stream.cancel().catch(()=>{}),n(R.request,c(e,R.response.headers));const{header:t,footer:r,headers:s,status:o}=((e,{getState:t,onShellReady:r})=>{const s=e.serverContext.response;e.response.status=s?.status??e.response.status??e.routerContext.statusCode??200,e.response.headers.has(h)||e.response.headers.set(h,m);const o=r?.({context:e})??{},a=l(e.routerContext,e.diagnostics),n=i(t?.({context:e}),e.diagnostics),c=o.header||e.html.header,d=o.footer||e.html.footer;return e.diagnostics?.inspectShell({header:c,footer:d}),{header:c,footer:n+a+d,headers:new Headers(e.response.headers),status:e.response.status}})(R,{getState:w,onShellReady:S});if("HEAD"===R.request.method||[204,205,304].includes(o))return J(),await B.stream.cancel().catch(()=>{}),new Response(null,{headers:s,status:o});const u=a(t,B.stream,r,J,G),p=d(u,g?(e,t)=>g({context:R,html:e,isEnd:t}):void 0,R.diagnostics);return B.start(),new Response(p,{headers:s,status:o})}catch(e){throw J(e),B.stream.locked||await B.stream.cancel(e).catch(()=>{}),e}var M};export{p as default};
2
2
  //# sourceMappingURL=render.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sources":["../../src/core/render.tsx"],"sourcesContent":[null],"names":["HTML_CONTENT_TYPE","CONTENT_TYPE","render","async","createApp","handler","renderToStream","context","abortDelay","getState","onError","onResponse","onRouterReady","onShellError","onShellReady","prepare","routerRequestContext","executionContext","queried","query","request","requestContext","Response","headResponse","mergeResponseHeaders","response","headers","routerContext","isStream","serverContext","basename","isServer","router","createStaticRouter","dataRoutes","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","error","streamError","obtainStreamError","code","RenderAborted","allReady","then","shellReady","stream","cancel","catch","shellError","Error","String","html","Headers","set","method","status","createShellErrorResponse","serverResponse","Boolean","has","header","footer","statusCode","shell","routerState","buildRouterState","customState","buildCustomState","prepareHtmlResponse","includes","body","composeHtml","transformed","transformHtml","isEnd","undefined","start","locked"],"mappings":"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"}
1
+ {"version":3,"file":"render.js","sources":["../../src/core/render.tsx"],"sourcesContent":[null],"names":["HTML_CONTENT_TYPE","CONTENT_TYPE","render","async","createApp","handler","renderToStream","context","abortDelay","getState","onError","onResponse","onRouterReady","onShellError","onShellReady","prepare","routerRequestContext","executionContext","queried","query","request","requestContext","Response","headResponse","mergeResponseHeaders","response","headers","routerContext","isStream","serverContext","basename","isServer","router","createStaticRouter","dataRoutes","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","error","streamError","obtainStreamError","code","RenderAborted","allReady","then","shellReady","stream","cancel","catch","shellError","Error","String","html","Headers","set","method","status","createShellErrorResponse","serverResponse","Boolean","has","header","footer","statusCode","shell","routerState","buildRouterState","diagnostics","customState","buildCustomState","shellFooter","inspectShell","prepareHtmlResponse","includes","body","composeHtml","transformed","transformHtml","isEnd","undefined","start","locked"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
+ import type Diagnostics from '../services/diagnostics.js';
1
2
  type TTransformHtml = (html: string, isEnd: boolean) => string | undefined | void;
2
3
  /**
3
4
  * Apply response hooks to decoded text without splitting UTF-8 characters.
4
5
  */
5
- declare const transformHtml: (stream: ReadableStream<Uint8Array>, transform?: TTransformHtml) => ReadableStream<Uint8Array>;
6
+ declare const transformHtml: (stream: ReadableStream<Uint8Array>, transform?: TTransformHtml, diagnostics?: Diagnostics) => ReadableStream<Uint8Array>;
6
7
  export type { TTransformHtml };
7
8
  export default transformHtml;
@@ -1,2 +1,2 @@
1
- const e=(e,n)=>{if(!n)return e;const r=new TextDecoder,o=new TextEncoder,t=(e,r)=>{e&&r.enqueue(o.encode(n(e,!1)??e))};return e.pipeThrough(new TransformStream({flush:e=>{t(r.decode(),e);const c=n("",!0);c&&e.enqueue(o.encode(c))},transform:(e,n)=>t(r.decode(e,{stream:!0}),n)}))};export{e as default};
1
+ const e=(e,n,t)=>{if(!n&&!t)return e;const r=e.getReader(),a=new TextDecoder,c=n?new TextEncoder:void 0;let o=!1;const s=(e,n)=>{n.enqueue(c.encode(e)),t?.append(String(e))},l=(e,r)=>{if(!e)return;const a=n?.(e,!1);t?.inspectOnResponse(a),s(a??e,r)};return new ReadableStream({cancel:async e=>{o=!0;try{await r.cancel(e)}finally{r.releaseLock()}},pull:async e=>{try{for(;!o;){const c=await r.read();if(o)return;if(c.done){const c=a.decode();if(n){l(c,e);const r=n("",!0);t?.inspectOnResponse(r),r&&s(r,e)}else c&&t?.append(c);return t?.complete(),o=!0,r.releaseLock(),void e.close()}const i=a.decode(c.value,{stream:!0});if(n){if(!i)continue;l(i,e)}else t?.append(i),e.enqueue(c.value);return}}catch(n){if(o)return;o=!0,e.error(n);try{await r.cancel(n).catch(()=>{})}finally{r.releaseLock()}}}},{highWaterMark:0})};export{e as default};
2
2
  //# sourceMappingURL=transform-html.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform-html.js","sources":["../../src/core/transform-html.ts"],"sourcesContent":[null],"names":["transformHtml","stream","transform","decoder","TextDecoder","encoder","TextEncoder","apply","html","controller","enqueue","encode","pipeThrough","TransformStream","flush","decode","chunk"],"mappings":"AAKA,MAAMA,EAAgB,CACpBC,EACAC,KAEA,IAAKA,EACH,OAAOD,EAGT,MAAME,EAAU,IAAIC,YACdC,EAAU,IAAIC,YAKdC,EAAQ,CAACC,EAAcC,KACtBD,GAILC,EAAWC,QAAQL,EAAQM,OAAOT,EAAUM,GAAM,IAAUA,KAG9D,OAAOP,EAAOW,YACZ,IAAIC,gBAAwC,CAI1CC,MAAQL,IACNF,EAAMJ,EAAQY,SAAUN,GAExB,MAAMD,EAAON,EAAU,IAAI,GAEvBM,GACFC,EAAWC,QAAQL,EAAQM,OAAOH,KAOtCN,UAAW,CAACc,EAAOP,IAAeF,EAAMJ,EAAQY,OAAOC,EAAO,CAAEf,QAAQ,IAASQ"}
1
+ {"version":3,"file":"transform-html.js","sources":["../../src/core/transform-html.ts"],"sourcesContent":[null],"names":["transformHtml","stream","transform","diagnostics","reader","getReader","decoder","TextDecoder","encoder","TextEncoder","undefined","isStopped","emit","html","controller","enqueue","encode","append","String","apply","result","inspectOnResponse","ReadableStream","cancel","async","reason","releaseLock","pull","chunk","read","done","remaining","decode","complete","close","value","error","catch","highWaterMark"],"mappings":"AAOA,MAAMA,EAAgB,CACpBC,EACAC,EACAC,KAEA,IAAKD,IAAcC,EACjB,OAAOF,EAGT,MAAMG,EAASH,EAAOI,YAChBC,EAAU,IAAIC,YACdC,EAAUN,EAAY,IAAIO,iBAAgBC,EAChD,IAAIC,GAAY,EAKhB,MAAMC,EAAO,CAACC,EAAcC,KAC1BA,EAAWC,QAAQP,EAASQ,OAAOH,IACnCV,GAAac,OAAOC,OAAOL,KAMvBM,EAAQ,CAACN,EAAcC,KAC3B,IAAKD,EACH,OAGF,MAAMO,EAASlB,IAAYW,GAAM,GAEjCV,GAAakB,kBAAkBD,GAC/BR,EAAKQ,GAAUP,EAAMC,IAGvB,OAAO,IAAIQ,eACT,CAIEC,OAAQC,MAAOC,IACbd,GAAY,EAEZ,UACQP,EAAOmB,OAAOE,EACtB,SACErB,EAAOsB,aACT,GAMFC,KAAMH,MAAOV,IACX,IACE,MAAQH,GAAW,CACjB,MAAMiB,QAAcxB,EAAOyB,OAE3B,GAAIlB,EACF,OAGF,GAAIiB,EAAME,KAAM,CACd,MAAMC,EAAYzB,EAAQ0B,SAE1B,GAAI9B,EAAW,CACbiB,EAAMY,EAAWjB,GAEjB,MAAMD,EAAOX,EAAU,IAAI,GAE3BC,GAAakB,kBAAkBR,GAE3BA,GACFD,EAAKC,EAAMC,EAEf,MAAWiB,GACT5B,GAAac,OAAOc,GAQtB,OALA5B,GAAa8B,WACbtB,GAAY,EACZP,EAAOsB,mBACPZ,EAAWoB,OAGb,CAEA,MAAMrB,EAAOP,EAAQ0B,OAAOJ,EAAMO,MAAO,CAAElC,QAAQ,IAEnD,GAAIC,EAAW,CACb,IAAKW,EACH,SAGFM,EAAMN,EAAMC,EACd,MACEX,GAAac,OAAOJ,GACpBC,EAAWC,QAAQa,EAAMO,OAG3B,MACF,CACF,CAAE,MAAOC,GACP,GAAIzB,EACF,OAGFA,GAAY,EACZG,EAAWsB,MAAMA,GAEjB,UACQhC,EAAOmB,OAAOa,GAAOC,MAAM,OACnC,SACEjC,EAAOsB,aACT,CACF,IAIJ,CAAEY,cAAe"}
@@ -1,5 +1,6 @@
1
+ import type Diagnostics from '../services/diagnostics.js';
1
2
  /**
2
3
  * Build custom state
3
4
  */
4
- declare function buildCustomState(initState?: Record<string, Record<string, any>> | void): string;
5
+ declare function buildCustomState(initState?: Record<string, Record<string, any>> | void, diagnostics?: Diagnostics): string;
5
6
  export default buildCustomState;
@@ -1,2 +1,2 @@
1
- import t from"./html-escape.js";function r(r){return Object.entries(r??{}).map(([r,e])=>{if(!r||!e||!Object.keys(e||{}).length)return"";const i=t(JSON.stringify(JSON.stringify(e)));return`<script async>window${/^[A-Za-z_$][\w$]*$/.test(r)?`.${r}`:`[${t(JSON.stringify(r))}]`} = JSON.parse(${i});<\/script>`}).join("").trim()}export{r as default};
1
+ import t from"./html-escape.js";function e(e,r){r?.inspectState(e);return Object.entries(e??{}).map(([e,r])=>{if(!e||!r||!Object.keys(r||{}).length)return"";const i=t(JSON.stringify(JSON.stringify(r)));return`<script async>window${/^[A-Za-z_$][\w$]*$/.test(e)?`.${e}`:`[${t(JSON.stringify(e))}]`} = JSON.parse(${i});<\/script>`}).join("").trim()}export{e as default};
2
2
  //# sourceMappingURL=build-custom-state.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-custom-state.js","sources":["../../src/helpers/build-custom-state.ts"],"sourcesContent":[null],"names":["buildCustomState","initState","Object","entries","map","key","state","keys","length","json","htmlEscape","JSON","stringify","test","join","trim"],"mappings":"gCAKA,SAASA,EAAiBC,GAcxB,OAbqBC,OAAOC,QAAQF,GAAa,CAAA,GAAIG,IAAI,EAAEC,EAAKC,MAC9D,IAAKD,IAAQC,IAAUJ,OAAOK,KAAKD,GAAS,IAAIE,OAC9C,MAAO,GAGT,MAAMC,EAAOC,EAAWC,KAAKC,UAAUD,KAAKC,UAAUN,KAKtD,MAAO,uBAJU,qBAAqBO,KAAKR,GACvC,IAAIA,IACJ,IAAIK,EAAWC,KAAKC,UAAUP,uBAEqBI,kBAGrCK,KAAK,IAAIC,MAC/B"}
1
+ {"version":3,"file":"build-custom-state.js","sources":["../../src/helpers/build-custom-state.ts"],"sourcesContent":[null],"names":["buildCustomState","initState","diagnostics","inspectState","Object","entries","map","key","state","keys","length","json","htmlEscape","JSON","stringify","test","join","trim"],"mappings":"gCAMA,SAASA,EACPC,EACAC,GAEAA,GAAaC,aAAaF,GAe1B,OAbqBG,OAAOC,QAAQJ,GAAa,CAAA,GAAIK,IAAI,EAAEC,EAAKC,MAC9D,IAAKD,IAAQC,IAAUJ,OAAOK,KAAKD,GAAS,IAAIE,OAC9C,MAAO,GAGT,MAAMC,EAAOC,EAAWC,KAAKC,UAAUD,KAAKC,UAAUN,KAKtD,MAAO,uBAJU,qBAAqBO,KAAKR,GACvC,IAAIA,IACJ,IAAIK,EAAWC,KAAKC,UAAUP,uBAEqBI,kBAGrCK,KAAK,IAAIC,MAC/B"}
@@ -1,6 +1,7 @@
1
1
  import type { StaticHandlerContext } from 'react-router';
2
+ import type Diagnostics from '../services/diagnostics.js';
2
3
  /**
3
4
  * Build router state
4
5
  */
5
- declare function buildRouterState(context: StaticHandlerContext): string;
6
+ declare function buildRouterState(context: StaticHandlerContext, diagnostics?: Diagnostics): string;
6
7
  export default buildRouterState;
@@ -1,2 +1,2 @@
1
- import r from"./html-escape.js";import t from"./serialize-errors.js";function a(a){const{loaderData:o,actionData:i,errors:s}=a,e={loaderData:o,actionData:i,errors:t(s)};return`<script async>window.__staticRouterHydrationData = JSON.parse(${r(JSON.stringify(JSON.stringify(e)))});<\/script>`}export{a as default};
1
+ import r from"./html-escape.js";import t from"./serialize-errors.js";function a(a,o){o?.inspectRouterState(a);const{loaderData:e,actionData:i,errors:s}=a,n={loaderData:e,actionData:i,errors:t(s)};return`<script async>window.__staticRouterHydrationData = JSON.parse(${r(JSON.stringify(JSON.stringify(n)))});<\/script>`}export{a as default};
2
2
  //# sourceMappingURL=build-router-state.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-router-state.js","sources":["../../src/helpers/build-router-state.ts"],"sourcesContent":[null],"names":["buildRouterState","context","loaderData","actionData","errors","routerState","serializeErrors","htmlEscape","JSON","stringify"],"mappings":"qEAOA,SAASA,EAAiBC,GACxB,MAAMC,WAAEA,EAAUC,WAAEA,EAAUC,OAAEA,GAAWH,EACrCI,EAAc,CAClBH,aACAC,aACAC,OAAQE,EAAgBF,IAI1B,MAAO,iEAFMG,EAAWC,KAAKC,UAAUD,KAAKC,UAAUJ,kBAGxD"}
1
+ {"version":3,"file":"build-router-state.js","sources":["../../src/helpers/build-router-state.ts"],"sourcesContent":[null],"names":["buildRouterState","context","diagnostics","inspectRouterState","loaderData","actionData","errors","routerState","serializeErrors","htmlEscape","JSON","stringify"],"mappings":"qEAQA,SAASA,EAAiBC,EAA+BC,GACvDA,GAAaC,mBAAmBF,GAEhC,MAAMG,WAAEA,EAAUC,WAAEA,EAAUC,OAAEA,GAAWL,EACrCM,EAAc,CAClBH,aACAC,aACAC,OAAQE,EAAgBF,IAI1B,MAAO,iEAFMG,EAAWC,KAAKC,UAAUD,KAAKC,UAAUJ,kBAGxD"}
@@ -1,2 +1,2 @@
1
- import{readFile as t}from"node:fs/promises";import e from"../services/route-assets.js";const o=async({indexFile:e,outlet:o="\x3c!--ssr-outlet--\x3e"})=>{const n=(await t(e,"utf8")).split(o);if(!o||2!==n.length)throw new Error(`Invalid HTML shell in "${e}": expected exactly one non-empty outlet ${JSON.stringify(o)}.`);const[s,r]=n;return()=>({header:s,footer:r})},n=({buildDir:t,modulePreload:o=!1})=>{const n=new e(t,o);return async({context:t,executionContext:e})=>{const o=n.injectAssets(t);o.has("Link")&&await(e?.onEarlyHints?.(o))}};export{n as createRouteAssetPreparer,o as loadHtmlShell};
1
+ import{readFile as t}from"node:fs/promises";import{splitHtmlShell as e}from"../services/diagnostics.js";import s from"../services/route-assets.js";const o=async({indexFile:s,outlet:o="\x3c!--ssr-outlet--\x3e"})=>{const r=await t(s,"utf8"),[n,i]=e(r,s,o);return()=>({header:n,footer:i})},r=({buildDir:t,modulePreload:e=!1})=>{const o=new s(t,e);return async({context:t,executionContext:e})=>{const s=o.injectAssets(t);s.has("Link")&&await(e?.onEarlyHints?.(s))}};export{r as createRouteAssetPreparer,o as loadHtmlShell};
2
2
  //# sourceMappingURL=production.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"production.js","sources":["../../src/node/production.ts"],"sourcesContent":[null],"names":["loadHtmlShell","async","indexFile","outlet","parts","readFile","split","length","Error","JSON","stringify","header","footer","createRouteAssetPreparer","buildDir","modulePreload","assets","RouteAssets","context","executionContext","hints","injectAssets","has","onEarlyHints"],"mappings":"uFAiBA,MAAMA,EAAgBC,OACpBC,YACAC,SAAS,8BAET,MACMC,SADaC,EAASH,EAAW,SACpBI,MAAMH,GAEzB,IAAKA,GAA2B,IAAjBC,EAAMG,OACnB,MAAM,IAAIC,MACR,0BAA0BN,6CAAqDO,KAAKC,UAAUP,OAIlG,MAAOQ,EAAQC,GAAUR,EAEzB,MAAO,KAAA,CAASO,SAAQC,YAMpBC,EAA2B,EAC/BC,WACAC,iBAAgB,MAEhB,MAAMC,EAAS,IAAIC,EAAYH,EAAUC,GAEzC,OAAOd,OAASiB,UAASC,uBACvB,MAAMC,EAAQJ,EAAOK,aAAaH,GAE9BE,EAAME,IAAI,eACNH,GAAkBI,eAAeH"}
1
+ {"version":3,"file":"production.js","sources":["../../src/node/production.ts"],"sourcesContent":[null],"names":["loadHtmlShell","async","indexFile","outlet","html","readFile","header","footer","splitHtmlShell","createRouteAssetPreparer","buildDir","modulePreload","assets","RouteAssets","context","executionContext","hints","injectAssets","has","onEarlyHints"],"mappings":"mJAkBA,MAAMA,EAAgBC,OACpBC,YACAC,SAAS,8BAET,MAAMC,QAAaC,EAASH,EAAW,SAChCI,EAAQC,GAAUC,EAAeJ,EAAMF,EAAWC,GAEzD,MAAO,KAAA,CAASG,SAAQC,YAMpBE,EAA2B,EAC/BC,WACAC,iBAAgB,MAEhB,MAAMC,EAAS,IAAIC,EAAYH,EAAUC,GAEzC,OAAOV,OAASa,UAASC,uBACvB,MAAMC,EAAQJ,EAAOK,aAAaH,GAE9BE,EAAME,IAAI,eACNH,GAAkBI,eAAeH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lomray/vite-ssr-boost",
3
- "version": "8.1.0-beta.1",
3
+ "version": "8.2.0-beta.1",
4
4
  "description": "Vite plugin for create awesome SSR or SPA applications on React.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -58,6 +58,7 @@
58
58
  "lint:format": "eslint . --fix",
59
59
  "ts:check": "tsc --project ./tsconfig.json --skipLibCheck --noemit",
60
60
  "test": "vitest run",
61
+ "test:size": "node scripts/test-browser-size.mjs",
61
62
  "test:core:no-optional": "node scripts/test-core-no-optional.mjs",
62
63
  "test:edge:packed": "node scripts/test-packed-edge.mjs",
63
64
  "test:bun": "bun scripts/test-bun.mjs",
@@ -0,0 +1,66 @@
1
+ import type { StaticHandlerContext } from 'react-router';
2
+ import Logger from './logger.js';
3
+ type TDiagnosticCode = 'SSR_BOOST_LOADER_NOT_SERIALIZABLE' | 'SSR_BOOST_STATE_NOT_SERIALIZABLE' | 'SSR_BOOST_OUTLET_MISSING' | 'SSR_BOOST_HYDRATION_STATE_MISSING' | 'SSR_BOOST_DUPLICATE_OUTPUT' | 'SSR_BOOST_ONRESPONSE_INVALID_RETURN';
4
+ interface ISerializationIssue {
5
+ path: string;
6
+ reason: string;
7
+ }
8
+ /**
9
+ * Resolve overrides without requiring Node globals in Fetch runtimes.
10
+ */
11
+ declare const isDiagnosticsEnabled: (enabled?: boolean) => boolean;
12
+ /**
13
+ * Keep warnings and fatal shell errors linked to the same stable reference.
14
+ */
15
+ declare const formatDiagnostic: (code: TDiagnosticCode, sentence: string) => string;
16
+ /**
17
+ * Reject unusable file-backed shells in every runtime mode.
18
+ */
19
+ declare const splitHtmlShell: (html: string, file: string, outlet?: string) => [string, string];
20
+ /**
21
+ * Find values JSON cannot preserve, descending only into plain objects and arrays.
22
+ */
23
+ declare const walkSerializable: (value: unknown, report: (issue: ISerializationIssue) => void, path?: string, ancestors?: Set<object>) => void;
24
+ /**
25
+ * Inspect one development response while allowing every chunk to stream immediately.
26
+ */
27
+ declare class Diagnostics {
28
+ protected readonly route: string;
29
+ protected readonly logger: Pick<Logger, 'warn'>;
30
+ protected chunks: string[];
31
+ constructor(route: string, logger?: Pick<Logger, 'warn'>);
32
+ /**
33
+ * Emit each concrete message once per process, including across handler instances.
34
+ */
35
+ protected warn(code: TDiagnosticCode, detail: string): void;
36
+ /**
37
+ * A split Fetch shell has one insertion boundary and must not retain raw outlets.
38
+ */
39
+ inspectShell({ header, footer }: {
40
+ header: string;
41
+ footer: string;
42
+ }): void;
43
+ /**
44
+ * Include React Router's route id and the full loader/action key path.
45
+ */
46
+ inspectRouterState({ loaderData, actionData }: StaticHandlerContext): void;
47
+ /**
48
+ * Check custom state before the serializer can omit or coerce it.
49
+ */
50
+ inspectState(state: unknown): void;
51
+ /**
52
+ * Hooks are synchronous and can only keep, replace or withhold a chunk.
53
+ */
54
+ inspectOnResponse(value: unknown): void;
55
+ /**
56
+ * Retain only the output that actually leaves the response transform.
57
+ */
58
+ append(html: string): void;
59
+ /**
60
+ * Scan completed HTML so markers split across chunks are still recognized.
61
+ */
62
+ complete(): void;
63
+ }
64
+ export { formatDiagnostic, isDiagnosticsEnabled, splitHtmlShell, walkSerializable };
65
+ export type { ISerializationIssue, TDiagnosticCode };
66
+ export default Diagnostics;
@@ -0,0 +1,2 @@
1
+ import t from"./logger.js";const e="\x3c!--ssr-outlet--\x3e",o="window.__staticRouterHydrationData",s=Symbol.for("@lomray/vite-ssr-boost/diagnostics"),r=globalThis,n=t=>{const e="undefined"==typeof process?void 0:process.env;return"0"===e?.SSR_BOOST_DIAGNOSTICS||"1"===e?.SSR_BOOST_DIAGNOSTICS?"1"===e.SSR_BOOST_DIAGNOSTICS:t??"production"!==e?.NODE_ENV},i=(t,e)=>`[ssr-boost] ${t}: ${e} See https://lomray-software.github.io/vite-ssr-boost/reference/diagnostics#${t.toLowerCase()}`,a=(t,o,s=e)=>{const r=t.split(s);if(!s||2!==r.length)throw new Error(i("SSR_BOOST_OUTLET_MISSING",`Invalid HTML shell in ${JSON.stringify(o)}: expected exactly one non-empty outlet ${JSON.stringify(s)}.`));return r},S=t=>{if(null===t)return"null";if("object"!=typeof t){return{bigint:"BigInt",symbol:"Symbol"}[typeof t]??typeof t}const e=Object.getPrototypeOf(t),o=e?.constructor?.name;return"string"==typeof o&&o?o:"object"},c=(t,e,o="$",s=new Set)=>{const r=typeof t;if("function"===r||"bigint"===r||"symbol"===r)return void e({path:o,reason:`${S(t)} is not JSON-serializable`});if(null===t||"object"!==r)return;const n=t,i=Object.getPrototypeOf(n);if(i!==Object.prototype&&null!==i&&(!Array.isArray(n)||i!==Array.prototype)){const t=S(n);return void e({path:o,reason:"Date"===t?"Date hydrates as a string":`${t} is not JSON-serializable`})}if(s.has(n))e({path:o,reason:"a circular reference is not JSON-serializable"});else{s.add(n);for(const[t,r]of Object.entries(n)){const i=Array.isArray(n)&&/^(0|[1-9]\d*)$/.test(t)?`[${t}]`:/^[A-Za-z_$][\w$]*$/.test(t)?`.${t}`:`[${JSON.stringify(t)}]`;c(r,e,o+i,s)}s.delete(n)}};class l{route;logger;chunks=[];constructor(e,o=new t){this.route=e,this.logger=o}warn(t,e){const o=i(t,e),n=r[s]??=new Set;n.has(o)||(n.add(o),this.logger.warn(o,{}))}inspectShell({header:t,footer:o}){("string"!=typeof t||"string"!=typeof o||t.includes(e)||o.includes(e))&&this.warn("SSR_BOOST_OUTLET_MISSING",`HTML shell for route ${JSON.stringify(this.route)} must supply both header and footer around exactly one ${e} outlet, with no outlet left in either half.`)}inspectRouterState({loaderData:t,actionData:e}){for(const[o,s]of Object.entries({loaderData:t,actionData:e}))for(const[t,e]of Object.entries(s??{}))c(e,({path:e,reason:o})=>this.warn("SSR_BOOST_LOADER_NOT_SERIALIZABLE",`Route ${JSON.stringify(t)} at ${e}: ${o}.`),`${o}[${JSON.stringify(t)}]`)}inspectState(t){c(t,({path:t,reason:e})=>this.warn("SSR_BOOST_STATE_NOT_SERIALIZABLE",`getState for route ${JSON.stringify(this.route)} at ${t}: ${e}.`))}inspectOnResponse(t){void 0!==t&&"string"!=typeof t&&this.warn("SSR_BOOST_ONRESPONSE_INVALID_RETURN",`onResponse for route ${JSON.stringify(this.route)} returned ${S(t)}; return a string or undefined.`)}append(t){this.chunks.push(t)}complete(){const t=this.chunks.join("");this.chunks=[];const e=new Map,s=t=>{e.set(t,(e.get(t)??0)+1)},r=t.replace(/<!--[\s\S]*?-->/g,"").replace(/(<(script|style|textarea|title)\b(?:[^"'<>]|"[^"]*"|'[^']*')*>)([\s\S]*?)<\/\2\s*>/gi,(t,e,r,n)=>{if("script"===r.toLowerCase()){/\bwindow\.__staticRouterHydrationData\s*=/.test(n)&&s(o);for(const t of n.matchAll(/\$RC\s*\(\s*(["'])(B:[^"']+)\1/g))s(`$RC("${t[2]}")`)}return e});for(const t of r.matchAll(/<([a-z][\w:-]*)\b((?:[^"'<>]|"[^"]*"|'[^']*')*)>/gi)){const e=t[1].toLowerCase();"html"!==e&&"head"!==e||s(`<${e}>`);for(const e of t[2].matchAll(/([^\s=]+)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>]+))/g)){const t=e[2]??e[3]??e[4];"id"===e[1].toLowerCase()&&/^(S|B):/.test(t)&&s(`id="${t}"`)}}e.has(o)||this.warn("SSR_BOOST_HYDRATION_STATE_MISSING",`Completed response for route ${JSON.stringify(this.route)} has no ${o} script; preserve the hydration footer in onResponse.`);for(const[t,o]of e)o>1&&this.warn("SSR_BOOST_DUPLICATE_OUTPUT",`Completed response for route ${JSON.stringify(this.route)} repeats ${t}; onResponse must return undefined to keep a chunk and '' to withhold one.`)}}export{l as default,i as formatDiagnostic,n as isDiagnosticsEnabled,a as splitHtmlShell,c as walkSerializable};
2
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sources":["../../src/services/diagnostics.ts"],"sourcesContent":[null],"names":["OUTLET","HYDRATION","warnedKey","Symbol","for","registry","globalThis","isDiagnosticsEnabled","enabled","env","process","undefined","SSR_BOOST_DIAGNOSTICS","NODE_ENV","formatDiagnostic","code","sentence","toLowerCase","splitHtmlShell","html","file","outlet","parts","split","length","Error","JSON","stringify","valueType","value","bigint","symbol","prototype","Object","getPrototypeOf","name","constructor","walkSerializable","report","path","ancestors","Set","type","reason","object","Array","isArray","has","add","key","child","entries","suffix","test","delete","Diagnostics","route","logger","chunks","Logger","this","warn","detail","message","warned","inspectShell","header","footer","includes","inspectRouterState","loaderData","actionData","kind","data","inspectState","state","inspectOnResponse","append","push","complete","join","markers","Map","count","marker","set","get","markup","replace","_tag","opening","content","match","matchAll","attribute","total"],"mappings":"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"}