SPB Git forge

spb/websensor

Public
33commits 1branches 0releases
3.4 MBsize
maindefault branch
10 days agolast push
TypeScript 55.4% Python 43.2% SQL 1.2%
1.4 KB · 38 lines typescript
Raw Blame History
1"use client";23import { clientApiBase } from "./api";45const KEY = "ws_owner";6const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";78/** Anonymous owner token for watchlists/alerts (phase 1, no accounts). Generated once per browser. */9export function ownerToken(): string {10  if (typeof window === "undefined") return "";11  let t = window.localStorage.getItem(KEY);12  if (!t || !/^[A-Za-z0-9_-]{16,80}$/.test(t)) {13    const bytes = new Uint8Array(32);14    window.crypto.getRandomValues(bytes);15    t = Array.from(bytes, (b) => ALPHABET[b % ALPHABET.length]).join("");16    window.localStorage.setItem(KEY, t);17  }18  return t;19}2021export async function ownerFetch<T>(path: string, init: RequestInit = {}): Promise<T> {22  const res = await fetch(`${clientApiBase()}${path}`, {23    ...init,24    headers: { "content-type": "application/json", accept: "application/json", "x-websensor-owner": ownerToken(), ...(init.headers ?? {}) },25  });26  if (!res.ok) {27    const body = (await res.json().catch(() => ({}))) as { error?: string };28    throw new Error(body.error ?? `HTTP ${res.status}`);29  }30  return (await res.json()) as T;31}3233export async function publicFetch<T>(path: string): Promise<T> {34  const res = await fetch(`${clientApiBase()}${path}`, { headers: { accept: "application/json" } });35  if (!res.ok) throw new Error(`HTTP ${res.status}`);36  return (await res.json()) as T;37}38