@lovable.dev/vite-tanstack-config 2.19.3 → 2.19.5

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.
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- let node_fs_promises = require("node:fs/promises");
3
2
  let node_path = require("node:path");
3
+ let node_fs_promises = require("node:fs/promises");
4
4
  //#region src/dev-server-bridge/error-collector.ts
5
5
  const DEFAULT_ENDPOINT = "/__lovable/error-collector";
6
6
  const DEFAULT_OUTPUT_FILE = "/tmp/runtime-errors.log";
@@ -1,5 +1,5 @@
1
- import { appendFile, mkdir, writeFile } from "node:fs/promises";
2
1
  import { dirname, resolve } from "node:path";
2
+ import { appendFile, mkdir, writeFile } from "node:fs/promises";
3
3
  //#region src/dev-server-bridge/error-collector.ts
4
4
  const DEFAULT_ENDPOINT = "/__lovable/error-collector";
5
5
  const DEFAULT_OUTPUT_FILE = "/tmp/runtime-errors.log";
package/dist/index.cjs CHANGED
@@ -21,6 +21,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  enumerable: true
22
22
  }) : target, mod));
23
23
  //#endregion
24
+ let node_path = require("node:path");
24
25
  let node_url = require("node:url");
25
26
  let vite = require("vite");
26
27
  let node_https = require("node:https");
@@ -152,7 +153,7 @@ function bundledDevCssUrlShim() {
152
153
  //#endregion
153
154
  //#region package.json
154
155
  var name = "@lovable.dev/vite-tanstack-config";
155
- var version = "2.19.3";
156
+ var version = "2.19.5";
156
157
  //#endregion
157
158
  //#region src/logging.ts
158
159
  const PACKAGE_NAME = "@lovable.dev/vite-tanstack-config";
@@ -731,9 +732,14 @@ function lovableBuildErrorDiagnostics() {
731
732
  }
732
733
  };
733
734
  }
735
+ function nitroEmitDirs(dirs) {
736
+ if (!dirs) return [SERVER_OUTPUT_DIR];
737
+ const found = [dirs.nitroOutput.serverDir, ...dirs.entryDirs].filter((dir) => !!dir);
738
+ return [...new Set(found)];
739
+ }
734
740
  const NODEJS_COMPAT_DEFAULT_ON_DATE = "2026-08-04";
735
- const SANDBOX_WRANGLER_CONFIG_PATH = `${SERVER_OUTPUT_DIR}/wrangler.json`;
736
- function stripRedundantNodejsCompatFlag() {
741
+ const NITRO_WRANGLER_CONFIG = "wrangler.json";
742
+ function stripRedundantNodejsCompatFlag(dirs) {
737
743
  let root = process.cwd();
738
744
  return {
739
745
  name: "lovable-strip-redundant-nodejs-compat",
@@ -745,13 +751,18 @@ function stripRedundantNodejsCompatFlag() {
745
751
  order: "post",
746
752
  handler: async () => {
747
753
  const { readFile, writeFile } = await import("node:fs/promises");
748
- const configPath = (await import("node:path")).join(root, SANDBOX_WRANGLER_CONFIG_PATH);
754
+ let configPath;
749
755
  let parsed;
750
- try {
751
- parsed = JSON.parse(await readFile(configPath, "utf8"));
752
- } catch {
753
- return;
756
+ for (const dir of nitroEmitDirs(dirs)) {
757
+ configPath = (0, node_path.join)((0, node_path.resolve)(root, dir), NITRO_WRANGLER_CONFIG);
758
+ try {
759
+ parsed = JSON.parse(await readFile(configPath, "utf8"));
760
+ break;
761
+ } catch {
762
+ configPath = void 0;
763
+ }
754
764
  }
765
+ if (configPath === void 0) return;
755
766
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return;
756
767
  const config = parsed;
757
768
  if (typeof config.compatibility_date !== "string") return;
@@ -768,14 +779,15 @@ function stripRedundantNodejsCompatFlag() {
768
779
  };
769
780
  }
770
781
  const NITRO_SERVER_ENTRY = "index.mjs";
771
- const NITRO_WRANGLER_CONFIG = "wrangler.json";
782
+ const NITRO_DEFAULT_OUTPUT_DIR = ".output";
783
+ const VITE_DEFAULT_OUTPUT_DIR = "dist";
772
784
  const DEFAULT_SERVER_ENTRY_NAME = "server";
773
785
  const PRERENDER_PREVIEW_HOST = "127.0.0.1";
774
786
  const TSS_PRERENDERING_ENV = "TSS_PRERENDERING";
775
787
  const SHIM_MARKER = "// Generated by @lovable.dev/vite-tanstack-config for the prerender preview server.";
776
- function prerenderShimSource(vars) {
788
+ function prerenderShimSource(vars, entrySpecifier) {
777
789
  return `${SHIM_MARKER}
778
- import server from "./${NITRO_SERVER_ENTRY}";
790
+ import server from "${entrySpecifier}";
779
791
 
780
792
  const env = ${JSON.stringify(vars)};
781
793
  const ctx = { waitUntil() {}, passThroughOnException() {}, props: {} };
@@ -790,16 +802,54 @@ export default {
790
802
  };
791
803
  `;
792
804
  }
793
- function prerenderPreviewShim(state) {
805
+ function captureNitroServerDir(nitroOpts) {
806
+ const output = {};
807
+ const hooks = nitroOpts.hooks ?? {};
808
+ const userCompiled = hooks.compiled;
809
+ nitroOpts.hooks = {
810
+ ...hooks,
811
+ compiled: async (nitro) => {
812
+ const serverDir = nitro?.options?.output?.serverDir;
813
+ if (typeof serverDir === "string") output.serverDir = serverDir;
814
+ if (typeof userCompiled === "function") await userCompiled(nitro);
815
+ }
816
+ };
817
+ return output;
818
+ }
819
+ function previewServerOutputDir(viteConfig) {
820
+ const ssrOutDir = viteConfig?.environments?.ssr?.build?.outDir;
821
+ if (typeof ssrOutDir === "string") return ssrOutDir;
822
+ const rootOutDir = viteConfig?.build?.outDir;
823
+ return (0, node_path.join)(typeof rootOutDir === "string" ? rootOutDir : VITE_DEFAULT_OUTPUT_DIR, "server");
824
+ }
825
+ function pinnedNitroServerDir(nitroOpts) {
826
+ const output = nitroOpts.output;
827
+ const dir = typeof output?.dir === "string" ? output.dir : void 0;
828
+ const serverDir = typeof output?.serverDir === "string" ? output.serverDir : void 0;
829
+ const resolved = serverDir ? serverDir.replace(/\{\{\s*output\.dir\s*\}\}/g, dir ?? NITRO_DEFAULT_OUTPUT_DIR) : dir && (0, node_path.join)(dir, "server");
830
+ return resolved && !resolved.includes("{{") ? resolved : void 0;
831
+ }
832
+ function prerenderShimDirs(viteConfig, nitroOpts) {
833
+ const shimDir = previewServerOutputDir(viteConfig);
834
+ const candidates = [
835
+ pinnedNitroServerDir(nitroOpts),
836
+ (0, node_path.join)(NITRO_DEFAULT_OUTPUT_DIR, "server"),
837
+ shimDir
838
+ ];
839
+ return {
840
+ shimDir,
841
+ entryDirs: [...new Set(candidates.filter((dir) => !!dir))],
842
+ nitroOutput: captureNitroServerDir(nitroOpts)
843
+ };
844
+ }
845
+ function prerenderPreviewShim(state, dirs) {
794
846
  let root = process.cwd();
795
- let serverOutDir = SERVER_OUTPUT_DIR;
796
847
  let serverEntryName = DEFAULT_SERVER_ENTRY_NAME;
797
848
  return {
798
849
  name: "lovable-prerender-preview-shim",
799
850
  apply: "build",
800
851
  config(userConfig) {
801
852
  const ssrBuild = userConfig.environments?.ssr?.build;
802
- if (ssrBuild?.outDir) serverOutDir = ssrBuild.outDir;
803
853
  const input = ssrBuild?.rolldownOptions?.input ?? ssrBuild?.rollupOptions?.input;
804
854
  if (typeof input === "string") serverEntryName = input;
805
855
  },
@@ -809,8 +859,7 @@ function prerenderPreviewShim(state) {
809
859
  buildApp: {
810
860
  order: "post",
811
861
  handler: async () => {
812
- const { access, readFile, writeFile } = await import("node:fs/promises");
813
- const nodePath = await import("node:path");
862
+ const { access, mkdir, readFile, writeFile } = await import("node:fs/promises");
814
863
  const exists = async (candidate) => {
815
864
  try {
816
865
  await access(candidate);
@@ -819,28 +868,40 @@ function prerenderPreviewShim(state) {
819
868
  return false;
820
869
  }
821
870
  };
822
- const outDir = nodePath.resolve(root, serverOutDir);
823
- if (!await exists(nodePath.join(outDir, NITRO_SERVER_ENTRY))) {
824
- logWarning(`Cannot prerender: nitro's ${NITRO_SERVER_ENTRY} is not in ${serverOutDir}, so the preview shim was not written and every prerendered route will fall back to SSR.`);
871
+ const candidates = nitroEmitDirs(dirs);
872
+ let entryDir;
873
+ for (const candidate of candidates) {
874
+ const resolved = (0, node_path.resolve)(root, candidate);
875
+ if (await exists((0, node_path.join)(resolved, NITRO_SERVER_ENTRY))) {
876
+ entryDir = resolved;
877
+ break;
878
+ }
879
+ }
880
+ if (!entryDir) {
881
+ logWarning(`Cannot prerender: nitro's ${NITRO_SERVER_ENTRY} is in none of ${candidates.join(", ")}, so the preview shim was not written and every prerendered route will fall back to SSR.`);
825
882
  return;
826
883
  }
827
- const basename = nodePath.basename(serverEntryName, nodePath.extname(serverEntryName));
828
- if (!basename || basename === "index") {
829
- logWarning(`Cannot prerender: the server entry "${serverEntryName}" would need a shim at ${SERVER_OUTPUT_DIR}/index.js, which outranks nitro's own entry when publishing. Rename the entry to anything but \`index\`.`);
884
+ const entryName = (0, node_path.basename)(serverEntryName, (0, node_path.extname)(serverEntryName));
885
+ const wouldOutrankNitroEntry = entryName === "index" && dirs.shimDir === SERVER_OUTPUT_DIR;
886
+ if (!entryName || wouldOutrankNitroEntry) {
887
+ logWarning(`Cannot prerender: the server entry "${serverEntryName}" would need a shim at ${dirs.shimDir}/index.js, which outranks nitro's own entry when publishing. Rename the entry to anything but \`index\`.`);
830
888
  return;
831
889
  }
832
- const target = nodePath.join(outDir, `${basename}.js`);
890
+ const shimDir = (0, node_path.resolve)(root, dirs.shimDir);
891
+ const target = (0, node_path.join)(shimDir, `${entryName}.js`);
833
892
  const occupant = await readFile(target, "utf8").catch(() => void 0);
834
893
  if (occupant !== void 0 && !occupant.startsWith(SHIM_MARKER)) {
835
- logWarning(`Cannot prerender: ${basename}.js already exists in ${serverOutDir} and was not written by this plugin.`);
894
+ logWarning(`Cannot prerender: ${entryName}.js already exists in ${dirs.shimDir} and was not written by this plugin.`);
836
895
  return;
837
896
  }
838
897
  let vars = {};
839
898
  try {
840
- const candidate = JSON.parse(await readFile(nodePath.join(outDir, NITRO_WRANGLER_CONFIG), "utf8"))?.vars;
899
+ const candidate = JSON.parse(await readFile((0, node_path.join)(entryDir, NITRO_WRANGLER_CONFIG), "utf8"))?.vars;
841
900
  if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) vars = candidate;
842
901
  } catch {}
843
- await writeFile(target, prerenderShimSource(vars));
902
+ const specifier = (0, node_path.relative)(shimDir, (0, node_path.join)(entryDir, NITRO_SERVER_ENTRY)).split(node_path.sep).join("/");
903
+ await mkdir(shimDir, { recursive: true });
904
+ await writeFile(target, prerenderShimSource(vars, specifier.startsWith(".") ? specifier : `./${specifier}`));
844
905
  state.file = target;
845
906
  }
846
907
  }
@@ -1101,12 +1162,13 @@ function defineConfig(configOrOptions = {}) {
1101
1162
  };
1102
1163
  }
1103
1164
  } else if (!nitroOpts.preset && !await nitroSupportsDefaultPreset()) logWarning("The installed `nitro` predates the `defaultPreset` option (3.0.260603-beta), so the Cloudflare fallback is ignored and a zero-config build may target Node instead. Upgrade nitro to >=3.0.260603-beta, or set an explicit `nitro: { preset: \"cloudflare-module\" }`.");
1165
+ const nitroDirs = prerenderEnabled || isSandbox ? prerenderShimDirs(options.vite, nitroOpts) : void 0;
1104
1166
  internalPlugins.push(nitro(nitroOpts));
1105
- if (prerenderEnabled) {
1167
+ if (prerenderEnabled && nitroDirs) {
1106
1168
  const shimState = {};
1107
- internalPlugins.push(prerenderPreviewShim(shimState), prerenderPreviewShimCleanup(shimState));
1169
+ internalPlugins.push(prerenderPreviewShim(shimState, nitroDirs), prerenderPreviewShimCleanup(shimState));
1108
1170
  }
1109
- if (isSandbox) internalPlugins.push(stripRedundantNodejsCompatFlag());
1171
+ if (isSandbox) internalPlugins.push(stripRedundantNodejsCompatFlag(nitroDirs));
1110
1172
  }
1111
1173
  }
1112
1174
  const viteReact = (await import("@vitejs/plugin-react")).default;
package/dist/index.d.cts CHANGED
@@ -18,7 +18,18 @@ type PrerenderPage = {
18
18
  };
19
19
  //#endregion
20
20
  //#region src/index.d.ts
21
- declare function stripRedundantNodejsCompatFlag(): Plugin;
21
+ declare function stripRedundantNodejsCompatFlag(dirs?: PrerenderShimDirs): Plugin;
22
+ type NitroOutput = {
23
+ serverDir?: string;
24
+ };
25
+ type PrerenderShimDirs = {
26
+ /** Where upstream's preview middleware imports the server build from. */
27
+ shimDir: string;
28
+ /** Ordered fallbacks for the directory nitro emitted its entry into. */
29
+ entryDirs: string[];
30
+ /** Filled by nitro's `compiled` hook, which fires inside its own post-order `buildApp`. */
31
+ nitroOutput: NitroOutput;
32
+ };
22
33
  interface LovableViteTanstackOptions {
23
34
  plugins?: PluginOption[];
24
35
  vite?: UserConfig;
package/dist/index.d.ts CHANGED
@@ -18,7 +18,18 @@ type PrerenderPage = {
18
18
  };
19
19
  //#endregion
20
20
  //#region src/index.d.ts
21
- declare function stripRedundantNodejsCompatFlag(): Plugin;
21
+ declare function stripRedundantNodejsCompatFlag(dirs?: PrerenderShimDirs): Plugin;
22
+ type NitroOutput = {
23
+ serverDir?: string;
24
+ };
25
+ type PrerenderShimDirs = {
26
+ /** Where upstream's preview middleware imports the server build from. */
27
+ shimDir: string;
28
+ /** Ordered fallbacks for the directory nitro emitted its entry into. */
29
+ entryDirs: string[];
30
+ /** Filled by nitro's `compiled` hook, which fires inside its own post-order `buildApp`. */
31
+ nitroOutput: NitroOutput;
32
+ };
22
33
  interface LovableViteTanstackOptions {
23
34
  plugins?: PluginOption[];
24
35
  vite?: UserConfig;
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { basename, extname, join, relative, resolve, sep } from "node:path";
1
2
  import { fileURLToPath } from "node:url";
2
3
  import { loadEnv, mergeConfig } from "vite";
3
4
  import https from "node:https";
@@ -128,7 +129,7 @@ function bundledDevCssUrlShim() {
128
129
  //#endregion
129
130
  //#region package.json
130
131
  var name = "@lovable.dev/vite-tanstack-config";
131
- var version = "2.19.3";
132
+ var version = "2.19.5";
132
133
  //#endregion
133
134
  //#region src/logging.ts
134
135
  const PACKAGE_NAME = "@lovable.dev/vite-tanstack-config";
@@ -707,9 +708,14 @@ function lovableBuildErrorDiagnostics() {
707
708
  }
708
709
  };
709
710
  }
711
+ function nitroEmitDirs(dirs) {
712
+ if (!dirs) return [SERVER_OUTPUT_DIR];
713
+ const found = [dirs.nitroOutput.serverDir, ...dirs.entryDirs].filter((dir) => !!dir);
714
+ return [...new Set(found)];
715
+ }
710
716
  const NODEJS_COMPAT_DEFAULT_ON_DATE = "2026-08-04";
711
- const SANDBOX_WRANGLER_CONFIG_PATH = `${SERVER_OUTPUT_DIR}/wrangler.json`;
712
- function stripRedundantNodejsCompatFlag() {
717
+ const NITRO_WRANGLER_CONFIG = "wrangler.json";
718
+ function stripRedundantNodejsCompatFlag(dirs) {
713
719
  let root = process.cwd();
714
720
  return {
715
721
  name: "lovable-strip-redundant-nodejs-compat",
@@ -721,13 +727,18 @@ function stripRedundantNodejsCompatFlag() {
721
727
  order: "post",
722
728
  handler: async () => {
723
729
  const { readFile, writeFile } = await import("node:fs/promises");
724
- const configPath = (await import("node:path")).join(root, SANDBOX_WRANGLER_CONFIG_PATH);
730
+ let configPath;
725
731
  let parsed;
726
- try {
727
- parsed = JSON.parse(await readFile(configPath, "utf8"));
728
- } catch {
729
- return;
732
+ for (const dir of nitroEmitDirs(dirs)) {
733
+ configPath = join(resolve(root, dir), NITRO_WRANGLER_CONFIG);
734
+ try {
735
+ parsed = JSON.parse(await readFile(configPath, "utf8"));
736
+ break;
737
+ } catch {
738
+ configPath = void 0;
739
+ }
730
740
  }
741
+ if (configPath === void 0) return;
731
742
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return;
732
743
  const config = parsed;
733
744
  if (typeof config.compatibility_date !== "string") return;
@@ -744,14 +755,15 @@ function stripRedundantNodejsCompatFlag() {
744
755
  };
745
756
  }
746
757
  const NITRO_SERVER_ENTRY = "index.mjs";
747
- const NITRO_WRANGLER_CONFIG = "wrangler.json";
758
+ const NITRO_DEFAULT_OUTPUT_DIR = ".output";
759
+ const VITE_DEFAULT_OUTPUT_DIR = "dist";
748
760
  const DEFAULT_SERVER_ENTRY_NAME = "server";
749
761
  const PRERENDER_PREVIEW_HOST = "127.0.0.1";
750
762
  const TSS_PRERENDERING_ENV = "TSS_PRERENDERING";
751
763
  const SHIM_MARKER = "// Generated by @lovable.dev/vite-tanstack-config for the prerender preview server.";
752
- function prerenderShimSource(vars) {
764
+ function prerenderShimSource(vars, entrySpecifier) {
753
765
  return `${SHIM_MARKER}
754
- import server from "./${NITRO_SERVER_ENTRY}";
766
+ import server from "${entrySpecifier}";
755
767
 
756
768
  const env = ${JSON.stringify(vars)};
757
769
  const ctx = { waitUntil() {}, passThroughOnException() {}, props: {} };
@@ -766,16 +778,54 @@ export default {
766
778
  };
767
779
  `;
768
780
  }
769
- function prerenderPreviewShim(state) {
781
+ function captureNitroServerDir(nitroOpts) {
782
+ const output = {};
783
+ const hooks = nitroOpts.hooks ?? {};
784
+ const userCompiled = hooks.compiled;
785
+ nitroOpts.hooks = {
786
+ ...hooks,
787
+ compiled: async (nitro) => {
788
+ const serverDir = nitro?.options?.output?.serverDir;
789
+ if (typeof serverDir === "string") output.serverDir = serverDir;
790
+ if (typeof userCompiled === "function") await userCompiled(nitro);
791
+ }
792
+ };
793
+ return output;
794
+ }
795
+ function previewServerOutputDir(viteConfig) {
796
+ const ssrOutDir = viteConfig?.environments?.ssr?.build?.outDir;
797
+ if (typeof ssrOutDir === "string") return ssrOutDir;
798
+ const rootOutDir = viteConfig?.build?.outDir;
799
+ return join(typeof rootOutDir === "string" ? rootOutDir : VITE_DEFAULT_OUTPUT_DIR, "server");
800
+ }
801
+ function pinnedNitroServerDir(nitroOpts) {
802
+ const output = nitroOpts.output;
803
+ const dir = typeof output?.dir === "string" ? output.dir : void 0;
804
+ const serverDir = typeof output?.serverDir === "string" ? output.serverDir : void 0;
805
+ const resolved = serverDir ? serverDir.replace(/\{\{\s*output\.dir\s*\}\}/g, dir ?? NITRO_DEFAULT_OUTPUT_DIR) : dir && join(dir, "server");
806
+ return resolved && !resolved.includes("{{") ? resolved : void 0;
807
+ }
808
+ function prerenderShimDirs(viteConfig, nitroOpts) {
809
+ const shimDir = previewServerOutputDir(viteConfig);
810
+ const candidates = [
811
+ pinnedNitroServerDir(nitroOpts),
812
+ join(NITRO_DEFAULT_OUTPUT_DIR, "server"),
813
+ shimDir
814
+ ];
815
+ return {
816
+ shimDir,
817
+ entryDirs: [...new Set(candidates.filter((dir) => !!dir))],
818
+ nitroOutput: captureNitroServerDir(nitroOpts)
819
+ };
820
+ }
821
+ function prerenderPreviewShim(state, dirs) {
770
822
  let root = process.cwd();
771
- let serverOutDir = SERVER_OUTPUT_DIR;
772
823
  let serverEntryName = DEFAULT_SERVER_ENTRY_NAME;
773
824
  return {
774
825
  name: "lovable-prerender-preview-shim",
775
826
  apply: "build",
776
827
  config(userConfig) {
777
828
  const ssrBuild = userConfig.environments?.ssr?.build;
778
- if (ssrBuild?.outDir) serverOutDir = ssrBuild.outDir;
779
829
  const input = ssrBuild?.rolldownOptions?.input ?? ssrBuild?.rollupOptions?.input;
780
830
  if (typeof input === "string") serverEntryName = input;
781
831
  },
@@ -785,8 +835,7 @@ function prerenderPreviewShim(state) {
785
835
  buildApp: {
786
836
  order: "post",
787
837
  handler: async () => {
788
- const { access, readFile, writeFile } = await import("node:fs/promises");
789
- const nodePath = await import("node:path");
838
+ const { access, mkdir, readFile, writeFile } = await import("node:fs/promises");
790
839
  const exists = async (candidate) => {
791
840
  try {
792
841
  await access(candidate);
@@ -795,28 +844,40 @@ function prerenderPreviewShim(state) {
795
844
  return false;
796
845
  }
797
846
  };
798
- const outDir = nodePath.resolve(root, serverOutDir);
799
- if (!await exists(nodePath.join(outDir, NITRO_SERVER_ENTRY))) {
800
- logWarning(`Cannot prerender: nitro's ${NITRO_SERVER_ENTRY} is not in ${serverOutDir}, so the preview shim was not written and every prerendered route will fall back to SSR.`);
847
+ const candidates = nitroEmitDirs(dirs);
848
+ let entryDir;
849
+ for (const candidate of candidates) {
850
+ const resolved = resolve(root, candidate);
851
+ if (await exists(join(resolved, NITRO_SERVER_ENTRY))) {
852
+ entryDir = resolved;
853
+ break;
854
+ }
855
+ }
856
+ if (!entryDir) {
857
+ logWarning(`Cannot prerender: nitro's ${NITRO_SERVER_ENTRY} is in none of ${candidates.join(", ")}, so the preview shim was not written and every prerendered route will fall back to SSR.`);
801
858
  return;
802
859
  }
803
- const basename = nodePath.basename(serverEntryName, nodePath.extname(serverEntryName));
804
- if (!basename || basename === "index") {
805
- logWarning(`Cannot prerender: the server entry "${serverEntryName}" would need a shim at ${SERVER_OUTPUT_DIR}/index.js, which outranks nitro's own entry when publishing. Rename the entry to anything but \`index\`.`);
860
+ const entryName = basename(serverEntryName, extname(serverEntryName));
861
+ const wouldOutrankNitroEntry = entryName === "index" && dirs.shimDir === SERVER_OUTPUT_DIR;
862
+ if (!entryName || wouldOutrankNitroEntry) {
863
+ logWarning(`Cannot prerender: the server entry "${serverEntryName}" would need a shim at ${dirs.shimDir}/index.js, which outranks nitro's own entry when publishing. Rename the entry to anything but \`index\`.`);
806
864
  return;
807
865
  }
808
- const target = nodePath.join(outDir, `${basename}.js`);
866
+ const shimDir = resolve(root, dirs.shimDir);
867
+ const target = join(shimDir, `${entryName}.js`);
809
868
  const occupant = await readFile(target, "utf8").catch(() => void 0);
810
869
  if (occupant !== void 0 && !occupant.startsWith(SHIM_MARKER)) {
811
- logWarning(`Cannot prerender: ${basename}.js already exists in ${serverOutDir} and was not written by this plugin.`);
870
+ logWarning(`Cannot prerender: ${entryName}.js already exists in ${dirs.shimDir} and was not written by this plugin.`);
812
871
  return;
813
872
  }
814
873
  let vars = {};
815
874
  try {
816
- const candidate = JSON.parse(await readFile(nodePath.join(outDir, NITRO_WRANGLER_CONFIG), "utf8"))?.vars;
875
+ const candidate = JSON.parse(await readFile(join(entryDir, NITRO_WRANGLER_CONFIG), "utf8"))?.vars;
817
876
  if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) vars = candidate;
818
877
  } catch {}
819
- await writeFile(target, prerenderShimSource(vars));
878
+ const specifier = relative(shimDir, join(entryDir, NITRO_SERVER_ENTRY)).split(sep).join("/");
879
+ await mkdir(shimDir, { recursive: true });
880
+ await writeFile(target, prerenderShimSource(vars, specifier.startsWith(".") ? specifier : `./${specifier}`));
820
881
  state.file = target;
821
882
  }
822
883
  }
@@ -1077,12 +1138,13 @@ function defineConfig(configOrOptions = {}) {
1077
1138
  };
1078
1139
  }
1079
1140
  } else if (!nitroOpts.preset && !await nitroSupportsDefaultPreset()) logWarning("The installed `nitro` predates the `defaultPreset` option (3.0.260603-beta), so the Cloudflare fallback is ignored and a zero-config build may target Node instead. Upgrade nitro to >=3.0.260603-beta, or set an explicit `nitro: { preset: \"cloudflare-module\" }`.");
1141
+ const nitroDirs = prerenderEnabled || isSandbox ? prerenderShimDirs(options.vite, nitroOpts) : void 0;
1080
1142
  internalPlugins.push(nitro(nitroOpts));
1081
- if (prerenderEnabled) {
1143
+ if (prerenderEnabled && nitroDirs) {
1082
1144
  const shimState = {};
1083
- internalPlugins.push(prerenderPreviewShim(shimState), prerenderPreviewShimCleanup(shimState));
1145
+ internalPlugins.push(prerenderPreviewShim(shimState, nitroDirs), prerenderPreviewShimCleanup(shimState));
1084
1146
  }
1085
- if (isSandbox) internalPlugins.push(stripRedundantNodejsCompatFlag());
1147
+ if (isSandbox) internalPlugins.push(stripRedundantNodejsCompatFlag(nitroDirs));
1086
1148
  }
1087
1149
  }
1088
1150
  const viteReact = (await import("@vitejs/plugin-react")).default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovable.dev/vite-tanstack-config",
3
- "version": "2.19.3",
3
+ "version": "2.19.5",
4
4
  "description": "Vite config wrapper for Lovable TanStack Start projects",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",