@gjsify/utils 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 +26 -0
- package/lib/esm/base64.js +72 -0
- package/lib/esm/byte-array.js +6 -0
- package/lib/esm/cli.js +1 -2
- package/lib/esm/defer.js +6 -0
- package/lib/esm/encoding.js +35 -0
- package/lib/esm/fs.js +2 -1
- package/lib/esm/gio-errors.js +98 -0
- package/lib/esm/gio.js +39 -0
- package/lib/esm/globals.js +8 -0
- package/lib/esm/index.js +10 -8
- package/lib/esm/main-loop.js +28 -0
- package/lib/esm/next-tick.js +6 -0
- package/lib/esm/structured-clone.js +169 -0
- package/lib/types/base64.d.ts +8 -0
- package/lib/types/byte-array.d.ts +7 -0
- package/lib/types/defer.d.ts +7 -0
- package/lib/types/encoding.d.ts +11 -0
- package/lib/types/gio-errors.d.ts +28 -0
- package/lib/types/gio.d.ts +17 -0
- package/lib/types/globals.d.ts +5 -0
- package/lib/types/index.d.ts +10 -8
- package/lib/types/main-loop.d.ts +20 -0
- package/lib/types/next-tick.d.ts +5 -0
- package/lib/types/structured-clone.d.ts +15 -0
- package/package.json +18 -20
- package/src/base64.ts +78 -0
- package/src/byte-array.ts +12 -0
- package/src/defer.ts +11 -0
- package/src/encoding.ts +36 -0
- package/src/fs.ts +2 -2
- package/src/gio-errors.ts +101 -0
- package/src/gio.ts +67 -0
- package/src/globals.ts +13 -0
- package/src/index.ts +10 -9
- package/src/main-loop.ts +62 -0
- package/src/next-tick.ts +16 -0
- package/src/structured-clone.ts +242 -0
- package/src/test.ts +1 -3
- package/tsconfig.json +27 -10
- package/tsconfig.tsbuildinfo +1 -0
- package/lib/cjs/cancel-handler.js +0 -22
- package/lib/cjs/cli.js +0 -11
- package/lib/cjs/error.js +0 -21
- package/lib/cjs/file.js +0 -13
- package/lib/cjs/fs.js +0 -21
- package/lib/cjs/index.js +0 -14
- package/lib/cjs/log.js +0 -159
- package/lib/cjs/message.js +0 -13
- package/lib/cjs/os.js +0 -81
- package/lib/cjs/path.js +0 -50
- package/lib/cjs/process.js +0 -41
- package/lib/cjs/system.js +0 -47
- package/lib/cjs/tty.js +0 -13
- package/lib/cjs/types/cancel-signals.js +0 -0
- package/lib/cjs/types/error-data.js +0 -0
- package/lib/cjs/types/index.js +0 -8
- package/lib/cjs/types/signal-methods.js +0 -0
- package/lib/cjs/types/stack-trace-frame.js +0 -0
- package/lib/cjs/types/structured-log-data.js +0 -0
- package/lib/cjs/types/uncaught-exception-data.js +0 -0
- package/lib/cjs/types/unhandled-rejection-data.js +0 -0
- package/lib/cjs/types/user-info.js +0 -0
- package/lib/cjs/version.js +0 -7
- package/lib/esm/cancel-handler.js +0 -22
- package/lib/esm/log.js +0 -159
- package/lib/esm/os.js +0 -81
- package/lib/esm/process.js +0 -41
- package/lib/esm/system.js +0 -47
- package/lib/esm/tty.js +0 -13
- package/lib/esm/types/cancel-signals.js +0 -0
- package/lib/esm/types/error-data.js +0 -0
- package/lib/esm/types/index.js +0 -8
- package/lib/esm/types/signal-methods.js +0 -0
- package/lib/esm/types/stack-trace-frame.js +0 -0
- package/lib/esm/types/structured-log-data.js +0 -0
- package/lib/esm/types/uncaught-exception-data.js +0 -0
- package/lib/esm/types/unhandled-rejection-data.js +0 -0
- package/lib/esm/types/user-info.js +0 -0
- package/lib/esm/version.js +0 -7
- package/lib/types/cancel-handler.d.ts +0 -4
- package/lib/types/log.d.ts +0 -29
- package/lib/types/os.d.ts +0 -7
- package/lib/types/process.d.ts +0 -6
- package/lib/types/system.d.ts +0 -5
- package/lib/types/tty.d.ts +0 -5
- package/lib/types/types/cancel-signals.d.ts +0 -5
- package/lib/types/types/error-data.d.ts +0 -7
- package/lib/types/types/index.d.ts +0 -8
- package/lib/types/types/signal-methods.d.ts +0 -62
- package/lib/types/types/stack-trace-frame.d.ts +0 -6
- package/lib/types/types/structured-log-data.d.ts +0 -5
- package/lib/types/types/uncaught-exception-data.d.ts +0 -4
- package/lib/types/types/unhandled-rejection-data.d.ts +0 -5
- package/lib/types/types/user-info.d.ts +0 -8
- package/lib/types/version.d.ts +0 -1
- package/src/cancel-handler.ts +0 -24
- package/src/log.ts +0 -218
- package/src/os.ts +0 -94
- package/src/process.spec.ts +0 -24
- package/src/process.ts +0 -46
- package/src/system.ts +0 -56
- package/src/tty.spec.ts +0 -10
- package/src/tty.ts +0 -10
- package/src/types/cancel-signals.ts +0 -6
- package/src/types/error-data.ts +0 -8
- package/src/types/index.ts +0 -8
- package/src/types/signal-methods.ts +0 -63
- package/src/types/stack-trace-frame.ts +0 -7
- package/src/types/structured-log-data.ts +0 -5
- package/src/types/uncaught-exception-data.ts +0 -5
- package/src/types/unhandled-rejection-data.ts +0 -6
- package/src/types/user-info.ts +0 -9
- package/src/version.ts +0 -4
- package/test.gjs.js +0 -34758
- package/test.gjs.js.map +0 -7
- package/test.gjs.js.meta.json +0 -1
- package/tsconfig.types.json +0 -7
- package/tsconfig.types.tsbuildinfo +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# @gjsify/utils
|
|
2
|
+
|
|
3
|
+
Shared utility functions for gjsify packages including error polyfills, structured clone, and GNOME library helpers.
|
|
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/utils
|
|
11
|
+
# or
|
|
12
|
+
yarn add @gjsify/utils
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { ensureMainLoop } from '@gjsify/utils';
|
|
19
|
+
|
|
20
|
+
// Start GLib MainLoop if not already running (no-op on Node.js)
|
|
21
|
+
ensureMainLoop();
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## License
|
|
25
|
+
|
|
26
|
+
MIT
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const B64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
2
|
+
const B64_LOOKUP = new Uint8Array(256);
|
|
3
|
+
for (let i = 0; i < B64_CHARS.length; i++) B64_LOOKUP[B64_CHARS.charCodeAt(i)] = i;
|
|
4
|
+
function atobPolyfill(str) {
|
|
5
|
+
if (typeof globalThis.atob === "function") return globalThis.atob(str);
|
|
6
|
+
const cleaned = str.replace(/[=\s]/g, "");
|
|
7
|
+
let result = "";
|
|
8
|
+
let bits = 0;
|
|
9
|
+
let collected = 0;
|
|
10
|
+
for (let i = 0; i < cleaned.length; i++) {
|
|
11
|
+
bits = bits << 6 | B64_LOOKUP[cleaned.charCodeAt(i)];
|
|
12
|
+
collected += 6;
|
|
13
|
+
if (collected >= 8) {
|
|
14
|
+
collected -= 8;
|
|
15
|
+
result += String.fromCharCode(bits >> collected & 255);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
function btoaPolyfill(str) {
|
|
21
|
+
if (typeof globalThis.btoa === "function") return globalThis.btoa(str);
|
|
22
|
+
let result = "";
|
|
23
|
+
let i = 0;
|
|
24
|
+
for (; i + 2 < str.length; i += 3) {
|
|
25
|
+
const n = str.charCodeAt(i) << 16 | str.charCodeAt(i + 1) << 8 | str.charCodeAt(i + 2);
|
|
26
|
+
result += B64_CHARS[n >> 18 & 63] + B64_CHARS[n >> 12 & 63] + B64_CHARS[n >> 6 & 63] + B64_CHARS[n & 63];
|
|
27
|
+
}
|
|
28
|
+
if (i + 1 === str.length) {
|
|
29
|
+
const n = str.charCodeAt(i) << 16;
|
|
30
|
+
result += B64_CHARS[n >> 18 & 63] + B64_CHARS[n >> 12 & 63] + "==";
|
|
31
|
+
} else if (i + 2 === str.length) {
|
|
32
|
+
const n = str.charCodeAt(i) << 16 | str.charCodeAt(i + 1) << 8;
|
|
33
|
+
result += B64_CHARS[n >> 18 & 63] + B64_CHARS[n >> 12 & 63] + B64_CHARS[n >> 6 & 63] + "=";
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
function base64Decode(str) {
|
|
38
|
+
const cleaned = str.replace(/[=\s]/g, "");
|
|
39
|
+
const bytes = new Uint8Array(cleaned.length * 3 >> 2);
|
|
40
|
+
let bits = 0;
|
|
41
|
+
let collected = 0;
|
|
42
|
+
let pos = 0;
|
|
43
|
+
for (let i = 0; i < cleaned.length; i++) {
|
|
44
|
+
bits = bits << 6 | B64_LOOKUP[cleaned.charCodeAt(i)];
|
|
45
|
+
collected += 6;
|
|
46
|
+
if (collected >= 8) {
|
|
47
|
+
collected -= 8;
|
|
48
|
+
bytes[pos++] = bits >> collected & 255;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return bytes.subarray(0, pos);
|
|
52
|
+
}
|
|
53
|
+
function base64Encode(bytes) {
|
|
54
|
+
let result = "";
|
|
55
|
+
const len = bytes.length;
|
|
56
|
+
for (let i = 0; i < len; i += 3) {
|
|
57
|
+
const b0 = bytes[i];
|
|
58
|
+
const b1 = i + 1 < len ? bytes[i + 1] : 0;
|
|
59
|
+
const b2 = i + 2 < len ? bytes[i + 2] : 0;
|
|
60
|
+
result += B64_CHARS[b0 >> 2];
|
|
61
|
+
result += B64_CHARS[(b0 & 3) << 4 | b1 >> 4];
|
|
62
|
+
result += i + 1 < len ? B64_CHARS[(b1 & 15) << 2 | b2 >> 6] : "=";
|
|
63
|
+
result += i + 2 < len ? B64_CHARS[b2 & 63] : "=";
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
atobPolyfill,
|
|
69
|
+
base64Decode,
|
|
70
|
+
base64Encode,
|
|
71
|
+
btoaPolyfill
|
|
72
|
+
};
|
package/lib/esm/cli.js
CHANGED
|
@@ -2,8 +2,7 @@ import GLib from "@girs/glib-2.0";
|
|
|
2
2
|
const byteArray = imports.byteArray;
|
|
3
3
|
const cli = (commandLine) => {
|
|
4
4
|
const [res, out, err, status] = GLib.spawn_command_line_sync(commandLine);
|
|
5
|
-
if (err.byteLength)
|
|
6
|
-
throw new Error(byteArray.toString(err));
|
|
5
|
+
if (err.byteLength) throw new Error(byteArray.toString(err));
|
|
7
6
|
return byteArray.toString(out);
|
|
8
7
|
};
|
|
9
8
|
export {
|
package/lib/esm/defer.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const VALID_ENCODINGS = ["utf8", "ascii", "latin1", "binary", "base64", "base64url", "hex", "ucs2", "utf16le"];
|
|
2
|
+
function normalizeEncoding(enc) {
|
|
3
|
+
if (!enc || enc === "utf8" || enc === "utf-8") return "utf8";
|
|
4
|
+
const lower = ("" + enc).toLowerCase().replace(/-/g, "");
|
|
5
|
+
switch (lower) {
|
|
6
|
+
case "utf8":
|
|
7
|
+
return "utf8";
|
|
8
|
+
case "ascii":
|
|
9
|
+
return "ascii";
|
|
10
|
+
case "latin1":
|
|
11
|
+
case "binary":
|
|
12
|
+
return "latin1";
|
|
13
|
+
case "base64":
|
|
14
|
+
return "base64";
|
|
15
|
+
case "base64url":
|
|
16
|
+
return "base64url";
|
|
17
|
+
case "hex":
|
|
18
|
+
return "hex";
|
|
19
|
+
case "ucs2":
|
|
20
|
+
case "utf16le":
|
|
21
|
+
return "utf16le";
|
|
22
|
+
default:
|
|
23
|
+
return "utf8";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function checkEncoding(encoding) {
|
|
27
|
+
const lower = ("" + encoding).toLowerCase().replace(/-/g, "");
|
|
28
|
+
if (!VALID_ENCODINGS.includes(lower)) {
|
|
29
|
+
throw new TypeError(`Unknown encoding: ${encoding}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
checkEncoding,
|
|
34
|
+
normalizeEncoding
|
|
35
|
+
};
|
package/lib/esm/fs.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import Gio from "@girs/gio-2.0";
|
|
2
|
+
import GioUnix from "@girs/giounix-2.0";
|
|
2
3
|
const existsFD = (fd) => {
|
|
3
4
|
try {
|
|
4
|
-
let stream =
|
|
5
|
+
let stream = GioUnix.InputStream.new(fd, false);
|
|
5
6
|
stream.close(null);
|
|
6
7
|
return true;
|
|
7
8
|
} catch (error) {
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
const GIO_ERROR_TO_NODE = {
|
|
2
|
+
0: "EIO",
|
|
3
|
+
// FAILED
|
|
4
|
+
1: "ENOENT",
|
|
5
|
+
// NOT_FOUND
|
|
6
|
+
2: "EEXIST",
|
|
7
|
+
// EXISTS
|
|
8
|
+
3: "EISDIR",
|
|
9
|
+
// IS_DIRECTORY
|
|
10
|
+
4: "ENOTDIR",
|
|
11
|
+
// NOT_DIRECTORY
|
|
12
|
+
5: "ENOTEMPTY",
|
|
13
|
+
// NOT_EMPTY
|
|
14
|
+
6: "ENOENT",
|
|
15
|
+
// NOT_REGULAR_FILE
|
|
16
|
+
7: "ENFILE",
|
|
17
|
+
// TOO_MANY_OPEN_FILES
|
|
18
|
+
9: "EACCES",
|
|
19
|
+
// NOT_MOUNTABLE_FILE
|
|
20
|
+
10: "ENFILE",
|
|
21
|
+
// FILENAME_TOO_LONG
|
|
22
|
+
11: "EINVAL",
|
|
23
|
+
// INVALID_FILENAME
|
|
24
|
+
12: "ELOOP",
|
|
25
|
+
// TOO_MANY_LINKS
|
|
26
|
+
13: "ENOSPC",
|
|
27
|
+
// NO_SPACE
|
|
28
|
+
14: "EACCES",
|
|
29
|
+
// PERMISSION_DENIED
|
|
30
|
+
17: "ELOOP",
|
|
31
|
+
// TOO_MANY_LINKS (duplicate guard)
|
|
32
|
+
19: "ENOSPC",
|
|
33
|
+
// NO_SPACE (duplicate guard)
|
|
34
|
+
20: "ENOTSUP",
|
|
35
|
+
// NOT_SUPPORTED
|
|
36
|
+
22: "EMFILE",
|
|
37
|
+
// TOO_MANY_OPEN_FILES
|
|
38
|
+
24: "EROFS",
|
|
39
|
+
// READ_ONLY
|
|
40
|
+
25: "ECANCELED",
|
|
41
|
+
// CANCELLED
|
|
42
|
+
26: "EBUSY",
|
|
43
|
+
// BUSY
|
|
44
|
+
27: "ETIMEDOUT",
|
|
45
|
+
// TIMED_OUT
|
|
46
|
+
28: "EHOSTUNREACH",
|
|
47
|
+
// HOST_NOT_FOUND (was WOULD_BLOCK)
|
|
48
|
+
30: "EHOSTUNREACH",
|
|
49
|
+
// HOST_NOT_FOUND
|
|
50
|
+
31: "ENETUNREACH",
|
|
51
|
+
// NETWORK_UNREACHABLE
|
|
52
|
+
32: "ECONNREFUSED",
|
|
53
|
+
// CONNECTION_REFUSED (legacy value)
|
|
54
|
+
33: "EADDRINUSE",
|
|
55
|
+
// ADDRESS_IN_USE
|
|
56
|
+
34: "ECONNRESET",
|
|
57
|
+
// CONNECTION_CLOSED (mapped to reset)
|
|
58
|
+
36: "EPIPE",
|
|
59
|
+
// BROKEN_PIPE
|
|
60
|
+
38: "ENETUNREACH",
|
|
61
|
+
// NETWORK_UNREACHABLE (actual GJS value)
|
|
62
|
+
39: "ECONNREFUSED",
|
|
63
|
+
// CONNECTION_REFUSED (actual GJS value)
|
|
64
|
+
40: "ECONNREFUSED",
|
|
65
|
+
// PROXY_FAILED
|
|
66
|
+
41: "EACCES",
|
|
67
|
+
// PROXY_AUTH_FAILED
|
|
68
|
+
44: "ECONNRESET",
|
|
69
|
+
// CONNECTION_CLOSED (actual GJS value)
|
|
70
|
+
46: "EMSGSIZE"
|
|
71
|
+
// MESSAGE_TOO_LARGE
|
|
72
|
+
};
|
|
73
|
+
function createNodeError(err, syscall, details) {
|
|
74
|
+
const errObj = err;
|
|
75
|
+
const code = GIO_ERROR_TO_NODE[errObj?.code ?? -1] || "EIO";
|
|
76
|
+
let msg = `${code}: ${errObj?.message || "unknown error"}, ${syscall}`;
|
|
77
|
+
if (details?.path) msg += ` '${details.path}'`;
|
|
78
|
+
if (details?.dest) msg += ` -> '${details.dest}'`;
|
|
79
|
+
if (details?.address) msg += ` ${details.address}`;
|
|
80
|
+
if (details?.port != null) msg += `:${details.port}`;
|
|
81
|
+
const error = new Error(msg);
|
|
82
|
+
error.code = code;
|
|
83
|
+
error.syscall = syscall;
|
|
84
|
+
error.errno = -(errObj?.code || 0);
|
|
85
|
+
if (details?.path) error.path = details.path;
|
|
86
|
+
if (details?.address) error.address = details.address;
|
|
87
|
+
if (details?.port != null) error.port = details.port;
|
|
88
|
+
return error;
|
|
89
|
+
}
|
|
90
|
+
function isNotFoundError(err) {
|
|
91
|
+
const errObj = err;
|
|
92
|
+
return errObj?.code === 1 || errObj?.code === "ENOENT";
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
GIO_ERROR_TO_NODE,
|
|
96
|
+
createNodeError,
|
|
97
|
+
isNotFoundError
|
|
98
|
+
};
|
package/lib/esm/gio.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import GLib from "@girs/glib-2.0";
|
|
2
|
+
const byteArray = imports.byteArray;
|
|
3
|
+
function gioAsync(obj, asyncMethod, finishMethod, ...args) {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
obj[asyncMethod](...args, (_self, asyncRes) => {
|
|
6
|
+
try {
|
|
7
|
+
resolve(obj[finishMethod](asyncRes));
|
|
8
|
+
} catch (error) {
|
|
9
|
+
reject(error);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
async function readBytesAsync(inputStream, count = 4096, ioPriority = GLib.PRIORITY_DEFAULT, cancellable = null) {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
inputStream.read_bytes_async(count, ioPriority, cancellable, (_self, asyncRes) => {
|
|
17
|
+
try {
|
|
18
|
+
const res = inputStream.read_bytes_finish(asyncRes);
|
|
19
|
+
if (res.get_size() === 0) {
|
|
20
|
+
return resolve(null);
|
|
21
|
+
}
|
|
22
|
+
return resolve(byteArray.fromGBytes(res));
|
|
23
|
+
} catch (error) {
|
|
24
|
+
reject(error);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async function* inputStreamAsyncIterator(inputStream, count = 4096, ioPriority = GLib.PRIORITY_DEFAULT, cancellable = null) {
|
|
30
|
+
let chunk;
|
|
31
|
+
while ((chunk = await readBytesAsync(inputStream, count, ioPriority, cancellable)) !== null) {
|
|
32
|
+
yield chunk;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
gioAsync,
|
|
37
|
+
inputStreamAsyncIterator,
|
|
38
|
+
readBytesAsync
|
|
39
|
+
};
|
package/lib/esm/index.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
1
|
+
export * from "./base64.js";
|
|
2
|
+
export * from "./byte-array.js";
|
|
3
3
|
export * from "./cli.js";
|
|
4
|
+
export * from "./defer.js";
|
|
5
|
+
export * from "./encoding.js";
|
|
6
|
+
export * from "./globals.js";
|
|
4
7
|
export * from "./error.js";
|
|
5
8
|
export * from "./file.js";
|
|
6
9
|
export * from "./fs.js";
|
|
7
|
-
export * from "./
|
|
10
|
+
export * from "./gio.js";
|
|
11
|
+
export * from "./gio-errors.js";
|
|
8
12
|
export * from "./message.js";
|
|
9
|
-
export * from "./
|
|
13
|
+
export * from "./next-tick.js";
|
|
10
14
|
export * from "./path.js";
|
|
11
|
-
export * from "./
|
|
12
|
-
export * from "./
|
|
13
|
-
export * from "./tty.js";
|
|
14
|
-
export * from "./version.js";
|
|
15
|
+
export * from "./structured-clone.js";
|
|
16
|
+
export * from "./main-loop.js";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
let _started = false;
|
|
2
|
+
let _loop = null;
|
|
3
|
+
function ensureMainLoop() {
|
|
4
|
+
const gjsImports = globalThis.imports;
|
|
5
|
+
if (!gjsImports) return void 0;
|
|
6
|
+
if (_started) return _loop;
|
|
7
|
+
const GLibModule = gjsImports.gi.GLib;
|
|
8
|
+
_loop = new GLibModule.MainLoop(null, false);
|
|
9
|
+
_started = true;
|
|
10
|
+
if (GLibModule.main_depth() === 0) {
|
|
11
|
+
try {
|
|
12
|
+
_loop.runAsync();
|
|
13
|
+
} catch {
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return _loop;
|
|
17
|
+
}
|
|
18
|
+
function quitMainLoop() {
|
|
19
|
+
if (_loop) {
|
|
20
|
+
_loop.quit();
|
|
21
|
+
_started = false;
|
|
22
|
+
_loop = null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
ensureMainLoop,
|
|
27
|
+
quitMainLoop
|
|
28
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
const nextTick = typeof globalThis.process?.nextTick === "function" ? globalThis.process.nextTick : typeof globalThis.queueMicrotask === "function" ? (fn, ...args) => queueMicrotask(() => fn(...args)) : (fn, ...args) => {
|
|
2
|
+
Promise.resolve().then(() => fn(...args));
|
|
3
|
+
};
|
|
4
|
+
export {
|
|
5
|
+
nextTick
|
|
6
|
+
};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const { toString } = Object.prototype;
|
|
2
|
+
function classOf(value) {
|
|
3
|
+
return toString.call(value).slice(8, -1);
|
|
4
|
+
}
|
|
5
|
+
function throwDataCloneError(message) {
|
|
6
|
+
const DOMExceptionCtor = globalThis.DOMException;
|
|
7
|
+
if (typeof DOMExceptionCtor === "function") {
|
|
8
|
+
throw new DOMExceptionCtor(message, "DataCloneError");
|
|
9
|
+
}
|
|
10
|
+
const error = new Error(message);
|
|
11
|
+
error.name = "DataCloneError";
|
|
12
|
+
throw error;
|
|
13
|
+
}
|
|
14
|
+
const ERROR_CONSTRUCTORS = {
|
|
15
|
+
Error,
|
|
16
|
+
EvalError,
|
|
17
|
+
RangeError,
|
|
18
|
+
ReferenceError,
|
|
19
|
+
SyntaxError,
|
|
20
|
+
TypeError,
|
|
21
|
+
URIError
|
|
22
|
+
};
|
|
23
|
+
const TYPED_ARRAY_TAGS = /* @__PURE__ */ new Set([
|
|
24
|
+
"Int8Array",
|
|
25
|
+
"Uint8Array",
|
|
26
|
+
"Uint8ClampedArray",
|
|
27
|
+
"Int16Array",
|
|
28
|
+
"Uint16Array",
|
|
29
|
+
"Int32Array",
|
|
30
|
+
"Uint32Array",
|
|
31
|
+
"Float32Array",
|
|
32
|
+
"Float64Array",
|
|
33
|
+
"BigInt64Array",
|
|
34
|
+
"BigUint64Array"
|
|
35
|
+
]);
|
|
36
|
+
function internalClone(value, seen) {
|
|
37
|
+
if (value === null || value === void 0) return value;
|
|
38
|
+
const type = typeof value;
|
|
39
|
+
if (type === "boolean" || type === "number" || type === "string" || type === "bigint") {
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
if (type === "symbol") {
|
|
43
|
+
throwDataCloneError("Symbol cannot be cloned");
|
|
44
|
+
}
|
|
45
|
+
if (type === "function") {
|
|
46
|
+
throwDataCloneError("Function cannot be cloned");
|
|
47
|
+
}
|
|
48
|
+
const obj = value;
|
|
49
|
+
if (seen.has(obj)) return seen.get(obj);
|
|
50
|
+
const tag = classOf(obj);
|
|
51
|
+
if (tag === "Date") {
|
|
52
|
+
return new Date(obj.getTime());
|
|
53
|
+
}
|
|
54
|
+
if (tag === "RegExp") {
|
|
55
|
+
return new RegExp(obj.source, obj.flags);
|
|
56
|
+
}
|
|
57
|
+
if (tag === "Boolean") return Object(obj.valueOf());
|
|
58
|
+
if (tag === "Number") return Object(obj.valueOf());
|
|
59
|
+
if (tag === "String") return Object(obj.valueOf());
|
|
60
|
+
if (tag === "BigInt") return Object(BigInt.prototype.valueOf.call(obj));
|
|
61
|
+
if (obj instanceof Error) {
|
|
62
|
+
const src = obj;
|
|
63
|
+
const ctorName = src.constructor?.name;
|
|
64
|
+
const Ctor = ctorName && ERROR_CONSTRUCTORS[ctorName] || ERROR_CONSTRUCTORS[src.name] || Error;
|
|
65
|
+
const cloned = new Ctor(src.message);
|
|
66
|
+
cloned.name = src.name;
|
|
67
|
+
if ("cause" in src) {
|
|
68
|
+
Object.defineProperty(cloned, "cause", {
|
|
69
|
+
value: internalClone(src.cause, seen),
|
|
70
|
+
writable: true,
|
|
71
|
+
enumerable: false,
|
|
72
|
+
configurable: true
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return cloned;
|
|
76
|
+
}
|
|
77
|
+
if (tag === "DOMException") {
|
|
78
|
+
const DOMExceptionCtor = globalThis.DOMException;
|
|
79
|
+
if (typeof DOMExceptionCtor === "function") {
|
|
80
|
+
const src = obj;
|
|
81
|
+
return new DOMExceptionCtor(src.message, src.name);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (tag === "ArrayBuffer") {
|
|
85
|
+
const src = obj;
|
|
86
|
+
const cloned = src.slice(0);
|
|
87
|
+
seen.set(obj, cloned);
|
|
88
|
+
return cloned;
|
|
89
|
+
}
|
|
90
|
+
if (tag === "SharedArrayBuffer") {
|
|
91
|
+
return obj;
|
|
92
|
+
}
|
|
93
|
+
if (tag === "DataView") {
|
|
94
|
+
const src = obj;
|
|
95
|
+
const bufferClone = internalClone(src.buffer, seen);
|
|
96
|
+
const cloned = new DataView(bufferClone, src.byteOffset, src.byteLength);
|
|
97
|
+
seen.set(obj, cloned);
|
|
98
|
+
return cloned;
|
|
99
|
+
}
|
|
100
|
+
if (TYPED_ARRAY_TAGS.has(tag)) {
|
|
101
|
+
const src = obj;
|
|
102
|
+
const bufferClone = internalClone(src.buffer, seen);
|
|
103
|
+
const Ctor = src.constructor;
|
|
104
|
+
const cloned = new Ctor(bufferClone, src.byteOffset, src.length);
|
|
105
|
+
seen.set(obj, cloned);
|
|
106
|
+
return cloned;
|
|
107
|
+
}
|
|
108
|
+
if (tag === "Map") {
|
|
109
|
+
const cloned = /* @__PURE__ */ new Map();
|
|
110
|
+
seen.set(obj, cloned);
|
|
111
|
+
for (const [k, v] of obj) {
|
|
112
|
+
cloned.set(internalClone(k, seen), internalClone(v, seen));
|
|
113
|
+
}
|
|
114
|
+
return cloned;
|
|
115
|
+
}
|
|
116
|
+
if (tag === "Set") {
|
|
117
|
+
const cloned = /* @__PURE__ */ new Set();
|
|
118
|
+
seen.set(obj, cloned);
|
|
119
|
+
for (const v of obj) {
|
|
120
|
+
cloned.add(internalClone(v, seen));
|
|
121
|
+
}
|
|
122
|
+
return cloned;
|
|
123
|
+
}
|
|
124
|
+
{
|
|
125
|
+
const g = globalThis;
|
|
126
|
+
const BlobCtor = g.Blob;
|
|
127
|
+
const FileCtor = g.File;
|
|
128
|
+
if (typeof FileCtor === "function" && obj instanceof FileCtor) {
|
|
129
|
+
const src = obj;
|
|
130
|
+
return new FileCtor([obj], src.name, { type: src.type, lastModified: src.lastModified });
|
|
131
|
+
}
|
|
132
|
+
if (typeof BlobCtor === "function" && obj instanceof BlobCtor) {
|
|
133
|
+
const src = obj;
|
|
134
|
+
return new BlobCtor([obj], { type: src.type });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (obj instanceof WeakMap) throwDataCloneError("WeakMap cannot be cloned");
|
|
138
|
+
if (obj instanceof WeakSet) throwDataCloneError("WeakSet cannot be cloned");
|
|
139
|
+
if (obj instanceof WeakRef) throwDataCloneError("WeakRef cannot be cloned");
|
|
140
|
+
if (typeof globalThis.Promise === "function" && obj instanceof Promise) {
|
|
141
|
+
throwDataCloneError("Promise cannot be cloned");
|
|
142
|
+
}
|
|
143
|
+
if (tag === "Array") {
|
|
144
|
+
const src = obj;
|
|
145
|
+
const cloned = [];
|
|
146
|
+
seen.set(obj, cloned);
|
|
147
|
+
for (let i = 0; i < src.length; i++) {
|
|
148
|
+
if (i in src) {
|
|
149
|
+
cloned[i] = internalClone(src[i], seen);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return cloned;
|
|
153
|
+
}
|
|
154
|
+
if (tag === "Object" || typeof obj === "object") {
|
|
155
|
+
const cloned = {};
|
|
156
|
+
seen.set(obj, cloned);
|
|
157
|
+
for (const key of Object.keys(obj)) {
|
|
158
|
+
cloned[key] = internalClone(obj[key], seen);
|
|
159
|
+
}
|
|
160
|
+
return cloned;
|
|
161
|
+
}
|
|
162
|
+
throwDataCloneError(`${tag} cannot be cloned`);
|
|
163
|
+
}
|
|
164
|
+
function structuredClone(value, _options) {
|
|
165
|
+
return internalClone(value, /* @__PURE__ */ new Map());
|
|
166
|
+
}
|
|
167
|
+
export {
|
|
168
|
+
structuredClone
|
|
169
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Decode a base64 string to a binary string. Uses native atob when available. */
|
|
2
|
+
export declare function atobPolyfill(str: string): string;
|
|
3
|
+
/** Encode a binary string to base64. Uses native btoa when available. */
|
|
4
|
+
export declare function btoaPolyfill(str: string): string;
|
|
5
|
+
/** Decode a base64 string directly to Uint8Array (avoids lossy atob string round-trip). */
|
|
6
|
+
export declare function base64Decode(str: string): Uint8Array;
|
|
7
|
+
/** Encode a Uint8Array to base64 string. */
|
|
8
|
+
export declare function base64Encode(bytes: Uint8Array): string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type GLib from '@girs/glib-2.0';
|
|
2
|
+
/**
|
|
3
|
+
* Convert GLib.Bytes to Uint8Array using GJS's byteArray module.
|
|
4
|
+
* This wraps the GJS-specific `imports.byteArray.fromGBytes()` API
|
|
5
|
+
* with proper typing to eliminate `as any` casts throughout the codebase.
|
|
6
|
+
*/
|
|
7
|
+
export declare function gbytesToUint8Array(bytes: GLib.Bytes): Uint8Array;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defer an event emission to the next macrotask, matching Node.js behavior
|
|
3
|
+
* for server 'listening', 'close', and 'error' events.
|
|
4
|
+
*/
|
|
5
|
+
export declare function deferEmit(emitter: {
|
|
6
|
+
emit(event: string | symbol, ...args: unknown[]): boolean;
|
|
7
|
+
}, event: string, ...args: unknown[]): void;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Canonical encoding names (matches BufferEncoding from @types/node). */
|
|
2
|
+
export type Encoding = 'utf8' | 'ascii' | 'latin1' | 'base64' | 'base64url' | 'hex' | 'utf16le' | 'binary' | 'ucs2' | 'ucs-2' | 'utf-8';
|
|
3
|
+
/**
|
|
4
|
+
* Normalize an encoding string to a canonical encoding value.
|
|
5
|
+
* Returns 'utf8' as default for undefined/null/empty input.
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeEncoding(enc?: string): Encoding;
|
|
8
|
+
/**
|
|
9
|
+
* Check that an encoding string is valid. Throws TypeError if not.
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkEncoding(encoding: string): void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Map from Gio.IOErrorEnum numeric values to Node.js error code strings. */
|
|
2
|
+
export declare const GIO_ERROR_TO_NODE: Record<number, string>;
|
|
3
|
+
export interface NodeErrorDetails {
|
|
4
|
+
path?: string;
|
|
5
|
+
dest?: string;
|
|
6
|
+
address?: string;
|
|
7
|
+
port?: number;
|
|
8
|
+
hostname?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Node.js-style ErrnoException (defined locally to avoid @types/node dependency). */
|
|
11
|
+
export interface ErrnoException extends Error {
|
|
12
|
+
errno?: number;
|
|
13
|
+
code?: string;
|
|
14
|
+
path?: string;
|
|
15
|
+
syscall?: string;
|
|
16
|
+
address?: string;
|
|
17
|
+
port?: number;
|
|
18
|
+
hostname?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a Node.js-style ErrnoException from a Gio error.
|
|
22
|
+
* Works for fs, net, dns, child-process, and other modules.
|
|
23
|
+
*/
|
|
24
|
+
export declare function createNodeError(err: unknown, syscall: string, details?: NodeErrorDetails): ErrnoException;
|
|
25
|
+
/**
|
|
26
|
+
* Check if a Gio error is a "not found" error.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isNotFoundError(err: unknown): boolean;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import Gio from '@girs/gio-2.0';
|
|
2
|
+
/**
|
|
3
|
+
* Generic promise wrapper for Gio async/finish method pairs.
|
|
4
|
+
*
|
|
5
|
+
* Example:
|
|
6
|
+
* const stream = await gioAsync<Gio.InputStream>(session, 'send_async', 'send_finish', msg, priority, null);
|
|
7
|
+
*/
|
|
8
|
+
export declare function gioAsync<T>(obj: any, asyncMethod: string, finishMethod: string, ...args: any[]): Promise<T>;
|
|
9
|
+
/**
|
|
10
|
+
* Promise wrapper around `Gio.InputStream.read_bytes_async` / `read_bytes_finish`.
|
|
11
|
+
* Returns a `Uint8Array` or `null` if the end of the stream is reached.
|
|
12
|
+
*/
|
|
13
|
+
export declare function readBytesAsync(inputStream: Gio.InputStream, count?: number, ioPriority?: number, cancellable?: Gio.Cancellable | null): Promise<Uint8Array | null>;
|
|
14
|
+
/**
|
|
15
|
+
* Async generator that yields `Uint8Array` chunks from a `Gio.InputStream`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function inputStreamAsyncIterator(inputStream: Gio.InputStream, count?: number, ioPriority?: number, cancellable?: Gio.Cancellable | null): AsyncGenerator<Uint8Array>;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
1
|
+
export * from './base64.js';
|
|
2
|
+
export * from './byte-array.js';
|
|
3
3
|
export * from './cli.js';
|
|
4
|
+
export * from './defer.js';
|
|
5
|
+
export * from './encoding.js';
|
|
6
|
+
export * from './globals.js';
|
|
4
7
|
export * from './error.js';
|
|
5
8
|
export * from './file.js';
|
|
6
9
|
export * from './fs.js';
|
|
7
|
-
export * from './
|
|
10
|
+
export * from './gio.js';
|
|
11
|
+
export * from './gio-errors.js';
|
|
8
12
|
export * from './message.js';
|
|
9
|
-
export * from './
|
|
13
|
+
export * from './next-tick.js';
|
|
10
14
|
export * from './path.js';
|
|
11
|
-
export * from './
|
|
12
|
-
export * from './
|
|
13
|
-
export * from './tty.js';
|
|
14
|
-
export * from './version.js';
|
|
15
|
+
export * from './structured-clone.js';
|
|
16
|
+
export * from './main-loop.js';
|