learning_ai_clock/web/src/lib/diagnostics.ts

54 lines
1.7 KiB
TypeScript

// ── Remote Diagnostics Client ─────────────────────────────────
// Delegates to @bytelyst/diagnostics-client shared package.
// Polls platform-service for active debug sessions targeting this install.
// Privacy: only captures console logs + JS errors when a session is active.
import { DiagnosticsClient } from '@bytelyst/diagnostics-client';
import { getAuthClient, PRODUCT_ID, getBaseUrl } from './auth-api';
function getOrCreateInstallId(): string {
const key = `${PRODUCT_ID}_diag_install_id`;
let id = localStorage.getItem(key);
if (!id) {
id =
typeof crypto?.randomUUID === 'function'
? crypto.randomUUID()
: Math.random().toString(36).slice(2) + Date.now().toString(36);
localStorage.setItem(key, id);
}
return id;
}
export function initDiagnostics(): void {
if (typeof window === 'undefined') return;
DiagnosticsClient.getInstance({
productId: PRODUCT_ID,
anonymousInstallId: getOrCreateInstallId(),
platform: 'web',
channel: 'pwa',
osFamily: 'unknown',
appVersion: process.env.NEXT_PUBLIC_APP_VERSION ?? '0.1.0',
buildNumber: process.env.NEXT_PUBLIC_BUILD_NUMBER ?? '1',
releaseChannel: process.env.NEXT_PUBLIC_RELEASE_CHANNEL ?? 'beta',
serverUrl: getBaseUrl(),
getAuthToken: () => {
const token = getAuthClient().getAccessToken();
if (!token) throw new Error('unauthenticated');
return token;
},
captureConsole: true,
captureErrors: true,
captureNetwork: false,
pollIntervalMs: 30_000,
});
void DiagnosticsClient.getInstance().start();
}
export function stopDiagnostics(): void {
try {
DiagnosticsClient.getInstance().stop();
} catch {
// not initialized
}
}