UNPKG

open-collaboration-protocol

Version:

Open Collaboration Protocol implementation, part of the Open Collaboration Tools project

88 lines 3.05 kB
// ****************************************************************************** // Copyright 2024 TypeFox GmbH // This program and the accompanying materials are made available under the // terms of the MIT License, which is available in the project root. // ****************************************************************************** import { Emitter } from '../utils/event.js'; import { Deferred } from '../utils/promise.js'; import { io } from 'socket.io-client'; export const SocketIoTransportProvider = { id: 'socket.io', createTransport: (url, headers) => { const parsedUrl = new URL(url); let path = parsedUrl.pathname; if (path && !path.endsWith('/')) { path += '/'; } // Path always ends in .../socket.io path += 'socket.io'; const socket = io(url, { path, extraHeaders: headers }); const transport = new SocketIoTransport(socket); return transport; } }; export class SocketIoTransport { socket; id = 'socket.io'; onReconnectEmitter = new Emitter(); onDisconnectEmitter = new Emitter(); onErrorEmitter = new Emitter(); disconnectTimeout; ready = new Deferred(); get onDisconnect() { return this.onDisconnectEmitter.event; } get onReconnect() { return this.onReconnectEmitter.event; } get onError() { return this.onErrorEmitter.event; } constructor(socket) { this.socket = socket; this.socket.on('disconnect', (_reason, _description) => { this.ready.reject(); this.ready = new Deferred(); // Give it 30 seconds to reconnect before firing the disconnect event this.disconnectTimeout = setTimeout(() => { this.onDisconnectEmitter.fire(); this.disconnectTimeout = undefined; }, 30_000); }); this.socket.io.on('reconnect', () => { if (this.disconnectTimeout) { clearTimeout(this.disconnectTimeout); this.disconnectTimeout = undefined; this.ready.resolve(); } this.onReconnectEmitter.fire(); }); const timeout = setTimeout(() => { this.onErrorEmitter.fire('Websocket connection timed out.'); this.ready.reject(); }, 30_000); this.socket.on('error', () => { this.onErrorEmitter.fire('Websocket connection closed unexpectedly.'); this.ready.reject(); clearTimeout(timeout); }); this.socket.on('connect', () => { this.ready.resolve(); clearTimeout(timeout); }); } async write(data) { await this.ready.promise.then(() => this.socket.send(data)); } read(cb) { this.socket.on('message', data => cb(data)); } dispose() { this.onDisconnectEmitter.dispose(); this.socket.close(); } } //# sourceMappingURL=socket-io-transport.js.map