> ## Documentation Index
> Fetch the complete documentation index at: https://crosslink.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

> All events emitted by Crosslink

## Host events

`CrosslinkServer` extends Node's `EventEmitter`. Use `server.typedOn(event, callback)` for typed payloads, or the inherited `.on()`.

### `devicePaired`

Emitted when a device completes pairing.

```js theme={null}
server.typedOn("devicePaired", (record) => {
  console.log(`Paired: ${record.deviceId}`);
});
```

Payload is the full `TrustedDeviceRecord`.

### `deviceRevoked`

Emitted when a device's access is revoked.

```js theme={null}
server.typedOn("deviceRevoked", (deviceId) => {
  console.log(`Revoked: ${deviceId}`);
});
```

### `deviceConnected`

Emitted when a paired device opens a session.

```js theme={null}
server.typedOn("deviceConnected", (info) => {
  console.log(`Connected: ${info.deviceId} via ${info.transport}`);
});
```

| Property    | Type     | Description                                                       |
| ----------- | -------- | ----------------------------------------------------------------- |
| `deviceId`  | `string` | Device ID                                                         |
| `transport` | `string` | Transport kind (`lan`, `crosslink-relayed`, `webrtc-direct`, ...) |

### `deviceDisconnected`

Emitted when a paired device's session closes. Same payload shape as `deviceConnected`.

### `pairingIssued`

Emitted whenever a new pairing code is generated. Payload is the `PairingCodeInfo` returned by `server.getPairingCode()`.

### `connectivity`

Emitted whenever host reachability changes.

```js theme={null}
server.typedOn("connectivity", (status) => {
  console.log(status.message);
});
```

Payload is a `ConnectivityStatus`: `{ reach, lan, relay, signaling, webrtc, message, transports }`.

There is no `error` or `clientError` server event — `server.start()` / `server.getPairingCode()` reject their promise on failure instead.

***

## Client events

`CrosslinkClient` is not an event emitter. The only lifecycle notification is `onStateChange`, set either as a constructor option or subscribed to later.

```js theme={null}
const unsubscribe = client.onStateChange((state, detail) => {
  console.log("State:", state, detail);
});
```

States (`ConnectionState`):

* `offline` -- No connection
* `discovering` -- Resolving how to reach the host
* `pairing` -- Pairing handshake in progress
* `connecting` -- Dialing a transport candidate
* `direct` -- Connected over LAN, memory, or a direct WebRTC channel
* `turn-relayed` -- Connected via TURN relay
* `crosslink-relayed` -- Connected via the Crosslink relay service
* `reconnecting` -- Recovering after a dropped connection
* `unauthorized` -- Host rejected the session
* `revoked` -- Host revoked this device
* `protocol-incompatible` -- No mutually supported protocol version

`isConnected(state)` (from `@crosslink/react`) is `true` for `"direct"`, `"crosslink-relayed"`, and `"turn-relayed"`.

There are no `connected` / `disconnected` / `error` client events.

***

## RPC events

`RpcClient` has no event emitter surface (no `connected`, `disconnected`, or `error` events, and no `.on()` method). Connection lifecycle is observed through the client's `onStateChange`, and per-call failures reject the `rpc.call()` promise with a `CrosslinkError`.

### Custom events

Declare and emit custom events on the host, subscribe on the client:

```js theme={null}
// Host
server.declareEvent("app.tick");
setInterval(() => server.emit("app.tick", { t: Date.now() }), 1000);

// Client
rpc.subscribe("app.tick", (payload) => {
  console.log("Tick:", payload.t);
});
```
