# client ws

Source: https://apigenie.pl/techdocs/reference/cli-generate_client_ws

Generate a TypeScript client of the WebSocket channels of an AsyncAPI document.

## Usage

```sh
apigenie-generator client ws [...OPTIONS] INPUT_FILE
```

## Description

The input must be an AsyncAPI 3.x document. Documents referencing other files are bundled first.

The generator creates one class per WebSocket channel, i.e. a channel with a `ws` binding, or a
channel of a server whose protocol is `ws` or `wss` (every channel when the document has no
servers). Other channels are skipped. The client uses the `WebSocket` class of browsers and of
Node.js 22 or later, and has no dependencies.

An AsyncAPI document describes an application. By default the client is its counterpart: it
sends the messages of `receive` operations and receives the messages of `send` operations. Set
the `perspective` option to `application` to generate the application instead.

```ts
import { RoomClient } from "chat-api-client";

const room = new RoomClient();
room.onRoomEvent((event) => console.log(event.kind));
await room.connect({ params: { roomId: "general" }, query: { token } });
room.sendJoin({ type: "join", user });
```

Each class has:

- `connect(options)`: opens the connection. Options are the server (`server`, a key of the
  document's servers, or `baseUrl`), the values of server variables (`variables`), the values of
  the parameters of the channel address (`params`), the query parameters of the WebSocket binding
  (`query`), handshake headers (`headers`, see below), subprotocols (`protocols`) and a
  `webSocketFactory`.
- `send<Message>(payload)` for every message the client sends.
- `on<Message>(handler)` for every message it receives, when the channel receives one message, or
  when its messages can be told apart by a property with a distinct constant value (e.g.
  `type: { const: join }`). `onMessage(handler)` receives every message of a channel receiving
  several. Handlers return a function removing them.
- `request<Operation>(payload, { timeoutMs })` for every operation whose `reply` is on the same
  channel, when the request and reply messages have a correlation id in their payloads (e.g.
  `$message.payload#/requestId`): it sends the request and resolves with the reply carrying the
  same id, or rejects after `timeoutMs` (30 seconds by default) or when the connection closes.
  The reply also reaches its `on<Message>` handler. Operation `requestPickup` gives
  `requestPickup`, `bookPickup` gives `requestBookPickup`.
- `onError`, `onClose`, `onUnknownMessage`, `close()` and `connected`.

Payloads are encoded by the content type of the message: JSON for `application/json` and
`*/*+json` (the default), text for `text/*`, binary data (`ArrayBuffer`) otherwise.

Browsers can't send headers with the WebSocket handshake, so the `headers` option requires a
`webSocketFactory` creating sockets that can, e.g. of the `ws` package.

The generated package contains `src/types.ts` (component schemas), `src/messages.ts` (payload
types and type guards), `src/client.ts`, `src/metadata.ts` (servers and channels),
`src/runtime.ts` and `src/index.ts`, with `package.json` and `tsconfig.json`.

The reply messages of an operation's `reply` on the same channel are received messages like the
others. Not supported, and reported as warnings: replies on another channel or at a
runtime-expression address, and WebSocket binding methods other than `GET`. Security schemes and
requirements are not generated.

## Extensions

| Extension | Effect |
| --------- | ------ |
| `x-apigenie.codegen.name` | on a channel: the base of its names (`LobbyClient`); on a message: the base of its types (`PostPayload`); on a component schema: the name of its type |
| `x-apigenie.codegen.disabled` | `true` on a channel or an operation leaves it out (with the operations of a channel left out) |

The extensions can live in an overlay for this target instead of in the document, e.g.
`ws.overlay.yaml`:

```yaml
overlay: 1.0.0
info:
  title: WebSocket names
  version: 1.0.0
actions:
  - target: $.channels.room
    update:
      x-apigenie:
        codegen:
          name: Lobby
  - target: $.components.messages.ChatMessage
    update:
      x-apigenie:
        codegen:
          name: Post
```

```sh
apigenie-generator client ws asyncapi.yaml --overlay ws.overlay.yaml -o out
```

## Options

### -c, --config

Path to the configuration file to use. See the "Configuration" section for more information.

### --overlay OVERLAY

Path to an OpenAPI Overlay (1.0 to 1.2) applied to the input before generating, e.g. one setting the
extensions of the "Extensions" section. Can be repeated: the overlays apply in order, after those
listed under `commands.generate.client_ws.overlay` in the configuration file (with paths relative to
it). Warnings and errors about a value an overlay set point to the overlay. The overlays apply to
the AsyncAPI document bundled with the files it references.

### --strict

Makes an overlay action whose target selects nothing an error (exit status 2, nothing is generated)
instead of a warning (`OVERLAY:LINE:COL: action #N (TARGET) selects no nodes.`).

### -o, --output

Directory where the package is generated.

### --package-name

Name of the generated package. Defaults to the title of the API followed by `-client`.

### --package-version

Version of the generated package. Defaults to the version of the API.

## Configuration

```yaml
version: '1.0'
commands:
  generate:
    client_ws:
      layout: package
      import_extension: .js
      perspective: counterpart
```

| Option | Description |
| ------ | ----------- |
| `layout` | `package` (default): an npm package with sources in `src/`; `sources`: the sources only |
| `import_extension` | Extension of relative imports: `.js` (default, Node.js) or an empty string (bundlers) |
| `perspective` | `counterpart` (default): the client of the described application; `application`: the application itself |
