@lomray/vite-ssr-boost 7.1.0 → 8.0.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.
Files changed (130) hide show
  1. package/README.md +17 -1
  2. package/adapters/body.d.ts +5 -0
  3. package/adapters/body.js +2 -0
  4. package/adapters/body.js.map +1 -0
  5. package/adapters/compression.d.ts +11 -0
  6. package/adapters/compression.js +2 -0
  7. package/adapters/compression.js.map +1 -0
  8. package/adapters/edge.d.ts +11 -0
  9. package/adapters/edge.js +2 -0
  10. package/adapters/edge.js.map +1 -0
  11. package/adapters/express/create-request.d.ts +11 -0
  12. package/adapters/express/create-request.js +2 -0
  13. package/adapters/express/create-request.js.map +1 -0
  14. package/{node → adapters/express}/entry.d.ts +8 -14
  15. package/adapters/express/entry.js.map +1 -0
  16. package/{services → adapters/express}/prepare-server.d.ts +14 -21
  17. package/adapters/express/prepare-server.js +2 -0
  18. package/adapters/express/prepare-server.js.map +1 -0
  19. package/{node → adapters/express}/render.d.ts +8 -8
  20. package/adapters/express/render.js +2 -0
  21. package/adapters/express/render.js.map +1 -0
  22. package/{node → adapters/express}/server.d.ts +1 -1
  23. package/adapters/express/server.js +2 -0
  24. package/adapters/express/server.js.map +1 -0
  25. package/adapters/express.d.ts +11 -0
  26. package/adapters/express.js +2 -0
  27. package/adapters/express.js.map +1 -0
  28. package/adapters/fastify.d.ts +23 -0
  29. package/adapters/fastify.js +2 -0
  30. package/adapters/fastify.js.map +1 -0
  31. package/adapters/hono.d.ts +13 -0
  32. package/adapters/hono.js +2 -0
  33. package/adapters/hono.js.map +1 -0
  34. package/adapters/node.d.ts +18 -0
  35. package/adapters/node.js +2 -0
  36. package/adapters/node.js.map +1 -0
  37. package/cli/run-dev.js +1 -1
  38. package/cli/run-dev.js.map +1 -1
  39. package/cli/run-prod.d.ts +1 -1
  40. package/cli/run-prod.js +1 -1
  41. package/cli/run-prod.js.map +1 -1
  42. package/cli/run-serverless.d.ts +2 -2
  43. package/cli/run-serverless.js +1 -1
  44. package/cli/run-serverless.js.map +1 -1
  45. package/components/response-status.js +1 -1
  46. package/components/response-status.js.map +1 -1
  47. package/core/compose-html.d.ts +5 -0
  48. package/core/compose-html.js +2 -0
  49. package/core/compose-html.js.map +1 -0
  50. package/core/early-hints.d.ts +6 -0
  51. package/core/early-hints.js +2 -0
  52. package/core/early-hints.js.map +1 -0
  53. package/core/handler.d.ts +30 -0
  54. package/core/handler.js +2 -0
  55. package/core/handler.js.map +1 -0
  56. package/core/head-response.d.ts +5 -0
  57. package/core/head-response.js +2 -0
  58. package/core/head-response.js.map +1 -0
  59. package/core/headers.d.ts +13 -0
  60. package/core/headers.js +2 -0
  61. package/core/headers.js.map +1 -0
  62. package/core/render.d.ts +101 -0
  63. package/core/render.js +2 -0
  64. package/core/render.js.map +1 -0
  65. package/core/transform-html.d.ts +7 -0
  66. package/core/transform-html.js +2 -0
  67. package/core/transform-html.js.map +1 -0
  68. package/core/types.d.ts +8 -0
  69. package/core/types.js +2 -0
  70. package/core/types.js.map +1 -0
  71. package/edge/render-to-stream.d.ts +6 -0
  72. package/edge/render-to-stream.js +2 -0
  73. package/edge/render-to-stream.js.map +1 -0
  74. package/helpers/build-custom-state.d.ts +1 -2
  75. package/helpers/build-custom-state.js +1 -1
  76. package/helpers/build-custom-state.js.map +1 -1
  77. package/helpers/obtain-stream-error.js +1 -1
  78. package/helpers/obtain-stream-error.js.map +1 -1
  79. package/interfaces/fc-route.d.ts +1 -1
  80. package/interfaces/fc-route.js.map +1 -1
  81. package/node/compress-response.d.ts +6 -0
  82. package/node/compress-response.js +2 -0
  83. package/node/compress-response.js.map +1 -0
  84. package/node/create-headers.d.ts +6 -0
  85. package/node/create-headers.js +2 -0
  86. package/node/create-headers.js.map +1 -0
  87. package/node/create-request.d.ts +13 -0
  88. package/node/create-request.js +2 -0
  89. package/node/create-request.js.map +1 -0
  90. package/node/http.d.ts +6 -0
  91. package/node/http.js +2 -0
  92. package/node/http.js.map +1 -0
  93. package/node/render-to-stream.d.ts +6 -0
  94. package/node/render-to-stream.js +2 -0
  95. package/node/render-to-stream.js.map +1 -0
  96. package/node/request-signal.d.ts +10 -0
  97. package/node/request-signal.js +2 -0
  98. package/node/request-signal.js.map +1 -0
  99. package/node/split-link-header.d.ts +5 -0
  100. package/node/split-link-header.js +2 -0
  101. package/node/split-link-header.js.map +1 -0
  102. package/node/write-early-hints.d.ts +6 -0
  103. package/node/write-early-hints.js +2 -0
  104. package/node/write-early-hints.js.map +1 -0
  105. package/node/write-fetch-response.d.ts +10 -0
  106. package/node/write-fetch-response.js +2 -0
  107. package/node/write-fetch-response.js.map +1 -0
  108. package/package.json +45 -3
  109. package/services/server-config.d.ts +3 -4
  110. package/services/server-config.js.map +1 -1
  111. package/services/ssr-manifest.d.ts +25 -8
  112. package/services/ssr-manifest.js +1 -1
  113. package/services/ssr-manifest.js.map +1 -1
  114. package/helpers/handle-response.d.ts +0 -7
  115. package/helpers/handle-response.js +0 -2
  116. package/helpers/handle-response.js.map +0 -1
  117. package/node/create-fetch-request.d.ts +0 -7
  118. package/node/create-fetch-request.js +0 -2
  119. package/node/create-fetch-request.js.map +0 -1
  120. package/node/entry.js.map +0 -1
  121. package/node/render.js +0 -2
  122. package/node/render.js.map +0 -1
  123. package/node/server.js +0 -2
  124. package/node/server.js.map +0 -1
  125. package/node/write-response.d.ts +0 -14
  126. package/node/write-response.js +0 -2
  127. package/node/write-response.js.map +0 -1
  128. package/services/prepare-server.js +0 -2
  129. package/services/prepare-server.js.map +0 -1
  130. /package/{node → adapters/express}/entry.js +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"render.js","sources":["../../src/node/render.tsx"],"sourcesContent":["import chalk from 'chalk';\nimport type { Request, Response as ExpressResponse } from 'express';\nimport React from 'react';\nimport { renderToPipeableStream } from 'react-dom/server';\nimport type { StaticHandlerContext, StaticHandler } from 'react-router';\nimport { createStaticRouter, StaticRouterProvider } from 'react-router';\nimport StreamError from '@constants/stream-error';\nimport type { IServerContext } from '@context/server';\nimport { ServerProvider } from '@context/server';\nimport handleResponse from '@helpers/handle-response';\nimport type { IObtainStreamErrorOut } from '@helpers/obtain-stream-error';\nimport obtainStreamError from '@helpers/obtain-stream-error';\nimport createFetchRequest from '@node/create-fetch-request';\nimport type { TApp } from '@node/entry';\nimport writeResponse from '@node/write-response';\nimport type ServerConfig from '@services/server-config';\nimport SsrManifest from '@services/ssr-manifest';\n\nexport interface IRequestContext<TAppProps = Record<any, any>> {\n req: Request;\n res: ExpressResponse;\n appProps: NonNullable<TAppProps>;\n html: { header: string; footer: string };\n routerContext?: StaticHandlerContext;\n serverContext?: IServerContext;\n isStream?: boolean;\n hasEarlyHints?: boolean;\n didError?: StreamError;\n}\n\nexport type TRender<TAppProps = Record<any, any>> = (\n config: ServerConfig,\n context: IRequestContext<TAppProps>,\n options: IRenderOptions,\n) => Promise<void>;\n\nexport interface IRenderParams<TAppProps = Record<string, any>> {\n App: TApp<TAppProps>;\n handler: StaticHandler;\n}\n\nexport interface IRenderOptions<TAppProps = Record<string, any>> {\n abortDelay?: number;\n onRouterReady?: (params: {\n context: IRequestContext<TAppProps>;\n }) => Promise<IRouterReadyOut> | IRouterReadyOut;\n onShellReady?: (params: { context: IRequestContext<TAppProps> }) => IShellReadyOut;\n onShellError?: (params: {\n context: IRequestContext<TAppProps>;\n error: Error;\n }) => string | undefined | void; // return html or undefined\n onError?: (params: { context: IRequestContext<TAppProps>; error: IObtainStreamErrorOut }) => void;\n onResponse?: (params: {\n context: IRequestContext<TAppProps>;\n html: string;\n }) => string | undefined | void;\n getState?: (params: {\n context: IRequestContext<TAppProps>;\n }) => Record<string, Record<string, any>> | undefined | void;\n}\n\nexport interface IRouterReadyOut {\n isStream?: boolean;\n}\n\nexport interface IShellReadyOut {\n header?: string;\n footer?: string;\n}\n\n/**\n * Render application\n */\nasync function render(\n { App, handler }: IRenderParams, // @see entry (bind)\n config: ServerConfig,\n context: IRequestContext,\n {\n onRouterReady,\n onShellReady,\n onResponse,\n onShellError,\n onError,\n getState,\n abortDelay = 15000,\n }: IRenderOptions,\n): Promise<void> {\n const { req, res } = context;\n const fetchRequest = createFetchRequest(req);\n\n context.routerContext = (await handler.query(fetchRequest, {\n requestContext: context,\n })) as StaticHandlerContext;\n\n /**\n * Handle response from page loader, router context can be Response\n */\n const statusCode = handleResponse(res, context.routerContext);\n\n if (!statusCode) {\n return;\n }\n\n SsrManifest.get(config).injectAssets(context);\n\n const { isStream = true } = (await onRouterReady?.({ context })) ?? {};\n\n context.isStream = isStream;\n context.serverContext = {\n response: null,\n isServer: true,\n basename: context.routerContext?.basename,\n };\n\n const router = createStaticRouter(handler.dataRoutes, context.routerContext);\n const write = res.write.bind(res) as (...args: unknown[]) => boolean;\n const Logger = config.getLogger();\n let abortTimer: NodeJS.Timeout | undefined = undefined;\n\n /**\n * Listen response and stream to add possibility modify html on fly\n * E.g. listen stream and append some data\n */\n res.write = (data: string | Uint8Array, ...args): boolean => {\n const isString = typeof data === 'string';\n const html = isString ? data : Buffer.from(data).toString();\n const modifiedHtml = onResponse?.({ context, html });\n\n if (modifiedHtml) {\n return write(isString ? modifiedHtml : Buffer.from(modifiedHtml), ...args);\n }\n\n return write(data, ...args);\n };\n\n const { serverContext, routerContext, appProps } = context;\n\n const { pipe, abort } = renderToPipeableStream(\n <ServerProvider context={serverContext}>\n <App server={{ ...appProps, req }}>\n <StaticRouterProvider router={router} context={routerContext} hydrate={false} />\n </App>\n </ServerProvider>,\n {\n onShellReady(): void {\n if (!isStream) {\n return;\n }\n\n writeResponse(context, {\n pipe,\n statusCode,\n onShellReady,\n getState,\n });\n },\n onAllReady(): void {\n clearTimeout(abortTimer);\n\n if (isStream) {\n return;\n }\n\n writeResponse(context, {\n pipe,\n statusCode,\n onShellReady,\n getState,\n });\n },\n onShellError(e: Error): void {\n const htmlError =\n onShellError?.({ context, error: e }) ||\n `<!doctype html><p>Something went wrong: ${e.message}</p>`;\n\n res.status(500);\n res.setHeader('content-type', 'text/html');\n res.send(htmlError);\n },\n onError(err): void {\n clearTimeout(abortTimer);\n\n const error = obtainStreamError(err);\n const { code, message } = error;\n const { didError } = context;\n\n context.didError = didError ?? code;\n\n onError?.({ context, error });\n Logger.info(chalk.red(`Stream error. Code: ${code}`));\n\n if (\n [StreamError.RenderAborted, StreamError.RenderTimeout, StreamError.RenderCancel].includes(\n code,\n )\n ) {\n Logger.info(chalk.dim(message));\n\n return;\n }\n\n Logger.error(err as string);\n },\n },\n );\n\n // Abandon and switch to client rendering if enough time passes.\n abortTimer = setTimeout(() => {\n context.didError = StreamError.RenderTimeout;\n abort();\n }, abortDelay);\n\n // Detect cancel request\n req.on('close', () => {\n context.didError = StreamError.RenderCancel;\n abort();\n });\n}\n\nexport default render;\n"],"names":["async","render","App","handler","config","context","onRouterReady","onShellReady","onResponse","onShellError","onError","getState","abortDelay","req","res","fetchRequest","createFetchRequest","routerContext","query","requestContext","statusCode","handleResponse","SsrManifest","get","injectAssets","isStream","serverContext","response","isServer","basename","router","createStaticRouter","dataRoutes","write","bind","Logger","getLogger","abortTimer","data","args","isString","html","Buffer","from","toString","modifiedHtml","appProps","pipe","abort","renderToPipeableStream","React","createElement","ServerProvider","server","StaticRouterProvider","hydrate","writeResponse","onAllReady","clearTimeout","e","htmlError","error","message","status","setHeader","send","err","obtainStreamError","code","didError","info","chalk","red","StreamError","RenderAborted","RenderTimeout","RenderCancel","includes","dim","setTimeout","on"],"mappings":"ueAyEAA,eAAeC,GACbC,IAAEA,EAAGC,QAAEA,GACPC,EACAC,GACAC,cACEA,EAAaC,aACbA,EAAYC,WACZA,EAAUC,aACVA,EAAYC,QACZA,EAAOC,SACPA,EAAQC,WACRA,EAAa,OAGf,MAAMC,IAAEA,EAAGC,IAAEA,GAAQT,EACfU,EAAeC,EAAmBH,GAExCR,EAAQY,oBAAuBd,EAAQe,MAAMH,EAAc,CACzDI,eAAgBd,IAMlB,MAAMe,EAAaC,EAAeP,EAAKT,EAAQY,eAE/C,IAAKG,EACH,OAGFE,EAAYC,IAAInB,GAAQoB,aAAanB,GAErC,MAAMoB,SAAEA,GAAW,SAAgBnB,IAAgB,CAAED,cAAe,CAAA,EAEpEA,EAAQoB,SAAWA,EACnBpB,EAAQqB,cAAgB,CACtBC,SAAU,KACVC,UAAU,EACVC,SAAUxB,EAAQY,eAAeY,UAGnC,MAAMC,EAASC,EAAmB5B,EAAQ6B,WAAY3B,EAAQY,eACxDgB,EAAQnB,EAAImB,MAAMC,KAAKpB,GACvBqB,EAAS/B,EAAOgC,YACtB,IAAIC,EAMJvB,EAAImB,MAAQ,CAACK,KAA8BC,KACzC,MAAMC,EAA2B,iBAATF,EAClBG,EAAOD,EAAWF,EAAOI,OAAOC,KAAKL,GAAMM,WAC3CC,EAAerC,IAAa,CAAEH,UAASoC,SAE7C,OAAII,EACKZ,EAAMO,EAAWK,EAAeH,OAAOC,KAAKE,MAAkBN,GAGhEN,EAAMK,KAASC,EAAK,EAG7B,MAAMb,cAAEA,EAAaT,cAAEA,EAAa6B,SAAEA,GAAazC,GAE7C0C,KAAEA,EAAIC,MAAEA,GAAUC,EACtBC,EAAAC,cAACC,EAAc,CAAC/C,QAASqB,GACvBwB,EAAAC,cAACjD,GAAImD,OAAQ,IAAKP,EAAUjC,QAC1BqC,EAAAC,cAACG,EAAoB,CAACxB,OAAQA,EAAQzB,QAASY,EAAesC,SAAS,MAG3E,CACEhD,eACOkB,GAIL+B,EAAcnD,EAAS,CACrB0C,OACA3B,aACAb,eACAI,YAEJ,EACA8C,aACEC,aAAarB,GAETZ,GAIJ+B,EAAcnD,EAAS,CACrB0C,OACA3B,aACAb,eACAI,YAEJ,EACAF,aAAakD,GACX,MAAMC,EACJnD,IAAe,CAAEJ,UAASwD,MAAOF,KACjC,2CAA2CA,EAAEG,cAE/ChD,EAAIiD,OAAO,KACXjD,EAAIkD,UAAU,eAAgB,aAC9BlD,EAAImD,KAAKL,EACX,EACAlD,QAAQwD,GACNR,aAAarB,GAEb,MAAMwB,EAAQM,EAAkBD,IAC1BE,KAAEA,EAAIN,QAAEA,GAAYD,GACpBQ,SAAEA,GAAahE,EAErBA,EAAQgE,SAAWA,GAAYD,EAE/B1D,IAAU,CAAEL,UAASwD,UACrB1B,EAAOmC,KAAKC,EAAMC,IAAI,uBAAuBJ,MAG3C,CAACK,EAAYC,cAAeD,EAAYE,cAAeF,EAAYG,cAAcC,SAC/ET,GAGFjC,EAAOmC,KAAKC,EAAMO,IAAIhB,IAKxB3B,EAAO0B,MAAMK,EACf,IAKJ7B,EAAa0C,YAAW,KACtB1E,EAAQgE,SAAWI,EAAYE,cAC/B3B,GAAO,GACNpC,GAGHC,EAAImE,GAAG,SAAS,KACd3E,EAAQgE,SAAWI,EAAYG,aAC/B5B,GAAO,GAEX"}
package/node/server.js DELETED
@@ -1,2 +0,0 @@
1
- import e from"node:http";import r from"node:https";import t from"path";import s from"compression";import o from"express";import i from"../helpers/print-server-info.js";import a from"../services/prepare-server.js";import n from"../services/server-api.js";async function p(p){const c=o().disable("x-powered-by"),d=new n;p.setApp(c);const m=a.init(p,d);if(!p.isProd){const e=await(await import("vite")).createServer({server:{middlewareMode:!0,watch:{usePolling:!0,interval:100}},appType:"custom",mode:p.mode});c.use(e.middlewares),p.setVite(e)}const{isSPA:l}=p.getParams();if(l||await m.onAppCreated(),p.isProd){const{root:e,publicDir:r}=p.getParams(),{compression:i,expressStatic:a}=m.getMiddlewaresConfig();if(i&&c.use(s(i)),l||c.use(((e,r,t)=>{"/index.html"!==e.url||d.hasAccessIndexHtml()||(e.url="/index-not-found.html"),t()})),a){const{basename:s,...i}=a;c.use(s,o.static(t.resolve(`${e}/${r}`),{...i,index:!!l&&void 0}))}}return l?c.use(/(.*)/,((e,r,t)=>{(async()=>{try{const t=(await m.loadHtml(e)).join("");r.send(t)}catch(e){p.getLogger().error(`Failed to handle request: ${e?.message}`,{error:e}),t()}})()})):c.use(/(.*)/,((e,r,t)=>{(async()=>{try{const[{render:s,onRequest:o,...i},a]=await Promise.all([m.loadEntrypoint(),m.loadHtml(e)]),{appProps:n,hasEarlyHints:c,shouldSkip:d,shouldCancel:l}=await(o?.(e,r))??{},[u,f]=a;if(l)return;if(d)return t();const h={req:e,res:r,hasEarlyHints:c,appProps:n??{},html:{header:u,footer:f}};await s(p,h,i)}catch(e){p.getLogger().error(`Failed to handle request: ${e?.message}`,{error:e}),t()}})()})),{run:({version:t,isPrintInfo:s=!0}={})=>{const{port:o,host:a}=p.getParams(),n=Boolean(p.getVite()?.config?.server?.https);p.isHost&&!p.isProd&&(p.getVite().config.server.host=a);const l=(n?r.createServer(p.getVite().config.server.https,c):e.createServer(c)).listen(o,a,(()=>{m.onServerStarted?.(c,d,l),s&&i(p,{version:t,server:l})}));return l},app:c}}export{p as default};
2
- //# sourceMappingURL=server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.js","sources":["../../src/node/server.ts"],"sourcesContent":["import http from 'node:http';\nimport https from 'node:https';\nimport type { Server } from 'node:net';\nimport path from 'path';\nimport compression from 'compression';\nimport type { Express } from 'express';\nimport express from 'express';\nimport printServerInfo from '@helpers/print-server-info';\nimport type { IRequestContext } from '@node/render';\nimport PrepareServer from '@services/prepare-server';\nimport ServerApi from '@services/server-api';\nimport type ServerConfig from '@services/server-config';\n\nexport interface ICreateServerOut {\n run: (options?: { version?: string; isPrintInfo?: boolean }) => Server;\n app: Express;\n}\n\n/**\n * Create SSR server\n */\nasync function createServer(config: ServerConfig): Promise<ICreateServerOut> {\n const app = express().disable('x-powered-by');\n const serverApi = new ServerApi();\n\n config.setApp(app);\n\n const prepareServer = PrepareServer.init(config, serverApi);\n\n if (!config.isProd) {\n // Create Vite server in middleware mode and configure the app type as\n // 'custom', disabling Vite's own HTML serving logic so parent server\n // can take control\n const vite = await (\n await import('vite')\n ).createServer({\n server: {\n middlewareMode: true,\n watch: {\n // During tests, we edit the files too fast and sometimes chokidar\n // misses change events, so enforce polling for consistency\n usePolling: true,\n interval: 100,\n },\n },\n appType: 'custom',\n mode: config.mode,\n });\n\n // Use vite's connect instance as middleware\n app.use(vite.middlewares);\n\n config.setVite(vite);\n }\n\n const { isSPA } = config.getParams();\n\n if (!isSPA) {\n await prepareServer.onAppCreated();\n }\n\n if (config.isProd) {\n const { root, publicDir } = config.getParams();\n const { compression: compressionConfig, expressStatic } = prepareServer.getMiddlewaresConfig();\n\n if (compressionConfig) {\n app.use(compression(compressionConfig));\n }\n\n if (!isSPA) {\n // ignore index.html file in SSR mode\n app.use((req, _, next) => {\n if (req.url === '/index.html' && !serverApi.hasAccessIndexHtml()) {\n req.url = '/index-not-found.html';\n }\n\n next();\n });\n }\n\n if (expressStatic) {\n const { basename, ...expressStaticOpts } = expressStatic;\n\n app.use(\n basename!,\n express.static(path.resolve(`${root}/${publicDir}`), {\n ...expressStaticOpts,\n index: isSPA ? undefined : false,\n }),\n );\n }\n }\n\n // SSR mode\n if (!isSPA) {\n app.use(/(.*)/, (req, res, next) => {\n void (async () => {\n try {\n const [{ render, onRequest, ...renderParams }, clientHtml] = await Promise.all([\n prepareServer.loadEntrypoint(),\n prepareServer.loadHtml(req),\n ]);\n const { appProps, hasEarlyHints, shouldSkip, shouldCancel } =\n (await onRequest?.(req, res)) ?? {};\n const [header, footer] = clientHtml;\n\n if (shouldCancel) {\n return;\n }\n\n if (shouldSkip) {\n return next();\n }\n\n const context: IRequestContext = {\n req,\n res,\n hasEarlyHints,\n appProps: appProps ?? {},\n html: { header, footer },\n };\n\n await render(config, context, renderParams);\n } catch (e) {\n config\n .getLogger()\n .error(`Failed to handle request: ${(e as Error)?.message}`, { error: e as Error });\n next();\n }\n })();\n });\n } else {\n // SPA mode, redirect any request to index.html\n app.use(/(.*)/, (req, res, next) => {\n void (async () => {\n try {\n const html = (await prepareServer.loadHtml(req)).join('');\n\n res.send(html);\n } catch (e) {\n config\n .getLogger()\n .error(`Failed to handle request: ${(e as Error)?.message}`, { error: e as Error });\n next();\n }\n })();\n });\n }\n\n return {\n run: ({ version, isPrintInfo = true } = {}): Server => {\n const { port, host } = config.getParams();\n const isHTTPS = Boolean(config.getVite()?.config?.server?.https);\n\n // update resolved host for print network link\n if (config.isHost && !config.isProd) {\n config.getVite()!.config.server.host = host;\n }\n\n const server = (\n isHTTPS\n ? https.createServer(config.getVite()!.config.server.https!, app)\n : http.createServer(app)\n ).listen(port, host, () => {\n void prepareServer.onServerStarted?.(app, serverApi, server);\n\n if (!isPrintInfo) {\n return;\n }\n\n void printServerInfo(config, { version, server });\n });\n\n return server;\n },\n app,\n };\n}\n\nexport default createServer;\n"],"names":["async","createServer","config","app","express","disable","serverApi","ServerApi","setApp","prepareServer","PrepareServer","init","isProd","vite","import","server","middlewareMode","watch","usePolling","interval","appType","mode","use","middlewares","setVite","isSPA","getParams","onAppCreated","root","publicDir","compression","compressionConfig","expressStatic","getMiddlewaresConfig","req","_","next","url","hasAccessIndexHtml","basename","expressStaticOpts","static","path","resolve","index","undefined","res","html","loadHtml","join","send","e","getLogger","error","message","render","onRequest","renderParams","clientHtml","Promise","all","loadEntrypoint","appProps","hasEarlyHints","shouldSkip","shouldCancel","header","footer","context","run","version","isPrintInfo","port","host","isHTTPS","Boolean","getVite","https","isHost","http","listen","onServerStarted","printServerInfo"],"mappings":"8PAqBAA,eAAeC,EAAaC,GAC1B,MAAMC,EAAMC,IAAUC,QAAQ,gBACxBC,EAAY,IAAIC,EAEtBL,EAAOM,OAAOL,GAEd,MAAMM,EAAgBC,EAAcC,KAAKT,EAAQI,GAEjD,IAAKJ,EAAOU,OAAQ,CAIlB,MAAMC,cACEC,OAAO,SACbb,aAAa,CACbc,OAAQ,CACNC,gBAAgB,EAChBC,MAAO,CAGLC,YAAY,EACZC,SAAU,MAGdC,QAAS,SACTC,KAAMnB,EAAOmB,OAIflB,EAAImB,IAAIT,EAAKU,aAEbrB,EAAOsB,QAAQX,EACjB,CAEA,MAAMY,MAAEA,GAAUvB,EAAOwB,YAMzB,GAJKD,SACGhB,EAAckB,eAGlBzB,EAAOU,OAAQ,CACjB,MAAMgB,KAAEA,EAAIC,UAAEA,GAAc3B,EAAOwB,aAC3BI,YAAaC,EAAiBC,cAAEA,GAAkBvB,EAAcwB,uBAiBxE,GAfIF,GACF5B,EAAImB,IAAIQ,EAAYC,IAGjBN,GAEHtB,EAAImB,KAAI,CAACY,EAAKC,EAAGC,KACC,gBAAZF,EAAIG,KAA0B/B,EAAUgC,uBAC1CJ,EAAIG,IAAM,yBAGZD,GAAM,IAINJ,EAAe,CACjB,MAAMO,SAAEA,KAAaC,GAAsBR,EAE3C7B,EAAImB,IACFiB,EACAnC,EAAQqC,OAAOC,EAAKC,QAAQ,GAAGf,KAAQC,KAAc,IAChDW,EACHI,QAAOnB,QAAQoB,IAGrB,CACF,CA0DA,OAvDKpB,EAuCHtB,EAAImB,IAAI,QAAQ,CAACY,EAAKY,EAAKV,KACpB,WACH,IACE,MAAMW,SAActC,EAAcuC,SAASd,IAAMe,KAAK,IAEtDH,EAAII,KAAKH,EACX,CAAE,MAAOI,GACPjD,EACGkD,YACAC,MAAM,6BAA8BF,GAAaG,UAAW,CAAED,MAAOF,IACxEf,GACF,CACD,EAXI,EAWD,IAlDNjC,EAAImB,IAAI,QAAQ,CAACY,EAAKY,EAAKV,KACpB,WACH,IACE,OAAOmB,OAAEA,EAAMC,UAAEA,KAAcC,GAAgBC,SAAoBC,QAAQC,IAAI,CAC7EnD,EAAcoD,iBACdpD,EAAcuC,SAASd,MAEnB4B,SAAEA,EAAQC,cAAEA,EAAaC,WAAEA,EAAUC,aAAEA,SACpCT,IAAYtB,EAAKY,KAAS,CAAA,GAC5BoB,EAAQC,GAAUT,EAEzB,GAAIO,EACF,OAGF,GAAID,EACF,OAAO5B,IAGT,MAAMgC,EAA2B,CAC/BlC,MACAY,MACAiB,gBACAD,SAAUA,GAAY,CAAA,EACtBf,KAAM,CAAEmB,SAAQC,iBAGZZ,EAAOrD,EAAQkE,EAASX,EAChC,CAAE,MAAON,GACPjD,EACGkD,YACAC,MAAM,6BAA8BF,GAAaG,UAAW,CAAED,MAAOF,IACxEf,GACF,CACD,EAjCI,EAiCD,IAoBD,CACLiC,IAAK,EAAGC,UAASC,eAAc,GAAS,CAAA,KACtC,MAAMC,KAAEA,EAAIC,KAAEA,GAASvE,EAAOwB,YACxBgD,EAAUC,QAAQzE,EAAO0E,WAAW1E,QAAQa,QAAQ8D,OAGtD3E,EAAO4E,SAAW5E,EAAOU,SAC3BV,EAAO0E,UAAW1E,OAAOa,OAAO0D,KAAOA,GAGzC,MAAM1D,GACJ2D,EACIG,EAAM5E,aAAaC,EAAO0E,UAAW1E,OAAOa,OAAO8D,MAAQ1E,GAC3D4E,EAAK9E,aAAaE,IACtB6E,OAAOR,EAAMC,GAAM,KACdhE,EAAcwE,kBAAkB9E,EAAKG,EAAWS,GAEhDwD,GAIAW,EAAgBhF,EAAQ,CAAEoE,UAASvD,UAAS,IAGnD,OAAOA,CAAM,EAEfZ,MAEJ"}
@@ -1,14 +0,0 @@
1
- /// <reference types="react-dom" />
2
- import { PipeableStream } from 'react-dom/server';
3
- import { IRenderOptions, IRequestContext } from "./render.js";
4
- interface IWriteResponseParams {
5
- pipe: PipeableStream['pipe'];
6
- onShellReady: IRenderOptions['onShellReady'];
7
- getState: IRenderOptions['getState'];
8
- statusCode?: number;
9
- }
10
- /**
11
- * Send response to client
12
- */
13
- declare const writeResponse: (context: IRequestContext, params: IWriteResponseParams) => void;
14
- export { writeResponse as default };
@@ -1,2 +0,0 @@
1
- import e from"../helpers/build-custom-state.js";import t from"../helpers/build-router-state.js";import r from"../helpers/handle-response.js";const o=(o,s)=>{const{res:n,didError:d,serverContext:i,routerContext:a,html:l}=o,{pipe:p,onShellReady:f,getState:h}=s;let{statusCode:m}=s;if(m=r(n,i.response,m),!m)return;if(d){const e=n.end.bind(n);n.end=(...t)=>(n.write(c||l.footer),e(...t))}n.status(m),n.setHeader("content-type","text/html");const{header:u,footer:c}=f?.({context:o})??{},x=t(a),b=e(h?.({context:o}));l.footer=x+b+l.footer,n.write(u||l.header),p(n),d||n.write(c||l.footer)};export{o as default};
2
- //# sourceMappingURL=write-response.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"write-response.js","sources":["../../src/node/write-response.ts"],"sourcesContent":["import type { Response as ExpressResponse } from 'express';\nimport type { PipeableStream } from 'react-dom/server';\nimport buildCustomState from '@helpers/build-custom-state';\nimport buildRouterState from '@helpers/build-router-state';\nimport handleResponse from '@helpers/handle-response';\nimport type { IRenderOptions, IRequestContext } from '@node/render';\n\ninterface IWriteResponseParams {\n pipe: PipeableStream['pipe'];\n onShellReady: IRenderOptions['onShellReady'];\n getState: IRenderOptions['getState'];\n statusCode?: number; // default status\n}\n\n/**\n * Send response to client\n */\nconst writeResponse = (context: IRequestContext, params: IWriteResponseParams): void => {\n const { res, didError, serverContext, routerContext, html } = context;\n const { pipe, onShellReady, getState } = params;\n let { statusCode } = params;\n\n // handle response from server components (navigate, status)\n statusCode = handleResponse(res, serverContext!.response, statusCode);\n\n if (!statusCode) {\n return;\n }\n\n // catch close connection from React and write footer\n if (didError) {\n const end = res.end.bind(res) as ExpressResponse['end'];\n\n res.end = (...args: unknown[]): ExpressResponse => {\n // send second part of app shell\n res.write(modifiedFooter || html.footer);\n\n // @ts-ignore\n return end(...args);\n };\n }\n\n res.status(statusCode);\n res.setHeader('content-type', 'text/html');\n\n const { header: modifiedHeader, footer: modifiedFooter } = onShellReady?.({ context }) ?? {};\n const routerState = buildRouterState(routerContext!);\n const customState = buildCustomState(getState?.({ context }));\n\n html.footer = routerState + customState + html.footer;\n\n // send first part of app shell\n res.write(modifiedHeader || html.header);\n // start streaming app\n pipe(res);\n\n if (!didError) {\n // send second part of app shell\n res.write(modifiedFooter || html.footer);\n }\n};\n\nexport default writeResponse;\n"],"names":["writeResponse","context","params","res","didError","serverContext","routerContext","html","pipe","onShellReady","getState","statusCode","handleResponse","response","end","bind","args","write","modifiedFooter","footer","status","setHeader","header","modifiedHeader","routerState","buildRouterState","customState","buildCustomState"],"mappings":"6IAiBA,MAAMA,EAAgB,CAACC,EAA0BC,KAC/C,MAAMC,IAAEA,EAAGC,SAAEA,EAAQC,cAAEA,EAAaC,cAAEA,EAAaC,KAAEA,GAASN,GACxDO,KAAEA,EAAIC,aAAEA,EAAYC,SAAEA,GAAaR,EACzC,IAAIS,WAAEA,GAAeT,EAKrB,GAFAS,EAAaC,EAAeT,EAAKE,EAAeQ,SAAUF,IAErDA,EACH,OAIF,GAAIP,EAAU,CACZ,MAAMU,EAAMX,EAAIW,IAAIC,KAAKZ,GAEzBA,EAAIW,IAAM,IAAIE,KAEZb,EAAIc,MAAMC,GAAkBX,EAAKY,QAG1BL,KAAOE,GAElB,CAEAb,EAAIiB,OAAOT,GACXR,EAAIkB,UAAU,eAAgB,aAE9B,MAAQC,OAAQC,EAAgBJ,OAAQD,GAAmBT,IAAe,CAAER,aAAc,CAAA,EACpFuB,EAAcC,EAAiBnB,GAC/BoB,EAAcC,EAAiBjB,IAAW,CAAET,aAElDM,EAAKY,OAASK,EAAcE,EAAcnB,EAAKY,OAG/ChB,EAAIc,MAAMM,GAAkBhB,EAAKe,QAEjCd,EAAKL,GAEAC,GAEHD,EAAIc,MAAMC,GAAkBX,EAAKY,OACnC"}
@@ -1,2 +0,0 @@
1
- import e from"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"./server-api.js";class n{config;serverApi;entrypoint;onServerCreated;onServerStarted;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(`<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};
2
- //# sourceMappingURL=prepare-server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prepare-server.js","sources":["../../src/services/prepare-server.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { pathToFileURL } from 'node:url';\nimport chalk from 'chalk';\nimport type { Request } from 'express';\nimport type { TRouteObject } from '@interfaces/route-object';\nimport type { IEntrypointOptions, IPrepareRenderOut } from '@node/entry';\nimport type { TRender } from '@node/render';\nimport ServerApi from '@services/server-api';\nimport type ServerConfig from '@services/server-config';\n\ninterface IPrepareServerEntrypointLoadOut<TAppProps = Record<string, any>> {\n render: TRender;\n routes: TRouteObject[];\n abortDelay?: number;\n onRequest?: IEntrypointOptions<TAppProps>['onRequest'];\n onRouterReady?: IEntrypointOptions<TAppProps>['onRouterReady'];\n onShellReady?: IEntrypointOptions<TAppProps>['onShellReady'];\n onShellError?: IEntrypointOptions<TAppProps>['onShellError'];\n onResponse?: IEntrypointOptions<TAppProps>['onResponse'];\n onError?: IEntrypointOptions<TAppProps>['onError'];\n getState?: IEntrypointOptions<TAppProps>['getState'];\n}\n\n/**\n * Load server entrypoint and template\n * DEV MODE: refresh entrypoint and template\n */\nclass PrepareServer {\n /**\n * Server configuration\n */\n protected readonly config: ServerConfig;\n\n /**\n * Server API\n */\n protected readonly serverApi: ServerApi;\n\n /**\n * Entrypoint resolved params\n */\n protected entrypoint?: IPrepareServerEntrypointLoadOut;\n\n /**\n * Hook which calls after express server created\n */\n protected onServerCreated?: IEntrypointOptions['onServerCreated'];\n\n /**\n * Hook which calls after express server started\n */\n public onServerStarted?: IEntrypointOptions['onServerStarted'];\n\n /**\n * Html shell\n */\n protected html: string;\n\n /**\n * Middlewares configs\n */\n protected middlewaresConfigs?: IPrepareRenderOut['middlewares'];\n\n /**\n * @constructor\n */\n protected constructor(config: ServerConfig, serverApi?: ServerApi) {\n this.config = config;\n this.serverApi = serverApi ?? new ServerApi();\n }\n\n /**\n * Init service\n */\n public static init(config: ServerConfig, serverApi?: ServerApi): PrepareServer {\n return new PrepareServer(config, serverApi);\n }\n\n /**\n * Resolve and return entrypoint params\n */\n public async loadEntrypoint(shouldInit = true): Promise<IPrepareServerEntrypointLoadOut> {\n // load server entrypoint each time only in development mode (for fast refresh)\n if (this.entrypoint && this.config.isProd) {\n return this.entrypoint;\n }\n\n const { root, isProd, serverFile } = this.config.getParams();\n const entrypointPath = path.resolve(`${root}/${serverFile}`);\n\n let resolvedEntrypoint: IPrepareRenderOut;\n\n try {\n if (!isProd) {\n resolvedEntrypoint = (\n await this.config.getVite()!.ssrLoadModule(entrypointPath, {\n fixStacktrace: true,\n })\n ).default as IPrepareRenderOut;\n } else {\n resolvedEntrypoint = (\n (await import(pathToFileURL(entrypointPath).toString())) as { default: IPrepareRenderOut }\n ).default;\n }\n } catch (e) {\n if (\n e instanceof Error &&\n e.message.includes('Cannot find module') &&\n e.message.includes('/build/')\n ) {\n this.config\n .getLogger()\n .error(\n chalk.red(\n `Before starting the server, you need to create a build: ${chalk.yellow(\n 'ssr-boost build',\n )} or provide path to build dir: ${chalk.yellow(\n 'ssr-boost start --build-dir build',\n )}`,\n ),\n );\n\n return process.exit(1);\n }\n\n throw e;\n }\n\n if (!shouldInit && resolvedEntrypoint.init) {\n delete resolvedEntrypoint.init;\n }\n\n const { render, init, routes, abortDelay, loggerProd, loggerDev, middlewares } =\n resolvedEntrypoint;\n\n this.middlewaresConfigs = middlewares;\n\n if (loggerProd && isProd) {\n this.config.setLogger(loggerProd);\n } else if (loggerDev && !isProd) {\n this.config.setLogger(loggerDev);\n }\n\n const { onServerCreated, onServerStarted, ...renderParams } =\n (await init?.({\n config: this.config,\n })) ?? {};\n\n this.entrypoint = {\n render,\n routes,\n abortDelay,\n ...renderParams,\n };\n this.onServerCreated = onServerCreated;\n this.onServerStarted = onServerStarted;\n\n return this.entrypoint;\n }\n\n /**\n * Load and return html shell\n */\n public async loadHtml(req: Request): Promise<[string, string]> {\n const { isProd, root, indexFile, clientFile } = this.config.getParams();\n\n if (!this.html || !isProd) {\n this.html = fs.readFileSync(path.resolve(`${root}/${indexFile}`), 'utf-8');\n }\n\n let modifiedHtml = this.html;\n\n if (!isProd) {\n const clientFileEntry = path.posix.normalize(\n `${this.config.getVite()?.config.base}/${clientFile}`,\n );\n\n // Apply Vite HTML transforms. This injects the Vite HMR client,\n // and also applies HTML transforms from Vite plugins, e.g. global\n // preambles from @vitejs/plugin-react\n modifiedHtml = (\n await this.config.getVite()!.transformIndexHtml(req.originalUrl, this.html, indexFile)\n )\n // remove 'async' attribute from app entrypoint for development\n // it might cause problems with preambles from @vitejs/plugin-react\n .replace(\n new RegExp(\n `<script[^>]*?\\\\bsrc=[\"']/?${clientFileEntry}([^\"']*)[\"'][^>]*?\\\\sasync\\\\b`,\n 'g',\n ),\n (match) => match.replace(/\\sasync\\b/, ''),\n );\n }\n\n return modifiedHtml.split('<!--ssr-outlet-->') as [string, string];\n }\n\n /**\n * Run server created hook\n */\n public async onAppCreated(): Promise<PrepareServer> {\n await this.loadEntrypoint();\n await this.onServerCreated?.(this.config.getApp()!, this.serverApi);\n\n return this;\n }\n\n /**\n * Return SSR express middlewares configs\n */\n public getMiddlewaresConfig(): NonNullable<PrepareServer['middlewaresConfigs']> {\n const { compression, expressStatic } = this.middlewaresConfigs ?? {};\n\n return {\n compression:\n compression !== false\n ? {\n ...(compression ?? {}),\n }\n : false,\n expressStatic:\n expressStatic !== false\n ? {\n ...(expressStatic ?? {}),\n basename: expressStatic?.basename ?? '/',\n }\n : false,\n };\n }\n}\n\nexport default PrepareServer;\n"],"names":["PrepareServer","config","serverApi","entrypoint","onServerCreated","onServerStarted","html","middlewaresConfigs","constructor","this","ServerApi","static","async","shouldInit","isProd","root","serverFile","getParams","entrypointPath","path","resolve","resolvedEntrypoint","import","pathToFileURL","toString","default","getVite","ssrLoadModule","fixStacktrace","e","Error","message","includes","getLogger","error","chalk","red","yellow","process","exit","init","render","routes","abortDelay","loggerProd","loggerDev","middlewares","setLogger","renderParams","req","indexFile","clientFile","fs","readFileSync","modifiedHtml","clientFileEntry","posix","normalize","base","transformIndexHtml","originalUrl","replace","RegExp","match","split","loadEntrypoint","getApp","getMiddlewaresConfig","compression","expressStatic","basename"],"mappings":"oKA6BA,MAAMA,EAIeC,OAKAC,UAKTC,WAKAC,gBAKHC,gBAKGC,KAKAC,mBAKVC,YAAsBP,EAAsBC,GAC1CO,KAAKR,OAASA,EACdQ,KAAKP,UAAYA,GAAa,IAAIQ,CACpC,CAKOC,YAAYV,EAAsBC,GACvC,OAAO,IAAIF,EAAcC,EAAQC,EACnC,CAKOU,qBAAqBC,GAAa,GAEvC,GAAIJ,KAAKN,YAAcM,KAAKR,OAAOa,OACjC,OAAOL,KAAKN,WAGd,MAAMY,KAAEA,EAAID,OAAEA,EAAME,WAAEA,GAAeP,KAAKR,OAAOgB,YAC3CC,EAAiBC,EAAKC,QAAQ,GAAGL,KAAQC,KAE/C,IAAIK,EAEJ,IAQIA,EAPGP,SAQMQ,OAAOC,EAAcL,GAAgBM,aAC5CC,eAPMhB,KAAKR,OAAOyB,UAAWC,cAAcT,EAAgB,CACzDU,eAAe,KAEjBH,OAMN,CAAE,MAAOI,GACP,GACEA,aAAaC,OACbD,EAAEE,QAAQC,SAAS,uBACnBH,EAAEE,QAAQC,SAAS,WAcnB,OAZAvB,KAAKR,OACFgC,YACAC,MACCC,EAAMC,IACJ,2DAA2DD,EAAME,OAC/D,oDACiCF,EAAME,OACvC,yCAKDC,EAAQC,KAAK,GAGtB,MAAMV,CACR,EAEKhB,GAAcQ,EAAmBmB,aAC7BnB,EAAmBmB,KAG5B,MAAMC,OAAEA,EAAMD,KAAEA,EAAIE,OAAEA,EAAMC,WAAEA,EAAUC,WAAEA,EAAUC,UAAEA,EAASC,YAAEA,GAC/DzB,EAEFZ,KAAKF,mBAAqBuC,EAEtBF,GAAc9B,EAChBL,KAAKR,OAAO8C,UAAUH,GACbC,IAAc/B,GACvBL,KAAKR,OAAO8C,UAAUF,GAGxB,MAAMzC,gBAAEA,EAAeC,gBAAEA,KAAoB2C,SACpCR,IAAO,CACZvC,OAAQQ,KAAKR,WACR,CAAA,EAWT,OATAQ,KAAKN,WAAa,CAChBsC,SACAC,SACAC,gBACGK,GAELvC,KAAKL,gBAAkBA,EACvBK,KAAKJ,gBAAkBA,EAEhBI,KAAKN,UACd,CAKOS,eAAeqC,GACpB,MAAMnC,OAAEA,EAAMC,KAAEA,EAAImC,UAAEA,EAASC,WAAEA,GAAe1C,KAAKR,OAAOgB,YAEvDR,KAAKH,MAASQ,IACjBL,KAAKH,KAAO8C,EAAGC,aAAalC,EAAKC,QAAQ,GAAGL,KAAQmC,KAAc,UAGpE,IAAII,EAAe7C,KAAKH,KAExB,IAAKQ,EAAQ,CACX,MAAMyC,EAAkBpC,EAAKqC,MAAMC,UACjC,GAAGhD,KAAKR,OAAOyB,WAAWzB,OAAOyD,QAAQP,KAM3CG,SACQ7C,KAAKR,OAAOyB,UAAWiC,mBAAmBV,EAAIW,YAAanD,KAAKH,KAAM4C,IAI3EW,QACC,IAAIC,OACF,6BAA6BP,iCAC7B,MAEDQ,GAAUA,EAAMF,QAAQ,YAAa,KAE5C,CAEA,OAAOP,EAAaU,MAAM,0BAC5B,CAKOpD,qBAIL,aAHMH,KAAKwD,uBACLxD,KAAKL,kBAAkBK,KAAKR,OAAOiE,SAAWzD,KAAKP,YAElDO,IACT,CAKO0D,uBACL,MAAMC,YAAEA,EAAWC,cAAEA,GAAkB5D,KAAKF,oBAAsB,CAAA,EAElE,MAAO,CACL6D,aACkB,IAAhBA,GACI,IACMA,GAAe,CAAA,GAG3BC,eACoB,IAAlBA,GACI,IACMA,GAAiB,CAAA,EACrBC,SAAUD,GAAeC,UAAY,KAIjD"}
File without changes