1import {
2 ORCHESTRATION_PROTOCOL_QUERY_PARAM,
3 ORCHESTRATION_PROTOCOL_VERSION,
4 type ExecutionEnvironmentDescriptor,
5} from "@t3tools/contracts";
6
7import { ConnectionBlockedError } from "./model.ts";
8
9export function orchestrationProtocolCompatibilityError(
10 descriptor: ExecutionEnvironmentDescriptor,
11): ConnectionBlockedError | null {
12 // Servers shipped before negotiation use the original wire protocol.
13 const serverProtocolVersion = descriptor.orchestrationProtocolVersion ?? 1;
14 if (serverProtocolVersion === ORCHESTRATION_PROTOCOL_VERSION) {
15 return null;
16 }
17 return serverProtocolVersion > ORCHESTRATION_PROTOCOL_VERSION
18 ? new ConnectionBlockedError({
19 reason: "unsupported",
20 detail: `This client is not supported by this server. Update your app or use a compatible release to connect to ${descriptor.label}.`,
21 })
22 : new ConnectionBlockedError({
23 reason: "unsupported",
24 detail: `This client requires a newer server. Update the server on ${descriptor.label} to connect.`,
25 ...(canSelfUpdate(descriptor) ? { serverUpdateRequired: true } : {}),
26 });
27}
28
29/** Whether this client can drive the host's update remotely. */
30function canSelfUpdate(descriptor: ExecutionEnvironmentDescriptor): boolean {
31 const { serverSelfUpdate, desktopAppUpdate } = descriptor.capabilities;
32 return (
33 serverSelfUpdate !== undefined &&
34 (serverSelfUpdate !== "desktop-managed" || desktopAppUpdate === true)
35 );
36}
37
38export function appendOrchestrationProtocol(socketUrl: string): string {
39 const url = new URL(socketUrl);
40 url.searchParams.set(ORCHESTRATION_PROTOCOL_QUERY_PARAM, String(ORCHESTRATION_PROTOCOL_VERSION));
41 return url.toString();
42}