Files
Greenlens/services/installPing.ts
2026-07-13 00:03:28 +02:00

47 lines
1.7 KiB
TypeScript

import { AppMetaDb } from './database';
import { getConfiguredBackendRootUrl } from '../utils/backendUrl';
import { getAppInfoHeaders } from '../utils/appInfoHeaders';
const INSTALL_ID_KEY = 'install_ping_id_v1';
const INSTALL_REPORTED_KEY = 'install_ping_reported_v1';
const REQUEST_TIMEOUT_MS = 10000;
const getOrCreateInstallId = (): string => {
const existing = AppMetaDb.get(INSTALL_ID_KEY);
if (existing) return existing;
const installId = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}-${Math.random().toString(36).slice(2, 12)}`;
AppMetaDb.set(INSTALL_ID_KEY, installId);
return installId;
};
// Reports this install to the backend exactly once (fire-and-forget). The
// backend dedupes by install id, so retrying after a failed attempt is safe.
export const reportInstallOnce = async (): Promise<void> => {
try {
if (AppMetaDb.get(INSTALL_REPORTED_KEY) === '1') return;
const backendBaseUrl = getConfiguredBackendRootUrl();
if (!backendBaseUrl) return;
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
try {
const response = await fetch(`${backendBaseUrl.replace(/\/$/, '')}/v1/app-install`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...getAppInfoHeaders(),
},
body: JSON.stringify({ installId: getOrCreateInstallId() }),
signal: controller.signal,
});
if (response.ok) {
AppMetaDb.set(INSTALL_REPORTED_KEY, '1');
}
} finally {
clearTimeout(timeout);
}
} catch {
// Offline or backend unreachable — retried on next app start.
}
};