From dd194be60cba3f32319e2162604c35a4bdec7409 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 7 Dec 2024 14:24:32 +0100 Subject: [PATCH] chore: adjust sudo handling chore: wip --- bin/cli.ts | 1 - reverse-proxy.config.ts | 8 +- src/hosts.ts | 165 ++++++++++++++-------------------------- src/https.ts | 2 - 4 files changed, 62 insertions(+), 114 deletions(-) diff --git a/bin/cli.ts b/bin/cli.ts index 7b661d1..0ffd2f0 100644 --- a/bin/cli.ts +++ b/bin/cli.ts @@ -31,7 +31,6 @@ cli .example('reverse-proxy start --from localhost:5173 --to my-project.test --key-path /absolute/path/to/key --cert-path /absolute/path/to/cert') .action(async (options?: ReverseProxyOption) => { if (!options?.from || !options.to) { - console.log('in here', config) return startProxies(config) } diff --git a/reverse-proxy.config.ts b/reverse-proxy.config.ts index 579101a..7bc7999 100644 --- a/reverse-proxy.config.ts +++ b/reverse-proxy.config.ts @@ -12,12 +12,12 @@ const config: ReverseProxyOptions = { proxies: [ { from: 'localhost:5173', - to: 'test.localhost', - }, - { - from: 'localhost:5174', to: 'test.local', }, + // { + // from: 'localhost:5174', + // to: 'test.local', + // }, ], verbose: false, } diff --git a/src/hosts.ts b/src/hosts.ts index 0b70359..1a16c02 100644 --- a/src/hosts.ts +++ b/src/hosts.ts @@ -1,62 +1,29 @@ -import { spawn } from 'node:child_process' +import { exec, spawn } from 'node:child_process' import fs from 'node:fs' import os from 'node:os' import path from 'node:path' import process from 'node:process' +import { promisify } from 'node:util' import { log } from '@stacksjs/cli' import { debugLog } from './utils' +const execAsync = promisify(exec) + export const hostsFilePath: string = process.platform === 'win32' ? path.join(process.env.windir || 'C:\\Windows', 'System32', 'drivers', 'etc', 'hosts') : '/etc/hosts' -async function sudoWrite(operation: 'append' | 'write', content: string): Promise { - return new Promise((resolve, reject) => { - if (process.platform === 'win32') { - reject(new Error('Administrator privileges required on Windows')) - return - } - - const tmpFile = path.join(os.tmpdir(), 'hosts.tmp') +// Single function to execute sudo commands +async function execSudo(command: string): Promise { + if (process.platform === 'win32') + throw new Error('Administrator privileges required on Windows') - try { - if (operation === 'append') { - // For append, read current content first - const currentContent = fs.readFileSync(hostsFilePath, 'utf8') - fs.writeFileSync(tmpFile, currentContent + content, 'utf8') - } - else { - // For write, just write the new content - fs.writeFileSync(tmpFile, content, 'utf8') - } - - const sudo = spawn('sudo', ['cp', tmpFile, hostsFilePath]) - - sudo.on('close', (code) => { - try { - fs.unlinkSync(tmpFile) - if (code === 0) - resolve() - else - reject(new Error(`sudo process exited with code ${code}`)) - } - catch (err) { - reject(err) - } - }) - - sudo.on('error', (err) => { - try { - fs.unlinkSync(tmpFile) - } - catch { } - reject(err) - }) - } - catch (err) { - reject(err) - } - }) + try { + await execAsync(`sudo ${command}`) + } + catch (error) { + throw new Error(`Failed to execute sudo command: ${(error as Error).message}`) + } } export async function addHosts(hosts: string[], verbose?: boolean): Promise { @@ -85,40 +52,32 @@ export async function addHosts(hosts: string[], verbose?: boolean): Promise log.warn(entry)) - - if (process.platform === 'win32') { - log.warn('\nOn Windows:') - log.warn('1. Run notepad as administrator') - log.warn('2. Open C:\\Windows\\System32\\drivers\\etc\\hosts') - } - else { - log.warn('\nOn Unix systems:') - log.warn(`sudo nano ${hostsFilePath}`) - } - - throw new Error('Failed to modify hosts file: manual intervention required') - } + catch (error) { + log.error('Failed to modify hosts file automatically') + log.warn('Please add these entries to your hosts file manually:') + hostEntries.split('\n').forEach(entry => log.warn(entry)) + + if (process.platform === 'win32') { + log.warn('\nOn Windows:') + log.warn('1. Run notepad as administrator') + log.warn('2. Open C:\\Windows\\System32\\drivers\\etc\\hosts') } else { - throw writeErr + log.warn('\nOn Unix systems:') + log.warn(`sudo nano ${hostsFilePath}`) } + + throw new Error('Failed to modify hosts file: manual intervention required') + } + finally { + fs.unlinkSync(tmpFile) } } catch (err) { @@ -153,43 +112,36 @@ export async function removeHosts(hosts: string[], verbose?: boolean): Promise { - log.warn('# Added by rpx') - log.warn(`127.0.0.1 ${host}`) - log.warn(`::1 ${host}`) - }) - - if (process.platform === 'win32') { - log.warn('\nOn Windows:') - log.warn('1. Run notepad as administrator') - log.warn('2. Open C:\\Windows\\System32\\drivers\\etc\\hosts') - } - else { - log.warn('\nOn Unix systems:') - log.warn(`sudo nano ${hostsFilePath}`) - } - - throw new Error('Failed to modify hosts file: manual intervention required') - } + catch (error) { + log.error('Failed to modify hosts file automatically') + log.warn('Please remove these entries from your hosts file manually:') + hosts.forEach((host) => { + log.warn('# Added by rpx') + log.warn(`127.0.0.1 ${host}`) + log.warn(`::1 ${host}`) + }) + + if (process.platform === 'win32') { + log.warn('\nOn Windows:') + log.warn('1. Run notepad as administrator') + log.warn('2. Open C:\\Windows\\System32\\drivers\\etc\\hosts') } else { - throw writeErr + log.warn('\nOn Unix systems:') + log.warn(`sudo nano ${hostsFilePath}`) } + + throw new Error('Failed to modify hosts file: manual intervention required') + } + finally { + fs.unlinkSync(tmpFile) } } catch (err) { @@ -199,7 +151,6 @@ export async function removeHosts(hosts: string[], verbose?: boolean): Promise { debugLog('hosts', `Checking hosts: ${hosts}`, verbose) diff --git a/src/https.ts b/src/https.ts index f301256..36d16f1 100644 --- a/src/https.ts +++ b/src/https.ts @@ -194,8 +194,6 @@ export async function generateCertificate(options: ReverseProxyOptions): Promise // Generate the host certificate with all domains const hostConfig = httpsConfig(options, options.verbose) - // eslint-disable-next-line no-console - console.log('hostConfig', hostConfig) log.info(`Generating host certificate for: ${domains.join(', ')}`) const hostCert = await generateCert({