Skip to content

JS SDK — Client Usage

How to use generated TypeScript clients to make unary and streaming RPC calls from the browser.

Generated Client

The ionc compile --only browser command generates a TypeScript file with typed client classes for each service. Given this schema:

service UserService(spaceId: u4) {
    GetUser(userId: u4): User;
    stream WatchUpdates(): User;
}

The generated code provides a typed client class.

Unary Calls (HTTP POST)

Unary methods use IonUnaryRequest under the hood — a single HTTP POST with CBOR body and CBOR response:

import { UserServiceClient } from './generated/services';

const client = new UserServiceClient("https://api.example.com", 1);
// base arg: spaceId = 1

const user = await client.GetUser(42);
console.log(user.name);  // fully typed

Under the hood:

  1. Arguments are serialized to CBOR: [spaceId, userId]
  2. HTTP POST to /ion/UserService/GetUser.unary
  3. Response body (CBOR) is deserialized into a User object

Streaming Calls (WebSocket)

Streaming methods use IonWsClient — a WebSocket connection that yields typed events:

const stream = client.WatchUpdates();

stream.on("data", (user) => {
    console.log(`Updated: ${user.name}`);
});

stream.on("end", () => {
    console.log("Stream ended");
});

stream.on("error", (err) => {
    console.error("Stream error:", err);
});

Wire Protocol

Opcode Meaning
0x00 Data — CBOR-encoded message payload
0x01 End — graceful stream termination
0x02 Error — error with protocol error code and message

Each WebSocket binary message is prefixed with a 1-byte opcode followed by the CBOR payload.

Authentication

Ticket-based authentication is supported via the WebSocket subprotocol header. Set the ticket when creating the client:

const client = new UserServiceClient(
    "https://api.example.com",
    1,  // spaceId
    { ticket: "eyJhbG..." }
);