@gjsify/node-gi 0.13.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/globals.js ADDED
@@ -0,0 +1,140 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // @gjsify/node-gi/globals — seed GJS's ambient globals on Node.
3
+ //
4
+ // GJS source relies on a handful of globals that exist implicitly under gjs:
5
+ // `print` / `printerr` / `log` / `logError`, the `ARGV` array, and the legacy
6
+ // `imports` object (`imports.gi.Gtk`, `imports.gi.versions`, `imports.system`,
7
+ // `imports.gettext`, …). On Node these don't exist, so importing this module
8
+ // (a side effect) installs Node-backed equivalents that route through the same
9
+ // node-gi backend `gi://` uses. The gjsify `--app node` build injects this for
10
+ // any bundle that references those globals; it is also importable directly.
11
+ //
12
+ // Reference: GJS's global definitions (gjs/modules/{print,system,gettext}). The
13
+ // legacy `imports.*` namespace mirrors gjs/modules/esm/gi.js's require shape.
14
+ import { requireGi } from './gi.js';
15
+
16
+ // GJS stringifies each argument with String() and joins with a space (no
17
+ // util.inspect object formatting) — match that for fidelity.
18
+ function gjsFormat(args) {
19
+ return args.map((a) => String(a)).join(' ');
20
+ }
21
+
22
+ /**
23
+ * Install the GJS ambient globals on `globalThis` (idempotent — each global is
24
+ * only defined if absent, so it never clobbers a host that already provides it).
25
+ */
26
+ export function installGjsGlobals() {
27
+ const g = globalThis;
28
+
29
+ if (typeof g.print === 'undefined') {
30
+ g.print = (...args) => console.log(gjsFormat(args));
31
+ }
32
+ if (typeof g.printerr === 'undefined') {
33
+ g.printerr = (...args) => console.error(gjsFormat(args));
34
+ }
35
+ if (typeof g.log === 'undefined') {
36
+ // GJS `log` writes to the GLib structured log (stderr/journal).
37
+ g.log = (...args) => console.error(gjsFormat(args));
38
+ }
39
+ if (typeof g.logError === 'undefined') {
40
+ g.logError = (error, prefix) => {
41
+ const head = prefix ? `${prefix}: ` : '';
42
+ const body = error && error.stack ? error.stack : String(error);
43
+ console.error(head + body);
44
+ };
45
+ }
46
+ if (typeof g.ARGV === 'undefined') {
47
+ // GJS ARGV excludes the interpreter + the script path (Node's argv[0]+[1]).
48
+ g.ARGV = (typeof process !== 'undefined' && Array.isArray(process.argv))
49
+ ? process.argv.slice(2)
50
+ : [];
51
+ }
52
+
53
+ if (typeof g.imports === 'undefined') {
54
+ g.imports = makeImports();
55
+ }
56
+
57
+ return g.imports;
58
+ }
59
+
60
+ // Build the legacy `imports` object. `imports.gi.<Ns>` resolves a namespace via
61
+ // the node-gi backend, honouring a version pinned in `imports.gi.versions.<Ns>`
62
+ // (which GJS code sets before the first access).
63
+ function makeImports() {
64
+ const giVersions = Object.create(null);
65
+ const giCache = new Map();
66
+ const gi = new Proxy(
67
+ { versions: giVersions },
68
+ {
69
+ get(target, name) {
70
+ if (name === 'versions') return giVersions;
71
+ if (typeof name !== 'string') return target[name];
72
+ if (giCache.has(name)) return giCache.get(name);
73
+ const ns = requireGi(name, giVersions[name]);
74
+ giCache.set(name, ns);
75
+ return ns;
76
+ },
77
+ has(_target, name) {
78
+ return name === 'versions' || typeof name === 'string';
79
+ },
80
+ },
81
+ );
82
+
83
+ // Minimal `imports.system` — the most-used members (exit, gc, the program
84
+ // identity). Backed by Node's process where there is an equivalent.
85
+ const system = {
86
+ exit(code) {
87
+ if (typeof process !== 'undefined') process.exit(code ?? 0);
88
+ },
89
+ gc() {
90
+ if (typeof globalThis.gc === 'function') globalThis.gc();
91
+ },
92
+ get programInvocationName() {
93
+ return (typeof process !== 'undefined' && process.argv[1]) || '';
94
+ },
95
+ get programPath() {
96
+ return (typeof process !== 'undefined' && process.argv[1]) || null;
97
+ },
98
+ version: 0,
99
+ addressOf() {
100
+ return '0x0';
101
+ },
102
+ refcount() {
103
+ return 0;
104
+ },
105
+ breakpoint() {},
106
+ dumpHeap() {},
107
+ dumpMemoryInfo() {},
108
+ };
109
+
110
+ // Minimal `imports.gettext` — a no-translation passthrough (the strings are
111
+ // returned untranslated, which is the correct fallback when no catalog is
112
+ // bound). Mirrors the surface GJS apps call at module load.
113
+ const identity = (s) => s;
114
+ const gettext = {
115
+ gettext: identity,
116
+ dgettext: (_domain, s) => s,
117
+ dcgettext: (_domain, s) => s,
118
+ ngettext: (s, p, n) => (n === 1 ? s : p),
119
+ dngettext: (_domain, s, p, n) => (n === 1 ? s : p),
120
+ pgettext: (_ctx, s) => s,
121
+ dpgettext: (_domain, _ctx, s) => s,
122
+ domain: (_domain) => ({
123
+ gettext: identity,
124
+ ngettext: (s, p, n) => (n === 1 ? s : p),
125
+ pgettext: (_ctx, s) => s,
126
+ }),
127
+ setlocale: () => null,
128
+ bindtextdomain: () => null,
129
+ textdomain: () => null,
130
+ bindtextdomainCodeset: () => null,
131
+ LocaleCategory: { ALL: 6, COLLATE: 3, CTYPE: 0, MESSAGES: 5, MONETARY: 4, NUMERIC: 1, TIME: 2 },
132
+ };
133
+
134
+ return { gi, system, gettext, versions: Object.create(null) };
135
+ }
136
+
137
+ // Side effect on import: seed the globals.
138
+ installGjsGlobals();
139
+
140
+ export default installGjsGlobals;
package/index.d.ts ADDED
@@ -0,0 +1,268 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // @gjsify/node-gi — public type surface (milestone 1: headless-core scaffold).
3
+
4
+ /** Result of requiring a GObject-Introspection namespace. */
5
+ export interface RequiredNamespace {
6
+ /** The namespace name, e.g. "GLib". */
7
+ namespace: string;
8
+ /** The resolved typelib version, e.g. "2.0". */
9
+ version: string;
10
+ /** Number of top-level introspection infos in the namespace. */
11
+ infoCount: number;
12
+ }
13
+
14
+ /**
15
+ * Require a GObject-Introspection namespace and report its resolved version and
16
+ * top-level info count. The Node twin of GJS's `gi://` / `imports.gi` load step.
17
+ */
18
+ export function requireNamespace(namespace: string, version?: string): RequiredNamespace;
19
+
20
+ /** Enumerate the top-level introspection-info names of an already-required namespace. */
21
+ export function listInfoNames(namespace: string): string[];
22
+
23
+ /** The introspection kind of a top-level namespace member. */
24
+ export type InfoKind =
25
+ | 'function'
26
+ | 'object'
27
+ | 'interface'
28
+ | 'struct'
29
+ | 'union'
30
+ | 'enum'
31
+ | 'flags'
32
+ | 'constant'
33
+ | 'callback'
34
+ | 'other';
35
+
36
+ /**
37
+ * Classify a top-level namespace member so the L1 wrapper can decide how to
38
+ * surface it (class vs function vs enum vs constant). Returns `null` when the
39
+ * name is not found in the namespace.
40
+ */
41
+ export function findInfo(namespace: string, name: string): { kind: InfoKind } | null;
42
+
43
+ /** Read a namespace-level GI constant (e.g. `GLib.PRIORITY_DEFAULT`). */
44
+ export function getConstantValue(namespace: string, name: string): unknown;
45
+
46
+ /**
47
+ * Enumerate an enum/flags type's members as `{ rawGiName: number }`. The L1
48
+ * wrapper re-keys them GJS-style (UPPER_CASE, `-` → `_`).
49
+ */
50
+ export function getEnumValues(namespace: string, name: string): Record<string, number>;
51
+
52
+ /** Prepend a directory to the GIRepository typelib search path. */
53
+ export function prependSearchPath(path: string): void;
54
+
55
+ /**
56
+ * Invoke a namespace-level GObject-Introspection function (not an instance
57
+ * method) with IN-only primitive/string arguments. Returns the marshalled
58
+ * return value. Milestone 1: numbers, booleans and strings.
59
+ */
60
+ export function callFunction(namespace: string, functionName: string, args?: unknown[]): unknown;
61
+
62
+ /**
63
+ * Invoke an instance method on a GObject handle with IN-only
64
+ * primitive/string/object/enum args. The method is resolved against the
65
+ * instance's introspection type (own + implemented-interface methods, then up
66
+ * the parent chain). The Node twin of `obj.method(...)`.
67
+ */
68
+ export function callMethod(handle: GObjectHandle, methodName: string, args?: unknown[]): unknown;
69
+
70
+ /**
71
+ * Invoke a type-level constructor/static function (e.g. `Gio.File.new_for_path`,
72
+ * `Gtk.Label.new`) — a function found on a type but taking no instance. The Node
73
+ * twin of `Ns.Class.method(...)`.
74
+ */
75
+ export function callStaticMethod(
76
+ namespace: string,
77
+ typeName: string,
78
+ methodName: string,
79
+ args?: unknown[],
80
+ ): unknown;
81
+
82
+ /**
83
+ * Opaque handle to a live GObject instance, owned by node-gi and released when
84
+ * the handle is garbage-collected. Pass it back to {@link getProperty} /
85
+ * {@link setProperty} / {@link getTypeName}.
86
+ */
87
+ export type GObjectHandle = { readonly __nodeGiGObject: unique symbol };
88
+
89
+ /**
90
+ * Construct a GObject of `namespace.typeName` with optional construct/settable
91
+ * properties. Milestone 1: fundamental-typed properties (numbers, booleans,
92
+ * strings, enums/flags).
93
+ */
94
+ export function newObject(
95
+ namespace: string,
96
+ typeName: string,
97
+ props?: Record<string, unknown>,
98
+ ): GObjectHandle;
99
+
100
+ /**
101
+ * Opaque handle to a registered GType (from {@link registerClass}). Pass it to
102
+ * {@link constructType}.
103
+ */
104
+ export type TypeHandle = { readonly __nodeGiGType: unique symbol };
105
+
106
+ /** A custom GObject property declaration for {@link registerClass}. */
107
+ export interface PropertySpec {
108
+ /** Property name (canonical, e.g. "my-prop"). */
109
+ name: string;
110
+ /** Value type. */
111
+ type: 'string' | 'boolean' | 'int' | 'uint' | 'int64' | 'uint64' | 'double' | 'float';
112
+ /** `GParamFlags` bitfield (default `G_PARAM_READWRITE`). */
113
+ flags?: number;
114
+ /** Default value (type-appropriate). */
115
+ default?: string | number | boolean;
116
+ /** Minimum (numeric types). */
117
+ minimum?: number;
118
+ /** Maximum (numeric types). */
119
+ maximum?: number;
120
+ }
121
+
122
+ /** A custom GObject signal declaration for {@link registerClass}. */
123
+ export interface SignalSpec {
124
+ /** Signal name (e.g. "my-signal"). */
125
+ name: string;
126
+ /** Parameter types (same vocabulary as {@link PropertySpec.type}, plus "object"). */
127
+ paramTypes?: string[];
128
+ /** Return type ("void" by default). */
129
+ returnType?: string;
130
+ /** `GSignalFlags` bitfield (default `G_SIGNAL_RUN_LAST`). */
131
+ flags?: number;
132
+ }
133
+
134
+ /**
135
+ * Custom vfunc overrides for a {@link registerClass} subtype: a map from a parent
136
+ * GObject vfunc name (e.g. `"constructed"`) to the JS function that overrides it.
137
+ * The override is invoked as a method on the instance — `this` is the GObject
138
+ * handle — with the vfunc's declared arguments as JS arguments, and its return is
139
+ * marshalled back to C. Chain-up to the parent vfunc lands in a later milestone,
140
+ * so an override fully replaces the inherited implementation.
141
+ */
142
+ export type VFuncMap = Record<string, (this: GObjectHandle, ...args: unknown[]) => unknown>;
143
+
144
+ /** Custom properties, signals + vfunc overrides installed on a {@link registerClass} subtype. */
145
+ export interface RegisterClassOptions {
146
+ properties?: PropertySpec[];
147
+ signals?: SignalSpec[];
148
+ vfuncs?: VFuncMap;
149
+ }
150
+
151
+ /**
152
+ * Register a new GObject subclass of `parentNamespace.parentTypeName` named
153
+ * `name`, inheriting the parent's class/instance layout, and return an opaque
154
+ * type handle. `options` installs custom properties (backed by a per-instance
155
+ * value store), signals, and vfunc overrides (an ffi closure written into the new
156
+ * type's class vtable) in the new type's `class_init` — the Node twin of (the
157
+ * engine half of) GJS's `GObject.registerClass`. vfunc chain-up to the parent
158
+ * implementation lands in a later milestone.
159
+ */
160
+ export function registerClass(
161
+ name: string,
162
+ parentNamespace: string,
163
+ parentTypeName: string,
164
+ options?: RegisterClassOptions,
165
+ ): TypeHandle;
166
+
167
+ /**
168
+ * Construct a GObject of a registered type handle (from {@link registerClass})
169
+ * with optional construct/settable properties.
170
+ */
171
+ export function constructType(typeHandle: TypeHandle, props?: Record<string, unknown>): GObjectHandle;
172
+
173
+ /** Read a GObject property. */
174
+ export function getProperty(handle: GObjectHandle, name: string): unknown;
175
+
176
+ /** Write a GObject property. */
177
+ export function setProperty(handle: GObjectHandle, name: string, value: unknown): void;
178
+
179
+ /**
180
+ * Whether the instance's type has a GObject property by this name (kebab- or
181
+ * snake-case). The L1 wrapper uses it to route `obj.foo` to a property read vs
182
+ * an `obj.foo()` method call.
183
+ */
184
+ export function hasProperty(handle: GObjectHandle, name: string): boolean;
185
+
186
+ /** The runtime GType name of a GObject handle (e.g. "GSimpleAction"). */
187
+ export function getTypeName(handle: GObjectHandle): string;
188
+
189
+ /**
190
+ * Whether `value` is one of node-gi's GObject-instance handles (tag-checked, no
191
+ * dereference). Lets the L1 wrapper wrap object-typed return values for chaining
192
+ * without misclassifying a {@link TypeHandle}.
193
+ */
194
+ export function isGObjectHandle(value: unknown): boolean;
195
+
196
+ /**
197
+ * Opaque handle to a boxed/struct instance (e.g. a GMainLoop), owned by node-gi
198
+ * and released when garbage-collected (a fully-owned boxed is `g_boxed_free`d).
199
+ * Pass it to {@link callBoxedMethod}.
200
+ */
201
+ export type BoxedHandle = { readonly __nodeGiBoxed: unique symbol };
202
+
203
+ /**
204
+ * Invoke an instance method on a boxed/struct handle (e.g. `mainLoop.run()` /
205
+ * `mainLoop.quit()`). The method is resolved against the boxed GType's
206
+ * introspection info and invoked with the boxed pointer as the instance.
207
+ */
208
+ export function callBoxedMethod(handle: BoxedHandle, methodName: string, args?: unknown[]): unknown;
209
+
210
+ /**
211
+ * Whether `value` is one of node-gi's boxed/struct handles (tag-checked, no
212
+ * dereference). The L1 wrapper uses it to wrap boxed return values with a
213
+ * method-routing proxy.
214
+ */
215
+ export function isBoxedHandle(value: unknown): boolean;
216
+
217
+ /**
218
+ * Attach the libuv-backed GSource to the default GLib main context so a blocking
219
+ * GLib main loop (`GLib.MainLoop.run()`, `Gio.Application.run()`) keeps Node's
220
+ * timers, promises and I/O alive — the Node twin of GJS running the GLib loop as
221
+ * the process loop. Idempotent and harmless until a GLib loop actually runs.
222
+ */
223
+ export function startMainLoop(): void;
224
+
225
+ /**
226
+ * Connect a JS callback to a GObject signal; returns a handler id. The callback
227
+ * receives the signal arguments (the emitter instance is not passed in this
228
+ * milestone).
229
+ */
230
+ export function connectSignal(
231
+ handle: GObjectHandle,
232
+ signalName: string,
233
+ callback: (...args: unknown[]) => unknown,
234
+ after?: boolean,
235
+ ): number;
236
+
237
+ /** Emit a signal; returns the signal's return value (undefined for void signals). */
238
+ export function emitSignal(handle: GObjectHandle, signalName: string, args?: unknown[]): unknown;
239
+
240
+ /** Disconnect a previously connected signal handler. */
241
+ export function disconnectSignal(handle: GObjectHandle, handlerId: number): void;
242
+
243
+ declare const native: {
244
+ requireNamespace: typeof requireNamespace;
245
+ listInfoNames: typeof listInfoNames;
246
+ findInfo: typeof findInfo;
247
+ getConstantValue: typeof getConstantValue;
248
+ getEnumValues: typeof getEnumValues;
249
+ prependSearchPath: typeof prependSearchPath;
250
+ callFunction: typeof callFunction;
251
+ callMethod: typeof callMethod;
252
+ callStaticMethod: typeof callStaticMethod;
253
+ newObject: typeof newObject;
254
+ registerClass: typeof registerClass;
255
+ constructType: typeof constructType;
256
+ getProperty: typeof getProperty;
257
+ setProperty: typeof setProperty;
258
+ hasProperty: typeof hasProperty;
259
+ getTypeName: typeof getTypeName;
260
+ isGObjectHandle: typeof isGObjectHandle;
261
+ callBoxedMethod: typeof callBoxedMethod;
262
+ isBoxedHandle: typeof isBoxedHandle;
263
+ startMainLoop: typeof startMainLoop;
264
+ connectSignal: typeof connectSignal;
265
+ emitSignal: typeof emitSignal;
266
+ disconnectSignal: typeof disconnectSignal;
267
+ };
268
+ export default native;
package/index.js ADDED
@@ -0,0 +1,261 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // @gjsify/node-gi — thin ESM loader for the native GObject-Introspection addon.
3
+ //
4
+ // Reference: refs/node-gtk (romgrk, MIT). Hand-authored loader shim — a native
5
+ // package's JS entry is a loader, not a tsc artifact, and the repo ignores
6
+ // `lib/`, so it lives at the package root. The native binary is built by
7
+ // node-gyp into build/{Release,Debug}.
8
+ import { createRequire } from 'node:module';
9
+ import { fileURLToPath } from 'node:url';
10
+ import { dirname, join } from 'node:path';
11
+ import { existsSync } from 'node:fs';
12
+
13
+ const require = createRequire(import.meta.url);
14
+ const here = dirname(fileURLToPath(import.meta.url)); // package root
15
+
16
+ function loadNative() {
17
+ const candidates = [
18
+ join(here, 'build', 'Release', 'node_gi.node'),
19
+ join(here, 'build', 'Debug', 'node_gi.node'),
20
+ ];
21
+ for (const candidate of candidates) {
22
+ if (existsSync(candidate)) return require(candidate);
23
+ }
24
+ throw new Error(
25
+ '@gjsify/node-gi: native addon not built. Run `node-gyp rebuild` in ' +
26
+ here +
27
+ ' (requires a C++ toolchain and the girepository-2.0 / glib-2.0 development headers).',
28
+ );
29
+ }
30
+
31
+ const native = loadNative();
32
+
33
+ /**
34
+ * Require a GObject-Introspection namespace and report its resolved version
35
+ * and top-level info count. The Node twin of GJS's gi:// / imports.gi load step.
36
+ * @param {string} namespace e.g. "GLib"
37
+ * @param {string} [version] e.g. "2.0" (omit to let GIRepository resolve)
38
+ * @returns {{ namespace: string, version: string, infoCount: number }}
39
+ */
40
+ export const requireNamespace = native.requireNamespace;
41
+
42
+ /**
43
+ * Enumerate the top-level introspection-info names of an already-required namespace.
44
+ * @param {string} namespace
45
+ * @returns {string[]}
46
+ */
47
+ export const listInfoNames = native.listInfoNames;
48
+
49
+ /**
50
+ * Classify a top-level namespace member (so the L1 wrapper knows whether it is a
51
+ * constructible class, a callable function, an enum, a constant, …). Returns
52
+ * `null` when the name is not found.
53
+ * @param {string} namespace
54
+ * @param {string} name
55
+ * @returns {{ kind: 'function'|'object'|'interface'|'struct'|'union'|'enum'|'flags'|'constant'|'callback'|'other' } | null}
56
+ */
57
+ export const findInfo = native.findInfo;
58
+
59
+ /**
60
+ * Read a namespace-level GI constant (e.g. `GLib.PRIORITY_DEFAULT`) and marshal
61
+ * it to a JS value.
62
+ * @param {string} namespace
63
+ * @param {string} name
64
+ * @returns {unknown}
65
+ */
66
+ export const getConstantValue = native.getConstantValue;
67
+
68
+ /**
69
+ * Enumerate an enum/flags type's members as `{ rawGiName: number }` (the L1
70
+ * wrapper re-keys them GJS-style: UPPER_CASE with `-` → `_`).
71
+ * @param {string} namespace
72
+ * @param {string} name
73
+ * @returns {Record<string, number>}
74
+ */
75
+ export const getEnumValues = native.getEnumValues;
76
+
77
+ /**
78
+ * Prepend a directory to the GIRepository typelib search path (call before
79
+ * requireNamespace for non-system typelibs).
80
+ * @param {string} path
81
+ * @returns {void}
82
+ */
83
+ export const prependSearchPath = native.prependSearchPath;
84
+
85
+ /**
86
+ * Invoke a namespace-level GObject-Introspection function (not an instance
87
+ * method) with IN-only primitive/string arguments. The first marshalling slice;
88
+ * instance methods, OUT/INOUT params and compound types follow.
89
+ * @param {string} namespace e.g. "GLib"
90
+ * @param {string} functionName e.g. "get_host_name"
91
+ * @param {unknown[]} [args]
92
+ * @returns {unknown}
93
+ */
94
+ export const callFunction = native.callFunction;
95
+
96
+ /**
97
+ * Invoke an instance method on a GObject handle with IN-only
98
+ * primitive/string/object/enum args. The method is resolved against the
99
+ * instance's introspection type (own + implemented-interface methods, then up
100
+ * the parent chain) — the Node twin of `obj.method(...)`.
101
+ * @param {unknown} handle a handle from {@link newObject}
102
+ * @param {string} methodName GI method name, e.g. "get_name"
103
+ * @param {unknown[]} [args]
104
+ * @returns {unknown}
105
+ */
106
+ export const callMethod = native.callMethod;
107
+
108
+ /**
109
+ * Invoke a type-level constructor/static function (e.g. `Gio.File.new_for_path`,
110
+ * `Gtk.Label.new`) — a function found on a type but taking no instance. The Node
111
+ * twin of `Ns.Class.method(...)`.
112
+ * @param {string} namespace e.g. "Gio"
113
+ * @param {string} typeName e.g. "File"
114
+ * @param {string} methodName e.g. "new_for_path"
115
+ * @param {unknown[]} [args]
116
+ * @returns {unknown}
117
+ */
118
+ export const callStaticMethod = native.callStaticMethod;
119
+
120
+ /**
121
+ * Construct a GObject of `namespace.typeName` with optional construct/settable
122
+ * properties, returning an opaque handle owned by node-gi (released on GC).
123
+ * @param {string} namespace e.g. "Gio"
124
+ * @param {string} typeName e.g. "SimpleAction"
125
+ * @param {Record<string, unknown>} [props]
126
+ * @returns {unknown} opaque GObject handle
127
+ */
128
+ export const newObject = native.newObject;
129
+
130
+ /**
131
+ * Register a new GObject subclass of `parentNamespace.parentTypeName` named
132
+ * `name`, inheriting the parent's class/instance layout, and return an opaque
133
+ * type handle. Construct instances of it with {@link constructType}. The optional
134
+ * `options` installs custom properties (backed by a per-instance value store),
135
+ * signals, and vfunc overrides in the new type's `class_init` — the Node twin of
136
+ * (the engine half of) GJS's `GObject.registerClass`. A `vfuncs` entry maps a
137
+ * parent vfunc name (e.g. `constructed`) to a JS function that overrides it; the
138
+ * override runs as a method on the instance (`this` is the GObject handle). vfunc
139
+ * chain-up to the parent implementation lands in a later milestone.
140
+ * @param {string} name unique GType name, e.g. "MyAction"
141
+ * @param {string} parentNamespace e.g. "Gio"
142
+ * @param {string} parentTypeName e.g. "SimpleAction"
143
+ * @param {{ properties?: Array<{name:string,type:string,flags?:number,default?:unknown,minimum?:number,maximum?:number}>, signals?: Array<{name:string,paramTypes?:string[],returnType?:string,flags?:number}>, vfuncs?: Record<string, (...args: unknown[]) => unknown> }} [options]
144
+ * @returns {unknown} opaque type handle
145
+ */
146
+ export const registerClass = native.registerClass;
147
+
148
+ /**
149
+ * Construct a GObject of a registered type handle (from {@link registerClass})
150
+ * with optional construct/settable properties, returning an owned handle.
151
+ * @param {unknown} typeHandle a handle from {@link registerClass}
152
+ * @param {Record<string, unknown>} [props]
153
+ * @returns {unknown} opaque GObject handle
154
+ */
155
+ export const constructType = native.constructType;
156
+
157
+ /**
158
+ * Read a GObject property.
159
+ * @param {unknown} handle a handle from {@link newObject}
160
+ * @param {string} name property name (kebab- or snake-case as GObject expects)
161
+ * @returns {unknown}
162
+ */
163
+ export const getProperty = native.getProperty;
164
+
165
+ /**
166
+ * Write a GObject property.
167
+ * @param {unknown} handle a handle from {@link newObject}
168
+ * @param {string} name property name
169
+ * @param {unknown} value
170
+ * @returns {void}
171
+ */
172
+ export const setProperty = native.setProperty;
173
+
174
+ /**
175
+ * Whether the instance's type has a GObject property by this name (kebab- or
176
+ * snake-case). The L1 wrapper uses it to route `obj.foo` to a property read vs
177
+ * an `obj.foo()` method call.
178
+ * @param {unknown} handle
179
+ * @param {string} name
180
+ * @returns {boolean}
181
+ */
182
+ export const hasProperty = native.hasProperty;
183
+
184
+ /**
185
+ * The runtime GType name of a GObject handle (e.g. "GSimpleAction").
186
+ * @param {unknown} handle
187
+ * @returns {string}
188
+ */
189
+ export const getTypeName = native.getTypeName;
190
+
191
+ /**
192
+ * Whether `value` is one of node-gi's GObject-instance handles (tag-checked, no
193
+ * dereference). Lets the L1 wrapper wrap object-typed return values for chaining
194
+ * without misclassifying a registerClass type handle.
195
+ * @param {unknown} value
196
+ * @returns {boolean}
197
+ */
198
+ export const isGObjectHandle = native.isGObjectHandle;
199
+
200
+ /**
201
+ * Invoke an instance method on a boxed/struct handle (e.g. `mainLoop.run()` /
202
+ * `mainLoop.quit()`). The method is resolved against the boxed GType's
203
+ * introspection info and invoked with the boxed pointer as the instance.
204
+ * @param {unknown} handle a boxed handle (e.g. from `GLib.MainLoop.new(...)`)
205
+ * @param {string} methodName GI method name, e.g. "run"
206
+ * @param {unknown[]} [args]
207
+ * @returns {unknown}
208
+ */
209
+ export const callBoxedMethod = native.callBoxedMethod;
210
+
211
+ /**
212
+ * Whether `value` is one of node-gi's boxed/struct handles (tag-checked, no
213
+ * dereference). The L1 wrapper uses it to wrap boxed return values (GMainLoop,
214
+ * …) with a method-routing proxy.
215
+ * @param {unknown} value
216
+ * @returns {boolean}
217
+ */
218
+ export const isBoxedHandle = native.isBoxedHandle;
219
+
220
+ /**
221
+ * Attach the libuv-backed GSource to the default GLib main context so a blocking
222
+ * GLib main loop (`GLib.MainLoop.run()`, `Gio.Application.run()`) keeps Node's
223
+ * timers, promises and I/O alive — the Node twin of GJS running the GLib loop as
224
+ * the process loop. Idempotent and harmless until a GLib loop actually runs (it
225
+ * adds no libuv handle, so it neither keeps Node alive nor pumps libuv on its
226
+ * own). The L1 layer calls it once when a namespace is first required.
227
+ * @returns {void}
228
+ */
229
+ export const startMainLoop = native.startMainLoop;
230
+
231
+ /**
232
+ * Connect a JS callback to a GObject signal. Returns a handler id for
233
+ * {@link disconnectSignal}. The callback receives the signal arguments
234
+ * (the emitter instance is not passed in this milestone).
235
+ * @param {unknown} handle a handle from {@link newObject}
236
+ * @param {string} signalName
237
+ * @param {(...args: unknown[]) => unknown} callback
238
+ * @param {boolean} [after] connect in the "after" phase
239
+ * @returns {number} handler id
240
+ */
241
+ export const connectSignal = native.connectSignal;
242
+
243
+ /**
244
+ * Emit a signal on a GObject with optional arguments; returns the signal's
245
+ * return value (or undefined for void signals).
246
+ * @param {unknown} handle
247
+ * @param {string} signalName
248
+ * @param {unknown[]} [args]
249
+ * @returns {unknown}
250
+ */
251
+ export const emitSignal = native.emitSignal;
252
+
253
+ /**
254
+ * Disconnect a previously connected signal handler.
255
+ * @param {unknown} handle
256
+ * @param {number} handlerId from {@link connectSignal}
257
+ * @returns {void}
258
+ */
259
+ export const disconnectSignal = native.disconnectSignal;
260
+
261
+ export default native;