Files
healer-man/src/app/dungeonSimulationClient.ts
T
2026-09-16 14:30:58 -04:00

88 lines
3.2 KiB
TypeScript

import type { PlayerSession } from "./types";
import { requestOnlineJson } from "./onlineAccountClient";
import type {
DungeonReplaySummary,
DungeonReplayV1,
DungeonRouteApproval,
DungeonRouteReview,
DungeonRouteReviewStatus,
DungeonSimulationReportV1,
} from "../game/dungeonSimulationTypes";
function gmToken(session: PlayerSession | null): string {
if (session?.kind !== "account" || !session.accessToken || !session.roles?.includes("gm")) {
throw new Error("Game Master access is required.");
}
return session.accessToken;
}
export async function fetchDungeonRouteApprovals(): Promise<readonly DungeonRouteApproval[]> {
return (await requestOnlineJson<{ approvals: DungeonRouteApproval[] }>("/api/dungeon-route-approvals")).approvals;
}
export async function fetchGmDungeonRoutes(session: PlayerSession | null): Promise<{
readonly reviews: readonly DungeonRouteReview[];
readonly latestReplays: readonly DungeonReplaySummary[];
}> {
return requestOnlineJson("/api/gm/dungeon-routes", {}, gmToken(session));
}
export async function putDungeonRouteReview(
session: PlayerSession | null,
route: { readonly dungeonId: string; readonly routeId: string; readonly routeHash: string },
update: {
readonly status: DungeonRouteReviewStatus;
readonly expectedRevision: number;
readonly note?: string;
readonly criticalOverrideNote?: string;
},
): Promise<DungeonRouteReview> {
const response = await requestOnlineJson<{ review: DungeonRouteReview }>(
`/api/gm/dungeon-routes/${encodeURIComponent(route.dungeonId)}/${encodeURIComponent(route.routeId)}/review`,
{ method: "PUT", body: JSON.stringify({ ...update, routeHash: route.routeHash }) },
gmToken(session),
);
return response.review;
}
export async function fetchDungeonSimulationReplays(
session: PlayerSession | null,
dungeonId?: string,
): Promise<readonly DungeonReplaySummary[]> {
const query = dungeonId ? `?dungeon=${encodeURIComponent(dungeonId)}` : "";
return (await requestOnlineJson<{ replays: DungeonReplaySummary[] }>(
`/api/gm/dungeon-sim/replays${query}`,
{},
gmToken(session),
)).replays;
}
export async function saveDungeonSimulationReplay(
session: PlayerSession | null,
replay: DungeonReplayV1,
): Promise<DungeonReplaySummary> {
return (await requestOnlineJson<{ replay: DungeonReplaySummary }>(
"/api/gm/dungeon-sim/replays",
{ method: "POST", body: JSON.stringify(replay) },
gmToken(session),
)).replay;
}
export function fetchDungeonSimulationReplay(
session: PlayerSession | null,
replayId: string,
): Promise<DungeonReplayV1> {
return requestOnlineJson(`/api/gm/dungeon-sim/replays/${encodeURIComponent(replayId)}`, {}, gmToken(session));
}
export function fetchDungeonSimulationReport(
session: PlayerSession | null,
replayId: string,
): Promise<DungeonSimulationReportV1> {
return requestOnlineJson(`/api/gm/dungeon-sim/replays/${encodeURIComponent(replayId)}/report`, {}, gmToken(session));
}
export function deleteDungeonSimulationReplay(session: PlayerSession | null, replayId: string): Promise<{ readonly ok: true }> {
return requestOnlineJson(`/api/gm/dungeon-sim/replays/${encodeURIComponent(replayId)}`, { method: "DELETE" }, gmToken(session));
}