(opts?: { host?: string })
| 65 | } |
| 66 | |
| 67 | export async function startCallbackServer(opts?: { host?: string }): Promise<CallbackServerHandle> { |
| 68 | const host = opts?.host ?? '127.0.0.1'; |
| 69 | const received: CallbackRecord[] = []; |
| 70 | type Listener = { |
| 71 | predicate: (record: CallbackRecord) => boolean; |
| 72 | resolve: (record: CallbackRecord | null) => void; |
| 73 | }; |
| 74 | const listeners: Listener[] = []; |
| 75 | |
| 76 | const server: Server = createServer((req, res) => { |
| 77 | readBody(req) |
| 78 | .then(raw => { |
| 79 | const contentType = req.headers['content-type'] ?? ''; |
| 80 | let body: unknown = raw; |
| 81 | if (contentType.includes('application/json') && raw.length > 0) { |
| 82 | try { |
| 83 | body = JSON.parse(raw); |
| 84 | } catch { |
| 85 | // Keep raw body on parse failure — the driver may still want to inspect. |
| 86 | } |
| 87 | } |
| 88 | const record: CallbackRecord = { |
| 89 | method: req.method ?? 'GET', |
| 90 | path: req.url ?? '/', |
| 91 | headers: headersToObject(req.headers), |
| 92 | body, |
| 93 | receivedAt: Date.now(), |
| 94 | }; |
| 95 | received.push(record); |
| 96 | |
| 97 | res.writeHead(200, { 'Content-Type': 'application/json' }); |
| 98 | res.end('{"ok":true}'); |
| 99 | |
| 100 | for (let i = listeners.length - 1; i >= 0; i--) { |
| 101 | const listener = listeners[i]; |
| 102 | if (listener && listener.predicate(record)) { |
| 103 | listener.resolve(record); |
| 104 | listeners.splice(i, 1); |
| 105 | } |
| 106 | } |
| 107 | }) |
| 108 | .catch(err => { |
| 109 | console.error('callback-server read error:', err); |
| 110 | res.writeHead(500); |
| 111 | res.end(); |
| 112 | }); |
| 113 | }); |
| 114 | |
| 115 | await new Promise<void>((resolve, reject) => { |
| 116 | server.once('error', reject); |
| 117 | server.listen(0, host, () => resolve()); |
| 118 | }); |
| 119 | |
| 120 | const address = server.address() as AddressInfo; |
| 121 | const port = address.port; |
| 122 | const url = `http://${host}:${port}`; |
| 123 | const callbackUrl = `${url}/callback`; |
| 124 |
no test coverage detected