Initial commit: code as received (Create/Anything export)
Insole-production time tracker exported from the Create/Anything AI platform. Baseline snapshot before any reverse-engineering or cleanup. - apps/mobile: Expo Router app (iOS/Android/web), the only workspace - publisher/: standalone OpenNext/AWS deploy tooling for the web side - Backend (/api/tasks, /api/logs + DB) lives remotely, not in this repo
This commit is contained in:
78
apps/mobile/__create/sentry.ts
Normal file
78
apps/mobile/__create/sentry.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import * as Sentry from "@sentry/react-native";
|
||||
import { sendLogsToRemote } from "./report-error-to-remote";
|
||||
|
||||
function isActive(): boolean {
|
||||
return (
|
||||
!__DEV__ &&
|
||||
process.env.EXPO_PUBLIC_CREATE_ENV !== "DEVELOPMENT" &&
|
||||
!!process.env.EXPO_PUBLIC_SENTRY_DSN
|
||||
);
|
||||
}
|
||||
|
||||
let initialized = false;
|
||||
|
||||
// Mirror a Sentry event into the Anything logs pipeline so native and JS
|
||||
// crashes — including startup crashes that Sentry caches natively and reports
|
||||
// on the next launch — surface in the Flux builder, not only the Sentry
|
||||
// dashboard.
|
||||
function forwardEventToRemote(event: Sentry.Event): void {
|
||||
try {
|
||||
const exception = event.exception?.values?.[0];
|
||||
const lines: string[] = [];
|
||||
if (exception && (exception.type || exception.value)) {
|
||||
lines.push(`${exception.type ?? "Error"}: ${exception.value ?? ""}`);
|
||||
} else if (typeof event.message === "string") {
|
||||
lines.push(event.message);
|
||||
}
|
||||
const frames = exception?.stacktrace?.frames;
|
||||
if (frames && frames.length > 0) {
|
||||
lines.push(
|
||||
frames
|
||||
.slice(-20)
|
||||
.reverse()
|
||||
.map(
|
||||
(frame) =>
|
||||
` at ${frame.function ?? "?"} (${frame.filename ?? "?"}:${frame.lineno ?? 0})`,
|
||||
)
|
||||
.join("\n"),
|
||||
);
|
||||
}
|
||||
const message = lines.join("\n").trim();
|
||||
if (!message) return;
|
||||
const timestamp =
|
||||
typeof event.timestamp === "number"
|
||||
? new Date(event.timestamp * 1000).toISOString()
|
||||
: new Date().toISOString();
|
||||
sendLogsToRemote([
|
||||
{
|
||||
message: `[SENTRY] ${message}`,
|
||||
timestamp,
|
||||
level: "error",
|
||||
source: "TEST_FLIGHT",
|
||||
},
|
||||
]);
|
||||
} catch (_err) {
|
||||
// Silent
|
||||
}
|
||||
}
|
||||
|
||||
export function initSentry(): void {
|
||||
try {
|
||||
if (!isActive() || initialized) return;
|
||||
initialized = true;
|
||||
Sentry.init({
|
||||
dsn: process.env.EXPO_PUBLIC_SENTRY_DSN,
|
||||
enableNativeCrashHandling: true,
|
||||
beforeSend: (event) => {
|
||||
forwardEventToRemote(event);
|
||||
return event;
|
||||
},
|
||||
});
|
||||
const projectGroupId = process.env.EXPO_PUBLIC_PROJECT_GROUP_ID;
|
||||
if (projectGroupId) {
|
||||
Sentry.setTag("projectGroupId", projectGroupId);
|
||||
}
|
||||
} catch (_err) {
|
||||
// Silent — Sentry must never crash the host app
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user