← back to Govarbitrage
apps/mobile/lib/settings.ts
98 lines
/**
* Settings persistence — base URL and Basic Auth credentials stored in
* expo-secure-store so they never touch AsyncStorage (unencrypted).
*
* Keys:
* GOVARB_BASE_URL — e.g. "https://auctions.agentabrams.com"
* GOVARB_USERNAME — Basic auth username
* GOVARB_PASSWORD — Basic auth password
*/
import * as SecureStore from "expo-secure-store";
export { buildBasicAuthHeader } from "./auth-headers";
const KEYS = {
BASE_URL: "GOVARB_BASE_URL",
USERNAME: "GOVARB_USERNAME",
PASSWORD: "GOVARB_PASSWORD",
// Sign in with Apple — the app session JWT issued by /api/auth/apple, plus the
// account identity to show in Settings. Optional: absent = signed out.
SESSION_JWT: "GOVARB_SESSION_JWT",
ACCOUNT_NAME: "GOVARB_ACCOUNT_NAME",
ACCOUNT_EMAIL: "GOVARB_ACCOUNT_EMAIL",
} as const;
const DEFAULTS = {
BASE_URL: "https://auctions.agentabrams.com",
// Empty by default — the default server's read API is public, so a fresh
// install sends no Authorization header. Credentials are only for users
// pointing the app at their own self-hosted server.
USERNAME: "",
PASSWORD: "",
} as const;
export interface AppSettings {
baseUrl: string;
username: string;
password: string;
}
export async function loadSettings(): Promise<AppSettings> {
const [baseUrl, username, password] = await Promise.all([
SecureStore.getItemAsync(KEYS.BASE_URL),
SecureStore.getItemAsync(KEYS.USERNAME),
SecureStore.getItemAsync(KEYS.PASSWORD),
]);
return {
baseUrl: baseUrl ?? DEFAULTS.BASE_URL,
username: username ?? DEFAULTS.USERNAME,
password: password ?? DEFAULTS.PASSWORD,
};
}
export async function saveSettings(settings: AppSettings): Promise<void> {
await Promise.all([
SecureStore.setItemAsync(KEYS.BASE_URL, settings.baseUrl.trim()),
SecureStore.setItemAsync(KEYS.USERNAME, settings.username.trim()),
SecureStore.setItemAsync(KEYS.PASSWORD, settings.password),
]);
}
// ── Sign in with Apple session ──────────────────────────────────────────────
export interface AppleAccount {
token: string;
name: string | null;
email: string | null;
}
/** The signed-in Apple account, or null when signed out. */
export async function loadAppleAccount(): Promise<AppleAccount | null> {
const [token, name, email] = await Promise.all([
SecureStore.getItemAsync(KEYS.SESSION_JWT),
SecureStore.getItemAsync(KEYS.ACCOUNT_NAME),
SecureStore.getItemAsync(KEYS.ACCOUNT_EMAIL),
]);
if (!token) return null;
return { token, name: name ?? null, email: email ?? null };
}
export async function saveAppleAccount(account: AppleAccount): Promise<void> {
await Promise.all([
SecureStore.setItemAsync(KEYS.SESSION_JWT, account.token),
account.name
? SecureStore.setItemAsync(KEYS.ACCOUNT_NAME, account.name)
: SecureStore.deleteItemAsync(KEYS.ACCOUNT_NAME),
account.email
? SecureStore.setItemAsync(KEYS.ACCOUNT_EMAIL, account.email)
: SecureStore.deleteItemAsync(KEYS.ACCOUNT_EMAIL),
]);
}
export async function clearAppleAccount(): Promise<void> {
await Promise.all([
SecureStore.deleteItemAsync(KEYS.SESSION_JWT),
SecureStore.deleteItemAsync(KEYS.ACCOUNT_NAME),
SecureStore.deleteItemAsync(KEYS.ACCOUNT_EMAIL),
]);
}