@mobilewright/driver-mobile-use 0.0.1

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.
@@ -0,0 +1,39 @@
1
+ import type { AppInfo, ConnectionConfig, DeviceInfo, GestureSequence, HardwareButton, LaunchOptions, ListDevicesOptions, MobilewrightDriver, Orientation, RecordingOptions, RecordingResult, ScreenSize, ScreenshotOptions, Session, SwipeDirection, SwipeOptions, ViewNode } from '@mobilewright/protocol';
2
+ export declare const DEFAULT_URL = "wss://api.mobilenexthq.com/ws";
3
+ export interface MobileUseDriverOptions {
4
+ region?: string;
5
+ apiKey?: string;
6
+ }
7
+ export declare class MobileUseDriver implements MobilewrightDriver {
8
+ private session;
9
+ private readonly options;
10
+ constructor(options?: MobileUseDriverOptions);
11
+ connect(config: ConnectionConfig): Promise<Session>;
12
+ disconnect(): Promise<void>;
13
+ private buildFilters;
14
+ getViewHierarchy(): Promise<ViewNode[]>;
15
+ tap(x: number, y: number): Promise<void>;
16
+ doubleTap(x: number, y: number): Promise<void>;
17
+ longPress(x: number, y: number, duration?: number): Promise<void>;
18
+ typeText(text: string): Promise<void>;
19
+ swipe(direction: SwipeDirection, opts?: SwipeOptions): Promise<void>;
20
+ gesture(gestures: GestureSequence): Promise<void>;
21
+ pressButton(button: HardwareButton): Promise<void>;
22
+ screenshot(opts?: ScreenshotOptions): Promise<Buffer>;
23
+ getScreenSize(): Promise<ScreenSize>;
24
+ getOrientation(): Promise<Orientation>;
25
+ setOrientation(orientation: Orientation): Promise<void>;
26
+ startRecording(opts: RecordingOptions): Promise<void>;
27
+ stopRecording(): Promise<RecordingResult>;
28
+ launchApp(bundleId: string, opts?: LaunchOptions): Promise<void>;
29
+ terminateApp(bundleId: string): Promise<void>;
30
+ listApps(): Promise<AppInfo[]>;
31
+ getForegroundApp(): Promise<AppInfo>;
32
+ installApp(path: string): Promise<void>;
33
+ uninstallApp(bundleId: string): Promise<void>;
34
+ listDevices(opts?: ListDevicesOptions): Promise<DeviceInfo[]>;
35
+ openUrl(url: string): Promise<void>;
36
+ private call;
37
+ private requireSession;
38
+ }
39
+ //# sourceMappingURL=driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,gBAAgB,EAChB,UAAU,EAGV,eAAe,EACf,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EAEX,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,QAAQ,EACT,MAAM,wBAAwB,CAAC;AAGhC,eAAO,MAAM,WAAW,kCAAkC,CAAC;AA6D3D,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA0DD,qBAAa,eAAgB,YAAW,kBAAkB;IACxD,OAAO,CAAC,OAAO,CAAyE;IACxF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;gBAErC,OAAO,GAAE,sBAA2B;IAM1C,OAAO,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBnD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IASjC,OAAO,CAAC,YAAY;IAqBd,gBAAgB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAOvC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK9C,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,KAAK,CAAC,SAAS,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BpE,OAAO,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjD,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlD,UAAU,CAAC,IAAI,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAarD,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC;IAMpC,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAKtC,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvD,cAAc,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrD,aAAa,IAAI,OAAO,CAAC,eAAe,CAAC;IAMzC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhE,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAW9B,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IASpC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7C,WAAW,CAAC,IAAI,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAwB7D,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzC,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,cAAc;CAMvB"}
package/dist/driver.js ADDED
@@ -0,0 +1,247 @@
1
+ import createDebug from 'debug';
2
+ import { RpcClient } from './rpc-client.js';
3
+ export const DEFAULT_URL = 'wss://api.mobilenexthq.com/ws';
4
+ const VALID_PLATFORMS = new Set(['ios', 'android']);
5
+ const VALID_DEVICE_TYPES = new Set(['real', 'simulator', 'emulator']);
6
+ const VALID_DEVICE_STATES = new Set(['online', 'offline']);
7
+ function toPlatform(value) {
8
+ return VALID_PLATFORMS.has(value) ? value : undefined;
9
+ }
10
+ function toDeviceType(value) {
11
+ return VALID_DEVICE_TYPES.has(value) ? value : 'real';
12
+ }
13
+ function toDeviceState(value) {
14
+ return VALID_DEVICE_STATES.has(value) ? value : 'offline';
15
+ }
16
+ function elementToViewNode(el) {
17
+ const bounds = el.rect ?? { x: 0, y: 0, width: 0, height: 0 };
18
+ return {
19
+ type: el.type ?? 'Unknown',
20
+ label: el.label || undefined,
21
+ identifier: el.identifier || el.name || undefined,
22
+ value: el.value || undefined,
23
+ text: el.label || undefined,
24
+ isVisible: typeof el.visible === 'boolean' ? el.visible : bounds.width > 0 && bounds.height > 0,
25
+ isEnabled: el.enabled ?? true,
26
+ bounds,
27
+ children: el.children?.map(elementToViewNode) ?? [],
28
+ raw: { ...el },
29
+ };
30
+ }
31
+ function appendQueryParam(url, key, value) {
32
+ const separator = url.includes('?') ? '&' : '?';
33
+ return `${url}${separator}${key}=${encodeURIComponent(value)}`;
34
+ }
35
+ const debug = createDebug('mw:driver-mobile-use');
36
+ export class MobileUseDriver {
37
+ constructor(options = {}) {
38
+ this.session = null;
39
+ this.options = options;
40
+ }
41
+ // ─── Connection ──────────────────────────────────────────────
42
+ async connect(config) {
43
+ const baseUrl = config.url ?? DEFAULT_URL;
44
+ const url = this.options.apiKey
45
+ ? appendQueryParam(baseUrl, 'token', this.options.apiKey)
46
+ : baseUrl;
47
+ debug('connecting to %s', baseUrl);
48
+ const rpc = new RpcClient(url, config.timeout);
49
+ await rpc.connect();
50
+ debug('websocket connected');
51
+ const platform = config.platform;
52
+ const filters = this.buildFilters(config);
53
+ debug('allocating device with filters %o', filters);
54
+ const result = await rpc.call('fleet.allocate', { filters });
55
+ debug('allocated device %s (session=%s, model=%s)', result.device.id, result.sessionId, result.device.model);
56
+ const deviceId = result.device.id;
57
+ this.session = { deviceId, platform, rpc };
58
+ return { deviceId, platform };
59
+ }
60
+ async disconnect() {
61
+ const session = this.requireSession();
62
+ debug('releasing device %s', session.deviceId);
63
+ await session.rpc.call('fleet.release', { deviceId: session.deviceId });
64
+ await session.rpc.disconnect();
65
+ this.session = null;
66
+ debug('disconnected');
67
+ }
68
+ buildFilters(config) {
69
+ const filters = [
70
+ { attribute: 'platform', operator: 'EQUALS', value: config.platform },
71
+ ];
72
+ if (config.deviceName) {
73
+ const name = typeof config.deviceName === 'string'
74
+ ? config.deviceName
75
+ : config.deviceName.source;
76
+ filters.push({ attribute: 'name', operator: 'CONTAINS', value: name });
77
+ }
78
+ if (config.osVersion) {
79
+ filters.push({ attribute: 'version', operator: 'EQUALS', value: config.osVersion });
80
+ }
81
+ return filters;
82
+ }
83
+ // ─── UI hierarchy ───────────────────────────────────────────
84
+ async getViewHierarchy() {
85
+ const result = await this.call('device.dump.ui');
86
+ return result.elements.map(elementToViewNode);
87
+ }
88
+ // ─── Input ──────────────────────────────────────────────────
89
+ async tap(x, y) {
90
+ await this.call('device.io.tap', { x: Math.round(x), y: Math.round(y) });
91
+ }
92
+ async doubleTap(x, y) {
93
+ await this.call('device.io.tap', { x, y });
94
+ await this.call('device.io.tap', { x, y });
95
+ }
96
+ async longPress(x, y, duration) {
97
+ await this.call('device.io.longpress', { x, y, ...(duration !== undefined && { duration }) });
98
+ }
99
+ async typeText(text) {
100
+ await this.call('device.io.text', { text });
101
+ }
102
+ async swipe(direction, opts) {
103
+ const screen = await this.getScreenSize();
104
+ const centerX = screen.width / 2;
105
+ const centerY = screen.height / 2;
106
+ const startX = opts?.startX ?? centerX;
107
+ const startY = opts?.startY ?? centerY;
108
+ const isHorizontal = direction === 'left' || direction === 'right';
109
+ const defaultDistance = (isHorizontal ? screen.width : screen.height) * 0.5;
110
+ const distance = opts?.distance ?? defaultDistance;
111
+ let endX = startX;
112
+ let endY = startY;
113
+ switch (direction) {
114
+ case 'up':
115
+ endY = startY - distance;
116
+ break;
117
+ case 'down':
118
+ endY = startY + distance;
119
+ break;
120
+ case 'left':
121
+ endX = startX - distance;
122
+ break;
123
+ case 'right':
124
+ endX = startX + distance;
125
+ break;
126
+ }
127
+ await this.call('device.io.swipe', {
128
+ x1: Math.round(startX),
129
+ y1: Math.round(startY),
130
+ x2: Math.round(endX),
131
+ y2: Math.round(endY),
132
+ ...(opts?.duration !== undefined && { duration: opts.duration }),
133
+ });
134
+ }
135
+ async gesture(gestures) {
136
+ await this.call('device.io.gesture', { actions: gestures.pointers });
137
+ }
138
+ async pressButton(button) {
139
+ await this.call('device.io.button', { button });
140
+ }
141
+ // ─── Screen ─────────────────────────────────────────────────
142
+ async screenshot(opts) {
143
+ const result = await this.call('device.screenshot', {
144
+ ...(opts?.format && { format: opts.format }),
145
+ ...(opts?.quality !== undefined && { quality: opts.quality }),
146
+ });
147
+ let b64 = result.data;
148
+ const commaIdx = b64.indexOf(',');
149
+ if (commaIdx !== -1) {
150
+ b64 = b64.slice(commaIdx + 1);
151
+ }
152
+ return Buffer.from(b64, 'base64');
153
+ }
154
+ async getScreenSize() {
155
+ const result = await this.call('device.info');
156
+ const info = result.device;
157
+ return info.screenSize ?? { width: info.screenWidth ?? 0, height: info.screenHeight ?? 0, scale: 1 };
158
+ }
159
+ async getOrientation() {
160
+ const result = await this.call('device.io.orientation.get');
161
+ return result.orientation === 'landscape' ? 'landscape' : 'portrait';
162
+ }
163
+ async setOrientation(orientation) {
164
+ await this.call('device.io.orientation.set', { orientation });
165
+ }
166
+ // ─── Recording ──────────────────────────────────────────────
167
+ async startRecording(opts) {
168
+ await this.call('device.screenrecord', {
169
+ output: opts.output,
170
+ ...(opts.timeLimit !== undefined && { timeLimit: opts.timeLimit }),
171
+ });
172
+ }
173
+ async stopRecording() {
174
+ return this.call('device.screenrecord.stop');
175
+ }
176
+ // ─── Apps ───────────────────────────────────────────────────
177
+ async launchApp(bundleId, opts) {
178
+ await this.call('device.apps.launch', {
179
+ bundleId,
180
+ ...(opts?.locales && { locales: opts.locales }),
181
+ });
182
+ }
183
+ async terminateApp(bundleId) {
184
+ await this.call('device.apps.terminate', { bundleId });
185
+ }
186
+ async listApps() {
187
+ // iOS returns a flat array, Android returns { apps: [...] }.
188
+ const result = await this.call('device.apps.list');
189
+ const apps = Array.isArray(result) ? result : result.apps;
190
+ return apps.map((app) => ({
191
+ bundleId: app.bundleId ?? app.packageName ?? '',
192
+ name: app.appName,
193
+ version: app.version,
194
+ }));
195
+ }
196
+ async getForegroundApp() {
197
+ const result = await this.call('device.apps.foreground');
198
+ return {
199
+ bundleId: result.bundleId ?? result.packageName ?? '',
200
+ name: result.appName,
201
+ version: result.version,
202
+ };
203
+ }
204
+ async installApp(path) {
205
+ await this.call('device.apps.install', { path });
206
+ }
207
+ async uninstallApp(bundleId) {
208
+ await this.call('device.apps.uninstall', { bundleId });
209
+ }
210
+ // ─── Device ─────────────────────────────────────────────────
211
+ async listDevices(opts) {
212
+ const result = await this.call('device.list');
213
+ let devices = result.data.devices;
214
+ if (opts?.platform) {
215
+ devices = devices.filter((d) => d.platform === opts.platform);
216
+ }
217
+ if (opts?.state) {
218
+ devices = devices.filter((d) => d.state === opts.state);
219
+ }
220
+ return devices
221
+ .filter((d) => toPlatform(d.platform) !== undefined)
222
+ .map((d) => ({
223
+ id: d.id ?? d.udid ?? '',
224
+ name: d.name,
225
+ platform: toPlatform(d.platform),
226
+ type: toDeviceType(d.type),
227
+ state: toDeviceState(d.state),
228
+ model: d.model,
229
+ osVersion: d.version,
230
+ }));
231
+ }
232
+ async openUrl(url) {
233
+ await this.call('device.url', { url });
234
+ }
235
+ // ─── Helpers ────────────────────────────────────────────────
236
+ call(method, params) {
237
+ const session = this.requireSession();
238
+ return session.rpc.call(method, { deviceId: session.deviceId, ...params });
239
+ }
240
+ requireSession() {
241
+ if (!this.session) {
242
+ throw new Error('No active session. Call connect() first.');
243
+ }
244
+ return this.session;
245
+ }
246
+ }
247
+ //# sourceMappingURL=driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=example.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example.d.ts","sourceRoot":"","sources":["../src/example.ts"],"names":[],"mappings":""}
@@ -0,0 +1,39 @@
1
+ import { writeFileSync } from 'node:fs';
2
+ import { MobileUseDriver } from './driver.js';
3
+ const API_KEY = "mob_Z2WFuDmQR3v7A5HJN1bJ18UjETPr4cDueZEt";
4
+ async function main() {
5
+ const driver = new MobileUseDriver({
6
+ // region: 'us-west-2',
7
+ // apiKey: 'your-api-key',
8
+ apiKey: API_KEY,
9
+ });
10
+ // Connect to a device
11
+ const session = await driver.connect({
12
+ platform: 'ios',
13
+ });
14
+ console.log('Connected:', session);
15
+ // Get screen size
16
+ const screenSize = await driver.getScreenSize();
17
+ console.log('Screen size:', screenSize);
18
+ // Get orientation
19
+ const orientation = await driver.getOrientation();
20
+ console.log('Orientation:', orientation);
21
+ // Take a screenshot and save to file
22
+ const screenshot = await driver.screenshot();
23
+ writeFileSync('screenshot.png', screenshot);
24
+ console.log('Screenshot saved to screenshot.png (%d bytes)', screenshot.length);
25
+ // List elements on screen
26
+ const elements = await driver.getViewHierarchy();
27
+ console.log('Elements on screen:', JSON.stringify(elements, null, 2));
28
+ // Type text
29
+ await driver.typeText('Hello from mobile-use driver!');
30
+ console.log('Typed text on screen');
31
+ // Disconnect
32
+ await driver.disconnect();
33
+ console.log('Disconnected');
34
+ }
35
+ main().catch((err) => {
36
+ console.error(err);
37
+ process.exit(1);
38
+ });
39
+ //# sourceMappingURL=example.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example.js","sourceRoot":"","sources":["../src/example.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,OAAO,GAAG,0CAA0C,CAAC;AAE3D,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,uBAAuB;QACvB,0BAA0B;QAC1B,MAAM,EAAE,OAAO;KAChB,CAAC,CAAC;IAEH,sBAAsB;IACtB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC;QACnC,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAEnC,kBAAkB;IAClB,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;IAExC,kBAAkB;IAClB,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAEzC,qCAAqC;IACrC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;IAC7C,aAAa,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,+CAA+C,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAEhF,0BAA0B;IAC1B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,gBAAgB,EAAE,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAEtE,YAAY;IACZ,MAAM,MAAM,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAEpC,aAAa;IACb,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;IAC1B,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;AAC9B,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { MobileUseDriver, DEFAULT_URL, type MobileUseDriverOptions } from './driver.js';
2
+ export { RpcClient } from './rpc-client.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { MobileUseDriver, DEFAULT_URL } from './driver.js';
2
+ export { RpcClient } from './rpc-client.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,WAAW,EAA+B,MAAM,aAAa,CAAC;AACxF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,36 @@
1
+ export declare class RpcError extends Error {
2
+ readonly code: number;
3
+ readonly data?: unknown | undefined;
4
+ constructor(message: string, code: number, data?: unknown | undefined);
5
+ }
6
+ export interface JsonRpcRequest {
7
+ jsonrpc: '2.0';
8
+ id: number;
9
+ method: string;
10
+ params?: Record<string, unknown>;
11
+ }
12
+ export interface JsonRpcResponse {
13
+ jsonrpc: '2.0';
14
+ id: number;
15
+ result?: unknown;
16
+ error?: {
17
+ code: number;
18
+ message: string;
19
+ data?: unknown;
20
+ };
21
+ }
22
+ export declare class RpcClient {
23
+ private url;
24
+ private requestTimeout;
25
+ private ws;
26
+ private nextId;
27
+ private pending;
28
+ private connectionPromise;
29
+ constructor(url: string, requestTimeout?: number);
30
+ connect(): Promise<void>;
31
+ call<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
32
+ disconnect(): Promise<void>;
33
+ get isConnected(): boolean;
34
+ private handleMessage;
35
+ }
36
+ //# sourceMappingURL=rpc-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-client.d.ts","sourceRoot":"","sources":["../src/rpc-client.ts"],"names":[],"mappings":"AAEA,qBAAa,QAAS,SAAQ,KAAK;IAG/B,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO;gBAFvB,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,YAAA;CAK1B;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3D;AAQD,qBAAa,SAAS;IAOlB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,cAAc;IAPxB,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,iBAAiB,CAA8B;gBAG7C,GAAG,EAAE,MAAM,EACX,cAAc,SAAS;IAG3B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAmExB,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAiCP,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAOjC,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,OAAO,CAAC,aAAa;CA0BtB"}
@@ -0,0 +1,140 @@
1
+ import WebSocket from 'ws';
2
+ export class RpcError extends Error {
3
+ constructor(message, code, data) {
4
+ super(message);
5
+ this.code = code;
6
+ this.data = data;
7
+ this.name = 'RpcError';
8
+ }
9
+ }
10
+ export class RpcClient {
11
+ constructor(url, requestTimeout = 30_000) {
12
+ this.url = url;
13
+ this.requestTimeout = requestTimeout;
14
+ this.ws = null;
15
+ this.nextId = 1;
16
+ this.pending = new Map();
17
+ this.connectionPromise = null;
18
+ }
19
+ async connect() {
20
+ if (this.ws?.readyState === WebSocket.OPEN) {
21
+ return;
22
+ }
23
+ if (this.connectionPromise) {
24
+ return this.connectionPromise;
25
+ }
26
+ this.connectionPromise = new Promise((resolve, reject) => {
27
+ let settled = false;
28
+ const ws = new WebSocket(this.url);
29
+ const timeout = setTimeout(() => {
30
+ ws.terminate();
31
+ if (!settled) {
32
+ settled = true;
33
+ reject(new Error(`Connection to ${this.url} timed out`));
34
+ }
35
+ }, this.requestTimeout);
36
+ ws.on('open', () => {
37
+ clearTimeout(timeout);
38
+ this.ws = ws;
39
+ this.connectionPromise = null;
40
+ settled = true;
41
+ resolve();
42
+ });
43
+ ws.on('error', (err) => {
44
+ clearTimeout(timeout);
45
+ this.connectionPromise = null;
46
+ if (!settled) {
47
+ settled = true;
48
+ // Node may wrap connection failures in AggregateError (e.g. IPv4+IPv6).
49
+ // Unwrap to surface the actual error message.
50
+ if (err instanceof AggregateError && err.errors.length > 0) {
51
+ reject(new Error(`Failed to connect to ${this.url}: ${err.errors.map((e) => e.message).join('; ')}`));
52
+ }
53
+ else {
54
+ reject(new Error(`Failed to connect to ${this.url}: ${err.message}`));
55
+ }
56
+ }
57
+ });
58
+ ws.on('message', (data) => {
59
+ this.handleMessage(data);
60
+ });
61
+ ws.on('close', (code, reason) => {
62
+ this.ws = null;
63
+ const reasonStr = reason.toString() || 'no reason';
64
+ const msg = `WebSocket connection closed (code=${code}, reason=${reasonStr})`;
65
+ if (!settled) {
66
+ clearTimeout(timeout);
67
+ this.connectionPromise = null;
68
+ settled = true;
69
+ reject(new Error(msg));
70
+ }
71
+ for (const [id, req] of this.pending) {
72
+ clearTimeout(req.timer);
73
+ req.reject(new Error(msg));
74
+ this.pending.delete(id);
75
+ }
76
+ });
77
+ });
78
+ return this.connectionPromise;
79
+ }
80
+ async call(method, params) {
81
+ await this.connect();
82
+ const ws = this.ws;
83
+ if (!ws || ws.readyState !== WebSocket.OPEN) {
84
+ throw new Error('WebSocket is not connected');
85
+ }
86
+ const id = this.nextId++;
87
+ const request = {
88
+ jsonrpc: '2.0',
89
+ id,
90
+ method,
91
+ ...(params !== undefined && { params }),
92
+ };
93
+ return new Promise((resolve, reject) => {
94
+ const timer = setTimeout(() => {
95
+ this.pending.delete(id);
96
+ reject(new Error(`RPC call "${method}" timed out after ${this.requestTimeout}ms`));
97
+ }, this.requestTimeout);
98
+ this.pending.set(id, {
99
+ resolve: resolve,
100
+ reject,
101
+ timer,
102
+ });
103
+ ws.send(JSON.stringify(request));
104
+ });
105
+ }
106
+ async disconnect() {
107
+ if (this.ws) {
108
+ this.ws.close();
109
+ this.ws = null;
110
+ }
111
+ }
112
+ get isConnected() {
113
+ return this.ws?.readyState === WebSocket.OPEN;
114
+ }
115
+ handleMessage(data) {
116
+ let response;
117
+ try {
118
+ response = JSON.parse(data.toString());
119
+ }
120
+ catch {
121
+ return;
122
+ }
123
+ const pending = this.pending.get(response.id);
124
+ if (!pending) {
125
+ return;
126
+ }
127
+ this.pending.delete(response.id);
128
+ clearTimeout(pending.timer);
129
+ if (response.error) {
130
+ const detail = typeof response.error.data === 'string'
131
+ ? response.error.data
132
+ : response.error.message;
133
+ pending.reject(new RpcError(detail, response.error.code, response.error.data));
134
+ }
135
+ else {
136
+ pending.resolve(response.result);
137
+ }
138
+ }
139
+ }
140
+ //# sourceMappingURL=rpc-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc-client.js","sourceRoot":"","sources":["../src/rpc-client.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@mobilewright/driver-mobile-use",
3
+ "version": "0.0.1",
4
+ "description": "mobile-use.com driver for Mobilewright",
5
+ "homepage": "https://mobilewright.dev",
6
+ "license": "Apache-2.0",
7
+ "engines": {
8
+ "node": ">=18"
9
+ },
10
+ "type": "module",
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "scripts": {
20
+ "build": "tsc -b",
21
+ "prepublishOnly": "tsc -b"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/mobile-next/mobilewright.git",
26
+ "directory": "packages/driver-mobile-use"
27
+ },
28
+ "files": [
29
+ "dist"
30
+ ],
31
+ "dependencies": {
32
+ "@mobilewright/protocol": "^0.0.1",
33
+ "debug": "^4.4.3",
34
+ "ws": "^8.18.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/debug": "^4.1.13",
38
+ "@types/ws": "^8.5.0"
39
+ }
40
+ }