UNPKG

node-system-bridge

Version:

A cross-platform system automation library for Node.js and Electron, written in Rust

255 lines (182 loc) 6.4 kB
# Node System Bridge [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) > A cross‑platform system bridge written in Rust, exposing mouse, keyboard, process, window, clipboard and system‑info capabilities to Node.js / Electron apps. ## ✨ Features - 🚀 **Process control**: launch apps, check status, kill processes, list processes - 🖱️ **Mouse control**: click, move, smooth move, scroll, drag - ⌨️ **Keyboard input**: type text, special keys, human‑like typing - 🪟 **Window control**: bring window to front by process id - 📋 **Clipboard**: read / write / clear system clipboard - 💻 **System info**: fast hardware / OS / network information - 🌐 **Cross‑platform API**: macOS & Windows today, Linux planned - 📦 **Prebuilt binaries**: no Rust toolchain required for consumers - 🎯 **ESM & CommonJS**: works in modern Electron and classic Node ## 📦 Installation ```bash npm install node-system-bridge ``` Prebuilt native binaries are shipped for **macOS (Intel & Apple Silicon)** and **Windows x64**. Linux support is planned. ## 🚀 Quick Start ### ESM (recommended, Electron 28+) ```javascript // main.mjs / Electron main (ESM) import { Process } from 'node-system-bridge' // Use the real executable path, not just the .app bundle const calcPath = '/System/Applications/Calculator.app/Contents/MacOS/Calculator' const pid = await Process.launchApp(calcPath) console.log('Calculator PID:', pid) const isRunning = await Process.isRunning(pid) console.log('Is running:', isRunning) await Process.killProcess(pid) ``` ### CommonJS ```javascript // main.cjs const { Process } = require('node-system-bridge') const chromePath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' Process.launchApp(chromePath, ['https://github.com']) .then(pid => { console.log('Chrome PID:', pid) }) ``` ### Path notes (important) Always pass an **executable path**, not just a bundle/folder: ```javascript // macOS await Process.launchApp('/Applications/Safari.app/Contents/MacOS/Safari') // Windows await Process.launchApp('C:\\Program Files\\MyApp\\app.exe') // Linux await Process.launchApp('/usr/bin/firefox') ``` ### Using with Electron & asar (important) When you package your Electron app with `asar`, native `.node` binaries must be **unpacked**, otherwise they cannot be loaded at runtime. This library already detects Electron and will **prefer loading from `app.asar.unpacked`** when it sees a path like: ```text .../resources/app.asar/node_modules/node-system-bridge/... ``` It will automatically try: ```text .../resources/app.asar.unpacked/node_modules/node-system-bridge/node-system-bridge.<platform>.node ``` So in your packager config (for example `electron-builder`), make sure `node-system-bridge` is unpacked: ```json { "build": { "asarUnpack": [ "node_modules/node-system-bridge/**" ] } } ``` After that, you can simply import in Electron main / preload: ```javascript // ESM import { System } from 'node-system-bridge' // or CommonJS const { System } = require('node-system-bridge') ``` ## 🛠️ Modules & API Overview ### Process ```typescript // Start an app Process.launchApp(appPath: string, args?: string[]): Promise<number> // Kill a process Process.killProcess(pid: number): Promise<void> // Check if a process is running Process.isRunning(pid: number): Promise<boolean> // Get all processes Process.getAllProcesses(): Promise<ProcessInfo[]> interface ProcessInfo { pid: number name: string cpuUsage: number memory: number parentPid?: number cmd: string[] exe?: string cwd?: string } ``` ```javascript // Launch Chrome and filter all Chrome processes const pid = await Process.launchApp( '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', ['--new-window', 'https://github.com'] ) const all = await Process.getAllProcesses() const chromeProcesses = all.filter(p => p.name.toLowerCase().includes('chrome') ) ``` ### Mouse ```javascript import { Mouse } from 'node-system-bridge' // Simple click Mouse.click(100, 200) // Smooth move & scroll Mouse.moveToSmooth(500, 300) Mouse.scroll(-5) ``` ### Keyboard & Clipboard ```javascript import { Keyboard, Clipboard } from 'node-system-bridge' // Human‑like typing Keyboard.typeText('Hello World') // Type from clipboard Clipboard.writeText('From clipboard') Keyboard.typeFromClipboard('fast') // Special key Keyboard.pressKey('enter') ``` ### Window ```typescript // Bring the main window of a process to front (non‑always‑on‑top) Window.bringToFront(pid: number): Promise<void> ``` ```javascript import { Process, Window } from 'node-system-bridge' const chromePath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' const pid = await Process.launchApp(chromePath) // wait for window creation await new Promise(r => setTimeout(r, 2000)) await Window.bringToFront(pid) ``` ### System info ```typescript System.getSystemInfo(): Promise<SystemInfo> ``` ```javascript import { System } from 'node-system-bridge' const info = await System.getSystemInfo() console.log({ hostname: info.hostname, platform: info.platform, // "win32" | "darwin" | "linux" arch: info.arch, // "x64" | "arm64" manufacturer: info.manufacturer, model: info.model, cpuBrand: info.cpuBrand, macs: info.macs, source: info.source // "wmi" | "wmic" | "basic" | ... }) ``` ## 🌍 Platform Support | Platform | Arch | Min Version | Status | |---------|------|------------|------------| | macOS | x64 | 10.13+ | ✅ Supported | | macOS | ARM64 | 11.0+ | ✅ Supported | | Windows | x64 | 10+ | ✅ Supported | | Linux | x64 | 3.10+ | 🚧 Planned | Current npm package ships **macOS + Windows** prebuilt binaries. Linux will be added in future releases. ## 📋 Requirements - **Node.js**: 16.0.0+ - **Electron**: 12.0.0+ (25+ recommended) - **OS**: - Windows 10+ - macOS 10.13+ - Linux (X11, planned) ## 📄 License MIT License — see `LICENSE`. --- Made with ❤️ using Rust and Node.js.