@mediar-ai/terminator 0.20.6
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/Cargo.toml +23 -0
- package/README.md +216 -0
- package/build.rs +4 -0
- package/index.d.ts +738 -0
- package/index.js +321 -0
- package/node_example.js +64 -0
- package/package.json +64 -0
- package/src/desktop.rs +520 -0
- package/src/element.rs +581 -0
- package/src/exceptions.rs +58 -0
- package/src/lib.rs +20 -0
- package/src/locator.rs +172 -0
- package/src/selector.rs +139 -0
- package/src/types.rs +308 -0
- package/sync-version.js +60 -0
- package/test-tree.js +83 -0
- package/tests/comprehensive-ui-elements.test.js +524 -0
- package/tests/element-chaining.test.js +158 -0
- package/tests/element-range.test.js +207 -0
- package/tests/element-scroll-into-view.test.js +256 -0
- package/tests/element-value.test.js +264 -0
- package/tests/locator-validate.test.js +260 -0
- package/tests/locator-waitfor.test.js +286 -0
- package/wrapper.d.ts +42 -0
- package/wrapper.js +170 -0
package/Cargo.toml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "terminator-node-bindings"
|
|
3
|
+
version.workspace = true
|
|
4
|
+
edition.workspace = true
|
|
5
|
+
|
|
6
|
+
[lib]
|
|
7
|
+
name = "terminator_node_bindings"
|
|
8
|
+
crate-type = ["cdylib"]
|
|
9
|
+
|
|
10
|
+
[dependencies]
|
|
11
|
+
# NAPI for Node.js bindings
|
|
12
|
+
# Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
|
|
13
|
+
napi = { version = "2.12.2", default-features = false, features = [
|
|
14
|
+
"napi4",
|
|
15
|
+
"tokio_rt",
|
|
16
|
+
] }
|
|
17
|
+
napi-derive = "2.12.2"
|
|
18
|
+
terminator = { workspace = true }
|
|
19
|
+
tracing-subscriber = { workspace = true }
|
|
20
|
+
serde_json = "1.0"
|
|
21
|
+
|
|
22
|
+
[build-dependencies]
|
|
23
|
+
napi-build = "2.0.1"
|
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# @mediar-ai/terminator
|
|
2
|
+
|
|
3
|
+
Node.js/TypeScript bindings for the Terminator Rust library - AI-native GUI automation for Windows, macOS, and Linux.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @mediar-ai/terminator
|
|
9
|
+
# or
|
|
10
|
+
bun install @mediar-ai/terminator
|
|
11
|
+
# or
|
|
12
|
+
yarn add @mediar-ai/terminator
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
const { Desktop } = require('@mediar-ai/terminator');
|
|
19
|
+
|
|
20
|
+
async function main() {
|
|
21
|
+
const desktop = new Desktop();
|
|
22
|
+
|
|
23
|
+
// Get root element
|
|
24
|
+
const root = desktop.root();
|
|
25
|
+
console.log('Root element:', root.role(), root.name());
|
|
26
|
+
|
|
27
|
+
// Find and click a button
|
|
28
|
+
const locator = desktop.locator('role:button');
|
|
29
|
+
try {
|
|
30
|
+
const button = await locator.first(0); // timeout in ms (0 = immediate, no retry)
|
|
31
|
+
console.log('Found button:', button.name());
|
|
32
|
+
await button.click();
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.log('Button not found:', error.message);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Take a screenshot
|
|
38
|
+
const screenshot = await desktop.captureScreen();
|
|
39
|
+
console.log(`Screenshot: ${screenshot.width}x${screenshot.height}`);
|
|
40
|
+
|
|
41
|
+
// Run a command
|
|
42
|
+
const result = await desktop.runCommand('echo hello', 'echo hello');
|
|
43
|
+
console.log('Command output:', result.stdout);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
main().catch(console.error);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## TypeScript Support
|
|
50
|
+
|
|
51
|
+
This package includes TypeScript definitions out of the box:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { Desktop, ElementNotFoundError } from '@mediar-ai/terminator';
|
|
55
|
+
|
|
56
|
+
const desktop = new Desktop();
|
|
57
|
+
const root = desktop.root();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Error Handling
|
|
61
|
+
|
|
62
|
+
The library provides specific error types for better error handling:
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
const {
|
|
66
|
+
Desktop,
|
|
67
|
+
ElementNotFoundError,
|
|
68
|
+
TimeoutError,
|
|
69
|
+
PermissionDeniedError
|
|
70
|
+
} = require('@mediar-ai/terminator');
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const button = await desktop.locator('role:button').first(1000); // wait up to 1 second
|
|
74
|
+
await button.click();
|
|
75
|
+
} catch (error) {
|
|
76
|
+
if (error instanceof ElementNotFoundError) {
|
|
77
|
+
console.log('Element not found');
|
|
78
|
+
} else if (error instanceof TimeoutError) {
|
|
79
|
+
console.log('Operation timed out');
|
|
80
|
+
} else if (error instanceof PermissionDeniedError) {
|
|
81
|
+
console.log('Permission denied');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Platform Support
|
|
87
|
+
|
|
88
|
+
- ✅ Windows (x64)
|
|
89
|
+
|
|
90
|
+
## API Reference
|
|
91
|
+
|
|
92
|
+
### Desktop
|
|
93
|
+
|
|
94
|
+
- `new Desktop()` - Create a new desktop automation instance
|
|
95
|
+
- `root()` - Get the root element
|
|
96
|
+
- `applications()` - List all applications
|
|
97
|
+
- `locator(selector)` - Create a locator for finding elements
|
|
98
|
+
- `captureScreen()` - Take a screenshot
|
|
99
|
+
- `runCommand(windowsCmd, unixCmd)` - Run a system command
|
|
100
|
+
- `executeBrowserScript(script)` - Execute JavaScript in focused browser tab
|
|
101
|
+
- `navigateBrowser(url, browser?)` - Navigate to URL in specified browser
|
|
102
|
+
- `delay(delayMs)` - Delay execution for specified milliseconds
|
|
103
|
+
|
|
104
|
+
### Element
|
|
105
|
+
|
|
106
|
+
- `click()` - Click the element
|
|
107
|
+
- `type(text)` - Type text into the element
|
|
108
|
+
- `scrollIntoView()` - Scroll element into view if off-screen
|
|
109
|
+
- `role()` - Get element role
|
|
110
|
+
- `name()` - Get element name
|
|
111
|
+
- `children()` - Get child elements
|
|
112
|
+
- `isToggled()` - Check if toggleable control is toggled
|
|
113
|
+
- `setToggled(state)` - Set toggle state (checkbox, toggle switch)
|
|
114
|
+
- `isSelected()` - Check if element is selected (list item, tree node, tab)
|
|
115
|
+
- `setSelected(state)` - Set selection state
|
|
116
|
+
- `getRangeValue()` - Get value from range control (slider, progress bar)
|
|
117
|
+
- `setRangeValue(value)` - Set value of range control
|
|
118
|
+
- `getValue()` - Get value attribute (text inputs, combo boxes)
|
|
119
|
+
|
|
120
|
+
### Locator
|
|
121
|
+
|
|
122
|
+
- `first(timeoutMs)` - Get the first matching element (timeout in milliseconds required)
|
|
123
|
+
- `all(timeoutMs, depth?)` - Get all matching elements (timeout in milliseconds required)
|
|
124
|
+
- `validate(timeoutMs)` - Validate element existence without throwing (returns `{exists, element?, error?}`)
|
|
125
|
+
- `waitFor(condition, timeoutMs)` - Wait for element to meet condition ('exists', 'visible', 'enabled', 'focused')
|
|
126
|
+
- `timeout(timeoutMs)` - Set default timeout for this locator
|
|
127
|
+
- `within(element)` - Scope search to an element
|
|
128
|
+
- `locator(selector)` - Chain another selector
|
|
129
|
+
|
|
130
|
+
## Examples
|
|
131
|
+
|
|
132
|
+
### Element Validation
|
|
133
|
+
|
|
134
|
+
The `validate()` method is useful for conditional logic when you need to check if an element exists without throwing an error:
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
const { Desktop } = require('@mediar-ai/terminator');
|
|
138
|
+
|
|
139
|
+
async function main() {
|
|
140
|
+
const desktop = new Desktop();
|
|
141
|
+
|
|
142
|
+
// Check if a submit button exists
|
|
143
|
+
const result = await desktop.locator('role:button|Submit').validate(5000);
|
|
144
|
+
|
|
145
|
+
if (result.exists) {
|
|
146
|
+
console.log('Submit button found!');
|
|
147
|
+
await result.element.click();
|
|
148
|
+
} else {
|
|
149
|
+
console.log('Submit button not found, showing alternative flow');
|
|
150
|
+
// Handle the case where element doesn't exist
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// You can also check for errors (invalid selector, platform errors)
|
|
154
|
+
if (result.error) {
|
|
155
|
+
console.error('Validation error:', result.error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
main().catch(console.error);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Key differences between `validate()` and `first()`:**
|
|
163
|
+
- `first()` throws an error if element is not found
|
|
164
|
+
- `validate()` returns `{exists: false}` if element is not found
|
|
165
|
+
- Use `validate()` for optional elements or conditional logic
|
|
166
|
+
- Use `first()` when you expect the element to exist
|
|
167
|
+
|
|
168
|
+
### Conditional Waiting
|
|
169
|
+
|
|
170
|
+
The `waitFor()` method waits for an element to meet a specific condition. This is useful for dynamic UIs where elements change state:
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
const { Desktop } = require('@mediar-ai/terminator');
|
|
174
|
+
|
|
175
|
+
async function main() {
|
|
176
|
+
const desktop = new Desktop();
|
|
177
|
+
|
|
178
|
+
// Wait for a button to become visible (not just exist)
|
|
179
|
+
const submitButton = await desktop
|
|
180
|
+
.locator('role:button|Submit')
|
|
181
|
+
.waitFor('visible', 10000);
|
|
182
|
+
|
|
183
|
+
await submitButton.click();
|
|
184
|
+
|
|
185
|
+
// Wait for a button to become enabled after form validation
|
|
186
|
+
const nextButton = await desktop
|
|
187
|
+
.locator('role:button|Next')
|
|
188
|
+
.waitFor('enabled', 5000);
|
|
189
|
+
|
|
190
|
+
await nextButton.click();
|
|
191
|
+
|
|
192
|
+
// Wait for an input field to receive focus
|
|
193
|
+
const nameInput = await desktop
|
|
194
|
+
.locator('role:textfield|Name')
|
|
195
|
+
.waitFor('focused', 3000);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
main().catch(console.error);
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Available conditions:**
|
|
202
|
+
- `'exists'` - Wait for element to appear in the UI
|
|
203
|
+
- `'visible'` - Wait for element to be visible
|
|
204
|
+
- `'enabled'` - Wait for element to be enabled (not disabled)
|
|
205
|
+
- `'focused'` - Wait for element to have keyboard focus
|
|
206
|
+
|
|
207
|
+
**Key differences:**
|
|
208
|
+
- `first()` - Waits for element to exist, throws if not found
|
|
209
|
+
- `validate()` - Checks if element exists, never throws
|
|
210
|
+
- `waitFor()` - Waits for specific condition to be met, throws on timeout
|
|
211
|
+
|
|
212
|
+
See the [examples directory](https://github.com/mediar-ai/terminator/tree/main/examples) for more usage examples.
|
|
213
|
+
|
|
214
|
+
## Repository
|
|
215
|
+
|
|
216
|
+
https://github.com/mediar-ai/terminator
|
package/build.rs
ADDED