Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion crates/bindings-typescript/src/sdk/db_connection_impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,21 @@ export class DbConnectionImpl<RemoteModule extends UntypedRemoteModule>
*/
isDisconnectRequested = false;

/**
* Whether the initial connection handshake completed, i.e. the
* `InitialConnection` message was received and `onConnect` was invoked.
* Used to route websocket errors on an established connection to the
* `disconnect` path instead of `connectError`.
*/
#everConnected = false;

/**
* The websocket error that ended an established connection, if any.
* Passed to the `disconnect` emit so `onDisconnect` callbacks receive
* the error that caused the disconnect, per their documented contract.
*/
#connectionError?: ErrorEvent = undefined;

/**
* Whether the underlying websocket has entered `CLOSING` (2) or `CLOSED`
* (3). This becomes true even when the browser never delivered an
Expand Down Expand Up @@ -378,10 +393,19 @@ export class DbConnectionImpl<RemoteModule extends UntypedRemoteModule>

this.ws.onclose = () => {
this.isActive = false;
this.#emitter.emit('disconnect', this);
this.#emitter.emit('disconnect', this, this.#connectionError);
};
this.ws.onerror = (e: ErrorEvent) => {
this.isActive = false;
if (this.#everConnected) {
// An error on an established connection is not a connect
// failure. Record it and close the socket so the `onclose` ->
// 'disconnect' path handles teardown, per the documented
// `onDisconnect` contract.
this.#connectionError = e;
this.ws?.close();
return;
}
this.#emitter.emit('connectError', this, e);
};
this.ws.onopen = this.#handleOnOpen.bind(this);
Expand Down Expand Up @@ -909,6 +933,7 @@ export class DbConnectionImpl<RemoteModule extends UntypedRemoteModule>
this.token = serverMessage.value.token;
}
this.#setConnectionId(serverMessage.value.connectionId);
this.#everConnected = true;
this.#emitter.emit('connect', this, this.identity, this.token);
break;
}
Expand Down