1// ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 2// SABR.AI · Sync-Client (v123) 3// ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 4// Spricht mit /api/family (Vercel Serverless). Läuft die App über 5// Tunnel/localhost, wird automatisch die Live-Domain angesprochen 6// (CORS ist serverseitig offen). Graceful: jeder Fehler â die App 7// arbeitet lokal weiter wie bisher. 8// 9// Public: 10// window.SABR_sync.call(payload) â Promise<json> 11// window.SABR_sync.deviceId() â stabile Geräte-ID 12// window.SABR_sync.online â letzter Call ok? 13// window.SABR_sync.persistent â Server-Storage dauerhaft? 14// ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 15(function () { 16 'use strict'; 17 18 const LIVE_ORIGIN = 'https://sabr-liart.vercel.app'; 19 const onLive = /\.vercel\.app$/.test(location.hostname); 20 const API = (onLive ? '' : LIVE_ORIGIN) + '/api/family'; 21 22 function deviceId() { 23 let id = null; 24 try { id = localStorage.getItem('sabr_device_id'); } catch (_) {} 25 if (!id) { 26 id = 'd' + Math.random().toString(36).slice(2, 10) + Date.now().toString(36); 27 try { localStorage.setItem('sabr_device_id', id); } catch (_) {} 28 } 29 return id; 30 } 31 32 async function call(payload, timeoutMs) { 33 const ctrl = new AbortController(); 34 const to = setTimeout(() => ctrl.abort(), timeoutMs || 7000); 35 try { 36 const r = await fetch(API, { 37 method: 'POST', 38 headers: { 'Content-Type': 'application/json' }, 39 body: JSON.stringify(Object.assign({ deviceId: deviceId() }, payload)), 40 signal: ctrl.signal 41 }); 42 const j = await r.json().catch(() => ({ ok: false, error: 'parse' })); 43 window.SABR_sync.online = !!j.ok || r.status === 404 || r.status === 403; // Server erreichbar 44 if (typeof j.persistent === 'boolean') window.SABR_sync.persistent = j.persistent; 45 j.httpStatus = r.status; 46 return j; 47 } catch (e) { 48 window.SABR_sync.online = false; 49 return { ok: false, error: 'network', detail: String(e && e.name || e) }; 50 } finally { 51 clearTimeout(to); 52 } 53 } 54 55 window.SABR_sync = { call: call, deviceId: deviceId, online: null, persistent: null, api: API }; 56})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.