@lovable.dev/vite-tanstack-config 2.7.5-rc.5 → 2.7.5-rc.6
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 +725 -590
- package/dist/index.d.cts +55 -56
- package/dist/index.d.ts +55 -56
- package/dist/index.js +697 -573
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -1,505 +1,604 @@
|
|
|
1
|
-
|
|
2
|
-
//#region \0rolldown/runtime.js
|
|
1
|
+
"use strict";
|
|
3
2
|
var __create = Object.create;
|
|
4
3
|
var __defProp = Object.defineProperty;
|
|
5
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
9
12
|
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
18
19
|
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
defineConfig: () => defineConfig,
|
|
34
|
+
lovableAssetsProxyPlugin: () => lovableAssetsProxyPlugin
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(src_exports);
|
|
37
|
+
var import_vite = require("vite");
|
|
38
|
+
|
|
39
|
+
// src/assetsProxyPlugin.ts
|
|
40
|
+
var import_node_https = __toESM(require("https"), 1);
|
|
41
|
+
var ASSET_RE = /^\/__l5e\/assets-v1\//;
|
|
42
|
+
var PREVIEW_HOST_ENV = "LOVABLE_PREVIEW_HOST";
|
|
43
|
+
var HOP_BY_HOP = /* @__PURE__ */ new Set([
|
|
44
|
+
"host",
|
|
45
|
+
"connection",
|
|
46
|
+
"keep-alive",
|
|
47
|
+
"proxy-authenticate",
|
|
48
|
+
"proxy-authorization",
|
|
49
|
+
"te",
|
|
50
|
+
"trailer",
|
|
51
|
+
"transfer-encoding",
|
|
52
|
+
"upgrade",
|
|
53
|
+
"content-length",
|
|
54
|
+
"cookie"
|
|
42
55
|
]);
|
|
43
56
|
function pickRequestHeaders(src) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
57
|
+
const out = {};
|
|
58
|
+
for (const [k, v] of Object.entries(src)) {
|
|
59
|
+
if (v === void 0)
|
|
60
|
+
continue;
|
|
61
|
+
if (HOP_BY_HOP.has(k.toLowerCase()))
|
|
62
|
+
continue;
|
|
63
|
+
out[k] = v;
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
51
66
|
}
|
|
52
|
-
/**
|
|
53
|
-
* Forwards `/__l5e/assets-v1/*` requests from the Vite dev server to the
|
|
54
|
-
* Lovable preview proxy so assets resolve when the page is loaded directly
|
|
55
|
-
* from the sandbox dev server (e.g. `localhost:8080`) instead of via
|
|
56
|
-
* `*.lovable.app` / `*.lovableproject.com`.
|
|
57
|
-
*
|
|
58
|
-
* No-op unless `LOVABLE_PREVIEW_HOST` is set (host only, no scheme), e.g.
|
|
59
|
-
* `id-preview--<project-id>.lovable.app`.
|
|
60
|
-
*/
|
|
61
67
|
function lovableAssetsProxyPlugin() {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
68
|
+
const previewHost = process.env[PREVIEW_HOST_ENV]?.trim();
|
|
69
|
+
return {
|
|
70
|
+
name: "lovable:assets-proxy",
|
|
71
|
+
apply: "serve",
|
|
72
|
+
configureServer(server) {
|
|
73
|
+
if (!previewHost)
|
|
74
|
+
return;
|
|
75
|
+
const middleware = (req, res, next) => {
|
|
76
|
+
const url = req.url ?? "";
|
|
77
|
+
if (!ASSET_RE.test(url))
|
|
78
|
+
return next();
|
|
79
|
+
const upstream = import_node_https.default.request(
|
|
80
|
+
{
|
|
81
|
+
host: previewHost,
|
|
82
|
+
port: 443,
|
|
83
|
+
method: req.method,
|
|
84
|
+
path: url,
|
|
85
|
+
headers: { ...pickRequestHeaders(req.headers), host: previewHost }
|
|
86
|
+
},
|
|
87
|
+
(upRes) => {
|
|
88
|
+
res.statusCode = upRes.statusCode ?? 502;
|
|
89
|
+
for (const [k, v] of Object.entries(upRes.headers)) {
|
|
90
|
+
if (v === void 0)
|
|
91
|
+
continue;
|
|
92
|
+
if (HOP_BY_HOP.has(k.toLowerCase()))
|
|
93
|
+
continue;
|
|
94
|
+
res.setHeader(k, v);
|
|
95
|
+
}
|
|
96
|
+
upRes.pipe(res);
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
upstream.on("error", (err) => {
|
|
100
|
+
server.config.logger.warn(
|
|
101
|
+
`[@lovable.dev/vite-tanstack-config] asset proxy ${url} \u2192 ${previewHost} failed: ${err.message}`
|
|
102
|
+
);
|
|
103
|
+
if (!res.headersSent) {
|
|
104
|
+
res.statusCode = 502;
|
|
105
|
+
res.end();
|
|
106
|
+
} else {
|
|
107
|
+
res.destroy(err);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
req.pipe(upstream);
|
|
111
|
+
};
|
|
112
|
+
server.middlewares.use(middleware);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
101
115
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
116
|
+
|
|
117
|
+
// src/index.ts
|
|
118
|
+
var SANDBOX_ENV_VAR = "DEV_SERVER__PROJECT_PATH";
|
|
119
|
+
var LOVABLE_SANDBOX_ENV_VAR = "LOVABLE_SANDBOX";
|
|
106
120
|
function isSandboxEnvironment() {
|
|
107
|
-
|
|
121
|
+
return process.env[LOVABLE_SANDBOX_ENV_VAR] === "1" || !!process.env[SANDBOX_ENV_VAR];
|
|
108
122
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
var TOOL_MANAGED_WATCH_IGNORES = [
|
|
124
|
+
"**/.workspace/**",
|
|
125
|
+
"**/.agents/**",
|
|
126
|
+
"**/.claude/**",
|
|
127
|
+
"**/.lovable/**",
|
|
128
|
+
"**/.tanstack/tmp/**"
|
|
115
129
|
];
|
|
116
130
|
function logWarning(message) {
|
|
117
|
-
|
|
131
|
+
console.warn(`[@lovable.dev/vite-tanstack-config] ${message}`);
|
|
118
132
|
}
|
|
119
|
-
|
|
120
|
-
3,
|
|
121
|
-
0,
|
|
122
|
-
260603
|
|
123
|
-
];
|
|
133
|
+
var NITRO_DEFAULT_PRESET_MIN = [3, 0, 260603];
|
|
124
134
|
async function nitroSupportsDefaultPreset() {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
135
|
+
try {
|
|
136
|
+
const { createRequire } = await import("module");
|
|
137
|
+
const require2 = createRequire(`${process.cwd()}/package.json`);
|
|
138
|
+
const { version } = require2("nitro/package.json");
|
|
139
|
+
const match = typeof version === "string" ? /^(\d+)\.(\d+)\.(\d+)/.exec(version) : null;
|
|
140
|
+
if (!match)
|
|
141
|
+
return true;
|
|
142
|
+
const parts = [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
143
|
+
for (let i = 0; i < 3; i++) {
|
|
144
|
+
if (parts[i] !== NITRO_DEFAULT_PRESET_MIN[i])
|
|
145
|
+
return parts[i] > NITRO_DEFAULT_PRESET_MIN[i];
|
|
146
|
+
}
|
|
147
|
+
return true;
|
|
148
|
+
} catch {
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
140
151
|
}
|
|
141
152
|
function validateHeaders(config) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
153
|
+
const headers = config.server?.headers;
|
|
154
|
+
if (!headers)
|
|
155
|
+
return;
|
|
156
|
+
const headerKeys = Object.keys(headers);
|
|
157
|
+
if (headerKeys.length > 0) {
|
|
158
|
+
logWarning(`Your config includes server headers that will be removed in sandbox mode: ${headerKeys.join(", ")}`);
|
|
159
|
+
}
|
|
146
160
|
}
|
|
147
161
|
function isExternalUrl(url) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
"0.0.0.0",
|
|
155
|
-
"::"
|
|
156
|
-
].includes(parsed.hostname);
|
|
157
|
-
} catch {
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
162
|
+
try {
|
|
163
|
+
const parsed = new URL(url);
|
|
164
|
+
return !["localhost", "127.0.0.1", "::1", "0.0.0.0", "::"].includes(parsed.hostname);
|
|
165
|
+
} catch {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
160
168
|
}
|
|
161
169
|
function validateProxy(config) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
const proxy = config.server?.proxy;
|
|
171
|
+
if (!proxy)
|
|
172
|
+
return;
|
|
173
|
+
for (const [path, proxyConfig] of Object.entries(proxy)) {
|
|
174
|
+
if (typeof proxyConfig === "string") {
|
|
175
|
+
if (isExternalUrl(proxyConfig)) {
|
|
176
|
+
logWarning(
|
|
177
|
+
`Proxy '${path}' targets external URL: ${proxyConfig}. This may cause issues in the sandbox environment.`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
} else if (proxyConfig) {
|
|
181
|
+
const target = typeof proxyConfig.target === "string" ? proxyConfig.target : void 0;
|
|
182
|
+
if (target && isExternalUrl(target)) {
|
|
183
|
+
logWarning(
|
|
184
|
+
`Proxy '${path}' targets external URL: ${target}. This may cause issues in the sandbox environment.`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
if (proxyConfig.ws) {
|
|
188
|
+
logWarning(`Proxy '${path}' enables WebSocket proxying, which may interfere with HMR.`);
|
|
189
|
+
}
|
|
190
|
+
if (proxyConfig.changeOrigin) {
|
|
191
|
+
logWarning(`Proxy '${path}' changes origin, which may cause CORS issues.`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
172
195
|
}
|
|
173
196
|
function validateCors(config) {
|
|
174
|
-
|
|
197
|
+
if (config.server?.cors && typeof config.server.cors !== "boolean" && config.server.cors !== null) {
|
|
198
|
+
logWarning("Custom CORS config detected. Sandbox requires specific CORS settings for proxy compatibility.");
|
|
199
|
+
}
|
|
175
200
|
}
|
|
176
201
|
function validatePort(config) {
|
|
177
|
-
|
|
202
|
+
if (config.server?.port && config.server.port !== 8080) {
|
|
203
|
+
logWarning(`Port ${config.server.port} configured, but sandbox requires port 8080. Using 8080.`);
|
|
204
|
+
}
|
|
178
205
|
}
|
|
179
206
|
function validateConfig(config) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
207
|
+
validateHeaders(config);
|
|
208
|
+
validateProxy(config);
|
|
209
|
+
validateCors(config);
|
|
210
|
+
validatePort(config);
|
|
184
211
|
}
|
|
185
212
|
function cleanServerConfig(config) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
213
|
+
if (config.server?.headers || config.server?.cors || config.server?.proxy) {
|
|
214
|
+
const { headers: _headers, cors: _cors, proxy: _proxy, ...serverRest } = config.server;
|
|
215
|
+
return {
|
|
216
|
+
...config,
|
|
217
|
+
server: serverRest
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
return config;
|
|
194
221
|
}
|
|
195
222
|
function applyWatchDebounceDefaults(config) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
223
|
+
const existingWatch = config.server?.watch ?? {};
|
|
224
|
+
const existingAwaitWriteFinish = existingWatch.awaitWriteFinish;
|
|
225
|
+
const hasAwaitWriteFinishObject = !!existingAwaitWriteFinish && typeof existingAwaitWriteFinish === "object" && !Array.isArray(existingAwaitWriteFinish);
|
|
226
|
+
return (0, import_vite.mergeConfig)(config, {
|
|
227
|
+
server: {
|
|
228
|
+
watch: {
|
|
229
|
+
...existingWatch,
|
|
230
|
+
awaitWriteFinish: {
|
|
231
|
+
...hasAwaitWriteFinishObject ? existingAwaitWriteFinish : {},
|
|
232
|
+
stabilityThreshold: 1e3,
|
|
233
|
+
pollInterval: 100
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
});
|
|
207
238
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
239
|
+
var SSR_CAPTURE_KEY = "__LOVABLE_TANSTACK_CAPTURE_SSR_ERROR__";
|
|
240
|
+
var HANDLER_RAN_KEY = "__LOVABLE_TANSTACK_HANDLER_RAN__";
|
|
241
|
+
var BUILD_ERROR_MESSAGE = /transform failed with \d+ error|failed to parse source/i;
|
|
211
242
|
function isBuildError(error) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
243
|
+
if (typeof error === "string")
|
|
244
|
+
return BUILD_ERROR_MESSAGE.test(error);
|
|
245
|
+
if (!error || typeof error !== "object")
|
|
246
|
+
return false;
|
|
247
|
+
const e = error;
|
|
248
|
+
if (typeof e.plugin === "string" && (e.plugin.startsWith("vite:") || e.plugin.startsWith("esbuild:")))
|
|
249
|
+
return true;
|
|
250
|
+
if (e.frame != null && e.loc != null)
|
|
251
|
+
return true;
|
|
252
|
+
if (Array.isArray(e.errors) && e.errors.length > 0 && e.errors.every((x) => x != null && typeof x === "object" && "text" in x && "location" in x)) {
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
const message = typeof e.message === "string" ? e.message : "";
|
|
256
|
+
return BUILD_ERROR_MESSAGE.test(message);
|
|
220
257
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
258
|
+
var BUILD_DIAGNOSTICS_PLUGIN_NAME = "lovable-build-error-diagnostics";
|
|
259
|
+
var MAX_DIAGNOSTIC_JSON_LENGTH = 6e3;
|
|
260
|
+
var MAX_DIAGNOSTIC_STRING_LENGTH = 2e3;
|
|
261
|
+
var MAX_DIAGNOSTIC_NESTED_ERRORS = 20;
|
|
262
|
+
var MAX_DIAGNOSTIC_DEPTH = 4;
|
|
263
|
+
var COMPACT_DIAGNOSTIC_STRING_LENGTH = 300;
|
|
264
|
+
var COMPACT_DIAGNOSTIC_NESTED_ERRORS = 3;
|
|
265
|
+
var COMPACT_DIAGNOSTIC_DEPTH = 3;
|
|
266
|
+
var DIAGNOSTIC_ERROR_FIELDS = [
|
|
267
|
+
"name",
|
|
268
|
+
"message",
|
|
269
|
+
"plugin",
|
|
270
|
+
"pluginCode",
|
|
271
|
+
"id",
|
|
272
|
+
"moduleId",
|
|
273
|
+
"hook",
|
|
274
|
+
"code",
|
|
275
|
+
"loc",
|
|
276
|
+
"frame",
|
|
277
|
+
"stack",
|
|
278
|
+
"cause"
|
|
242
279
|
];
|
|
243
280
|
function truncateDiagnosticString(value) {
|
|
244
|
-
|
|
281
|
+
return truncateDiagnosticStringTo(value, MAX_DIAGNOSTIC_STRING_LENGTH);
|
|
245
282
|
}
|
|
246
283
|
function truncateDiagnosticStringTo(value, maxLength) {
|
|
247
|
-
|
|
284
|
+
return value.length > maxLength ? `${value.slice(0, maxLength)}...[truncated]` : value;
|
|
248
285
|
}
|
|
249
286
|
function readDiagnosticProperty(value, key) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
287
|
+
try {
|
|
288
|
+
return value[key];
|
|
289
|
+
} catch (error) {
|
|
290
|
+
return `[unreadable: ${error instanceof Error ? error.message : String(error)}]`;
|
|
291
|
+
}
|
|
255
292
|
}
|
|
256
293
|
function serializeOwnDiagnosticProperties(value, depth, seen) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
294
|
+
const keys = Object.keys(value);
|
|
295
|
+
const output = {};
|
|
296
|
+
for (const key of keys.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS)) {
|
|
297
|
+
const nested = readDiagnosticProperty(value, key);
|
|
298
|
+
if (nested == null || nested === "")
|
|
299
|
+
continue;
|
|
300
|
+
output[key] = serializeDiagnosticValue(nested, depth + 1, seen);
|
|
301
|
+
}
|
|
302
|
+
if (keys.length > MAX_DIAGNOSTIC_NESTED_ERRORS) {
|
|
303
|
+
output.properties_truncated = keys.length - MAX_DIAGNOSTIC_NESTED_ERRORS;
|
|
304
|
+
}
|
|
305
|
+
return output;
|
|
266
306
|
}
|
|
267
307
|
function describeDiagnosticPrimitive(value) {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
308
|
+
if (typeof value === "symbol")
|
|
309
|
+
return value.description ? `Symbol(${value.description})` : "Symbol()";
|
|
310
|
+
if (typeof value === "bigint")
|
|
311
|
+
return value.toString();
|
|
312
|
+
if (typeof value === "function")
|
|
313
|
+
return `[function ${value.name || "anonymous"}]`;
|
|
314
|
+
return String(value);
|
|
272
315
|
}
|
|
273
316
|
function describeDiagnosticObject(value) {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
317
|
+
const constructorName = value.constructor?.name;
|
|
318
|
+
if (typeof constructorName === "string" && constructorName !== "" && constructorName !== "Object") {
|
|
319
|
+
return `[${constructorName}]`;
|
|
320
|
+
}
|
|
321
|
+
return Object.prototype.toString.call(value);
|
|
277
322
|
}
|
|
278
323
|
function serializeDiagnosticValue(value, depth, seen) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
324
|
+
if (value == null)
|
|
325
|
+
return value;
|
|
326
|
+
if (typeof value === "string")
|
|
327
|
+
return truncateDiagnosticString(value);
|
|
328
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
329
|
+
return value;
|
|
330
|
+
if (typeof value !== "object")
|
|
331
|
+
return describeDiagnosticPrimitive(value);
|
|
332
|
+
if (seen.has(value))
|
|
333
|
+
return "[circular]";
|
|
334
|
+
if (depth >= MAX_DIAGNOSTIC_DEPTH)
|
|
335
|
+
return "[max depth]";
|
|
336
|
+
seen.add(value);
|
|
337
|
+
try {
|
|
338
|
+
if (Array.isArray(value)) {
|
|
339
|
+
return value.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS).map((item) => serializeDiagnosticValue(item, depth + 1, seen));
|
|
340
|
+
}
|
|
341
|
+
const record = value;
|
|
342
|
+
const output = {};
|
|
343
|
+
for (const field of DIAGNOSTIC_ERROR_FIELDS) {
|
|
344
|
+
if (!(field in record))
|
|
345
|
+
continue;
|
|
346
|
+
const nested = readDiagnosticProperty(record, field);
|
|
347
|
+
if (nested == null || nested === "")
|
|
348
|
+
continue;
|
|
349
|
+
output[field] = serializeDiagnosticValue(nested, depth + 1, seen);
|
|
350
|
+
}
|
|
351
|
+
const nestedErrors = readDiagnosticProperty(record, "errors");
|
|
352
|
+
if (Array.isArray(nestedErrors)) {
|
|
353
|
+
output.errors = nestedErrors.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS).map((item) => serializeDiagnosticValue(item, depth + 1, seen));
|
|
354
|
+
if (nestedErrors.length > MAX_DIAGNOSTIC_NESTED_ERRORS) {
|
|
355
|
+
output.errors_truncated = nestedErrors.length - MAX_DIAGNOSTIC_NESTED_ERRORS;
|
|
356
|
+
}
|
|
357
|
+
} else if (nestedErrors != null && nestedErrors !== "") {
|
|
358
|
+
output.errors = serializeDiagnosticValue(nestedErrors, depth + 1, seen);
|
|
359
|
+
}
|
|
360
|
+
if (Object.keys(output).length > 0)
|
|
361
|
+
return output;
|
|
362
|
+
const ownProperties = serializeOwnDiagnosticProperties(record, depth, seen);
|
|
363
|
+
return Object.keys(ownProperties).length > 0 ? ownProperties : describeDiagnosticObject(value);
|
|
364
|
+
} catch (error) {
|
|
365
|
+
return `[unreadable object: ${error instanceof Error ? error.message : String(error)}]`;
|
|
366
|
+
} finally {
|
|
367
|
+
seen.delete(value);
|
|
368
|
+
}
|
|
309
369
|
}
|
|
310
370
|
function compactDiagnosticValue(value, depth) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
371
|
+
if (value == null)
|
|
372
|
+
return value;
|
|
373
|
+
if (typeof value === "string")
|
|
374
|
+
return truncateDiagnosticStringTo(value, COMPACT_DIAGNOSTIC_STRING_LENGTH);
|
|
375
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
376
|
+
return value;
|
|
377
|
+
if (typeof value !== "object")
|
|
378
|
+
return describeDiagnosticPrimitive(value);
|
|
379
|
+
if (depth >= COMPACT_DIAGNOSTIC_DEPTH)
|
|
380
|
+
return "[max depth]";
|
|
381
|
+
try {
|
|
382
|
+
if (Array.isArray(value)) {
|
|
383
|
+
const items = value.slice(0, COMPACT_DIAGNOSTIC_NESTED_ERRORS).map((item) => compactDiagnosticValue(item, depth + 1));
|
|
384
|
+
if (value.length > COMPACT_DIAGNOSTIC_NESTED_ERRORS) {
|
|
385
|
+
items.push(`[${value.length - COMPACT_DIAGNOSTIC_NESTED_ERRORS} items truncated]`);
|
|
386
|
+
}
|
|
387
|
+
return items;
|
|
388
|
+
}
|
|
389
|
+
const record = value;
|
|
390
|
+
const output = {};
|
|
391
|
+
const keys = Object.keys(record);
|
|
392
|
+
for (const key of keys.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS)) {
|
|
393
|
+
const nested = readDiagnosticProperty(record, key);
|
|
394
|
+
if (nested == null || nested === "")
|
|
395
|
+
continue;
|
|
396
|
+
output[key] = compactDiagnosticValue(nested, depth + 1);
|
|
397
|
+
}
|
|
398
|
+
if (keys.length > MAX_DIAGNOSTIC_NESTED_ERRORS) {
|
|
399
|
+
output.properties_truncated = keys.length - MAX_DIAGNOSTIC_NESTED_ERRORS;
|
|
400
|
+
}
|
|
401
|
+
return output;
|
|
402
|
+
} catch (error) {
|
|
403
|
+
return `[unreadable object: ${error instanceof Error ? error.message : String(error)}]`;
|
|
404
|
+
}
|
|
335
405
|
}
|
|
336
406
|
function stringifyDiagnosticPayload(diagnostics) {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
return JSON.stringify({
|
|
350
|
-
diagnostics_truncated: true,
|
|
351
|
-
message: "Diagnostic payload exceeded output budget."
|
|
352
|
-
});
|
|
407
|
+
const full = JSON.stringify(diagnostics);
|
|
408
|
+
if (full && full.length <= MAX_DIAGNOSTIC_JSON_LENGTH)
|
|
409
|
+
return full;
|
|
410
|
+
const compact = compactDiagnosticValue(diagnostics, 0);
|
|
411
|
+
const compactPayload = compact != null && typeof compact === "object" && !Array.isArray(compact) ? { ...compact, diagnostics_truncated: true } : { diagnostics_truncated: true, value: compact };
|
|
412
|
+
const compactJson = JSON.stringify(compactPayload);
|
|
413
|
+
if (compactJson.length <= MAX_DIAGNOSTIC_JSON_LENGTH)
|
|
414
|
+
return compactJson;
|
|
415
|
+
return JSON.stringify({
|
|
416
|
+
diagnostics_truncated: true,
|
|
417
|
+
message: "Diagnostic payload exceeded output budget."
|
|
418
|
+
});
|
|
353
419
|
}
|
|
354
420
|
function lovableBuildErrorDiagnostics() {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
421
|
+
let emitted = false;
|
|
422
|
+
const emitDiagnostics = (error) => {
|
|
423
|
+
if (!error || emitted)
|
|
424
|
+
return;
|
|
425
|
+
emitted = true;
|
|
426
|
+
try {
|
|
427
|
+
const diagnostics = serializeDiagnosticValue(error, 0, /* @__PURE__ */ new WeakSet());
|
|
428
|
+
const output = `
|
|
429
|
+
[lovable-build-error-diagnostics]
|
|
430
|
+
${stringifyDiagnosticPayload(diagnostics)}
|
|
431
|
+
[/lovable-build-error-diagnostics]
|
|
432
|
+
`;
|
|
433
|
+
let written = false;
|
|
434
|
+
const write = () => {
|
|
435
|
+
if (written)
|
|
436
|
+
return;
|
|
437
|
+
written = true;
|
|
438
|
+
try {
|
|
439
|
+
process.stderr.write(output);
|
|
440
|
+
} catch {
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
setImmediate(write);
|
|
444
|
+
process.once("exit", write);
|
|
445
|
+
} catch {
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
return {
|
|
449
|
+
name: BUILD_DIAGNOSTICS_PLUGIN_NAME,
|
|
450
|
+
apply: "build",
|
|
451
|
+
buildEnd(error) {
|
|
452
|
+
emitDiagnostics(error);
|
|
453
|
+
},
|
|
454
|
+
// Rolldown raises output-phase errors after a clean buildEnd; only
|
|
455
|
+
// renderError sees them.
|
|
456
|
+
renderError(error) {
|
|
457
|
+
emitDiagnostics(error);
|
|
458
|
+
}
|
|
459
|
+
};
|
|
383
460
|
}
|
|
384
461
|
function devSsrErrorLogger() {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
462
|
+
let lastCapture;
|
|
463
|
+
const CAPTURE_TTL_MS = 5e3;
|
|
464
|
+
const handlerRanFlag = Symbol("lovableHandlerRan");
|
|
465
|
+
const capture = (error) => {
|
|
466
|
+
lastCapture = { error, at: Date.now() };
|
|
467
|
+
};
|
|
468
|
+
const consumeCapture = () => {
|
|
469
|
+
if (!lastCapture)
|
|
470
|
+
return void 0;
|
|
471
|
+
if (Date.now() - lastCapture.at > CAPTURE_TTL_MS) {
|
|
472
|
+
lastCapture = void 0;
|
|
473
|
+
return void 0;
|
|
474
|
+
}
|
|
475
|
+
const { error } = lastCapture;
|
|
476
|
+
lastCapture = void 0;
|
|
477
|
+
return error;
|
|
478
|
+
};
|
|
479
|
+
return {
|
|
480
|
+
name: "dev-ssr-error-logger",
|
|
481
|
+
apply: "serve",
|
|
482
|
+
configureServer(server) {
|
|
483
|
+
globalThis[SSR_CAPTURE_KEY] = capture;
|
|
484
|
+
globalThis[HANDLER_RAN_KEY] = (event) => {
|
|
485
|
+
const res = event?.node?.res;
|
|
486
|
+
if (res)
|
|
487
|
+
res[handlerRanFlag] = true;
|
|
488
|
+
};
|
|
489
|
+
const g = globalThis;
|
|
490
|
+
if (typeof g.addEventListener === "function") {
|
|
491
|
+
const addListener = g.addEventListener;
|
|
492
|
+
addListener("error", (e) => capture(e.error ?? e));
|
|
493
|
+
addListener("unhandledrejection", (e) => capture(e.reason));
|
|
494
|
+
}
|
|
495
|
+
const onUnhandledRejection = (reason) => capture(reason);
|
|
496
|
+
process.on("unhandledRejection", onUnhandledRejection);
|
|
497
|
+
server.httpServer?.once("close", () => {
|
|
498
|
+
process.off("unhandledRejection", onUnhandledRejection);
|
|
499
|
+
});
|
|
500
|
+
server.middlewares.use((req, res, next) => {
|
|
501
|
+
let handled = false;
|
|
502
|
+
const handleErrorResponse = () => {
|
|
503
|
+
if (handled || res.statusCode < 500)
|
|
504
|
+
return;
|
|
505
|
+
handled = true;
|
|
506
|
+
const captured = consumeCapture();
|
|
507
|
+
const ranHandler = Boolean(res[handlerRanFlag]);
|
|
508
|
+
let source;
|
|
509
|
+
if (!ranHandler) {
|
|
510
|
+
source = "vite";
|
|
511
|
+
} else if (isBuildError(captured)) {
|
|
512
|
+
source = "build";
|
|
513
|
+
} else {
|
|
514
|
+
source = "app";
|
|
515
|
+
}
|
|
516
|
+
if (!res.headersSent) {
|
|
517
|
+
try {
|
|
518
|
+
res.setHeader("x-lovable-error-source", source);
|
|
519
|
+
} catch {
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
const where = [req.method, req.url].filter(Boolean).join(" ") || "the request";
|
|
523
|
+
let data;
|
|
524
|
+
if (captured instanceof Error) {
|
|
525
|
+
data = { name: captured.name, message: captured.message, stack: captured.stack };
|
|
526
|
+
} else if (typeof captured === "string" && captured.length > 0) {
|
|
527
|
+
data = { name: "Error", message: captured };
|
|
528
|
+
} else if (ranHandler) {
|
|
529
|
+
data = {
|
|
530
|
+
message: `The app returned ${res.statusCode} while handling ${where}. The error was handled by a route or error boundary, so no stack was captured \u2014 check the failing loader/route code and the dev server output.`
|
|
531
|
+
};
|
|
532
|
+
} else {
|
|
533
|
+
data = {
|
|
534
|
+
message: `Dev server returned ${res.statusCode} for ${where} before the app handler ran. This is usually a Vite build/transform error \u2014 check the dev server output for the underlying error.`
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
try {
|
|
538
|
+
server.ws.send({ type: "custom", event: "server-ssr-error", data });
|
|
539
|
+
} catch {
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
const origWriteHead = res.writeHead.bind(res);
|
|
543
|
+
res.writeHead = (...args) => {
|
|
544
|
+
if (typeof args[0] === "number")
|
|
545
|
+
res.statusCode = args[0];
|
|
546
|
+
handleErrorResponse();
|
|
547
|
+
return origWriteHead(...args);
|
|
548
|
+
};
|
|
549
|
+
const origEnd = res.end.bind(res);
|
|
550
|
+
res.end = (...args) => {
|
|
551
|
+
handleErrorResponse();
|
|
552
|
+
return origEnd(...args);
|
|
553
|
+
};
|
|
554
|
+
next();
|
|
555
|
+
});
|
|
556
|
+
},
|
|
557
|
+
transform(code, id) {
|
|
558
|
+
const normalizedId = id.replace(/\\/g, "/");
|
|
559
|
+
const isTargetModule = normalizedId.includes("/@tanstack/start-server-core/src/request-response.ts") || normalizedId.includes("/@tanstack/start-server-core/dist/esm/request-response.js");
|
|
560
|
+
if (!isTargetModule) {
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
const needle = "handler(request, requestOpts)";
|
|
564
|
+
if (!code.includes(needle)) {
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
return code.replace(
|
|
568
|
+
needle,
|
|
569
|
+
`(globalThis.${HANDLER_RAN_KEY}?.(typeof h3Event === "undefined" ? undefined : h3Event), Promise.resolve(${needle}).catch((err) => { globalThis.${SSR_CAPTURE_KEY}?.(err); throw err; }))`
|
|
570
|
+
);
|
|
571
|
+
}
|
|
572
|
+
};
|
|
481
573
|
}
|
|
482
574
|
function devServerFnErrorLogger() {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
575
|
+
const HMR_SEND_KEY = "__TANSTACK_SERVER_FN_HMR_SEND__";
|
|
576
|
+
return {
|
|
577
|
+
name: "dev-server-fn-error-logger",
|
|
578
|
+
apply: "serve",
|
|
579
|
+
enforce: "pre",
|
|
580
|
+
configureServer(server) {
|
|
581
|
+
globalThis[HMR_SEND_KEY] = (data) => {
|
|
582
|
+
server.ws.send({
|
|
583
|
+
type: "custom",
|
|
584
|
+
event: "server-fn-error",
|
|
585
|
+
data
|
|
586
|
+
});
|
|
587
|
+
};
|
|
588
|
+
},
|
|
589
|
+
transform(code, id) {
|
|
590
|
+
const normalizedId = id.replace(/\\/g, "/");
|
|
591
|
+
const isTargetModule = normalizedId.includes("/@tanstack/start-server-core/src/server-functions-handler.ts") || normalizedId.includes("/@tanstack/start-server-core/dist/esm/server-functions-handler.js");
|
|
592
|
+
if (!isTargetModule) {
|
|
593
|
+
return null;
|
|
594
|
+
}
|
|
595
|
+
const needle = "const unwrapped = res.result || res.error";
|
|
596
|
+
if (!code.includes(needle)) {
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
599
|
+
return code.replace(
|
|
600
|
+
needle,
|
|
601
|
+
`${needle}
|
|
503
602
|
|
|
504
603
|
if (res?.error) {
|
|
505
604
|
const err = res.error
|
|
@@ -513,156 +612,192 @@ function devServerFnErrorLogger() {
|
|
|
513
612
|
stack: typeof err?.stack === 'string' ? err.stack : undefined,
|
|
514
613
|
}
|
|
515
614
|
globalThis.${HMR_SEND_KEY}?.(payload)
|
|
516
|
-
}`
|
|
517
|
-
|
|
518
|
-
|
|
615
|
+
}`
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
};
|
|
519
619
|
}
|
|
520
620
|
function defineConfig(configOrOptions = {}) {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
621
|
+
return async (env) => {
|
|
622
|
+
const { command, mode } = env;
|
|
623
|
+
const isSandbox = isSandboxEnvironment();
|
|
624
|
+
const isDevBuild = command === "build" && mode === "development";
|
|
625
|
+
let options;
|
|
626
|
+
if (typeof configOrOptions === "function") {
|
|
627
|
+
const userConfig = await Promise.resolve(configOrOptions(env));
|
|
628
|
+
options = { vite: userConfig };
|
|
629
|
+
} else if (configOrOptions instanceof Promise) {
|
|
630
|
+
options = { vite: await configOrOptions };
|
|
631
|
+
} else {
|
|
632
|
+
const optionObject = configOrOptions && typeof configOrOptions === "object" ? configOrOptions : {};
|
|
633
|
+
if ("cloudflare" in optionObject) {
|
|
634
|
+
if (optionObject.cloudflare === false && !("nitro" in optionObject)) {
|
|
635
|
+
optionObject.nitro = false;
|
|
636
|
+
logWarning(
|
|
637
|
+
"`cloudflare: false` is deprecated in v2 \u2014 migrated to `nitro: false`. Update your config to drop the warning."
|
|
638
|
+
);
|
|
639
|
+
} else {
|
|
640
|
+
logWarning(
|
|
641
|
+
"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."
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
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;
|
|
646
|
+
options = hasLovableKey ? optionObject : { vite: optionObject };
|
|
647
|
+
}
|
|
648
|
+
const internalPlugins = [];
|
|
649
|
+
if (mode === "development") {
|
|
650
|
+
const { devtools } = await import("@tanstack/devtools-vite");
|
|
651
|
+
internalPlugins.push(
|
|
652
|
+
devtools({
|
|
653
|
+
logging: false,
|
|
654
|
+
eventBusConfig: { enabled: false },
|
|
655
|
+
enhancedLogs: { enabled: false },
|
|
656
|
+
consolePiping: { enabled: false },
|
|
657
|
+
removeDevtoolsOnBuild: false,
|
|
658
|
+
injectSource: { enabled: true }
|
|
659
|
+
})
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
const tailwindcss = (await import("@tailwindcss/vite")).default;
|
|
663
|
+
internalPlugins.push(tailwindcss());
|
|
664
|
+
const tsConfigPaths = (await import("vite-tsconfig-paths")).default;
|
|
665
|
+
internalPlugins.push(tsConfigPaths({ projects: ["./tsconfig.json"] }));
|
|
666
|
+
if (options.serverFnErrorLogger !== false) {
|
|
667
|
+
internalPlugins.push(devServerFnErrorLogger());
|
|
668
|
+
}
|
|
669
|
+
if (options.ssrErrorLogger !== false) {
|
|
670
|
+
internalPlugins.push(devSsrErrorLogger());
|
|
671
|
+
}
|
|
672
|
+
if (command === "build" && isSandbox) {
|
|
673
|
+
internalPlugins.push(lovableBuildErrorDiagnostics());
|
|
674
|
+
}
|
|
675
|
+
const { tanstackStart } = await import("@tanstack/react-start/plugin/vite");
|
|
676
|
+
const tanstackStartDefaults = {
|
|
677
|
+
importProtection: {
|
|
678
|
+
behavior: "error",
|
|
679
|
+
client: {
|
|
680
|
+
files: ["**/server/**"],
|
|
681
|
+
specifiers: ["server-only"]
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
const tanstackStartOptions = (0, import_vite.mergeConfig)(tanstackStartDefaults, options.tanstackStart ?? {});
|
|
686
|
+
internalPlugins.push(tanstackStart(tanstackStartOptions));
|
|
687
|
+
const explicitNitro = options.nitro === true || typeof options.nitro === "object" && options.nitro !== null;
|
|
688
|
+
const shouldRunNitro = options.nitro !== false && command === "build";
|
|
689
|
+
if (shouldRunNitro) {
|
|
690
|
+
let nitroMod;
|
|
691
|
+
try {
|
|
692
|
+
nitroMod = await import("nitro/vite");
|
|
693
|
+
} catch (err) {
|
|
694
|
+
if (explicitNitro || isSandbox) {
|
|
695
|
+
const reason = explicitNitro ? `an explicit \`nitro\` option (${options.nitro === true ? "true" : "{ ... }"}) was set in vite.config.ts` : "running inside a Lovable sandbox";
|
|
696
|
+
throw new Error(
|
|
697
|
+
`[@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)}`
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
if (nitroMod) {
|
|
702
|
+
const { nitro } = nitroMod;
|
|
703
|
+
const userNitroOpts = typeof options.nitro === "object" && options.nitro ? options.nitro : {};
|
|
704
|
+
const nitroOpts = { defaultPreset: "cloudflare-module", ...userNitroOpts };
|
|
705
|
+
if (isSandbox) {
|
|
706
|
+
delete nitroOpts.defaultPreset;
|
|
707
|
+
nitroOpts.preset = "cloudflare-module";
|
|
708
|
+
nitroOpts.output = { dir: "dist", serverDir: "dist/server", publicDir: "dist/client" };
|
|
709
|
+
nitroOpts.cloudflare = { nodeCompat: true, deployConfig: true, ...userNitroOpts.cloudflare };
|
|
710
|
+
} else if (!nitroOpts.preset && !await nitroSupportsDefaultPreset()) {
|
|
711
|
+
logWarning(
|
|
712
|
+
'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" }`.'
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
internalPlugins.push(nitro(nitroOpts));
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
const viteReact = (await import("@vitejs/plugin-react")).default;
|
|
719
|
+
internalPlugins.push(viteReact(options.react));
|
|
720
|
+
if (command === "serve") {
|
|
721
|
+
const hmrGateOpt = options.hmrGate;
|
|
722
|
+
const enableHmrGate = isSandbox ? hmrGateOpt !== false : !!hmrGateOpt;
|
|
723
|
+
if (enableHmrGate) {
|
|
724
|
+
const { hmrGatePlugin } = await import("@lovable.dev/vite-plugin-hmr-gate");
|
|
725
|
+
const hmrGateOptions = typeof hmrGateOpt === "object" ? hmrGateOpt : {};
|
|
726
|
+
internalPlugins.push(hmrGatePlugin(hmrGateOptions));
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
if (command === "serve" && isSandbox) {
|
|
730
|
+
const { devServerBridgePlugin } = await import("@lovable.dev/vite-plugin-dev-server-bridge");
|
|
731
|
+
internalPlugins.push(devServerBridgePlugin());
|
|
732
|
+
}
|
|
733
|
+
if (command === "serve") {
|
|
734
|
+
internalPlugins.push(lovableAssetsProxyPlugin());
|
|
735
|
+
}
|
|
736
|
+
let envDefine = {};
|
|
737
|
+
if (options.envDefine !== false) {
|
|
738
|
+
const loadedEnv = (0, import_vite.loadEnv)(mode, process.cwd(), "VITE_");
|
|
739
|
+
for (const [key, value] of Object.entries(loadedEnv)) {
|
|
740
|
+
envDefine[`import.meta.env.${key}`] = JSON.stringify(value);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
let config = {
|
|
744
|
+
define: envDefine,
|
|
745
|
+
// Client-scoped so React DevTools gets the dev react-dom; a global NODE_ENV
|
|
746
|
+
// flip would emit jsxDEV, which the react-server SSR runtime can't resolve.
|
|
747
|
+
...isDevBuild ? {
|
|
748
|
+
environments: { client: { define: { "process.env.NODE_ENV": JSON.stringify("development") } } },
|
|
749
|
+
esbuild: { keepNames: true }
|
|
750
|
+
} : {},
|
|
751
|
+
// Match the build's CSS pipeline in dev. Vite uses PostCSS in dev and only
|
|
752
|
+
// runs Lightning CSS at build, so build-time transforms (e.g. collapsing a
|
|
753
|
+
// hand-written `-webkit-backdrop-filter` to the prefixed form Chrome ignores)
|
|
754
|
+
// break the built/static output while the dev preview looks fine. Running
|
|
755
|
+
// Lightning CSS in both keeps the preview honest.
|
|
756
|
+
css: { transformer: "lightningcss" },
|
|
757
|
+
resolve: {
|
|
758
|
+
alias: {
|
|
759
|
+
"@": `${process.cwd()}/src`
|
|
760
|
+
},
|
|
761
|
+
dedupe: [
|
|
762
|
+
"react",
|
|
763
|
+
"react-dom",
|
|
764
|
+
"react/jsx-runtime",
|
|
765
|
+
"react/jsx-dev-runtime",
|
|
766
|
+
"@tanstack/react-query",
|
|
767
|
+
"@tanstack/query-core"
|
|
768
|
+
]
|
|
769
|
+
},
|
|
770
|
+
// Dep re-optimization rotates the optimized-dep hash and 504s tabs holding
|
|
771
|
+
// the old one; pre-bundle the always-present client deps + tolerate stale
|
|
772
|
+
// requests. React core only — including @tanstack/react-start would pull its
|
|
773
|
+
// node:async_hooks server entry into the client bundle and crash hydration.
|
|
774
|
+
optimizeDeps: {
|
|
775
|
+
include: ["react", "react-dom", "react-dom/client", "react/jsx-runtime", "react/jsx-dev-runtime"],
|
|
776
|
+
ignoreOutdatedRequests: true
|
|
777
|
+
},
|
|
778
|
+
plugins: [...internalPlugins, ...options.plugins ?? []]
|
|
779
|
+
};
|
|
780
|
+
if (options.vite) {
|
|
781
|
+
config = (0, import_vite.mergeConfig)(config, options.vite);
|
|
782
|
+
}
|
|
783
|
+
if (isSandbox) {
|
|
784
|
+
validateConfig(config);
|
|
785
|
+
config = cleanServerConfig(
|
|
786
|
+
(0, import_vite.mergeConfig)(config, {
|
|
787
|
+
server: { host: "::", port: 8080, strictPort: true, watch: { ignored: [...TOOL_MANAGED_WATCH_IGNORES] } }
|
|
788
|
+
})
|
|
789
|
+
);
|
|
790
|
+
} else {
|
|
791
|
+
config = (0, import_vite.mergeConfig)({ server: { host: "::", port: 8080 } }, config);
|
|
792
|
+
}
|
|
793
|
+
if (isSandbox) {
|
|
794
|
+
return config;
|
|
795
|
+
}
|
|
796
|
+
return applyWatchDebounceDefaults(config);
|
|
797
|
+
};
|
|
665
798
|
}
|
|
666
|
-
|
|
667
|
-
exports
|
|
668
|
-
|
|
799
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
800
|
+
0 && (module.exports = {
|
|
801
|
+
defineConfig,
|
|
802
|
+
lovableAssetsProxyPlugin
|
|
803
|
+
});
|