/** * 03 — Error handling * * Every namespace throws `GameCoreError` on non-2xx responses. Always * branch on `.status` (numeric HTTP code) and optionally `.code` * (machine-readable string set by the API for known cases). * * try { * await gc.checkout.create(...); * } catch (e) { * if (e instanceof GameCoreError) { * if (e.status === 401) { /* re-auth *\/ } * if (e.status === 429) { /* backoff + retry *\/ } * if (e.code === "INSUFFICIENT_FUNDS") { /* show top-up CTA *\/ } * } * } * * Run with: * GAMECORE_API_KEY=gc_live_... bun run examples/03-error-handling.ts */ import { GameCoreClient, GameCoreError } from "@gamecore-api/sdk"; const gc = new GameCoreClient({ apiKey: process.env.GAMECORE_API_KEY!, baseUrl: "https://api.gamecore-api.tech", // Optional: catch silent JWT expiry across all endpoints. Fires // when a request returned 401 with code "TOKEN_EXPIRED" — useful // for showing a "please log in again" toast without wrapping // every call. onAuthError: () => { console.warn("auth expired — redirect to login"); }, }); // Force a 404 to demonstrate the error shape try { await gc.catalog.getGame("definitely-not-a-real-game-slug-9999"); } catch (e) { if (e instanceof GameCoreError) { console.log("caught:", { name: e.name, status: e.status, code: e.code, message: e.message, }); } else { throw e; } } // Patterns worth knowing: // // • 401 + code "UNAUTHORIZED" → API key invalid or revoked. Stop // the request, re-fetch a fresh key from your secret store. // • 410 + code "TOKEN_EXPIRED" → user JWT expired. Triggers // `onAuthError` if you provided one. // • 429 + code "RATE_LIMITED" → token bucket. Read the `Retry-After` // header if present, otherwise back off ~1s and retry. // • 400 with field-level details → check `message` for the offending // field (server returns plain-English reason for predictable cases // like "amount must be ≥ 1" or "delivery data missing for product X"). // Retry helper with exponential backoff for transient errors async function withRetry(fn: () => Promise, attempts = 3): Promise { let lastError: unknown; for (let i = 0; i < attempts; i++) { try { return await fn(); } catch (e) { lastError = e; const transient = e instanceof GameCoreError && (e.status === 429 || e.status >= 500); if (!transient) throw e; await new Promise((r) => setTimeout(r, 2 ** i * 500)); } } throw lastError; } const games = await withRetry(() => gc.catalog.getHomepageGames()); console.log("got", games.length, "games");