@lomray/vite-ssr-boost 1.0.0-beta.20 → 1.0.0-beta.22

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/cli/build.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  interface IBuildParams {
2
2
  isOnlyClient?: boolean;
3
3
  isWatch?: boolean;
4
+ isEject?: boolean;
4
5
  isUnlockRobots?: boolean;
5
6
  clientOptions?: string;
6
7
  serverOptions?: string;
@@ -10,5 +11,5 @@ interface IBuildParams {
10
11
  /**
11
12
  * Build production application
12
13
  */
13
- declare function build({ onFinish, isOnlyClient, isWatch, isUnlockRobots, clientOptions, serverOptions, mode, }: IBuildParams): Promise<void>;
14
+ declare function build({ onFinish, isOnlyClient, isWatch, isUnlockRobots, isEject, clientOptions, serverOptions, mode, }: IBuildParams): Promise<void>;
14
15
  export { build as default };
package/cli/build.js CHANGED
@@ -1,2 +1,2 @@
1
- import o from"node:child_process";import e from"node:fs";import t from"node:path";import{performance as s}from"node:perf_hooks";import r from"chalk";import{resolveConfig as i}from"vite";import n from"./vite-reset-cache.js";import l from"../constants/cli-name.js";import{createDevMarker as p}from"../helpers/dev-marker.js";import a from"../helpers/plugin-config.js";import c from"../helpers/unlock-robots.js";import d from"../services/ssr-manifest.js";const m=o=>{const e=new Promise(((e,t)=>{o.on("exit",(o=>{e(o)})),o.on("close",(o=>{e(o)})),o.on("error",(o=>{t(o)}))}));return o.stdout?.pipe(process.stdout),o.stderr?.pipe(process.stderr),e.command=o,e};async function u({onFinish:u,isOnlyClient:v=!1,isWatch:f=!1,isUnlockRobots:O=!1,clientOptions:S="",serverOptions:b="",mode:h=""}){const _=s.now(),$=await i({},"build",h,"production"===h?"production":"development"),g=a($),{outDir:w}=$.build,R=["client"],B=new AbortController,C=h?`--mode ${h}`:"",D=process.env.NODE_ENV||"development",j="production"===D,y=t.resolve($.root,w);await n(),e.existsSync(y)&&e.rmSync(y,{recursive:!0});const A=m(o.spawn(`vite build ${S} --emptyOutDir --outDir ${w}/client ${C}`,{signal:B.signal,stdio:[process.stdin,"pipe",process.stderr],shell:!0,env:{...process.env,FORCE_COLOR:"2",SSR_BOOST_IS_SSR:v?"0":"1",SSR_BOOST_ACTION:global.viteBoostAction}}));let E;if(f||await A,v||(E=m(o.spawn(`vite build ${b} --emptyOutDir --outDir ${w}/server --ssr ${g.serverFile} ${C}`,{signal:B.signal,stdio:[process.stdin,"pipe",process.stderr],shell:!0,env:{...process.env,FORCE_COLOR:"2",SSR_BOOST_IS_SSR:v?"0":"1",SSR_BOOST_ACTION:global.viteBoostAction}})),f||(await E,await d.get($.root,{alias:$.resolve.alias,buildDir:w}).buildRoutesManifest(g.preloadAssets)),R.push("server")),f){process.on("exit",(()=>{B.abort()}));let o=v?1:2;const e=t=>{Buffer.from(t).toString().includes("built in")&&(o-=1,o||(A.command.stdout.removeListener("data",e),E?.command.stdout.removeListener("data",e),p(j,$),u?.()))};return A.command.stdout.on("data",e),void E?.command.stdout.on("data",e)}O&&c($.root,w),p(j,$),u?.();const N=r.dim(`${r.yellowBright(R.join(","))} built in ${r.reset(r.bold(Math.ceil(s.now()-_)))} ms`);console.info(`\n ${r.green(`${r.bold(l.toUpperCase())}`)} ${N} ${j?"":r.redBright(`NODE_ENV=${D}`)}\n`)}export{u as default};
1
+ import o from"node:child_process";import{performance as e}from"node:perf_hooks";import t from"chalk";import i from"./vite-reset-cache.js";import s from"../constants/cli-name.js";import{createDevMarker as r}from"../helpers/dev-marker.js";import n from"../services/build.js";async function a({onFinish:a,isOnlyClient:l=!1,isWatch:d=!1,isUnlockRobots:c=!1,isEject:m=!1,clientOptions:p="",serverOptions:u="",mode:O=""}){const f=e.now(),v=new n({mode:O}),S=["client"],$=new AbortController,_=O?`--mode ${O}`:"";await v.makeConfig(),await i(),v.clearBuildFolder();const b=v.promisifyProcess(o.spawn(`vite build ${p} --emptyOutDir --outDir ${v.outDir}/client ${_}`,{signal:$.signal,stdio:[process.stdin,"pipe",process.stderr],shell:!0,env:{...process.env,FORCE_COLOR:"2",SSR_BOOST_IS_SSR:l?"0":"1",SSR_BOOST_ACTION:global.viteBoostAction}}));let g;if(d||await b,l||(g=v.promisifyProcess(o.spawn(`vite build ${u} --emptyOutDir --outDir ${v.outDir}/server --ssr ${v.serverFile} ${_}`,{signal:$.signal,stdio:[process.stdin,"pipe",process.stderr],shell:!0,env:{...process.env,FORCE_COLOR:"2",SSR_BOOST_IS_SSR:l?"0":"1",SSR_BOOST_ACTION:global.viteBoostAction}})),d||(await g,await v.buildManifest(),m&&v.eject()),S.push("server")),d){process.on("exit",(()=>{$.abort()}));let o=l?1:2;const e=t=>{Buffer.from(t).toString().includes("built in")&&(o-=1,o||(b.command.stdout.removeListener("data",e),g?.command.stdout.removeListener("data",e),r(v.isProd,v.viteConfig),a?.()))};return b.command.stdout.on("data",e),void g?.command.stdout.on("data",e)}c&&v.unlockRobots(),r(v.isProd,v.viteConfig),a?.();const h=t.dim(`${t.yellowBright(S.join(","))} built in ${t.reset(t.bold(Math.ceil(e.now()-f)))} ms`);console.info(`\n ${t.green(`${t.bold(s.toUpperCase())}`)} ${h} ${v.isProd?"":t.redBright(`NODE_ENV=${v.nodeEnv}`)}\n`)}export{a as default};
2
2
  //# sourceMappingURL=build.js.map
package/cli/build.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"build.js","sources":["../../src/cli/build.ts"],"sourcesContent":["import childProcess from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { performance } from 'node:perf_hooks';\nimport chalk from 'chalk';\nimport { resolveConfig } from 'vite';\nimport viteResetCache from '@cli/vite-reset-cache';\nimport cliName from '@constants/cli-name';\nimport { createDevMarker } from '@helpers/dev-marker';\nimport getPluginConfig from '@helpers/plugin-config';\nimport unlockRobots from '@helpers/unlock-robots';\nimport SsrManifest from '@services/ssr-manifest';\n\ninterface IBuildParams {\n isOnlyClient?: boolean;\n isWatch?: boolean;\n isUnlockRobots?: boolean;\n clientOptions?: string;\n serverOptions?: string;\n mode?: string;\n onFinish?: () => void;\n}\n\n/**\n * Promisify spawn process\n */\nconst promisify = (command: childProcess.ChildProcess) => {\n const promise = new Promise((resolve, reject) => {\n command.on('exit', (code) => {\n resolve(code);\n });\n\n command.on('close', (code) => {\n resolve(code);\n });\n\n command.on('error', (message) => {\n reject(message);\n });\n });\n\n command.stdout?.pipe(process.stdout);\n command.stderr?.pipe(process.stderr);\n\n promise['command'] = command;\n\n return promise;\n};\n\n/**\n * Build production application\n */\nasync function build({\n onFinish,\n isOnlyClient = false,\n isWatch = false,\n isUnlockRobots = false,\n clientOptions = '',\n serverOptions = '',\n mode = '',\n}: IBuildParams): Promise<void> {\n const perfStart = performance.now();\n const config = await resolveConfig(\n {},\n 'build',\n mode,\n mode === 'production' ? 'production' : 'development',\n );\n const pluginConfig = getPluginConfig(config);\n const { outDir } = config.build;\n const types = ['client'];\n const controller = new AbortController();\n const modeOpt = mode ? `--mode ${mode}` : '';\n const nodeEnv = process.env.NODE_ENV || 'development';\n const isProd = nodeEnv === 'production';\n const buildDir = path.resolve(config.root, outDir);\n\n // this is required step - build with different env may cause problems\n await viteResetCache();\n\n // clear build folder\n if (fs.existsSync(buildDir)) {\n fs.rmSync(buildDir, { recursive: true });\n }\n\n /**\n * Build client\n */\n const clientProcess = promisify(\n childProcess.spawn(\n `vite build ${clientOptions} --emptyOutDir --outDir ${outDir}/client ${modeOpt}`,\n {\n signal: controller.signal,\n stdio: [process.stdin, 'pipe', process.stderr],\n shell: true,\n env: {\n ...process.env,\n FORCE_COLOR: '2',\n SSR_BOOST_IS_SSR: isOnlyClient ? '0' : '1',\n SSR_BOOST_ACTION: global.viteBoostAction,\n },\n },\n ),\n );\n\n if (!isWatch) {\n await clientProcess;\n }\n\n let serverProcess: Promise<unknown> | undefined;\n\n /**\n * Build server\n */\n if (!isOnlyClient) {\n serverProcess = promisify(\n childProcess.spawn(\n `vite build ${serverOptions} --emptyOutDir --outDir ${outDir}/server --ssr ${pluginConfig.serverFile} ${modeOpt}`,\n {\n signal: controller.signal,\n stdio: [process.stdin, 'pipe', process.stderr],\n shell: true,\n env: {\n ...process.env,\n FORCE_COLOR: '2',\n SSR_BOOST_IS_SSR: isOnlyClient ? '0' : '1',\n SSR_BOOST_ACTION: global.viteBoostAction,\n },\n },\n ),\n );\n\n if (!isWatch) {\n await serverProcess;\n await SsrManifest.get(config.root, {\n alias: config.resolve.alias,\n buildDir: outDir,\n }).buildRoutesManifest(pluginConfig.preloadAssets);\n }\n\n types.push('server');\n }\n\n /**\n * Preview mode\n */\n if (isWatch) {\n process.on('exit', () => {\n controller.abort();\n });\n\n let buildCount = isOnlyClient ? 1 : 2;\n const listener = (buff: Uint8Array): void => {\n const msg = Buffer.from(buff).toString();\n\n if (msg.includes('built in')) {\n buildCount -= 1;\n\n if (!buildCount) {\n clientProcess['command'].stdout.removeListener('data', listener);\n serverProcess?.['command'].stdout.removeListener('data', listener);\n createDevMarker(isProd, config);\n onFinish?.();\n }\n }\n };\n\n /**\n * Listen output for call onFinish\n */\n clientProcess['command'].stdout.on('data', listener);\n serverProcess?.['command'].stdout.on('data', listener);\n\n return;\n }\n\n if (isUnlockRobots) {\n unlockRobots(config.root, outDir);\n }\n\n createDevMarker(isProd, config);\n onFinish?.();\n\n const buildDurationString = chalk.dim(\n `${chalk.yellowBright(types.join(','))} built in ${chalk.reset(\n chalk.bold(Math.ceil(performance.now() - perfStart)),\n )} ms`,\n );\n\n console.info(\n `\\n ${chalk.green(`${chalk.bold(cliName.toUpperCase())}`)} ${buildDurationString} ${\n isProd ? '' : chalk.redBright(`NODE_ENV=${nodeEnv}`)\n }\\n`,\n );\n}\n\nexport default build;\n"],"names":["promisify","command","promise","Promise","resolve","reject","on","code","message","stdout","pipe","process","stderr","async","build","onFinish","isOnlyClient","isWatch","isUnlockRobots","clientOptions","serverOptions","mode","perfStart","performance","now","config","resolveConfig","pluginConfig","getPluginConfig","outDir","types","controller","AbortController","modeOpt","nodeEnv","env","NODE_ENV","isProd","buildDir","path","root","viteResetCache","fs","existsSync","rmSync","recursive","clientProcess","childProcess","spawn","signal","stdio","stdin","shell","FORCE_COLOR","SSR_BOOST_IS_SSR","SSR_BOOST_ACTION","global","viteBoostAction","serverProcess","serverFile","SsrManifest","get","alias","buildRoutesManifest","preloadAssets","push","abort","buildCount","listener","buff","Buffer","from","toString","includes","removeListener","createDevMarker","unlockRobots","buildDurationString","chalk","dim","yellowBright","join","reset","bold","Math","ceil","console","info","green","cliName","toUpperCase","redBright"],"mappings":"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"}
1
+ {"version":3,"file":"build.js","sources":["../../src/cli/build.ts"],"sourcesContent":["import childProcess from 'node:child_process';\nimport { performance } from 'node:perf_hooks';\nimport chalk from 'chalk';\nimport viteResetCache from '@cli/vite-reset-cache';\nimport cliName from '@constants/cli-name';\nimport { createDevMarker } from '@helpers/dev-marker';\nimport Build from '@services/build';\n\ninterface IBuildParams {\n isOnlyClient?: boolean;\n isWatch?: boolean;\n isEject?: boolean;\n isUnlockRobots?: boolean;\n clientOptions?: string;\n serverOptions?: string;\n mode?: string;\n onFinish?: () => void;\n}\n\n/**\n * Build production application\n */\nasync function build({\n onFinish,\n isOnlyClient = false,\n isWatch = false,\n isUnlockRobots = false,\n isEject = false,\n clientOptions = '',\n serverOptions = '',\n mode = '',\n}: IBuildParams): Promise<void> {\n const perfStart = performance.now();\n const buildService = new Build({ mode });\n const types = ['client'];\n const controller = new AbortController();\n const modeOpt = mode ? `--mode ${mode}` : '';\n\n await buildService.makeConfig();\n\n // this is required step - build with different env may cause problems\n await viteResetCache();\n buildService.clearBuildFolder();\n\n /**\n * Build client\n */\n const clientProcess = buildService.promisifyProcess(\n childProcess.spawn(\n `vite build ${clientOptions} --emptyOutDir --outDir ${buildService.outDir}/client ${modeOpt}`,\n {\n signal: controller.signal,\n stdio: [process.stdin, 'pipe', process.stderr],\n shell: true,\n env: {\n ...process.env,\n FORCE_COLOR: '2',\n SSR_BOOST_IS_SSR: isOnlyClient ? '0' : '1',\n SSR_BOOST_ACTION: global.viteBoostAction,\n },\n },\n ),\n );\n\n if (!isWatch) {\n await clientProcess;\n }\n\n let serverProcess: Promise<unknown> | undefined;\n\n /**\n * Build server\n */\n if (!isOnlyClient) {\n serverProcess = buildService.promisifyProcess(\n childProcess.spawn(\n `vite build ${serverOptions} --emptyOutDir --outDir ${buildService.outDir}/server --ssr ${buildService.serverFile} ${modeOpt}`,\n {\n signal: controller.signal,\n stdio: [process.stdin, 'pipe', process.stderr],\n shell: true,\n env: {\n ...process.env,\n FORCE_COLOR: '2',\n SSR_BOOST_IS_SSR: isOnlyClient ? '0' : '1',\n SSR_BOOST_ACTION: global.viteBoostAction,\n },\n },\n ),\n );\n\n if (!isWatch) {\n await serverProcess;\n await buildService.buildManifest();\n\n if (isEject) {\n buildService.eject();\n }\n }\n\n types.push('server');\n }\n\n /**\n * Preview mode\n */\n if (isWatch) {\n process.on('exit', () => {\n controller.abort();\n });\n\n let buildCount = isOnlyClient ? 1 : 2;\n const listener = (buff: Uint8Array): void => {\n const msg = Buffer.from(buff).toString();\n\n if (msg.includes('built in')) {\n buildCount -= 1;\n\n if (!buildCount) {\n clientProcess['command'].stdout.removeListener('data', listener);\n serverProcess?.['command'].stdout.removeListener('data', listener);\n createDevMarker(buildService.isProd, buildService.viteConfig);\n onFinish?.();\n }\n }\n };\n\n /**\n * Listen output for call onFinish\n */\n clientProcess['command'].stdout.on('data', listener);\n serverProcess?.['command'].stdout.on('data', listener);\n\n return;\n }\n\n if (isUnlockRobots) {\n buildService.unlockRobots();\n }\n\n createDevMarker(buildService.isProd, buildService.viteConfig);\n onFinish?.();\n\n const buildDurationString = chalk.dim(\n `${chalk.yellowBright(types.join(','))} built in ${chalk.reset(\n chalk.bold(Math.ceil(performance.now() - perfStart)),\n )} ms`,\n );\n\n console.info(\n `\\n ${chalk.green(`${chalk.bold(cliName.toUpperCase())}`)} ${buildDurationString} ${\n buildService.isProd ? '' : chalk.redBright(`NODE_ENV=${buildService.nodeEnv}`)\n }\\n`,\n );\n}\n\nexport default build;\n"],"names":["async","build","onFinish","isOnlyClient","isWatch","isUnlockRobots","isEject","clientOptions","serverOptions","mode","perfStart","performance","now","buildService","Build","types","controller","AbortController","modeOpt","makeConfig","viteResetCache","clearBuildFolder","clientProcess","promisifyProcess","childProcess","spawn","outDir","signal","stdio","process","stdin","stderr","shell","env","FORCE_COLOR","SSR_BOOST_IS_SSR","SSR_BOOST_ACTION","global","viteBoostAction","serverProcess","serverFile","buildManifest","eject","push","on","abort","buildCount","listener","buff","Buffer","from","toString","includes","stdout","removeListener","createDevMarker","isProd","viteConfig","unlockRobots","buildDurationString","chalk","dim","yellowBright","join","reset","bold","Math","ceil","console","info","green","cliName","toUpperCase","redBright","nodeEnv"],"mappings":"iRAsBAA,eAAeC,GAAMC,SACnBA,EAAQC,aACRA,GAAe,EAAKC,QACpBA,GAAU,EAAKC,eACfA,GAAiB,EAAKC,QACtBA,GAAU,EAAKC,cACfA,EAAgB,GAAEC,cAClBA,EAAgB,GAAEC,KAClBA,EAAO,KAEP,MAAMC,EAAYC,EAAYC,MACxBC,EAAe,IAAIC,EAAM,CAAEL,SAC3BM,EAAQ,CAAC,UACTC,EAAa,IAAIC,gBACjBC,EAAUT,EAAO,UAAUA,IAAS,SAEpCI,EAAaM,mBAGbC,IACNP,EAAaQ,mBAKb,MAAMC,EAAgBT,EAAaU,iBACjCC,EAAaC,MACX,cAAclB,4BAAwCM,EAAaa,iBAAiBR,IACpF,CACES,OAAQX,EAAWW,OACnBC,MAAO,CAACC,QAAQC,MAAO,OAAQD,QAAQE,QACvCC,OAAO,EACPC,IAAK,IACAJ,QAAQI,IACXC,YAAa,IACbC,iBAAkBhC,EAAe,IAAM,IACvCiC,iBAAkBC,OAAOC,oBAUjC,IAAIC,EAsCJ,GA1CKnC,SACGkB,EAQHnB,IACHoC,EAAgB1B,EAAaU,iBAC3BC,EAAaC,MACX,cAAcjB,4BAAwCK,EAAaa,uBAAuBb,EAAa2B,cAActB,IACrH,CACES,OAAQX,EAAWW,OACnBC,MAAO,CAACC,QAAQC,MAAO,OAAQD,QAAQE,QACvCC,OAAO,EACPC,IAAK,IACAJ,QAAQI,IACXC,YAAa,IACbC,iBAAkBhC,EAAe,IAAM,IACvCiC,iBAAkBC,OAAOC,oBAM5BlC,UACGmC,QACA1B,EAAa4B,gBAEfnC,GACFO,EAAa6B,SAIjB3B,EAAM4B,KAAK,WAMTvC,EAAS,CACXyB,QAAQe,GAAG,QAAQ,KACjB5B,EAAW6B,OAAO,IAGpB,IAAIC,EAAa3C,EAAe,EAAI,EACpC,MAAM4C,EAAYC,IACJC,OAAOC,KAAKF,GAAMG,WAEtBC,SAAS,cACfN,GAAc,EAETA,IACHxB,EAAuB,QAAE+B,OAAOC,eAAe,OAAQP,GACvDR,GAAyB,QAAEc,OAAOC,eAAe,OAAQP,GACzDQ,EAAgB1C,EAAa2C,OAAQ3C,EAAa4C,YAClDvD,OAEH,EASH,OAHAoB,EAAuB,QAAE+B,OAAOT,GAAG,OAAQG,QAC3CR,GAAyB,QAAEc,OAAOT,GAAG,OAAQG,EAG9C,CAEG1C,GACFQ,EAAa6C,eAGfH,EAAgB1C,EAAa2C,OAAQ3C,EAAa4C,YAClDvD,MAEA,MAAMyD,EAAsBC,EAAMC,IAChC,GAAGD,EAAME,aAAa/C,EAAMgD,KAAK,kBAAkBH,EAAMI,MACvDJ,EAAMK,KAAKC,KAAKC,KAAKxD,EAAYC,MAAQF,WAI7C0D,QAAQC,KACN,OAAOT,EAAMU,MAAM,GAAGV,EAAMK,KAAKM,EAAQC,sBAAsBb,KAC7D9C,EAAa2C,OAAS,GAAKI,EAAMa,UAAU,YAAY5D,EAAa6D,eAG1E"}
package/cli.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import{readFileSync as o}from"fs";import e from"chalk";import{Command as n,Option as t}from"commander";import i from"./cli/build.js";import r from"./cli/keyboard-input.js";import s from"./cli/run-dev.js";import d from"./cli/run-docker-build.js";import a from"./cli/run-prod.js";import c from"./cli/vite-reset-cache.js";import l from"./constants/cli-actions.js";import p from"./constants/cli-context.js";import m from"./constants/cli-name.js";const{description:f,version:u}=JSON.parse(o(new URL("./package.json",import.meta.url),"utf8")),v=()=>{process.stdin.isTTY&&(process.stdin.setRawMode(!0),process.stdin.on("data",r).setEncoding("utf8").resume())},O=new n;O.name(m).description(f).version(u).hook("preAction",((o,e)=>{global.viteBoostAction=e.name()}));const w=new t("--host","Ability to access the local instance on other devices under the same network.").default(!1),k=new t("--only-client","Build/run only client side part.").default(!1),g=new t("--port [port]","Server port.").default(3e3),b=new t("--mode [mode]","Env mode.").env("VITE_ENV_MODE").default("production");O.command(l.dev).description("Run development server.").addOption(w).addOption(new t("--reset-cache","Clear vite cache before run.").default(!1)).addOption(new t("--mode [mode]","Env mode.").env("VITE_ENV_MODE").default("development")).action((async({host:o,resetCache:e,mode:n})=>{e&&await c();const t=async e=>{const{server:t,config:i}=await s({version:u,isHost:o,isPrintInfo:e,mode:n});p.server=t,p.config=i};return p.reboot=t,v(),t()})),O.command(l.build).description("Create production build.").addOption(k).addOption(b).addOption(new t("--client-options [client-options]",'Pass vite build options for client. Example: --client-options="--ssrManifest"').env("VITE_BUILD_CLIENT_OPTIONS").default("")).addOption(new t("--server-options [server-options]","Pass vite build options for server.").env("VITE_BUILD_SERVER_OPTIONS").default("")).addOption(new t("--unlock-robots","Change general directive Disallow to Allow in robots.txt").default(!1)).action((async({onlyClient:o,clientOptions:e,serverOptions:n,mode:t,unlockRobots:r})=>{await i({isOnlyClient:o,isUnlockRobots:r,clientOptions:e,serverOptions:n,mode:t})})),O.command(l.start).description("Run production server.").addOption(w).addOption(g).addOption(k).action((({host:o,port:e,onlyClient:n})=>{const t=async t=>{const{server:i,config:r}=await a({version:u,isHost:o,isPrintInfo:t,port:e,onlyClient:n});p.server=i,p.config=r};return p.reboot=t,v(),t()})),O.command(l.preview).description("Build and preview production.").addOption(k).addOption(w).addOption(g).addOption(b).action((async({host:o,port:n,onlyClient:t,mode:r})=>{global.viteBoostStartTime=performance.now();const s=async i=>{const{server:r,config:s}=await a({version:u,isHost:o,isPrintInfo:i,port:n,onlyClient:t});r.on("listening",(()=>{setTimeout((()=>{s.getLogger().info(e.yellow("\n Running preview mode... \n"))}),0)})),p.server=r,p.config=s};p.reboot=s,v();await i({mode:r,isWatch:!0,isOnlyClient:t,clientOptions:"-w",serverOptions:"-w",onFinish:()=>{s()}})})),O.command(l.buildDocker).description("Create docker image with production build.").requiredOption("--image-name <image-name>","Docker image name.").addOption(new t("--docker-options [docker-options]","Extra docker options which pass to docker build command.")).addOption(new t("--docker-file [docker-file]","Name of the Dockerfile (Default is PLUGIN_PATH/workflow/Dockerfile).")).addOption(k).addOption(b).action((async({imageName:o,dockerOptions:e,dockerFile:n,onlyClient:t,mode:i})=>{await d({imageName:o,dockerOptions:e,dockerFile:n,isOnlyClient:t,mode:i})})),O.parse();
2
+ import{readFileSync as o}from"fs";import e from"chalk";import{Command as t,Option as n}from"commander";import i from"./cli/build.js";import r from"./cli/keyboard-input.js";import s from"./cli/run-dev.js";import d from"./cli/run-docker-build.js";import a from"./cli/run-prod.js";import c from"./cli/vite-reset-cache.js";import l from"./constants/cli-actions.js";import p from"./constants/cli-context.js";import m from"./constants/cli-name.js";const{description:u,version:f}=JSON.parse(o(new URL("./package.json",import.meta.url),"utf8")),v=()=>{process.stdin.isTTY&&(process.stdin.setRawMode(!0),process.stdin.on("data",r).setEncoding("utf8").resume())},O=new t;O.name(m).description(u).version(f).hook("preAction",((o,e)=>{global.viteBoostAction=e.name()}));const w=new n("--host","Ability to access the local instance on other devices under the same network.").default(!1),k=new n("--only-client","Build/run only client side part.").default(!1),g=new n("--port [port]","Server port.").default(3e3),y=new n("--mode [mode]","Env mode.").env("VITE_ENV_MODE").default("production");O.command(l.dev).description("Run development server.").addOption(w).addOption(new n("--reset-cache","Clear vite cache before run.").default(!1)).addOption(new n("--mode [mode]","Env mode.").env("VITE_ENV_MODE").default("development")).action((async({host:o,resetCache:e,mode:t})=>{e&&await c();const n=async e=>{const{server:n,config:i}=await s({version:f,isHost:o,isPrintInfo:e,mode:t});p.server=n,p.config=i};return p.reboot=n,v(),n()})),O.command(l.build).description("Create production build.").addOption(k).addOption(y).addOption(new n("--client-options [client-options]",'Pass vite build options for client. Example: --client-options="--ssrManifest"').env("VITE_BUILD_CLIENT_OPTIONS").default("")).addOption(new n("--server-options [server-options]","Pass vite build options for server.").env("VITE_BUILD_SERVER_OPTIONS").default("")).addOption(new n("--unlock-robots","Change general directive Disallow to Allow in robots.txt").default(!1)).addOption(new n("--eject","Produces entrypoint file to run app without cli").default(!1)).action((async({onlyClient:o,clientOptions:e,serverOptions:t,mode:n,unlockRobots:r,eject:s})=>{await i({isOnlyClient:o,isUnlockRobots:r,isEject:s,clientOptions:e,serverOptions:t,mode:n})})),O.command(l.start).description("Run production server.").addOption(w).addOption(g).addOption(k).action((({host:o,port:e,onlyClient:t})=>{const n=async n=>{const{server:i,config:r}=await a({version:f,isHost:o,isPrintInfo:n,port:e,onlyClient:t});p.server=i,p.config=r};return p.reboot=n,v(),n()})),O.command(l.preview).description("Build and preview production.").addOption(k).addOption(w).addOption(g).addOption(y).action((async({host:o,port:t,onlyClient:n,mode:r})=>{global.viteBoostStartTime=performance.now();const s=async i=>{const{server:r,config:s}=await a({version:f,isHost:o,isPrintInfo:i,port:t,onlyClient:n});r.on("listening",(()=>{setTimeout((()=>{s.getLogger().info(e.yellow("\n Running preview mode... \n"))}),0)})),p.server=r,p.config=s};p.reboot=s,v();await i({mode:r,isWatch:!0,isOnlyClient:n,clientOptions:"-w",serverOptions:"-w",onFinish:()=>{s()}})})),O.command(l.buildDocker).description("Create docker image with production build.").requiredOption("--image-name <image-name>","Docker image name.").addOption(new n("--docker-options [docker-options]","Extra docker options which pass to docker build command.")).addOption(new n("--docker-file [docker-file]","Name of the Dockerfile (Default is PLUGIN_PATH/workflow/Dockerfile).")).addOption(k).addOption(y).action((async({imageName:o,dockerOptions:e,dockerFile:t,onlyClient:n,mode:i})=>{await d({imageName:o,dockerOptions:e,dockerFile:t,isOnlyClient:n,mode:i})})),O.parse();
3
3
  //# sourceMappingURL=cli.js.map
package/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from 'fs';\nimport chalk from 'chalk';\nimport { Command, Option } from 'commander';\nimport runBuild from '@cli/build';\nimport onKeyPress from '@cli/keyboard-input';\nimport runDev from '@cli/run-dev';\nimport runDockerBuild from '@cli/run-docker-build';\nimport runProd from '@cli/run-prod';\nimport viteResetCache from '@cli/vite-reset-cache';\nimport CliActions from '@constants/cli-actions';\nimport cliContext from '@constants/cli-context';\nimport cliName from '@constants/cli-name';\n\n/**\n * Parse package meta\n */\nconst { description, version } = JSON.parse(\n readFileSync(new URL('./package.json', import.meta.url), 'utf8'),\n) as { name: string; description: string; version: string };\n\n/**\n * Enable shortcuts\n * listen keyboard command\n */\nconst enableShortcuts = (): void => {\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n process.stdin.on('data', onKeyPress).setEncoding('utf8').resume();\n }\n};\n\nconst program = new Command();\n\nprogram\n .name(cliName)\n .description(description)\n .version(version)\n .hook('preAction', (_, actionCommand) => {\n // pass cli action to plugin config\n global.viteBoostAction = actionCommand.name();\n });\n\n/**\n * Common options\n */\nconst hostOption = new Option(\n '--host',\n 'Ability to access the local instance on other devices under the same network.',\n).default(false);\nconst onlyClientOption = new Option('--only-client', 'Build/run only client side part.').default(\n false,\n);\nconst portOption = new Option('--port [port]', 'Server port.').default(3000);\nconst envModeOption = new Option('--mode [mode]', 'Env mode.')\n .env('VITE_ENV_MODE')\n .default('production');\n\n/**\n * Cli commands\n */\n\nprogram\n .command(CliActions.dev)\n .description('Run development server.')\n .addOption(hostOption)\n .addOption(new Option('--reset-cache', 'Clear vite cache before run.').default(false))\n .addOption(new Option('--mode [mode]', 'Env mode.').env('VITE_ENV_MODE').default('development'))\n .action(async ({ host, resetCache, mode }) => {\n if (resetCache) {\n await viteResetCache();\n }\n\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n const { server, config } = await runDev({ version, isHost: host, isPrintInfo, mode });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n return command();\n });\n\nprogram\n .command(CliActions.build)\n .description('Create production build.')\n .addOption(onlyClientOption)\n .addOption(envModeOption)\n .addOption(\n new Option(\n '--client-options [client-options]',\n 'Pass vite build options for client. Example: --client-options=\"--ssrManifest\"',\n )\n .env('VITE_BUILD_CLIENT_OPTIONS')\n .default(''),\n )\n .addOption(\n new Option('--server-options [server-options]', 'Pass vite build options for server.')\n .env('VITE_BUILD_SERVER_OPTIONS')\n .default(''),\n )\n .addOption(\n new Option(\n '--unlock-robots',\n 'Change general directive Disallow to Allow in robots.txt',\n ).default(false),\n )\n .action(async ({ onlyClient, clientOptions, serverOptions, mode, unlockRobots }) => {\n await runBuild({\n isOnlyClient: onlyClient,\n isUnlockRobots: unlockRobots,\n clientOptions,\n serverOptions,\n mode,\n });\n });\n\nprogram\n .command(CliActions.start)\n .description('Run production server.')\n .addOption(hostOption)\n .addOption(portOption)\n .addOption(onlyClientOption)\n .action(({ host, port, onlyClient }) => {\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n const { server, config } = await runProd({\n version,\n isHost: host,\n isPrintInfo,\n port,\n onlyClient,\n });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n return command();\n });\n\nprogram\n .command(CliActions.preview)\n .description('Build and preview production.')\n .addOption(onlyClientOption)\n .addOption(hostOption)\n .addOption(portOption)\n .addOption(envModeOption)\n .action(async ({ host, port, onlyClient, mode }) => {\n global.viteBoostStartTime = performance.now();\n\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n const { server, config } = await runProd({\n version,\n isHost: host,\n isPrintInfo,\n port,\n onlyClient,\n });\n\n server.on('listening', () => {\n setTimeout(() => {\n config.getLogger().info(chalk.yellow('\\n Running preview mode... \\n'));\n }, 0);\n });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n const buildOptions = '-w';\n\n await runBuild({\n mode,\n isWatch: true,\n isOnlyClient: onlyClient,\n clientOptions: buildOptions,\n serverOptions: buildOptions,\n onFinish: () => {\n void command();\n },\n });\n });\n\nprogram\n .command(CliActions.buildDocker)\n .description('Create docker image with production build.')\n .requiredOption('--image-name <image-name>', 'Docker image name.')\n .addOption(\n new Option(\n '--docker-options [docker-options]',\n 'Extra docker options which pass to docker build command.',\n ),\n )\n .addOption(\n new Option(\n '--docker-file [docker-file]',\n 'Name of the Dockerfile (Default is PLUGIN_PATH/workflow/Dockerfile).',\n ),\n )\n .addOption(onlyClientOption)\n .addOption(envModeOption)\n .action(async ({ imageName, dockerOptions, dockerFile, onlyClient, mode }) => {\n await runDockerBuild({\n imageName,\n dockerOptions,\n dockerFile,\n isOnlyClient: onlyClient,\n mode,\n });\n });\n\nprogram.parse();\n"],"names":["description","version","JSON","parse","readFileSync","URL","url","enableShortcuts","process","stdin","isTTY","setRawMode","on","onKeyPress","setEncoding","resume","program","Command","name","cliName","hook","_","actionCommand","global","viteBoostAction","hostOption","Option","default","onlyClientOption","portOption","envModeOption","env","command","CliActions","dev","addOption","action","async","host","resetCache","mode","viteResetCache","isPrintInfo","server","config","runDev","isHost","cliContext","reboot","build","onlyClient","clientOptions","serverOptions","unlockRobots","runBuild","isOnlyClient","isUnlockRobots","start","port","runProd","preview","viteBoostStartTime","performance","now","setTimeout","getLogger","info","chalk","yellow","isWatch","onFinish","buildDocker","requiredOption","imageName","dockerOptions","dockerFile","runDockerBuild"],"mappings":";0bAkBA,MAAMA,YAAEA,EAAWC,QAAEA,GAAYC,KAAKC,MACpCC,EAAa,IAAIC,IAAI,6BAA8BC,KAAM,SAOrDC,EAAkB,KAClBC,QAAQC,MAAMC,QAChBF,QAAQC,MAAME,YAAW,GACzBH,QAAQC,MAAMG,GAAG,OAAQC,GAAYC,YAAY,QAAQC,SAC1D,EAGGC,EAAU,IAAIC,EAEpBD,EACGE,KAAKC,GACLnB,YAAYA,GACZC,QAAQA,GACRmB,KAAK,aAAa,CAACC,EAAGC,KAErBC,OAAOC,gBAAkBF,EAAcJ,MAAM,IAMjD,MAAMO,EAAa,IAAIC,EACrB,SACA,iFACAC,SAAQ,GACJC,EAAmB,IAAIF,EAAO,gBAAiB,oCAAoCC,SACvF,GAEIE,EAAa,IAAIH,EAAO,gBAAiB,gBAAgBC,QAAQ,KACjEG,EAAgB,IAAIJ,EAAO,gBAAiB,aAC/CK,IAAI,iBACJJ,QAAQ,cAMXX,EACGgB,QAAQC,EAAWC,KACnBlC,YAAY,2BACZmC,UAAUV,GACVU,UAAU,IAAIT,EAAO,gBAAiB,gCAAgCC,SAAQ,IAC9EQ,UAAU,IAAIT,EAAO,gBAAiB,aAAaK,IAAI,iBAAiBJ,QAAQ,gBAChFS,QAAOC,OAASC,OAAMC,aAAYC,WAC7BD,SACIE,IAGR,MAAMT,EAAUK,MAAOK,IACrB,MAAMC,OAAEA,EAAMC,OAAEA,SAAiBC,EAAO,CAAE5C,UAAS6C,OAAQR,EAAMI,cAAaF,SAE9EO,EAAWJ,OAASA,EACpBI,EAAWH,OAASA,CAAM,EAO5B,OAJAG,EAAWC,OAAShB,EAEpBzB,IAEOyB,GAAS,IAGpBhB,EACGgB,QAAQC,EAAWgB,OACnBjD,YAAY,4BACZmC,UAAUP,GACVO,UAAUL,GACVK,UACC,IAAIT,EACF,oCACA,iFAECK,IAAI,6BACJJ,QAAQ,KAEZQ,UACC,IAAIT,EAAO,oCAAqC,uCAC7CK,IAAI,6BACJJ,QAAQ,KAEZQ,UACC,IAAIT,EACF,kBACA,4DACAC,SAAQ,IAEXS,QAAOC,OAASa,aAAYC,gBAAeC,gBAAeZ,OAAMa,yBACzDC,EAAS,CACbC,aAAcL,EACdM,eAAgBH,EAChBF,gBACAC,gBACAZ,QACA,IAGNxB,EACGgB,QAAQC,EAAWwB,OACnBzD,YAAY,0BACZmC,UAAUV,GACVU,UAAUN,GACVM,UAAUP,GACVQ,QAAO,EAAGE,OAAMoB,OAAMR,iBACrB,MAAMlB,EAAUK,MAAOK,IACrB,MAAMC,OAAEA,EAAMC,OAAEA,SAAiBe,EAAQ,CACvC1D,UACA6C,OAAQR,EACRI,cACAgB,OACAR,eAGFH,EAAWJ,OAASA,EACpBI,EAAWH,OAASA,CAAM,EAO5B,OAJAG,EAAWC,OAAShB,EAEpBzB,IAEOyB,GAAS,IAGpBhB,EACGgB,QAAQC,EAAW2B,SACnB5D,YAAY,iCACZmC,UAAUP,GACVO,UAAUV,GACVU,UAAUN,GACVM,UAAUL,GACVM,QAAOC,OAASC,OAAMoB,OAAMR,aAAYV,WACvCjB,OAAOsC,mBAAqBC,YAAYC,MAExC,MAAM/B,EAAUK,MAAOK,IACrB,MAAMC,OAAEA,EAAMC,OAAEA,SAAiBe,EAAQ,CACvC1D,UACA6C,OAAQR,EACRI,cACAgB,OACAR,eAGFP,EAAO/B,GAAG,aAAa,KACrBoD,YAAW,KACTpB,EAAOqB,YAAYC,KAAKC,EAAMC,OAAO,kCAAkC,GACtE,EAAE,IAGPrB,EAAWJ,OAASA,EACpBI,EAAWH,OAASA,CAAM,EAG5BG,EAAWC,OAAShB,EAEpBzB,UAIM+C,EAAS,CACbd,OACA6B,SAAS,EACTd,aAAcL,EACdC,cANmB,KAOnBC,cAPmB,KAQnBkB,SAAU,KACHtC,GAAS,GAEhB,IAGNhB,EACGgB,QAAQC,EAAWsC,aACnBvE,YAAY,8CACZwE,eAAe,4BAA6B,sBAC5CrC,UACC,IAAIT,EACF,oCACA,6DAGHS,UACC,IAAIT,EACF,8BACA,yEAGHS,UAAUP,GACVO,UAAUL,GACVM,QAAOC,OAASoC,YAAWC,gBAAeC,aAAYzB,aAAYV,iBAC3DoC,EAAe,CACnBH,YACAC,gBACAC,aACApB,aAAcL,EACdV,QACA,IAGNxB,EAAQb"}
1
+ {"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from 'fs';\nimport chalk from 'chalk';\nimport { Command, Option } from 'commander';\nimport runBuild from '@cli/build';\nimport onKeyPress from '@cli/keyboard-input';\nimport runDev from '@cli/run-dev';\nimport runDockerBuild from '@cli/run-docker-build';\nimport runProd from '@cli/run-prod';\nimport viteResetCache from '@cli/vite-reset-cache';\nimport CliActions from '@constants/cli-actions';\nimport cliContext from '@constants/cli-context';\nimport cliName from '@constants/cli-name';\n\n/**\n * Parse package meta\n */\nconst { description, version } = JSON.parse(\n readFileSync(new URL('./package.json', import.meta.url), 'utf8'),\n) as { name: string; description: string; version: string };\n\n/**\n * Enable shortcuts\n * listen keyboard command\n */\nconst enableShortcuts = (): void => {\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n process.stdin.on('data', onKeyPress).setEncoding('utf8').resume();\n }\n};\n\nconst program = new Command();\n\nprogram\n .name(cliName)\n .description(description)\n .version(version)\n .hook('preAction', (_, actionCommand) => {\n // pass cli action to plugin config\n global.viteBoostAction = actionCommand.name();\n });\n\n/**\n * Common options\n */\nconst hostOption = new Option(\n '--host',\n 'Ability to access the local instance on other devices under the same network.',\n).default(false);\nconst onlyClientOption = new Option('--only-client', 'Build/run only client side part.').default(\n false,\n);\nconst portOption = new Option('--port [port]', 'Server port.').default(3000);\nconst envModeOption = new Option('--mode [mode]', 'Env mode.')\n .env('VITE_ENV_MODE')\n .default('production');\n\n/**\n * Cli commands\n */\n\nprogram\n .command(CliActions.dev)\n .description('Run development server.')\n .addOption(hostOption)\n .addOption(new Option('--reset-cache', 'Clear vite cache before run.').default(false))\n .addOption(new Option('--mode [mode]', 'Env mode.').env('VITE_ENV_MODE').default('development'))\n .action(async ({ host, resetCache, mode }) => {\n if (resetCache) {\n await viteResetCache();\n }\n\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n const { server, config } = await runDev({ version, isHost: host, isPrintInfo, mode });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n return command();\n });\n\nprogram\n .command(CliActions.build)\n .description('Create production build.')\n .addOption(onlyClientOption)\n .addOption(envModeOption)\n .addOption(\n new Option(\n '--client-options [client-options]',\n 'Pass vite build options for client. Example: --client-options=\"--ssrManifest\"',\n )\n .env('VITE_BUILD_CLIENT_OPTIONS')\n .default(''),\n )\n .addOption(\n new Option('--server-options [server-options]', 'Pass vite build options for server.')\n .env('VITE_BUILD_SERVER_OPTIONS')\n .default(''),\n )\n .addOption(\n new Option(\n '--unlock-robots',\n 'Change general directive Disallow to Allow in robots.txt',\n ).default(false),\n )\n .addOption(\n new Option('--eject', 'Produces entrypoint file to run app without cli').default(false),\n )\n .action(async ({ onlyClient, clientOptions, serverOptions, mode, unlockRobots, eject }) => {\n await runBuild({\n isOnlyClient: onlyClient,\n isUnlockRobots: unlockRobots,\n isEject: eject,\n clientOptions,\n serverOptions,\n mode,\n });\n });\n\nprogram\n .command(CliActions.start)\n .description('Run production server.')\n .addOption(hostOption)\n .addOption(portOption)\n .addOption(onlyClientOption)\n .action(({ host, port, onlyClient }) => {\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n const { server, config } = await runProd({\n version,\n isHost: host,\n isPrintInfo,\n port,\n onlyClient,\n });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n return command();\n });\n\nprogram\n .command(CliActions.preview)\n .description('Build and preview production.')\n .addOption(onlyClientOption)\n .addOption(hostOption)\n .addOption(portOption)\n .addOption(envModeOption)\n .action(async ({ host, port, onlyClient, mode }) => {\n global.viteBoostStartTime = performance.now();\n\n const command = async (isPrintInfo?: boolean): Promise<void> => {\n const { server, config } = await runProd({\n version,\n isHost: host,\n isPrintInfo,\n port,\n onlyClient,\n });\n\n server.on('listening', () => {\n setTimeout(() => {\n config.getLogger().info(chalk.yellow('\\n Running preview mode... \\n'));\n }, 0);\n });\n\n cliContext.server = server;\n cliContext.config = config;\n };\n\n cliContext.reboot = command;\n\n enableShortcuts();\n\n const buildOptions = '-w';\n\n await runBuild({\n mode,\n isWatch: true,\n isOnlyClient: onlyClient,\n clientOptions: buildOptions,\n serverOptions: buildOptions,\n onFinish: () => {\n void command();\n },\n });\n });\n\nprogram\n .command(CliActions.buildDocker)\n .description('Create docker image with production build.')\n .requiredOption('--image-name <image-name>', 'Docker image name.')\n .addOption(\n new Option(\n '--docker-options [docker-options]',\n 'Extra docker options which pass to docker build command.',\n ),\n )\n .addOption(\n new Option(\n '--docker-file [docker-file]',\n 'Name of the Dockerfile (Default is PLUGIN_PATH/workflow/Dockerfile).',\n ),\n )\n .addOption(onlyClientOption)\n .addOption(envModeOption)\n .action(async ({ imageName, dockerOptions, dockerFile, onlyClient, mode }) => {\n await runDockerBuild({\n imageName,\n dockerOptions,\n dockerFile,\n isOnlyClient: onlyClient,\n mode,\n });\n });\n\nprogram.parse();\n"],"names":["description","version","JSON","parse","readFileSync","URL","url","enableShortcuts","process","stdin","isTTY","setRawMode","on","onKeyPress","setEncoding","resume","program","Command","name","cliName","hook","_","actionCommand","global","viteBoostAction","hostOption","Option","default","onlyClientOption","portOption","envModeOption","env","command","CliActions","dev","addOption","action","async","host","resetCache","mode","viteResetCache","isPrintInfo","server","config","runDev","isHost","cliContext","reboot","build","onlyClient","clientOptions","serverOptions","unlockRobots","eject","runBuild","isOnlyClient","isUnlockRobots","isEject","start","port","runProd","preview","viteBoostStartTime","performance","now","setTimeout","getLogger","info","chalk","yellow","isWatch","onFinish","buildDocker","requiredOption","imageName","dockerOptions","dockerFile","runDockerBuild"],"mappings":"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"}
package/node/entry.d.ts CHANGED
@@ -6,6 +6,7 @@ import { IRenderOptions, TRender } from "./render.js";
6
6
  import ServerConfig from "../services/server-config.js";
7
7
  interface IInitServerRequestOut<T = Record<string, any>> {
8
8
  appProps?: T;
9
+ hasEarlyHints?: boolean;
9
10
  }
10
11
  interface IEntrypointOptions<TAppProps = Record<string, any>> {
11
12
  onServerCreated?: (app: Express) => Promise<void> | void;
@@ -22,7 +23,6 @@ interface IPrepareRenderOut<TAppProps = Record<string, any>> {
22
23
  init: IEntryServerOptions<TAppProps>['init'];
23
24
  routes: TRouteObject[];
24
25
  abortDelay?: number;
25
- hasEarlyHints?: boolean;
26
26
  }
27
27
  interface IAppServerProps<T = Record<string, any>> {
28
28
  server: T;
@@ -38,5 +38,5 @@ interface IEntryServerOptions<TAppProps = Record<string, any>> {
38
38
  /**
39
39
  * Render server side application
40
40
  */
41
- declare function entry<TAppProps>(App: TApp<TAppProps>, routes: TRouteObject[], { init, abortDelay, hasEarlyHints }?: IEntryServerOptions<TAppProps>): IPrepareRenderOut<TAppProps>;
41
+ declare function entry<TAppProps>(App: TApp<TAppProps>, routes: TRouteObject[], { init, abortDelay }?: IEntryServerOptions<TAppProps>): IPrepareRenderOut<TAppProps>;
42
42
  export { entry as default, IInitServerRequestOut, IEntrypointOptions, IPrepareRenderOut, IAppServerProps, TApp, IEntryServerOptions };
package/node/entry.js CHANGED
@@ -1,2 +1,2 @@
1
- import{createStaticHandler as r}from"react-router-dom/server.mjs";import t from"./render.js";function e(e,n,{init:a,abortDelay:o,hasEarlyHints:i}={}){const s=r(n);return{render:t.bind(null,{handler:s,App:e}),init:a,routes:n,abortDelay:o,hasEarlyHints:i}}export{e as default};
1
+ import{createStaticHandler as r}from"react-router-dom/server.mjs";import e from"./render.js";function t(t,o,{init:n,abortDelay:a}={}){const i=r(o);return{render:e.bind(null,{handler:i,App:t}),init:n,routes:o,abortDelay:a}}export{t as default};
2
2
  //# sourceMappingURL=entry.js.map
package/node/entry.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"entry.js","sources":["../../src/node/entry.tsx"],"sourcesContent":["import type { Express, Request, Response as ExpressResponse } from 'express';\nimport type { FC, PropsWithChildren } from 'react';\nimport type { RouteObject } from 'react-router-dom';\nimport { createStaticHandler } from 'react-router-dom/server.mjs';\nimport type { TRouteObject } from '@interfaces/route-object';\nimport type { IRenderOptions, IRenderParams, TRender } from '@node/render';\nimport render from '@node/render';\nimport type ServerConfig from '@services/server-config';\n\nexport interface IInitServerRequestOut<T = Record<string, any>> {\n appProps?: T;\n}\n\nexport interface IEntrypointOptions<TAppProps = Record<string, any>> {\n onServerCreated?: (app: Express) => Promise<void> | void;\n onRequest?: (\n req: Request,\n res: ExpressResponse,\n ) => Promise<IInitServerRequestOut<TAppProps>> | IInitServerRequestOut<TAppProps>;\n onRouterReady?: IRenderOptions<TAppProps>['onRouterReady'];\n onShellReady?: IRenderOptions<TAppProps>['onShellReady'];\n onShellError?: IRenderOptions<TAppProps>['onShellError'];\n onResponse?: IRenderOptions<TAppProps>['onResponse'];\n onError?: IRenderOptions<TAppProps>['onError'];\n getState?: IRenderOptions<TAppProps>['getState'];\n}\n\nexport interface IPrepareRenderOut<TAppProps = Record<string, any>> {\n render: TRender;\n init: IEntryServerOptions<TAppProps>['init'];\n routes: TRouteObject[];\n abortDelay?: number;\n hasEarlyHints?: boolean;\n}\n\nexport interface IAppServerProps<T = Record<string, any>> {\n server: T;\n}\n\nexport type TApp<T> = FC<PropsWithChildren<Record<string, any> & IAppServerProps<T>>>;\n\nexport interface IEntryServerOptions<TAppProps = Record<string, any>> {\n abortDelay?: number;\n hasEarlyHints?: boolean;\n init?: (params: {\n config: ServerConfig;\n }) => IEntrypointOptions<TAppProps> | Promise<IEntrypointOptions<TAppProps>>;\n}\n\n/**\n * Render server side application\n */\nfunction entry<TAppProps>(\n App: TApp<TAppProps>,\n routes: TRouteObject[],\n { init, abortDelay, hasEarlyHints }: IEntryServerOptions<TAppProps> = {},\n): IPrepareRenderOut<TAppProps> {\n const handler = createStaticHandler(routes as RouteObject[]);\n\n return {\n render: render.bind(null, { handler, App } as IRenderParams<TAppProps>) as TRender,\n init,\n routes,\n abortDelay,\n hasEarlyHints,\n };\n}\n\nexport default entry;\n"],"names":["entry","App","routes","init","abortDelay","hasEarlyHints","handler","createStaticHandler","render","bind"],"mappings":"6FAoDA,SAASA,EACPC,EACAC,GACAC,KAAEA,EAAIC,WAAEA,EAAUC,cAAEA,GAAkD,IAEtE,MAAMC,EAAUC,EAAoBL,GAEpC,MAAO,CACLM,OAAQA,EAAOC,KAAK,KAAM,CAAEH,UAASL,QACrCE,OACAD,SACAE,aACAC,gBAEJ"}
1
+ {"version":3,"file":"entry.js","sources":["../../src/node/entry.tsx"],"sourcesContent":["import type { Express, Request, Response as ExpressResponse } from 'express';\nimport type { FC, PropsWithChildren } from 'react';\nimport type { RouteObject } from 'react-router-dom';\nimport { createStaticHandler } from 'react-router-dom/server.mjs';\nimport type { TRouteObject } from '@interfaces/route-object';\nimport type { IRenderOptions, IRenderParams, TRender } from '@node/render';\nimport render from '@node/render';\nimport type ServerConfig from '@services/server-config';\n\nexport interface IInitServerRequestOut<T = Record<string, any>> {\n appProps?: T;\n hasEarlyHints?: boolean;\n}\n\nexport interface IEntrypointOptions<TAppProps = Record<string, any>> {\n onServerCreated?: (app: Express) => Promise<void> | void;\n onRequest?: (\n req: Request,\n res: ExpressResponse,\n ) => Promise<IInitServerRequestOut<TAppProps>> | IInitServerRequestOut<TAppProps>;\n onRouterReady?: IRenderOptions<TAppProps>['onRouterReady'];\n onShellReady?: IRenderOptions<TAppProps>['onShellReady'];\n onShellError?: IRenderOptions<TAppProps>['onShellError'];\n onResponse?: IRenderOptions<TAppProps>['onResponse'];\n onError?: IRenderOptions<TAppProps>['onError'];\n getState?: IRenderOptions<TAppProps>['getState'];\n}\n\nexport interface IPrepareRenderOut<TAppProps = Record<string, any>> {\n render: TRender;\n init: IEntryServerOptions<TAppProps>['init'];\n routes: TRouteObject[];\n abortDelay?: number;\n}\n\nexport interface IAppServerProps<T = Record<string, any>> {\n server: T;\n}\n\nexport type TApp<T> = FC<PropsWithChildren<Record<string, any> & IAppServerProps<T>>>;\n\nexport interface IEntryServerOptions<TAppProps = Record<string, any>> {\n abortDelay?: number;\n hasEarlyHints?: boolean;\n init?: (params: {\n config: ServerConfig;\n }) => IEntrypointOptions<TAppProps> | Promise<IEntrypointOptions<TAppProps>>;\n}\n\n/**\n * Render server side application\n */\nfunction entry<TAppProps>(\n App: TApp<TAppProps>,\n routes: TRouteObject[],\n { init, abortDelay }: IEntryServerOptions<TAppProps> = {},\n): IPrepareRenderOut<TAppProps> {\n const handler = createStaticHandler(routes as RouteObject[]);\n\n return {\n render: render.bind(null, { handler, App } as IRenderParams<TAppProps>) as TRender,\n init,\n routes,\n abortDelay,\n };\n}\n\nexport default entry;\n"],"names":["entry","App","routes","init","abortDelay","handler","createStaticHandler","render","bind"],"mappings":"6FAoDA,SAASA,EACPC,EACAC,GACAC,KAAEA,EAAIC,WAAEA,GAA+C,IAEvD,MAAMC,EAAUC,EAAoBJ,GAEpC,MAAO,CACLK,OAAQA,EAAOC,KAAK,KAAM,CAAEH,UAASJ,QACrCE,OACAD,SACAE,aAEJ"}
package/node/render.d.ts CHANGED
@@ -18,6 +18,7 @@ interface IRequestContext<TAppProps = Record<any, any>> {
18
18
  routerContext?: StaticHandlerContext;
19
19
  serverContext?: IServerContext;
20
20
  isStream?: boolean;
21
+ hasEarlyHints?: boolean;
21
22
  didError?: StreamError;
22
23
  }
23
24
  type TRender<TAppProps = Record<any, any>> = (config: ServerConfig, context: IRequestContext<TAppProps>, options: IRenderOptions) => Promise<void>;
@@ -27,7 +28,6 @@ interface IRenderParams<TAppProps = Record<string, any>> {
27
28
  }
28
29
  interface IRenderOptions<TAppProps = Record<string, any>> {
29
30
  abortDelay?: number;
30
- hasEarlyHints?: boolean;
31
31
  onRouterReady?: (params: {
32
32
  context: IRequestContext<TAppProps>;
33
33
  }) => Promise<IRouterReadyOut> | IRouterReadyOut;
@@ -61,5 +61,5 @@ interface IShellReadyOut {
61
61
  * Render application
62
62
  */
63
63
  declare function render({ App, handler }: IRenderParams, // @see entry (bind)
64
- config: ServerConfig, context: IRequestContext, { onRouterReady, onShellReady, onResponse, onShellError, onError, getState, abortDelay, hasEarlyHints, }: IRenderOptions): Promise<void>;
64
+ config: ServerConfig, context: IRequestContext, { onRouterReady, onShellReady, onResponse, onShellError, onError, getState, abortDelay, }: IRenderOptions): Promise<void>;
65
65
  export { render as default, IRequestContext, TRender, IRenderParams, IRenderOptions, IRouterReadyOut, IShellReadyOut };
package/node/render.js CHANGED
@@ -1,2 +1,2 @@
1
- import e from"chalk";import r from"react";import{renderToPipeableStream as t}from"react-dom/server";import{createStaticRouter as o,StaticRouterProvider as n}from"react-router-dom/server.mjs";import s from"../constants/stream-error.js";import{ServerProvider as a}from"../context/server.js";import m from"../helpers/handle-response.js";import i from"../helpers/obtain-stream-error.js";import c from"./create-fetch-request.js";import d from"./write-response.js";import l from"../services/ssr-manifest.js";async function p({App:p,handler:u},f,h,{onRouterReady:x,onShellReady:S,onResponse:g,onShellError:y,onError:R,getState:C,abortDelay:E=15e3,hasEarlyHints:j=!0}){const{req:v,res:w}=h,b=c(v);h.routerContext=await u.query(b,{requestContext:h});const q=m(w,h.routerContext);if(!q)return;l.get(f.getParams().root).injectAssets(h,j);const{isStream:T=!0}=await(x?.({context:h}))??{};h.isStream=T,h.serverContext={response:null,isServer:!0};const A=o(u.dataRoutes,h.routerContext),$=w.write.bind(w),B=f.getLogger();let H;w.write=(e,...r)=>{const t="string"==typeof e,o=t?e:Buffer.from(e).toString(),n=g?.({context:h,html:o});return n?$(t?`${n}${e}`:Buffer.concat([Buffer.from(n),e]),...r):$(e,...r)};const{serverContext:P,routerContext:k,appProps:D}=h,{pipe:L,abort:z}=t(r.createElement(a,{context:P},r.createElement(p,{server:{...D,req:v}},r.createElement(n,{router:A,context:k,hydrate:!1}))),{onShellReady(){T&&d(h,{pipe:L,statusCode:q,onShellReady:S,getState:C})},onAllReady(){clearTimeout(H),T||d(h,{pipe:L,statusCode:q,onShellReady:S,getState:C})},onShellError(e){const r=y?.({context:h,error:e})||`<!doctype html><p>Something went wrong: ${e.message}</p>`;w.status(500),w.setHeader("content-type","text/html"),w.send(r)},onError(r){clearTimeout(H);const t=i(r),{code:o,message:n}=t,{didError:a}=h;h.didError=a??o,R?.({context:h,error:t}),B.info(e.red(`Stream error. Code: ${o}`)),[s.RenderAborted,s.RenderTimeout,s.RenderCancel].includes(o)?B.info(e.dim(n)):B.error(r)}});H=setTimeout((()=>{h.didError=s.RenderTimeout,z()}),E),v.on("close",(()=>{h.didError=s.RenderCancel,z()}))}export{p as default};
1
+ import e from"chalk";import r from"react";import{renderToPipeableStream as t}from"react-dom/server";import{createStaticRouter as o,StaticRouterProvider as n}from"react-router-dom/server.mjs";import s from"../constants/stream-error.js";import{ServerProvider as a}from"../context/server.js";import m from"../helpers/handle-response.js";import i from"../helpers/obtain-stream-error.js";import c from"./create-fetch-request.js";import d from"./write-response.js";import l from"../services/ssr-manifest.js";async function p({App:p,handler:u},f,h,{onRouterReady:x,onShellReady:S,onResponse:g,onShellError:R,onError:y,getState:C,abortDelay:E=15e3}){const{req:j,res:v}=h,w=c(j);h.routerContext=await u.query(w,{requestContext:h});const b=m(v,h.routerContext);if(!b)return;l.get(f.getParams().root).injectAssets(h);const{isStream:q=!0}=await(x?.({context:h}))??{};h.isStream=q,h.serverContext={response:null,isServer:!0};const T=o(u.dataRoutes,h.routerContext),A=v.write.bind(v),$=f.getLogger();let B;v.write=(e,...r)=>{const t="string"==typeof e,o=t?e:Buffer.from(e).toString(),n=g?.({context:h,html:o});return n?A(t?`${n}${e}`:Buffer.concat([Buffer.from(n),e]),...r):A(e,...r)};const{serverContext:P,routerContext:k,appProps:D}=h,{pipe:H,abort:L}=t(r.createElement(a,{context:P},r.createElement(p,{server:{...D,req:j}},r.createElement(n,{router:T,context:k,hydrate:!1}))),{onShellReady(){q&&d(h,{pipe:H,statusCode:b,onShellReady:S,getState:C})},onAllReady(){clearTimeout(B),q||d(h,{pipe:H,statusCode:b,onShellReady:S,getState:C})},onShellError(e){const r=R?.({context:h,error:e})||`<!doctype html><p>Something went wrong: ${e.message}</p>`;v.status(500),v.setHeader("content-type","text/html"),v.send(r)},onError(r){clearTimeout(B);const t=i(r),{code:o,message:n}=t,{didError:a}=h;h.didError=a??o,y?.({context:h,error:t}),$.info(e.red(`Stream error. Code: ${o}`)),[s.RenderAborted,s.RenderTimeout,s.RenderCancel].includes(o)?$.info(e.dim(n)):$.error(r)}});B=setTimeout((()=>{h.didError=s.RenderTimeout,L()}),E),j.on("close",(()=>{h.didError=s.RenderCancel,L()}))}export{p as default};
2
2
  //# sourceMappingURL=render.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sources":["../../src/node/render.tsx"],"sourcesContent":["import type { StaticHandler } from '@remix-run/router';\nimport chalk from 'chalk';\nimport type { Request, Response as ExpressResponse } from 'express';\nimport React from 'react';\nimport { renderToPipeableStream } from 'react-dom/server';\nimport type { StaticHandlerContext } from 'react-router-dom/server';\nimport { createStaticRouter, StaticRouterProvider } from 'react-router-dom/server.mjs';\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 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 hasEarlyHints?: boolean;\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 hasEarlyHints = true,\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.getParams().root).injectAssets(context, hasEarlyHints);\n\n const { isStream = true } = (await onRouterReady?.({ context })) ?? {};\n\n context.isStream = isStream;\n context.serverContext = { response: null, isServer: true };\n\n const router = createStaticRouter(handler.dataRoutes, context.routerContext);\n const write = res.write.bind(res);\n const Logger = config.getLogger();\n let abortTimer: NodeJS.Timer | 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 additionalHtml = onResponse?.({ context, html });\n\n if (additionalHtml) {\n return write(\n isString ? `${additionalHtml}${data}` : Buffer.concat([Buffer.from(additionalHtml), data]),\n ...args,\n ) as boolean;\n }\n\n return write(data, ...args) as boolean;\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","hasEarlyHints","req","res","fetchRequest","createFetchRequest","routerContext","query","requestContext","statusCode","handleResponse","SsrManifest","get","getParams","root","injectAssets","isStream","serverContext","response","isServer","router","createStaticRouter","dataRoutes","write","bind","Logger","getLogger","abortTimer","data","args","isString","html","Buffer","from","toString","additionalHtml","concat","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":"sfA0EAA,eAAeC,GACbC,IAAEA,EAAGC,QAAEA,GACPC,EACAC,GACAC,cACEA,EAAaC,aACbA,EAAYC,WACZA,EAAUC,aACVA,EAAYC,QACZA,EAAOC,SACPA,EAAQC,WACRA,EAAa,KAAKC,cAClBA,GAAgB,IAGlB,MAAMC,IAAEA,EAAGC,IAAEA,GAAQV,EACfW,EAAeC,EAAmBH,GAExCT,EAAQa,oBAAuBf,EAAQgB,MAAMH,EAAc,CACzDI,eAAgBf,IAMlB,MAAMgB,EAAaC,EAAeP,EAAKV,EAAQa,eAE/C,IAAKG,EACH,OAGFE,EAAYC,IAAIpB,EAAOqB,YAAYC,MAAMC,aAAatB,EAASQ,GAE/D,MAAMe,SAAEA,GAAW,SAAgBtB,IAAgB,CAAED,cAAe,GAEpEA,EAAQuB,SAAWA,EACnBvB,EAAQwB,cAAgB,CAAEC,SAAU,KAAMC,UAAU,GAEpD,MAAMC,EAASC,EAAmB9B,EAAQ+B,WAAY7B,EAAQa,eACxDiB,EAAQpB,EAAIoB,MAAMC,KAAKrB,GACvBsB,EAASjC,EAAOkC,YACtB,IAAIC,EAMJxB,EAAIoB,MAAQ,CAACK,KAA8BC,KACzC,MAAMC,EAA2B,iBAATF,EAClBG,EAAOD,EAAWF,EAAOI,OAAOC,KAAKL,GAAMM,WAC3CC,EAAiBvC,IAAa,CAAEH,UAASsC,SAE/C,OAAII,EACKZ,EACLO,EAAW,GAAGK,IAAiBP,IAASI,OAAOI,OAAO,CAACJ,OAAOC,KAAKE,GAAiBP,OACjFC,GAIAN,EAAMK,KAASC,EAAgB,EAGxC,MAAMZ,cAAEA,EAAaX,cAAEA,EAAa+B,SAAEA,GAAa5C,GAE7C6C,KAAEA,EAAIC,MAAEA,GAAUC,EACtBC,EAACC,cAAAC,EAAe,CAAAlD,QAASwB,GACvBwB,EAACC,cAAApD,GAAIsD,OAAQ,IAAKP,EAAUnC,QAC1BuC,EAAAC,cAACG,EAAqB,CAAAzB,OAAQA,EAAQ3B,QAASa,EAAewC,SAAS,MAG3E,CACEnD,eACOqB,GAIL+B,EAActD,EAAS,CACrB6C,OACA7B,aACAd,eACAI,YAEH,EACDiD,aACEC,aAAatB,GAETX,GAIJ+B,EAActD,EAAS,CACrB6C,OACA7B,aACAd,eACAI,YAEH,EACDF,aAAaqD,GACX,MAAMC,EACJtD,IAAe,CAAEJ,UAAS2D,MAAOF,KACjC,2CAA2CA,EAAEG,cAE/ClD,EAAImD,OAAO,KACXnD,EAAIoD,UAAU,eAAgB,aAC9BpD,EAAIqD,KAAKL,EACV,EACDrD,QAAQ2D,GACNR,aAAatB,GAEb,MAAMyB,EAAQM,EAAkBD,IAC1BE,KAAEA,EAAIN,QAAEA,GAAYD,GACpBQ,SAAEA,GAAanE,EAErBA,EAAQmE,SAAWA,GAAYD,EAE/B7D,IAAU,CAAEL,UAAS2D,UACrB3B,EAAOoC,KAAKC,EAAMC,IAAI,uBAAuBJ,MAG3C,CAACK,EAAYC,cAAeD,EAAYE,cAAeF,EAAYG,cAAcC,SAC/ET,GAGFlC,EAAOoC,KAAKC,EAAMO,IAAIhB,IAKxB5B,EAAO2B,MAAMK,EACd,IAKL9B,EAAa2C,YAAW,KACtB7E,EAAQmE,SAAWI,EAAYE,cAC/B3B,GAAO,GACNvC,GAGHE,EAAIqE,GAAG,SAAS,KACd9E,EAAQmE,SAAWI,EAAYG,aAC/B5B,GAAO,GAEX"}
1
+ {"version":3,"file":"render.js","sources":["../../src/node/render.tsx"],"sourcesContent":["import type { StaticHandler } from '@remix-run/router';\nimport chalk from 'chalk';\nimport type { Request, Response as ExpressResponse } from 'express';\nimport React from 'react';\nimport { renderToPipeableStream } from 'react-dom/server';\nimport type { StaticHandlerContext } from 'react-router-dom/server';\nimport { createStaticRouter, StaticRouterProvider } from 'react-router-dom/server.mjs';\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.getParams().root).injectAssets(context);\n\n const { isStream = true } = (await onRouterReady?.({ context })) ?? {};\n\n context.isStream = isStream;\n context.serverContext = { response: null, isServer: true };\n\n const router = createStaticRouter(handler.dataRoutes, context.routerContext);\n const write = res.write.bind(res);\n const Logger = config.getLogger();\n let abortTimer: NodeJS.Timer | 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 additionalHtml = onResponse?.({ context, html });\n\n if (additionalHtml) {\n return write(\n isString ? `${additionalHtml}${data}` : Buffer.concat([Buffer.from(additionalHtml), data]),\n ...args,\n ) as boolean;\n }\n\n return write(data, ...args) as boolean;\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","getParams","root","injectAssets","isStream","serverContext","response","isServer","router","createStaticRouter","dataRoutes","write","bind","Logger","getLogger","abortTimer","data","args","isString","html","Buffer","from","toString","additionalHtml","concat","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":"sfA0EAA,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,EAAOoB,YAAYC,MAAMC,aAAarB,GAEtD,MAAMsB,SAAEA,GAAW,SAAgBrB,IAAgB,CAAED,cAAe,GAEpEA,EAAQsB,SAAWA,EACnBtB,EAAQuB,cAAgB,CAAEC,SAAU,KAAMC,UAAU,GAEpD,MAAMC,EAASC,EAAmB7B,EAAQ8B,WAAY5B,EAAQY,eACxDiB,EAAQpB,EAAIoB,MAAMC,KAAKrB,GACvBsB,EAAShC,EAAOiC,YACtB,IAAIC,EAMJxB,EAAIoB,MAAQ,CAACK,KAA8BC,KACzC,MAAMC,EAA2B,iBAATF,EAClBG,EAAOD,EAAWF,EAAOI,OAAOC,KAAKL,GAAMM,WAC3CC,EAAiBtC,IAAa,CAAEH,UAASqC,SAE/C,OAAII,EACKZ,EACLO,EAAW,GAAGK,IAAiBP,IAASI,OAAOI,OAAO,CAACJ,OAAOC,KAAKE,GAAiBP,OACjFC,GAIAN,EAAMK,KAASC,EAAgB,EAGxC,MAAMZ,cAAEA,EAAaX,cAAEA,EAAa+B,SAAEA,GAAa3C,GAE7C4C,KAAEA,EAAIC,MAAEA,GAAUC,EACtBC,EAACC,cAAAC,EAAe,CAAAjD,QAASuB,GACvBwB,EAACC,cAAAnD,GAAIqD,OAAQ,IAAKP,EAAUnC,QAC1BuC,EAAAC,cAACG,EAAqB,CAAAzB,OAAQA,EAAQ1B,QAASY,EAAewC,SAAS,MAG3E,CACElD,eACOoB,GAIL+B,EAAcrD,EAAS,CACrB4C,OACA7B,aACAb,eACAI,YAEH,EACDgD,aACEC,aAAatB,GAETX,GAIJ+B,EAAcrD,EAAS,CACrB4C,OACA7B,aACAb,eACAI,YAEH,EACDF,aAAaoD,GACX,MAAMC,EACJrD,IAAe,CAAEJ,UAAS0D,MAAOF,KACjC,2CAA2CA,EAAEG,cAE/ClD,EAAImD,OAAO,KACXnD,EAAIoD,UAAU,eAAgB,aAC9BpD,EAAIqD,KAAKL,EACV,EACDpD,QAAQ0D,GACNR,aAAatB,GAEb,MAAMyB,EAAQM,EAAkBD,IAC1BE,KAAEA,EAAIN,QAAEA,GAAYD,GACpBQ,SAAEA,GAAalE,EAErBA,EAAQkE,SAAWA,GAAYD,EAE/B5D,IAAU,CAAEL,UAAS0D,UACrB3B,EAAOoC,KAAKC,EAAMC,IAAI,uBAAuBJ,MAG3C,CAACK,EAAYC,cAAeD,EAAYE,cAAeF,EAAYG,cAAcC,SAC/ET,GAGFlC,EAAOoC,KAAKC,EAAMO,IAAIhB,IAKxB5B,EAAO2B,MAAMK,EACd,IAKL9B,EAAa2C,YAAW,KACtB5E,EAAQkE,SAAWI,EAAYE,cAC/B3B,GAAO,GACNtC,GAGHC,EAAIqE,GAAG,SAAS,KACd7E,EAAQkE,SAAWI,EAAYG,aAC/B5B,GAAO,GAEX"}
package/node/server.js CHANGED
@@ -1,2 +1,2 @@
1
- import e from"path";import r from"compression";import t from"express";import s from"../helpers/print-server-info.js";import o from"../services/prepare-server.js";async function i(i){const a=t().disable("x-powered-by");if(i.setApp(a),i.isProd){const{root:s,publicDir:o,isSPA:n}=i.getParams();a.use(r()),n||a.use(((e,r,t)=>{"/index.html"===e.url&&(e.url="/index-not-found.html"),t()})),a.use(t.static(e.resolve(`${s}/${o}`),{index:!!n&&void 0}))}else{const e=await(await import("vite")).createServer({server:{middlewareMode:!0,watch:{usePolling:!0,interval:100}},appType:"custom",mode:i.mode});a.use(e.middlewares),i.setVite(e)}const n=o.init(i);return i.isSPA?a.use("*",((e,r,t)=>{(async()=>{try{const t=(await n.loadHtml(e)).join("");r.send(t)}catch(e){t(e)}})()})):(await n.onAppCreated(),a.use("*",((e,r,t)=>{(async()=>{try{const[{render:t,onRequest:s,...o},a]=await Promise.all([n.loadEntrypoint(),n.loadHtml(e)]),{appProps:p}=await(s?.(e,r))??{},[m,c]=a,d={req:e,res:r,appProps:p??{},html:{header:m,footer:c}};await t(i,d,o)}catch(e){t(e)}})()}))),{run:({version:e,isPrintInfo:r=!0}={})=>{const{port:t,host:o}=i.getParams();i.isHost&&!i.isProd&&(i.getVite().config.server.host=o);const n=a.listen(t,o,(()=>{r&&s(n,i,{version:e})}));return n}}}export{i as default};
1
+ import e from"path";import r from"compression";import t from"express";import s from"../helpers/print-server-info.js";import o from"../services/prepare-server.js";async function i(i){const a=t().disable("x-powered-by");if(i.setApp(a),i.isProd){const{root:s,publicDir:o,isSPA:n}=i.getParams();a.use(r()),n||a.use(((e,r,t)=>{"/index.html"===e.url&&(e.url="/index-not-found.html"),t()})),a.use(t.static(e.resolve(`${s}/${o}`),{index:!!n&&void 0}))}else{const e=await(await import("vite")).createServer({server:{middlewareMode:!0,watch:{usePolling:!0,interval:100}},appType:"custom",mode:i.mode});a.use(e.middlewares),i.setVite(e)}const n=o.init(i);return i.isSPA?a.use("*",((e,r,t)=>{(async()=>{try{const t=(await n.loadHtml(e)).join("");r.send(t)}catch(e){t(e)}})()})):(await n.onAppCreated(),a.use("*",((e,r,t)=>{(async()=>{try{const[{render:t,onRequest:s,...o},a]=await Promise.all([n.loadEntrypoint(),n.loadHtml(e)]),{appProps:p,hasEarlyHints:l}=await(s?.(e,r))??{},[m,c]=a,d={req:e,res:r,hasEarlyHints:l,appProps:p??{},html:{header:m,footer:c}};await t(i,d,o)}catch(e){t(e)}})()}))),{run:({version:e,isPrintInfo:r=!0}={})=>{const{port:t,host:o}=i.getParams();i.isHost&&!i.isProd&&(i.getVite().config.server.host=o);const n=a.listen(t,o,(()=>{r&&s(n,i,{version:e})}));return n}}}export{i as default};
2
2
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sources":["../../src/node/server.ts"],"sourcesContent":["import type { Server } from 'node:net';\nimport path from 'path';\nimport compression from 'compression';\nimport express from 'express';\nimport printServerInfo from '@helpers/print-server-info';\nimport type { IRequestContext } from '@node/render';\nimport PrepareServer from '@services/prepare-server';\nimport type ServerConfig from '@services/server-config';\n\nexport interface ICreateServerOut {\n run: (options?: { version?: string; isPrintInfo?: boolean }) => Server;\n}\n\n/**\n * Create SSR server\n */\nasync function createServer(config: ServerConfig): Promise<ICreateServerOut> {\n const app = express().disable('x-powered-by');\n\n config.setApp(app);\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 } else {\n const { root, publicDir, isSPA } = config.getParams();\n\n app.use(compression());\n\n if (!isSPA) {\n // ignore index.html file in SSR mode\n app.use((req, res, next) => {\n if (req.url === '/index.html') {\n req.url = '/index-not-found.html';\n }\n\n next();\n });\n }\n\n app.use(\n express.static(path.resolve(`${root}/${publicDir}`), {\n index: isSPA ? undefined : false,\n }),\n );\n }\n\n const prepareServer = PrepareServer.init(config);\n\n // SSR mode\n if (!config.isSPA) {\n await prepareServer.onAppCreated();\n\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 } = (await onRequest?.(req, res)) ?? {};\n const [header, footer] = clientHtml;\n\n const context: IRequestContext = {\n req,\n res,\n appProps: appProps ?? {},\n html: { header, footer },\n };\n\n await render(config, context, renderParams);\n } catch (e) {\n next(e);\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 next(e);\n }\n })();\n });\n }\n\n return {\n run: ({ version, isPrintInfo = true } = {}): Server => {\n const { port, host } = config.getParams();\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 = app.listen(port, host, () => {\n if (!isPrintInfo) {\n return;\n }\n\n void printServerInfo(server, config, { version });\n });\n\n return server;\n },\n };\n}\n\nexport default createServer;\n"],"names":["async","createServer","config","app","express","disable","setApp","isProd","root","publicDir","isSPA","getParams","use","compression","req","res","next","url","static","path","resolve","index","undefined","vite","import","server","middlewareMode","watch","usePolling","interval","appType","mode","middlewares","setVite","prepareServer","PrepareServer","init","html","loadHtml","join","send","e","onAppCreated","render","onRequest","renderParams","clientHtml","Promise","all","loadEntrypoint","appProps","header","footer","context","run","version","isPrintInfo","port","host","isHost","getVite","listen","printServerInfo"],"mappings":"kKAgBAA,eAAeC,EAAaC,GAC1B,MAAMC,EAAMC,IAAUC,QAAQ,gBAI9B,GAFAH,EAAOI,OAAOH,GAETD,EAAOK,OAwBL,CACL,MAAMC,KAAEA,EAAIC,UAAEA,EAASC,MAAEA,GAAUR,EAAOS,YAE1CR,EAAIS,IAAIC,KAEHH,GAEHP,EAAIS,KAAI,CAACE,EAAKC,EAAKC,KACD,gBAAZF,EAAIG,MACNH,EAAIG,IAAM,yBAGZD,GAAM,IAIVb,EAAIS,IACFR,EAAQc,OAAOC,EAAKC,QAAQ,GAAGZ,KAAQC,KAAc,CACnDY,QAAOX,QAAQY,IAGpB,KA7CmB,CAIlB,MAAMC,cACEC,OAAO,SACbvB,aAAa,CACbwB,OAAQ,CACNC,gBAAgB,EAChBC,MAAO,CAGLC,YAAY,EACZC,SAAU,MAGdC,QAAS,SACTC,KAAM7B,EAAO6B,OAIf5B,EAAIS,IAAIW,EAAKS,aAEb9B,EAAO+B,QAAQV,EAChB,CAuBD,MAAMW,EAAgBC,EAAcC,KAAKlC,GA4CzC,OAzCKA,EAAOQ,MA4BVP,EAAIS,IAAI,KAAK,CAACE,EAAKC,EAAKC,KACjB,WACH,IACE,MAAMqB,SAAcH,EAAcI,SAASxB,IAAMyB,KAAK,IAEtDxB,EAAIyB,KAAKH,EACV,CAAC,MAAOI,GACPzB,EAAKyB,EACN,CACF,EARI,EAQD,WApCAP,EAAcQ,eAEpBvC,EAAIS,IAAI,KAAK,CAACE,EAAKC,EAAKC,KACjB,WACH,IACE,OAAO2B,OAAEA,EAAMC,UAAEA,KAAcC,GAAgBC,SAAoBC,QAAQC,IAAI,CAC7Ed,EAAce,iBACdf,EAAcI,SAASxB,MAEnBoC,SAAEA,SAAoBN,IAAY9B,EAAKC,KAAS,IAC/CoC,EAAQC,GAAUN,EAEnBO,EAA2B,CAC/BvC,MACAC,MACAmC,SAAUA,GAAY,CAAE,EACxBb,KAAM,CAAEc,SAAQC,iBAGZT,EAAOzC,EAAQmD,EAASR,EAC/B,CAAC,MAAOJ,GACPzB,EAAKyB,EACN,CACF,EApBI,EAoBD,KAiBD,CACLa,IAAK,EAAGC,UAASC,eAAc,GAAS,CAAA,KACtC,MAAMC,KAAEA,EAAIC,KAAEA,GAASxD,EAAOS,YAG1BT,EAAOyD,SAAWzD,EAAOK,SAC3BL,EAAO0D,UAAW1D,OAAOuB,OAAOiC,KAAOA,GAGzC,MAAMjC,EAAStB,EAAI0D,OAAOJ,EAAMC,GAAM,KAC/BF,GAIAM,EAAgBrC,EAAQvB,EAAQ,CAAEqD,WAAU,IAGnD,OAAO9B,CAAM,EAGnB"}
1
+ {"version":3,"file":"server.js","sources":["../../src/node/server.ts"],"sourcesContent":["import type { Server } from 'node:net';\nimport path from 'path';\nimport compression from 'compression';\nimport express from 'express';\nimport printServerInfo from '@helpers/print-server-info';\nimport type { IRequestContext } from '@node/render';\nimport PrepareServer from '@services/prepare-server';\nimport type ServerConfig from '@services/server-config';\n\nexport interface ICreateServerOut {\n run: (options?: { version?: string; isPrintInfo?: boolean }) => Server;\n}\n\n/**\n * Create SSR server\n */\nasync function createServer(config: ServerConfig): Promise<ICreateServerOut> {\n const app = express().disable('x-powered-by');\n\n config.setApp(app);\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 } else {\n const { root, publicDir, isSPA } = config.getParams();\n\n app.use(compression());\n\n if (!isSPA) {\n // ignore index.html file in SSR mode\n app.use((req, res, next) => {\n if (req.url === '/index.html') {\n req.url = '/index-not-found.html';\n }\n\n next();\n });\n }\n\n app.use(\n express.static(path.resolve(`${root}/${publicDir}`), {\n index: isSPA ? undefined : false,\n }),\n );\n }\n\n const prepareServer = PrepareServer.init(config);\n\n // SSR mode\n if (!config.isSPA) {\n await prepareServer.onAppCreated();\n\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 } = (await onRequest?.(req, res)) ?? {};\n const [header, footer] = clientHtml;\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 next(e);\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 next(e);\n }\n })();\n });\n }\n\n return {\n run: ({ version, isPrintInfo = true } = {}): Server => {\n const { port, host } = config.getParams();\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 = app.listen(port, host, () => {\n if (!isPrintInfo) {\n return;\n }\n\n void printServerInfo(server, config, { version });\n });\n\n return server;\n },\n };\n}\n\nexport default createServer;\n"],"names":["async","createServer","config","app","express","disable","setApp","isProd","root","publicDir","isSPA","getParams","use","compression","req","res","next","url","static","path","resolve","index","undefined","vite","import","server","middlewareMode","watch","usePolling","interval","appType","mode","middlewares","setVite","prepareServer","PrepareServer","init","html","loadHtml","join","send","e","onAppCreated","render","onRequest","renderParams","clientHtml","Promise","all","loadEntrypoint","appProps","hasEarlyHints","header","footer","context","run","version","isPrintInfo","port","host","isHost","getVite","listen","printServerInfo"],"mappings":"kKAgBAA,eAAeC,EAAaC,GAC1B,MAAMC,EAAMC,IAAUC,QAAQ,gBAI9B,GAFAH,EAAOI,OAAOH,GAETD,EAAOK,OAwBL,CACL,MAAMC,KAAEA,EAAIC,UAAEA,EAASC,MAAEA,GAAUR,EAAOS,YAE1CR,EAAIS,IAAIC,KAEHH,GAEHP,EAAIS,KAAI,CAACE,EAAKC,EAAKC,KACD,gBAAZF,EAAIG,MACNH,EAAIG,IAAM,yBAGZD,GAAM,IAIVb,EAAIS,IACFR,EAAQc,OAAOC,EAAKC,QAAQ,GAAGZ,KAAQC,KAAc,CACnDY,QAAOX,QAAQY,IAGpB,KA7CmB,CAIlB,MAAMC,cACEC,OAAO,SACbvB,aAAa,CACbwB,OAAQ,CACNC,gBAAgB,EAChBC,MAAO,CAGLC,YAAY,EACZC,SAAU,MAGdC,QAAS,SACTC,KAAM7B,EAAO6B,OAIf5B,EAAIS,IAAIW,EAAKS,aAEb9B,EAAO+B,QAAQV,EAChB,CAuBD,MAAMW,EAAgBC,EAAcC,KAAKlC,GA6CzC,OA1CKA,EAAOQ,MA6BVP,EAAIS,IAAI,KAAK,CAACE,EAAKC,EAAKC,KACjB,WACH,IACE,MAAMqB,SAAcH,EAAcI,SAASxB,IAAMyB,KAAK,IAEtDxB,EAAIyB,KAAKH,EACV,CAAC,MAAOI,GACPzB,EAAKyB,EACN,CACF,EARI,EAQD,WArCAP,EAAcQ,eAEpBvC,EAAIS,IAAI,KAAK,CAACE,EAAKC,EAAKC,KACjB,WACH,IACE,OAAO2B,OAAEA,EAAMC,UAAEA,KAAcC,GAAgBC,SAAoBC,QAAQC,IAAI,CAC7Ed,EAAce,iBACdf,EAAcI,SAASxB,MAEnBoC,SAAEA,EAAQC,cAAEA,SAAyBP,IAAY9B,EAAKC,KAAS,IAC9DqC,EAAQC,GAAUP,EAEnBQ,EAA2B,CAC/BxC,MACAC,MACAoC,gBACAD,SAAUA,GAAY,CAAE,EACxBb,KAAM,CAAEe,SAAQC,iBAGZV,EAAOzC,EAAQoD,EAAST,EAC/B,CAAC,MAAOJ,GACPzB,EAAKyB,EACN,CACF,EArBI,EAqBD,KAiBD,CACLc,IAAK,EAAGC,UAASC,eAAc,GAAS,CAAA,KACtC,MAAMC,KAAEA,EAAIC,KAAEA,GAASzD,EAAOS,YAG1BT,EAAO0D,SAAW1D,EAAOK,SAC3BL,EAAO2D,UAAW3D,OAAOuB,OAAOkC,KAAOA,GAGzC,MAAMlC,EAAStB,EAAI2D,OAAOJ,EAAMC,GAAM,KAC/BF,GAIAM,EAAgBtC,EAAQvB,EAAQ,CAAEsD,WAAU,IAGnD,OAAO/B,CAAM,EAGnB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lomray/vite-ssr-boost",
3
- "version": "1.0.0-beta.20",
3
+ "version": "1.0.0-beta.22",
4
4
  "description": "Vite plugin for create awesome SSR or SPA applications on React.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -0,0 +1,94 @@
1
+ /// <reference types="node" />
2
+ import childProcess from 'node:child_process';
3
+ import { ResolvedConfig } from 'vite';
4
+ import { IPluginConfig } from "../helpers/plugin-config.js";
5
+ interface IBuildParams {
6
+ mode: string;
7
+ }
8
+ /**
9
+ * Build service
10
+ */
11
+ declare class Build {
12
+ /**
13
+ * Is production build
14
+ */
15
+ isProd: boolean;
16
+ /**
17
+ * Node environment
18
+ */
19
+ nodeEnv: string;
20
+ /**
21
+ * Build folder
22
+ */
23
+ buildDir: string;
24
+ /**
25
+ * Relative build dir
26
+ */
27
+ outDir: string;
28
+ /**
29
+ * Server file
30
+ */
31
+ serverFile: string;
32
+ /**
33
+ * Vite config
34
+ */
35
+ viteConfig: ResolvedConfig;
36
+ /**
37
+ * Plugin config
38
+ */
39
+ pluginConfig: IPluginConfig;
40
+ /**
41
+ * Build params
42
+ */
43
+ protected params: IBuildParams;
44
+ /**
45
+ * @constructor
46
+ */
47
+ /**
48
+ * @constructor
49
+ */
50
+ constructor(params: IBuildParams);
51
+ /**
52
+ * Make config
53
+ */
54
+ /**
55
+ * Make config
56
+ */
57
+ makeConfig(): Promise<void>;
58
+ /**
59
+ * Clear build folder
60
+ */
61
+ /**
62
+ * Clear build folder
63
+ */
64
+ clearBuildFolder(): void;
65
+ /**
66
+ * Promisify spawn process
67
+ */
68
+ /**
69
+ * Promisify spawn process
70
+ */
71
+ promisifyProcess(command: childProcess.ChildProcess): Promise<unknown>;
72
+ /**
73
+ * Build assets manifest file
74
+ */
75
+ /**
76
+ * Build assets manifest file
77
+ */
78
+ buildManifest(): Promise<void>;
79
+ /**
80
+ * Change general directive Disallow to Allow in robots.txt.
81
+ */
82
+ /**
83
+ * Change general directive Disallow to Allow in robots.txt.
84
+ */
85
+ unlockRobots(): void;
86
+ /**
87
+ * Eject cli to run app via node
88
+ */
89
+ /**
90
+ * Eject cli to run app via node
91
+ */
92
+ eject(): void;
93
+ }
94
+ export { Build as default };
@@ -0,0 +1,2 @@
1
+ import i from"node:fs";import o from"node:path";import t from"chalk";import{resolveConfig as s}from"vite";import e from"../helpers/plugin-config.js";import n from"./ssr-manifest.js";class r{isProd;nodeEnv;buildDir;outDir;serverFile;viteConfig;pluginConfig;params;constructor(i){this.params=i}async makeConfig(){const{mode:i}=this.params;this.viteConfig=await s({},"build",i,"production"===i?"production":"development"),this.pluginConfig=e(this.viteConfig),this.buildDir=o.resolve(this.viteConfig.root,this.viteConfig.build.outDir),this.outDir=this.viteConfig.build.outDir,this.serverFile=this.pluginConfig.serverFile,this.nodeEnv=process.env.NODE_ENV||"development",this.isProd="production"===this.nodeEnv}clearBuildFolder(){i.existsSync(this.buildDir)&&i.rmSync(this.buildDir,{recursive:!0})}promisifyProcess(i){const o=new Promise(((o,t)=>{i.on("exit",(i=>{o(i)})),i.on("close",(i=>{o(i)})),i.on("error",(i=>{t(i)}))}));return i.stdout?.pipe(process.stdout),i.stderr?.pipe(process.stderr),o.command=i,o}async buildManifest(){await n.get(this.viteConfig.root,{alias:this.viteConfig.resolve.alias,buildDir:this.viteConfig.build.outDir}).buildRoutesManifest(this.pluginConfig.preloadAssets)}unlockRobots(){const o=`${this.buildDir}/client/robots.txt`;if(!i.existsSync(o))return void console.warn(`Failed to unlock robots.txt, file not exist: ${o}`);const s=i.readFileSync(o,{encoding:"utf-8"}).replace(/Disallow: \/$/m,"Allow: /");i.writeFileSync(o,s,{encoding:"utf-8"}),console.info(t.blue("\nrobots.txt unlocked."))}eject(){const o=`${this.buildDir}/server/start.js`;i.writeFileSync(o,"import runProd from '@lomray/vite-ssr-boost/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"})}}export{r as default};
2
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sources":["../../src/services/build.ts"],"sourcesContent":["import type childProcess from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport chalk from 'chalk';\nimport type { ResolvedConfig } from 'vite';\nimport { resolveConfig } from 'vite';\nimport type { IPluginConfig } from '@helpers/plugin-config';\nimport getPluginConfig from '@helpers/plugin-config';\nimport SsrManifest from '@services/ssr-manifest';\n\ninterface IBuildParams {\n mode: string;\n}\n\n/**\n * Build service\n */\nclass Build {\n /**\n * Is production build\n */\n public isProd: boolean;\n\n /**\n * Node environment\n */\n public nodeEnv: string;\n\n /**\n * Build folder\n */\n public buildDir: string;\n\n /**\n * Relative build dir\n */\n public outDir: string;\n\n /**\n * Server file\n */\n public serverFile: string;\n\n /**\n * Vite config\n */\n public viteConfig: ResolvedConfig;\n\n /**\n * Plugin config\n */\n public pluginConfig: IPluginConfig;\n\n /**\n * Build params\n */\n protected params: IBuildParams;\n\n /**\n * @constructor\n */\n constructor(params: IBuildParams) {\n this.params = params;\n }\n\n /**\n * Make config\n */\n public async makeConfig(): Promise<void> {\n const { mode } = this.params;\n\n this.viteConfig = await resolveConfig(\n {},\n 'build',\n mode,\n mode === 'production' ? 'production' : 'development',\n );\n this.pluginConfig = getPluginConfig(this.viteConfig);\n this.buildDir = path.resolve(this.viteConfig.root, this.viteConfig.build.outDir);\n this.outDir = this.viteConfig.build.outDir;\n this.serverFile = this.pluginConfig.serverFile;\n this.nodeEnv = process.env.NODE_ENV || 'development';\n this.isProd = this.nodeEnv === 'production';\n }\n\n /**\n * Clear build folder\n */\n public clearBuildFolder(): void {\n // clear build folder\n if (fs.existsSync(this.buildDir)) {\n fs.rmSync(this.buildDir, { recursive: true });\n }\n }\n\n /**\n * Promisify spawn process\n */\n public promisifyProcess(command: childProcess.ChildProcess): Promise<unknown> {\n const promise = new Promise((resolve, reject) => {\n command.on('exit', (code) => {\n resolve(code);\n });\n\n command.on('close', (code) => {\n resolve(code);\n });\n\n command.on('error', (message) => {\n reject(message);\n });\n });\n\n command.stdout?.pipe(process.stdout);\n command.stderr?.pipe(process.stderr);\n\n promise['command'] = command;\n\n return promise;\n }\n\n /**\n * Build assets manifest file\n */\n public async buildManifest(): Promise<void> {\n await SsrManifest.get(this.viteConfig.root, {\n alias: this.viteConfig.resolve.alias,\n buildDir: this.viteConfig.build.outDir,\n }).buildRoutesManifest(this.pluginConfig.preloadAssets);\n }\n\n /**\n * Change general directive Disallow to Allow in robots.txt.\n */\n public unlockRobots(): void {\n const robotsFile = `${this.buildDir}/client/robots.txt`;\n\n if (!fs.existsSync(robotsFile)) {\n console.warn(`Failed to unlock robots.txt, file not exist: ${robotsFile}`);\n\n return;\n }\n\n const data = fs\n .readFileSync(robotsFile, { encoding: 'utf-8' })\n .replace(/Disallow: \\/$/m, 'Allow: /');\n\n fs.writeFileSync(robotsFile, data, { encoding: 'utf-8' });\n\n console.info(chalk.blue('\\nrobots.txt unlocked.'));\n }\n\n /**\n * Eject cli to run app via node\n */\n public eject(): void {\n const entrypoint = `${this.buildDir}/server/start.js`;\n const script =\n \"import runProd from '@lomray/vite-ssr-boost/cli/run-prod.js';\\n\\n\" +\n 'const VERSION = process.env.VERSION || \"1.0.0\";\\n' +\n 'const PORT = process.env.PORT || 3000;\\n' +\n 'const IS_HOST = process.env.IS_HOST || \"0\";\\n' +\n 'const ONLY_CLIENT = process.env.ONLY_CLIENT || \"0\";\\n\\n' +\n `await runProd({\n version: VERSION,\n isHost: IS_HOST === '1',\n isPrintInfo: true,\n port: PORT,\n onlyClient: ONLY_CLIENT === '1',\n });\\n`;\n\n fs.writeFileSync(entrypoint, script, {\n encoding: 'utf-8',\n });\n }\n}\n\nexport default Build;\n"],"names":["Build","isProd","nodeEnv","buildDir","outDir","serverFile","viteConfig","pluginConfig","params","constructor","this","async","mode","resolveConfig","getPluginConfig","path","resolve","root","build","process","env","NODE_ENV","clearBuildFolder","fs","existsSync","rmSync","recursive","promisifyProcess","command","promise","Promise","reject","on","code","message","stdout","pipe","stderr","SsrManifest","get","alias","buildRoutesManifest","preloadAssets","unlockRobots","robotsFile","console","warn","data","readFileSync","encoding","replace","writeFileSync","info","chalk","blue","eject","entrypoint"],"mappings":"sLAiBA,MAAMA,EAIGC,OAKAC,QAKAC,SAKAC,OAKAC,WAKAC,WAKAC,aAKGC,OAKVC,YAAYD,GACVE,KAAKF,OAASA,CACf,CAKMG,mBACL,MAAMC,KAAEA,GAASF,KAAKF,OAEtBE,KAAKJ,iBAAmBO,EACtB,GACA,QACAD,EACS,eAATA,EAAwB,aAAe,eAEzCF,KAAKH,aAAeO,EAAgBJ,KAAKJ,YACzCI,KAAKP,SAAWY,EAAKC,QAAQN,KAAKJ,WAAWW,KAAMP,KAAKJ,WAAWY,MAAMd,QACzEM,KAAKN,OAASM,KAAKJ,WAAWY,MAAMd,OACpCM,KAAKL,WAAaK,KAAKH,aAAaF,WACpCK,KAAKR,QAAUiB,QAAQC,IAAIC,UAAY,cACvCX,KAAKT,OAA0B,eAAjBS,KAAKR,OACpB,CAKMoB,mBAEDC,EAAGC,WAAWd,KAAKP,WACrBoB,EAAGE,OAAOf,KAAKP,SAAU,CAAEuB,WAAW,GAEzC,CAKMC,iBAAiBC,GACtB,MAAMC,EAAU,IAAIC,SAAQ,CAACd,EAASe,KACpCH,EAAQI,GAAG,QAASC,IAClBjB,EAAQiB,EAAK,IAGfL,EAAQI,GAAG,SAAUC,IACnBjB,EAAQiB,EAAK,IAGfL,EAAQI,GAAG,SAAUE,IACnBH,EAAOG,EAAQ,GACf,IAQJ,OALAN,EAAQO,QAAQC,KAAKjB,QAAQgB,QAC7BP,EAAQS,QAAQD,KAAKjB,QAAQkB,QAE7BR,EAAiB,QAAID,EAEdC,CACR,CAKMlB,4BACC2B,EAAYC,IAAI7B,KAAKJ,WAAWW,KAAM,CAC1CuB,MAAO9B,KAAKJ,WAAWU,QAAQwB,MAC/BrC,SAAUO,KAAKJ,WAAWY,MAAMd,SAC/BqC,oBAAoB/B,KAAKH,aAAamC,cAC1C,CAKMC,eACL,MAAMC,EAAa,GAAGlC,KAAKP,6BAE3B,IAAKoB,EAAGC,WAAWoB,GAGjB,YAFAC,QAAQC,KAAK,gDAAgDF,KAK/D,MAAMG,EAAOxB,EACVyB,aAAaJ,EAAY,CAAEK,SAAU,UACrCC,QAAQ,iBAAkB,YAE7B3B,EAAG4B,cAAcP,EAAYG,EAAM,CAAEE,SAAU,UAE/CJ,QAAQO,KAAKC,EAAMC,KAAK,0BACzB,CAKMC,QACL,MAAMC,EAAa,GAAG9C,KAAKP,2BAe3BoB,EAAG4B,cAAcK,EAbf,2bAamC,CACnCP,SAAU,SAEb"}
@@ -7,7 +7,6 @@ interface IPrepareServerEntrypointLoadOut<TAppProps = Record<string, any>> {
7
7
  render: TRender;
8
8
  routes: TRouteObject[];
9
9
  abortDelay?: number;
10
- hasEarlyHints?: boolean;
11
10
  onRequest?: IEntrypointOptions<TAppProps>['onRequest'];
12
11
  onRouterReady?: IEntrypointOptions<TAppProps>['onRouterReady'];
13
12
  onShellReady?: IEntrypointOptions<TAppProps>['onShellReady'];
@@ -1,2 +1,2 @@
1
- import t from"fs";import e from"node:process";import r from"path";import i from"chalk";class o{config;entrypoint;onServerCreated;html;constructor(t){this.config=t}static init(t){return new o(t)}async loadEntrypoint(t=!0){if(this.entrypoint&&this.config.isProd)return this.entrypoint;const{root:o,isProd:s,serverFile:n}=this.config.getParams(),a=r.resolve(`${o}/${n}`);let l;try{l=s?(await import(a)).default:(await this.config.getVite().ssrLoadModule(a,{fixStacktrace:!0})).default}catch(t){if(t.message.includes("Cannot find module")&&t.message.includes("/build/"))return this.config.getLogger().error(i.red(`Before starting the server, you need to create a build: ${i.yellow("ssr-boost build")}`)),e.exit(1);throw t}!t&&l.init&&delete l.init;const{render:c,init:h,routes:d,abortDelay:f,hasEarlyHints:g}=l,{onServerCreated:m,...p}=await(h?.({config:this.config}))??{};return this.entrypoint={render:c,routes:d,abortDelay:f,hasEarlyHints:g,...p},this.onServerCreated=m,this.entrypoint}async loadHtml(e){const{isProd:i,root:o,indexFile:s}=this.config.getParams();this.html&&i||(this.html=t.readFileSync(r.resolve(`${o}/${s}`),"utf-8"));let n=this.html;return i||(n=(await this.config.getVite().transformIndexHtml(e.originalUrl,this.html)).replace(/(<script.+)(>[\s\S]+injectIntoGlobalHook.+)/,"$1async$2")),n.split("\x3c!--ssr-outlet--\x3e")}async onAppCreated(){return await this.loadEntrypoint(),await(this.onServerCreated?.(this.config.getApp())),this}}export{o as default};
1
+ import t from"fs";import e from"node:process";import r from"path";import i from"chalk";class o{config;entrypoint;onServerCreated;html;constructor(t){this.config=t}static init(t){return new o(t)}async loadEntrypoint(t=!0){if(this.entrypoint&&this.config.isProd)return this.entrypoint;const{root:o,isProd:n,serverFile:s}=this.config.getParams(),a=r.resolve(`${o}/${s}`);let l;try{l=n?(await import(a)).default:(await this.config.getVite().ssrLoadModule(a,{fixStacktrace:!0})).default}catch(t){if(t.message.includes("Cannot find module")&&t.message.includes("/build/"))return this.config.getLogger().error(i.red(`Before starting the server, you need to create a build: ${i.yellow("ssr-boost build")}`)),e.exit(1);throw t}!t&&l.init&&delete l.init;const{render:c,init:d,routes:h,abortDelay:f}=l,{onServerCreated:g,...m}=await(d?.({config:this.config}))??{};return this.entrypoint={render:c,routes:h,abortDelay:f,...m},this.onServerCreated=g,this.entrypoint}async loadHtml(e){const{isProd:i,root:o,indexFile:n}=this.config.getParams();this.html&&i||(this.html=t.readFileSync(r.resolve(`${o}/${n}`),"utf-8"));let s=this.html;return i||(s=(await this.config.getVite().transformIndexHtml(e.originalUrl,this.html)).replace(/(<script.+)(>[\s\S]+injectIntoGlobalHook.+)/,"$1async$2")),s.split("\x3c!--ssr-outlet--\x3e")}async onAppCreated(){return await this.loadEntrypoint(),await(this.onServerCreated?.(this.config.getApp())),this}}export{o as default};
2
2
  //# sourceMappingURL=prepare-server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prepare-server.js","sources":["../../src/services/prepare-server.ts"],"sourcesContent":["import fs from 'fs';\nimport process from 'node:process';\nimport path from 'path';\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 type ServerConfig from '@services/server-config';\n\ninterface IPrepareServerEntrypointLoadOut<TAppProps = Record<string, any>> {\n render: TRender;\n routes: TRouteObject[];\n abortDelay?: number;\n hasEarlyHints?: boolean;\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 * 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 * Html shell\n */\n protected html: string;\n\n /**\n * @constructor\n */\n protected constructor(config: ServerConfig) {\n this.config = config;\n }\n\n /**\n * Init service\n */\n public static init(config: ServerConfig): PrepareServer {\n return new PrepareServer(config);\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;\n } else {\n resolvedEntrypoint = (await import(entrypointPath)).default;\n }\n } catch (e) {\n if (e.message.includes('Cannot find module') && e.message.includes('/build/')) {\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 )}`,\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, hasEarlyHints } = resolvedEntrypoint;\n const { onServerCreated, ...renderParams } =\n (await init?.({\n config: this.config,\n })) ?? {};\n\n this.entrypoint = {\n render,\n routes,\n abortDelay,\n hasEarlyHints,\n ...renderParams,\n };\n this.onServerCreated = onServerCreated;\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 } = 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 // 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 = (await this.config.getVite()!.transformIndexHtml(req.originalUrl, this.html))\n // Make vite script 'async'\n .replace(/(<script.+)(>[\\s\\S]+injectIntoGlobalHook.+)/, '$1async$2');\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()!);\n\n return this;\n }\n}\n\nexport default PrepareServer;\n"],"names":["PrepareServer","config","entrypoint","onServerCreated","html","constructor","this","static","async","shouldInit","isProd","root","serverFile","getParams","entrypointPath","path","resolve","resolvedEntrypoint","import","default","getVite","ssrLoadModule","fixStacktrace","e","message","includes","getLogger","error","chalk","red","yellow","process","exit","init","render","routes","abortDelay","hasEarlyHints","renderParams","req","indexFile","fs","readFileSync","modifiedHtml","transformIndexHtml","originalUrl","replace","split","loadEntrypoint","getApp"],"mappings":"uFA4BA,MAAMA,EAIeC,OAKTC,WAKAC,gBAKAC,KAKVC,YAAsBJ,GACpBK,KAAKL,OAASA,CACf,CAKMM,YAAYN,GACjB,OAAO,IAAID,EAAcC,EAC1B,CAKMO,qBAAqBC,GAAa,GAEvC,GAAIH,KAAKJ,YAAcI,KAAKL,OAAOS,OACjC,OAAOJ,KAAKJ,WAGd,MAAMS,KAAEA,EAAID,OAAEA,EAAME,WAAEA,GAAeN,KAAKL,OAAOY,YAC3CC,EAAiBC,EAAKC,QAAQ,GAAGL,KAAQC,KAE/C,IAAIK,EAEJ,IAQIA,EAPGP,SAOyBQ,OAAOJ,IAAiBK,eAL5Cb,KAAKL,OAAOmB,UAAWC,cAAcP,EAAgB,CACzDQ,eAAe,KAEjBH,OAIL,CAAC,MAAOI,GACP,GAAIA,EAAEC,QAAQC,SAAS,uBAAyBF,EAAEC,QAAQC,SAAS,WAWjE,OAVAnB,KAAKL,OACFyB,YACAC,MACCC,EAAMC,IACJ,2DAA2DD,EAAME,OAC/D,uBAKDC,EAAQC,KAAK,GAGtB,MAAMT,CACP,EAEId,GAAcQ,EAAmBgB,aAC7BhB,EAAmBgB,KAG5B,MAAMC,OAAEA,EAAMD,KAAEA,EAAIE,OAAEA,EAAMC,WAAEA,EAAUC,cAAEA,GAAkBpB,GACtDd,gBAAEA,KAAoBmC,SACnBL,IAAO,CACZhC,OAAQK,KAAKL,WACR,CAAA,EAWT,OATAK,KAAKJ,WAAa,CAChBgC,SACAC,SACAC,aACAC,mBACGC,GAELhC,KAAKH,gBAAkBA,EAEhBG,KAAKJ,UACb,CAKMM,eAAe+B,GACpB,MAAM7B,OAAEA,EAAMC,KAAEA,EAAI6B,UAAEA,GAAclC,KAAKL,OAAOY,YAE3CP,KAAKF,MAASM,IACjBJ,KAAKF,KAAOqC,EAAGC,aAAa3B,EAAKC,QAAQ,GAAGL,KAAQ6B,KAAc,UAGpE,IAAIG,EAAerC,KAAKF,KAWxB,OATKM,IAIHiC,SAAsBrC,KAAKL,OAAOmB,UAAWwB,mBAAmBL,EAAIM,YAAavC,KAAKF,OAEnF0C,QAAQ,8CAA+C,cAGrDH,EAAaI,MAAM,0BAC3B,CAKMvC,qBAIL,aAHMF,KAAK0C,uBACL1C,KAAKH,kBAAkBG,KAAKL,OAAOgD,WAElC3C,IACR"}
1
+ {"version":3,"file":"prepare-server.js","sources":["../../src/services/prepare-server.ts"],"sourcesContent":["import fs from 'fs';\nimport process from 'node:process';\nimport path from 'path';\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 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 * 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 * Html shell\n */\n protected html: string;\n\n /**\n * @constructor\n */\n protected constructor(config: ServerConfig) {\n this.config = config;\n }\n\n /**\n * Init service\n */\n public static init(config: ServerConfig): PrepareServer {\n return new PrepareServer(config);\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;\n } else {\n resolvedEntrypoint = (await import(entrypointPath)).default;\n }\n } catch (e) {\n if (e.message.includes('Cannot find module') && e.message.includes('/build/')) {\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 )}`,\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 } = resolvedEntrypoint;\n const { onServerCreated, ...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\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 } = 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 // 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 = (await this.config.getVite()!.transformIndexHtml(req.originalUrl, this.html))\n // Make vite script 'async'\n .replace(/(<script.+)(>[\\s\\S]+injectIntoGlobalHook.+)/, '$1async$2');\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()!);\n\n return this;\n }\n}\n\nexport default PrepareServer;\n"],"names":["PrepareServer","config","entrypoint","onServerCreated","html","constructor","this","static","async","shouldInit","isProd","root","serverFile","getParams","entrypointPath","path","resolve","resolvedEntrypoint","import","default","getVite","ssrLoadModule","fixStacktrace","e","message","includes","getLogger","error","chalk","red","yellow","process","exit","init","render","routes","abortDelay","renderParams","req","indexFile","fs","readFileSync","modifiedHtml","transformIndexHtml","originalUrl","replace","split","loadEntrypoint","getApp"],"mappings":"uFA2BA,MAAMA,EAIeC,OAKTC,WAKAC,gBAKAC,KAKVC,YAAsBJ,GACpBK,KAAKL,OAASA,CACf,CAKMM,YAAYN,GACjB,OAAO,IAAID,EAAcC,EAC1B,CAKMO,qBAAqBC,GAAa,GAEvC,GAAIH,KAAKJ,YAAcI,KAAKL,OAAOS,OACjC,OAAOJ,KAAKJ,WAGd,MAAMS,KAAEA,EAAID,OAAEA,EAAME,WAAEA,GAAeN,KAAKL,OAAOY,YAC3CC,EAAiBC,EAAKC,QAAQ,GAAGL,KAAQC,KAE/C,IAAIK,EAEJ,IAQIA,EAPGP,SAOyBQ,OAAOJ,IAAiBK,eAL5Cb,KAAKL,OAAOmB,UAAWC,cAAcP,EAAgB,CACzDQ,eAAe,KAEjBH,OAIL,CAAC,MAAOI,GACP,GAAIA,EAAEC,QAAQC,SAAS,uBAAyBF,EAAEC,QAAQC,SAAS,WAWjE,OAVAnB,KAAKL,OACFyB,YACAC,MACCC,EAAMC,IACJ,2DAA2DD,EAAME,OAC/D,uBAKDC,EAAQC,KAAK,GAGtB,MAAMT,CACP,EAEId,GAAcQ,EAAmBgB,aAC7BhB,EAAmBgB,KAG5B,MAAMC,OAAEA,EAAMD,KAAEA,EAAIE,OAAEA,EAAMC,WAAEA,GAAenB,GACvCd,gBAAEA,KAAoBkC,SACnBJ,IAAO,CACZhC,OAAQK,KAAKL,WACR,CAAA,EAUT,OARAK,KAAKJ,WAAa,CAChBgC,SACAC,SACAC,gBACGC,GAEL/B,KAAKH,gBAAkBA,EAEhBG,KAAKJ,UACb,CAKMM,eAAe8B,GACpB,MAAM5B,OAAEA,EAAMC,KAAEA,EAAI4B,UAAEA,GAAcjC,KAAKL,OAAOY,YAE3CP,KAAKF,MAASM,IACjBJ,KAAKF,KAAOoC,EAAGC,aAAa1B,EAAKC,QAAQ,GAAGL,KAAQ4B,KAAc,UAGpE,IAAIG,EAAepC,KAAKF,KAWxB,OATKM,IAIHgC,SAAsBpC,KAAKL,OAAOmB,UAAWuB,mBAAmBL,EAAIM,YAAatC,KAAKF,OAEnFyC,QAAQ,8CAA+C,cAGrDH,EAAaI,MAAM,0BAC3B,CAKMtC,qBAIL,aAHMF,KAAKyC,uBACLzC,KAAKH,kBAAkBG,KAAKL,OAAO+C,WAElC1C,IACR"}
@@ -152,6 +152,6 @@ declare class SsrManifest {
152
152
  /**
153
153
  * Inject route assets to head html
154
154
  */
155
- injectAssets(context: IRequestContext, hasEarlyHits?: boolean): void;
155
+ injectAssets({ routerContext, html, res, hasEarlyHints }: IRequestContext): void;
156
156
  }
157
157
  export { SsrManifest as default };
@@ -1,2 +1,2 @@
1
- import t from"node:fs";import s from"node:path";import e from"./prepare-server.js";import i from"./server-config.js";const r="\r\n";class n{static instance=null;root;buildDir;manifestName="manifest.json";assetsManifest="assets-manifest.json";alias;routesAssets=null;constructor(t,{buildDir:s,alias:e}={}){this.root=t,this.buildDir=s,this.alias=e}static get(t,s={}){return null===n.instance&&(n.instance=new n(t,s)),n.instance}getAssetsManifestFile(){return`${s.resolve(this.root,this.buildDir||"")}/server/${this.assetsManifest}`}loadClientManifest(){const e=s.resolve(this.root,`${this.buildDir||""}/client/${this.manifestName}`);if(!t.existsSync(e))return{};const i=JSON.parse(t.readFileSync(e,{encoding:"utf-8"}));return t.rmSync(e),i}loadAssetsManifest(){if(null!==this.routesAssets)return this.routesAssets;const s=this.getAssetsManifestFile();return t.existsSync(s)?(this.routesAssets=JSON.parse(t.readFileSync(s,{encoding:"utf-8"})),this.routesAssets):{}}async getRoutesIds(t,s){const e={};for(const i in t){const r=t[i],n=[s,i].filter(Boolean).join("-");if(r.lazy){const t=await r.lazy();e[n]=this.normalizeRoutePath(t?.pathId)}else r.children&&Object.assign(e,await this.getRoutesIds(r.children,n))}return e}async buildRoutesManifest(s){const r=i.init({isProd:!0}),n=e.init(r),a=this.loadClientManifest(),{routes:o}=await n.loadEntrypoint(!1),l=await this.getRoutesIds(o),c=this.getRouteImportPostfix(),h={};Object.entries(l).forEach((([t,e])=>{const i=c.find((t=>void 0!==a[`${e}${t}`])),r=a[`${e}${i||""}`],n=[...r?.assets??[],...r?.css??[],r.file,...(s?r?.imports??[]:[]).map((t=>a[t]?.file))].filter((t=>t&&this.getAssetType(t))).map((t=>`/${t}`));n&&(h[t]=n)})),t.writeFileSync(this.getAssetsManifestFile(),JSON.stringify(h,null,2),{encoding:"utf-8"})}getAliases(){const t={};return this.alias?.forEach((({find:s,replacement:e})=>{"string"==typeof s&&(t[s]=e)})),t}getRouteImportPostfix(){return["","/index"].map((t=>[".js",".ts",".tsx"].map((s=>`${t}${s}`)))).flat()}normalizeRoutePath(t){if(!t)return;let e="";if(t.startsWith("./")||t.startsWith("../"))e=s.resolve(this.root,t);else{const s=this.getAliases(),[i]=t.split("/");s[i]&&(e=t.replace(i,s[i]))}return e.replace(this.root,"").replace(/^\/|\/$/g,"")}getAssets(t){const s=t?.map((({route:t})=>t.id)).filter(Boolean)??[];if(!s.length)return[];const e=this.loadAssetsManifest();return s.map((t=>e[t])).filter(Boolean).flat()}getAssetWeight(t){switch(this.getAssetType(t)){case"style":return 1;case"script":return 2;default:return 3}}getAssetType(t){const s=t.split(".").at(-1)?.toLowerCase();switch(s){case"css":return"style";case"js":return"script";case"svg":case"jpg":case"jpeg":case"png":case"webp":case"gif":case"ico":return"image";case"ttf":case"otf":case"woff":case"woff2":return"font";default:return null}}writeEarlyHits(t,s){s.write(`HTTP/1.1 103 Early Hints${r}`),t.forEach((t=>{const e=this.getAssetType(t);e&&["style","script"].includes(e)&&s.write(`Link: <${t}>; rel=preload; as=${e}${r}`)})),s.write(r)}injectAssets(t,s=!0){const e=this.getAssets(t.routerContext?.matches).sort(((t,s)=>{const e=this.getAssetWeight(t),i=this.getAssetWeight(s);return e===i?0:e-i})),i=e.map((t=>t.endsWith(".css")?`<link rel="stylesheet" href="${t}">`:t.endsWith(".js")?`<script async type="module" src="${t}"><\/script>`:null)).filter(Boolean);t.html.header=t.html.header.replace("</head>",`${i.join("\n")}</head>`),s&&i.length&&t.res.socket&&this.writeEarlyHits(e,t.res.socket)}}export{n as default};
1
+ import t from"node:fs";import s from"node:path";import e from"./prepare-server.js";import i from"./server-config.js";const r="\r\n";class n{static instance=null;root;buildDir;manifestName="manifest.json";assetsManifest="assets-manifest.json";alias;routesAssets=null;constructor(t,{buildDir:s,alias:e}={}){this.root=t,this.buildDir=s,this.alias=e}static get(t,s={}){return null===n.instance&&(n.instance=new n(t,s)),n.instance}getAssetsManifestFile(){return`${s.resolve(this.root,this.buildDir||"")}/server/${this.assetsManifest}`}loadClientManifest(){const e=s.resolve(this.root,`${this.buildDir||""}/client/${this.manifestName}`);if(!t.existsSync(e))return{};const i=JSON.parse(t.readFileSync(e,{encoding:"utf-8"}));return t.rmSync(e),i}loadAssetsManifest(){if(null!==this.routesAssets)return this.routesAssets;const s=this.getAssetsManifestFile();return t.existsSync(s)?(this.routesAssets=JSON.parse(t.readFileSync(s,{encoding:"utf-8"})),this.routesAssets):{}}async getRoutesIds(t,s){const e={};for(const i in t){const r=t[i],n=[s,i].filter(Boolean).join("-");if(r.lazy){const t=await r.lazy();e[n]=this.normalizeRoutePath(t?.pathId)}else r.children&&Object.assign(e,await this.getRoutesIds(r.children,n))}return e}async buildRoutesManifest(s){const r=i.init({isProd:!0}),n=e.init(r),a=this.loadClientManifest(),{routes:o}=await n.loadEntrypoint(!1),l=await this.getRoutesIds(o),c=this.getRouteImportPostfix(),h={};Object.entries(l).forEach((([t,e])=>{const i=c.find((t=>void 0!==a[`${e}${t}`])),r=a[`${e}${i||""}`],n=[...r?.assets??[],...r?.css??[],r.file,...(s?r?.imports??[]:[]).map((t=>a[t]?.file))].filter((t=>t&&this.getAssetType(t))).map((t=>`/${t}`));n&&(h[t]=n)})),t.writeFileSync(this.getAssetsManifestFile(),JSON.stringify(h,null,2),{encoding:"utf-8"})}getAliases(){const t={};return this.alias?.forEach((({find:s,replacement:e})=>{"string"==typeof s&&(t[s]=e)})),t}getRouteImportPostfix(){return["","/index"].map((t=>[".js",".ts",".tsx"].map((s=>`${t}${s}`)))).flat()}normalizeRoutePath(t){if(!t)return;let e="";if(t.startsWith("./")||t.startsWith("../"))e=s.resolve(this.root,t);else{const s=this.getAliases(),[i]=t.split("/");s[i]&&(e=t.replace(i,s[i]))}return e.replace(this.root,"").replace(/^\/|\/$/g,"")}getAssets(t){const s=t?.map((({route:t})=>t.id)).filter(Boolean)??[];if(!s.length)return[];const e=this.loadAssetsManifest();return s.map((t=>e[t])).filter(Boolean).flat()}getAssetWeight(t){switch(this.getAssetType(t)){case"style":return 1;case"script":return 2;default:return 3}}getAssetType(t){const s=t.split(".").at(-1)?.toLowerCase();switch(s){case"css":return"style";case"js":return"script";case"svg":case"jpg":case"jpeg":case"png":case"webp":case"gif":case"ico":return"image";case"ttf":case"otf":case"woff":case"woff2":return"font";default:return null}}writeEarlyHits(t,s){s.write(`HTTP/1.1 103 Early Hints${r}`),t.forEach((t=>{const e=this.getAssetType(t);e&&["style","script"].includes(e)&&s.write(`Link: <${t}>; rel=preload; as=${e}${r}`)})),s.write(r)}injectAssets({routerContext:t,html:s,res:e,hasEarlyHints:i=!0}){const r=this.getAssets(t?.matches).sort(((t,s)=>{const e=this.getAssetWeight(t),i=this.getAssetWeight(s);return e===i?0:e-i})),n=r.map((t=>t.endsWith(".css")?`<link rel="stylesheet" href="${t}">`:t.endsWith(".js")?`<script async type="module" src="${t}"><\/script>`:null)).filter(Boolean);s.header=s.header.replace("</head>",`${n.join("\n")}</head>`),i&&n.length&&e.socket&&this.writeEarlyHits(r,e.socket)}}export{n as default};
2
2
  //# sourceMappingURL=ssr-manifest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ssr-manifest.js","sources":["../../src/services/ssr-manifest.ts"],"sourcesContent":["import fs from 'node:fs';\nimport type { Socket } from 'node:net';\nimport path from 'node:path';\nimport type { AgnosticDataRouteMatch } from '@remix-run/router/dist/utils';\nimport type { RouteObject } from 'react-router-dom';\nimport type { Alias } from 'vite';\nimport type { IRequestContext } from '@node/render';\nimport PrepareServer from '@services/prepare-server';\nimport ServerConfig from '@services/server-config';\n\ninterface ISsrManifestParams {\n alias?: Alias[];\n buildDir?: string;\n}\n\ninterface IManifest {\n [path: string]: {\n assets: string[];\n css: string[];\n file: string;\n imports: string[];\n };\n}\n\nconst CRLF = '\\r\\n';\n\n/**\n * Working with SSR Manifest file\n */\nclass SsrManifest {\n /**\n * Singleton\n */\n protected static instance: SsrManifest | null = null;\n\n /**\n * Project root path\n */\n protected root: string;\n\n /**\n * Build dir\n */\n protected buildDir?: string;\n\n /**\n * Client manifest file name\n */\n protected manifestName = 'manifest.json';\n\n /**\n * Assets manifest file name\n */\n protected assetsManifest = 'assets-manifest.json';\n\n /**\n * Vite resolve aliases\n */\n protected alias?: Alias[];\n\n /**\n * Loaded assets manifest file\n */\n protected routesAssets: Record<string, string[]> | null = null;\n\n /**\n * @constructor\n */\n protected constructor(root: string, { buildDir, alias }: ISsrManifestParams = {}) {\n this.root = root;\n this.buildDir = buildDir;\n this.alias = alias;\n }\n\n /**\n * Get singleton instance\n */\n public static get(root: string, params: ISsrManifestParams = {}): SsrManifest {\n if (SsrManifest.instance === null) {\n SsrManifest.instance = new SsrManifest(root, params);\n }\n\n return SsrManifest.instance;\n }\n\n /**\n * Get assets manifest file name\n */\n protected getAssetsManifestFile(): string {\n const outDir = path.resolve(this.root, this.buildDir || '');\n\n return `${outDir}/server/${this.assetsManifest}`;\n }\n\n /**\n * Load client ssr manifest\n */\n protected loadClientManifest(): IManifest {\n const clientSsrManifest = path.resolve(\n this.root,\n `${this.buildDir || ''}/client/${this.manifestName}`,\n );\n\n if (!fs.existsSync(clientSsrManifest)) {\n return {};\n }\n\n const result = JSON.parse(\n fs.readFileSync(clientSsrManifest, { encoding: 'utf-8' }),\n ) as IManifest;\n\n fs.rmSync(clientSsrManifest);\n\n return result;\n }\n\n /**\n * Load assets manifest\n */\n protected loadAssetsManifest(): Record<string, string[]> {\n if (this.routesAssets !== null) {\n return this.routesAssets;\n }\n\n const manifestFile = this.getAssetsManifestFile();\n\n if (!fs.existsSync(manifestFile)) {\n return {};\n }\n\n this.routesAssets = JSON.parse(fs.readFileSync(manifestFile, { encoding: 'utf-8' })) as Record<\n string,\n string[]\n >;\n\n return this.routesAssets;\n }\n\n /**\n * Recursive walk routes and return id's with route import path\n */\n protected async getRoutesIds(\n routes: RouteObject[],\n index?: string,\n ): Promise<Record<string, string>> {\n const result = {};\n\n for (const routeIndex in routes) {\n const route = routes[routeIndex];\n const routeId = [index, routeIndex].filter(Boolean).join('-');\n\n if (route.lazy) {\n const resolvedRoute = await route.lazy();\n\n result[routeId] = this.normalizeRoutePath(resolvedRoute?.['pathId'] as string);\n } else if (route.children) {\n Object.assign(result, await this.getRoutesIds(route.children, routeId));\n }\n }\n\n return result;\n }\n\n /**\n * Build routes manifest file\n */\n public async buildRoutesManifest(shouldPreloadAssets: boolean): Promise<void> {\n const serverConfig = ServerConfig.init({ isProd: true });\n const prepareServer = PrepareServer.init(serverConfig);\n const manifest = this.loadClientManifest();\n const { routes } = await prepareServer.loadEntrypoint(false);\n const routesPaths = await this.getRoutesIds(routes as RouteObject[]);\n const postfixes = this.getRouteImportPostfix();\n\n const result = {};\n\n // find route assets\n Object.entries(routesPaths).forEach(([routeId, routePath]) => {\n const routePostfix = postfixes.find((postfix) => {\n const filePath = `${routePath}${postfix}`;\n\n return manifest[filePath] !== undefined;\n });\n const routeFile = `${routePath}${routePostfix || ''}`;\n const routeMeta = manifest[routeFile];\n const routeAssets = [\n ...(routeMeta?.assets ?? []),\n ...(routeMeta?.css ?? []),\n routeMeta.file,\n ...(shouldPreloadAssets ? routeMeta?.imports ?? [] : []).map(\n (nestedAsset) => manifest[nestedAsset]?.file,\n ),\n ]\n .filter(\n (asset) =>\n // keep only js,css,image,fonts files\n asset && this.getAssetType(asset),\n )\n .map((asset) => `/${asset}`);\n\n if (routeAssets) {\n result[routeId] = routeAssets;\n }\n });\n\n fs.writeFileSync(this.getAssetsManifestFile(), JSON.stringify(result, null, 2), {\n encoding: 'utf-8',\n });\n }\n\n /**\n * Load aliases manifest\n */\n protected getAliases(): Record<string, string> {\n const aliases = {};\n\n this.alias?.forEach(({ find, replacement }) => {\n if (typeof find !== 'string') {\n return;\n }\n\n aliases[find] = replacement;\n });\n\n return aliases;\n }\n\n /**\n * Return route postfix\n */\n protected getRouteImportPostfix(): string[] {\n return ['', '/index']\n .map((prefix) => ['.js', '.ts', '.tsx'].map((ext) => `${prefix}${ext}`))\n .flat();\n }\n\n /**\n * Normalized route path\n */\n protected normalizeRoutePath(routePath?: string): string | undefined {\n if (!routePath) {\n return;\n }\n\n let fullPath = '';\n\n // relative import\n if (routePath.startsWith('./') || routePath.startsWith('../')) {\n fullPath = path.resolve(this.root, routePath);\n } else {\n // alias import\n const aliases = this.getAliases();\n // get alias\n const [routeAlias] = routePath.split('/');\n\n if (aliases[routeAlias]) {\n fullPath = routePath.replace(routeAlias, aliases[routeAlias]);\n }\n }\n\n return fullPath.replace(this.root, '').replace(/^\\/|\\/$/g, '');\n }\n\n /**\n * Get provided route assets\n */\n public getAssets(routes?: AgnosticDataRouteMatch[]): string[] {\n const routeIds = routes?.map(({ route }) => route.id).filter(Boolean) ?? [];\n\n if (!routeIds.length) {\n return [];\n }\n\n const routesAssets = this.loadAssetsManifest();\n\n return routeIds\n .map((routeId) => routesAssets[routeId])\n .filter(Boolean)\n .flat();\n }\n\n /**\n * Get asset weight\n */\n protected getAssetWeight(asset: string): number {\n const type = this.getAssetType(asset);\n\n switch (type) {\n case 'style':\n return 1;\n\n case 'script':\n return 2;\n\n default:\n return 3;\n }\n }\n\n /**\n * Get asset type\n */\n protected getAssetType(asset: string): string | null {\n const ext = asset.split('.').at(-1)?.toLowerCase();\n\n switch (ext) {\n case 'css':\n return 'style';\n\n case 'js':\n return 'script';\n\n case 'svg':\n case 'jpg':\n case 'jpeg':\n case 'png':\n case 'webp':\n case 'gif':\n case 'ico':\n return 'image';\n\n case 'ttf':\n case 'otf':\n case 'woff':\n case 'woff2':\n return 'font';\n\n default:\n return null;\n }\n }\n\n /**\n * Write 103 Early Hits header\n */\n public writeEarlyHits(assets: string[], socket: Socket): void {\n socket.write(`HTTP/1.1 103 Early Hints${CRLF}`);\n assets.forEach((asset) => {\n const type = this.getAssetType(asset);\n\n if (!type || !['style', 'script'].includes(type)) {\n return;\n }\n\n socket.write(`Link: <${asset}>; rel=preload; as=${type}${CRLF}`);\n });\n socket.write(CRLF);\n }\n\n /**\n * Inject route assets to head html\n */\n public injectAssets(context: IRequestContext, hasEarlyHits = true): void {\n const assets = this.getAssets(context.routerContext?.matches).sort((a, b) => {\n const aWeight = this.getAssetWeight(a);\n const bWeight = this.getAssetWeight(b);\n\n return aWeight === bWeight ? 0 : aWeight - bWeight;\n });\n const htmlAssets = assets\n .map((asset) => {\n if (asset.endsWith('.css')) {\n return `<link rel=\"stylesheet\" href=\"${asset}\">`;\n } else if (asset.endsWith('.js')) {\n return `<script async type=\"module\" src=\"${asset}\"></script>`;\n }\n\n return null;\n })\n .filter(Boolean);\n\n context.html.header = context.html.header.replace('</head>', `${htmlAssets.join('\\n')}</head>`);\n\n if (hasEarlyHits && htmlAssets.length && context.res.socket) {\n this.writeEarlyHits(assets, context.res.socket);\n }\n }\n}\n\nexport default SsrManifest;\n"],"names":["CRLF","SsrManifest","static","root","buildDir","manifestName","assetsManifest","alias","routesAssets","constructor","this","params","instance","getAssetsManifestFile","path","resolve","loadClientManifest","clientSsrManifest","fs","existsSync","result","JSON","parse","readFileSync","encoding","rmSync","loadAssetsManifest","manifestFile","async","routes","index","routeIndex","route","routeId","filter","Boolean","join","lazy","resolvedRoute","normalizeRoutePath","children","Object","assign","getRoutesIds","shouldPreloadAssets","serverConfig","ServerConfig","init","isProd","prepareServer","PrepareServer","manifest","loadEntrypoint","routesPaths","postfixes","getRouteImportPostfix","entries","forEach","routePath","routePostfix","find","postfix","undefined","routeMeta","routeAssets","assets","css","file","imports","map","nestedAsset","asset","getAssetType","writeFileSync","stringify","getAliases","aliases","replacement","prefix","ext","flat","fullPath","startsWith","routeAlias","split","replace","getAssets","routeIds","id","length","getAssetWeight","at","toLowerCase","writeEarlyHits","socket","write","type","includes","injectAssets","context","hasEarlyHits","routerContext","matches","sort","a","b","aWeight","bWeight","htmlAssets","endsWith","html","header","res"],"mappings":"qHAwBA,MAAMA,EAAO,OAKb,MAAMC,EAIMC,gBAAsC,KAKtCC,KAKAC,SAKAC,aAAe,gBAKfC,eAAiB,uBAKjBC,MAKAC,aAAgD,KAK1DC,YAAsBN,GAAcC,SAAEA,EAAQG,MAAEA,GAA8B,CAAA,GAC5EG,KAAKP,KAAOA,EACZO,KAAKN,SAAWA,EAChBM,KAAKH,MAAQA,CACd,CAKML,WAAWC,EAAcQ,EAA6B,IAK3D,OAJ6B,OAAzBV,EAAYW,WACdX,EAAYW,SAAW,IAAIX,EAAYE,EAAMQ,IAGxCV,EAAYW,QACpB,CAKSC,wBAGR,MAAO,GAFQC,EAAKC,QAAQL,KAAKP,KAAMO,KAAKN,UAAY,cAE7BM,KAAKJ,gBACjC,CAKSU,qBACR,MAAMC,EAAoBH,EAAKC,QAC7BL,KAAKP,KACL,GAAGO,KAAKN,UAAY,aAAaM,KAAKL,gBAGxC,IAAKa,EAAGC,WAAWF,GACjB,MAAO,GAGT,MAAMG,EAASC,KAAKC,MAClBJ,EAAGK,aAAaN,EAAmB,CAAEO,SAAU,WAKjD,OAFAN,EAAGO,OAAOR,GAEHG,CACR,CAKSM,qBACR,GAA0B,OAAtBhB,KAAKF,aACP,OAAOE,KAAKF,aAGd,MAAMmB,EAAejB,KAAKG,wBAE1B,OAAKK,EAAGC,WAAWQ,IAInBjB,KAAKF,aAAea,KAAKC,MAAMJ,EAAGK,aAAaI,EAAc,CAAEH,SAAU,WAKlEd,KAAKF,cARH,EASV,CAKSoB,mBACRC,EACAC,GAEA,MAAMV,EAAS,CAAA,EAEf,IAAK,MAAMW,KAAcF,EAAQ,CAC/B,MAAMG,EAAQH,EAAOE,GACfE,EAAU,CAACH,EAAOC,GAAYG,OAAOC,SAASC,KAAK,KAEzD,GAAIJ,EAAMK,KAAM,CACd,MAAMC,QAAsBN,EAAMK,OAElCjB,EAAOa,GAAWvB,KAAK6B,mBAAmBD,GAAwB,OACnE,MAAUN,EAAMQ,UACfC,OAAOC,OAAOtB,QAAcV,KAAKiC,aAAaX,EAAMQ,SAAUP,GAEjE,CAED,OAAOb,CACR,CAKMQ,0BAA0BgB,GAC/B,MAAMC,EAAeC,EAAaC,KAAK,CAAEC,QAAQ,IAC3CC,EAAgBC,EAAcH,KAAKF,GACnCM,EAAWzC,KAAKM,sBAChBa,OAAEA,SAAiBoB,EAAcG,gBAAe,GAChDC,QAAoB3C,KAAKiC,aAAad,GACtCyB,EAAY5C,KAAK6C,wBAEjBnC,EAAS,CAAA,EAGfqB,OAAOe,QAAQH,GAAaI,SAAQ,EAAExB,EAASyB,MAC7C,MAAMC,EAAeL,EAAUM,MAAMC,QAGLC,IAAvBX,EAFU,GAAGO,IAAYG,OAK5BE,EAAYZ,EADA,GAAGO,IAAYC,GAAgB,MAE3CK,EAAc,IACdD,GAAWE,QAAU,MACrBF,GAAWG,KAAO,GACtBH,EAAUI,SACNvB,EAAsBmB,GAAWK,SAAW,GAAK,IAAIC,KACtDC,GAAgBnB,EAASmB,IAAcH,QAGzCjC,QACEqC,GAECA,GAAS7D,KAAK8D,aAAaD,KAE9BF,KAAKE,GAAU,IAAIA,MAElBP,IACF5C,EAAOa,GAAW+B,EACnB,IAGH9C,EAAGuD,cAAc/D,KAAKG,wBAAyBQ,KAAKqD,UAAUtD,EAAQ,KAAM,GAAI,CAC9EI,SAAU,SAEb,CAKSmD,aACR,MAAMC,EAAU,CAAA,EAUhB,OARAlE,KAAKH,OAAOkD,SAAQ,EAAGG,OAAMiB,kBACP,iBAATjB,IAIXgB,EAAQhB,GAAQiB,EAAW,IAGtBD,CACR,CAKSrB,wBACR,MAAO,CAAC,GAAI,UACTc,KAAKS,GAAW,CAAC,MAAO,MAAO,QAAQT,KAAKU,GAAQ,GAAGD,IAASC,QAChEC,MACJ,CAKSzC,mBAAmBmB,GAC3B,IAAKA,EACH,OAGF,IAAIuB,EAAW,GAGf,GAAIvB,EAAUwB,WAAW,OAASxB,EAAUwB,WAAW,OACrDD,EAAWnE,EAAKC,QAAQL,KAAKP,KAAMuD,OAC9B,CAEL,MAAMkB,EAAUlE,KAAKiE,cAEdQ,GAAczB,EAAU0B,MAAM,KAEjCR,EAAQO,KACVF,EAAWvB,EAAU2B,QAAQF,EAAYP,EAAQO,IAEpD,CAED,OAAOF,EAASI,QAAQ3E,KAAKP,KAAM,IAAIkF,QAAQ,WAAY,GAC5D,CAKMC,UAAUzD,GACf,MAAM0D,EAAW1D,GAAQwC,KAAI,EAAGrC,WAAYA,EAAMwD,KAAItD,OAAOC,UAAY,GAEzE,IAAKoD,EAASE,OACZ,MAAO,GAGT,MAAMjF,EAAeE,KAAKgB,qBAE1B,OAAO6D,EACJlB,KAAKpC,GAAYzB,EAAayB,KAC9BC,OAAOC,SACP6C,MACJ,CAKSU,eAAenB,GAGvB,OAFa7D,KAAK8D,aAAaD,IAG7B,IAAK,QACH,OAAO,EAET,IAAK,SACH,OAAO,EAET,QACE,OAAO,EAEZ,CAKSC,aAAaD,GACrB,MAAMQ,EAAMR,EAAMa,MAAM,KAAKO,IAAI,IAAIC,cAErC,OAAQb,GACN,IAAK,MACH,MAAO,QAET,IAAK,KACH,MAAO,SAET,IAAK,MACL,IAAK,MACL,IAAK,OACL,IAAK,MACL,IAAK,OACL,IAAK,MACL,IAAK,MACH,MAAO,QAET,IAAK,MACL,IAAK,MACL,IAAK,OACL,IAAK,QACH,MAAO,OAET,QACE,OAAO,KAEZ,CAKMc,eAAe5B,EAAkB6B,GACtCA,EAAOC,MAAM,2BAA2B/F,KACxCiE,EAAOR,SAASc,IACd,MAAMyB,EAAOtF,KAAK8D,aAAaD,GAE1ByB,GAAS,CAAC,QAAS,UAAUC,SAASD,IAI3CF,EAAOC,MAAM,UAAUxB,uBAA2ByB,IAAOhG,IAAO,IAElE8F,EAAOC,MAAM/F,EACd,CAKMkG,aAAaC,EAA0BC,GAAe,GAC3D,MAAMnC,EAASvD,KAAK4E,UAAUa,EAAQE,eAAeC,SAASC,MAAK,CAACC,EAAGC,KACrE,MAAMC,EAAUhG,KAAKgF,eAAec,GAC9BG,EAAUjG,KAAKgF,eAAee,GAEpC,OAAOC,IAAYC,EAAU,EAAID,EAAUC,CAAO,IAE9CC,EAAa3C,EAChBI,KAAKE,GACAA,EAAMsC,SAAS,QACV,gCAAgCtC,MAC9BA,EAAMsC,SAAS,OACjB,oCAAoCtC,gBAGtC,OAERrC,OAAOC,SAEVgE,EAAQW,KAAKC,OAASZ,EAAQW,KAAKC,OAAO1B,QAAQ,UAAW,GAAGuB,EAAWxE,KAAK,gBAE5EgE,GAAgBQ,EAAWnB,QAAUU,EAAQa,IAAIlB,QACnDpF,KAAKmF,eAAe5B,EAAQkC,EAAQa,IAAIlB,OAE3C"}
1
+ {"version":3,"file":"ssr-manifest.js","sources":["../../src/services/ssr-manifest.ts"],"sourcesContent":["import fs from 'node:fs';\nimport type { Socket } from 'node:net';\nimport path from 'node:path';\nimport type { AgnosticDataRouteMatch } from '@remix-run/router/dist/utils';\nimport type { RouteObject } from 'react-router-dom';\nimport type { Alias } from 'vite';\nimport type { IRequestContext } from '@node/render';\nimport PrepareServer from '@services/prepare-server';\nimport ServerConfig from '@services/server-config';\n\ninterface ISsrManifestParams {\n alias?: Alias[];\n buildDir?: string;\n}\n\ninterface IManifest {\n [path: string]: {\n assets: string[];\n css: string[];\n file: string;\n imports: string[];\n };\n}\n\nconst CRLF = '\\r\\n';\n\n/**\n * Working with SSR Manifest file\n */\nclass SsrManifest {\n /**\n * Singleton\n */\n protected static instance: SsrManifest | null = null;\n\n /**\n * Project root path\n */\n protected root: string;\n\n /**\n * Build dir\n */\n protected buildDir?: string;\n\n /**\n * Client manifest file name\n */\n protected manifestName = 'manifest.json';\n\n /**\n * Assets manifest file name\n */\n protected assetsManifest = 'assets-manifest.json';\n\n /**\n * Vite resolve aliases\n */\n protected alias?: Alias[];\n\n /**\n * Loaded assets manifest file\n */\n protected routesAssets: Record<string, string[]> | null = null;\n\n /**\n * @constructor\n */\n protected constructor(root: string, { buildDir, alias }: ISsrManifestParams = {}) {\n this.root = root;\n this.buildDir = buildDir;\n this.alias = alias;\n }\n\n /**\n * Get singleton instance\n */\n public static get(root: string, params: ISsrManifestParams = {}): SsrManifest {\n if (SsrManifest.instance === null) {\n SsrManifest.instance = new SsrManifest(root, params);\n }\n\n return SsrManifest.instance;\n }\n\n /**\n * Get assets manifest file name\n */\n protected getAssetsManifestFile(): string {\n const outDir = path.resolve(this.root, this.buildDir || '');\n\n return `${outDir}/server/${this.assetsManifest}`;\n }\n\n /**\n * Load client ssr manifest\n */\n protected loadClientManifest(): IManifest {\n const clientSsrManifest = path.resolve(\n this.root,\n `${this.buildDir || ''}/client/${this.manifestName}`,\n );\n\n if (!fs.existsSync(clientSsrManifest)) {\n return {};\n }\n\n const result = JSON.parse(\n fs.readFileSync(clientSsrManifest, { encoding: 'utf-8' }),\n ) as IManifest;\n\n fs.rmSync(clientSsrManifest);\n\n return result;\n }\n\n /**\n * Load assets manifest\n */\n protected loadAssetsManifest(): Record<string, string[]> {\n if (this.routesAssets !== null) {\n return this.routesAssets;\n }\n\n const manifestFile = this.getAssetsManifestFile();\n\n if (!fs.existsSync(manifestFile)) {\n return {};\n }\n\n this.routesAssets = JSON.parse(fs.readFileSync(manifestFile, { encoding: 'utf-8' })) as Record<\n string,\n string[]\n >;\n\n return this.routesAssets;\n }\n\n /**\n * Recursive walk routes and return id's with route import path\n */\n protected async getRoutesIds(\n routes: RouteObject[],\n index?: string,\n ): Promise<Record<string, string>> {\n const result = {};\n\n for (const routeIndex in routes) {\n const route = routes[routeIndex];\n const routeId = [index, routeIndex].filter(Boolean).join('-');\n\n if (route.lazy) {\n const resolvedRoute = await route.lazy();\n\n result[routeId] = this.normalizeRoutePath(resolvedRoute?.['pathId'] as string);\n } else if (route.children) {\n Object.assign(result, await this.getRoutesIds(route.children, routeId));\n }\n }\n\n return result;\n }\n\n /**\n * Build routes manifest file\n */\n public async buildRoutesManifest(shouldPreloadAssets: boolean): Promise<void> {\n const serverConfig = ServerConfig.init({ isProd: true });\n const prepareServer = PrepareServer.init(serverConfig);\n const manifest = this.loadClientManifest();\n const { routes } = await prepareServer.loadEntrypoint(false);\n const routesPaths = await this.getRoutesIds(routes as RouteObject[]);\n const postfixes = this.getRouteImportPostfix();\n\n const result = {};\n\n // find route assets\n Object.entries(routesPaths).forEach(([routeId, routePath]) => {\n const routePostfix = postfixes.find((postfix) => {\n const filePath = `${routePath}${postfix}`;\n\n return manifest[filePath] !== undefined;\n });\n const routeFile = `${routePath}${routePostfix || ''}`;\n const routeMeta = manifest[routeFile];\n const routeAssets = [\n ...(routeMeta?.assets ?? []),\n ...(routeMeta?.css ?? []),\n routeMeta.file,\n ...(shouldPreloadAssets ? routeMeta?.imports ?? [] : []).map(\n (nestedAsset) => manifest[nestedAsset]?.file,\n ),\n ]\n .filter(\n (asset) =>\n // keep only js,css,image,fonts files\n asset && this.getAssetType(asset),\n )\n .map((asset) => `/${asset}`);\n\n if (routeAssets) {\n result[routeId] = routeAssets;\n }\n });\n\n fs.writeFileSync(this.getAssetsManifestFile(), JSON.stringify(result, null, 2), {\n encoding: 'utf-8',\n });\n }\n\n /**\n * Load aliases manifest\n */\n protected getAliases(): Record<string, string> {\n const aliases = {};\n\n this.alias?.forEach(({ find, replacement }) => {\n if (typeof find !== 'string') {\n return;\n }\n\n aliases[find] = replacement;\n });\n\n return aliases;\n }\n\n /**\n * Return route postfix\n */\n protected getRouteImportPostfix(): string[] {\n return ['', '/index']\n .map((prefix) => ['.js', '.ts', '.tsx'].map((ext) => `${prefix}${ext}`))\n .flat();\n }\n\n /**\n * Normalized route path\n */\n protected normalizeRoutePath(routePath?: string): string | undefined {\n if (!routePath) {\n return;\n }\n\n let fullPath = '';\n\n // relative import\n if (routePath.startsWith('./') || routePath.startsWith('../')) {\n fullPath = path.resolve(this.root, routePath);\n } else {\n // alias import\n const aliases = this.getAliases();\n // get alias\n const [routeAlias] = routePath.split('/');\n\n if (aliases[routeAlias]) {\n fullPath = routePath.replace(routeAlias, aliases[routeAlias]);\n }\n }\n\n return fullPath.replace(this.root, '').replace(/^\\/|\\/$/g, '');\n }\n\n /**\n * Get provided route assets\n */\n public getAssets(routes?: AgnosticDataRouteMatch[]): string[] {\n const routeIds = routes?.map(({ route }) => route.id).filter(Boolean) ?? [];\n\n if (!routeIds.length) {\n return [];\n }\n\n const routesAssets = this.loadAssetsManifest();\n\n return routeIds\n .map((routeId) => routesAssets[routeId])\n .filter(Boolean)\n .flat();\n }\n\n /**\n * Get asset weight\n */\n protected getAssetWeight(asset: string): number {\n const type = this.getAssetType(asset);\n\n switch (type) {\n case 'style':\n return 1;\n\n case 'script':\n return 2;\n\n default:\n return 3;\n }\n }\n\n /**\n * Get asset type\n */\n protected getAssetType(asset: string): string | null {\n const ext = asset.split('.').at(-1)?.toLowerCase();\n\n switch (ext) {\n case 'css':\n return 'style';\n\n case 'js':\n return 'script';\n\n case 'svg':\n case 'jpg':\n case 'jpeg':\n case 'png':\n case 'webp':\n case 'gif':\n case 'ico':\n return 'image';\n\n case 'ttf':\n case 'otf':\n case 'woff':\n case 'woff2':\n return 'font';\n\n default:\n return null;\n }\n }\n\n /**\n * Write 103 Early Hits header\n */\n public writeEarlyHits(assets: string[], socket: Socket): void {\n socket.write(`HTTP/1.1 103 Early Hints${CRLF}`);\n assets.forEach((asset) => {\n const type = this.getAssetType(asset);\n\n if (!type || !['style', 'script'].includes(type)) {\n return;\n }\n\n socket.write(`Link: <${asset}>; rel=preload; as=${type}${CRLF}`);\n });\n socket.write(CRLF);\n }\n\n /**\n * Inject route assets to head html\n */\n public injectAssets({ routerContext, html, res, hasEarlyHints = true }: IRequestContext): void {\n const assets = this.getAssets(routerContext?.matches).sort((a, b) => {\n const aWeight = this.getAssetWeight(a);\n const bWeight = this.getAssetWeight(b);\n\n return aWeight === bWeight ? 0 : aWeight - bWeight;\n });\n const htmlAssets = assets\n .map((asset) => {\n if (asset.endsWith('.css')) {\n return `<link rel=\"stylesheet\" href=\"${asset}\">`;\n } else if (asset.endsWith('.js')) {\n return `<script async type=\"module\" src=\"${asset}\"></script>`;\n }\n\n return null;\n })\n .filter(Boolean);\n\n html.header = html.header.replace('</head>', `${htmlAssets.join('\\n')}</head>`);\n\n if (hasEarlyHints && htmlAssets.length && res.socket) {\n this.writeEarlyHits(assets, res.socket);\n }\n }\n}\n\nexport default SsrManifest;\n"],"names":["CRLF","SsrManifest","static","root","buildDir","manifestName","assetsManifest","alias","routesAssets","constructor","this","params","instance","getAssetsManifestFile","path","resolve","loadClientManifest","clientSsrManifest","fs","existsSync","result","JSON","parse","readFileSync","encoding","rmSync","loadAssetsManifest","manifestFile","async","routes","index","routeIndex","route","routeId","filter","Boolean","join","lazy","resolvedRoute","normalizeRoutePath","children","Object","assign","getRoutesIds","shouldPreloadAssets","serverConfig","ServerConfig","init","isProd","prepareServer","PrepareServer","manifest","loadEntrypoint","routesPaths","postfixes","getRouteImportPostfix","entries","forEach","routePath","routePostfix","find","postfix","undefined","routeMeta","routeAssets","assets","css","file","imports","map","nestedAsset","asset","getAssetType","writeFileSync","stringify","getAliases","aliases","replacement","prefix","ext","flat","fullPath","startsWith","routeAlias","split","replace","getAssets","routeIds","id","length","getAssetWeight","at","toLowerCase","writeEarlyHits","socket","write","type","includes","injectAssets","routerContext","html","res","hasEarlyHints","matches","sort","a","b","aWeight","bWeight","htmlAssets","endsWith","header"],"mappings":"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"}
@@ -1,5 +0,0 @@
1
- /**
2
- * Change general directive Disallow to Allow in robots.txt.
3
- */
4
- declare const unlockRobots: (root: string, buildFolder: string) => void;
5
- export { unlockRobots as default };
@@ -1,2 +0,0 @@
1
- import o from"node:fs";import t from"node:path";import e from"chalk";const n=(n,l)=>{const i=`${t.resolve(n,l)}/client/robots.txt`;if(!o.existsSync(i))return void console.warn(`Failed to unlock robots.txt, file not exist: ${i}`);const r=o.readFileSync(i,{encoding:"utf-8"}).replace(/Disallow: \/$/m,"Allow: /");o.writeFileSync(i,r,{encoding:"utf-8"}),console.info(e.blue("\nrobots.txt unlocked."))};export{n as default};
2
- //# sourceMappingURL=unlock-robots.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"unlock-robots.js","sources":["../../src/helpers/unlock-robots.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport chalk from 'chalk';\n\n/**\n * Change general directive Disallow to Allow in robots.txt.\n */\nconst unlockRobots = (root: string, buildFolder: string): void => {\n const buildPath = path.resolve(root, buildFolder);\n const robotsFile = `${buildPath}/client/robots.txt`;\n\n if (!fs.existsSync(robotsFile)) {\n console.warn(`Failed to unlock robots.txt, file not exist: ${robotsFile}`);\n\n return;\n }\n\n const data = fs\n .readFileSync(robotsFile, { encoding: 'utf-8' })\n .replace(/Disallow: \\/$/m, 'Allow: /');\n\n fs.writeFileSync(robotsFile, data, { encoding: 'utf-8' });\n\n console.info(chalk.blue('\\nrobots.txt unlocked.'));\n};\n\nexport default unlockRobots;\n"],"names":["unlockRobots","root","buildFolder","robotsFile","path","resolve","fs","existsSync","console","warn","data","readFileSync","encoding","replace","writeFileSync","info","chalk","blue"],"mappings":"qEAOA,MAAMA,EAAe,CAACC,EAAcC,KAClC,MACMC,EAAa,GADDC,EAAKC,QAAQJ,EAAMC,uBAGrC,IAAKI,EAAGC,WAAWJ,GAGjB,YAFAK,QAAQC,KAAK,gDAAgDN,KAK/D,MAAMO,EAAOJ,EACVK,aAAaR,EAAY,CAAES,SAAU,UACrCC,QAAQ,iBAAkB,YAE7BP,EAAGQ,cAAcX,EAAYO,EAAM,CAAEE,SAAU,UAE/CJ,QAAQO,KAAKC,EAAMC,KAAK,0BAA0B"}