Client d'application
Ce que toute application Expo partage : la session bearer derrière un port de stockage, le client de découverte avec l'adresse d'un produit et le client d'API (bearer, délai, gestion du 401).
Three Expo apps had copied the same session, discovery and API code, and two more were starting.
@krizaka/app-client is that code, once, with ports in and no native module imported: the app passes
expo-secure-store, its fetch and its language.
const storage = secureStorage(SecureStore);
const session = createSessionStore({ storage, key: "yomizaka.session" });
const discovery = createAppDiscovery({ product: "yomizaka", hostSuffix: "yomizaka.com", appVersion, baked, storage, env });
const api = createApiClient({ baseUrl: () => discovery.getService("yomizaka").apiBase, session, fetch: appConfig.fetch, language, productName: "Yomizaka", timeoutMs: 20_000 });-
Session. The bearer token lives in the Keychain or Keystore, never a cookie;
onChangefires when a session starts or ends. -
Discovery. Krizaka's signed manifest, keys and host allow-list plus the product's own domain;
EXPO_PUBLIC_APP_URLwins for local work, and a malformed build input fails at start. -
API client. JSON with the bearer,
credentials: "omit", a timeout that fails like a network error, and a 401 that drops the session. -
Auth context (
@krizaka/app-client/react).createAuth(session, { signIn, signOut })gives the screensuseAuth():loading, thensignedInorsignedOut, followed when a session starts or ends.
Decision: ADR-004.