# server ws

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

Generate a TypeScript (Node.js) server of the WebSocket channels of an AsyncAPI document.

## Usage

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

## Description

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

The server serves the WebSocket channels of the document (see
[apigenie-generator client ws](/techdocs/reference/cli-generate_client_ws)) at their addresses, using the
[ws](https://github.com/websockets/ws) package. By default it implements the application the
document describes: it sends the messages of `send` operations and receives the messages of
`receive` operations. Set the `perspective` option to `counterpart` to swap them.

```ts
import { createServer } from "chat-api-server";

const server = createServer({
  room: {
    onConnect(session) {
      console.log(`joined ${session.params.roomId}`);
    },
    onJoin(session, payload) {
      session.sendRoomEvent({ kind: "joined", user: payload.user });
    },
  },
});
await server.listen(8080);
```

For every channel, the generated code has:

- a session class (`RoomSession`): a connection of a client, with the values of the address
  parameters (`params`), the query parameters converted to the types of the WebSocket binding
  (`query`), the handshake `headers`, `send<Message>(payload)` methods and `close()`. The
  reply messages of an operation whose `reply` is on the same channel get `send<Message>`
  methods too, and, when the request and reply messages have a correlation id in their payloads,
  `replyTo<Operation>(request, reply)` sends the reply with the request's correlation id copied
  into it (e.g. `session.replyToRequestPickup(request, confirmation)`).
- a handler interface (`RoomHandler`) with `onConnect`, `on<Message>` for every message the
  server receives (when the channel receives one message, or when its messages can be told apart
  by a property with a distinct constant value), `onMessage` for every message of a channel
  receiving several, `onUnknownMessage`, `onClose` and `onError`

The handlers of a session are called one at a time, in the order of the events; a handler
returning a promise delays the next one until it settles. Errors thrown by handlers are passed to
`onError`.

`createServer(handlers, options)` serves the channels with handlers. Connections to other
addresses are rejected with status 404. Options are an existing HTTP server to attach to
(`server`) and a path prefix of all addresses (`basePath`). The result has `listen(port, host)`,
`close()`, `address()` and `httpServer`.

The generated package contains `src/types.ts`, `src/messages.ts`, `src/server.ts`,
`src/metadata.ts`, `src/runtime.ts` and `src/index.ts`, with `package.json` (depending on `ws`)
and `tsconfig.json`.

Not supported, and reported as warnings: replies on another channel or at a runtime-expression
address, channels without an address, and channels sharing an address with another channel (only
the first one is served). Security schemes and requirements are not generated: the server checks
no credentials on the handshake, and the headers schema of the WebSocket binding is not typed.

## Extensions

| Extension | Effect |
| --------- | ------ |
| `x-apigenie.codegen.name` | on a channel: the base of its names (`LobbyHandler`); 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 server 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.server_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 `-server`.

### --package-version

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

## Configuration

```yaml
version: '1.0'
commands:
  generate:
    server_ws:
      layout: package
      import_extension: .js
      perspective: application
```

| 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` | `application` (default): the described application; `counterpart`: its client |
