Create bluesky bots via configuration.
1import { WebSocketClient, WebSocketClientOptions } from "@vinerima/wah";
2import { JetstreamPostCreateCommitSchema, JetstreamPostCreateCommit } from "../types/message";
3import { commitToPost } from "./wsToFeed";
4import type { Post } from "../types/post";
5import { Logger } from "./logger";
6
7export interface JetstreamClientOptions {
8 /** Single Jetstream service URL or array of URLs for failover. */
9 service: string | string[];
10 /** Query parameters appended to the WebSocket URL (e.g. `wantedCollections`). */
11 queryParams?: Record<string, string | number | boolean>;
12 /** Reconnection configuration. */
13 reconnect?: WebSocketClientOptions["reconnect"];
14 /** Heartbeat ping interval in milliseconds. Default: 10000. */
15 pingInterval?: number;
16 /** Called for each new post received from the firehose. */
17 onPost?: (post: Post) => void | Promise<void>;
18}
19
20/**
21 * Creates a `@vinerima/wah` WebSocketClient pre-configured for the
22 * Bluesky Jetstream firehose. It registers a schema-validated handler
23 * for post creation events and converts them to `Post` objects.
24 *
25 * @param options - Jetstream connection and handler options.
26 * @returns A configured and connected `WebSocketClient` instance.
27 */
28export function createJetstreamClient(options: JetstreamClientOptions): WebSocketClient {
29 const client = new WebSocketClient({
30 service: options.service,
31 queryParams: options.queryParams,
32 reconnect: options.reconnect,
33 pingInterval: options.pingInterval,
34 logger: {
35 custom: {
36 debug: (msg, ctx) => Logger.debug(msg, ctx as object),
37 info: (msg, ctx) => Logger.info(msg, ctx as object),
38 warn: (msg, ctx) => Logger.warn(msg, ctx as object),
39 error: (msg, ctx) => Logger.error(msg, ctx as object),
40 },
41 },
42 });
43
44 client.handle<JetstreamPostCreateCommit>(JetstreamPostCreateCommitSchema, async ctx => {
45 const post = commitToPost(ctx.data);
46 if (post && options.onPost) {
47 await options.onPost(post);
48 }
49 });
50
51 client.connect();
52
53 return client;
54}