feat: 초기 프로젝트 설정 및 룰.md 파일 추가
This commit is contained in:
20
api.hyungi.net/node_modules/systeminformation/LICENSE
generated
vendored
Normal file
20
api.hyungi.net/node_modules/systeminformation/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2025 Sebastian Hildebrandt
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
1199
api.hyungi.net/node_modules/systeminformation/README.md
generated
vendored
Normal file
1199
api.hyungi.net/node_modules/systeminformation/README.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
222
api.hyungi.net/node_modules/systeminformation/lib/audio.js
generated
vendored
Normal file
222
api.hyungi.net/node_modules/systeminformation/lib/audio.js
generated
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// audio.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 16. audio
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const exec = require('child_process').exec;
|
||||
const execSync = require('child_process').execSync;
|
||||
const util = require('./util');
|
||||
|
||||
let _platform = process.platform;
|
||||
|
||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
||||
const _darwin = (_platform === 'darwin');
|
||||
const _windows = (_platform === 'win32');
|
||||
const _freebsd = (_platform === 'freebsd');
|
||||
const _openbsd = (_platform === 'openbsd');
|
||||
const _netbsd = (_platform === 'netbsd');
|
||||
const _sunos = (_platform === 'sunos');
|
||||
|
||||
function parseAudioType(str, input, output) {
|
||||
str = str.toLowerCase();
|
||||
let result = '';
|
||||
|
||||
if (str.indexOf('input') >= 0) { result = 'Microphone'; }
|
||||
if (str.indexOf('display audio') >= 0) { result = 'Speaker'; }
|
||||
if (str.indexOf('speak') >= 0) { result = 'Speaker'; }
|
||||
if (str.indexOf('laut') >= 0) { result = 'Speaker'; }
|
||||
if (str.indexOf('loud') >= 0) { result = 'Speaker'; }
|
||||
if (str.indexOf('head') >= 0) { result = 'Headset'; }
|
||||
if (str.indexOf('mic') >= 0) { result = 'Microphone'; }
|
||||
if (str.indexOf('mikr') >= 0) { result = 'Microphone'; }
|
||||
if (str.indexOf('phone') >= 0) { result = 'Phone'; }
|
||||
if (str.indexOf('controll') >= 0) { result = 'Controller'; }
|
||||
if (str.indexOf('line o') >= 0) { result = 'Line Out'; }
|
||||
if (str.indexOf('digital o') >= 0) { result = 'Digital Out'; }
|
||||
if (str.indexOf('smart sound technology') >= 0) { result = 'Digital Signal Processor'; }
|
||||
if (str.indexOf('high definition audio') >= 0) { result = 'Sound Driver'; }
|
||||
|
||||
if (!result && output) {
|
||||
result = 'Speaker';
|
||||
} else if (!result && input) {
|
||||
result = 'Microphone';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function getLinuxAudioPci() {
|
||||
let cmd = 'lspci -v 2>/dev/null';
|
||||
let result = [];
|
||||
try {
|
||||
const parts = execSync(cmd, util.execOptsLinux).toString().split('\n\n');
|
||||
parts.forEach(element => {
|
||||
const lines = element.split('\n');
|
||||
if (lines && lines.length && lines[0].toLowerCase().indexOf('audio') >= 0) {
|
||||
const audio = {};
|
||||
audio.slotId = lines[0].split(' ')[0];
|
||||
audio.driver = util.getValue(lines, 'Kernel driver in use', ':', true) || util.getValue(lines, 'Kernel modules', ':', true);
|
||||
result.push(audio);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
} catch (e) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function parseLinuxAudioPciMM(lines, audioPCI) {
|
||||
const result = {};
|
||||
const slotId = util.getValue(lines, 'Slot');
|
||||
|
||||
const pciMatch = audioPCI.filter(function (item) { return item.slotId === slotId; });
|
||||
|
||||
result.id = slotId;
|
||||
result.name = util.getValue(lines, 'SDevice');
|
||||
result.manufacturer = util.getValue(lines, 'SVendor');
|
||||
result.revision = util.getValue(lines, 'Rev');
|
||||
result.driver = pciMatch && pciMatch.length === 1 && pciMatch[0].driver ? pciMatch[0].driver : '';
|
||||
result.default = null;
|
||||
result.channel = 'PCIe';
|
||||
result.type = parseAudioType(result.name, null, null);
|
||||
result.in = null;
|
||||
result.out = null;
|
||||
result.status = 'online';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseDarwinChannel(str) {
|
||||
let result = '';
|
||||
|
||||
if (str.indexOf('builtin') >= 0) { result = 'Built-In'; }
|
||||
if (str.indexOf('extern') >= 0) { result = 'Audio-Jack'; }
|
||||
if (str.indexOf('hdmi') >= 0) { result = 'HDMI'; }
|
||||
if (str.indexOf('displayport') >= 0) { result = 'Display-Port'; }
|
||||
if (str.indexOf('usb') >= 0) { result = 'USB'; }
|
||||
if (str.indexOf('pci') >= 0) { result = 'PCIe'; }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseDarwinAudio(audioObject, id) {
|
||||
const result = {};
|
||||
const channelStr = ((audioObject.coreaudio_device_transport || '') + ' ' + (audioObject._name || '')).toLowerCase();
|
||||
|
||||
result.id = id;
|
||||
result.name = audioObject._name;
|
||||
result.manufacturer = audioObject.coreaudio_device_manufacturer;
|
||||
result.revision = null;
|
||||
result.driver = null;
|
||||
result.default = !!(audioObject.coreaudio_default_audio_input_device || '') || !!(audioObject.coreaudio_default_audio_output_device || '');
|
||||
result.channel = parseDarwinChannel(channelStr);
|
||||
result.type = parseAudioType(result.name, !!(audioObject.coreaudio_device_input || ''), !!(audioObject.coreaudio_device_output || ''));
|
||||
result.in = !!(audioObject.coreaudio_device_input || '');
|
||||
result.out = !!(audioObject.coreaudio_device_output || '');
|
||||
result.status = 'online';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseWindowsAudio(lines) {
|
||||
const result = {};
|
||||
const status = util.getValue(lines, 'StatusInfo', ':');
|
||||
|
||||
result.id = util.getValue(lines, 'DeviceID', ':'); // PNPDeviceID??
|
||||
result.name = util.getValue(lines, 'name', ':');
|
||||
result.manufacturer = util.getValue(lines, 'manufacturer', ':');
|
||||
result.revision = null;
|
||||
result.driver = null;
|
||||
result.default = null;
|
||||
result.channel = null;
|
||||
result.type = parseAudioType(result.name, null, null);
|
||||
result.in = null;
|
||||
result.out = null;
|
||||
result.status = status;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function audio(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
let result = [];
|
||||
if (_linux || _freebsd || _openbsd || _netbsd) {
|
||||
let cmd = 'lspci -vmm 2>/dev/null';
|
||||
exec(cmd, function (error, stdout) {
|
||||
// PCI
|
||||
if (!error) {
|
||||
const audioPCI = getLinuxAudioPci();
|
||||
const parts = stdout.toString().split('\n\n');
|
||||
parts.forEach(element => {
|
||||
const lines = element.split('\n');
|
||||
if (util.getValue(lines, 'class', ':', true).toLowerCase().indexOf('audio') >= 0) {
|
||||
const audio = parseLinuxAudioPciMM(lines, audioPCI);
|
||||
result.push(audio);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_darwin) {
|
||||
let cmd = 'system_profiler SPAudioDataType -json';
|
||||
exec(cmd, function (error, stdout) {
|
||||
if (!error) {
|
||||
try {
|
||||
const outObj = JSON.parse(stdout.toString());
|
||||
if (outObj.SPAudioDataType && outObj.SPAudioDataType.length && outObj.SPAudioDataType[0] && outObj.SPAudioDataType[0]['_items'] && outObj.SPAudioDataType[0]['_items'].length) {
|
||||
for (let i = 0; i < outObj.SPAudioDataType[0]['_items'].length; i++) {
|
||||
const audio = parseDarwinAudio(outObj.SPAudioDataType[0]['_items'][i], i);
|
||||
result.push(audio);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_windows) {
|
||||
util.powerShell('Get-CimInstance Win32_SoundDevice | select DeviceID,StatusInfo,Name,Manufacturer | fl').then((stdout, error) => {
|
||||
if (!error) {
|
||||
const parts = stdout.toString().split(/\n\s*\n/);
|
||||
parts.forEach(element => {
|
||||
const lines = element.split('\n');
|
||||
if (util.getValue(lines, 'name', ':')) {
|
||||
result.push(parseWindowsAudio(lines));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.audio = audio;
|
||||
312
api.hyungi.net/node_modules/systeminformation/lib/battery.js
generated
vendored
Normal file
312
api.hyungi.net/node_modules/systeminformation/lib/battery.js
generated
vendored
Normal file
@@ -0,0 +1,312 @@
|
||||
'use strict';
|
||||
// @ts-check;
|
||||
// ==================================================================================
|
||||
// battery.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 6. Battery
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const exec = require('child_process').exec;
|
||||
const fs = require('fs');
|
||||
const util = require('./util');
|
||||
|
||||
let _platform = process.platform;
|
||||
|
||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
||||
const _darwin = (_platform === 'darwin');
|
||||
const _windows = (_platform === 'win32');
|
||||
const _freebsd = (_platform === 'freebsd');
|
||||
const _openbsd = (_platform === 'openbsd');
|
||||
const _netbsd = (_platform === 'netbsd');
|
||||
const _sunos = (_platform === 'sunos');
|
||||
|
||||
function parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity) {
|
||||
const result = {};
|
||||
let status = util.getValue(lines, 'BatteryStatus', ':').trim();
|
||||
// 1 = "Discharging"
|
||||
// 2 = "On A/C"
|
||||
// 3 = "Fully Charged"
|
||||
// 4 = "Low"
|
||||
// 5 = "Critical"
|
||||
// 6 = "Charging"
|
||||
// 7 = "Charging High"
|
||||
// 8 = "Charging Low"
|
||||
// 9 = "Charging Critical"
|
||||
// 10 = "Undefined"
|
||||
// 11 = "Partially Charged"
|
||||
if (status >= 0) {
|
||||
const statusValue = status ? parseInt(status) : 0;
|
||||
result.status = statusValue;
|
||||
result.hasBattery = true;
|
||||
result.maxCapacity = fullChargeCapacity || parseInt(util.getValue(lines, 'DesignCapacity', ':') || 0);
|
||||
result.designedCapacity = parseInt(util.getValue(lines, 'DesignCapacity', ':') || designedCapacity);
|
||||
result.voltage = parseInt(util.getValue(lines, 'DesignVoltage', ':') || 0) / 1000.0;
|
||||
result.capacityUnit = 'mWh';
|
||||
result.percent = parseInt(util.getValue(lines, 'EstimatedChargeRemaining', ':') || 0);
|
||||
result.currentCapacity = parseInt(result.maxCapacity * result.percent / 100);
|
||||
result.isCharging = (statusValue >= 6 && statusValue <= 9) || statusValue === 11 || ((statusValue !== 3) && (statusValue !== 1) && result.percent < 100);
|
||||
result.acConnected = result.isCharging || statusValue === 2;
|
||||
result.model = util.getValue(lines, 'DeviceID', ':');
|
||||
} else {
|
||||
result.status = -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = function (callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
let result = {
|
||||
hasBattery: false,
|
||||
cycleCount: 0,
|
||||
isCharging: false,
|
||||
designedCapacity: 0,
|
||||
maxCapacity: 0,
|
||||
currentCapacity: 0,
|
||||
voltage: 0,
|
||||
capacityUnit: '',
|
||||
percent: 0,
|
||||
timeRemaining: null,
|
||||
acConnected: true,
|
||||
type: '',
|
||||
model: '',
|
||||
manufacturer: '',
|
||||
serial: ''
|
||||
};
|
||||
|
||||
if (_linux) {
|
||||
let battery_path = '';
|
||||
if (fs.existsSync('/sys/class/power_supply/BAT1/uevent')) {
|
||||
battery_path = '/sys/class/power_supply/BAT1/';
|
||||
} else if (fs.existsSync('/sys/class/power_supply/BAT0/uevent')) {
|
||||
battery_path = '/sys/class/power_supply/BAT0/';
|
||||
}
|
||||
|
||||
let acConnected = false;
|
||||
let acPath = '';
|
||||
if (fs.existsSync('/sys/class/power_supply/AC/online')) {
|
||||
acPath = '/sys/class/power_supply/AC/online';
|
||||
} else if (fs.existsSync('/sys/class/power_supply/AC0/online')) {
|
||||
acPath = '/sys/class/power_supply/AC0/online';
|
||||
}
|
||||
|
||||
if (acPath) {
|
||||
const file = fs.readFileSync(acPath);
|
||||
acConnected = file.toString().trim() === '1';
|
||||
}
|
||||
|
||||
if (battery_path) {
|
||||
fs.readFile(battery_path + 'uevent', function (error, stdout) {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
|
||||
result.isCharging = (util.getValue(lines, 'POWER_SUPPLY_STATUS', '=').toLowerCase() === 'charging');
|
||||
result.acConnected = acConnected || result.isCharging;
|
||||
result.voltage = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_VOLTAGE_NOW', '='), 10) / 1000000.0;
|
||||
result.capacityUnit = result.voltage ? 'mWh' : 'mAh';
|
||||
result.cycleCount = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CYCLE_COUNT', '='), 10);
|
||||
result.maxCapacity = Math.round(parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_FULL', '=', true, true), 10) / 1000.0 * (result.voltage || 1));
|
||||
const desingedMinVoltage = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_VOLTAGE_MIN_DESIGN', '='), 10) / 1000000.0;
|
||||
result.designedCapacity = Math.round(parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_FULL_DESIGN', '=', true, true), 10) / 1000.0 * (desingedMinVoltage || result.voltage || 1));
|
||||
result.currentCapacity = Math.round(parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_NOW', '='), 10) / 1000.0 * (result.voltage || 1));
|
||||
if (!result.maxCapacity) {
|
||||
result.maxCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_FULL', '=', true, true), 10) / 1000.0;
|
||||
result.designedCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_FULL_DESIGN', '=', true, true), 10) / 1000.0 | result.maxCapacity;
|
||||
result.currentCapacity = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_NOW', '='), 10) / 1000.0;
|
||||
}
|
||||
const percent = util.getValue(lines, 'POWER_SUPPLY_CAPACITY', '=');
|
||||
const energy = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_ENERGY_NOW', '='), 10);
|
||||
const power = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_POWER_NOW', '='), 10);
|
||||
const current = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CURRENT_NOW', '='), 10);
|
||||
const charge = parseInt('0' + util.getValue(lines, 'POWER_SUPPLY_CHARGE_NOW', '='), 10);
|
||||
|
||||
result.percent = parseInt('0' + percent, 10);
|
||||
if (result.maxCapacity && result.currentCapacity) {
|
||||
result.hasBattery = true;
|
||||
if (!percent) {
|
||||
result.percent = 100.0 * result.currentCapacity / result.maxCapacity;
|
||||
}
|
||||
}
|
||||
if (result.isCharging) {
|
||||
result.hasBattery = true;
|
||||
}
|
||||
if (energy && power) {
|
||||
result.timeRemaining = Math.floor(energy / power * 60);
|
||||
} else if (current && charge) {
|
||||
result.timeRemaining = Math.floor(charge / current * 60);
|
||||
} else if (current && result.currentCapacity) {
|
||||
result.timeRemaining = Math.floor(result.currentCapacity / current * 60);
|
||||
}
|
||||
result.type = util.getValue(lines, 'POWER_SUPPLY_TECHNOLOGY', '=');
|
||||
result.model = util.getValue(lines, 'POWER_SUPPLY_MODEL_NAME', '=');
|
||||
result.manufacturer = util.getValue(lines, 'POWER_SUPPLY_MANUFACTURER', '=');
|
||||
result.serial = util.getValue(lines, 'POWER_SUPPLY_SERIAL_NUMBER', '=');
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
if (_freebsd || _openbsd || _netbsd) {
|
||||
exec('sysctl -i hw.acpi.battery hw.acpi.acline', function (error, stdout) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
const batteries = parseInt('0' + util.getValue(lines, 'hw.acpi.battery.units'), 10);
|
||||
const percent = parseInt('0' + util.getValue(lines, 'hw.acpi.battery.life'), 10);
|
||||
result.hasBattery = (batteries > 0);
|
||||
result.cycleCount = null;
|
||||
result.isCharging = util.getValue(lines, 'hw.acpi.acline') !== '1';
|
||||
result.acConnected = result.isCharging;
|
||||
result.maxCapacity = null;
|
||||
result.currentCapacity = null;
|
||||
result.capacityUnit = 'unknown';
|
||||
result.percent = batteries ? percent : null;
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
|
||||
if (_darwin) {
|
||||
exec('ioreg -n AppleSmartBattery -r | egrep "CycleCount|IsCharging|DesignCapacity|MaxCapacity|CurrentCapacity|DeviceName|BatterySerialNumber|Serial|TimeRemaining|Voltage"; pmset -g batt | grep %', function (error, stdout) {
|
||||
if (stdout) {
|
||||
let lines = stdout.toString().replace(/ +/g, '').replace(/"+/g, '').replace(/-/g, '').split('\n');
|
||||
result.cycleCount = parseInt('0' + util.getValue(lines, 'cyclecount', '='), 10);
|
||||
result.voltage = parseInt('0' + util.getValue(lines, 'voltage', '='), 10) / 1000.0;
|
||||
result.capacityUnit = result.voltage ? 'mWh' : 'mAh';
|
||||
result.maxCapacity = Math.round(parseInt('0' + util.getValue(lines, 'applerawmaxcapacity', '='), 10) * (result.voltage || 1));
|
||||
result.currentCapacity = Math.round(parseInt('0' + util.getValue(lines, 'applerawcurrentcapacity', '='), 10) * (result.voltage || 1));
|
||||
result.designedCapacity = Math.round(parseInt('0' + util.getValue(lines, 'DesignCapacity', '='), 10) * (result.voltage || 1));
|
||||
result.manufacturer = 'Apple';
|
||||
result.serial = util.getValue(lines, 'BatterySerialNumber', '=') || util.getValue(lines, 'Serial', '=');
|
||||
result.model = util.getValue(lines, 'DeviceName', '=');
|
||||
let percent = null;
|
||||
const line = util.getValue(lines, 'internal', 'Battery');
|
||||
let parts = line.split(';');
|
||||
if (parts && parts[0]) {
|
||||
let parts2 = parts[0].split('\t');
|
||||
if (parts2 && parts2[1]) {
|
||||
percent = parseFloat(parts2[1].trim().replace(/%/g, ''));
|
||||
}
|
||||
}
|
||||
if (parts && parts[1]) {
|
||||
result.isCharging = (parts[1].trim() === 'charging');
|
||||
result.acConnected = (parts[1].trim() !== 'discharging');
|
||||
} else {
|
||||
result.isCharging = util.getValue(lines, 'ischarging', '=').toLowerCase() === 'yes';
|
||||
result.acConnected = result.isCharging;
|
||||
}
|
||||
if (result.maxCapacity && result.currentCapacity) {
|
||||
result.hasBattery = true;
|
||||
result.type = 'Li-ion';
|
||||
result.percent = percent !== null ? percent : Math.round(100.0 * result.currentCapacity / result.maxCapacity);
|
||||
if (!result.isCharging) {
|
||||
result.timeRemaining = parseInt('0' + util.getValue(lines, 'TimeRemaining', '='), 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
if (_windows) {
|
||||
try {
|
||||
const workload = [];
|
||||
workload.push(util.powerShell('Get-CimInstance Win32_Battery | select BatteryStatus, DesignCapacity, DesignVoltage, EstimatedChargeRemaining, DeviceID | fl'));
|
||||
workload.push(util.powerShell('(Get-WmiObject -Class BatteryStaticData -Namespace ROOT/WMI).DesignedCapacity'));
|
||||
workload.push(util.powerShell('(Get-CimInstance -Class BatteryFullChargedCapacity -Namespace ROOT/WMI).FullChargedCapacity'));
|
||||
util.promiseAll(
|
||||
workload
|
||||
).then((data) => {
|
||||
if (data) {
|
||||
let parts = data.results[0].split(/\n\s*\n/);
|
||||
let batteries = [];
|
||||
const hasValue = value => /\S/.test(value);
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
if (hasValue(parts[i]) && (!batteries.length || !hasValue(parts[i - 1]))) {
|
||||
batteries.push([]);
|
||||
}
|
||||
if (hasValue(parts[i])) {
|
||||
batteries[batteries.length - 1].push(parts[i]);
|
||||
}
|
||||
}
|
||||
let designCapacities = data.results[1].split('\r\n').filter(e => e);
|
||||
let fullChargeCapacities = data.results[2].split('\r\n').filter(e => e);
|
||||
if (batteries.length) {
|
||||
let first = false;
|
||||
let additionalBatteries = [];
|
||||
for (let i = 0; i < batteries.length; i++) {
|
||||
let lines = batteries[i][0].split('\r\n');
|
||||
const designedCapacity = designCapacities && designCapacities.length >= (i + 1) && designCapacities[i] ? util.toInt(designCapacities[i]) : 0;
|
||||
const fullChargeCapacity = fullChargeCapacities && fullChargeCapacities.length >= (i + 1) && fullChargeCapacities[i] ? util.toInt(fullChargeCapacities[i]) : 0;
|
||||
const parsed = parseWinBatteryPart(lines, designedCapacity, fullChargeCapacity);
|
||||
if (!first && parsed.status > 0 && parsed.status !== 10) {
|
||||
result.hasBattery = parsed.hasBattery;
|
||||
result.maxCapacity = parsed.maxCapacity;
|
||||
result.designedCapacity = parsed.designedCapacity;
|
||||
result.voltage = parsed.voltage;
|
||||
result.capacityUnit = parsed.capacityUnit;
|
||||
result.percent = parsed.percent;
|
||||
result.currentCapacity = parsed.currentCapacity;
|
||||
result.isCharging = parsed.isCharging;
|
||||
result.acConnected = parsed.acConnected;
|
||||
result.model = parsed.model;
|
||||
first = true;
|
||||
} else if (parsed.status !== -1) {
|
||||
additionalBatteries.push(
|
||||
{
|
||||
hasBattery: parsed.hasBattery,
|
||||
maxCapacity: parsed.maxCapacity,
|
||||
designedCapacity: parsed.designedCapacity,
|
||||
voltage: parsed.voltage,
|
||||
capacityUnit: parsed.capacityUnit,
|
||||
percent: parsed.percent,
|
||||
currentCapacity: parsed.currentCapacity,
|
||||
isCharging: parsed.isCharging,
|
||||
timeRemaining: null,
|
||||
acConnected: parsed.acConnected,
|
||||
model: parsed.model,
|
||||
type: '',
|
||||
manufacturer: '',
|
||||
serial: ''
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!first && additionalBatteries.length) {
|
||||
result = additionalBatteries[0];
|
||||
additionalBatteries.shift();
|
||||
}
|
||||
if (additionalBatteries.length) {
|
||||
result.additionalBatteries = additionalBatteries;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
237
api.hyungi.net/node_modules/systeminformation/lib/bluetooth.js
generated
vendored
Normal file
237
api.hyungi.net/node_modules/systeminformation/lib/bluetooth.js
generated
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// audio.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 17. bluetooth
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const exec = require('child_process').exec;
|
||||
const execSync = require('child_process').execSync;
|
||||
const path = require('path');
|
||||
const util = require('./util');
|
||||
const bluetoothVendors = require('./bluetoothVendors');
|
||||
const fs = require('fs');
|
||||
|
||||
let _platform = process.platform;
|
||||
|
||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
||||
const _darwin = (_platform === 'darwin');
|
||||
const _windows = (_platform === 'win32');
|
||||
const _freebsd = (_platform === 'freebsd');
|
||||
const _openbsd = (_platform === 'openbsd');
|
||||
const _netbsd = (_platform === 'netbsd');
|
||||
const _sunos = (_platform === 'sunos');
|
||||
|
||||
function parseBluetoothType(str) {
|
||||
let result = '';
|
||||
|
||||
if (str.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
|
||||
if (str.indexOf('mouse') >= 0) { result = 'Mouse'; }
|
||||
if (str.indexOf('trackpad') >= 0) { result = 'Trackpad'; }
|
||||
if (str.indexOf('speaker') >= 0) { result = 'Speaker'; }
|
||||
if (str.indexOf('headset') >= 0) { result = 'Headset'; }
|
||||
if (str.indexOf('phone') >= 0) { result = 'Phone'; }
|
||||
if (str.indexOf('macbook') >= 0) { result = 'Computer'; }
|
||||
if (str.indexOf('imac') >= 0) { result = 'Computer'; }
|
||||
if (str.indexOf('ipad') >= 0) { result = 'Tablet'; }
|
||||
if (str.indexOf('watch') >= 0) { result = 'Watch'; }
|
||||
if (str.indexOf('headphone') >= 0) { result = 'Headset'; }
|
||||
// to be continued ...
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseBluetoothManufacturer(str) {
|
||||
let result = str.split(' ')[0];
|
||||
str = str.toLowerCase();
|
||||
if (str.indexOf('apple') >= 0) { result = 'Apple'; }
|
||||
if (str.indexOf('ipad') >= 0) { result = 'Apple'; }
|
||||
if (str.indexOf('imac') >= 0) { result = 'Apple'; }
|
||||
if (str.indexOf('iphone') >= 0) { result = 'Apple'; }
|
||||
if (str.indexOf('magic mouse') >= 0) { result = 'Apple'; }
|
||||
if (str.indexOf('magic track') >= 0) { result = 'Apple'; }
|
||||
if (str.indexOf('macbook') >= 0) { result = 'Apple'; }
|
||||
// to be continued ...
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseBluetoothVendor(str) {
|
||||
const id = parseInt(str);
|
||||
if (!isNaN(id)) return bluetoothVendors[id];
|
||||
}
|
||||
|
||||
function parseLinuxBluetoothInfo(lines, macAddr1, macAddr2) {
|
||||
const result = {};
|
||||
|
||||
result.device = null;
|
||||
result.name = util.getValue(lines, 'name', '=');
|
||||
result.manufacturer = null;
|
||||
result.macDevice = macAddr1;
|
||||
result.macHost = macAddr2;
|
||||
result.batteryPercent = null;
|
||||
result.type = parseBluetoothType(result.name.toLowerCase());
|
||||
result.connected = false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseDarwinBluetoothDevices(bluetoothObject, macAddr2) {
|
||||
const result = {};
|
||||
const typeStr = ((bluetoothObject.device_minorClassOfDevice_string || bluetoothObject.device_majorClassOfDevice_string || bluetoothObject.device_minorType || '') + (bluetoothObject.device_name || '')).toLowerCase();
|
||||
|
||||
result.device = bluetoothObject.device_services || '';
|
||||
result.name = bluetoothObject.device_name || '';
|
||||
result.manufacturer = bluetoothObject.device_manufacturer || parseBluetoothVendor(bluetoothObject.device_vendorID) || parseBluetoothManufacturer(bluetoothObject.device_name || '') || '';
|
||||
result.macDevice = (bluetoothObject.device_addr || bluetoothObject.device_address || '').toLowerCase().replace(/-/g, ':');
|
||||
result.macHost = macAddr2;
|
||||
result.batteryPercent = bluetoothObject.device_batteryPercent || null;
|
||||
result.type = parseBluetoothType(typeStr);
|
||||
result.connected = bluetoothObject.device_isconnected === 'attrib_Yes' || false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseWindowsBluetooth(lines) {
|
||||
const result = {};
|
||||
|
||||
result.device = null;
|
||||
result.name = util.getValue(lines, 'name', ':');
|
||||
result.manufacturer = util.getValue(lines, 'manufacturer', ':');
|
||||
result.macDevice = null;
|
||||
result.macHost = null;
|
||||
result.batteryPercent = null;
|
||||
result.type = parseBluetoothType(result.name.toLowerCase());
|
||||
result.connected = null;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function bluetoothDevices(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
let result = [];
|
||||
if (_linux) {
|
||||
// get files in /var/lib/bluetooth/ recursive
|
||||
const btFiles = util.getFilesInPath('/var/lib/bluetooth/');
|
||||
btFiles.forEach((element) => {
|
||||
const filename = path.basename(element);
|
||||
const pathParts = element.split('/');
|
||||
const macAddr1 = pathParts.length >= 6 ? pathParts[pathParts.length - 2] : null;
|
||||
const macAddr2 = pathParts.length >= 7 ? pathParts[pathParts.length - 3] : null;
|
||||
if (filename === 'info') {
|
||||
const infoFile = fs.readFileSync(element, { encoding: 'utf8' }).split('\n');
|
||||
result.push(parseLinuxBluetoothInfo(infoFile, macAddr1, macAddr2));
|
||||
}
|
||||
});
|
||||
// determine "connected" with hcitool con
|
||||
try {
|
||||
const hdicon = execSync('hcitool con', util.execOptsLinux).toString().toLowerCase();
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
if (result[i].macDevice && result[i].macDevice.length > 10 && hdicon.indexOf(result[i].macDevice.toLowerCase()) >= 0) {
|
||||
result[i].connected = true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
if (_darwin) {
|
||||
let cmd = 'system_profiler SPBluetoothDataType -json';
|
||||
exec(cmd, function (error, stdout) {
|
||||
if (!error) {
|
||||
try {
|
||||
const outObj = JSON.parse(stdout.toString());
|
||||
if (outObj.SPBluetoothDataType && outObj.SPBluetoothDataType.length && outObj.SPBluetoothDataType[0] && outObj.SPBluetoothDataType[0]['device_title'] && outObj.SPBluetoothDataType[0]['device_title'].length) {
|
||||
// missing: host BT Adapter macAddr ()
|
||||
let macAddr2 = null;
|
||||
if (outObj.SPBluetoothDataType[0]['local_device_title'] && outObj.SPBluetoothDataType[0].local_device_title.general_address) {
|
||||
macAddr2 = outObj.SPBluetoothDataType[0].local_device_title.general_address.toLowerCase().replace(/-/g, ':');
|
||||
}
|
||||
outObj.SPBluetoothDataType[0]['device_title'].forEach((element) => {
|
||||
const obj = element;
|
||||
const objKey = Object.keys(obj);
|
||||
if (objKey && objKey.length === 1) {
|
||||
const innerObject = obj[objKey[0]];
|
||||
innerObject.device_name = objKey[0];
|
||||
const bluetoothDevice = parseDarwinBluetoothDevices(innerObject, macAddr2);
|
||||
result.push(bluetoothDevice);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (outObj.SPBluetoothDataType && outObj.SPBluetoothDataType.length && outObj.SPBluetoothDataType[0] && outObj.SPBluetoothDataType[0]['device_connected'] && outObj.SPBluetoothDataType[0]['device_connected'].length) {
|
||||
const macAddr2 = outObj.SPBluetoothDataType[0].controller_properties && outObj.SPBluetoothDataType[0].controller_properties.controller_address ? outObj.SPBluetoothDataType[0].controller_properties.controller_address.toLowerCase().replace(/-/g, ':') : null;
|
||||
outObj.SPBluetoothDataType[0]['device_connected'].forEach((element) => {
|
||||
const obj = element;
|
||||
const objKey = Object.keys(obj);
|
||||
if (objKey && objKey.length === 1) {
|
||||
const innerObject = obj[objKey[0]];
|
||||
innerObject.device_name = objKey[0];
|
||||
innerObject.device_isconnected = 'attrib_Yes';
|
||||
const bluetoothDevice = parseDarwinBluetoothDevices(innerObject, macAddr2);
|
||||
result.push(bluetoothDevice);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (outObj.SPBluetoothDataType && outObj.SPBluetoothDataType.length && outObj.SPBluetoothDataType[0] && outObj.SPBluetoothDataType[0]['device_not_connected'] && outObj.SPBluetoothDataType[0]['device_not_connected'].length) {
|
||||
const macAddr2 = outObj.SPBluetoothDataType[0].controller_properties && outObj.SPBluetoothDataType[0].controller_properties.controller_address ? outObj.SPBluetoothDataType[0].controller_properties.controller_address.toLowerCase().replace(/-/g, ':') : null;
|
||||
outObj.SPBluetoothDataType[0]['device_not_connected'].forEach((element) => {
|
||||
const obj = element;
|
||||
const objKey = Object.keys(obj);
|
||||
if (objKey && objKey.length === 1) {
|
||||
const innerObject = obj[objKey[0]];
|
||||
innerObject.device_name = objKey[0];
|
||||
innerObject.device_isconnected = 'attrib_No';
|
||||
const bluetoothDevice = parseDarwinBluetoothDevices(innerObject, macAddr2);
|
||||
result.push(bluetoothDevice);
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_windows) {
|
||||
util.powerShell('Get-CimInstance Win32_PNPEntity | select PNPClass, Name, Manufacturer | fl').then((stdout, error) => {
|
||||
if (!error) {
|
||||
const parts = stdout.toString().split(/\n\s*\n/);
|
||||
parts.forEach((part) => {
|
||||
if (util.getValue(part.split('\n'), 'PNPClass', ':') === 'Bluetooth') {
|
||||
result.push(parseWindowsBluetooth(part.split('\n')));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_freebsd || _netbsd || _openbsd || _sunos) {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.bluetoothDevices = bluetoothDevices;
|
||||
1138
api.hyungi.net/node_modules/systeminformation/lib/bluetoothVendors.js
generated
vendored
Normal file
1138
api.hyungi.net/node_modules/systeminformation/lib/bluetoothVendors.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
91
api.hyungi.net/node_modules/systeminformation/lib/cli.js
generated
vendored
Normal file
91
api.hyungi.net/node_modules/systeminformation/lib/cli.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// cli.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Dependencies
|
||||
// ----------------------------------------------------------------------------------
|
||||
const si = require('./index');
|
||||
const lib_version = require('../package.json').version;
|
||||
|
||||
function capFirst(string) {
|
||||
return string[0].toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
function printLines(obj) {
|
||||
for (const property in obj) {
|
||||
console.log(capFirst(property) + ' '.substring(0, 17 - property.length) + ': ' + (obj[property] || ''));
|
||||
}
|
||||
console.log();
|
||||
}
|
||||
|
||||
function info() {
|
||||
console.log('┌─────────────────────────────────────────────────────────────────────────────────────────┐');
|
||||
console.log('│ SYSTEMINFORMATION '.substring(0, 80 - lib_version.length) + 'Version: ' + lib_version + ' │');
|
||||
console.log('└─────────────────────────────────────────────────────────────────────────────────────────┘');
|
||||
|
||||
si.osInfo().then(res => {
|
||||
console.log();
|
||||
console.log('Operating System:');
|
||||
console.log('──────────────────────────────────────────────────────────────────────────────────────────');
|
||||
delete res.serial;
|
||||
delete res.servicepack;
|
||||
delete res.logofile;
|
||||
delete res.fqdn;
|
||||
delete res.uefi;
|
||||
printLines(res);
|
||||
si.system().then(res => {
|
||||
console.log('System:');
|
||||
console.log('──────────────────────────────────────────────────────────────────────────────────────────');
|
||||
delete res.serial;
|
||||
delete res.uuid;
|
||||
delete res.sku;
|
||||
delete res.uuid;
|
||||
printLines(res);
|
||||
si.cpu().then(res => {
|
||||
console.log('CPU:');
|
||||
console.log('──────────────────────────────────────────────────────────────────────────────────────────');
|
||||
delete res.cache;
|
||||
delete res.governor;
|
||||
delete res.flags;
|
||||
delete res.virtualization;
|
||||
delete res.revision;
|
||||
delete res.voltage;
|
||||
delete res.vendor;
|
||||
delete res.speedMin;
|
||||
delete res.speedMax;
|
||||
printLines(res);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Main
|
||||
// ----------------------------------------------------------------------------------
|
||||
(function () {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
if (args[0] === 'info') {
|
||||
info();
|
||||
} else {
|
||||
si.getStaticData().then(
|
||||
((data) => {
|
||||
data.time = si.time();
|
||||
console.log(JSON.stringify(data, null, 2));
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
})();
|
||||
1883
api.hyungi.net/node_modules/systeminformation/lib/cpu.js
generated
vendored
Normal file
1883
api.hyungi.net/node_modules/systeminformation/lib/cpu.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
766
api.hyungi.net/node_modules/systeminformation/lib/docker.js
generated
vendored
Normal file
766
api.hyungi.net/node_modules/systeminformation/lib/docker.js
generated
vendored
Normal file
@@ -0,0 +1,766 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// docker.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 13. Docker
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const util = require('./util');
|
||||
const DockerSocket = require('./dockerSocket');
|
||||
|
||||
let _platform = process.platform;
|
||||
const _windows = (_platform === 'win32');
|
||||
|
||||
let _docker_container_stats = {};
|
||||
let _docker_socket;
|
||||
let _docker_last_read = 0;
|
||||
|
||||
|
||||
// --------------------------
|
||||
// get containers (parameter all: get also inactive/exited containers)
|
||||
|
||||
function dockerInfo(callback) {
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
if (!_docker_socket) {
|
||||
_docker_socket = new DockerSocket();
|
||||
}
|
||||
const result = {};
|
||||
|
||||
_docker_socket.getInfo((data) => {
|
||||
result.id = data.ID;
|
||||
result.containers = data.Containers;
|
||||
result.containersRunning = data.ContainersRunning;
|
||||
result.containersPaused = data.ContainersPaused;
|
||||
result.containersStopped = data.ContainersStopped;
|
||||
result.images = data.Images;
|
||||
result.driver = data.Driver;
|
||||
result.memoryLimit = data.MemoryLimit;
|
||||
result.swapLimit = data.SwapLimit;
|
||||
result.kernelMemory = data.KernelMemory;
|
||||
result.cpuCfsPeriod = data.CpuCfsPeriod;
|
||||
result.cpuCfsQuota = data.CpuCfsQuota;
|
||||
result.cpuShares = data.CPUShares;
|
||||
result.cpuSet = data.CPUSet;
|
||||
result.ipv4Forwarding = data.IPv4Forwarding;
|
||||
result.bridgeNfIptables = data.BridgeNfIptables;
|
||||
result.bridgeNfIp6tables = data.BridgeNfIp6tables;
|
||||
result.debug = data.Debug;
|
||||
result.nfd = data.NFd;
|
||||
result.oomKillDisable = data.OomKillDisable;
|
||||
result.ngoroutines = data.NGoroutines;
|
||||
result.systemTime = data.SystemTime;
|
||||
result.loggingDriver = data.LoggingDriver;
|
||||
result.cgroupDriver = data.CgroupDriver;
|
||||
result.nEventsListener = data.NEventsListener;
|
||||
result.kernelVersion = data.KernelVersion;
|
||||
result.operatingSystem = data.OperatingSystem;
|
||||
result.osType = data.OSType;
|
||||
result.architecture = data.Architecture;
|
||||
result.ncpu = data.NCPU;
|
||||
result.memTotal = data.MemTotal;
|
||||
result.dockerRootDir = data.DockerRootDir;
|
||||
result.httpProxy = data.HttpProxy;
|
||||
result.httpsProxy = data.HttpsProxy;
|
||||
result.noProxy = data.NoProxy;
|
||||
result.name = data.Name;
|
||||
result.labels = data.Labels;
|
||||
result.experimentalBuild = data.ExperimentalBuild;
|
||||
result.serverVersion = data.ServerVersion;
|
||||
result.clusterStore = data.ClusterStore;
|
||||
result.clusterAdvertise = data.ClusterAdvertise;
|
||||
result.defaultRuntime = data.DefaultRuntime;
|
||||
result.liveRestoreEnabled = data.LiveRestoreEnabled;
|
||||
result.isolation = data.Isolation;
|
||||
result.initBinary = data.InitBinary;
|
||||
result.productLicense = data.ProductLicense;
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.dockerInfo = dockerInfo;
|
||||
|
||||
function dockerImages(all, callback) {
|
||||
|
||||
// fallback - if only callback is given
|
||||
if (util.isFunction(all) && !callback) {
|
||||
callback = all;
|
||||
all = false;
|
||||
}
|
||||
if (typeof all === 'string' && all === 'true') {
|
||||
all = true;
|
||||
}
|
||||
if (typeof all !== 'boolean' && all !== undefined) {
|
||||
all = false;
|
||||
}
|
||||
|
||||
all = all || false;
|
||||
let result = [];
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
if (!_docker_socket) {
|
||||
_docker_socket = new DockerSocket();
|
||||
}
|
||||
const workload = [];
|
||||
|
||||
_docker_socket.listImages(all, data => {
|
||||
let dockerImages = {};
|
||||
try {
|
||||
dockerImages = data;
|
||||
if (dockerImages && Object.prototype.toString.call(dockerImages) === '[object Array]' && dockerImages.length > 0) {
|
||||
|
||||
dockerImages.forEach(function (element) {
|
||||
|
||||
if (element.Names && Object.prototype.toString.call(element.Names) === '[object Array]' && element.Names.length > 0) {
|
||||
element.Name = element.Names[0].replace(/^\/|\/$/g, '');
|
||||
}
|
||||
workload.push(dockerImagesInspect(element.Id.trim(), element));
|
||||
});
|
||||
if (workload.length) {
|
||||
Promise.all(
|
||||
workload
|
||||
).then((data) => {
|
||||
if (callback) { callback(data); }
|
||||
resolve(data);
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
} catch (err) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// container inspect (for one container)
|
||||
|
||||
function dockerImagesInspect(imageID, payload) {
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
imageID = imageID || '';
|
||||
if (typeof imageID !== 'string') {
|
||||
return resolve();
|
||||
}
|
||||
const imageIDSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(imageID, true)).trim();
|
||||
if (imageIDSanitized) {
|
||||
|
||||
if (!_docker_socket) {
|
||||
_docker_socket = new DockerSocket();
|
||||
}
|
||||
|
||||
_docker_socket.inspectImage(imageIDSanitized.trim(), data => {
|
||||
try {
|
||||
resolve({
|
||||
id: payload.Id,
|
||||
container: data.Container,
|
||||
comment: data.Comment,
|
||||
os: data.Os,
|
||||
architecture: data.Architecture,
|
||||
parent: data.Parent,
|
||||
dockerVersion: data.DockerVersion,
|
||||
size: data.Size,
|
||||
sharedSize: payload.SharedSize,
|
||||
virtualSize: data.VirtualSize,
|
||||
author: data.Author,
|
||||
created: data.Created ? Math.round(new Date(data.Created).getTime() / 1000) : 0,
|
||||
containerConfig: data.ContainerConfig ? data.ContainerConfig : {},
|
||||
graphDriver: data.GraphDriver ? data.GraphDriver : {},
|
||||
repoDigests: data.RepoDigests ? data.RepoDigests : {},
|
||||
repoTags: data.RepoTags ? data.RepoTags : {},
|
||||
config: data.Config ? data.Config : {},
|
||||
rootFS: data.RootFS ? data.RootFS : {},
|
||||
});
|
||||
} catch (err) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.dockerImages = dockerImages;
|
||||
|
||||
function dockerContainers(all, callback) {
|
||||
|
||||
function inContainers(containers, id) {
|
||||
let filtered = containers.filter(obj => {
|
||||
/**
|
||||
* @namespace
|
||||
* @property {string} Id
|
||||
*/
|
||||
return (obj.Id && (obj.Id === id));
|
||||
});
|
||||
return (filtered.length > 0);
|
||||
}
|
||||
|
||||
// fallback - if only callback is given
|
||||
if (util.isFunction(all) && !callback) {
|
||||
callback = all;
|
||||
all = false;
|
||||
}
|
||||
if (typeof all === 'string' && all === 'true') {
|
||||
all = true;
|
||||
}
|
||||
if (typeof all !== 'boolean' && all !== undefined) {
|
||||
all = false;
|
||||
}
|
||||
|
||||
all = all || false;
|
||||
let result = [];
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
if (!_docker_socket) {
|
||||
_docker_socket = new DockerSocket();
|
||||
}
|
||||
const workload = [];
|
||||
|
||||
_docker_socket.listContainers(all, data => {
|
||||
let docker_containers = {};
|
||||
try {
|
||||
docker_containers = data;
|
||||
if (docker_containers && Object.prototype.toString.call(docker_containers) === '[object Array]' && docker_containers.length > 0) {
|
||||
// GC in _docker_container_stats
|
||||
for (let key in _docker_container_stats) {
|
||||
if ({}.hasOwnProperty.call(_docker_container_stats, key)) {
|
||||
if (!inContainers(docker_containers, key)) { delete _docker_container_stats[key]; }
|
||||
}
|
||||
}
|
||||
|
||||
docker_containers.forEach(function (element) {
|
||||
|
||||
if (element.Names && Object.prototype.toString.call(element.Names) === '[object Array]' && element.Names.length > 0) {
|
||||
element.Name = element.Names[0].replace(/^\/|\/$/g, '');
|
||||
}
|
||||
workload.push(dockerContainerInspect(element.Id.trim(), element));
|
||||
});
|
||||
if (workload.length) {
|
||||
Promise.all(
|
||||
workload
|
||||
).then((data) => {
|
||||
if (callback) { callback(data); }
|
||||
resolve(data);
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
} catch (err) {
|
||||
// GC in _docker_container_stats
|
||||
for (let key in _docker_container_stats) {
|
||||
if ({}.hasOwnProperty.call(_docker_container_stats, key)) {
|
||||
if (!inContainers(docker_containers, key)) { delete _docker_container_stats[key]; }
|
||||
}
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// container inspect (for one container)
|
||||
|
||||
function dockerContainerInspect(containerID, payload) {
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
containerID = containerID || '';
|
||||
if (typeof containerID !== 'string') {
|
||||
return resolve();
|
||||
}
|
||||
const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
|
||||
if (containerIdSanitized) {
|
||||
|
||||
if (!_docker_socket) {
|
||||
_docker_socket = new DockerSocket();
|
||||
}
|
||||
|
||||
_docker_socket.getInspect(containerIdSanitized.trim(), data => {
|
||||
try {
|
||||
resolve({
|
||||
id: payload.Id,
|
||||
name: payload.Name,
|
||||
image: payload.Image,
|
||||
imageID: payload.ImageID,
|
||||
command: payload.Command,
|
||||
created: payload.Created,
|
||||
started: data.State && data.State.StartedAt ? Math.round(new Date(data.State.StartedAt).getTime() / 1000) : 0,
|
||||
finished: data.State && data.State.FinishedAt && !data.State.FinishedAt.startsWith('0001-01-01') ? Math.round(new Date(data.State.FinishedAt).getTime() / 1000) : 0,
|
||||
createdAt: data.Created ? data.Created : '',
|
||||
startedAt: data.State && data.State.StartedAt ? data.State.StartedAt : '',
|
||||
finishedAt: data.State && data.State.FinishedAt && !data.State.FinishedAt.startsWith('0001-01-01') ? data.State.FinishedAt : '',
|
||||
state: payload.State,
|
||||
restartCount: data.RestartCount || 0,
|
||||
platform: data.Platform || '',
|
||||
driver: data.Driver || '',
|
||||
ports: payload.Ports,
|
||||
mounts: payload.Mounts,
|
||||
// hostconfig: payload.HostConfig,
|
||||
// network: payload.NetworkSettings
|
||||
});
|
||||
} catch (err) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.dockerContainers = dockerContainers;
|
||||
|
||||
// --------------------------
|
||||
// helper functions for calculation of docker stats
|
||||
|
||||
function docker_calcCPUPercent(cpu_stats, precpu_stats) {
|
||||
/**
|
||||
* @namespace
|
||||
* @property {object} cpu_usage
|
||||
* @property {number} cpu_usage.total_usage
|
||||
* @property {number} system_cpu_usage
|
||||
* @property {object} cpu_usage
|
||||
* @property {Array} cpu_usage.percpu_usage
|
||||
*/
|
||||
|
||||
if (!_windows) {
|
||||
let cpuPercent = 0.0;
|
||||
// calculate the change for the cpu usage of the container in between readings
|
||||
let cpuDelta = cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage;
|
||||
// calculate the change for the entire system between readings
|
||||
let systemDelta = cpu_stats.system_cpu_usage - precpu_stats.system_cpu_usage;
|
||||
|
||||
if (systemDelta > 0.0 && cpuDelta > 0.0) {
|
||||
// calculate the change for the cpu usage of the container in between readings
|
||||
if (precpu_stats.online_cpus) {
|
||||
cpuPercent = (cpuDelta / systemDelta) * precpu_stats.online_cpus * 100.0;
|
||||
}
|
||||
else {
|
||||
cpuPercent = (cpuDelta / systemDelta) * cpu_stats.cpu_usage.percpu_usage.length * 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
return cpuPercent;
|
||||
} else {
|
||||
let nanoSecNow = util.nanoSeconds();
|
||||
let cpuPercent = 0.0;
|
||||
if (_docker_last_read > 0) {
|
||||
let possIntervals = (nanoSecNow - _docker_last_read); // / 100 * os.cpus().length;
|
||||
let intervalsUsed = cpu_stats.cpu_usage.total_usage - precpu_stats.cpu_usage.total_usage;
|
||||
if (possIntervals > 0) {
|
||||
cpuPercent = 100.0 * intervalsUsed / possIntervals;
|
||||
}
|
||||
}
|
||||
_docker_last_read = nanoSecNow;
|
||||
return cpuPercent;
|
||||
}
|
||||
}
|
||||
|
||||
function docker_calcNetworkIO(networks) {
|
||||
let rx;
|
||||
let wx;
|
||||
for (let key in networks) {
|
||||
// skip loop if the property is from prototype
|
||||
if (!{}.hasOwnProperty.call(networks, key)) { continue; }
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
* @property {number} rx_bytes
|
||||
* @property {number} tx_bytes
|
||||
*/
|
||||
let obj = networks[key];
|
||||
rx = +obj.rx_bytes;
|
||||
wx = +obj.tx_bytes;
|
||||
}
|
||||
return {
|
||||
rx,
|
||||
wx
|
||||
};
|
||||
}
|
||||
|
||||
function docker_calcBlockIO(blkio_stats) {
|
||||
let result = {
|
||||
r: 0,
|
||||
w: 0
|
||||
};
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
* @property {Array} io_service_bytes_recursive
|
||||
*/
|
||||
if (blkio_stats && blkio_stats.io_service_bytes_recursive && Object.prototype.toString.call(blkio_stats.io_service_bytes_recursive) === '[object Array]' && blkio_stats.io_service_bytes_recursive.length > 0) {
|
||||
blkio_stats.io_service_bytes_recursive.forEach(function (element) {
|
||||
/**
|
||||
* @namespace
|
||||
* @property {string} op
|
||||
* @property {number} value
|
||||
*/
|
||||
|
||||
if (element.op && element.op.toLowerCase() === 'read' && element.value) {
|
||||
result.r += element.value;
|
||||
}
|
||||
if (element.op && element.op.toLowerCase() === 'write' && element.value) {
|
||||
result.w += element.value;
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function dockerContainerStats(containerIDs, callback) {
|
||||
|
||||
let containerArray = [];
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
|
||||
// fallback - if only callback is given
|
||||
if (util.isFunction(containerIDs) && !callback) {
|
||||
callback = containerIDs;
|
||||
containerArray = ['*'];
|
||||
} else {
|
||||
containerIDs = containerIDs || '*';
|
||||
if (typeof containerIDs !== 'string') {
|
||||
if (callback) { callback([]); }
|
||||
return resolve([]);
|
||||
}
|
||||
let containerIDsSanitized = '';
|
||||
try {
|
||||
containerIDsSanitized.__proto__.toLowerCase = util.stringToLower;
|
||||
containerIDsSanitized.__proto__.replace = util.stringReplace;
|
||||
containerIDsSanitized.__proto__.toString = util.stringToString;
|
||||
containerIDsSanitized.__proto__.substr = util.stringSubstr;
|
||||
containerIDsSanitized.__proto__.substring = util.stringSubstring;
|
||||
containerIDsSanitized.__proto__.trim = util.stringTrim;
|
||||
containerIDsSanitized.__proto__.startsWith = util.stringStartWith;
|
||||
} catch (e) {
|
||||
Object.setPrototypeOf(containerIDsSanitized, util.stringObj);
|
||||
}
|
||||
|
||||
containerIDsSanitized = containerIDs;
|
||||
containerIDsSanitized = containerIDsSanitized.trim();
|
||||
if (containerIDsSanitized !== '*') {
|
||||
containerIDsSanitized = '';
|
||||
const s = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerIDs, true)).trim();
|
||||
const l = util.mathMin(s.length, 2000);
|
||||
for (let i = 0; i <= l; i++) {
|
||||
if (s[i] !== undefined) {
|
||||
s[i].__proto__.toLowerCase = util.stringToLower;
|
||||
const sl = s[i].toLowerCase();
|
||||
if (sl && sl[0] && !sl[1]) {
|
||||
containerIDsSanitized = containerIDsSanitized + sl[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
containerIDsSanitized = containerIDsSanitized.trim().toLowerCase().replace(/,+/g, '|');
|
||||
containerArray = containerIDsSanitized.split('|');
|
||||
}
|
||||
|
||||
const result = [];
|
||||
|
||||
const workload = [];
|
||||
if (containerArray.length && containerArray[0].trim() === '*') {
|
||||
containerArray = [];
|
||||
dockerContainers().then(allContainers => {
|
||||
for (let container of allContainers) {
|
||||
containerArray.push(container.id.substring(0, 12));
|
||||
}
|
||||
if (containerArray.length) {
|
||||
dockerContainerStats(containerArray.join(',')).then(result => {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
for (let containerID of containerArray) {
|
||||
workload.push(dockerContainerStatsSingle(containerID.trim()));
|
||||
}
|
||||
if (workload.length) {
|
||||
Promise.all(
|
||||
workload
|
||||
).then((data) => {
|
||||
if (callback) { callback(data); }
|
||||
resolve(data);
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// container stats (for one container)
|
||||
|
||||
function dockerContainerStatsSingle(containerID) {
|
||||
containerID = containerID || '';
|
||||
let result = {
|
||||
id: containerID,
|
||||
memUsage: 0,
|
||||
memLimit: 0,
|
||||
memPercent: 0,
|
||||
cpuPercent: 0,
|
||||
pids: 0,
|
||||
netIO: {
|
||||
rx: 0,
|
||||
wx: 0
|
||||
},
|
||||
blockIO: {
|
||||
r: 0,
|
||||
w: 0
|
||||
},
|
||||
restartCount: 0,
|
||||
cpuStats: {},
|
||||
precpuStats: {},
|
||||
memoryStats: {},
|
||||
networks: {},
|
||||
};
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
if (containerID) {
|
||||
|
||||
if (!_docker_socket) {
|
||||
_docker_socket = new DockerSocket();
|
||||
}
|
||||
|
||||
_docker_socket.getInspect(containerID, dataInspect => {
|
||||
try {
|
||||
_docker_socket.getStats(containerID, data => {
|
||||
try {
|
||||
let stats = data;
|
||||
if (!stats.message) {
|
||||
if (data.id) { result.id = data.id; }
|
||||
result.memUsage = (stats.memory_stats && stats.memory_stats.usage ? stats.memory_stats.usage : 0);
|
||||
result.memLimit = (stats.memory_stats && stats.memory_stats.limit ? stats.memory_stats.limit : 0);
|
||||
result.memPercent = (stats.memory_stats && stats.memory_stats.usage && stats.memory_stats.limit ? stats.memory_stats.usage / stats.memory_stats.limit * 100.0 : 0);
|
||||
result.cpuPercent = (stats.cpu_stats && stats.precpu_stats ? docker_calcCPUPercent(stats.cpu_stats, stats.precpu_stats) : 0);
|
||||
result.pids = (stats.pids_stats && stats.pids_stats.current ? stats.pids_stats.current : 0);
|
||||
result.restartCount = (dataInspect.RestartCount ? dataInspect.RestartCount : 0);
|
||||
if (stats.networks) { result.netIO = docker_calcNetworkIO(stats.networks); }
|
||||
if (stats.blkio_stats) { result.blockIO = docker_calcBlockIO(stats.blkio_stats); }
|
||||
result.cpuStats = (stats.cpu_stats ? stats.cpu_stats : {});
|
||||
result.precpuStats = (stats.precpu_stats ? stats.precpu_stats : {});
|
||||
result.memoryStats = (stats.memory_stats ? stats.memory_stats : {});
|
||||
result.networks = (stats.networks ? stats.networks : {});
|
||||
}
|
||||
} catch (err) {
|
||||
util.noop();
|
||||
}
|
||||
// }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (err) {
|
||||
util.noop();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.dockerContainerStats = dockerContainerStats;
|
||||
|
||||
// --------------------------
|
||||
// container processes (for one container)
|
||||
|
||||
function dockerContainerProcesses(containerID, callback) {
|
||||
let result = [];
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
containerID = containerID || '';
|
||||
if (typeof containerID !== 'string') {
|
||||
return resolve(result);
|
||||
}
|
||||
const containerIdSanitized = (util.isPrototypePolluted() ? '' : util.sanitizeShellString(containerID, true)).trim();
|
||||
|
||||
if (containerIdSanitized) {
|
||||
|
||||
if (!_docker_socket) {
|
||||
_docker_socket = new DockerSocket();
|
||||
}
|
||||
|
||||
_docker_socket.getProcesses(containerIdSanitized, data => {
|
||||
/**
|
||||
* @namespace
|
||||
* @property {Array} Titles
|
||||
* @property {Array} Processes
|
||||
**/
|
||||
try {
|
||||
if (data && data.Titles && data.Processes) {
|
||||
let titles = data.Titles.map(function (value) {
|
||||
return value.toUpperCase();
|
||||
});
|
||||
let pos_pid = titles.indexOf('PID');
|
||||
let pos_ppid = titles.indexOf('PPID');
|
||||
let pos_pgid = titles.indexOf('PGID');
|
||||
let pos_vsz = titles.indexOf('VSZ');
|
||||
let pos_time = titles.indexOf('TIME');
|
||||
let pos_elapsed = titles.indexOf('ELAPSED');
|
||||
let pos_ni = titles.indexOf('NI');
|
||||
let pos_ruser = titles.indexOf('RUSER');
|
||||
let pos_user = titles.indexOf('USER');
|
||||
let pos_rgroup = titles.indexOf('RGROUP');
|
||||
let pos_group = titles.indexOf('GROUP');
|
||||
let pos_stat = titles.indexOf('STAT');
|
||||
let pos_rss = titles.indexOf('RSS');
|
||||
let pos_command = titles.indexOf('COMMAND');
|
||||
|
||||
data.Processes.forEach(process => {
|
||||
result.push({
|
||||
pidHost: (pos_pid >= 0 ? process[pos_pid] : ''),
|
||||
ppid: (pos_ppid >= 0 ? process[pos_ppid] : ''),
|
||||
pgid: (pos_pgid >= 0 ? process[pos_pgid] : ''),
|
||||
user: (pos_user >= 0 ? process[pos_user] : ''),
|
||||
ruser: (pos_ruser >= 0 ? process[pos_ruser] : ''),
|
||||
group: (pos_group >= 0 ? process[pos_group] : ''),
|
||||
rgroup: (pos_rgroup >= 0 ? process[pos_rgroup] : ''),
|
||||
stat: (pos_stat >= 0 ? process[pos_stat] : ''),
|
||||
time: (pos_time >= 0 ? process[pos_time] : ''),
|
||||
elapsed: (pos_elapsed >= 0 ? process[pos_elapsed] : ''),
|
||||
nice: (pos_ni >= 0 ? process[pos_ni] : ''),
|
||||
rss: (pos_rss >= 0 ? process[pos_rss] : ''),
|
||||
vsz: (pos_vsz >= 0 ? process[pos_vsz] : ''),
|
||||
command: (pos_command >= 0 ? process[pos_command] : '')
|
||||
});
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
util.noop();
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.dockerContainerProcesses = dockerContainerProcesses;
|
||||
|
||||
function dockerVolumes(callback) {
|
||||
|
||||
let result = [];
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
if (!_docker_socket) {
|
||||
_docker_socket = new DockerSocket();
|
||||
}
|
||||
_docker_socket.listVolumes((data) => {
|
||||
let dockerVolumes = {};
|
||||
try {
|
||||
dockerVolumes = data;
|
||||
if (dockerVolumes && dockerVolumes.Volumes && Object.prototype.toString.call(dockerVolumes.Volumes) === '[object Array]' && dockerVolumes.Volumes.length > 0) {
|
||||
|
||||
dockerVolumes.Volumes.forEach(function (element) {
|
||||
|
||||
result.push({
|
||||
name: element.Name,
|
||||
driver: element.Driver,
|
||||
labels: element.Labels,
|
||||
mountpoint: element.Mountpoint,
|
||||
options: element.Options,
|
||||
scope: element.Scope,
|
||||
created: element.CreatedAt ? Math.round(new Date(element.CreatedAt).getTime() / 1000) : 0,
|
||||
});
|
||||
});
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
} catch (err) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.dockerVolumes = dockerVolumes;
|
||||
|
||||
function dockerAll(callback) {
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
dockerContainers(true).then(result => {
|
||||
if (result && Object.prototype.toString.call(result) === '[object Array]' && result.length > 0) {
|
||||
let l = result.length;
|
||||
result.forEach(function (element) {
|
||||
dockerContainerStats(element.id).then((res) => {
|
||||
// include stats in array
|
||||
element.memUsage = res[0].memUsage;
|
||||
element.memLimit = res[0].memLimit;
|
||||
element.memPercent = res[0].memPercent;
|
||||
element.cpuPercent = res[0].cpuPercent;
|
||||
element.pids = res[0].pids;
|
||||
element.netIO = res[0].netIO;
|
||||
element.blockIO = res[0].blockIO;
|
||||
element.cpuStats = res[0].cpuStats;
|
||||
element.precpuStats = res[0].precpuStats;
|
||||
element.memoryStats = res[0].memoryStats;
|
||||
element.networks = res[0].networks;
|
||||
|
||||
dockerContainerProcesses(element.id).then(processes => {
|
||||
element.processes = processes;
|
||||
|
||||
l -= 1;
|
||||
if (l === 0) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
// all done??
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.dockerAll = dockerAll;
|
||||
327
api.hyungi.net/node_modules/systeminformation/lib/dockerSocket.js
generated
vendored
Normal file
327
api.hyungi.net/node_modules/systeminformation/lib/dockerSocket.js
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// dockerSockets.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 13. DockerSockets
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const net = require('net');
|
||||
const isWin = require('os').type() === 'Windows_NT';
|
||||
const socketPath = isWin ? '//./pipe/docker_engine' : '/var/run/docker.sock';
|
||||
|
||||
class DockerSocket {
|
||||
|
||||
getInfo(callback) {
|
||||
try {
|
||||
|
||||
let socket = net.createConnection({ path: socketPath });
|
||||
let alldata = '';
|
||||
let data;
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.write('GET http:/info HTTP/1.0\r\n\r\n');
|
||||
});
|
||||
|
||||
socket.on('data', data => {
|
||||
alldata = alldata + data.toString();
|
||||
});
|
||||
|
||||
socket.on('error', () => {
|
||||
socket = false;
|
||||
callback({});
|
||||
});
|
||||
|
||||
socket.on('end', () => {
|
||||
let startbody = alldata.indexOf('\r\n\r\n');
|
||||
alldata = alldata.substring(startbody + 4);
|
||||
socket = false;
|
||||
try {
|
||||
data = JSON.parse(alldata);
|
||||
callback(data);
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
}
|
||||
|
||||
listImages(all, callback) {
|
||||
try {
|
||||
|
||||
let socket = net.createConnection({ path: socketPath });
|
||||
let alldata = '';
|
||||
let data;
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.write('GET http:/images/json' + (all ? '?all=1' : '') + ' HTTP/1.0\r\n\r\n');
|
||||
});
|
||||
|
||||
socket.on('data', data => {
|
||||
alldata = alldata + data.toString();
|
||||
});
|
||||
|
||||
socket.on('error', () => {
|
||||
socket = false;
|
||||
callback({});
|
||||
});
|
||||
|
||||
socket.on('end', () => {
|
||||
let startbody = alldata.indexOf('\r\n\r\n');
|
||||
alldata = alldata.substring(startbody + 4);
|
||||
socket = false;
|
||||
try {
|
||||
data = JSON.parse(alldata);
|
||||
callback(data);
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
}
|
||||
|
||||
inspectImage(id, callback) {
|
||||
id = id || '';
|
||||
if (id) {
|
||||
try {
|
||||
let socket = net.createConnection({ path: socketPath });
|
||||
let alldata = '';
|
||||
let data;
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.write('GET http:/images/' + id + '/json?stream=0 HTTP/1.0\r\n\r\n');
|
||||
});
|
||||
|
||||
socket.on('data', data => {
|
||||
alldata = alldata + data.toString();
|
||||
});
|
||||
|
||||
socket.on('error', () => {
|
||||
socket = false;
|
||||
callback({});
|
||||
});
|
||||
|
||||
socket.on('end', () => {
|
||||
let startbody = alldata.indexOf('\r\n\r\n');
|
||||
alldata = alldata.substring(startbody + 4);
|
||||
socket = false;
|
||||
try {
|
||||
data = JSON.parse(alldata);
|
||||
callback(data);
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
} else {
|
||||
callback({});
|
||||
}
|
||||
}
|
||||
|
||||
listContainers(all, callback) {
|
||||
try {
|
||||
|
||||
let socket = net.createConnection({ path: socketPath });
|
||||
let alldata = '';
|
||||
let data;
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.write('GET http:/containers/json' + (all ? '?all=1' : '') + ' HTTP/1.0\r\n\r\n');
|
||||
});
|
||||
|
||||
socket.on('data', data => {
|
||||
alldata = alldata + data.toString();
|
||||
});
|
||||
|
||||
socket.on('error', () => {
|
||||
socket = false;
|
||||
callback({});
|
||||
});
|
||||
|
||||
socket.on('end', () => {
|
||||
let startbody = alldata.indexOf('\r\n\r\n');
|
||||
alldata = alldata.substring(startbody + 4);
|
||||
socket = false;
|
||||
try {
|
||||
data = JSON.parse(alldata);
|
||||
callback(data);
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
}
|
||||
|
||||
getStats(id, callback) {
|
||||
id = id || '';
|
||||
if (id) {
|
||||
try {
|
||||
let socket = net.createConnection({ path: socketPath });
|
||||
let alldata = '';
|
||||
let data;
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.write('GET http:/containers/' + id + '/stats?stream=0 HTTP/1.0\r\n\r\n');
|
||||
});
|
||||
|
||||
socket.on('data', data => {
|
||||
alldata = alldata + data.toString();
|
||||
});
|
||||
|
||||
socket.on('error', () => {
|
||||
socket = false;
|
||||
callback({});
|
||||
});
|
||||
|
||||
socket.on('end', () => {
|
||||
let startbody = alldata.indexOf('\r\n\r\n');
|
||||
alldata = alldata.substring(startbody + 4);
|
||||
socket = false;
|
||||
try {
|
||||
data = JSON.parse(alldata);
|
||||
callback(data);
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
} else {
|
||||
callback({});
|
||||
}
|
||||
}
|
||||
|
||||
getInspect(id, callback) {
|
||||
id = id || '';
|
||||
if (id) {
|
||||
try {
|
||||
let socket = net.createConnection({ path: socketPath });
|
||||
let alldata = '';
|
||||
let data;
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.write('GET http:/containers/' + id + '/json?stream=0 HTTP/1.0\r\n\r\n');
|
||||
});
|
||||
|
||||
socket.on('data', data => {
|
||||
alldata = alldata + data.toString();
|
||||
});
|
||||
|
||||
socket.on('error', () => {
|
||||
socket = false;
|
||||
callback({});
|
||||
});
|
||||
|
||||
socket.on('end', () => {
|
||||
let startbody = alldata.indexOf('\r\n\r\n');
|
||||
alldata = alldata.substring(startbody + 4);
|
||||
socket = false;
|
||||
try {
|
||||
data = JSON.parse(alldata);
|
||||
callback(data);
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
} else {
|
||||
callback({});
|
||||
}
|
||||
}
|
||||
|
||||
getProcesses(id, callback) {
|
||||
id = id || '';
|
||||
if (id) {
|
||||
try {
|
||||
let socket = net.createConnection({ path: socketPath });
|
||||
let alldata = '';
|
||||
let data;
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.write('GET http:/containers/' + id + '/top?ps_args=-opid,ppid,pgid,vsz,time,etime,nice,ruser,user,rgroup,group,stat,rss,args HTTP/1.0\r\n\r\n');
|
||||
});
|
||||
|
||||
socket.on('data', data => {
|
||||
alldata = alldata + data.toString();
|
||||
});
|
||||
|
||||
socket.on('error', () => {
|
||||
socket = false;
|
||||
callback({});
|
||||
});
|
||||
|
||||
socket.on('end', () => {
|
||||
let startbody = alldata.indexOf('\r\n\r\n');
|
||||
alldata = alldata.substring(startbody + 4);
|
||||
socket = false;
|
||||
try {
|
||||
data = JSON.parse(alldata);
|
||||
callback(data);
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
} else {
|
||||
callback({});
|
||||
}
|
||||
}
|
||||
|
||||
listVolumes(callback) {
|
||||
try {
|
||||
|
||||
let socket = net.createConnection({ path: socketPath });
|
||||
let alldata = '';
|
||||
let data;
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.write('GET http:/volumes HTTP/1.0\r\n\r\n');
|
||||
});
|
||||
|
||||
socket.on('data', data => {
|
||||
alldata = alldata + data.toString();
|
||||
});
|
||||
|
||||
socket.on('error', () => {
|
||||
socket = false;
|
||||
callback({});
|
||||
});
|
||||
|
||||
socket.on('end', () => {
|
||||
let startbody = alldata.indexOf('\r\n\r\n');
|
||||
alldata = alldata.substring(startbody + 4);
|
||||
socket = false;
|
||||
try {
|
||||
data = JSON.parse(alldata);
|
||||
callback(data);
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
callback({});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DockerSocket;
|
||||
1547
api.hyungi.net/node_modules/systeminformation/lib/filesystem.js
generated
vendored
Normal file
1547
api.hyungi.net/node_modules/systeminformation/lib/filesystem.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1130
api.hyungi.net/node_modules/systeminformation/lib/graphics.js
generated
vendored
Normal file
1130
api.hyungi.net/node_modules/systeminformation/lib/graphics.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1053
api.hyungi.net/node_modules/systeminformation/lib/index.d.ts
generated
vendored
Normal file
1053
api.hyungi.net/node_modules/systeminformation/lib/index.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
513
api.hyungi.net/node_modules/systeminformation/lib/index.js
generated
vendored
Normal file
513
api.hyungi.net/node_modules/systeminformation/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,513 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// index.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Contributors: Guillaume Legrain (https://github.com/glegrain)
|
||||
// Riccardo Novaglia (https://github.com/richy24)
|
||||
// Quentin Busuttil (https://github.com/Buzut)
|
||||
// Lapsio (https://github.com/lapsio)
|
||||
// csy (https://github.com/csy1983)
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Dependencies
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const lib_version = require('../package.json').version;
|
||||
const util = require('./util');
|
||||
const system = require('./system');
|
||||
const osInfo = require('./osinfo');
|
||||
const cpu = require('./cpu');
|
||||
const memory = require('./memory');
|
||||
const battery = require('./battery');
|
||||
const graphics = require('./graphics');
|
||||
const filesystem = require('./filesystem');
|
||||
const network = require('./network');
|
||||
const wifi = require('./wifi');
|
||||
const processes = require('./processes');
|
||||
const users = require('./users');
|
||||
const internet = require('./internet');
|
||||
const docker = require('./docker');
|
||||
const vbox = require('./virtualbox');
|
||||
const printer = require('./printer');
|
||||
const usb = require('./usb');
|
||||
const audio = require('./audio');
|
||||
const bluetooth = require('./bluetooth');
|
||||
|
||||
let _platform = process.platform;
|
||||
const _windows = (_platform === 'win32');
|
||||
const _freebsd = (_platform === 'freebsd');
|
||||
const _openbsd = (_platform === 'openbsd');
|
||||
const _netbsd = (_platform === 'netbsd');
|
||||
const _sunos = (_platform === 'sunos');
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// init
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
if (_windows) {
|
||||
util.getCodepage();
|
||||
util.getPowershell();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// General
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
function version() {
|
||||
return lib_version;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Get static and dynamic data (all)
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------
|
||||
// get static data - they should not change until restarted
|
||||
|
||||
function getStaticData(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
|
||||
let data = {};
|
||||
|
||||
data.version = version();
|
||||
|
||||
Promise.all([
|
||||
system.system(),
|
||||
system.bios(),
|
||||
system.baseboard(),
|
||||
system.chassis(),
|
||||
osInfo.osInfo(),
|
||||
osInfo.uuid(),
|
||||
osInfo.versions(),
|
||||
cpu.cpu(),
|
||||
cpu.cpuFlags(),
|
||||
graphics.graphics(),
|
||||
network.networkInterfaces(),
|
||||
memory.memLayout(),
|
||||
filesystem.diskLayout(),
|
||||
audio.audio(),
|
||||
bluetooth.bluetoothDevices(),
|
||||
usb.usb(),
|
||||
printer.printer(),
|
||||
]).then((res) => {
|
||||
data.system = res[0];
|
||||
data.bios = res[1];
|
||||
data.baseboard = res[2];
|
||||
data.chassis = res[3];
|
||||
data.os = res[4];
|
||||
data.uuid = res[5];
|
||||
data.versions = res[6];
|
||||
data.cpu = res[7];
|
||||
data.cpu.flags = res[8];
|
||||
data.graphics = res[9];
|
||||
data.net = res[10];
|
||||
data.memLayout = res[11];
|
||||
data.diskLayout = res[12];
|
||||
data.audio = res[13];
|
||||
data.bluetooth = res[14];
|
||||
data.usb = res[15];
|
||||
data.printer = res[16];
|
||||
if (callback) { callback(data); }
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// --------------------------
|
||||
// get all dynamic data - e.g. for monitoring agents
|
||||
// may take some seconds to get all data
|
||||
// --------------------------
|
||||
// 2 additional parameters needed
|
||||
// - srv: comma separated list of services to monitor e.g. "mysql, apache, postgresql"
|
||||
// - iface: define network interface for which you like to monitor network speed e.g. "eth0"
|
||||
|
||||
function getDynamicData(srv, iface, callback) {
|
||||
|
||||
if (util.isFunction(iface)) {
|
||||
callback = iface;
|
||||
iface = '';
|
||||
}
|
||||
if (util.isFunction(srv)) {
|
||||
callback = srv;
|
||||
srv = '';
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
|
||||
iface = iface || network.getDefaultNetworkInterface();
|
||||
srv = srv || '';
|
||||
|
||||
// use closure to track ƒ completion
|
||||
let functionProcessed = (function () {
|
||||
let totalFunctions = 15;
|
||||
if (_windows) { totalFunctions = 13; }
|
||||
if (_freebsd || _openbsd || _netbsd) { totalFunctions = 11; }
|
||||
if (_sunos) { totalFunctions = 6; }
|
||||
|
||||
return function () {
|
||||
if (--totalFunctions === 0) {
|
||||
if (callback) {
|
||||
callback(data);
|
||||
}
|
||||
resolve(data);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
let data = {};
|
||||
|
||||
// get time
|
||||
data.time = osInfo.time();
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
* @property {Object} versions
|
||||
* @property {string} versions.node
|
||||
* @property {string} versions.v8
|
||||
*/
|
||||
data.node = process.versions.node;
|
||||
data.v8 = process.versions.v8;
|
||||
|
||||
cpu.cpuCurrentSpeed().then((res) => {
|
||||
data.cpuCurrentSpeed = res;
|
||||
functionProcessed();
|
||||
});
|
||||
|
||||
users.users().then((res) => {
|
||||
data.users = res;
|
||||
functionProcessed();
|
||||
});
|
||||
|
||||
processes.processes().then((res) => {
|
||||
data.processes = res;
|
||||
functionProcessed();
|
||||
});
|
||||
|
||||
cpu.currentLoad().then((res) => {
|
||||
data.currentLoad = res;
|
||||
functionProcessed();
|
||||
});
|
||||
|
||||
if (!_sunos) {
|
||||
cpu.cpuTemperature().then((res) => {
|
||||
data.temp = res;
|
||||
functionProcessed();
|
||||
});
|
||||
}
|
||||
|
||||
if (!_openbsd && !_freebsd && !_netbsd && !_sunos) {
|
||||
network.networkStats(iface).then((res) => {
|
||||
data.networkStats = res;
|
||||
functionProcessed();
|
||||
});
|
||||
}
|
||||
|
||||
if (!_sunos) {
|
||||
network.networkConnections().then((res) => {
|
||||
data.networkConnections = res;
|
||||
functionProcessed();
|
||||
});
|
||||
}
|
||||
|
||||
memory.mem().then((res) => {
|
||||
data.mem = res;
|
||||
functionProcessed();
|
||||
});
|
||||
|
||||
if (!_sunos) {
|
||||
battery().then((res) => {
|
||||
data.battery = res;
|
||||
functionProcessed();
|
||||
});
|
||||
}
|
||||
|
||||
if (!_sunos) {
|
||||
processes.services(srv).then((res) => {
|
||||
data.services = res;
|
||||
functionProcessed();
|
||||
});
|
||||
}
|
||||
|
||||
if (!_sunos) {
|
||||
filesystem.fsSize().then((res) => {
|
||||
data.fsSize = res;
|
||||
functionProcessed();
|
||||
});
|
||||
}
|
||||
|
||||
if (!_windows && !_openbsd && !_freebsd && !_netbsd && !_sunos) {
|
||||
filesystem.fsStats().then((res) => {
|
||||
data.fsStats = res;
|
||||
functionProcessed();
|
||||
});
|
||||
}
|
||||
|
||||
if (!_windows && !_openbsd && !_freebsd && !_netbsd && !_sunos) {
|
||||
filesystem.disksIO().then((res) => {
|
||||
data.disksIO = res;
|
||||
functionProcessed();
|
||||
});
|
||||
}
|
||||
|
||||
if (!_openbsd && !_freebsd && !_netbsd && !_sunos) {
|
||||
wifi.wifiNetworks().then((res) => {
|
||||
data.wifiNetworks = res;
|
||||
functionProcessed();
|
||||
});
|
||||
}
|
||||
|
||||
internet.inetLatency().then((res) => {
|
||||
data.inetLatency = res;
|
||||
functionProcessed();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// get all data at once
|
||||
// --------------------------
|
||||
// 2 additional parameters needed
|
||||
// - srv: comma separated list of services to monitor e.g. "mysql, apache, postgresql"
|
||||
// - iface: define network interface for which you like to monitor network speed e.g. "eth0"
|
||||
|
||||
function getAllData(srv, iface, callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
let data = {};
|
||||
|
||||
if (iface && util.isFunction(iface) && !callback) {
|
||||
callback = iface;
|
||||
iface = '';
|
||||
}
|
||||
|
||||
if (srv && util.isFunction(srv) && !iface && !callback) {
|
||||
callback = srv;
|
||||
srv = '';
|
||||
iface = '';
|
||||
}
|
||||
|
||||
getStaticData().then((res) => {
|
||||
data = res;
|
||||
getDynamicData(srv, iface).then((res) => {
|
||||
for (let key in res) {
|
||||
if ({}.hasOwnProperty.call(res, key)) {
|
||||
data[key] = res[key];
|
||||
}
|
||||
}
|
||||
if (callback) { callback(data); }
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function get(valueObject, callback) {
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
const allPromises = Object.keys(valueObject)
|
||||
.filter(func => ({}.hasOwnProperty.call(exports, func)))
|
||||
.map(func => {
|
||||
const params = valueObject[func].substring(valueObject[func].lastIndexOf('(') + 1, valueObject[func].lastIndexOf(')'));
|
||||
let funcWithoutParams = func.indexOf(')') >= 0 ? func.split(')')[1].trim() : func;
|
||||
funcWithoutParams = func.indexOf('|') >= 0 ? func.split('|')[0].trim() : funcWithoutParams;
|
||||
if (params) {
|
||||
return exports[funcWithoutParams](params);
|
||||
} else {
|
||||
return exports[funcWithoutParams]('');
|
||||
}
|
||||
});
|
||||
|
||||
Promise.all(allPromises).then((data) => {
|
||||
const result = {};
|
||||
let i = 0;
|
||||
for (let key in valueObject) {
|
||||
if ({}.hasOwnProperty.call(valueObject, key) && {}.hasOwnProperty.call(exports, key) && data.length > i) {
|
||||
if (valueObject[key] === '*' || valueObject[key] === 'all') {
|
||||
result[key] = data[i];
|
||||
} else {
|
||||
let keys = valueObject[key];
|
||||
let filter = '';
|
||||
let filterParts = [];
|
||||
// remove params
|
||||
if (keys.indexOf(')') >= 0) {
|
||||
keys = keys.split(')')[1].trim();
|
||||
}
|
||||
// extract filter and remove it from keys
|
||||
if (keys.indexOf('|') >= 0) {
|
||||
filter = keys.split('|')[1].trim();
|
||||
filterParts = filter.split(':');
|
||||
|
||||
keys = keys.split('|')[0].trim();
|
||||
}
|
||||
keys = keys.replace(/,/g, ' ').replace(/ +/g, ' ').split(' ');
|
||||
if (data[i]) {
|
||||
if (Array.isArray(data[i])) {
|
||||
// result is in an array, go through all elements of array and pick only the right ones
|
||||
const partialArray = [];
|
||||
data[i].forEach(element => {
|
||||
let partialRes = {};
|
||||
if (keys.length === 1 && (keys[0] === '*' || keys[0] === 'all')) {
|
||||
partialRes = element;
|
||||
} else {
|
||||
keys.forEach(k => {
|
||||
if ({}.hasOwnProperty.call(element, k)) {
|
||||
partialRes[k] = element[k];
|
||||
}
|
||||
});
|
||||
}
|
||||
// if there is a filter, then just take those elements
|
||||
if (filter && filterParts.length === 2) {
|
||||
if ({}.hasOwnProperty.call(partialRes, filterParts[0].trim())) {
|
||||
const val = partialRes[filterParts[0].trim()];
|
||||
if (typeof val == 'number') {
|
||||
if (val === parseFloat(filterParts[1].trim())) {
|
||||
partialArray.push(partialRes);
|
||||
}
|
||||
} else if (typeof val == 'string') {
|
||||
if (val.toLowerCase() === filterParts[1].trim().toLowerCase()) {
|
||||
partialArray.push(partialRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
partialArray.push(partialRes);
|
||||
}
|
||||
|
||||
});
|
||||
result[key] = partialArray;
|
||||
} else {
|
||||
const partialRes = {};
|
||||
keys.forEach(k => {
|
||||
if ({}.hasOwnProperty.call(data[i], k)) {
|
||||
partialRes[k] = data[i][k];
|
||||
}
|
||||
});
|
||||
result[key] = partialRes;
|
||||
}
|
||||
} else {
|
||||
result[key] = {};
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function observe(valueObject, interval, callback) {
|
||||
let _data = null;
|
||||
|
||||
const result = setInterval(() => {
|
||||
get(valueObject).then((data) => {
|
||||
if (JSON.stringify(_data) !== JSON.stringify(data)) {
|
||||
_data = Object.assign({}, data);
|
||||
callback(data);
|
||||
}
|
||||
});
|
||||
}, interval);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
// export all libs
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
exports.version = version;
|
||||
exports.system = system.system;
|
||||
exports.bios = system.bios;
|
||||
exports.baseboard = system.baseboard;
|
||||
exports.chassis = system.chassis;
|
||||
|
||||
exports.time = osInfo.time;
|
||||
exports.osInfo = osInfo.osInfo;
|
||||
exports.versions = osInfo.versions;
|
||||
exports.shell = osInfo.shell;
|
||||
exports.uuid = osInfo.uuid;
|
||||
|
||||
exports.cpu = cpu.cpu;
|
||||
exports.cpuFlags = cpu.cpuFlags;
|
||||
exports.cpuCache = cpu.cpuCache;
|
||||
exports.cpuCurrentSpeed = cpu.cpuCurrentSpeed;
|
||||
exports.cpuTemperature = cpu.cpuTemperature;
|
||||
exports.currentLoad = cpu.currentLoad;
|
||||
exports.fullLoad = cpu.fullLoad;
|
||||
|
||||
exports.mem = memory.mem;
|
||||
exports.memLayout = memory.memLayout;
|
||||
|
||||
exports.battery = battery;
|
||||
|
||||
exports.graphics = graphics.graphics;
|
||||
|
||||
exports.fsSize = filesystem.fsSize;
|
||||
exports.fsOpenFiles = filesystem.fsOpenFiles;
|
||||
exports.blockDevices = filesystem.blockDevices;
|
||||
exports.fsStats = filesystem.fsStats;
|
||||
exports.disksIO = filesystem.disksIO;
|
||||
exports.diskLayout = filesystem.diskLayout;
|
||||
|
||||
exports.networkInterfaceDefault = network.networkInterfaceDefault;
|
||||
exports.networkGatewayDefault = network.networkGatewayDefault;
|
||||
exports.networkInterfaces = network.networkInterfaces;
|
||||
exports.networkStats = network.networkStats;
|
||||
exports.networkConnections = network.networkConnections;
|
||||
|
||||
exports.wifiNetworks = wifi.wifiNetworks;
|
||||
exports.wifiInterfaces = wifi.wifiInterfaces;
|
||||
exports.wifiConnections = wifi.wifiConnections;
|
||||
|
||||
exports.services = processes.services;
|
||||
exports.processes = processes.processes;
|
||||
exports.processLoad = processes.processLoad;
|
||||
|
||||
exports.users = users.users;
|
||||
|
||||
exports.inetChecksite = internet.inetChecksite;
|
||||
exports.inetLatency = internet.inetLatency;
|
||||
|
||||
exports.dockerInfo = docker.dockerInfo;
|
||||
exports.dockerImages = docker.dockerImages;
|
||||
exports.dockerContainers = docker.dockerContainers;
|
||||
exports.dockerContainerStats = docker.dockerContainerStats;
|
||||
exports.dockerContainerProcesses = docker.dockerContainerProcesses;
|
||||
exports.dockerVolumes = docker.dockerVolumes;
|
||||
exports.dockerAll = docker.dockerAll;
|
||||
|
||||
exports.vboxInfo = vbox.vboxInfo;
|
||||
|
||||
exports.printer = printer.printer;
|
||||
|
||||
exports.usb = usb.usb;
|
||||
|
||||
exports.audio = audio.audio;
|
||||
exports.bluetoothDevices = bluetooth.bluetoothDevices;
|
||||
|
||||
exports.getStaticData = getStaticData;
|
||||
exports.getDynamicData = getDynamicData;
|
||||
exports.getAllData = getAllData;
|
||||
exports.get = get;
|
||||
exports.observe = observe;
|
||||
|
||||
exports.powerShellStart = util.powerShellStart;
|
||||
exports.powerShellRelease = util.powerShellRelease;
|
||||
219
api.hyungi.net/node_modules/systeminformation/lib/internet.js
generated
vendored
Normal file
219
api.hyungi.net/node_modules/systeminformation/lib/internet.js
generated
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// internet.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 12. Internet
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const util = require('./util');
|
||||
|
||||
let _platform = process.platform;
|
||||
|
||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
||||
const _darwin = (_platform === 'darwin');
|
||||
const _windows = (_platform === 'win32');
|
||||
const _freebsd = (_platform === 'freebsd');
|
||||
const _openbsd = (_platform === 'openbsd');
|
||||
const _netbsd = (_platform === 'netbsd');
|
||||
const _sunos = (_platform === 'sunos');
|
||||
|
||||
// --------------------------
|
||||
// check if external site is available
|
||||
|
||||
function inetChecksite(url, callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
let result = {
|
||||
url: url,
|
||||
ok: false,
|
||||
status: 404,
|
||||
ms: null
|
||||
};
|
||||
if (typeof url !== 'string') {
|
||||
if (callback) { callback(result); }
|
||||
return resolve(result);
|
||||
}
|
||||
let urlSanitized = '';
|
||||
const s = util.sanitizeShellString(url, true);
|
||||
const l = util.mathMin(s.length, 2000);
|
||||
for (let i = 0; i <= l; i++) {
|
||||
if (s[i] !== undefined) {
|
||||
try {
|
||||
s[i].__proto__.toLowerCase = util.stringToLower;
|
||||
} catch (e) {
|
||||
Object.setPrototypeOf(s[i], util.stringObj);
|
||||
}
|
||||
|
||||
const sl = s[i].toLowerCase();
|
||||
if (sl && sl[0] && !sl[1] && sl[0].length === 1) {
|
||||
urlSanitized = urlSanitized + sl[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
result.url = urlSanitized;
|
||||
try {
|
||||
if (urlSanitized && !util.isPrototypePolluted()) {
|
||||
try {
|
||||
urlSanitized.__proto__.startsWith = util.stringStartWith;
|
||||
} catch (e) {
|
||||
Object.setPrototypeOf(urlSanitized, util.stringObj);
|
||||
}
|
||||
|
||||
if (urlSanitized.startsWith('file:') || urlSanitized.startsWith('gopher:') || urlSanitized.startsWith('telnet:') || urlSanitized.startsWith('mailto:') || urlSanitized.startsWith('news:') || urlSanitized.startsWith('nntp:')) {
|
||||
if (callback) { callback(result); }
|
||||
return resolve(result);
|
||||
}
|
||||
|
||||
util.checkWebsite(urlSanitized).then((res) => {
|
||||
result.status = res.statusCode;
|
||||
result.ok = res.statusCode >= 200 && res.statusCode <= 399;;
|
||||
result.ms = (result.ok ? res.time : null);
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
} catch (err) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.inetChecksite = inetChecksite;
|
||||
|
||||
// --------------------------
|
||||
// check inet latency
|
||||
|
||||
function inetLatency(host, callback) {
|
||||
|
||||
// fallback - if only callback is given
|
||||
if (util.isFunction(host) && !callback) {
|
||||
callback = host;
|
||||
host = '';
|
||||
}
|
||||
|
||||
host = host || '8.8.8.8';
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
if (typeof host !== 'string') {
|
||||
if (callback) { callback(null); }
|
||||
return resolve(null);
|
||||
}
|
||||
let hostSanitized = '';
|
||||
const s = (util.isPrototypePolluted() ? '8.8.8.8' : util.sanitizeShellString(host, true)).trim();
|
||||
const l = util.mathMin(s.length, 2000);
|
||||
for (let i = 0; i <= l; i++) {
|
||||
if (!(s[i] === undefined)) {
|
||||
try {
|
||||
s[i].__proto__.toLowerCase = util.stringToLower;
|
||||
} catch (e) {
|
||||
Object.setPrototypeOf(s[i], util.stringObj);
|
||||
}
|
||||
|
||||
const sl = s[i].toLowerCase();
|
||||
if (sl && sl[0] && !sl[1]) {
|
||||
hostSanitized = hostSanitized + sl[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
hostSanitized.__proto__.startsWith = util.stringStartWith;
|
||||
} catch (e) {
|
||||
Object.setPrototypeOf(hostSanitized, util.stringObj);
|
||||
}
|
||||
|
||||
if (hostSanitized.startsWith('file:') || hostSanitized.startsWith('gopher:') || hostSanitized.startsWith('telnet:') || hostSanitized.startsWith('mailto:') || hostSanitized.startsWith('news:') || hostSanitized.startsWith('nntp:')) {
|
||||
if (callback) { callback(null); }
|
||||
return resolve(null);
|
||||
}
|
||||
let params;
|
||||
if (_linux || _freebsd || _openbsd || _netbsd || _darwin) {
|
||||
if (_linux) {
|
||||
params = ['-c', '2', '-w', '3', hostSanitized];
|
||||
}
|
||||
if (_freebsd || _openbsd || _netbsd) {
|
||||
params = ['-c', '2', '-t', '3', hostSanitized];
|
||||
}
|
||||
if (_darwin) {
|
||||
params = ['-c2', '-t3', hostSanitized];
|
||||
}
|
||||
util.execSafe('ping', params).then((stdout) => {
|
||||
let result = null;
|
||||
if (stdout) {
|
||||
const lines = stdout.split('\n').filter((line) => (line.indexOf('rtt') >= 0 || line.indexOf('round-trip') >= 0 || line.indexOf('avg') >= 0)).join('\n');
|
||||
|
||||
const line = lines.split('=');
|
||||
if (line.length > 1) {
|
||||
const parts = line[1].split('/');
|
||||
if (parts.length > 1) {
|
||||
result = parseFloat(parts[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
const params = ['-s', '-a', hostSanitized, '56', '2'];
|
||||
const filt = 'avg';
|
||||
util.execSafe('ping', params, { timeout: 3000 }).then((stdout) => {
|
||||
let result = null;
|
||||
if (stdout) {
|
||||
const lines = stdout.split('\n').filter(line => line.indexOf(filt) >= 0).join('\n');
|
||||
const line = lines.split('=');
|
||||
if (line.length > 1) {
|
||||
const parts = line[1].split('/');
|
||||
if (parts.length > 1) {
|
||||
result = parseFloat(parts[1].replace(',', '.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_windows) {
|
||||
let result = null;
|
||||
try {
|
||||
const params = [hostSanitized, '-n', '1'];
|
||||
util.execSafe('ping', params, util.execOptsWin).then((stdout) => {
|
||||
if (stdout) {
|
||||
let lines = stdout.split('\r\n');
|
||||
lines.shift();
|
||||
lines.forEach(function (line) {
|
||||
if ((line.toLowerCase().match(/ms/g) || []).length === 3) {
|
||||
let l = line.replace(/ +/g, ' ').split(' ');
|
||||
if (l.length > 6) {
|
||||
result = parseFloat(l[l.length - 1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.inetLatency = inetLatency;
|
||||
566
api.hyungi.net/node_modules/systeminformation/lib/memory.js
generated
vendored
Normal file
566
api.hyungi.net/node_modules/systeminformation/lib/memory.js
generated
vendored
Normal file
@@ -0,0 +1,566 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// memory.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 5. Memory
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const os = require('os');
|
||||
const exec = require('child_process').exec;
|
||||
const execSync = require('child_process').execSync;
|
||||
const util = require('./util');
|
||||
const fs = require('fs');
|
||||
|
||||
let _platform = process.platform;
|
||||
|
||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
||||
const _darwin = (_platform === 'darwin');
|
||||
const _windows = (_platform === 'win32');
|
||||
const _freebsd = (_platform === 'freebsd');
|
||||
const _openbsd = (_platform === 'openbsd');
|
||||
const _netbsd = (_platform === 'netbsd');
|
||||
const _sunos = (_platform === 'sunos');
|
||||
|
||||
const RAM_manufacturers = {
|
||||
'00CE': 'Samsung Electronics Inc',
|
||||
'014F': 'Transcend Information Inc.',
|
||||
'017A': 'Apacer Technology Inc.',
|
||||
'0198': 'HyperX',
|
||||
'029E': 'Corsair',
|
||||
'02FE': 'Elpida',
|
||||
'04CB': 'A-DATA',
|
||||
'04CD': 'G.Skill International Enterprise',
|
||||
'059B': 'Crucial',
|
||||
'1315': 'Crucial',
|
||||
'2C00': 'Micron Technology Inc.',
|
||||
'5105': 'Qimonda AG i. In.',
|
||||
'802C': 'Micron Technology Inc.',
|
||||
'80AD': 'Hynix Semiconductor Inc.',
|
||||
'80CE': 'Samsung Electronics Inc.',
|
||||
'8551': 'Qimonda AG i. In.',
|
||||
'859B': 'Crucial',
|
||||
'AD00': 'Hynix Semiconductor Inc.',
|
||||
'CE00': 'Samsung Electronics Inc.',
|
||||
'SAMSUNG': 'Samsung Electronics Inc.',
|
||||
'HYNIX': 'Hynix Semiconductor Inc.',
|
||||
'G-SKILL': 'G-Skill International Enterprise',
|
||||
'G.SKILL': 'G-Skill International Enterprise',
|
||||
'TRANSCEND': 'Transcend Information',
|
||||
'APACER': 'Apacer Technology Inc',
|
||||
'MICRON': 'Micron Technology Inc.',
|
||||
'QIMONDA': 'Qimonda AG i. In.',
|
||||
};
|
||||
|
||||
// _______________________________________________________________________________________
|
||||
// | R A M | H D |
|
||||
// |______________________|_________________________| | |
|
||||
// | active buffers/cache | | |
|
||||
// |________________________________________________|___________|_________|______________|
|
||||
// | used free | used free |
|
||||
// |____________________________________________________________|________________________|
|
||||
// | total | swap |
|
||||
// |____________________________________________________________|________________________|
|
||||
|
||||
// free (older versions)
|
||||
// ----------------------------------
|
||||
// # free
|
||||
// total used free shared buffers cached
|
||||
// Mem: 16038 (1) 15653 (2) 384 (3) 0 (4) 236 (5) 14788 (6)
|
||||
// -/+ buffers/cache: 628 (7) 15409 (8)
|
||||
// Swap: 16371 83 16288
|
||||
//
|
||||
// |------------------------------------------------------------|
|
||||
// | R A M |
|
||||
// |______________________|_____________________________________|
|
||||
// | active (2-(5+6) = 7) | available (3+5+6 = 8) |
|
||||
// |______________________|_________________________|___________|
|
||||
// | active | buffers/cache (5+6) | |
|
||||
// |________________________________________________|___________|
|
||||
// | used (2) | free (3) |
|
||||
// |____________________________________________________________|
|
||||
// | total (1) |
|
||||
// |____________________________________________________________|
|
||||
|
||||
//
|
||||
// free (since free von procps-ng 3.3.10)
|
||||
// ----------------------------------
|
||||
// # free
|
||||
// total used free shared buffers/cache available
|
||||
// Mem: 16038 (1) 628 (2) 386 (3) 0 (4) 15024 (5) 14788 (6)
|
||||
// Swap: 16371 83 16288
|
||||
//
|
||||
// |------------------------------------------------------------|
|
||||
// | R A M |
|
||||
// |______________________|_____________________________________|
|
||||
// | | available (6) estimated |
|
||||
// |______________________|_________________________|___________|
|
||||
// | active (2) | buffers/cache (5) | free (3) |
|
||||
// |________________________________________________|___________|
|
||||
// | total (1) |
|
||||
// |____________________________________________________________|
|
||||
//
|
||||
// Reference: http://www.software-architect.net/blog/article/date/2015/06/12/-826c6e5052.html
|
||||
|
||||
// /procs/meminfo - sample (all in kB)
|
||||
//
|
||||
// MemTotal: 32806380 kB
|
||||
// MemFree: 17977744 kB
|
||||
// MemAvailable: 19768972 kB
|
||||
// Buffers: 517028 kB
|
||||
// Cached: 2161876 kB
|
||||
// SwapCached: 456 kB
|
||||
// Active: 12081176 kB
|
||||
// Inactive: 2164616 kB
|
||||
// Active(anon): 10832884 kB
|
||||
// Inactive(anon): 1477272 kB
|
||||
// Active(file): 1248292 kB
|
||||
// Inactive(file): 687344 kB
|
||||
// Unevictable: 0 kB
|
||||
// Mlocked: 0 kB
|
||||
// SwapTotal: 16768892 kB
|
||||
// SwapFree: 16768304 kB
|
||||
// Dirty: 268 kB
|
||||
// Writeback: 0 kB
|
||||
// AnonPages: 11568832 kB
|
||||
// Mapped: 719992 kB
|
||||
// Shmem: 743272 kB
|
||||
// Slab: 335716 kB
|
||||
// SReclaimable: 256364 kB
|
||||
// SUnreclaim: 79352 kB
|
||||
|
||||
function mem(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
|
||||
let result = {
|
||||
total: os.totalmem(),
|
||||
free: os.freemem(),
|
||||
used: os.totalmem() - os.freemem(),
|
||||
|
||||
active: os.totalmem() - os.freemem(), // temporarily (fallback)
|
||||
available: os.freemem(), // temporarily (fallback)
|
||||
buffers: 0,
|
||||
cached: 0,
|
||||
slab: 0,
|
||||
buffcache: 0,
|
||||
reclaimable: 0,
|
||||
|
||||
swaptotal: 0,
|
||||
swapused: 0,
|
||||
swapfree: 0,
|
||||
writeback: null,
|
||||
dirty: null
|
||||
};
|
||||
|
||||
if (_linux) {
|
||||
try {
|
||||
fs.readFile('/proc/meminfo', function (error, stdout) {
|
||||
if (!error) {
|
||||
const lines = stdout.toString().split('\n');
|
||||
result.total = parseInt(util.getValue(lines, 'memtotal'), 10);
|
||||
result.total = result.total ? result.total * 1024 : os.totalmem();
|
||||
result.free = parseInt(util.getValue(lines, 'memfree'), 10);
|
||||
result.free = result.free ? result.free * 1024 : os.freemem();
|
||||
result.used = result.total - result.free;
|
||||
|
||||
result.buffers = parseInt(util.getValue(lines, 'buffers'), 10);
|
||||
result.buffers = result.buffers ? result.buffers * 1024 : 0;
|
||||
result.cached = parseInt(util.getValue(lines, 'cached'), 10);
|
||||
result.cached = result.cached ? result.cached * 1024 : 0;
|
||||
result.slab = parseInt(util.getValue(lines, 'slab'), 10);
|
||||
result.slab = result.slab ? result.slab * 1024 : 0;
|
||||
result.buffcache = result.buffers + result.cached + result.slab;
|
||||
|
||||
let available = parseInt(util.getValue(lines, 'memavailable'), 10);
|
||||
result.available = available ? available * 1024 : result.free + result.buffcache;
|
||||
result.active = result.total - result.available;
|
||||
|
||||
result.swaptotal = parseInt(util.getValue(lines, 'swaptotal'), 10);
|
||||
result.swaptotal = result.swaptotal ? result.swaptotal * 1024 : 0;
|
||||
result.swapfree = parseInt(util.getValue(lines, 'swapfree'), 10);
|
||||
result.swapfree = result.swapfree ? result.swapfree * 1024 : 0;
|
||||
result.swapused = result.swaptotal - result.swapfree;
|
||||
result.writeback = parseInt(util.getValue(lines, 'writeback'), 10);
|
||||
result.writeback = result.writeback ? result.writeback * 1024 : 0;
|
||||
result.dirty = parseInt(util.getValue(lines, 'dirty'), 10);
|
||||
result.dirty = result.dirty ? result.dirty * 1024 : 0;
|
||||
result.reclaimable = parseInt(util.getValue(lines, 'sreclaimable'), 10);
|
||||
result.reclaimable = result.reclaimable ? result.reclaimable * 1024 : 0;
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
if (_freebsd || _openbsd || _netbsd) {
|
||||
try {
|
||||
exec('/sbin/sysctl hw.realmem hw.physmem vm.stats.vm.v_page_count vm.stats.vm.v_wire_count vm.stats.vm.v_active_count vm.stats.vm.v_inactive_count vm.stats.vm.v_cache_count vm.stats.vm.v_free_count vm.stats.vm.v_page_size', function (error, stdout) {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
const pagesize = parseInt(util.getValue(lines, 'vm.stats.vm.v_page_size'), 10);
|
||||
const inactive = parseInt(util.getValue(lines, 'vm.stats.vm.v_inactive_count'), 10) * pagesize;
|
||||
const cache = parseInt(util.getValue(lines, 'vm.stats.vm.v_cache_count'), 10) * pagesize;
|
||||
|
||||
result.total = parseInt(util.getValue(lines, 'hw.realmem'), 10);
|
||||
if (isNaN(result.total)) { result.total = parseInt(util.getValue(lines, 'hw.physmem'), 10); }
|
||||
result.free = parseInt(util.getValue(lines, 'vm.stats.vm.v_free_count'), 10) * pagesize;
|
||||
result.buffcache = inactive + cache;
|
||||
result.available = result.buffcache + result.free;
|
||||
result.active = result.total - result.free - result.buffcache;
|
||||
|
||||
result.swaptotal = 0;
|
||||
result.swapfree = 0;
|
||||
result.swapused = 0;
|
||||
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
if (_sunos) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
if (_darwin) {
|
||||
let pageSize = 4096;
|
||||
try {
|
||||
let sysPpageSize = util.toInt(execSync('sysctl -n vm.pagesize').toString());
|
||||
pageSize = sysPpageSize || pageSize;
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
try {
|
||||
exec('vm_stat 2>/dev/null | egrep "Pages active|Pages inactive"', function (error, stdout) {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
result.active = (parseInt(util.getValue(lines, 'Pages active'), 10) || 0) * pageSize;
|
||||
result.reclaimable = (parseInt(util.getValue(lines, 'Pages inactive'), 10) || 0) * pageSize;
|
||||
result.buffcache = result.used - result.active;
|
||||
result.available = result.free + result.buffcache;
|
||||
}
|
||||
exec('sysctl -n vm.swapusage 2>/dev/null', function (error, stdout) {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
if (lines.length > 0) {
|
||||
let firstline = lines[0].replace(/,/g, '.').replace(/M/g, '');
|
||||
let lineArray = firstline.trim().split(' ');
|
||||
lineArray.forEach(line => {
|
||||
if (line.toLowerCase().indexOf('total') !== -1) { result.swaptotal = parseFloat(line.split('=')[1].trim()) * 1024 * 1024; }
|
||||
if (line.toLowerCase().indexOf('used') !== -1) { result.swapused = parseFloat(line.split('=')[1].trim()) * 1024 * 1024; }
|
||||
if (line.toLowerCase().indexOf('free') !== -1) { result.swapfree = parseFloat(line.split('=')[1].trim()) * 1024 * 1024; }
|
||||
});
|
||||
}
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
if (_windows) {
|
||||
let swaptotal = 0;
|
||||
let swapused = 0;
|
||||
try {
|
||||
util.powerShell('Get-CimInstance Win32_PageFileUsage | Select AllocatedBaseSize, CurrentUsage').then((stdout, error) => {
|
||||
if (!error) {
|
||||
let lines = stdout.split('\r\n').filter(line => line.trim() !== '').filter((line, idx) => idx > 0);
|
||||
lines.forEach(function (line) {
|
||||
if (line !== '') {
|
||||
line = line.trim().split(/\s\s+/);
|
||||
swaptotal = swaptotal + (parseInt(line[0], 10) || 0);
|
||||
swapused = swapused + (parseInt(line[1], 10) || 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
result.swaptotal = swaptotal * 1024 * 1024;
|
||||
result.swapused = swapused * 1024 * 1024;
|
||||
result.swapfree = result.swaptotal - result.swapused;
|
||||
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.mem = mem;
|
||||
|
||||
function memLayout(callback) {
|
||||
|
||||
function getManufacturer(manId) {
|
||||
const manIdSearch = manId.replace('0x', '').toUpperCase();
|
||||
if (manIdSearch.length >= 4 && {}.hasOwnProperty.call(RAM_manufacturers, manIdSearch)) {
|
||||
return (RAM_manufacturers[manIdSearch]);
|
||||
}
|
||||
return manId;
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
|
||||
let result = [];
|
||||
|
||||
if (_linux || _freebsd || _openbsd || _netbsd) {
|
||||
exec('export LC_ALL=C; dmidecode -t memory 2>/dev/null | grep -iE "Size:|Type|Speed|Manufacturer|Form Factor|Locator|Memory Device|Serial Number|Voltage|Part Number"; unset LC_ALL', function (error, stdout) {
|
||||
if (!error) {
|
||||
let devices = stdout.toString().split('Memory Device');
|
||||
devices.shift();
|
||||
devices.forEach(function (device) {
|
||||
let lines = device.split('\n');
|
||||
const sizeString = util.getValue(lines, 'Size');
|
||||
const size = sizeString.indexOf('GB') >= 0 ? parseInt(sizeString, 10) * 1024 * 1024 * 1024 : parseInt(sizeString, 10) * 1024 * 1024;
|
||||
let bank = util.getValue(lines, 'Bank Locator');
|
||||
if (bank.toLowerCase().indexOf('bad') >= 0) {
|
||||
bank = '';
|
||||
}
|
||||
if (parseInt(util.getValue(lines, 'Size'), 10) > 0) {
|
||||
const totalWidth = util.toInt(util.getValue(lines, 'Total Width'));
|
||||
const dataWidth = util.toInt(util.getValue(lines, 'Data Width'));
|
||||
result.push({
|
||||
size,
|
||||
bank,
|
||||
type: util.getValue(lines, 'Type:'),
|
||||
ecc: dataWidth && totalWidth ? totalWidth > dataWidth : false,
|
||||
clockSpeed: (util.getValue(lines, 'Configured Clock Speed:') ? parseInt(util.getValue(lines, 'Configured Clock Speed:'), 10) : (util.getValue(lines, 'Speed:') ? parseInt(util.getValue(lines, 'Speed:'), 10) : null)),
|
||||
formFactor: util.getValue(lines, 'Form Factor:'),
|
||||
manufacturer: getManufacturer(util.getValue(lines, 'Manufacturer:')),
|
||||
partNum: util.getValue(lines, 'Part Number:'),
|
||||
serialNum: util.getValue(lines, 'Serial Number:'),
|
||||
voltageConfigured: parseFloat(util.getValue(lines, 'Configured Voltage:')) || null,
|
||||
voltageMin: parseFloat(util.getValue(lines, 'Minimum Voltage:')) || null,
|
||||
voltageMax: parseFloat(util.getValue(lines, 'Maximum Voltage:')) || null,
|
||||
});
|
||||
} else {
|
||||
result.push({
|
||||
size: 0,
|
||||
bank,
|
||||
type: 'Empty',
|
||||
ecc: null,
|
||||
clockSpeed: 0,
|
||||
formFactor: util.getValue(lines, 'Form Factor:'),
|
||||
partNum: '',
|
||||
serialNum: '',
|
||||
voltageConfigured: null,
|
||||
voltageMin: null,
|
||||
voltageMax: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!result.length) {
|
||||
result.push({
|
||||
size: os.totalmem(),
|
||||
bank: '',
|
||||
type: '',
|
||||
ecc: null,
|
||||
clockSpeed: 0,
|
||||
formFactor: '',
|
||||
partNum: '',
|
||||
serialNum: '',
|
||||
voltageConfigured: null,
|
||||
voltageMin: null,
|
||||
voltageMax: null,
|
||||
});
|
||||
|
||||
// Try Raspberry PI
|
||||
try {
|
||||
let stdout = execSync('cat /proc/cpuinfo 2>/dev/null', util.execOptsLinux);
|
||||
let lines = stdout.toString().split('\n');
|
||||
let version = util.getValue(lines, 'revision', ':', true).toLowerCase();
|
||||
|
||||
if (util.isRaspberry(lines)) {
|
||||
|
||||
const clockSpeed = {
|
||||
'0': 400,
|
||||
'1': 450,
|
||||
'2': 450,
|
||||
'3': 3200,
|
||||
'4': 4267
|
||||
};
|
||||
result[0].type = 'LPDDR2';
|
||||
result[0].type = version && version[2] && (version[2] === '3') ? 'LPDDR4' : result[0].type;
|
||||
result[0].type = version && version[2] && (version[2] === '4') ? 'LPDDR4X' : result[0].type;
|
||||
result[0].ecc = false;
|
||||
result[0].clockSpeed = version && version[2] && clockSpeed[version[2]] || 400;
|
||||
result[0].clockSpeed = version && version[4] && version[4] === 'd' ? 500 : result[0].clockSpeed;
|
||||
result[0].formFactor = 'SoC';
|
||||
|
||||
stdout = execSync('vcgencmd get_config sdram_freq 2>/dev/null', util.execOptsLinux);
|
||||
lines = stdout.toString().split('\n');
|
||||
let freq = parseInt(util.getValue(lines, 'sdram_freq', '=', true), 10) || 0;
|
||||
if (freq) {
|
||||
result[0].clockSpeed = freq;
|
||||
}
|
||||
|
||||
stdout = execSync('vcgencmd measure_volts sdram_p 2>/dev/null', util.execOptsLinux);
|
||||
lines = stdout.toString().split('\n');
|
||||
let voltage = parseFloat(util.getValue(lines, 'volt', '=', true)) || 0;
|
||||
if (voltage) {
|
||||
result[0].voltageConfigured = voltage;
|
||||
result[0].voltageMin = voltage;
|
||||
result[0].voltageMax = voltage;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
|
||||
if (_darwin) {
|
||||
exec('system_profiler SPMemoryDataType', function (error, stdout) {
|
||||
if (!error) {
|
||||
const allLines = stdout.toString().split('\n');
|
||||
const eccStatus = util.getValue(allLines, 'ecc', ':', true).toLowerCase();
|
||||
let devices = stdout.toString().split(' BANK ');
|
||||
let hasBank = true;
|
||||
if (devices.length === 1) {
|
||||
devices = stdout.toString().split(' DIMM');
|
||||
hasBank = false;
|
||||
}
|
||||
devices.shift();
|
||||
devices.forEach(function (device) {
|
||||
let lines = device.split('\n');
|
||||
const bank = (hasBank ? 'BANK ' : 'DIMM') + lines[0].trim().split('/')[0];
|
||||
const size = parseInt(util.getValue(lines, ' Size'));
|
||||
if (size) {
|
||||
result.push({
|
||||
size: size * 1024 * 1024 * 1024,
|
||||
bank: bank,
|
||||
type: util.getValue(lines, ' Type:'),
|
||||
ecc: eccStatus ? eccStatus === 'enabled' : null,
|
||||
clockSpeed: parseInt(util.getValue(lines, ' Speed:'), 10),
|
||||
formFactor: '',
|
||||
manufacturer: getManufacturer(util.getValue(lines, ' Manufacturer:')),
|
||||
partNum: util.getValue(lines, ' Part Number:'),
|
||||
serialNum: util.getValue(lines, ' Serial Number:'),
|
||||
voltageConfigured: null,
|
||||
voltageMin: null,
|
||||
voltageMax: null,
|
||||
});
|
||||
} else {
|
||||
result.push({
|
||||
size: 0,
|
||||
bank: bank,
|
||||
type: 'Empty',
|
||||
ecc: null,
|
||||
clockSpeed: 0,
|
||||
formFactor: '',
|
||||
manufacturer: '',
|
||||
partNum: '',
|
||||
serialNum: '',
|
||||
voltageConfigured: null,
|
||||
voltageMin: null,
|
||||
voltageMax: null,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!result.length) {
|
||||
const lines = stdout.toString().split('\n');
|
||||
const size = parseInt(util.getValue(lines, ' Memory:'));
|
||||
const type = util.getValue(lines, ' Type:');
|
||||
const manufacturerId = util.getValue(lines, ' Manufacturer:');
|
||||
if (size && type) {
|
||||
result.push({
|
||||
size: size * 1024 * 1024 * 1024,
|
||||
bank: '0',
|
||||
type,
|
||||
ecc: false,
|
||||
clockSpeed: null,
|
||||
formFactor: 'SOC',
|
||||
manufacturer: getManufacturer(manufacturerId),
|
||||
partNum: '',
|
||||
serialNum: '',
|
||||
voltageConfigured: null,
|
||||
voltageMin: null,
|
||||
voltageMax: null,
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
if (_windows) {
|
||||
// https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.4.0a.pdf
|
||||
const memoryTypes = 'Unknown|Other|DRAM|Synchronous DRAM|Cache DRAM|EDO|EDRAM|VRAM|SRAM|RAM|ROM|FLASH|EEPROM|FEPROM|EPROM|CDRAM|3DRAM|SDRAM|SGRAM|RDRAM|DDR|DDR2|DDR2 FB-DIMM|Reserved|DDR3|FBD2|DDR4|LPDDR|LPDDR2|LPDDR3|LPDDR4|Logical non-volatile device|HBM|HBM2|DDR5|LPDDR5'.split('|');
|
||||
const FormFactors = 'Unknown|Other|SIP|DIP|ZIP|SOJ|Proprietary|SIMM|DIMM|TSOP|PGA|RIMM|SODIMM|SRIMM|SMD|SSMP|QFP|TQFP|SOIC|LCC|PLCC|BGA|FPBGA|LGA'.split('|');
|
||||
|
||||
try {
|
||||
util.powerShell('Get-CimInstance Win32_PhysicalMemory | select DataWidth,TotalWidth,Capacity,BankLabel,MemoryType,SMBIOSMemoryType,ConfiguredClockSpeed,Speed,FormFactor,Manufacturer,PartNumber,SerialNumber,ConfiguredVoltage,MinVoltage,MaxVoltage,Tag | fl').then((stdout, error) => {
|
||||
if (!error) {
|
||||
let devices = stdout.toString().split(/\n\s*\n/);
|
||||
devices.shift();
|
||||
devices.forEach(function (device) {
|
||||
let lines = device.split('\r\n');
|
||||
const dataWidth = util.toInt(util.getValue(lines, 'DataWidth', ':'));
|
||||
const totalWidth = util.toInt(util.getValue(lines, 'TotalWidth', ':'));
|
||||
const size = parseInt(util.getValue(lines, 'Capacity', ':'), 10) || 0;
|
||||
const tag = util.getValue(lines, 'Tag', ':');
|
||||
const tagInt = util.splitByNumber(tag);
|
||||
if (size) {
|
||||
result.push({
|
||||
size,
|
||||
bank: util.getValue(lines, 'BankLabel', ':') + (tagInt[1] ? '/' + tagInt[1] : ''), // BankLabel
|
||||
type: memoryTypes[parseInt(util.getValue(lines, 'MemoryType', ':'), 10) || parseInt(util.getValue(lines, 'SMBIOSMemoryType', ':'), 10)],
|
||||
ecc: dataWidth && totalWidth ? totalWidth > dataWidth : false,
|
||||
clockSpeed: parseInt(util.getValue(lines, 'ConfiguredClockSpeed', ':'), 10) || parseInt(util.getValue(lines, 'Speed', ':'), 10) || 0,
|
||||
formFactor: FormFactors[parseInt(util.getValue(lines, 'FormFactor', ':'), 10) || 0],
|
||||
manufacturer: getManufacturer(util.getValue(lines, 'Manufacturer', ':')),
|
||||
partNum: util.getValue(lines, 'PartNumber', ':'),
|
||||
serialNum: util.getValue(lines, 'SerialNumber', ':'),
|
||||
voltageConfigured: (parseInt(util.getValue(lines, 'ConfiguredVoltage', ':'), 10) || 0) / 1000.0,
|
||||
voltageMin: (parseInt(util.getValue(lines, 'MinVoltage', ':'), 10) || 0) / 1000.0,
|
||||
voltageMax: (parseInt(util.getValue(lines, 'MaxVoltage', ':'), 10) || 0) / 1000.0,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.memLayout = memLayout;
|
||||
|
||||
1815
api.hyungi.net/node_modules/systeminformation/lib/network.js
generated
vendored
Normal file
1815
api.hyungi.net/node_modules/systeminformation/lib/network.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1273
api.hyungi.net/node_modules/systeminformation/lib/osinfo.js
generated
vendored
Normal file
1273
api.hyungi.net/node_modules/systeminformation/lib/osinfo.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
210
api.hyungi.net/node_modules/systeminformation/lib/printer.js
generated
vendored
Normal file
210
api.hyungi.net/node_modules/systeminformation/lib/printer.js
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// printers.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 15. printers
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const exec = require('child_process').exec;
|
||||
const util = require('./util');
|
||||
|
||||
let _platform = process.platform;
|
||||
|
||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
||||
const _darwin = (_platform === 'darwin');
|
||||
const _windows = (_platform === 'win32');
|
||||
const _freebsd = (_platform === 'freebsd');
|
||||
const _openbsd = (_platform === 'openbsd');
|
||||
const _netbsd = (_platform === 'netbsd');
|
||||
const _sunos = (_platform === 'sunos');
|
||||
|
||||
const winPrinterStatus = {
|
||||
1: 'Other',
|
||||
2: 'Unknown',
|
||||
3: 'Idle',
|
||||
4: 'Printing',
|
||||
5: 'Warmup',
|
||||
6: 'Stopped Printing',
|
||||
7: 'Offline',
|
||||
};
|
||||
|
||||
function parseLinuxCupsHeader(lines) {
|
||||
const result = {};
|
||||
if (lines && lines.length) {
|
||||
if (lines[0].indexOf(' CUPS v') > 0) {
|
||||
const parts = lines[0].split(' CUPS v');
|
||||
result.cupsVersion = parts[1];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseLinuxCupsPrinter(lines) {
|
||||
const result = {};
|
||||
const printerId = util.getValue(lines, 'PrinterId', ' ');
|
||||
result.id = printerId ? parseInt(printerId, 10) : null;
|
||||
result.name = util.getValue(lines, 'Info', ' ');
|
||||
result.model = lines.length > 0 && lines[0] ? lines[0].split(' ')[0] : '';
|
||||
result.uri = util.getValue(lines, 'DeviceURI', ' ');
|
||||
result.uuid = util.getValue(lines, 'UUID', ' ');
|
||||
result.status = util.getValue(lines, 'State', ' ');
|
||||
result.local = util.getValue(lines, 'Location', ' ').toLowerCase().startsWith('local');
|
||||
result.default = null;
|
||||
result.shared = util.getValue(lines, 'Shared', ' ').toLowerCase().startsWith('yes');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseLinuxLpstatPrinter(lines, id) {
|
||||
const result = {};
|
||||
result.id = id;
|
||||
result.name = util.getValue(lines, 'Description', ':', true);
|
||||
result.model = lines.length > 0 && lines[0] ? lines[0].split(' ')[0] : '';
|
||||
result.uri = null;
|
||||
result.uuid = null;
|
||||
result.status = lines.length > 0 && lines[0] ? (lines[0].indexOf(' idle') > 0 ? 'idle' : (lines[0].indexOf(' printing') > 0 ? 'printing' : 'unknown')) : null;
|
||||
result.local = util.getValue(lines, 'Location', ':', true).toLowerCase().startsWith('local');
|
||||
result.default = null;
|
||||
result.shared = util.getValue(lines, 'Shared', ' ').toLowerCase().startsWith('yes');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseDarwinPrinters(printerObject, id) {
|
||||
const result = {};
|
||||
const uriParts = printerObject.uri.split('/');
|
||||
result.id = id;
|
||||
result.name = printerObject._name;
|
||||
result.model = uriParts.length ? uriParts[uriParts.length - 1] : '';
|
||||
result.uri = printerObject.uri;
|
||||
result.uuid = null;
|
||||
result.status = printerObject.status;
|
||||
result.local = printerObject.printserver === 'local';
|
||||
result.default = printerObject.default === 'yes';
|
||||
result.shared = printerObject.shared === 'yes';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseWindowsPrinters(lines, id) {
|
||||
const result = {};
|
||||
const status = parseInt(util.getValue(lines, 'PrinterStatus', ':'), 10);
|
||||
|
||||
result.id = id;
|
||||
result.name = util.getValue(lines, 'name', ':');
|
||||
result.model = util.getValue(lines, 'DriverName', ':');
|
||||
result.uri = null;
|
||||
result.uuid = null;
|
||||
result.status = winPrinterStatus[status] ? winPrinterStatus[status] : null;
|
||||
result.local = util.getValue(lines, 'Local', ':').toUpperCase() === 'TRUE';
|
||||
result.default = util.getValue(lines, 'Default', ':').toUpperCase() === 'TRUE';
|
||||
result.shared = util.getValue(lines, 'Shared', ':').toUpperCase() === 'TRUE';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function printer(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
let result = [];
|
||||
if (_linux || _freebsd || _openbsd || _netbsd) {
|
||||
let cmd = 'cat /etc/cups/printers.conf 2>/dev/null';
|
||||
exec(cmd, function (error, stdout) {
|
||||
// printers.conf
|
||||
if (!error) {
|
||||
const parts = stdout.toString().split('<Printer ');
|
||||
const printerHeader = parseLinuxCupsHeader(parts[0]);
|
||||
for (let i = 1; i < parts.length; i++) {
|
||||
const printers = parseLinuxCupsPrinter(parts[i].split('\n'));
|
||||
if (printers.name) {
|
||||
printers.engine = 'CUPS';
|
||||
printers.engineVersion = printerHeader.cupsVersion;
|
||||
result.push(printers);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.length === 0) {
|
||||
if (_linux) {
|
||||
cmd = 'export LC_ALL=C; lpstat -lp 2>/dev/null; unset LC_ALL';
|
||||
// lpstat
|
||||
exec(cmd, function (error, stdout) {
|
||||
const parts = ('\n' + stdout.toString()).split('\nprinter ');
|
||||
for (let i = 1; i < parts.length; i++) {
|
||||
const printers = parseLinuxLpstatPrinter(parts[i].split('\n'), i);
|
||||
result.push(printers);
|
||||
}
|
||||
});
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (_darwin) {
|
||||
let cmd = 'system_profiler SPPrintersDataType -json';
|
||||
exec(cmd, function (error, stdout) {
|
||||
if (!error) {
|
||||
try {
|
||||
const outObj = JSON.parse(stdout.toString());
|
||||
if (outObj.SPPrintersDataType && outObj.SPPrintersDataType.length) {
|
||||
for (let i = 0; i < outObj.SPPrintersDataType.length; i++) {
|
||||
const printer = parseDarwinPrinters(outObj.SPPrintersDataType[i], i);
|
||||
result.push(printer);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_windows) {
|
||||
util.powerShell('Get-CimInstance Win32_Printer | select PrinterStatus,Name,DriverName,Local,Default,Shared | fl').then((stdout, error) => {
|
||||
if (!error) {
|
||||
const parts = stdout.toString().split(/\n\s*\n/);
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const printer = parseWindowsPrinters(parts[i].split('\n'), i);
|
||||
if (printer.name || printer.model) {
|
||||
result.push(printer);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.printer = printer;
|
||||
1313
api.hyungi.net/node_modules/systeminformation/lib/processes.js
generated
vendored
Normal file
1313
api.hyungi.net/node_modules/systeminformation/lib/processes.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
736
api.hyungi.net/node_modules/systeminformation/lib/system.js
generated
vendored
Normal file
736
api.hyungi.net/node_modules/systeminformation/lib/system.js
generated
vendored
Normal file
@@ -0,0 +1,736 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// system.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 2. System (Hardware, BIOS, Base Board)
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const util = require('./util');
|
||||
const exec = require('child_process').exec;
|
||||
const execSync = require('child_process').execSync;
|
||||
const execPromise = util.promisify(require('child_process').exec);
|
||||
|
||||
let _platform = process.platform;
|
||||
|
||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
||||
const _darwin = (_platform === 'darwin');
|
||||
const _windows = (_platform === 'win32');
|
||||
const _freebsd = (_platform === 'freebsd');
|
||||
const _openbsd = (_platform === 'openbsd');
|
||||
const _netbsd = (_platform === 'netbsd');
|
||||
const _sunos = (_platform === 'sunos');
|
||||
|
||||
function system(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
|
||||
let result = {
|
||||
manufacturer: '',
|
||||
model: 'Computer',
|
||||
version: '',
|
||||
serial: '-',
|
||||
uuid: '-',
|
||||
sku: '-',
|
||||
virtual: false
|
||||
};
|
||||
|
||||
if (_linux || _freebsd || _openbsd || _netbsd) {
|
||||
exec('export LC_ALL=C; dmidecode -t system 2>/dev/null; unset LC_ALL', function (error, stdout) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
result.manufacturer = cleanDefaults(util.getValue(lines, 'manufacturer'));
|
||||
result.model = cleanDefaults(util.getValue(lines, 'product name'));
|
||||
result.version = cleanDefaults(util.getValue(lines, 'version'));
|
||||
result.serial = cleanDefaults(util.getValue(lines, 'serial number'));
|
||||
result.uuid = cleanDefaults((util.getValue(lines, 'uuid'))).toLowerCase();
|
||||
result.sku = cleanDefaults(util.getValue(lines, 'sku number'));
|
||||
// Non-Root values
|
||||
const cmd = `echo -n "product_name: "; cat /sys/devices/virtual/dmi/id/product_name 2>/dev/null; echo;
|
||||
echo -n "product_serial: "; cat /sys/devices/virtual/dmi/id/product_serial 2>/dev/null; echo;
|
||||
echo -n "product_uuid: "; cat /sys/devices/virtual/dmi/id/product_uuid 2>/dev/null; echo;
|
||||
echo -n "product_version: "; cat /sys/devices/virtual/dmi/id/product_version 2>/dev/null; echo;
|
||||
echo -n "sys_vendor: "; cat /sys/devices/virtual/dmi/id/sys_vendor 2>/dev/null; echo;`;
|
||||
try {
|
||||
lines = execSync(cmd, util.execOptsLinux).toString().split('\n');
|
||||
result.manufacturer = cleanDefaults(result.manufacturer === '' ? util.getValue(lines, 'sys_vendor') : result.manufacturer);
|
||||
result.model = cleanDefaults(result.model === '' ? util.getValue(lines, 'product_name') : result.model);
|
||||
result.version = cleanDefaults(result.version === '' ? util.getValue(lines, 'product_version') : result.version);
|
||||
result.serial = cleanDefaults(result.serial === '' ? util.getValue(lines, 'product_serial') : result.serial);
|
||||
result.uuid = cleanDefaults(result.uuid === '' ? util.getValue(lines, 'product_uuid').toLowerCase() : result.uuid);
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
if (!result.serial) { result.serial = '-'; }
|
||||
if (!result.manufacturer) { result.manufacturer = ''; }
|
||||
if (!result.model) { result.model = 'Computer'; }
|
||||
if (!result.version) { result.version = ''; }
|
||||
if (!result.sku) { result.sku = '-'; }
|
||||
|
||||
// detect virtual (1)
|
||||
if (result.model.toLowerCase() === 'virtualbox' || result.model.toLowerCase() === 'kvm' || result.model.toLowerCase() === 'virtual machine' || result.model.toLowerCase() === 'bochs' || result.model.toLowerCase().startsWith('vmware') || result.model.toLowerCase().startsWith('droplet')) {
|
||||
result.virtual = true;
|
||||
switch (result.model.toLowerCase()) {
|
||||
case 'virtualbox':
|
||||
result.virtualHost = 'VirtualBox';
|
||||
break;
|
||||
case 'vmware':
|
||||
result.virtualHost = 'VMware';
|
||||
break;
|
||||
case 'kvm':
|
||||
result.virtualHost = 'KVM';
|
||||
break;
|
||||
case 'bochs':
|
||||
result.virtualHost = 'bochs';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result.manufacturer.toLowerCase().startsWith('vmware') || result.manufacturer.toLowerCase() === 'xen') {
|
||||
result.virtual = true;
|
||||
switch (result.manufacturer.toLowerCase()) {
|
||||
case 'vmware':
|
||||
result.virtualHost = 'VMware';
|
||||
break;
|
||||
case 'xen':
|
||||
result.virtualHost = 'Xen';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!result.virtual) {
|
||||
try {
|
||||
const disksById = execSync('ls -1 /dev/disk/by-id/ 2>/dev/null', util.execOptsLinux).toString();
|
||||
if (disksById.indexOf('_QEMU_') >= 0) {
|
||||
result.virtual = true;
|
||||
result.virtualHost = 'QEMU';
|
||||
}
|
||||
if (disksById.indexOf('_VBOX_') >= 0) {
|
||||
result.virtual = true;
|
||||
result.virtualHost = 'VirtualBox';
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
}
|
||||
if (!result.virtual && (os.release().toLowerCase().indexOf('microsoft') >= 0 || os.release().toLowerCase().endsWith('wsl2'))) {
|
||||
const kernelVersion = parseFloat(os.release().toLowerCase());
|
||||
result.virtual = true;
|
||||
result.manufacturer = 'Microsoft';
|
||||
result.model = 'WSL';
|
||||
result.version = kernelVersion < 4.19 ? '1' : '2';
|
||||
}
|
||||
if ((_freebsd || _openbsd || _netbsd) && !result.virtualHost) {
|
||||
try {
|
||||
const procInfo = execSync('dmidecode -t 4', util.execOptsLinux);
|
||||
const procLines = procInfo.toString().split('\n');
|
||||
const procManufacturer = util.getValue(procLines, 'manufacturer', ':', true);
|
||||
switch (procManufacturer.toLowerCase()) {
|
||||
case 'virtualbox':
|
||||
result.virtualHost = 'VirtualBox';
|
||||
break;
|
||||
case 'vmware':
|
||||
result.virtualHost = 'VMware';
|
||||
break;
|
||||
case 'kvm':
|
||||
result.virtualHost = 'KVM';
|
||||
break;
|
||||
case 'bochs':
|
||||
result.virtualHost = 'bochs';
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
}
|
||||
// detect docker
|
||||
if (fs.existsSync('/.dockerenv') || fs.existsSync('/.dockerinit')) {
|
||||
result.model = 'Docker Container';
|
||||
}
|
||||
try {
|
||||
const stdout = execSync('dmesg 2>/dev/null | grep -iE "virtual|hypervisor" | grep -iE "vmware|qemu|kvm|xen" | grep -viE "Nested Virtualization|/virtual/"');
|
||||
// detect virtual machines
|
||||
let lines = stdout.toString().split('\n');
|
||||
if (lines.length > 0) {
|
||||
if (result.model === 'Computer') { result.model = 'Virtual machine'; }
|
||||
result.virtual = true;
|
||||
if (stdout.toString().toLowerCase().indexOf('vmware') >= 0 && !result.virtualHost) {
|
||||
result.virtualHost = 'VMware';
|
||||
}
|
||||
if (stdout.toString().toLowerCase().indexOf('qemu') >= 0 && !result.virtualHost) {
|
||||
result.virtualHost = 'QEMU';
|
||||
}
|
||||
if (stdout.toString().toLowerCase().indexOf('xen') >= 0 && !result.virtualHost) {
|
||||
result.virtualHost = 'Xen';
|
||||
}
|
||||
if (stdout.toString().toLowerCase().indexOf('kvm') >= 0 && !result.virtualHost) {
|
||||
result.virtualHost = 'KVM';
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
|
||||
if (result.manufacturer === '' && result.model === 'Computer' && result.version === '') {
|
||||
// Check Raspberry Pi
|
||||
fs.readFile('/proc/cpuinfo', function (error, stdout) {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
result.model = util.getValue(lines, 'hardware', ':', true).toUpperCase();
|
||||
result.version = util.getValue(lines, 'revision', ':', true).toLowerCase();
|
||||
result.serial = util.getValue(lines, 'serial', ':', true);
|
||||
const model = util.getValue(lines, 'model:', ':', true);
|
||||
// reference values: https://elinux.org/RPi_HardwareHistory
|
||||
// https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
|
||||
if (util.isRaspberry(lines)) {
|
||||
const rPIRevision = util.decodePiCpuinfo(lines);
|
||||
result.model = rPIRevision.model;
|
||||
result.version = rPIRevision.revisionCode;
|
||||
result.manufacturer = 'Raspberry Pi Foundation';
|
||||
result.raspberry = {
|
||||
manufacturer: rPIRevision.manufacturer,
|
||||
processor: rPIRevision.processor,
|
||||
type: rPIRevision.type,
|
||||
revision: rPIRevision.revision
|
||||
};
|
||||
}
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (_darwin) {
|
||||
exec('ioreg -c IOPlatformExpertDevice -d 2', function (error, stdout) {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().replace(/[<>"]/g, '').split('\n');
|
||||
|
||||
const model = util.getAppleModel(util.getValue(lines, 'model', '=', true));
|
||||
// const modelParts = util.splitByNumber(model);
|
||||
// const version = util.getValue(lines, 'version', '=', true);
|
||||
result.manufacturer = util.getValue(lines, 'manufacturer', '=', true);
|
||||
result.model = model.key;
|
||||
result.type = macOsChassisType(model.version);
|
||||
result.version = model.version;
|
||||
result.serial = util.getValue(lines, 'ioplatformserialnumber', '=', true);
|
||||
result.uuid = util.getValue(lines, 'ioplatformuuid', '=', true).toLowerCase();
|
||||
result.sku = util.getValue(lines, 'board-id', '=', true) || util.getValue(lines, 'target-sub-type', '=', true);
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
if (_windows) {
|
||||
try {
|
||||
util.powerShell('Get-CimInstance Win32_ComputerSystemProduct | select Name,Vendor,Version,IdentifyingNumber,UUID | fl').then((stdout, error) => {
|
||||
if (!error) {
|
||||
let lines = stdout.split('\r\n');
|
||||
result.manufacturer = util.getValue(lines, 'vendor', ':');
|
||||
result.model = util.getValue(lines, 'name', ':');
|
||||
result.version = util.getValue(lines, 'version', ':');
|
||||
result.serial = util.getValue(lines, 'identifyingnumber', ':');
|
||||
result.uuid = util.getValue(lines, 'uuid', ':').toLowerCase();
|
||||
// detect virtual (1)
|
||||
const model = result.model.toLowerCase();
|
||||
if (model === 'virtualbox' || model === 'kvm' || model === 'virtual machine' || model === 'bochs' || model.startsWith('vmware') || model.startsWith('qemu') || model.startsWith('parallels')) {
|
||||
result.virtual = true;
|
||||
if (model.startsWith('virtualbox')) { result.virtualHost = 'VirtualBox'; }
|
||||
if (model.startsWith('vmware')) { result.virtualHost = 'VMware'; }
|
||||
if (model.startsWith('kvm')) { result.virtualHost = 'KVM'; }
|
||||
if (model.startsWith('bochs')) { result.virtualHost = 'bochs'; }
|
||||
if (model.startsWith('qemu')) { result.virtualHost = 'KVM'; }
|
||||
if (model.startsWith('parallels')) { result.virtualHost = 'Parallels'; }
|
||||
}
|
||||
const manufacturer = result.manufacturer.toLowerCase();
|
||||
if (manufacturer.startsWith('vmware') || manufacturer.startsWith('qemu') || manufacturer === 'xen' || manufacturer.startsWith('parallels')) {
|
||||
result.virtual = true;
|
||||
if (manufacturer.startsWith('vmware')) { result.virtualHost = 'VMware'; }
|
||||
if (manufacturer.startsWith('xen')) { result.virtualHost = 'Xen'; }
|
||||
if (manufacturer.startsWith('qemu')) { result.virtualHost = 'KVM'; }
|
||||
if (manufacturer.startsWith('parallels')) { result.virtualHost = 'Parallels'; }
|
||||
}
|
||||
util.powerShell('Get-CimInstance MS_Systeminformation -Namespace "root/wmi" | select systemsku | fl ').then((stdout, error) => {
|
||||
if (!error) {
|
||||
let lines = stdout.split('\r\n');
|
||||
result.sku = util.getValue(lines, 'systemsku', ':');
|
||||
}
|
||||
if (!result.virtual) {
|
||||
util.powerShell('Get-CimInstance Win32_bios | select Version, SerialNumber, SMBIOSBIOSVersion').then((stdout, error) => {
|
||||
if (!error) {
|
||||
let lines = stdout.toString();
|
||||
if (lines.indexOf('VRTUAL') >= 0 || lines.indexOf('A M I ') >= 0 || lines.indexOf('VirtualBox') >= 0 || lines.indexOf('VMWare') >= 0 || lines.indexOf('Xen') >= 0 || lines.indexOf('Parallels') >= 0) {
|
||||
result.virtual = true;
|
||||
if (lines.indexOf('VirtualBox') >= 0 && !result.virtualHost) {
|
||||
result.virtualHost = 'VirtualBox';
|
||||
}
|
||||
if (lines.indexOf('VMware') >= 0 && !result.virtualHost) {
|
||||
result.virtualHost = 'VMware';
|
||||
}
|
||||
if (lines.indexOf('Xen') >= 0 && !result.virtualHost) {
|
||||
result.virtualHost = 'Xen';
|
||||
}
|
||||
if (lines.indexOf('VRTUAL') >= 0 && !result.virtualHost) {
|
||||
result.virtualHost = 'Hyper-V';
|
||||
}
|
||||
if (lines.indexOf('A M I') >= 0 && !result.virtualHost) {
|
||||
result.virtualHost = 'Virtual PC';
|
||||
}
|
||||
if (lines.indexOf('Parallels') >= 0 && !result.virtualHost) {
|
||||
result.virtualHost = 'Parallels';
|
||||
}
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.system = system;
|
||||
|
||||
function cleanDefaults(s) {
|
||||
const cmpStr = s.toLowerCase();
|
||||
if (cmpStr.indexOf('o.e.m.') === -1 && cmpStr.indexOf('default string') === -1 && cmpStr !== 'default') {
|
||||
return s || '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
function bios(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
|
||||
let result = {
|
||||
vendor: '',
|
||||
version: '',
|
||||
releaseDate: '',
|
||||
revision: '',
|
||||
};
|
||||
let cmd = '';
|
||||
if (_linux || _freebsd || _openbsd || _netbsd) {
|
||||
if (process.arch === 'arm') {
|
||||
cmd = 'cat /proc/cpuinfo | grep Serial';
|
||||
} else {
|
||||
cmd = 'export LC_ALL=C; dmidecode -t bios 2>/dev/null; unset LC_ALL';
|
||||
}
|
||||
exec(cmd, function (error, stdout) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
result.vendor = util.getValue(lines, 'Vendor');
|
||||
result.version = util.getValue(lines, 'Version');
|
||||
let datetime = util.getValue(lines, 'Release Date');
|
||||
result.releaseDate = util.parseDateTime(datetime).date;
|
||||
result.revision = util.getValue(lines, 'BIOS Revision');
|
||||
result.serial = util.getValue(lines, 'SerialNumber');
|
||||
let language = util.getValue(lines, 'Currently Installed Language').split('|')[0];
|
||||
if (language) {
|
||||
result.language = language;
|
||||
}
|
||||
if (lines.length && stdout.toString().indexOf('Characteristics:') >= 0) {
|
||||
const features = [];
|
||||
lines.forEach(line => {
|
||||
if (line.indexOf(' is supported') >= 0) {
|
||||
const feature = line.split(' is supported')[0].trim();
|
||||
features.push(feature);
|
||||
}
|
||||
});
|
||||
result.features = features;
|
||||
}
|
||||
// Non-Root values
|
||||
const cmd = `echo -n "bios_date: "; cat /sys/devices/virtual/dmi/id/bios_date 2>/dev/null; echo;
|
||||
echo -n "bios_vendor: "; cat /sys/devices/virtual/dmi/id/bios_vendor 2>/dev/null; echo;
|
||||
echo -n "bios_version: "; cat /sys/devices/virtual/dmi/id/bios_version 2>/dev/null; echo;`;
|
||||
try {
|
||||
lines = execSync(cmd, util.execOptsLinux).toString().split('\n');
|
||||
result.vendor = !result.vendor ? util.getValue(lines, 'bios_vendor') : result.vendor;
|
||||
result.version = !result.version ? util.getValue(lines, 'bios_version') : result.version;
|
||||
datetime = util.getValue(lines, 'bios_date');
|
||||
result.releaseDate = !result.releaseDate ? util.parseDateTime(datetime).date : result.releaseDate;
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_darwin) {
|
||||
result.vendor = 'Apple Inc.';
|
||||
exec(
|
||||
'system_profiler SPHardwareDataType -json', function (error, stdout) {
|
||||
try {
|
||||
const hardwareData = JSON.parse(stdout.toString());
|
||||
if (hardwareData && hardwareData.SPHardwareDataType && hardwareData.SPHardwareDataType.length) {
|
||||
let bootRomVersion = hardwareData.SPHardwareDataType[0].boot_rom_version;
|
||||
bootRomVersion = bootRomVersion ? bootRomVersion.split('(')[0].trim() : null;
|
||||
result.version = bootRomVersion;
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
result.vendor = 'Sun Microsystems';
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
if (_windows) {
|
||||
try {
|
||||
util.powerShell('Get-CimInstance Win32_bios | select Description,Version,Manufacturer,@{n="ReleaseDate";e={$_.ReleaseDate.ToString("yyyy-MM-dd")}},BuildNumber,SerialNumber,SMBIOSBIOSVersion | fl').then((stdout, error) => {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\r\n');
|
||||
const description = util.getValue(lines, 'description', ':');
|
||||
const version = util.getValue(lines, 'SMBIOSBIOSVersion', ':');
|
||||
if (description.indexOf(' Version ') !== -1) {
|
||||
// ... Phoenix ROM BIOS PLUS Version 1.10 A04
|
||||
result.vendor = description.split(' Version ')[0].trim();
|
||||
result.version = description.split(' Version ')[1].trim();
|
||||
} else if (description.indexOf(' Ver: ') !== -1) {
|
||||
// ... BIOS Date: 06/27/16 17:50:16 Ver: 1.4.5
|
||||
result.vendor = util.getValue(lines, 'manufacturer', ':');
|
||||
result.version = description.split(' Ver: ')[1].trim();
|
||||
} else {
|
||||
result.vendor = util.getValue(lines, 'manufacturer', ':');
|
||||
result.version = version || util.getValue(lines, 'version', ':');
|
||||
}
|
||||
result.releaseDate = util.getValue(lines, 'releasedate', ':');
|
||||
result.revision = util.getValue(lines, 'buildnumber', ':');
|
||||
result.serial = cleanDefaults(util.getValue(lines, 'serialnumber', ':'));
|
||||
}
|
||||
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.bios = bios;
|
||||
|
||||
function baseboard(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
|
||||
let result = {
|
||||
manufacturer: '',
|
||||
model: '',
|
||||
version: '',
|
||||
serial: '-',
|
||||
assetTag: '-',
|
||||
memMax: null,
|
||||
memSlots: null
|
||||
};
|
||||
let cmd = '';
|
||||
if (_linux || _freebsd || _openbsd || _netbsd) {
|
||||
if (process.arch === 'arm') {
|
||||
cmd = 'cat /proc/cpuinfo | grep Serial';
|
||||
// 'BCM2709', 'BCM2835', 'BCM2708' -->
|
||||
} else {
|
||||
cmd = 'export LC_ALL=C; dmidecode -t 2 2>/dev/null; unset LC_ALL';
|
||||
}
|
||||
const workload = [];
|
||||
workload.push(execPromise(cmd));
|
||||
workload.push(execPromise('export LC_ALL=C; dmidecode -t memory 2>/dev/null'));
|
||||
util.promiseAll(
|
||||
workload
|
||||
).then((data) => {
|
||||
let lines = data.results[0] ? data.results[0].toString().split('\n') : [''];
|
||||
result.manufacturer = cleanDefaults(util.getValue(lines, 'Manufacturer'));
|
||||
result.model = cleanDefaults(util.getValue(lines, 'Product Name'));
|
||||
result.version = cleanDefaults(util.getValue(lines, 'Version'));
|
||||
result.serial = cleanDefaults(util.getValue(lines, 'Serial Number'));
|
||||
result.assetTag = cleanDefaults(util.getValue(lines, 'Asset Tag'));
|
||||
// Non-Root values
|
||||
const cmd = `echo -n "board_asset_tag: "; cat /sys/devices/virtual/dmi/id/board_asset_tag 2>/dev/null; echo;
|
||||
echo -n "board_name: "; cat /sys/devices/virtual/dmi/id/board_name 2>/dev/null; echo;
|
||||
echo -n "board_serial: "; cat /sys/devices/virtual/dmi/id/board_serial 2>/dev/null; echo;
|
||||
echo -n "board_vendor: "; cat /sys/devices/virtual/dmi/id/board_vendor 2>/dev/null; echo;
|
||||
echo -n "board_version: "; cat /sys/devices/virtual/dmi/id/board_version 2>/dev/null; echo;`;
|
||||
try {
|
||||
lines = execSync(cmd, util.execOptsLinux).toString().split('\n');
|
||||
result.manufacturer = cleanDefaults(!result.manufacturer ? util.getValue(lines, 'board_vendor') : result.manufacturer);
|
||||
result.model = cleanDefaults(!result.model ? util.getValue(lines, 'board_name') : result.model);
|
||||
result.version = cleanDefaults(!result.version ? util.getValue(lines, 'board_version') : result.version);
|
||||
result.serial = cleanDefaults(!result.serial ? util.getValue(lines, 'board_serial') : result.serial);
|
||||
result.assetTag = cleanDefaults(!result.assetTag ? util.getValue(lines, 'board_asset_tag') : result.assetTag);
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
|
||||
// mem
|
||||
lines = data.results[1] ? data.results[1].toString().split('\n') : [''];
|
||||
result.memMax = util.toInt(util.getValue(lines, 'Maximum Capacity')) * 1024 * 1024 * 1024 || null;
|
||||
result.memSlots = util.toInt(util.getValue(lines, 'Number Of Devices')) || null;
|
||||
|
||||
// raspberry
|
||||
if (util.isRaspberry()) {
|
||||
const rpi = util.decodePiCpuinfo();
|
||||
result.manufacturer = rpi.manufacturer;
|
||||
result.model = 'Raspberry Pi';
|
||||
result.serial = rpi.serial;
|
||||
result.version = rpi.type + ' - ' + rpi.revision;
|
||||
result.memMax = os.totalmem();
|
||||
result.memSlots = 0;
|
||||
}
|
||||
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_darwin) {
|
||||
const workload = [];
|
||||
workload.push(execPromise('ioreg -c IOPlatformExpertDevice -d 2'));
|
||||
workload.push(execPromise('system_profiler SPMemoryDataType'));
|
||||
util.promiseAll(
|
||||
workload
|
||||
).then((data) => {
|
||||
let lines = data.results[0] ? data.results[0].toString().replace(/[<>"]/g, '').split('\n') : [''];
|
||||
result.manufacturer = util.getValue(lines, 'manufacturer', '=', true);
|
||||
result.model = util.getValue(lines, 'model', '=', true);
|
||||
result.version = util.getValue(lines, 'version', '=', true);
|
||||
result.serial = util.getValue(lines, 'ioplatformserialnumber', '=', true);
|
||||
result.assetTag = util.getValue(lines, 'board-id', '=', true);
|
||||
|
||||
// mem
|
||||
let devices = data.results[1] ? data.results[1].toString().split(' BANK ') : [''];
|
||||
if (devices.length === 1) {
|
||||
devices = data.results[1] ? data.results[1].toString().split(' DIMM') : [''];
|
||||
}
|
||||
devices.shift();
|
||||
result.memSlots = devices.length;
|
||||
|
||||
if (os.arch() === 'arm64') {
|
||||
result.memSlots = 0;
|
||||
result.memMax = os.totalmem();
|
||||
}
|
||||
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
if (_windows) {
|
||||
try {
|
||||
const workload = [];
|
||||
const win10plus = parseInt(os.release()) >= 10;
|
||||
const maxCapacityAttribute = win10plus ? 'MaxCapacityEx' : 'MaxCapacity';
|
||||
workload.push(util.powerShell('Get-CimInstance Win32_baseboard | select Model,Manufacturer,Product,Version,SerialNumber,PartNumber,SKU | fl'));
|
||||
workload.push(util.powerShell(`Get-CimInstance Win32_physicalmemoryarray | select ${maxCapacityAttribute}, MemoryDevices | fl`));
|
||||
util.promiseAll(
|
||||
workload
|
||||
).then((data) => {
|
||||
let lines = data.results[0] ? data.results[0].toString().split('\r\n') : [''];
|
||||
|
||||
result.manufacturer = cleanDefaults(util.getValue(lines, 'manufacturer', ':'));
|
||||
result.model = cleanDefaults(util.getValue(lines, 'model', ':'));
|
||||
if (!result.model) {
|
||||
result.model = cleanDefaults(util.getValue(lines, 'product', ':'));
|
||||
}
|
||||
result.version = cleanDefaults(util.getValue(lines, 'version', ':'));
|
||||
result.serial = cleanDefaults(util.getValue(lines, 'serialnumber', ':'));
|
||||
result.assetTag = cleanDefaults(util.getValue(lines, 'partnumber', ':'));
|
||||
if (!result.assetTag) {
|
||||
result.assetTag = cleanDefaults(util.getValue(lines, 'sku', ':'));
|
||||
}
|
||||
|
||||
// memphysical
|
||||
lines = data.results[1] ? data.results[1].toString().split('\r\n') : [''];
|
||||
result.memMax = util.toInt(util.getValue(lines, maxCapacityAttribute, ':')) * (win10plus ? 1024 : 1) || null;
|
||||
result.memSlots = util.toInt(util.getValue(lines, 'MemoryDevices', ':')) || null;
|
||||
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.baseboard = baseboard;
|
||||
|
||||
function macOsChassisType(model) {
|
||||
model = model.toLowerCase();
|
||||
if (model.indexOf('macbookair') >= 0 || model.indexOf('macbook air') >= 0) { return 'Notebook'; }
|
||||
if (model.indexOf('macbookpro') >= 0 || model.indexOf('macbook pro') >= 0) { return 'Notebook'; }
|
||||
if (model.indexOf('macbook') >= 0) { return 'Notebook'; }
|
||||
if (model.indexOf('macmini') >= 0 || model.indexOf('mac mini') >= 0) { return 'Desktop'; }
|
||||
if (model.indexOf('imac') >= 0) { return 'Desktop'; }
|
||||
if (model.indexOf('macstudio') >= 0 || model.indexOf('mac studio') >= 0) { return 'Desktop'; }
|
||||
if (model.indexOf('macpro') >= 0 || model.indexOf('mac pro') >= 0) { return 'Tower'; }
|
||||
return 'Other';
|
||||
}
|
||||
|
||||
function chassis(callback) {
|
||||
const chassisTypes = ['Other',
|
||||
'Unknown',
|
||||
'Desktop',
|
||||
'Low Profile Desktop',
|
||||
'Pizza Box',
|
||||
'Mini Tower',
|
||||
'Tower',
|
||||
'Portable',
|
||||
'Laptop',
|
||||
'Notebook',
|
||||
'Hand Held',
|
||||
'Docking Station',
|
||||
'All in One',
|
||||
'Sub Notebook',
|
||||
'Space-Saving',
|
||||
'Lunch Box',
|
||||
'Main System Chassis',
|
||||
'Expansion Chassis',
|
||||
'SubChassis',
|
||||
'Bus Expansion Chassis',
|
||||
'Peripheral Chassis',
|
||||
'Storage Chassis',
|
||||
'Rack Mount Chassis',
|
||||
'Sealed-Case PC',
|
||||
'Multi-System Chassis',
|
||||
'Compact PCI',
|
||||
'Advanced TCA',
|
||||
'Blade',
|
||||
'Blade Enclosure',
|
||||
'Tablet',
|
||||
'Convertible',
|
||||
'Detachable',
|
||||
'IoT Gateway ',
|
||||
'Embedded PC',
|
||||
'Mini PC',
|
||||
'Stick PC',
|
||||
];
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
|
||||
let result = {
|
||||
manufacturer: '',
|
||||
model: '',
|
||||
type: '',
|
||||
version: '',
|
||||
serial: '-',
|
||||
assetTag: '-',
|
||||
sku: '',
|
||||
};
|
||||
if (_linux || _freebsd || _openbsd || _netbsd) {
|
||||
const cmd = `echo -n "chassis_asset_tag: "; cat /sys/devices/virtual/dmi/id/chassis_asset_tag 2>/dev/null; echo;
|
||||
echo -n "chassis_serial: "; cat /sys/devices/virtual/dmi/id/chassis_serial 2>/dev/null; echo;
|
||||
echo -n "chassis_type: "; cat /sys/devices/virtual/dmi/id/chassis_type 2>/dev/null; echo;
|
||||
echo -n "chassis_vendor: "; cat /sys/devices/virtual/dmi/id/chassis_vendor 2>/dev/null; echo;
|
||||
echo -n "chassis_version: "; cat /sys/devices/virtual/dmi/id/chassis_version 2>/dev/null; echo;`;
|
||||
exec(cmd, function (error, stdout) {
|
||||
let lines = stdout.toString().split('\n');
|
||||
result.manufacturer = cleanDefaults(util.getValue(lines, 'chassis_vendor'));
|
||||
const ctype = parseInt(util.getValue(lines, 'chassis_type').replace(/\D/g, ''));
|
||||
result.type = cleanDefaults((ctype && !isNaN(ctype) && ctype < chassisTypes.length) ? chassisTypes[ctype - 1] : '');
|
||||
result.version = cleanDefaults(util.getValue(lines, 'chassis_version'));
|
||||
result.serial = cleanDefaults(util.getValue(lines, 'chassis_serial'));
|
||||
result.assetTag = cleanDefaults(util.getValue(lines, 'chassis_asset_tag'));
|
||||
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_darwin) {
|
||||
exec('ioreg -c IOPlatformExpertDevice -d 2', function (error, stdout) {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().replace(/[<>"]/g, '').split('\n');
|
||||
const model = util.getAppleModel(util.getValue(lines, 'model', '=', true));
|
||||
// const modelParts = util.splitByNumber(model);
|
||||
// const version = util.getValue(lines, 'version', '=', true);
|
||||
result.manufacturer = util.getValue(lines, 'manufacturer', '=', true);
|
||||
result.model = model.key;
|
||||
result.type = macOsChassisType(model.model);
|
||||
result.version = model.version;
|
||||
result.serial = util.getValue(lines, 'ioplatformserialnumber', '=', true);
|
||||
result.assetTag = util.getValue(lines, 'board-id', '=', true) || util.getValue(lines, 'target-type', '=', true);
|
||||
result.sku = util.getValue(lines, 'target-sub-type', '=', true);
|
||||
}
|
||||
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
if (_windows) {
|
||||
try {
|
||||
util.powerShell('Get-CimInstance Win32_SystemEnclosure | select Model,Manufacturer,ChassisTypes,Version,SerialNumber,PartNumber,SKU,SMBIOSAssetTag | fl').then((stdout, error) => {
|
||||
if (!error) {
|
||||
let lines = stdout.toString().split('\r\n');
|
||||
|
||||
result.manufacturer = cleanDefaults(util.getValue(lines, 'manufacturer', ':'));
|
||||
result.model = cleanDefaults(util.getValue(lines, 'model', ':'));
|
||||
const ctype = parseInt(util.getValue(lines, 'ChassisTypes', ':').replace(/\D/g, ''));
|
||||
result.type = (ctype && !isNaN(ctype) && ctype < chassisTypes.length) ? chassisTypes[ctype - 1] : '';
|
||||
result.version = cleanDefaults(util.getValue(lines, 'version', ':'));
|
||||
result.serial = cleanDefaults(util.getValue(lines, 'serialnumber', ':'));
|
||||
result.assetTag = cleanDefaults(util.getValue(lines, 'partnumber', ':'));
|
||||
if (!result.assetTag) {
|
||||
result.assetTag = cleanDefaults(util.getValue(lines, 'SMBIOSAssetTag', ':'));
|
||||
}
|
||||
result.sku = cleanDefaults(util.getValue(lines, 'sku', ':'));
|
||||
}
|
||||
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.chassis = chassis;
|
||||
279
api.hyungi.net/node_modules/systeminformation/lib/usb.js
generated
vendored
Normal file
279
api.hyungi.net/node_modules/systeminformation/lib/usb.js
generated
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// usb.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 16. usb
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const exec = require('child_process').exec;
|
||||
const util = require('./util');
|
||||
|
||||
let _platform = process.platform;
|
||||
|
||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
||||
const _darwin = (_platform === 'darwin');
|
||||
const _windows = (_platform === 'win32');
|
||||
const _freebsd = (_platform === 'freebsd');
|
||||
const _openbsd = (_platform === 'openbsd');
|
||||
const _netbsd = (_platform === 'netbsd');
|
||||
const _sunos = (_platform === 'sunos');
|
||||
|
||||
function getLinuxUsbType(type, name) {
|
||||
let result = type;
|
||||
const str = (name + ' ' + type).toLowerCase();
|
||||
if (str.indexOf('camera') >= 0) { result = 'Camera'; }
|
||||
else if (str.indexOf('hub') >= 0) { result = 'Hub'; }
|
||||
else if (str.indexOf('keybrd') >= 0) { result = 'Keyboard'; }
|
||||
else if (str.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
|
||||
else if (str.indexOf('mouse') >= 0) { result = 'Mouse'; }
|
||||
else if (str.indexOf('stora') >= 0) { result = 'Storage'; }
|
||||
else if (str.indexOf('microp') >= 0) { result = 'Microphone'; }
|
||||
else if (str.indexOf('headset') >= 0) { result = 'Audio'; }
|
||||
else if (str.indexOf('audio') >= 0) { result = 'Audio'; }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseLinuxUsb(usb) {
|
||||
const result = {};
|
||||
const lines = usb.split('\n');
|
||||
if (lines && lines.length && lines[0].indexOf('Device') >= 0) {
|
||||
const parts = lines[0].split(' ');
|
||||
result.bus = parseInt(parts[0], 10);
|
||||
if (parts[2]) {
|
||||
result.deviceId = parseInt(parts[2], 10);
|
||||
} else {
|
||||
result.deviceId = null;
|
||||
}
|
||||
} else {
|
||||
result.bus = null;
|
||||
result.deviceId = null;
|
||||
}
|
||||
const idVendor = util.getValue(lines, 'idVendor', ' ', true).trim();
|
||||
let vendorParts = idVendor.split(' ');
|
||||
vendorParts.shift();
|
||||
const vendor = vendorParts.join(' ');
|
||||
|
||||
const idProduct = util.getValue(lines, 'idProduct', ' ', true).trim();
|
||||
let productParts = idProduct.split(' ');
|
||||
productParts.shift();
|
||||
const product = productParts.join(' ');
|
||||
|
||||
const interfaceClass = util.getValue(lines, 'bInterfaceClass', ' ', true).trim();
|
||||
let interfaceClassParts = interfaceClass.split(' ');
|
||||
interfaceClassParts.shift();
|
||||
const usbType = interfaceClassParts.join(' ');
|
||||
|
||||
const iManufacturer = util.getValue(lines, 'iManufacturer', ' ', true).trim();
|
||||
let iManufacturerParts = iManufacturer.split(' ');
|
||||
iManufacturerParts.shift();
|
||||
const manufacturer = iManufacturerParts.join(' ');
|
||||
|
||||
const iSerial = util.getValue(lines, 'iSerial', ' ', true).trim();
|
||||
let iSerialParts = iSerial.split(' ');
|
||||
iSerialParts.shift();
|
||||
const serial = iSerialParts.join(' ');
|
||||
|
||||
result.id = (idVendor.startsWith('0x') ? idVendor.split(' ')[0].substr(2, 10) : '') + ':' + (idProduct.startsWith('0x') ? idProduct.split(' ')[0].substr(2, 10) : '');
|
||||
result.name = product;
|
||||
result.type = getLinuxUsbType(usbType, product);
|
||||
result.removable = null;
|
||||
result.vendor = vendor;
|
||||
result.manufacturer = manufacturer;
|
||||
result.maxPower = util.getValue(lines, 'MaxPower', ' ', true);
|
||||
result.serialNumber = serial;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function getDarwinUsbType(name) {
|
||||
let result = '';
|
||||
if (name.indexOf('camera') >= 0) { result = 'Camera'; }
|
||||
else if (name.indexOf('touch bar') >= 0) { result = 'Touch Bar'; }
|
||||
else if (name.indexOf('controller') >= 0) { result = 'Controller'; }
|
||||
else if (name.indexOf('headset') >= 0) { result = 'Audio'; }
|
||||
else if (name.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
|
||||
else if (name.indexOf('trackpad') >= 0) { result = 'Trackpad'; }
|
||||
else if (name.indexOf('sensor') >= 0) { result = 'Sensor'; }
|
||||
else if (name.indexOf('bthusb') >= 0) { result = 'Bluetooth'; }
|
||||
else if (name.indexOf('bth') >= 0) { result = 'Bluetooth'; }
|
||||
else if (name.indexOf('rfcomm') >= 0) { result = 'Bluetooth'; }
|
||||
else if (name.indexOf('usbhub') >= 0) { result = 'Hub'; }
|
||||
else if (name.indexOf(' hub') >= 0) { result = 'Hub'; }
|
||||
else if (name.indexOf('mouse') >= 0) { result = 'Mouse'; }
|
||||
else if (name.indexOf('microp') >= 0) { result = 'Microphone'; }
|
||||
else if (name.indexOf('removable') >= 0) { result = 'Storage'; }
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseDarwinUsb(usb, id) {
|
||||
const result = {};
|
||||
result.id = id;
|
||||
|
||||
usb = usb.replace(/ \|/g, '');
|
||||
usb = usb.trim();
|
||||
let lines = usb.split('\n');
|
||||
lines.shift();
|
||||
try {
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
lines[i] = lines[i].trim();
|
||||
lines[i] = lines[i].replace(/=/g, ':');
|
||||
if (lines[i] !== '{' && lines[i] !== '}' && lines[i + 1] && lines[i + 1].trim() !== '}') {
|
||||
lines[i] = lines[i] + ',';
|
||||
}
|
||||
|
||||
lines[i] = lines[i].replace(':Yes,', ':"Yes",');
|
||||
lines[i] = lines[i].replace(': Yes,', ': "Yes",');
|
||||
lines[i] = lines[i].replace(': Yes', ': "Yes"');
|
||||
lines[i] = lines[i].replace(':No,', ':"No",');
|
||||
lines[i] = lines[i].replace(': No,', ': "No",');
|
||||
lines[i] = lines[i].replace(': No', ': "No"');
|
||||
|
||||
// In this case (("com.apple.developer.driverkit.transport.usb"))
|
||||
lines[i] = lines[i].replace('((', '').replace('))', '');
|
||||
|
||||
// In case we have <923c11> we need make it "<923c11>" for correct JSON parse
|
||||
const match = /<(\w+)>/.exec(lines[i]);
|
||||
if (match) {
|
||||
const number = match[0];
|
||||
lines[i] = lines[i].replace(number, `"${number}"`);
|
||||
}
|
||||
}
|
||||
const usbObj = JSON.parse(lines.join('\n'));
|
||||
const removableDrive = (usbObj['Built-In'] ? usbObj['Built-In'].toLowerCase() !== 'yes' : true) && (usbObj['non-removable'] ? usbObj['non-removable'].toLowerCase() === 'no' : true);
|
||||
|
||||
result.bus = null;
|
||||
result.deviceId = null;
|
||||
result.id = usbObj['USB Address'] || null;
|
||||
result.name = usbObj['kUSBProductString'] || usbObj['USB Product Name'] || null;
|
||||
result.type = getDarwinUsbType((usbObj['kUSBProductString'] || usbObj['USB Product Name'] || '').toLowerCase() + (removableDrive ? ' removable' : ''));
|
||||
result.removable = usbObj['non-removable'] ? usbObj['non-removable'].toLowerCase() || '' === 'no' : true;
|
||||
result.vendor = usbObj['kUSBVendorString'] || usbObj['USB Vendor Name'] || null;
|
||||
result.manufacturer = usbObj['kUSBVendorString'] || usbObj['USB Vendor Name'] || null;
|
||||
|
||||
result.maxPower = null;
|
||||
result.serialNumber = usbObj['kUSBSerialNumberString'] || null;
|
||||
|
||||
if (result.name) {
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getWindowsUsbTypeCreation(creationclass, name) {
|
||||
let result = '';
|
||||
if (name.indexOf('storage') >= 0) { result = 'Storage'; }
|
||||
else if (name.indexOf('speicher') >= 0) { result = 'Storage'; }
|
||||
else if (creationclass.indexOf('usbhub') >= 0) { result = 'Hub'; }
|
||||
else if (creationclass.indexOf('storage') >= 0) { result = 'Storage'; }
|
||||
else if (creationclass.indexOf('usbcontroller') >= 0) { result = 'Controller'; }
|
||||
else if (creationclass.indexOf('keyboard') >= 0) { result = 'Keyboard'; }
|
||||
else if (creationclass.indexOf('pointing') >= 0) { result = 'Mouse'; }
|
||||
else if (creationclass.indexOf('microp') >= 0) { result = 'Microphone'; }
|
||||
else if (creationclass.indexOf('disk') >= 0) { result = 'Storage'; }
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseWindowsUsb(lines, id) {
|
||||
const usbType = getWindowsUsbTypeCreation(util.getValue(lines, 'CreationClassName', ':').toLowerCase(), util.getValue(lines, 'name', ':').toLowerCase());
|
||||
|
||||
if (usbType) {
|
||||
const result = {};
|
||||
result.bus = null;
|
||||
result.deviceId = util.getValue(lines, 'deviceid', ':');
|
||||
result.id = id;
|
||||
result.name = util.getValue(lines, 'name', ':');
|
||||
result.type = usbType;
|
||||
result.removable = null;
|
||||
result.vendor = null;
|
||||
result.manufacturer = util.getValue(lines, 'Manufacturer', ':');
|
||||
result.maxPower = null;
|
||||
result.serialNumber = null;
|
||||
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function usb(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
let result = [];
|
||||
if (_linux) {
|
||||
const cmd = 'export LC_ALL=C; lsusb -v 2>/dev/null; unset LC_ALL';
|
||||
exec(cmd, { maxBuffer: 1024 * 1024 * 128 }, function (error, stdout) {
|
||||
if (!error) {
|
||||
const parts = ('\n\n' + stdout.toString()).split('\n\nBus ');
|
||||
for (let i = 1; i < parts.length; i++) {
|
||||
const usb = parseLinuxUsb(parts[i]);
|
||||
result.push(usb);
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_darwin) {
|
||||
let cmd = 'ioreg -p IOUSB -c AppleUSBRootHubDevice -w0 -l';
|
||||
exec(cmd, { maxBuffer: 1024 * 1024 * 128 }, function (error, stdout) {
|
||||
if (!error) {
|
||||
const parts = (stdout.toString()).split(' +-o ');
|
||||
for (let i = 1; i < parts.length; i++) {
|
||||
const usb = parseDarwinUsb(parts[i]);
|
||||
if (usb) {
|
||||
result.push(usb);
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_windows) {
|
||||
util.powerShell('Get-CimInstance CIM_LogicalDevice | where { $_.Description -match "USB"} | select Name,CreationClassName,DeviceId,Manufacturer | fl').then((stdout, error) => {
|
||||
if (!error) {
|
||||
const parts = stdout.toString().split(/\n\s*\n/);
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const usb = parseWindowsUsb(parts[i].split('\n'), i);
|
||||
if (usb && result.filter(x => x.deviceId === usb.deviceId).length === 0) {
|
||||
result.push(usb);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos || _freebsd || _openbsd || _netbsd) {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.usb = usb;
|
||||
|
||||
371
api.hyungi.net/node_modules/systeminformation/lib/users.js
generated
vendored
Normal file
371
api.hyungi.net/node_modules/systeminformation/lib/users.js
generated
vendored
Normal file
@@ -0,0 +1,371 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// users.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 11. Users/Sessions
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const exec = require('child_process').exec;
|
||||
const util = require('./util');
|
||||
|
||||
let _platform = process.platform;
|
||||
|
||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
||||
const _darwin = (_platform === 'darwin');
|
||||
const _windows = (_platform === 'win32');
|
||||
const _freebsd = (_platform === 'freebsd');
|
||||
const _openbsd = (_platform === 'openbsd');
|
||||
const _netbsd = (_platform === 'netbsd');
|
||||
const _sunos = (_platform === 'sunos');
|
||||
|
||||
function parseUsersLinux(lines, phase) {
|
||||
let result = [];
|
||||
let result_who = [];
|
||||
let result_w = {};
|
||||
let w_first = true;
|
||||
let w_header = [];
|
||||
let w_pos = [];
|
||||
let who_line = {};
|
||||
|
||||
let is_whopart = true;
|
||||
lines.forEach(function (line) {
|
||||
if (line === '---') {
|
||||
is_whopart = false;
|
||||
} else {
|
||||
let l = line.replace(/ +/g, ' ').split(' ');
|
||||
|
||||
// who part
|
||||
if (is_whopart) {
|
||||
result_who.push({
|
||||
user: l[0],
|
||||
tty: l[1],
|
||||
date: l[2],
|
||||
time: l[3],
|
||||
ip: (l && l.length > 4) ? l[4].replace(/\(/g, '').replace(/\)/g, '') : ''
|
||||
});
|
||||
} else {
|
||||
// w part
|
||||
if (w_first) { // header
|
||||
w_header = l;
|
||||
w_header.forEach(function (item) {
|
||||
w_pos.push(line.indexOf(item));
|
||||
});
|
||||
w_first = false;
|
||||
} else {
|
||||
// split by w_pos
|
||||
result_w.user = line.substring(w_pos[0], w_pos[1] - 1).trim();
|
||||
result_w.tty = line.substring(w_pos[1], w_pos[2] - 1).trim();
|
||||
result_w.ip = line.substring(w_pos[2], w_pos[3] - 1).replace(/\(/g, '').replace(/\)/g, '').trim();
|
||||
result_w.command = line.substring(w_pos[7], 1000).trim();
|
||||
// find corresponding 'who' line
|
||||
who_line = result_who.filter(function (obj) {
|
||||
return (obj.user.substring(0, 8).trim() === result_w.user && obj.tty === result_w.tty);
|
||||
});
|
||||
if (who_line.length === 1) {
|
||||
result.push({
|
||||
user: who_line[0].user,
|
||||
tty: who_line[0].tty,
|
||||
date: who_line[0].date,
|
||||
time: who_line[0].time,
|
||||
ip: who_line[0].ip,
|
||||
command: result_w.command
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (result.length === 0 && phase === 2) {
|
||||
return result_who;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function parseUsersDarwin(lines) {
|
||||
let result = [];
|
||||
let result_who = [];
|
||||
let result_w = {};
|
||||
let who_line = {};
|
||||
|
||||
let is_whopart = true;
|
||||
lines.forEach(function (line) {
|
||||
if (line === '---') {
|
||||
is_whopart = false;
|
||||
} else {
|
||||
let l = line.replace(/ +/g, ' ').split(' ');
|
||||
|
||||
// who part
|
||||
if (is_whopart) {
|
||||
let dt = ('' + new Date().getFullYear()) + '-' + ('0' + ('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.indexOf(l[2].toUpperCase()) / 3 + 1)).slice(-2) + '-' + ('0' + l[3]).slice(-2);
|
||||
try {
|
||||
if (new Date(dt) > new Date) {
|
||||
dt = ('' + (new Date().getFullYear() - 1)) + '-' + ('0' + ('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.indexOf(l[2].toUpperCase()) / 3 + 1)).slice(-2) + '-' + ('0' + l[3]).slice(-2);
|
||||
}
|
||||
} catch {
|
||||
util.noop();
|
||||
}
|
||||
result_who.push({
|
||||
user: l[0],
|
||||
tty: l[1],
|
||||
date: dt,
|
||||
time: l[4],
|
||||
});
|
||||
} else {
|
||||
// w part
|
||||
// split by w_pos
|
||||
result_w.user = l[0];
|
||||
result_w.tty = l[1];
|
||||
result_w.ip = (l[2] !== '-') ? l[2] : '';
|
||||
result_w.command = l.slice(5, 1000).join(' ');
|
||||
// find corresponding 'who' line
|
||||
who_line = result_who.filter(function (obj) {
|
||||
return (obj.user.substring(0, 10) === result_w.user.substring(0, 10) && (obj.tty.substring(3, 1000) === result_w.tty || obj.tty === result_w.tty));
|
||||
});
|
||||
if (who_line.length === 1) {
|
||||
result.push({
|
||||
user: who_line[0].user,
|
||||
tty: who_line[0].tty,
|
||||
date: who_line[0].date,
|
||||
time: who_line[0].time,
|
||||
ip: result_w.ip,
|
||||
command: result_w.command
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function users(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
let result = [];
|
||||
|
||||
// linux
|
||||
if (_linux) {
|
||||
exec('export LC_ALL=C; who --ips; echo "---"; w; unset LC_ALL | tail -n +2', function (error, stdout) {
|
||||
if (!error) {
|
||||
// lines / split
|
||||
let lines = stdout.toString().split('\n');
|
||||
result = parseUsersLinux(lines, 1);
|
||||
if (result.length === 0) {
|
||||
exec('who; echo "---"; w | tail -n +2', function (error, stdout) {
|
||||
if (!error) {
|
||||
// lines / split
|
||||
lines = stdout.toString().split('\n');
|
||||
result = parseUsersLinux(lines, 2);
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
} else {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (_freebsd || _openbsd || _netbsd) {
|
||||
exec('who; echo "---"; w -ih', function (error, stdout) {
|
||||
if (!error) {
|
||||
// lines / split
|
||||
let lines = stdout.toString().split('\n');
|
||||
result = parseUsersDarwin(lines);
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
exec('who; echo "---"; w -h', function (error, stdout) {
|
||||
if (!error) {
|
||||
// lines / split
|
||||
let lines = stdout.toString().split('\n');
|
||||
result = parseUsersDarwin(lines);
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
|
||||
if (_darwin) {
|
||||
exec('export LC_ALL=C; who; echo "---"; w -ih; unset LC_ALL', function (error, stdout) {
|
||||
if (!error) {
|
||||
// lines / split
|
||||
let lines = stdout.toString().split('\n');
|
||||
result = parseUsersDarwin(lines);
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_windows) {
|
||||
try {
|
||||
let cmd = 'Get-CimInstance Win32_LogonSession | select LogonId,@{n="StartTime";e={$_.StartTime.ToString("yyyy-MM-dd HH:mm:ss")}} | fl' + '; echo \'#-#-#-#\';';
|
||||
cmd += 'Get-CimInstance Win32_LoggedOnUser | select antecedent,dependent | fl ' + '; echo \'#-#-#-#\';';
|
||||
cmd += '$process = (Get-CimInstance Win32_Process -Filter "name = \'explorer.exe\'"); Invoke-CimMethod -InputObject $process[0] -MethodName GetOwner | select user, domain | fl; get-process -name explorer | select-object sessionid | fl; echo \'#-#-#-#\';';
|
||||
cmd += 'query user';
|
||||
util.powerShell(cmd).then((data) => {
|
||||
if (data) {
|
||||
data = data.split('#-#-#-#');
|
||||
let sessions = parseWinSessions((data[0] || '').split(/\n\s*\n/));
|
||||
let loggedons = parseWinLoggedOn((data[1] || '').split(/\n\s*\n/));
|
||||
let queryUser = parseWinUsersQuery((data[3] || '').split('\r\n'));
|
||||
let users = parseWinUsers((data[2] || '').split(/\n\s*\n/), queryUser);
|
||||
for (let id in loggedons) {
|
||||
if ({}.hasOwnProperty.call(loggedons, id)) {
|
||||
loggedons[id].dateTime = {}.hasOwnProperty.call(sessions, id) ? sessions[id] : '';
|
||||
}
|
||||
}
|
||||
users.forEach(user => {
|
||||
let dateTime = '';
|
||||
for (let id in loggedons) {
|
||||
if ({}.hasOwnProperty.call(loggedons, id)) {
|
||||
if (loggedons[id].user === user.user && (!dateTime || dateTime < loggedons[id].dateTime)) {
|
||||
dateTime = loggedons[id].dateTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.push({
|
||||
user: user.user,
|
||||
tty: user.tty,
|
||||
date: `${dateTime.substring(0, 10)}`,
|
||||
time: `${dateTime.substring(11, 19)}`,
|
||||
ip: '',
|
||||
command: ''
|
||||
});
|
||||
});
|
||||
}
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function parseWinSessions(sessionParts) {
|
||||
const sessions = {};
|
||||
sessionParts.forEach(session => {
|
||||
const lines = session.split('\r\n');
|
||||
const id = util.getValue(lines, 'LogonId');
|
||||
const starttime = util.getValue(lines, 'starttime');
|
||||
if (id) {
|
||||
sessions[id] = starttime;
|
||||
}
|
||||
});
|
||||
return sessions;
|
||||
}
|
||||
|
||||
function fuzzyMatch(name1, name2) {
|
||||
name1 = name1.toLowerCase();
|
||||
name2 = name2.toLowerCase();
|
||||
let eq = 0;
|
||||
let len = name1.length;
|
||||
if (name2.length > len) { len = name2.length; }
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
const c1 = name1[i] || '';
|
||||
const c2 = name2[i] || '';
|
||||
if (c1 === c2) { eq++; }
|
||||
}
|
||||
return (len > 10 ? eq / len > 0.9 : (len > 0 ? eq / len > 0.8 : false));
|
||||
}
|
||||
|
||||
function parseWinUsers(userParts, userQuery) {
|
||||
const users = [];
|
||||
userParts.forEach(user => {
|
||||
const lines = user.split('\r\n');
|
||||
|
||||
const domain = util.getValue(lines, 'domain', ':', true);
|
||||
const username = util.getValue(lines, 'user', ':', true);
|
||||
const sessionid = util.getValue(lines, 'sessionid', ':', true);
|
||||
|
||||
if (username) {
|
||||
const quser = userQuery.filter(item => fuzzyMatch(item.user, username));
|
||||
users.push({
|
||||
domain,
|
||||
user: username,
|
||||
tty: quser && quser[0] && quser[0].tty ? quser[0].tty : sessionid
|
||||
});
|
||||
}
|
||||
});
|
||||
return users;
|
||||
}
|
||||
|
||||
function parseWinLoggedOn(loggedonParts) {
|
||||
const loggedons = {};
|
||||
loggedonParts.forEach(loggedon => {
|
||||
const lines = loggedon.split('\r\n');
|
||||
|
||||
const antecendent = util.getValue(lines, 'antecedent', ':', true);
|
||||
let parts = antecendent.split('=');
|
||||
const name = parts.length > 2 ? parts[1].split(',')[0].replace(/"/g, '').trim() : '';
|
||||
const domain = parts.length > 2 ? parts[2].replace(/"/g, '').replace(/\)/g, '').trim() : '';
|
||||
const dependent = util.getValue(lines, 'dependent', ':', true);
|
||||
parts = dependent.split('=');
|
||||
const id = parts.length > 1 ? parts[1].replace(/"/g, '').replace(/\)/g, '').trim() : '';
|
||||
if (id) {
|
||||
loggedons[id] = {
|
||||
domain,
|
||||
user: name
|
||||
};
|
||||
}
|
||||
});
|
||||
return loggedons;
|
||||
}
|
||||
|
||||
function parseWinUsersQuery(lines) {
|
||||
lines = lines.filter(item => item);
|
||||
let result = [];
|
||||
const header = lines[0];
|
||||
const headerDelimiter = [];
|
||||
if (header) {
|
||||
const start = (header[0] === ' ') ? 1 : 0;
|
||||
headerDelimiter.push(start - 1);
|
||||
let nextSpace = 0;
|
||||
for (let i = start + 1; i < header.length; i++) {
|
||||
if (header[i] === ' ' && ((header[i - 1] === ' ') || (header[i - 1] === '.'))) {
|
||||
nextSpace = i;
|
||||
} else {
|
||||
if (nextSpace) {
|
||||
headerDelimiter.push(nextSpace);
|
||||
nextSpace = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
if (lines[i].trim()) {
|
||||
const user = lines[i].substring(headerDelimiter[0] + 1, headerDelimiter[1]).trim() || '';
|
||||
const tty = lines[i].substring(headerDelimiter[1] + 1, headerDelimiter[2] - 2).trim() || '';
|
||||
result.push({
|
||||
user: user,
|
||||
tty: tty,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
exports.users = users;
|
||||
2616
api.hyungi.net/node_modules/systeminformation/lib/util.js
generated
vendored
Normal file
2616
api.hyungi.net/node_modules/systeminformation/lib/util.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
107
api.hyungi.net/node_modules/systeminformation/lib/virtualbox.js
generated
vendored
Normal file
107
api.hyungi.net/node_modules/systeminformation/lib/virtualbox.js
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// virtualbox.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 14. Docker
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const os = require('os');
|
||||
const exec = require('child_process').exec;
|
||||
const util = require('./util');
|
||||
|
||||
function vboxInfo(callback) {
|
||||
|
||||
// fallback - if only callback is given
|
||||
let result = [];
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
try {
|
||||
exec(util.getVboxmanage() + ' list vms --long', function (error, stdout) {
|
||||
let parts = (os.EOL + stdout.toString()).split(os.EOL + 'Name:');
|
||||
parts.shift();
|
||||
parts.forEach(part => {
|
||||
const lines = ('Name:' + part).split(os.EOL);
|
||||
const state = util.getValue(lines, 'State');
|
||||
const running = state.startsWith('running');
|
||||
const runningSinceString = running ? state.replace('running (since ', '').replace(')', '').trim() : '';
|
||||
let runningSince = 0;
|
||||
try {
|
||||
if (running) {
|
||||
const sinceDateObj = new Date(runningSinceString);
|
||||
const offset = sinceDateObj.getTimezoneOffset();
|
||||
runningSince = Math.round((Date.now() - Date.parse(sinceDateObj)) / 1000) + offset * 60;
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
const stoppedSinceString = !running ? state.replace('powered off (since', '').replace(')', '').trim() : '';
|
||||
let stoppedSince = 0;
|
||||
try {
|
||||
if (!running) {
|
||||
const sinceDateObj = new Date(stoppedSinceString);
|
||||
const offset = sinceDateObj.getTimezoneOffset();
|
||||
stoppedSince = Math.round((Date.now() - Date.parse(sinceDateObj)) / 1000) + offset * 60;
|
||||
}
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
result.push({
|
||||
id: util.getValue(lines, 'UUID'),
|
||||
name: util.getValue(lines, 'Name'),
|
||||
running,
|
||||
started: runningSinceString,
|
||||
runningSince,
|
||||
stopped: stoppedSinceString,
|
||||
stoppedSince,
|
||||
guestOS: util.getValue(lines, 'Guest OS'),
|
||||
hardwareUUID: util.getValue(lines, 'Hardware UUID'),
|
||||
memory: parseInt(util.getValue(lines, 'Memory size', ' '), 10),
|
||||
vram: parseInt(util.getValue(lines, 'VRAM size'), 10),
|
||||
cpus: parseInt(util.getValue(lines, 'Number of CPUs'), 10),
|
||||
cpuExepCap: util.getValue(lines, 'CPU exec cap'),
|
||||
cpuProfile: util.getValue(lines, 'CPUProfile'),
|
||||
chipset: util.getValue(lines, 'Chipset'),
|
||||
firmware: util.getValue(lines, 'Firmware'),
|
||||
pageFusion: util.getValue(lines, 'Page Fusion') === 'enabled',
|
||||
configFile: util.getValue(lines, 'Config file'),
|
||||
snapshotFolder: util.getValue(lines, 'Snapshot folder'),
|
||||
logFolder: util.getValue(lines, 'Log folder'),
|
||||
hpet: util.getValue(lines, 'HPET') === 'enabled',
|
||||
pae: util.getValue(lines, 'PAE') === 'enabled',
|
||||
longMode: util.getValue(lines, 'Long Mode') === 'enabled',
|
||||
tripleFaultReset: util.getValue(lines, 'Triple Fault Reset') === 'enabled',
|
||||
apic: util.getValue(lines, 'APIC') === 'enabled',
|
||||
x2Apic: util.getValue(lines, 'X2APIC') === 'enabled',
|
||||
acpi: util.getValue(lines, 'ACPI') === 'enabled',
|
||||
ioApic: util.getValue(lines, 'IOAPIC') === 'enabled',
|
||||
biosApicMode: util.getValue(lines, 'BIOS APIC mode'),
|
||||
bootMenuMode: util.getValue(lines, 'Boot menu mode'),
|
||||
bootDevice1: util.getValue(lines, 'Boot Device 1'),
|
||||
bootDevice2: util.getValue(lines, 'Boot Device 2'),
|
||||
bootDevice3: util.getValue(lines, 'Boot Device 3'),
|
||||
bootDevice4: util.getValue(lines, 'Boot Device 4'),
|
||||
timeOffset: util.getValue(lines, 'Time offset'),
|
||||
rtc: util.getValue(lines, 'RTC'),
|
||||
});
|
||||
});
|
||||
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
if (callback) { callback(result); }
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.vboxInfo = vboxInfo;
|
||||
852
api.hyungi.net/node_modules/systeminformation/lib/wifi.js
generated
vendored
Normal file
852
api.hyungi.net/node_modules/systeminformation/lib/wifi.js
generated
vendored
Normal file
@@ -0,0 +1,852 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// wifi.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2025
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 9. wifi
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const os = require('os');
|
||||
const exec = require('child_process').exec;
|
||||
const execSync = require('child_process').execSync;
|
||||
const util = require('./util');
|
||||
|
||||
let _platform = process.platform;
|
||||
|
||||
const _linux = (_platform === 'linux' || _platform === 'android');
|
||||
const _darwin = (_platform === 'darwin');
|
||||
const _windows = (_platform === 'win32');
|
||||
|
||||
function wifiDBFromQuality(quality) {
|
||||
const qual = parseFloat(quality);
|
||||
if (qual < 0) { return 0; }
|
||||
if (qual >= 100) { return -50; }
|
||||
return (qual / 2 - 100);
|
||||
}
|
||||
|
||||
function wifiQualityFromDB(db) {
|
||||
const result = 2 * (parseFloat(db) + 100);
|
||||
return result <= 100 ? result : 100;
|
||||
}
|
||||
|
||||
const _wifi_frequencies = {
|
||||
1: 2412,
|
||||
2: 2417,
|
||||
3: 2422,
|
||||
4: 2427,
|
||||
5: 2432,
|
||||
6: 2437,
|
||||
7: 2442,
|
||||
8: 2447,
|
||||
9: 2452,
|
||||
10: 2457,
|
||||
11: 2462,
|
||||
12: 2467,
|
||||
13: 2472,
|
||||
14: 2484,
|
||||
32: 5160,
|
||||
34: 5170,
|
||||
36: 5180,
|
||||
38: 5190,
|
||||
40: 5200,
|
||||
42: 5210,
|
||||
44: 5220,
|
||||
46: 5230,
|
||||
48: 5240,
|
||||
50: 5250,
|
||||
52: 5260,
|
||||
54: 5270,
|
||||
56: 5280,
|
||||
58: 5290,
|
||||
60: 5300,
|
||||
62: 5310,
|
||||
64: 5320,
|
||||
68: 5340,
|
||||
96: 5480,
|
||||
100: 5500,
|
||||
102: 5510,
|
||||
104: 5520,
|
||||
106: 5530,
|
||||
108: 5540,
|
||||
110: 5550,
|
||||
112: 5560,
|
||||
114: 5570,
|
||||
116: 5580,
|
||||
118: 5590,
|
||||
120: 5600,
|
||||
122: 5610,
|
||||
124: 5620,
|
||||
126: 5630,
|
||||
128: 5640,
|
||||
132: 5660,
|
||||
134: 5670,
|
||||
136: 5680,
|
||||
138: 5690,
|
||||
140: 5700,
|
||||
142: 5710,
|
||||
144: 5720,
|
||||
149: 5745,
|
||||
151: 5755,
|
||||
153: 5765,
|
||||
155: 5775,
|
||||
157: 5785,
|
||||
159: 5795,
|
||||
161: 5805,
|
||||
165: 5825,
|
||||
169: 5845,
|
||||
173: 5865,
|
||||
183: 4915,
|
||||
184: 4920,
|
||||
185: 4925,
|
||||
187: 4935,
|
||||
188: 4940,
|
||||
189: 4945,
|
||||
192: 4960,
|
||||
196: 4980
|
||||
};
|
||||
|
||||
function wifiFrequencyFromChannel(channel) {
|
||||
return {}.hasOwnProperty.call(_wifi_frequencies, channel) ? _wifi_frequencies[channel] : null;
|
||||
}
|
||||
|
||||
function wifiChannelFromFrequencs(frequency) {
|
||||
let channel = 0;
|
||||
for (let key in _wifi_frequencies) {
|
||||
if ({}.hasOwnProperty.call(_wifi_frequencies, key)) {
|
||||
if (_wifi_frequencies[key] === frequency) { channel = util.toInt(key); }
|
||||
}
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
function ifaceListLinux() {
|
||||
const result = [];
|
||||
const cmd = 'iw dev 2>/dev/null';
|
||||
try {
|
||||
const all = execSync(cmd, util.execOptsLinux).toString().split('\n').map(line => line.trim()).join('\n');
|
||||
const parts = all.split('\nInterface ');
|
||||
parts.shift();
|
||||
parts.forEach(ifaceDetails => {
|
||||
const lines = ifaceDetails.split('\n');
|
||||
const iface = lines[0];
|
||||
const id = util.toInt(util.getValue(lines, 'ifindex', ' '));
|
||||
const mac = util.getValue(lines, 'addr', ' ');
|
||||
const channel = util.toInt(util.getValue(lines, 'channel', ' '));
|
||||
result.push({
|
||||
id,
|
||||
iface,
|
||||
mac,
|
||||
channel
|
||||
});
|
||||
});
|
||||
return result;
|
||||
} catch (e) {
|
||||
try {
|
||||
const all = execSync('nmcli -t -f general,wifi-properties,wired-properties,interface-flags,capabilities,nsp device show 2>/dev/null', util.execOptsLinux).toString();
|
||||
const parts = all.split('\n\n');
|
||||
let i = 1;
|
||||
parts.forEach(ifaceDetails => {
|
||||
const lines = ifaceDetails.split('\n');
|
||||
const iface = util.getValue(lines, 'GENERAL.DEVICE');
|
||||
const type = util.getValue(lines, 'GENERAL.TYPE');
|
||||
const id = i++; // // util.getValue(lines, 'GENERAL.PATH');
|
||||
const mac = util.getValue(lines, 'GENERAL.HWADDR');
|
||||
const channel = '';
|
||||
if (type.toLowerCase() === 'wifi') {
|
||||
result.push({
|
||||
id,
|
||||
iface,
|
||||
mac,
|
||||
channel
|
||||
});
|
||||
}
|
||||
});
|
||||
return result;
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function nmiDeviceLinux(iface) {
|
||||
const cmd = `nmcli -t -f general,wifi-properties,capabilities,ip4,ip6 device show ${iface} 2> /dev/null`;
|
||||
try {
|
||||
const lines = execSync(cmd, util.execOptsLinux).toString().split('\n');
|
||||
const ssid = util.getValue(lines, 'GENERAL.CONNECTION');
|
||||
return {
|
||||
iface,
|
||||
type: util.getValue(lines, 'GENERAL.TYPE'),
|
||||
vendor: util.getValue(lines, 'GENERAL.VENDOR'),
|
||||
product: util.getValue(lines, 'GENERAL.PRODUCT'),
|
||||
mac: util.getValue(lines, 'GENERAL.HWADDR').toLowerCase(),
|
||||
ssid: ssid !== '--' ? ssid : null
|
||||
};
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function nmiConnectionLinux(ssid) {
|
||||
const cmd = `nmcli -t --show-secrets connection show ${ssid} 2>/dev/null`;
|
||||
try {
|
||||
const lines = execSync(cmd, util.execOptsLinux).toString().split('\n');
|
||||
const bssid = util.getValue(lines, '802-11-wireless.seen-bssids').toLowerCase();
|
||||
return {
|
||||
ssid: ssid !== '--' ? ssid : null,
|
||||
uuid: util.getValue(lines, 'connection.uuid'),
|
||||
type: util.getValue(lines, 'connection.type'),
|
||||
autoconnect: util.getValue(lines, 'connection.autoconnect') === 'yes',
|
||||
security: util.getValue(lines, '802-11-wireless-security.key-mgmt'),
|
||||
bssid: bssid !== '--' ? bssid : null
|
||||
};
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function wpaConnectionLinux(iface) {
|
||||
if (!iface) {
|
||||
return {};
|
||||
}
|
||||
const cmd = `wpa_cli -i ${iface} status 2>&1`;
|
||||
try {
|
||||
const lines = execSync(cmd, util.execOptsLinux).toString().split('\n');
|
||||
const freq = util.toInt(util.getValue(lines, 'freq', '='));
|
||||
return {
|
||||
ssid: util.getValue(lines, 'ssid', '='),
|
||||
uuid: util.getValue(lines, 'uuid', '='),
|
||||
security: util.getValue(lines, 'key_mgmt', '='),
|
||||
freq,
|
||||
channel: wifiChannelFromFrequencs(freq),
|
||||
bssid: util.getValue(lines, 'bssid', '=').toLowerCase()
|
||||
};
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function getWifiNetworkListNmi() {
|
||||
const result = [];
|
||||
const cmd = 'nmcli -t -m multiline --fields active,ssid,bssid,mode,chan,freq,signal,security,wpa-flags,rsn-flags device wifi list 2>/dev/null';
|
||||
try {
|
||||
const stdout = execSync(cmd, util.execOptsLinux);
|
||||
const parts = stdout.toString().split('ACTIVE:');
|
||||
parts.shift();
|
||||
parts.forEach(part => {
|
||||
part = 'ACTIVE:' + part;
|
||||
const lines = part.split(os.EOL);
|
||||
const channel = util.getValue(lines, 'CHAN');
|
||||
const frequency = util.getValue(lines, 'FREQ').toLowerCase().replace('mhz', '').trim();
|
||||
const security = util.getValue(lines, 'SECURITY').replace('(', '').replace(')', '');
|
||||
const wpaFlags = util.getValue(lines, 'WPA-FLAGS').replace('(', '').replace(')', '');
|
||||
const rsnFlags = util.getValue(lines, 'RSN-FLAGS').replace('(', '').replace(')', '');
|
||||
const quality = util.getValue(lines, 'SIGNAL');
|
||||
result.push({
|
||||
ssid: util.getValue(lines, 'SSID'),
|
||||
bssid: util.getValue(lines, 'BSSID').toLowerCase(),
|
||||
mode: util.getValue(lines, 'MODE'),
|
||||
channel: channel ? parseInt(channel, 10) : null,
|
||||
frequency: frequency ? parseInt(frequency, 10) : null,
|
||||
signalLevel: wifiDBFromQuality(quality),
|
||||
quality: quality ? parseInt(quality, 10) : null,
|
||||
security: security && security !== 'none' ? security.split(' ') : [],
|
||||
wpaFlags: wpaFlags && wpaFlags !== 'none' ? wpaFlags.split(' ') : [],
|
||||
rsnFlags: rsnFlags && rsnFlags !== 'none' ? rsnFlags.split(' ') : []
|
||||
});
|
||||
});
|
||||
return result;
|
||||
} catch (e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function getWifiNetworkListIw(iface) {
|
||||
const result = [];
|
||||
try {
|
||||
let iwlistParts = execSync(`export LC_ALL=C; iwlist ${iface} scan 2>&1; unset LC_ALL`, util.execOptsLinux).toString().split(' Cell ');
|
||||
if (iwlistParts[0].indexOf('resource busy') >= 0) { return -1; }
|
||||
if (iwlistParts.length > 1) {
|
||||
iwlistParts.shift();
|
||||
iwlistParts.forEach(element => {
|
||||
const lines = element.split('\n');
|
||||
const channel = util.getValue(lines, 'channel', ':', true);
|
||||
const address = (lines && lines.length && lines[0].indexOf('Address:') >= 0 ? lines[0].split('Address:')[1].trim().toLowerCase() : '');
|
||||
const mode = util.getValue(lines, 'mode', ':', true);
|
||||
const frequency = util.getValue(lines, 'frequency', ':', true);
|
||||
const qualityString = util.getValue(lines, 'Quality', '=', true);
|
||||
const dbParts = qualityString.toLowerCase().split('signal level=');
|
||||
const db = dbParts.length > 1 ? util.toInt(dbParts[1]) : 0;
|
||||
const quality = db ? wifiQualityFromDB(db) : 0;
|
||||
const ssid = util.getValue(lines, 'essid', ':', true);
|
||||
|
||||
// security and wpa-flags
|
||||
const isWpa = element.indexOf(' WPA ') >= 0;
|
||||
const isWpa2 = element.indexOf('WPA2 ') >= 0;
|
||||
const security = [];
|
||||
if (isWpa) { security.push('WPA'); }
|
||||
if (isWpa2) { security.push('WPA2'); }
|
||||
const wpaFlags = [];
|
||||
let wpaFlag = '';
|
||||
lines.forEach(function (line) {
|
||||
const l = line.trim().toLowerCase();
|
||||
if (l.indexOf('group cipher') >= 0) {
|
||||
if (wpaFlag) {
|
||||
wpaFlags.push(wpaFlag);
|
||||
}
|
||||
const parts = l.split(':');
|
||||
if (parts.length > 1) {
|
||||
wpaFlag = parts[1].trim().toUpperCase();
|
||||
}
|
||||
}
|
||||
if (l.indexOf('pairwise cipher') >= 0) {
|
||||
const parts = l.split(':');
|
||||
if (parts.length > 1) {
|
||||
if (parts[1].indexOf('tkip')) { wpaFlag = (wpaFlag ? 'TKIP/' + wpaFlag : 'TKIP'); }
|
||||
else if (parts[1].indexOf('ccmp')) { wpaFlag = (wpaFlag ? 'CCMP/' + wpaFlag : 'CCMP'); }
|
||||
else if (parts[1].indexOf('proprietary')) { wpaFlag = (wpaFlag ? 'PROP/' + wpaFlag : 'PROP'); }
|
||||
}
|
||||
}
|
||||
if (l.indexOf('authentication suites') >= 0) {
|
||||
const parts = l.split(':');
|
||||
if (parts.length > 1) {
|
||||
if (parts[1].indexOf('802.1x')) { wpaFlag = (wpaFlag ? '802.1x/' + wpaFlag : '802.1x'); }
|
||||
else if (parts[1].indexOf('psk')) { wpaFlag = (wpaFlag ? 'PSK/' + wpaFlag : 'PSK'); }
|
||||
}
|
||||
}
|
||||
});
|
||||
if (wpaFlag) {
|
||||
wpaFlags.push(wpaFlag);
|
||||
}
|
||||
|
||||
result.push({
|
||||
ssid,
|
||||
bssid: address,
|
||||
mode,
|
||||
channel: channel ? util.toInt(channel) : null,
|
||||
frequency: frequency ? util.toInt(frequency.replace('.', '')) : null,
|
||||
signalLevel: db,
|
||||
quality,
|
||||
security,
|
||||
wpaFlags,
|
||||
rsnFlags: []
|
||||
});
|
||||
});
|
||||
}
|
||||
return result;
|
||||
} catch (e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
function parseWifiDarwinXX(wifiObj) {
|
||||
const result = [];
|
||||
if (wifiObj) {
|
||||
wifiObj.forEach(function (wifiItem) {
|
||||
const signalLevel = wifiItem.RSSI;
|
||||
let security = [];
|
||||
let wpaFlags = [];
|
||||
let ssid = wifiItem.SSID_STR || '';
|
||||
if (wifiItem.WPA_IE) {
|
||||
security.push('WPA');
|
||||
if (wifiItem.WPA_IE.IE_KEY_WPA_UCIPHERS) {
|
||||
wifiItem.WPA_IE.IE_KEY_WPA_UCIPHERS.forEach(function (ciphers) {
|
||||
if (ciphers === 0 && wpaFlags.indexOf('unknown/TKIP') === -1) { wpaFlags.push('unknown/TKIP'); }
|
||||
if (ciphers === 2 && wpaFlags.indexOf('PSK/TKIP') === -1) { wpaFlags.push('PSK/TKIP'); }
|
||||
if (ciphers === 4 && wpaFlags.indexOf('PSK/AES') === -1) { wpaFlags.push('PSK/AES'); }
|
||||
});
|
||||
}
|
||||
}
|
||||
if (wifiItem.RSN_IE) {
|
||||
security.push('WPA2');
|
||||
if (wifiItem.RSN_IE.IE_KEY_RSN_UCIPHERS) {
|
||||
wifiItem.RSN_IE.IE_KEY_RSN_UCIPHERS.forEach(function (ciphers) {
|
||||
if (ciphers === 0 && wpaFlags.indexOf('unknown/TKIP') === -1) { wpaFlags.push('unknown/TKIP'); }
|
||||
if (ciphers === 2 && wpaFlags.indexOf('TKIP/TKIP') === -1) { wpaFlags.push('TKIP/TKIP'); }
|
||||
if (ciphers === 4 && wpaFlags.indexOf('PSK/AES') === -1) { wpaFlags.push('PSK/AES'); }
|
||||
});
|
||||
}
|
||||
}
|
||||
if (wifiItem.SSID && ssid === '') {
|
||||
try {
|
||||
ssid = Buffer.from(wifiItem.SSID, 'base64').toString('utf8');
|
||||
} catch (err) {
|
||||
util.noop();
|
||||
}
|
||||
}
|
||||
result.push({
|
||||
ssid,
|
||||
bssid: wifiItem.BSSID || '',
|
||||
mode: '',
|
||||
channel: wifiItem.CHANNEL,
|
||||
frequency: wifiFrequencyFromChannel(wifiItem.CHANNEL),
|
||||
signalLevel: signalLevel ? parseInt(signalLevel, 10) : null,
|
||||
quality: wifiQualityFromDB(signalLevel),
|
||||
security,
|
||||
wpaFlags,
|
||||
rsnFlags: []
|
||||
});
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function parseWifiDarwin(wifiStr) {
|
||||
const result = [];
|
||||
try {
|
||||
let wifiObj = JSON.parse(wifiStr);
|
||||
wifiObj = wifiObj.SPAirPortDataType[0].spairport_airport_interfaces[0].spairport_airport_other_local_wireless_networks;
|
||||
wifiObj.forEach(function (wifiItem) {
|
||||
|
||||
let security = [];
|
||||
const sm = wifiItem.spairport_security_mode || '';
|
||||
if (sm === 'spairport_security_mode_wep') {
|
||||
security.push('WEP');
|
||||
} else if (sm === 'spairport_security_mode_wpa2_personal') {
|
||||
security.push('WPA2');
|
||||
} else if (sm.startsWith('spairport_security_mode_wpa2_enterprise')) {
|
||||
security.push('WPA2 EAP');
|
||||
} else if (sm.startsWith('pairport_security_mode_wpa3_transition')) {
|
||||
security.push('WPA2/WPA3');
|
||||
} else if (sm.startsWith('pairport_security_mode_wpa3')) {
|
||||
security.push('WPA3');
|
||||
}
|
||||
const channel = parseInt(('' + wifiItem.spairport_network_channel).split(' ')[0]) || 0;
|
||||
const signalLevel = wifiItem.spairport_signal_noise || null;
|
||||
|
||||
result.push({
|
||||
ssid: wifiItem._name || '',
|
||||
bssid: wifiItem.spairport_network_bssid || null,
|
||||
mode: wifiItem.spairport_network_phymode,
|
||||
channel,
|
||||
frequency: wifiFrequencyFromChannel(channel),
|
||||
signalLevel: signalLevel ? parseInt(signalLevel, 10) : null,
|
||||
quality: wifiQualityFromDB(signalLevel),
|
||||
security,
|
||||
wpaFlags: [],
|
||||
rsnFlags: []
|
||||
});
|
||||
});
|
||||
return result;
|
||||
} catch (e) {
|
||||
return result;
|
||||
}
|
||||
};
|
||||
function wifiNetworks(callback) {
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
let result = [];
|
||||
if (_linux) {
|
||||
result = getWifiNetworkListNmi();
|
||||
if (result.length === 0) {
|
||||
try {
|
||||
const iwconfigParts = execSync('export LC_ALL=C; iwconfig 2>/dev/null; unset LC_ALL', util.execOptsLinux).toString().split('\n\n');
|
||||
let iface = '';
|
||||
iwconfigParts.forEach(element => {
|
||||
if (element.indexOf('no wireless') === -1 && element.trim() !== '') {
|
||||
iface = element.split(' ')[0];
|
||||
}
|
||||
});
|
||||
if (iface) {
|
||||
let ifaceSanitized = '';
|
||||
const s = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(iface, true);
|
||||
const l = util.mathMin(s.length, 2000);
|
||||
|
||||
for (let i = 0; i <= l; i++) {
|
||||
if (s[i] !== undefined) {
|
||||
ifaceSanitized = ifaceSanitized + s[i];
|
||||
}
|
||||
}
|
||||
|
||||
const res = getWifiNetworkListIw(ifaceSanitized);
|
||||
if (res === -1) {
|
||||
// try again after 4 secs
|
||||
setTimeout(function (iface) {
|
||||
const res = getWifiNetworkListIw(iface);
|
||||
if (res != -1) { result = res; }
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}, 4000);
|
||||
} else {
|
||||
result = res;
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
} catch (e) {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
} else if (_darwin) {
|
||||
let cmd = 'system_profiler SPAirPortDataType -json 2>/dev/null';
|
||||
exec(cmd, { maxBuffer: 1024 * 40000 }, function (error, stdout) {
|
||||
result = parseWifiDarwin(stdout.toString());
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} else if (_windows) {
|
||||
let cmd = 'netsh wlan show networks mode=Bssid';
|
||||
util.powerShell(cmd).then((stdout) => {
|
||||
const ssidParts = stdout.toString('utf8').split(os.EOL + os.EOL + 'SSID ');
|
||||
ssidParts.shift();
|
||||
|
||||
ssidParts.forEach(ssidPart => {
|
||||
const ssidLines = ssidPart.split(os.EOL);
|
||||
if (ssidLines && ssidLines.length >= 8 && ssidLines[0].indexOf(':') >= 0) {
|
||||
const bssidsParts = ssidPart.split(' BSSID');
|
||||
bssidsParts.shift();
|
||||
|
||||
bssidsParts.forEach((bssidPart) => {
|
||||
const bssidLines = bssidPart.split(os.EOL);
|
||||
const bssidLine = bssidLines[0].split(':');
|
||||
bssidLine.shift();
|
||||
const bssid = bssidLine.join(':').trim().toLowerCase();
|
||||
const channel = bssidLines[3].split(':').pop().trim();
|
||||
const quality = bssidLines[1].split(':').pop().trim();
|
||||
|
||||
result.push({
|
||||
ssid: ssidLines[0].split(':').pop().trim(),
|
||||
bssid,
|
||||
mode: '',
|
||||
channel: channel ? parseInt(channel, 10) : null,
|
||||
frequency: wifiFrequencyFromChannel(channel),
|
||||
signalLevel: wifiDBFromQuality(quality),
|
||||
quality: quality ? parseInt(quality, 10) : null,
|
||||
security: [ssidLines[2].split(':').pop().trim()],
|
||||
wpaFlags: [ssidLines[3].split(':').pop().trim()],
|
||||
rsnFlags: []
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.wifiNetworks = wifiNetworks;
|
||||
|
||||
function getVendor(model) {
|
||||
model = model.toLowerCase();
|
||||
let result = '';
|
||||
if (model.indexOf('intel') >= 0) { result = 'Intel'; }
|
||||
else if (model.indexOf('realtek') >= 0) { result = 'Realtek'; }
|
||||
else if (model.indexOf('qualcom') >= 0) { result = 'Qualcom'; }
|
||||
else if (model.indexOf('broadcom') >= 0) { result = 'Broadcom'; }
|
||||
else if (model.indexOf('cavium') >= 0) { result = 'Cavium'; }
|
||||
else if (model.indexOf('cisco') >= 0) { result = 'Cisco'; }
|
||||
else if (model.indexOf('marvel') >= 0) { result = 'Marvel'; }
|
||||
else if (model.indexOf('zyxel') >= 0) { result = 'Zyxel'; }
|
||||
else if (model.indexOf('melanox') >= 0) { result = 'Melanox'; }
|
||||
else if (model.indexOf('d-link') >= 0) { result = 'D-Link'; }
|
||||
else if (model.indexOf('tp-link') >= 0) { result = 'TP-Link'; }
|
||||
else if (model.indexOf('asus') >= 0) { result = 'Asus'; }
|
||||
else if (model.indexOf('linksys') >= 0) { result = 'Linksys'; }
|
||||
return result;
|
||||
}
|
||||
|
||||
function formatBssid(s) {
|
||||
s = s.replace(/</g, '').replace(/>/g, '').match(/.{1,2}/g) || [];
|
||||
return s.join(':');
|
||||
}
|
||||
|
||||
function wifiConnections(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
const result = [];
|
||||
|
||||
if (_linux) {
|
||||
const ifaces = ifaceListLinux();
|
||||
const networkList = getWifiNetworkListNmi();
|
||||
ifaces.forEach(ifaceDetail => {
|
||||
let ifaceSanitized = '';
|
||||
const s = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(ifaceDetail.iface, true);
|
||||
const ll = util.mathMin(s.length, 2000);
|
||||
|
||||
for (let i = 0; i <= ll; i++) {
|
||||
if (s[i] !== undefined) {
|
||||
ifaceSanitized = ifaceSanitized + s[i];
|
||||
}
|
||||
}
|
||||
|
||||
const nmiDetails = nmiDeviceLinux(ifaceSanitized);
|
||||
const wpaDetails = wpaConnectionLinux(ifaceSanitized);
|
||||
const ssid = nmiDetails.ssid || wpaDetails.ssid;
|
||||
const network = networkList.filter(nw => nw.ssid === ssid);
|
||||
let ssidSanitized = '';
|
||||
const t = util.isPrototypePolluted() ? '---' : util.sanitizeShellString(ssid, true);
|
||||
const l = util.mathMin(t.length, 32);
|
||||
for (let i = 0; i <= l; i++) {
|
||||
if (t[i] !== undefined) {
|
||||
ssidSanitized = ssidSanitized + t[i];
|
||||
}
|
||||
}
|
||||
|
||||
const nmiConnection = nmiConnectionLinux(ssidSanitized);
|
||||
const channel = network && network.length && network[0].channel ? network[0].channel : (wpaDetails.channel ? wpaDetails.channel : null);
|
||||
const bssid = network && network.length && network[0].bssid ? network[0].bssid : (wpaDetails.bssid ? wpaDetails.bssid : null);
|
||||
const signalLevel = network && network.length && network[0].signalLevel ? network[0].signalLevel : null;
|
||||
if (ssid && bssid) {
|
||||
result.push({
|
||||
id: ifaceDetail.id,
|
||||
iface: ifaceDetail.iface,
|
||||
model: nmiDetails.product,
|
||||
ssid,
|
||||
bssid: network && network.length && network[0].bssid ? network[0].bssid : (wpaDetails.bssid ? wpaDetails.bssid : null),
|
||||
channel,
|
||||
frequency: channel ? wifiFrequencyFromChannel(channel) : null,
|
||||
type: nmiConnection.type ? nmiConnection.type : '802.11',
|
||||
security: nmiConnection.security ? nmiConnection.security : (wpaDetails.security ? wpaDetails.security : null),
|
||||
signalLevel,
|
||||
quality: wifiQualityFromDB(signalLevel),
|
||||
txRate: null
|
||||
});
|
||||
}
|
||||
});
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
} else if (_darwin) {
|
||||
let cmd = 'system_profiler SPNetworkDataType SPAirPortDataType -xml 2>/dev/null; echo "######" ; ioreg -n AppleBCMWLANSkywalkInterface -r 2>/dev/null';
|
||||
exec(cmd, function (error, stdout) {
|
||||
try {
|
||||
const parts = stdout.toString().split('######');
|
||||
const profilerObj = util.plistParser(parts[0]);
|
||||
const networkObj = profilerObj[0]._SPCommandLineArguments.indexOf('SPNetworkDataType') >= 0 ? profilerObj[0]._items : profilerObj[1]._items;
|
||||
const airportObj = profilerObj[0]._SPCommandLineArguments.indexOf('SPAirPortDataType') >= 0 ? profilerObj[0]._items[0].spairport_airport_interfaces : profilerObj[1]._items[0].spairport_airport_interfaces;
|
||||
|
||||
// parts[1] : ioreg
|
||||
let lines3 = [];
|
||||
if (parts[1].indexOf(' | {') > 0 && parts[1].indexOf(' | }') > parts[1].indexOf(' | {')) {
|
||||
lines3 = parts[1].split(' | {')[1].split(' | }')[0].replace(/ \| /g, '').replace(/"/g, '').split('\n');
|
||||
}
|
||||
|
||||
const networkWifiObj = networkObj.find((item) => { return item._name === 'Wi-Fi'; });
|
||||
const airportWifiObj = airportObj[0].spairport_current_network_information;
|
||||
|
||||
const channel = parseInt(('' + airportWifiObj.spairport_network_channel).split(' ')[0]) || 0;
|
||||
const signalLevel = airportWifiObj.spairport_signal_noise || null;
|
||||
|
||||
let security = [];
|
||||
const sm = airportWifiObj.spairport_security_mode || '';
|
||||
if (sm === 'spairport_security_mode_wep') {
|
||||
security.push('WEP');
|
||||
} else if (sm === 'spairport_security_mode_wpa2_personal') {
|
||||
security.push('WPA2');
|
||||
} else if (sm.startsWith('spairport_security_mode_wpa2_enterprise')) {
|
||||
security.push('WPA2 EAP');
|
||||
} else if (sm.startsWith('pairport_security_mode_wpa3_transition')) {
|
||||
security.push('WPA2/WPA3');
|
||||
} else if (sm.startsWith('pairport_security_mode_wpa3')) {
|
||||
security.push('WPA3');
|
||||
}
|
||||
|
||||
result.push({
|
||||
id: networkWifiObj._name || 'Wi-Fi',
|
||||
iface: networkWifiObj.interface || '',
|
||||
model: networkWifiObj.hardware || '',
|
||||
ssid: airportWifiObj._name || '',
|
||||
bssid: airportWifiObj.spairport_network_bssid || '',
|
||||
channel,
|
||||
frequency: channel ? wifiFrequencyFromChannel(channel) : null,
|
||||
type: airportWifiObj.spairport_network_phymode || '802.11',
|
||||
security,
|
||||
signalLevel: signalLevel ? parseInt(signalLevel, 10) : null,
|
||||
quality: wifiQualityFromDB(signalLevel),
|
||||
txRate: airportWifiObj.spairport_network_rate || null,
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
util.noop();
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} else if (_windows) {
|
||||
let cmd = 'netsh wlan show interfaces';
|
||||
util.powerShell(cmd).then(function (stdout) {
|
||||
const allLines = stdout.toString().split('\r\n');
|
||||
for (let i = 0; i < allLines.length; i++) {
|
||||
allLines[i] = allLines[i].trim();
|
||||
}
|
||||
const parts = allLines.join('\r\n').split(':\r\n\r\n');
|
||||
parts.shift();
|
||||
parts.forEach(part => {
|
||||
const lines = part.split('\r\n');
|
||||
if (lines.length >= 5) {
|
||||
const iface = lines[0].indexOf(':') >= 0 ? lines[0].split(':')[1].trim() : '';
|
||||
const model = lines[1].indexOf(':') >= 0 ? lines[1].split(':')[1].trim() : '';
|
||||
const id = lines[2].indexOf(':') >= 0 ? lines[2].split(':')[1].trim() : '';
|
||||
const ssid = util.getValue(lines, 'SSID', ':', true);
|
||||
const bssid = util.getValue(lines, 'BSSID', ':', true) || util.getValue(lines, 'AP BSSID', ':', true);
|
||||
const quality = util.getValue(lines, 'Signal', ':', true);
|
||||
const signalLevel = wifiDBFromQuality(quality);
|
||||
const type = util.getValue(lines, 'Radio type', ':', true) || util.getValue(lines, 'Type de radio', ':', true) || util.getValue(lines, 'Funktyp', ':', true) || null;
|
||||
const security = util.getValue(lines, 'authentication', ':', true) || util.getValue(lines, 'Authentification', ':', true) || util.getValue(lines, 'Authentifizierung', ':', true) || null;
|
||||
const channel = util.getValue(lines, 'Channel', ':', true) || util.getValue(lines, 'Canal', ':', true) || util.getValue(lines, 'Kanal', ':', true) || null;
|
||||
const txRate = util.getValue(lines, 'Transmit rate (mbps)', ':', true) || util.getValue(lines, 'Transmission (mbit/s)', ':', true) || util.getValue(lines, 'Empfangsrate (MBit/s)', ':', true) || null;
|
||||
if (model && id && ssid && bssid) {
|
||||
result.push({
|
||||
id,
|
||||
iface,
|
||||
model,
|
||||
ssid,
|
||||
bssid,
|
||||
channel: util.toInt(channel),
|
||||
frequency: channel ? wifiFrequencyFromChannel(channel) : null,
|
||||
type,
|
||||
security,
|
||||
signalLevel,
|
||||
quality: quality ? parseInt(quality, 10) : null,
|
||||
txRate: util.toInt(txRate) || null
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.wifiConnections = wifiConnections;
|
||||
|
||||
function wifiInterfaces(callback) {
|
||||
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
const result = [];
|
||||
|
||||
if (_linux) {
|
||||
const ifaces = ifaceListLinux();
|
||||
ifaces.forEach(ifaceDetail => {
|
||||
const nmiDetails = nmiDeviceLinux(ifaceDetail.iface);
|
||||
result.push({
|
||||
id: ifaceDetail.id,
|
||||
iface: ifaceDetail.iface,
|
||||
model: nmiDetails.product ? nmiDetails.product : null,
|
||||
vendor: nmiDetails.vendor ? nmiDetails.vendor : null,
|
||||
mac: ifaceDetail.mac,
|
||||
});
|
||||
});
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
} else if (_darwin) {
|
||||
let cmd = 'system_profiler SPNetworkDataType';
|
||||
exec(cmd, function (error, stdout) {
|
||||
const parts1 = stdout.toString().split('\n\n Wi-Fi:\n\n');
|
||||
if (parts1.length > 1) {
|
||||
const lines = parts1[1].split('\n\n')[0].split('\n');
|
||||
const iface = util.getValue(lines, 'BSD Device Name', ':', true);
|
||||
const mac = util.getValue(lines, 'MAC Address', ':', true);
|
||||
const model = util.getValue(lines, 'hardware', ':', true);
|
||||
result.push({
|
||||
id: 'Wi-Fi',
|
||||
iface,
|
||||
model,
|
||||
vendor: '',
|
||||
mac
|
||||
});
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} else if (_windows) {
|
||||
let cmd = 'netsh wlan show interfaces';
|
||||
util.powerShell(cmd).then(function (stdout) {
|
||||
const allLines = stdout.toString().split('\r\n');
|
||||
for (let i = 0; i < allLines.length; i++) {
|
||||
allLines[i] = allLines[i].trim();
|
||||
}
|
||||
const parts = allLines.join('\r\n').split(':\r\n\r\n');
|
||||
parts.shift();
|
||||
parts.forEach(part => {
|
||||
const lines = part.split('\r\n');
|
||||
if (lines.length >= 5) {
|
||||
const iface = lines[0].indexOf(':') >= 0 ? lines[0].split(':')[1].trim() : '';
|
||||
const model = lines[1].indexOf(':') >= 0 ? lines[1].split(':')[1].trim() : '';
|
||||
const id = lines[2].indexOf(':') >= 0 ? lines[2].split(':')[1].trim() : '';
|
||||
const macParts = lines[3].indexOf(':') >= 0 ? lines[3].split(':') : [];
|
||||
macParts.shift();
|
||||
const mac = macParts.join(':').trim();
|
||||
const vendor = getVendor(model);
|
||||
if (iface && model && id && mac) {
|
||||
result.push({
|
||||
id,
|
||||
iface,
|
||||
model,
|
||||
vendor,
|
||||
mac,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.wifiInterfaces = wifiInterfaces;
|
||||
101
api.hyungi.net/node_modules/systeminformation/package.json
generated
vendored
Normal file
101
api.hyungi.net/node_modules/systeminformation/package.json
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"name": "systeminformation",
|
||||
"version": "5.27.1",
|
||||
"description": "Advanced, lightweight system and OS information library",
|
||||
"license": "MIT",
|
||||
"author": "Sebastian Hildebrandt <hildebrandt@plus-innovations.com> (https://plus-innovations.com)",
|
||||
"homepage": "https://systeminformation.io",
|
||||
"main": "./lib/index.js",
|
||||
"type": "commonjs",
|
||||
"bin": {
|
||||
"systeminformation": "lib/cli.js"
|
||||
},
|
||||
"types": "./lib/index.d.ts",
|
||||
"scripts": {
|
||||
"test": "node ./test/test.js",
|
||||
"testDeno": "deno run -A ./test/test.js"
|
||||
},
|
||||
"files": [
|
||||
"lib/"
|
||||
],
|
||||
"keywords": [
|
||||
"system information",
|
||||
"sysinfo",
|
||||
"monitor",
|
||||
"monitoring",
|
||||
"os",
|
||||
"linux",
|
||||
"osx",
|
||||
"windows",
|
||||
"freebsd",
|
||||
"openbsd",
|
||||
"netbsd",
|
||||
"cpu",
|
||||
"cpuload",
|
||||
"physical cores",
|
||||
"logical cores",
|
||||
"processor",
|
||||
"cores",
|
||||
"threads",
|
||||
"socket type",
|
||||
"memory",
|
||||
"file system",
|
||||
"fsstats",
|
||||
"diskio",
|
||||
"block devices",
|
||||
"netstats",
|
||||
"network",
|
||||
"network interfaces",
|
||||
"network connections",
|
||||
"network stats",
|
||||
"iface",
|
||||
"printer",
|
||||
"processes",
|
||||
"users",
|
||||
"internet",
|
||||
"battery",
|
||||
"docker",
|
||||
"docker stats",
|
||||
"docker processes",
|
||||
"graphics",
|
||||
"graphic card",
|
||||
"graphic controller",
|
||||
"gpu",
|
||||
"display",
|
||||
"smart",
|
||||
"disk layout",
|
||||
"usb",
|
||||
"audio",
|
||||
"bluetooth",
|
||||
"wifi",
|
||||
"wifinetworks",
|
||||
"virtual box",
|
||||
"virtualbox",
|
||||
"vm",
|
||||
"backend",
|
||||
"hardware",
|
||||
"BIOS",
|
||||
"chassis"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebhildebrandt/systeminformation.git"
|
||||
},
|
||||
"funding": {
|
||||
"type": "Buy me a coffee",
|
||||
"url": "https://www.buymeacoffee.com/systeminfo"
|
||||
},
|
||||
"os": [
|
||||
"darwin",
|
||||
"linux",
|
||||
"win32",
|
||||
"freebsd",
|
||||
"openbsd",
|
||||
"netbsd",
|
||||
"sunos",
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user