import Logger from 'electron-log' import EventEmitter from 'events' import http from 'http' import { URL } from 'url' import { OAuthCallbackServerOptions } from './types' export class CallBackServer { private server: Promise private events: EventEmitter constructor(options: OAuthCallbackServerOptions) { const { port, path, events } = options this.events = events this.server = this.initialize(port, path) } initialize(port: number, path: string): Promise { const server = http.createServer((req, res) => { // Only handle requests to the callback path if (req.url?.startsWith(path)) { try { // Parse the URL to extract the authorization code const url = new URL(req.url, `http://localhost:${port}`) const code = url.searchParams.get('code') if (code) { // Emit the code event this.events.emit('auth-code-received', code) } } catch (error) { Logger.error('Error processing OAuth callback:', error) res.writeHead(500, { 'Content-Type': 'text/plain' }) res.end('Internal Server Error') } } else { // Not a callback request res.writeHead(404, { 'Content-Type': 'text/plain' }) res.end('Not Found') } }) // Handle server errors server.on('error', (error) => { Logger.error('OAuth callback server error:', error) }) const runningServer = new Promise((resolve, reject) => { server.listen(port, () => { Logger.info(`OAuth callback server listening on port ${port}`) resolve(server) }) server.on('error', (error) => { reject(error) }) }) return runningServer } get getServer(): Promise { return this.server } async close() { const server = await this.server server.close() } async waitForAuthCode(): Promise { return new Promise((resolve) => { this.events.once('auth-code-received', (code) => { resolve(code) }) }) } }