Skip to content
Back to archipelago.banuacoder.com

Infrastructure SDKs

websocket_sdk Free ​

Tier
Freeversion 1.2.5
Command
archipelago generate websocket_sdk
Generates
  • infrastructure/websocket_sdk_api
  • infrastructure/websocket_sdk_dart (if selected)
  • infrastructure/websocket_sdk_phoenix (if selected)

WebSocket client abstraction with dart:io or Phoenix implementation.

Variables ​

VariableTypeDefaultDescription
appNamestring—The name of your application
websocketLibraryenum (dart, phoenix)dartThe WebSocket library to use
isForMonorepobooleantrueWhether this is being generated as part of a monorepo

Usage ​

Interactive ​

bash
archipelago generate websocket_sdk

Non-interactive (CI) ​

bash
archipelago generate websocket_sdk --config my_config.json

Config Template ​

json
{
  "@appName": "The name of your application",
  "appName": "MyApp",
  "@websocketLibrary": "The WebSocket library to use (dart | phoenix)",
  "websocketLibrary": "dart",
  "@isForMonorepo": "Whether this is being generated as part of a monorepo",
  "isForMonorepo": true
}

Generated Structure ​

Always generated:

text
infrastructure/
└── websocket_sdk_api/
    ├── lib/
    │   ├── websocket_sdk_api.dart
    │   └── src/
    │       ├── client/
    │       │   └── websocket_client.dart
    │       ├── exceptions/
    │       │   ├── exceptions.dart
    │       │   ├── websocket_closed_exception.dart
    │       │   ├── websocket_connection_exception.dart
    │       │   ├── websocket_exception.dart
    │       │   └── websocket_send_exception.dart
    │       ├── interceptor/
    │       │   └── websocket_interceptor.dart
    │       ├── message/
    │       │   ├── websocket_message.dart
    │       │   └── websocket_message_type.dart
    │       └── state/
    │           └── connection_state.dart
    ├── pubspec.yaml
    └── README.md

When websocketLibrary is dart:

text
infrastructure/
└── websocket_sdk_dart/
    ├── lib/
    │   ├── websocket_sdk_dart.dart
    │   └── src/
    │       ├── client/
    │       │   └── dart_websocket_client.dart
    │       ├── config/
    │       │   └── websocket_config.dart
    │       └── di/
    │           ├── injector.dart
    │           ├── injector.module.dart
    │           └── register_module.dart
    ├── pubspec.yaml
    └── README.md

When websocketLibrary is phoenix:

text
infrastructure/
└── websocket_sdk_phoenix/
    ├── lib/
    │   ├── websocket_sdk_phoenix.dart
    │   └── src/
    │       ├── channel/
    │       │   └── phoenix_channel_manager.dart
    │       ├── client/
    │       │   └── phoenix_websocket_client.dart
    │       ├── config/
    │       │   └── phoenix_config.dart
    │       └── di/
    │           ├── injector.dart
    │           └── register_module.dart
    ├── pubspec.yaml
    └── README.md

API ​

dart
abstract class WebSocketClient {
  ConnectionState get state;
  Stream<ConnectionState> get stateStream;
  Stream<WebSocketMessage> get messageStream;

  Future<void> connect(Uri uri, {Map<String, String>? headers});
  Future<void> disconnect({int? code, String? reason});

  void send(WebSocketMessage message);
  void sendText(String text);
  void sendJson(Map<String, dynamic> json);
  void sendBytes(List<int> bytes);

  void addInterceptor(WebSocketInterceptor interceptor);
  void removeInterceptor(WebSocketInterceptor interceptor);

  void dispose();
}

enum ConnectionState { disconnected, connecting, connected, disconnecting, error }
dart
final client = getIt<WebSocketClient>();
client.stateStream.listen((state) => print('state: $state'));
client.messageStream.listen((msg) => print(msg.dataAsMap ?? msg.dataAsString));

await client.connect(Uri.parse('wss://example.com/socket'));
client.sendJson({'type': 'ping'});

WebSocketMessage carries data, an optional type (text/json/binary), and topic/event/ref fields for pub/sub systems like Phoenix. dataAsString/dataAsMap/dataAsBytes cast data to the matching shape or return null.

DI and wiring notes ​

Each variant's pubspec.yaml declares its archipelago: di_modules block for monorepo_toolkit generate host-registry, with no cross-package ordering constraint:

yaml
archipelago:
  di_modules:
    - class: WebsocketSdkDartPackageModule      # websocketLibrary: dart
    # or
    - class: WebsocketSdkPhoenixPackageModule   # websocketLibrary: phoenix

Since 1.1.0, post_gen.dart adds the selected variant's pubspec dependency and wires its PackageModule into injector.dart automatically — before this fix the package was generated into the workspace but never actually registered, so getIt<WebSocketClient>() threw an unregistered-type error in every generated project.

Switch the client ​

A generated app wires one client: dart:io or Phoenix. Both register as the WebSocketClient from websocket_sdk_api, so code that uses only websocket_sdk_api does not change when you switch. Brick 1.2.0 and later does the switch in one step. Run the brick again and pick the other websocketLibrary:

bash
archipelago generate websocket_sdk   # answer websocketLibrary: phoenix
# or, in CI, with websocketLibrary set in the config file
archipelago generate websocket_sdk --config websocket_sdk.json

The post_gen hook then does these steps:

  1. It generates infrastructure/websocket_sdk_phoenix/.
  2. It removes websocket_sdk_dart from apps/<app>/pubspec.yaml. It also removes its import and ExternalModule(WebsocketSdkDartPackageModule) from apps/<app>/lib/di/injector.dart.
  3. It adds websocket_sdk_phoenix and ExternalModule(WebsocketSdkPhoenixPackageModule).
  4. It sets infrastructure.websocket.library: phoenix (and enabled: true) in archipelago.yaml.

The old package stays in infrastructure/websocket_sdk_dart/, because you may have changed it. The hook prints the command to delete it. Delete it only if nothing else depends on it. Then regenerate the DI code:

bash
melos bootstrap
melos run build

The switch from phoenix to dart works the same way. If you run the brick again with the client that is already wired, nothing changes. Code that imports package:phoenix_socket or dart:io's WebSocket directly is not part of the switch.

Dependencies ​

  • websocketLibrary: dart — raw dart:io WebSocket, no external pub dependency beyond meta
  • websocketLibrary: phoenix — phoenix_socket: ^0.8.0 (Phoenix Channels client)

Known Limitations ​

  • Reconnection in the dart:io client is opt-in and simple. It is off by default. With WebSocketConfig(reconnectOnClose: true), the client reconnects to the last URI after a close, waits a fixed reconnectDelay (default 5 s) before each attempt, and stops after maxReconnectAttempts (default 3). A successful connect resets the count. There is no exponential backoff. When the attempts run out, state stays disconnected and the caller must reconnect.
  • The Phoenix variant leaves reconnection to phoenix_socket, which retries with PhoenixConfig.reconnectDelays (default 1, 2, 5 and 10 s). In DI mode the injected PhoenixSocket uses its own options.
  • Only one variant is wired at a time. Switching websocketLibrary means running the brick again (see Switch the client), not a runtime toggle.

Changelog ​

Run archipelago brick info websocket_sdk to see the latest published version. Enterprise customers can read the full CHANGELOG.md in the brick source repository.