@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.
Files changed (119) hide show
  1. package/README.md +26 -0
  2. package/lib/esm/base64.js +72 -0
  3. package/lib/esm/byte-array.js +6 -0
  4. package/lib/esm/cli.js +1 -2
  5. package/lib/esm/defer.js +6 -0
  6. package/lib/esm/encoding.js +35 -0
  7. package/lib/esm/fs.js +2 -1
  8. package/lib/esm/gio-errors.js +98 -0
  9. package/lib/esm/gio.js +39 -0
  10. package/lib/esm/globals.js +8 -0
  11. package/lib/esm/index.js +10 -8
  12. package/lib/esm/main-loop.js +28 -0
  13. package/lib/esm/next-tick.js +6 -0
  14. package/lib/esm/structured-clone.js +169 -0
  15. package/lib/types/base64.d.ts +8 -0
  16. package/lib/types/byte-array.d.ts +7 -0
  17. package/lib/types/defer.d.ts +7 -0
  18. package/lib/types/encoding.d.ts +11 -0
  19. package/lib/types/gio-errors.d.ts +28 -0
  20. package/lib/types/gio.d.ts +17 -0
  21. package/lib/types/globals.d.ts +5 -0
  22. package/lib/types/index.d.ts +10 -8
  23. package/lib/types/main-loop.d.ts +20 -0
  24. package/lib/types/next-tick.d.ts +5 -0
  25. package/lib/types/structured-clone.d.ts +15 -0
  26. package/package.json +18 -20
  27. package/src/base64.ts +78 -0
  28. package/src/byte-array.ts +12 -0
  29. package/src/defer.ts +11 -0
  30. package/src/encoding.ts +36 -0
  31. package/src/fs.ts +2 -2
  32. package/src/gio-errors.ts +101 -0
  33. package/src/gio.ts +67 -0
  34. package/src/globals.ts +13 -0
  35. package/src/index.ts +10 -9
  36. package/src/main-loop.ts +62 -0
  37. package/src/next-tick.ts +16 -0
  38. package/src/structured-clone.ts +242 -0
  39. package/src/test.ts +1 -3
  40. package/tsconfig.json +27 -10
  41. package/tsconfig.tsbuildinfo +1 -0
  42. package/lib/cjs/cancel-handler.js +0 -22
  43. package/lib/cjs/cli.js +0 -11
  44. package/lib/cjs/error.js +0 -21
  45. package/lib/cjs/file.js +0 -13
  46. package/lib/cjs/fs.js +0 -21
  47. package/lib/cjs/index.js +0 -14
  48. package/lib/cjs/log.js +0 -159
  49. package/lib/cjs/message.js +0 -13
  50. package/lib/cjs/os.js +0 -81
  51. package/lib/cjs/path.js +0 -50
  52. package/lib/cjs/process.js +0 -41
  53. package/lib/cjs/system.js +0 -47
  54. package/lib/cjs/tty.js +0 -13
  55. package/lib/cjs/types/cancel-signals.js +0 -0
  56. package/lib/cjs/types/error-data.js +0 -0
  57. package/lib/cjs/types/index.js +0 -8
  58. package/lib/cjs/types/signal-methods.js +0 -0
  59. package/lib/cjs/types/stack-trace-frame.js +0 -0
  60. package/lib/cjs/types/structured-log-data.js +0 -0
  61. package/lib/cjs/types/uncaught-exception-data.js +0 -0
  62. package/lib/cjs/types/unhandled-rejection-data.js +0 -0
  63. package/lib/cjs/types/user-info.js +0 -0
  64. package/lib/cjs/version.js +0 -7
  65. package/lib/esm/cancel-handler.js +0 -22
  66. package/lib/esm/log.js +0 -159
  67. package/lib/esm/os.js +0 -81
  68. package/lib/esm/process.js +0 -41
  69. package/lib/esm/system.js +0 -47
  70. package/lib/esm/tty.js +0 -13
  71. package/lib/esm/types/cancel-signals.js +0 -0
  72. package/lib/esm/types/error-data.js +0 -0
  73. package/lib/esm/types/index.js +0 -8
  74. package/lib/esm/types/signal-methods.js +0 -0
  75. package/lib/esm/types/stack-trace-frame.js +0 -0
  76. package/lib/esm/types/structured-log-data.js +0 -0
  77. package/lib/esm/types/uncaught-exception-data.js +0 -0
  78. package/lib/esm/types/unhandled-rejection-data.js +0 -0
  79. package/lib/esm/types/user-info.js +0 -0
  80. package/lib/esm/version.js +0 -7
  81. package/lib/types/cancel-handler.d.ts +0 -4
  82. package/lib/types/log.d.ts +0 -29
  83. package/lib/types/os.d.ts +0 -7
  84. package/lib/types/process.d.ts +0 -6
  85. package/lib/types/system.d.ts +0 -5
  86. package/lib/types/tty.d.ts +0 -5
  87. package/lib/types/types/cancel-signals.d.ts +0 -5
  88. package/lib/types/types/error-data.d.ts +0 -7
  89. package/lib/types/types/index.d.ts +0 -8
  90. package/lib/types/types/signal-methods.d.ts +0 -62
  91. package/lib/types/types/stack-trace-frame.d.ts +0 -6
  92. package/lib/types/types/structured-log-data.d.ts +0 -5
  93. package/lib/types/types/uncaught-exception-data.d.ts +0 -4
  94. package/lib/types/types/unhandled-rejection-data.d.ts +0 -5
  95. package/lib/types/types/user-info.d.ts +0 -8
  96. package/lib/types/version.d.ts +0 -1
  97. package/src/cancel-handler.ts +0 -24
  98. package/src/log.ts +0 -218
  99. package/src/os.ts +0 -94
  100. package/src/process.spec.ts +0 -24
  101. package/src/process.ts +0 -46
  102. package/src/system.ts +0 -56
  103. package/src/tty.spec.ts +0 -10
  104. package/src/tty.ts +0 -10
  105. package/src/types/cancel-signals.ts +0 -6
  106. package/src/types/error-data.ts +0 -8
  107. package/src/types/index.ts +0 -8
  108. package/src/types/signal-methods.ts +0 -63
  109. package/src/types/stack-trace-frame.ts +0 -7
  110. package/src/types/structured-log-data.ts +0 -5
  111. package/src/types/uncaught-exception-data.ts +0 -5
  112. package/src/types/unhandled-rejection-data.ts +0 -6
  113. package/src/types/user-info.ts +0 -9
  114. package/src/version.ts +0 -4
  115. package/test.gjs.js +0 -34758
  116. package/test.gjs.js.map +0 -7
  117. package/test.gjs.js.meta.json +0 -1
  118. package/tsconfig.types.json +0 -7
  119. 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
+ };
@@ -0,0 +1,6 @@
1
+ function gbytesToUint8Array(bytes) {
2
+ return imports.byteArray.fromGBytes(bytes);
3
+ }
4
+ export {
5
+ gbytesToUint8Array
6
+ };
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 {
@@ -0,0 +1,6 @@
1
+ function deferEmit(emitter, event, ...args) {
2
+ setTimeout(() => emitter.emit(event, ...args), 0);
3
+ }
4
+ export {
5
+ deferEmit
6
+ };
@@ -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 = Gio.UnixInputStream.new(fd, false);
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
+ };
@@ -0,0 +1,8 @@
1
+ function registerGlobal(name, value) {
2
+ if (typeof globalThis[name] === "undefined") {
3
+ globalThis[name] = value;
4
+ }
5
+ }
6
+ export {
7
+ registerGlobal
8
+ };
package/lib/esm/index.js CHANGED
@@ -1,14 +1,16 @@
1
- export * from "./types/index.js";
2
- export * from "./cancel-handler.js";
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 "./log.js";
10
+ export * from "./gio.js";
11
+ export * from "./gio-errors.js";
8
12
  export * from "./message.js";
9
- export * from "./os.js";
13
+ export * from "./next-tick.js";
10
14
  export * from "./path.js";
11
- export * from "./process.js";
12
- export * from "./system.js";
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>;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Register a value as a global property if it doesn't already exist.
3
+ * This is a no-op in environments where the global is already defined (e.g. Node.js).
4
+ */
5
+ export declare function registerGlobal(name: string, value: unknown): void;
@@ -1,14 +1,16 @@
1
- export * from './types/index.js';
2
- export * from './cancel-handler.js';
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 './log.js';
10
+ export * from './gio.js';
11
+ export * from './gio-errors.js';
8
12
  export * from './message.js';
9
- export * from './os.js';
13
+ export * from './next-tick.js';
10
14
  export * from './path.js';
11
- export * from './process.js';
12
- export * from './system.js';
13
- export * from './tty.js';
14
- export * from './version.js';
15
+ export * from './structured-clone.js';
16
+ export * from './main-loop.js';