/******************************************************************************** * Copyright (c) 2026 CrossBreeze, EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the MIT License which is available in the project root. * * SPDX-License-Identifier: MIT ********************************************************************************/ import { WebSocketConnectionSource } from '@theia/core/lib/browser/messaging/ws-connection-source'; import { type Event } from '@theia/core/lib/common/event'; import { type AbstractChannel } from '@theia/core/lib/common/message-rpc/channel'; import { type interfaces } from '@theia/core/shared/inversify'; import { type ConnectionResilienceOptions } from '../common/connection-resilience-options'; import { type ConnectionBufferOverflow, FramedSocketWriteBuffer } from '../common/framed-socket-write-buffer'; /** * Sends a message only once the server has confirmed the session, and only * behind anything already queued. * * Theia sends straight away when `socket.connected` is true and buffers * otherwise. The gap is that reconnecting sets that flag immediately, while the * session is only confirmed a round trip later. A message produced in that * window either jumps ahead of older messages still waiting in the buffer, or, * if nothing was waiting, goes out on a socket whose channel the server has not * attached yet and is discarded by a peer with no listener for it. * * Losing one or reordering them is equally unrecoverable for anything that * applies messages by position. Theia's plugin host keeps a line-indexed copy of * every open document, so a single late or missing edit leaves that copy wrong * for good, and the next edit past its end fails. * * The server side needs no equivalent: it adopts its socket and flushes in one * synchronous step, so it has no window of this kind. */ export declare class SessionAwareConnectionSource extends WebSocketConnectionSource { /** * Whether the server has confirmed, on the socket in use right now, that it * still holds this frontend's session. A connected socket is not enough: * until the handshake is answered the server has not attached its channel to * this socket, and a message sent meanwhile reaches a peer with no listener * for it and is discarded without a trace. */ protected sessionResumed: boolean; protected sessionListenersAttached: boolean; /** * Every connect starts a socket the server has not confirmed yet, including * the reconnects socket.io performs on its own. Resetting here rather than on * disconnect also covers a connect that follows no clean disconnect event. */ protected handleSocketConnected(): void; /** * Watches the connection handshake for its outcome. * * Attached once, to the socket socket.io reuses across reconnects, and before * the base class adds its own per-negotiation listeners — so this has already * recorded the outcome by the time the base class reacts to it by flushing. */ protected trackSessionState(): void; /** Whether a message may go out now, as opposed to waiting in the buffer. */ protected get canSend(): boolean; /** * Copied from Theia apart from the duplicate check on receipt and the `onCommit` body, because * the base builds both callbacks inline and exposes no narrower seam. Re-diff when the supported * range moves. * * Called once per session, so the receive-side state starts afresh with the server's numbering. */ protected createChannel(): AbstractChannel; /** Fires when the buffer runs out of room, so an adopter can say so rather than just stopping. */ get onBufferOverflow(): Event; /** * The write buffer Theia injected into the base class. * * Reached through a structural view rather than as `this.writeBuffer`, * because that member is `private` in Theia 1.70 and only became `protected` * in 1.71 — and this package compiles against the whole range. The view * asserts nothing the versions disagree about: the field is there in both, * holding whatever `SocketWriteBuffer` is bound, and the check below is what * establishes it is ours. */ protected get framedBuffer(): FramedSocketWriteBuffer; } /** * Replaces the frontend pieces that decide how outgoing messages survive a * reconnect. Every one of them rebinds something Theia's * `messagingFrontendModule` already bound, so this belongs in a module loaded * into the same container. * * It must be a `frontendPreload` module rather than a normal frontend module: * Theia's preloader resolves `WebSocketConnectionSource` (and with it the write * buffer) while loading i18n and OS settings, which happens before any frontend * module is loaded. A rebind there would come too late — the instances would * already exist. All `frontendPreload` modules, by contrast, are loaded before * the preloader constructs anything. * * Does nothing but warn on a Theia too old to expose the buffer binding, so the * package keeps one supported range rather than splitting its floor for this * feature. Returns whether the hardening was installed, for an adopter that * wants to branch on it. */ export declare function bindConnectionResilience(isBound: interfaces.IsBound, rebind: interfaces.Rebind, options?: ConnectionResilienceOptions): boolean; //# sourceMappingURL=session-aware-connection-source.d.ts.map