Files
beenvoice-app/lib/instance-url.ts
T
soconnor 14c880123c Add beenvoice mobile companion app with full dark mode support.
Expo app with dashboard, time clock, invoices, and settings — native tabs, glass UI, theme-aware components, and iOS Live Activities.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 22:36:37 -04:00

43 lines
1.3 KiB
TypeScript

import AsyncStorage from "@react-native-async-storage/async-storage";
const STORAGE_KEY = "beenvoice:instance-url";
export function normalizeInstanceUrl(input: string): string | null {
const trimmed = input.trim().replace(/\/$/, "");
if (!trimmed) return null;
let url = trimmed;
if (!/^https?:\/\//i.test(url)) {
const isLocal =
/^(localhost|127\.|192\.168\.|10\.|172\.(1[6-9]|2\d|3[01])\.)/i.test(url);
url = `${isLocal ? "http" : "https"}://${url}`;
}
try {
const parsed = new URL(url);
if (!parsed.hostname) return null;
return `${parsed.protocol}//${parsed.host}`;
} catch {
return null;
}
}
export async function loadStoredInstanceUrl(): Promise<string | null> {
const stored = await AsyncStorage.getItem(STORAGE_KEY);
if (!stored) return null;
return normalizeInstanceUrl(stored) ?? stored.replace(/\/$/, "");
}
export async function saveStoredInstanceUrl(url: string): Promise<string> {
const normalized = normalizeInstanceUrl(url);
if (!normalized) {
throw new Error("Enter a valid server URL (e.g. beenvoice.app or localhost:3000)");
}
await AsyncStorage.setItem(STORAGE_KEY, normalized);
return normalized;
}
export async function clearStoredInstanceUrl(): Promise<void> {
await AsyncStorage.removeItem(STORAGE_KEY);
}