import type { AtomId, Binding, Conformance, InterfaceRevisionId, OperationBinding, OperationId, WorkspaceRevision, } from "./types.js"; export type ConcreteBinding = Exclude; export type ResolvedBinding = { conformance: Conformance; entry: OperationBinding; binding: ConcreteBinding }; /** Follow public operations on the same receiver, never private attachment names. */ export function resolveForwardedBinding( workspace: Pick, atomId: AtomId, interfaceRevisionId: InterfaceRevisionId, operationId: OperationId, ): ResolvedBinding { const visited = new Set(); for (;;) { const key = `${interfaceRevisionId}\0${operationId}`; if (visited.has(key)) throw new Error(`Forwarding cycle at ${interfaceRevisionId}/${operationId}`); visited.add(key); const conformance = workspace.conformances.find( (c) => c.atomId === atomId && c.interfaceRevisionId === interfaceRevisionId, ); const entry = conformance?.operationBindings.find((b) => b.operationId === operationId); if (!conformance || !entry) throw new Error(`Missing forwarding target ${atomId} as ${interfaceRevisionId}/${operationId}`); if (entry.binding.kind !== "interface") return { conformance, entry, binding: entry.binding }; interfaceRevisionId = entry.binding.interfaceRevisionId; operationId = entry.binding.operationId; } }