@mukea/uiohook-napi 1.5.4

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 (38) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/binding.gyp +85 -0
  4. package/dist/index.d.ts +194 -0
  5. package/dist/index.js +206 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/prebuild-test-noop.d.ts +0 -0
  8. package/dist/prebuild-test-noop.js +3 -0
  9. package/dist/prebuild-test-noop.js.map +1 -0
  10. package/libuiohook/include/uiohook.h +457 -0
  11. package/libuiohook/src/darwin/input_helper.c +535 -0
  12. package/libuiohook/src/darwin/input_helper.h +203 -0
  13. package/libuiohook/src/darwin/input_hook.c +1436 -0
  14. package/libuiohook/src/darwin/post_event.c +303 -0
  15. package/libuiohook/src/darwin/system_properties.c +479 -0
  16. package/libuiohook/src/logger.c +40 -0
  17. package/libuiohook/src/logger.h +32 -0
  18. package/libuiohook/src/windows/input_helper.c +913 -0
  19. package/libuiohook/src/windows/input_helper.h +146 -0
  20. package/libuiohook/src/windows/input_hook.c +722 -0
  21. package/libuiohook/src/windows/post_event.c +248 -0
  22. package/libuiohook/src/windows/system_properties.c +231 -0
  23. package/libuiohook/src/x11/input_helper.c +1846 -0
  24. package/libuiohook/src/x11/input_helper.h +108 -0
  25. package/libuiohook/src/x11/input_hook.c +1116 -0
  26. package/libuiohook/src/x11/post_event.c +427 -0
  27. package/libuiohook/src/x11/system_properties.c +494 -0
  28. package/package.json +60 -0
  29. package/prebuilds/darwin/darwin-arm64/@mukea+uiohook-napi.node +0 -0
  30. package/prebuilds/darwin/darwin-x64/@mukea+uiohook-napi.node +0 -0
  31. package/prebuilds/linux/linux-arm64/@mukea+uiohook-napi.node +0 -0
  32. package/prebuilds/linux/linux-x64/@mukea+uiohook-napi.node +0 -0
  33. package/prebuilds/windows/win32-x64/@mukea+uiohook-napi.node +0 -0
  34. package/src/lib/addon.c +337 -0
  35. package/src/lib/napi_helpers.c +51 -0
  36. package/src/lib/napi_helpers.h +53 -0
  37. package/src/lib/uiohook_worker.c +200 -0
  38. package/src/lib/uiohook_worker.h +12 -0
@@ -0,0 +1,494 @@
1
+ /* libUIOHook: Cross-platform keyboard and mouse hooking from userland.
2
+ * Copyright (C) 2006-2023 Alexander Barker. All Rights Reserved.
3
+ * https://github.com/kwhat/libuiohook/
4
+ *
5
+ * libUIOHook is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU Lesser General Public License as published
7
+ * by the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * libUIOHook is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public License
16
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ #include <stdbool.h>
20
+ #include <stdio.h>
21
+ #include <stdlib.h>
22
+ #include <uiohook.h>
23
+ #include <X11/Xlib.h>
24
+ #include <X11/XKBlib.h>
25
+
26
+ #ifdef USE_XF86MISC
27
+ #include <X11/extensions/xf86misc.h>
28
+ #include <X11/extensions/xf86mscstr.h>
29
+ #endif
30
+
31
+ #if defined(USE_XINERAMA) && !defined(USE_XRANDR)
32
+ #include <X11/extensions/Xinerama.h>
33
+ #elif defined(USE_XRANDR)
34
+ #include <pthread.h>
35
+ #include <X11/extensions/Xrandr.h>
36
+ #endif
37
+
38
+ #ifdef USE_XT
39
+ #include <X11/Intrinsic.h>
40
+
41
+ static XtAppContext xt_context;
42
+ static Display *xt_disp;
43
+ #endif
44
+
45
+ #include "input_helper.h"
46
+ #include "logger.h"
47
+
48
+ #ifdef USE_XRANDR
49
+ static pthread_mutex_t xrandr_mutex = PTHREAD_MUTEX_INITIALIZER;
50
+ static XRRScreenResources *xrandr_resources = NULL;
51
+
52
+ static void settings_cleanup_proc(void *arg) {
53
+ if (pthread_mutex_trylock(&xrandr_mutex) == 0) {
54
+ if (xrandr_resources != NULL) {
55
+ XRRFreeScreenResources(xrandr_resources);
56
+ xrandr_resources = NULL;
57
+ }
58
+
59
+ if (arg != NULL) {
60
+ XCloseDisplay((Display *) arg);
61
+ arg = NULL;
62
+ }
63
+
64
+ pthread_mutex_unlock(&xrandr_mutex);
65
+ }
66
+ }
67
+
68
+ static void *settings_thread_proc(void *arg) {
69
+ Display *settings_disp = XOpenDisplay(XDisplayName(NULL));;
70
+ if (settings_disp != NULL) {
71
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: %s\n",
72
+ __FUNCTION__, __LINE__, "XOpenDisplay success.");
73
+
74
+ pthread_cleanup_push(settings_cleanup_proc, settings_disp);
75
+
76
+ int event_base = 0;
77
+ int error_base = 0;
78
+ if (XRRQueryExtension(settings_disp, &event_base, &error_base)) {
79
+ Window root = XDefaultRootWindow(settings_disp);
80
+ unsigned long event_mask = RRScreenChangeNotifyMask;
81
+ XRRSelectInput(settings_disp, root, event_mask);
82
+
83
+ XEvent ev;
84
+
85
+ while(settings_disp != NULL) {
86
+ XNextEvent(settings_disp, &ev);
87
+
88
+ if (ev.type == event_base + RRScreenChangeNotifyMask) {
89
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: Received XRRScreenChangeNotifyEvent.\n",
90
+ __FUNCTION__, __LINE__);
91
+
92
+ pthread_mutex_lock(&xrandr_mutex);
93
+ if (xrandr_resources != NULL) {
94
+ XRRFreeScreenResources(xrandr_resources);
95
+ }
96
+
97
+ xrandr_resources = XRRGetScreenResources(settings_disp, root);
98
+ if (xrandr_resources == NULL) {
99
+ logger(LOG_LEVEL_WARN, "%s [%u]: XRandR could not get screen resources!\n",
100
+ __FUNCTION__, __LINE__);
101
+ }
102
+ pthread_mutex_unlock(&xrandr_mutex);
103
+ } else {
104
+ logger(LOG_LEVEL_WARN, "%s [%u]: XRandR is not currently available!\n",
105
+ __FUNCTION__, __LINE__);
106
+ }
107
+ }
108
+ }
109
+
110
+ // Execute the thread cleanup handler.
111
+ pthread_cleanup_pop(1);
112
+
113
+ } else {
114
+ logger(LOG_LEVEL_ERROR, "%s [%u]: XOpenDisplay failure!\n",
115
+ __FUNCTION__, __LINE__);
116
+ }
117
+
118
+ return NULL;
119
+ }
120
+ #endif
121
+
122
+ UIOHOOK_API screen_data* hook_create_screen_info(unsigned char *count) {
123
+ *count = 0;
124
+ screen_data *screens = NULL;
125
+
126
+ // Check and make sure we could connect to the x server.
127
+ if (helper_disp != NULL) {
128
+ #if defined(USE_XINERAMA) && !defined(USE_XRANDR)
129
+ if (XineramaIsActive(helper_disp)) {
130
+ int xine_count = 0;
131
+ XineramaScreenInfo *xine_info = XineramaQueryScreens(helper_disp, &xine_count);
132
+
133
+ if (xine_info != NULL) {
134
+ if (xine_count > UINT8_MAX) {
135
+ *count = UINT8_MAX;
136
+
137
+ logger(LOG_LEVEL_WARN, "%s [%u]: Screen count overflow detected!\n",
138
+ __FUNCTION__, __LINE__);
139
+ } else {
140
+ *count = (uint8_t) xine_count;
141
+ }
142
+
143
+ screens = malloc(sizeof(screen_data) * xine_count);
144
+
145
+ if (screens != NULL) {
146
+ for (int i = 0; i < xine_count; i++) {
147
+ screens[i] = (screen_data) {
148
+ .number = xine_info[i].screen_number,
149
+ .x = xine_info[i].x_org,
150
+ .y = xine_info[i].y_org,
151
+ .width = xine_info[i].width,
152
+ .height = xine_info[i].height
153
+ };
154
+ }
155
+ }
156
+
157
+ XFree(xine_info);
158
+ }
159
+ }
160
+ #elif defined(USE_XRANDR)
161
+ pthread_mutex_lock(&xrandr_mutex);
162
+ if (xrandr_resources != NULL) {
163
+ int xrandr_count = xrandr_resources->ncrtc;
164
+ if (xrandr_count > UINT8_MAX) {
165
+ *count = UINT8_MAX;
166
+
167
+ logger(LOG_LEVEL_WARN, "%s [%u]: Screen count overflow detected!\n",
168
+ __FUNCTION__, __LINE__);
169
+ } else {
170
+ *count = (uint8_t) xrandr_count;
171
+ }
172
+
173
+ screens = malloc(sizeof(screen_data) * xrandr_count);
174
+
175
+ if (screens != NULL) {
176
+ for (int i = 0; i < xrandr_count; i++) {
177
+ XRRCrtcInfo *crtc_info = XRRGetCrtcInfo(helper_disp, xrandr_resources, xrandr_resources->crtcs[i]);
178
+
179
+ if (crtc_info != NULL) {
180
+ screens[i] = (screen_data) {
181
+ .number = i + 1,
182
+ .x = crtc_info->x,
183
+ .y = crtc_info->y,
184
+ .width = crtc_info->width,
185
+ .height = crtc_info->height
186
+ };
187
+
188
+ XRRFreeCrtcInfo(crtc_info);
189
+ } else {
190
+ logger(LOG_LEVEL_WARN, "%s [%u]: XRandr failed to return crtc information! (%#X)\n",
191
+ __FUNCTION__, __LINE__, xrandr_resources->crtcs[i]);
192
+ }
193
+ }
194
+ }
195
+ }
196
+ pthread_mutex_unlock(&xrandr_mutex);
197
+ #else
198
+ Screen* default_screen = DefaultScreenOfDisplay(helper_disp);
199
+
200
+ if (default_screen->width > 0 && default_screen->height > 0) {
201
+ screens = malloc(sizeof(screen_data));
202
+
203
+ if (screens != NULL) {
204
+ *count = 1;
205
+ screens[0] = (screen_data) {
206
+ .number = 1,
207
+ .x = 0,
208
+ .y = 0,
209
+ .width = default_screen->width,
210
+ .height = default_screen->height
211
+ };
212
+ }
213
+ }
214
+ #endif
215
+ } else {
216
+ logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
217
+ __FUNCTION__, __LINE__);
218
+ }
219
+
220
+ return screens;
221
+ }
222
+
223
+ UIOHOOK_API long int hook_get_auto_repeat_rate() {
224
+ bool successful = false;
225
+ long int value = -1;
226
+ unsigned int delay = 0, rate = 0;
227
+
228
+ // Check and make sure we could connect to the x server.
229
+ if (helper_disp != NULL) {
230
+ // Attempt to acquire the keyboard auto repeat rate using the XKB extension.
231
+ if (!successful) {
232
+ successful = XkbGetAutoRepeatRate(helper_disp, XkbUseCoreKbd, &delay, &rate);
233
+
234
+ if (successful) {
235
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: XkbGetAutoRepeatRate: %u.\n",
236
+ __FUNCTION__, __LINE__, rate);
237
+ }
238
+ }
239
+
240
+ #ifdef USE_XF86MISC
241
+ // Fallback to the XF86 Misc extension if available and other efforts failed.
242
+ if (!successful) {
243
+ XF86MiscKbdSettings kb_info;
244
+ successful = (bool) XF86MiscGetKbdSettings(helper_disp, &kb_info);
245
+ if (successful) {
246
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: XF86MiscGetKbdSettings: %i.\n",
247
+ __FUNCTION__, __LINE__, kbdinfo.rate);
248
+
249
+ delay = (unsigned int) kbdinfo.delay;
250
+ rate = (unsigned int) kbdinfo.rate;
251
+ }
252
+ }
253
+ #endif
254
+ } else {
255
+ logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
256
+ __FUNCTION__, __LINE__);
257
+ }
258
+
259
+ if (successful) {
260
+ value = (long int) rate;
261
+ }
262
+
263
+ return value;
264
+ }
265
+
266
+ UIOHOOK_API long int hook_get_auto_repeat_delay() {
267
+ bool successful = false;
268
+ long int value = -1;
269
+ unsigned int delay = 0, rate = 0;
270
+
271
+ // Check and make sure we could connect to the x server.
272
+ if (helper_disp != NULL) {
273
+ // Attempt to acquire the keyboard auto repeat rate using the XKB extension.
274
+ if (!successful) {
275
+ successful = XkbGetAutoRepeatRate(helper_disp, XkbUseCoreKbd, &delay, &rate);
276
+
277
+ if (successful) {
278
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: XkbGetAutoRepeatRate: %u.\n",
279
+ __FUNCTION__, __LINE__, delay);
280
+ }
281
+ }
282
+
283
+ #ifdef USE_XF86MISC
284
+ // Fallback to the XF86 Misc extension if available and other efforts failed.
285
+ if (!successful) {
286
+ XF86MiscKbdSettings kb_info;
287
+ successful = (bool) XF86MiscGetKbdSettings(helper_disp, &kb_info);
288
+ if (successful) {
289
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: XF86MiscGetKbdSettings: %i.\n",
290
+ __FUNCTION__, __LINE__, kbdinfo.delay);
291
+
292
+ delay = (unsigned int) kbdinfo.delay;
293
+ rate = (unsigned int) kbdinfo.rate;
294
+ }
295
+ }
296
+ #endif
297
+ } else {
298
+ logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
299
+ __FUNCTION__, __LINE__);
300
+ }
301
+
302
+ if (successful) {
303
+ value = (long int) delay;
304
+ }
305
+
306
+ return value;
307
+ }
308
+
309
+ UIOHOOK_API long int hook_get_pointer_acceleration_multiplier() {
310
+ long int value = -1;
311
+ int accel_numerator, accel_denominator, threshold;
312
+
313
+ // Check and make sure we could connect to the x server.
314
+ if (helper_disp != NULL) {
315
+ XGetPointerControl(helper_disp, &accel_numerator, &accel_denominator, &threshold);
316
+ if (accel_denominator >= 0) {
317
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: XGetPointerControl: %i.\n",
318
+ __FUNCTION__, __LINE__, accel_denominator);
319
+
320
+ value = (long int) accel_denominator;
321
+ }
322
+ } else {
323
+ logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
324
+ __FUNCTION__, __LINE__);
325
+ }
326
+
327
+ return value;
328
+ }
329
+
330
+ UIOHOOK_API long int hook_get_pointer_acceleration_threshold() {
331
+ long int value = -1;
332
+ int accel_numerator, accel_denominator, threshold;
333
+
334
+ // Check and make sure we could connect to the x server.
335
+ if (helper_disp != NULL) {
336
+ XGetPointerControl(helper_disp, &accel_numerator, &accel_denominator, &threshold);
337
+ if (threshold >= 0) {
338
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: XGetPointerControl: %i.\n",
339
+ __FUNCTION__, __LINE__, threshold);
340
+
341
+ value = (long int) threshold;
342
+ }
343
+ } else {
344
+ logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
345
+ __FUNCTION__, __LINE__);
346
+ }
347
+
348
+ return value;
349
+ }
350
+
351
+ UIOHOOK_API long int hook_get_pointer_sensitivity() {
352
+ long int value = -1;
353
+ int accel_numerator, accel_denominator, threshold;
354
+
355
+ // Check and make sure we could connect to the x server.
356
+ if (helper_disp != NULL) {
357
+ XGetPointerControl(helper_disp, &accel_numerator, &accel_denominator, &threshold);
358
+ if (accel_numerator >= 0) {
359
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: XGetPointerControl: %i.\n",
360
+ __FUNCTION__, __LINE__, accel_numerator);
361
+
362
+ value = (long int) accel_numerator;
363
+ }
364
+ } else {
365
+ logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
366
+ __FUNCTION__, __LINE__);
367
+ }
368
+
369
+ return value;
370
+ }
371
+
372
+ UIOHOOK_API long int hook_get_multi_click_time() {
373
+ long int value = 200;
374
+ int click_time;
375
+ bool successful = false;
376
+
377
+ #ifdef USE_XT
378
+ // Check and make sure we could connect to the x server.
379
+ if (xt_disp != NULL) {
380
+ // Try and use the Xt extention to get the current multi-click.
381
+ if (!successful) {
382
+ // Fall back to the X Toolkit extension if available and other efforts failed.
383
+ click_time = XtGetMultiClickTime(xt_disp);
384
+ if (click_time >= 0) {
385
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: XtGetMultiClickTime: %i.\n",
386
+ __FUNCTION__, __LINE__, click_time);
387
+
388
+ successful = true;
389
+ }
390
+ }
391
+ } else {
392
+ logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
393
+ __FUNCTION__, __LINE__, "XOpenDisplay failure!");
394
+ }
395
+ #endif
396
+
397
+ // Check and make sure we could connect to the x server.
398
+ if (helper_disp != NULL) {
399
+ // Try and acquire the multi-click time from the user defined X defaults.
400
+ if (!successful) {
401
+ char *xprop = XGetDefault(helper_disp, "*", "multiClickTime");
402
+ if (xprop != NULL && sscanf(xprop, "%4i", &click_time) != EOF) {
403
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: X default 'multiClickTime' property: %i.\n",
404
+ __FUNCTION__, __LINE__, click_time);
405
+
406
+ successful = true;
407
+ }
408
+ }
409
+
410
+ if (!successful) {
411
+ char *xprop = XGetDefault(helper_disp, "OpenWindows", "MultiClickTimeout");
412
+ if (xprop != NULL && sscanf(xprop, "%4i", &click_time) != EOF) {
413
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: X default 'MultiClickTimeout' property: %i.\n",
414
+ __FUNCTION__, __LINE__, click_time);
415
+
416
+ successful = true;
417
+ }
418
+ }
419
+ } else {
420
+ logger(LOG_LEVEL_WARN, "%s [%u]: XDisplay helper_disp is unavailable!\n",
421
+ __FUNCTION__, __LINE__);
422
+ }
423
+
424
+ if (successful) {
425
+ value = (long int) click_time;
426
+ }
427
+
428
+ return value;
429
+ }
430
+
431
+ // Create a shared object constructor.
432
+ __attribute__ ((constructor))
433
+ void on_library_load() {
434
+ // Make sure we are initialized for threading.
435
+ XInitThreads();
436
+
437
+ // Open local display.
438
+ helper_disp = XOpenDisplay(XDisplayName(NULL));
439
+ if (helper_disp == NULL) {
440
+ logger(LOG_LEVEL_ERROR, "%s [%u]: %s\n",
441
+ __FUNCTION__, __LINE__, "XOpenDisplay failure!");
442
+ } else {
443
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: %s\n",
444
+ __FUNCTION__, __LINE__, "XOpenDisplay success.");
445
+ }
446
+
447
+ #ifdef USE_XRANDR
448
+ // Create the thread attribute.
449
+ pthread_attr_t settings_thread_attr;
450
+ pthread_attr_init(&settings_thread_attr);
451
+
452
+ pthread_t settings_thread_id;
453
+ if (pthread_create(&settings_thread_id, &settings_thread_attr, settings_thread_proc, NULL) == 0) {
454
+ logger(LOG_LEVEL_DEBUG, "%s [%u]: Successfully created settings thread.\n",
455
+ __FUNCTION__, __LINE__);
456
+ } else {
457
+ logger(LOG_LEVEL_ERROR, "%s [%u]: Failed to create settings thread!\n",
458
+ __FUNCTION__, __LINE__);
459
+ }
460
+
461
+ // Make sure the thread attribute is removed.
462
+ pthread_attr_destroy(&settings_thread_attr);
463
+ #endif
464
+
465
+ #ifdef USE_XT
466
+ XtToolkitInitialize();
467
+ xt_context = XtCreateApplicationContext();
468
+
469
+ int argc = 0;
470
+ char ** argv = { NULL };
471
+ xt_disp = XtOpenDisplay(xt_context, NULL, "UIOHook", "libuiohook", NULL, 0, &argc, argv);
472
+ #endif
473
+ }
474
+
475
+ // Create a shared object destructor.
476
+ __attribute__ ((destructor))
477
+ void on_library_unload() {
478
+ // Disable the event hook.
479
+ //hook_stop();
480
+
481
+ // Cleanup.
482
+ unload_input_helper();
483
+
484
+ #ifdef USE_XT
485
+ XtCloseDisplay(xt_disp);
486
+ XtDestroyApplicationContext(xt_context);
487
+ #endif
488
+
489
+ // Destroy the native displays.
490
+ if (helper_disp != NULL) {
491
+ XCloseDisplay(helper_disp);
492
+ helper_disp = NULL;
493
+ }
494
+ }
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@mukea/uiohook-napi",
3
+ "version": "1.5.4",
4
+ "author": {
5
+ "name": "mukea.cc"
6
+ },
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/mukea-org/uiohook-napi"
10
+ },
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "iohook",
14
+ "uiohook",
15
+ "libuiohook",
16
+ "hook",
17
+ "input",
18
+ "keyboard",
19
+ "mouse"
20
+ ],
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "default": "./dist/index.js"
25
+ }
26
+ },
27
+ "scripts": {
28
+ "install": "node-gyp-build",
29
+ "prebuild": "prebuildify --napi",
30
+ "prepublishOnly": "npm run build-ts && npm run prebuild",
31
+ "build-ts": "tsc",
32
+ "demo": "ts-node src/demo.ts",
33
+ "make-libuiohook-patch": "git -C ./libuiohook diff --cached > ./src/libuiohook.patch",
34
+ "apply-libuiohook-patch": "git -C ./libuiohook apply ../src/libuiohook.patch"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "binding.gyp",
39
+ "libuiohook/src",
40
+ "libuiohook/include",
41
+ "src/lib",
42
+ "prebuilds"
43
+ ],
44
+ "devDependencies": {
45
+ "@types/node": "^20.11.30",
46
+ "prebuildify": "^6.0.1",
47
+ "ts-node": "^10.9.2",
48
+ "typescript": "^5.9.3"
49
+ },
50
+ "dependencies": {
51
+ "node-gyp-build": "4.x.x"
52
+ },
53
+ "prebuild": {
54
+ "test": "dist/prebuild-test-noop.js"
55
+ },
56
+ "gypfile": true,
57
+ "engines": {
58
+ "node": ">=18"
59
+ }
60
+ }