fix(core-realtime): address Phase 2 code review (typing, error handling, params)

- Type socket.data.user via AppSocketData/AppSocket generics (no more any)
- Wrap Gate 1 authenticator call in try/catch so exceptions reject the
  connection with connect_error instead of being swallowed
- Fix Gate 3 userScoped channel authorize: derive params.userId from the
  authenticated socket user so owner-inbound is accepted
- Await io.close(callback) in stop() to ensure full shutdown
- Remove unused httpServer field from constructor (io already holds the ref)
- Extract CHANNEL_ROOM_PREFIX/channelRoom helper to channel-room.ts;
  replace three `ch:${name}` magic strings; re-export from index
- Add JSDoc to ChannelScope explaining userScoped params/template convention
- Fix "allows subscribe + invokes handler with ctx" test: hoist received
  outside beforeEach and assert ctx shape
- New test: rejects connection when authenticator throws
- New test: userScoped channel accepts inbound from owner, rejects from anon
This commit is contained in:
2026-05-08 21:52:52 +02:00
parent 964fabf796
commit 228cfb57c0
7 changed files with 221 additions and 68 deletions

View File

@@ -1,5 +1,6 @@
import { describe, it, expect, vi } from "vitest";
import { z } from "zod";
import { channelRoom } from "@/channel-room";
import { SocketIORealtimeBroadcaster } from "@/socket-io-realtime-broadcaster";
import { defineRealtimeChannel } from "@/realtime-channel";
@@ -16,7 +17,7 @@ describe("SocketIORealtimeBroadcaster", () => {
const io = { to } as never;
const b = new SocketIORealtimeBroadcaster(io);
await b.broadcast(ch, { x: 1 });
expect(to).toHaveBeenCalledWith("ch:a.b");
expect(to).toHaveBeenCalledWith(channelRoom("a.b"));
expect(emit).toHaveBeenCalledWith("a.b", { x: 1 });
});