export interface PushSubscriptionData { endpoint: string; keys: { p256dh: string; auth: string; }; } export interface VapidPublicKeyResponse { publicKey: string | null; } const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000/api/v1'; export async function getVapidPublicKey(): Promise { try { const response = await fetch(`${API_BASE_URL}/push/vapid-public-key`); if (!response.ok) { throw new Error('Failed to fetch VAPID public key'); } const data: VapidPublicKeyResponse = await response.json(); return data.publicKey; } catch { return null; } } export async function subscribeToPush( subscription: PushSubscriptionData, ): Promise { try { const response = await fetch(`${API_BASE_URL}/push/subscribe`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ endpoint: subscription.endpoint, p256dh: subscription.keys.p256dh, auth: subscription.keys.auth, }), }); return response.ok; } catch { return false; } } export async function unsubscribeFromPush( endpoint: string, ): Promise { try { const response = await fetch(`${API_BASE_URL}/push/unsubscribe`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ endpoint }), }); return response.ok; } catch { return false; } } export function urlBase64ToUint8Array(base64String: string): Uint8Array { const padding = '='.repeat((4 - (base64String.length % 4)) % 4); const base64 = (base64String + padding) .replace(/-/g, '+') .replace(/_/g, '/'); const rawData = window.atob(base64); const outputArray = new Uint8Array(rawData.length); for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); } return outputArray; }