UNPKG

ob

Version:

OB (The Second Terminal Printer) - A lightweight server-client tool for real-time terminal logging and progress display via Unix sockets. Ideal for CLI apps needing dynamic output management.

108 lines (97 loc) 2.53 kB
#!/usr/bin/env node /* .-. .-') \ ( OO ) .-'),-----. ;-----.\ ( OO' .-. '| .-. | / | | | || '-' /_) \_) | |\| || .-. `. \ | | | || | \ | `' '-' '| '--' / 2025.07.14 `-----' `------' The second terminal printer */ import net from 'net' import fs from 'fs' import os from 'os' import util from 'util' const SOCKET_PATH = os.platform() === 'win32' ? '\\\\.\\pipe\\log-pipe' : '/tmp/log.sock' function styleText(format, text) { const codes = { red: '\x1b[31m', bgBlue: '\x1b[44m', bold: '\x1b[1m', reset: '\x1b[0m', } const styles = Array.isArray(format) ? format : [format] return styles.map((f) => codes[f]).join('') + text + codes.reset } function parseStr(string) { try { const arr = JSON.parse(string) if (!Array.isArray(arr)) { return 'Error: Invalid string.' } return arr } catch (error) { return new Error(error).toString() } } function logger(string) { if (string.startsWith('Error')) { console.log(styleText('red', string)) return } const result = parseStr(string) if (typeof result == 'string') { console.log(styleText('red', result)) return } const args = result.map((item) => util.inspect(item, { depth: null, colors: true, compact: false, }), ) console.log(...args) } function startLogServer() { if (os.platform() !== 'win32') { try { if (fs.existsSync(SOCKET_PATH)) { fs.unlinkSync(SOCKET_PATH) console.log(`Cleaned up existing socket file: ${SOCKET_PATH}`) } } catch (err) { console.error(`Failed to clean up socket file: ${err.message}`) } } const server = net.createServer((socket) => { socket.on('data', (data) => logger(data.toString())) socket.on('end', () => {}) }) server.listen(SOCKET_PATH, () => { console.log(`Log server listening on ${SOCKET_PATH}`) console.log('Press Ctrl+C to stop.') }) server.on('error', (err) => { console.error(`Server error: ${err.message}`) process.exit(1) }) process.on('SIGINT', () => { server.close() if (os.platform() !== 'win32') { try { if (fs.existsSync(SOCKET_PATH)) { fs.unlinkSync(SOCKET_PATH) console.log(`Cleaned up socket file: ${SOCKET_PATH}`) } } catch (err) { console.error(`Failed to clean up socket file on exit: ${err.message}`) } } console.log('Log server stopped.') process.exit() }) } startLogServer()