110 lines
3.9 KiB
TypeScript
110 lines
3.9 KiB
TypeScript
// Why: pure compat evaluators shared between desktop tests, renderer runtime
|
|
// switching, and the mobile mirror. All version numbers are passed in to keep
|
|
// the logic dependency-free and easy to duplicate in Expo.
|
|
|
|
export type RuntimeCompatVerdict =
|
|
| {
|
|
kind: 'ok'
|
|
clientProtocolVersion: number
|
|
serverProtocolVersion: number
|
|
}
|
|
| {
|
|
kind: 'blocked'
|
|
reason: 'client-too-old' | 'server-too-old'
|
|
clientProtocolVersion: number
|
|
serverProtocolVersion: number
|
|
requiredClientProtocolVersion?: number
|
|
requiredServerProtocolVersion?: number
|
|
}
|
|
|
|
export function evaluateRuntimeCompat(input: {
|
|
clientProtocolVersion: number
|
|
minCompatibleServerProtocolVersion: number
|
|
serverProtocolVersion: number | undefined
|
|
serverMinCompatibleClientProtocolVersion: number | undefined
|
|
}): RuntimeCompatVerdict {
|
|
// Why: absent fields are protocol 0. New clients can give old servers a
|
|
// clear "update server" error instead of attempting partially-supported RPCs.
|
|
const serverProtocolVersion = input.serverProtocolVersion ?? 0
|
|
const requiredClientProtocolVersion = input.serverMinCompatibleClientProtocolVersion ?? 0
|
|
|
|
if (input.clientProtocolVersion < requiredClientProtocolVersion) {
|
|
return {
|
|
kind: 'blocked',
|
|
reason: 'client-too-old',
|
|
clientProtocolVersion: input.clientProtocolVersion,
|
|
serverProtocolVersion,
|
|
requiredClientProtocolVersion
|
|
}
|
|
}
|
|
if (serverProtocolVersion < input.minCompatibleServerProtocolVersion) {
|
|
return {
|
|
kind: 'blocked',
|
|
reason: 'server-too-old',
|
|
clientProtocolVersion: input.clientProtocolVersion,
|
|
serverProtocolVersion,
|
|
requiredServerProtocolVersion: input.minCompatibleServerProtocolVersion
|
|
}
|
|
}
|
|
return {
|
|
kind: 'ok',
|
|
clientProtocolVersion: input.clientProtocolVersion,
|
|
serverProtocolVersion
|
|
}
|
|
}
|
|
|
|
export function describeRuntimeCompatBlock(verdict: RuntimeCompatVerdict): string {
|
|
if (verdict.kind === 'ok') {
|
|
return 'Runtime client and server are compatible.'
|
|
}
|
|
if (verdict.reason === 'client-too-old') {
|
|
return `This Orca client is too old for the selected server. Update Orca on this machine. Client protocol ${verdict.clientProtocolVersion}, server requires client protocol ${verdict.requiredClientProtocolVersion}.`
|
|
}
|
|
return `The selected Orca server is too old for this client. Update Orca on the server. Server protocol ${verdict.serverProtocolVersion}, client requires server protocol ${verdict.requiredServerProtocolVersion}.`
|
|
}
|
|
|
|
export type CompatVerdict =
|
|
| { kind: 'ok' }
|
|
| {
|
|
kind: 'blocked'
|
|
reason: 'mobile-too-old' | 'desktop-too-old'
|
|
desktopVersion: number
|
|
requiredMobileVersion?: number
|
|
requiredDesktopVersion?: number
|
|
}
|
|
|
|
export function evaluateCompat(input: {
|
|
mobileProtocolVersion: number
|
|
minCompatibleDesktopVersion: number
|
|
desktopProtocolVersion: number | undefined
|
|
desktopMinCompatibleMobileVersion: number | undefined
|
|
}): CompatVerdict {
|
|
// Why: absent fields → 0 lets mobile keep talking to pre-PR desktops.
|
|
// Bumping minCompatibleDesktopVersion above 0 will fence those older
|
|
// desktops alongside any explicitly-version-0 desktop, which is the
|
|
// intended kill-switch behavior.
|
|
const desktopVersion = input.desktopProtocolVersion ?? 0
|
|
const requiredMobile = input.desktopMinCompatibleMobileVersion ?? 0
|
|
|
|
// Why: mobile-too-old precedence — if desktop says "I refuse this
|
|
// mobile build" (kill switch), that wins over any local mobile
|
|
// judgment about desktop's age.
|
|
if (input.mobileProtocolVersion < requiredMobile) {
|
|
return {
|
|
kind: 'blocked',
|
|
reason: 'mobile-too-old',
|
|
desktopVersion,
|
|
requiredMobileVersion: requiredMobile
|
|
}
|
|
}
|
|
if (desktopVersion < input.minCompatibleDesktopVersion) {
|
|
return {
|
|
kind: 'blocked',
|
|
reason: 'desktop-too-old',
|
|
desktopVersion,
|
|
requiredDesktopVersion: input.minCompatibleDesktopVersion
|
|
}
|
|
}
|
|
return { kind: 'ok' }
|
|
}
|