@gjsify/process 0.0.4 → 0.1.0

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,10 +1,35 @@
1
1
  # @gjsify/process
2
2
 
3
- Node.js process module for Gjs
3
+ GJS implementation of the Node.js `process` module using GLib. Extends EventEmitter with env, cwd, platform, 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/process
11
+ # or
12
+ yarn add @gjsify/process
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```typescript
18
+ import process from '@gjsify/process';
19
+
20
+ console.log(process.cwd());
21
+ console.log(process.env.HOME);
22
+ console.log(process.platform);
23
+ ```
4
24
 
5
25
  ## Inspirations and credits
26
+
6
27
  - https://github.com/cgjs/cgjs/tree/master/packages/process
7
28
  - https://github.com/denoland/deno_std/blob/main/node/process.ts
8
29
  - https://github.com/geut/brode/blob/main/packages/browser-node-core/src/process.js
9
30
  - https://github.com/aleclarson/process-browserify
10
- - https://github.com/defunctzombie/node-process
31
+ - https://github.com/defunctzombie/node-process
32
+
33
+ ## License
34
+
35
+ MIT
package/lib/esm/index.js CHANGED
@@ -1,6 +1,432 @@
1
- export * from "@gjsify/deno_std/node/process";
2
- import process from "@gjsify/deno_std/node/process";
3
- var src_default = process;
1
+ import { EventEmitter } from "@gjsify/events";
2
+ function getGjsGlobal() {
3
+ return globalThis;
4
+ }
5
+ function detectGjsVersion() {
6
+ try {
7
+ const system = getGjsGlobal().imports?.system;
8
+ if (system?.version !== void 0) {
9
+ const v = Number(system.version);
10
+ const major = Math.floor(v / 1e4);
11
+ const minor = Math.floor(v % 1e4 / 100);
12
+ const patch = v % 100;
13
+ return `${major}.${minor}.${patch}`;
14
+ }
15
+ } catch {
16
+ }
17
+ return void 0;
18
+ }
19
+ function detectNodeVersion() {
20
+ if (typeof globalThis.process?.versions?.node === "string") {
21
+ return globalThis.process.versions.node;
22
+ }
23
+ return void 0;
24
+ }
25
+ function detectVersionInfo() {
26
+ const nodeVersion = detectNodeVersion();
27
+ if (nodeVersion) {
28
+ return {
29
+ version: globalThis.process.version,
30
+ versions: { ...globalThis.process.versions },
31
+ title: globalThis.process?.title || "node"
32
+ };
33
+ }
34
+ const gjsVersion = detectGjsVersion();
35
+ const versions2 = {
36
+ node: "20.0.0"
37
+ // Compatibility version — many npm packages check process.versions.node
38
+ };
39
+ if (gjsVersion) versions2.gjs = gjsVersion;
40
+ return {
41
+ version: "v20.0.0",
42
+ // Compatibility version for Node.js API level checks
43
+ versions: versions2,
44
+ title: "gjs"
45
+ };
46
+ }
47
+ function detectPpid() {
48
+ if (typeof globalThis.process?.ppid === "number") {
49
+ return globalThis.process.ppid;
50
+ }
51
+ try {
52
+ const GLib = getGjsGlobal().imports?.gi?.GLib;
53
+ if (GLib) {
54
+ const [, contents] = GLib.file_get_contents("/proc/self/status");
55
+ if (contents) {
56
+ const str = new TextDecoder().decode(contents);
57
+ const match = str.match(/PPid:\s+(\d+)/);
58
+ if (match) return parseInt(match[1], 10);
59
+ }
60
+ }
61
+ } catch {
62
+ }
63
+ return 0;
64
+ }
65
+ function detectPlatform() {
66
+ try {
67
+ const GLib = getGjsGlobal().imports?.gi?.GLib;
68
+ if (GLib) {
69
+ const osInfo = GLib.get_os_info("ID");
70
+ if (osInfo) return "linux";
71
+ }
72
+ } catch {
73
+ }
74
+ if (typeof getGjsGlobal().imports?.system !== "undefined") {
75
+ return "linux";
76
+ }
77
+ if (typeof globalThis.process?.platform === "string") {
78
+ return globalThis.process.platform;
79
+ }
80
+ return "linux";
81
+ }
82
+ function detectArch() {
83
+ if (typeof globalThis.process?.arch === "string") {
84
+ return globalThis.process.arch;
85
+ }
86
+ try {
87
+ const system = getGjsGlobal().imports?.system;
88
+ if (system?.programInvocationName) {
89
+ }
90
+ } catch {
91
+ }
92
+ return "x64";
93
+ }
94
+ function getCwd() {
95
+ try {
96
+ const GLib = getGjsGlobal().imports?.gi?.GLib;
97
+ if (GLib?.get_current_dir) return GLib.get_current_dir();
98
+ } catch {
99
+ }
100
+ return "/";
101
+ }
102
+ function getEnvProxy() {
103
+ if (typeof globalThis.process?.env === "object") {
104
+ return globalThis.process.env;
105
+ }
106
+ try {
107
+ const GLib = getGjsGlobal().imports?.gi?.GLib;
108
+ if (GLib) {
109
+ return new Proxy({}, {
110
+ get(_target, prop) {
111
+ if (typeof prop !== "string") return void 0;
112
+ return GLib.getenv(prop) ?? void 0;
113
+ },
114
+ set(_target, prop, value) {
115
+ if (typeof prop !== "string") return false;
116
+ GLib.setenv(prop, String(value), true);
117
+ return true;
118
+ },
119
+ deleteProperty(_target, prop) {
120
+ if (typeof prop !== "string") return false;
121
+ GLib.unsetenv(prop);
122
+ return true;
123
+ },
124
+ has(_target, prop) {
125
+ if (typeof prop !== "string") return false;
126
+ return GLib.getenv(prop) !== null;
127
+ },
128
+ ownKeys(_target) {
129
+ const envp = GLib.listenv();
130
+ return envp;
131
+ },
132
+ getOwnPropertyDescriptor(_target, prop) {
133
+ if (typeof prop !== "string") return void 0;
134
+ const val = GLib.getenv(prop);
135
+ if (val === null) return void 0;
136
+ return { configurable: true, enumerable: true, writable: true, value: val };
137
+ }
138
+ });
139
+ }
140
+ } catch {
141
+ }
142
+ return {};
143
+ }
144
+ function getArgv() {
145
+ if (typeof globalThis.process?.argv !== "undefined") {
146
+ return globalThis.process.argv;
147
+ }
148
+ try {
149
+ const system = getGjsGlobal().imports?.system;
150
+ if (system?.programArgs) {
151
+ return [system.programInvocationName || "gjs", ...system.programArgs];
152
+ }
153
+ } catch {
154
+ }
155
+ return ["gjs"];
156
+ }
157
+ function getExecPath() {
158
+ if (typeof globalThis.process?.execPath === "string") {
159
+ return globalThis.process.execPath;
160
+ }
161
+ try {
162
+ const system = getGjsGlobal().imports?.system;
163
+ if (system?.programInvocationName) return system.programInvocationName;
164
+ } catch {
165
+ }
166
+ return "/usr/bin/gjs";
167
+ }
168
+ function getPid() {
169
+ if (typeof globalThis.process?.pid === "number") {
170
+ return globalThis.process.pid;
171
+ }
172
+ try {
173
+ const GLib = getGjsGlobal().imports?.gi?.GLib;
174
+ if (GLib) {
175
+ const [, contents] = GLib.file_get_contents("/proc/self/stat");
176
+ if (contents) {
177
+ const str = new TextDecoder().decode(contents);
178
+ const pid2 = parseInt(str, 10);
179
+ if (!isNaN(pid2)) return pid2;
180
+ }
181
+ }
182
+ } catch {
183
+ }
184
+ return 0;
185
+ }
186
+ const startTime = Date.now();
187
+ function getMonotonicTime() {
188
+ try {
189
+ const GLib = getGjsGlobal().imports?.gi?.GLib;
190
+ if (GLib?.get_monotonic_time) {
191
+ return BigInt(GLib.get_monotonic_time()) * 1000n;
192
+ }
193
+ } catch {
194
+ }
195
+ if (typeof performance?.now === "function") {
196
+ return BigInt(Math.round(performance.now() * 1e6));
197
+ }
198
+ return BigInt(Date.now()) * 1000000n;
199
+ }
200
+ const hrtimeBase = getMonotonicTime();
201
+ class Process extends EventEmitter {
202
+ platform;
203
+ arch;
204
+ env;
205
+ argv;
206
+ argv0;
207
+ execPath;
208
+ pid;
209
+ ppid;
210
+ version;
211
+ versions;
212
+ title;
213
+ execArgv;
214
+ config;
215
+ exitCode;
216
+ constructor() {
217
+ super();
218
+ this.platform = detectPlatform();
219
+ this.arch = detectArch();
220
+ this.env = getEnvProxy();
221
+ this.argv = getArgv();
222
+ this.argv0 = this.argv[0] || "gjs";
223
+ this.execPath = getExecPath();
224
+ this.execArgv = globalThis.process?.execArgv ?? [];
225
+ this.config = globalThis.process?.config ?? { target_defaults: {}, variables: {} };
226
+ this.pid = getPid();
227
+ this.ppid = detectPpid();
228
+ const versionInfo = detectVersionInfo();
229
+ this.version = versionInfo.version;
230
+ this.versions = versionInfo.versions;
231
+ this.title = versionInfo.title;
232
+ }
233
+ cwd() {
234
+ return getCwd();
235
+ }
236
+ chdir(directory) {
237
+ try {
238
+ const GLib = getGjsGlobal().imports?.gi?.GLib;
239
+ if (GLib?.chdir) {
240
+ if (!GLib.file_test(
241
+ directory,
242
+ 16
243
+ /* G_FILE_TEST_EXISTS */
244
+ )) {
245
+ const err = new Error(`ENOENT: no such file or directory, chdir '${directory}'`);
246
+ err.code = "ENOENT";
247
+ err.syscall = "chdir";
248
+ err.path = directory;
249
+ throw err;
250
+ }
251
+ GLib.chdir(directory);
252
+ return;
253
+ }
254
+ } catch (e) {
255
+ if (e && typeof e === "object" && e.code === "ENOENT") throw e;
256
+ }
257
+ if (typeof globalThis.process?.chdir === "function") {
258
+ globalThis.process.chdir(directory);
259
+ return;
260
+ }
261
+ throw new Error("process.chdir() is not supported in this environment");
262
+ }
263
+ kill(pid2, signal) {
264
+ if (typeof globalThis.process?.kill === "function") {
265
+ return globalThis.process.kill(pid2, signal);
266
+ }
267
+ try {
268
+ const GLib = getGjsGlobal().imports?.gi?.GLib;
269
+ if (GLib) {
270
+ const sig = typeof signal === "number" ? String(signal) : signal || "SIGTERM";
271
+ const sigArg = sig.startsWith("SIG") ? `-${sig.slice(3)}` : `-${sig}`;
272
+ GLib.spawn_command_line_sync(`kill ${sigArg} ${pid2}`);
273
+ return true;
274
+ }
275
+ } catch {
276
+ }
277
+ throw new Error("process.kill() is not supported in this environment");
278
+ }
279
+ exit(code) {
280
+ this.exitCode = code ?? this.exitCode ?? 0;
281
+ this.emit("exit", this.exitCode);
282
+ try {
283
+ const system = getGjsGlobal().imports?.system;
284
+ if (system?.exit) {
285
+ system.exit(this.exitCode);
286
+ }
287
+ } catch {
288
+ }
289
+ if (typeof globalThis.process?.exit === "function") {
290
+ globalThis.process.exit(this.exitCode);
291
+ }
292
+ throw new Error(`process.exit(${this.exitCode})`);
293
+ }
294
+ nextTick(callback, ...args) {
295
+ if (typeof queueMicrotask === "function") {
296
+ queueMicrotask(() => callback(...args));
297
+ } else {
298
+ Promise.resolve().then(() => callback(...args));
299
+ }
300
+ }
301
+ hrtime(time) {
302
+ const now = getMonotonicTime() - hrtimeBase;
303
+ const seconds = Number(now / 1000000000n);
304
+ const nanoseconds = Number(now % 1000000000n);
305
+ if (time) {
306
+ let diffSec = seconds - time[0];
307
+ let diffNano = nanoseconds - time[1];
308
+ if (diffNano < 0) {
309
+ diffSec--;
310
+ diffNano += 1e9;
311
+ }
312
+ return [diffSec, diffNano];
313
+ }
314
+ return [seconds, nanoseconds];
315
+ }
316
+ uptime() {
317
+ return (Date.now() - startTime) / 1e3;
318
+ }
319
+ memoryUsage() {
320
+ try {
321
+ const GLib = getGjsGlobal().imports?.gi?.GLib;
322
+ if (GLib) {
323
+ const [, contents] = GLib.file_get_contents("/proc/self/status");
324
+ if (contents) {
325
+ const str = new TextDecoder().decode(contents);
326
+ const vmRSS = str.match(/VmRSS:\s+(\d+)/);
327
+ const rss = vmRSS ? parseInt(vmRSS[1], 10) * 1024 : 0;
328
+ return { rss, heapTotal: rss, heapUsed: rss, external: 0, arrayBuffers: 0 };
329
+ }
330
+ }
331
+ } catch {
332
+ }
333
+ if (typeof globalThis.process?.memoryUsage === "function") {
334
+ return globalThis.process.memoryUsage();
335
+ }
336
+ return { rss: 0, heapTotal: 0, heapUsed: 0, external: 0, arrayBuffers: 0 };
337
+ }
338
+ cpuUsage(previousValue) {
339
+ if (typeof globalThis.process?.cpuUsage === "function") {
340
+ return globalThis.process.cpuUsage(previousValue);
341
+ }
342
+ return { user: 0, system: 0 };
343
+ }
344
+ // Stub: stdout/stderr/stdin — these need stream to be implemented fully
345
+ // Note: Cannot check globalThis.process.stdout here — on GJS globalThis.process
346
+ // IS this instance, so that would cause infinite recursion.
347
+ stdout = { write: (data) => {
348
+ console.log(data);
349
+ return true;
350
+ }, fd: 1 };
351
+ stderr = { write: (data) => {
352
+ console.error(data);
353
+ return true;
354
+ }, fd: 2 };
355
+ stdin = { fd: 0 };
356
+ abort() {
357
+ this.exit(1);
358
+ }
359
+ // no-op stubs for compatibility
360
+ umask(mask) {
361
+ return 18;
362
+ }
363
+ emitWarning(warning, name) {
364
+ if (typeof warning === "string") {
365
+ console.warn(`(${name || "Warning"}): ${warning}`);
366
+ } else {
367
+ console.warn(warning.message);
368
+ }
369
+ }
370
+ }
371
+ Process.prototype.hrtime.bigint = function() {
372
+ return getMonotonicTime() - hrtimeBase;
373
+ };
374
+ const process = new Process();
375
+ const platform = process.platform;
376
+ const arch = process.arch;
377
+ const env = process.env;
378
+ const argv = process.argv;
379
+ const argv0 = process.argv0;
380
+ const execPath = process.execPath;
381
+ const pid = process.pid;
382
+ const ppid = process.ppid;
383
+ const version = process.version;
384
+ const versions = process.versions;
385
+ const cwd = process.cwd.bind(process);
386
+ const chdir = process.chdir.bind(process);
387
+ const exit = process.exit.bind(process);
388
+ const nextTick = process.nextTick.bind(process);
389
+ const hrtime = process.hrtime.bind(process);
390
+ const uptime = process.uptime.bind(process);
391
+ const memoryUsage = process.memoryUsage.bind(process);
392
+ const cpuUsage = process.cpuUsage.bind(process);
393
+ const kill = process.kill.bind(process);
394
+ const abort = process.abort.bind(process);
395
+ const umask = process.umask.bind(process);
396
+ const emitWarning = process.emitWarning.bind(process);
397
+ const execArgv = process.execArgv;
398
+ const config = process.config;
399
+ const stdout = process.stdout;
400
+ const stderr = process.stderr;
401
+ const stdin = process.stdin;
402
+ var index_default = process;
4
403
  export {
5
- src_default as default
404
+ abort,
405
+ arch,
406
+ argv,
407
+ argv0,
408
+ chdir,
409
+ config,
410
+ cpuUsage,
411
+ cwd,
412
+ index_default as default,
413
+ emitWarning,
414
+ env,
415
+ execArgv,
416
+ execPath,
417
+ exit,
418
+ hrtime,
419
+ kill,
420
+ memoryUsage,
421
+ nextTick,
422
+ pid,
423
+ platform,
424
+ ppid,
425
+ stderr,
426
+ stdin,
427
+ stdout,
428
+ umask,
429
+ uptime,
430
+ version,
431
+ versions
6
432
  };
@@ -1,3 +1,92 @@
1
- export * from '@gjsify/deno_std/node/process';
2
- import process from '@gjsify/deno_std/node/process';
1
+ import { EventEmitter } from '@gjsify/events';
2
+ type ProcessPlatform = NodeJS.Platform;
3
+ type ProcessArch = NodeJS.Architecture;
4
+ declare class Process extends EventEmitter {
5
+ readonly platform: ProcessPlatform;
6
+ readonly arch: ProcessArch;
7
+ readonly env: Record<string, string | undefined>;
8
+ readonly argv: string[];
9
+ readonly argv0: string;
10
+ readonly execPath: string;
11
+ readonly pid: number;
12
+ readonly ppid: number;
13
+ readonly version: string;
14
+ readonly versions: Record<string, string>;
15
+ title: string;
16
+ readonly execArgv: string[];
17
+ readonly config: Record<string, unknown>;
18
+ exitCode: number | undefined;
19
+ constructor();
20
+ cwd(): string;
21
+ chdir(directory: string): void;
22
+ kill(pid: number, signal?: string | number): boolean;
23
+ exit(code?: number): never;
24
+ nextTick(callback: Function, ...args: unknown[]): void;
25
+ hrtime(time?: [number, number]): [number, number];
26
+ uptime(): number;
27
+ memoryUsage(): {
28
+ rss: number;
29
+ heapTotal: number;
30
+ heapUsed: number;
31
+ external: number;
32
+ arrayBuffers: number;
33
+ };
34
+ cpuUsage(previousValue?: {
35
+ user: number;
36
+ system: number;
37
+ }): {
38
+ user: number;
39
+ system: number;
40
+ };
41
+ readonly stdout: {
42
+ write: (data: string) => boolean;
43
+ fd: number;
44
+ };
45
+ readonly stderr: {
46
+ write: (data: string) => boolean;
47
+ fd: number;
48
+ };
49
+ readonly stdin: {
50
+ fd: number;
51
+ };
52
+ abort(): void;
53
+ umask(mask?: number): number;
54
+ emitWarning(warning: string | Error, name?: string): void;
55
+ }
56
+ declare const process: Process;
57
+ export declare const platform: NodeJS.Platform;
58
+ export declare const arch: NodeJS.Architecture;
59
+ export declare const env: Record<string, string>;
60
+ export declare const argv: string[];
61
+ export declare const argv0: string;
62
+ export declare const execPath: string;
63
+ export declare const pid: number;
64
+ export declare const ppid: number;
65
+ export declare const version: string;
66
+ export declare const versions: Record<string, string>;
67
+ export declare const cwd: any;
68
+ export declare const chdir: any;
69
+ export declare const exit: any;
70
+ export declare const nextTick: any;
71
+ export declare const hrtime: any;
72
+ export declare const uptime: any;
73
+ export declare const memoryUsage: any;
74
+ export declare const cpuUsage: any;
75
+ export declare const kill: any;
76
+ export declare const abort: any;
77
+ export declare const umask: any;
78
+ export declare const emitWarning: any;
79
+ export declare const execArgv: string[];
80
+ export declare const config: Record<string, unknown>;
81
+ export declare const stdout: {
82
+ write: (data: string) => boolean;
83
+ fd: number;
84
+ };
85
+ export declare const stderr: {
86
+ write: (data: string) => boolean;
87
+ fd: number;
88
+ };
89
+ export declare const stdin: {
90
+ fd: number;
91
+ };
3
92
  export default process;
package/package.json CHANGED
@@ -1,33 +1,26 @@
1
1
  {
2
2
  "name": "@gjsify/process",
3
- "version": "0.0.4",
3
+ "version": "0.1.0",
4
4
  "description": "Node.js process module for Gjs",
5
- "main": "lib/cjs/index.js",
6
5
  "module": "lib/esm/index.js",
7
6
  "types": "lib/types/index.d.ts",
8
7
  "type": "module",
9
8
  "exports": {
10
9
  ".": {
11
- "import": {
12
- "types": "./lib/types/index.d.ts",
13
- "default": "./lib/esm/index.js"
14
- },
15
- "require": {
16
- "types": "./lib/types/index.d.ts",
17
- "default": "./lib/cjs/index.js"
18
- }
10
+ "types": "./lib/types/index.d.ts",
11
+ "default": "./lib/esm/index.js"
19
12
  }
20
13
  },
21
14
  "scripts": {
22
- "clear": "rm -rf lib tsconfig.types.tsbuildinfo test.gjs.mjs test.node.mjs",
23
- "print:name": "echo '@gjsify/process'",
24
- "build": "yarn print:name && yarn build:gjsify && yarn build:types",
15
+ "clear": "rm -rf lib tsconfig.tsbuildinfo tsconfig.types.tsbuildinfo test.gjs.mjs test.node.mjs || exit 0",
16
+ "check": "tsc --noEmit",
17
+ "build": "yarn build:gjsify && yarn build:types",
25
18
  "build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
26
- "build:types": "tsc --project tsconfig.types.json || exit 0",
19
+ "build:types": "tsc",
27
20
  "build:test": "yarn build:test:gjs && yarn build:test:node",
28
21
  "build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs",
29
22
  "build:test:node": "gjsify build src/test.mts --app node --outfile test.node.mjs",
30
- "test": "yarn print:name && yarn build:gjsify && yarn build:test && yarn test:node && yarn test:gjs",
23
+ "test": "yarn build:gjsify && yarn build:test && yarn test:node && yarn test:gjs",
31
24
  "test:gjs": "gjs -m test.gjs.mjs",
32
25
  "test:node": "node test.node.mjs"
33
26
  },
@@ -37,12 +30,12 @@
37
30
  "process"
38
31
  ],
39
32
  "dependencies": {
40
- "@girs/gjs": "^3.2.6",
41
- "@gjsify/utils": "^0.0.4"
33
+ "@gjsify/events": "^0.1.0"
42
34
  },
43
35
  "devDependencies": {
44
- "@gjsify/cli": "^0.0.4",
45
- "@types/node": "^20.10.5",
46
- "typescript": "^5.3.3"
36
+ "@gjsify/cli": "^0.1.0",
37
+ "@gjsify/unit": "^0.1.0",
38
+ "@types/node": "^25.5.0",
39
+ "typescript": "^6.0.2"
47
40
  }
48
41
  }