@gjsify/os 0.0.4 → 0.1.1

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/README.md CHANGED
@@ -1,3 +1,28 @@
1
1
  # @gjsify/os
2
2
 
3
- Node.js os module for Gjs
3
+ GJS implementation of the Node.js `os` module using GLib. Provides homedir, hostname, cpus, and more.
4
+
5
+ Part of the [gjsify](https://github.com/gjsify/gjsify) project — Node.js and Web APIs for GJS (GNOME JavaScript).
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @gjsify/os
11
+ # or
12
+ yarn add @gjsify/os
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```typescript
18
+ import { homedir, hostname, platform, cpus } from '@gjsify/os';
19
+
20
+ console.log(homedir());
21
+ console.log(hostname());
22
+ console.log(platform());
23
+ console.log(cpus().length);
24
+ ```
25
+
26
+ ## License
27
+
28
+ MIT
@@ -115,6 +115,21 @@ var constants_default = {
115
115
  "SIGPOLL": 29,
116
116
  "SIGPWR": 30,
117
117
  "SIGSYS": 31
118
+ },
119
+ "priority": {
120
+ "PRIORITY_LOW": 19,
121
+ "PRIORITY_BELOW_NORMAL": 10,
122
+ "PRIORITY_NORMAL": 0,
123
+ "PRIORITY_ABOVE_NORMAL": -7,
124
+ "PRIORITY_HIGH": -14,
125
+ "PRIORITY_HIGHEST": -20
126
+ },
127
+ "dlopen": {
128
+ "RTLD_LAZY": 1,
129
+ "RTLD_NOW": 2,
130
+ "RTLD_GLOBAL": 256,
131
+ "RTLD_LOCAL": 0,
132
+ "RTLD_DEEPBIND": 8
118
133
  }
119
134
  };
120
135
  export {
package/lib/esm/darwin.js CHANGED
@@ -1,12 +1,10 @@
1
1
  import { createSubnet } from "./createSubnet.js";
2
2
  import { cli } from "@gjsify/utils";
3
- const EOL = /\r\n|\n/;
4
3
  const NOMAC = "00:00:00:00:00:00";
5
4
  const getIPv6Subnet = createSubnet(128, 16, 16, ":");
6
5
  const parseInterfaces = function(info) {
7
6
  info = info.trim();
8
- if (info.length < 1 || !/\binet\b/.test(info))
9
- return;
7
+ if (info.length < 1 || !/\binet\b/.test(info)) return;
10
8
  const lines = info.split("\n");
11
9
  const iface = [];
12
10
  const length = lines.length;
@@ -60,7 +58,27 @@ const cpus = () => {
60
58
  return cpus2;
61
59
  };
62
60
  const endianness = () => "LE";
63
- const freemem = () => parseFloat(cli("sysctl -n hw.memsize")) - parseFloat(cli("sysctl -n hw.physmem"));
61
+ const freemem = () => {
62
+ try {
63
+ const vmstat = cli("vm_stat");
64
+ const pageSizeMatch = /page size of (\d+) bytes/.exec(vmstat);
65
+ const pageSize = pageSizeMatch ? parseInt(pageSizeMatch[1], 10) : 16384;
66
+ let freePages = 0;
67
+ const freeMatch = /Pages free:\s+(\d+)/.exec(vmstat);
68
+ if (freeMatch) freePages += parseInt(freeMatch[1], 10);
69
+ const specMatch = /Pages speculative:\s+(\d+)/.exec(vmstat);
70
+ if (specMatch) freePages += parseInt(specMatch[1], 10);
71
+ const purgeMatch = /Pages purgeable:\s+(\d+)/.exec(vmstat);
72
+ if (purgeMatch) freePages += parseInt(purgeMatch[1], 10);
73
+ if (freePages > 0) return freePages * pageSize;
74
+ } catch {
75
+ }
76
+ try {
77
+ return parseFloat(cli("sysctl -n hw.memsize")) - parseFloat(cli("sysctl -n hw.physmem"));
78
+ } catch {
79
+ return 0;
80
+ }
81
+ };
64
82
  const loadavg = () => /load\s+averages:\s+(\d+(?:\.\d+))\s+(\d+(?:\.\d+))\s+(\d+(?:\.\d+))/.test(
65
83
  cli("uptime")
66
84
  ) && [
@@ -71,7 +89,7 @@ const loadavg = () => /load\s+averages:\s+(\d+(?:\.\d+))\s+(\d+(?:\.\d+))\s+(\d+
71
89
  const networkInterfaces = () => {
72
90
  const ifaces = {};
73
91
  const groups = [];
74
- const lines = cli("ifconfig").split(EOL);
92
+ const lines = cli("ifconfig").split(/\r\n|\n/);
75
93
  const length = lines.length;
76
94
  for (let group = [], re = /^\S+?:/, i = 0; i < length; i++) {
77
95
  if (re.test(lines[i])) {
@@ -81,28 +99,46 @@ const networkInterfaces = () => {
81
99
  }
82
100
  --i;
83
101
  }
84
- groups.push(group.join(EOL));
102
+ groups.push(group.join("\n"));
85
103
  }
86
104
  groups.forEach(parseInterfaces, ifaces);
87
105
  return ifaces;
88
106
  };
89
107
  const totalmem = () => {
90
- let I, mem = cli("free -b").split(EOL);
91
- mem[0].split(/\s+/).some((info, i) => info === "total" && (I = i));
92
- return parseFloat(mem[1].split(/\s+/)[I + 1]);
108
+ try {
109
+ return parseFloat(cli("sysctl -n hw.memsize"));
110
+ } catch {
111
+ return 0;
112
+ }
93
113
  };
94
114
  const uptime = () => {
95
- const uptime2 = cli("uptime");
96
- const up = /up\s+([^,]+)?,/.test(uptime2) && RegExp.$1;
115
+ try {
116
+ const boottime = cli("sysctl -n kern.boottime");
117
+ const secMatch = /sec\s*=\s*(\d+)/.exec(boottime);
118
+ if (secMatch) {
119
+ const bootSec = parseInt(secMatch[1], 10);
120
+ const nowSec = Math.floor(Date.now() / 1e3);
121
+ return nowSec - bootSec;
122
+ }
123
+ } catch {
124
+ }
125
+ const output = cli("uptime");
126
+ const up = /up\s+([^,]+)?,/.test(output) && RegExp.$1;
97
127
  switch (true) {
98
128
  case /^(\d+):(\d+)$/.test(up):
99
129
  return (parseInt(RegExp.$1, 10) * 60 + parseInt(RegExp.$2, 10)) * 60;
100
130
  case /^(\d+)\s+mins?$/.test(up):
101
131
  return parseInt(RegExp.$1, 10) * 60;
102
- case /^(\d+)\s+days?$/.test(up):
103
- return parseInt(RegExp.$1, 10) * 86400 + (/days?,\s+^(\d+):(\d+)$/.test(uptime2) && (parseInt(RegExp.$1, 10) * 60 + parseInt(RegExp.$2, 10)) * 60);
132
+ case /^(\d+)\s+days?$/.test(up): {
133
+ const days = parseInt(RegExp.$1, 10) * 86400;
134
+ const timeMatch = /days?,\s+(\d+):(\d+)/.exec(output);
135
+ if (timeMatch) {
136
+ return days + (parseInt(timeMatch[1], 10) * 60 + parseInt(timeMatch[2], 10)) * 60;
137
+ }
138
+ return days;
139
+ }
104
140
  }
105
- return up;
141
+ return 0;
106
142
  };
107
143
  export {
108
144
  cpus,
package/lib/esm/index.js CHANGED
@@ -1,92 +1,234 @@
1
- import { cli, getPathSeparator, getOs } from "@gjsify/utils";
1
+ import { cli, getPathSeparator } from "@gjsify/utils";
2
+ import Gio from "@girs/gio-2.0";
3
+ let _os = "";
4
+ const getOs = () => {
5
+ if (_os) return _os;
6
+ const os = cli("uname -o").trim();
7
+ if (/\bDarwin\b/i.test(os)) {
8
+ _os = "darwin";
9
+ return _os;
10
+ }
11
+ if (/\bLinux\b/i.test(os)) {
12
+ _os = "linux";
13
+ return _os;
14
+ }
15
+ _os = "win32";
16
+ return _os;
17
+ };
18
+ let _pid = 0;
19
+ const getPid = () => {
20
+ if (!_pid) _pid = new Gio.Credentials().get_unix_pid();
21
+ return _pid;
22
+ };
2
23
  import * as linux from "./linux.js";
3
24
  import * as darwin from "./darwin.js";
4
25
  import GLib from "@girs/glib-2.0";
5
26
  import constants from "./constants.js";
6
27
  const EOL = getPathSeparator() === "/" ? "\n" : "\r\n";
28
+ const devNull = getPathSeparator() === "/" ? "/dev/null" : "\\\\.\\nul";
7
29
  const homedir = () => GLib.get_home_dir();
8
30
  const hostname = () => GLib.get_host_name();
9
- const release = () => cli("uname -r");
31
+ const release = () => cli("uname -r").trim();
10
32
  const tmpdir = () => GLib.get_tmp_dir();
11
- const type = () => cli("uname");
12
- const userInfo = () => ({
13
- uid: 1e3,
14
- gid: 100,
15
- username: GLib.get_user_name(),
16
- homedir: GLib.get_home_dir()
17
- });
33
+ const type = () => cli("uname").trim();
34
+ const platform = () => cli("uname -s").trim().toLowerCase();
35
+ const arch = () => {
36
+ const machine2 = cli("uname -m").trim();
37
+ if (machine2 === "x86_64" || machine2 === "amd64") return "x64";
38
+ if (machine2 === "aarch64" || machine2 === "arm64") return "arm64";
39
+ if (machine2 === "i686" || machine2 === "i386") return "ia32";
40
+ if (machine2.startsWith("arm")) return "arm";
41
+ return machine2;
42
+ };
43
+ const machine = () => cli("uname -m").trim();
44
+ const version = () => cli("uname -v").trim();
45
+ const uptime = () => {
46
+ const _os2 = getOs();
47
+ switch (_os2) {
48
+ case "darwin":
49
+ return darwin.uptime();
50
+ case "linux":
51
+ return linux.uptime();
52
+ default:
53
+ return 0;
54
+ }
55
+ };
56
+ const totalmem = () => {
57
+ const _os2 = getOs();
58
+ switch (_os2) {
59
+ case "darwin":
60
+ return darwin.totalmem();
61
+ case "linux":
62
+ return linux.totalmem();
63
+ default:
64
+ return 0;
65
+ }
66
+ };
67
+ const availableParallelism = () => {
68
+ const c = cpus();
69
+ return c ? c.length : 1;
70
+ };
71
+ const userInfo = () => {
72
+ let uid = 1e3;
73
+ let gid = 100;
74
+ let shell = "";
75
+ try {
76
+ uid = parseInt(cli("id -u"), 10);
77
+ gid = parseInt(cli("id -g"), 10);
78
+ shell = GLib.getenv("SHELL") || "";
79
+ } catch {
80
+ }
81
+ return {
82
+ uid,
83
+ gid,
84
+ username: GLib.get_user_name(),
85
+ homedir: GLib.get_home_dir(),
86
+ shell
87
+ };
88
+ };
18
89
  const cpus = () => {
19
- const _os = getOs();
20
- switch (_os) {
90
+ const _os2 = getOs();
91
+ switch (_os2) {
21
92
  case "darwin":
22
93
  return darwin.cpus();
23
94
  case "linux":
24
95
  return linux.cpus();
25
96
  default:
26
- console.warn(`${_os} is not supported!`);
97
+ console.warn(`${_os2} is not supported!`);
27
98
  break;
28
99
  }
29
100
  };
30
101
  const endianness = () => {
31
- const _os = getOs();
32
- switch (_os) {
102
+ const _os2 = getOs();
103
+ switch (_os2) {
33
104
  case "darwin":
34
105
  return darwin.endianness();
35
106
  case "linux":
36
107
  return linux.endianness();
37
108
  default:
38
- console.warn(`${_os} is not supported!`);
109
+ console.warn(`${_os2} is not supported!`);
39
110
  break;
40
111
  }
41
112
  };
42
113
  const freemem = () => {
43
- const _os = getOs();
44
- switch (_os) {
114
+ const _os2 = getOs();
115
+ switch (_os2) {
45
116
  case "darwin":
46
117
  return darwin.freemem();
47
118
  case "linux":
48
119
  return linux.freemem();
49
120
  default:
50
- console.warn(`${_os} is not supported!`);
121
+ console.warn(`${_os2} is not supported!`);
51
122
  break;
52
123
  }
53
124
  };
54
125
  const loadavg = () => {
55
- const _os = getOs();
56
- switch (_os) {
126
+ const _os2 = getOs();
127
+ switch (_os2) {
57
128
  case "darwin":
58
129
  return darwin.loadavg();
59
130
  case "linux":
60
131
  return linux.loadavg();
61
132
  default:
62
- console.warn(`${_os} is not supported!`);
133
+ console.warn(`${_os2} is not supported!`);
63
134
  break;
64
135
  }
65
136
  };
66
137
  const networkInterfaces = () => {
67
- const _os = getOs();
68
- switch (_os) {
138
+ const _os2 = getOs();
139
+ switch (_os2) {
69
140
  case "darwin":
70
141
  return darwin.networkInterfaces();
71
142
  case "linux":
72
143
  return linux.networkInterfaces();
73
144
  default:
74
- console.warn(`${_os} is not supported!`);
145
+ console.warn(`${_os2} is not supported!`);
75
146
  break;
76
147
  }
77
148
  };
149
+ const getPriority = (pid) => {
150
+ const targetPid = pid === void 0 || pid === 0 ? getPid() : pid;
151
+ try {
152
+ const nice = cli(`ps -o ni= -p ${targetPid}`).trim();
153
+ const val = parseInt(nice, 10);
154
+ if (!isNaN(val)) return val;
155
+ } catch {
156
+ }
157
+ return 0;
158
+ };
159
+ const setPriority = (pidOrPriority, priority) => {
160
+ let pid;
161
+ let prio;
162
+ if (priority === void 0) {
163
+ prio = pidOrPriority;
164
+ pid = 0;
165
+ } else {
166
+ pid = pidOrPriority;
167
+ prio = priority;
168
+ }
169
+ if (typeof pid !== "number" || !Number.isInteger(pid)) {
170
+ throw new TypeError('The "pid" argument must be an integer');
171
+ }
172
+ if (typeof prio !== "number" || !Number.isInteger(prio) || prio < -20 || prio > 19) {
173
+ throw new RangeError('The "priority" argument must be an integer between -20 and 19');
174
+ }
175
+ try {
176
+ const actualPid = pid === 0 ? getPid() : pid;
177
+ cli(`renice -n ${prio} -p ${actualPid}`);
178
+ } catch (err) {
179
+ const error = new Error(`A system error occurred: priority could not be set`);
180
+ error.code = "ERR_SYSTEM_ERROR";
181
+ throw error;
182
+ }
183
+ };
184
+ var index_default = {
185
+ EOL,
186
+ arch,
187
+ availableParallelism,
188
+ constants,
189
+ cpus,
190
+ devNull,
191
+ endianness,
192
+ freemem,
193
+ getPriority,
194
+ homedir,
195
+ hostname,
196
+ loadavg,
197
+ machine,
198
+ networkInterfaces,
199
+ platform,
200
+ release,
201
+ setPriority,
202
+ tmpdir,
203
+ totalmem,
204
+ type,
205
+ uptime,
206
+ userInfo,
207
+ version
208
+ };
78
209
  export {
79
210
  EOL,
211
+ arch,
212
+ availableParallelism,
80
213
  constants,
81
214
  cpus,
215
+ index_default as default,
216
+ devNull,
82
217
  endianness,
83
218
  freemem,
219
+ getPriority,
84
220
  homedir,
85
221
  hostname,
86
222
  loadavg,
223
+ machine,
87
224
  networkInterfaces,
225
+ platform,
88
226
  release,
227
+ setPriority,
89
228
  tmpdir,
229
+ totalmem,
90
230
  type,
91
- userInfo
231
+ uptime,
232
+ userInfo,
233
+ version
92
234
  };
package/lib/esm/linux.js CHANGED
@@ -1,12 +1,18 @@
1
+ import GLib from "@girs/glib-2.0";
1
2
  import { createSubnet } from "./createSubnet.js";
2
3
  import { cli } from "@gjsify/utils";
4
+ const byteArray = imports.byteArray;
3
5
  const EOL = /\r\n|\n/;
6
+ function readTextFile(path) {
7
+ const [ok, contents] = GLib.file_get_contents(path);
8
+ if (!ok || !contents) return "";
9
+ return byteArray.toString(contents);
10
+ }
4
11
  const getIPv4Subnet = createSubnet(32, 8, 10, ".");
5
12
  const getIPv6Subnet = createSubnet(128, 16, 16, ":");
6
13
  function parseInterfaces(info) {
7
14
  info = info.trim();
8
- if (info.length < 1)
9
- return;
15
+ if (info.length < 1) return;
10
16
  let iface = [], mac;
11
17
  for (let line, lines = info.split(EOL), i = 0; i < lines.length; i++) {
12
18
  line = lines[i];
@@ -26,25 +32,22 @@ function parseInterfaces(info) {
26
32
  break;
27
33
  }
28
34
  }
29
- if (mac)
30
- this[info.slice(0, info.indexOf(":"))] = iface;
35
+ if (mac) this[info.slice(0, info.indexOf(":"))] = iface;
31
36
  }
32
37
  ;
33
38
  const cpus = () => {
34
39
  const PROCESSOR = /^processor\s*:\s*(\d+)/i;
35
40
  const NAME = /^model[\s_]+name\s*:([^\r\n]+)/i;
36
41
  const FREQ = /^cpu[\s_]+MHz\s*:\s*(\d+)/i;
37
- const cpus2 = [];
42
+ const result = [];
38
43
  let cpu;
39
- cli("cat /proc/cpuinfo").split(EOL).forEach((line) => {
44
+ readTextFile("/proc/cpuinfo").split(EOL).forEach((line) => {
40
45
  switch (true) {
41
46
  case PROCESSOR.test(line):
42
- cpus2[RegExp.$1.trim()] = cpu = {
47
+ result[RegExp.$1.trim()] = cpu = {
43
48
  model: "",
44
49
  speed: 0,
45
- get times() {
46
- return {};
47
- }
50
+ times: { user: 0, nice: 0, sys: 0, idle: 0, irq: 0 }
48
51
  };
49
52
  break;
50
53
  case NAME.test(line):
@@ -55,32 +58,114 @@ const cpus = () => {
55
58
  break;
56
59
  }
57
60
  });
58
- return cpus2;
61
+ try {
62
+ const statLines = readTextFile("/proc/stat").split(EOL);
63
+ for (const line of statLines) {
64
+ const m = /^cpu(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\d+\s+(\d+)/.exec(line);
65
+ if (m && result[parseInt(m[1], 10)]) {
66
+ result[parseInt(m[1], 10)].times = {
67
+ user: parseInt(m[2], 10) * 10,
68
+ nice: parseInt(m[3], 10) * 10,
69
+ sys: parseInt(m[4], 10) * 10,
70
+ idle: parseInt(m[5], 10) * 10,
71
+ irq: parseInt(m[6], 10) * 10
72
+ };
73
+ }
74
+ }
75
+ } catch {
76
+ }
77
+ return result;
59
78
  };
60
79
  const endianness = () => "LE";
61
80
  const freemem = () => {
62
- let I, mem = cli("free -b").split(EOL);
63
- mem[0].split(/\s+/).some((info, i) => info === "free" && (I = i));
64
- return parseFloat(mem[1].split(/\s+/)[I + 1]);
81
+ const content = readTextFile("/proc/meminfo");
82
+ let memFree = 0;
83
+ for (const line of content.split("\n")) {
84
+ const available = /^MemAvailable:\s+(\d+)\s+kB/.exec(line);
85
+ if (available) return parseInt(available[1], 10) * 1024;
86
+ const free = /^MemFree:\s+(\d+)\s+kB/.exec(line);
87
+ if (free) memFree = parseInt(free[1], 10) * 1024;
88
+ }
89
+ return memFree;
65
90
  };
66
91
  const loadavg = () => /(\d+(?:\.\d+))\s+(\d+(?:\.\d+))\s+(\d+(?:\.\d+))/.test(
67
- cli("cat /proc/loadavg")
92
+ readTextFile("/proc/loadavg")
68
93
  ) && [
69
94
  parseFloat(RegExp.$1),
70
95
  parseFloat(RegExp.$2),
71
96
  parseFloat(RegExp.$3)
72
97
  ];
73
98
  const networkInterfaces = () => {
99
+ try {
100
+ const ifaces = {};
101
+ cli("ip addr").split(/^\d+:\s+/m).forEach(parseInterfaces, ifaces);
102
+ return ifaces;
103
+ } catch {
104
+ return readNetworkInterfacesFromProc();
105
+ }
106
+ };
107
+ function readNetworkInterfacesFromProc() {
74
108
  const ifaces = {};
75
- cli("ip addr").split(/^\d+:\s+/m).forEach(parseInterfaces, ifaces);
109
+ const macs = {};
110
+ try {
111
+ const netDev = readTextFile("/proc/net/dev");
112
+ for (const line of netDev.split("\n").slice(2)) {
113
+ const name = line.split(":")[0]?.trim();
114
+ if (!name) continue;
115
+ ifaces[name] = [];
116
+ try {
117
+ macs[name] = readTextFile(`/sys/class/net/${name}/address`).trim();
118
+ } catch {
119
+ macs[name] = "00:00:00:00:00:00";
120
+ }
121
+ }
122
+ } catch {
123
+ return ifaces;
124
+ }
125
+ try {
126
+ const inet6 = readTextFile("/proc/net/if_inet6");
127
+ for (const line of inet6.split("\n")) {
128
+ const parts = line.trim().split(/\s+/);
129
+ if (parts.length < 6) continue;
130
+ const [addrHex, , prefixLen, , , devName] = parts;
131
+ const groups = addrHex.match(/.{4}/g);
132
+ if (!groups || !ifaces[devName]) continue;
133
+ ifaces[devName].push({
134
+ address: groups.join(":"),
135
+ netmask: getIPv6Subnet(prefixLen),
136
+ family: "IPv6",
137
+ mac: macs[devName] || "00:00:00:00:00:00",
138
+ internal: devName === "lo"
139
+ });
140
+ }
141
+ } catch {
142
+ }
143
+ if (ifaces["lo"]) {
144
+ ifaces["lo"].unshift({
145
+ address: "127.0.0.1",
146
+ netmask: "255.0.0.0",
147
+ family: "IPv4",
148
+ mac: macs["lo"] || "00:00:00:00:00:00",
149
+ internal: true
150
+ });
151
+ }
152
+ for (const name of Object.keys(ifaces)) {
153
+ if (ifaces[name].length === 0) delete ifaces[name];
154
+ }
76
155
  return ifaces;
77
- };
156
+ }
78
157
  const totalmem = () => {
79
- let I, mem = cli("free -b").split(EOL);
80
- mem[0].split(/\s+/).some((info, i) => info === "total" && (I = i));
81
- return parseFloat(mem[1].split(/\s+/)[I + 1]);
158
+ const content = readTextFile("/proc/meminfo");
159
+ for (const line of content.split("\n")) {
160
+ const match = /^MemTotal:\s+(\d+)\s+kB/.exec(line);
161
+ if (match) return parseInt(match[1], 10) * 1024;
162
+ }
163
+ return 0;
164
+ };
165
+ const uptime = () => {
166
+ const content = readTextFile("/proc/uptime").trim();
167
+ return parseFloat(content.split(" ")[0]) || 0;
82
168
  };
83
- const uptime = () => (Date.now() - Date.parse(cli("uptime -s").replace(" ", "T"))) / 1e3;
84
169
  export {
85
170
  cpus,
86
171
  endianness,