/******************************************************************************** * Copyright (c) 2026 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 { ChannelLogger, ConnectionReporter, type ConnectionAttempt, type ConnectionTarget } from '@hydranium/client-theia/browser'; import { Clock } from '@hydranium/client-theia/common'; import { type DataPort, type ResolvedMessage, type RpcConnectionLifecycle } from '@hydranium/protocol'; import { Emitter, MessageService, type Event } from '@theia/core'; import { type ServiceConnectionProvider } from '@theia/core/lib/browser'; import { WorkspaceService } from '@theia/workspace/lib/browser'; import type { MessageConnection } from 'vscode-jsonrpc'; import { type ChannelConnectionHandle } from './channel-connection'; /** * A {@link DataPort} over a Theia frontend channel. * * Subclasses supply {@link servicePath}; everything above the port — * `DataConnection`, its sessions, and whatever model a widget drives — is * host-neutral and shared with the VS Code and browser shells. * * Bind one per service path and in singleton scope. Theia keys a frontend * channel by its path and refuses a second on a path already open, and the * throw escapes the `openChannelConnection` the loser is awaiting, leaving that * promise unsettled rather than rejected. */ export declare abstract class ChannelDataPort implements DataPort { protected readonly connectionProvider: ServiceConnectionProvider; protected readonly workspaceService: WorkspaceService; protected readonly messageService: MessageService; protected readonly connectionReporter: ConnectionReporter; readonly logger: ChannelLogger; /** Times the channel's reconnect escalation: the container's {@link Clock}, or a `SystemClock`. */ protected readonly clock: Clock; /** Frontend service path the backend forwarder for this head is registered under. */ protected abstract readonly servicePath: string; /** * Re-open the channel when the current connection is lost. Default `true` — * re-opening is the only thing that recovers a restarted language server, * which binds new ephemeral ports. Turn it off for a frontend that tears * itself down on transport loss instead. */ protected readonly reconnectOnConnectionLoss: boolean; protected readonly disposeEmitter: Emitter; readonly onDispose: Event; protected handle?: ChannelConnectionHandle; /** Set by {@link dispose}, after which {@link connect} rejects. */ protected disposed: boolean; /** How long a connection may take before it is reported as failed; it keeps trying after. */ protected readonly connectFailureNoticeMs: number; protected attempt?: ConnectionAttempt; protected attemptTimer?: ReturnType; /** Set once {@link connectionLifecycle} reports, which then owns the connection failures. */ protected reportsConnections: boolean; /** Reports each connection generation through the {@link ConnectionReporter}. */ readonly connectionLifecycle: RpcConnectionLifecycle; /** * Open the workspace-gated channel and hand back its listening connection. * * Gated because the backend forwarder discovers the head's port by executing * a command the language server answers, and the language server only * launches once there is a workspace to launch it for. Asking earlier polls * a command nobody has registered. * * Rejects once the port is disposed: the consumer reconnects when the * dispose fires {@link onDispose}, and a channel opened then is closed by * nothing. */ connect(): Promise; /** * Surface a transport or write failure as a Theia notification. * * Swallowing it is the failure this exists to prevent: a dead connection and * an empty document are indistinguishable in a widget. * * `reported` is already a complete sentence with the detail interpolated, so * wrapping it in a sentence of the host's own would nest one owner's clause * inside another's and leave no translator in control of the whole. */ reportError(_error: unknown, reported: ResolvedMessage): void; /** End the current attempt through `settle`, or cancel it. */ protected settleAttempt(settle?: (attempt: ConnectionAttempt) => void): void; protected get connectionTarget(): ConnectionTarget; /** One object per port: the reporter keys what it has shown on it. */ protected cachedConnectionTarget?: ConnectionTarget; protected unreachableMessage(): string; protected connectTimeoutMessage(): string; dispose(): void; } //# sourceMappingURL=channel-data-port.d.ts.map