webdriverio-execute 0.2.0 → 0.2.2

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Vince Graics
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.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vince Graics
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 CHANGED
@@ -1,157 +1,157 @@
1
- # wdiox
2
-
3
- Interactive browser and app CLI for developers, powered by [WebdriverIO](https://webdriver.io).
4
-
5
- ```
6
- npm install -g webdriverio-execute
7
- ```
8
-
9
- ## How it works
10
-
11
- Each command is stateless. Sessions are stored as JSON in `~/.wdio-x/sessions/`. Commands attach to an existing session by reading that file — no daemon, no background process.
12
-
13
- `snapshot` captures all interactable elements and assigns short refs (`e1`, `e2`, …). Subsequent commands use those refs to act on elements.
14
-
15
- ## Commands
16
-
17
- ### `open` / `new` / `start`
18
-
19
- Open a browser or Appium session.
20
-
21
- ```bash
22
- wdiox open https://example.com
23
- wdiox open https://example.com --browser firefox
24
- wdiox open --app /path/to/app.apk --device "emulator-5554"
25
- wdiox open --app /path/to/app.ipa --device "iPhone 15"
26
- ```
27
-
28
- | Option | Default | Description |
29
- |---|---|---|
30
- | `--browser` | `chrome` | Browser to use (`chrome`, `firefox`, `edge`, `safari`) |
31
- | `--app` | — | Path to mobile app (`.apk`, `.ipa`, `.app`) |
32
- | `--device` | `emulator-5554` | Device name |
33
- | `--platform` | auto-detected | `android` or `ios` |
34
- | `--hostname` | `localhost` | WebDriver/Appium server hostname |
35
- | `--port` | `4723` (mobile) / `4444` (browser) | Server port |
36
- | `--grant-permissions` | `true` | Auto-grant app permissions (Appium) |
37
- | `--accept-alert` | `true` | Auto-accept native alerts (Appium) |
38
- | `--auto-dismiss` | `false` | Auto-dismiss native alerts (Appium) |
39
- | `--session` | `default` | Session name |
40
-
41
- If a session with the given name is already active, you'll be prompted to close it first.
42
-
43
- ---
44
-
45
- ### `snapshot`
46
-
47
- Capture interactable elements on the current page or screen and assign numbered refs.
48
-
49
- ```bash
50
- wdiox snapshot
51
- wdiox snapshot --no-visible # include off-screen elements
52
- ```
53
-
54
- ```
55
- Page: https://example.com/login
56
-
57
- e1 input[email] "Email address" #email
58
- e2 input[password] "Password" #password
59
- e3 button "Sign in" button*=Sign in
60
-
61
- 3 elements - default session
62
- ```
63
-
64
- ---
65
-
66
- ### `click`
67
-
68
- Click an element by ref.
69
-
70
- ```bash
71
- wdiox click e3
72
- ```
73
-
74
- ---
75
-
76
- ### `fill` / `type`
77
-
78
- Clear and type into an input by ref.
79
-
80
- ```bash
81
- wdiox fill e1 "hello@example.com"
82
- wdiox type e2 "mysecretpassword"
83
- ```
84
-
85
- ---
86
-
87
- ### `screenshot`
88
-
89
- Save a screenshot.
90
-
91
- ```bash
92
- wdiox screenshot
93
- wdiox screenshot /tmp/login-page.png
94
- ```
95
-
96
- ---
97
-
98
- ### `close` / `stop`
99
-
100
- Close the current session.
101
-
102
- ```bash
103
- wdiox close
104
- wdiox close --session myapp
105
- ```
106
-
107
- ---
108
-
109
- ### `ls` / `session-list`
110
-
111
- List all active sessions.
112
-
113
- ```bash
114
- wdiox ls
115
- ```
116
-
117
- ```
118
- NAME BROWSER URL STATUS
119
- default chrome https://example.com active
120
- myapp Android /path/to/app.apk active
121
- ```
122
-
123
- ---
124
-
125
- ## Multi-session
126
-
127
- Every command accepts `--session <name>` (or `-s <name>`) to target a specific session. The `WDIO_SESSION` environment variable sets the default session name.
128
-
129
- ```bash
130
- wdiox open https://site-a.com --session a
131
- wdiox open https://site-b.com --session b
132
- wdiox snapshot --session a
133
- wdiox click e1 --session a
134
- wdiox close --session b
135
- ```
136
-
137
- ## Typical browser workflow
138
-
139
- ```bash
140
- wdiox open https://example.com
141
- wdiox snapshot
142
- wdiox fill e1 "user@example.com"
143
- wdiox fill e2 "password"
144
- wdiox click e3
145
- wdiox screenshot
146
- wdiox close
147
- ```
148
-
149
- ## Typical mobile workflow
150
-
151
- ```bash
152
- wdiox open --app ./app.apk --device "emulator-5554"
153
- wdiox snapshot
154
- wdiox click e1
155
- wdiox fill e2 "hello"
156
- wdiox close
157
- ```
1
+ # wdiox — WebdriverIO Execute
2
+
3
+ Interactive browser and app CLI for developers, powered by [WebdriverIO](https://webdriver.io).
4
+
5
+ ```
6
+ npm install -g webdriverio-execute
7
+ ```
8
+
9
+ ## How it works
10
+
11
+ Each command is stateless. Sessions are stored as JSON in `~/.wdio-x/sessions/`. Commands attach to an existing session by reading that file — no daemon, no background process.
12
+
13
+ `snapshot` captures all interactable elements and assigns short refs (`e1`, `e2`, …). Subsequent commands use those refs to act on elements.
14
+
15
+ ## Commands
16
+
17
+ ### `open` / `new` / `start`
18
+
19
+ Open a browser or Appium session.
20
+
21
+ ```bash
22
+ wdiox open https://example.com
23
+ wdiox open https://example.com --browser firefox
24
+ wdiox open --app /path/to/app.apk --device "emulator-5554"
25
+ wdiox open --app /path/to/app.ipa --device "iPhone 15"
26
+ ```
27
+
28
+ | Option | Default | Description |
29
+ |---|---|---|
30
+ | `--browser` | `chrome` | Browser to use (`chrome`, `firefox`, `edge`, `safari`) |
31
+ | `--app` | — | Path to mobile app (`.apk`, `.ipa`, `.app`) |
32
+ | `--device` | `emulator-5554` | Device name |
33
+ | `--platform` | auto-detected | `android` or `ios` |
34
+ | `--hostname` | `localhost` | WebDriver/Appium server hostname |
35
+ | `--port` | `4723` (mobile) / `4444` (browser) | Server port |
36
+ | `--grant-permissions` | `true` | Auto-grant app permissions (Appium) |
37
+ | `--accept-alert` | `true` | Auto-accept native alerts (Appium) |
38
+ | `--auto-dismiss` | `false` | Auto-dismiss native alerts (Appium) |
39
+ | `--session` | `default` | Session name |
40
+
41
+ If a session with the given name is already active, you'll be prompted to close it first.
42
+
43
+ ---
44
+
45
+ ### `snapshot`
46
+
47
+ Capture interactable elements on the current page or screen and assign numbered refs.
48
+
49
+ ```bash
50
+ wdiox snapshot
51
+ wdiox snapshot --no-visible # include off-screen elements
52
+ ```
53
+
54
+ ```
55
+ Page: https://example.com/login
56
+
57
+ e1 input[email] "Email address" #email
58
+ e2 input[password] "Password" #password
59
+ e3 button "Sign in" button*=Sign in
60
+
61
+ 3 elements - default session
62
+ ```
63
+
64
+ ---
65
+
66
+ ### `click`
67
+
68
+ Click an element by ref.
69
+
70
+ ```bash
71
+ wdiox click e3
72
+ ```
73
+
74
+ ---
75
+
76
+ ### `fill` / `type`
77
+
78
+ Clear and type into an input by ref.
79
+
80
+ ```bash
81
+ wdiox fill e1 "hello@example.com"
82
+ wdiox type e2 "mysecretpassword"
83
+ ```
84
+
85
+ ---
86
+
87
+ ### `screenshot`
88
+
89
+ Save a screenshot.
90
+
91
+ ```bash
92
+ wdiox screenshot
93
+ wdiox screenshot /tmp/login-page.png
94
+ ```
95
+
96
+ ---
97
+
98
+ ### `close` / `stop`
99
+
100
+ Close the current session.
101
+
102
+ ```bash
103
+ wdiox close
104
+ wdiox close --session myapp
105
+ ```
106
+
107
+ ---
108
+
109
+ ### `ls` / `session-list`
110
+
111
+ List all active sessions.
112
+
113
+ ```bash
114
+ wdiox ls
115
+ ```
116
+
117
+ ```
118
+ NAME BROWSER URL STATUS
119
+ default chrome https://example.com active
120
+ myapp Android /path/to/app.apk active
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Multi-session
126
+
127
+ Every command accepts `--session <name>` (or `-s <name>`) to target a specific session. The `WDIO_SESSION` environment variable sets the default session name.
128
+
129
+ ```bash
130
+ wdiox open https://site-a.com --session a
131
+ wdiox open https://site-b.com --session b
132
+ wdiox snapshot --session a
133
+ wdiox click e1 --session a
134
+ wdiox close --session b
135
+ ```
136
+
137
+ ## Typical browser workflow
138
+
139
+ ```bash
140
+ wdiox open https://example.com
141
+ wdiox snapshot
142
+ wdiox fill e1 "user@example.com"
143
+ wdiox fill e2 "password"
144
+ wdiox click e3
145
+ wdiox screenshot
146
+ wdiox close
147
+ ```
148
+
149
+ ## Typical mobile workflow
150
+
151
+ ```bash
152
+ wdiox open --app ./app.apk --device "emulator-5554"
153
+ wdiox snapshot
154
+ wdiox click e1
155
+ wdiox fill e2 "hello"
156
+ wdiox close
157
+ ```
package/bin/wdiox.js CHANGED
File without changes
package/build/cli.js CHANGED
@@ -188,6 +188,7 @@ Close it and start a new one? (y/N) `);
188
188
  capabilities["appium:autoDismissAlerts"] = argv.autoDismiss;
189
189
  } else {
190
190
  capabilities.browserName = argv.browser;
191
+ capabilities["wdio:chromedriverOptions"] = { spawnOpts: { detached: true } };
191
192
  }
192
193
  const remoteOpts = { capabilities, logLevel: process.env.WDIO_LOG_LEVEL ?? "error" };
193
194
  if (argv.hostname || argv.port || isMobile) {
@@ -218,15 +219,37 @@ __export(close_exports, {
218
219
  desc: () => desc2,
219
220
  handler: () => handler2
220
221
  });
222
+ import os2 from "os";
223
+ import { execSync } from "child_process";
221
224
  import { attach as attach2 } from "webdriverio";
222
225
  var command2 = ["close", "stop"];
223
226
  var desc2 = "Close the current session";
227
+ function killProcess(pid) {
228
+ const platform = os2.platform();
229
+ try {
230
+ if (platform === "win32") {
231
+ execSync(`taskkill /F /PID ${pid}`, { stdio: "ignore" });
232
+ } else {
233
+ execSync(`kill -9 ${pid}`, { stdio: "ignore" });
234
+ }
235
+ } catch {
236
+ }
237
+ }
224
238
  var handler2 = withSession(async (argv, meta, sessionsDir) => {
225
239
  const sessionName = argv.session;
240
+ const caps = meta.capabilities;
241
+ const browserPid = typeof caps["goog:processID"] === "number" ? caps["goog:processID"] : void 0;
242
+ const driverPid = typeof caps["wdio:driverPID"] === "number" ? caps["wdio:driverPID"] : void 0;
226
243
  try {
227
244
  const browser = await attach2(buildAttachOptions(meta));
228
245
  await browser.deleteSession();
229
246
  } catch {
247
+ if (browserPid) {
248
+ killProcess(browserPid);
249
+ }
250
+ if (driverPid && driverPid !== browserPid) {
251
+ killProcess(driverPid);
252
+ }
230
253
  }
231
254
  await deleteSessionFiles(sessionName, sessionsDir);
232
255
  console.log(`Session "${sessionName}" closed.`);
package/build/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/commands/open.ts","../src/session.ts","../src/commands/close.ts","../src/commands/snapshot.ts","../src/refs.ts","../src/format.ts","../src/commands/click.ts","../src/commands/type.ts","../src/commands/screenshot.ts","../src/commands/session-list.ts"],"sourcesContent":["import yargs from 'yargs';\nimport type { CommandModule } from 'yargs';\nimport { hideBin } from 'yargs/helpers';\n\nimport * as openCmd from './commands/open.js';\nimport * as closeCmd from './commands/close.js';\nimport * as snapshotCmd from './commands/snapshot.js';\nimport * as clickCmd from './commands/click.js';\nimport * as fillCmd from './commands/type';\nimport * as screenshotCmd from './commands/screenshot.js';\nimport * as sessionListCmd from './commands/session-list.js';\n\nconst commands = [\n openCmd, closeCmd, snapshotCmd, clickCmd,\n fillCmd, screenshotCmd, sessionListCmd,\n] as unknown as CommandModule[];\n\nexport async function run() {\n\n // webdriverio's attach() can spawn async BiDi connections that fail after\n // the function returns (e.g. stale session). Suppress these so the CLI\n // doesn't crash during close/reconnect of dead sessions.\n process.on('unhandledRejection', () => {});\n\n let cli = yargs(hideBin(process.argv))\n .scriptName('wdiox')\n .usage('$0 <command> [options]')\n .option('session', {\n alias: 's',\n type: 'string',\n default: process.env.WDIO_SESSION || 'default',\n describe: 'Session name',\n });\n\n for (const cmd of commands) {\n cli = cli.command(cmd);\n }\n\n await cli\n .demandCommand(1, 'You need to specify a command. Try: wdiox open <url>')\n .strict()\n .help()\n .version()\n .parse();\n\n // webdriverio keeps HTTP agents alive — force clean exit after command completes\n process.exit(0);\n}\n","import readline from 'node:readline/promises';\nimport type { ArgumentsCamelCase, Argv } from 'yargs';\nimport type { Capabilities } from '@wdio/types';\nimport { attach, remote } from 'webdriverio';\n\nimport { writeSession, readSession, getSessionDir, buildAttachOptions, deleteSessionFiles } from '../session.js';\n\nexport const command = ['open [url]', 'new [url]', 'start [url]'];\nexport const desc = 'Open a browser or Appium session';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('url', {\n type: 'string',\n describe: 'URL to navigate to',\n })\n .option('browser', {\n alias: 'b',\n type: 'string',\n default: 'chrome',\n describe: 'Browser to use (chrome, firefox, edge, safari)',\n })\n .option('app', {\n type: 'string',\n describe: 'Path to mobile app (.apk, .ipa, .app)',\n })\n .option('device', {\n alias: 'd',\n type: 'string',\n describe: 'Device name for mobile testing',\n })\n .option('platform', {\n type: 'string',\n describe: 'Mobile platform (android, ios)',\n })\n .option('path', {\n type: 'string',\n describe: 'WebDriver/Appium server session path (default: /)',\n })\n .option('port', {\n alias: 'p',\n type: 'number',\n describe: 'WebDriver/Appium server port (default: 4723)',\n })\n .option('hostname', {\n type: 'string',\n describe: 'WebDriver/Appium server hostname (default: localhost)',\n })\n .option('grant-permissions', {\n type: 'boolean',\n default: true,\n describe: 'Auto-grant app permissions (Appium only)',\n })\n .option('accept-alert', {\n type: 'boolean',\n default: true,\n describe: 'Auto-accept native alerts (Appium only)',\n })\n .option('auto-dismiss', {\n type: 'boolean',\n default: false,\n describe: 'Auto-dismiss native alerts (Appium only)',\n });\n};\n\ninterface OpenArgs {\n url?: string\n browser: string\n session: string\n app?: string\n device?: string\n platform?: string\n port?: number\n hostname?: string\n grantPermissions: boolean\n acceptAlert: boolean\n autoDismiss: boolean\n _sessionsDir?: string\n}\n\nexport async function handler (argv: ArgumentsCamelCase<OpenArgs>) {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const existing = await readSession(sessionName, sessionsDir);\n if (existing) {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const context = existing.url || (existing.capabilities['appium:app'] as string) || '';\n const answer = await rl.question(`Session [${sessionName}] is already active${context ? ` (${context})` : ''}.\\nClose it and start a new one? (y/N) `);\n rl.close();\n\n if (answer.trim().toLowerCase() !== 'y') {\n return;\n }\n\n try {\n const old = await attach(buildAttachOptions(existing));\n await old.deleteSession();\n } catch {\n // Already dead\n }\n await deleteSessionFiles(sessionName, sessionsDir);\n }\n\n const capabilities: Record<string, unknown> = {};\n\n const isMobile = !!argv.app;\n if (isMobile) {\n const platform = argv.platform ?? (argv.app?.endsWith('.apk') ? 'android' : 'ios');\n\n capabilities.platformName = platform === 'ios' ? 'iOS' : 'Android';\n capabilities['appium:app'] = argv.app;\n capabilities['appium:deviceName'] = argv.device ?? 'emulator-5554';\n capabilities['appium:newCommandTimeout'] = 300;\n capabilities['appium:automationName'] = platform === 'ios' ? 'XCUITest' : 'UiAutomator2';\n capabilities['appium:autoGrantPermissions'] = argv.grantPermissions;\n capabilities['appium:autoAcceptAlerts'] = argv.acceptAlert;\n capabilities['appium:autoDismissAlerts'] = argv.autoDismiss;\n } else {\n capabilities.browserName = argv.browser;\n }\n\n const remoteOpts: Record<string, unknown> = { capabilities, logLevel: process.env.WDIO_LOG_LEVEL ?? 'error' };\n // For mobile / Appium, explicit connection is required\n if (argv.hostname || argv.port || isMobile) {\n remoteOpts.hostname = argv.hostname ?? 'localhost';\n remoteOpts.port = argv.port ?? (isMobile ? 4723 : 4444);\n remoteOpts.path = argv.path ?? '/';\n }\n\n const browser = await remote(remoteOpts as unknown as Capabilities.WebdriverIOConfig);\n\n if (argv.url) {\n await browser.url(argv.url);\n }\n\n const opts = browser.options as Capabilities.WebdriverIOConfig;\n await writeSession(sessionName, {\n sessionId: browser.sessionId,\n hostname: opts?.hostname || 'localhost',\n port: opts?.port || 4444,\n capabilities: { ...capabilities, ...browser.capabilities as Record<string, unknown> },\n created: new Date().toISOString(),\n url: argv.url || '',\n }, sessionsDir);\n\n console.log(`Session \"${sessionName}\" started.`);\n}\n","import os from 'node:os';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { AttachOptions } from 'webdriverio';\nimport type { ArgumentsCamelCase } from 'yargs';\n\nexport interface SessionMetadata {\n sessionId: string\n hostname: string\n port: number\n capabilities: Record<string, unknown>\n created: string\n url: string\n}\n\nexport interface SessionEntry {\n name: string\n metadata: SessionMetadata\n}\n\nconst DEFAULT_SESSION_DIR = path.join(os.homedir(), '.wdio-x', 'sessions');\n\nfunction isEnoent(err: unknown): boolean {\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * Build attach options from session metadata for use with webdriverio's `attach()`.\n */\nexport function buildAttachOptions(meta: SessionMetadata): AttachOptions {\n return {\n sessionId: meta.sessionId,\n capabilities: meta.capabilities as WebdriverIO.Capabilities,\n options: {\n hostname: meta.hostname,\n port: meta.port,\n logLevel: process.env.WDIO_LOG_LEVEL ?? 'error',\n },\n } as AttachOptions;\n}\n\n/**\n * Returns the session directory path. Defaults to ~/.wdio-x/sessions/.\n */\nexport function getSessionDir (baseDir?: string): string {\n return baseDir ?? DEFAULT_SESSION_DIR;\n}\n\n/**\n * Returns the file path for a session's metadata JSON file.\n */\nexport function getSessionPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.json`);\n}\n\n/**\n * Returns the file path for a session's refs JSON file.\n */\nexport function getRefsPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.refs.json`);\n}\n\n/**\n * Writes session metadata to disk, creating the directory if needed.\n */\nexport async function writeSession (\n name: string,\n metadata: SessionMetadata,\n baseDir?: string,\n): Promise<void> {\n const dir = getSessionDir(baseDir);\n await fs.mkdir(dir, { recursive: true });\n const filePath = getSessionPath(name, baseDir);\n await fs.writeFile(filePath, JSON.stringify(metadata, null, 2));\n}\n\n/**\n * Reads session metadata from disk. Returns null if the session file does not exist.\n */\nexport async function readSession (\n name: string,\n baseDir?: string,\n): Promise<SessionMetadata | null> {\n const filePath = getSessionPath(name, baseDir);\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content) as SessionMetadata;\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Deletes both the .json and .refs.json files for a session.\n * Does not throw if the files do not exist.\n */\nexport async function deleteSessionFiles (\n name: string,\n baseDir?: string,\n): Promise<void> {\n const sessionPath = getSessionPath(name, baseDir);\n const refsPath = getRefsPath(name, baseDir);\n await Promise.all([\n fs.rm(sessionPath, { force: true }),\n fs.rm(refsPath, { force: true }),\n ]);\n}\n\n/**\n * Lists all sessions in the session directory.\n * Only considers .json files (excludes .refs.json).\n * Returns an empty array if the directory does not exist.\n */\nexport async function listSessions (baseDir?: string): Promise<SessionEntry[]> {\n const dir = getSessionDir(baseDir);\n let files: string[];\n try {\n files = await fs.readdir(dir);\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return [];\n }\n throw err;\n }\n\n const sessionFiles = files.filter(\n (f) => f.endsWith('.json') && !f.endsWith('.refs.json'),\n );\n\n return await Promise.all(\n sessionFiles.map(async (f) => {\n const name = f.replace(/\\.json$/, '');\n const metadata = await readSession(name, baseDir);\n return { name, metadata: metadata! };\n }),\n );\n}\n\ninterface SessionArgs {\n session: string\n _sessionsDir?: string\n}\n\n/**\n * Wraps a command handler that requires an active session.\n * Reads the session from disk and exits early with an error if not found.\n */\nexport function withSession<T extends SessionArgs>(\n fn: (argv: ArgumentsCamelCase<T>, meta: SessionMetadata, sessionsDir: string) => Promise<void>,\n): (argv: ArgumentsCamelCase<T>) => Promise<void> {\n return async function handler(argv: ArgumentsCamelCase<T>): Promise<void> {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const meta = await readSession(sessionName, sessionsDir);\n if (!meta) {\n console.error(`Error: No active session [${sessionName}]. Run wdiox open <url> first.`);\n return;\n }\n\n await fn(argv, meta, sessionsDir);\n };\n}\n","import type { ArgumentsCamelCase } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { deleteSessionFiles, buildAttachOptions, withSession } from '../session.js';\n\nexport const command = ['close', 'stop'];\nexport const desc = 'Close the current session';\n\ninterface CloseArgs {\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<CloseArgs>(async (argv: ArgumentsCamelCase<CloseArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n\n try {\n const browser = await attach(buildAttachOptions(meta));\n await browser.deleteSession();\n } catch {\n // Session may already be dead - clean up anyway\n }\n\n await deleteSessionFiles(sessionName, sessionsDir);\n console.log(`Session \"${sessionName}\" closed.`);\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\nimport { writeRefs, type RefMap } from '../refs.js';\nimport { getInteractableBrowserElements, getMobileVisibleElements } from '@wdio/mcp/snapshot';\nimport {\n formatBrowserElement,\n formatMobileElement,\n} from '../format.js';\n\nexport const command = 'snapshot';\nexport const desc = 'Capture interactive elements on the page or screen';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .option('visible', {\n type: 'boolean',\n default: true,\n describe: 'Only show elements in viewport',\n });\n};\n\ninterface SnapshotArgs {\n session: string\n visible: boolean\n _sessionsDir?: string\n}\n\nexport const handler = withSession<SnapshotArgs>(async (argv: ArgumentsCamelCase<SnapshotArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const browser = await attach(buildAttachOptions(meta));\n\n const isMobile = browser.isAndroid || browser.isIOS;\n const refs: RefMap = {};\n\n if (isMobile) {\n const platform = browser.isIOS ? 'ios' : 'android';\n const elements = await getMobileVisibleElements(browser, platform);\n const filtered = argv.visible\n ? elements.filter(el => el.isInViewport)\n : elements;\n\n const appName = (meta.capabilities['appium:app'] as string) || 'unknown';\n console.log(`\\n App: ${appName}\\n`);\n\n filtered.forEach((el, i) => {\n const ref = `e${i + 1}`;\n console.log(formatMobileElement(ref, {\n tagName: el.tagName,\n text: el.text,\n selector: el.selector,\n accessibilityId: el.accessibilityId,\n resourceId: el.resourceId,\n }));\n refs[ref] = {\n selector: el.selector,\n tagName: el.tagName,\n text: el.text,\n };\n });\n\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\n } else {\n const elements = await getInteractableBrowserElements(browser);\n const filtered = argv.visible\n ? elements.filter(el => el.isInViewport)\n : elements;\n\n const currentUrl = await browser.getUrl();\n console.log(`\\n Page: ${currentUrl}\\n`);\n\n filtered.forEach((el, i) => {\n const ref = `e${i + 1}`;\n console.log(formatBrowserElement(ref, el));\n refs[ref] = {\n selector: el.selector,\n tagName: el.tagName,\n text: el.name || '',\n };\n });\n\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\n }\n\n await writeRefs(getRefsPath(sessionName, sessionsDir), refs);\n});\n","import fs from 'node:fs/promises';\n\nexport interface RefEntry {\n selector?: string\n tagName: string\n text?: string\n placeholder?: string\n [key: string]: unknown\n}\n\nexport type RefMap = Record<string, RefEntry>;\n\nfunction isEnoent (err: unknown): boolean {\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * Writes a ref map to disk as JSON.\n */\nexport async function writeRefs (refsPath: string, refs: RefMap): Promise<void> {\n await fs.writeFile(refsPath, JSON.stringify(refs, null, 2), 'utf-8');\n}\n\n/**\n * Reads a ref map from disk. Returns null if the file doesn't exist.\n */\nexport async function readRefs (refsPath: string): Promise<RefMap | null> {\n try {\n const content = await fs.readFile(refsPath, 'utf-8');\n return JSON.parse(content) as RefMap;\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Look up a ref by key: reads refs file, finds the entry, resolves its selector.\n * Logs appropriate error messages and returns null on failure.\n */\nexport async function lookupRef (\n refsPath: string,\n refKey: string,\n): Promise<{ ref: RefEntry; selector: string } | null> {\n const refs = await readRefs(refsPath);\n if (!refs) {\n console.error('Error: No snapshot taken. Run wdiox snapshot first.');\n return null;\n }\n\n const ref = refs[refKey];\n if (!ref) {\n const available = Object.keys(refs);\n const range = available.length > 0\n ? `Available: ${available[0]}-${available[available.length - 1]}`\n : 'No refs available';\n console.error(`Error: ${refKey} not found in snapshot. ${range}`);\n return null;\n }\n\n if (!ref.selector) {\n console.error(`Error: Could not resolve selector for ${refKey}`);\n return null;\n }\n\n return { ref, selector: ref.selector };\n}\n","export interface BrowserElementFormatInput {\n tagName: string\n role?: string\n type?: string\n name?: string\n href?: string\n selector: string\n}\n\nexport interface MobileElementFormatInput {\n tagName: string\n text?: string\n selector: string\n accessibilityId?: string\n resourceId?: string\n}\n\nexport interface SessionListEntry {\n name: string\n browser: string\n url: string\n status: string\n}\n\nfunction truncate(str: string, max = 80): string {\n return str.length <= max ? str : str.slice(0, max - 3) + '...';\n}\n\nexport function formatBrowserElement(ref: string, el: BrowserElementFormatInput): string {\n const tag = (el.role && el.role !== el.tagName ? el.role : el.tagName) + (el.type ? `[${el.type}]` : '');\n const desc = [el.name && `\"${truncate(el.name)}\"`, el.href && `-> ${truncate(el.href)}`].filter(Boolean).join(' ');\n return [ref.padEnd(4), tag, desc, el.selector].filter(Boolean).join(' ');\n}\n\nexport function formatMobileElement(ref: string, el: MobileElementFormatInput): string {\n const selector = el.accessibilityId ? `[accessibility-id: ${el.accessibilityId}]`\n : el.resourceId ? `[resource-id: ${el.resourceId}]`\n : truncate(el.selector);\n const parts = [ref.padEnd(4), el.tagName.padEnd(28), el.text && `\"${truncate(el.text)}\"`, selector];\n return parts.filter(Boolean).join(' ');\n}\n\nexport function formatSessionList(entries: SessionListEntry[]): string {\n if (entries.length === 0) return 'No active sessions.';\n\n const cols = (['name', 'browser', 'url', 'status'] as const).map((key) => ({\n key,\n header: key.toUpperCase(),\n width: Math.max(key.length, ...entries.map((e) => e[key].length)),\n }));\n\n const row = (e: SessionListEntry) => cols.map((c) => e[c.key].padEnd(c.width)).join(' ');\n const header = cols.map((c) => c.header.padEnd(c.width)).join(' ');\n\n return [header, ...entries.map(row)].join('\\n');\n}\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, getRefsPath, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = 'click <ref>';\nexport const desc = 'Click an element by snapshot reference (e.g., e1)';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1, a3)',\n });\n};\n\ninterface ClickArgs {\n ref: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ClickArgs>(async (argv: ArgumentsCamelCase<ClickArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n await browser.$(result.selector).click();\n console.log(`Clicked ${refKey} (${result.ref.selector})`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error clicking ${refKey}: ${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = ['type <ref> <text>', 'fill <ref> <text>'];\nexport const desc = 'Clear and type text into an input element by snapshot reference';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1)',\n })\n .positional('text', {\n type: 'string',\n describe: 'Text to type',\n });\n};\n\ninterface FillArgs {\n ref: string\n text: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<FillArgs>(async (argv: ArgumentsCamelCase<FillArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n const element = await browser.$(result.selector);\n await element.clearValue();\n await element.addValue(argv.text as string);\n console.log(`Filled ${refKey} with \"${argv.text}\"`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error: ${refKey} not found on page — the page may have changed. Run wdiox snapshot to refresh.\\n${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, withSession } from '../session.js';\n\nexport const command = 'screenshot [path]';\nexport const desc = 'Save a screenshot of the current page or screen';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('path', {\n type: 'string',\n describe: 'File path to save screenshot (default: ./screenshot-<timestamp>.png)',\n });\n};\n\ninterface ScreenshotArgs {\n path?: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ScreenshotArgs>(async (argv: ArgumentsCamelCase<ScreenshotArgs>, meta) => {\n const browser = await attach(buildAttachOptions(meta));\n\n const filePath = (argv.path as string) ||\n `screenshot-${new Date().toISOString().replace(/[:.]/g, '-')}.png`;\n\n await browser.saveScreenshot(filePath);\n console.log(`Screenshot saved to ${filePath}`);\n});\n","import type { ArgumentsCamelCase } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { listSessions, getSessionDir, deleteSessionFiles, buildAttachOptions } from '../session.js';\nimport { formatSessionList, type SessionListEntry } from '../format.js';\n\nexport const command = ['session-list', 'ls'];\nexport const desc = 'List all active sessions';\n\ninterface SessionListArgs {\n _sessionsDir?: string\n}\n\nexport async function handler (argv: ArgumentsCamelCase<SessionListArgs>) {\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n const sessions = await listSessions(sessionsDir);\n\n if (sessions.length === 0) {\n console.log('No active sessions.');\n return;\n }\n\n const entries: SessionListEntry[] = [];\n\n for (const session of sessions) {\n let status = 'active';\n try {\n const browser = await attach(buildAttachOptions(session.metadata));\n await browser.getPageSource();\n } catch {\n status = 'expired';\n await deleteSessionFiles(session.name, sessionsDir);\n }\n\n const caps = session.metadata.capabilities;\n const browserName = (caps.browserName as string)\n || (caps.platformName as string)\n || 'unknown';\n entries.push({\n name: session.name,\n browser: browserName,\n url: session.metadata.url,\n status,\n });\n }\n\n console.log(formatSessionList(entries));\n}\n"],"mappings":"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","names":["handler","yargs","command","desc","handler","attach","command","desc","handler","attach","builder","command","desc","handler","attach","fs","isEnoent","desc","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","command","desc","handler","attach","command","desc","handler","attach"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/commands/open.ts","../src/session.ts","../src/commands/close.ts","../src/commands/snapshot.ts","../src/refs.ts","../src/format.ts","../src/commands/click.ts","../src/commands/type.ts","../src/commands/screenshot.ts","../src/commands/session-list.ts"],"sourcesContent":["import yargs from 'yargs';\r\nimport type { CommandModule } from 'yargs';\r\nimport { hideBin } from 'yargs/helpers';\r\n\r\nimport * as openCmd from './commands/open.js';\r\nimport * as closeCmd from './commands/close.js';\r\nimport * as snapshotCmd from './commands/snapshot.js';\r\nimport * as clickCmd from './commands/click.js';\r\nimport * as fillCmd from './commands/type';\r\nimport * as screenshotCmd from './commands/screenshot.js';\r\nimport * as sessionListCmd from './commands/session-list.js';\r\n\r\nconst commands = [\r\n openCmd, closeCmd, snapshotCmd, clickCmd,\r\n fillCmd, screenshotCmd, sessionListCmd,\r\n] as unknown as CommandModule[];\r\n\r\nexport async function run() {\r\n\r\n // webdriverio's attach() can spawn async BiDi connections that fail after\r\n // the function returns (e.g. stale session). Suppress these so the CLI\r\n // doesn't crash during close/reconnect of dead sessions.\r\n process.on('unhandledRejection', () => {});\r\n\r\n let cli = yargs(hideBin(process.argv))\r\n .scriptName('wdiox')\r\n .usage('$0 <command> [options]')\r\n .option('session', {\r\n alias: 's',\r\n type: 'string',\r\n default: process.env.WDIO_SESSION || 'default',\r\n describe: 'Session name',\r\n });\r\n\r\n for (const cmd of commands) {\r\n cli = cli.command(cmd);\r\n }\r\n\r\n await cli\r\n .demandCommand(1, 'You need to specify a command. Try: wdiox open <url>')\r\n .strict()\r\n .help()\r\n .version()\r\n .parse();\r\n\r\n // webdriverio keeps HTTP agents alive — force clean exit after command completes\r\n process.exit(0);\r\n}\r\n","import readline from 'node:readline/promises';\nimport type { ArgumentsCamelCase, Argv } from 'yargs';\nimport type { Capabilities } from '@wdio/types';\nimport { attach, remote } from 'webdriverio';\n\nimport { writeSession, readSession, getSessionDir, buildAttachOptions, deleteSessionFiles } from '../session.js';\n\nexport const command = ['open [url]', 'new [url]', 'start [url]'];\nexport const desc = 'Open a browser or Appium session';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('url', {\n type: 'string',\n describe: 'URL to navigate to',\n })\n .option('browser', {\n alias: 'b',\n type: 'string',\n default: 'chrome',\n describe: 'Browser to use (chrome, firefox, edge, safari)',\n })\n .option('app', {\n type: 'string',\n describe: 'Path to mobile app (.apk, .ipa, .app)',\n })\n .option('device', {\n alias: 'd',\n type: 'string',\n describe: 'Device name for mobile testing',\n })\n .option('platform', {\n type: 'string',\n describe: 'Mobile platform (android, ios)',\n })\n .option('path', {\n type: 'string',\n describe: 'WebDriver/Appium server session path (default: /)',\n })\n .option('port', {\n alias: 'p',\n type: 'number',\n describe: 'WebDriver/Appium server port (default: 4723)',\n })\n .option('hostname', {\n type: 'string',\n describe: 'WebDriver/Appium server hostname (default: localhost)',\n })\n .option('grant-permissions', {\n type: 'boolean',\n default: true,\n describe: 'Auto-grant app permissions (Appium only)',\n })\n .option('accept-alert', {\n type: 'boolean',\n default: true,\n describe: 'Auto-accept native alerts (Appium only)',\n })\n .option('auto-dismiss', {\n type: 'boolean',\n default: false,\n describe: 'Auto-dismiss native alerts (Appium only)',\n });\n};\n\ninterface OpenArgs {\n url?: string\n browser: string\n session: string\n app?: string\n device?: string\n platform?: string\n port?: number\n hostname?: string\n grantPermissions: boolean\n acceptAlert: boolean\n autoDismiss: boolean\n _sessionsDir?: string\n}\n\nexport async function handler (argv: ArgumentsCamelCase<OpenArgs>) {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const existing = await readSession(sessionName, sessionsDir);\n if (existing) {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const context = existing.url || (existing.capabilities['appium:app'] as string) || '';\n const answer = await rl.question(`Session [${sessionName}] is already active${context ? ` (${context})` : ''}.\\nClose it and start a new one? (y/N) `);\n rl.close();\n\n if (answer.trim().toLowerCase() !== 'y') {\n return;\n }\n\n try {\n const old = await attach(buildAttachOptions(existing));\n await old.deleteSession();\n } catch {\n // Already dead\n }\n await deleteSessionFiles(sessionName, sessionsDir);\n }\n\n const capabilities: Record<string, unknown> = {};\n\n const isMobile = !!argv.app;\n if (isMobile) {\n const platform = argv.platform ?? (argv.app?.endsWith('.apk') ? 'android' : 'ios');\n\n capabilities.platformName = platform === 'ios' ? 'iOS' : 'Android';\n capabilities['appium:app'] = argv.app;\n capabilities['appium:deviceName'] = argv.device ?? 'emulator-5554';\n capabilities['appium:newCommandTimeout'] = 300;\n capabilities['appium:automationName'] = platform === 'ios' ? 'XCUITest' : 'UiAutomator2';\n capabilities['appium:autoGrantPermissions'] = argv.grantPermissions;\n capabilities['appium:autoAcceptAlerts'] = argv.acceptAlert;\n capabilities['appium:autoDismissAlerts'] = argv.autoDismiss;\n } else {\n capabilities.browserName = argv.browser;\n capabilities['wdio:chromedriverOptions'] = { spawnOpts: { detached: true } };\n }\n\n const remoteOpts: Record<string, unknown> = { capabilities, logLevel: process.env.WDIO_LOG_LEVEL ?? 'error' };\n // For mobile / Appium, explicit connection is required\n if (argv.hostname || argv.port || isMobile) {\n remoteOpts.hostname = argv.hostname ?? 'localhost';\n remoteOpts.port = argv.port ?? (isMobile ? 4723 : 4444);\n remoteOpts.path = argv.path ?? '/';\n }\n\n const browser = await remote(remoteOpts as unknown as Capabilities.WebdriverIOConfig);\n\n if (argv.url) {\n await browser.url(argv.url);\n }\n\n const opts = browser.options as Capabilities.WebdriverIOConfig;\n await writeSession(sessionName, {\n sessionId: browser.sessionId,\n hostname: opts?.hostname || 'localhost',\n port: opts?.port || 4444,\n capabilities: { ...capabilities, ...browser.capabilities as Record<string, unknown> },\n created: new Date().toISOString(),\n url: argv.url || '',\n }, sessionsDir);\n\n console.log(`Session \"${sessionName}\" started.`);\n}\n","import os from 'node:os';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\n\nimport type { AttachOptions } from 'webdriverio';\nimport type { ArgumentsCamelCase } from 'yargs';\n\nexport interface SessionMetadata {\n sessionId: string\n hostname: string\n port: number\n capabilities: Record<string, unknown>\n created: string\n url: string\n}\n\nexport interface SessionEntry {\n name: string\n metadata: SessionMetadata\n}\n\nconst DEFAULT_SESSION_DIR = path.join(os.homedir(), '.wdio-x', 'sessions');\n\nfunction isEnoent(err: unknown): boolean {\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * Build attach options from session metadata for use with webdriverio's `attach()`.\n */\nexport function buildAttachOptions(meta: SessionMetadata): AttachOptions {\n return {\n sessionId: meta.sessionId,\n capabilities: meta.capabilities as WebdriverIO.Capabilities,\n options: {\n hostname: meta.hostname,\n port: meta.port,\n logLevel: process.env.WDIO_LOG_LEVEL ?? 'error',\n },\n } as AttachOptions;\n}\n\n/**\n * Returns the session directory path. Defaults to ~/.wdio-x/sessions/.\n */\nexport function getSessionDir (baseDir?: string): string {\n return baseDir ?? DEFAULT_SESSION_DIR;\n}\n\n/**\n * Returns the file path for a session's metadata JSON file.\n */\nexport function getSessionPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.json`);\n}\n\n/**\n * Returns the file path for a session's refs JSON file.\n */\nexport function getRefsPath (name: string, baseDir?: string): string {\n return path.join(getSessionDir(baseDir), `${name}.refs.json`);\n}\n\n/**\n * Writes session metadata to disk, creating the directory if needed.\n */\nexport async function writeSession (\n name: string,\n metadata: SessionMetadata,\n baseDir?: string,\n): Promise<void> {\n const dir = getSessionDir(baseDir);\n await fs.mkdir(dir, { recursive: true });\n const filePath = getSessionPath(name, baseDir);\n await fs.writeFile(filePath, JSON.stringify(metadata, null, 2));\n}\n\n/**\n * Reads session metadata from disk. Returns null if the session file does not exist.\n */\nexport async function readSession (\n name: string,\n baseDir?: string,\n): Promise<SessionMetadata | null> {\n const filePath = getSessionPath(name, baseDir);\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content) as SessionMetadata;\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Deletes both the .json and .refs.json files for a session.\n * Does not throw if the files do not exist.\n */\nexport async function deleteSessionFiles (\n name: string,\n baseDir?: string,\n): Promise<void> {\n const sessionPath = getSessionPath(name, baseDir);\n const refsPath = getRefsPath(name, baseDir);\n await Promise.all([\n fs.rm(sessionPath, { force: true }),\n fs.rm(refsPath, { force: true }),\n ]);\n}\n\n/**\n * Lists all sessions in the session directory.\n * Only considers .json files (excludes .refs.json).\n * Returns an empty array if the directory does not exist.\n */\nexport async function listSessions (baseDir?: string): Promise<SessionEntry[]> {\n const dir = getSessionDir(baseDir);\n let files: string[];\n try {\n files = await fs.readdir(dir);\n } catch (err: unknown) {\n if (isEnoent(err)) {\n return [];\n }\n throw err;\n }\n\n const sessionFiles = files.filter(\n (f) => f.endsWith('.json') && !f.endsWith('.refs.json'),\n );\n\n return await Promise.all(\n sessionFiles.map(async (f) => {\n const name = f.replace(/\\.json$/, '');\n const metadata = await readSession(name, baseDir);\n return { name, metadata: metadata! };\n }),\n );\n}\n\ninterface SessionArgs {\n session: string\n _sessionsDir?: string\n}\n\n/**\n * Wraps a command handler that requires an active session.\n * Reads the session from disk and exits early with an error if not found.\n */\nexport function withSession<T extends SessionArgs>(\n fn: (argv: ArgumentsCamelCase<T>, meta: SessionMetadata, sessionsDir: string) => Promise<void>,\n): (argv: ArgumentsCamelCase<T>) => Promise<void> {\n return async function handler(argv: ArgumentsCamelCase<T>): Promise<void> {\n const sessionName = argv.session as string;\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\n\n const meta = await readSession(sessionName, sessionsDir);\n if (!meta) {\n console.error(`Error: No active session [${sessionName}]. Run wdiox open <url> first.`);\n return;\n }\n\n await fn(argv, meta, sessionsDir);\n };\n}\n","import os from 'node:os';\nimport { execSync } from 'node:child_process';\n\nimport type { ArgumentsCamelCase } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { deleteSessionFiles, buildAttachOptions, withSession } from '../session.js';\n\nexport const command = ['close', 'stop'];\nexport const desc = 'Close the current session';\n\ninterface CloseArgs {\n session: string\n _sessionsDir?: string\n}\n\nfunction killProcess(pid: number): void {\n const platform = os.platform();\n try {\n if (platform === 'win32') {\n execSync(`taskkill /F /PID ${pid}`, { stdio: 'ignore' });\n } else {\n execSync(`kill -9 ${pid}`, { stdio: 'ignore' });\n }\n } catch {\n // Process may already be dead\n }\n}\n\nexport const handler = withSession<CloseArgs>(async (argv: ArgumentsCamelCase<CloseArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const caps = meta.capabilities as Record<string, unknown>;\n const browserPid = typeof caps['goog:processID'] === 'number' ? caps['goog:processID'] : undefined;\n const driverPid = typeof caps['wdio:driverPID'] === 'number' ? caps['wdio:driverPID'] : undefined;\n\n try {\n const browser = await attach(buildAttachOptions(meta));\n await browser.deleteSession();\n } catch {\n if (browserPid) {\n killProcess(browserPid);\n }\n if (driverPid && driverPid !== browserPid) {\n killProcess(driverPid);\n }\n }\n\n await deleteSessionFiles(sessionName, sessionsDir);\n console.log(`Session \"${sessionName}\" closed.`);\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\r\nimport { attach } from 'webdriverio';\r\n\r\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\r\nimport { writeRefs, type RefMap } from '../refs.js';\r\nimport { getInteractableBrowserElements, getMobileVisibleElements } from '@wdio/mcp/snapshot';\r\nimport {\r\n formatBrowserElement,\r\n formatMobileElement,\r\n} from '../format.js';\r\n\r\nexport const command = 'snapshot';\r\nexport const desc = 'Capture interactive elements on the page or screen';\r\n\r\nexport const builder = (yargs: Argv) => {\r\n return yargs\r\n .option('visible', {\r\n type: 'boolean',\r\n default: true,\r\n describe: 'Only show elements in viewport',\r\n });\r\n};\r\n\r\ninterface SnapshotArgs {\r\n session: string\r\n visible: boolean\r\n _sessionsDir?: string\r\n}\r\n\r\nexport const handler = withSession<SnapshotArgs>(async (argv: ArgumentsCamelCase<SnapshotArgs>, meta, sessionsDir) => {\r\n const sessionName = argv.session as string;\r\n const browser = await attach(buildAttachOptions(meta));\r\n\r\n const isMobile = browser.isAndroid || browser.isIOS;\r\n const refs: RefMap = {};\r\n\r\n if (isMobile) {\r\n const platform = browser.isIOS ? 'ios' : 'android';\r\n const elements = await getMobileVisibleElements(browser, platform);\r\n const filtered = argv.visible\r\n ? elements.filter(el => el.isInViewport)\r\n : elements;\r\n\r\n const appName = (meta.capabilities['appium:app'] as string) || 'unknown';\r\n console.log(`\\n App: ${appName}\\n`);\r\n\r\n filtered.forEach((el, i) => {\r\n const ref = `e${i + 1}`;\r\n console.log(formatMobileElement(ref, {\r\n tagName: el.tagName,\r\n text: el.text,\r\n selector: el.selector,\r\n accessibilityId: el.accessibilityId,\r\n resourceId: el.resourceId,\r\n }));\r\n refs[ref] = {\r\n selector: el.selector,\r\n tagName: el.tagName,\r\n text: el.text,\r\n };\r\n });\r\n\r\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\r\n } else {\r\n const elements = await getInteractableBrowserElements(browser);\r\n const filtered = argv.visible\r\n ? elements.filter(el => el.isInViewport)\r\n : elements;\r\n\r\n const currentUrl = await browser.getUrl();\r\n console.log(`\\n Page: ${currentUrl}\\n`);\r\n\r\n filtered.forEach((el, i) => {\r\n const ref = `e${i + 1}`;\r\n console.log(formatBrowserElement(ref, el));\r\n refs[ref] = {\r\n selector: el.selector,\r\n tagName: el.tagName,\r\n text: el.name || '',\r\n };\r\n });\r\n\r\n console.log(`\\n ${filtered.length} elements - ${sessionName} session\\n`);\r\n }\r\n\r\n await writeRefs(getRefsPath(sessionName, sessionsDir), refs);\r\n});\r\n","import fs from 'node:fs/promises';\r\n\r\nexport interface RefEntry {\r\n selector?: string\r\n tagName: string\r\n text?: string\r\n placeholder?: string\r\n [key: string]: unknown\r\n}\r\n\r\nexport type RefMap = Record<string, RefEntry>;\r\n\r\nfunction isEnoent (err: unknown): boolean {\r\n return err instanceof Error && 'code' in err && (err as NodeJS.ErrnoException).code === 'ENOENT';\r\n}\r\n\r\n/**\r\n * Writes a ref map to disk as JSON.\r\n */\r\nexport async function writeRefs (refsPath: string, refs: RefMap): Promise<void> {\r\n await fs.writeFile(refsPath, JSON.stringify(refs, null, 2), 'utf-8');\r\n}\r\n\r\n/**\r\n * Reads a ref map from disk. Returns null if the file doesn't exist.\r\n */\r\nexport async function readRefs (refsPath: string): Promise<RefMap | null> {\r\n try {\r\n const content = await fs.readFile(refsPath, 'utf-8');\r\n return JSON.parse(content) as RefMap;\r\n } catch (err: unknown) {\r\n if (isEnoent(err)) {\r\n return null;\r\n }\r\n throw err;\r\n }\r\n}\r\n\r\n/**\r\n * Look up a ref by key: reads refs file, finds the entry, resolves its selector.\r\n * Logs appropriate error messages and returns null on failure.\r\n */\r\nexport async function lookupRef (\r\n refsPath: string,\r\n refKey: string,\r\n): Promise<{ ref: RefEntry; selector: string } | null> {\r\n const refs = await readRefs(refsPath);\r\n if (!refs) {\r\n console.error('Error: No snapshot taken. Run wdiox snapshot first.');\r\n return null;\r\n }\r\n\r\n const ref = refs[refKey];\r\n if (!ref) {\r\n const available = Object.keys(refs);\r\n const range = available.length > 0\r\n ? `Available: ${available[0]}-${available[available.length - 1]}`\r\n : 'No refs available';\r\n console.error(`Error: ${refKey} not found in snapshot. ${range}`);\r\n return null;\r\n }\r\n\r\n if (!ref.selector) {\r\n console.error(`Error: Could not resolve selector for ${refKey}`);\r\n return null;\r\n }\r\n\r\n return { ref, selector: ref.selector };\r\n}\r\n","export interface BrowserElementFormatInput {\r\n tagName: string\r\n role?: string\r\n type?: string\r\n name?: string\r\n href?: string\r\n selector: string\r\n}\r\n\r\nexport interface MobileElementFormatInput {\r\n tagName: string\r\n text?: string\r\n selector: string\r\n accessibilityId?: string\r\n resourceId?: string\r\n}\r\n\r\nexport interface SessionListEntry {\r\n name: string\r\n browser: string\r\n url: string\r\n status: string\r\n}\r\n\r\nfunction truncate(str: string, max = 80): string {\r\n return str.length <= max ? str : str.slice(0, max - 3) + '...';\r\n}\r\n\r\nexport function formatBrowserElement(ref: string, el: BrowserElementFormatInput): string {\r\n const tag = (el.role && el.role !== el.tagName ? el.role : el.tagName) + (el.type ? `[${el.type}]` : '');\r\n const desc = [el.name && `\"${truncate(el.name)}\"`, el.href && `-> ${truncate(el.href)}`].filter(Boolean).join(' ');\r\n return [ref.padEnd(4), tag, desc, el.selector].filter(Boolean).join(' ');\r\n}\r\n\r\nexport function formatMobileElement(ref: string, el: MobileElementFormatInput): string {\r\n const selector = el.accessibilityId ? `[accessibility-id: ${el.accessibilityId}]`\r\n : el.resourceId ? `[resource-id: ${el.resourceId}]`\r\n : truncate(el.selector);\r\n const parts = [ref.padEnd(4), el.tagName.padEnd(28), el.text && `\"${truncate(el.text)}\"`, selector];\r\n return parts.filter(Boolean).join(' ');\r\n}\r\n\r\nexport function formatSessionList(entries: SessionListEntry[]): string {\r\n if (entries.length === 0) return 'No active sessions.';\r\n\r\n const cols = (['name', 'browser', 'url', 'status'] as const).map((key) => ({\r\n key,\r\n header: key.toUpperCase(),\r\n width: Math.max(key.length, ...entries.map((e) => e[key].length)),\r\n }));\r\n\r\n const row = (e: SessionListEntry) => cols.map((c) => e[c.key].padEnd(c.width)).join(' ');\r\n const header = cols.map((c) => c.header.padEnd(c.width)).join(' ');\r\n\r\n return [header, ...entries.map(row)].join('\\n');\r\n}\r\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, getRefsPath, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = 'click <ref>';\nexport const desc = 'Click an element by snapshot reference (e.g., e1)';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1, a3)',\n });\n};\n\ninterface ClickArgs {\n ref: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ClickArgs>(async (argv: ArgumentsCamelCase<ClickArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n await browser.$(result.selector).click();\n console.log(`Clicked ${refKey} (${result.ref.selector})`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error clicking ${refKey}: ${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { getRefsPath, buildAttachOptions, withSession } from '../session.js';\nimport { lookupRef } from '../refs.js';\n\nexport const command = ['type <ref> <text>', 'fill <ref> <text>'];\nexport const desc = 'Clear and type text into an input element by snapshot reference';\n\nexport const builder = (yargs: Argv) => {\n return yargs\n .positional('ref', {\n type: 'string',\n describe: 'Element reference from snapshot (e.g., e1)',\n })\n .positional('text', {\n type: 'string',\n describe: 'Text to type',\n });\n};\n\ninterface FillArgs {\n ref: string\n text: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<FillArgs>(async (argv: ArgumentsCamelCase<FillArgs>, meta, sessionsDir) => {\n const sessionName = argv.session as string;\n const refKey = argv.ref as string;\n const result = await lookupRef(getRefsPath(sessionName, sessionsDir), refKey);\n if (!result) {\n return;\n }\n\n const browser = await attach(buildAttachOptions(meta));\n\n try {\n const element = await browser.$(result.selector);\n await element.clearValue();\n await element.addValue(argv.text as string);\n console.log(`Filled ${refKey} with \"${argv.text}\"`);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n console.error(`Error: ${refKey} not found on page — the page may have changed. Run wdiox snapshot to refresh.\\n${msg}`);\n }\n});\n","import type { ArgumentsCamelCase, Argv } from 'yargs';\nimport { attach } from 'webdriverio';\n\nimport { buildAttachOptions, withSession } from '../session.js';\n\nexport const command = 'screenshot [path]';\nexport const desc = 'Save a screenshot of the current page or screen';\n\nexport const builder = (yargs: Argv) => {\n return yargs.positional('path', {\n type: 'string',\n describe: 'File path to save screenshot (default: ./screenshot-<timestamp>.png)',\n });\n};\n\ninterface ScreenshotArgs {\n path?: string\n session: string\n _sessionsDir?: string\n}\n\nexport const handler = withSession<ScreenshotArgs>(async (argv: ArgumentsCamelCase<ScreenshotArgs>, meta) => {\n const browser = await attach(buildAttachOptions(meta));\n\n const filePath = (argv.path as string) ||\n `screenshot-${new Date().toISOString().replace(/[:.]/g, '-')}.png`;\n\n await browser.saveScreenshot(filePath);\n console.log(`Screenshot saved to ${filePath}`);\n});\n","import type { ArgumentsCamelCase } from 'yargs';\r\nimport { attach } from 'webdriverio';\r\n\r\nimport { listSessions, getSessionDir, deleteSessionFiles, buildAttachOptions } from '../session.js';\r\nimport { formatSessionList, type SessionListEntry } from '../format.js';\r\n\r\nexport const command = ['session-list', 'ls'];\r\nexport const desc = 'List all active sessions';\r\n\r\ninterface SessionListArgs {\r\n _sessionsDir?: string\r\n}\r\n\r\nexport async function handler (argv: ArgumentsCamelCase<SessionListArgs>) {\r\n const sessionsDir = (argv._sessionsDir as string) || getSessionDir();\r\n const sessions = await listSessions(sessionsDir);\r\n\r\n if (sessions.length === 0) {\r\n console.log('No active sessions.');\r\n return;\r\n }\r\n\r\n const entries: SessionListEntry[] = [];\r\n\r\n for (const session of sessions) {\r\n let status = 'active';\r\n try {\r\n const browser = await attach(buildAttachOptions(session.metadata));\r\n await browser.getPageSource();\r\n } catch {\r\n status = 'expired';\r\n await deleteSessionFiles(session.name, sessionsDir);\r\n }\r\n\r\n const caps = session.metadata.capabilities;\r\n const browserName = (caps.browserName as string)\r\n || (caps.platformName as string)\r\n || 'unknown';\r\n entries.push({\r\n name: session.name,\r\n browser: browserName,\r\n url: session.metadata.url,\r\n status,\r\n });\r\n }\r\n\r\n console.log(formatSessionList(entries));\r\n}\r\n"],"mappings":"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","names":["handler","yargs","command","desc","handler","os","attach","command","desc","os","handler","attach","builder","command","desc","handler","attach","fs","isEnoent","desc","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","builder","command","desc","handler","attach","command","desc","builder","yargs","handler","attach","command","desc","handler","attach","command","desc","handler","attach"]}
package/package.json CHANGED
@@ -1,68 +1,68 @@
1
- {
2
- "name": "webdriverio-execute",
3
- "version": "0.2.0",
4
- "repository": {
5
- "type": "git",
6
- "url": "git+https://github.com/Winify/webdriverio-execute.git"
7
- },
8
- "description": "Interactive browser and app CLI for developers using WebdriverIO",
9
- "author": "Vince Graics <wince17@gmail.com>",
10
- "homepage": "https://github.com/Winify/webdriverio-execute",
11
- "license": "MIT",
12
- "bin": {
13
- "wdiox": "./bin/wdiox.js"
14
- },
15
- "engines": {
16
- "node": ">=18.20.0"
17
- },
18
- "keywords": [
19
- "webdriver",
20
- "webdriverio",
21
- "wdio",
22
- "cli",
23
- "browser",
24
- "automation"
25
- ],
26
- "bugs": {
27
- "url": "https://github.com/Winify/webdriverio-execute/issues"
28
- },
29
- "type": "module",
30
- "files": [
31
- "bin",
32
- "build",
33
- "README.md"
34
- ],
35
- "types": "./dist/index.d.ts",
36
- "scripts": {
37
- "bundle": "rimraf build && tsup",
38
- "postbundle": "pnpm pack",
39
- "dev": "tsup --watch",
40
- "test": "vitest run",
41
- "typecheck": "tsc --noEmit",
42
- "lint": "eslint --fix && pnpm run typecheck",
43
- "link": "pnpm run bundle && pnpm i && pnpm link --global"
44
- },
45
- "dependencies": {
46
- "@wdio/mcp": "^2.3.0",
47
- "@wdio/types": "^9.24.0",
48
- "webdriverio": "^9.24.0",
49
- "yargs": "^17.7.2"
50
- },
51
- "devDependencies": {
52
- "@types/node": "^24.10.13",
53
- "@types/yargs": "^17.0.24",
54
- "@wdio/eslint": "^0.1.3",
55
- "eslint": "^9.39.2",
56
- "husky": "^9.1.7",
57
- "lint-staged": "^16.2.7",
58
- "release-it": "^19.2.4",
59
- "rimraf": "^6.1.2",
60
- "tsup": "^8.0.0",
61
- "typescript": "^5.0.0",
62
- "vitest": "^2.0.0"
63
- },
64
- "publishConfig": {
65
- "access": "public"
66
- },
67
- "packageManager": "pnpm@10.26.2"
68
- }
1
+ {
2
+ "name": "webdriverio-execute",
3
+ "version": "0.2.2",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/Winify/webdriverio-execute.git"
7
+ },
8
+ "description": "Interactive browser and app CLI for developers using WebdriverIO",
9
+ "author": "Vince Graics <wince17@gmail.com>",
10
+ "homepage": "https://github.com/Winify/webdriverio-execute",
11
+ "license": "MIT",
12
+ "bin": {
13
+ "wdiox": "./bin/wdiox.js"
14
+ },
15
+ "engines": {
16
+ "node": ">=18.20.0"
17
+ },
18
+ "keywords": [
19
+ "webdriver",
20
+ "webdriverio",
21
+ "wdio",
22
+ "cli",
23
+ "browser",
24
+ "automation"
25
+ ],
26
+ "bugs": {
27
+ "url": "https://github.com/Winify/webdriverio-execute/issues"
28
+ },
29
+ "type": "module",
30
+ "files": [
31
+ "bin",
32
+ "build",
33
+ "README.md"
34
+ ],
35
+ "types": "./dist/index.d.ts",
36
+ "scripts": {
37
+ "bundle": "rimraf build && tsup",
38
+ "postbundle": "pnpm pack",
39
+ "dev": "tsup --watch",
40
+ "test": "vitest run",
41
+ "typecheck": "tsc --noEmit",
42
+ "lint": "eslint --fix && pnpm run typecheck",
43
+ "link": "pnpm run bundle && pnpm i && pnpm link --global"
44
+ },
45
+ "dependencies": {
46
+ "@wdio/mcp": "^2.3.0",
47
+ "@wdio/types": "^9.24.0",
48
+ "webdriverio": "^9.24.0",
49
+ "yargs": "^17.7.2"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^24.10.13",
53
+ "@types/yargs": "^17.0.24",
54
+ "@wdio/eslint": "^0.1.3",
55
+ "eslint": "^9.39.2",
56
+ "husky": "^9.1.7",
57
+ "lint-staged": "^16.2.7",
58
+ "release-it": "^19.2.4",
59
+ "rimraf": "^6.1.2",
60
+ "tsup": "^8.0.0",
61
+ "typescript": "^5.0.0",
62
+ "vitest": "^2.0.0"
63
+ },
64
+ "publishConfig": {
65
+ "access": "public"
66
+ },
67
+ "packageManager": "pnpm@10.26.2"
68
+ }