| 321 | } |
| 322 | |
| 323 | export function getAvailablePort(): Promise<number> { |
| 324 | return new Promise((resolve, reject) => { |
| 325 | let port = 0; |
| 326 | try { |
| 327 | const portStr = process.env['OAUTH_CALLBACK_PORT']; |
| 328 | if (portStr) { |
| 329 | port = parseInt(portStr, 10); |
| 330 | if (isNaN(port) || port <= 0 || port > 65535) { |
| 331 | return reject( |
| 332 | new Error(`Invalid value for OAUTH_CALLBACK_PORT: "${portStr}"`), |
| 333 | ); |
| 334 | } |
| 335 | return resolve(port); |
| 336 | } |
| 337 | const server = net.createServer(); |
| 338 | server.listen(0, () => { |
| 339 | const address = server.address()! as net.AddressInfo; |
| 340 | port = address.port; |
| 341 | }); |
| 342 | server.on('listening', () => { |
| 343 | server.close(); |
| 344 | server.unref(); |
| 345 | }); |
| 346 | server.on('error', (e) => reject(e)); |
| 347 | server.on('close', () => resolve(port)); |
| 348 | } catch (e) { |
| 349 | reject(e); |
| 350 | } |
| 351 | }); |
| 352 | } |
| 353 | |
| 354 | async function loadCachedCredentials(client: OAuth2Client): Promise<boolean> { |
| 355 | const pathsToTry = [ |