MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / openOAuthSystemBrowser

Function openOAuthSystemBrowser

packages/react/src/api/oauth-popup.ts:257–332  ·  view source on GitHub ↗
(
  input: OpenOAuthSystemBrowserInput<TAuth>,
)

Source from the content-addressed store, hash-verified

255const OAUTH_AWAIT_DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
256
257export const openOAuthSystemBrowser = <TAuth>(
258 input: OpenOAuthSystemBrowserInput<TAuth>,
259): (() => void) => {
260 let settled = false;
261 let pollTimer: ReturnType<typeof setTimeout> | null = null;
262 let timeoutHandle: ReturnType<typeof setTimeout> | null = null;
263 const controller = new AbortController();
264
265 const settle = () => {
266 if (settled) return;
267 settled = true;
268 if (pollTimer !== null) clearTimeout(pollTimer);
269 if (timeoutHandle !== null) clearTimeout(timeoutHandle);
270 controller.abort();
271 };
272
273 const poll = async () => {
274 if (settled) return;
275 // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: fetch can reject for transient network errors during polling
276 try {
277 // The await poll is now gated like the rest of /api — carry the bearer
278 // (standalone web). On desktop the connection has no client-side auth and
279 // the main process injects the header instead.
280 const authorization = getExecutorServerAuthorizationHeader();
281 const response = await fetch(`/api/oauth/await/${encodeURIComponent(input.sessionId)}`, {
282 signal: controller.signal,
283 cache: "no-store",
284 ...(authorization ? { headers: { authorization } } : {}),
285 });
286 if (!response.ok) return;
287 const body = (await response.json()) as unknown;
288 if (body === null || settled) return;
289 if (!isOAuthPopupResult<TAuth>(body)) return;
290 settle();
291 input.onResult(body);
292 } catch {
293 // Transient — next tick will retry. AbortError after settle is also caught here.
294 }
295 };
296
297 void (async () => {
298 // oxlint-disable-next-line executor/no-try-catch-or-throw -- boundary: openExternal is host-provided IPC, no Effect runtime in this browser-only helper
299 try {
300 await input.openExternal(input.url);
301 } catch (cause: unknown) {
302 if (settled) return;
303 settle();
304 input.onOpenFailed?.(cause);
305 }
306 })();
307
308 // Sequential poll loop: one request at a time, reconnecting `pollMs` after
309 // the previous one settles. A long-polling server may hold each request for
310 // many seconds, so a fixed interval would stack overlapping requests.
311 const scheduleReconnect = () => {
312 if (settled) return;
313 pollTimer = setTimeout(() => {
314 pollTimer = null;

Callers 2

useOAuthPopupFlowFunction · 0.90

Calls 2

runPollFunction · 0.85
settleFunction · 0.70

Tested by

no test coverage detected