Repository: directus/directus
File: sdk/src/realtime/composable.ts (TypeScript)

Code before:
				} else if (state.code !== 'closed') {
					// error state
					throw new Error(`Cannot connect when state is "${state.code}"`);
				}

				const { promise: connectPromise, resolve, reject } = Promise.withResolvers<WebSocketInterface>();

				state = {
					code: 'connecting',
					connection: connectPromise,
				};

				// we need to use THIS here instead of client to access overridden functions
				const self = this as AuthWSClient<Schema>;
				const url = await getSocketUrl(self);
				debug('info', `Connecting to ${url}...`);

				let resolved = false;
				const ws = new client.globals.WebSocket(url);

				let connectTimeout: ReturnType<typeof setTimeout> | undefined;

				if (config.connect) {
					connectTimeout = setTimeout(() => {
						reject('Connection attempt timed out.');
					}, config.connect.timeout ?? 10000);
				}

				ws.addEventListener('open', async (evt: Event) => {
					debug('info', `Connection open.`);

					state = { code: 'open', connection: ws, firstMessage: true };
					reconnectState.attempts = 0;
					reconnectState.active = false;
					clearTimeout(connectTimeout);
					handleMessages(self);

					if (config.authMode === 'handshake' && hasAuth(self)) {
						const access_token = await self.getToken();

						if (!access_token) {
							return reject(
								'No token for authenticating the websocket. Make sure to provide one or call the login() function beforehand.',
							);
						}

						ws.send(auth({ access_token }));
						const confirm = await messageCallback(ws);

						if (
							!(

Review comment (suggestion):
We should wrap a try catch below this to update the state as any error thrown would result in a hanging `connecting` state

Code after:
				return state.code === 'open';
			},
			async connect() {
				wasManuallyDisconnected = false;

				if (state.code === 'connecting') {
					// wait for the current connection to open
					return await state.connection;
				} else if (state.code !== 'closed') {
					// error state
					throw new Error(`Cannot connect when state is "${state.code}"`);
				}

				// Eventually update to Promise.withResolvers()
				let resolve!: (value: WebSocketInterface | PromiseLike<WebSocketInterface>) => void;
				let reject!: (reason?: any) => void;

				const connectPromise = new Promise<WebSocketInterface>((res, rej) => {
					resolve = res;
					reject = rej;
				});

				state = {
					code: 'connecting',
					connection: connectPromise,
				};

				// we need to use THIS here instead of client to access overridden functions
				const self = this as AuthWSClient<Schema>;
				let ws: WebSocketInterface;

				try {
					const url = await getSocketUrl(self);
					debug('info', `Connecting to ${url}...`);

					ws = new client.globals.WebSocket(url);
				} catch (e) {
					state = { code: 'closed' };
					reject(e);
					throw e;
				}

				let resolved = false;
				let connectTimeout: ReturnType<typeof setTimeout> | undefined;

				if (config.connect) {
					connectTimeout = setTimeout(() => {
						reject('Connection attempt timed out.');
					}, config.connect.timeout ?? 10000);
				}