MCPcopy Create free account
hub / github.com/heygen-com/hyperframes / startLoopback

Function startLoopback

packages/cli/src/auth/loopback.ts:50–99  ·  view source on GitHub ↗
(opts: LoopbackOptions)

Source from the content-addressed store, hash-verified

48const DEFAULT_TIMEOUT_MS = 120_000;
49
50export async function startLoopback(opts: LoopbackOptions): Promise<LoopbackHandle> {
51 const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
52
53 let resolveResult!: (value: LoopbackResult) => void;
54 let rejectResult!: (err: Error) => void;
55 const result = new Promise<LoopbackResult>((resolve, reject) => {
56 resolveResult = resolve;
57 rejectResult = reject;
58 });
59
60 // redirectUri is the value the IdP sees on /authorize. RFC 6749 §4.1.3
61 // requires the token exchange's redirect_uri to be byte-identical to
62 // it, so we capture this string once and reuse it on both hops — never
63 // reconstructing from req.socket.localAddress later (which can drift
64 // on dual-stack hosts).
65 let redirectUri = "";
66
67 const server = createServer((req, res) =>
68 handleRequest(req, res, opts.state, redirectUri, resolveResult, rejectResult),
69 );
70
71 await listen(server, opts.port ?? 0);
72 const address = server.address() as AddressInfo;
73 redirectUri = `http://127.0.0.1:${address.port}${CALLBACK_PATH}`;
74
75 let closed = false;
76 const close = async (): Promise<void> => {
77 if (closed) return;
78 closed = true;
79 clearTimeout(timer);
80 // `server.close()` only refuses NEW connections — it does NOT
81 // terminate existing keep-alive sockets, which browsers default to
82 // and idle for minutes (Chrome ~5min). Without `closeAllConnections`
83 // the CLI process hangs after "Signed in" until the browser closes
84 // its idle socket. `respond()` also emits `Connection: close` so the
85 // browser doesn't try to keep-alive in the first place.
86 server.closeAllConnections?.();
87 await new Promise<void>((resolve) => server.close(() => resolve()));
88 };
89
90 const timer = setTimeout(() => {
91 rejectResult(new Error(`OAuth callback timed out after ${timeoutMs}ms`));
92 void close();
93 }, timeoutMs);
94
95 // When result settles, drain the timer + shutdown.
96 result.finally(close).catch(() => {});
97
98 return { result, redirectUri, close };
99}
100
101async function listen(server: Server, port: number): Promise<void> {
102 await new Promise<void>((resolve, reject) => {

Callers 3

loopback.test.tsFile · 0.85
expectRejectionFunction · 0.85

Calls 3

handleRequestFunction · 0.85
listenFunction · 0.85
closeFunction · 0.70

Tested by 1

expectRejectionFunction · 0.68