The seats route closes its block and the carried copies of the template's helpers are gone: the server builds again
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CCLa2PaEeCj8njQZSWGqHx
This commit is contained in:
1 parent
29a68f4d9d
commit
8e9f5fb8ce
3 files changed
+3
-63
No files matched your search
+1
-61
@@ -231,67 +231,6 @@ function provenBank(req: IncomingMessage, claimed: unknown, forget: unknown): {
|
|||||||
return proven;
|
return proven;
|
||||||
}
|
}
|
||||||
|
|
||||||
function send(res: ServerResponse, status: number, body: unknown): void {
|
|
||||||
res.writeHead(status, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' });
|
|
||||||
res.end(status === 204 ? undefined : JSON.stringify(body));
|
|
||||||
}
|
|
||||||
|
|
||||||
function readBytes(req: IncomingMessage, limit: number, tooBig: string): Promise<Buffer> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const declared = Number(req.headers['content-length'] ?? 0);
|
|
||||||
if (declared > limit) {
|
|
||||||
reject(new RoomError(tooBig, 413));
|
|
||||||
req.destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let size = 0;
|
|
||||||
const chunks: Buffer[] = [];
|
|
||||||
req.on('data', (chunk: Buffer) => {
|
|
||||||
size += chunk.length;
|
|
||||||
if (size > limit) {
|
|
||||||
reject(new RoomError(tooBig, 413));
|
|
||||||
req.destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
chunks.push(chunk);
|
|
||||||
});
|
|
||||||
req.on('end', () => resolve(Buffer.concat(chunks)));
|
|
||||||
req.on('error', reject);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function readBody(req: IncomingMessage): Promise<Record<string, unknown>> {
|
|
||||||
const bytes = await readBytes(req, BODY_LIMIT, 'That is more than a move needs.');
|
|
||||||
if (bytes.length === 0) return {};
|
|
||||||
try {
|
|
||||||
return JSON.parse(bytes.toString('utf8')) as Record<string, unknown>;
|
|
||||||
} catch {
|
|
||||||
throw new RoomError('The request was not JSON.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A report, an answer, or a call to the table is worth waking the keeper for; the desk's own replies are not. */
|
|
||||||
function ringBell(title: string, detail: { fingerprint: string[]; tags: Record<string, string>; extra: Record<string, unknown> }): void {
|
|
||||||
Sentry.captureMessage(title, { level: 'error', ...detail });
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The seats a browser claims, kept to the ones its tokens prove. */
|
|
||||||
function provenSeats(raw: unknown): { roomId: string; seat: string }[] {
|
|
||||||
const claims = Array.isArray(raw) ? raw.slice(0, 50) : [];
|
|
||||||
const proven: { roomId: string; seat: string }[] = [];
|
|
||||||
for (const claim of claims) {
|
|
||||||
if (typeof claim !== 'object' || claim === null) continue;
|
|
||||||
const c = claim as Record<string, unknown>;
|
|
||||||
try {
|
|
||||||
const room = rooms.get(String(c.roomId ?? ''));
|
|
||||||
proven.push({ roomId: room.id, seat: rooms.seatOf(room, typeof c.token === 'string' ? c.token : undefined).id });
|
|
||||||
} catch {
|
|
||||||
// A seat this browser cannot prove is not its business.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return proven;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The seats a browser claims, kept to the ones its tokens prove. */
|
/** The seats a browser claims, kept to the ones its tokens prove. */
|
||||||
function provenSeats(raw: unknown): { roomId: string; seat: string }[] {
|
function provenSeats(raw: unknown): { roomId: string; seat: string }[] {
|
||||||
const claims = Array.isArray(raw) ? raw.slice(0, 50) : [];
|
const claims = Array.isArray(raw) ? raw.slice(0, 50) : [];
|
||||||
@@ -427,6 +366,7 @@ async function handle(req: IncomingMessage, res: ServerResponse): Promise<void>
|
|||||||
return send(res, 200, found);
|
return send(res, 200, found);
|
||||||
}
|
}
|
||||||
throw new RoomError('Not here.', 404);
|
throw new RoomError('Not here.', 404);
|
||||||
|
}
|
||||||
if (parts[0] !== 'api' || parts[1] !== 'rooms') throw new RoomError('Not here.', 404);
|
if (parts[0] !== 'api' || parts[1] !== 'rooms') throw new RoomError('Not here.', 404);
|
||||||
|
|
||||||
if (parts.length === 2 && req.method === 'POST') {
|
if (parts.length === 2 && req.method === 'POST') {
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ describe('a seat a browser lost', () => {
|
|||||||
rooms.seen(other.room, other.token, 'home');
|
rooms.seen(other.room, other.token, 'home');
|
||||||
expect(rooms.findSeats('Bo', 'home', other.room.id).seated.map((s) => s.roomId)).toEqual([other.room.id]);
|
expect(rooms.findSeats('Bo', 'home', other.room.id).seated.map((s) => s.roomId)).toEqual([other.room.id]);
|
||||||
expect(rooms.findSeats('Bo', 'home').seated.map((s) => s.roomId).sort()).toEqual([other.room.id, room.id].sort());
|
expect(rooms.findSeats('Bo', 'home').seated.map((s) => s.roomId).sort()).toEqual([other.room.id, room.id].sort());
|
||||||
room.over = true;
|
room.state!.over = { winner: 'A', reason: 'the test says so' };
|
||||||
expect(rooms.findSeats('Bo', 'home').seated.map((s) => s.roomId)).toEqual([other.room.id]);
|
expect(rooms.findSeats('Bo', 'home').seated.map((s) => s.roomId)).toEqual([other.room.id]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
+1
-1
@@ -318,7 +318,7 @@ export class Rooms {
|
|||||||
} catch {
|
} catch {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (room.over) continue;
|
if (room.state?.over) continue;
|
||||||
const seat = room.seats.find((s) => (!s.bot || s.standIn) && s.name.toLowerCase() === wanted);
|
const seat = room.seats.find((s) => (!s.bot || s.standIn) && s.name.toLowerCase() === wanted);
|
||||||
if (seat) found.push({ room, seat });
|
if (seat) found.push({ room, seat });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user