@lomray/vite-ssr-boost 8.3.0 → 8.4.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/adapters/express/entry.d.ts +1 -1
- package/adapters/express/entry.js.map +1 -1
- package/adapters/express/render.d.ts +7 -3
- package/adapters/express/render.js +1 -1
- package/adapters/express/render.js.map +1 -1
- package/core/cache-control.d.ts +15 -0
- package/core/cache-control.js +2 -0
- package/core/cache-control.js.map +1 -0
- package/core/conditional-request.d.ts +12 -0
- package/core/conditional-request.js +2 -0
- package/core/conditional-request.js.map +1 -0
- package/core/copy-loader-headers.d.ts +9 -0
- package/core/copy-loader-headers.js +2 -0
- package/core/copy-loader-headers.js.map +1 -0
- package/core/document-headers.d.ts +34 -0
- package/core/document-headers.js +2 -0
- package/core/document-headers.js.map +1 -0
- package/core/handler.js +1 -1
- package/core/handler.js.map +1 -1
- package/core/render.d.ts +6 -5
- package/core/render.js +1 -1
- package/core/render.js.map +1 -1
- package/http.d.ts +7 -0
- package/http.js +2 -0
- package/http.js.map +1 -0
- package/package.json +1 -1
- package/services/build.js +1 -1
- package/services/diagnostics.d.ts +5 -1
- package/services/diagnostics.js +1 -1
- package/services/diagnostics.js.map +1 -1
|
@@ -15,7 +15,7 @@ export interface IInitServerRequestOut<T = Record<string, any>> {
|
|
|
15
15
|
shouldSkip?: boolean;
|
|
16
16
|
shouldCancel?: boolean;
|
|
17
17
|
}
|
|
18
|
-
export interface IEntrypointOptions<TAppProps = Record<string, any>> extends Pick<IRenderOptions<TAppProps>, 'onRouterReady' | 'onShellReady' | 'onShellError' | 'onResponse' | 'onError' | 'getState' | 'getBody' | 'hydration' | 'nonce' | 'bootstrapScriptContent'> {
|
|
18
|
+
export interface IEntrypointOptions<TAppProps = Record<string, any>> extends Pick<IRenderOptions<TAppProps>, 'onRouterReady' | 'onShellReady' | 'onShellError' | 'onResponse' | 'onError' | 'getState' | 'getBody' | 'hydration' | 'nonce' | 'bootstrapScriptContent' | 'documentHeaders' | 'sessionCookie' | 'protectPrivate'> {
|
|
19
19
|
onServerCreated?: (app: Express, serverApi: ServerApi) => Promise<void> | void;
|
|
20
20
|
onServerStarted?: (app: Express, serverApi: ServerApi, server: Server) => Promise<void> | void;
|
|
21
21
|
onRequest?: (req: Request, res: ExpressResponse) => Promise<IInitServerRequestOut<TAppProps>> | IInitServerRequestOut<TAppProps>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.js","sources":["../../../src/adapters/express/entry.tsx"],"sourcesContent":[null],"names":["entry","App","routes","init","routerOptions","rest","handler","createStaticHandler","render","bind"],"mappings":"
|
|
1
|
+
{"version":3,"file":"entry.js","sources":["../../../src/adapters/express/entry.tsx"],"sourcesContent":[null],"names":["entry","App","routes","init","routerOptions","rest","handler","createStaticHandler","render","bind"],"mappings":"8EAkFA,SAASA,EACPC,EACAC,GACAC,KAAEA,EAAIC,cAAEA,KAAkBC,GAAyC,IAEnE,MAAMC,EAAUC,EAAoBL,EAAyBE,GAE7D,MAAO,CACLI,OAAQA,EAAOC,KAAK,KAAM,CAAEH,UAASL,QACrCE,OACAD,YACGG,EAEP"}
|
|
@@ -3,12 +3,16 @@ import type { StaticHandlerContext, StaticHandler } from 'react-router';
|
|
|
3
3
|
import type { TApp } from './entry.js';
|
|
4
4
|
import StreamError from '../../constants/stream-error.js';
|
|
5
5
|
import type { IServerContext } from '../../context/server.js';
|
|
6
|
+
import type { ICoreRenderOptions, ISsrRequestContext } from '../../core/render.js';
|
|
6
7
|
import type { IObtainStreamErrorOut } from '../../helpers/obtain-stream-error.js';
|
|
7
8
|
import type ServerConfig from '../../services/server-config.js';
|
|
8
9
|
export interface IRequestContext<TAppProps = Record<any, any>> {
|
|
10
|
+
/** @deprecated Use request; planned for removal in 9.0. */
|
|
9
11
|
req: ExpressRequest;
|
|
12
|
+
/** @deprecated Use response.headers/status; planned for removal in 9.0. */
|
|
10
13
|
res: ExpressResponse;
|
|
11
14
|
request: Request;
|
|
15
|
+
response: ISsrRequestContext['response'];
|
|
12
16
|
appProps: NonNullable<TAppProps>;
|
|
13
17
|
html: {
|
|
14
18
|
header: string;
|
|
@@ -20,12 +24,12 @@ export interface IRequestContext<TAppProps = Record<any, any>> {
|
|
|
20
24
|
hasEarlyHints?: boolean;
|
|
21
25
|
didError?: StreamError;
|
|
22
26
|
}
|
|
23
|
-
export type TRender<TAppProps = Record<any, any>> = (config: ServerConfig, context: Omit<IRequestContext<TAppProps>, 'request'>, options: IRenderOptions) => Promise<void>;
|
|
27
|
+
export type TRender<TAppProps = Record<any, any>> = (config: ServerConfig, context: Omit<IRequestContext<TAppProps>, 'request' | 'response'>, options: IRenderOptions) => Promise<void>;
|
|
24
28
|
export interface IRenderParams<TAppProps = Record<string, any>> {
|
|
25
29
|
App: TApp<TAppProps>;
|
|
26
30
|
handler: StaticHandler;
|
|
27
31
|
}
|
|
28
|
-
export interface IRenderOptions<TAppProps = Record<string, any>> {
|
|
32
|
+
export interface IRenderOptions<TAppProps = Record<string, any>> extends Pick<ICoreRenderOptions<TAppProps>, 'documentHeaders' | 'sessionCookie' | 'protectPrivate'> {
|
|
29
33
|
hydration?: 'early' | 'footer';
|
|
30
34
|
nonce?: string;
|
|
31
35
|
bootstrapScriptContent?: string;
|
|
@@ -64,5 +68,5 @@ export interface IShellReadyOut {
|
|
|
64
68
|
/**
|
|
65
69
|
* Render application
|
|
66
70
|
*/
|
|
67
|
-
declare function render({ App, handler }: IRenderParams, config: ServerConfig, initialContext: Omit<IRequestContext, 'request'>, { onRouterReady, onShellReady, onResponse, onShellError, onError, getBody, getState, hydration, nonce, bootstrapScriptContent, abortDelay, }: IRenderOptions): Promise<void>;
|
|
71
|
+
declare function render({ App, handler }: IRenderParams, config: ServerConfig, initialContext: Omit<IRequestContext, 'request' | 'response'>, { onRouterReady, onShellReady, onResponse, onShellError, onError, getBody, getState, hydration, nonce, bootstrapScriptContent, documentHeaders, sessionCookie, protectPrivate, abortDelay, }: IRenderOptions): Promise<void>;
|
|
68
72
|
export default render;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"chalk";import
|
|
1
|
+
import e from"chalk";import r from"react";import t from"./create-request.js";import s from"../../constants/stream-error.js";import o 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 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,r,s)=>{const o={signal:r};return s&&"GET"!==e.method&&"HEAD"!==e.method&&(o.body=s(e)??null),t(e,o)};async function g({App:t,handler:g},x,S,{onRouterReady:w,onShellReady:v,onResponse:C,onShellError:E,onError:b,getBody:j,getState:R,hydration:q,nonce:H,bootstrapScriptContent:k,documentHeaders:A,sessionCookie:P,protectPrivate:D,abortDelay:L=15e3}){const{appProps:O,html:T,req:B,res:G}=S,U=x.getLogger(),$=c(B,G);try{const c=Object.assign(S,{request:y(B,$.signal,j),response:{headers:new Headers}}),z={appProps:O,diagnostics:u(!x.isProd)?new h(new URL(c.request.url).pathname,U):void 0,html:T,request:c.request,response:c.response};if(!x.isProd&&z.diagnostics){const{diagnostics:e}=z;for(const r of["req","res"]){let t=c[r];Object.defineProperty(c,r,{configurable:!0,enumerable:!0,get:()=>(e.deprecatedReqRes(),t),set:e=>{t=e}})}}const F=e=>(c.request=e.request,c.response=e.response,c.didError=e.didError,c.html=e.html,c.isStream=e.isStream,c.routerContext=e.routerContext,c.serverContext=e.serverContext,c),I=await i({createApp:(e,s)=>r.createElement(t,{server:{...s.appProps,req:B}},e),handler:g,renderToStream:d},z,{abortDelay:L,hydration:q,nonce:H,bootstrapScriptContent:k,documentHeaders:A,sessionCookie:P,protectPrivate:D,getState:R?({context:e})=>R({context:F(e)}):void 0,onError:({context:r,error:t})=>{const{code:o,message:n}=t;if(b?.({context:F(r),error:t}),U.info(e.red(`Stream error. Code: ${o}`)),[s.RenderAborted,s.RenderTimeout,s.RenderCancel].includes(o))return void U.info(e.dim(n));const{original:a}=t;U.error(a)},onResponse:C?({context:e,html:r,isEnd:t})=>C({context:F(e),html:r,isEnd:t}):void 0,onRouterReady:w?({context:e})=>w({context:F(e)}):void 0,onShellError:E?({context:e,error:r})=>E({context:F(e),error:r}):void 0,onShellReady:({context:e})=>{const r=F(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,G);const t={headers:new Headers(e.response.headers),status:e.response.status},s=v?.({context:r});return((e,r,t)=>{if(!r.headersSent&&!r.writableEnded){e.response.status!==t.status&&r.status(e.response.status??200);const s=new Set([...t.headers.keys(),...e.response.headers.keys()]);for(const o of s)e.response.headers.get(o)!==t.headers.get(o)&&(e.response.headers.has(o)?r.setHeader(o,"set-cookie"===o?a(e.response.headers):e.response.headers.get(o)):r.removeHeader(o))}const s=new Headers(e.response.headers);s.delete("Set-Cookie");for(const[e,t]of Object.entries(r.getHeaders()))if("set-cookie"!==e.toLowerCase()&&void 0!==t)if(Array.isArray(t))for(const r of t)s.append(e,r);else s.set(e,"number"==typeof t?String(t):t);e.response.headers=s,e.response.status=r.statusCode})(e,G,t),s??{}},prepare:async({context:e,executionContext:r})=>{const t=F(e),s=f.get(x);await s.prepareDevAssets(e.routerContext?.matches);const n=s.injectAssets(t);t.hasEarlyHints&&await o(r,n)},routerRequestContext:c},{onEarlyHints:e=>p(G,e)});F(z),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 m(e,r)})(G,I)}finally{$.dispose()}}export{g 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","hydration","nonce","bootstrapScriptContent","abortDelay","appProps","html","shellHtml","res","Logger","getLogger","requestSignal","createRequestSignal","context","Object","assign","request","coreContext","diagnostics","isDiagnosticsEnabled","isProd","Diagnostics","URL","url","pathname","undefined","
|
|
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","hydration","nonce","bootstrapScriptContent","documentHeaders","sessionCookie","protectPrivate","abortDelay","appProps","html","shellHtml","res","Logger","getLogger","requestSignal","createRequestSignal","context","Object","assign","request","response","headers","Headers","coreContext","diagnostics","isDiagnosticsEnabled","isProd","Diagnostics","URL","url","pathname","undefined","name","value","defineProperty","configurable","enumerable","get","deprecatedReqRes","set","next","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","setHeader","cookies","getSetCookieHeaders","length","prepareResponse","previous","shell","names","Set","keys","has","removeHeader","delete","entries","getHeaders","toLowerCase","Array","isArray","item","append","String","statusCode","syncResponse","prepare","executionContext","manifest","SsrManifest","prepareDevAssets","matches","hints","injectAssets","hasEarlyHints","emitEarlyHints","routerRequestContext","onEarlyHints","writeEarlyHints","location","destroyed","writeFetchHeaders","cancel","redirect","writeFetchResponse","writeResponse","dispose"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ICachePolicy {
|
|
2
|
+
public?: boolean;
|
|
3
|
+
private?: boolean;
|
|
4
|
+
maxAge?: number;
|
|
5
|
+
sMaxAge?: number;
|
|
6
|
+
staleWhileRevalidate?: number;
|
|
7
|
+
staleIfError?: number;
|
|
8
|
+
noStore?: boolean;
|
|
9
|
+
noCache?: boolean;
|
|
10
|
+
mustRevalidate?: boolean;
|
|
11
|
+
immutable?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/** Build a deterministic Cache-Control field; durations are non-negative integer seconds. */
|
|
14
|
+
declare const cacheControl: (policy: ICachePolicy) => string;
|
|
15
|
+
export default cacheControl;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e={public:"public",private:"private",maxAge:"max-age",sMaxAge:"s-maxage",staleWhileRevalidate:"stale-while-revalidate",staleIfError:"stale-if-error",noStore:"no-store",noCache:"no-cache",mustRevalidate:"must-revalidate",immutable:"immutable"},a=new Set(["maxAge","sMaxAge","staleWhileRevalidate","staleIfError"]),t=t=>{if(!t||"object"!=typeof t||Array.isArray(t))throw new TypeError("Cache policy must be an object.");for(const[r,i]of Object.entries(t)){if(!Object.hasOwn(e,r))throw new TypeError(`Unknown cache directive: ${r}.`);if(void 0!==i&&(a.has(r)?"number"!=typeof i||!Number.isSafeInteger(i)||i<0:"boolean"!=typeof i))throw new TypeError(`Invalid cache directive: ${r}.`)}if(t.public&&t.private)throw new TypeError("Cache policy cannot be both public and private.");if(t.noStore&&(t.public||t.immutable||[...a].some(e=>void 0!==t[e]))||t.private&&void 0!==t.sMaxAge||t.immutable&&(t.noCache||t.mustRevalidate)||(t.noCache||t.mustRevalidate)&&(void 0!==t.staleWhileRevalidate||void 0!==t.staleIfError))throw new TypeError("Cache policy contains conflicting directives.");return Object.entries(e).flatMap(([e,r])=>{const i=t[e];return void 0===i||!1===i?[]:[a.has(e)?`${r}=${i}`:r]}).join(", ")};export{t as default};
|
|
2
|
+
//# sourceMappingURL=cache-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-control.js","sources":["../../src/core/cache-control.ts"],"sourcesContent":[null],"names":["directives","public","private","maxAge","sMaxAge","staleWhileRevalidate","staleIfError","noStore","noCache","mustRevalidate","immutable","seconds","Set","cacheControl","policy","Array","isArray","TypeError","name","value","Object","entries","hasOwn","undefined","has","Number","isSafeInteger","some","flatMap","directive","join"],"mappings":"AAaA,MAAMA,EAAa,CACjBC,OAAQ,SACRC,QAAS,UACTC,OAAQ,UACRC,QAAS,WACTC,qBAAsB,yBACtBC,aAAc,iBACdC,QAAS,WACTC,QAAS,WACTC,eAAgB,kBAChBC,UAAW,aAEPC,EAAU,IAAIC,IAAI,CAAC,SAAU,UAAW,uBAAwB,iBAGhEC,EAAgBC,IACpB,IAAKA,GAA4B,iBAAXA,GAAuBC,MAAMC,QAAQF,GACzD,MAAM,IAAIG,UAAU,mCAGtB,IAAK,MAAOC,EAAMC,KAAUC,OAAOC,QAAQP,GAAS,CAClD,IAAKM,OAAOE,OAAOtB,EAAYkB,GAC7B,MAAM,IAAID,UAAU,4BAA4BC,MAGlD,QAAcK,IAAVJ,IAKFR,EAAQa,IAAIN,GACS,iBAAVC,IAAuBM,OAAOC,cAAcP,IAAUA,EAAQ,EACpD,kBAAVA,GAEX,MAAM,IAAIF,UAAU,4BAA4BC,KAEpD,CAEA,GAAIJ,EAAOb,QAAUa,EAAOZ,QAC1B,MAAM,IAAIe,UAAU,mDAGtB,GACGH,EAAOP,UACLO,EAAOb,QACNa,EAAOJ,WACP,IAAIC,GAASgB,KAAMT,QAAgDK,IAAvCT,EAAOI,MACtCJ,EAAOZ,cAA8BqB,IAAnBT,EAAOV,SACzBU,EAAOJ,YAAcI,EAAON,SAAWM,EAAOL,kBAC7CK,EAAON,SAAWM,EAAOL,uBACQc,IAAhCT,EAAOT,2BAA8DkB,IAAxBT,EAAOR,cAEvD,MAAM,IAAIW,UAAU,iDAGtB,OAAOG,OAAOC,QAAQrB,GACnB4B,QAAQ,EAAEV,EAAMW,MACf,MAAMV,EAAQL,EAAOI,GAErB,YAAcK,IAAVJ,IAAiC,IAAVA,EAClB,GAGF,CAACR,EAAQa,IAAIN,GAAQ,GAAGW,KAAaV,IAAUU,KAEvDC,KAAK"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface IConditionalValidators {
|
|
2
|
+
/** Quoted entity tag, optionally prefixed with W/. Must identify the selected representation. */
|
|
3
|
+
etag?: string;
|
|
4
|
+
lastModified?: string | Date;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Evaluate GET/HEAD cache validators for an existing successful representation.
|
|
8
|
+
* If-None-Match takes precedence, uses weak comparison, and may contain a list.
|
|
9
|
+
* Call before sending a buffered response; this helper never reads or hashes a stream.
|
|
10
|
+
*/
|
|
11
|
+
declare const conditionalRequest: (request: Request, { etag, lastModified }: IConditionalValidators) => Response | undefined;
|
|
12
|
+
export default conditionalRequest;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=/^(?:W\/)?"[\x21\x23-\x7e\x80-\xff]*"$/,t=/^(?:[A-Za-z]{3}, \d{2} [A-Za-z]{3} \d{4} \d{2}:\d{2}:\d{2} GMT|[A-Za-z]+, \d{2}-[A-Za-z]{3}-\d{2} \d{2}:\d{2}:\d{2} GMT|[A-Za-z]{3} [A-Za-z]{3} [ \d]\d \d{2}:\d{2}:\d{2} \d{4})$/,d=(d,{etag:a,lastModified:i})=>{if(void 0!==a&&!e.test(a))throw new TypeError("ETag must be a quoted entity tag, optionally prefixed with W/.");const o=void 0===i?void 0:new Date(i).getTime();if(void 0!==o&&!Number.isFinite(o))throw new TypeError("Last-Modified must be a valid date.");if(!["GET","HEAD"].includes(d.method))return;const s=d.headers.get("If-None-Match");let r=!1;if(null!==s){const e=s.match(/(?:W\/)?"[\x21\x23-\x7e\x80-\xff]*"|\*/g)??[];r=/^(?:\*|(?:W\/)?"[\x21\x23-\x7e\x80-\xff]*"(?:\s*,\s*(?:W\/)?"[\x21\x23-\x7e\x80-\xff]*")*)$/.test(s)&&e.some(e=>"*"===e||a&&e.replace(/^W\//,"")===a.replace(/^W\//,""))}else if(void 0!==o){const e=d.headers.get("If-Modified-Since"),a=null!==e&&t.test(e)?Date.parse(e):NaN;r=Number.isFinite(a)&&Math.floor(o/1e3)<=Math.floor(a/1e3)}if(!r)return;const n=new Headers;return void 0!==a&&n.set("ETag",a),void 0!==o&&n.set("Last-Modified",new Date(o).toUTCString()),new Response(null,{status:304,headers:n})};export{d as default};
|
|
2
|
+
//# sourceMappingURL=conditional-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conditional-request.js","sources":["../../src/core/conditional-request.ts"],"sourcesContent":[null],"names":["entityTag","httpDate","conditionalRequest","request","etag","lastModified","undefined","test","TypeError","modified","Date","getTime","Number","isFinite","includes","method","noneMatch","headers","get","hasMatch","list","match","some","tag","replace","since","timestamp","parse","NaN","Math","floor","Headers","set","toUTCString","Response","status"],"mappings":"AAMA,MAAMA,EAAY,wCAEZC,EACJ,oLAOIC,EAAqB,CACzBC,GACEC,OAAMC,mBAER,QAAaC,IAATF,IAAuBJ,EAAUO,KAAKH,GACxC,MAAM,IAAII,UAAU,kEAGtB,MAAMC,OAA4BH,IAAjBD,OAA6BC,EAAY,IAAII,KAAKL,GAAcM,UAEjF,QAAiBL,IAAbG,IAA2BG,OAAOC,SAASJ,GAC7C,MAAM,IAAID,UAAU,uCAGtB,IAAK,CAAC,MAAO,QAAQM,SAASX,EAAQY,QACpC,OAGF,MAAMC,EAAYb,EAAQc,QAAQC,IAAI,iBACtC,IAAIC,GAAW,EAEf,GAAkB,OAAdH,EAAoB,CAEtB,MAAMI,EAAiBJ,EAAUK,MAAM,4CAA8C,GAMrFF,EAJE,8FAA8FZ,KAC5FS,IAKFI,EAAKE,KACFC,GAAgB,MAARA,GAAgBnB,GAAQmB,EAAIC,QAAQ,OAAQ,MAAQpB,EAAKoB,QAAQ,OAAQ,IAExF,MAAO,QAAiBlB,IAAbG,EAAwB,CACjC,MAAMgB,EAAQtB,EAAQc,QAAQC,IAAI,qBAC5BQ,EAAsB,OAAVD,GAAkBxB,EAASM,KAAKkB,GAASf,KAAKiB,MAAMF,GAASG,IAE/ET,EACEP,OAAOC,SAASa,IAAcG,KAAKC,MAAMrB,EAAW,MAASoB,KAAKC,MAAMJ,EAAY,IACxF,CAEA,IAAKP,EACH,OAGF,MAAMF,EAAU,IAAIc,QAUpB,YARazB,IAATF,GACFa,EAAQe,IAAI,OAAQ5B,QAGLE,IAAbG,GACFQ,EAAQe,IAAI,gBAAiB,IAAItB,KAAKD,GAAUwB,eAG3C,IAAIC,SAAS,KAAM,CAAEC,OAAQ,IAAKlB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { StaticHandlerContext } from 'react-router';
|
|
2
|
+
/**
|
|
3
|
+
* Copy only named fields, visiting matched routes root to leaf, loader before action.
|
|
4
|
+
* The first ordinary value wins (including Cache-Control); all cookies are appended.
|
|
5
|
+
*/
|
|
6
|
+
declare const copyLoaderHeaders: (routerContext: Pick<StaticHandlerContext, "matches" | "loaderHeaders" | "actionHeaders">, { allow }: {
|
|
7
|
+
allow: readonly string[];
|
|
8
|
+
}) => Headers;
|
|
9
|
+
export default copyLoaderHeaders;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{getHeaderEntries as e,getSetCookieHeaders as o}from"./headers.js";const t=(t,{allow:a})=>{const s=new Headers,r=new Set(a.map(e=>e.toLowerCase()));r.delete("content-type");for(const{route:a}of t.matches)for(const n of[t.loaderHeaders[a.id],t.actionHeaders[a.id]])n&&(e(n).forEach(([e,o])=>{r.has(e.toLowerCase())&&!s.has(e)&&s.set(e,o)}),r.has("set-cookie")&&o(n).forEach(e=>s.append("Set-Cookie",e)));return s};export{t as default};
|
|
2
|
+
//# sourceMappingURL=copy-loader-headers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-loader-headers.js","sources":["../../src/core/copy-loader-headers.ts"],"sourcesContent":[null],"names":["copyLoaderHeaders","routerContext","allow","headers","Headers","allowed","Set","map","name","toLowerCase","delete","route","matches","source","loaderHeaders","id","actionHeaders","getHeaderEntries","forEach","value","has","set","getSetCookieHeaders","cookie","append"],"mappings":"yEAOA,MAAMA,EAAoB,CACxBC,GACEC,YAEF,MAAMC,EAAU,IAAIC,QACdC,EAAU,IAAIC,IAAIJ,EAAMK,IAAKC,GAASA,EAAKC,gBAEjDJ,EAAQK,OAAO,gBAEf,IAAK,MAAMC,MAAEA,KAAWV,EAAcW,QACpC,IAAK,MAAMC,IAAU,CACnBZ,EAAca,cAAcH,EAAMI,IAClCd,EAAce,cAAcL,EAAMI,KAE7BF,IAILI,EAAiBJ,GAAQK,QAAQ,EAAEV,EAAMW,MACnCd,EAAQe,IAAIZ,EAAKC,iBAAmBN,EAAQiB,IAAIZ,IAClDL,EAAQkB,IAAIb,EAAMW,KAIlBd,EAAQe,IAAI,eACdE,EAAoBT,GAAQK,QAASK,GAAWpB,EAAQqB,OAAO,aAAcD,KAKnF,OAAOpB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { StaticHandlerContext } from 'react-router';
|
|
2
|
+
export interface IDocumentHeadersOptions {
|
|
3
|
+
/** Exact, case-sensitive cookie name. Empty values count as present. */
|
|
4
|
+
sessionCookie?: string;
|
|
5
|
+
/** Explicit escape hatch: let rules control credentialed responses too. Default: true. */
|
|
6
|
+
protectPrivate?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface IDocumentHeaderContext {
|
|
9
|
+
request: Request;
|
|
10
|
+
routerContext?: StaticHandlerContext;
|
|
11
|
+
response: {
|
|
12
|
+
headers: Headers;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export interface IDocumentRuleContext {
|
|
16
|
+
request: Request;
|
|
17
|
+
url: URL;
|
|
18
|
+
/** User-Agent heuristic for policy selection, never an authentication signal. */
|
|
19
|
+
isBot: boolean;
|
|
20
|
+
hasCookie: (name: string) => boolean;
|
|
21
|
+
routerContext?: StaticHandlerContext;
|
|
22
|
+
}
|
|
23
|
+
export interface IDocumentHeaderRule {
|
|
24
|
+
when: (context: IDocumentRuleContext) => boolean;
|
|
25
|
+
set: HeadersInit;
|
|
26
|
+
}
|
|
27
|
+
/** Test cookie presence without decoding, exposing, or comparing credential values. */
|
|
28
|
+
export declare const hasCookie: (request: Request, name: string) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Compute fresh document headers after hooks. Later rules replace ordinary fields;
|
|
31
|
+
* cookies append. Credential protection runs last unless explicitly disabled.
|
|
32
|
+
*/
|
|
33
|
+
declare const documentHeaders: (rules: readonly IDocumentHeaderRule[], { sessionCookie, protectPrivate }?: IDocumentHeadersOptions) => ((context: IDocumentHeaderContext) => Headers);
|
|
34
|
+
export default documentHeaders;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{getHeaderEntries as e,getSetCookieHeaders as t}from"./headers.js";const o=(e,t)=>(e.headers.get("Cookie")??"").split(";").some(e=>{const o=e.indexOf("=");return-1!==o&&e.slice(0,o).trim()===t}),r=(r,{sessionCookie:s,protectPrivate:n=!0}={})=>({request:a,routerContext:i,response:c})=>{const h=new Headers(c.headers),d={request:a,url:new URL(a.url),isBot:/bot|crawler|spider|crawling/i.test(a.headers.get("User-Agent")??""),hasCookie:e=>o(a,e),routerContext:i};for(const o of r){if(!o.when(d))continue;const r=new Headers(o.set);e(r).forEach(([e,t])=>h.set(e,t)),t(r).forEach(e=>h.append("Set-Cookie",e))}n&&(h.has("Set-Cookie")||a.headers.has("Authorization")||s&&o(a,s))&&h.set("Cache-Control","private, no-store");const l=(h.get("Vary")??"").split(",").map(e=>e.trim()).filter(e=>e&&"cookie"!==e.toLowerCase());return l.length?h.set("Vary",l.join(", ")):h.delete("Vary"),h};export{r as default,o as hasCookie};
|
|
2
|
+
//# sourceMappingURL=document-headers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-headers.js","sources":["../../src/core/document-headers.ts"],"sourcesContent":[null],"names":["hasCookie","request","name","headers","get","split","some","cookie","separator","indexOf","slice","trim","documentHeaders","rules","sessionCookie","protectPrivate","routerContext","response","Headers","ruleContext","url","URL","isBot","test","rule","when","selected","set","getHeaderEntries","forEach","value","getSetCookieHeaders","append","has","vary","map","filter","toLowerCase","length","join","delete"],"mappings":"yEA+BO,MAAMA,EAAY,CAACC,EAAkBC,KACzCD,EAAQE,QAAQC,IAAI,WAAa,IAAIC,MAAM,KAAKC,KAAMC,IACrD,MAAMC,EAAYD,EAAOE,QAAQ,KAEjC,OAAqB,IAAdD,GAAoBD,EAAOG,MAAM,EAAGF,GAAWG,SAAWT,IAO/DU,EAAkB,CACtBC,GACEC,gBAAeC,kBAAiB,GAAkC,KAE7D,EAAGd,UAASe,gBAAeC,eAChC,MAAMd,EAAU,IAAIe,QAAQD,EAASd,SAC/BgB,EAAoC,CACxClB,UACAmB,IAAK,IAAIC,IAAIpB,EAAQmB,KACrBE,MAAO,+BAA+BC,KAAKtB,EAAQE,QAAQC,IAAI,eAAiB,IAChFJ,UAAYE,GAASF,EAAUC,EAASC,GACxCc,iBAGF,IAAK,MAAMQ,KAAQX,EAAO,CACxB,IAAKW,EAAKC,KAAKN,GACb,SAGF,MAAMO,EAAW,IAAIR,QAAQM,EAAKG,KAElCC,EAAiBF,GAAUG,QAAQ,EAAE3B,EAAM4B,KAAW3B,EAAQwB,IAAIzB,EAAM4B,IACxEC,EAAoBL,GAAUG,QAAStB,GAAWJ,EAAQ6B,OAAO,aAAczB,GACjF,CAGEQ,IACCZ,EAAQ8B,IAAI,eACXhC,EAAQE,QAAQ8B,IAAI,kBACnBnB,GAAiBd,EAAUC,EAASa,KAEvCX,EAAQwB,IAAI,gBAAiB,qBAK/B,MAAMO,GAAQ/B,EAAQC,IAAI,SAAW,IAClCC,MAAM,KACN8B,IAAKjC,GAASA,EAAKS,QACnByB,OAAQlC,GAASA,GAA+B,WAAvBA,EAAKmC,eAQjC,OANIH,EAAKI,OACPnC,EAAQwB,IAAI,OAAQO,EAAKK,KAAK,OAE9BpC,EAAQqC,OAAO,QAGVrC"}
|
package/core/handler.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"./head-response.js";import
|
|
1
|
+
import{hasCookie as e}from"./document-headers.js";import s from"./head-response.js";import o from"./render.js";import t,{isDiagnosticsEnabled as r}from"../services/diagnostics.js";const n=(n,{diagnostics:a,getHtml:i,onRequest:p,...c})=>async(d,m)=>{const u=r(a)?new t(new URL(d.url).pathname):void 0,h=await(p?.({executionContext:m,request:d}));if(h instanceof Response)return u?.inspectCachePolicy(h.headers,Boolean(c.sessionCookie&&e(d,c.sessionCookie))),s(d,h);const f={appProps:h?.appProps??{},diagnostics:u,html:await i(d),request:d,response:{headers:new Headers(h?.headers),status:h?.status}};return o(n,f,c,m)};export{n 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","options","async","request","executionContext","
|
|
1
|
+
{"version":3,"file":"handler.js","sources":["../../src/core/handler.ts"],"sourcesContent":[null],"names":["createHandler","params","diagnostics","getHtml","onRequest","options","async","request","executionContext","requestDiagnostics","isDiagnosticsEnabled","Diagnostics","URL","url","pathname","undefined","requestInit","Response","inspectCachePolicy","headers","Boolean","sessionCookie","hasCookie","headResponse","context","appProps","html","response","Headers","status","render"],"mappings":"oLAyCA,MAAMA,EAAgB,CACpBC,GACEC,cAAaC,UAASC,eAAcC,KAK/BC,MAAOC,EAASC,KACrB,MAAMC,EAAqBC,EAAqBR,GAC5C,IAAIS,EAAY,IAAIC,IAAIL,EAAQM,KAAKC,eACrCC,EACEC,QAAoBZ,IAAY,CAAEI,mBAAkBD,aAE1D,GAAIS,aAAuBC,SAMzB,OALAR,GAAoBS,mBAClBF,EAAYG,QACZC,QAAQf,EAAQgB,eAAiBC,EAAUf,EAASF,EAAQgB,iBAGvDE,EAAahB,EAASS,GAG/B,MAAMQ,EAAyC,CAC7CC,SAAWT,GAAaS,UAAY,GACpCvB,YAAaO,EACbiB,WAAYvB,EAAQI,GACpBA,UACAoB,SAAU,CACRR,QAAS,IAAIS,QAAQZ,GAAaG,SAClCU,OAAQb,GAAaa,SAIzB,OAAOC,EAAO7B,EAAQuB,EAASnB,EAASG"}
|
package/core/render.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ReactNode } from 'react';
|
|
|
2
2
|
import type { StaticHandler, StaticHandlerContext } from 'react-router';
|
|
3
3
|
import StreamError from '../constants/stream-error.js';
|
|
4
4
|
import type { IServerContext } from '../context/server.js';
|
|
5
|
+
import type { IDocumentHeaderRule, IDocumentHeadersOptions } from './document-headers.js';
|
|
5
6
|
import type { ISsrExecutionContext } from './types.js';
|
|
6
7
|
import type { IObtainStreamErrorOut } from '../helpers/obtain-stream-error.js';
|
|
7
8
|
import type Diagnostics from '../services/diagnostics.js';
|
|
@@ -59,7 +60,9 @@ export interface ICoreRenderParams<TAppProps = Record<string, any>> {
|
|
|
59
60
|
handler: StaticHandler;
|
|
60
61
|
renderToStream: TRenderToStream;
|
|
61
62
|
}
|
|
62
|
-
export interface ICoreRenderOptions<TAppProps = Record<string, any>> {
|
|
63
|
+
export interface ICoreRenderOptions<TAppProps = Record<string, any>> extends IDocumentHeadersOptions {
|
|
64
|
+
/** Opt in to document policies after onShellReady; redirects keep their header contract. */
|
|
65
|
+
documentHeaders?: readonly IDocumentHeaderRule[];
|
|
63
66
|
/** Hydrate the parsed shell while deferred boundaries are still pending. */
|
|
64
67
|
hydration?: 'early' | 'footer';
|
|
65
68
|
nonce?: string;
|
|
@@ -103,8 +106,6 @@ export interface ICoreRenderOptions<TAppProps = Record<string, any>> {
|
|
|
103
106
|
}) => Promise<void> | void;
|
|
104
107
|
routerRequestContext?: unknown;
|
|
105
108
|
}
|
|
106
|
-
/**
|
|
107
|
-
|
|
108
|
-
*/
|
|
109
|
-
declare const render: <TAppProps>({ createApp, handler, renderToStream }: ICoreRenderParams<TAppProps>, context: ISsrRequestContext<TAppProps>, { abortDelay, getState, hydration, nonce, bootstrapScriptContent, onError, onResponse, onRouterReady, onShellError, onShellReady, prepare, routerRequestContext, }: ICoreRenderOptions<TAppProps>, executionContext?: ISsrExecutionContext) => Promise<Response>;
|
|
109
|
+
/** Inspect the committed metadata, including redirect and shell-error responses. */
|
|
110
|
+
declare const render: <TAppProps>(params: ICoreRenderParams<TAppProps>, context: ISsrRequestContext<TAppProps>, options: ICoreRenderOptions<TAppProps>, executionContext?: ISsrExecutionContext) => Promise<Response>;
|
|
110
111
|
export default render;
|
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 n from"./compose-html.js";import a from"./data-stream.js";import c from"./head-response.js";import{mergeResponseHeaders as
|
|
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 n from"./compose-html.js";import a from"./data-stream.js";import c,{hasCookie as i}from"./document-headers.js";import d from"./head-response.js";import{mergeResponseHeaders as l}from"./headers.js";import m from"./transform-html.js";import u from"../helpers/build-custom-state.js";import h from"../helpers/obtain-stream-error.js";const p="text/html",C="Content-Type",f=async({createApp:i,handler:f,renderToStream:x},w,{abortDelay:y=15e3,getState:R,hydration:S="footer",nonce:g,bootstrapScriptContent:v,onError:E,onResponse:b,onRouterReady:q,onShellError:j,onShellReady:k,prepare:H,routerRequestContext:P,documentHeaders:T,sessionCookie:A,protectPrivate:B},_)=>{const D=await f.query(w.request,{requestContext:P??w});if(D instanceof Response)return d(w.request,l(D,w.response.headers));w.routerContext=D;const L=new a(D,w.diagnostics,g);try{await(H?.({context:w,executionContext:_}))}catch(e){throw L.cancel(),e}const{isStream:I=!0}=await(q?.({context:w}))??{};w.isStream=I,w.serverContext={basename:w.routerContext.basename,isServer:!0,response:null};const $=t(f.dataRoutes,w.routerContext),z=e.createElement(s,{context:w.serverContext},i(e.createElement(r,{router:$,context:w.routerContext,hydrate:!1}),w)),F=new AbortController;let G,J,K=!1;const M=()=>Q(w.request.signal.reason),N=()=>clearTimeout(U),O=()=>{N(),w.request.signal.removeEventListener("abort",M)},Q=e=>{K||(K=!0,G=e,O(),w.didError??=o.RenderCancel,L.abort(),F.abort(e),J?.abort(e))},U=setTimeout(()=>{w.didError=o.RenderTimeout,Q()},y);w.request.signal.aborted?Q(w.request.signal.reason):w.request.signal.addEventListener("abort",M,{once:!0});try{J=await x(z,{nonce:g,bootstrapScriptContent:"early"===S&&I?`(window.__ssrBoostStream = window.__ssrBoostStream || []).push(["shell"]);${v??""};document.currentScript?.remove();`:v,onError:e=>{const t=h(e);!K||t.code!==o.RenderAborted&&e!==F.signal.reason||(t.code=w.didError===o.RenderTimeout?o.RenderTimeout:o.RenderCancel);const{code:r}=t;w.didError??=r,E?.({context:w,error:t})},signal:F.signal}),K&&J.abort(G),Promise.all([J.allReady,L.done]).then(N,N),await(I?J.shellReady:Promise.all([J.allReady,L.done]))}catch(e){return Q(e),await(J?.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>",n=new Headers(e.response.headers);return n.set(C,p),new Response("HEAD"===e.request.method?null:s,{headers:n,status:500})})(w,e,j)}try{const e=w.serverContext.response;if(e&&(V=e,Boolean(V&&V.status>=300&&V.status<400&&V.headers.has("Location"))))return Q(),await J.stream.cancel().catch(()=>{}),d(w.request,l(e,w.response.headers));const{header:t,footer:r,headers:o,status:s}=((e,{getState:t,onShellReady:r,hydration:o,nonce:s,documentHeaders:n,sessionCookie:a,protectPrivate:i},d)=>{const l=e.serverContext.response;e.response.status=l?.status??e.response.status??e.routerContext.statusCode??200,e.response.headers.has(C)||e.response.headers.set(C,p);const m=r?.({context:e})??{},h="early"===o&&e.isStream,f=u(t?.({context:e}),e.diagnostics,s,Boolean(h));let x=m.header||e.html.header;const w=m.footer||e.html.footer;e.diagnostics?.inspectShell({header:x,footer:w});let y=w;return h?x+=f+d.state(!0):y=f+d.state(!1)+d.take()+y,n&&(e.response.headers=c(n,{sessionCookie:a,protectPrivate:i})(e)),{header:x,footer:y,headers:new Headers(e.response.headers),status:e.response.status}})(w,{getState:R,onShellReady:k,hydration:S,nonce:g,documentHeaders:T,sessionCookie:A,protectPrivate:B},L);if("HEAD"===w.request.method||[204,205,304].includes(s))return Q(),await J.stream.cancel().catch(()=>{}),new Response(null,{headers:o,status:s});const a=n(t,J.stream,r,Q,O,L),i=m(a,b?(e,t)=>b({context:w,html:e,isEnd:t}):void 0,w.diagnostics);return J.start(),new Response(i,{headers:o,status:s})}catch(e){throw Q(e),J.stream.locked||await J.stream.cancel(e).catch(()=>{}),e}var V},x=async(e,t,r,o)=>{const s=await f(e,t,r,o);return t.diagnostics?.inspectCachePolicy(s.headers,Boolean(r.sessionCookie&&i(t.request,r.sessionCookie))),s};export{x 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","
|
|
1
|
+
{"version":3,"file":"render.js","sources":["../../src/core/render.tsx"],"sourcesContent":[null],"names":["HTML_CONTENT_TYPE","CONTENT_TYPE","renderResponse","async","createApp","handler","renderToStream","context","abortDelay","getState","hydration","nonce","bootstrapScriptContent","onError","onResponse","onRouterReady","onShellError","onShellReady","prepare","routerRequestContext","documentHeaders","rules","sessionCookie","protectPrivate","executionContext","queried","query","request","requestContext","Response","headResponse","mergeResponseHeaders","response","headers","routerContext","dataStream","DataStream","diagnostics","error","cancel","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","streamError","obtainStreamError","code","RenderAborted","Promise","all","allReady","done","then","shellReady","stream","catch","shellError","Error","String","html","Headers","set","method","status","createShellErrorResponse","serverResponse","Boolean","has","header","footer","statusCode","shell","isEarly","customState","buildCustomState","shellFooter","inspectShell","state","take","prepareHtmlResponse","includes","body","composeHtml","transformed","transformHtml","isEnd","undefined","start","locked","render","params","options","inspectCachePolicy","hasCookie"],"mappings":"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"}
|
package/http.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { default as cacheControl } from './core/cache-control.js';
|
|
2
|
+
export type { ICachePolicy } from './core/cache-control.js';
|
|
3
|
+
export { default as conditionalRequest } from './core/conditional-request.js';
|
|
4
|
+
export type { IConditionalValidators } from './core/conditional-request.js';
|
|
5
|
+
export { default as copyLoaderHeaders } from './core/copy-loader-headers.js';
|
|
6
|
+
export { default as documentHeaders } from './core/document-headers.js';
|
|
7
|
+
export type { IDocumentHeaderContext, IDocumentHeaderRule, IDocumentHeadersOptions, IDocumentRuleContext, } from './core/document-headers.js';
|
package/http.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export{default as cacheControl}from"./core/cache-control.js";export{default as conditionalRequest}from"./core/conditional-request.js";export{default as copyLoaderHeaders}from"./core/copy-loader-headers.js";export{default as documentHeaders}from"./core/document-headers.js";
|
|
2
|
+
//# sourceMappingURL=http.js.map
|
package/http.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
package/package.json
CHANGED
package/services/build.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import i from"node:child_process";import s from"node:fs";import t from"node:path";import e from"chalk";import{resolveConfig as o}from"vite";import r from"../cli/diagnostic-codes.js";import n from"../cli/helpers/vite-reset-cache.js";import l from"../helpers/create-focus-only.js";import{createDevMarker as a}from"../helpers/dev-marker.js";import c from"../helpers/plugin-config.js";import d from"../helpers/process-stop.js";import u from"./server-config.js";import h from"./ssr-manifest.js";class p{isProd;nodeEnv;buildDir;viteConfig;pluginConfig;params={mode:"",clientOptions:"",serverOptions:"",focusOnly:"app",isWatch:!1,isUnlockRobots:!1,isEject:!1,isServerless:!1,isNoWarnings:!1};abortController=null;runningBuild=[];hasPreviewModeExitListener=!1;diagnosticCodes=new Set;constructor(i){this.params={...this.params,...i}}async makeConfig(){const{mode:i}=this.params;this.viteConfig=await o({},"build",i,"production"),this.pluginConfig=c(this.viteConfig),this.buildDir=t.resolve(this.viteConfig.root,this.viteConfig.build.outDir),this.nodeEnv=process.env.NODE_ENV||"production",this.isProd="production"===this.nodeEnv}clearBuildFolder(){s.existsSync(this.buildDir)&&s.rmSync(this.buildDir,{recursive:!0})}getIsProd(){return this.isProd}getNodeEnv(){return this.nodeEnv}getRunningBuildNames(){return this.runningBuild.map(({name:i})=>i)}promisifyProcess(i,s=!1){const t=new Promise((t,e)=>{i.on("exit",i=>{t(i)}),i.on("close",i=>{t(i)}),i.on("error",i=>{e(i)}),s&&i.stderr?.on("data",i=>{const s=Buffer.from(i).toString();(s.includes("warning")||s.includes("WARNING"))&&t(1)})});i.stdout?.pipe(process.stdout),i.stderr?.pipe(process.stderr);for(const s of[i.stdout,i.stderr]){let i="";s?.on("data",s=>{const t=i+Buffer.from(s).toString();r.filter(i=>t.includes(i)).forEach(i=>this.diagnosticCodes.add(i)),i=t.slice(-80)})}return{promise:t,command:i}}buildManifest(){console.info(e.blue("Building routes manifest file"));const i=u.init({isProd:this.isProd,mode:this.params.mode},{root:this.viteConfig.root,clientFile:this.pluginConfig.clientFile});h.get(i,{buildDir:this.viteConfig.build.outDir,viteAliases:this.viteConfig.resolve.alias,basename:this.viteConfig.base,renderBuiltUrl:this.viteConfig?.experimental?.renderBuiltUrl}).buildRoutesManifest()}unlockRobots(){const i=`${this.buildDir}/client/robots.txt`;if(!s.existsSync(i))return void console.warn(`Failed to unlock robots.txt, file not exist: ${i}`);const t=s.readFileSync(i,{encoding:"utf-8"}).replace(/Disallow: \/$/m,"Allow: /");s.writeFileSync(i,t,{encoding:"utf-8"}),console.info(e.blue("\nrobots.txt unlocked."))}eject(){const i=`${this.buildDir}/server/start.js`;s.writeFileSync(i,"import runProd from '
|
|
1
|
+
import i from"node:child_process";import s from"node:fs";import t from"node:path";import e from"chalk";import{resolveConfig as o}from"vite";import r from"../cli/diagnostic-codes.js";import n from"../cli/helpers/vite-reset-cache.js";import l from"../helpers/create-focus-only.js";import{createDevMarker as a}from"../helpers/dev-marker.js";import c from"../helpers/plugin-config.js";import d from"../helpers/process-stop.js";import u from"./server-config.js";import h from"./ssr-manifest.js";class p{isProd;nodeEnv;buildDir;viteConfig;pluginConfig;params={mode:"",clientOptions:"",serverOptions:"",focusOnly:"app",isWatch:!1,isUnlockRobots:!1,isEject:!1,isServerless:!1,isNoWarnings:!1};abortController=null;runningBuild=[];hasPreviewModeExitListener=!1;diagnosticCodes=new Set;constructor(i){this.params={...this.params,...i}}async makeConfig(){const{mode:i}=this.params;this.viteConfig=await o({},"build",i,"production"),this.pluginConfig=c(this.viteConfig),this.buildDir=t.resolve(this.viteConfig.root,this.viteConfig.build.outDir),this.nodeEnv=process.env.NODE_ENV||"production",this.isProd="production"===this.nodeEnv}clearBuildFolder(){s.existsSync(this.buildDir)&&s.rmSync(this.buildDir,{recursive:!0})}getIsProd(){return this.isProd}getNodeEnv(){return this.nodeEnv}getRunningBuildNames(){return this.runningBuild.map(({name:i})=>i)}promisifyProcess(i,s=!1){const t=new Promise((t,e)=>{i.on("exit",i=>{t(i)}),i.on("close",i=>{t(i)}),i.on("error",i=>{e(i)}),s&&i.stderr?.on("data",i=>{const s=Buffer.from(i).toString();(s.includes("warning")||s.includes("WARNING"))&&t(1)})});i.stdout?.pipe(process.stdout),i.stderr?.pipe(process.stderr);for(const s of[i.stdout,i.stderr]){let i="";s?.on("data",s=>{const t=i+Buffer.from(s).toString();r.filter(i=>t.includes(i)).forEach(i=>this.diagnosticCodes.add(i)),i=t.slice(-80)})}return{promise:t,command:i}}buildManifest(){console.info(e.blue("Building routes manifest file"));const i=u.init({isProd:this.isProd,mode:this.params.mode},{root:this.viteConfig.root,clientFile:this.pluginConfig.clientFile});h.get(i,{buildDir:this.viteConfig.build.outDir,viteAliases:this.viteConfig.resolve.alias,basename:this.viteConfig.base,renderBuiltUrl:this.viteConfig?.experimental?.renderBuiltUrl}).buildRoutesManifest()}unlockRobots(){const i=`${this.buildDir}/client/robots.txt`;if(!s.existsSync(i))return void console.warn(`Failed to unlock robots.txt, file not exist: ${i}`);const t=s.readFileSync(i,{encoding:"utf-8"}).replace(/Disallow: \/$/m,"Allow: /");s.writeFileSync(i,t,{encoding:"utf-8"}),console.info(e.blue("\nrobots.txt unlocked."))}eject(){const i=`${this.buildDir}/server/start.js`;s.writeFileSync(i,"import runProd from '../cli/run-prod.js';\n\nconst VERSION = process.env.VERSION || \"1.0.0\";\nconst PORT = process.env.PORT || 3000;\nconst IS_HOST = process.env.IS_HOST || \"0\";\nconst ONLY_CLIENT = process.env.ONLY_CLIENT || \"0\";\n\nawait runProd({\n version: VERSION,\n isHost: IS_HOST === '1',\n isPrintInfo: true,\n port: PORT,\n onlyClient: ONLY_CLIENT === '1',\n });\n",{encoding:"utf-8"})}createServerless(){const i=`${this.buildDir}/server/serverless.js`;s.writeFileSync(i,"import runServerless from '../cli/run-serverless.js';\n\nexport default await runServerless({ version: process.env.VERSION || \"1.0.0\" });\n",{encoding:"utf-8"})}async spawnBuild(s,t,e={}){const{mode:o,isNoWarnings:r}=this.params,{focusOnly:n=this.params.focusOnly,shouldWait:a=!1,env:c={}}=e,d=o&&!t.includes("--mode")?`--mode ${o}`:"",u=this.promisifyProcess(i.spawn(`vite build ${t} ${d} --emptyOutDir`,{signal:this.abortController.signal,stdio:[process.stdin,"pipe","pipe"],shell:!0,env:{...process.env,...c,FORCE_COLOR:"2",SSR_BOOST_IS_SSR:l(n).isOnlyClient()?"0":"1",SSR_BOOST_ACTION:global.viteBoostAction}}),r);this.runningBuild.push({name:s,buildProcess:u}),a&&await this.waitLastBuild()}async waitLastBuild(){const i=this.runningBuild.at(-1);if(!i)return;const s=await i.buildProcess.promise;d(s,!0)}runPreviewMode(){this.hasPreviewModeExitListener||(process.on("exit",()=>{this.abortController.abort()}),this.hasPreviewModeExitListener=!0);const{onFinish:i}=this.params;let s=this.runningBuild.length;const t=e=>{Buffer.from(e).toString().includes("built in")&&(s-=1,s||(this.runningBuild.forEach(({buildProcess:i})=>{i.command.stdout?.removeListener("data",t)}),a(this.isProd,this.viteConfig),i?.()))};this.runningBuild.forEach(({buildProcess:i})=>{i.command.stdout?.on("data",t)})}async build(){await this.makeConfig(),await n(),this.clearBuildFolder(),this.diagnosticCodes.clear();const{clientOptions:i,serverOptions:e,onFinish:o,isWatch:r,focusOnly:c,isEject:d,isServerless:u,isUnlockRobots:h}=this.params,{outDir:p}=this.viteConfig.build,f=l(c);this.abortController=new AbortController,this.runningBuild=[],f.isClient()&&await this.spawnBuild("client",`${i} --outDir ${p}/client`,{shouldWait:!r}),f.isServer()&&(await this.spawnBuild("server",`${e} --outDir ${p}/server --ssr ${this.pluginConfig.serverFile}`,{shouldWait:!r}),r||(this.buildManifest(),d&&this.eject(),u&&this.createServerless()));const{entrypoint:m}=this.pluginConfig;if(m?.length&&f.isEntrypoint())for(const{name:i,type:s,serverFile:t,buildOptions:e=""}of m){const o=t&&"ssr"===s?`--ssr ${t}`:"";await this.spawnBuild(i,`${e} ${o} --outDir ${p}/${i}`,{shouldWait:!r,focusOnly:"ssr"===s?"server":"client",env:{SSR_BOOST_CUSTOM_ENTRYPOINT_BUILD_NAME:i}})}r?this.runPreviewMode():(h&&this.unlockRobots(),a(this.isProd,this.viteConfig),s.mkdirSync(this.buildDir,{recursive:!0}),s.writeFileSync(t.join(this.buildDir,"ssr-boost-diagnostics.json"),JSON.stringify({codes:[...this.diagnosticCodes].sort((i,s)=>i.localeCompare(s))},null,2)),o?.())}}export{p as default};
|
|
2
2
|
//# sourceMappingURL=build.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { StaticHandlerContext } from 'react-router';
|
|
2
2
|
import Logger from './logger.js';
|
|
3
|
-
type TDiagnosticCode = 'SSR_BOOST_LOADER_NOT_SERIALIZABLE' | 'SSR_BOOST_STREAM_PROMISE_ABORTED' | 'SSR_BOOST_STATE_NOT_SERIALIZABLE' | 'SSR_BOOST_OUTLET_MISSING' | 'SSR_BOOST_HYDRATION_STATE_MISSING' | 'SSR_BOOST_DUPLICATE_OUTPUT' | 'SSR_BOOST_ONRESPONSE_INVALID_RETURN';
|
|
3
|
+
type TDiagnosticCode = 'SSR_BOOST_CACHE_PRIVATE_LEAK' | 'SSR_BOOST_DEPRECATED_REQ_RES' | 'SSR_BOOST_LOADER_NOT_SERIALIZABLE' | 'SSR_BOOST_STREAM_PROMISE_ABORTED' | 'SSR_BOOST_STATE_NOT_SERIALIZABLE' | 'SSR_BOOST_OUTLET_MISSING' | 'SSR_BOOST_HYDRATION_STATE_MISSING' | 'SSR_BOOST_DUPLICATE_OUTPUT' | 'SSR_BOOST_ONRESPONSE_INVALID_RETURN';
|
|
4
4
|
interface ISerializationIssue {
|
|
5
5
|
path: string;
|
|
6
6
|
reason: string;
|
|
@@ -34,6 +34,8 @@ declare class Diagnostics {
|
|
|
34
34
|
* Emit each concrete message once per process, including across handler instances.
|
|
35
35
|
*/
|
|
36
36
|
protected warn(code: TDiagnosticCode, detail: string): void;
|
|
37
|
+
/** Warn once for either legacy Express field, regardless of route or hook. */
|
|
38
|
+
deprecatedReqRes(): void;
|
|
37
39
|
/**
|
|
38
40
|
* A split Fetch shell has one insertion boundary and must not retain raw outlets.
|
|
39
41
|
*/
|
|
@@ -41,6 +43,8 @@ declare class Diagnostics {
|
|
|
41
43
|
header: string;
|
|
42
44
|
footer: string;
|
|
43
45
|
}): void;
|
|
46
|
+
/** Warn about explicitly public documents carrying credentials without logging their values. */
|
|
47
|
+
inspectCachePolicy(headers: Headers, hasSessionCookie: boolean): void;
|
|
44
48
|
/**
|
|
45
49
|
* Include React Router's route id and the full loader/action key path.
|
|
46
50
|
*/
|
package/services/diagnostics.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import t from"./logger.js";const e="\x3c!--ssr-outlet--\x3e",o="window.__staticRouterHydrationData",
|
|
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},c=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"},S=(t,e,o="$",s=new Set,r=!1)=>{const n=typeof t;if(r&&(t instanceof Promise||t instanceof Date||t instanceof RegExp||"bigint"===n))return;if("function"===n||"bigint"===n||"symbol"===n)return void e({path:o,reason:`${c(t)} is not JSON-serializable`});if(null===t||"object"!==n)return;const i=t,a=Object.getPrototypeOf(i);if(!(r&&(i instanceof Map||i instanceof Set)||a===Object.prototype||null===a||Array.isArray(i)&&a===Array.prototype)){const t=c(i);return void e({path:o,reason:"Date"===t?"Date hydrates as a string":`${t} is not JSON-serializable`})}if(s.has(i))return void e({path:o,reason:"a circular reference is not JSON-serializable"});s.add(i);const f=r&&i instanceof Map?[...i].flatMap(([t,e],o)=>[[`${o}.key`,t],[`${o}.value`,e]]):r&&i instanceof Set?[...i].map((t,e)=>[String(e),t]):Object.entries(i);for(const[t,n]of f){const a=Array.isArray(i)&&/^(0|[1-9]\d*)$/.test(t)?`[${t}]`:/^[A-Za-z_$][\w$]*$/.test(t)?`.${t}`:`[${JSON.stringify(t)}]`;S(n,e,o+a,s,r)}s.delete(i)};class f{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,{}))}deprecatedReqRes(){this.warn("SSR_BOOST_DEPRECATED_REQ_RES","context.req and context.res are deprecated in 8.x and planned for removal in 9.0; use context.request, context.response.headers/context.response.status and React Router HTTP helpers such as redirect().")}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.`)}inspectCachePolicy(t,e){/(?:^|,)\s*public\s*(?:,|$)/i.test(t.get("Cache-Control")??"")&&(t.has("Set-Cookie")||e)&&this.warn("SSR_BOOST_CACHE_PRIVATE_LEAK",`Response for route ${JSON.stringify(this.route)} is public with Set-Cookie or a session cookie. Use private, no-store and bypass the shared cache for authenticated requests.`)}inspectRouterState({loaderData:t,actionData:e}){for(const[o,s]of Object.entries({loaderData:t,actionData:e}))for(const[t,e]of Object.entries(s??{}))S(e,({path:e,reason:o})=>this.warn("SSR_BOOST_LOADER_NOT_SERIALIZABLE",`Route ${JSON.stringify(t)} at ${e}: ${o}.`),`${o}[${JSON.stringify(t)}]`,new Set,!0)}streamAborted(t){this.warn("SSR_BOOST_STREAM_PROMISE_ABORTED",`Route ${JSON.stringify(this.route)} aborted with ${t} pending loader/action promise(s); the browser receives a rejection when connected.`)}inspectStreamValue(t,e){S(t,({path:t,reason:e})=>this.warn("SSR_BOOST_LOADER_NOT_SERIALIZABLE",`Route ${JSON.stringify(this.route)} at ${t}: ${e}.`),`promise[${e}]`,new Set,!0)}inspectState(t){S(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 ${c(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{f as default,i as formatDiagnostic,n as isDiagnosticsEnabled,a as splitHtmlShell,S as walkSerializable};
|
|
2
2
|
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -1 +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","streamed","type","Promise","Date","RegExp","reason","object","Map","Array","isArray","has","add","entries","flatMap","key","child","index","map","String","suffix","test","delete","Diagnostics","route","logger","chunks","Logger","this","warn","detail","message","warned","inspectShell","header","footer","includes","inspectRouterState","loaderData","actionData","kind","data","streamAborted","count","inspectStreamValue","id","inspectState","state","inspectOnResponse","append","push","complete","join","markers","marker","set","
|
|
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","streamed","type","Promise","Date","RegExp","reason","object","Map","Array","isArray","has","add","entries","flatMap","key","child","index","map","String","suffix","test","delete","Diagnostics","route","logger","chunks","Logger","this","warn","detail","message","warned","deprecatedReqRes","inspectShell","header","footer","includes","inspectCachePolicy","headers","hasSessionCookie","get","inspectRouterState","loaderData","actionData","kind","data","streamAborted","count","inspectStreamValue","id","inspectState","state","inspectOnResponse","append","push","complete","join","markers","marker","set","markup","replace","_tag","opening","content","match","matchAll","attribute","total"],"mappings":"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"}
|