Files
t5de-hub/apps/web/app/rooms/actions.ts
T
dhkatzandClaude Opus 5.5 2a1fc94df6
CI / test (push) Successful in 1m5s
Hosted rooms: the hub's side
Rooms made on the website (hosted_room, migration 0005), the REST routes in
docs/hosted-rooms.md, and the realtime room.* protocol: joining with the
capacity, adult and linked-account rules, seats, numbered messages with
forged senders dropped and a rate limit, closing. The Rooms page lists them,
with a form to make one and the owner's edit and close.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 03:21:21 -07:00

57 lines
1.8 KiB
TypeScript

"use server";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { api, unwrap } from "@/lib/api";
import { attempt, field, type ActionState } from "@/lib/actions";
const rating = (form: FormData) => (field(form, "rating") === "adult" ? ("adult" as const) : ("general" as const));
/** Makes a hosted room, then goes back to the list. */
export async function createRoom(_: ActionState, form: FormData): Promise<ActionState> {
const state = await attempt(async () => {
unwrap(
await api["hosted-rooms"].post({
name: field(form, "name"),
description: field(form, "description"),
roomPid: Number(field(form, "roomPid")),
rating: rating(form),
maxUsers: Number(field(form, "maxUsers")),
imvuId: Number(field(form, "imvuId")),
}),
);
revalidatePath("/rooms");
});
if (state?.error) return state;
redirect("/rooms");
}
/** The owner's changes to a room. */
export async function saveRoom(_: ActionState, form: FormData): Promise<ActionState> {
const n = field(form, "n");
const state = await attempt(async () => {
unwrap(
await api["hosted-rooms"]({ n }).patch({
name: field(form, "name"),
description: field(form, "description"),
roomPid: Number(field(form, "roomPid")),
rating: rating(form),
maxUsers: Number(field(form, "maxUsers")),
}),
);
revalidatePath("/rooms");
});
if (state?.error) return state;
redirect("/rooms");
}
/** Closes a room: everyone in it is sent out. */
export async function closeRoom(_: ActionState, form: FormData): Promise<ActionState> {
const n = field(form, "n");
const state = await attempt(async () => {
unwrap(await api["hosted-rooms"]({ n }).delete());
revalidatePath("/rooms");
});
if (state?.error) return state;
redirect("/rooms");
}