@eventista/sdk-api-client
REST and GraphQL client for Eventista APIs. Provides RestClient (apisauce-backed) with HMAC request signing, pluggable storage adapter, and platform-agnostic core.
Install
Section titled “Install”bun add @eventista/sdk-api-client @eventista/sdk-coreRestClient works the same on every runtime — what changes is the StorageAdapter you wire in for token persistence.
Web example (Next.js)
Section titled “Web example (Next.js)”Use the bundled createWebSessionStorageAdapter from the /adapters/web sub-path. It reads/writes window.sessionStorage and is safe to import in the browser bundle.
"use client";import { RestClient } from "@eventista/sdk-api-client";import { createWebSessionStorageAdapter } from "@eventista/sdk-api-client/adapters/web";
export const apiClient = new RestClient({ baseURL: process.env.NEXT_PUBLIC_API_URL!, storage: createWebSessionStorageAdapter(), getLanguage: async () => "en", getSigningSecret: () => process.env.NEXT_PUBLIC_API_SIGNING_SECRET, onUnauthorized: () => { window.location.href = "/login"; },});"use client";import { useEffect, useState } from "react";import { apiClient } from "@/lib/apiClient";
export default function EventsPage() { const [events, setEvents] = useState<unknown[]>([]); useEffect(() => { apiClient.get<{ events: unknown[] }>("/v1/events").then((res) => { if (res.data && !res.data.isErr) setEvents(res.data.data.events); }); }, []); return <pre>{JSON.stringify(events, null, 2)}</pre>;}For server-side rendering (route handlers, server components), use MemoryStorageAdapter — no persistence between requests is the correct SSR behavior.
React Native example (Expo)
Section titled “React Native example (Expo)”@react-native-async-storage/async-storage already exposes a Promise-based API that satisfies StorageAdapter — no wrapper needed beyond the type assertion.
import { RestClient, type StorageAdapter } from "@eventista/sdk-api-client";import AsyncStorage from "@react-native-async-storage/async-storage";
const rnStorage: StorageAdapter = { getItem: (key) => AsyncStorage.getItem(key), setItem: (key, value) => AsyncStorage.setItem(key, value), removeItem: (key) => AsyncStorage.removeItem(key),};
export const apiClient = new RestClient({ baseURL: process.env.EXPO_PUBLIC_API_URL!, storage: rnStorage, getLanguage: async () => "en", getSigningSecret: () => process.env.EXPO_PUBLIC_API_SIGNING_SECRET,});// app/(tabs)/events.tsximport { useEffect, useState } from "react";import { FlatList, Text } from "react-native";import { apiClient } from "../../lib/apiClient";
export default function EventsScreen() { const [events, setEvents] = useState<{ id: string; name: string }[]>([]); useEffect(() => { apiClient .get<{ events: { id: string; name: string }[] }>("/v1/events") .then((res) => { if (res.data && !res.data.isErr) setEvents(res.data.data.events); }); }, []); return ( <FlatList data={events} keyExtractor={(item) => item.id} renderItem={({ item }) => <Text>{item.name}</Text>} /> );}Request signing
Section titled “Request signing”The interceptor signs whitelisted endpoints (currently add-to-cart and payment/order/create) with HMAC-SHA256 over the canonical
{timestamp}\n{method}\n{path}\n{bodySha256Hex} string. Provide getSigningSecret to enable signing — the HMAC is computed via @noble/hashes (pure JS, audited) so signing works unchanged on web, Node, and React Native / Hermes without any platform adapter or polyfill.
Status
Section titled “Status”WIP. Public API is unstable — do not depend on it for production yet.