@gjsify/os 0.3.13 → 0.3.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/constants.js +136 -135
- package/lib/esm/createSubnet.js +13 -13
- package/lib/esm/darwin.js +132 -133
- package/lib/esm/index.js +170 -196
- package/lib/esm/linux.js +158 -152
- package/lib/esm/win32.js +3 -0
- package/package.json +6 -6
package/lib/esm/linux.js
CHANGED
|
@@ -1,177 +1,183 @@
|
|
|
1
|
-
import GLib from "@girs/glib-2.0";
|
|
2
1
|
import { createSubnet } from "./createSubnet.js";
|
|
3
2
|
import { cli } from "@gjsify/utils";
|
|
3
|
+
import GLib from "@girs/glib-2.0";
|
|
4
|
+
|
|
5
|
+
//#region src/linux.ts
|
|
4
6
|
const byteArray = imports.byteArray;
|
|
5
7
|
const EOL = /\r\n|\n/;
|
|
8
|
+
/**
|
|
9
|
+
* Read a text file directly via GLib (no subprocess).
|
|
10
|
+
*/
|
|
6
11
|
function readTextFile(path) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
12
|
+
const [ok, contents] = GLib.file_get_contents(path);
|
|
13
|
+
if (!ok || !contents) return "";
|
|
14
|
+
return byteArray.toString(contents);
|
|
10
15
|
}
|
|
11
16
|
const getIPv4Subnet = createSubnet(32, 8, 10, ".");
|
|
12
17
|
const getIPv6Subnet = createSubnet(128, 16, 16, ":");
|
|
13
18
|
function parseInterfaces(info) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
19
|
+
info = info.trim();
|
|
20
|
+
if (info.length < 1) return;
|
|
21
|
+
let iface = [], mac;
|
|
22
|
+
for (let line, lines = info.split(EOL), i = 0; i < lines.length; i++) {
|
|
23
|
+
line = lines[i];
|
|
24
|
+
switch (true) {
|
|
25
|
+
case /link\/\S+\s+((?:\S{2}:)+\S{2})/.test(line):
|
|
26
|
+
mac = RegExp.$1;
|
|
27
|
+
break;
|
|
28
|
+
case /inet(\d*)\s+(\S+)/.test(line):
|
|
29
|
+
let ip = RegExp.$2.split("/"), v = RegExp.$1 || "4";
|
|
30
|
+
iface.push({
|
|
31
|
+
address: ip[0],
|
|
32
|
+
netmask: (v === "4" ? getIPv4Subnet : getIPv6Subnet)(ip[1]),
|
|
33
|
+
family: "IPv" + v,
|
|
34
|
+
mac,
|
|
35
|
+
internal: ip[0] === "127.0.0.1"
|
|
36
|
+
});
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (mac) this[info.slice(0, info.indexOf(":"))] = iface;
|
|
36
41
|
}
|
|
37
42
|
;
|
|
38
43
|
const cpus = () => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
44
|
+
const PROCESSOR = /^processor\s*:\s*(\d+)/i;
|
|
45
|
+
const NAME = /^model[\s_]+name\s*:([^\r\n]+)/i;
|
|
46
|
+
const FREQ = /^cpu[\s_]+MHz\s*:\s*(\d+)/i;
|
|
47
|
+
const result = [];
|
|
48
|
+
let cpu;
|
|
49
|
+
readTextFile("/proc/cpuinfo").split(EOL).forEach((line) => {
|
|
50
|
+
switch (true) {
|
|
51
|
+
case PROCESSOR.test(line):
|
|
52
|
+
result[RegExp.$1.trim()] = cpu = {
|
|
53
|
+
model: "",
|
|
54
|
+
speed: 0,
|
|
55
|
+
times: {
|
|
56
|
+
user: 0,
|
|
57
|
+
nice: 0,
|
|
58
|
+
sys: 0,
|
|
59
|
+
idle: 0,
|
|
60
|
+
irq: 0
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
break;
|
|
64
|
+
case NAME.test(line):
|
|
65
|
+
cpu.model = RegExp.$1.trim();
|
|
66
|
+
break;
|
|
67
|
+
case FREQ.test(line):
|
|
68
|
+
cpu.speed = parseFloat(RegExp.$1.trim());
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
try {
|
|
73
|
+
const statLines = readTextFile("/proc/stat").split(EOL);
|
|
74
|
+
for (const line of statLines) {
|
|
75
|
+
const m = /^cpu(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+\s+(\d+)/.exec(line);
|
|
76
|
+
if (m && result[parseInt(m[1], 10)]) {
|
|
77
|
+
result[parseInt(m[1], 10)].times = {
|
|
78
|
+
user: parseInt(m[2], 10) * 10,
|
|
79
|
+
nice: parseInt(m[3], 10) * 10,
|
|
80
|
+
sys: parseInt(m[4], 10) * 10,
|
|
81
|
+
idle: parseInt(m[5], 10) * 10,
|
|
82
|
+
irq: parseInt(m[6], 10) * 10
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} catch {}
|
|
87
|
+
return result;
|
|
78
88
|
};
|
|
79
89
|
const endianness = () => "LE";
|
|
80
90
|
const freemem = () => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
91
|
+
const content = readTextFile("/proc/meminfo");
|
|
92
|
+
let memFree = 0;
|
|
93
|
+
for (const line of content.split("\n")) {
|
|
94
|
+
const available = /^MemAvailable:\s+(\d+)\s+kB/.exec(line);
|
|
95
|
+
if (available) return parseInt(available[1], 10) * 1024;
|
|
96
|
+
const free = /^MemFree:\s+(\d+)\s+kB/.exec(line);
|
|
97
|
+
if (free) memFree = parseInt(free[1], 10) * 1024;
|
|
98
|
+
}
|
|
99
|
+
return memFree;
|
|
90
100
|
};
|
|
91
|
-
const loadavg = () => /(\d+(?:\.\d+))\s+(\d+(?:\.\d+))\s+(\d+(?:\.\d+))/.test(
|
|
92
|
-
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
parseFloat(RegExp.$2),
|
|
96
|
-
parseFloat(RegExp.$3)
|
|
101
|
+
const loadavg = () => /(\d+(?:\.\d+))\s+(\d+(?:\.\d+))\s+(\d+(?:\.\d+))/.test(readTextFile("/proc/loadavg")) && [
|
|
102
|
+
parseFloat(RegExp.$1),
|
|
103
|
+
parseFloat(RegExp.$2),
|
|
104
|
+
parseFloat(RegExp.$3)
|
|
97
105
|
];
|
|
98
106
|
const networkInterfaces = () => {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
107
|
+
try {
|
|
108
|
+
const ifaces = {};
|
|
109
|
+
cli("ip addr").split(/^\d+:\s+/m).forEach(parseInterfaces, ifaces);
|
|
110
|
+
return ifaces;
|
|
111
|
+
} catch {
|
|
112
|
+
return readNetworkInterfacesFromProc();
|
|
113
|
+
}
|
|
106
114
|
};
|
|
115
|
+
/**
|
|
116
|
+
* Fallback: read network interface data from procfs/sysfs when `ip` is unavailable.
|
|
117
|
+
* Provides interface names + MACs from sysfs, IPv6 from /proc/net/if_inet6,
|
|
118
|
+
* and loopback IPv4 (127.0.0.1). Other IPv4 addresses require `ip` or `ifconfig`.
|
|
119
|
+
*/
|
|
107
120
|
function readNetworkInterfacesFromProc() {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
return ifaces;
|
|
121
|
+
const ifaces = {};
|
|
122
|
+
const macs = {};
|
|
123
|
+
try {
|
|
124
|
+
const netDev = readTextFile("/proc/net/dev");
|
|
125
|
+
for (const line of netDev.split("\n").slice(2)) {
|
|
126
|
+
const name = line.split(":")[0]?.trim();
|
|
127
|
+
if (!name) continue;
|
|
128
|
+
ifaces[name] = [];
|
|
129
|
+
try {
|
|
130
|
+
macs[name] = readTextFile(`/sys/class/net/${name}/address`).trim();
|
|
131
|
+
} catch {
|
|
132
|
+
macs[name] = "00:00:00:00:00:00";
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} catch {
|
|
136
|
+
return ifaces;
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const inet6 = readTextFile("/proc/net/if_inet6");
|
|
140
|
+
for (const line of inet6.split("\n")) {
|
|
141
|
+
const parts = line.trim().split(/\s+/);
|
|
142
|
+
if (parts.length < 6) continue;
|
|
143
|
+
const [addrHex, , prefixLen, , , devName] = parts;
|
|
144
|
+
const groups = addrHex.match(/.{4}/g);
|
|
145
|
+
if (!groups || !ifaces[devName]) continue;
|
|
146
|
+
ifaces[devName].push({
|
|
147
|
+
address: groups.join(":"),
|
|
148
|
+
netmask: getIPv6Subnet(prefixLen),
|
|
149
|
+
family: "IPv6",
|
|
150
|
+
mac: macs[devName] || "00:00:00:00:00:00",
|
|
151
|
+
internal: devName === "lo"
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
} catch {}
|
|
155
|
+
if (ifaces["lo"]) {
|
|
156
|
+
ifaces["lo"].unshift({
|
|
157
|
+
address: "127.0.0.1",
|
|
158
|
+
netmask: "255.0.0.0",
|
|
159
|
+
family: "IPv4",
|
|
160
|
+
mac: macs["lo"] || "00:00:00:00:00:00",
|
|
161
|
+
internal: true
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
for (const name of Object.keys(ifaces)) {
|
|
165
|
+
if (ifaces[name].length === 0) delete ifaces[name];
|
|
166
|
+
}
|
|
167
|
+
return ifaces;
|
|
156
168
|
}
|
|
157
169
|
const totalmem = () => {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
170
|
+
const content = readTextFile("/proc/meminfo");
|
|
171
|
+
for (const line of content.split("\n")) {
|
|
172
|
+
const match = /^MemTotal:\s+(\d+)\s+kB/.exec(line);
|
|
173
|
+
if (match) return parseInt(match[1], 10) * 1024;
|
|
174
|
+
}
|
|
175
|
+
return 0;
|
|
164
176
|
};
|
|
165
177
|
const uptime = () => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
};
|
|
169
|
-
export {
|
|
170
|
-
cpus,
|
|
171
|
-
endianness,
|
|
172
|
-
freemem,
|
|
173
|
-
loadavg,
|
|
174
|
-
networkInterfaces,
|
|
175
|
-
totalmem,
|
|
176
|
-
uptime
|
|
178
|
+
const content = readTextFile("/proc/uptime").trim();
|
|
179
|
+
return parseFloat(content.split(" ")[0]) || 0;
|
|
177
180
|
};
|
|
181
|
+
|
|
182
|
+
//#endregion
|
|
183
|
+
export { cpus, endianness, freemem, loadavg, networkInterfaces, totalmem, uptime };
|
package/lib/esm/win32.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/os",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.14",
|
|
4
4
|
"description": "Node.js os module for Gjs",
|
|
5
5
|
"module": "lib/esm/index.js",
|
|
6
6
|
"types": "lib/types/index.d.ts",
|
|
@@ -30,13 +30,13 @@
|
|
|
30
30
|
"os"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@girs/gio-2.0": "
|
|
34
|
-
"@girs/glib-2.0": "
|
|
35
|
-
"@gjsify/utils": "^0.3.
|
|
33
|
+
"@girs/gio-2.0": "2.88.0-4.0.0-rc.9",
|
|
34
|
+
"@girs/glib-2.0": "2.88.0-4.0.0-rc.9",
|
|
35
|
+
"@gjsify/utils": "^0.3.14"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@gjsify/cli": "^0.3.
|
|
39
|
-
"@gjsify/unit": "^0.3.
|
|
38
|
+
"@gjsify/cli": "^0.3.14",
|
|
39
|
+
"@gjsify/unit": "^0.3.14",
|
|
40
40
|
"@types/node": "^25.6.0",
|
|
41
41
|
"typescript": "^6.0.3"
|
|
42
42
|
}
|