(line: string)
| 151 | } |
| 152 | |
| 153 | async function handleLine(line: string): Promise<void> { |
| 154 | if (closed) return; |
| 155 | const trimmed = line.trim(); |
| 156 | if (trimmed.length === 0) return; |
| 157 | |
| 158 | let msg: JsonRpcRequest | null = null; |
| 159 | try { |
| 160 | msg = JSON.parse(trimmed) as JsonRpcRequest; |
| 161 | } catch (err) { |
| 162 | writeLine( |
| 163 | errorResponse(null, JSONRPC_PARSE_ERROR, "invalid JSON", { |
| 164 | text: err instanceof Error ? err.message : String(err), |
| 165 | }), |
| 166 | ); |
| 167 | return; |
| 168 | } |
| 169 | |
| 170 | // Reverse-direction response: the client is replying to a request |
| 171 | // we previously sent via `serverRequest`. Match by `srv-` ID and |
| 172 | // resolve / reject the matching pending promise. |
| 173 | const raw = msg as unknown as Record<string, unknown>; |
| 174 | if ( |
| 175 | raw && |
| 176 | typeof raw === "object" && |
| 177 | typeof raw.id === "string" && |
| 178 | (raw.id as string).startsWith("srv-") && |
| 179 | (raw.result !== undefined || raw.error !== undefined) |
| 180 | ) { |
| 181 | const id = raw.id as string; |
| 182 | const pending = serverPending.get(id); |
| 183 | if (pending) { |
| 184 | serverPending.delete(id); |
| 185 | if (pending.timer) clearTimeout(pending.timer); |
| 186 | if (raw.error != null) { |
| 187 | pending.reject(raw.error); |
| 188 | } else { |
| 189 | pending.resolve(raw.result); |
| 190 | } |
| 191 | } |
| 192 | return; |
| 193 | } |
| 194 | |
| 195 | if (!msg || typeof msg !== "object" || msg.jsonrpc !== "2.0" || !msg.method) { |
| 196 | writeLine(errorResponse(msg?.id ?? null, JSONRPC_INVALID_REQUEST, "not JSON-RPC 2.0")); |
| 197 | return; |
| 198 | } |
| 199 | |
| 200 | try { |
| 201 | const result = await dispatch(msg.method, msg.params); |
| 202 | if (msg.id !== undefined && msg.id !== null) { |
| 203 | const ok: JsonRpcSuccess = { |
| 204 | jsonrpc: "2.0", |
| 205 | id: msg.id, |
| 206 | result, |
| 207 | }; |
| 208 | writeLine(ok); |
| 209 | } |
| 210 | } catch (err) { |
no test coverage detected