@gjsify/utils 0.4.0 → 0.4.3

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/package.json CHANGED
@@ -1,44 +1,47 @@
1
1
  {
2
- "name": "@gjsify/utils",
3
- "version": "0.4.0",
4
- "description": "Utils module for gjsify",
5
- "module": "lib/esm/index.js",
6
- "types": "lib/types/index.d.ts",
7
- "type": "module",
8
- "exports": {
9
- ".": {
10
- "types": "./lib/types/index.d.ts",
11
- "default": "./lib/esm/index.js"
2
+ "name": "@gjsify/utils",
3
+ "version": "0.4.3",
4
+ "description": "Utils module for gjsify",
5
+ "module": "lib/esm/index.js",
6
+ "types": "lib/types/index.d.ts",
7
+ "files": [
8
+ "lib"
9
+ ],
10
+ "type": "module",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./lib/types/index.d.ts",
14
+ "default": "./lib/esm/index.js"
15
+ },
16
+ "./main-loop": {
17
+ "types": "./lib/types/main-loop.d.ts",
18
+ "default": "./lib/esm/main-loop.js"
19
+ }
12
20
  },
13
- "./main-loop": {
14
- "types": "./lib/types/main-loop.d.ts",
15
- "default": "./lib/esm/main-loop.js"
21
+ "scripts": {
22
+ "clear": "rm -rf lib tsconfig.tsbuildinfo tsconfig.types.tsbuildinfo test.gjs.mjs test.node.mjs || exit 0",
23
+ "check": "tsc --noEmit",
24
+ "build": "gjsify run build:gjsify && gjsify run build:types",
25
+ "build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
26
+ "build:types": "tsc",
27
+ "build:test": "gjsify run build:test:gjs",
28
+ "build:test:gjs": "gjsify build src/test.ts --app gjs --outfile test.gjs.js",
29
+ "test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:gjs",
30
+ "test:gjs": "gjsify run test.gjs.js"
31
+ },
32
+ "keywords": [
33
+ "gjs",
34
+ "node",
35
+ "fs"
36
+ ],
37
+ "devDependencies": {
38
+ "@gjsify/cli": "workspace:^",
39
+ "typescript": "^6.0.3"
40
+ },
41
+ "dependencies": {
42
+ "@girs/gio-2.0": "2.88.0-4.0.0-rc.15",
43
+ "@girs/giounix-2.0": "2.0.0-4.0.0-rc.15",
44
+ "@girs/gjs": "4.0.0-rc.15",
45
+ "@girs/glib-2.0": "2.88.0-4.0.0-rc.15"
16
46
  }
17
- },
18
- "scripts": {
19
- "clear": "rm -rf lib tsconfig.tsbuildinfo tsconfig.types.tsbuildinfo test.gjs.mjs test.node.mjs || exit 0",
20
- "check": "tsc --noEmit",
21
- "build": "yarn build:gjsify && yarn build:types",
22
- "build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
23
- "build:types": "tsc",
24
- "build:test": "yarn build:test:gjs",
25
- "build:test:gjs": "gjsify build src/test.ts --app gjs --outfile test.gjs.js",
26
- "test": "yarn build:gjsify && yarn build:test && yarn test:gjs",
27
- "test:gjs": "gjsify run test.gjs.js"
28
- },
29
- "keywords": [
30
- "gjs",
31
- "node",
32
- "fs"
33
- ],
34
- "devDependencies": {
35
- "@gjsify/cli": "^0.4.0",
36
- "typescript": "^6.0.3"
37
- },
38
- "dependencies": {
39
- "@girs/gio-2.0": "2.88.0-4.0.0-rc.15",
40
- "@girs/giounix-2.0": "2.0.0-4.0.0-rc.15",
41
- "@girs/gjs": "4.0.0-rc.15",
42
- "@girs/glib-2.0": "2.88.0-4.0.0-rc.15"
43
- }
44
- }
47
+ }
package/src/base64.ts DELETED
@@ -1,78 +0,0 @@
1
- // Base64 encoding/decoding utilities for GJS
2
- // Shared by @gjsify/buffer and @gjsify/string_decoder
3
- // Reference: RFC 4648
4
-
5
- const B64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
6
- const B64_LOOKUP = new Uint8Array(256);
7
- for (let i = 0; i < B64_CHARS.length; i++) B64_LOOKUP[B64_CHARS.charCodeAt(i)] = i;
8
-
9
- /** Decode a base64 string to a binary string. Uses native atob when available. */
10
- export function atobPolyfill(str: string): string {
11
- if (typeof globalThis.atob === 'function') return globalThis.atob(str);
12
- const cleaned = str.replace(/[=\s]/g, '');
13
- let result = '';
14
- let bits = 0;
15
- let collected = 0;
16
- for (let i = 0; i < cleaned.length; i++) {
17
- bits = (bits << 6) | B64_LOOKUP[cleaned.charCodeAt(i)];
18
- collected += 6;
19
- if (collected >= 8) {
20
- collected -= 8;
21
- result += String.fromCharCode((bits >> collected) & 0xff);
22
- }
23
- }
24
- return result;
25
- }
26
-
27
- /** Encode a binary string to base64. Uses native btoa when available. */
28
- export function btoaPolyfill(str: string): string {
29
- if (typeof globalThis.btoa === 'function') return globalThis.btoa(str);
30
- let result = '';
31
- let i = 0;
32
- for (; i + 2 < str.length; i += 3) {
33
- const n = (str.charCodeAt(i) << 16) | (str.charCodeAt(i + 1) << 8) | str.charCodeAt(i + 2);
34
- result += B64_CHARS[(n >> 18) & 63] + B64_CHARS[(n >> 12) & 63] + B64_CHARS[(n >> 6) & 63] + B64_CHARS[n & 63];
35
- }
36
- if (i + 1 === str.length) {
37
- const n = str.charCodeAt(i) << 16;
38
- result += B64_CHARS[(n >> 18) & 63] + B64_CHARS[(n >> 12) & 63] + '==';
39
- } else if (i + 2 === str.length) {
40
- const n = (str.charCodeAt(i) << 16) | (str.charCodeAt(i + 1) << 8);
41
- result += B64_CHARS[(n >> 18) & 63] + B64_CHARS[(n >> 12) & 63] + B64_CHARS[(n >> 6) & 63] + '=';
42
- }
43
- return result;
44
- }
45
-
46
- /** Decode a base64 string directly to Uint8Array (avoids lossy atob string round-trip). */
47
- export function base64Decode(str: string): Uint8Array {
48
- const cleaned = str.replace(/[=\s]/g, '');
49
- const bytes = new Uint8Array((cleaned.length * 3) >> 2);
50
- let bits = 0;
51
- let collected = 0;
52
- let pos = 0;
53
- for (let i = 0; i < cleaned.length; i++) {
54
- bits = (bits << 6) | B64_LOOKUP[cleaned.charCodeAt(i)];
55
- collected += 6;
56
- if (collected >= 8) {
57
- collected -= 8;
58
- bytes[pos++] = (bits >> collected) & 0xff;
59
- }
60
- }
61
- return bytes.subarray(0, pos);
62
- }
63
-
64
- /** Encode a Uint8Array to base64 string. */
65
- export function base64Encode(bytes: Uint8Array): string {
66
- let result = '';
67
- const len = bytes.length;
68
- for (let i = 0; i < len; i += 3) {
69
- const b0 = bytes[i];
70
- const b1 = i + 1 < len ? bytes[i + 1] : 0;
71
- const b2 = i + 2 < len ? bytes[i + 2] : 0;
72
- result += B64_CHARS[b0 >> 2];
73
- result += B64_CHARS[((b0 & 3) << 4) | (b1 >> 4)];
74
- result += i + 1 < len ? B64_CHARS[((b1 & 0xf) << 2) | (b2 >> 6)] : '=';
75
- result += i + 2 < len ? B64_CHARS[b2 & 0x3f] : '=';
76
- }
77
- return result;
78
- }
package/src/byte-array.ts DELETED
@@ -1,12 +0,0 @@
1
- import type GLib from '@girs/glib-2.0';
2
-
3
- declare const imports: { byteArray: { fromGBytes(input: GLib.Bytes): Uint8Array } };
4
-
5
- /**
6
- * Convert GLib.Bytes to Uint8Array using GJS's byteArray module.
7
- * This wraps the GJS-specific `imports.byteArray.fromGBytes()` API
8
- * with proper typing to eliminate `as any` casts throughout the codebase.
9
- */
10
- export function gbytesToUint8Array(bytes: GLib.Bytes): Uint8Array {
11
- return imports.byteArray.fromGBytes(bytes);
12
- }
package/src/callable.ts DELETED
@@ -1,63 +0,0 @@
1
- // Legacy `.call(this)` compatibility shim for ES6 classes.
2
- //
3
- // Reference: refs/node/lib/internal/streams/legacy.js (Node core Stream() as a
4
- // regular function, deliberately callable via .call()).
5
- // Reference: refs/readable-stream/lib/internal/streams/legacy.js (same pattern).
6
- // Implements the legacy callable pattern for our class-based hierarchy so
7
- // pre-ES2015 CJS consumers can do `Cls.call(this)` + `util.inherits(Sub, Cls)`.
8
- // Without this shim, packages that do `EventEmitter.call(this)` or
9
- // `Stream.call(this)` crash with:
10
- // TypeError: Class constructor Foo cannot be invoked without 'new'
11
- //
12
- // Copyright (c) Node.js contributors. MIT license.
13
- // Modifications: implemented as a Proxy wrapper for GJSify's ES6 classes.
14
-
15
- /**
16
- * Wrap an ES6 class so it supports both the modern `new Cls(...)` pattern and
17
- * the legacy `Cls.call(thisArg, ...)` / `Cls(...)` (no-`new`) patterns.
18
- *
19
- * The `apply` trap has two modes:
20
- *
21
- * 1. **`Cls.call(thisArg, ...)`** — a real consumer instance is provided.
22
- * We materialise a temporary instance via `Reflect.construct` (so field
23
- * initializers and constructor bodies run normally) and transplant its
24
- * own property descriptors onto `thisArg`. This is how Node-era CJS
25
- * consumers + `util.inherits(Sub, Cls)` chains expect to subclass our
26
- * ES6 classes.
27
- *
28
- * 2. **`Cls(...)`** (called as a plain function — `thisArg` is `undefined`
29
- * in strict mode or `globalThis` in sloppy mode) — we treat the call as
30
- * a constructor call and return a fresh `new Cls(...)`. Node's stream
31
- * constructors implement this guard explicitly:
32
- * `if (!(this instanceof PassThrough)) return new PassThrough(...)`
33
- * so consumers like `merge2` invoke `Stream.PassThrough(opts)` without
34
- * `new` and rely on the result being a real instance. Without this
35
- * branch the apply trap would crash with "undefined is not a non-null
36
- * object" when it tried to `Object.defineProperty(thisArg, …)`.
37
- *
38
- * The default Proxy traps pass `construct`, `get` and `getPrototypeOf`
39
- * straight through, so `new Wrapped()`, `Wrapped.prototype` (consulted by
40
- * `util.inherits`) and `instance instanceof Wrapped` all behave identically
41
- * to the underlying class.
42
- */
43
- export function makeCallable<T extends new (...args: any[]) => any>(Cls: T): T {
44
- return new Proxy(Cls, {
45
- apply(target, thisArg: object | undefined | null, args: any[]) {
46
- // No-`new` invocation (`Cls(...)`): no usable receiver to mutate
47
- // — return a freshly constructed instance instead. globalThis is
48
- // also treated as "no receiver" because that is what a sloppy-
49
- // mode plain function call surfaces.
50
- if (thisArg == null || thisArg === globalThis) {
51
- return Reflect.construct(target, args, target);
52
- }
53
- // `Cls.call(thisArg, ...)`: transplant a fresh instance's own
54
- // properties onto the caller-supplied receiver.
55
- const tmp = Reflect.construct(target, args, target);
56
- for (const key of Reflect.ownKeys(tmp)) {
57
- const desc = Object.getOwnPropertyDescriptor(tmp, key);
58
- if (desc) Object.defineProperty(thisArg, key, desc);
59
- }
60
- return thisArg;
61
- },
62
- });
63
- }
package/src/cli.ts DELETED
@@ -1,10 +0,0 @@
1
- import GLib from '@girs/glib-2.0';
2
- const byteArray = imports.byteArray;
3
-
4
- export const cli = (commandLine: string): string => {
5
- const [res, out, err, status] = GLib.spawn_command_line_sync(commandLine);
6
-
7
- if(err.byteLength) throw new Error(byteArray.toString(err));
8
-
9
- return byteArray.toString(out);
10
- };
package/src/defer.ts DELETED
@@ -1,11 +0,0 @@
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 function deferEmit(
6
- emitter: { emit(event: string | symbol, ...args: unknown[]): boolean },
7
- event: string,
8
- ...args: unknown[]
9
- ): void {
10
- setTimeout(() => emitter.emit(event, ...args), 0);
11
- }
package/src/encoding.ts DELETED
@@ -1,36 +0,0 @@
1
- // Shared encoding normalization utilities.
2
- // Used by buffer, string_decoder, crypto, and other packages that deal with encodings.
3
-
4
- /** Canonical encoding names (matches BufferEncoding from @types/node). */
5
- export type Encoding = 'utf8' | 'ascii' | 'latin1' | 'base64' | 'base64url' | 'hex' | 'utf16le' | 'binary' | 'ucs2' | 'ucs-2' | 'utf-8';
6
-
7
- const VALID_ENCODINGS = ['utf8', 'ascii', 'latin1', 'binary', 'base64', 'base64url', 'hex', 'ucs2', 'utf16le'];
8
-
9
- /**
10
- * Normalize an encoding string to a canonical encoding value.
11
- * Returns 'utf8' as default for undefined/null/empty input.
12
- */
13
- export function normalizeEncoding(enc?: string): Encoding {
14
- if (!enc || enc === 'utf8' || enc === 'utf-8') return 'utf8';
15
- const lower = ('' + enc).toLowerCase().replace(/-/g, '');
16
- switch (lower) {
17
- case 'utf8': return 'utf8';
18
- case 'ascii': return 'ascii';
19
- case 'latin1': case 'binary': return 'latin1';
20
- case 'base64': return 'base64';
21
- case 'base64url': return 'base64url';
22
- case 'hex': return 'hex';
23
- case 'ucs2': case 'utf16le': return 'utf16le';
24
- default: return 'utf8';
25
- }
26
- }
27
-
28
- /**
29
- * Check that an encoding string is valid. Throws TypeError if not.
30
- */
31
- export function checkEncoding(encoding: string): void {
32
- const lower = ('' + encoding).toLowerCase().replace(/-/g, '');
33
- if (!VALID_ENCODINGS.includes(lower)) {
34
- throw new TypeError(`Unknown encoding: ${encoding}`);
35
- }
36
- }
package/src/error.ts DELETED
@@ -1,38 +0,0 @@
1
- /**
2
- * Defines the static Error.captureStackTrace method,
3
- * this is not present in SpiderMonkey because it comes from V8
4
- * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#static_methods
5
- * @see https://nodejs.org/dist/latest-v18.x/docs/api/errors.html#errorcapturestacktracetargetobject-constructoropt
6
- */
7
- export const initErrorV8Methods = (ErrorConstructor: typeof Error) => {
8
- // See https://nodejs.org/dist/latest-v18.x/docs/api/errors.html#errorcapturestacktracetargetobject-constructoropt
9
- if (!(Error as any).captureStackTrace) {
10
- /**
11
- * A non-standard V8 function.
12
- * Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.
13
- * @param targetObject
14
- * @param constructorOpt
15
- */
16
- (Error as any).captureStackTrace = function(targetObject: object, constructorOpt?: Function) {
17
- const container = new Error();
18
-
19
- const target = constructorOpt || targetObject;
20
-
21
- Object.defineProperty(target, 'stack', {
22
- configurable: true,
23
- get: function getStack() {
24
- var stack = container.stack;
25
-
26
- Object.defineProperty(this, 'stack', {
27
- value: stack
28
- });
29
-
30
- return stack;
31
- }
32
- });
33
- }
34
- }
35
-
36
- // TODO Error.stackTraceLimit()
37
- // TODO Error.prepareStackTrace()
38
- }
package/src/file.ts DELETED
@@ -1,12 +0,0 @@
1
- import GLib from '@girs/glib-2.0';
2
-
3
- const byteArray = imports.byteArray;
4
-
5
- export const readJSON = (path: string) => {
6
- const [ok, contents] = GLib.file_get_contents(path);
7
- if (ok) {
8
- const map = JSON.parse(byteArray.toString(contents));
9
- return map;
10
- }
11
- throw new Error(`Error on require "${path}"`);
12
- }
package/src/fs.ts DELETED
@@ -1,24 +0,0 @@
1
- import Gio from '@girs/gio-2.0';
2
- import GioUnix from '@girs/giounix-2.0';
3
- /** Check if a file descriptor exists */
4
- export const existsFD = (fd: number) => {
5
- try {
6
- let stream = GioUnix.InputStream.new(fd, false);
7
- stream.close(null);
8
- // File descriptor 12345 exists
9
- return true
10
- } catch (error) {
11
- // File descriptor 12345 does not exist
12
- return false
13
- }
14
- }
15
-
16
- export function existsSync(path: string) {
17
- // TODO: accept buffer and URL too
18
- if (typeof path !== 'string' || path === '') {
19
- return false;
20
- }
21
-
22
- const file = Gio.File.new_for_path(path);
23
- return file.query_exists(null);
24
- }
package/src/gio-errors.ts DELETED
@@ -1,156 +0,0 @@
1
- // Shared Gio.IOErrorEnum → Node.js error code mapping.
2
- // Used by fs, net, http, dns, child-process, and other packages that wrap Gio operations.
3
- //
4
- // The enum values are numeric constants from GLib — we use numbers directly
5
- // to avoid importing Gio just for error handling (keeps this usable in Node.js tests too).
6
-
7
- /** Map from Gio.IOErrorEnum numeric values to Node.js error code strings. */
8
- export const GIO_ERROR_TO_NODE: Record<number, string> = {
9
- 0: 'EIO', // FAILED
10
- 1: 'ENOENT', // NOT_FOUND
11
- 2: 'EEXIST', // EXISTS
12
- 3: 'EISDIR', // IS_DIRECTORY
13
- 4: 'ENOTDIR', // NOT_DIRECTORY
14
- 5: 'ENOTEMPTY', // NOT_EMPTY
15
- 6: 'ENOENT', // NOT_REGULAR_FILE
16
- 7: 'ENFILE', // TOO_MANY_OPEN_FILES
17
- 9: 'EACCES', // NOT_MOUNTABLE_FILE
18
- 10: 'ENFILE', // FILENAME_TOO_LONG
19
- 11: 'EINVAL', // INVALID_FILENAME
20
- 12: 'ELOOP', // TOO_MANY_LINKS
21
- 13: 'ENOSPC', // NO_SPACE
22
- 14: 'EACCES', // PERMISSION_DENIED
23
- 17: 'ELOOP', // TOO_MANY_LINKS (duplicate guard)
24
- 19: 'ENOSPC', // NO_SPACE (duplicate guard)
25
- 20: 'ENOTSUP', // NOT_SUPPORTED
26
- 22: 'EMFILE', // TOO_MANY_OPEN_FILES
27
- 24: 'EROFS', // READ_ONLY
28
- 25: 'ECANCELED', // CANCELLED
29
- 26: 'EBUSY', // BUSY
30
- 27: 'ETIMEDOUT', // TIMED_OUT
31
- 28: 'EHOSTUNREACH', // HOST_NOT_FOUND (was WOULD_BLOCK)
32
- 30: 'EHOSTUNREACH', // HOST_NOT_FOUND
33
- 31: 'ENETUNREACH', // NETWORK_UNREACHABLE
34
- 32: 'ECONNREFUSED', // CONNECTION_REFUSED (legacy value)
35
- 33: 'EADDRINUSE', // ADDRESS_IN_USE
36
- 34: 'ECONNRESET', // CONNECTION_CLOSED (mapped to reset)
37
- 36: 'EPIPE', // BROKEN_PIPE
38
- 38: 'ENETUNREACH', // NETWORK_UNREACHABLE (actual GJS value)
39
- 39: 'ECONNREFUSED', // CONNECTION_REFUSED (actual GJS value)
40
- 40: 'ECONNREFUSED', // PROXY_FAILED
41
- 41: 'EACCES', // PROXY_AUTH_FAILED
42
- 44: 'ECONNRESET', // CONNECTION_CLOSED (actual GJS value)
43
- 46: 'EMSGSIZE', // MESSAGE_TOO_LARGE
44
- };
45
-
46
- export interface NodeErrorDetails {
47
- path?: string;
48
- dest?: string;
49
- address?: string;
50
- port?: number;
51
- hostname?: string;
52
- }
53
-
54
- /** Node.js-style ErrnoException (defined locally to avoid @types/node dependency). */
55
- export interface ErrnoException extends Error {
56
- errno?: number;
57
- code?: string;
58
- path?: string;
59
- syscall?: string;
60
- address?: string;
61
- port?: number;
62
- hostname?: string;
63
- }
64
-
65
- /**
66
- * Create a Node.js-style ErrnoException from a Gio error.
67
- * Works for fs, net, dns, child-process, and other modules.
68
- */
69
- export function createNodeError(
70
- err: unknown,
71
- syscall: string,
72
- details?: NodeErrorDetails
73
- ): ErrnoException {
74
- const errObj = err as { code?: number; message?: string } | null | undefined;
75
- const code = GIO_ERROR_TO_NODE[errObj?.code ?? -1] || 'EIO';
76
-
77
- let msg = `${code}: ${errObj?.message || 'unknown error'}, ${syscall}`;
78
- if (details?.path) msg += ` '${details.path}'`;
79
- if (details?.dest) msg += ` -> '${details.dest}'`;
80
- if (details?.address) msg += ` ${details.address}`;
81
- if (details?.port != null) msg += `:${details.port}`;
82
-
83
- const error = new Error(msg) as ErrnoException;
84
- error.code = code;
85
- error.syscall = syscall;
86
- error.errno = -(errObj?.code || 0);
87
-
88
- if (details?.path) error.path = details.path;
89
- if (details?.address) error.address = details.address;
90
- if (details?.port != null) error.port = details.port;
91
-
92
- return error;
93
- }
94
-
95
- /**
96
- * Check if a Gio error is a "not found" error.
97
- */
98
- export function isNotFoundError(err: unknown): boolean {
99
- const errObj = err as { code?: number | string } | null | undefined;
100
- return errObj?.code === 1 || errObj?.code === 'ENOENT';
101
- }
102
-
103
- /**
104
- * Map from GLib.FileError numeric values to Node.js error code strings.
105
- * Distinct from Gio.IOErrorEnum — GLib.IOChannel.new_file() and some other
106
- * low-level GLib APIs throw GLib.FileError (domain "g-file-error"), which
107
- * has different numeric values than Gio.IOErrorEnum (domain "g-io-error-quark").
108
- */
109
- export const GLIB_FILE_ERROR_TO_NODE: Record<number, string> = {
110
- 0: 'EEXIST',
111
- 1: 'EISDIR',
112
- 2: 'EACCES',
113
- 3: 'ENAMETOOLONG',
114
- 4: 'ENOENT',
115
- 5: 'ENOTDIR',
116
- 6: 'ENXIO',
117
- 7: 'ENODEV',
118
- 8: 'EROFS',
119
- 11: 'ELOOP',
120
- 12: 'ENOSPC',
121
- 13: 'ENOMEM',
122
- 14: 'EMFILE',
123
- 15: 'ENFILE',
124
- 16: 'EBADF',
125
- 17: 'EINVAL',
126
- 18: 'EPIPE',
127
- 21: 'EIO',
128
- 22: 'EPERM',
129
- 24: 'EIO',
130
- };
131
-
132
- /**
133
- * Map a GLib.FileError to a Node.js-style ErrnoException. Counterpart to
134
- * `createNodeError` for the Gio.IOErrorEnum case; kept separate because the
135
- * enum domains differ.
136
- */
137
- export function createGLibFileError(
138
- err: unknown,
139
- syscall: string,
140
- details?: NodeErrorDetails,
141
- ): ErrnoException {
142
- const errObj = err as { code?: number; message?: string } | null | undefined;
143
- const code = GLIB_FILE_ERROR_TO_NODE[errObj?.code ?? -1] ?? 'EIO';
144
-
145
- let msg = `${code}: ${errObj?.message || 'unknown error'}, ${syscall}`;
146
- if (details?.path) msg += ` '${details.path}'`;
147
- if (details?.dest) msg += ` -> '${details.dest}'`;
148
-
149
- const error = new Error(msg) as ErrnoException;
150
- error.code = code;
151
- error.syscall = syscall;
152
- error.errno = -(errObj?.code || 0);
153
- if (details?.path) error.path = details.path;
154
-
155
- return error;
156
- }
package/src/gio.ts DELETED
@@ -1,67 +0,0 @@
1
- import Gio from '@girs/gio-2.0';
2
- import GLib from '@girs/glib-2.0';
3
-
4
- const byteArray = imports.byteArray;
5
-
6
- /**
7
- * Generic promise wrapper for Gio async/finish method pairs.
8
- *
9
- * Example:
10
- * const stream = await gioAsync<Gio.InputStream>(session, 'send_async', 'send_finish', msg, priority, null);
11
- */
12
- export function gioAsync<T>(
13
- obj: any,
14
- asyncMethod: string,
15
- finishMethod: string,
16
- ...args: any[]
17
- ): Promise<T> {
18
- return new Promise<T>((resolve, reject) => {
19
- obj[asyncMethod](...args, (_self: any, asyncRes: Gio.AsyncResult) => {
20
- try {
21
- resolve(obj[finishMethod](asyncRes));
22
- } catch (error) {
23
- reject(error);
24
- }
25
- });
26
- });
27
- }
28
-
29
- /**
30
- * Promise wrapper around `Gio.InputStream.read_bytes_async` / `read_bytes_finish`.
31
- * Returns a `Uint8Array` or `null` if the end of the stream is reached.
32
- */
33
- export async function readBytesAsync(
34
- inputStream: Gio.InputStream,
35
- count = 4096,
36
- ioPriority = GLib.PRIORITY_DEFAULT,
37
- cancellable: Gio.Cancellable | null = null
38
- ): Promise<Uint8Array | null> {
39
- return new Promise<Uint8Array | null>((resolve, reject) => {
40
- inputStream.read_bytes_async(count, ioPriority, cancellable, (_self, asyncRes) => {
41
- try {
42
- const res = inputStream.read_bytes_finish(asyncRes);
43
- if (res.get_size() === 0) {
44
- return resolve(null);
45
- }
46
- return resolve(byteArray.fromGBytes(res));
47
- } catch (error) {
48
- reject(error);
49
- }
50
- });
51
- });
52
- }
53
-
54
- /**
55
- * Async generator that yields `Uint8Array` chunks from a `Gio.InputStream`.
56
- */
57
- export async function* inputStreamAsyncIterator(
58
- inputStream: Gio.InputStream,
59
- count = 4096,
60
- ioPriority = GLib.PRIORITY_DEFAULT,
61
- cancellable: Gio.Cancellable | null = null
62
- ): AsyncGenerator<Uint8Array> {
63
- let chunk: Uint8Array | null;
64
- while ((chunk = await readBytesAsync(inputStream, count, ioPriority, cancellable)) !== null) {
65
- yield chunk;
66
- }
67
- }
package/src/globals.ts DELETED
@@ -1,13 +0,0 @@
1
- // Shared utility for registering global polyfills.
2
- // Used by web packages (abort-controller, dom-exception, streams, webcrypto, etc.)
3
- // to consistently register globals only when they're missing.
4
-
5
- /**
6
- * Register a value as a global property if it doesn't already exist.
7
- * This is a no-op in environments where the global is already defined (e.g. Node.js).
8
- */
9
- export function registerGlobal(name: string, value: unknown): void {
10
- if (typeof (globalThis as any)[name] === 'undefined') {
11
- (globalThis as any)[name] = value;
12
- }
13
- }
package/src/index.ts DELETED
@@ -1,18 +0,0 @@
1
- export * from './callable.js';
2
- export * from './base64.js';
3
- export * from './byte-array.js';
4
- export * from './cli.js';
5
- export * from './defer.js';
6
- export * from './encoding.js';
7
- export * from './globals.js';
8
- export * from './error.js';
9
- export * from './file.js';
10
- export * from './fs.js';
11
- export * from './gio.js';
12
- export * from './gio-errors.js';
13
- export * from './message.js';
14
- export * from './microtask.js';
15
- export * from './next-tick.js';
16
- export * from './path.js';
17
- export * from './structured-clone.js';
18
- export * from './main-loop.js';
package/src/log.spec.ts DELETED
@@ -1,32 +0,0 @@
1
- import { describe, it, assert, spy } from '@gjsify/unit';
2
- // import { logSignals } from '@gjsify/utils';
3
- // import type { StructuredLogData } from '@gjsify/utils';
4
-
5
- const createUncaughtException = async () => {
6
- throw new Error("top level error");
7
- }
8
-
9
- const sleep = (ms: number) => {
10
- return new Promise(resolve => setTimeout(resolve, ms))
11
- }
12
-
13
- export default async () => {
14
- await describe('logSignals', async () => {
15
- // TODO: Fix this test
16
-
17
- // await it("should emit an uncaughtException event on a top level throw", async () => {
18
- // const onUnhandledRejection = spy((_self, _data: StructuredLogData, _promiseData) => {});
19
-
20
- // const signalHandlerId = logSignals.connect("unhandledRejection", onUnhandledRejection);
21
-
22
- // createUncaughtException();
23
-
24
- // await sleep(10);
25
-
26
- // logSignals.disconnect(signalHandlerId)
27
-
28
- // assert.strictEqual(onUnhandledRejection.calls.length, 1, "onUnhandledRejection should be called.")
29
- // // assert.strictEqual(onUnhandledRejection.calls[0].arguments[0], error)
30
- // })
31
- });
32
- }