WebSocket clients

View as Markdown

Fern generates typed WebSocket clients from your AsyncAPI channel definitions. The generated clients handle connection management, typed send/receive messages, and automatic reconnection.

Fern generates WebSocket clients for TypeScript, Python, Java, C#, and Rust. Go generates types only, and Ruby is not yet supported.

Enable WebSocket client generation

Add the config flag to the relevant generator in your generators.yml:

1groups:
2 ts-sdk:
3 generators:
4 - name: fernapi/fern-typescript-sdk
5 version: ...
6 config:
7 generateWebSocketClients: true

Java generates WebSocket clients by default with no additional configuration.

Generated SDK behavior

Given an AsyncAPI channel definition like:

asyncapi.yml
1asyncapi: 3.0.0
2info:
3 title: Plant Monitoring Service
4 version: 1.0.0
5channels:
6 plantUpdates:
7 address: /plants/{plant_id}/updates
8 parameters:
9 plant_id:
10 description: Plant identifier
11 messages:
12 SensorReading:
13 $ref: '#/components/messages/SensorReading'
14 PlantStatus:
15 $ref: '#/components/messages/PlantStatus'
16operations:
17 sendReading:
18 action: send
19 channel:
20 $ref: '#/channels/plantUpdates'
21 messages:
22 - $ref: '#/channels/plantUpdates/messages/SensorReading'
23 receivePlantStatus:
24 action: receive
25 channel:
26 $ref: '#/channels/plantUpdates'
27 messages:
28 - $ref: '#/channels/plantUpdates/messages/PlantStatus'
29components:
30 messages:
31 SensorReading:
32 payload:
33 type: object
34 properties:
35 temperature:
36 type: number
37 humidity:
38 type: number
39 PlantStatus:
40 payload:
41 type: object
42 properties:
43 health:
44 type: string
45 needsWater:
46 type: boolean

Fern generates the following client code.

Send methods are named send + the operation name from the spec. The sendReading operation produces sendSendReading in TypeScript, Python, Java, and Rust. C# uses overloaded Send() methods instead.

Receive handling varies by language:

  • TypeScript — a generic socket.on("message", handler) callback
  • Python — typed responses from ws.recv()
  • Java — per-message-type handlers like onPlantStatus(handler)
  • C# — typed Event<T> properties like PlantStatus.Subscribe(handler)
  • Rust — a typed enum from ws.recv()

The TypeScript SDK generates a typed socket class with send methods, event handlers, and a ReconnectingWebSocket that automatically retries dropped connections.

1const client = new PlantClient({ token: "..." });
2
3const socket = await client.plantUpdates.createPlantUpdatesConnection({
4 plantId: "plant-123",
5});
6
7socket.on("open", () => {
8 console.log("Connected");
9});
10
11socket.on("message", (message) => {
12 // message is typed as PlantStatus
13 console.log(message.health);
14});
15
16socket.on("error", (error) => {
17 console.error(error);
18});
19
20socket.sendSendReading({ temperature: 22.5, humidity: 65 });
21
22socket.close();

Authentication

In TypeScript, Python, Java, and Rust, WebSocket clients automatically inherit the authentication configured on the root client. Headers — including bearer tokens, API keys, and custom headers — are sent with the WebSocket handshake request.

1const client = new PlantClient({
2 token: "your-bearer-token",
3});
4
5// Auth headers are forwarded to the WebSocket handshake
6const socket = await client.plantUpdates.createPlantUpdatesConnection({
7 plantId: "plant-123",
8});

In C#, the WebSocket client is constructed with an Options object that includes the connection URL and channel parameters. Configure authentication through the HttpInvoker option or by setting headers on the underlying client.

Defining WebSocket channels

WebSocket clients are generated from channel definitions in your AsyncAPI specification. For defining channels, messages, and operations, see Publish/subscribe operations.