@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/LICENSE +26 -0
- package/README.md +220 -0
- package/binding.gyp +34 -0
- package/gi.d.ts +28 -0
- package/gi.js +256 -0
- package/globals.d.ts +66 -0
- package/globals.js +140 -0
- package/index.d.ts +268 -0
- package/index.js +261 -0
- package/package.json +63 -0
- package/src/addon.cc +2110 -0
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;
|