@lovable.dev/vite-tanstack-config 2.6.0 → 2.6.2-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 +283 -2
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +281 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -30,11 +30,92 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
|
-
defineConfig: () => defineConfig
|
|
33
|
+
defineConfig: () => defineConfig,
|
|
34
|
+
lovableAssetsProxyPlugin: () => lovableAssetsProxyPlugin
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(src_exports);
|
|
36
37
|
var import_lovable_tagger = require("lovable-tagger");
|
|
37
38
|
var import_vite = require("vite");
|
|
39
|
+
|
|
40
|
+
// src/assetsProxyPlugin.ts
|
|
41
|
+
var import_node_https = __toESM(require("https"), 1);
|
|
42
|
+
var ASSET_RE = /^\/__l5e\/assets-v1\//;
|
|
43
|
+
var PREVIEW_HOST_ENV = "LOVABLE_PREVIEW_HOST";
|
|
44
|
+
var HOP_BY_HOP = /* @__PURE__ */ new Set([
|
|
45
|
+
"host",
|
|
46
|
+
"connection",
|
|
47
|
+
"keep-alive",
|
|
48
|
+
"proxy-authenticate",
|
|
49
|
+
"proxy-authorization",
|
|
50
|
+
"te",
|
|
51
|
+
"trailer",
|
|
52
|
+
"transfer-encoding",
|
|
53
|
+
"upgrade",
|
|
54
|
+
"content-length",
|
|
55
|
+
"cookie"
|
|
56
|
+
]);
|
|
57
|
+
function pickRequestHeaders(src) {
|
|
58
|
+
const out = {};
|
|
59
|
+
for (const [k, v] of Object.entries(src)) {
|
|
60
|
+
if (v === void 0)
|
|
61
|
+
continue;
|
|
62
|
+
if (HOP_BY_HOP.has(k.toLowerCase()))
|
|
63
|
+
continue;
|
|
64
|
+
out[k] = v;
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
function lovableAssetsProxyPlugin() {
|
|
69
|
+
const previewHost = process.env[PREVIEW_HOST_ENV]?.trim();
|
|
70
|
+
return {
|
|
71
|
+
name: "lovable:assets-proxy",
|
|
72
|
+
apply: "serve",
|
|
73
|
+
configureServer(server) {
|
|
74
|
+
if (!previewHost)
|
|
75
|
+
return;
|
|
76
|
+
const middleware = (req, res, next) => {
|
|
77
|
+
const url = req.url ?? "";
|
|
78
|
+
if (!ASSET_RE.test(url))
|
|
79
|
+
return next();
|
|
80
|
+
const upstream = import_node_https.default.request(
|
|
81
|
+
{
|
|
82
|
+
host: previewHost,
|
|
83
|
+
port: 443,
|
|
84
|
+
method: req.method,
|
|
85
|
+
path: url,
|
|
86
|
+
headers: { ...pickRequestHeaders(req.headers), host: previewHost }
|
|
87
|
+
},
|
|
88
|
+
(upRes) => {
|
|
89
|
+
res.statusCode = upRes.statusCode ?? 502;
|
|
90
|
+
for (const [k, v] of Object.entries(upRes.headers)) {
|
|
91
|
+
if (v === void 0)
|
|
92
|
+
continue;
|
|
93
|
+
if (HOP_BY_HOP.has(k.toLowerCase()))
|
|
94
|
+
continue;
|
|
95
|
+
res.setHeader(k, v);
|
|
96
|
+
}
|
|
97
|
+
upRes.pipe(res);
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
upstream.on("error", (err) => {
|
|
101
|
+
server.config.logger.warn(
|
|
102
|
+
`[@lovable.dev/vite-tanstack-config] asset proxy ${url} \u2192 ${previewHost} failed: ${err.message}`
|
|
103
|
+
);
|
|
104
|
+
if (!res.headersSent) {
|
|
105
|
+
res.statusCode = 502;
|
|
106
|
+
res.end();
|
|
107
|
+
} else {
|
|
108
|
+
res.destroy(err);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
req.pipe(upstream);
|
|
112
|
+
};
|
|
113
|
+
server.middlewares.use(middleware);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/index.ts
|
|
38
119
|
var SANDBOX_ENV_VAR = "DEV_SERVER__PROJECT_PATH";
|
|
39
120
|
var LOVABLE_SANDBOX_ENV_VAR = "LOVABLE_SANDBOX";
|
|
40
121
|
function isSandboxEnvironment() {
|
|
@@ -175,6 +256,199 @@ function isBuildError(error) {
|
|
|
175
256
|
const message = typeof e.message === "string" ? e.message : "";
|
|
176
257
|
return BUILD_ERROR_MESSAGE.test(message);
|
|
177
258
|
}
|
|
259
|
+
var BUILD_DIAGNOSTICS_PLUGIN_NAME = "lovable-build-error-diagnostics";
|
|
260
|
+
var MAX_DIAGNOSTIC_JSON_LENGTH = 6e3;
|
|
261
|
+
var MAX_DIAGNOSTIC_STRING_LENGTH = 2e3;
|
|
262
|
+
var MAX_DIAGNOSTIC_NESTED_ERRORS = 20;
|
|
263
|
+
var MAX_DIAGNOSTIC_DEPTH = 4;
|
|
264
|
+
var COMPACT_DIAGNOSTIC_STRING_LENGTH = 300;
|
|
265
|
+
var COMPACT_DIAGNOSTIC_NESTED_ERRORS = 3;
|
|
266
|
+
var COMPACT_DIAGNOSTIC_DEPTH = 3;
|
|
267
|
+
var DIAGNOSTIC_ERROR_FIELDS = [
|
|
268
|
+
"name",
|
|
269
|
+
"message",
|
|
270
|
+
"plugin",
|
|
271
|
+
"pluginCode",
|
|
272
|
+
"id",
|
|
273
|
+
"moduleId",
|
|
274
|
+
"hook",
|
|
275
|
+
"code",
|
|
276
|
+
"loc",
|
|
277
|
+
"frame",
|
|
278
|
+
"stack",
|
|
279
|
+
"cause"
|
|
280
|
+
];
|
|
281
|
+
function truncateDiagnosticString(value) {
|
|
282
|
+
return truncateDiagnosticStringTo(value, MAX_DIAGNOSTIC_STRING_LENGTH);
|
|
283
|
+
}
|
|
284
|
+
function truncateDiagnosticStringTo(value, maxLength) {
|
|
285
|
+
return value.length > maxLength ? `${value.slice(0, maxLength)}...[truncated]` : value;
|
|
286
|
+
}
|
|
287
|
+
function readDiagnosticProperty(value, key) {
|
|
288
|
+
try {
|
|
289
|
+
return value[key];
|
|
290
|
+
} catch (error) {
|
|
291
|
+
return `[unreadable: ${error instanceof Error ? error.message : String(error)}]`;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function serializeOwnDiagnosticProperties(value, depth, seen) {
|
|
295
|
+
const keys = Object.keys(value);
|
|
296
|
+
const output = {};
|
|
297
|
+
for (const key of keys.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS)) {
|
|
298
|
+
const nested = readDiagnosticProperty(value, key);
|
|
299
|
+
if (nested == null || nested === "")
|
|
300
|
+
continue;
|
|
301
|
+
output[key] = serializeDiagnosticValue(nested, depth + 1, seen);
|
|
302
|
+
}
|
|
303
|
+
if (keys.length > MAX_DIAGNOSTIC_NESTED_ERRORS) {
|
|
304
|
+
output.properties_truncated = keys.length - MAX_DIAGNOSTIC_NESTED_ERRORS;
|
|
305
|
+
}
|
|
306
|
+
return output;
|
|
307
|
+
}
|
|
308
|
+
function describeDiagnosticPrimitive(value) {
|
|
309
|
+
if (typeof value === "symbol")
|
|
310
|
+
return value.description ? `Symbol(${value.description})` : "Symbol()";
|
|
311
|
+
if (typeof value === "bigint")
|
|
312
|
+
return value.toString();
|
|
313
|
+
if (typeof value === "function")
|
|
314
|
+
return `[function ${value.name || "anonymous"}]`;
|
|
315
|
+
return String(value);
|
|
316
|
+
}
|
|
317
|
+
function describeDiagnosticObject(value) {
|
|
318
|
+
const constructorName = value.constructor?.name;
|
|
319
|
+
if (typeof constructorName === "string" && constructorName !== "" && constructorName !== "Object") {
|
|
320
|
+
return `[${constructorName}]`;
|
|
321
|
+
}
|
|
322
|
+
return Object.prototype.toString.call(value);
|
|
323
|
+
}
|
|
324
|
+
function serializeDiagnosticValue(value, depth, seen) {
|
|
325
|
+
if (value == null)
|
|
326
|
+
return value;
|
|
327
|
+
if (typeof value === "string")
|
|
328
|
+
return truncateDiagnosticString(value);
|
|
329
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
330
|
+
return value;
|
|
331
|
+
if (typeof value !== "object")
|
|
332
|
+
return describeDiagnosticPrimitive(value);
|
|
333
|
+
if (seen.has(value))
|
|
334
|
+
return "[circular]";
|
|
335
|
+
if (depth >= MAX_DIAGNOSTIC_DEPTH)
|
|
336
|
+
return "[max depth]";
|
|
337
|
+
seen.add(value);
|
|
338
|
+
try {
|
|
339
|
+
if (Array.isArray(value)) {
|
|
340
|
+
return value.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS).map((item) => serializeDiagnosticValue(item, depth + 1, seen));
|
|
341
|
+
}
|
|
342
|
+
const record = value;
|
|
343
|
+
const output = {};
|
|
344
|
+
for (const field of DIAGNOSTIC_ERROR_FIELDS) {
|
|
345
|
+
if (!(field in record))
|
|
346
|
+
continue;
|
|
347
|
+
const nested = readDiagnosticProperty(record, field);
|
|
348
|
+
if (nested == null || nested === "")
|
|
349
|
+
continue;
|
|
350
|
+
output[field] = serializeDiagnosticValue(nested, depth + 1, seen);
|
|
351
|
+
}
|
|
352
|
+
const nestedErrors = readDiagnosticProperty(record, "errors");
|
|
353
|
+
if (Array.isArray(nestedErrors)) {
|
|
354
|
+
output.errors = nestedErrors.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS).map((item) => serializeDiagnosticValue(item, depth + 1, seen));
|
|
355
|
+
if (nestedErrors.length > MAX_DIAGNOSTIC_NESTED_ERRORS) {
|
|
356
|
+
output.errors_truncated = nestedErrors.length - MAX_DIAGNOSTIC_NESTED_ERRORS;
|
|
357
|
+
}
|
|
358
|
+
} else if (nestedErrors != null && nestedErrors !== "") {
|
|
359
|
+
output.errors = serializeDiagnosticValue(nestedErrors, depth + 1, seen);
|
|
360
|
+
}
|
|
361
|
+
if (Object.keys(output).length > 0)
|
|
362
|
+
return output;
|
|
363
|
+
const ownProperties = serializeOwnDiagnosticProperties(record, depth, seen);
|
|
364
|
+
return Object.keys(ownProperties).length > 0 ? ownProperties : describeDiagnosticObject(value);
|
|
365
|
+
} catch (error) {
|
|
366
|
+
return `[unreadable object: ${error instanceof Error ? error.message : String(error)}]`;
|
|
367
|
+
} finally {
|
|
368
|
+
seen.delete(value);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function compactDiagnosticValue(value, depth) {
|
|
372
|
+
if (value == null)
|
|
373
|
+
return value;
|
|
374
|
+
if (typeof value === "string")
|
|
375
|
+
return truncateDiagnosticStringTo(value, COMPACT_DIAGNOSTIC_STRING_LENGTH);
|
|
376
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
377
|
+
return value;
|
|
378
|
+
if (typeof value !== "object")
|
|
379
|
+
return describeDiagnosticPrimitive(value);
|
|
380
|
+
if (depth >= COMPACT_DIAGNOSTIC_DEPTH)
|
|
381
|
+
return "[max depth]";
|
|
382
|
+
try {
|
|
383
|
+
if (Array.isArray(value)) {
|
|
384
|
+
const items = value.slice(0, COMPACT_DIAGNOSTIC_NESTED_ERRORS).map((item) => compactDiagnosticValue(item, depth + 1));
|
|
385
|
+
if (value.length > COMPACT_DIAGNOSTIC_NESTED_ERRORS) {
|
|
386
|
+
items.push(`[${value.length - COMPACT_DIAGNOSTIC_NESTED_ERRORS} items truncated]`);
|
|
387
|
+
}
|
|
388
|
+
return items;
|
|
389
|
+
}
|
|
390
|
+
const record = value;
|
|
391
|
+
const output = {};
|
|
392
|
+
const keys = Object.keys(record);
|
|
393
|
+
for (const key of keys.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS)) {
|
|
394
|
+
const nested = readDiagnosticProperty(record, key);
|
|
395
|
+
if (nested == null || nested === "")
|
|
396
|
+
continue;
|
|
397
|
+
output[key] = compactDiagnosticValue(nested, depth + 1);
|
|
398
|
+
}
|
|
399
|
+
if (keys.length > MAX_DIAGNOSTIC_NESTED_ERRORS) {
|
|
400
|
+
output.properties_truncated = keys.length - MAX_DIAGNOSTIC_NESTED_ERRORS;
|
|
401
|
+
}
|
|
402
|
+
return output;
|
|
403
|
+
} catch (error) {
|
|
404
|
+
return `[unreadable object: ${error instanceof Error ? error.message : String(error)}]`;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function stringifyDiagnosticPayload(diagnostics) {
|
|
408
|
+
const full = JSON.stringify(diagnostics);
|
|
409
|
+
if (full && full.length <= MAX_DIAGNOSTIC_JSON_LENGTH)
|
|
410
|
+
return full;
|
|
411
|
+
const compact = compactDiagnosticValue(diagnostics, 0);
|
|
412
|
+
const compactPayload = compact != null && typeof compact === "object" && !Array.isArray(compact) ? { ...compact, diagnostics_truncated: true } : { diagnostics_truncated: true, value: compact };
|
|
413
|
+
const compactJson = JSON.stringify(compactPayload);
|
|
414
|
+
if (compactJson.length <= MAX_DIAGNOSTIC_JSON_LENGTH)
|
|
415
|
+
return compactJson;
|
|
416
|
+
return JSON.stringify({
|
|
417
|
+
diagnostics_truncated: true,
|
|
418
|
+
message: "Diagnostic payload exceeded output budget."
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
function lovableBuildErrorDiagnostics() {
|
|
422
|
+
return {
|
|
423
|
+
name: BUILD_DIAGNOSTICS_PLUGIN_NAME,
|
|
424
|
+
apply: "build",
|
|
425
|
+
buildEnd(error) {
|
|
426
|
+
if (!error)
|
|
427
|
+
return;
|
|
428
|
+
try {
|
|
429
|
+
const diagnostics = serializeDiagnosticValue(error, 0, /* @__PURE__ */ new WeakSet());
|
|
430
|
+
const output = `
|
|
431
|
+
[lovable-build-error-diagnostics]
|
|
432
|
+
${stringifyDiagnosticPayload(diagnostics)}
|
|
433
|
+
[/lovable-build-error-diagnostics]
|
|
434
|
+
`;
|
|
435
|
+
let written = false;
|
|
436
|
+
const write = () => {
|
|
437
|
+
if (written)
|
|
438
|
+
return;
|
|
439
|
+
written = true;
|
|
440
|
+
try {
|
|
441
|
+
process.stderr.write(output);
|
|
442
|
+
} catch {
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
setImmediate(write);
|
|
446
|
+
process.once("exit", write);
|
|
447
|
+
} catch {
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
}
|
|
178
452
|
function devSsrErrorLogger() {
|
|
179
453
|
let lastCapture;
|
|
180
454
|
const CAPTURE_TTL_MS = 5e3;
|
|
@@ -373,6 +647,9 @@ function defineConfig(configOrOptions = {}) {
|
|
|
373
647
|
if (options.ssrErrorLogger !== false) {
|
|
374
648
|
internalPlugins.push(devSsrErrorLogger());
|
|
375
649
|
}
|
|
650
|
+
if (command === "build" && isSandbox) {
|
|
651
|
+
internalPlugins.push(lovableBuildErrorDiagnostics());
|
|
652
|
+
}
|
|
376
653
|
const { tanstackStart } = await import("@tanstack/react-start/plugin/vite");
|
|
377
654
|
const tanstackStartDefaults = {
|
|
378
655
|
importProtection: {
|
|
@@ -431,6 +708,9 @@ function defineConfig(configOrOptions = {}) {
|
|
|
431
708
|
const { devServerBridgePlugin } = await import("@lovable.dev/vite-plugin-dev-server-bridge");
|
|
432
709
|
internalPlugins.push(devServerBridgePlugin());
|
|
433
710
|
}
|
|
711
|
+
if (command === "serve") {
|
|
712
|
+
internalPlugins.push(lovableAssetsProxyPlugin());
|
|
713
|
+
}
|
|
434
714
|
if (command === "serve" && mode === "development") {
|
|
435
715
|
internalPlugins.push((0, import_lovable_tagger.componentTagger)());
|
|
436
716
|
}
|
|
@@ -499,5 +779,6 @@ function defineConfig(configOrOptions = {}) {
|
|
|
499
779
|
}
|
|
500
780
|
// Annotate the CommonJS export names for ESM import in node:
|
|
501
781
|
0 && (module.exports = {
|
|
502
|
-
defineConfig
|
|
782
|
+
defineConfig,
|
|
783
|
+
lovableAssetsProxyPlugin
|
|
503
784
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import { PluginOption, UserConfig, ConfigEnv, UserConfigFnObject, UserConfigFnPromise, UserConfigFn } from 'vite';
|
|
1
|
+
import { Plugin, PluginOption, UserConfig, ConfigEnv, UserConfigFnObject, UserConfigFnPromise, UserConfigFn } from 'vite';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Forwards `/__l5e/assets-v1/*` requests from the Vite dev server to the
|
|
5
|
+
* Lovable preview proxy so assets resolve when the page is loaded directly
|
|
6
|
+
* from the sandbox dev server (e.g. `localhost:8080`) instead of via
|
|
7
|
+
* `*.lovable.app` / `*.lovableproject.com`.
|
|
8
|
+
*
|
|
9
|
+
* No-op unless `LOVABLE_PREVIEW_HOST` is set (host only, no scheme), e.g.
|
|
10
|
+
* `id-preview--<project-id>.lovable.app`.
|
|
11
|
+
*/
|
|
12
|
+
declare function lovableAssetsProxyPlugin(): Plugin;
|
|
2
13
|
|
|
3
14
|
interface LovableViteTanstackOptions {
|
|
4
15
|
plugins?: PluginOption[];
|
|
@@ -59,4 +70,4 @@ declare function defineConfig(config: UserConfigFnPromise): (env: ConfigEnv) =>
|
|
|
59
70
|
declare function defineConfig(config: UserConfigFn): (env: ConfigEnv) => Promise<UserConfig>;
|
|
60
71
|
declare function defineConfig(options?: LovableViteTanstackOptions): (env: ConfigEnv) => Promise<UserConfig>;
|
|
61
72
|
|
|
62
|
-
export { type LovableViteTanstackOptions, defineConfig };
|
|
73
|
+
export { type LovableViteTanstackOptions, defineConfig, lovableAssetsProxyPlugin };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import { PluginOption, UserConfig, ConfigEnv, UserConfigFnObject, UserConfigFnPromise, UserConfigFn } from 'vite';
|
|
1
|
+
import { Plugin, PluginOption, UserConfig, ConfigEnv, UserConfigFnObject, UserConfigFnPromise, UserConfigFn } from 'vite';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Forwards `/__l5e/assets-v1/*` requests from the Vite dev server to the
|
|
5
|
+
* Lovable preview proxy so assets resolve when the page is loaded directly
|
|
6
|
+
* from the sandbox dev server (e.g. `localhost:8080`) instead of via
|
|
7
|
+
* `*.lovable.app` / `*.lovableproject.com`.
|
|
8
|
+
*
|
|
9
|
+
* No-op unless `LOVABLE_PREVIEW_HOST` is set (host only, no scheme), e.g.
|
|
10
|
+
* `id-preview--<project-id>.lovable.app`.
|
|
11
|
+
*/
|
|
12
|
+
declare function lovableAssetsProxyPlugin(): Plugin;
|
|
2
13
|
|
|
3
14
|
interface LovableViteTanstackOptions {
|
|
4
15
|
plugins?: PluginOption[];
|
|
@@ -59,4 +70,4 @@ declare function defineConfig(config: UserConfigFnPromise): (env: ConfigEnv) =>
|
|
|
59
70
|
declare function defineConfig(config: UserConfigFn): (env: ConfigEnv) => Promise<UserConfig>;
|
|
60
71
|
declare function defineConfig(options?: LovableViteTanstackOptions): (env: ConfigEnv) => Promise<UserConfig>;
|
|
61
72
|
|
|
62
|
-
export { type LovableViteTanstackOptions, defineConfig };
|
|
73
|
+
export { type LovableViteTanstackOptions, defineConfig, lovableAssetsProxyPlugin };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,86 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { componentTagger } from "lovable-tagger";
|
|
3
3
|
import { mergeConfig, loadEnv } from "vite";
|
|
4
|
+
|
|
5
|
+
// src/assetsProxyPlugin.ts
|
|
6
|
+
import https from "https";
|
|
7
|
+
var ASSET_RE = /^\/__l5e\/assets-v1\//;
|
|
8
|
+
var PREVIEW_HOST_ENV = "LOVABLE_PREVIEW_HOST";
|
|
9
|
+
var HOP_BY_HOP = /* @__PURE__ */ new Set([
|
|
10
|
+
"host",
|
|
11
|
+
"connection",
|
|
12
|
+
"keep-alive",
|
|
13
|
+
"proxy-authenticate",
|
|
14
|
+
"proxy-authorization",
|
|
15
|
+
"te",
|
|
16
|
+
"trailer",
|
|
17
|
+
"transfer-encoding",
|
|
18
|
+
"upgrade",
|
|
19
|
+
"content-length",
|
|
20
|
+
"cookie"
|
|
21
|
+
]);
|
|
22
|
+
function pickRequestHeaders(src) {
|
|
23
|
+
const out = {};
|
|
24
|
+
for (const [k, v] of Object.entries(src)) {
|
|
25
|
+
if (v === void 0)
|
|
26
|
+
continue;
|
|
27
|
+
if (HOP_BY_HOP.has(k.toLowerCase()))
|
|
28
|
+
continue;
|
|
29
|
+
out[k] = v;
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
function lovableAssetsProxyPlugin() {
|
|
34
|
+
const previewHost = process.env[PREVIEW_HOST_ENV]?.trim();
|
|
35
|
+
return {
|
|
36
|
+
name: "lovable:assets-proxy",
|
|
37
|
+
apply: "serve",
|
|
38
|
+
configureServer(server) {
|
|
39
|
+
if (!previewHost)
|
|
40
|
+
return;
|
|
41
|
+
const middleware = (req, res, next) => {
|
|
42
|
+
const url = req.url ?? "";
|
|
43
|
+
if (!ASSET_RE.test(url))
|
|
44
|
+
return next();
|
|
45
|
+
const upstream = https.request(
|
|
46
|
+
{
|
|
47
|
+
host: previewHost,
|
|
48
|
+
port: 443,
|
|
49
|
+
method: req.method,
|
|
50
|
+
path: url,
|
|
51
|
+
headers: { ...pickRequestHeaders(req.headers), host: previewHost }
|
|
52
|
+
},
|
|
53
|
+
(upRes) => {
|
|
54
|
+
res.statusCode = upRes.statusCode ?? 502;
|
|
55
|
+
for (const [k, v] of Object.entries(upRes.headers)) {
|
|
56
|
+
if (v === void 0)
|
|
57
|
+
continue;
|
|
58
|
+
if (HOP_BY_HOP.has(k.toLowerCase()))
|
|
59
|
+
continue;
|
|
60
|
+
res.setHeader(k, v);
|
|
61
|
+
}
|
|
62
|
+
upRes.pipe(res);
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
upstream.on("error", (err) => {
|
|
66
|
+
server.config.logger.warn(
|
|
67
|
+
`[@lovable.dev/vite-tanstack-config] asset proxy ${url} \u2192 ${previewHost} failed: ${err.message}`
|
|
68
|
+
);
|
|
69
|
+
if (!res.headersSent) {
|
|
70
|
+
res.statusCode = 502;
|
|
71
|
+
res.end();
|
|
72
|
+
} else {
|
|
73
|
+
res.destroy(err);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
req.pipe(upstream);
|
|
77
|
+
};
|
|
78
|
+
server.middlewares.use(middleware);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/index.ts
|
|
4
84
|
var SANDBOX_ENV_VAR = "DEV_SERVER__PROJECT_PATH";
|
|
5
85
|
var LOVABLE_SANDBOX_ENV_VAR = "LOVABLE_SANDBOX";
|
|
6
86
|
function isSandboxEnvironment() {
|
|
@@ -141,6 +221,199 @@ function isBuildError(error) {
|
|
|
141
221
|
const message = typeof e.message === "string" ? e.message : "";
|
|
142
222
|
return BUILD_ERROR_MESSAGE.test(message);
|
|
143
223
|
}
|
|
224
|
+
var BUILD_DIAGNOSTICS_PLUGIN_NAME = "lovable-build-error-diagnostics";
|
|
225
|
+
var MAX_DIAGNOSTIC_JSON_LENGTH = 6e3;
|
|
226
|
+
var MAX_DIAGNOSTIC_STRING_LENGTH = 2e3;
|
|
227
|
+
var MAX_DIAGNOSTIC_NESTED_ERRORS = 20;
|
|
228
|
+
var MAX_DIAGNOSTIC_DEPTH = 4;
|
|
229
|
+
var COMPACT_DIAGNOSTIC_STRING_LENGTH = 300;
|
|
230
|
+
var COMPACT_DIAGNOSTIC_NESTED_ERRORS = 3;
|
|
231
|
+
var COMPACT_DIAGNOSTIC_DEPTH = 3;
|
|
232
|
+
var DIAGNOSTIC_ERROR_FIELDS = [
|
|
233
|
+
"name",
|
|
234
|
+
"message",
|
|
235
|
+
"plugin",
|
|
236
|
+
"pluginCode",
|
|
237
|
+
"id",
|
|
238
|
+
"moduleId",
|
|
239
|
+
"hook",
|
|
240
|
+
"code",
|
|
241
|
+
"loc",
|
|
242
|
+
"frame",
|
|
243
|
+
"stack",
|
|
244
|
+
"cause"
|
|
245
|
+
];
|
|
246
|
+
function truncateDiagnosticString(value) {
|
|
247
|
+
return truncateDiagnosticStringTo(value, MAX_DIAGNOSTIC_STRING_LENGTH);
|
|
248
|
+
}
|
|
249
|
+
function truncateDiagnosticStringTo(value, maxLength) {
|
|
250
|
+
return value.length > maxLength ? `${value.slice(0, maxLength)}...[truncated]` : value;
|
|
251
|
+
}
|
|
252
|
+
function readDiagnosticProperty(value, key) {
|
|
253
|
+
try {
|
|
254
|
+
return value[key];
|
|
255
|
+
} catch (error) {
|
|
256
|
+
return `[unreadable: ${error instanceof Error ? error.message : String(error)}]`;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
function serializeOwnDiagnosticProperties(value, depth, seen) {
|
|
260
|
+
const keys = Object.keys(value);
|
|
261
|
+
const output = {};
|
|
262
|
+
for (const key of keys.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS)) {
|
|
263
|
+
const nested = readDiagnosticProperty(value, key);
|
|
264
|
+
if (nested == null || nested === "")
|
|
265
|
+
continue;
|
|
266
|
+
output[key] = serializeDiagnosticValue(nested, depth + 1, seen);
|
|
267
|
+
}
|
|
268
|
+
if (keys.length > MAX_DIAGNOSTIC_NESTED_ERRORS) {
|
|
269
|
+
output.properties_truncated = keys.length - MAX_DIAGNOSTIC_NESTED_ERRORS;
|
|
270
|
+
}
|
|
271
|
+
return output;
|
|
272
|
+
}
|
|
273
|
+
function describeDiagnosticPrimitive(value) {
|
|
274
|
+
if (typeof value === "symbol")
|
|
275
|
+
return value.description ? `Symbol(${value.description})` : "Symbol()";
|
|
276
|
+
if (typeof value === "bigint")
|
|
277
|
+
return value.toString();
|
|
278
|
+
if (typeof value === "function")
|
|
279
|
+
return `[function ${value.name || "anonymous"}]`;
|
|
280
|
+
return String(value);
|
|
281
|
+
}
|
|
282
|
+
function describeDiagnosticObject(value) {
|
|
283
|
+
const constructorName = value.constructor?.name;
|
|
284
|
+
if (typeof constructorName === "string" && constructorName !== "" && constructorName !== "Object") {
|
|
285
|
+
return `[${constructorName}]`;
|
|
286
|
+
}
|
|
287
|
+
return Object.prototype.toString.call(value);
|
|
288
|
+
}
|
|
289
|
+
function serializeDiagnosticValue(value, depth, seen) {
|
|
290
|
+
if (value == null)
|
|
291
|
+
return value;
|
|
292
|
+
if (typeof value === "string")
|
|
293
|
+
return truncateDiagnosticString(value);
|
|
294
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
295
|
+
return value;
|
|
296
|
+
if (typeof value !== "object")
|
|
297
|
+
return describeDiagnosticPrimitive(value);
|
|
298
|
+
if (seen.has(value))
|
|
299
|
+
return "[circular]";
|
|
300
|
+
if (depth >= MAX_DIAGNOSTIC_DEPTH)
|
|
301
|
+
return "[max depth]";
|
|
302
|
+
seen.add(value);
|
|
303
|
+
try {
|
|
304
|
+
if (Array.isArray(value)) {
|
|
305
|
+
return value.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS).map((item) => serializeDiagnosticValue(item, depth + 1, seen));
|
|
306
|
+
}
|
|
307
|
+
const record = value;
|
|
308
|
+
const output = {};
|
|
309
|
+
for (const field of DIAGNOSTIC_ERROR_FIELDS) {
|
|
310
|
+
if (!(field in record))
|
|
311
|
+
continue;
|
|
312
|
+
const nested = readDiagnosticProperty(record, field);
|
|
313
|
+
if (nested == null || nested === "")
|
|
314
|
+
continue;
|
|
315
|
+
output[field] = serializeDiagnosticValue(nested, depth + 1, seen);
|
|
316
|
+
}
|
|
317
|
+
const nestedErrors = readDiagnosticProperty(record, "errors");
|
|
318
|
+
if (Array.isArray(nestedErrors)) {
|
|
319
|
+
output.errors = nestedErrors.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS).map((item) => serializeDiagnosticValue(item, depth + 1, seen));
|
|
320
|
+
if (nestedErrors.length > MAX_DIAGNOSTIC_NESTED_ERRORS) {
|
|
321
|
+
output.errors_truncated = nestedErrors.length - MAX_DIAGNOSTIC_NESTED_ERRORS;
|
|
322
|
+
}
|
|
323
|
+
} else if (nestedErrors != null && nestedErrors !== "") {
|
|
324
|
+
output.errors = serializeDiagnosticValue(nestedErrors, depth + 1, seen);
|
|
325
|
+
}
|
|
326
|
+
if (Object.keys(output).length > 0)
|
|
327
|
+
return output;
|
|
328
|
+
const ownProperties = serializeOwnDiagnosticProperties(record, depth, seen);
|
|
329
|
+
return Object.keys(ownProperties).length > 0 ? ownProperties : describeDiagnosticObject(value);
|
|
330
|
+
} catch (error) {
|
|
331
|
+
return `[unreadable object: ${error instanceof Error ? error.message : String(error)}]`;
|
|
332
|
+
} finally {
|
|
333
|
+
seen.delete(value);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
function compactDiagnosticValue(value, depth) {
|
|
337
|
+
if (value == null)
|
|
338
|
+
return value;
|
|
339
|
+
if (typeof value === "string")
|
|
340
|
+
return truncateDiagnosticStringTo(value, COMPACT_DIAGNOSTIC_STRING_LENGTH);
|
|
341
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
342
|
+
return value;
|
|
343
|
+
if (typeof value !== "object")
|
|
344
|
+
return describeDiagnosticPrimitive(value);
|
|
345
|
+
if (depth >= COMPACT_DIAGNOSTIC_DEPTH)
|
|
346
|
+
return "[max depth]";
|
|
347
|
+
try {
|
|
348
|
+
if (Array.isArray(value)) {
|
|
349
|
+
const items = value.slice(0, COMPACT_DIAGNOSTIC_NESTED_ERRORS).map((item) => compactDiagnosticValue(item, depth + 1));
|
|
350
|
+
if (value.length > COMPACT_DIAGNOSTIC_NESTED_ERRORS) {
|
|
351
|
+
items.push(`[${value.length - COMPACT_DIAGNOSTIC_NESTED_ERRORS} items truncated]`);
|
|
352
|
+
}
|
|
353
|
+
return items;
|
|
354
|
+
}
|
|
355
|
+
const record = value;
|
|
356
|
+
const output = {};
|
|
357
|
+
const keys = Object.keys(record);
|
|
358
|
+
for (const key of keys.slice(0, MAX_DIAGNOSTIC_NESTED_ERRORS)) {
|
|
359
|
+
const nested = readDiagnosticProperty(record, key);
|
|
360
|
+
if (nested == null || nested === "")
|
|
361
|
+
continue;
|
|
362
|
+
output[key] = compactDiagnosticValue(nested, depth + 1);
|
|
363
|
+
}
|
|
364
|
+
if (keys.length > MAX_DIAGNOSTIC_NESTED_ERRORS) {
|
|
365
|
+
output.properties_truncated = keys.length - MAX_DIAGNOSTIC_NESTED_ERRORS;
|
|
366
|
+
}
|
|
367
|
+
return output;
|
|
368
|
+
} catch (error) {
|
|
369
|
+
return `[unreadable object: ${error instanceof Error ? error.message : String(error)}]`;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function stringifyDiagnosticPayload(diagnostics) {
|
|
373
|
+
const full = JSON.stringify(diagnostics);
|
|
374
|
+
if (full && full.length <= MAX_DIAGNOSTIC_JSON_LENGTH)
|
|
375
|
+
return full;
|
|
376
|
+
const compact = compactDiagnosticValue(diagnostics, 0);
|
|
377
|
+
const compactPayload = compact != null && typeof compact === "object" && !Array.isArray(compact) ? { ...compact, diagnostics_truncated: true } : { diagnostics_truncated: true, value: compact };
|
|
378
|
+
const compactJson = JSON.stringify(compactPayload);
|
|
379
|
+
if (compactJson.length <= MAX_DIAGNOSTIC_JSON_LENGTH)
|
|
380
|
+
return compactJson;
|
|
381
|
+
return JSON.stringify({
|
|
382
|
+
diagnostics_truncated: true,
|
|
383
|
+
message: "Diagnostic payload exceeded output budget."
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
function lovableBuildErrorDiagnostics() {
|
|
387
|
+
return {
|
|
388
|
+
name: BUILD_DIAGNOSTICS_PLUGIN_NAME,
|
|
389
|
+
apply: "build",
|
|
390
|
+
buildEnd(error) {
|
|
391
|
+
if (!error)
|
|
392
|
+
return;
|
|
393
|
+
try {
|
|
394
|
+
const diagnostics = serializeDiagnosticValue(error, 0, /* @__PURE__ */ new WeakSet());
|
|
395
|
+
const output = `
|
|
396
|
+
[lovable-build-error-diagnostics]
|
|
397
|
+
${stringifyDiagnosticPayload(diagnostics)}
|
|
398
|
+
[/lovable-build-error-diagnostics]
|
|
399
|
+
`;
|
|
400
|
+
let written = false;
|
|
401
|
+
const write = () => {
|
|
402
|
+
if (written)
|
|
403
|
+
return;
|
|
404
|
+
written = true;
|
|
405
|
+
try {
|
|
406
|
+
process.stderr.write(output);
|
|
407
|
+
} catch {
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
setImmediate(write);
|
|
411
|
+
process.once("exit", write);
|
|
412
|
+
} catch {
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
}
|
|
144
417
|
function devSsrErrorLogger() {
|
|
145
418
|
let lastCapture;
|
|
146
419
|
const CAPTURE_TTL_MS = 5e3;
|
|
@@ -339,6 +612,9 @@ function defineConfig(configOrOptions = {}) {
|
|
|
339
612
|
if (options.ssrErrorLogger !== false) {
|
|
340
613
|
internalPlugins.push(devSsrErrorLogger());
|
|
341
614
|
}
|
|
615
|
+
if (command === "build" && isSandbox) {
|
|
616
|
+
internalPlugins.push(lovableBuildErrorDiagnostics());
|
|
617
|
+
}
|
|
342
618
|
const { tanstackStart } = await import("@tanstack/react-start/plugin/vite");
|
|
343
619
|
const tanstackStartDefaults = {
|
|
344
620
|
importProtection: {
|
|
@@ -397,6 +673,9 @@ function defineConfig(configOrOptions = {}) {
|
|
|
397
673
|
const { devServerBridgePlugin } = await import("@lovable.dev/vite-plugin-dev-server-bridge");
|
|
398
674
|
internalPlugins.push(devServerBridgePlugin());
|
|
399
675
|
}
|
|
676
|
+
if (command === "serve") {
|
|
677
|
+
internalPlugins.push(lovableAssetsProxyPlugin());
|
|
678
|
+
}
|
|
400
679
|
if (command === "serve" && mode === "development") {
|
|
401
680
|
internalPlugins.push(componentTagger());
|
|
402
681
|
}
|
|
@@ -464,5 +743,6 @@ function defineConfig(configOrOptions = {}) {
|
|
|
464
743
|
};
|
|
465
744
|
}
|
|
466
745
|
export {
|
|
467
|
-
defineConfig
|
|
746
|
+
defineConfig,
|
|
747
|
+
lovableAssetsProxyPlugin
|
|
468
748
|
};
|