@lovable.dev/vite-tanstack-config 1.6.0 → 1.8.0-rc.0

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/dist/index.cjs CHANGED
@@ -130,6 +130,7 @@ function applyWatchDebounceDefaults(config) {
130
130
  }
131
131
  });
132
132
  }
133
+ var SSR_CAPTURE_KEY = "__LOVABLE_TANSTACK_CAPTURE_SSR_ERROR__";
133
134
  function devSsrErrorLogger() {
134
135
  let lastCapture;
135
136
  const CAPTURE_TTL_MS = 5e3;
@@ -151,6 +152,7 @@ function devSsrErrorLogger() {
151
152
  name: "dev-ssr-error-logger",
152
153
  apply: "serve",
153
154
  configureServer(server) {
155
+ globalThis[SSR_CAPTURE_KEY] = capture;
154
156
  const g = globalThis;
155
157
  if (typeof g.addEventListener === "function") {
156
158
  const addListener = g.addEventListener;
@@ -188,6 +190,21 @@ function devSsrErrorLogger() {
188
190
  };
189
191
  next();
190
192
  });
193
+ },
194
+ transform(code, id) {
195
+ const normalizedId = id.replace(/\\/g, "/");
196
+ const isTargetModule = normalizedId.includes("/@tanstack/start-server-core/src/request-response.ts") || normalizedId.includes("/@tanstack/start-server-core/dist/esm/request-response.js");
197
+ if (!isTargetModule) {
198
+ return null;
199
+ }
200
+ const needle = "handler(request, requestOpts)";
201
+ if (!code.includes(needle)) {
202
+ return null;
203
+ }
204
+ return code.replace(
205
+ needle,
206
+ `Promise.resolve(${needle}).catch((err) => { globalThis.${SSR_CAPTURE_KEY}?.(err); throw err; })`
207
+ );
191
208
  }
192
209
  };
193
210
  }
@@ -249,7 +266,19 @@ function defineConfig(configOrOptions = {}) {
249
266
  options = { vite: await configOrOptions };
250
267
  } else {
251
268
  const optionObject = configOrOptions && typeof configOrOptions === "object" ? configOrOptions : {};
252
- const hasLovableKey = "vite" in optionObject || "serverFnErrorLogger" in optionObject || "ssrErrorLogger" in optionObject || "cloudflare" in optionObject || "tanstackStart" in optionObject || "react" in optionObject || "envDefine" in optionObject || "hmrGate" in optionObject;
269
+ if ("cloudflare" in optionObject) {
270
+ if (optionObject.cloudflare === false && !("nitro" in optionObject)) {
271
+ optionObject.nitro = false;
272
+ logWarning(
273
+ "`cloudflare: false` is deprecated in v2 \u2014 migrated to `nitro: false`. Update your config to drop the warning."
274
+ );
275
+ } else {
276
+ logWarning(
277
+ "The `cloudflare` option was removed in v2. Use `nitro: false` to disable the deploy plugin, or `nitro: { preset: '...' }` to configure it. The `cloudflare` setting is being ignored."
278
+ );
279
+ }
280
+ }
281
+ const hasLovableKey = "vite" in optionObject || "serverFnErrorLogger" in optionObject || "ssrErrorLogger" in optionObject || "nitro" in optionObject || "tanstackStart" in optionObject || "react" in optionObject || "envDefine" in optionObject || "hmrGate" in optionObject;
253
282
  options = hasLovableKey ? optionObject : { vite: optionObject };
254
283
  }
255
284
  const internalPlugins = [];
@@ -263,16 +292,6 @@ function defineConfig(configOrOptions = {}) {
263
292
  if (options.ssrErrorLogger !== false) {
264
293
  internalPlugins.push(devSsrErrorLogger());
265
294
  }
266
- if (options.cloudflare !== false && command === "build") {
267
- try {
268
- const { cloudflare } = await import("@cloudflare/vite-plugin");
269
- const cfOptions = typeof options.cloudflare === "object" && options.cloudflare || {
270
- viteEnvironment: { name: "ssr" }
271
- };
272
- internalPlugins.push(cloudflare(cfOptions));
273
- } catch {
274
- }
275
- }
276
295
  const { tanstackStart } = await import("@tanstack/react-start/plugin/vite");
277
296
  const tanstackStartDefaults = {
278
297
  importProtection: {
@@ -285,6 +304,42 @@ function defineConfig(configOrOptions = {}) {
285
304
  };
286
305
  const tanstackStartOptions = (0, import_vite.mergeConfig)(tanstackStartDefaults, options.tanstackStart ?? {});
287
306
  internalPlugins.push(tanstackStart(tanstackStartOptions));
307
+ const explicitNitro = options.nitro === true || typeof options.nitro === "object" && options.nitro !== null;
308
+ const shouldRunNitro = options.nitro !== false && command === "build" && (explicitNitro || isSandbox);
309
+ if (options.nitro === void 0 && command === "build" && !isSandbox) {
310
+ console.info(
311
+ "[@lovable.dev/vite-tanstack-config] No Lovable context detected \u2014 skipping nitro deploy plugin. Pass `nitro: true` (or `nitro: { ... }`) to force-enable."
312
+ );
313
+ }
314
+ if (shouldRunNitro) {
315
+ let nitroMod;
316
+ try {
317
+ nitroMod = await import("nitro/vite");
318
+ } catch (err) {
319
+ if (explicitNitro || isSandbox) {
320
+ const reason = explicitNitro ? `an explicit \`nitro\` option (${options.nitro === true ? "true" : "{ ... }"}) was set in vite.config.ts` : "running inside a Lovable sandbox";
321
+ throw new Error(
322
+ `[@lovable.dev/vite-tanstack-config] ${reason}, but the \`nitro\` package isn't installed. Add \`nitro\` to your devDependencies (matches peerDependency >=3.0.260429-beta). Original import error: ${err instanceof Error ? err.message : String(err)}`
323
+ );
324
+ }
325
+ }
326
+ if (nitroMod) {
327
+ const { nitro } = nitroMod;
328
+ const userNitroOpts = typeof options.nitro === "object" && options.nitro ? options.nitro : {};
329
+ const preset = userNitroOpts.preset ?? process.env.NITRO_PRESET ?? "cloudflare-module";
330
+ const output = {
331
+ dir: "dist",
332
+ serverDir: "dist/server",
333
+ publicDir: "dist/client",
334
+ ...userNitroOpts.output
335
+ };
336
+ const nitroOpts = { ...userNitroOpts, preset, output };
337
+ if (preset === "cloudflare-module") {
338
+ nitroOpts.cloudflare = { nodeCompat: true, deployConfig: true, ...userNitroOpts.cloudflare };
339
+ }
340
+ internalPlugins.push(nitro(nitroOpts));
341
+ }
342
+ }
288
343
  const viteReact = (await import("@vitejs/plugin-react")).default;
289
344
  internalPlugins.push(viteReact(options.react));
290
345
  if (command === "serve") {
package/dist/index.d.cts CHANGED
@@ -5,7 +5,37 @@ interface LovableViteTanstackOptions {
5
5
  vite?: UserConfig;
6
6
  serverFnErrorLogger?: boolean;
7
7
  ssrErrorLogger?: boolean;
8
- cloudflare?: Record<string, unknown> | false;
8
+ /**
9
+ * Options forwarded to `nitro()` from `nitro/vite`.
10
+ *
11
+ * Behavior:
12
+ * - **undefined** (default): auto — nitro runs only when a Lovable context
13
+ * is detected (sandbox + prod-deploy build via `DEV_SERVER__PROJECT_PATH`
14
+ * / `LOVABLE_SANDBOX`). Users who clone their project and self-deploy
15
+ * on their own infra get a Vite-only build with no Cloudflare-specific
16
+ * bundling.
17
+ * - **`true`**: force-on with package defaults (`cloudflare-module` preset,
18
+ * `dist/server` + `dist/client` layout). Use this in non-Lovable
19
+ * environments where you still want the Nitro deploy bundle.
20
+ * - **object**: force-on, with these overrides on top of the defaults.
21
+ * - **`false`**: skip nitro entirely.
22
+ *
23
+ * The option surface is narrow on purpose — Nitro v3 is still pre-RC, so
24
+ * we only expose stable build-time knobs to reduce churn if
25
+ * `NitroPluginConfig` schema changes. File an issue if you need more.
26
+ */
27
+ nitro?: true | {
28
+ preset?: string;
29
+ output?: {
30
+ dir?: string;
31
+ publicDir?: string;
32
+ serverDir?: string;
33
+ };
34
+ cloudflare?: {
35
+ nodeCompat?: boolean;
36
+ deployConfig?: boolean;
37
+ };
38
+ } | false;
9
39
  /** Options forwarded to tanstackStart(). */
10
40
  tanstackStart?: Record<string, unknown>;
11
41
  /** Options forwarded to viteReact(). */
package/dist/index.d.ts CHANGED
@@ -5,7 +5,37 @@ interface LovableViteTanstackOptions {
5
5
  vite?: UserConfig;
6
6
  serverFnErrorLogger?: boolean;
7
7
  ssrErrorLogger?: boolean;
8
- cloudflare?: Record<string, unknown> | false;
8
+ /**
9
+ * Options forwarded to `nitro()` from `nitro/vite`.
10
+ *
11
+ * Behavior:
12
+ * - **undefined** (default): auto — nitro runs only when a Lovable context
13
+ * is detected (sandbox + prod-deploy build via `DEV_SERVER__PROJECT_PATH`
14
+ * / `LOVABLE_SANDBOX`). Users who clone their project and self-deploy
15
+ * on their own infra get a Vite-only build with no Cloudflare-specific
16
+ * bundling.
17
+ * - **`true`**: force-on with package defaults (`cloudflare-module` preset,
18
+ * `dist/server` + `dist/client` layout). Use this in non-Lovable
19
+ * environments where you still want the Nitro deploy bundle.
20
+ * - **object**: force-on, with these overrides on top of the defaults.
21
+ * - **`false`**: skip nitro entirely.
22
+ *
23
+ * The option surface is narrow on purpose — Nitro v3 is still pre-RC, so
24
+ * we only expose stable build-time knobs to reduce churn if
25
+ * `NitroPluginConfig` schema changes. File an issue if you need more.
26
+ */
27
+ nitro?: true | {
28
+ preset?: string;
29
+ output?: {
30
+ dir?: string;
31
+ publicDir?: string;
32
+ serverDir?: string;
33
+ };
34
+ cloudflare?: {
35
+ nodeCompat?: boolean;
36
+ deployConfig?: boolean;
37
+ };
38
+ } | false;
9
39
  /** Options forwarded to tanstackStart(). */
10
40
  tanstackStart?: Record<string, unknown>;
11
41
  /** Options forwarded to viteReact(). */
package/dist/index.js CHANGED
@@ -96,6 +96,7 @@ function applyWatchDebounceDefaults(config) {
96
96
  }
97
97
  });
98
98
  }
99
+ var SSR_CAPTURE_KEY = "__LOVABLE_TANSTACK_CAPTURE_SSR_ERROR__";
99
100
  function devSsrErrorLogger() {
100
101
  let lastCapture;
101
102
  const CAPTURE_TTL_MS = 5e3;
@@ -117,6 +118,7 @@ function devSsrErrorLogger() {
117
118
  name: "dev-ssr-error-logger",
118
119
  apply: "serve",
119
120
  configureServer(server) {
121
+ globalThis[SSR_CAPTURE_KEY] = capture;
120
122
  const g = globalThis;
121
123
  if (typeof g.addEventListener === "function") {
122
124
  const addListener = g.addEventListener;
@@ -154,6 +156,21 @@ function devSsrErrorLogger() {
154
156
  };
155
157
  next();
156
158
  });
159
+ },
160
+ transform(code, id) {
161
+ const normalizedId = id.replace(/\\/g, "/");
162
+ const isTargetModule = normalizedId.includes("/@tanstack/start-server-core/src/request-response.ts") || normalizedId.includes("/@tanstack/start-server-core/dist/esm/request-response.js");
163
+ if (!isTargetModule) {
164
+ return null;
165
+ }
166
+ const needle = "handler(request, requestOpts)";
167
+ if (!code.includes(needle)) {
168
+ return null;
169
+ }
170
+ return code.replace(
171
+ needle,
172
+ `Promise.resolve(${needle}).catch((err) => { globalThis.${SSR_CAPTURE_KEY}?.(err); throw err; })`
173
+ );
157
174
  }
158
175
  };
159
176
  }
@@ -215,7 +232,19 @@ function defineConfig(configOrOptions = {}) {
215
232
  options = { vite: await configOrOptions };
216
233
  } else {
217
234
  const optionObject = configOrOptions && typeof configOrOptions === "object" ? configOrOptions : {};
218
- const hasLovableKey = "vite" in optionObject || "serverFnErrorLogger" in optionObject || "ssrErrorLogger" in optionObject || "cloudflare" in optionObject || "tanstackStart" in optionObject || "react" in optionObject || "envDefine" in optionObject || "hmrGate" in optionObject;
235
+ if ("cloudflare" in optionObject) {
236
+ if (optionObject.cloudflare === false && !("nitro" in optionObject)) {
237
+ optionObject.nitro = false;
238
+ logWarning(
239
+ "`cloudflare: false` is deprecated in v2 \u2014 migrated to `nitro: false`. Update your config to drop the warning."
240
+ );
241
+ } else {
242
+ logWarning(
243
+ "The `cloudflare` option was removed in v2. Use `nitro: false` to disable the deploy plugin, or `nitro: { preset: '...' }` to configure it. The `cloudflare` setting is being ignored."
244
+ );
245
+ }
246
+ }
247
+ const hasLovableKey = "vite" in optionObject || "serverFnErrorLogger" in optionObject || "ssrErrorLogger" in optionObject || "nitro" in optionObject || "tanstackStart" in optionObject || "react" in optionObject || "envDefine" in optionObject || "hmrGate" in optionObject;
219
248
  options = hasLovableKey ? optionObject : { vite: optionObject };
220
249
  }
221
250
  const internalPlugins = [];
@@ -229,16 +258,6 @@ function defineConfig(configOrOptions = {}) {
229
258
  if (options.ssrErrorLogger !== false) {
230
259
  internalPlugins.push(devSsrErrorLogger());
231
260
  }
232
- if (options.cloudflare !== false && command === "build") {
233
- try {
234
- const { cloudflare } = await import("@cloudflare/vite-plugin");
235
- const cfOptions = typeof options.cloudflare === "object" && options.cloudflare || {
236
- viteEnvironment: { name: "ssr" }
237
- };
238
- internalPlugins.push(cloudflare(cfOptions));
239
- } catch {
240
- }
241
- }
242
261
  const { tanstackStart } = await import("@tanstack/react-start/plugin/vite");
243
262
  const tanstackStartDefaults = {
244
263
  importProtection: {
@@ -251,6 +270,42 @@ function defineConfig(configOrOptions = {}) {
251
270
  };
252
271
  const tanstackStartOptions = mergeConfig(tanstackStartDefaults, options.tanstackStart ?? {});
253
272
  internalPlugins.push(tanstackStart(tanstackStartOptions));
273
+ const explicitNitro = options.nitro === true || typeof options.nitro === "object" && options.nitro !== null;
274
+ const shouldRunNitro = options.nitro !== false && command === "build" && (explicitNitro || isSandbox);
275
+ if (options.nitro === void 0 && command === "build" && !isSandbox) {
276
+ console.info(
277
+ "[@lovable.dev/vite-tanstack-config] No Lovable context detected \u2014 skipping nitro deploy plugin. Pass `nitro: true` (or `nitro: { ... }`) to force-enable."
278
+ );
279
+ }
280
+ if (shouldRunNitro) {
281
+ let nitroMod;
282
+ try {
283
+ nitroMod = await import("nitro/vite");
284
+ } catch (err) {
285
+ if (explicitNitro || isSandbox) {
286
+ const reason = explicitNitro ? `an explicit \`nitro\` option (${options.nitro === true ? "true" : "{ ... }"}) was set in vite.config.ts` : "running inside a Lovable sandbox";
287
+ throw new Error(
288
+ `[@lovable.dev/vite-tanstack-config] ${reason}, but the \`nitro\` package isn't installed. Add \`nitro\` to your devDependencies (matches peerDependency >=3.0.260429-beta). Original import error: ${err instanceof Error ? err.message : String(err)}`
289
+ );
290
+ }
291
+ }
292
+ if (nitroMod) {
293
+ const { nitro } = nitroMod;
294
+ const userNitroOpts = typeof options.nitro === "object" && options.nitro ? options.nitro : {};
295
+ const preset = userNitroOpts.preset ?? process.env.NITRO_PRESET ?? "cloudflare-module";
296
+ const output = {
297
+ dir: "dist",
298
+ serverDir: "dist/server",
299
+ publicDir: "dist/client",
300
+ ...userNitroOpts.output
301
+ };
302
+ const nitroOpts = { ...userNitroOpts, preset, output };
303
+ if (preset === "cloudflare-module") {
304
+ nitroOpts.cloudflare = { nodeCompat: true, deployConfig: true, ...userNitroOpts.cloudflare };
305
+ }
306
+ internalPlugins.push(nitro(nitroOpts));
307
+ }
308
+ }
254
309
  const viteReact = (await import("@vitejs/plugin-react")).default;
255
310
  internalPlugins.push(viteReact(options.react));
256
311
  if (command === "serve") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovable.dev/vite-tanstack-config",
3
- "version": "1.6.0",
3
+ "version": "1.8.0-rc.0",
4
4
  "description": "Vite config wrapper for Lovable TanStack Start projects",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -9,15 +9,6 @@
9
9
  "files": [
10
10
  "dist"
11
11
  ],
12
- "scripts": {
13
- "build": "tsup src/index.ts --format cjs,esm --dts --outDir dist",
14
- "typecheck": "tsgo --noEmit",
15
- "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
16
- "test": "vitest",
17
- "prepublishOnly": "npm run clean && npm run build",
18
- "clean": "rimraf dist",
19
- "coverage": "vitest run --coverage"
20
- },
21
12
  "keywords": [
22
13
  "vite",
23
14
  "tanstack",
@@ -28,32 +19,34 @@
28
19
  "dependencies": {
29
20
  "@lovable.dev/vite-plugin-dev-server-bridge": "^1.0.0",
30
21
  "@lovable.dev/vite-plugin-hmr-gate": "^1.0.0",
31
- "lovable-tagger": "1.2.0"
22
+ "lovable-tagger": "1.2.0",
23
+ "nitro": "3.0.260429-beta"
32
24
  },
33
25
  "peerDependencies": {
34
26
  "vite": ">=5.0.0 <9.0.0",
35
27
  "@tailwindcss/vite": ">=4.0.0",
36
28
  "vite-tsconfig-paths": ">=6.0.0",
37
- "@cloudflare/vite-plugin": ">=1.0.0",
38
29
  "@tanstack/react-start": ">=1.100.0",
39
30
  "@vitejs/plugin-react": ">=4.0.0"
40
31
  },
41
- "peerDependenciesMeta": {
42
- "@cloudflare/vite-plugin": {
43
- "optional": true
44
- }
45
- },
46
32
  "devDependencies": {
47
- "@cloudflare/vite-plugin": "^1.25.5",
48
33
  "@tanstack/react-start": "^1.162.9",
49
34
  "@vitejs/plugin-react": "^4.5.2",
50
35
  "@tailwindcss/vite": "^4.2.1",
51
- "@types/node": "catalog:",
36
+ "@types/node": "22.13.13",
52
37
  "rimraf": "^5.0.0",
53
38
  "tsup": "^7.2.0",
54
- "typescript": "catalog:",
39
+ "typescript": "^5.9.3",
55
40
  "vite": "^7.3.1",
56
41
  "vite-tsconfig-paths": "^6.0.2",
57
- "vitest": "catalog:"
42
+ "vitest": "^4.1.5"
43
+ },
44
+ "scripts": {
45
+ "build": "tsup src/index.ts --format cjs,esm --dts --outDir dist",
46
+ "typecheck": "tsgo --noEmit",
47
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
48
+ "test": "vitest",
49
+ "clean": "rimraf dist",
50
+ "coverage": "vitest run --coverage"
58
51
  }
59
- }
52
+ }