template: tanstack_start_ts_current-40f3c252c0da

This commit is contained in:
Lovable
2025-01-01 00:00:00 +00:00
commit cb75921659
71 changed files with 6545 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
// Captures the original Error out-of-band so server.ts can recover the stack
// when h3 has already swallowed the throw into a generic 500 Response.
let lastCapturedError: { error: unknown; at: number } | undefined;
const TTL_MS = 5_000;
function record(error: unknown) {
lastCapturedError = { error, at: Date.now() };
}
if (typeof globalThis.addEventListener === "function") {
globalThis.addEventListener("error", (event) => record((event as ErrorEvent).error ?? event));
globalThis.addEventListener("unhandledrejection", (event) =>
record((event as PromiseRejectionEvent).reason),
);
}
export function consumeLastCapturedError(): unknown {
if (!lastCapturedError) return undefined;
if (Date.now() - lastCapturedError.at > TTL_MS) {
lastCapturedError = undefined;
return undefined;
}
const { error } = lastCapturedError;
lastCapturedError = undefined;
return error;
}
+30
View File
@@ -0,0 +1,30 @@
export function renderErrorPage(): string {
return `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>This page didn't load</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
body { font: 15px/1.5 system-ui, -apple-system, sans-serif; background: #fafafa; color: #111; display: grid; place-items: center; min-height: 100vh; margin: 0; padding: 1.5rem; }
.card { max-width: 28rem; width: 100%; text-align: center; padding: 2rem; }
h1 { font-size: 1.25rem; margin: 0 0 0.5rem; }
p { color: #4b5563; margin: 0 0 1.5rem; }
.actions { display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; }
a, button { padding: 0.5rem 1rem; border-radius: 0.375rem; font: inherit; cursor: pointer; text-decoration: none; border: 1px solid transparent; }
.primary { background: #111; color: #fff; }
.secondary { background: #fff; color: #111; border-color: #d1d5db; }
</style>
</head>
<body>
<div class="card">
<h1>This page didn't load</h1>
<p>Something went wrong on our end. You can try refreshing or head back home.</p>
<div class="actions">
<button class="primary" onclick="location.reload()">Try again</button>
<a class="secondary" href="/">Go home</a>
</div>
</div>
</body>
</html>`;
}
+36
View File
@@ -0,0 +1,36 @@
type LovableErrorOptions = {
mechanism?: "manual" | "onerror" | "unhandledrejection" | "react_error_boundary";
handled?: boolean;
severity?: "error" | "warning" | "info";
};
type LovableEvents = {
captureException?: (
error: unknown,
context?: Record<string, unknown>,
options?: LovableErrorOptions,
) => void;
};
declare global {
interface Window {
__lovableEvents?: LovableEvents;
}
}
export function reportLovableError(error: unknown, context: Record<string, unknown> = {}) {
if (typeof window === "undefined") return;
window.__lovableEvents?.captureException?.(
error,
{
source: "react_error_boundary",
route: window.location.pathname,
...context,
},
{
mechanism: "react_error_boundary",
handled: false,
severity: "error",
},
);
}
+6
View File
@@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}