Документація / WebSockets і SSE

WebSockets і SSE

Realtime-ендпоїнти у файлах маршрутів — WS-експорти та хелпер sse().

Додано у 1.0

Два realtime-примітиви, обидва живуть у звичайних файлах маршрутів.

WebSockets

Експортуйте WS із файлу маршруту. Шлях файлу — це URL WebSocket-а:

// app/routes/ws/rooms/[room].ts
import { defineWebSocket } from '@hopak/core';

export const WS = defineWebSocket({
  open(ws) {
    ws.subscribe(ws.data.params.room);
  },
  message(ws, message) {
    ws.publish(ws.data.params.room, message);
  },
  close(ws) {
    ws.unsubscribe(ws.data.params.room);
  },
});
// client
const socket = new WebSocket('ws://localhost:3000/ws/rooms/lobby?as=ada');

Auth на WebSockets

Upgrade виконується після ланцюжка before-middleware, тож ті самі guard-и, що захищають HTTP-маршрути, захищають і сокети:

// app/routes/ws/feed.ts
import { defineRoute, defineWebSocket } from '@hopak/core';
import { requireAuth } from '../../middleware/auth';

export const GET = defineRoute({
  handler: () => new Response(null, { status: 426 }),
  before: [requireAuth()],
});

export const WS = defineWebSocket({
  open(ws) { /* only authenticated clients reach here */ },
});

Server-Sent Events

Для односпрямованих потоків обробник збирає sse():

// app/routes/events.ts
import { defineRoute, sse } from '@hopak/core';

export const GET = defineRoute({
  handler: sse(async (stream, ctx) => {
    stream.send({ hello: ctx.query.get('name') ?? 'world' });

    const timer = setInterval(() => {
      stream.send({ tick: Date.now() }, { event: 'tick' });
    }, 1000);

    await stream.closed;         // resolves when the client disconnects
    clearInterval(timer);
  }),
});