diff --git a/tools/src/commands/dev/config/commands.ts b/tools/src/commands/dev/config/commands.ts index 5da04102f..5154bf729 100644 --- a/tools/src/commands/dev/config/commands.ts +++ b/tools/src/commands/dev/config/commands.ts @@ -4,6 +4,7 @@ import { PB_BINARY_PATH, PB_DIR, PB_KWARGS, PB_HOST, PB_PORT } from '@/constants import executeCommand from '@/utils/commands' import { checkAddressInUse, checkPortInUse, delay, killExistingProcess } from '@/utils/helpers' import logger from '@/utils/logger' +import chalk from 'chalk' /** * Service command configurations @@ -19,14 +20,14 @@ export const SERVICE_COMMANDS: Record = { command: async () => { if (checkAddressInUse(PB_HOST, PB_PORT)) { logger.error( - `Database address ${PB_HOST}:${PB_PORT} is already in use.` + `Database address ${chalk.blue(`${PB_HOST}:${PB_PORT}`)} is already in use.` ) process.exit(1) } if (!fs.existsSync(PB_BINARY_PATH)) { logger.error( - `PocketBase binary does not exist: ${PB_BINARY_PATH}. Please run "bun forge db init" to initialize the database.` + `PocketBase binary does not exist: ${chalk.blue(PB_BINARY_PATH)}. Please run "bun forge db init" to initialize the database.` ) process.exit(1) } diff --git a/tools/src/utils/commands.ts b/tools/src/utils/commands.ts index d248796c6..b9874d19f 100644 --- a/tools/src/utils/commands.ts +++ b/tools/src/utils/commands.ts @@ -6,6 +6,7 @@ import { ROOT_DIR } from '@/constants/constants' import logger from './logger' import { addDependency, removeDependency } from './packageJson' +import chalk from 'chalk' interface CommandExecutionOptions { stdio?: IOType | [IOType, IOType, IOType] @@ -34,12 +35,12 @@ export default function executeCommand( cmd = typeof command === 'function' ? command() : command } catch (error) { logger.error(`Failed to generate command.`) - logger.debug(`Error details: ${error}`) + logger.debug(`Error details: ${chalk.grey(String(error))}`) process.exit(1) } try { - logger.debug(`Executing: ${cmd}`) + logger.debug(`Executing command ${chalk.blue(cmd)} with arguments: ${chalk.blue(_arguments.length ? _arguments.join(' ') : `${chalk.red('none')}`)}`) const [toBeExecuted, ...args] = cmd.split(' ') @@ -51,11 +52,11 @@ export default function executeCommand( }) if (result.stdout) { - logger.debug(result.stdout.toString()) + logger.debug(chalk.grey(result.stdout.toString())) } if (result.stderr) { - logger.debug(result.stderr.toString()) + logger.debug(chalk.grey(result.stderr.toString())) } if (result.error) { @@ -67,7 +68,7 @@ export default function executeCommand( } if (!options.stdio || options.stdio === 'pipe') { - logger.debug(`Completed: ${cmd}`) + logger.debug(`Command Completed: ${chalk.blue(cmd)}, exit code: ${chalk.blue(String(result.status))}`) } return result.stdout?.toString().trim() || '' @@ -76,8 +77,8 @@ export default function executeCommand( throw error } - logger.error(`Command execution failed: ${cmd}`) - logger.debug(`Error details: ${error}`) + logger.error(`Command execution failed: ${chalk.blue(cmd)}`) + logger.debug(`Error details: ${chalk.grey(String(error))}`) process.exit(1) } } @@ -111,7 +112,7 @@ export function installPackage( fs.rmSync(targetDir, { recursive: true, force: true }) } - logger.debug(`Installing ${fullName} from registry...`) + logger.debug(`Installing ${chalk.blue(fullName)} from registry...`) executeCommand(`bun add ${fullName}@latest --ignore-scripts`, { cwd: ROOT_DIR @@ -120,12 +121,11 @@ export function installPackage( const installedPath = path.join(ROOT_DIR, 'node_modules', fullName) if (!fs.existsSync(installedPath)) { - logger.error(`Failed to find installed package at ${installedPath}`) + logger.error(`Failed to find installed package at ${chalk.blue(installedPath)}`) process.exit(1) } - logger.debug(`Copying ${fullName} to ${targetDir}...`) - + logger.debug(`Copying ${chalk.blue(fullName)} to ${chalk.blue(targetDir)}...`) fs.cpSync(installedPath, targetDir, { recursive: true, dereference: true }) // Add to target package.json (apps or locales) diff --git a/tools/src/utils/helpers.ts b/tools/src/utils/helpers.ts index a7d52bebe..1404ada1f 100644 --- a/tools/src/utils/helpers.ts +++ b/tools/src/utils/helpers.ts @@ -1,3 +1,4 @@ +import chalk from 'chalk' import prompts from 'prompts' import executeCommand from './commands' @@ -60,7 +61,7 @@ export function getEnvVar(varName: string, fallback?: string): string { return fallback } - logger.error(`Missing required environment variable: ${varName}`) + logger.error(`Missing required environment variable: ${chalk.red(varName)}`) process.exit(1) } @@ -77,7 +78,9 @@ export function killExistingProcess( if (typeof processKeywordOrPID === 'number') { process.kill(processKeywordOrPID) - logger.debug(`Killed process with PID: ${String(processKeywordOrPID)}`) + logger.debug( + `Killed process with PID: ${chalk.blue(String(processKeywordOrPID))}` + ) return } @@ -92,7 +95,7 @@ export function killExistingProcess( }) logger.debug( - `Killed process matching keyword: ${processKeywordOrPID} (PID: ${serverInstance})` + `Killed process matching keyword: ${chalk.blue(processKeywordOrPID)} (PID: ${chalk.blue(serverInstance)})` ) return parseInt(serverInstance, 10) @@ -129,19 +132,51 @@ export function checkPortInUse(port: number): boolean { * @returns True if the port is in use, false otherwise */ export function checkAddressInUse(address: string, port: string): boolean { - logger.debug(`Checking if address ${address}:${port} is in use...`); + logger.debug( + `Checking if address ${chalk.blue(address)}:${chalk.blue(port)} is in use...` + ) - try { - executeCommand('nc', { exitOnError: false }, [ - '-zv', - address, - port, - ]); + try { + executeCommand('nc', { exitOnError: false }, ['-zv', address, port]) - return true; - } catch { - return false; - } + const ssOutput = executeCommand('ss', { exitOnError: false }, [ + '-tlnp', + 'src', + `${address}:${port}` + ]) + + const lines = ssOutput.trim().split('\n') + + if (lines.length > 1) { + const processLine = lines[1] + + const processMatch = processLine.match( + /users:\(\("([^"]+)",pid=(\d+),fd=\d+\)\)/ + ) + + if (processMatch) { + const processName = processMatch[1] + + const pid = processMatch[2] + + logger.error( + `Address ${chalk.blue(address)}:${chalk.blue(port)} is in use by process: ${chalk.blue(processName)} (PID: ${chalk.blue(pid)})` + ) + } else { + logger.error( + `Address ${chalk.blue(address)}:${chalk.blue(port)} is in use, but could not parse process info.` + ) + } + } else { + logger.error( + `Address ${chalk.blue(address)}:${chalk.blue(port)} is in use, but no process info found.` + ) + } + + return true + } catch { + return false + } } /**