# WebsockexNova
A robust, highly extensible WebSocket client library for Elixir with elegant abstractions for building specialized WebSocket clients.
This library is based on the excellent [Websockex](https://github.com/Azolo/websockex) library by [Azolo](https://github.com/Azolo) and has been heavily extended with additional capabilities including behavior-based extensibility, adapter patterns, Gun transport integration, automatic reconnection, subscription management, rate limiting, and more.
## Features
- **Behavior-Based Architecture**: Easily extendable through behavior interfaces
- **Adapter Pattern**: Customize specific aspects of WebSocket communication
- **Default Implementations**: Sensible defaults provided for all behaviors
- **Gun Integration**: Uses the battle-tested Gun library as the transport layer
- **Client Macro**: Simplify creation of service-specific WebSocket clients
- **Adapter Macro**: Build service-specific adapters with minimal boilerplate
- **Rate Limiting**: Built-in rate limiting capabilities
- **Observability**: Rich telemetry and logging support
## Installation
Add `websockex_nova` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:websockex_nova, "~> 0.1.0"}
]
end
```
## Usage
### Basic Usage
```elixir
# Connect to a WebSocket server
{:ok, conn} = WebsockexNova.Client.connect(WebsockexNova.Defaults.DefaultAdapter, %{
host: "echo.websocket.org",
port: 443,
path: "/",
transport: :tls
})
# Send a message
{:ok, response} = WebsockexNova.Client.send_text(conn, "Hello, WebSocket!")
# Close the connection
WebsockexNova.Client.close(conn)
```
### Using ClientMacro
Create service-specific clients with minimal boilerplate using `WebsockexNova.ClientMacro`:
```elixir
defmodule MyApp.DeribitClient do
use WebsockexNova.ClientMacro, adapter: MyApp.DeribitAdapter
# Add domain-specific methods:
def subscribe_to_trades(conn, instrument, opts \\ nil) do
channel = "trades.#{instrument}.raw"
subscribe(conn, channel, opts)
end
def subscribe_to_ticker(conn, instrument, opts \\ nil) do
channel = "ticker.#{instrument}.raw"
subscribe(conn, channel, opts)
end
end
# Usage
{:ok, conn} = MyApp.DeribitClient.connect()
{:ok, _} = MyApp.DeribitClient.subscribe_to_trades(conn, "BTC-PERPETUAL")
```
### Using AdapterMacro
Create service-specific adapters with minimal boilerplate using `WebsockexNova.Adapter`:
```elixir
defmodule MyApp.DeribitAdapter do
use WebsockexNova.Adapter
# Override only what you need:
@impl WebsockexNova.Behaviors.ConnectionHandler
def connection_info(opts) do
defaults = %{
host: "www.deribit.com",
port: 443,
path: "/ws/api/v2",
transport: :tls
}
{:ok, Map.merge(defaults, opts)}
end
@impl WebsockexNova.Behaviors.MessageHandler
def handle_message(message, state) do
# Custom message handling...
{:ok, decoded_message, updated_state}
end
end
```
## Documentation
Comprehensive documentation is available in the `docs/` directory:
- **Architecture Overview**: `docs/architecture.md`
- **Client Macro Guide**: `docs/client_macro.md`
- **Implementation Plan**: `docs/plan.md`
## License
This project is licensed under the MIT License - see the LICENSE file for details.