gestament 0.1.0 → 0.3.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 (86) hide show
  1. package/README.md +4 -6
  2. package/dist/displaySession.d.ts +18 -0
  3. package/dist/displaySession.d.ts.map +1 -0
  4. package/dist/element.d.ts +2 -2
  5. package/dist/errors-6gj5YuLw.cjs +36 -0
  6. package/dist/errors-6gj5YuLw.cjs.map +1 -0
  7. package/dist/errors-CCW4ATME.js +37 -0
  8. package/dist/errors-CCW4ATME.js.map +1 -0
  9. package/dist/errors.d.ts +2 -2
  10. package/dist/errors.d.ts.map +1 -1
  11. package/dist/generated/packageMetadata.d.ts +4 -4
  12. package/dist/gestament-config.d.ts +2 -2
  13. package/dist/gestament-launcher-driver.cjs +656 -0
  14. package/dist/gestament-launcher-driver.cjs.map +1 -0
  15. package/dist/gestament-launcher-driver.d.ts +13 -0
  16. package/dist/gestament-launcher-driver.d.ts.map +1 -0
  17. package/dist/gestament-launcher-driver.mjs +655 -0
  18. package/dist/gestament-launcher-driver.mjs.map +1 -0
  19. package/dist/gestament-tray-host.cjs +1 -1
  20. package/dist/gestament-tray-host.d.ts +2 -2
  21. package/dist/gestament-tray-host.mjs +1 -1
  22. package/dist/gestament-xvfb-pool-probe.cjs +29 -0
  23. package/dist/gestament-xvfb-pool-probe.cjs.map +1 -0
  24. package/dist/gestament-xvfb-pool-probe.d.ts +13 -0
  25. package/dist/gestament-xvfb-pool-probe.d.ts.map +1 -0
  26. package/dist/gestament-xvfb-pool-probe.mjs +28 -0
  27. package/dist/gestament-xvfb-pool-probe.mjs.map +1 -0
  28. package/dist/gestament-xvfb-worker.d.ts +2 -2
  29. package/dist/gestament-xvfb.cjs +8 -2
  30. package/dist/gestament-xvfb.cjs.map +1 -1
  31. package/dist/gestament-xvfb.d.ts +2 -2
  32. package/dist/gestament-xvfb.mjs +8 -2
  33. package/dist/gestament-xvfb.mjs.map +1 -1
  34. package/dist/index.cjs +4 -1074
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.ts +2 -2
  37. package/dist/index.mjs +4 -1074
  38. package/dist/index.mjs.map +1 -1
  39. package/dist/launchGtkApp-BIO_5Xjn.cjs +2479 -0
  40. package/dist/launchGtkApp-BIO_5Xjn.cjs.map +1 -0
  41. package/dist/launchGtkApp-qi1qm5G4.js +2479 -0
  42. package/dist/launchGtkApp-qi1qm5G4.js.map +1 -0
  43. package/dist/launchGtkApp.d.ts +2 -2
  44. package/dist/launchGtkApp.d.ts.map +1 -1
  45. package/dist/launcherDriverProtocol.d.ts +107 -0
  46. package/dist/launcherDriverProtocol.d.ts.map +1 -0
  47. package/dist/{native-BRnrsqMn.cjs → native-CBXaFWP-.cjs} +14 -40
  48. package/dist/native-CBXaFWP-.cjs.map +1 -0
  49. package/dist/{native-DAhTiLnf.js → native-CWdUmdty.js} +48 -74
  50. package/dist/native-CWdUmdty.js.map +1 -0
  51. package/dist/native.d.ts +4 -2
  52. package/dist/native.d.ts.map +1 -1
  53. package/dist/prerequisites-BuZST2Dy.cjs +15 -0
  54. package/dist/prerequisites-BuZST2Dy.cjs.map +1 -0
  55. package/dist/prerequisites-JB0SKPVd.js +16 -0
  56. package/dist/prerequisites-JB0SKPVd.js.map +1 -0
  57. package/dist/prerequisites.d.ts +23 -0
  58. package/dist/prerequisites.d.ts.map +1 -0
  59. package/dist/testing.cjs +3 -0
  60. package/dist/testing.cjs.map +1 -1
  61. package/dist/testing.d.ts +4 -2
  62. package/dist/testing.d.ts.map +1 -1
  63. package/dist/testing.mjs +4 -1
  64. package/dist/testing.mjs.map +1 -1
  65. package/dist/tray.d.ts +2 -2
  66. package/dist/types.d.ts +84 -2
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/wait-DV5gkXs8.js +113 -0
  69. package/dist/wait-DV5gkXs8.js.map +1 -0
  70. package/dist/wait-eOIz4nZm.cjs +112 -0
  71. package/dist/wait-eOIz4nZm.cjs.map +1 -0
  72. package/dist/wait.d.ts +67 -0
  73. package/dist/wait.d.ts.map +1 -0
  74. package/package.json +8 -8
  75. package/prebuilds/linux-arm/gtk3/node.napi.armv7.glibc.node +0 -0
  76. package/prebuilds/linux-arm/gtk4/node.napi.armv7.glibc.node +0 -0
  77. package/prebuilds/linux-arm64/gtk3/node.napi.glibc.node +0 -0
  78. package/prebuilds/linux-arm64/gtk4/node.napi.glibc.node +0 -0
  79. package/prebuilds/linux-ia32/gtk3/node.napi.glibc.node +0 -0
  80. package/prebuilds/linux-ia32/gtk4/node.napi.glibc.node +0 -0
  81. package/prebuilds/linux-riscv64/gtk3/node.napi.glibc.node +0 -0
  82. package/prebuilds/linux-riscv64/gtk4/node.napi.glibc.node +0 -0
  83. package/prebuilds/linux-x64/gtk3/node.napi.glibc.node +0 -0
  84. package/prebuilds/linux-x64/gtk4/node.napi.glibc.node +0 -0
  85. package/dist/native-BRnrsqMn.cjs.map +0 -1
  86. package/dist/native-DAhTiLnf.js.map +0 -1
@@ -0,0 +1,656 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ const node_child_process = require("node:child_process");
4
+ const node_net = require("node:net");
5
+ const node_fs = require("node:fs");
6
+ const node_path = require("node:path");
7
+ const errors = require("./errors-6gj5YuLw.cjs");
8
+ const launchGtkApp = require("./launchGtkApp-BIO_5Xjn.cjs");
9
+ const wait = require("./wait-eOIz4nZm.cjs");
10
+ const trayHostReadyLine = "gestament-tray-host-ready";
11
+ const trayHostReadyTimeoutMs = 3e4;
12
+ const apps = /* @__PURE__ */ new Map();
13
+ const elements = /* @__PURE__ */ new Map();
14
+ const trayItems = /* @__PURE__ */ new Map();
15
+ const imageInfos = /* @__PURE__ */ new Map();
16
+ const staleElementIds = /* @__PURE__ */ new Set();
17
+ const staleTrayItemIds = /* @__PURE__ */ new Set();
18
+ const staleImageInfoIds = /* @__PURE__ */ new Set();
19
+ let nextAppId = 1;
20
+ let nextElementId = 1;
21
+ let nextTrayItemId = 1;
22
+ let nextImageInfoId = 1;
23
+ let shuttingDown = false;
24
+ let trayHostProcess;
25
+ const parseArguments = (args) => {
26
+ let socketPath;
27
+ let withTrayHost = false;
28
+ let index = 0;
29
+ while (index < args.length) {
30
+ const argument = args[index];
31
+ if (argument === "--socket") {
32
+ const value = args[index + 1];
33
+ if (value === void 0 || value.length === 0) {
34
+ throw new Error("--socket requires a Unix socket path.");
35
+ }
36
+ socketPath = value;
37
+ index += 2;
38
+ continue;
39
+ }
40
+ if (argument === "--with-tray-host") {
41
+ withTrayHost = true;
42
+ index += 1;
43
+ continue;
44
+ }
45
+ throw new Error(`Unknown gestament launcher driver option: ${argument}`);
46
+ }
47
+ if (socketPath === void 0) {
48
+ throw new Error("Missing --socket option.");
49
+ }
50
+ return { socketPath, withTrayHost };
51
+ };
52
+ const waitForTrayHostReady = (host) => new Promise((resolveReady, rejectReady) => {
53
+ if (host.stdout === null) {
54
+ rejectReady(new Error("gestament tray host did not expose stdout."));
55
+ return;
56
+ }
57
+ let output = "";
58
+ let settled = false;
59
+ const timeout = setTimeout(() => {
60
+ if (!settled) {
61
+ settled = true;
62
+ rejectReady(new Error("Timed out waiting for gestament tray host."));
63
+ }
64
+ }, trayHostReadyTimeoutMs);
65
+ host.stdout.on("data", (chunk) => {
66
+ const text = chunk.toString("utf8");
67
+ output += text;
68
+ if (!settled && output.includes(trayHostReadyLine)) {
69
+ settled = true;
70
+ clearTimeout(timeout);
71
+ resolveReady();
72
+ return;
73
+ }
74
+ if (settled) {
75
+ process.stdout.write(text);
76
+ }
77
+ });
78
+ host.once("exit", (code, signal) => {
79
+ if (!settled) {
80
+ settled = true;
81
+ clearTimeout(timeout);
82
+ rejectReady(
83
+ new Error(
84
+ `gestament tray host exited before ready: code=${String(
85
+ code
86
+ )}, signal=${String(signal)}`
87
+ )
88
+ );
89
+ }
90
+ });
91
+ host.once("error", (error) => {
92
+ if (!settled) {
93
+ settled = true;
94
+ clearTimeout(timeout);
95
+ rejectReady(error);
96
+ }
97
+ });
98
+ });
99
+ const startTrayHost = async () => {
100
+ const executablePath = process.argv[1];
101
+ if (executablePath === void 0) {
102
+ throw new Error("Missing executable path.");
103
+ }
104
+ const hostPath = node_path.resolve(
105
+ node_path.dirname(node_fs.realpathSync(executablePath)),
106
+ "gestament-tray-host.cjs"
107
+ );
108
+ const host = node_child_process.spawn(process.execPath, [hostPath], {
109
+ env: process.env,
110
+ stdio: ["ignore", "pipe", "inherit"]
111
+ });
112
+ try {
113
+ await waitForTrayHostReady(host);
114
+ return host;
115
+ } catch (error) {
116
+ if (host.exitCode === null && host.signalCode === null) {
117
+ host.kill("SIGTERM");
118
+ }
119
+ throw error;
120
+ }
121
+ };
122
+ const connectToParent = (socketPath) => new Promise((resolveConnect, rejectConnect) => {
123
+ const socket = node_net.createConnection(socketPath);
124
+ const rejectFromError = (error) => {
125
+ socket.removeListener("connect", resolveFromConnect);
126
+ rejectConnect(error);
127
+ };
128
+ const resolveFromConnect = () => {
129
+ socket.removeListener("error", rejectFromError);
130
+ resolveConnect(socket);
131
+ };
132
+ socket.once("error", rejectFromError);
133
+ socket.once("connect", resolveFromConnect);
134
+ });
135
+ const writeReady = (socket) => {
136
+ const ready = { type: "ready" };
137
+ socket.write(`${JSON.stringify(ready)}
138
+ `);
139
+ };
140
+ const wireEnvironmentToGtkAppEnvironment = (env) => {
141
+ const appEnv = {};
142
+ for (const [key, value] of Object.entries(env)) {
143
+ appEnv[key] = value === null ? void 0 : value;
144
+ }
145
+ return appEnv;
146
+ };
147
+ const toWireCapture = (capture) => ({
148
+ bounds: capture.bounds,
149
+ clipped: capture.clipped,
150
+ imageBase64: capture.image.toString("base64"),
151
+ visibleBounds: capture.visibleBounds
152
+ });
153
+ const registerApp = (app) => {
154
+ const appId = `app-${nextAppId}`;
155
+ nextAppId += 1;
156
+ apps.set(appId, app);
157
+ return { appId };
158
+ };
159
+ const registerElement = (appId, element) => {
160
+ const elementId = `element-${nextElementId}`;
161
+ nextElementId += 1;
162
+ elements.set(elementId, { appId, element });
163
+ return { elementId, kind: element.kind };
164
+ };
165
+ const registerTrayItem = (appId, trayItem) => {
166
+ const trayItemId = `tray-${nextTrayItemId}`;
167
+ nextTrayItemId += 1;
168
+ trayItems.set(trayItemId, { appId, trayItem });
169
+ return { trayItemId };
170
+ };
171
+ const registerImageInfo = (appId, info) => {
172
+ const imageInfoId = `image-info-${nextImageInfoId}`;
173
+ nextImageInfoId += 1;
174
+ imageInfos.set(imageInfoId, { appId, capture: info.capture });
175
+ return {
176
+ bounds: info.bounds,
177
+ description: info.description,
178
+ imageInfoId,
179
+ locale: info.locale,
180
+ position: info.position,
181
+ size: info.size
182
+ };
183
+ };
184
+ const resolveApp = (appId) => {
185
+ const app = apps.get(appId);
186
+ if (app === void 0) {
187
+ throw errors.createGtkAppExitedError(
188
+ "GTK application has exited or was released."
189
+ );
190
+ }
191
+ return app;
192
+ };
193
+ const resolveElementEntry = (elementId) => {
194
+ const entry = elements.get(elementId);
195
+ if (entry === void 0) {
196
+ if (staleElementIds.has(elementId)) {
197
+ throw errors.createGtkStaleElementError("GTK element is no longer available.");
198
+ }
199
+ throw errors.createGtkAppExitedError("GTK element is not registered.");
200
+ }
201
+ if (!apps.has(entry.appId)) {
202
+ throw errors.createGtkStaleElementError("GTK element is no longer available.");
203
+ }
204
+ return entry;
205
+ };
206
+ const resolveTrayItemEntry = (trayItemId) => {
207
+ const entry = trayItems.get(trayItemId);
208
+ if (entry === void 0) {
209
+ if (staleTrayItemIds.has(trayItemId)) {
210
+ throw errors.createGtkStaleElementError("Tray item is no longer registered.");
211
+ }
212
+ throw errors.createGtkAppExitedError("GTK tray item is not registered.");
213
+ }
214
+ if (!apps.has(entry.appId)) {
215
+ throw errors.createGtkStaleElementError("Tray item is no longer registered.");
216
+ }
217
+ return entry;
218
+ };
219
+ const resolveImageInfoEntry = (imageInfoId) => {
220
+ const entry = imageInfos.get(imageInfoId);
221
+ if (entry === void 0) {
222
+ if (staleImageInfoIds.has(imageInfoId)) {
223
+ throw errors.createGtkStaleElementError(
224
+ "GTK image info is no longer available."
225
+ );
226
+ }
227
+ throw errors.createGtkAppExitedError("GTK image info is not registered.");
228
+ }
229
+ if (!apps.has(entry.appId)) {
230
+ throw errors.createGtkStaleElementError("GTK image info is no longer available.");
231
+ }
232
+ return entry;
233
+ };
234
+ const removeAppRefs = (appId) => {
235
+ for (const [elementId, entry] of elements) {
236
+ if (entry.appId === appId) {
237
+ staleElementIds.add(elementId);
238
+ elements.delete(elementId);
239
+ }
240
+ }
241
+ for (const [trayItemId, entry] of trayItems) {
242
+ if (entry.appId === appId) {
243
+ staleTrayItemIds.add(trayItemId);
244
+ trayItems.delete(trayItemId);
245
+ }
246
+ }
247
+ for (const [imageInfoId, entry] of imageInfos) {
248
+ if (entry.appId === appId) {
249
+ staleImageInfoIds.add(imageInfoId);
250
+ imageInfos.delete(imageInfoId);
251
+ }
252
+ }
253
+ };
254
+ const releaseApp = async (appId) => {
255
+ const app = apps.get(appId);
256
+ if (app === void 0) {
257
+ return;
258
+ }
259
+ apps.delete(appId);
260
+ removeAppRefs(appId);
261
+ await app.release();
262
+ };
263
+ const releaseApps = async () => {
264
+ const appIds = [...apps.keys()];
265
+ await Promise.all(appIds.map((appId) => releaseApp(appId)));
266
+ };
267
+ const stopTrayHost = () => {
268
+ if (trayHostProcess !== void 0 && trayHostProcess.exitCode === null && trayHostProcess.signalCode === null) {
269
+ trayHostProcess.kill("SIGTERM");
270
+ }
271
+ };
272
+ const releaseAll = async () => {
273
+ await releaseApps();
274
+ stopTrayHost();
275
+ };
276
+ const asMethod = (target, methodName, kindLabel) => {
277
+ const value = target[methodName];
278
+ if (typeof value !== "function") {
279
+ throw errors.createGtkUnsupportedInterfaceError(
280
+ `${kindLabel} does not support ${methodName}().`
281
+ );
282
+ }
283
+ return value;
284
+ };
285
+ const callElementMethod = (entry, methodName, args = []) => asMethod(
286
+ entry.element,
287
+ methodName,
288
+ `GTK ${entry.element.kind} element`
289
+ )(...args);
290
+ const callTrayItemMethod = (entry, methodName, args = []) => asMethod(entry.trayItem, methodName, "GTK tray item")(...args);
291
+ const serializeError = (error) => {
292
+ if (error instanceof Error) {
293
+ const maybeCode = error.code;
294
+ const base = {
295
+ message: error.message,
296
+ name: error.name
297
+ };
298
+ const withStack = error.stack === void 0 ? base : { ...base, stack: error.stack };
299
+ return typeof maybeCode === "string" ? { ...withStack, code: maybeCode } : withStack;
300
+ }
301
+ return {
302
+ message: String(error),
303
+ name: "Error"
304
+ };
305
+ };
306
+ const appPayload = (payload) => payload;
307
+ const elementPayload = (payload) => payload;
308
+ const trayPayload = (payload) => payload;
309
+ const optionalElementRef = (appId, element) => element === void 0 ? null : registerElement(appId, element);
310
+ const optionalTrayItemRef = (appId, trayItem) => trayItem === void 0 ? null : registerTrayItem(appId, trayItem);
311
+ const handleLauncherCommand = async (command, payload) => {
312
+ switch (command) {
313
+ case "launcher.launch": {
314
+ const launchPayload = payload;
315
+ const launchOptions = {
316
+ env: wireEnvironmentToGtkAppEnvironment(launchPayload.env),
317
+ ...launchPayload.timeoutMs === null ? {} : { timeoutMs: launchPayload.timeoutMs }
318
+ };
319
+ const app = await launchGtkApp.launchGtkApp(
320
+ launchPayload.appPath,
321
+ launchPayload.args,
322
+ launchOptions
323
+ );
324
+ return registerApp(app);
325
+ }
326
+ case "launcher.release":
327
+ await releaseAll();
328
+ return null;
329
+ case "launcher.reset":
330
+ await releaseApps();
331
+ return {
332
+ appCount: apps.size,
333
+ elementCount: elements.size,
334
+ imageInfoCount: imageInfos.size,
335
+ trayItemCount: trayItems.size
336
+ };
337
+ default:
338
+ throw errors.createGtkOperationFailedError(`Unsupported command: ${command}`);
339
+ }
340
+ };
341
+ const handleAppCommand = async (command, payload) => {
342
+ const { appId } = appPayload(payload);
343
+ const app = resolveApp(appId);
344
+ switch (command) {
345
+ case "app.release":
346
+ await releaseApp(appId);
347
+ return null;
348
+ case "app.capture":
349
+ return toWireCapture(await app.capture());
350
+ case "app.findById": {
351
+ const { id } = payload;
352
+ return optionalElementRef(appId, await app.findById(id));
353
+ }
354
+ case "app.getById": {
355
+ const { id } = payload;
356
+ return registerElement(appId, await app.getById(id));
357
+ }
358
+ case "app.findByPath": {
359
+ const { path } = payload;
360
+ return optionalElementRef(appId, await app.findByPath(path));
361
+ }
362
+ case "app.getByPath": {
363
+ const { path } = payload;
364
+ return registerElement(appId, await app.getByPath(path));
365
+ }
366
+ case "app.windowAt": {
367
+ const { index } = payload;
368
+ return optionalElementRef(appId, await app.windowAt(index));
369
+ }
370
+ case "app.getWindowCount":
371
+ return app.getWindowCount();
372
+ case "app.findTrayItem": {
373
+ const { selector } = payload;
374
+ return optionalTrayItemRef(appId, await app.findTrayItem(selector));
375
+ }
376
+ case "app.getTrayItem": {
377
+ const { selector } = payload;
378
+ return registerTrayItem(appId, await app.getTrayItem(selector));
379
+ }
380
+ case "app.trayItemAt": {
381
+ const { index } = payload;
382
+ return optionalTrayItemRef(appId, await app.trayItemAt(index));
383
+ }
384
+ case "app.getTrayItemCount":
385
+ return app.getTrayItemCount();
386
+ default:
387
+ throw errors.createGtkOperationFailedError(
388
+ `Unsupported app command: ${command}`
389
+ );
390
+ }
391
+ };
392
+ const handleElementCommand = async (command, payload) => {
393
+ const { elementId } = elementPayload(payload);
394
+ const entry = resolveElementEntry(elementId);
395
+ switch (command) {
396
+ case "element.info":
397
+ return entry.element.info();
398
+ case "element.capture":
399
+ return toWireCapture(await entry.element.capture());
400
+ case "element.childAt": {
401
+ const { index } = payload;
402
+ return optionalElementRef(
403
+ entry.appId,
404
+ await callElementMethod(entry, "childAt", [index])
405
+ );
406
+ }
407
+ case "element.getChildCount":
408
+ return callElementMethod(entry, "getChildCount");
409
+ case "element.click":
410
+ await callElementMethod(entry, "click");
411
+ return null;
412
+ case "element.text":
413
+ return callElementMethod(entry, "text");
414
+ case "element.setText": {
415
+ const { text } = payload;
416
+ await callElementMethod(entry, "setText", [text]);
417
+ return null;
418
+ }
419
+ case "element.isChecked":
420
+ return callElementMethod(entry, "isChecked");
421
+ case "element.toggle":
422
+ await callElementMethod(entry, "toggle");
423
+ return null;
424
+ case "element.value":
425
+ return callElementMethod(entry, "value");
426
+ case "element.valueInfo":
427
+ return callElementMethod(entry, "valueInfo");
428
+ case "element.setValue": {
429
+ const { value } = payload;
430
+ await callElementMethod(entry, "setValue", [value]);
431
+ return null;
432
+ }
433
+ case "element.increment":
434
+ await callElementMethod(entry, "increment");
435
+ return null;
436
+ case "element.decrement":
437
+ await callElementMethod(entry, "decrement");
438
+ return null;
439
+ case "element.getSelectedChildCount":
440
+ return callElementMethod(entry, "getSelectedChildCount");
441
+ case "element.selectedChildAt": {
442
+ const { selectedIndex } = payload;
443
+ return optionalElementRef(
444
+ entry.appId,
445
+ await callElementMethod(entry, "selectedChildAt", [selectedIndex])
446
+ );
447
+ }
448
+ case "element.isChildSelected": {
449
+ const { index } = payload;
450
+ return callElementMethod(entry, "isChildSelected", [index]);
451
+ }
452
+ case "element.selectChildAt": {
453
+ const { index } = payload;
454
+ await callElementMethod(entry, "selectChildAt", [index]);
455
+ return null;
456
+ }
457
+ case "element.deselectChildAt": {
458
+ const { index } = payload;
459
+ await callElementMethod(entry, "deselectChildAt", [index]);
460
+ return null;
461
+ }
462
+ case "element.selectAllChildren":
463
+ await callElementMethod(entry, "selectAllChildren");
464
+ return null;
465
+ case "element.clearSelection":
466
+ await callElementMethod(entry, "clearSelection");
467
+ return null;
468
+ case "element.getRowCount":
469
+ return callElementMethod(entry, "getRowCount");
470
+ case "element.getColumnCount":
471
+ return callElementMethod(entry, "getColumnCount");
472
+ case "element.cellAt": {
473
+ const { column, row } = payload;
474
+ return optionalElementRef(
475
+ entry.appId,
476
+ await callElementMethod(entry, "cellAt", [row, column])
477
+ );
478
+ }
479
+ case "element.selectedRows":
480
+ return callElementMethod(entry, "selectedRows");
481
+ case "element.selectedColumns":
482
+ return callElementMethod(entry, "selectedColumns");
483
+ case "element.isRowSelected": {
484
+ const { row } = payload;
485
+ return callElementMethod(entry, "isRowSelected", [row]);
486
+ }
487
+ case "element.isColumnSelected": {
488
+ const { column } = payload;
489
+ return callElementMethod(entry, "isColumnSelected", [column]);
490
+ }
491
+ case "element.isCellSelected": {
492
+ const { column, row } = payload;
493
+ return callElementMethod(entry, "isCellSelected", [row, column]);
494
+ }
495
+ case "element.selectRow": {
496
+ const { row } = payload;
497
+ await callElementMethod(entry, "selectRow", [row]);
498
+ return null;
499
+ }
500
+ case "element.deselectRow": {
501
+ const { row } = payload;
502
+ await callElementMethod(entry, "deselectRow", [row]);
503
+ return null;
504
+ }
505
+ case "element.selectColumn": {
506
+ const { column } = payload;
507
+ await callElementMethod(entry, "selectColumn", [column]);
508
+ return null;
509
+ }
510
+ case "element.deselectColumn": {
511
+ const { column } = payload;
512
+ await callElementMethod(entry, "deselectColumn", [column]);
513
+ return null;
514
+ }
515
+ case "element.imageInfo": {
516
+ const info = await callElementMethod(
517
+ entry,
518
+ "imageInfo"
519
+ );
520
+ return registerImageInfo(entry.appId, info);
521
+ }
522
+ default:
523
+ throw errors.createGtkOperationFailedError(
524
+ `Unsupported element command: ${command}`
525
+ );
526
+ }
527
+ };
528
+ const handleImageInfoCommand = async (command, payload) => {
529
+ if (command !== "imageInfo.capture") {
530
+ throw errors.createGtkOperationFailedError(
531
+ `Unsupported image info command: ${command}`
532
+ );
533
+ }
534
+ const { imageInfoId } = payload;
535
+ const entry = resolveImageInfoEntry(imageInfoId);
536
+ return toWireCapture(await entry.capture());
537
+ };
538
+ const handleTrayCommand = async (command, payload) => {
539
+ const { trayItemId } = trayPayload(payload);
540
+ const entry = resolveTrayItemEntry(trayItemId);
541
+ switch (command) {
542
+ case "tray.metadata":
543
+ return entry.trayItem.metadata();
544
+ case "tray.element":
545
+ return optionalElementRef(
546
+ entry.appId,
547
+ await callTrayItemMethod(entry, "element")
548
+ );
549
+ case "tray.capture":
550
+ return toWireCapture(await entry.trayItem.capture());
551
+ case "tray.click":
552
+ await entry.trayItem.click();
553
+ return null;
554
+ case "tray.openMenu":
555
+ return optionalElementRef(
556
+ entry.appId,
557
+ await callTrayItemMethod(entry, "openMenu")
558
+ );
559
+ default:
560
+ throw errors.createGtkOperationFailedError(
561
+ `Unsupported tray command: ${command}`
562
+ );
563
+ }
564
+ };
565
+ const handleRequest = async (request) => {
566
+ if (request.command.startsWith("launcher.")) {
567
+ return handleLauncherCommand(request.command, request.payload);
568
+ }
569
+ if (request.command.startsWith("app.")) {
570
+ return handleAppCommand(request.command, request.payload);
571
+ }
572
+ if (request.command.startsWith("element.")) {
573
+ return handleElementCommand(request.command, request.payload);
574
+ }
575
+ if (request.command.startsWith("imageInfo.")) {
576
+ return handleImageInfoCommand(request.command, request.payload);
577
+ }
578
+ if (request.command.startsWith("tray.")) {
579
+ return handleTrayCommand(request.command, request.payload);
580
+ }
581
+ throw errors.createGtkOperationFailedError(
582
+ `Unsupported launcher driver command: ${request.command}`
583
+ );
584
+ };
585
+ const writeResponse = (socket, id, response) => {
586
+ socket.write(`${JSON.stringify({ id, ...response })}
587
+ `);
588
+ };
589
+ const handleRequestLine = async (socket, line) => {
590
+ const request = JSON.parse(line);
591
+ try {
592
+ const value = request.deadlineMs === void 0 || request.deadlineMs === null ? await handleRequest(request) : await wait.runWithWaitDeadline(
593
+ request.deadlineMs,
594
+ () => handleRequest(request)
595
+ );
596
+ writeResponse(socket, request.id, { ok: true, value });
597
+ if (request.command === "launcher.release") {
598
+ socket.end();
599
+ }
600
+ } catch (error) {
601
+ writeResponse(socket, request.id, {
602
+ error: serializeError(error),
603
+ ok: false
604
+ });
605
+ }
606
+ };
607
+ const installSocketProtocol = (socket) => {
608
+ let input = "";
609
+ socket.on("data", (chunk) => {
610
+ input += chunk.toString("utf8");
611
+ let newlineIndex = input.indexOf("\n");
612
+ while (newlineIndex >= 0) {
613
+ const line = input.slice(0, newlineIndex);
614
+ input = input.slice(newlineIndex + 1);
615
+ void handleRequestLine(socket, line);
616
+ newlineIndex = input.indexOf("\n");
617
+ }
618
+ });
619
+ socket.once("close", () => {
620
+ void shutdown(0);
621
+ });
622
+ socket.once("error", () => {
623
+ void shutdown(1);
624
+ });
625
+ };
626
+ const shutdown = async (exitCode) => {
627
+ if (shuttingDown) {
628
+ return;
629
+ }
630
+ shuttingDown = true;
631
+ await releaseAll();
632
+ process.exitCode = exitCode;
633
+ setImmediate(() => {
634
+ process.exit(exitCode);
635
+ });
636
+ };
637
+ const run = async () => {
638
+ const parsed = parseArguments(process.argv.slice(2));
639
+ trayHostProcess = parsed.withTrayHost ? await startTrayHost() : void 0;
640
+ const socket = await connectToParent(parsed.socketPath);
641
+ installSocketProtocol(socket);
642
+ writeReady(socket);
643
+ process.once("SIGINT", () => {
644
+ void shutdown(130);
645
+ });
646
+ process.once("SIGTERM", () => {
647
+ void shutdown(143);
648
+ });
649
+ };
650
+ run().catch((error) => {
651
+ const message = error instanceof Error ? error.message : String(error);
652
+ process.stderr.write(`gestament launcher driver: ${message}
653
+ `);
654
+ process.exitCode = 2;
655
+ });
656
+ //# sourceMappingURL=gestament-launcher-driver.cjs.map