import { CommandError, NOT_FOUND_CODES, type CommandName, type GameEngine } from "@deadhead/engine"; import type { RouteName } from "@deadhead/schema"; import { ApiError, type ApiClient } from "./client"; /** The HTTP status the server sent for a code, so screens read refusals as before. */ function statusFor(code: CommandError["code"]): number { if (code === "validation-error") return 400; if (code === "unauthorized") return 401; return NOT_FOUND_CODES.has(code) ? 404 : 409; } /** * The typed client over the engine instead of HTTP (CR-014 Step 14.7): the * same catalog names, inputs and outputs, and refusals as the same `ApiError`s. */ export function createEngineClient(engine: GameEngine): ApiClient { let prompt: Promise = Promise.resolve(); return { async call(name, input) { try { const result = await engine.call(name as RouteName as CommandName, input as never); // Notifications are asked for once the player owns the business (decision 0.5.91). if (name === "acceptDeal") prompt = engine.requestNotificationPermission().catch(() => {}); return result as never; } catch (error) { if (error instanceof CommandError) { throw new ApiError(statusFor(error.code), error.code, error.message); } throw error; } }, notificationPrompt: () => prompt, }; }