keyspy 1.0.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 (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +287 -0
  3. package/build/index.d.ts +53 -0
  4. package/build/index.d.ts.map +1 -0
  5. package/build/index.js +149 -0
  6. package/build/ts/MacKeyServer.d.ts +45 -0
  7. package/build/ts/MacKeyServer.d.ts.map +1 -0
  8. package/build/ts/MacKeyServer.js +159 -0
  9. package/build/ts/WinKeyServer.d.ts +30 -0
  10. package/build/ts/WinKeyServer.d.ts.map +1 -0
  11. package/build/ts/WinKeyServer.js +88 -0
  12. package/build/ts/X11KeyServer.d.ts +45 -0
  13. package/build/ts/X11KeyServer.d.ts.map +1 -0
  14. package/build/ts/X11KeyServer.js +159 -0
  15. package/build/ts/_data/MacGlobalKeyLookup.d.ts +3 -0
  16. package/build/ts/_data/MacGlobalKeyLookup.d.ts.map +1 -0
  17. package/build/ts/_data/MacGlobalKeyLookup.js +155 -0
  18. package/build/ts/_data/WinGlobalKeyLookup.d.ts +6 -0
  19. package/build/ts/_data/WinGlobalKeyLookup.d.ts.map +1 -0
  20. package/build/ts/_data/WinGlobalKeyLookup.js +181 -0
  21. package/build/ts/_data/X11GlobalKeyLookup.d.ts +3 -0
  22. package/build/ts/_data/X11GlobalKeyLookup.d.ts.map +1 -0
  23. package/build/ts/_data/X11GlobalKeyLookup.js +144 -0
  24. package/build/ts/_types/IConfig.d.ts +15 -0
  25. package/build/ts/_types/IConfig.d.ts.map +1 -0
  26. package/build/ts/_types/IConfig.js +3 -0
  27. package/build/ts/_types/IGlobalKey.d.ts +19 -0
  28. package/build/ts/_types/IGlobalKey.d.ts.map +1 -0
  29. package/build/ts/_types/IGlobalKey.js +3 -0
  30. package/build/ts/_types/IGlobalKeyDownMap.d.ts +5 -0
  31. package/build/ts/_types/IGlobalKeyDownMap.d.ts.map +1 -0
  32. package/build/ts/_types/IGlobalKeyDownMap.js +3 -0
  33. package/build/ts/_types/IGlobalKeyEvent.d.ts +17 -0
  34. package/build/ts/_types/IGlobalKeyEvent.d.ts.map +1 -0
  35. package/build/ts/_types/IGlobalKeyEvent.js +3 -0
  36. package/build/ts/_types/IGlobalKeyListener.d.ts +14 -0
  37. package/build/ts/_types/IGlobalKeyListener.d.ts.map +1 -0
  38. package/build/ts/_types/IGlobalKeyListener.js +3 -0
  39. package/build/ts/_types/IGlobalKeyListenerRaw.d.ts +7 -0
  40. package/build/ts/_types/IGlobalKeyListenerRaw.d.ts.map +1 -0
  41. package/build/ts/_types/IGlobalKeyListenerRaw.js +3 -0
  42. package/build/ts/_types/IGlobalKeyLookup.d.ts +9 -0
  43. package/build/ts/_types/IGlobalKeyLookup.d.ts.map +1 -0
  44. package/build/ts/_types/IGlobalKeyLookup.js +3 -0
  45. package/build/ts/_types/IGlobalKeyResult.d.ts +12 -0
  46. package/build/ts/_types/IGlobalKeyResult.d.ts.map +1 -0
  47. package/build/ts/_types/IGlobalKeyResult.js +3 -0
  48. package/build/ts/_types/IGlobalKeyServer.d.ts +16 -0
  49. package/build/ts/_types/IGlobalKeyServer.d.ts.map +1 -0
  50. package/build/ts/_types/IGlobalKeyServer.js +3 -0
  51. package/build/ts/_types/IMacConfig.d.ts +10 -0
  52. package/build/ts/_types/IMacConfig.d.ts.map +1 -0
  53. package/build/ts/_types/IMacConfig.js +3 -0
  54. package/build/ts/_types/IWindowsConfig.d.ts +10 -0
  55. package/build/ts/_types/IWindowsConfig.d.ts.map +1 -0
  56. package/build/ts/_types/IWindowsConfig.js +3 -0
  57. package/build/ts/_types/IX11Config.d.ts +10 -0
  58. package/build/ts/_types/IX11Config.d.ts.map +1 -0
  59. package/build/ts/_types/IX11Config.js +3 -0
  60. package/build/ts/isSpawnEventSupported.d.ts +6 -0
  61. package/build/ts/isSpawnEventSupported.d.ts.map +1 -0
  62. package/build/ts/isSpawnEventSupported.js +18 -0
  63. package/package.json +80 -0
  64. package/scripts/download-binaries.js +191 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 LaunchMenu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,287 @@
1
+ # KeySpy 🕵️
2
+
3
+ > A powerful, cross-platform keyboard and mouse event listener for Node.js
4
+
5
+ KeySpy is a modern, lightweight library that provides global keyboard and mouse event monitoring across Windows, macOS, and Linux. Unlike other solutions, KeySpy uses pre-compiled native binaries and a multi-process architecture for maximum stability and compatibility.
6
+
7
+ ## ✨ Features
8
+
9
+ - 🌍 **Cross-platform**: Works on Windows, macOS, and Linux (X11)
10
+ - 🚀 **Zero compilation**: Pre-compiled binaries downloaded automatically, no node-gyp required
11
+ - 🔒 **System-level capture**: Can intercept system shortcuts like Ctrl+Alt+Delete, Cmd+Space
12
+ - 🎯 **Event blocking**: Prevent captured events from reaching other applications
13
+ - 📦 **TypeScript ready**: Full TypeScript support with comprehensive type definitions
14
+ - 🏗️ **Modern architecture**: Multi-process design for enhanced stability
15
+ - ⚡ **High performance**: Optimized native implementations for each platform
16
+ - 📥 **Smart installation**: Automatically downloads platform-specific binaries from GitHub Releases
17
+
18
+ ## 🔧 Platform Support
19
+
20
+ | Platform | Status | Implementation | Tested On |
21
+ |----------|--------|---------------|-----------|
22
+ | Windows | ✅ Full | C++ (Low-level hooks) | Windows 10/11 |
23
+ | macOS | ✅ Full | Swift (CGEventTap) | macOS 10.14+ |
24
+ | Linux | ✅ X11 Only | C++ (XInput2) | Ubuntu, Arch Linux |
25
+
26
+ ## 🚀 Quick Start
27
+
28
+ ```ts
29
+ import { GlobalKeyboardListener } from "keyspy";
30
+
31
+ const keyspy = new GlobalKeyboardListener();
32
+
33
+ // Listen to all keyboard events
34
+ keyspy.addListener((e, down) => {
35
+ console.log(`${e.name} ${e.state} [${e.rawKey._nameRaw}]`);
36
+ });
37
+ ```
38
+
39
+ ## 📖 Usage Examples
40
+
41
+ ### Basic Event Logging
42
+
43
+ ```ts
44
+ import { GlobalKeyboardListener } from "keyspy";
45
+
46
+ const keyspy = new GlobalKeyboardListener();
47
+
48
+ keyspy.addListener((e, down) => {
49
+ console.log(`Key: ${e.name}, State: ${e.state}, Location: ${e.location}`);
50
+ });
51
+ ```
52
+
53
+ ### Capturing System Shortcuts
54
+
55
+ ```ts
56
+ // Capture Cmd+Space (macOS) or Win+Space (Windows)
57
+ keyspy.addListener((e, down) => {
58
+ if (e.state === "DOWN" && e.name === "SPACE" &&
59
+ (down["LEFT META"] || down["RIGHT META"])) {
60
+ console.log("System shortcut captured!");
61
+ return true; // Prevent the event from reaching other apps
62
+ }
63
+ });
64
+
65
+ // Capture Alt+F4
66
+ keyspy.addListener((e, down) => {
67
+ if (e.state === "DOWN" && e.name === "F4" &&
68
+ (down["LEFT ALT"] || down["RIGHT ALT"])) {
69
+ console.log("Alt+F4 intercepted!");
70
+ return true;
71
+ }
72
+ });
73
+ ```
74
+
75
+ ### Advanced Configuration
76
+
77
+ ```ts
78
+ const keyspy = new GlobalKeyboardListener({
79
+ windows: {
80
+ onError: (errorCode) => console.error("Windows error:", errorCode),
81
+ onInfo: (info) => console.info("Windows info:", info)
82
+ },
83
+ mac: {
84
+ onError: (errorCode) => console.error("macOS error:", errorCode),
85
+ },
86
+ x11: {
87
+ onError: (errorCode) => console.error("Linux error:", errorCode),
88
+ }
89
+ });
90
+ ```
91
+
92
+ ### Cleanup and Resource Management
93
+
94
+ ```ts
95
+ // Remove specific listener
96
+ const myListener = (e, down) => { /* ... */ };
97
+ keyspy.addListener(myListener);
98
+ keyspy.removeListener(myListener);
99
+
100
+ // Clean shutdown
101
+ keyspy.kill(); // Removes all listeners and stops the key server
102
+ ```
103
+
104
+ ## 📦 Installation
105
+
106
+ ```bash
107
+ npm install keyspy
108
+ # or
109
+ pnpm add keyspy
110
+ # or
111
+ yarn add keyspy
112
+ ```
113
+
114
+ **What happens during installation:**
115
+ 1. 📦 Downloads the main package (TypeScript code)
116
+ 2. 🔍 Detects your platform (Windows/macOS/Linux) and architecture
117
+ 3. 📥 Automatically downloads the appropriate pre-compiled binary from GitHub Releases
118
+ 4. ✅ Ready to use immediately!
119
+
120
+ ## 🤔 Why KeySpy?
121
+
122
+ Choosing the right keyboard listener for your Node.js project can be challenging. Here's how KeySpy compares to other popular solutions:
123
+
124
+ | Feature | Electron globalShortcut | IOHook | **KeySpy** |
125
+ |---------|------------------------|--------|------------|
126
+ | **Setup Complexity** | Simple | Complex (node-gyp) | **Simple** |
127
+ | **System Shortcuts** | ❌ Limited | ✅ Full | **✅ Full** |
128
+ | **Event Blocking** | ❌ No | ✅ Yes | **✅ Yes** |
129
+ | **Node.js Compatibility** | ❌ Electron only | ⚠️ Version dependent | **✅ All versions** |
130
+ | **Compilation Required** | ❌ No | ❌ Yes | **✅ No** |
131
+ | **Arbitrary Key Support** | ❌ Limited | ⚠️ Limited | **✅ Full** |
132
+ | **Process Architecture** | In-process | In-process | **Multi-process** |
133
+
134
+ ### 🎯 **KeySpy Advantages**
135
+
136
+ - **🔧 Zero Setup**: Pre-compiled binaries work out of the box
137
+ - **🌐 Universal**: Compatible with all Node.js versions (14+)
138
+ - **🔒 System-Level**: Capture any key combination, including OS shortcuts
139
+ - **🛡️ Stable**: Multi-process architecture prevents crashes
140
+ - **📝 TypeScript**: Full type definitions included
141
+ - **🎮 Flexible**: Listen to individual keys or complex combinations
142
+
143
+ ### ⚠️ **Considerations**
144
+
145
+ - **Permissions**: macOS requires Accessibility permissions
146
+ - **Antivirus**: Some antivirus software may flag the native binaries
147
+ - **Performance**: Small overhead due to inter-process communication
148
+
149
+ ## 🛠️ Development
150
+
151
+ ### Quick Development Setup
152
+
153
+ ```bash
154
+ # Clone and setup
155
+ git clone https://github.com/teomyth/keyspy.git
156
+ cd keyspy
157
+ pnpm install
158
+
159
+ # Development workflow
160
+ pnpm dev # Watch mode compilation
161
+ pnpm build # Production build
162
+ pnpm test # Run all tests
163
+ pnpm test:manual # Interactive testing
164
+ ```
165
+
166
+ ### Building Native Binaries
167
+
168
+ KeySpy includes pre-compiled binaries, but you can rebuild them if needed:
169
+
170
+ ```bash
171
+ # Platform-specific builds
172
+ pnpm build:win # Windows (requires MinGW)
173
+ pnpm build:swift # macOS (requires Xcode)
174
+ pnpm build:x11 # Linux (requires X11 dev libraries)
175
+ ```
176
+
177
+ ### Code Quality
178
+
179
+ ```bash
180
+ pnpm lint # Check code quality with Biome
181
+ pnpm lint:fix # Auto-fix issues
182
+ pnpm format # Format code
183
+ pnpm clean # Remove build artifacts
184
+ ```
185
+
186
+ ### Testing
187
+
188
+ ```bash
189
+ pnpm test:unit # Unit tests
190
+ pnpm test:integration # Integration tests
191
+ pnpm test:manual # Manual interactive testing
192
+ ```
193
+
194
+ ## 📋 API Reference
195
+
196
+ ### GlobalKeyboardListener
197
+
198
+ #### Constructor
199
+
200
+ ```ts
201
+ new GlobalKeyboardListener(config?: IConfig)
202
+ ```
203
+
204
+ #### Methods
205
+
206
+ - `addListener(listener: IGlobalKeyListener): Promise<void>` - Add event listener
207
+ - `removeListener(listener: IGlobalKeyListener): void` - Remove event listener
208
+ - `kill(): void` - Stop all listeners and cleanup
209
+
210
+ #### Event Object
211
+
212
+ ```ts
213
+ interface IGlobalKeyEvent {
214
+ name: string; // Key name (e.g., "A", "SPACE", "F1")
215
+ state: "UP" | "DOWN"; // Key state
216
+ rawKey: IGlobalKey; // Raw key information
217
+ vKey: number; // Virtual key code
218
+ scanCode: number; // Scan code
219
+ location: [number, number]; // Mouse location (for mouse events)
220
+ }
221
+ ```
222
+
223
+ ## 🔒 Security & Permissions
224
+
225
+ ### macOS
226
+ - Requires **Accessibility** permissions in System Preferences
227
+ - First run will prompt for permission automatically
228
+
229
+ ### Windows
230
+ - May require administrator privileges for system-wide hooks
231
+ - Some antivirus software may flag the binary (false positive)
232
+
233
+ ### Linux
234
+ - Requires X11 display server
235
+ - May need to run with appropriate user permissions
236
+
237
+ ## 🔧 Troubleshooting
238
+
239
+ ### Binary Download Issues
240
+
241
+ If the automatic binary download fails during installation:
242
+
243
+ ```bash
244
+ # Option 1: Manual download from GitHub Releases
245
+ # Visit: https://github.com/teomyth/keyspy/releases
246
+ # Download the appropriate file for your platform
247
+
248
+ # Option 2: Build from source
249
+ npm run build:swift # macOS
250
+ npm run build:x11 # Linux
251
+ npm run build:win # Windows
252
+
253
+ # Option 3: Skip download in CI environments
254
+ export KEYSPY_SKIP_DOWNLOAD=true
255
+ npm install keyspy
256
+ ```
257
+
258
+ ### Platform Support
259
+
260
+ - **macOS**: ARM64 (Apple Silicon) and x64 (Intel) - Universal binary
261
+ - **Linux**: x64 only, requires X11
262
+ - **Windows**: x64 only
263
+
264
+ ### Common Issues
265
+
266
+ 1. **"Binary not found"**: Run the appropriate build command for your platform
267
+ 2. **Permission denied**: Make sure the binary has execute permissions (`chmod +x`)
268
+ 3. **Network issues**: Check your internet connection and GitHub access
269
+
270
+ ## 🤝 Contributing
271
+
272
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
273
+
274
+ 1. Fork the repository
275
+ 2. Create a feature branch
276
+ 3. Make your changes
277
+ 4. Add tests if applicable
278
+ 5. Submit a pull request
279
+
280
+ ## 📄 License
281
+
282
+ MIT License - see [LICENSE](LICENSE) file for details.
283
+
284
+ ## 🙏 Acknowledgments
285
+
286
+ - Original concept inspired by [LaunchMenu](https://github.com/LaunchMenu/LaunchMenu)
287
+ - Built with modern tooling: TypeScript, Biome, Jest, and Turbo
@@ -0,0 +1,53 @@
1
+ import type { IConfig } from "./ts/_types/IConfig";
2
+ import type { IGlobalKeyListener } from "./ts/_types/IGlobalKeyListener";
3
+ import type { IGlobalKeyServer } from "./ts/_types/IGlobalKeyServer";
4
+ export * from "./ts/_types/IGlobalKeyListener";
5
+ export * from "./ts/_types/IGlobalKeyEvent";
6
+ export * from "./ts/_types/IGlobalKey";
7
+ export * from "./ts/_types/IGlobalKeyDownMap";
8
+ export * from "./ts/_types/IWindowsConfig";
9
+ export * from "./ts/_types/IConfig";
10
+ export * from "./ts/_types/IGlobalKeyResult";
11
+ /**
12
+ * A cross-platform global keyboard listener. Ideal for setting up global keyboard shortcuts
13
+ * and key-loggers (usually for automation).
14
+ * This keyserver uses low-level hooks on Windows OS and Event Taps on Mac OS, which allows
15
+ * event propagation to be halted to the rest of the operating system as well as allowing
16
+ * any key to be used for shortcuts.
17
+ */
18
+ export declare class GlobalKeyboardListener {
19
+ /** The underlying keyServer used to listen and halt propagation of events */
20
+ protected keyServer: IGlobalKeyServer;
21
+ protected listeners: Array<IGlobalKeyListener>;
22
+ protected config: IConfig;
23
+ /** Whether the server is currently running */
24
+ protected isRunning: boolean;
25
+ protected stopTimeoutID: NodeJS.Timeout | number;
26
+ /** The underlying map of keys that are being held down */
27
+ private readonly isDown;
28
+ /**
29
+ * Creates a new keyboard listener
30
+ * @param config The optional configuration for the key listener
31
+ */
32
+ constructor(config?: IConfig);
33
+ /**
34
+ * Add a global keyboard listener to the global keyboard listener server.
35
+ * @param listener The listener to add to the global keyboard listener
36
+ * @throws An exception if the process could not be started
37
+ */
38
+ addListener(listener: IGlobalKeyListener): Promise<void>;
39
+ /**
40
+ * Remove a global keyboard listener from the global keyboard listener server.
41
+ * @param listener The listener to remove from the global keyboard listener
42
+ */
43
+ removeListener(listener: IGlobalKeyListener): void;
44
+ /** Removes all listeners and destroys the key server */
45
+ kill(): void;
46
+ /** Start the key server */
47
+ protected start(): Promise<void>;
48
+ /** Stop the key server */
49
+ protected stop(): void;
50
+ /** The following listener is used to monitor which keys are being held down */
51
+ private baseListener;
52
+ }
53
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,8BAA8B,CAAC;AAE7C;;;;;;GAMG;AACH,qBAAa,sBAAsB;IACjC,6EAA6E;IAC7E,SAAS,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACtC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC/C,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC;IAE1B,8CAA8C;IAC9C,SAAS,CAAC,SAAS,UAAS;IAC5B,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAK;IAErD,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAE3C;;;OAGG;gBACgB,MAAM,GAAE,OAAY;IAmBvC;;;;OAIG;IACU,WAAW,CAAC,QAAQ,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrE;;;OAGG;IACI,cAAc,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAWzD,wDAAwD;IACjD,IAAI;IAKX,2BAA2B;IAC3B,SAAS,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOhC,0BAA0B;IAC1B,SAAS,CAAC,IAAI,IAAI,IAAI;IAKtB,+EAA+E;IAC/E,OAAO,CAAC,YAAY,CA+BlB;CACH"}
package/build/index.js ADDED
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.GlobalKeyboardListener = void 0;
21
+ const node_os_1 = __importDefault(require("node:os"));
22
+ const MacKeyServer_1 = require("./ts/MacKeyServer");
23
+ const WinKeyServer_1 = require("./ts/WinKeyServer");
24
+ const X11KeyServer_1 = require("./ts/X11KeyServer");
25
+ __exportStar(require("./ts/_types/IGlobalKeyListener"), exports);
26
+ __exportStar(require("./ts/_types/IGlobalKeyEvent"), exports);
27
+ __exportStar(require("./ts/_types/IGlobalKey"), exports);
28
+ __exportStar(require("./ts/_types/IGlobalKeyDownMap"), exports);
29
+ __exportStar(require("./ts/_types/IWindowsConfig"), exports);
30
+ __exportStar(require("./ts/_types/IConfig"), exports);
31
+ __exportStar(require("./ts/_types/IGlobalKeyResult"), exports);
32
+ /**
33
+ * A cross-platform global keyboard listener. Ideal for setting up global keyboard shortcuts
34
+ * and key-loggers (usually for automation).
35
+ * This keyserver uses low-level hooks on Windows OS and Event Taps on Mac OS, which allows
36
+ * event propagation to be halted to the rest of the operating system as well as allowing
37
+ * any key to be used for shortcuts.
38
+ */
39
+ class GlobalKeyboardListener {
40
+ /**
41
+ * Creates a new keyboard listener
42
+ * @param config The optional configuration for the key listener
43
+ */
44
+ constructor(config = {}) {
45
+ /** Whether the server is currently running */
46
+ this.isRunning = false;
47
+ this.stopTimeoutID = 0;
48
+ /** The following listener is used to monitor which keys are being held down */
49
+ this.baseListener = (event) => {
50
+ if (event.name) {
51
+ switch (event.state) {
52
+ case "DOWN":
53
+ this.isDown[event.name] = true;
54
+ break;
55
+ case "UP":
56
+ this.isDown[event.name] = false;
57
+ break;
58
+ }
59
+ }
60
+ let stopPropagation = false;
61
+ for (const onKey of this.listeners) {
62
+ //Forward event
63
+ try {
64
+ const res = onKey(event, this.isDown);
65
+ //Handle catch data
66
+ if (res instanceof Object) {
67
+ if (res.stopPropagation)
68
+ stopPropagation = true;
69
+ if (res.stopImmediatePropagation)
70
+ break;
71
+ }
72
+ else if (res) {
73
+ stopPropagation = true;
74
+ }
75
+ }
76
+ catch (e) {
77
+ console.error(e);
78
+ }
79
+ }
80
+ return stopPropagation;
81
+ };
82
+ this.listeners = [];
83
+ this.isDown = {};
84
+ this.config = config;
85
+ switch (node_os_1.default.platform()) {
86
+ case "win32":
87
+ this.keyServer = new WinKeyServer_1.WinKeyServer(this.baseListener, config.windows);
88
+ break;
89
+ case "darwin":
90
+ this.keyServer = new MacKeyServer_1.MacKeyServer(this.baseListener, config.mac);
91
+ break;
92
+ case "linux":
93
+ this.keyServer = new X11KeyServer_1.X11KeyServer(this.baseListener, config.x11);
94
+ break;
95
+ default:
96
+ throw Error("This OS is not supported");
97
+ }
98
+ }
99
+ /**
100
+ * Add a global keyboard listener to the global keyboard listener server.
101
+ * @param listener The listener to add to the global keyboard listener
102
+ * @throws An exception if the process could not be started
103
+ */
104
+ async addListener(listener) {
105
+ this.listeners.push(listener);
106
+ if (this.listeners.length === 1) {
107
+ clearTimeout(this.stopTimeoutID);
108
+ await this.start();
109
+ }
110
+ }
111
+ /**
112
+ * Remove a global keyboard listener from the global keyboard listener server.
113
+ * @param listener The listener to remove from the global keyboard listener
114
+ */
115
+ removeListener(listener) {
116
+ var _a;
117
+ const index = this.listeners.indexOf(listener);
118
+ if (index !== -1) {
119
+ this.listeners.splice(index, 1);
120
+ if (this.listeners.length === 0) {
121
+ if (this.config.disposeDelay === -1)
122
+ this.stop();
123
+ else
124
+ this.stopTimeoutID = setTimeout(() => this.stop(), (_a = this.config.disposeDelay) !== null && _a !== void 0 ? _a : 100);
125
+ }
126
+ }
127
+ }
128
+ /** Removes all listeners and destroys the key server */
129
+ kill() {
130
+ this.listeners = [];
131
+ this.stop();
132
+ }
133
+ /** Start the key server */
134
+ start() {
135
+ let promise = Promise.resolve();
136
+ if (!this.isRunning)
137
+ promise = this.keyServer.start();
138
+ this.isRunning = true;
139
+ return promise;
140
+ }
141
+ /** Stop the key server */
142
+ stop() {
143
+ if (this.isRunning)
144
+ this.keyServer.stop();
145
+ this.isRunning = false;
146
+ }
147
+ }
148
+ exports.GlobalKeyboardListener = GlobalKeyboardListener;
149
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxzREFBeUI7QUFDekIsb0RBQWlEO0FBQ2pELG9EQUFpRDtBQUNqRCxvREFBaUQ7QUFPakQsaUVBQStDO0FBQy9DLDhEQUE0QztBQUM1Qyx5REFBdUM7QUFDdkMsZ0VBQThDO0FBQzlDLDZEQUEyQztBQUMzQyxzREFBb0M7QUFDcEMsK0RBQTZDO0FBRTdDOzs7Ozs7R0FNRztBQUNILE1BQWEsc0JBQXNCO0lBYWpDOzs7T0FHRztJQUNILFlBQW1CLFNBQWtCLEVBQUU7UUFYdkMsOENBQThDO1FBQ3BDLGNBQVMsR0FBRyxLQUFLLENBQUM7UUFDbEIsa0JBQWEsR0FBNEIsQ0FBQyxDQUFDO1FBNEVyRCwrRUFBK0U7UUFDdkUsaUJBQVksR0FBMEIsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUN0RCxJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDZixRQUFRLEtBQUssQ0FBQyxLQUFLLEVBQUUsQ0FBQztvQkFDcEIsS0FBSyxNQUFNO3dCQUNULElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQzt3QkFDL0IsTUFBTTtvQkFDUixLQUFLLElBQUk7d0JBQ1AsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO3dCQUNoQyxNQUFNO2dCQUNWLENBQUM7WUFDSCxDQUFDO1lBRUQsSUFBSSxlQUFlLEdBQUcsS0FBSyxDQUFDO1lBQzVCLEtBQUssTUFBTSxLQUFLLElBQUksSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNuQyxlQUFlO2dCQUNmLElBQUksQ0FBQztvQkFDSCxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztvQkFF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
@@ -0,0 +1,45 @@
1
+ import type { IGlobalKeyServer } from "./_types/IGlobalKeyServer";
2
+ import type { IGlobalKeyListenerRaw } from "./_types/IGlobalKeyListenerRaw";
3
+ import type { IGlobalKeyEvent } from "./_types/IGlobalKeyEvent";
4
+ import type { IMacConfig } from "./_types/IMacConfig";
5
+ /** Use this class to listen to key events on Mac OS */
6
+ export declare class MacKeyServer implements IGlobalKeyServer {
7
+ protected listener: IGlobalKeyListenerRaw;
8
+ private proc;
9
+ private config;
10
+ private running;
11
+ private restarting;
12
+ /**
13
+ * Creates a new key server for mac
14
+ * @param listener The callback to report key events to
15
+ * @param config Additional optional configuration for the server
16
+ */
17
+ constructor(listener: IGlobalKeyListenerRaw, config?: IMacConfig);
18
+ /**
19
+ * Start the Key server and listen for keypresses
20
+ * @param skipPerms Whether to skip attempting to add permissions
21
+ */
22
+ start(skipPerms?: boolean): Promise<void>;
23
+ /**
24
+ * Deals with the startup process of the server, possibly adding perms if required and restarting
25
+ * @param skipPerms Whether to skip attempting to add permissions
26
+ */
27
+ protected handleStartup(skipPerms: boolean): Promise<void>;
28
+ /**
29
+ * Makes sure that the given path is executable
30
+ * @param path The path to add the perms to
31
+ */
32
+ protected addPerms(path: string): Promise<void>;
33
+ /** Stop the Key server */
34
+ stop(): void;
35
+ /**
36
+ * Obtains a IGlobalKeyEvent from stdout buffer data
37
+ * @param data Data from stdout
38
+ * @returns The standardized key event data
39
+ */
40
+ protected _getEventData(data: Buffer): {
41
+ event: IGlobalKeyEvent;
42
+ eventId: string;
43
+ }[];
44
+ }
45
+ //# sourceMappingURL=MacKeyServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MacKeyServer.d.ts","sourceRoot":"","sources":["../../src/ts/MacKeyServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAElE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAKtD,uDAAuD;AACvD,qBAAa,YAAa,YAAW,gBAAgB;IACnD,SAAS,CAAC,QAAQ,EAAE,qBAAqB,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,MAAM,CAAa;IAE3B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;IAE3B;;;;OAIG;gBACS,QAAQ,EAAE,qBAAqB,EAAE,MAAM,GAAE,UAAe;IAKpE;;;OAGG;IACI,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BhD;;;OAGG;IACH,SAAS,CAAC,aAAa,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAwC1D;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB/C,0BAA0B;IACnB,IAAI;IAMX;;;;OAIG;IACH,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,eAAe,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE;CAiCrF"}